diff --git a/.clang-format b/.clang-format index 68766810a2d55..d17301209a080 100644 --- a/.clang-format +++ b/.clang-format @@ -58,6 +58,8 @@ IncludeCategories: # DART headers - Regex: '^$' Priority: 10 + - Regex: '^$' + Priority: 11 - Regex: '^$' Priority: 20 - Regex: '^$' @@ -84,7 +86,7 @@ IncludeCategories: Priority: 31 - Regex: '^$' Priority: 32 - - Regex: '^$' + - Regex: '^$' Priority: 33 - Regex: '^$' Priority: 40 diff --git a/cmake/DARTConfig.cmake.in b/cmake/DARTConfig.cmake.in index 552fa293fd2aa..84dfda8b57cb3 100644 --- a/cmake/DARTConfig.cmake.in +++ b/cmake/DARTConfig.cmake.in @@ -143,6 +143,9 @@ endfunction() list(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_LIST_DIR}) +# TODO: Improve the include mechanism +include(dart_v7Targets) + # Default component: dart list(APPEND @PROJECT_NAME_UPPERCASE@_FIND_COMPONENTS dart) diff --git a/cmake/DARTFindDependencies.cmake b/cmake/DARTFindDependencies.cmake index 33af2bb1d0aed..1c22898d45be7 100644 --- a/cmake/DARTFindDependencies.cmake +++ b/cmake/DARTFindDependencies.cmake @@ -131,6 +131,11 @@ find_package(Python3 COMPONENTS Interpreter Development) option(DART_SKIP_spdlog "If ON, do not use spdlog even if it is found." OFF) mark_as_advanced(DART_SKIP_spdlog) dart_find_package(spdlog) +if(spdlog_FOUND) + set(DART_HAVE_SPDLOG 1) +else() + set(DART_HAVE_SPDLOG 0) +endif() #-------------------- # Misc. dependencies diff --git a/dart/CMakeLists.txt b/dart/CMakeLists.txt index 3c547e94389f2..f75b317b06b77 100644 --- a/dart/CMakeLists.txt +++ b/dart/CMakeLists.txt @@ -13,6 +13,7 @@ set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY "${DART_BINARY_DIR}/lib") #=============================================================================== # Source directories #=============================================================================== +# v7 # common # math # integration @@ -60,6 +61,8 @@ set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY "${DART_BINARY_DIR}/lib") # gui - (utils), {dart-gui} # gui-osg - (gui), {dart-gui-osg} +add_subdirectory(v7) + # Component. This should be called before adding subdirectories. add_component(${PROJECT_NAME} dart) @@ -84,14 +87,6 @@ add_subdirectory(simulation) add_subdirectory(utils) # tinyxml2, bullet add_subdirectory(gui) # opengl, glut, bullet -set(DART_CONFIG_HPP_IN ${DART_SOURCE_DIR}/dart/config.hpp.in) -set(DART_CONFIG_HPP_OUT ${DART_BINARY_DIR}/dart/config.hpp) -if(DART_VERBOSE) - message(STATUS ${DART_CONFIG_HPP_OUT}) -endif() -configure_file(${DART_CONFIG_HPP_IN} ${DART_CONFIG_HPP_OUT} @ONLY) -install(FILES ${DART_CONFIG_HPP_OUT} DESTINATION include/dart) - # Print building component get_property(components GLOBAL PROPERTY ${PROJECT_NAME}_COMPONENTS) if(DART_VERBOSE) @@ -124,33 +119,22 @@ target_link_libraries(dart PUBLIC ${CMAKE_DL_LIBS} ${PROJECT_NAME}-external-odelcpsolver + v7 Eigen3::Eigen fcl assimp ) -if(TARGET fmt::fmt-header-only) - target_link_libraries(dart PUBLIC fmt::fmt-header-only) -elseif(TARGET fmt::fmt) +if(TARGET fmt::fmt) target_link_libraries(dart PUBLIC fmt::fmt) else() message(FATAL_ERROR "Failed to find fmt targets") endif() # spdlog settings -if(spdlog_FOUND) - # Prefer header only target - if(TARGET spdlog::spdlog_header_only) - target_link_libraries(dart PUBLIC spdlog::spdlog_header_only) - target_compile_definitions(dart PUBLIC -DDART_HAVE_spdlog=1) - elseif(TARGET spdlog::spdlog) - target_link_libraries(dart PUBLIC spdlog::spdlog) - target_compile_definitions(dart PUBLIC -DDART_HAVE_spdlog=1) - else() - message(WARNING "spdlog found, but no target is found. Expected spdlog::spdlog or target_link_library_public spdlog::spdlog_header_only") - target_compile_definitions(dart PUBLIC -DDART_HAVE_spdlog=0) - endif() -else() - target_compile_definitions(dart PUBLIC -DDART_HAVE_spdlog=0) +if(TARGET spdlog::spdlog_header_only) + target_link_libraries(dart PUBLIC spdlog::spdlog_header_only) +elseif(TARGET spdlog::spdlog) + target_link_libraries(dart PUBLIC spdlog::spdlog) endif() # octomap settings @@ -241,3 +225,11 @@ endif() install(FILES dart.hpp DESTINATION include/dart/ COMPONENT headers) dart_format_add(${dart_core_headers} ${dart_core_sources}) + +set(DART_CONFIG_HPP_IN ${DART_SOURCE_DIR}/dart/config.hpp.in) +set(DART_CONFIG_HPP_OUT ${DART_BINARY_DIR}/dart/config.hpp) +if(DART_VERBOSE) + message(STATUS ${DART_CONFIG_HPP_OUT}) +endif() +configure_file(${DART_CONFIG_HPP_IN} ${DART_CONFIG_HPP_OUT} @ONLY) +install(FILES ${DART_CONFIG_HPP_OUT} DESTINATION include/dart) diff --git a/dart/common/Logging.hpp b/dart/common/Logging.hpp index 2ec2251c149e8..62dd84be94254 100644 --- a/dart/common/Logging.hpp +++ b/dart/common/Logging.hpp @@ -33,114 +33,6 @@ #ifndef DART_COMMON_LOGGING_HPP_ #define DART_COMMON_LOGGING_HPP_ -// clang-format off -#define DART_LOG_LEVEL_TRACE 0 -#define DART_LOG_LEVEL_DEBUG 1 -#define DART_LOG_LEVEL_INFO 2 -#define DART_LOG_LEVEL_WARN 3 -#define DART_LOG_LEVEL_ERROR 4 -#define DART_LOG_LEVEL_FATAL 5 -#define DART_LOG_LEVEL_OFF 6 -// clang-format on - -// Default active log level -#if !defined(DART_ACTIVE_LOG_LEVEL) - #define DART_ACTIVE_LOG_LEVEL DART_LOG_LEVEL_INFO -#endif - -#if DART_ACTIVE_LOG_LEVEL <= DART_LOG_LEVEL_TRACE - #define DART_TRACE(...) ::dart::common::trace(__VA_ARGS__) -#else - #define DART_TRACE(...) (void)0 -#endif - -#if DART_ACTIVE_LOG_LEVEL <= DART_LOG_LEVEL_DEBUG - #define DART_DEBUG(...) ::dart::common::debug(__VA_ARGS__) -#else - #define DART_DEBUG(...) (void)0 -#endif - -#if DART_ACTIVE_LOG_LEVEL <= DART_LOG_LEVEL_INFO - #define DART_INFO(...) ::dart::common::info(__VA_ARGS__) -#else - #define DART_INFO(...) (void)0 -#endif - -#if DART_ACTIVE_LOG_LEVEL <= DART_LOG_LEVEL_WARN - #define DART_WARN(...) ::dart::common::warn(__VA_ARGS__) -#else - #define DART_WARN(...) (void)0 -#endif - -#if DART_ACTIVE_LOG_LEVEL <= DART_LOG_LEVEL_ERROR - #define DART_ERROR(...) ::dart::common::error(__VA_ARGS__) -#else - #define DART_ERROR(...) (void)0 -#endif - -#if DART_ACTIVE_LOG_LEVEL <= DART_LOG_LEVEL_FATAL - #define DART_FATAL(...) ::dart::common::fatal(__VA_ARGS__) -#else - #define DART_FATAL(...) (void)0 -#endif - -namespace dart::common { - -/// \brief Logs for a trace message -/// -/// Logs for the most fine-grained information than any other log levels. -/// -/// \sa info -template -void trace(const S& format_str, Args&&... args); - -/// \brief Logs for a debug message -/// -/// Logs for fine-grained information that is useful for debugging. -/// -/// \sa info -template -void debug(const S& format_str, Args&&... args); - -/// \brief Logs for a information message -/// -/// Logs for useful information from normal operations. -/// -/// You can use a Python like formatting API as -/// \code -/// dart::common::info("Hello {}!", "World"); // logged as "Hello World!" -/// \endcode -template -void info(const S& format_str, Args&&... args); - -/// \brief Logs for a warning message -/// -/// Logs for warning information that is potentially harmful. -/// -/// \sa info -template -void warn(const S& format_str, Args&&... args); - -/// \brief Logs for a error message -/// -/// Logs for errors that might still allow the application to continue running, -/// but the application might lead to unexpected behavior. -/// -/// \sa info -template -void error(const S& format_str, Args&&... args); - -/// \brief Logs for a fatal error message -/// -/// Logs for highly sever errors that will presumably lead the application to -/// crash. -/// -/// \sa info -template -void fatal(const S& format_str, Args&&... args); - -} // namespace dart::common - -#include +#include #endif // DART_COMMON_LOGGING_HPP_ diff --git a/dart/common/Macros.hpp b/dart/common/Macros.hpp index a7d92840a0b30..b38e9316e00b9 100644 --- a/dart/common/Macros.hpp +++ b/dart/common/Macros.hpp @@ -33,46 +33,6 @@ #ifndef DART_COMMON_MACROS_HPP_ #define DART_COMMON_MACROS_HPP_ -#include - -#include - -// DART_NUM_ARGS( [, [, ...]]) -#define DETAIL_DART_NUM_ARGS(z, a, b, c, d, e, f, cnt, ...) cnt -#define DART_NUM_ARGS(...) \ - DETAIL_DART_NUM_ARGS(, ##__VA_ARGS__, 6, 5, 4, 3, 2, 1, 0) - -// DART_CONCAT(a, b) -#define DETAIL_DART_CONCAT(a, b) a##b -#define DART_CONCAT(a, b) DETAIL_DART_CONCAT(a, b) - -// Macro to suppress -Wunused-parameter and -Wunused-variable warnings in -// release mode when a variable is only used in assertions. -// -// Usage: DART_UNUSED( [, [, ...]]) -#define DETAIL_DART_UNUSED_0() -#define DETAIL_DART_UNUSED_1(a) (void)(a) -#define DETAIL_DART_UNUSED_2(a, b) (void)(a), DETAIL_DART_UNUSED_1(b) -#define DETAIL_DART_UNUSED_3(a, b, c) (void)(a), DETAIL_DART_UNUSED_2(b, c) -#define DETAIL_DART_UNUSED_4(a, b, c, d) \ - (void)(a), DETAIL_DART_UNUSED_3(b, c, d) -#define DETAIL_DART_UNUSED_5(a, b, c, d, e) \ - (void)(a), DETAIL_DART_UNUSED_4(b, c, d, e) -#define DETAIL_DART_UNUSED_6(a, b, c, d, e, f) \ - (void)(a), DETAIL_DART_UNUSED_5(b, c, d, e, f) -#define DART_UNUSED(...) \ - DART_CONCAT(DETAIL_DART_UNUSED_, DART_NUM_ARGS(__VA_ARGS__))(__VA_ARGS__) - -// DART_ASSERT( [, ]) -#define DETAIL_DART_ASSERT_1(condition) assert(condition) -#define DETAIL_DART_ASSERT_2(condition, message) assert((condition) && #message) -#define DART_ASSERT(...) \ - DART_CONCAT(DETAIL_DART_ASSERT_, DART_NUM_ARGS(__VA_ARGS__)) \ - (__VA_ARGS__) - -// Macro to mark the function is not implemented -#define DART_NOT_IMPLEMENTED \ - DART_FATAL("Not implemented: {}:{}", __FILE__, __LINE__); \ - void(0) +#include #endif diff --git a/dart/common/Uri.hpp b/dart/common/Uri.hpp index db31c0fa4695a..377c40ba2abe6 100644 --- a/dart/common/Uri.hpp +++ b/dart/common/Uri.hpp @@ -30,200 +30,12 @@ * POSSIBILITY OF SUCH DAMAGE. */ -#ifndef DART_COMMON_URI_HPP_ -#define DART_COMMON_URI_HPP_ +#pragma once -#include +#include -namespace dart { -namespace common { +namespace dart::common { -class UriComponent final -{ -public: - using value_type = std::string; - using reference_type = value_type&; - using reference_const_type = const value_type&; - using pointer_type = value_type*; - using pointer_const_type = const value_type*; +using Uri = v7::Uri; - UriComponent(); - UriComponent(reference_const_type _value); - - operator bool() const; - - bool operator!() const; - - UriComponent& operator=(reference_const_type _value); - - reference_type operator*(); - reference_const_type operator*() const; - - pointer_type operator->(); - pointer_const_type operator->() const; - - void assign(reference_const_type _value); - void reset(); - - reference_type get(); - reference_const_type get() const; - - reference_type get_value_or(reference_type _default); - reference_const_type get_value_or(reference_const_type _default) const; - -private: - bool mExists; - std::string mValue; -}; - -/// The Uri struct provides URI parsing and merging functionality based on RFC -/// 3986. -/// -/// We have Uri as a struct rather than class to expose member variables. Many -/// ResourceRetreiver classes rewrite URIs to other types of URIs (e.g, resolve -/// 'package://' URIs to 'file://' URIs), which is easier to implement if you -/// have direct access to the URI components. -struct Uri final -{ - /// Scheme, e.g. 'http', 'file', 'package' - UriComponent mScheme; - - /// Authority, e.g. 'google.com', 'en.wikipedia.org' - UriComponent mAuthority; - - /// Path, e.g. '/index.html', '/foo/bar.txt' - UriComponent mPath; - - /// Query string, i.e. the part of the URI after the ? - UriComponent mQuery; - - /// Fragment, e.g. the part of the URI after the # - UriComponent mFragment; - - /// Constructor - Uri() = default; - - /// Constructor that takes a URI or local path. Internally, this is equivalent - /// to calling fromStringOrPath(_input) after default constructor. - /// - /// We don't declare this constructor as explicit in order to allow implicit - /// conversion from string so that you can pass in string parameter to a - /// function that takes Uri. - Uri(const std::string& _input); - - /// Constructor that takes a URI or local path as const char*. The behavior is - /// identical to Uri(const std::string&). - Uri(const char* _input); - - /// Clear the URI by reset()ing all components. - void clear(); - - /// Parse a URI from a string; return success. All the components will be - /// cleared on failure. - bool fromString(const std::string& _input); - - /// Parse a local path (i.e. URI with no schema) from a string; return - /// success. Note that the input path should be absolute path. All the - /// components will be cleared on failure. - bool fromPath(const std::string& _path); - - /// Parse a URI or local path (i.e. URI with no schema) from a string; return - /// success. We assume that any string without a scheme is a path. All the - /// components will be cleared on failure. - bool fromStringOrPath(const std::string& _input); - - /// Resolve a relative path reference; return success. All the components will - /// be cleared on failure. - bool fromRelativeUri( - const std::string& _base, - const std::string& _relative, - bool _strict = false); - - /// Resolve a relative path reference; return success. All the components will - /// be cleared on failure. - bool fromRelativeUri( - const char* _base, const char* _relative, bool _strict = false); - - /// Resolve a relative path reference; return success. All the components will - /// be cleared on failure. - bool fromRelativeUri( - const Uri& _base, const std::string& _relative, bool _strict = false); - - /// Resolve a relative path reference; return success. All the components will - /// be cleared on failure. - bool fromRelativeUri( - const Uri& _base, const char* _relative, bool _strict = false); - - /// Resolve a relative path reference; return success. All the components will - /// be cleared on failure. - bool fromRelativeUri( - const Uri& _base, const Uri& _relative, bool _strict = false); - - /// Combine the parts of the URI into a string. - std::string toString() const; - - /// Create URI from a string; return an empty URI on failure. - static Uri createFromString(const std::string& _input); - - /// Create file URI from a string; return an empty URI on failure. - static Uri createFromPath(const std::string& _path); - - /// Create general URI or file URI from a string; return an empty URI on - /// failure. - static Uri createFromStringOrPath(const std::string& _input); - - /// Create URI resolving a relative path reference; return an empty URI on - /// failure. - static Uri createFromRelativeUri( - const std::string& _base, - const std::string& _relative, - bool _strict = false); - - /// Create URI resolving a relative path reference; return an empty URI on - /// failure. - static Uri createFromRelativeUri( - const Uri& _base, const std::string& _relative, bool _strict = false); - - /// Create URI resolving a relative path reference; return an empty URI on - /// failure. - static Uri createFromRelativeUri( - const Uri& _base, const Uri& _relative, bool _strict = false); - - /// Parse a URI from a string; return an empty string on failure. - static std::string getUri(const std::string& _input); - - /// Resolve a relative path reference; return an empty string on failure. - static std::string getRelativeUri( - const std::string& _base, - const std::string& _relative, - bool _strict = false); - - /// Resolve a relative path reference; return an empty string on failure. - static std::string getRelativeUri( - const Uri& _base, const std::string& _relative, bool _strict = false); - - /// Resolve a relative path reference; return an empty string on failure. - static std::string getRelativeUri( - const Uri& _base, const Uri& _relative, bool _strict = false); - - /// Get the path component of the URI as a string. - std::string getPath() const; - - /// Get the path in the local filesystem as a string. You should use this - /// function rather than getPath() if you are trying to access a local file. - /// Note that this function is identical to getPath() for Unix systems, but - /// differ by the leading '/' on Windows. - std::string getFilesystemPath() const; - -private: - /// Implement section 5.2.3 of RFC 3986. - static std::string mergePaths(const Uri& _base, const Uri& _relative); - - /// Implement section 5.2.4 of RFC 3986. - static std::string removeDotSegments(const std::string& _path); -}; - -} // namespace common -} // namespace dart - -#endif // ifndef DART_COMMON_URI_HPP_ +} // namespace dart::common diff --git a/dart/common/detail/Logging-impl.hpp b/dart/common/detail/Logging-impl.hpp deleted file mode 100644 index 32dce9511f445..0000000000000 --- a/dart/common/detail/Logging-impl.hpp +++ /dev/null @@ -1,152 +0,0 @@ -/* - * Copyright (c) 2011-2024, The DART development contributors - * All rights reserved. - * - * The list of contributors can be found at: - * https://github.com/dartsim/dart/blob/main/LICENSE - * - * This file is provided under the following "BSD-style" License: - * Redistribution and use in source and binary forms, with or - * without modification, are permitted provided that the following - * conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials provided - * with the distribution. - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND - * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, - * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED - * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN - * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef DART_COMMON_DETAIL_LOGGING_IMPL_HPP_ -#define DART_COMMON_DETAIL_LOGGING_IMPL_HPP_ - -#include - -#if DART_HAVE_spdlog - #include -#else - #include - #include -#endif - -namespace dart::common { - -#if !DART_HAVE_spdlog -namespace detail { - -//============================================================================== -template -void print(std::ostream& os, const S1& header, const S2& format_str, int color) -{ - os << "\033[1;" << color << "m" << header << "\033[0m " << format_str - << std::endl; -} - -//============================================================================== -template -void print( - std::ostream& os, - const S& header, - std::string format_str, - int color, - Arg&& arg, - Args&&... args) -{ - os << "\033[1;" << color << "m" << header << "\033[0m " << format_str - << " [args]: "; - os << std::forward(arg); - ((os << ", " << std::forward(args)), ...); - os << std::endl; -} - -} // namespace detail -#endif - -//============================================================================== -template -void trace(const S& format_str, [[maybe_unused]] Args&&... args) -{ -#if DART_HAVE_spdlog - spdlog::trace(format_str, std::forward(args)...); -#else - detail::print( - std::cout, "[trace]", format_str, 38, std::forward(args)...); -#endif -} - -//============================================================================== -template -void debug(const S& format_str, [[maybe_unused]] Args&&... args) -{ -#if DART_HAVE_spdlog - spdlog::debug(format_str, std::forward(args)...); -#else - detail::print( - std::cout, "[debug]", format_str, 36, std::forward(args)...); -#endif -} - -//============================================================================== -template -void info(const S& format_str, [[maybe_unused]] Args&&... args) -{ -#if DART_HAVE_spdlog - spdlog::info(format_str, std::forward(args)...); -#else - detail::print( - std::cout, "[info]", format_str, 32, std::forward(args)...); -#endif -} - -//============================================================================== -template -void warn(const S& format_str, [[maybe_unused]] Args&&... args) -{ -#if DART_HAVE_spdlog - spdlog::warn(format_str, std::forward(args)...); -#else - detail::print( - std::cerr, "[warn]", format_str, 33, std::forward(args)...); -#endif -} - -//============================================================================== -template -void error(const S& format_str, [[maybe_unused]] Args&&... args) -{ -#if DART_HAVE_spdlog - spdlog::error(format_str, std::forward(args)...); -#else - detail::print( - std::cerr, "[error]", format_str, 31, std::forward(args)...); -#endif -} - -//============================================================================== -template -void fatal(const S& format_str, [[maybe_unused]] Args&&... args) -{ -#if DART_HAVE_spdlog - spdlog::critical(format_str, std::forward(args)...); -#else - detail::print( - std::cerr, "[fatal]", format_str, 35, std::forward(args)...); -#endif -} - -} // namespace dart::common - -#endif // DART_COMMON_DETAIL_LOGGING_IMPL_HPP_ diff --git a/dart/config.hpp.in b/dart/config.hpp.in index 7ee2997fd7a80..7fefbcf7c77d7 100644 --- a/dart/config.hpp.in +++ b/dart/config.hpp.in @@ -1,4 +1,5 @@ /* config.hpp. Generated by CMake for @PROJECT_NAME@. */ + #pragma once /* Version number */ @@ -76,6 +77,7 @@ // TODO(JS): Change names to DART_HAVE_* // TODO(JS): Use target_compile_definitions( PUBLIC // -DDART_HAVE_*=1) +#cmakedefine01 DART_HAVE_SPDLOG #cmakedefine01 DART_ENABLE_SIMD diff --git a/dart/v7/CMakeLists.txt b/dart/v7/CMakeLists.txt new file mode 100644 index 0000000000000..48e429bd9de08 --- /dev/null +++ b/dart/v7/CMakeLists.txt @@ -0,0 +1,39 @@ +# Copyright (c) The DART development contributors +# All rights reserved. +# +# The list of contributors can be found at: +# https://github.com/dartsim/dart/blob/master/LICENSE +# +# This file is provided under the following "BSD-style" License: +# Redistribution and use in source and binary forms, with or +# without modification, are permitted provided that the following +# conditions are met: +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above +# copyright notice, this list of conditions and the following +# disclaimer in the documentation and/or other materials provided +# with the distribution. +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND +# CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, +# INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF +# USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED +# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. + +dart_library( + NAME v7 + GLOB_HEADERS + GLOB_SOURCES + PUBLIC_LINK_LIBRARIES + Eigen3::Eigen + $<$:EnTT::EnTT> + $<$:spdlog::spdlog_header_only> +) diff --git a/dart/v7/assert.hpp b/dart/v7/assert.hpp new file mode 100644 index 0000000000000..813902d537607 --- /dev/null +++ b/dart/v7/assert.hpp @@ -0,0 +1,75 @@ +/* + * Copyright (c) The DART development contributors + * All rights reserved. + * + * The list of contributors can be found at: + * https://github.com/dartsim/dart/blob/main/LICENSE + * + * This file is provided under the following "BSD-style" License: + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#pragma once + +#include + +#include + +// DART_NUM_ARGS( [, [, ...]]) +#define DETAIL_DART_NUM_ARGS(z, a, b, c, d, e, f, cnt, ...) cnt +#define DART_NUM_ARGS(...) \ + DETAIL_DART_NUM_ARGS(, ##__VA_ARGS__, 6, 5, 4, 3, 2, 1, 0) + +// DART_CONCAT(a, b) +#define DETAIL_DART_CONCAT(a, b) a##b +#define DART_CONCAT(a, b) DETAIL_DART_CONCAT(a, b) + +// Macro to suppress -Wunused-parameter and -Wunused-variable warnings in +// release mode when a variable is only used in assertions. +// +// Usage: DART_UNUSED( [, [, ...]]) +#define DETAIL_DART_UNUSED_0() +#define DETAIL_DART_UNUSED_1(a) (void)(a) +#define DETAIL_DART_UNUSED_2(a, b) (void)(a), DETAIL_DART_UNUSED_1(b) +#define DETAIL_DART_UNUSED_3(a, b, c) (void)(a), DETAIL_DART_UNUSED_2(b, c) +#define DETAIL_DART_UNUSED_4(a, b, c, d) \ + (void)(a), DETAIL_DART_UNUSED_3(b, c, d) +#define DETAIL_DART_UNUSED_5(a, b, c, d, e) \ + (void)(a), DETAIL_DART_UNUSED_4(b, c, d, e) +#define DETAIL_DART_UNUSED_6(a, b, c, d, e, f) \ + (void)(a), DETAIL_DART_UNUSED_5(b, c, d, e, f) +#define DART_UNUSED(...) \ + DART_CONCAT(DETAIL_DART_UNUSED_, DART_NUM_ARGS(__VA_ARGS__))(__VA_ARGS__) + +// DART_ASSERT( [, ]) +#define DETAIL_DART_ASSERT_1(condition) assert(condition) +#define DETAIL_DART_ASSERT_2(condition, message) assert((condition) && #message) +#define DART_ASSERT(...) \ + DART_CONCAT(DETAIL_DART_ASSERT_, DART_NUM_ARGS(__VA_ARGS__)) \ + (__VA_ARGS__) + +// Macro to mark the function is not implemented +#define DART_NOT_IMPLEMENTED \ + DART_FATAL("Not implemented: {}:{}", __FILE__, __LINE__); \ + void(0) diff --git a/dart/v7/fwd.hpp b/dart/v7/fwd.hpp new file mode 100644 index 0000000000000..24c665c7b2560 --- /dev/null +++ b/dart/v7/fwd.hpp @@ -0,0 +1,41 @@ +/* + * Copyright (c) The DART development contributors + * All rights reserved. + * + * The list of contributors can be found at: + * https://github.com/dartsim/dart/blob/main/LICENSE + * + * This file is provided under the following "BSD-style" License: + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#pragma once + +#include + +namespace dart::v7 { + +// Placeholder for the v7 API + +} // namespace dart::v7 diff --git a/dart/v7/logging.hpp b/dart/v7/logging.hpp new file mode 100644 index 0000000000000..fb8f35260f2a3 --- /dev/null +++ b/dart/v7/logging.hpp @@ -0,0 +1,293 @@ +/* + * Copyright (c) The DART development contributors + * All rights reserved. + * + * The list of contributors can be found at: + * https://github.com/dartsim/dart/blob/main/LICENSE + * + * This file is provided under the following "BSD-style" License: + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#pragma once + +#include + +// clang-format off +#define DART_LOG_LEVEL_TRACE 0 +#define DART_LOG_LEVEL_DEBUG 1 +#define DART_LOG_LEVEL_INFO 2 +#define DART_LOG_LEVEL_WARN 3 +#define DART_LOG_LEVEL_ERROR 4 +#define DART_LOG_LEVEL_FATAL 5 +#define DART_LOG_LEVEL_OFF 6 +// clang-format on + +// Default active log level +#if !defined(DART_ACTIVE_LOG_LEVEL) + #define DART_ACTIVE_LOG_LEVEL DART_LOG_LEVEL_INFO +#endif + +#if DART_ACTIVE_LOG_LEVEL <= DART_LOG_LEVEL_TRACE + #define DART_TRACE(...) ::dart::common::trace(__VA_ARGS__) +#else + #define DART_TRACE(...) (void)0 +#endif + +#if DART_ACTIVE_LOG_LEVEL <= DART_LOG_LEVEL_DEBUG + #define DART_DEBUG(...) ::dart::common::debug(__VA_ARGS__) +#else + #define DART_DEBUG(...) (void)0 +#endif + +#if DART_ACTIVE_LOG_LEVEL <= DART_LOG_LEVEL_INFO + #define DART_INFO(...) ::dart::common::info(__VA_ARGS__) +#else + #define DART_INFO(...) (void)0 +#endif + +#if DART_ACTIVE_LOG_LEVEL <= DART_LOG_LEVEL_WARN + #define DART_WARN(...) ::dart::common::warn(__VA_ARGS__) +#else + #define DART_WARN(...) (void)0 +#endif + +#if DART_ACTIVE_LOG_LEVEL <= DART_LOG_LEVEL_ERROR + #define DART_ERROR(...) ::dart::common::error(__VA_ARGS__) +#else + #define DART_ERROR(...) (void)0 +#endif + +#if DART_ACTIVE_LOG_LEVEL <= DART_LOG_LEVEL_FATAL + #define DART_FATAL(...) ::dart::common::fatal(__VA_ARGS__) +#else + #define DART_FATAL(...) (void)0 +#endif + +#define DART_TRACE_IF(condition, ...) \ + if (condition) { \ + DART_TRACE(__VA_ARGS__); \ + } + +#define DART_DEBUG_IF(condition, ...) \ + if (condition) { \ + DART_DEBUG(__VA_ARGS__); \ + } + +#define DART_INFO_IF(condition, ...) \ + if (condition) { \ + DART_INFO(__VA_ARGS__); \ + } + +#define DART_WARN_IF(condition, ...) \ + if (condition) { \ + DART_WARN(__VA_ARGS__); \ + } + +#define DART_ERROR_IF(condition, ...) \ + if (condition) { \ + DART_ERROR(__VA_ARGS__); \ + } + +#define DART_FATAL_IF(condition, ...) \ + if (condition) { \ + DART_FATAL(__VA_ARGS__); \ + } + +namespace dart::common { + +/// \brief Logs for a trace message +/// +/// Logs for the most fine-grained information than any other log levels. +/// +/// \sa info +template +void trace(const S& format_str, Args&&... args); + +/// \brief Logs for a debug message +/// +/// Logs for fine-grained information that is useful for debugging. +/// +/// \sa info +template +void debug(const S& format_str, Args&&... args); + +/// \brief Logs for a information message +/// +/// Logs for useful information from normal operations. +/// +/// You can use a Python like formatting API as +/// \code +/// dart::common::info("Hello {}!", "World"); // logged as "Hello World!" +/// \endcode +template +void info(const S& format_str, Args&&... args); + +/// \brief Logs for a warning message +/// +/// Logs for warning information that is potentially harmful. +/// +/// \sa info +template +void warn(const S& format_str, Args&&... args); + +/// \brief Logs for a error message +/// +/// Logs for errors that might still allow the application to continue running, +/// but the application might lead to unexpected behavior. +/// +/// \sa info +template +void error(const S& format_str, Args&&... args); + +/// \brief Logs for a fatal error message +/// +/// Logs for highly sever errors that will presumably lead the application to +/// crash. +/// +/// \sa info +template +void fatal(const S& format_str, Args&&... args); + +} // namespace dart::common + +//============================================================================== +// +// Implementation +// +//============================================================================== + +#if DART_HAVE_SPDLOG + #include +#else + #include + #include +#endif + +namespace dart::common { + +#if !DART_HAVE_SPDLOG +namespace detail { + +//============================================================================== +template +void print(std::ostream& os, const S1& header, const S2& format_str, int color) +{ + os << "\033[1;" << color << "m" << header << "\033[0m " << format_str + << std::endl; +} + +//============================================================================== +template +void print( + std::ostream& os, + const S& header, + std::string format_str, + int color, + Arg&& arg, + Args&&... args) +{ + os << "\033[1;" << color << "m" << header << "\033[0m " << format_str + << " [args]: "; + os << std::forward(arg); + ((os << ", " << std::forward(args)), ...); + os << std::endl; +} + +} // namespace detail +#endif + +//============================================================================== +template +void trace(const S& format_str, [[maybe_unused]] Args&&... args) +{ +#if DART_HAVE_SPDLOG + spdlog::trace(format_str, std::forward(args)...); +#else + detail::print( + std::cout, "[trace]", format_str, 38, std::forward(args)...); +#endif +} + +//============================================================================== +template +void debug(const S& format_str, [[maybe_unused]] Args&&... args) +{ +#if DART_HAVE_SPDLOG + spdlog::debug(format_str, std::forward(args)...); +#else + detail::print( + std::cout, "[debug]", format_str, 36, std::forward(args)...); +#endif +} + +//============================================================================== +template +void info(const S& format_str, [[maybe_unused]] Args&&... args) +{ +#if DART_HAVE_SPDLOG + spdlog::info(format_str, std::forward(args)...); +#else + detail::print( + std::cout, "[info]", format_str, 32, std::forward(args)...); +#endif +} + +//============================================================================== +template +void warn(const S& format_str, [[maybe_unused]] Args&&... args) +{ +#if DART_HAVE_SPDLOG + spdlog::warn(format_str, std::forward(args)...); +#else + detail::print( + std::cerr, "[warn]", format_str, 33, std::forward(args)...); +#endif +} + +//============================================================================== +template +void error(const S& format_str, [[maybe_unused]] Args&&... args) +{ +#if DART_HAVE_SPDLOG + spdlog::error(format_str, std::forward(args)...); +#else + detail::print( + std::cerr, "[error]", format_str, 31, std::forward(args)...); +#endif +} + +//============================================================================== +template +void fatal(const S& format_str, [[maybe_unused]] Args&&... args) +{ +#if DART_HAVE_SPDLOG + spdlog::critical(format_str, std::forward(args)...); +#else + detail::print( + std::cerr, "[fatal]", format_str, 35, std::forward(args)...); +#endif +} + +} // namespace dart::common diff --git a/dart/common/Uri.cpp b/dart/v7/uri.cpp similarity index 74% rename from dart/common/Uri.cpp rename to dart/v7/uri.cpp index 6ab0857701513..2da1a1de40cb2 100644 --- a/dart/common/Uri.cpp +++ b/dart/v7/uri.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011-2024, The DART development contributors + * Copyright (c) The DART development contributors * All rights reserved. * * The list of contributors can be found at: @@ -30,110 +30,95 @@ * POSSIBILITY OF SUCH DAMAGE. */ -#include "dart/common/Uri.hpp" +#include "dart/v7/uri.hpp" -#include "dart/common/Console.hpp" +#include +#include #include #include -#include +namespace dart::v7 { -static bool startsWith(const std::string& _target, const std::string& _prefix) +namespace { + +// TODO: Move to string_utils.hpp +inline bool startsWith(const std::string& target, const std::string& prefix) { - return _target.substr(0, _prefix.size()) == _prefix; + return target.substr(0, prefix.size()) == prefix; } -namespace dart { -namespace common { +} // namespace -/* - * UriComponent - */ - -//============================================================================== UriComponent::UriComponent() { reset(); } -//============================================================================== UriComponent::UriComponent(reference_const_type _value) { assign(_value); } -//============================================================================== UriComponent::operator bool() const { return mExists; } -//============================================================================== bool UriComponent::operator!() const { return !mExists; } -//============================================================================== auto UriComponent::operator=(reference_const_type _value) -> UriComponent& { assign(_value); return *this; } -//============================================================================== auto UriComponent::operator*() -> reference_type { return get(); } -//============================================================================== auto UriComponent::operator*() const -> reference_const_type { return get(); } -//============================================================================== auto UriComponent::operator->() -> pointer_type { return &get(); } -//============================================================================== auto UriComponent::operator->() const -> pointer_const_type { return &get(); } -//============================================================================== void UriComponent::assign(reference_const_type _value) { mExists = true; mValue = _value; } -//============================================================================== void UriComponent::reset() { mExists = false; } -//============================================================================== auto UriComponent::get() -> reference_type { assert(mExists); return mValue; } -//============================================================================== auto UriComponent::get() const -> reference_const_type { assert(mExists); return mValue; } -//============================================================================== auto UriComponent::get_value_or(reference_type _default) -> reference_type { if (mExists) @@ -142,7 +127,6 @@ auto UriComponent::get_value_or(reference_type _default) -> reference_type return _default; } -//============================================================================== auto UriComponent::get_value_or(reference_const_type _default) const -> reference_const_type { @@ -152,31 +136,26 @@ auto UriComponent::get_value_or(reference_const_type _default) const return _default; } -/* - * Uri - */ - -//============================================================================== -Uri::Uri(const std::string& _input) +Uri::Uri(const std::string& input) { - if (!fromStringOrPath(_input)) - dtwarn << "[Uri::Uri] Failed parsing URI '" << _input << "'.\n"; + if (!fromStringOrPath(input)) { + DART_WARN("[Uri::Uri] Failed parsing URI '{}'.", input); + } // We don't need to clear since fromStringOrPath() does not set any component // on failure. } -//============================================================================== -Uri::Uri(const char* _input) +Uri::Uri(const char* input) { - if (!fromStringOrPath(std::string(_input))) - dtwarn << "[Uri::Uri] Failed parsing URI '" << _input << "'.\n"; + if (!fromStringOrPath(std::string(input))) { + DART_WARN("[Uri::Uri] Failed parsing URI '{}'.", input); + } // We don't need to clear since fromStringOrPath() does not set any component // on failure. } -//============================================================================== void Uri::clear() { mScheme.reset(); @@ -186,7 +165,6 @@ void Uri::clear() mFragment.reset(); } -//============================================================================== bool Uri::fromString(const std::string& _input) { // This is regex is from Appendix B of RFC 3986. @@ -233,7 +211,6 @@ bool Uri::fromString(const std::string& _input) return true; } -//============================================================================== bool Uri::fromPath(const std::string& _path) { // TODO(JS): We might want to check validity of _path. @@ -251,7 +228,6 @@ bool Uri::fromPath(const std::string& _path) #endif } -//============================================================================== bool Uri::fromStringOrPath(const std::string& _input) { // TODO(JS): Need to check if _input is an "absolute" path? @@ -282,14 +258,12 @@ bool Uri::fromStringOrPath(const std::string& _input) return fromString(_input); } -//============================================================================== bool Uri::fromRelativeUri( const std::string& _base, const std::string& _relative, bool _strict) { Uri baseUri; if (!baseUri.fromString(_base)) { - dtwarn << "[Uri::fromRelativeUri] Failed parsing base URI '" << _base - << "'.\n"; + DART_WARN("[Uri::fromRelativeUri] Failed parsing base URI '{}'.", _base); clear(); return false; } @@ -297,21 +271,19 @@ bool Uri::fromRelativeUri( return fromRelativeUri(baseUri, _relative, _strict); } -//============================================================================== bool Uri::fromRelativeUri( const char* _base, const char* _relative, bool _strict) { return fromRelativeUri(std::string(_base), std::string(_relative), _strict); } -//============================================================================== bool Uri::fromRelativeUri( const Uri& _base, const std::string& _relative, bool _strict) { Uri relativeUri; if (!relativeUri.fromString(_relative)) { - dtwarn << "[Uri::fromRelativeUri] Failed parsing relative URI '" - << _relative << "'.\n"; + DART_WARN( + "[Uri::fromRelativeUri] Failed parsing relative URI '{}'.", _relative); clear(); return false; } @@ -319,13 +291,11 @@ bool Uri::fromRelativeUri( return fromRelativeUri(_base, relativeUri, _strict); } -//============================================================================== bool Uri::fromRelativeUri(const Uri& _base, const char* _relative, bool _strict) { return fromRelativeUri(_base, std::string(_relative), _strict); } -//============================================================================== bool Uri::fromRelativeUri( const Uri& _base, const Uri& _relative, bool /*_strict*/) { @@ -373,7 +343,6 @@ bool Uri::fromRelativeUri( return true; } -//============================================================================== std::string Uri::toString() const { // This function implements the pseudo-code from Section 5.3 of RFC 3986. @@ -396,13 +365,11 @@ std::string Uri::toString() const return output.str(); } -//============================================================================== Uri Uri::createFromString(const std::string& _input) { Uri uri; if (!uri.fromString(_input)) { - dtwarn << "[Uri::createFromString] Failed parsing URI '" << _input - << "'.\n"; + DART_WARN("[Uri::createFromString] Failed parsing URI '{}'", _input); } // We don't need to clear uri since fromString() does not set any component @@ -411,13 +378,11 @@ Uri Uri::createFromString(const std::string& _input) return uri; } -//============================================================================== Uri Uri::createFromPath(const std::string& _path) { Uri fileUri; if (!fileUri.fromPath(_path)) { - dtwarn << "[Uri::createFromPath] Failed parsing local path '" << _path - << "'.\n"; + DART_WARN("[Uri::createFromPath] Failed parsing local path '{}'", _path); } // We don't need to clear uri since fromString() does not set any component @@ -426,13 +391,11 @@ Uri Uri::createFromPath(const std::string& _path) return fileUri; } -//============================================================================== Uri Uri::createFromStringOrPath(const std::string& _input) { Uri uri; if (!uri.fromStringOrPath(_input)) { - dtwarn << "[Uri::createFromString] Failed parsing URI '" << _input - << "'.\n"; + DART_WARN("[Uri::createFromString] Failed parsing URI '{}'", _input); } // We don't need to clear uri since fromString() does not set any component @@ -441,14 +404,16 @@ Uri Uri::createFromStringOrPath(const std::string& _input) return uri; } -//============================================================================== Uri Uri::createFromRelativeUri( const std::string& _base, const std::string& _relative, bool _strict) { Uri mergedUri; if (!mergedUri.fromRelativeUri(_base, _relative, _strict)) { - dtwarn << "[Uri::createFromRelativeUri] Failed merging URI '" << _relative - << "' with base URI '" << _base << "'.\n"; + DART_WARN( + "[Uri::createFromRelativeUri] Failed merging URI '{}' with base URI " + "'{}'", + _relative, + _base); } // We don't need to clear mergedUri since fromRelativeUri() does not set any @@ -457,14 +422,16 @@ Uri Uri::createFromRelativeUri( return mergedUri; } -//============================================================================== Uri Uri::createFromRelativeUri( const Uri& _base, const std::string& _relative, bool _strict) { Uri mergedUri; if (!mergedUri.fromRelativeUri(_base, _relative, _strict)) { - dtwarn << "[Uri::createFromRelativeUri] Failed merging URI '" << _relative - << "' with base URI '" << _base.toString() << "'.\n"; + DART_WARN( + "[Uri::createFromRelativeUri] Failed merging URI '{}' with base URI " + "'{}", + _relative, + _base.toString()); } // We don't need to clear mergedUri since fromRelativeUri() does not set any @@ -473,15 +440,16 @@ Uri Uri::createFromRelativeUri( return mergedUri; } -//============================================================================== Uri Uri::createFromRelativeUri( const Uri& _baseUri, const Uri& _relativeUri, bool _strict) { Uri mergedUri; if (!mergedUri.fromRelativeUri(_baseUri, _relativeUri, _strict)) { - dtwarn << "[Uri::createFromRelativeUri] Failed merging URI '" - << _relativeUri.toString() << "' with base URI '" - << _baseUri.toString() << "'.\n"; + DART_WARN( + "[Uri::createFromRelativeUri] Failed merging URI '{}' with base URI " + "'{}'", + _relativeUri.toString(), + _baseUri.toString()); } // We don't need to clear mergedUri since fromRelativeUri() does not set any @@ -490,7 +458,6 @@ Uri Uri::createFromRelativeUri( return mergedUri; } -//============================================================================== std::string Uri::getUri(const std::string& _input) { Uri uri; @@ -500,7 +467,6 @@ std::string Uri::getUri(const std::string& _input) return ""; } -//============================================================================== std::string Uri::getRelativeUri( const std::string& _base, const std::string& _relative, bool _strict) { @@ -511,7 +477,6 @@ std::string Uri::getRelativeUri( return mergedUri.toString(); } -//============================================================================== std::string Uri::getRelativeUri( const Uri& _base, const std::string& _relative, bool _strict) { @@ -522,7 +487,6 @@ std::string Uri::getRelativeUri( return mergedUri.toString(); } -//============================================================================== std::string Uri::getRelativeUri( const Uri& _baseUri, const Uri& _relativeUri, bool _strict) { @@ -533,13 +497,11 @@ std::string Uri::getRelativeUri( return mergedUri.toString(); } -//============================================================================== std::string Uri::getPath() const { return mPath.get_value_or(""); } -//============================================================================== std::string Uri::getFilesystemPath() const { #ifdef _WIN32 @@ -554,7 +516,6 @@ std::string Uri::getFilesystemPath() const return getPath(); } -//============================================================================== std::string Uri::mergePaths(const Uri& _base, const Uri& _relative) { assert(_base.mPath && "The path component is always defined."); @@ -572,7 +533,6 @@ std::string Uri::mergePaths(const Uri& _base, const Uri& _relative) } } -//============================================================================== std::string Uri::removeDotSegments(const std::string& _path) { // 1. The input buffer is initialized with the now-appended path @@ -646,5 +606,4 @@ std::string Uri::removeDotSegments(const std::string& _path) return output; } -} // namespace common -} // namespace dart +} // namespace dart::v7 diff --git a/dart/v7/uri.hpp b/dart/v7/uri.hpp new file mode 100644 index 0000000000000..ff1ff4c73b154 --- /dev/null +++ b/dart/v7/uri.hpp @@ -0,0 +1,226 @@ +/* + * Copyright (c) The DART development contributors + * All rights reserved. + * + * The list of contributors can be found at: + * https://github.com/dartsim/dart/blob/main/LICENSE + * + * This file is provided under the following "BSD-style" License: + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#pragma once + +#include + +#include + +namespace dart::v7 { + +class UriComponent final +{ +public: + using value_type = std::string; + using reference_type = value_type&; + using reference_const_type = const value_type&; + using pointer_type = value_type*; + using pointer_const_type = const value_type*; + + UriComponent(); + UriComponent(reference_const_type _value); + + operator bool() const; + + bool operator!() const; + + UriComponent& operator=(reference_const_type _value); + + reference_type operator*(); + reference_const_type operator*() const; + + pointer_type operator->(); + pointer_const_type operator->() const; + + void assign(reference_const_type _value); + void reset(); + + reference_type get(); + reference_const_type get() const; + + reference_type get_value_or(reference_type _default); + reference_const_type get_value_or(reference_const_type _default) const; + +private: + bool mExists; + std::string mValue; +}; + +/// The Uri struct provides URI parsing and merging functionality based on RFC +/// 3986. +/// +/// We have Uri as a struct rather than class to expose member variables. Many +/// ResourceRetreiver classes rewrite URIs to other types of URIs (e.g, resolve +/// 'package://' URIs to 'file://' URIs), which is easier to implement if you +/// have direct access to the URI components. +struct Uri final +{ + /// Scheme, e.g. 'http', 'file', 'package' + UriComponent mScheme; + + /// Authority, e.g. 'google.com', 'en.wikipedia.org' + UriComponent mAuthority; + + /// Path, e.g. '/index.html', '/foo/bar.txt' + UriComponent mPath; + + /// Query string, i.e. the part of the URI after the ? + UriComponent mQuery; + + /// Fragment, e.g. the part of the URI after the # + UriComponent mFragment; + + /// Constructor + Uri() = default; + + /// Constructor that takes a URI or local path. Internally, this is equivalent + /// to calling fromStringOrPath(_input) after default constructor. + /// + /// We don't declare this constructor as explicit in order to allow implicit + /// conversion from string so that you can pass in string parameter to a + /// function that takes Uri. + Uri(const std::string& _input); + + /// Constructor that takes a URI or local path as const char*. The behavior is + /// identical to Uri(const std::string&). + Uri(const char* _input); + + /// Clear the URI by reset()ing all components. + void clear(); + + /// Parse a URI from a string; return success. All the components will be + /// cleared on failure. + bool fromString(const std::string& _input); + + /// Parse a local path (i.e. URI with no schema) from a string; return + /// success. Note that the input path should be absolute path. All the + /// components will be cleared on failure. + bool fromPath(const std::string& _path); + + /// Parse a URI or local path (i.e. URI with no schema) from a string; return + /// success. We assume that any string without a scheme is a path. All the + /// components will be cleared on failure. + bool fromStringOrPath(const std::string& _input); + + /// Resolve a relative path reference; return success. All the components will + /// be cleared on failure. + bool fromRelativeUri( + const std::string& _base, + const std::string& _relative, + bool _strict = false); + + /// Resolve a relative path reference; return success. All the components will + /// be cleared on failure. + bool fromRelativeUri( + const char* _base, const char* _relative, bool _strict = false); + + /// Resolve a relative path reference; return success. All the components will + /// be cleared on failure. + bool fromRelativeUri( + const Uri& _base, const std::string& _relative, bool _strict = false); + + /// Resolve a relative path reference; return success. All the components will + /// be cleared on failure. + bool fromRelativeUri( + const Uri& _base, const char* _relative, bool _strict = false); + + /// Resolve a relative path reference; return success. All the components will + /// be cleared on failure. + bool fromRelativeUri( + const Uri& _base, const Uri& _relative, bool _strict = false); + + /// Combine the parts of the URI into a string. + std::string toString() const; + + /// Create URI from a string; return an empty URI on failure. + static Uri createFromString(const std::string& _input); + + /// Create file URI from a string; return an empty URI on failure. + static Uri createFromPath(const std::string& _path); + + /// Create general URI or file URI from a string; return an empty URI on + /// failure. + static Uri createFromStringOrPath(const std::string& _input); + + /// Create URI resolving a relative path reference; return an empty URI on + /// failure. + static Uri createFromRelativeUri( + const std::string& _base, + const std::string& _relative, + bool _strict = false); + + /// Create URI resolving a relative path reference; return an empty URI on + /// failure. + static Uri createFromRelativeUri( + const Uri& _base, const std::string& _relative, bool _strict = false); + + /// Create URI resolving a relative path reference; return an empty URI on + /// failure. + static Uri createFromRelativeUri( + const Uri& _base, const Uri& _relative, bool _strict = false); + + /// Parse a URI from a string; return an empty string on failure. + static std::string getUri(const std::string& _input); + + /// Resolve a relative path reference; return an empty string on failure. + static std::string getRelativeUri( + const std::string& _base, + const std::string& _relative, + bool _strict = false); + + /// Resolve a relative path reference; return an empty string on failure. + static std::string getRelativeUri( + const Uri& _base, const std::string& _relative, bool _strict = false); + + /// Resolve a relative path reference; return an empty string on failure. + static std::string getRelativeUri( + const Uri& _base, const Uri& _relative, bool _strict = false); + + /// Get the path component of the URI as a string. + std::string getPath() const; + + /// Get the path in the local filesystem as a string. You should use this + /// function rather than getPath() if you are trying to access a local file. + /// Note that this function is identical to getPath() for Unix systems, but + /// differ by the leading '/' on Windows. + std::string getFilesystemPath() const; + +private: + /// Implement section 5.2.3 of RFC 3986. + static std::string mergePaths(const Uri& _base, const Uri& _relative); + + /// Implement section 5.2.4 of RFC 3986. + static std::string removeDotSegments(const std::string& _path); +}; + +} // namespace dart::v7 diff --git a/pixi.toml b/pixi.toml index 68663b9ae38cd..6b7d16685c2de 100644 --- a/pixi.toml +++ b/pixi.toml @@ -9,8 +9,11 @@ platforms = ["linux-64", "osx-64", "osx-arm64", "win-64"] [tasks] clean = "rm -rf build" configure-local = { cmd = "cmake -G Ninja -S . -B build -DDART_VERBOSE=ON -DCMAKE_INSTALL_PREFIX=$CONDA_PREFIX" } +build-v7 = { cmd = "cmake --build build --target v7 --parallel", depends_on = [ + "configure", +] } install-local = { cmd = "cmake --install build --prefix $CONDA_PREFIX", depends_on = [ - "configure_local", + "configure-local", "build", ] } example-hello-world = { cmd = "cmake --build build --target hello_world --parallel && ./build/bin/hello_world", depends_on = [ diff --git a/python/dartpy/CMakeLists.txt b/python/dartpy/CMakeLists.txt index b316e86714798..4295c412169d5 100644 --- a/python/dartpy/CMakeLists.txt +++ b/python/dartpy/CMakeLists.txt @@ -43,6 +43,7 @@ target_include_directories(${pybind_module} ) set(dartpy_libraries + v7 dart dart-utils dart-utils-urdf diff --git a/python/dartpy/dartpy.cpp b/python/dartpy/dartpy.cpp index 285421e81be7a..6b52c3d17c4e3 100644 --- a/python/dartpy/dartpy.cpp +++ b/python/dartpy/dartpy.cpp @@ -41,6 +41,7 @@ namespace python { void eigen_geometry(py::module& m); +void dart_v7(py::module& m); void dart_common(py::module& m); void dart_math(py::module& m); void dart_optimizer(py::module& m); @@ -63,6 +64,7 @@ PYBIND11_MODULE(dartpy, m) eigen_geometry(m); + dart_v7(m); dart_common(m); dart_math(m); dart_optimizer(m); diff --git a/python/dartpy/v7/module.cpp b/python/dartpy/v7/module.cpp new file mode 100644 index 0000000000000..b72cff495a80b --- /dev/null +++ b/python/dartpy/v7/module.cpp @@ -0,0 +1,44 @@ +/* + * Copyright (c) The DART development contributors + * All rights reserved. + * + * The list of contributors can be found at: + * https://github.com/dartsim/dart/blob/main/LICENSE + * + * This file is provided under the following "BSD-style" License: + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include + +namespace py = pybind11; + +namespace dart::python { + +void dart_v7(py::module& m) +{ + auto sm = m.def_submodule("v7"); +} + +} // namespace dart::python diff --git a/python/tests/unit/v7/__init__.py b/python/tests/unit/v7/__init__.py new file mode 100644 index 0000000000000..e69de29bb2d1d diff --git a/python/tests/unit/v7/test_import.py b/python/tests/unit/v7/test_import.py new file mode 100644 index 0000000000000..a9baec3895ac1 --- /dev/null +++ b/python/tests/unit/v7/test_import.py @@ -0,0 +1,11 @@ +import dartpy as dart +import pytest + + +def test_import(): + import dartpy.v7 as v7 + dir(v7) + + +if __name__ == "__main__": + pytest.main() diff --git a/tests/unit/CMakeLists.txt b/tests/unit/CMakeLists.txt index 31d5d17a05fe9..641711bb9308b 100644 --- a/tests/unit/CMakeLists.txt +++ b/tests/unit/CMakeLists.txt @@ -1,4 +1,5 @@ # Copyright (c) 2011-2024, The DART development contributors +add_subdirectory(v7) add_subdirectory(common) add_subdirectory(math) diff --git a/tests/unit/v7/CMakeLists.txt b/tests/unit/v7/CMakeLists.txt new file mode 100644 index 0000000000000..6891a6fc750f2 --- /dev/null +++ b/tests/unit/v7/CMakeLists.txt @@ -0,0 +1,9 @@ +# Copyright (c) 2011-2024, The DART development contributors + +dart_build_tests( + TYPE unit + COMPONENT_NAME v7 + TARGET_PREFIX UNIT_v7 + LINK_LIBRARIES v7 + GLOB_SOURCES +) diff --git a/tests/unit/v7/test_empty.cpp b/tests/unit/v7/test_empty.cpp new file mode 100644 index 0000000000000..df1f8523b8ca5 --- /dev/null +++ b/tests/unit/v7/test_empty.cpp @@ -0,0 +1,38 @@ +/* + * Copyright (c) The DART development contributors + * All rights reserved. + * + * The list of contributors can be found at: + * https://github.com/dartsim/dart/blob/main/LICENSE + * + * This file is provided under the following "BSD-style" License: + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include + +TEST(EmptyTest, Empty) +{ + EXPECT_TRUE(true); +}