├── .gitignore ├── CHANGELOG.rst ├── CMakeLists.txt ├── CONTRIBUTING.md ├── Doxyfile ├── LICENSE ├── QUALITY_DECLARATION.md ├── README.md ├── cmake └── check_c_compiler_uses_glibc.cmake ├── include └── rcutils │ ├── allocator.h │ ├── cmdline_parser.h │ ├── env.h │ ├── error_handling.h │ ├── filesystem.h │ ├── find.h │ ├── format_string.h │ ├── isalnum_no_locale.h │ ├── join.h │ ├── logging.h │ ├── macros.h │ ├── process.h │ ├── qsort.h │ ├── repl_str.h │ ├── sha256.h │ ├── shared_library.h │ ├── snprintf.h │ ├── split.h │ ├── stdatomic_helper.h │ ├── stdatomic_helper │ ├── gcc │ │ └── stdatomic.h │ └── win32 │ │ └── stdatomic.h │ ├── strcasecmp.h │ ├── strdup.h │ ├── strerror.h │ ├── testing │ └── fault_injection.h │ ├── time.h │ ├── types.h │ ├── types │ ├── array_list.h │ ├── char_array.h │ ├── hash_map.h │ ├── rcutils_ret.h │ ├── string_array.h │ ├── string_map.h │ └── uint8_array.h │ ├── visibility_control.h │ └── visibility_control_macros.h ├── package.xml ├── rcutils ├── __init__.py └── logging.py ├── resource └── logging_macros.h.em ├── src ├── allocator.c ├── array_list.c ├── char_array.c ├── cmdline_parser.c ├── common.h ├── env.c ├── error_handling.c ├── error_handling_helpers.h ├── filesystem.c ├── find.c ├── format_string.c ├── hash_map.c ├── join.c ├── logging.c ├── process.c ├── qsort.c ├── repl_str.c ├── sha256.c ├── shared_library.c ├── snprintf.c ├── split.c ├── strcasecmp.c ├── strdup.c ├── strerror.c ├── string_array.c ├── string_map.c ├── testing │ └── fault_injection.c ├── time.c ├── time_unix.c ├── time_win32.c └── uint8_array.c └── test ├── allocator_testing_utils.h ├── benchmark ├── benchmark_error_handling.cpp └── benchmark_logging.cpp ├── dummy_folder └── dummy.dummy ├── dummy_folder_with_subdir ├── dummy-subfolder │ ├── dummy-subfolder │ │ └── dummy.dummy │ └── dummy.dummy └── dummy.dummy ├── dummy_readable_file.txt ├── dummy_readable_writable_file.txt ├── dummy_shared_library ├── dummy_shared_library.c └── dummy_shared_library.h ├── mocking_utils ├── filesystem.hpp ├── patch.hpp └── remove_noexcept.hpp ├── test_allocator.cpp ├── test_array_list.cpp ├── test_atomics.c ├── test_char_array.cpp ├── test_cmdline_parser.cpp ├── test_env.cpp ├── test_error_handling.cpp ├── test_error_handling_helpers.cpp ├── test_filesystem.cpp ├── test_find.cpp ├── test_format_string.cpp ├── test_hash_map.cpp ├── test_isalnum_no_locale.cpp ├── test_join.cpp ├── test_logging.cpp ├── test_logging_bad_env.cpp ├── test_logging_console_output_handler.cpp ├── test_logging_custom_env.cpp ├── test_logging_enable_for.cpp ├── test_logging_long_messages.cpp ├── test_logging_long_messages.py ├── test_logging_long_messages.txt ├── test_logging_macros.c ├── test_logging_macros.cpp ├── test_logging_output_format.py ├── test_logging_output_format_complicated_escape.regex ├── test_logging_output_format_edge_cases.txt ├── test_logging_output_format_escape_sequence.regex ├── test_logging_output_format_long.txt ├── test_logging_output_format_no_tokens.txt ├── test_logging_output_format_simple_escape.regex ├── test_logging_output_timestamps.regex ├── test_macros.cpp ├── test_process.cpp ├── test_repl_str.cpp ├── test_sha256.cpp ├── test_shared_library.cpp ├── test_snprintf.cpp ├── test_split.cpp ├── test_strcasecmp.cpp ├── test_strdup.cpp ├── test_strerror.cpp ├── test_string_array.cpp ├── test_string_map.cpp ├── test_time.cpp ├── test_uint8_array.cpp └── time_bomb_allocator_testing_utils.h /.gitignore: -------------------------------------------------------------------------------- 1 | __pycache__ 2 | doc_output 3 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | Any contribution that you make to this repository will 2 | be under the Apache 2 License, as dictated by that 3 | [license](http://www.apache.org/licenses/LICENSE-2.0.html): 4 | 5 | ~~~ 6 | 5. Submission of Contributions. Unless You explicitly state otherwise, 7 | any Contribution intentionally submitted for inclusion in the Work 8 | by You to the Licensor shall be under the terms and conditions of 9 | this License, without any additional terms or conditions. 10 | Notwithstanding the above, nothing herein shall supersede or modify 11 | the terms of any separate license agreement you may have executed 12 | with Licensor regarding such Contributions. 13 | ~~~ 14 | 15 | Contributors must sign-off each commit by adding a `Signed-off-by: ...` 16 | line to commit messages to certify that they have the right to submit 17 | the code they are contributing to the project according to the 18 | [Developer Certificate of Origin (DCO)](https://developercertificate.org/). 19 | -------------------------------------------------------------------------------- /Doxyfile: -------------------------------------------------------------------------------- 1 | # All settings not listed here will use the Doxygen default values. 2 | 3 | PROJECT_NAME = "rcutils" 4 | PROJECT_NUMBER = master 5 | PROJECT_BRIEF = "C API providing common utilities and data structures." 6 | 7 | # Use these lines to include the generated logging_macro.h (update install path if needed) 8 | # Otherwise just generate for the local (non-generated header files) 9 | INPUT = CONTRIBUTING.md README.md QUALITY_DECLARATION.md ./include 10 | EXCLUDE_PATTERNS = */stdatomic_helper/* 11 | USE_MDFILE_AS_MAINPAGE = README.md 12 | RECURSIVE = YES 13 | OUTPUT_DIRECTORY = doc_output 14 | 15 | EXTRACT_ALL = YES 16 | SORT_MEMBER_DOCS = NO 17 | 18 | GENERATE_LATEX = NO 19 | 20 | ENABLE_PREPROCESSING = YES 21 | MACRO_EXPANSION = YES 22 | EXPAND_ONLY_PREDEF = YES 23 | PREDEFINED += RCUTILS_PUBLIC= 24 | PREDEFINED += RCUTILS_PUBLIC_TYPE= 25 | PREDEFINED += RCUTILS_WARN_UNUSED= 26 | PREDEFINED += RCUTILS_ENABLE_FAULT_INJECTION= 27 | PREDEFINED += DOXYGEN_ONLY 28 | 29 | # Tag files that do not exist will produce a warning and cross-project linking will not work. 30 | TAGFILES += "../../../doxygen_tag_files/cppreference-doxygen-web.tag.xml=http://en.cppreference.com/w/" 31 | # Uncomment to generate tag files for cross-project linking. 32 | #GENERATE_TAGFILE = "../../../doxygen_tag_files/rcutils.tag" 33 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # rcutils: ROS 2 C Utilities data structures 2 | 3 | `rcutils` is a C API consisting of macros, functions, and data structures used through out the ROS 2 code base. 4 | 5 | ## Quality Declaration 6 | 7 | This package claims to be in the **Quality Level 1** category, see the [Quality Declaration](./QUALITY_DECLARATION.md) for more details. 8 | 9 | ## API 10 | 11 | The API is a combination of parts: 12 | 13 | - Allocator concept, used to inject the allocating and deallocating methods into a function or type. 14 | - rcutils_allocator_t 15 | - rcutils/allocator.h 16 | - Command line interface utilities: 17 | - rcutils/cmdline_parser.h 18 | - Utilities for setting error states (error message, file, and line number) like `strerror` for `errno`: 19 | - rcutils/error_handling.h 20 | - Some basic filesystem utilities like checking for path existence, getting the cwd, etc...: 21 | - rcutils/filesystem.h 22 | - A C string find method: 23 | - rcutils_find() 24 | - rcutils_find_last() 25 | - rcutils/find.h 26 | - A convenient string formatting function, which takes a custom allocator: 27 | - rcutils_format_string() 28 | - rcutils/format_string.h 29 | - Functions for interfacing with process environment variables: 30 | - rcutils_get_env() 31 | - rcutils_get_home_dir() 32 | - rcutils_set_env() 33 | - rcutils/env.h 34 | - Extensible logging macros: 35 | - Some examples (not exhaustive): 36 | - RCUTILS_LOG_DEBUG() 37 | - RCUTILS_LOG_INFO_NAMED() 38 | - RCUTILS_LOG_WARN_ONCE() 39 | - RCUTILS_LOG_ERROR_SKIPFIRST_NAMED() 40 | - rcutils/logging_macros.h 41 | - rcutils/logging.h 42 | - Some basic utilities to load, unload and get symbols from shared libraries at run-time. 43 | - rcutils/shared_library.h 44 | - A string replacement function which takes an allocator, based on http://creativeandcritical.net/str-replace-c: 45 | - rcutils_repl_str() 46 | - rcutils/repl_str.h 47 | - String splitting functions which take a custom allocator: 48 | - rcutils_split() 49 | - rcutils_split_last() 50 | - rcutils/split.h 51 | - A version of `strdup` which takes an allocator: 52 | - rcutils_strdup() 53 | - rcutils/strdup.h 54 | - Portable implementations of "get system time" and "get steady time": 55 | - rcutils_system_time_now() 56 | - rcutils_steady_time_now() 57 | - rcutils/time.h 58 | - Some useful data structures: 59 | - A "string array" data structure (analogous to `std::vector`): 60 | - rcutils_string_array_t 61 | - rcutils/types/string_array.h 62 | - A "string-string map" data structure (analogous to `std::map`) 63 | - rcutils_string_map_t 64 | - rcutils/types/string_map.h 65 | - Macros for controlling symbol visibility and linkage for this library: 66 | - rcutils/visibility_control.h 67 | -------------------------------------------------------------------------------- /cmake/check_c_compiler_uses_glibc.cmake: -------------------------------------------------------------------------------- 1 | # Copyright 2020 Open Source Robotics Foundation, Inc. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | # 16 | # Checks if the C compiler uses glibc. 17 | # 18 | # @private 19 | # 20 | function(check_c_compiler_uses_glibc result_variable) 21 | include(CheckCSourceCompiles) 22 | 23 | set(GLIBC_TEST_CODE [====[ 24 | #include 25 | 26 | int main() { 27 | void * buffer[1]; 28 | int size = sizeof(buffer) / sizeof(void *); 29 | backtrace(&buffer, size); 30 | return 0; 31 | } 32 | ]====]) 33 | 34 | check_c_source_compiles("${GLIBC_TEST_CODE}" ${result_variable}) 35 | set(${result_variable} ${result_variable} PARENT_SCOPE) 36 | endfunction() 37 | -------------------------------------------------------------------------------- /include/rcutils/allocator.h: -------------------------------------------------------------------------------- 1 | // Copyright 2015 Open Source Robotics Foundation, Inc. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | /// \file 16 | 17 | #ifndef RCUTILS__ALLOCATOR_H_ 18 | #define RCUTILS__ALLOCATOR_H_ 19 | 20 | #ifdef __cplusplus 21 | extern "C" 22 | { 23 | #endif 24 | 25 | #include 26 | #include 27 | 28 | #include "rcutils/macros.h" 29 | #include "rcutils/types/rcutils_ret.h" 30 | #include "rcutils/visibility_control.h" 31 | 32 | /// Encapsulation of an allocator. 33 | /** 34 | * The default allocator uses malloc(), free(), calloc(), and realloc(). 35 | * It can be obtained using rcutils_get_default_allocator(). 36 | * 37 | * The allocator should be trivially copyable. 38 | * Meaning that the struct should continue to work after being assignment 39 | * copied into a new struct. 40 | * Specifically the object pointed to by the state pointer should remain valid 41 | * until all uses of the allocator have been made. 42 | * Particular care should be taken when giving an allocator to functions like 43 | * rcutils_*_init() where it is stored within another object and used later. 44 | * Developers should note that, while the fields of a const-qualified allocator 45 | * struct cannot be modified, the state of the allocator can be modified. 46 | */ 47 | typedef struct rcutils_allocator_s 48 | { 49 | /// Allocate memory, given a size and the `state` pointer. 50 | /** An error should be indicated by returning `NULL`. */ 51 | void * (*allocate)(size_t size, void * state); 52 | /// Deallocate previously allocated memory, mimicking free(). 53 | /** Also takes the `state` pointer. */ 54 | void (* deallocate)(void * pointer, void * state); 55 | /// Reallocate if possible, otherwise it deallocates and allocates. 56 | /** 57 | * Also takes the `state` pointer. 58 | * 59 | * If unsupported then do deallocate and then allocate. 60 | * This should behave as realloc() does, as opposed to posix's 61 | * [reallocf](https://linux.die.net/man/3/reallocf), i.e. the memory given 62 | * by pointer will not be free'd automatically if realloc() fails. 63 | * For reallocf-like behavior use rcutils_reallocf(). 64 | * This function must be able to take an input pointer of `NULL` and succeed. 65 | */ 66 | void * (*reallocate)(void * pointer, size_t size, void * state); 67 | /// Allocate memory with all elements set to zero, given a number of elements and their size. 68 | /** An error should be indicated by returning `NULL`. */ 69 | void * (*zero_allocate)(size_t number_of_elements, size_t size_of_element, void * state); 70 | /// Implementation defined state storage. 71 | /** 72 | * This is passed as the final parameter to other allocator functions. 73 | * Note that the contents of the state can be modified even in const-qualified 74 | * allocator objects. 75 | */ 76 | void * state; 77 | } rcutils_allocator_t; 78 | 79 | /// Return a zero initialized allocator. 80 | /** 81 | * Note that this is an invalid allocator and should only be used as a placeholder. 82 | */ 83 | RCUTILS_PUBLIC 84 | RCUTILS_WARN_UNUSED 85 | rcutils_allocator_t 86 | rcutils_get_zero_initialized_allocator(void); 87 | 88 | /// Return a properly initialized rcutils_allocator_t with default values. 89 | /** 90 | * This defaults to: 91 | * 92 | * - allocate = wraps malloc() 93 | * - deallocate = wraps free() 94 | * - reallocate = wraps realloc() 95 | * - zero_allocate = wraps calloc() 96 | * - state = `NULL` 97 | * 98 | *
99 | * Attribute | Adherence 100 | * ------------------ | ------------- 101 | * Allocates Memory | No 102 | * Thread-Safe | Yes 103 | * Uses Atomics | No 104 | * Lock-Free | Yes 105 | */ 106 | RCUTILS_PUBLIC 107 | RCUTILS_WARN_UNUSED 108 | rcutils_allocator_t 109 | rcutils_get_default_allocator(void); 110 | 111 | /// Return true if the given allocator has non-null function pointers. 112 | /** 113 | * \param[in] allocator to be checked by the function 114 | * \return `true` if the allocator is valid, `false` otherwise. 115 | */ 116 | RCUTILS_PUBLIC 117 | RCUTILS_WARN_UNUSED 118 | bool 119 | rcutils_allocator_is_valid(const rcutils_allocator_t * allocator); 120 | 121 | /// Check the given allocator and run fail_statement if it is not valid. 122 | #define RCUTILS_CHECK_ALLOCATOR(allocator, fail_statement) \ 123 | if (!rcutils_allocator_is_valid(allocator)) { \ 124 | fail_statement; \ 125 | } 126 | 127 | /// Check the given allocator, and set the message in msg and run fail_statement if it is not valid. 128 | #define RCUTILS_CHECK_ALLOCATOR_WITH_MSG(allocator, msg, fail_statement) \ 129 | if (!rcutils_allocator_is_valid(allocator)) { \ 130 | RCUTILS_SET_ERROR_MSG(msg); \ 131 | fail_statement; \ 132 | } 133 | 134 | /// Emulate the behavior of [reallocf](https://linux.die.net/man/3/reallocf). 135 | /** 136 | * This function will return `NULL` if the allocator is `NULL` or has `NULL` for 137 | * function pointer fields. 138 | * \param[inout] pointer to the memory which will be reallocated 139 | * \param[in] size in bytes 140 | * \param[in] allocator to be used to allocate and deallocate memory 141 | */ 142 | RCUTILS_PUBLIC 143 | RCUTILS_WARN_UNUSED 144 | void * 145 | rcutils_reallocf(void * pointer, size_t size, rcutils_allocator_t * allocator); 146 | 147 | #ifdef __cplusplus 148 | } 149 | #endif 150 | 151 | #endif // RCUTILS__ALLOCATOR_H_ 152 | -------------------------------------------------------------------------------- /include/rcutils/cmdline_parser.h: -------------------------------------------------------------------------------- 1 | // Copyright 2017 Open Source Robotics Foundation, Inc. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | /// \file 16 | 17 | #ifndef RCUTILS__CMDLINE_PARSER_H_ 18 | #define RCUTILS__CMDLINE_PARSER_H_ 19 | 20 | #ifdef __cplusplus 21 | extern "C" 22 | { 23 | #endif 24 | 25 | #include 26 | 27 | #include "rcutils/visibility_control.h" 28 | 29 | /// Return `true` if the option is defined in the command line arguments or `false` otherwise. 30 | /** 31 | * \param[in] begin first element to check in the array 32 | * \param[in] end last element to check in the array 33 | * \param[in] option string to find in the array of arguments 34 | * \return `true` if the option exists, or 35 | * \return `false` otherwise. 36 | */ 37 | RCUTILS_PUBLIC 38 | bool 39 | rcutils_cli_option_exist(char ** begin, char ** end, const char * option); 40 | 41 | /// Return the value for a specific option of the command line arguments. 42 | /** 43 | * \param[in] begin first element to check in the array 44 | * \param[in] end last element to check in the array 45 | * \param[in] option string to find in the array of arguments 46 | * \return the value for a specific option of the command line arguments, or 47 | * \return `NULL` if the option doesn't exist. 48 | */ 49 | RCUTILS_PUBLIC 50 | char * 51 | rcutils_cli_get_option(char ** begin, char ** end, const char * option); 52 | 53 | #ifdef __cplusplus 54 | } 55 | #endif 56 | 57 | #endif // RCUTILS__CMDLINE_PARSER_H_ 58 | -------------------------------------------------------------------------------- /include/rcutils/find.h: -------------------------------------------------------------------------------- 1 | // Copyright 2017 Open Source Robotics Foundation, Inc. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | /// \file 16 | 17 | #ifndef RCUTILS__FIND_H_ 18 | #define RCUTILS__FIND_H_ 19 | 20 | #ifdef __cplusplus 21 | extern "C" 22 | { 23 | #endif 24 | 25 | #include "rcutils/types.h" 26 | #include "rcutils/visibility_control.h" 27 | 28 | /// Return the first index of a character in a string. 29 | /** 30 | * Search in a string for the first occurence of a delimiter. 31 | * 32 | * \param[in] str null terminated c string to search 33 | * \param[in] delimiter the character to search for 34 | * \return the index of the first occurence of the delimiter if found, or 35 | * \return `SIZE_MAX` for invalid arguments, or 36 | * \return `SIZE_MAX` if the delimiter is not found. 37 | */ 38 | RCUTILS_PUBLIC 39 | size_t 40 | rcutils_find(const char * str, char delimiter); 41 | 42 | /// Return the first index of a character in a string of specified length. 43 | /** 44 | * Identical to rcutils_find_first() but without relying on the string to be a 45 | * null terminated c string. 46 | * 47 | * \param[in] str string to search 48 | * \param[in] delimiter the character to search for 49 | * \param[in] string_length length of the string to search 50 | * \return the index of the first occurence of the delimiter if found, or 51 | * \return `SIZE_MAX` for invalid arguments, or 52 | * \return `SIZE_MAX` if the delimiter is not found. 53 | */ 54 | RCUTILS_PUBLIC 55 | size_t 56 | rcutils_findn(const char * str, char delimiter, size_t string_length); 57 | 58 | /// Return the last index of a character in a string. 59 | /** 60 | * Search in a string for the last occurence of a delimiter. 61 | * 62 | * \param[in] str null terminated c string to search 63 | * \param[in] delimiter the character to search for 64 | * \return the index of the last occurence of the delimiter if found, or 65 | * \return `SIZE_MAX` for invalid arguments, or 66 | * \return `SIZE_MAX` if the delimiter is not found. 67 | */ 68 | RCUTILS_PUBLIC 69 | size_t 70 | rcutils_find_last(const char * str, char delimiter); 71 | 72 | /// Return the last index of a character in a string of specifed length. 73 | /** 74 | * Identical to rcutils_find_last() but without relying on the string to be a 75 | * null terminated c string. 76 | * 77 | * \param[in] str string to search 78 | * \param[in] delimiter the character to search for 79 | * \param[in] string_length length of the string to search 80 | * \return the index of the last occurence of the delimiter if found, or 81 | * \return `SIZE_MAX` for invalid arguments, or 82 | * \return `SIZE_MAX` if the delimiter is not found. 83 | */ 84 | RCUTILS_PUBLIC 85 | size_t 86 | rcutils_find_lastn(const char * str, char delimiter, size_t string_length); 87 | 88 | #ifdef __cplusplus 89 | } 90 | #endif 91 | 92 | #endif // RCUTILS__FIND_H_ 93 | -------------------------------------------------------------------------------- /include/rcutils/format_string.h: -------------------------------------------------------------------------------- 1 | // Copyright 2017 Open Source Robotics Foundation, Inc. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #ifndef RCUTILS__FORMAT_STRING_H_ 16 | #define RCUTILS__FORMAT_STRING_H_ 17 | 18 | #ifdef __cplusplus 19 | extern "C" 20 | { 21 | #endif 22 | 23 | #include 24 | 25 | #include "rcutils/allocator.h" 26 | #include "rcutils/macros.h" 27 | #include "rcutils/visibility_control.h" 28 | 29 | /// Return a newly allocated string, created with a format string. 30 | /** 31 | * This function is identical to rcutils_format_string_limit() except it has an 32 | * implicit limit of 2048. 33 | * For longer format strings, see rcutils_format_string_limit(). 34 | */ 35 | #define rcutils_format_string(allocator, format_string, ...) \ 36 | rcutils_format_string_limit(allocator, 2048, format_string, __VA_ARGS__) 37 | 38 | /// Return a newly allocated string, created with a format string up to a limit. 39 | /** 40 | * This function uses snprintf_s to determine the length of the resulting 41 | * string and allocates storage for the resulting string, formats it, and 42 | * then returns the result. 43 | * 44 | * This function can fail and therefore return null if the format_string is 45 | * null or if memory allocation fails or if snprintf_s fails. 46 | * An error message is not set in any case. 47 | * 48 | * Output strings that would be longer than the given limit are truncated. 49 | * 50 | * All returned strings are null terminated. 51 | * 52 | * The format string is passed to snprintf_s(), see its documentation for 53 | * how to use the format string. 54 | * 55 | * The returned string must be deallocated using the same allocator given once 56 | * it is no longer needed. 57 | * 58 | * \see rcutils_snprintf() 59 | * 60 | * \param[in] allocator the allocator to use for allocation 61 | * \param[in] limit maximum length of the output string 62 | * \param[in] format_string format of the output, must be null terminated 63 | * \return The newly allocated and format output string, or 64 | * \return `NULL` if there was an error. 65 | */ 66 | RCUTILS_PUBLIC 67 | RCUTILS_WARN_UNUSED 68 | char * 69 | rcutils_format_string_limit( 70 | rcutils_allocator_t allocator, 71 | size_t limit, 72 | const char * format_string, 73 | ...) 74 | /// @cond Doxygen_Suppress 75 | RCUTILS_ATTRIBUTE_PRINTF_FORMAT(3, 4) 76 | /// @endcond 77 | ; 78 | 79 | #ifdef __cplusplus 80 | } 81 | #endif 82 | 83 | #endif // RCUTILS__FORMAT_STRING_H_ 84 | -------------------------------------------------------------------------------- /include/rcutils/isalnum_no_locale.h: -------------------------------------------------------------------------------- 1 | // Copyright 2017 Open Source Robotics Foundation, Inc. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | /// \file 16 | 17 | #ifndef RCUTILS__ISALNUM_NO_LOCALE_H_ 18 | #define RCUTILS__ISALNUM_NO_LOCALE_H_ 19 | 20 | #ifdef __cplusplus 21 | extern "C" 22 | { 23 | #endif 24 | 25 | /// Custom isalnum() which is not affected by locale. 26 | static inline 27 | bool 28 | rcutils_isalnum_no_locale(char c) 29 | { 30 | // if in '0', ..., '9', then ok 31 | if (c >= 0x30 /*0*/ && c <= 0x39 /*9*/) { 32 | return true; 33 | } 34 | // if in 'A', ..., 'Z', then ok 35 | if (c >= 0x41 /*A*/ && c <= 0x5a /*Z*/) { 36 | return true; 37 | } 38 | // if in 'a', ..., 'z', then ok 39 | if (c >= 0x61 /*a*/ && c <= 0x7a /*z*/) { 40 | return true; 41 | } 42 | return false; 43 | } 44 | 45 | #ifdef __cplusplus 46 | } 47 | #endif 48 | 49 | #endif // RCUTILS__ISALNUM_NO_LOCALE_H_ 50 | -------------------------------------------------------------------------------- /include/rcutils/join.h: -------------------------------------------------------------------------------- 1 | // Copyright 2025 Open Source Robotics Foundation, Inc. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | /// \file 16 | 17 | #ifndef RCUTILS__JOIN_H_ 18 | #define RCUTILS__JOIN_H_ 19 | 20 | #ifdef __cplusplus 21 | extern "C" 22 | { 23 | #endif 24 | 25 | #include "rcutils/allocator.h" 26 | #include "rcutils/types.h" 27 | #include "rcutils/visibility_control.h" 28 | 29 | /// Concatenate members of an array into a single string 30 | /** 31 | * \param[in] string_array with the tokens to concatenate 32 | * \param[in] separator string to be inserted between tokens 33 | * \param[in] allocator for allocating new memory for the output string 34 | * \return concatenated string, or 35 | * \return `NULL` if there is an error. 36 | */ 37 | RCUTILS_PUBLIC 38 | char * 39 | rcutils_join( 40 | const rcutils_string_array_t * string_array, 41 | const char * separator, 42 | rcutils_allocator_t allocator); 43 | 44 | #ifdef __cplusplus 45 | } 46 | #endif 47 | 48 | #endif // RCUTILS__JOIN_H_ 49 | -------------------------------------------------------------------------------- /include/rcutils/process.h: -------------------------------------------------------------------------------- 1 | // Copyright 2019 Open Source Robotics Foundation, Inc. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | /// \file 16 | 17 | #ifndef RCUTILS__PROCESS_H_ 18 | #define RCUTILS__PROCESS_H_ 19 | 20 | #ifdef __cplusplus 21 | extern "C" 22 | { 23 | #endif 24 | 25 | #if defined _WIN32 || defined __CYGWIN__ 26 | #ifndef WIN32_LEAN_AND_MEAN 27 | #define WIN32_LEAN_AND_MEAN 28 | #endif 29 | 30 | #ifndef NOMINMAX 31 | #define NOMINMAX 32 | #endif 33 | // When building with MSVC 19.28.29333.0 on Windows 10 (as of 2020-11-11), 34 | // there appears to be a problem with winbase.h (which is included by 35 | // Windows.h). In particular, warnings of the form: 36 | // 37 | // warning C5105: macro expansion producing 'defined' has undefined behavior 38 | // 39 | // See https://developercommunity.visualstudio.com/content/problem/695656/wdk-and-sdk-are-not-compatible-with-experimentalpr.html 40 | // for more information. For now disable that warning when including windows.h 41 | #pragma warning(push) 42 | #pragma warning(disable : 5105) 43 | #include 44 | #pragma warning(pop) 45 | #endif 46 | 47 | #include "rcutils/allocator.h" 48 | #include "rcutils/macros.h" 49 | #include "rcutils/types/string_array.h" 50 | #include "rcutils/visibility_control.h" 51 | 52 | /// Retrieve the current process ID. 53 | /** 54 | * This function returns the current process ID, and is always successful. 55 | * 56 | * This function is thread-safe. 57 | * 58 | * \return The current process ID. 59 | */ 60 | RCUTILS_PUBLIC 61 | RCUTILS_WARN_UNUSED 62 | int rcutils_get_pid(void); 63 | 64 | /// Retrieve the current executable name. 65 | /** 66 | * This function portably retrieves the current program name and returns 67 | * a copy of it. 68 | * It is up to the caller to free the memory. 69 | * 70 | * This function is thread-safe. 71 | * 72 | * \param[in] allocator the allocator to use 73 | * \return The program name on success, or 74 | * \return NULL on failure. 75 | */ 76 | RCUTILS_PUBLIC 77 | RCUTILS_WARN_UNUSED 78 | char * rcutils_get_executable_name(rcutils_allocator_t allocator); 79 | 80 | /// Information about a subprocess created by this process 81 | typedef struct rcutils_process_s 82 | { 83 | #if defined _WIN32 || defined __CYGWIN__ 84 | /// The open handle to the process. 85 | HANDLE handle; 86 | #endif 87 | 88 | /// The process ID of the process. 89 | int pid; 90 | 91 | /// The allocator used to allocate and free memory for the process. 92 | rcutils_allocator_t allocator; 93 | } rcutils_process_t; 94 | 95 | /// Execute a command as a new subprocess. 96 | /** 97 | * This function runs a command by creating a new subprocess of the currently 98 | * running process. 99 | * 100 | * \param[in] args the command line arguments to be run 101 | * \param[in] allocator the allocator to use 102 | * \return The successfully created subprocess, or 103 | * \return NULL on failure. 104 | */ 105 | RCUTILS_PUBLIC 106 | RCUTILS_WARN_UNUSED 107 | rcutils_process_t * 108 | rcutils_start_process( 109 | const rcutils_string_array_t * args, 110 | rcutils_allocator_t * allocator); 111 | 112 | /// Release resources allocated when a subprocess was created. 113 | /** 114 | * Closes, cleans up, and deallocates resources which were allocated by 115 | * rcutils_start_process(), including the rcutils_process_t itself. 116 | * \param[in] process the process to be closed and deallocated 117 | */ 118 | RCUTILS_PUBLIC 119 | void rcutils_process_close(rcutils_process_t * process); 120 | 121 | /// Blocks until the given subprocess has been has exited. 122 | /** 123 | * Wait for a subprocess to terminate, and optionally retrieve the exit code 124 | * from that process. 125 | * Upon successful invocation of this function, subsequent calls will produce 126 | * undefined behavior. It should typically be followed by a call to 127 | * rcutils_process_close(). 128 | * \param[in] process The process to wait for 129 | * \param[out] status The exit code from that process 130 | * \return #RCUTILS_RET_OK if the process exited, or 131 | * \return #RCUTILS_RET_INVALID_ARGUMENT if the process argument is invalid 132 | * \return #RCUTILS_RET_ERROR if an unexpected error occurs. 133 | */ 134 | RCUTILS_PUBLIC 135 | RCUTILS_WARN_UNUSED 136 | rcutils_ret_t 137 | rcutils_process_wait(const rcutils_process_t * process, int * status); 138 | 139 | #ifdef __cplusplus 140 | } 141 | #endif 142 | 143 | #endif // RCUTILS__PROCESS_H_ 144 | -------------------------------------------------------------------------------- /include/rcutils/qsort.h: -------------------------------------------------------------------------------- 1 | // Copyright 2020 Open Source Robotics Foundation, Inc. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | /// \file 16 | 17 | #ifndef RCUTILS__QSORT_H_ 18 | #define RCUTILS__QSORT_H_ 19 | 20 | #ifdef __cplusplus 21 | extern "C" 22 | { 23 | #endif 24 | 25 | #include "rcutils/macros.h" 26 | #include "rcutils/types/rcutils_ret.h" 27 | #include "rcutils/visibility_control.h" 28 | 29 | /// Interface to qsort with rcutils-style argument validation. 30 | /** 31 | * This function changes the order of the elements in the array so that they 32 | * are in ascending order according to the given comparison function. 33 | * 34 | * This function is thread-safe. 35 | * 36 | * \param[inout] ptr object whose elements should be sorted. 37 | * \param[in] count number of elements present in the object. 38 | * \param[in] size size of each element, in bytes. 39 | * \param[in] comp function used to compare two elements. 40 | * \return #RCUTILS_RET_OK if successful, or 41 | * \return #RCUTILS_RET_INVALID_ARGUMENT for invalid arguments, or 42 | * \return #RCUTILS_RET_ERROR if an unknown error occurs. 43 | */ 44 | RCUTILS_PUBLIC 45 | RCUTILS_WARN_UNUSED 46 | rcutils_ret_t 47 | rcutils_qsort(void * ptr, size_t count, size_t size, int (* comp)(const void *, const void *)); 48 | 49 | #ifdef __cplusplus 50 | } 51 | #endif 52 | 53 | #endif // RCUTILS__QSORT_H_ 54 | -------------------------------------------------------------------------------- /include/rcutils/sha256.h: -------------------------------------------------------------------------------- 1 | // Copyright 2023 Open Source Robotics Foundation, Inc. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | /** \file sha256.h 16 | * \brief SHA256 implementation 17 | * 18 | * This contains an implementation of the SHA256 algorithm 19 | * It was originally copied from Brad Conte 20 | * https://github.com/B-Con/crypto-algorithms/blob/master/sha256.c 21 | * and modified to meet ros2 code formatting and compiler warning requirements. 22 | * Algorithm specification can be found here: 23 | * http://csrc.nist.gov/publications/fips/fips180-2/fips180-2withchangenotice.pdf 24 | * This implementation uses little endian byte order. 25 | * This implementation makes no security guarantees, its use case if for 26 | * non-sensitive comparison of message digests. 27 | */ 28 | 29 | #ifndef RCUTILS__SHA256_H_ 30 | #define RCUTILS__SHA256_H_ 31 | 32 | #ifdef __cplusplus 33 | extern "C" 34 | { 35 | #endif 36 | 37 | #include 38 | #include 39 | 40 | #include "rcutils/visibility_control.h" 41 | 42 | #define RCUTILS_SHA256_BLOCK_SIZE 32 43 | 44 | typedef struct RCUTILS_PUBLIC_TYPE rcutils_sha256_ctx_s 45 | { 46 | uint8_t data[64]; 47 | size_t datalen; 48 | uint64_t bitlen; 49 | uint32_t state[8]; 50 | } rcutils_sha256_ctx_t; 51 | 52 | /// Initialize the sha256 algorithm context with starting state. 53 | /** 54 | * Call this on any new context before starting to input data. 55 | * 56 | * \param[inout] ctx 57 | * \return void 58 | */ 59 | RCUTILS_PUBLIC 60 | void rcutils_sha256_init(rcutils_sha256_ctx_t * ctx); 61 | 62 | /// Add data to the sha256 algorithm 63 | /** 64 | * This may be called repeatedly on an initialized context. 65 | * 66 | * \param[inout] ctx Initialized sha256 context struct 67 | * \param[in] data Data to add to the total message being hashed 68 | * \param[in] data_len Size of the input data. 69 | * \return void 70 | */ 71 | RCUTILS_PUBLIC 72 | void rcutils_sha256_update(rcutils_sha256_ctx_t * ctx, const uint8_t * data, size_t data_len); 73 | 74 | /// Finalize and output sha256 hash for all data added. 75 | /** 76 | * Call only once on a context that has been initialized, and optionally updated with data. 77 | * 78 | * \param[inout] ctx Initialized sha256 context struct 79 | * \param[out] output_hash Calculated sha256 message digest to be filled 80 | * \return void 81 | */ 82 | #ifdef DOXYGEN_ONLY 83 | // One of the tools used by rosdoc2 misunderstands uint8_t[] as a uint8_t, 84 | // so make it a pointer for documentation purposes. 85 | RCUTILS_PUBLIC 86 | void rcutils_sha256_final( 87 | rcutils_sha256_ctx_t * ctx, 88 | uint8_t * output_hash); 89 | #else 90 | RCUTILS_PUBLIC 91 | void rcutils_sha256_final( 92 | rcutils_sha256_ctx_t * ctx, 93 | uint8_t output_hash[RCUTILS_SHA256_BLOCK_SIZE]); 94 | #endif 95 | 96 | #ifdef __cplusplus 97 | } 98 | #endif 99 | 100 | #endif // RCUTILS__SHA256_H_ 101 | -------------------------------------------------------------------------------- /include/rcutils/shared_library.h: -------------------------------------------------------------------------------- 1 | // Copyright 2020 Open Source Robotics Foundation, Inc. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | /// \file 16 | 17 | #ifndef RCUTILS__SHARED_LIBRARY_H_ 18 | #define RCUTILS__SHARED_LIBRARY_H_ 19 | 20 | #ifdef __cplusplus 21 | extern "C" 22 | { 23 | #endif 24 | 25 | #include 26 | 27 | #include "rcutils/allocator.h" 28 | #include "rcutils/types/rcutils_ret.h" 29 | #include "rcutils/macros.h" 30 | #include "rcutils/visibility_control.h" 31 | 32 | /// Handle to a loaded shared library. 33 | typedef struct RCUTILS_PUBLIC_TYPE rcutils_shared_library_s 34 | { 35 | /// The platform-specific pointer to the shared library 36 | void * lib_pointer; 37 | /// The path of the shared_library 38 | char * library_path; 39 | /// allocator 40 | rcutils_allocator_t allocator; 41 | } rcutils_shared_library_t; 42 | 43 | /// Return an empty shared library struct. 44 | /** 45 | * This function returns an empty and zero initialized shared library struct. 46 | * 47 | * Example: 48 | * 49 | * ```c 50 | * // Do not do this: 51 | * // rcutils_shared_library_t foo; 52 | * // rcutils_ret_t ret = rcutils_load_shared_library( 53 | * // &foo, 54 | * // "library_name", 55 | * // rcutils_get_default_allocator()); // undefined behavior! 56 | * // or 57 | * // rcutils_ret_t ret = rcutils_unload_shared_library(&foo); // undefined behavior! 58 | * 59 | * // Do this instead: 60 | * rcutils_shared_library_t bar = rcutils_get_zero_initialized_shared_library(); 61 | * rcutils_load_shared_library(&bar, "library_name", rcutils_get_default_allocator()); // ok 62 | * void * symbol = rcutils_get_symbol(&bar, "bazinga"); // ok 63 | * bool is_bazinga_symbol = rcutils_has_symbol(&bar, "bazinga"); // ok 64 | * rcutils_ret_t ret = rcutils_unload_shared_library(&bar); // ok 65 | * if (ret != RCUTILS_RET_ERROR) { 66 | * // error handling 67 | * } 68 | * ``` 69 | * */ 70 | RCUTILS_PUBLIC 71 | RCUTILS_WARN_UNUSED 72 | rcutils_shared_library_t 73 | rcutils_get_zero_initialized_shared_library(void); 74 | 75 | /// Return shared library pointer. 76 | /** 77 | * \param[inout] lib struct with the shared library pointer and shared library path name 78 | * \param[in] library_path string with the path of the library 79 | * \param[in] allocator to be used to allocate and deallocate memory 80 | * \return #RCUTILS_RET_OK if successful, or 81 | * \return #RCUTILS_RET_BAD_ALLOC if memory allocation fails, or 82 | * \return #RCUTILS_RET_ERROR if an unknown error occurs, or 83 | * \return #RCUTILS_RET_INVALID_ARGUMENT for invalid arguments. 84 | */ 85 | RCUTILS_PUBLIC 86 | RCUTILS_WARN_UNUSED 87 | rcutils_ret_t 88 | rcutils_load_shared_library( 89 | rcutils_shared_library_t * lib, 90 | const char * library_path, 91 | rcutils_allocator_t allocator); 92 | 93 | /// Return shared library symbol pointer. 94 | /** 95 | * \param[in] lib struct with the shared library pointer and shared library path name 96 | * \param[in] symbol_name name of the symbol inside the shared library 97 | * \return shared library symbol pointer, or 98 | * \return `NULL` if the symbol doesn't exist. 99 | */ 100 | RCUTILS_PUBLIC 101 | RCUTILS_WARN_UNUSED 102 | void * 103 | rcutils_get_symbol(const rcutils_shared_library_t * lib, const char * symbol_name); 104 | 105 | /// Return true if the shared library contains a specific symbol name otherwise returns false. 106 | /** 107 | * \param[in] lib struct with the shared library pointer and shared library path name 108 | * \param[in] symbol_name name of the symbol inside the shared library 109 | * \return `true` if the symbol exists, or 110 | * \return `false` otherwise. 111 | */ 112 | RCUTILS_PUBLIC 113 | RCUTILS_WARN_UNUSED 114 | bool 115 | rcutils_has_symbol(const rcutils_shared_library_t * lib, const char * symbol_name); 116 | 117 | /// Unload the shared library. 118 | /** 119 | * \param[in] lib rcutils_shared_library_t to be finalized 120 | * \return #RCUTILS_RET_OK if successful, or 121 | * \return #RCUTILS_RET_INVALID_ARGUMENT for invalid arguments, or 122 | * \return #RCUTILS_RET_ERROR if an unknown error occurs 123 | */ 124 | RCUTILS_PUBLIC 125 | RCUTILS_WARN_UNUSED 126 | rcutils_ret_t 127 | rcutils_unload_shared_library(rcutils_shared_library_t * lib); 128 | 129 | /// Check if the library is loaded. 130 | /** 131 | * This function only determines if "unload" has been called on the current shared library handle. 132 | * It could very well be that a second shared library handle is still open and therefore the library 133 | * being loaded. 134 | * \param[in] lib rcutils_shared_library_t to check 135 | * \return `true` if library is loaded, or 136 | * \return `false` otherwise. 137 | */ 138 | RCUTILS_PUBLIC 139 | RCUTILS_WARN_UNUSED 140 | bool 141 | rcutils_is_shared_library_loaded(rcutils_shared_library_t * lib); 142 | 143 | /// Get the library name for the compiled platform 144 | /** 145 | * \param[in] library_name library base name (without prefix and extension) 146 | * \param[out] library_name_platform library name for the compiled platform 147 | * \param[in] buffer_size size of library_name_platform buffer 148 | * \param[in] debug if true the library will return a debug library name, otherwise 149 | * it returns a normal library path 150 | * \return #RCUTILS_RET_OK if successful, or 151 | * \return #RCUTILS_RET_ERROR if an unknown error occurs 152 | */ 153 | RCUTILS_PUBLIC 154 | RCUTILS_WARN_UNUSED 155 | rcutils_ret_t 156 | rcutils_get_platform_library_name( 157 | const char * library_name, 158 | char * library_name_platform, 159 | unsigned int buffer_size, 160 | bool debug); 161 | 162 | #ifdef __cplusplus 163 | } 164 | #endif 165 | 166 | #endif // RCUTILS__SHARED_LIBRARY_H_ 167 | -------------------------------------------------------------------------------- /include/rcutils/snprintf.h: -------------------------------------------------------------------------------- 1 | // Copyright 2017 Open Source Robotics Foundation, Inc. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | /// \file 16 | 17 | #ifndef RCUTILS__SNPRINTF_H_ 18 | #define RCUTILS__SNPRINTF_H_ 19 | 20 | #ifdef __cplusplus 21 | extern "C" 22 | { 23 | #endif 24 | 25 | #include 26 | #include 27 | 28 | #include "rcutils/macros.h" 29 | #include "rcutils/visibility_control.h" 30 | 31 | /// Format a string. 32 | /** 33 | * This function just wraps snprintf() as defined in C11 in a portable way. 34 | * 35 | * On Windows this defaults to the _TRUNCATE behavior of _snprintf_s(), but 36 | * only returns -1 if errno is not 0. 37 | * Unlike _snprintf_s() which returns -1 when truncation occurs, this function 38 | * behaves like snprintf() (http://en.cppreference.com/w/cpp/io/c/fprintf): 39 | * 40 | * > Number of characters written if successful or negative value if an error 41 | * > occurred. 42 | * > If the resulting string gets truncated due to buf_size limit, function 43 | * > returns the total number of characters (not including the terminating 44 | * > null-byte) which would have been written, if the limit was not imposed. 45 | * 46 | * If `NULL` and `0` are given for buffer and buffer_size respectively, the 47 | * size of the string that would be generated is returned. 48 | * Either snprintf() or _vscprintf() is used to calculate this value. 49 | * 50 | * \see snprintf() 51 | * \see _snprintf_s() 52 | * \return the number of bytes that would have been written given enough space, or 53 | * \return a negative number if there is an error, but unlike _snprintf_s(), 54 | * -1 is not returned if there is truncation. 55 | */ 56 | RCUTILS_PUBLIC 57 | RCUTILS_WARN_UNUSED 58 | int 59 | rcutils_snprintf(char * buffer, size_t buffer_size, const char * format, ...) 60 | /// @cond Doxygen_Suppress 61 | RCUTILS_ATTRIBUTE_PRINTF_FORMAT(3, 4) 62 | /// @endcond 63 | ; 64 | 65 | /// Format a string with va_list for arguments, see rcutils_snprintf(). 66 | RCUTILS_PUBLIC 67 | RCUTILS_WARN_UNUSED 68 | int 69 | rcutils_vsnprintf(char * buffer, size_t buffer_size, const char * format, va_list args); 70 | 71 | #ifdef __cplusplus 72 | } 73 | #endif 74 | 75 | #endif // RCUTILS__SNPRINTF_H_ 76 | -------------------------------------------------------------------------------- /include/rcutils/split.h: -------------------------------------------------------------------------------- 1 | // Copyright 2017 Open Source Robotics Foundation, Inc. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | /// \file 16 | 17 | #ifndef RCUTILS__SPLIT_H_ 18 | #define RCUTILS__SPLIT_H_ 19 | 20 | #ifdef __cplusplus 21 | extern "C" 22 | { 23 | #endif 24 | 25 | #include "rcutils/allocator.h" 26 | #include "rcutils/types.h" 27 | #include "rcutils/visibility_control.h" 28 | 29 | /// Split a given string with the specified delimiter 30 | /** 31 | * \param[in] str string to split 32 | * \param[in] delimiter on where to split 33 | * \param[in] allocator for allocating new memory for the output array 34 | * \param[out] string_array with the split tokens 35 | * \return #RCUTILS_RET_OK if successful, or 36 | * \return #RCUTILS_RET_INVALID_ARGUMENT for invalid arguments, or 37 | * \return #RCUTILS_RET_BAD_ALLOC if memory allocation fails, or 38 | * \return #RCUTILS_RET_ERROR if an unknown error occurs 39 | */ 40 | RCUTILS_PUBLIC 41 | rcutils_ret_t 42 | rcutils_split( 43 | const char * str, 44 | char delimiter, 45 | rcutils_allocator_t allocator, 46 | rcutils_string_array_t * string_array); 47 | 48 | /// Split a given string on the last occurrence of the specified delimiter 49 | /** 50 | * \param[in] str string to split 51 | * \param[in] delimiter on where to split 52 | * \param[in] allocator for allocating new memory for the output array 53 | * \param[out] string_array with the split tokens 54 | * \return #RCUTILS_RET_OK if successful, or 55 | * \return #RCUTILS_RET_BAD_ALLOC if memory allocation fails, or 56 | * \return #RCUTILS_RET_ERROR if an unknown error occurs 57 | */ 58 | RCUTILS_PUBLIC 59 | rcutils_ret_t 60 | rcutils_split_last( 61 | const char * str, 62 | char delimiter, 63 | rcutils_allocator_t allocator, 64 | rcutils_string_array_t * string_array); 65 | 66 | #ifdef __cplusplus 67 | } 68 | #endif 69 | 70 | #endif // RCUTILS__SPLIT_H_ 71 | -------------------------------------------------------------------------------- /include/rcutils/strcasecmp.h: -------------------------------------------------------------------------------- 1 | // Copyright 2020 Open Source Robotics Foundation, Inc. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | /// \file 16 | 17 | #ifndef RCUTILS__STRCASECMP_H_ 18 | #define RCUTILS__STRCASECMP_H_ 19 | 20 | #ifdef __cplusplus 21 | extern "C" 22 | { 23 | #endif 24 | 25 | #include "rcutils/macros.h" 26 | #include "rcutils/visibility_control.h" 27 | 28 | /// Case insensitive string compare. 29 | /** 30 | * This function compares two strings ignoring case in a portable way. 31 | * This performs a byte-by-byte comparison of the strings s1 and s2, 32 | * ignoring the case of the characters. 33 | * 34 | * \param[in] s1 Null terminated string to compare. 35 | * \param[in] s2 Null terminated string to compare. 36 | * \param[out] value Pointer to comparison result. 37 | * An integer less than, equal to, or greater than zero if s1 is, after 38 | * ignoring case, found to be less than, to match, or be greater than s2, 39 | * respectively. 40 | * \return 0 if method succeeded, or 41 | * \return -1 if failed. 42 | */ 43 | RCUTILS_PUBLIC 44 | RCUTILS_WARN_UNUSED 45 | int 46 | rcutils_strcasecmp( 47 | const char * s1, 48 | const char * s2, 49 | int * value); 50 | 51 | /// Case insensitive string compare up to count characters. 52 | /** 53 | * This function compares two strings ignoring case in a portable way. 54 | * This performs a byte-by-byte comparison of the strings s1 and s2 up to count 55 | * characters of s1 and s2, ignoring the case of the characters. 56 | * 57 | * \param[in] s1 First string to compare. 58 | * \param[in] s2 Second string to compare. 59 | * \param[in] n Count of characters to compare. 60 | * \param[out] value Pointer to comparison result. 61 | * An integer less than, equal to, or greater than zero if s1 is, after 62 | * ignoring case, found to be less than, to match, or be greater than s2, 63 | * respectively. 64 | * \return 0 if method succeeded, or 65 | * \return -1 if failed. 66 | */ 67 | RCUTILS_PUBLIC 68 | RCUTILS_WARN_UNUSED 69 | int 70 | rcutils_strncasecmp( 71 | const char * s1, 72 | const char * s2, 73 | size_t n, 74 | int * value); 75 | 76 | #ifdef __cplusplus 77 | } 78 | #endif 79 | 80 | #endif // RCUTILS__STRCASECMP_H_ 81 | -------------------------------------------------------------------------------- /include/rcutils/strdup.h: -------------------------------------------------------------------------------- 1 | // Copyright 2017 Open Source Robotics Foundation, Inc. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | /// \file 16 | 17 | #ifndef RCUTILS__STRDUP_H_ 18 | #define RCUTILS__STRDUP_H_ 19 | 20 | #ifdef __cplusplus 21 | extern "C" 22 | { 23 | #endif 24 | 25 | #include 26 | 27 | #include "rcutils/allocator.h" 28 | #include "rcutils/macros.h" 29 | #include "rcutils/visibility_control.h" 30 | 31 | /// Return a duplicated string with an allocator, or null if an error occurs. 32 | /** 33 | * This function is identical to rcutils_strndup() except the length of the 34 | * c string does not have to be given and therefore the c string must be 35 | * null terminated. 36 | * 37 | * \see rcutils_strndup() 38 | * 39 | * \param[in] str null terminated c string to be duplicated 40 | * \param[in] allocator the allocator to use for allocation 41 | * \return duplicated string, or 42 | * \return `NULL` if there is an error. 43 | */ 44 | RCUTILS_PUBLIC 45 | RCUTILS_WARN_UNUSED 46 | char * 47 | rcutils_strdup(const char * str, rcutils_allocator_t allocator); 48 | 49 | /// Return a duplicated string with an allocator, or null if an error occurs. 50 | /** 51 | * This function can fail and return null if memory cannot be allocated or 52 | * if the input c string pointer is null. 53 | * In both cases no error message is set. 54 | * The returned string should be deallocated using the given allocator when 55 | * it is no longer needed. 56 | * 57 | * The max_length given does not include the null terminating character. 58 | * Therefore a max_length of 0 will still result in a duplicated string, but 59 | * the string will be an empty string of strlen 0, but it still must be 60 | * deallocated. 61 | * All returned strings are null terminated. 62 | * 63 | * \param[in] str null terminated c string to be duplicated 64 | * \param[in] max_length maximum length of the string to duplicate 65 | * \param[in] allocator the allocator to use for allocation 66 | * \return duplicated string, or 67 | * \return `NULL` if there is an error. 68 | */ 69 | RCUTILS_PUBLIC 70 | RCUTILS_WARN_UNUSED 71 | char * 72 | rcutils_strndup(const char * str, size_t max_length, rcutils_allocator_t allocator); 73 | 74 | #ifdef __cplusplus 75 | } 76 | #endif 77 | 78 | #endif // RCUTILS__STRDUP_H_ 79 | -------------------------------------------------------------------------------- /include/rcutils/strerror.h: -------------------------------------------------------------------------------- 1 | // Copyright 2020 Open Source Robotics Foundation, Inc. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | /// \file 16 | 17 | #ifndef RCUTILS__STRERROR_H_ 18 | #define RCUTILS__STRERROR_H_ 19 | 20 | #ifdef __cplusplus 21 | extern "C" 22 | { 23 | #endif 24 | 25 | #include "rcutils/visibility_control.h" 26 | 27 | /// Retrieve the string corresponding to the last system error. 28 | /** 29 | * This function retrieves the value of errno, and calls the system-specific 30 | * equivalent of `strerror` on it, storing the output in the provided buffer. 31 | * If the error message is longer than the buffer, it will be truncated. 32 | * The memory for the c-string buffer that is passed in must be managed by the 33 | * caller. 34 | * 35 | * This function is thread-safe. 36 | * 37 | * \param[inout] buffer The buffer in which to store the data 38 | * \param[in] buffer_length the maximum length of the buffer 39 | */ 40 | RCUTILS_PUBLIC 41 | void 42 | rcutils_strerror(char * buffer, size_t buffer_length); 43 | 44 | #ifdef __cplusplus 45 | } 46 | #endif 47 | 48 | #endif // RCUTILS__STRERROR_H_ 49 | -------------------------------------------------------------------------------- /include/rcutils/types.h: -------------------------------------------------------------------------------- 1 | // Copyright 2017 Open Source Robotics Foundation, Inc. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #ifndef RCUTILS__TYPES_H_ 16 | #define RCUTILS__TYPES_H_ 17 | 18 | #ifdef __cplusplus 19 | extern "C" 20 | { 21 | #endif 22 | 23 | #include "rcutils/types/array_list.h" 24 | #include "rcutils/types/char_array.h" 25 | #include "rcutils/types/hash_map.h" 26 | #include "rcutils/types/string_array.h" 27 | #include "rcutils/types/string_map.h" 28 | #include "rcutils/types/rcutils_ret.h" 29 | #include "rcutils/types/uint8_array.h" 30 | 31 | #ifdef __cplusplus 32 | } 33 | #endif 34 | 35 | #endif // RCUTILS__TYPES_H_ 36 | -------------------------------------------------------------------------------- /include/rcutils/types/rcutils_ret.h: -------------------------------------------------------------------------------- 1 | // Copyright 2017 Open Source Robotics Foundation, Inc. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | /// \file 16 | 17 | #ifndef RCUTILS__TYPES__RCUTILS_RET_H_ 18 | #define RCUTILS__TYPES__RCUTILS_RET_H_ 19 | 20 | #ifdef __cplusplus 21 | extern "C" 22 | { 23 | #endif 24 | 25 | /// The type that holds a return value for an rcutils operation. 26 | typedef int rcutils_ret_t; 27 | 28 | /// Successful operation. 29 | #define RCUTILS_RET_OK 0 30 | /// Operation produced a warning. 31 | #define RCUTILS_RET_WARN 1 32 | /// Generic failure in operation. 33 | #define RCUTILS_RET_ERROR 2 34 | 35 | /// Failed to allocate memory return code. 36 | #define RCUTILS_RET_BAD_ALLOC 10 37 | /// Invalid argument return code. 38 | #define RCUTILS_RET_INVALID_ARGUMENT 11 39 | /// Not enough storage to do operation. 40 | #define RCUTILS_RET_NOT_ENOUGH_SPACE 12 41 | /// Resource is not initialized 42 | #define RCUTILS_RET_NOT_INITIALIZED 13 43 | /// Resource for request not found 44 | #define RCUTILS_RET_NOT_FOUND 14 45 | 46 | /// Given string map was either already initialized or was not zero initialized. 47 | #define RCUTILS_RET_STRING_MAP_ALREADY_INIT 30 48 | /// Given string map is invalid, perhaps not initialized yet. 49 | #define RCUTILS_RET_STRING_MAP_INVALID 31 50 | /// Given key not found in given string map. 51 | #define RCUTILS_RET_STRING_KEY_NOT_FOUND 32 52 | 53 | /// Internal severity map for logger thresholds is invalid. 54 | #define RCUTILS_RET_LOGGING_SEVERITY_MAP_INVALID 40 55 | /// String representation of a severity is invalid. 56 | #define RCUTILS_RET_LOGGING_SEVERITY_STRING_INVALID 41 57 | 58 | /// There are no more entires beyond the last one in the map 59 | #define RCUTILS_RET_HASH_MAP_NO_MORE_ENTRIES 50 60 | 61 | 62 | #ifdef __cplusplus 63 | } 64 | #endif 65 | 66 | #endif // RCUTILS__TYPES__RCUTILS_RET_H_ 67 | -------------------------------------------------------------------------------- /include/rcutils/types/uint8_array.h: -------------------------------------------------------------------------------- 1 | // Copyright 2018 Open Source Robotics Foundation, Inc. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | /// \file 16 | 17 | #ifndef RCUTILS__TYPES__UINT8_ARRAY_H_ 18 | #define RCUTILS__TYPES__UINT8_ARRAY_H_ 19 | 20 | #if __cplusplus 21 | extern "C" 22 | { 23 | #endif 24 | 25 | #include 26 | 27 | #include "rcutils/allocator.h" 28 | #include "rcutils/types/rcutils_ret.h" 29 | #include "rcutils/visibility_control.h" 30 | 31 | /// The structure holding the metadata for a uint8 array. 32 | typedef struct RCUTILS_PUBLIC_TYPE rcutils_uint8_array_s 33 | { 34 | /// The allocated memory for the uint8 array. 35 | uint8_t * buffer; 36 | 37 | /// The number of valid elements in the uint8 array. 38 | size_t buffer_length; 39 | 40 | /// The maximum capacity of the uint8 array. 41 | size_t buffer_capacity; 42 | 43 | /// The allocator used to allocate and free memory for the uint8 array. 44 | rcutils_allocator_t allocator; 45 | } rcutils_uint8_array_t; 46 | 47 | /// Return a zero initialized uint8 array struct. 48 | /** 49 | * \return rcutils_uint8_array_t a zero initialized uint8 array struct 50 | */ 51 | RCUTILS_PUBLIC 52 | RCUTILS_WARN_UNUSED 53 | rcutils_uint8_array_t 54 | rcutils_get_zero_initialized_uint8_array(void); 55 | 56 | /// Initialize a zero initialized uint8 array struct. 57 | /** 58 | * This function may leak if the uint8 array struct is already initialized. 59 | * If the capacity is set to 0, no memory is allocated and the internal buffer 60 | * is still NULL. 61 | * 62 | * \param[inout] uint8_array a pointer to the to be initialized uint8 array struct 63 | * \param[in] buffer_capacity the size of the memory to allocate for the byte stream 64 | * \param[in] allocator the allocator to use for the memory allocation 65 | * \return #RCUTILS_RET_OK if successful, or 66 | * \return #RCUTILS_RET_INVALID_ARGUMENT if any arguments are invalid, or 67 | * \return 'RCUTILS_RET_BAD_ALLOC` if no memory could be allocated correctly 68 | * \return #RCUTILS_RET_ERROR if an unexpected error occurs. 69 | */ 70 | RCUTILS_PUBLIC 71 | RCUTILS_WARN_UNUSED 72 | rcutils_ret_t 73 | rcutils_uint8_array_init( 74 | rcutils_uint8_array_t * uint8_array, 75 | size_t buffer_capacity, 76 | const rcutils_allocator_t * allocator); 77 | 78 | /// Finalize a uint8 array struct. 79 | /** 80 | * Cleans up and deallocates any resources used in a rcutils_uint8_array_t. 81 | * The array passed to this function needs to have been initialized by 82 | * rcutils_uint8_array_init(). 83 | * Passing an uninitialized instance to this function leads to undefined 84 | * behavior. 85 | * 86 | * \param[in] uint8_array pointer to the rcutils_uint8_array_t to be cleaned up 87 | * \return #RCUTILS_RET_OK if successful, or 88 | * \return #RCUTILS_RET_INVALID_ARGUMENT if the uint8_array argument is invalid 89 | * \return #RCUTILS_RET_ERROR if an unexpected error occurs. 90 | */ 91 | RCUTILS_PUBLIC 92 | RCUTILS_WARN_UNUSED 93 | rcutils_ret_t 94 | rcutils_uint8_array_fini(rcutils_uint8_array_t * uint8_array); 95 | 96 | /// Resize the internal buffer of the uint8 array. 97 | /** 98 | * The internal buffer of the uint8 array can be resized dynamically if needed. 99 | * If the new size is smaller than the current capacity, then the memory is 100 | * truncated. 101 | * Be aware, that this might deallocate the memory and therefore invalidates any 102 | * pointers to this storage. 103 | * 104 | * \param[inout] uint8_array pointer to the instance of rcutils_uint8_array_t which is 105 | * being resized 106 | * \param[in] new_size the new size of the internal buffer 107 | * \return #RCUTILS_RET_OK if successful, or 108 | * \return #RCUTILS_RET_INVALID_ARGUMENT if new_size is set to zero 109 | * \return #RCUTILS_RET_BAD_ALLOC if memory allocation failed, or 110 | * \return #RCUTILS_RET_ERROR if an unexpected error occurs. 111 | */ 112 | RCUTILS_PUBLIC 113 | RCUTILS_WARN_UNUSED 114 | rcutils_ret_t 115 | rcutils_uint8_array_resize(rcutils_uint8_array_t * uint8_array, size_t new_size); 116 | 117 | #if __cplusplus 118 | } 119 | #endif 120 | 121 | #endif // RCUTILS__TYPES__UINT8_ARRAY_H_ 122 | -------------------------------------------------------------------------------- /include/rcutils/visibility_control.h: -------------------------------------------------------------------------------- 1 | // Copyright 2015 Open Source Robotics Foundation, Inc. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #ifndef RCUTILS__VISIBILITY_CONTROL_H_ 16 | #define RCUTILS__VISIBILITY_CONTROL_H_ 17 | 18 | #include "rcutils/visibility_control_macros.h" 19 | 20 | #ifdef RCUTILS_BUILDING_DLL 21 | # define RCUTILS_PUBLIC RCUTILS_EXPORT 22 | #else 23 | # define RCUTILS_PUBLIC RCUTILS_IMPORT 24 | #endif // !RCUTILS_BUILDING_DLL 25 | 26 | #if defined(_MSC_VER) || defined(__CYGWIN__) 27 | # define RCUTILS_PUBLIC_TYPE RCUTILS_PUBLIC 28 | #else // defined(_MSC_VER) || defined(__CYGWIN__) 29 | # define RCUTILS_PUBLIC_TYPE 30 | #endif // !defined(_MSC_VER) && !defined(__CYGWIN__) 31 | 32 | #endif // RCUTILS__VISIBILITY_CONTROL_H_ 33 | -------------------------------------------------------------------------------- /include/rcutils/visibility_control_macros.h: -------------------------------------------------------------------------------- 1 | // Copyright 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #ifndef RCUTILS__VISIBILITY_CONTROL_MACROS_H_ 16 | #define RCUTILS__VISIBILITY_CONTROL_MACROS_H_ 17 | 18 | // Defines macros to express whether a symbol is localed, imported, or exported 19 | // 20 | // Those macros are compatible with GCC, clang, and Microsoft Visual C++. They 21 | // can be used to enforce which symbols of a library are publicly accessible. 22 | // 23 | // RCUTILS_IMPORT, RCUTILS_EXPORT, and RCUTILS_LOCAL are respectively declaring 24 | // an imported, exported, or local symbol. 25 | // RCUTILS_LOCAL can be used directly. However, RCUTILS_IMPORT, and 26 | // RCUTILS_EXPORT may not be used directly. Every project need to provide 27 | // an additional header called `visibility_macros.h` containing: 28 | // 29 | // #ifdef _BUILDING_DLL 30 | // # define _PUBLIC RCUTILS_EXPORT 31 | // #else 32 | // # define _PUBLIC RCUTILS_IMPORT 33 | // #endif // !_BUILDING_DLL 34 | // #define _LOCAL RCUTILS_LOCAL 35 | // 36 | // ...where "" has been replaced by the project name, such as 37 | // "MY_PROJECT". 38 | // Your project CMakeLists.txt should also contain the following statement: 39 | // 40 | // target_compile_definitions( PRIVATE "_BUILDING_DLL") 41 | // 42 | // A public (exported) class should then be tagged as _PUBLIC, whereas 43 | // a non-public class should be tagged with _LOCAL. 44 | // 45 | // See GCC documentation: https://gcc.gnu.org/wiki/Visibility 46 | 47 | #if defined(_MSC_VER) || defined(__CYGWIN__) 48 | // Use the Windows syntax when compiling with Microsoft Visual C++. 49 | // 50 | // GCC on Windows also support this syntax. When compiling with cygwin, 51 | // prefer using dllimport/dllexport are the semantic of those flags is closer 52 | // to msvc++ behavior. See GCC documentation: 53 | // https://gcc.gnu.org/onlinedocs/gcc/Microsoft-Windows-Function-Attributes.html 54 | # define RCUTILS_IMPORT __declspec(dllimport) 55 | # define RCUTILS_EXPORT __declspec(dllexport) 56 | # define RCUTILS_LOCAL 57 | #else // defined(_MSC_VER) || defined(__CYGWIN__) 58 | // On Linux, use the GCC syntax. This syntax is understood by other compilers 59 | // such as clang, icpc, and xlc++. 60 | # define RCUTILS_IMPORT __attribute__ ((visibility("default"))) 61 | # define RCUTILS_EXPORT __attribute__ ((visibility("default"))) 62 | # define RCUTILS_LOCAL __attribute__ ((visibility("hidden"))) 63 | #endif // !defined(_MSC_VER) && !defined(__CYGWIN__) 64 | 65 | #endif // RCUTILS__VISIBILITY_CONTROL_MACROS_H_ 66 | -------------------------------------------------------------------------------- /package.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | rcutils 5 | 6.10.1 6 | Package containing various utility types and functions for C 7 | 8 | Alejandro Hernandez Cordero 9 | Chris Lalancette 10 | William Woodall 11 | 12 | Apache License 2.0 13 | 14 | Karsten Knese 15 | 16 | ament_cmake 17 | ament_cmake_ros_core 18 | python3-empy 19 | 20 | libatomic 21 | 22 | ament_cmake_gmock 23 | ament_cmake_gtest 24 | ament_cmake_pytest 25 | ament_lint_common 26 | ament_lint_auto 27 | mimick_vendor 28 | launch 29 | launch_testing 30 | launch_testing_ament_cmake 31 | osrf_testing_tools_cpp 32 | performance_test_fixture 33 | 34 | 35 | ament_cmake 36 | 37 | 38 | -------------------------------------------------------------------------------- /rcutils/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ros2/rcutils/697ebd943c3438ffb9f20b64d07d1c9654a4c8d1/rcutils/__init__.py -------------------------------------------------------------------------------- /src/allocator.c: -------------------------------------------------------------------------------- 1 | // Copyright 2015 Open Source Robotics Foundation, Inc. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #include 16 | #include 17 | 18 | #include "rcutils/allocator.h" 19 | 20 | #include "rcutils/error_handling.h" 21 | #include "rcutils/macros.h" 22 | 23 | // When this define evaluates to true (default), then messages will printed to 24 | // stderr when an error is encoutered while setting the error state. 25 | // For example, when memory cannot be allocated or a previous error state is 26 | // being overwritten. 27 | #ifndef RCUTILS_REPORT_ERROR_HANDLING_ERRORS 28 | #define RCUTILS_REPORT_ERROR_HANDLING_ERRORS 1 29 | #endif 30 | 31 | static void * 32 | __default_allocate(size_t size, void * state) 33 | { 34 | RCUTILS_CAN_RETURN_WITH_ERROR_OF(NULL); 35 | 36 | RCUTILS_UNUSED(state); 37 | return malloc(size); 38 | } 39 | 40 | static void 41 | __default_deallocate(void * pointer, void * state) 42 | { 43 | RCUTILS_UNUSED(state); 44 | free(pointer); 45 | } 46 | 47 | static void * 48 | __default_reallocate(void * pointer, size_t size, void * state) 49 | { 50 | RCUTILS_CAN_RETURN_WITH_ERROR_OF(NULL); 51 | 52 | RCUTILS_UNUSED(state); 53 | return realloc(pointer, size); 54 | } 55 | 56 | static void * 57 | __default_zero_allocate(size_t number_of_elements, size_t size_of_element, void * state) 58 | { 59 | RCUTILS_CAN_RETURN_WITH_ERROR_OF(NULL); 60 | 61 | RCUTILS_UNUSED(state); 62 | return calloc(number_of_elements, size_of_element); 63 | } 64 | 65 | rcutils_allocator_t 66 | rcutils_get_zero_initialized_allocator(void) 67 | { 68 | static rcutils_allocator_t zero_allocator = {0}; 69 | return zero_allocator; 70 | } 71 | 72 | rcutils_allocator_t 73 | rcutils_get_default_allocator(void) 74 | { 75 | static rcutils_allocator_t default_allocator = { 76 | .allocate = __default_allocate, 77 | .deallocate = __default_deallocate, 78 | .reallocate = __default_reallocate, 79 | .zero_allocate = __default_zero_allocate, 80 | .state = NULL, 81 | }; 82 | return default_allocator; 83 | } 84 | 85 | bool 86 | rcutils_allocator_is_valid(const rcutils_allocator_t * allocator) 87 | { 88 | if ( 89 | NULL == allocator || 90 | NULL == allocator->allocate || 91 | NULL == allocator->deallocate || 92 | NULL == allocator->zero_allocate || 93 | NULL == allocator->reallocate) 94 | { 95 | return false; 96 | } 97 | return true; 98 | } 99 | 100 | void * 101 | rcutils_reallocf(void * pointer, size_t size, rcutils_allocator_t * allocator) 102 | { 103 | if (!rcutils_allocator_is_valid(allocator)) { 104 | // cannot deallocate pointer, so print message to stderr and return NULL 105 | #if RCUTILS_REPORT_ERROR_HANDLING_ERRORS 106 | RCUTILS_SAFE_FWRITE_TO_STDERR( 107 | "[rcutils|allocator.c:" RCUTILS_STRINGIFY(__LINE__) "] rcutils_reallocf(): " 108 | "invalid allocator or allocator function pointers, memory leaked\n"); 109 | #endif 110 | return NULL; 111 | } 112 | void * new_pointer = allocator->reallocate(pointer, size, allocator->state); 113 | if (NULL == new_pointer) { 114 | allocator->deallocate(pointer, allocator->state); 115 | } 116 | return new_pointer; 117 | } 118 | -------------------------------------------------------------------------------- /src/cmdline_parser.c: -------------------------------------------------------------------------------- 1 | // Copyright 2017 Open Source Robotics Foundation, Inc. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #include 16 | 17 | #include "rcutils/cmdline_parser.h" 18 | 19 | bool rcutils_cli_option_exist(char ** begin, char ** end, const char * option) 20 | { 21 | // return std::find(begin, end, option) != end; 22 | for (size_t i = 0; i < (size_t)(end - begin); ++i) { 23 | if (strcmp(begin[i], option) == 0) { 24 | return true; 25 | } 26 | } 27 | return false; 28 | } 29 | 30 | char * rcutils_cli_get_option(char ** begin, char ** end, const char * option) 31 | { 32 | size_t idx = 0; 33 | size_t end_idx = (size_t)(end - begin); 34 | for (; idx < end_idx; ++idx) { 35 | if (strncmp(begin[idx], option, strlen(option)) == 0) { 36 | break; 37 | } 38 | } 39 | 40 | if (idx < end_idx - 1 && begin[idx++] != NULL) { 41 | return begin[idx]; 42 | } 43 | 44 | return NULL; 45 | } 46 | -------------------------------------------------------------------------------- /src/common.h: -------------------------------------------------------------------------------- 1 | // Copyright 2017 Open Source Robotics Foundation, Inc. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #ifndef COMMON_H_ 16 | #define COMMON_H_ 17 | 18 | #ifdef __cplusplus 19 | extern "C" 20 | { 21 | #endif 22 | 23 | #include "rcutils/error_handling.h" 24 | 25 | #ifdef __cplusplus 26 | } 27 | #endif 28 | 29 | #endif // COMMON_H_ 30 | -------------------------------------------------------------------------------- /src/env.c: -------------------------------------------------------------------------------- 1 | // Copyright 2020 Open Source Robotics Foundation, Inc. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #ifdef __cplusplus 16 | extern "C" 17 | { 18 | #endif 19 | 20 | #include 21 | #include 22 | #include 23 | 24 | #include "rcutils/env.h" 25 | #include "rcutils/error_handling.h" 26 | 27 | bool 28 | rcutils_set_env(const char * env_name, const char * env_value) 29 | { 30 | return rcutils_set_env_overwrite(env_name, env_value, true); 31 | } 32 | 33 | bool 34 | rcutils_set_env_overwrite(const char * env_name, const char * env_value, bool overwrite) 35 | { 36 | RCUTILS_CAN_RETURN_WITH_ERROR_OF(false); 37 | 38 | RCUTILS_CHECK_FOR_NULL_WITH_MSG( 39 | env_name, "env_name is null", return false); 40 | 41 | if ((int)overwrite == 0 && getenv(env_name) != NULL) { 42 | return true; 43 | } 44 | 45 | int set_ret; 46 | #ifdef _WIN32 47 | if (NULL == env_value) { 48 | env_value = ""; 49 | } 50 | set_ret = _putenv_s(env_name, env_value); 51 | #else 52 | if (NULL == env_value) { 53 | set_ret = unsetenv(env_name); 54 | } else { 55 | set_ret = setenv(env_name, env_value, (int) overwrite); 56 | } 57 | #endif 58 | 59 | if (set_ret != 0) { 60 | RCUTILS_SET_ERROR_MSG_WITH_FORMAT_STRING("setting environment variable failed: %d", errno); 61 | return false; 62 | } 63 | 64 | return true; 65 | } 66 | 67 | #ifdef _WIN32 68 | #pragma warning(push) 69 | #pragma warning(disable : 4996) 70 | #endif 71 | 72 | const char * 73 | rcutils_get_env(const char * env_name, const char ** env_value) 74 | { 75 | RCUTILS_CAN_RETURN_WITH_ERROR_OF("some string error"); 76 | 77 | if (NULL == env_name) { 78 | return "argument env_name is null"; 79 | } 80 | if (NULL == env_value) { 81 | return "argument env_value is null"; 82 | } 83 | 84 | #ifdef _WIN32 85 | size_t requiredSize = 0; 86 | char *buffer = NULL; 87 | if (getenv_s(&requiredSize, NULL, 0, env_name) == 0 && requiredSize > 0) { 88 | buffer = (char *)malloc(requiredSize * sizeof(char)); 89 | if (buffer != NULL) { 90 | if (getenv_s(&requiredSize, buffer, requiredSize, env_name) == 0) { 91 | *env_value = buffer; 92 | } else { 93 | free(buffer); 94 | *env_value = NULL; 95 | } 96 | } else { 97 | *env_value = NULL; 98 | } 99 | } else { 100 | *env_value = NULL; 101 | } 102 | #else 103 | *env_value = getenv(env_name); 104 | #endif 105 | 106 | if (NULL == *env_value) { 107 | *env_value = ""; 108 | } 109 | return NULL; 110 | } 111 | 112 | #ifdef _WIN32 113 | #pragma warning(pop) 114 | #endif 115 | 116 | const char * 117 | rcutils_get_home_dir(void) 118 | { 119 | const char * homedir; 120 | 121 | if (rcutils_get_env("HOME", &homedir) == NULL && *homedir != '\0') { 122 | // The HOME environment variable was set and is non-empty, return it. 123 | return homedir; 124 | } 125 | 126 | #ifdef _WIN32 127 | // We didn't find a HOME variable, try USERPROFILE on Windows. 128 | if (rcutils_get_env("USERPROFILE", &homedir) == NULL && *homedir != '\0') { 129 | // The USERPROFILE environment variable was set and is non-empty, return it. 130 | return homedir; 131 | } 132 | #endif 133 | 134 | // Couldn't get the home directory, return NULL. 135 | return NULL; 136 | } 137 | 138 | #ifdef __cplusplus 139 | } 140 | #endif 141 | -------------------------------------------------------------------------------- /src/find.c: -------------------------------------------------------------------------------- 1 | // Copyright 2017 Open Source Robotics Foundation, Inc. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #include 16 | #include 17 | #include 18 | #include 19 | 20 | #include "rcutils/find.h" 21 | #include "rcutils/types.h" 22 | 23 | size_t 24 | rcutils_find(const char * str, char delimiter) 25 | { 26 | if (NULL == str || 0 == strlen(str)) { 27 | return SIZE_MAX; 28 | } 29 | return rcutils_findn(str, delimiter, strlen(str)); 30 | } 31 | 32 | size_t 33 | rcutils_findn(const char * str, char delimiter, size_t string_length) 34 | { 35 | if (NULL == str || 0 == string_length) { 36 | return SIZE_MAX; 37 | } 38 | 39 | for (size_t i = 0; i < string_length; ++i) { 40 | if (str[i] == delimiter) { 41 | return i; 42 | } 43 | } 44 | return SIZE_MAX; 45 | } 46 | 47 | size_t 48 | rcutils_find_last(const char * str, char delimiter) 49 | { 50 | if (NULL == str || 0 == strlen(str)) { 51 | return SIZE_MAX; 52 | } 53 | return rcutils_find_lastn(str, delimiter, strlen(str)); 54 | } 55 | 56 | size_t 57 | rcutils_find_lastn(const char * str, char delimiter, size_t string_length) 58 | { 59 | if (NULL == str || 0 == string_length) { 60 | return SIZE_MAX; 61 | } 62 | 63 | #if defined(_GNU_SOURCE) 64 | const char * ptr = memrchr(str, delimiter, string_length); 65 | if (ptr == NULL) { 66 | return SIZE_MAX; 67 | } 68 | 69 | return ptr - str; 70 | #else 71 | for (size_t i = string_length - 1; i > 0; --i) { 72 | if (str[i] == delimiter) { 73 | return i; 74 | } 75 | } 76 | return str[0] == delimiter ? 0 : SIZE_MAX; 77 | #endif 78 | } 79 | -------------------------------------------------------------------------------- /src/format_string.c: -------------------------------------------------------------------------------- 1 | // Copyright 2017 Open Source Robotics Foundation, Inc. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #ifdef __cplusplus 16 | extern "C" 17 | { 18 | #endif 19 | 20 | #include "rcutils/format_string.h" 21 | 22 | #include 23 | #include 24 | #ifdef _WIN32 25 | #include 26 | #endif 27 | #include 28 | 29 | #include "rcutils/snprintf.h" 30 | 31 | char * 32 | rcutils_format_string_limit( 33 | rcutils_allocator_t allocator, 34 | size_t limit, 35 | const char * format_string, 36 | ...) 37 | { 38 | if (NULL == format_string) { 39 | return NULL; 40 | } 41 | RCUTILS_CHECK_ALLOCATOR(&allocator, return NULL); 42 | // extract the variadic arguments twice, once for length calculatio and once for formatting. 43 | va_list args1; 44 | va_start(args1, format_string); 45 | va_list args2; 46 | va_copy(args2, args1); 47 | // first calculate the output string 48 | size_t bytes_to_be_written = (size_t)rcutils_vsnprintf(NULL, 0, format_string, args1); 49 | va_end(args1); 50 | if (bytes_to_be_written == (size_t)-1) { 51 | va_end(args2); 52 | return NULL; 53 | } 54 | // allocate space for the return string 55 | if (bytes_to_be_written + 1 > limit) { 56 | bytes_to_be_written = limit - 1; 57 | } 58 | char * output_string = allocator.allocate(bytes_to_be_written + 1, allocator.state); 59 | if (NULL == output_string) { 60 | va_end(args2); 61 | return NULL; 62 | } 63 | // format the string 64 | int ret = rcutils_vsnprintf(output_string, bytes_to_be_written + 1, format_string, args2); 65 | if (0 > ret) { 66 | allocator.deallocate(output_string, allocator.state); 67 | va_end(args2); 68 | return NULL; 69 | } 70 | output_string[bytes_to_be_written] = '\0'; 71 | va_end(args2); 72 | return output_string; 73 | } 74 | 75 | #ifdef __cplusplus 76 | } 77 | #endif 78 | -------------------------------------------------------------------------------- /src/join.c: -------------------------------------------------------------------------------- 1 | // Copyright 2025 Open Source Robotics Foundation, Inc. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #ifdef __cplusplus 16 | extern "C" 17 | { 18 | #endif 19 | 20 | #include 21 | 22 | #include "rcutils/error_handling.h" 23 | #include "rcutils/join.h" 24 | #include "rcutils/macros.h" 25 | #include "rcutils/strdup.h" 26 | #include "rcutils/types.h" 27 | 28 | char * 29 | rcutils_join( 30 | const rcutils_string_array_t * string_array, 31 | const char * separator, 32 | rcutils_allocator_t allocator) 33 | { 34 | RCUTILS_CAN_RETURN_WITH_ERROR_OF(NULL); 35 | 36 | RCUTILS_CHECK_ARGUMENT_FOR_NULL(string_array, NULL); 37 | RCUTILS_CHECK_ARGUMENT_FOR_NULL(separator, NULL); 38 | RCUTILS_CHECK_ALLOCATOR_WITH_MSG( 39 | &allocator, "allocator is invalid", return NULL); 40 | 41 | if (string_array->size < 1) { 42 | return rcutils_strdup("", allocator); 43 | } 44 | 45 | size_t sep_length = strlen(separator); 46 | size_t string_length = sep_length * (string_array->size - 1); 47 | 48 | for (size_t i = 0; i < string_array->size; i++) { 49 | if (string_array->data[i]) { 50 | string_length += strlen(string_array->data[i]); 51 | } 52 | } 53 | 54 | char * new_string = allocator.allocate(string_length + 1, allocator.state); 55 | if (NULL == new_string) { 56 | RCUTILS_SET_ERROR_MSG("failed to allocate memory for new string"); 57 | return NULL; 58 | } 59 | 60 | char * pos = new_string; 61 | for (size_t i = 0; i < string_array->size; i++) { 62 | if (i != 0) { 63 | memcpy(pos, separator, sep_length); 64 | pos += sep_length; 65 | } 66 | if (string_array->data[i]) { 67 | string_length = strlen(string_array->data[i]); 68 | memcpy(pos, string_array->data[i], string_length); 69 | pos += string_length; 70 | } 71 | } 72 | 73 | *pos = '\0'; 74 | 75 | return new_string; 76 | } 77 | 78 | #ifdef __cplusplus 79 | } 80 | #endif 81 | -------------------------------------------------------------------------------- /src/qsort.c: -------------------------------------------------------------------------------- 1 | // Copyright 2020 Open Source Robotics Foundation, Inc. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #ifdef __cplusplus 16 | extern "C" 17 | { 18 | #endif 19 | 20 | #include 21 | 22 | #include "rcutils/error_handling.h" 23 | #include "rcutils/qsort.h" 24 | 25 | rcutils_ret_t 26 | rcutils_qsort(void * ptr, size_t count, size_t size, int (* comp)(const void *, const void *)) 27 | { 28 | RCUTILS_CHECK_FOR_NULL_WITH_MSG( 29 | comp, "comp is null", return RCUTILS_RET_INVALID_ARGUMENT); 30 | 31 | if (1 >= count) { 32 | return RCUTILS_RET_OK; 33 | } 34 | 35 | RCUTILS_CHECK_FOR_NULL_WITH_MSG( 36 | ptr, "ptr is null", return RCUTILS_RET_INVALID_ARGUMENT); 37 | 38 | qsort(ptr, count, size, comp); 39 | 40 | return RCUTILS_RET_OK; 41 | } 42 | 43 | #ifdef __cplusplus 44 | } 45 | #endif 46 | -------------------------------------------------------------------------------- /src/repl_str.c: -------------------------------------------------------------------------------- 1 | // Copyright 2015-2016 Laird Shaw 2 | // Copyright 2017 Open Source Robotics Foundation, Inc. 3 | // 4 | // Licensed under the Apache License, Version 2.0 (the "License"); 5 | // you may not use this file except in compliance with the License. 6 | // You may obtain a copy of the License at 7 | // 8 | // http://www.apache.org/licenses/LICENSE-2.0 9 | // 10 | // Unless required by applicable law or agreed to in writing, software 11 | // distributed under the License is distributed on an "AS IS" BASIS, 12 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | // See the License for the specific language governing permissions and 14 | // limitations under the License. 15 | 16 | // This function is based on the repl_str() from (on 2017-04-25): 17 | // 18 | // http://creativeandcritical.net/str-replace-c 19 | // 20 | // It is released under the Public Domain, and has been placed additionally 21 | // under the Apache 2.0 license by me (William Woodall). 22 | // 23 | // It has been modified to take a custom allocator and to fit some of our 24 | // style standards. 25 | 26 | // Note: the "tuning" values at the beginning of the function have been left as-is. 27 | 28 | #ifdef __cplusplus 29 | extern "C" 30 | { 31 | #endif 32 | 33 | #include 34 | #include 35 | #include 36 | 37 | #if (__STDC_VERSION__ >= 199901L) 38 | #include 39 | #endif 40 | 41 | #include "rcutils/repl_str.h" 42 | 43 | // *INDENT-OFF* (prevent uncrustify from messing with the original style) 44 | 45 | char * 46 | rcutils_repl_str( 47 | const char * str, 48 | const char * from, 49 | const char * to, 50 | const rcutils_allocator_t * allocator) 51 | { 52 | RCUTILS_CHECK_ALLOCATOR(allocator, return NULL); 53 | /* Adjust each of the below values to suit your needs. */ 54 | 55 | /* Increment positions cache size initially by this number. */ 56 | size_t cache_sz_inc = 16; 57 | /* Thereafter, each time capacity needs to be increased, 58 | * multiply the increment by this factor. */ 59 | const size_t cache_sz_inc_factor = 3; 60 | /* But never increment capacity by more than this number. */ 61 | const size_t cache_sz_inc_max = 1048576; 62 | 63 | char *pret, *ret = NULL; 64 | const char *pstr2, *pstr = str; 65 | size_t i, count = 0; 66 | #if (__STDC_VERSION__ >= 199901L) 67 | uintptr_t *pos_cache_tmp, *pos_cache = NULL; 68 | #else 69 | ptrdiff_t *pos_cache_tmp, *pos_cache = NULL; 70 | #endif 71 | size_t cache_sz = 0; 72 | size_t cpylen, orglen, retlen, tolen, fromlen = strlen(from); 73 | 74 | /* Find all matches and cache their positions. */ 75 | while ((pstr2 = strstr(pstr, from)) != NULL) { 76 | count++; 77 | 78 | /* Increase the cache size when necessary. */ 79 | if (cache_sz < count) { 80 | cache_sz += cache_sz_inc; 81 | pos_cache_tmp = 82 | allocator->reallocate(pos_cache, sizeof(*pos_cache) * cache_sz, allocator->state); 83 | if (pos_cache_tmp == NULL) { 84 | goto end_repl_str; 85 | } else { 86 | pos_cache = pos_cache_tmp; 87 | } 88 | cache_sz_inc *= cache_sz_inc_factor; 89 | if (cache_sz_inc > cache_sz_inc_max) { 90 | cache_sz_inc = cache_sz_inc_max; 91 | } 92 | } 93 | 94 | pos_cache[count-1] = (size_t)(pstr2 - str); 95 | pstr = pstr2 + fromlen; 96 | } 97 | 98 | orglen = (size_t)(pstr - str) + strlen(pstr); 99 | 100 | /* Allocate memory for the post-replacement string. */ 101 | if (count > 0) { 102 | tolen = strlen(to); 103 | retlen = orglen + (tolen - fromlen) * count; 104 | } else { 105 | retlen = orglen; 106 | } 107 | ret = allocator->allocate(retlen + 1, allocator->state); 108 | if (ret == NULL) { 109 | goto end_repl_str; 110 | } 111 | 112 | if (count == 0) { 113 | /* If no matches, then just duplicate the string. */ 114 | #if defined(_MSC_VER) 115 | # pragma warning(push) 116 | # pragma warning(disable: 4996) // strcpy may be unsafe 117 | #endif 118 | strcpy(ret, str); // NOLINT 119 | #if defined(_MSC_VER) 120 | # pragma warning(pop) 121 | #endif 122 | } else { 123 | /* Otherwise, duplicate the string whilst performing 124 | * the replacements using the position cache. */ 125 | pret = ret; 126 | memcpy(pret, str, pos_cache[0]); 127 | pret += pos_cache[0]; 128 | for (i = 0; i < count; i++) { 129 | memcpy(pret, to, tolen); 130 | pret += tolen; 131 | pstr = str + pos_cache[i] + fromlen; 132 | cpylen = (i == count-1 ? orglen : pos_cache[i+1]) - pos_cache[i] - fromlen; 133 | memcpy(pret, pstr, cpylen); 134 | pret += cpylen; 135 | } 136 | ret[retlen] = '\0'; 137 | } 138 | 139 | end_repl_str: 140 | /* Free the cache and return the post-replacement string, 141 | * which will be NULL in the event of an error. */ 142 | allocator->deallocate(pos_cache, allocator->state); 143 | return ret; 144 | } 145 | 146 | // *INDENT-ON* 147 | 148 | #ifdef __cplusplus 149 | } 150 | #endif 151 | -------------------------------------------------------------------------------- /src/snprintf.c: -------------------------------------------------------------------------------- 1 | // Copyright 2018 Open Source Robotics Foundation, Inc. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #ifdef __cplusplus 16 | extern "C" 17 | { 18 | #endif 19 | 20 | #include "rcutils/snprintf.h" 21 | 22 | #include 23 | #ifdef _WIN32 24 | #include 25 | #endif 26 | #include 27 | #include 28 | 29 | int 30 | rcutils_snprintf(char * buffer, size_t buffer_size, const char * format, ...) 31 | { 32 | va_list args; 33 | va_start(args, format); 34 | int ret = rcutils_vsnprintf(buffer, buffer_size, format, args); 35 | va_end(args); 36 | return ret; 37 | } 38 | 39 | int 40 | rcutils_vsnprintf(char * buffer, size_t buffer_size, const char * format, va_list args) 41 | { 42 | RCUTILS_CAN_FAIL_WITH({errno = EINVAL; return -1;}); 43 | 44 | if (NULL == format) { 45 | errno = EINVAL; 46 | return -1; 47 | } 48 | if (NULL == buffer && 0 == buffer_size) { 49 | #ifndef _WIN32 50 | return vsnprintf(NULL, 0, format, args); 51 | #else 52 | return _vscprintf(format, args); 53 | #endif 54 | } 55 | if (NULL == buffer || 0 == buffer_size) { 56 | errno = EINVAL; 57 | return -1; 58 | } 59 | int ret; 60 | #ifndef _WIN32 61 | ret = vsnprintf(buffer, buffer_size, format, args); 62 | #else 63 | // errno isn't explicitly set to 0 when truncation occurs. 64 | errno = 0; 65 | ret = _vsnprintf_s(buffer, buffer_size, _TRUNCATE, format, args); 66 | if (-1 == ret && 0 == errno) { 67 | // This is the case where truncation has occurred, return how long it would have been. 68 | return _vscprintf(format, args); 69 | } 70 | #endif 71 | return ret; 72 | } 73 | 74 | #ifdef __cplusplus 75 | } 76 | #endif 77 | -------------------------------------------------------------------------------- /src/strcasecmp.c: -------------------------------------------------------------------------------- 1 | // Copyright 2020 Open Source Robotics Foundation, Inc. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #ifdef __cplusplus 16 | extern "C" 17 | { 18 | #endif 19 | 20 | #include 21 | #include 22 | 23 | #include "rcutils/strcasecmp.h" 24 | 25 | int 26 | rcutils_strcasecmp( 27 | const char * s1, 28 | const char * s2, 29 | int * value) 30 | { 31 | if (s1 == NULL || s2 == NULL || value == NULL) { 32 | return -1; 33 | } 34 | #ifndef _WIN32 35 | *value = strcasecmp(s1, s2); 36 | #else 37 | *value = _stricmp(s1, s2); 38 | #endif 39 | return 0; 40 | } 41 | 42 | int 43 | rcutils_strncasecmp( 44 | const char * s1, 45 | const char * s2, 46 | size_t n, 47 | int * value) 48 | { 49 | if (s1 == NULL || s2 == NULL || value == NULL) { 50 | return -1; 51 | } 52 | #ifndef _WIN32 53 | *value = strncasecmp(s1, s2, n); 54 | #else 55 | *value = _strnicmp(s1, s2, n); 56 | #endif 57 | return 0; 58 | } 59 | 60 | #ifdef __cplusplus 61 | } 62 | #endif 63 | -------------------------------------------------------------------------------- /src/strdup.c: -------------------------------------------------------------------------------- 1 | // Copyright 2017 Open Source Robotics Foundation, Inc. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #ifdef __cplusplus 16 | extern "C" 17 | { 18 | #endif 19 | 20 | #include "rcutils/strdup.h" 21 | 22 | #include 23 | #include 24 | #include 25 | 26 | #include "./common.h" 27 | #include "rcutils/macros.h" 28 | 29 | 30 | char * 31 | rcutils_strdup(const char * str, rcutils_allocator_t allocator) 32 | { 33 | RCUTILS_CAN_RETURN_WITH_ERROR_OF(NULL); 34 | 35 | return rcutils_strndup(str, SIZE_MAX, allocator); 36 | } 37 | 38 | char * 39 | rcutils_strndup(const char * str, size_t max_length, rcutils_allocator_t allocator) 40 | { 41 | RCUTILS_CAN_RETURN_WITH_ERROR_OF(NULL); 42 | 43 | if (NULL == str) { 44 | return NULL; 45 | } 46 | RCUTILS_CHECK_ALLOCATOR(&allocator, return NULL); 47 | char * p = memchr(str, '\0', max_length); 48 | size_t string_length = p == NULL ? max_length : (size_t)(p - str); 49 | char * new_string = allocator.allocate(string_length + 1, allocator.state); 50 | if (NULL == new_string) { 51 | return NULL; 52 | } 53 | memcpy(new_string, str, string_length); 54 | new_string[string_length] = '\0'; 55 | return new_string; 56 | } 57 | 58 | #ifdef __cplusplus 59 | } 60 | #endif 61 | -------------------------------------------------------------------------------- /src/strerror.c: -------------------------------------------------------------------------------- 1 | // Copyright 2020 Open Source Robotics Foundation, Inc. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #ifdef __cplusplus 16 | extern "C" 17 | { 18 | #endif 19 | 20 | #include 21 | #include 22 | 23 | #include "rcutils/strerror.h" 24 | 25 | void 26 | rcutils_strerror(char * buffer, size_t buffer_length) 27 | { 28 | #if defined(_WIN32) 29 | strerror_s(buffer, buffer_length, errno); 30 | #elif defined(_GNU_SOURCE) && (!defined(ANDROID) || __ANDROID_API__ >= 23) && !defined(__QNXNTO__) 31 | /* GNU-specific */ 32 | char * msg = strerror_r(errno, buffer, buffer_length); 33 | if (msg != buffer) { 34 | strncpy(buffer, msg, buffer_length); 35 | buffer[buffer_length - 1] = '\0'; 36 | } 37 | #else 38 | /* XSI-compliant */ 39 | int error_status = strerror_r(errno, buffer, buffer_length); 40 | if (error_status != 0) { 41 | strncpy(buffer, "Failed to get error", buffer_length); 42 | buffer[buffer_length - 1] = '\0'; 43 | } 44 | #endif 45 | } 46 | 47 | #ifdef __cplusplus 48 | } 49 | #endif 50 | -------------------------------------------------------------------------------- /src/testing/fault_injection.c: -------------------------------------------------------------------------------- 1 | // Copyright 2020 Open Source Robotics Foundation, Inc. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #include "rcutils/testing/fault_injection.h" 16 | 17 | #include "rcutils/stdatomic_helper.h" 18 | 19 | static atomic_int_least64_t g_rcutils_fault_injection_count = ATOMIC_VAR_INIT(-1); 20 | 21 | void rcutils_fault_injection_set_count(int_least64_t count) 22 | { 23 | rcutils_atomic_store(&g_rcutils_fault_injection_count, count); 24 | } 25 | 26 | int_least64_t rcutils_fault_injection_get_count(void) 27 | { 28 | int_least64_t count = 0; 29 | rcutils_atomic_load(&g_rcutils_fault_injection_count, count); 30 | return count; 31 | } 32 | 33 | bool rcutils_fault_injection_is_test_complete(void) 34 | { 35 | #ifndef RCUTILS_ENABLE_FAULT_INJECTION 36 | return true; 37 | #else // RCUTILS_ENABLE_FAULT_INJECTION 38 | return rcutils_fault_injection_get_count() > RCUTILS_FAULT_INJECTION_NEVER_FAIL; 39 | #endif // RCUTILS_ENABLE_FAULT_INJECTION 40 | } 41 | 42 | int_least64_t _rcutils_fault_injection_maybe_fail(void) 43 | { 44 | bool set_atomic_success = false; 45 | int_least64_t current_count = rcutils_fault_injection_get_count(); 46 | do { 47 | // A fault_injection_count less than 0 means that maybe_fail doesn't fail, so just return. 48 | if (current_count <= RCUTILS_FAULT_INJECTION_NEVER_FAIL) { 49 | return current_count; 50 | } 51 | 52 | // Otherwise decrement by one, but do so in a thread-safe manner so that exactly one calling 53 | // thread gets the 0 case. 54 | int_least64_t desired_count = current_count - 1; 55 | rcutils_atomic_compare_exchange_strong( 56 | &g_rcutils_fault_injection_count, set_atomic_success, ¤t_count, desired_count); 57 | } while (!set_atomic_success); 58 | return current_count; 59 | } 60 | -------------------------------------------------------------------------------- /src/time.c: -------------------------------------------------------------------------------- 1 | // Copyright 2018 Open Source Robotics Foundation, Inc. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #if __cplusplus 16 | extern "C" 17 | { 18 | #endif 19 | 20 | #include "rcutils/time.h" 21 | 22 | #include 23 | #include 24 | #include 25 | #include 26 | 27 | #include "rcutils/allocator.h" 28 | #include "rcutils/error_handling.h" 29 | #include "rcutils/snprintf.h" 30 | 31 | rcutils_ret_t 32 | rcutils_time_point_value_as_nanoseconds_string( 33 | const rcutils_time_point_value_t * time_point, 34 | char * str, 35 | size_t str_size) 36 | { 37 | RCUTILS_CHECK_ARGUMENT_FOR_NULL(time_point, RCUTILS_RET_INVALID_ARGUMENT); 38 | RCUTILS_CHECK_ARGUMENT_FOR_NULL(str, RCUTILS_RET_INVALID_ARGUMENT); 39 | if (0 == str_size) { 40 | return RCUTILS_RET_OK; 41 | } 42 | if (rcutils_snprintf(str, str_size, "%.19" PRId64, *time_point) < 0) { 43 | RCUTILS_SET_ERROR_MSG("failed to format time point into string as nanoseconds"); 44 | return RCUTILS_RET_ERROR; 45 | } 46 | return RCUTILS_RET_OK; 47 | } 48 | 49 | rcutils_ret_t 50 | rcutils_time_point_value_as_date_string( 51 | const rcutils_time_point_value_t * time_point, 52 | char * str, 53 | size_t str_size) 54 | { 55 | RCUTILS_CHECK_ARGUMENT_FOR_NULL(time_point, RCUTILS_RET_INVALID_ARGUMENT); 56 | RCUTILS_CHECK_ARGUMENT_FOR_NULL(str, RCUTILS_RET_INVALID_ARGUMENT); 57 | if (0 == str_size) { 58 | return RCUTILS_RET_OK; 59 | } 60 | // best to abs it to avoid issues with negative values in C89, see: 61 | // https://stackoverflow.com/a/3604984/671658 62 | uint64_t abs_time_point = (uint64_t)llabs(*time_point); 63 | // break into two parts to avoid floating point error 64 | uint64_t seconds = abs_time_point / (1000u * 1000u * 1000u); 65 | uint64_t nanoseconds = abs_time_point % (1000u * 1000u * 1000u); 66 | // Make sure the buffer is large enough to hold the largest possible uint64_t 67 | char nanoseconds_str[21]; 68 | 69 | if (rcutils_snprintf(nanoseconds_str, sizeof(nanoseconds_str), "%" PRIu64, nanoseconds) < 0) { 70 | RCUTILS_SET_ERROR_MSG("failed to format time point nanoseconds into string"); 71 | return RCUTILS_RET_ERROR; 72 | } 73 | 74 | time_t now_t = (time_t)(seconds); 75 | struct tm ptm = {.tm_year = 0, .tm_mday = 0}; 76 | #ifdef _WIN32 77 | if (localtime_s(&ptm, &now_t) != 0) { 78 | RCUTILS_SET_ERROR_MSG("failed to get localtime"); 79 | return RCUTILS_RET_ERROR; 80 | } 81 | #else 82 | if (localtime_r(&now_t, &ptm) == NULL) { 83 | RCUTILS_SET_ERROR_MSG("failed to get localtime"); 84 | return RCUTILS_RET_ERROR; 85 | } 86 | #endif 87 | 88 | if (str_size < 32 || strftime(str, 32, "%Y-%m-%d %H:%M:%S", &ptm) == 0) { 89 | RCUTILS_SET_ERROR_MSG("failed to format time point into string as iso8601_date"); 90 | return RCUTILS_RET_ERROR; 91 | } 92 | static const int date_end_position = 19; 93 | if (rcutils_snprintf( 94 | &str[date_end_position], str_size - date_end_position, ".%.3s", 95 | nanoseconds_str) < 0) 96 | { 97 | RCUTILS_SET_ERROR_MSG("failed to format time point into string as date_time_with_ms"); 98 | return RCUTILS_RET_ERROR; 99 | } 100 | 101 | return RCUTILS_RET_OK; 102 | } 103 | 104 | rcutils_ret_t 105 | rcutils_time_point_value_as_seconds_string( 106 | const rcutils_time_point_value_t * time_point, 107 | char * str, 108 | size_t str_size) 109 | { 110 | RCUTILS_CHECK_ARGUMENT_FOR_NULL(time_point, RCUTILS_RET_INVALID_ARGUMENT); 111 | RCUTILS_CHECK_ARGUMENT_FOR_NULL(str, RCUTILS_RET_INVALID_ARGUMENT); 112 | if (0 == str_size) { 113 | return RCUTILS_RET_OK; 114 | } 115 | // best to abs it to avoid issues with negative values in C89, see: 116 | // https://stackoverflow.com/a/3604984/671658 117 | uint64_t abs_time_point = (uint64_t)llabs(*time_point); 118 | // break into two parts to avoid floating point error 119 | uint64_t seconds = abs_time_point / (1000u * 1000u * 1000u); 120 | uint64_t nanoseconds = abs_time_point % (1000u * 1000u * 1000u); 121 | if ( 122 | rcutils_snprintf( 123 | str, str_size, "%s%.10" PRId64 ".%.9" PRId64, 124 | (*time_point >= 0) ? "" : "-", seconds, nanoseconds) < 0) 125 | { 126 | RCUTILS_SET_ERROR_MSG("failed to format time point into string as float seconds"); 127 | return RCUTILS_RET_ERROR; 128 | } 129 | return RCUTILS_RET_OK; 130 | } 131 | 132 | #if __cplusplus 133 | } 134 | #endif 135 | -------------------------------------------------------------------------------- /src/time_unix.c: -------------------------------------------------------------------------------- 1 | // Copyright 2015 Open Source Robotics Foundation, Inc. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #if defined(_WIN32) 16 | # error time_unix.c is not intended to be used with win32 based systems 17 | #endif // defined(_WIN32) 18 | 19 | #include "rcutils/time.h" 20 | 21 | #if defined(__MACH__) && defined(__APPLE__) 22 | #include 23 | #include 24 | #endif // defined(__MACH__) && defined(__APPLE__) 25 | #include 26 | 27 | #if defined(__ZEPHYR__) 28 | #include 29 | #if ZEPHYR_VERSION_CODE >= ZEPHYR_VERSION(3, 1, 0) 30 | #include // Points to Zephyr toolchain posix time implementation 31 | #else 32 | #include // Points to Zephyr toolchain posix time implementation 33 | #endif 34 | #else // #if KERNELVERSION >= ZEPHYR_VERSION(3, 1, 0) 35 | #include 36 | #endif // defined(__ZEPHYR__) 37 | 38 | #include 39 | #include 40 | 41 | #include "rcutils/allocator.h" 42 | #include "rcutils/error_handling.h" 43 | 44 | #if !defined(__MACH__) && !defined(__APPLE__) // Assume clock_get_time is available on OS X. 45 | // This is an appropriate check for clock_gettime() according to: 46 | // http://man7.org/linux/man-pages/man2/clock_gettime.2.html 47 | # if !defined(_POSIX_TIMERS) || !_POSIX_TIMERS 48 | # error no monotonic clock function available 49 | # endif // !defined(_POSIX_TIMERS) || !_POSIX_TIMERS 50 | #endif // !defined(__MACH__) && !defined(__APPLE__) 51 | 52 | static inline bool would_be_negative(const struct timespec * const now) 53 | { 54 | return now->tv_sec < 0 || (now->tv_nsec < 0 && now->tv_sec == 0); 55 | } 56 | 57 | rcutils_ret_t 58 | rcutils_system_time_now(rcutils_time_point_value_t * now) 59 | { 60 | RCUTILS_CHECK_ARGUMENT_FOR_NULL(now, RCUTILS_RET_INVALID_ARGUMENT); 61 | struct timespec timespec_now; 62 | // Using clock_gettime(CLOCK_REALTIME) matches what both Linux and macOS use. 63 | // For macOS, see the clang implementation at 64 | // (https://github.com/llvm/llvm-project/blob/baebe12ad0d6f514cd33e418d6504075d3e79c0a/libcxx/src/chrono.cpp) 65 | if (clock_gettime(CLOCK_REALTIME, ×pec_now) < 0) { 66 | RCUTILS_SET_ERROR_MSG_WITH_FORMAT_STRING("Failed to get system time: %d", errno); 67 | return RCUTILS_RET_ERROR; 68 | } 69 | if (would_be_negative(×pec_now)) { 70 | RCUTILS_SET_ERROR_MSG("unexpected negative time"); 71 | return RCUTILS_RET_ERROR; 72 | } 73 | *now = RCUTILS_S_TO_NS((int64_t)timespec_now.tv_sec) + timespec_now.tv_nsec; 74 | return RCUTILS_RET_OK; 75 | } 76 | 77 | rcutils_ret_t 78 | rcutils_steady_time_now(rcutils_time_point_value_t * now) 79 | { 80 | RCUTILS_CHECK_ARGUMENT_FOR_NULL(now, RCUTILS_RET_INVALID_ARGUMENT); 81 | struct timespec timespec_now; 82 | clockid_t monotonic_clock = CLOCK_MONOTONIC; 83 | 84 | #if defined(__MACH__) && defined(__APPLE__) 85 | // On macOS, use CLOCK_MONOTONIC_RAW, which matches the clang implementation 86 | // (https://github.com/llvm/llvm-project/blob/baebe12ad0d6f514cd33e418d6504075d3e79c0a/libcxx/src/chrono.cpp) 87 | monotonic_clock = CLOCK_MONOTONIC_RAW; 88 | #endif // defined(__MACH__) && defined(__APPLE__) 89 | 90 | if (clock_gettime(monotonic_clock, ×pec_now) < 0) { 91 | RCUTILS_SET_ERROR_MSG_WITH_FORMAT_STRING("Failed to get steady time: %d", errno); 92 | return RCUTILS_RET_ERROR; 93 | } 94 | if (would_be_negative(×pec_now)) { 95 | RCUTILS_SET_ERROR_MSG("unexpected negative time"); 96 | return RCUTILS_RET_ERROR; 97 | } 98 | *now = RCUTILS_S_TO_NS((int64_t)timespec_now.tv_sec) + timespec_now.tv_nsec; 99 | return RCUTILS_RET_OK; 100 | } 101 | -------------------------------------------------------------------------------- /src/time_win32.c: -------------------------------------------------------------------------------- 1 | // Copyright 2015 Open Source Robotics Foundation, Inc. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #ifndef _WIN32 16 | # error time_win32.c is only intended to be used with win32 based systems 17 | #endif // _WIN32 18 | 19 | #ifdef __cplusplus 20 | extern "C" 21 | { 22 | #endif 23 | 24 | #include "rcutils/time.h" 25 | 26 | // When building with MSVC 19.28.29333.0 on Windows 10 (as of 2020-11-11), 27 | // there appears to be a problem with winbase.h (which is included by 28 | // Windows.h). In particular, warnings of the form: 29 | // 30 | // warning C5105: macro expansion producing 'defined' has undefined behavior 31 | // 32 | // See https://developercommunity.visualstudio.com/content/problem/695656/wdk-and-sdk-are-not-compatible-with-experimentalpr.html 33 | // for more information. For now disable that warning when including windows.h 34 | #pragma warning(push) 35 | #pragma warning(disable : 5105) 36 | #include 37 | #pragma warning(pop) 38 | 39 | #include "./common.h" 40 | #include "rcutils/allocator.h" 41 | #include "rcutils/error_handling.h" 42 | 43 | rcutils_ret_t 44 | rcutils_system_time_now(rcutils_time_point_value_t * now) 45 | { 46 | RCUTILS_CHECK_ARGUMENT_FOR_NULL(now, RCUTILS_RET_INVALID_ARGUMENT); 47 | FILETIME ft; 48 | GetSystemTimePreciseAsFileTime(&ft); 49 | LARGE_INTEGER li; 50 | li.LowPart = ft.dwLowDateTime; 51 | li.HighPart = ft.dwHighDateTime; 52 | // Adjust for January 1st, 1970, see: 53 | // https://support.microsoft.com/en-us/topic/bf03df72-96e4-59f3-1d02-b6781002dc7f 54 | li.QuadPart -= 116444736000000000; 55 | // Convert to nanoseconds from 100's of nanoseconds. 56 | *now = li.QuadPart * 100; 57 | return RCUTILS_RET_OK; 58 | } 59 | 60 | rcutils_ret_t 61 | rcutils_steady_time_now(rcutils_time_point_value_t * now) 62 | { 63 | RCUTILS_CHECK_ARGUMENT_FOR_NULL(now, RCUTILS_RET_INVALID_ARGUMENT); 64 | LARGE_INTEGER cpu_frequency, performance_count; 65 | // These should not ever fail since XP is already end of life: 66 | // From https://msdn.microsoft.com/en-us/library/windows/desktop/ms644905(v=vs.85).aspx and 67 | // https://msdn.microsoft.com/en-us/library/windows/desktop/ms644904(v=vs.85).aspx: 68 | // "On systems that run Windows XP or later, the function will always succeed and will 69 | // thus never return zero." 70 | QueryPerformanceFrequency(&cpu_frequency); 71 | QueryPerformanceCounter(&performance_count); 72 | // Calculate nanoseconds and seconds separately because 73 | // otherwise overflow can happen in intermediate calculations 74 | // This conversion will overflow if the PC runs >292 years non-stop 75 | const rcutils_time_point_value_t whole_seconds = 76 | performance_count.QuadPart / cpu_frequency.QuadPart; 77 | const rcutils_time_point_value_t remainder_count = 78 | performance_count.QuadPart % cpu_frequency.QuadPart; 79 | const rcutils_time_point_value_t remainder_ns = 80 | RCUTILS_S_TO_NS(remainder_count) / cpu_frequency.QuadPart; 81 | const rcutils_time_point_value_t total_ns = 82 | RCUTILS_S_TO_NS(whole_seconds) + remainder_ns; 83 | *now = total_ns; 84 | return RCUTILS_RET_OK; 85 | } 86 | 87 | #ifdef __cplusplus 88 | } 89 | #endif 90 | -------------------------------------------------------------------------------- /src/uint8_array.c: -------------------------------------------------------------------------------- 1 | // Copyright 2018 Open Source Robotics Foundation, Inc. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #include "rcutils/error_handling.h" 16 | #include "rcutils/types/uint8_array.h" 17 | 18 | rcutils_uint8_array_t 19 | rcutils_get_zero_initialized_uint8_array(void) 20 | { 21 | static rcutils_uint8_array_t uint8_array = {0}; 22 | return uint8_array; 23 | } 24 | 25 | rcutils_ret_t 26 | rcutils_uint8_array_init( 27 | rcutils_uint8_array_t * uint8_array, 28 | size_t buffer_capacity, 29 | const rcutils_allocator_t * allocator) 30 | { 31 | RCUTILS_CHECK_ARGUMENT_FOR_NULL(uint8_array, RCUTILS_RET_INVALID_ARGUMENT); 32 | RCUTILS_CHECK_ALLOCATOR(allocator, return RCUTILS_RET_INVALID_ARGUMENT); 33 | 34 | uint8_array->buffer_length = 0lu; 35 | uint8_array->buffer_capacity = buffer_capacity; 36 | uint8_array->allocator = *allocator; 37 | 38 | if (buffer_capacity > 0lu) { 39 | uint8_array->buffer = (uint8_t *)allocator->allocate( 40 | buffer_capacity * sizeof(uint8_t), allocator->state); 41 | RCUTILS_CHECK_FOR_NULL_WITH_MSG( 42 | uint8_array->buffer, 43 | "failed to allocate memory for uint8 array", 44 | uint8_array->buffer_capacity = 0lu; 45 | uint8_array->buffer_length = 0lu; 46 | return RCUTILS_RET_BAD_ALLOC); 47 | } 48 | 49 | return RCUTILS_RET_OK; 50 | } 51 | 52 | rcutils_ret_t 53 | rcutils_uint8_array_fini(rcutils_uint8_array_t * uint8_array) 54 | { 55 | RCUTILS_CHECK_ARGUMENT_FOR_NULL(uint8_array, RCUTILS_RET_INVALID_ARGUMENT); 56 | 57 | rcutils_allocator_t * allocator = &uint8_array->allocator; 58 | RCUTILS_CHECK_ALLOCATOR(allocator, return RCUTILS_RET_INVALID_ARGUMENT); 59 | 60 | allocator->deallocate(uint8_array->buffer, allocator->state); 61 | uint8_array->buffer = NULL; 62 | uint8_array->buffer_length = 0lu; 63 | uint8_array->buffer_capacity = 0lu; 64 | 65 | return RCUTILS_RET_OK; 66 | } 67 | 68 | rcutils_ret_t 69 | rcutils_uint8_array_resize(rcutils_uint8_array_t * uint8_array, size_t new_size) 70 | { 71 | RCUTILS_CHECK_ARGUMENT_FOR_NULL(uint8_array, RCUTILS_RET_INVALID_ARGUMENT); 72 | 73 | if (0lu == new_size) { 74 | RCUTILS_SET_ERROR_MSG("new size of uint8_array has to be greater than zero"); 75 | return RCUTILS_RET_INVALID_ARGUMENT; 76 | } 77 | 78 | rcutils_allocator_t * allocator = &uint8_array->allocator; 79 | RCUTILS_CHECK_ALLOCATOR(allocator, return RCUTILS_RET_INVALID_ARGUMENT); 80 | 81 | if (new_size == uint8_array->buffer_capacity) { 82 | // nothing to do here 83 | return RCUTILS_RET_OK; 84 | } 85 | 86 | uint8_array->buffer = rcutils_reallocf( 87 | uint8_array->buffer, new_size * sizeof(uint8_t), allocator); 88 | RCUTILS_CHECK_FOR_NULL_WITH_MSG( 89 | uint8_array->buffer, 90 | "failed to reallocate memory for uint8 array", 91 | uint8_array->buffer_capacity = 0lu; 92 | uint8_array->buffer_length = 0lu; 93 | return RCUTILS_RET_BAD_ALLOC); 94 | 95 | uint8_array->buffer_capacity = new_size; 96 | if (new_size < uint8_array->buffer_length) { 97 | uint8_array->buffer_length = new_size; 98 | } 99 | 100 | return RCUTILS_RET_OK; 101 | } 102 | -------------------------------------------------------------------------------- /test/allocator_testing_utils.h: -------------------------------------------------------------------------------- 1 | // Copyright 2017 Open Source Robotics Foundation, Inc. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #ifndef ALLOCATOR_TESTING_UTILS_H_ 16 | #define ALLOCATOR_TESTING_UTILS_H_ 17 | 18 | #ifdef __cplusplus 19 | extern "C" 20 | { 21 | #endif 22 | 23 | #include 24 | 25 | #include "rcutils/allocator.h" 26 | 27 | typedef struct __failing_allocator_state 28 | { 29 | bool is_failing; 30 | } __failing_allocator_state; 31 | 32 | void * 33 | failing_malloc(size_t size, void * state) 34 | { 35 | if (((__failing_allocator_state *)state)->is_failing) { 36 | return nullptr; 37 | } 38 | return rcutils_get_default_allocator().allocate(size, rcutils_get_default_allocator().state); 39 | } 40 | 41 | void * 42 | failing_realloc(void * pointer, size_t size, void * state) 43 | { 44 | if (((__failing_allocator_state *)state)->is_failing) { 45 | return nullptr; 46 | } 47 | return rcutils_get_default_allocator().reallocate( 48 | pointer, size, rcutils_get_default_allocator().state); 49 | } 50 | 51 | void 52 | failing_free(void * pointer, void * state) 53 | { 54 | if (((__failing_allocator_state *)state)->is_failing) { 55 | return; 56 | } 57 | rcutils_get_default_allocator().deallocate(pointer, rcutils_get_default_allocator().state); 58 | } 59 | 60 | void * 61 | failing_calloc(size_t number_of_elements, size_t size_of_element, void * state) 62 | { 63 | if (((__failing_allocator_state *)state)->is_failing) { 64 | return nullptr; 65 | } 66 | return rcutils_get_default_allocator().zero_allocate( 67 | number_of_elements, size_of_element, rcutils_get_default_allocator().state); 68 | } 69 | 70 | static inline rcutils_allocator_t 71 | get_failing_allocator(void) 72 | { 73 | static __failing_allocator_state state; 74 | state.is_failing = true; 75 | auto failing_allocator = rcutils_get_default_allocator(); 76 | failing_allocator.allocate = failing_malloc; 77 | failing_allocator.deallocate = failing_free; 78 | failing_allocator.reallocate = failing_realloc; 79 | failing_allocator.zero_allocate = failing_calloc; 80 | failing_allocator.state = &state; 81 | return failing_allocator; 82 | } 83 | 84 | static inline void 85 | set_failing_allocator_is_failing(rcutils_allocator_t & failing_allocator, bool state) 86 | { 87 | ((__failing_allocator_state *)failing_allocator.state)->is_failing = state; 88 | } 89 | 90 | #ifdef __cplusplus 91 | } 92 | #endif 93 | 94 | #endif // ALLOCATOR_TESTING_UTILS_H_ 95 | -------------------------------------------------------------------------------- /test/benchmark/benchmark_error_handling.cpp: -------------------------------------------------------------------------------- 1 | // Copyright 2020 Open Source Robotics Foundation, Inc. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #include 16 | #include 17 | #include 18 | 19 | #include "rcutils/error_handling.h" 20 | 21 | static void benchmark_err_handling(benchmark::State & state) 22 | { 23 | for (auto _ : state) { 24 | rcutils_ret_t ret = 25 | rcutils_initialize_error_handling_thread_local_storage(rcutils_get_default_allocator()); 26 | assert(ret == RCUTILS_RET_OK); 27 | (void)ret; 28 | rcutils_reset_error(); 29 | const char * test_message = "test message"; 30 | RCUTILS_SET_ERROR_MSG(test_message); 31 | } 32 | } 33 | 34 | BENCHMARK(benchmark_err_handling); 35 | -------------------------------------------------------------------------------- /test/benchmark/benchmark_logging.cpp: -------------------------------------------------------------------------------- 1 | // Copyright 2020 Open Source Robotics Foundation, Inc. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #include 16 | #include 17 | #include 18 | #include 19 | 20 | #include "../allocator_testing_utils.h" 21 | #include "osrf_testing_tools_cpp/scope_exit.hpp" 22 | #include "rcutils/logging.h" 23 | 24 | size_t g_log_calls = 0; 25 | struct LogEvent 26 | { 27 | const rcutils_log_location_t * location; 28 | int level; 29 | std::string name; 30 | rcutils_time_point_value_t timestamp; 31 | std::string message; 32 | }; 33 | LogEvent g_last_log_event; 34 | 35 | static void benchmark_logging(benchmark::State & state) 36 | { 37 | for (auto _ : state) { 38 | auto ret_value = rcutils_logging_initialize(); 39 | (void) ret_value; 40 | OSRF_TESTING_TOOLS_CPP_SCOPE_EXIT( 41 | { 42 | ret_value = rcutils_logging_shutdown(); 43 | (void) ret_value; 44 | }); 45 | rcutils_logging_set_default_logger_level(RCUTILS_LOG_SEVERITY_DEBUG); 46 | 47 | auto rcutils_logging_console_output_handler = []( 48 | const rcutils_log_location_t * location, 49 | int level, const char * name, rcutils_time_point_value_t timestamp, 50 | const char * format, va_list * args) -> void 51 | { 52 | g_log_calls += 1; 53 | g_last_log_event.location = location; 54 | g_last_log_event.level = level; 55 | g_last_log_event.name = name ? name : ""; 56 | g_last_log_event.timestamp = timestamp; 57 | char buffer[1024]; 58 | vsnprintf(buffer, sizeof(buffer), format, *args); 59 | g_last_log_event.message = buffer; 60 | }; 61 | 62 | rcutils_logging_output_handler_t original_function = rcutils_logging_get_output_handler(); 63 | rcutils_logging_set_output_handler(rcutils_logging_console_output_handler); 64 | int original_level = rcutils_logging_get_default_logger_level(); 65 | 66 | // check all attributes for a debug log message 67 | rcutils_log_location_t location = {"func", "file", 42u}; 68 | rcutils_log(&location, RCUTILS_LOG_SEVERITY_DEBUG, "name1", "message %d", 11); 69 | rcutils_logging_set_default_logger_level(RCUTILS_LOG_SEVERITY_ERROR); 70 | rcutils_log(NULL, RCUTILS_LOG_SEVERITY_INFO, "name2", "message %d", 22); 71 | rcutils_logging_set_default_logger_level(RCUTILS_LOG_SEVERITY_UNSET); 72 | rcutils_log(NULL, RCUTILS_LOG_SEVERITY_INFO, "name3", "message %d", 33); 73 | rcutils_log(NULL, RCUTILS_LOG_SEVERITY_WARN, "", "%s", ""); 74 | rcutils_log(NULL, RCUTILS_LOG_SEVERITY_ERROR, "", "%s", ""); 75 | rcutils_log(NULL, RCUTILS_LOG_SEVERITY_FATAL, NULL, "%s", ""); 76 | 77 | // restore original state 78 | rcutils_logging_set_default_logger_level(original_level); 79 | rcutils_logging_set_output_handler(original_function); 80 | } 81 | } 82 | 83 | BENCHMARK(benchmark_logging); 84 | -------------------------------------------------------------------------------- /test/dummy_folder/dummy.dummy: -------------------------------------------------------------------------------- 1 | ROS2 2 | -------------------------------------------------------------------------------- /test/dummy_folder_with_subdir/dummy-subfolder/dummy-subfolder/dummy.dummy: -------------------------------------------------------------------------------- 1 | ROS2 2 | -------------------------------------------------------------------------------- /test/dummy_folder_with_subdir/dummy-subfolder/dummy.dummy: -------------------------------------------------------------------------------- 1 | ROS2 2 | -------------------------------------------------------------------------------- /test/dummy_folder_with_subdir/dummy.dummy: -------------------------------------------------------------------------------- 1 | ROS2 2 | -------------------------------------------------------------------------------- /test/dummy_readable_file.txt: -------------------------------------------------------------------------------- 1 | ROS2 2 | -------------------------------------------------------------------------------- /test/dummy_readable_writable_file.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ros2/rcutils/697ebd943c3438ffb9f20b64d07d1c9654a4c8d1/test/dummy_readable_writable_file.txt -------------------------------------------------------------------------------- /test/dummy_shared_library/dummy_shared_library.c: -------------------------------------------------------------------------------- 1 | // Copyright 2020 Open Source Robotics Foundation, Inc. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #include "./dummy_shared_library.h" // NOLINT 16 | 17 | void print_name(void) 18 | { 19 | printf("print_name\n"); 20 | } 21 | -------------------------------------------------------------------------------- /test/dummy_shared_library/dummy_shared_library.h: -------------------------------------------------------------------------------- 1 | // Copyright 2020 Open Source Robotics Foundation, Inc. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #ifndef DUMMY_SHARED_LIBRARY__DUMMY_SHARED_LIBRARY_H_ 16 | #define DUMMY_SHARED_LIBRARY__DUMMY_SHARED_LIBRARY_H_ 17 | 18 | #if _WIN32 19 | #ifdef DUMMY_SHARED_LIBRARY_BUILDING_DLL 20 | #define DUMMY_SHARED_LIBRARY_PUBLIC __declspec(dllexport) 21 | #else 22 | #define DUMMY_SHARED_LIBRARY_PUBLIC __declspec(dllimport) 23 | #endif 24 | #else 25 | #define DUMMY_SHARED_LIBRARY_PUBLIC 26 | #endif 27 | 28 | #include 29 | 30 | DUMMY_SHARED_LIBRARY_PUBLIC 31 | void print_name(void); 32 | 33 | #endif // DUMMY_SHARED_LIBRARY__DUMMY_SHARED_LIBRARY_H_ 34 | -------------------------------------------------------------------------------- /test/test_allocator.cpp: -------------------------------------------------------------------------------- 1 | // Copyright 2015 Open Source Robotics Foundation, Inc. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #include 16 | 17 | #include "./allocator_testing_utils.h" 18 | #include "rcutils/allocator.h" 19 | #include "rcutils/testing/fault_injection.h" 20 | 21 | #include "osrf_testing_tools_cpp/memory_tools/memory_tools.hpp" 22 | #include "osrf_testing_tools_cpp/scope_exit.hpp" 23 | 24 | using osrf_testing_tools_cpp::memory_tools::disable_monitoring_in_all_threads; 25 | using osrf_testing_tools_cpp::memory_tools::enable_monitoring_in_all_threads; 26 | using osrf_testing_tools_cpp::memory_tools::on_unexpected_calloc; 27 | using osrf_testing_tools_cpp::memory_tools::on_unexpected_free; 28 | using osrf_testing_tools_cpp::memory_tools::on_unexpected_malloc; 29 | using osrf_testing_tools_cpp::memory_tools::on_unexpected_realloc; 30 | 31 | class TestAllocatorFixture : public ::testing::Test 32 | { 33 | public: 34 | TestAllocatorFixture() {} 35 | 36 | void SetUp() 37 | { 38 | osrf_testing_tools_cpp::memory_tools::initialize(); 39 | enable_monitoring_in_all_threads(); 40 | } 41 | 42 | void TearDown() 43 | { 44 | disable_monitoring_in_all_threads(); 45 | osrf_testing_tools_cpp::memory_tools::uninitialize(); 46 | } 47 | }; 48 | 49 | /* Tests the default allocator. 50 | */ 51 | TEST_F(TestAllocatorFixture, test_default_allocator_normal) 52 | { 53 | size_t mallocs = 0; 54 | size_t reallocs = 0; 55 | size_t callocs = 0; 56 | size_t frees = 0; 57 | on_unexpected_malloc([&mallocs]() {mallocs++;}); 58 | on_unexpected_realloc([&reallocs]() {reallocs++;}); 59 | on_unexpected_calloc([&callocs]() {callocs++;}); 60 | on_unexpected_free([&frees]() {frees++;}); 61 | 62 | rcutils_allocator_t allocator; 63 | EXPECT_NO_MEMORY_OPERATIONS( 64 | { 65 | allocator = rcutils_get_default_allocator(); 66 | }); 67 | EXPECT_EQ(0u, mallocs); 68 | EXPECT_EQ(0u, reallocs); 69 | EXPECT_EQ(0u, callocs); 70 | EXPECT_EQ(0u, frees); 71 | 72 | void * allocated_memory = nullptr; 73 | EXPECT_NO_MEMORY_OPERATIONS( 74 | { 75 | allocated_memory = allocator.allocate(1024, allocator.state); 76 | }); 77 | EXPECT_EQ(1u, mallocs); 78 | EXPECT_NE(nullptr, allocated_memory); 79 | EXPECT_NO_MEMORY_OPERATIONS( 80 | { 81 | allocated_memory = allocator.reallocate(allocated_memory, 2048, allocator.state); 82 | }); 83 | EXPECT_EQ(1u, reallocs); 84 | EXPECT_NE(nullptr, allocated_memory); 85 | EXPECT_NO_MEMORY_OPERATIONS( 86 | { 87 | allocator.deallocate(allocated_memory, allocator.state); 88 | allocated_memory = allocator.zero_allocate(1024, sizeof(void *), allocator.state); 89 | }); 90 | EXPECT_EQ(1u, callocs); 91 | EXPECT_NE(nullptr, allocated_memory); 92 | EXPECT_NO_MEMORY_OPERATIONS( 93 | { 94 | allocator.deallocate(allocated_memory, allocator.state); 95 | }); 96 | EXPECT_EQ(1u, mallocs); 97 | EXPECT_EQ(1u, reallocs); 98 | EXPECT_EQ(1u, callocs); 99 | EXPECT_EQ(2u, frees); 100 | } 101 | 102 | TEST(test_allocator, realloc_failing_allocators) { 103 | void * allocated_memory = nullptr; 104 | EXPECT_EQ(nullptr, rcutils_reallocf(allocated_memory, 1024, nullptr)); 105 | 106 | auto failing_allocator = get_failing_allocator(); 107 | EXPECT_EQ(nullptr, rcutils_reallocf(allocated_memory, 1024, &failing_allocator)); 108 | } 109 | 110 | TEST(test_allocator, default_allocator_maybe_fail) { 111 | rcutils_allocator_t allocator = rcutils_get_default_allocator(); 112 | 113 | // Check allocate 114 | rcutils_fault_injection_set_count(RCUTILS_FAULT_INJECTION_FAIL_NOW); 115 | EXPECT_EQ(nullptr, allocator.allocate(1u, allocator.state)); 116 | EXPECT_EQ(RCUTILS_FAULT_INJECTION_NEVER_FAIL, rcutils_fault_injection_get_count()); 117 | 118 | void * pointer = allocator.allocate(1u, allocator.state); 119 | ASSERT_NE(nullptr, pointer); 120 | OSRF_TESTING_TOOLS_CPP_SCOPE_EXIT( 121 | { 122 | allocator.deallocate(pointer, allocator.state); 123 | }); 124 | 125 | // Check reallocate 126 | rcutils_fault_injection_set_count(RCUTILS_FAULT_INJECTION_FAIL_NOW); 127 | EXPECT_EQ(nullptr, allocator.reallocate(pointer, 1u, allocator.state)); 128 | EXPECT_EQ(RCUTILS_FAULT_INJECTION_NEVER_FAIL, rcutils_fault_injection_get_count()); 129 | 130 | // Check zero_allocate 131 | rcutils_fault_injection_set_count(RCUTILS_FAULT_INJECTION_FAIL_NOW); 132 | EXPECT_EQ(nullptr, allocator.zero_allocate(1u, 1u, allocator.state)); 133 | EXPECT_EQ(RCUTILS_FAULT_INJECTION_NEVER_FAIL, rcutils_fault_injection_get_count()); 134 | } 135 | -------------------------------------------------------------------------------- /test/test_atomics.c: -------------------------------------------------------------------------------- 1 | // Copyright 2019 Open Source Robotics Foundation, Inc. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #include 16 | #include "rcutils/stdatomic_helper.h" 17 | 18 | // Cannot use gtest or C++ because stdatomic_helper.h forces a compiler error if C++ is used 19 | 20 | #define TEST_ATOMIC_TYPE(BASE_TYPE, ATOMIC_TYPE) \ 21 | do { \ 22 | ATOMIC_TYPE uut; \ 23 | atomic_init(&uut, (BASE_TYPE)0); \ 24 | BASE_TYPE loaded_value; \ 25 | rcutils_atomic_load(&uut, loaded_value); \ 26 | if ((BASE_TYPE)0 != loaded_value) { \ 27 | fprintf(stderr, "load test failed " #ATOMIC_TYPE " base " #BASE_TYPE "\n"); \ 28 | return 1; \ 29 | } \ 30 | BASE_TYPE exchanged_value; \ 31 | rcutils_atomic_store(&uut, (BASE_TYPE)28); \ 32 | rcutils_atomic_exchange(&uut, exchanged_value, (BASE_TYPE)42); \ 33 | rcutils_atomic_load(&uut, loaded_value); \ 34 | if ((BASE_TYPE)28 != exchanged_value) { \ 35 | fprintf(stderr, "exchange test failed " #ATOMIC_TYPE " base " #BASE_TYPE "\n"); \ 36 | return 1; \ 37 | } \ 38 | if ((BASE_TYPE)42 != loaded_value) { \ 39 | fprintf(stderr, "exchange test failed " #ATOMIC_TYPE " base " #BASE_TYPE "\n"); \ 40 | return 1; \ 41 | } \ 42 | } while (0) 43 | 44 | int 45 | main(int argc, char * argv[]) 46 | { 47 | (void)argc; 48 | (void)argv; 49 | TEST_ATOMIC_TYPE(_Bool, atomic_bool); 50 | TEST_ATOMIC_TYPE(char, atomic_char); 51 | TEST_ATOMIC_TYPE(signed char, atomic_schar); 52 | TEST_ATOMIC_TYPE(unsigned char, atomic_uchar); 53 | TEST_ATOMIC_TYPE(short, atomic_short); // NOLINT(runtime/int) 54 | TEST_ATOMIC_TYPE(unsigned short, atomic_ushort); // NOLINT(runtime/int) 55 | TEST_ATOMIC_TYPE(int, atomic_int); 56 | TEST_ATOMIC_TYPE(unsigned int, atomic_uint); 57 | TEST_ATOMIC_TYPE(long, atomic_long); // NOLINT(runtime/int) 58 | TEST_ATOMIC_TYPE(unsigned long, atomic_ulong); // NOLINT(runtime/int) 59 | TEST_ATOMIC_TYPE(long long, atomic_llong); // NOLINT(runtime/int) 60 | TEST_ATOMIC_TYPE(unsigned long long, atomic_ullong); // NOLINT(runtime/int) 61 | TEST_ATOMIC_TYPE(int_least16_t, atomic_int_least16_t); 62 | TEST_ATOMIC_TYPE(uint_least16_t, atomic_uint_least16_t); 63 | TEST_ATOMIC_TYPE(int_least32_t, atomic_int_least32_t); 64 | TEST_ATOMIC_TYPE(uint_least32_t, atomic_uint_least32_t); 65 | TEST_ATOMIC_TYPE(int_least64_t, atomic_int_least64_t); 66 | TEST_ATOMIC_TYPE(uint_least64_t, atomic_uint_least64_t); 67 | TEST_ATOMIC_TYPE(int_fast16_t, atomic_int_fast16_t); 68 | TEST_ATOMIC_TYPE(uint_fast16_t, atomic_uint_fast16_t); 69 | TEST_ATOMIC_TYPE(int_fast32_t, atomic_int_fast32_t); 70 | TEST_ATOMIC_TYPE(uint_fast32_t, atomic_uint_fast32_t); 71 | TEST_ATOMIC_TYPE(int_fast64_t, atomic_int_fast64_t); 72 | TEST_ATOMIC_TYPE(uint_fast64_t, atomic_uint_fast64_t); 73 | TEST_ATOMIC_TYPE(intptr_t, atomic_intptr_t); 74 | TEST_ATOMIC_TYPE(uintptr_t, atomic_uintptr_t); 75 | TEST_ATOMIC_TYPE(size_t, atomic_size_t); 76 | TEST_ATOMIC_TYPE(ptrdiff_t, atomic_ptrdiff_t); 77 | TEST_ATOMIC_TYPE(intmax_t, atomic_intmax_t); 78 | TEST_ATOMIC_TYPE(uintmax_t, atomic_uintmax_t); 79 | 80 | TEST_ATOMIC_TYPE(int *, _Atomic(int *)); 81 | TEST_ATOMIC_TYPE(int **, _Atomic(int **)); 82 | return 0; 83 | } 84 | -------------------------------------------------------------------------------- /test/test_cmdline_parser.cpp: -------------------------------------------------------------------------------- 1 | // Copyright 2020 Open Source Robotics Foundation, Inc. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #include 16 | 17 | #include "rcutils/cmdline_parser.h" 18 | 19 | 20 | TEST(CmdLineParser, cli_option_exist) { 21 | char const * args[] = {"option1", "option2", "option3"}; 22 | const int args_count = sizeof(args) / sizeof(char *); 23 | char ** arr = const_cast(args); 24 | 25 | EXPECT_TRUE(rcutils_cli_option_exist(arr, arr + args_count, "option1")); 26 | EXPECT_TRUE(rcutils_cli_option_exist(arr, arr + args_count, "option2")); 27 | EXPECT_TRUE(rcutils_cli_option_exist(arr, arr + args_count, "option3")); 28 | EXPECT_FALSE(rcutils_cli_option_exist(arr, arr + args_count, "opt")); 29 | EXPECT_FALSE(rcutils_cli_option_exist(arr, arr + args_count, "NotRelated")); 30 | } 31 | 32 | TEST(CmdLineParser, cli_get_option) { 33 | char const * args[] = {"option1", "sub1", "option2"}; 34 | const int args_count = sizeof(args) / sizeof(char *); 35 | char ** arr = const_cast(args); 36 | 37 | EXPECT_STREQ(rcutils_cli_get_option(arr, arr + args_count, "option1"), "sub1"); 38 | EXPECT_STREQ(rcutils_cli_get_option(arr, arr + args_count, "NotRelated"), NULL); 39 | EXPECT_STREQ(rcutils_cli_get_option(arr, arr + args_count, "option2"), NULL); 40 | } 41 | -------------------------------------------------------------------------------- /test/test_env.cpp: -------------------------------------------------------------------------------- 1 | // Copyright 2020 Open Source Robotics Foundation, Inc. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #include 16 | 17 | #include 18 | 19 | #include "rcutils/env.h" 20 | #include "rcutils/error_handling.h" 21 | 22 | TEST(TestEnv, test_set_env) { 23 | const char * res = nullptr; 24 | 25 | // Invalid cases 26 | EXPECT_FALSE(rcutils_set_env(nullptr, nullptr)); 27 | rcutils_reset_error(); 28 | EXPECT_FALSE(rcutils_set_env("=INVALID_ENV_VAR=", nullptr)); 29 | rcutils_reset_error(); 30 | EXPECT_FALSE(rcutils_set_env("=INVALID_ENV_VAR=", "InvalidEnvValue")); 31 | rcutils_reset_error(); 32 | 33 | // Ensure we're starting clean 34 | ASSERT_EQ(nullptr, rcutils_get_env("NEW_ENV_VAR", &res)); 35 | ASSERT_STREQ("", res); 36 | 37 | // Simple set 38 | ASSERT_TRUE(rcutils_set_env("NEW_ENV_VAR", "NewEnvValue")); 39 | ASSERT_STREQ(nullptr, rcutils_get_env("NEW_ENV_VAR", &res)); 40 | EXPECT_STREQ(res, "NewEnvValue"); 41 | 42 | // Re-set 43 | ASSERT_TRUE(rcutils_set_env("NEW_ENV_VAR", "DifferentEnvValue")); 44 | ASSERT_STREQ(nullptr, rcutils_get_env("NEW_ENV_VAR", &res)); 45 | EXPECT_STREQ(res, "DifferentEnvValue"); 46 | 47 | // Un-set 48 | ASSERT_TRUE(rcutils_set_env("NEW_ENV_VAR", nullptr)); 49 | ASSERT_EQ(nullptr, rcutils_get_env("NEW_ENV_VAR", &res)); 50 | EXPECT_STREQ("", res); 51 | 52 | // Un-set again 53 | ASSERT_TRUE(rcutils_set_env("NEW_ENV_VAR", nullptr)); 54 | ASSERT_EQ(nullptr, rcutils_get_env("NEW_ENV_VAR", &res)); 55 | EXPECT_STREQ("", res); 56 | } 57 | 58 | /* Tests rcutils_get_env. 59 | * 60 | * Expected environment variables must be set by the calling code: 61 | * 62 | * - EMPTY_TEST= 63 | * - NORMAL_TEST=foo 64 | * 65 | * These are set in the call to `ament_add_gtest()` in the `CMakeLists.txt`. 66 | */ 67 | TEST(TestEnv, test_get_env) { 68 | const char * env; 69 | const char * ret; 70 | ret = rcutils_get_env("NORMAL_TEST", NULL); 71 | EXPECT_STREQ("argument env_value is null", ret); 72 | ret = rcutils_get_env(NULL, &env); 73 | EXPECT_STREQ("argument env_name is null", ret); 74 | ret = rcutils_get_env("SHOULD_NOT_EXIST_TEST", &env); 75 | EXPECT_FALSE(ret); 76 | EXPECT_STREQ("", env); 77 | ret = rcutils_get_env("NORMAL_TEST", &env); 78 | EXPECT_FALSE(ret); 79 | EXPECT_FALSE(NULL == env); 80 | EXPECT_STREQ("foo", env); 81 | ret = rcutils_get_env("EMPTY_TEST", &env); 82 | EXPECT_FALSE(ret); 83 | EXPECT_FALSE(NULL == env); 84 | EXPECT_STREQ("", env); 85 | } 86 | 87 | /* Tests rcutils_get_env. 88 | * 89 | * Expected environment variables must be set by the calling code: 90 | * 91 | * - EMPTY_TEST= 92 | * - NORMAL_TEST=foo 93 | * 94 | * These are set in the call to `ament_add_gtest()` in the `CMakeLists.txt`. 95 | */ 96 | TEST(TestEnv, test_set_env_overwrite) { 97 | const char * env; 98 | const char * ret; 99 | 100 | // Do not overwrite environment variable if preset if overwrite is set false. 101 | EXPECT_TRUE(rcutils_set_env_overwrite("NORMAL_TEST", "NewEnvValue", false)); 102 | ret = rcutils_get_env("NORMAL_TEST", &env); 103 | EXPECT_TRUE(NULL == ret); 104 | EXPECT_STREQ("foo", env); 105 | 106 | // Overwrite environment variable if present if overwrite is set true. 107 | EXPECT_TRUE(rcutils_set_env_overwrite("NORMAL_TEST", "NewEnvValue", true)); 108 | ret = rcutils_get_env("NORMAL_TEST", &env); 109 | EXPECT_TRUE(NULL == ret); 110 | EXPECT_STREQ("NewEnvValue", env); 111 | } 112 | 113 | TEST(TestEnv, test_get_home) { 114 | EXPECT_STRNE(NULL, rcutils_get_home_dir()); 115 | const char * home = NULL; 116 | 117 | #ifdef _WIN32 118 | // Assert pre-condition that USERPROFILE is defined 119 | const char * ret = rcutils_get_env("USERPROFILE", &home); 120 | ASSERT_EQ(NULL, ret); 121 | 122 | // Check USERPROFILE is not defined 123 | EXPECT_TRUE(rcutils_set_env("USERPROFILE", NULL)); 124 | EXPECT_EQ(NULL, rcutils_get_home_dir()); 125 | #else 126 | // Assert pre-condition that HOME is defined 127 | const char * ret = rcutils_get_env("HOME", &home); 128 | ASSERT_EQ(NULL, ret); 129 | 130 | // Check HOME is not defined 131 | EXPECT_TRUE(rcutils_set_env("HOME", NULL)); 132 | EXPECT_EQ(NULL, rcutils_get_home_dir()); 133 | #endif 134 | } 135 | -------------------------------------------------------------------------------- /test/test_error_handling_helpers.cpp: -------------------------------------------------------------------------------- 1 | // Copyright 2018 Open Source Robotics Foundation, Inc. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #include 16 | 17 | #include "gmock/gmock.h" 18 | 19 | #include "osrf_testing_tools_cpp/memory_tools/gtest_quickstart.hpp" 20 | 21 | #include "../src/error_handling_helpers.h" 22 | 23 | TEST(test_error_handling, copy_string) { 24 | osrf_testing_tools_cpp::memory_tools::ScopedQuickstartGtest scoped_quickstart_gtest; 25 | char buffer[10]; 26 | memset(buffer, '?', sizeof(buffer)); 27 | size_t written; 28 | 29 | // normal truncation 30 | EXPECT_NO_MEMORY_OPERATIONS( 31 | { 32 | written = __rcutils_copy_string(buffer, 3, "0123456789"); 33 | }); 34 | EXPECT_EQ(written, 2u); 35 | EXPECT_EQ(strnlen(buffer, sizeof(buffer)), 2u); 36 | EXPECT_STREQ(buffer, "01"); 37 | 38 | // normal truncation, 1 short of buffer length 39 | EXPECT_NO_MEMORY_OPERATIONS( 40 | { 41 | written = __rcutils_copy_string(buffer, 9, "0123456789"); 42 | }); 43 | EXPECT_EQ(written, 8u); 44 | EXPECT_EQ(strnlen(buffer, sizeof(buffer)), 8u); 45 | EXPECT_STREQ(buffer, "01234567"); 46 | 47 | // input smaller than buffer, 1 short of buffer length 48 | EXPECT_NO_MEMORY_OPERATIONS( 49 | { 50 | written = __rcutils_copy_string(buffer, 9, ""); 51 | }); 52 | EXPECT_EQ(written, 0u); 53 | EXPECT_EQ(strnlen(buffer, sizeof(buffer)), 0u); 54 | EXPECT_STREQ(buffer, ""); 55 | 56 | // copy where src and dst overlap (testing use of memmove vs memcpy) 57 | EXPECT_NO_MEMORY_OPERATIONS( 58 | { 59 | written = __rcutils_copy_string(buffer, sizeof(buffer), "1234567890"); 60 | }); 61 | EXPECT_EQ(written, 9u); 62 | EXPECT_STREQ(buffer, "123456789"); 63 | EXPECT_NO_MEMORY_OPERATIONS( 64 | { 65 | written = __rcutils_copy_string(buffer, sizeof(buffer), buffer + 3); 66 | }); 67 | EXPECT_EQ(written, 6u); 68 | EXPECT_EQ(strnlen(buffer, sizeof(buffer)), (sizeof(buffer) - 1) - 3); 69 | EXPECT_STREQ(buffer, "456789"); 70 | } 71 | 72 | TEST(test_error_handling, reverse_str) { 73 | osrf_testing_tools_cpp::memory_tools::ScopedQuickstartGtest scoped_quickstart_gtest; 74 | { 75 | char buffer[] = "even"; 76 | EXPECT_NO_MEMORY_OPERATIONS( 77 | { 78 | __rcutils_reverse_str(buffer, strnlen(buffer, sizeof(buffer))); 79 | }); 80 | EXPECT_STREQ(buffer, "neve"); 81 | } 82 | { 83 | char buffer[] = "reverseme"; 84 | EXPECT_NO_MEMORY_OPERATIONS( 85 | { 86 | __rcutils_reverse_str(buffer, strnlen(buffer, sizeof(buffer))); 87 | }); 88 | EXPECT_STREQ(buffer, "emesrever"); 89 | } 90 | { 91 | char buffer[] = "a"; 92 | EXPECT_NO_MEMORY_OPERATIONS( 93 | { 94 | __rcutils_reverse_str(buffer, strnlen(buffer, sizeof(buffer))); 95 | }); 96 | EXPECT_STREQ(buffer, "a"); 97 | } 98 | { 99 | char buffer[] = "reverseme"; 100 | EXPECT_NO_MEMORY_OPERATIONS( 101 | { 102 | __rcutils_reverse_str(buffer, 3); 103 | }); 104 | EXPECT_STREQ(buffer, "vererseme"); 105 | } 106 | { 107 | char buffer[] = "doesntmatter"; 108 | EXPECT_NO_MEMORY_OPERATIONS( 109 | { 110 | __rcutils_reverse_str(buffer, 0); 111 | }); 112 | EXPECT_STREQ(buffer, "doesntmatter"); 113 | } 114 | } 115 | 116 | TEST(test_error_handling, convert_uint64_t_into_c_str) { 117 | osrf_testing_tools_cpp::memory_tools::ScopedQuickstartGtest scoped_quickstart_gtest; 118 | { 119 | uint64_t number = UINT64_MAX; 120 | char buffer[21]; 121 | EXPECT_NO_MEMORY_OPERATIONS( 122 | { 123 | __rcutils_convert_uint64_t_into_c_str(number, buffer, sizeof(buffer)); 124 | }); 125 | EXPECT_STREQ(buffer, "18446744073709551615"); 126 | } 127 | { 128 | uint64_t number = 0; 129 | char buffer[21]; 130 | EXPECT_NO_MEMORY_OPERATIONS( 131 | { 132 | __rcutils_convert_uint64_t_into_c_str(number, buffer, sizeof(buffer)); 133 | }); 134 | EXPECT_STREQ(buffer, "0"); 135 | } 136 | { 137 | uint64_t number = 42; 138 | char buffer[21]; 139 | EXPECT_NO_MEMORY_OPERATIONS( 140 | { 141 | __rcutils_convert_uint64_t_into_c_str(number, buffer, sizeof(buffer)); 142 | }); 143 | EXPECT_STREQ(buffer, "42"); 144 | } 145 | { 146 | uint64_t number = INT64_MAX; 147 | char buffer[21]; 148 | EXPECT_NO_MEMORY_OPERATIONS( 149 | { 150 | __rcutils_convert_uint64_t_into_c_str(number, buffer, sizeof(buffer)); 151 | }); 152 | EXPECT_STREQ(buffer, "9223372036854775807"); 153 | } 154 | } 155 | 156 | TEST(test_error_handling, format_error_string) { 157 | osrf_testing_tools_cpp::memory_tools::ScopedQuickstartGtest scoped_quickstart_gtest; 158 | rcutils_error_string_t error_string {""}; 159 | rcutils_error_state_t error_state {"test error message", "/path/to/source", 42}; 160 | 161 | EXPECT_NO_MEMORY_OPERATIONS( 162 | { 163 | __rcutils_format_error_string(&error_string, &error_state); 164 | }); 165 | } 166 | -------------------------------------------------------------------------------- /test/test_find.cpp: -------------------------------------------------------------------------------- 1 | // Copyright 2017 Open Source Robotics Foundation, Inc. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #include 16 | 17 | #include "gtest/gtest.h" 18 | 19 | #include "rcutils/find.h" 20 | 21 | #define LOG(expected, actual) printf("Expected: %zu Actual: %zu\n", expected, actual); 22 | 23 | size_t test_find(const char * str, char delimiter, size_t expected_pos) 24 | { 25 | size_t actual_pos = rcutils_find(str, delimiter); 26 | EXPECT_EQ(expected_pos, actual_pos); 27 | return actual_pos; 28 | } 29 | 30 | size_t test_findn(const char * str, char delimiter, size_t str_len, size_t expected_pos) 31 | { 32 | size_t actual_pos = rcutils_findn(str, delimiter, str_len); 33 | EXPECT_EQ(expected_pos, actual_pos); 34 | return actual_pos; 35 | } 36 | 37 | size_t test_find_last(const char * str, char delimiter, size_t expected_pos) 38 | { 39 | size_t actual_pos = rcutils_find_last(str, delimiter); 40 | EXPECT_EQ(expected_pos, actual_pos); 41 | return actual_pos; 42 | } 43 | 44 | size_t test_find_lastn(const char * str, char delimiter, size_t str_len, size_t expected_pos) 45 | { 46 | size_t actual_pos = rcutils_find_lastn(str, delimiter, str_len); 47 | EXPECT_EQ(expected_pos, actual_pos); 48 | return actual_pos; 49 | } 50 | 51 | TEST(test_find, find) { 52 | size_t ret0 = test_find("", '/', SIZE_MAX); 53 | // We cast SIZE_MAX to a size_t here (and below) to shut up warnings on macOS. 54 | // The problem on macOS is that size_t is a long unsigned int, while SIZE_MAX 55 | // is an unsigned long long. While the two are compatible on 64-bit, they are 56 | // not considered the "same" by the compiler, and throw a warning. Just cast 57 | // SIZE_MAX to size_t to make the compiler happy. 58 | LOG((size_t)SIZE_MAX, ret0); 59 | 60 | size_t ret00 = test_find(NULL, '/', SIZE_MAX); 61 | LOG((size_t)SIZE_MAX, ret00); 62 | 63 | size_t ret1 = test_find("hello_world", '/', SIZE_MAX); 64 | LOG((size_t)SIZE_MAX, ret1); 65 | 66 | size_t ret2 = test_find("hello/world", '/', 5); 67 | LOG((size_t)5, ret2); 68 | 69 | size_t ret3 = test_find("/hello/world", '/', 0); 70 | LOG((size_t)0, ret3); 71 | 72 | size_t ret4 = test_find("hello/world/", '/', 5); 73 | LOG((size_t)5, ret4); 74 | 75 | size_t ret5 = test_find("hello//world", '/', 5); 76 | LOG((size_t)5, ret5); 77 | 78 | size_t ret6 = test_find("/hello//world", '/', 0); 79 | LOG((size_t)0, ret6); 80 | } 81 | 82 | TEST(test_find, findn) { 83 | size_t ret0 = test_findn("", '/', 0, SIZE_MAX); 84 | LOG((size_t)SIZE_MAX, ret0); 85 | 86 | size_t ret1 = test_findn(NULL, '/', 10, SIZE_MAX); 87 | LOG((size_t)SIZE_MAX, ret1); 88 | 89 | size_t ret2 = test_findn("hello_world", '/', strlen("hello_world"), SIZE_MAX); 90 | LOG((size_t)SIZE_MAX, ret2); 91 | 92 | size_t ret3 = test_findn("hello/world", '/', strlen("hello/world"), 5); 93 | LOG((size_t)5, ret3); 94 | 95 | size_t ret4 = test_findn("hello///", '/', strlen("hello/"), 5); 96 | LOG((size_t)5, ret4); 97 | } 98 | 99 | TEST(test_find, find_last) { 100 | size_t ret0 = test_find_last("", '/', SIZE_MAX); 101 | LOG((size_t)SIZE_MAX, ret0); 102 | 103 | size_t ret00 = test_find_last(NULL, '/', SIZE_MAX); 104 | LOG((size_t)SIZE_MAX, ret00); 105 | 106 | size_t ret1 = test_find_last("hello_world", '/', SIZE_MAX); 107 | LOG((size_t)SIZE_MAX, ret1); 108 | 109 | size_t ret2 = test_find_last("hello/world", '/', 5); 110 | LOG((size_t)5, ret2); 111 | 112 | size_t ret3 = test_find_last("/hello/world", '/', 6); 113 | LOG((size_t)6, ret3); 114 | 115 | size_t ret4 = test_find_last("hello/world/", '/', strlen("hello_world/") - 1); 116 | LOG((size_t)strlen("hello_world/") - 1, ret4); 117 | 118 | size_t ret5 = test_find_last("hello//world", '/', 6); 119 | LOG((size_t)6, ret5); 120 | 121 | size_t ret6 = test_find_last("/hello//world", '/', 7); 122 | LOG((size_t)7, ret6); 123 | } 124 | 125 | TEST(test_find, find_lastn) { 126 | size_t ret0 = test_find_lastn("", '/', 0, SIZE_MAX); 127 | LOG((size_t)SIZE_MAX, ret0); 128 | 129 | size_t ret1 = test_find_lastn(NULL, '/', 10, SIZE_MAX); 130 | LOG((size_t)SIZE_MAX, ret1); 131 | 132 | size_t ret2 = test_find_lastn("hello_world", '/', strlen("hello_world"), SIZE_MAX); 133 | LOG((size_t)SIZE_MAX, ret2); 134 | 135 | size_t ret3 = test_find_lastn("hello/world", '/', strlen("hello/world"), 5); 136 | LOG((size_t)5, ret3); 137 | 138 | size_t ret4 = test_find_lastn("/hello/world", '/', strlen("/hello"), 0); 139 | LOG((size_t)0, ret4); 140 | 141 | size_t ret5 = test_find_lastn( 142 | "hello/world///", '/', strlen("hello/world/"), strlen("hello/world/") - 1); 143 | LOG((size_t)strlen("hello/world/") - 1, ret5); 144 | } 145 | -------------------------------------------------------------------------------- /test/test_format_string.cpp: -------------------------------------------------------------------------------- 1 | // Copyright 2017 Open Source Robotics Foundation, Inc. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #include 16 | 17 | #include 18 | 19 | #include "./allocator_testing_utils.h" 20 | 21 | #include "rcutils/allocator.h" 22 | #include "rcutils/format_string.h" 23 | 24 | TEST(test_format_string_limit, nominal) { 25 | { 26 | auto allocator = rcutils_get_default_allocator(); 27 | char * formatted = rcutils_format_string_limit(allocator, 10, "%s", "test"); 28 | EXPECT_STREQ("test", formatted); 29 | if (formatted) { 30 | allocator.deallocate(formatted, allocator.state); 31 | } 32 | } 33 | 34 | { 35 | auto allocator = rcutils_get_default_allocator(); 36 | char * formatted = rcutils_format_string_limit(allocator, 3, "%s", "test"); 37 | EXPECT_STREQ("te", formatted); 38 | if (formatted) { 39 | allocator.deallocate(formatted, allocator.state); 40 | } 41 | } 42 | 43 | { 44 | auto allocator = rcutils_get_default_allocator(); 45 | char * formatted = rcutils_format_string_limit(allocator, 3, "string is too long %s", "test"); 46 | EXPECT_STREQ("st", formatted); 47 | if (formatted) { 48 | allocator.deallocate(formatted, allocator.state); 49 | } 50 | } 51 | } 52 | 53 | TEST(test_format_string_limit, invalid_arguments) { 54 | auto allocator = rcutils_get_default_allocator(); 55 | auto failing_allocator = get_failing_allocator(); 56 | 57 | char * formatted = rcutils_format_string_limit(allocator, 10, NULL); 58 | EXPECT_STREQ(NULL, formatted); 59 | 60 | formatted = rcutils_format_string_limit(failing_allocator, 10, "%s", "test"); 61 | EXPECT_STREQ(NULL, formatted); 62 | } 63 | -------------------------------------------------------------------------------- /test/test_isalnum_no_locale.cpp: -------------------------------------------------------------------------------- 1 | // Copyright 2017 Open Source Robotics Foundation, Inc. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #include 16 | 17 | #include "gtest/gtest.h" 18 | 19 | #include "rcutils/isalnum_no_locale.h" 20 | 21 | TEST(test_isalnum_no_locale, valid_characters_ok) { 22 | std::string valid("0123456789" "ABCDEFGHIJKLMNOPQRSTUVWXYZ" "abcdefghijklmnopqrstuvwxyz"); 23 | for (auto & c : valid) { 24 | ASSERT_TRUE(rcutils_isalnum_no_locale(c)); 25 | } 26 | } 27 | 28 | TEST(test_isalnum_no_locale, invalid_characters_fail) { 29 | std::string invalid("/" /*0-9*/ ":;<=>?@" /*A-Z*/ "[\\]^_`" /*a-z*/); 30 | for (auto & c : invalid) { 31 | ASSERT_FALSE(rcutils_isalnum_no_locale(c)); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /test/test_join.cpp: -------------------------------------------------------------------------------- 1 | // Copyright 2025 Open Source Robotics Foundation, Inc. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #include "gtest/gtest.h" 16 | 17 | #include "./allocator_testing_utils.h" 18 | #include "./time_bomb_allocator_testing_utils.h" 19 | #include "rcutils/error_handling.h" 20 | #include "rcutils/join.h" 21 | #include "rcutils/types/string_array.h" 22 | 23 | #define LOG(expected, actual) printf("Expected: %s Actual: %s\n", expected, actual); 24 | 25 | TEST(test_join, join) { 26 | rcutils_allocator_t allocator = rcutils_get_default_allocator(); 27 | rcutils_allocator_t bad_allocator = rcutils_get_zero_initialized_allocator(); 28 | rcutils_allocator_t time_bomb_allocator = get_time_bomb_allocator(); 29 | rcutils_string_array_t tokens0 = rcutils_get_zero_initialized_string_array(); 30 | rcutils_string_array_t tokens1 = rcutils_get_zero_initialized_string_array(); 31 | rcutils_string_array_t tokens2 = rcutils_get_zero_initialized_string_array(); 32 | char * new_string; 33 | 34 | ASSERT_EQ( 35 | RCUTILS_RET_OK, 36 | rcutils_string_array_init(&tokens0, 0, &allocator)); 37 | ASSERT_EQ( 38 | RCUTILS_RET_OK, 39 | rcutils_string_array_init(&tokens1, 1, &allocator)); 40 | tokens1.data[0] = strdup("hallo"); 41 | ASSERT_EQ( 42 | RCUTILS_RET_OK, 43 | rcutils_string_array_init(&tokens2, 2, &allocator)); 44 | tokens2.data[0] = strdup("hello"); 45 | tokens2.data[1] = strdup("world"); 46 | 47 | EXPECT_STREQ( 48 | nullptr, 49 | rcutils_join(NULL, "-", allocator)); 50 | rcutils_reset_error(); 51 | 52 | EXPECT_STREQ( 53 | nullptr, 54 | rcutils_join(&tokens0, NULL, allocator)); 55 | rcutils_reset_error(); 56 | 57 | EXPECT_STREQ( 58 | nullptr, 59 | rcutils_join(&tokens0, " ", bad_allocator)); 60 | rcutils_reset_error(); 61 | 62 | // Allocating new_string fails 63 | set_time_bomb_allocator_malloc_count(time_bomb_allocator, 0); 64 | EXPECT_STREQ( 65 | nullptr, 66 | rcutils_join(&tokens2, " ", time_bomb_allocator)); 67 | rcutils_reset_error(); 68 | 69 | new_string = rcutils_join(&tokens0, " ", allocator); 70 | EXPECT_STREQ("", new_string); 71 | allocator.deallocate(new_string, &allocator.state); 72 | 73 | new_string = rcutils_join(&tokens1, " ", allocator); 74 | EXPECT_STREQ("hallo", new_string); 75 | allocator.deallocate(new_string, &allocator.state); 76 | 77 | new_string = rcutils_join(&tokens2, "", allocator); 78 | EXPECT_STREQ("helloworld", new_string); 79 | allocator.deallocate(new_string, &allocator.state); 80 | 81 | new_string = rcutils_join(&tokens2, " ", allocator); 82 | EXPECT_STREQ("hello world", new_string); 83 | allocator.deallocate(new_string, &allocator.state); 84 | 85 | new_string = rcutils_join(&tokens2, " ... ", allocator); 86 | EXPECT_STREQ("hello ... world", new_string); 87 | allocator.deallocate(new_string, &allocator.state); 88 | 89 | EXPECT_EQ( 90 | RCUTILS_RET_OK, 91 | rcutils_string_array_fini(&tokens0)); 92 | 93 | EXPECT_EQ( 94 | RCUTILS_RET_OK, 95 | rcutils_string_array_fini(&tokens1)); 96 | 97 | EXPECT_EQ( 98 | RCUTILS_RET_OK, 99 | rcutils_string_array_fini(&tokens2)); 100 | } 101 | -------------------------------------------------------------------------------- /test/test_logging_bad_env.cpp: -------------------------------------------------------------------------------- 1 | // Copyright 2020 Open Source Robotics Foundation, Inc. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #include 16 | 17 | #include "rcutils/logging.h" 18 | 19 | TEST(TestBadCustomEnv, test_initialize) { 20 | EXPECT_FALSE(g_rcutils_logging_initialized); 21 | ASSERT_EQ(RCUTILS_RET_INVALID_ARGUMENT, rcutils_logging_initialize()); 22 | } 23 | -------------------------------------------------------------------------------- /test/test_logging_console_output_handler.cpp: -------------------------------------------------------------------------------- 1 | // Copyright 2020 Open Source Robotics Foundation, Inc. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #include 16 | 17 | #include 18 | #include 19 | 20 | #include "osrf_testing_tools_cpp/scope_exit.hpp" 21 | #include "rcutils/logging.h" 22 | 23 | static void call_handler( 24 | const rcutils_log_location_t * location, 25 | int severity, const char * name, rcutils_time_point_value_t timestamp, 26 | const char * format, ...) 27 | { 28 | va_list args; 29 | va_start(args, format); 30 | rcutils_logging_console_output_handler(location, severity, name, timestamp, format, &args); 31 | va_end(args); 32 | } 33 | 34 | // There are no outputs of the handler function, and the only result are fprintf() calls. 35 | // This is just a smoke test to check that the code can handle simple inputs cleanly. 36 | TEST(TestLoggingConsoleOutputHandler, typical_inputs) { 37 | ASSERT_EQ(RCUTILS_RET_OK, rcutils_logging_initialize()); 38 | OSRF_TESTING_TOOLS_CPP_SCOPE_EXIT( 39 | { 40 | EXPECT_EQ(RCUTILS_RET_OK, rcutils_logging_shutdown()); 41 | }); 42 | 43 | rcutils_log_location_t log_location = { 44 | "test_function", 45 | "test_file", 46 | 1, 47 | }; 48 | const char * log_name = "test_name"; 49 | rcutils_time_point_value_t timestamp = 1; 50 | const char * format = "%s - %s"; 51 | call_handler( 52 | &log_location, RCUTILS_LOG_SEVERITY_DEBUG, log_name, timestamp, format, "part1", "part2"); 53 | call_handler( 54 | &log_location, RCUTILS_LOG_SEVERITY_INFO, log_name, timestamp, format, "part1", "part2"); 55 | call_handler( 56 | &log_location, RCUTILS_LOG_SEVERITY_WARN, log_name, timestamp, format, "part1", "part2"); 57 | call_handler( 58 | &log_location, RCUTILS_LOG_SEVERITY_ERROR, log_name, timestamp, format, "part1", "part2"); 59 | call_handler( 60 | &log_location, RCUTILS_LOG_SEVERITY_FATAL, log_name, timestamp, format, "part1", "part2"); 61 | } 62 | 63 | // There are no outputs of the handler function, and the only result are fprintf() calls. 64 | // This is just a smoke test to check that the code can handle bad inputs cleanly. 65 | TEST(TestLoggingConsoleOutputHandler, bad_inputs) { 66 | rcutils_log_location_t log_location = { 67 | "test_function", 68 | "test_file", 69 | 1, 70 | }; 71 | const char * log_name = "test_name"; 72 | rcutils_time_point_value_t timestamp = 1; 73 | const char * format = "%s - %s"; 74 | 75 | // Check !g_rcutils_logging_initialized 76 | call_handler( 77 | &log_location, RCUTILS_LOG_SEVERITY_DEBUG, log_name, timestamp, format, "part1", "part2"); 78 | 79 | ASSERT_EQ(RCUTILS_RET_OK, rcutils_logging_initialize()); 80 | OSRF_TESTING_TOOLS_CPP_SCOPE_EXIT( 81 | { 82 | EXPECT_EQ(RCUTILS_RET_OK, rcutils_logging_shutdown()); 83 | }); 84 | 85 | call_handler( 86 | nullptr, RCUTILS_LOG_SEVERITY_INFO, log_name, timestamp, format, "part1", "part2"); 87 | call_handler( 88 | &log_location, RCUTILS_LOG_SEVERITY_UNSET, log_name, timestamp, format, "part1", "part2"); 89 | call_handler( 90 | &log_location, RCUTILS_LOG_SEVERITY_INFO, nullptr, timestamp, format, "part1", "part2"); 91 | call_handler( 92 | &log_location, RCUTILS_LOG_SEVERITY_INFO, log_name, 0, format, "part1", "part2"); 93 | 94 | // If format is NULL, this call will segfault on some (but not all) systems 95 | call_handler( 96 | &log_location, RCUTILS_LOG_SEVERITY_INFO, log_name, timestamp, "bad format", "part1", "part2"); 97 | } 98 | -------------------------------------------------------------------------------- /test/test_logging_custom_env.cpp: -------------------------------------------------------------------------------- 1 | // Copyright 2020 Open Source Robotics Foundation, Inc. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #include 16 | 17 | #include 18 | #include 19 | 20 | #include "./allocator_testing_utils.h" 21 | #include "./mocking_utils/patch.hpp" 22 | #include "osrf_testing_tools_cpp/scope_exit.hpp" 23 | #include "rcutils/logging.h" 24 | 25 | TEST(TestLoggingCustomEnv, test_logging) { 26 | EXPECT_FALSE(g_rcutils_logging_initialized); 27 | ASSERT_EQ(RCUTILS_RET_OK, rcutils_logging_initialize()); 28 | OSRF_TESTING_TOOLS_CPP_SCOPE_EXIT( 29 | { 30 | EXPECT_EQ(RCUTILS_RET_OK, rcutils_logging_shutdown()); 31 | }); 32 | EXPECT_TRUE(g_rcutils_logging_initialized); 33 | rcutils_logging_set_default_logger_level(RCUTILS_LOG_SEVERITY_DEBUG); 34 | 35 | rcutils_ret_t ret; 36 | rcutils_allocator_t allocator = rcutils_get_default_allocator(); 37 | rcutils_char_array_t msg_buf, output_buf; 38 | ret = rcutils_char_array_init(&msg_buf, 1024, &allocator); 39 | ASSERT_EQ(RCUTILS_RET_OK, ret); 40 | ret = rcutils_char_array_init(&output_buf, 1024, &allocator); 41 | ASSERT_EQ(RCUTILS_RET_OK, ret); 42 | rcutils_time_point_value_t now = 0; 43 | 44 | ret = rcutils_logging_format_message( 45 | NULL, RCUTILS_LOG_SEVERITY_FATAL, NULL, now, msg_buf.buffer, &output_buf); 46 | EXPECT_EQ(RCUTILS_RET_OK, ret); 47 | 48 | EXPECT_EQ(RCUTILS_RET_OK, rcutils_char_array_fini(&output_buf)); 49 | EXPECT_EQ(RCUTILS_RET_OK, rcutils_char_array_fini(&msg_buf)); 50 | } 51 | 52 | TEST(TestLoggingCustomEnv, test_logging_with_buffering_issues) { 53 | auto mock = mocking_utils::patch("lib:rcutils", setvbuf, [](auto && ...) {return -1;}); 54 | EXPECT_FALSE(g_rcutils_logging_initialized); 55 | EXPECT_EQ(RCUTILS_RET_ERROR, rcutils_logging_initialize()); 56 | EXPECT_FALSE(g_rcutils_logging_initialized); 57 | } 58 | -------------------------------------------------------------------------------- /test/test_logging_enable_for.cpp: -------------------------------------------------------------------------------- 1 | // Copyright 2020 Open Source Robotics Foundation, Inc. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #include 16 | 17 | #include 18 | 19 | #include "osrf_testing_tools_cpp/scope_exit.hpp" 20 | #include "rcutils/logging.h" 21 | 22 | TEST(test_logging_logger_is_enabled_for, test_logging_logger_is_enabled_for) { 23 | bool ret; 24 | ret = rcutils_logging_logger_is_enabled_for( 25 | "rmw_fastrtps_cpp", RCUTILS_LOG_SEVERITY_DEBUG); 26 | ASSERT_FALSE(ret); 27 | 28 | rcutils_ret_t ret_set_severity; 29 | ret_set_severity = 30 | rcutils_logging_set_logger_level("rmw_fastrtps_cpp", RCUTILS_LOG_SEVERITY_DEBUG); 31 | ASSERT_EQ(RCUTILS_RET_OK, ret_set_severity); 32 | ret = rcutils_logging_logger_is_enabled_for( 33 | "rmw_fastrtps_cpp", RCUTILS_LOG_SEVERITY_DEBUG); 34 | ASSERT_TRUE(ret); 35 | 36 | ret_set_severity = 37 | rcutils_logging_set_logger_level("rmw_fastrtps_cpp", RCUTILS_LOG_SEVERITY_INFO); 38 | ASSERT_EQ(RCUTILS_RET_OK, ret_set_severity); 39 | ret = rcutils_logging_logger_is_enabled_for( 40 | "rmw_fastrtps_cpp", RCUTILS_LOG_SEVERITY_INFO); 41 | ASSERT_TRUE(ret); 42 | 43 | ret_set_severity = 44 | rcutils_logging_set_logger_level("rmw_fastrtps_cpp", RCUTILS_LOG_SEVERITY_WARN); 45 | ASSERT_EQ(RCUTILS_RET_OK, ret_set_severity); 46 | ret = rcutils_logging_logger_is_enabled_for( 47 | "rmw_fastrtps_cpp", RCUTILS_LOG_SEVERITY_WARN); 48 | ASSERT_TRUE(ret); 49 | 50 | ret_set_severity = 51 | rcutils_logging_set_logger_level("rmw_fastrtps_cpp", RCUTILS_LOG_SEVERITY_ERROR); 52 | ASSERT_EQ(RCUTILS_RET_OK, ret_set_severity); 53 | ret = rcutils_logging_logger_is_enabled_for( 54 | "rmw_fastrtps_cpp", RCUTILS_LOG_SEVERITY_ERROR); 55 | ASSERT_TRUE(ret); 56 | 57 | ret_set_severity = 58 | rcutils_logging_set_logger_level("rmw_fastrtps_cpp", RCUTILS_LOG_SEVERITY_FATAL); 59 | ASSERT_EQ(RCUTILS_RET_OK, ret_set_severity); 60 | ret = rcutils_logging_logger_is_enabled_for( 61 | "rmw_fastrtps_cpp", RCUTILS_LOG_SEVERITY_FATAL); 62 | ASSERT_TRUE(ret); 63 | } 64 | 65 | TEST(test_logging_logger_is_enabled_for, test_logger_is_enabled_for) { 66 | EXPECT_FALSE( 67 | rcutils_logging_logger_is_enabled_for("rcutils_test_loggers", RCUTILS_LOG_SEVERITY_DEBUG)); 68 | EXPECT_TRUE( 69 | rcutils_logging_logger_is_enabled_for("rcutils_test_loggers", RCUTILS_LOG_SEVERITY_FATAL)); 70 | 71 | ASSERT_EQ(RCUTILS_RET_OK, rcutils_logging_initialize()); 72 | OSRF_TESTING_TOOLS_CPP_SCOPE_EXIT( 73 | { 74 | EXPECT_EQ(RCUTILS_RET_OK, rcutils_logging_shutdown()); 75 | }); 76 | 77 | EXPECT_TRUE( 78 | rcutils_logging_logger_is_enabled_for("rcutils_test_loggers", RCUTILS_LOG_SEVERITY_INFO)); 79 | 80 | ASSERT_EQ( 81 | RCUTILS_RET_OK, 82 | rcutils_logging_set_logger_level( 83 | "rcutils_test_loggers", RCUTILS_LOG_SEVERITY_WARN)); 84 | 85 | EXPECT_FALSE( 86 | rcutils_logging_logger_is_enabled_for("rcutils_test_loggers", RCUTILS_LOG_SEVERITY_INFO)); 87 | 88 | EXPECT_FALSE(rcutils_logging_logger_is_enabled_for("rcutils_test_loggers", -1)); 89 | EXPECT_TRUE(rcutils_logging_logger_is_enabled_for("rcutils_test_loggers", 1000)); 90 | 91 | // These should all resort to default logging severity 92 | EXPECT_FALSE(rcutils_logging_logger_is_enabled_for("", RCUTILS_LOG_SEVERITY_DEBUG)); 93 | EXPECT_TRUE(rcutils_logging_logger_is_enabled_for("", RCUTILS_LOG_SEVERITY_FATAL)); 94 | 95 | EXPECT_FALSE(rcutils_logging_logger_is_enabled_for(NULL, RCUTILS_LOG_SEVERITY_DEBUG)); 96 | EXPECT_TRUE(rcutils_logging_logger_is_enabled_for(NULL, RCUTILS_LOG_SEVERITY_FATAL)); 97 | 98 | EXPECT_TRUE( 99 | rcutils_logging_logger_is_enabled_for("name_that_doesn't_exist", RCUTILS_LOG_SEVERITY_FATAL)); 100 | EXPECT_FALSE( 101 | rcutils_logging_logger_is_enabled_for("name_that_doesn't_exist", RCUTILS_LOG_SEVERITY_DEBUG)); 102 | 103 | EXPECT_TRUE( 104 | rcutils_logging_logger_is_enabled_for("name.that.doesn't.exist", RCUTILS_LOG_SEVERITY_FATAL)); 105 | EXPECT_FALSE( 106 | rcutils_logging_logger_is_enabled_for("name.that.doesn't.exist", RCUTILS_LOG_SEVERITY_DEBUG)); 107 | } 108 | -------------------------------------------------------------------------------- /test/test_logging_long_messages.cpp: -------------------------------------------------------------------------------- 1 | // Copyright 2017 Open Source Robotics Foundation, Inc. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #include 16 | 17 | #include "rcutils/error_handling.h" 18 | #include "rcutils/logging.h" 19 | #include "rcutils/types/rcutils_ret.h" 20 | 21 | int main(int, char **) 22 | { 23 | rcutils_ret_t ret = rcutils_logging_initialize(); 24 | if (ret != RCUTILS_RET_OK) { 25 | fprintf(stderr, "error initializing logging: %s\n", rcutils_get_error_string().str); 26 | return -1; 27 | } 28 | 29 | // check all attributes for a debug log message 30 | rcutils_log_location_t location = {"func", "file", 42u}; 31 | char message[2048]; 32 | message[0] = 'X'; 33 | for (size_t i = 1; i < sizeof(message) - 2; ++i) { 34 | message[i] = 'x'; 35 | } 36 | message[sizeof(message) - 2] = 'X'; 37 | message[sizeof(message) - 1] = '\0'; 38 | rcutils_log(&location, RCUTILS_LOG_SEVERITY_INFO, "name1", "%s", message); 39 | 40 | message[1] = '%'; 41 | message[2] = 'd'; 42 | rcutils_log(&location, RCUTILS_LOG_SEVERITY_INFO, "name2", message, 42); 43 | 44 | std::cout.flush(); 45 | 46 | return 0; 47 | } 48 | -------------------------------------------------------------------------------- /test/test_logging_long_messages.py: -------------------------------------------------------------------------------- 1 | # Copyright 2017 Open Source Robotics Foundation, Inc. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | import os 16 | import unittest 17 | 18 | from launch import LaunchDescription 19 | from launch.actions import ExecuteProcess 20 | from launch.actions import SetEnvironmentVariable 21 | 22 | import launch_testing 23 | import launch_testing.actions 24 | import launch_testing.asserts 25 | import launch_testing.markers 26 | 27 | 28 | @launch_testing.markers.keep_alive 29 | def generate_test_description(): 30 | launch_description = LaunchDescription() 31 | # Set the output format to a "verbose" format that is expected by the executable output 32 | launch_description.add_action( 33 | SetEnvironmentVariable( 34 | name='RCUTILS_CONSOLE_OUTPUT_FORMAT', 35 | value='[{severity}] [{name}]: {message} ' 36 | '({function_name}() at {file_name}:{line_number})' 37 | ) 38 | ) 39 | executable = os.path.join(os.getcwd(), 'test_logging_long_messages') 40 | if os.name == 'nt': 41 | executable += '.exe' 42 | process_name = 'test_logging_long_messages' 43 | launch_description.add_action( 44 | ExecuteProcess(cmd=[executable], name=process_name, output='screen') 45 | ) 46 | 47 | launch_description.add_action( 48 | launch_testing.actions.ReadyToTest() 49 | ) 50 | return launch_description, {'process_name': process_name} 51 | 52 | 53 | class TestLoggingLongMessages(unittest.TestCase): 54 | 55 | def test_logging_output(self, proc_output, process_name): 56 | """Test executable output against expectation.""" 57 | proc_output.assertWaitFor( 58 | expected_output=launch_testing.tools.expected_output_from_file( 59 | path=os.path.join(os.path.dirname(__file__), process_name) 60 | ), process=process_name, timeout=10 61 | ) 62 | -------------------------------------------------------------------------------- /test/test_logging_long_messages.txt: -------------------------------------------------------------------------------- 1 | [INFO] [name1]: XxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxX (func() at file:42) 2 | [INFO] [name2]: X42xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxX (func() at file:42) 3 | -------------------------------------------------------------------------------- /test/test_logging_macros.c: -------------------------------------------------------------------------------- 1 | // Copyright 2017 Open Source Robotics Foundation, Inc. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #include 16 | 17 | #include "rcutils/allocator.h" 18 | #include "rcutils/logging_macros.h" 19 | #include "rcutils/time.h" 20 | #include "rcutils/types/rcutils_ret.h" 21 | 22 | size_t g_log_calls = 0; 23 | 24 | struct LogEvent 25 | { 26 | const rcutils_log_location_t * location; 27 | int severity; 28 | const char * name; 29 | rcutils_time_point_value_t timestamp; 30 | char * message; 31 | }; 32 | struct LogEvent g_last_log_event; 33 | 34 | void custom_handler( 35 | const rcutils_log_location_t * location, 36 | int severity, const char * name, rcutils_time_point_value_t timestamp, 37 | const char * format, va_list * args) 38 | { 39 | rcutils_allocator_t allocator = rcutils_get_default_allocator(); 40 | g_log_calls += 1; 41 | g_last_log_event.location = location; 42 | g_last_log_event.severity = severity; 43 | g_last_log_event.name = name ? name : ""; 44 | g_last_log_event.timestamp = timestamp; 45 | if (g_last_log_event.message) { 46 | allocator.deallocate(g_last_log_event.message, allocator.state); 47 | } 48 | const size_t size = 1024; 49 | g_last_log_event.message = allocator.allocate(size, allocator.state); 50 | vsnprintf(g_last_log_event.message, size, format, *args); 51 | } 52 | 53 | int main(int argc, char ** argv) 54 | { 55 | (void)argc; 56 | (void)argv; 57 | 58 | g_log_calls = 0; 59 | if (g_rcutils_logging_initialized) { 60 | return 1; 61 | } 62 | rcutils_ret_t ret = rcutils_logging_initialize(); 63 | if (ret != RCUTILS_RET_OK || !g_rcutils_logging_initialized) { 64 | return 2; 65 | } 66 | 67 | rcutils_logging_output_handler_t previous_output_handler = \ 68 | rcutils_logging_get_output_handler(); 69 | rcutils_logging_set_output_handler(custom_handler); 70 | 71 | size_t line_number = __LINE__; RCUTILS_LOG_INFO("empty message"); 72 | if (g_log_calls != 1u) { 73 | fprintf(stderr, "unexpected number of log calls\n"); 74 | return 3; 75 | } 76 | if (NULL == g_last_log_event.location) { 77 | fprintf(stderr, "location unexpectedly nullptr\n"); 78 | return 4; 79 | } 80 | if (strcmp(g_last_log_event.location->function_name, "main")) { 81 | fprintf(stderr, "function unexpectedly not 'main'\n"); 82 | return 5; 83 | } 84 | if (g_last_log_event.location->line_number != line_number) { 85 | fprintf(stderr, "unexpected line number %zu\n", g_last_log_event.location->line_number); 86 | return 6; 87 | } 88 | if (g_last_log_event.severity != RCUTILS_LOG_SEVERITY_INFO) { 89 | fprintf(stderr, "severity unexpectedly not RCUTILS_LOG_SEVERITY_INFO\n"); 90 | return 7; 91 | } 92 | if (strcmp(g_last_log_event.name, "")) { 93 | fprintf(stderr, "name unexpectedly not empty string\n"); 94 | return 8; 95 | } 96 | if (strcmp(g_last_log_event.message, "empty message")) { 97 | fprintf(stderr, "message unexpectedly not 'empty message'\n"); 98 | return 9; 99 | } 100 | 101 | line_number = __LINE__; RCUTILS_LOG_INFO("message %s", "foo"); 102 | if (g_log_calls != 2u) { 103 | fprintf(stderr, "unexpected number of log calls\n"); 104 | return 10; 105 | } 106 | if (NULL == g_last_log_event.location) { 107 | fprintf(stderr, "location unexpectedly nullptr\n"); 108 | return 11; 109 | } 110 | if (strcmp(g_last_log_event.location->function_name, "main")) { 111 | fprintf(stderr, "function unexpectedly not 'main'\n"); 112 | return 12; 113 | } 114 | if (g_last_log_event.location->line_number != line_number) { 115 | fprintf(stderr, "unexpected line number %zu\n", g_last_log_event.location->line_number); 116 | return 13; 117 | } 118 | if (g_last_log_event.severity != RCUTILS_LOG_SEVERITY_INFO) { 119 | fprintf(stderr, "severity unexpectedly not RCUTILS_LOG_SEVERITY_INFO\n"); 120 | return 14; 121 | } 122 | if (strcmp(g_last_log_event.name, "")) { 123 | fprintf(stderr, "name unexpectedly not empty string\n"); 124 | return 15; 125 | } 126 | if (strcmp(g_last_log_event.message, "message foo")) { 127 | fprintf(stderr, "message unexpectedly not 'message foo'\n"); 128 | return 16; 129 | } 130 | 131 | rcutils_logging_set_output_handler(previous_output_handler); 132 | if (g_last_log_event.message) { 133 | rcutils_allocator_t allocator = rcutils_get_default_allocator(); 134 | allocator.deallocate(g_last_log_event.message, allocator.state); 135 | } 136 | 137 | ret = rcutils_logging_shutdown(); 138 | if (ret != RCUTILS_RET_OK || g_rcutils_logging_initialized) { 139 | fprintf(stderr, "rcutils_logging_shutdown() unexpectedly failed\n"); 140 | return 17; 141 | } 142 | } 143 | -------------------------------------------------------------------------------- /test/test_logging_output_format_complicated_escape.regex: -------------------------------------------------------------------------------- 1 | name1 0\a1\b23\n44\r5\t67 Xx{2045}X 2 | name2 0\a1\b23\n44\r5\t67 X42x{2043}X 3 | -------------------------------------------------------------------------------- /test/test_logging_output_format_edge_cases.txt: -------------------------------------------------------------------------------- 1 | {}}].({unknown_token}) {{{{ 2 | {}}].({unknown_token}) {{{{ 3 | -------------------------------------------------------------------------------- /test/test_logging_output_format_escape_sequence.regex: -------------------------------------------------------------------------------- 1 | name1 \x1b\[0m Xx{2045}X 2 | name2 \x1b\[0m X42x{2043}X 3 | -------------------------------------------------------------------------------- /test/test_logging_output_format_no_tokens.txt: -------------------------------------------------------------------------------- 1 | no_tokens 2 | no_tokens 3 | -------------------------------------------------------------------------------- /test/test_logging_output_format_simple_escape.regex: -------------------------------------------------------------------------------- 1 | \tname1\n\tXx{2045}X\n 2 | \tname2\n\tX42x{2043}X\n 3 | -------------------------------------------------------------------------------- /test/test_logging_output_timestamps.regex: -------------------------------------------------------------------------------- 1 | '[-]?[0-9]{10}[.][0-9]{9}' '[-]?[0-9]{19}'\n'[-]?[0-9]{10}[.][0-9]{9}' '[-]?[0-9]{19}' -------------------------------------------------------------------------------- /test/test_macros.cpp: -------------------------------------------------------------------------------- 1 | // Copyright 2020 Open Source Robotics Foundation, Inc. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #include 16 | 17 | #include "rcutils/macros.h" 18 | 19 | TEST(TestMacros, stringify) { 20 | #define NUMBER 23 21 | EXPECT_STREQ(RCUTILS_STRINGIFY(foo), "foo"); 22 | EXPECT_STREQ(RCUTILS_STRINGIFY(42), "42"); 23 | EXPECT_STREQ(RCUTILS_STRINGIFY(NUMBER), "23"); 24 | #undef NUMBER 25 | } 26 | 27 | TEST(TestMacros, join) { 28 | EXPECT_STREQ(RCUTILS_STRINGIFY(RCUTILS_JOIN(foo, bar)), "foobar"); 29 | EXPECT_STREQ(RCUTILS_STRINGIFY(RCUTILS_JOIN(RCUTILS_JOIN(fizz, buzz), 42)), "fizzbuzz42"); 30 | } 31 | -------------------------------------------------------------------------------- /test/test_process.cpp: -------------------------------------------------------------------------------- 1 | // Copyright 2020 Open Source Robotics Foundation, Inc. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #include 16 | 17 | #include "./allocator_testing_utils.h" 18 | #include "./time_bomb_allocator_testing_utils.h" 19 | #include "rcutils/allocator.h" 20 | #include "rcutils/error_handling.h" 21 | #include "rcutils/process.h" 22 | 23 | static const char * const g_cmake_command = RCUTILS_STRINGIFY(CMAKE_COMMAND); 24 | 25 | TEST(TestProcess, test_get_pid) { 26 | EXPECT_NE(rcutils_get_pid(), 0); 27 | } 28 | 29 | TEST(TestProcess, test_get_executable_name) { 30 | rcutils_allocator_t allocator = rcutils_get_default_allocator(); 31 | rcutils_allocator_t time_bomb_allocator = get_time_bomb_allocator(); 32 | 33 | // Allocating executable_name fails 34 | set_time_bomb_allocator_malloc_count(time_bomb_allocator, 0); 35 | EXPECT_STREQ(NULL, rcutils_get_executable_name(time_bomb_allocator)); 36 | 37 | // Allocating intermediate fails. This allocation doesn't happen on windows 38 | #if defined __APPLE__ || defined __FreeBSD__ || (defined __GNUC__ && !defined(__MINGW64__)) 39 | set_time_bomb_allocator_malloc_count(time_bomb_allocator, 1); 40 | EXPECT_STREQ(NULL, rcutils_get_executable_name(time_bomb_allocator)); 41 | #endif 42 | 43 | char * exec_name = rcutils_get_executable_name(allocator); 44 | EXPECT_STREQ("test_process", exec_name); 45 | allocator.deallocate(exec_name, allocator.state); 46 | } 47 | 48 | TEST(TestProcess, test_process_creation) { 49 | rcutils_allocator_t allocator = rcutils_get_default_allocator(); 50 | rcutils_allocator_t bad_allocator = rcutils_get_zero_initialized_allocator(); 51 | rcutils_allocator_t time_bomb_allocator = get_time_bomb_allocator(); 52 | rcutils_string_array_t args = rcutils_get_zero_initialized_string_array(); 53 | rcutils_process_t * process = NULL; 54 | rcutils_ret_t ret = RCUTILS_RET_OK; 55 | int exit_code = 42; 56 | 57 | ret = rcutils_string_array_init(&args, 4, &allocator); 58 | ASSERT_EQ(RCUTILS_RET_OK, ret); 59 | args.data[0] = strdup(g_cmake_command); 60 | args.data[1] = strdup("-E"); 61 | args.data[2] = strdup("echo"); 62 | args.data[3] = strdup(""); 63 | 64 | EXPECT_EQ(nullptr, rcutils_start_process(NULL, &allocator)); 65 | rcutils_reset_error(); 66 | 67 | EXPECT_EQ(nullptr, rcutils_start_process(&args, NULL)); 68 | rcutils_reset_error(); 69 | 70 | EXPECT_EQ(nullptr, rcutils_start_process(&args, &bad_allocator)); 71 | rcutils_reset_error(); 72 | 73 | set_time_bomb_allocator_calloc_count(time_bomb_allocator, 0); 74 | set_time_bomb_allocator_malloc_count(time_bomb_allocator, 0); 75 | EXPECT_EQ(nullptr, rcutils_start_process(&args, &time_bomb_allocator)); 76 | 77 | process = rcutils_start_process(&args, &allocator); 78 | EXPECT_NE(nullptr, process); 79 | 80 | ret = rcutils_process_wait(process, &exit_code); 81 | EXPECT_EQ(RCUTILS_RET_OK, ret); 82 | EXPECT_EQ(0, exit_code); 83 | 84 | rcutils_process_close(process); 85 | 86 | ret = rcutils_string_array_fini(&args); 87 | 88 | // cmake -E cat "file with space.txt" (returns 0) 89 | ret = rcutils_string_array_resize(&args, 4); 90 | ASSERT_EQ(RCUTILS_RET_OK, ret); 91 | args.data[0] = strdup(g_cmake_command); 92 | args.data[1] = strdup("-E"); 93 | args.data[2] = strdup("cat"); 94 | args.data[3] = strdup("file with space.txt"); 95 | 96 | process = rcutils_start_process(&args, &allocator); 97 | EXPECT_NE(nullptr, process); 98 | 99 | ret = rcutils_process_wait(process, &exit_code); 100 | EXPECT_EQ(RCUTILS_RET_OK, ret); 101 | EXPECT_EQ(0, exit_code); 102 | 103 | rcutils_process_close(process); 104 | 105 | ret = rcutils_string_array_fini(&args); 106 | 107 | // cmake -E false (returns 1) 108 | ret = rcutils_string_array_resize(&args, 3); 109 | ASSERT_EQ(RCUTILS_RET_OK, ret); 110 | args.data[0] = strdup(g_cmake_command); 111 | args.data[1] = strdup("-E"); 112 | allocator.deallocate(args.data[2], &allocator.state); 113 | args.data[2] = strdup("false"); 114 | 115 | process = rcutils_start_process(&args, &allocator); 116 | EXPECT_NE(nullptr, process); 117 | 118 | ret = rcutils_process_wait(process, &exit_code); 119 | EXPECT_EQ(RCUTILS_RET_OK, ret); 120 | EXPECT_EQ(1, exit_code); 121 | 122 | rcutils_process_close(process); 123 | 124 | ret = rcutils_string_array_fini(&args); 125 | ASSERT_EQ(RCUTILS_RET_OK, ret); 126 | } 127 | -------------------------------------------------------------------------------- /test/test_repl_str.cpp: -------------------------------------------------------------------------------- 1 | // Copyright 2017 Open Source Robotics Foundation, Inc. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #include 16 | 17 | #include 18 | 19 | #include "./allocator_testing_utils.h" 20 | #include "rcutils/allocator.h" 21 | #include "rcutils/repl_str.h" 22 | 23 | TEST(test_repl_str, nominal) { 24 | auto allocator = rcutils_get_default_allocator(); 25 | 26 | // replace with a string of the exact length 27 | { 28 | std::string typical = "foo/{bar}/baz"; 29 | char * out = rcutils_repl_str(typical.c_str(), "{bar}", "bbarr", &allocator); 30 | EXPECT_STREQ("foo/bbarr/baz", out); 31 | allocator.deallocate(out, allocator.state); 32 | } 33 | 34 | // replace with a string of a smaller length 35 | { 36 | std::string typical = "foo/{bar}/baz"; 37 | char * out = rcutils_repl_str(typical.c_str(), "{bar}", "bar", &allocator); 38 | EXPECT_STREQ("foo/bar/baz", out); 39 | allocator.deallocate(out, allocator.state); 40 | } 41 | 42 | // replace with a string of a longer length 43 | { 44 | std::string typical = "foo/{bar}/baz"; 45 | char * out = rcutils_repl_str(typical.c_str(), "{bar}", "barbar", &allocator); 46 | EXPECT_STREQ("foo/barbar/baz", out); 47 | allocator.deallocate(out, allocator.state); 48 | } 49 | 50 | // replace with an empty string 51 | { 52 | std::string typical = "foo/{bar}/baz"; 53 | char * out = rcutils_repl_str(typical.c_str(), "{bar}", "", &allocator); 54 | EXPECT_STREQ("foo//baz", out); 55 | allocator.deallocate(out, allocator.state); 56 | } 57 | 58 | // bad allocator 59 | { 60 | std::string typical = "foo/{bar}/baz"; 61 | rcutils_allocator_t failing_allocator = get_failing_allocator(); 62 | char * out = rcutils_repl_str(typical.c_str(), "{bar}", "", &failing_allocator); 63 | EXPECT_EQ(NULL, out); 64 | } 65 | 66 | // no matches 67 | { 68 | std::string typical = "foo/{bar}/baz"; 69 | char * out = rcutils_repl_str(typical.c_str(), "no match", "n/a", &allocator); 70 | EXPECT_STREQ(typical.c_str(), out); 71 | allocator.deallocate(out, allocator.state); 72 | } 73 | 74 | // no matches and bad allocator 75 | { 76 | std::string typical = "foo/{bar}/baz"; 77 | rcutils_allocator_t failing_allocator = get_failing_allocator(); 78 | char * out = rcutils_repl_str(typical.c_str(), "no match", "n/a", &failing_allocator); 79 | EXPECT_EQ(NULL, out); 80 | } 81 | 82 | // Force cache_sz_inc to exceed cache_sz_inc_max 83 | { 84 | std::stringstream ss; 85 | for (size_t i = 0; i < 1048576; ++i) { 86 | ss << "f"; 87 | } 88 | char * out = rcutils_repl_str(ss.str().c_str(), "f", "longer replacement", &allocator); 89 | EXPECT_NE(nullptr, out); 90 | allocator.deallocate(out, allocator.state); 91 | } 92 | } 93 | -------------------------------------------------------------------------------- /test/test_sha256.cpp: -------------------------------------------------------------------------------- 1 | // Copyright 2023 Open Source Robotics Foundation, Inc. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #include 16 | 17 | #include "rcutils/sha256.h" 18 | 19 | TEST(TestSHA256, test_text1) { 20 | uint8_t text1[] = {"abc"}; 21 | size_t text1_len = sizeof(text1) - 1; 22 | uint8_t expected_hash1[RCUTILS_SHA256_BLOCK_SIZE] = { 23 | 0xba, 0x78, 0x16, 0xbf, 0x8f, 0x01, 0xcf, 0xea, 24 | 0x41, 0x41, 0x40, 0xde, 0x5d, 0xae, 0x22, 0x23, 25 | 0xb0, 0x03, 0x61, 0xa3, 0x96, 0x17, 0x7a, 0x9c, 26 | 0xb4, 0x10, 0xff, 0x61, 0xf2, 0x00, 0x15, 0xad}; 27 | uint8_t buf[RCUTILS_SHA256_BLOCK_SIZE]; 28 | 29 | 30 | rcutils_sha256_ctx_t ctx; 31 | rcutils_sha256_init(&ctx); 32 | rcutils_sha256_update(&ctx, text1, text1_len); 33 | rcutils_sha256_final(&ctx, buf); 34 | 35 | ASSERT_EQ(0, memcmp(expected_hash1, buf, RCUTILS_SHA256_BLOCK_SIZE)); 36 | } 37 | 38 | TEST(TestSHA256, test_text2) { 39 | uint8_t text2[] = {"abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"}; 40 | size_t text2_len = sizeof(text2) - 1; 41 | uint8_t expected_hash2[RCUTILS_SHA256_BLOCK_SIZE] = { 42 | 0x24, 0x8d, 0x6a, 0x61, 0xd2, 0x06, 0x38, 0xb8, 43 | 0xe5, 0xc0, 0x26, 0x93, 0x0c, 0x3e, 0x60, 0x39, 44 | 0xa3, 0x3c, 0xe4, 0x59, 0x64, 0xff, 0x21, 0x67, 45 | 0xf6, 0xec, 0xed, 0xd4, 0x19, 0xdb, 0x06, 0xc1}; 46 | uint8_t buf[RCUTILS_SHA256_BLOCK_SIZE]; 47 | 48 | rcutils_sha256_ctx_t ctx; 49 | rcutils_sha256_init(&ctx); 50 | rcutils_sha256_update(&ctx, text2, text2_len); 51 | rcutils_sha256_final(&ctx, buf); 52 | 53 | ASSERT_EQ(0, memcmp(expected_hash2, buf, RCUTILS_SHA256_BLOCK_SIZE)); 54 | } 55 | 56 | TEST(TestSHA256, test_multi_update) { 57 | uint8_t text[] = {"aaaaaaaaaa"}; 58 | size_t text_len = sizeof(text) - 1; 59 | 60 | uint8_t expected_hash[RCUTILS_SHA256_BLOCK_SIZE] = { 61 | 0x28, 0x16, 0x59, 0x78, 0x88, 0xe4, 0xa0, 0xd3, 62 | 0xa3, 0x6b, 0x82, 0xb8, 0x33, 0x16, 0xab, 0x32, 63 | 0x68, 0x0e, 0xb8, 0xf0, 0x0f, 0x8c, 0xd3, 0xb9, 64 | 0x04, 0xd6, 0x81, 0x24, 0x6d, 0x28, 0x5a, 0x0e}; 65 | uint8_t buf[RCUTILS_SHA256_BLOCK_SIZE]; 66 | 67 | rcutils_sha256_ctx_t ctx; 68 | rcutils_sha256_init(&ctx); 69 | for (int i = 0; i < 10; i++) { 70 | rcutils_sha256_update(&ctx, text, text_len); 71 | } 72 | rcutils_sha256_final(&ctx, buf); 73 | 74 | ASSERT_EQ(0, memcmp(expected_hash, buf, RCUTILS_SHA256_BLOCK_SIZE)); 75 | } 76 | -------------------------------------------------------------------------------- /test/test_snprintf.cpp: -------------------------------------------------------------------------------- 1 | // Copyright 2018 Open Source Robotics Foundation, Inc. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #include 16 | 17 | #include "rcutils/snprintf.h" 18 | 19 | // Tests the rcutils_snprintf() function. 20 | TEST(TestSnprintf, test_snprintf) { 21 | const char * test_str = "0123456789"; 22 | char buffer[256]; 23 | int ret; 24 | 25 | ret = rcutils_snprintf(buffer, sizeof(buffer), "%s", test_str); 26 | EXPECT_EQ(static_cast(strlen(test_str)), ret); 27 | EXPECT_STREQ(test_str, buffer); 28 | 29 | ret = rcutils_snprintf(nullptr, 0, "%s", test_str); 30 | EXPECT_EQ(static_cast(strlen(test_str)), ret); 31 | 32 | ret = rcutils_snprintf(buffer, 4, "%s", test_str); // NOLINT(runtime/printf) 33 | EXPECT_EQ(static_cast(strlen(test_str)), ret); 34 | EXPECT_STREQ("012", buffer); 35 | 36 | ret = rcutils_snprintf(nullptr, sizeof(buffer), "%s", test_str); 37 | EXPECT_EQ(-1, ret); 38 | 39 | ret = rcutils_snprintf(buffer, 0, "%s", test_str); 40 | EXPECT_EQ(-1, ret); 41 | 42 | ret = rcutils_snprintf(buffer, 1, "%s", test_str); // NOLINT(runtime/printf) 43 | EXPECT_EQ(static_cast(strlen(test_str)), ret); 44 | EXPECT_STREQ("", buffer); 45 | 46 | ret = rcutils_snprintf(buffer, 2, "%s", test_str); // NOLINT(runtime/printf) 47 | EXPECT_EQ(static_cast(strlen(test_str)), ret); 48 | EXPECT_STREQ("0", buffer); 49 | 50 | ret = rcutils_snprintf(buffer, strlen(test_str), "%s", test_str); 51 | EXPECT_EQ(static_cast(strlen(test_str)), ret); 52 | EXPECT_STREQ("012345678", buffer); 53 | 54 | ret = rcutils_snprintf(buffer, strlen(test_str) + 1, "%s", test_str); 55 | EXPECT_EQ(static_cast(strlen(test_str)), ret); 56 | EXPECT_STREQ(test_str, buffer); 57 | 58 | EXPECT_EQ(-1, rcutils_snprintf(buffer, 2, NULL)); // NOLINT(runtime/printf) 59 | } 60 | -------------------------------------------------------------------------------- /test/test_strdup.cpp: -------------------------------------------------------------------------------- 1 | // Copyright 2017 Open Source Robotics Foundation, Inc. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #include 16 | 17 | #include 18 | #include 19 | 20 | #include "./allocator_testing_utils.h" 21 | #include "rcutils/allocator.h" 22 | #include "rcutils/strdup.h" 23 | 24 | TEST(test_strdup, nominal) { 25 | { 26 | std::string typical = "typical"; 27 | auto allocator = rcutils_get_default_allocator(); 28 | char * duped = rcutils_strdup(typical.c_str(), allocator); 29 | EXPECT_STREQ(typical.c_str(), duped); 30 | allocator.deallocate(duped, allocator.state); 31 | } 32 | 33 | { 34 | std::string empty = ""; 35 | auto allocator = rcutils_get_default_allocator(); 36 | char * duped = rcutils_strdup(empty.c_str(), allocator); 37 | EXPECT_STREQ(empty.c_str(), duped); 38 | allocator.deallocate(duped, allocator.state); 39 | } 40 | } 41 | 42 | TEST(test_strndup, nominal) { 43 | { 44 | std::string typical = "typical"; 45 | auto allocator = rcutils_get_default_allocator(); 46 | char * duped = rcutils_strndup(typical.c_str(), 3, allocator); 47 | EXPECT_STREQ(typical.substr(0, 3).c_str(), duped); 48 | allocator.deallocate(duped, allocator.state); 49 | } 50 | 51 | { 52 | std::string typical = "typical"; 53 | auto allocator = rcutils_get_default_allocator(); 54 | char * duped = rcutils_strndup(typical.c_str(), 0, allocator); 55 | size_t expected = 0; 56 | EXPECT_EQ(expected, strlen(duped)); 57 | EXPECT_STREQ("", duped); 58 | allocator.deallocate(duped, allocator.state); 59 | } 60 | 61 | { 62 | std::string empty = ""; 63 | auto allocator = rcutils_get_default_allocator(); 64 | char * duped = rcutils_strdup(empty.c_str(), allocator); 65 | EXPECT_STREQ(empty.c_str(), duped); 66 | allocator.deallocate(duped, allocator.state); 67 | } 68 | } 69 | 70 | TEST(test_strdup, invalid_arguments) { 71 | auto allocator = rcutils_get_default_allocator(); 72 | auto failing_allocator = get_failing_allocator(); 73 | EXPECT_EQ(NULL, rcutils_strdup(NULL, allocator)); 74 | EXPECT_EQ(NULL, rcutils_strndup(NULL, 5, allocator)); 75 | EXPECT_EQ(NULL, rcutils_strdup("something", failing_allocator)); 76 | } 77 | 78 | TEST(test_strndup, one_byte_overread) { 79 | auto allocator = rcutils_get_default_allocator(); 80 | char str[4]; 81 | char * p; 82 | memcpy(str, "test", sizeof(str)); 83 | 84 | // If there is a bug, a one byte overread happens here. Run this test under a 85 | // memory sanitizer to guarantee it causes a crash. 86 | p = rcutils_strndup(str, sizeof(str), allocator); 87 | if (NULL == p) { 88 | FAIL(); 89 | } 90 | ASSERT_STREQ(p, "test"); 91 | allocator.deallocate(p, allocator.state); 92 | } 93 | 94 | TEST(test_strndup, arbitrary_overread) { 95 | auto allocator = rcutils_get_default_allocator(); 96 | char str[1]; 97 | char * p; 98 | memcpy(str, "", sizeof(str)); 99 | 100 | // A buggy strndup() doesn't stop copying str at the null byte, instead it 101 | // copies SIZE_MAX bytes. 102 | // If there is a bug, this segfaults on anything with a MMU. 103 | p = rcutils_strndup(str, SIZE_MAX, allocator); 104 | if (NULL == p) { 105 | FAIL(); 106 | } 107 | ASSERT_STREQ(p, str); 108 | allocator.deallocate(p, allocator.state); 109 | } 110 | -------------------------------------------------------------------------------- /test/test_strerror.cpp: -------------------------------------------------------------------------------- 1 | // Copyright 2020 Open Source Robotics Foundation, Inc. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #include 16 | 17 | #include 18 | #ifdef _WIN32 19 | #include 20 | #else 21 | #include 22 | #endif 23 | 24 | #include "rcutils/macros.h" 25 | #include "rcutils/strerror.h" 26 | 27 | #include "mimick/mimick.h" 28 | 29 | TEST(test_strerror, get_error) { 30 | // cleaning possible errors 31 | errno = 0; 32 | 33 | char error_string[1024]; 34 | rcutils_strerror(error_string, sizeof(error_string)); 35 | #ifdef _WIN32 36 | ASSERT_STREQ(error_string, "No error"); 37 | #elif __APPLE__ 38 | ASSERT_STREQ(error_string, "Undefined error: 0"); 39 | #else 40 | ASSERT_STREQ(error_string, "Success"); 41 | #endif 42 | // Set the error "No such file or directory" 43 | errno = 2; 44 | 45 | rcutils_strerror(error_string, sizeof(error_string)); 46 | ASSERT_STREQ(error_string, "No such file or directory"); 47 | 48 | #if (!defined(_WIN32)) && (!( \ 49 | defined(_GNU_SOURCE) && (!defined(ANDROID) || __ANDROID_API__ >= 23))) 50 | // Hopefully this does not become a valid errno. 51 | errno = 12345; 52 | rcutils_strerror(error_string, sizeof(error_string)); 53 | ASSERT_STREQ(error_string, "Failed to get error") << 54 | "Calling rcutils_strerror with an errno of '" << errno << 55 | "' did not cause the expected error message."; 56 | #endif 57 | } 58 | 59 | /* 60 | Define the blueprint of a mock identified by `strerror_r_proto` 61 | strerror_r possible signatures: 62 | 63 | * int strerror_r(int errnum, char *buf, size_t buflen); (Case 1) 64 | * char *strerror_r(int errnum, char *buf, size_t buflen); (Case 2) 65 | * errno_t strerror_s( char *buf, rsize_t bufsz, errno_t errnum ); (Case 3) 66 | */ 67 | 68 | #if defined(_WIN32) 69 | const char expected_error_msg[] = "Failed to get error"; 70 | mmk_mock_define(strerror_s_mock, errno_t, char *, rsize_t, errno_t); 71 | 72 | errno_t mocked_windows_strerror(char * buf, rsize_t bufsz, errno_t errnum) 73 | { 74 | (void) errnum; 75 | strncpy_s(buf, static_cast(bufsz), expected_error_msg, static_cast(bufsz)); 76 | return errnum; 77 | } 78 | 79 | // Mocking test example 80 | TEST(test_strerror, test_mock) { 81 | // Mock the strerror_s function in the current module using 82 | // the `strerror_s_mock` blueprint. 83 | strerror_s_mock mock = mmk_mock(RCUTILS_STRINGIFY(strerror_s) "@lib:rcutils", strerror_s_mock); 84 | // Tell the mock to call mocked_windows_strerror instead 85 | mmk_when( 86 | strerror_s(mmk_any(char *), mmk_any(rsize_t), mmk_any(errno_t)), 87 | .then_call = (mmk_fn) mocked_windows_strerror); 88 | 89 | // Set the error (not used by the mock) 90 | errno = 2; 91 | char error_string[1024]; 92 | rcutils_strerror(error_string, sizeof(error_string)); 93 | ASSERT_STREQ(error_string, "Failed to get error"); 94 | mmk_reset(mock); 95 | } 96 | 97 | #elif defined(_GNU_SOURCE) && (!defined(ANDROID) || __ANDROID_API__ >= 23) 98 | const char expected_error_msg[] = "Failed to get error"; 99 | mmk_mock_define(strerror_r_mock, char *, int, char *, size_t); 100 | 101 | char * mocked_gnu_strerror(int errnum, char * buf, size_t buflen) 102 | { 103 | (void) errnum; 104 | strncpy(buf, expected_error_msg, buflen); 105 | return buf; 106 | } 107 | 108 | // Mocking test example 109 | TEST(test_strerror, test_mock) { 110 | // Mock the strerror_r function in the current module using 111 | // the `strerror_r_mock` blueprint. 112 | mmk_mock(RCUTILS_STRINGIFY(strerror_r) "@lib:rcutils", strerror_r_mock); 113 | // Tell the mock to call mocked_gnu_strerror instead 114 | mmk_when( 115 | strerror_r(mmk_any(int), mmk_any(char *), mmk_any(size_t) ), 116 | .then_call = (mmk_fn) mocked_gnu_strerror); 117 | 118 | // Set the error (not used by the mock) 119 | errno = 2; 120 | char error_string[1024]; 121 | rcutils_strerror(error_string, sizeof(error_string)); 122 | ASSERT_STREQ(error_string, "Failed to get error"); 123 | mmk_reset(strerror_r); 124 | } 125 | 126 | #else 127 | mmk_mock_define(strerror_r_mock, int, int, char *, size_t); 128 | 129 | // Mocking test example 130 | TEST(test_strerror, test_mock) { 131 | // Mock the strerror_r function in the current module using 132 | // the `strerror_r_mock` blueprint. 133 | mmk_mock(RCUTILS_STRINGIFY(strerror_r) "@lib:rcutils", strerror_r_mock); 134 | // Tell the mock to return NULL and set errno to EINVAL 135 | // whatever the given parameter is. 136 | mmk_when( 137 | strerror_r(mmk_any(int), mmk_any(char *), mmk_any(size_t) ), 138 | .then_return = mmk_val(int, EINVAL)); 139 | 140 | // Set the error "No such file or directory" (not used by the mock) 141 | errno = 2; 142 | char error_string[1024]; 143 | rcutils_strerror(error_string, sizeof(error_string)); 144 | ASSERT_STREQ(error_string, "Failed to get error"); 145 | mmk_reset(strerror_r); 146 | } 147 | #endif 148 | -------------------------------------------------------------------------------- /test/test_uint8_array.cpp: -------------------------------------------------------------------------------- 1 | // Copyright 2018 Open Source Robotics Foundation, Inc. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #include 16 | 17 | #include "rcutils/allocator.h" 18 | 19 | #include "rcutils/types/uint8_array.h" 20 | 21 | TEST(test_uint8_array, default_initialization) { 22 | auto uint8_array = rcutils_get_zero_initialized_uint8_array(); 23 | 24 | auto allocator = rcutils_get_default_allocator(); 25 | EXPECT_EQ(RCUTILS_RET_OK, rcutils_uint8_array_init(&uint8_array, 0, &allocator)); 26 | EXPECT_EQ(0lu, uint8_array.buffer_capacity); 27 | EXPECT_EQ(RCUTILS_RET_OK, rcutils_uint8_array_fini(&uint8_array)); 28 | EXPECT_EQ(0lu, uint8_array.buffer_capacity); 29 | EXPECT_FALSE(uint8_array.buffer); 30 | } 31 | 32 | TEST(test_uint8_array, resize) { 33 | auto uint8_array = rcutils_get_zero_initialized_uint8_array(); 34 | auto allocator = rcutils_get_default_allocator(); 35 | auto ret = rcutils_uint8_array_init(&uint8_array, 5, &allocator); 36 | ASSERT_EQ(RCUTILS_RET_OK, ret); 37 | 38 | for (size_t i = 0; i < 5; ++i) { 39 | uint8_t c = 0xFF; 40 | memcpy(uint8_array.buffer + i, &c, 1); 41 | } 42 | uint8_array.buffer_length = 5; 43 | for (size_t i = 0; i < uint8_array.buffer_length; ++i) { 44 | EXPECT_EQ(0xFF, uint8_array.buffer[i]); 45 | } 46 | 47 | ret = rcutils_uint8_array_resize(&uint8_array, 0); 48 | ASSERT_EQ(RCUTILS_RET_INVALID_ARGUMENT, ret); 49 | EXPECT_EQ(5lu, uint8_array.buffer_capacity); 50 | EXPECT_EQ(5lu, uint8_array.buffer_length); 51 | 52 | ret = rcutils_uint8_array_resize(&uint8_array, 10); 53 | ASSERT_EQ(RCUTILS_RET_OK, ret); 54 | EXPECT_EQ(10u, uint8_array.buffer_capacity); 55 | EXPECT_EQ(5u, uint8_array.buffer_length); 56 | 57 | for (uint8_t i = 0; i < 10; ++i) { 58 | uint8_t u = static_cast(0xFF - i); 59 | memcpy(uint8_array.buffer + i, &u, 1); 60 | } 61 | uint8_array.buffer_length = 10lu; 62 | for (size_t i = 0; i < uint8_array.buffer_length; ++i) { 63 | uint8_t u = static_cast(0xFF - i); 64 | EXPECT_EQ(u, uint8_array.buffer[i]); 65 | } 66 | 67 | ret = rcutils_uint8_array_resize(&uint8_array, 3); 68 | ASSERT_EQ(RCUTILS_RET_OK, ret); 69 | EXPECT_EQ(3lu, uint8_array.buffer_capacity); 70 | EXPECT_EQ(3lu, uint8_array.buffer_length); 71 | EXPECT_EQ(0xFF, uint8_array.buffer[0]); 72 | EXPECT_EQ(0xFF - 1, uint8_array.buffer[1]); 73 | EXPECT_EQ(0xFF - 2, uint8_array.buffer[2]); 74 | // the other fields are garbage. 75 | 76 | ASSERT_EQ(RCUTILS_RET_OK, rcutils_uint8_array_resize(&uint8_array, 3)); 77 | 78 | // cleanup only 3 fields 79 | EXPECT_EQ(RCUTILS_RET_OK, rcutils_uint8_array_fini(&uint8_array)); 80 | } 81 | -------------------------------------------------------------------------------- /test/time_bomb_allocator_testing_utils.h: -------------------------------------------------------------------------------- 1 | // Copyright 2020 Open Source Robotics Foundation, Inc. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #ifndef TIME_BOMB_ALLOCATOR_TESTING_UTILS_H_ 16 | #define TIME_BOMB_ALLOCATOR_TESTING_UTILS_H_ 17 | 18 | #ifdef __cplusplus 19 | extern "C" 20 | { 21 | #endif 22 | 23 | #include 24 | 25 | #include "rcutils/allocator.h" 26 | 27 | typedef struct __time_bomb_allocator_state 28 | { 29 | // Set these to negative if you want to disable time bomb for the associated function call. 30 | int malloc_count_until_failure; 31 | int realloc_count_until_failure; 32 | int free_count_until_failure; 33 | int calloc_count_until_failure; 34 | } __time_bomb_allocator_state; 35 | 36 | static void * 37 | time_bomb_malloc(size_t size, void * state) 38 | { 39 | if (((__time_bomb_allocator_state *)state)->malloc_count_until_failure >= 0 && 40 | ((__time_bomb_allocator_state *)state)->malloc_count_until_failure-- == 0) 41 | { 42 | printf("Malloc time bomb countdown reached 0, returning nullptr\n"); 43 | return nullptr; 44 | } 45 | return rcutils_get_default_allocator().allocate(size, rcutils_get_default_allocator().state); 46 | } 47 | 48 | static void * 49 | time_bomb_realloc(void * pointer, size_t size, void * state) 50 | { 51 | if (((__time_bomb_allocator_state *)state)->realloc_count_until_failure >= 0 && 52 | ((__time_bomb_allocator_state *)state)->realloc_count_until_failure-- == 0) 53 | { 54 | printf("Realloc time bomb countdown reached 0, returning nullptr\n"); 55 | return nullptr; 56 | } 57 | return rcutils_get_default_allocator().reallocate( 58 | pointer, size, rcutils_get_default_allocator().state); 59 | } 60 | 61 | static void 62 | time_bomb_free(void * pointer, void * state) 63 | { 64 | if (((__time_bomb_allocator_state *)state)->free_count_until_failure >= 0 && 65 | ((__time_bomb_allocator_state *)state)->free_count_until_failure-- == 0) 66 | { 67 | printf("Free time bomb countdown reached 0, not freeing memory\n"); 68 | return; 69 | } 70 | rcutils_get_default_allocator().deallocate(pointer, rcutils_get_default_allocator().state); 71 | } 72 | 73 | static void * 74 | time_bomb_calloc(size_t number_of_elements, size_t size_of_element, void * state) 75 | { 76 | if (((__time_bomb_allocator_state *)state)->calloc_count_until_failure >= 0 && 77 | ((__time_bomb_allocator_state *)state)->calloc_count_until_failure-- == 0) 78 | { 79 | printf("Calloc time bomb countdown reached 0, returning nullptr\n"); 80 | return nullptr; 81 | } 82 | return rcutils_get_default_allocator().zero_allocate( 83 | number_of_elements, size_of_element, rcutils_get_default_allocator().state); 84 | } 85 | 86 | /** 87 | * This allocator uses the rcutils default allocator functions, but decrements a time bomb counter 88 | * for each function call. When the counter reaches 0, that call will fail. 89 | * In the case of the allocating functions, it will return a nullptr. In the case of free, 90 | * it will fail to free the memory. 91 | * 92 | * Use this allocator when you need a fixed amount of calls to succeed before it fails. 93 | * 94 | * Set the count to negative for the time bomb effect to be disabled for that function. 95 | */ 96 | static inline rcutils_allocator_t 97 | get_time_bomb_allocator(void) 98 | { 99 | static __time_bomb_allocator_state state; 100 | state.malloc_count_until_failure = -1; 101 | state.realloc_count_until_failure = -1; 102 | state.free_count_until_failure = -1; 103 | state.calloc_count_until_failure = -1; 104 | auto time_bomb_allocator = rcutils_get_default_allocator(); 105 | time_bomb_allocator.allocate = time_bomb_malloc; 106 | time_bomb_allocator.deallocate = time_bomb_free; 107 | time_bomb_allocator.reallocate = time_bomb_realloc; 108 | time_bomb_allocator.zero_allocate = time_bomb_calloc; 109 | time_bomb_allocator.state = &state; 110 | return time_bomb_allocator; 111 | } 112 | 113 | /** 114 | * Set count to the number of times you want the call to succeed before it fails. 115 | * After it fails once, it will succeed until this count is reset. 116 | * Set it to a negative value to disable the time bomb effect for that function. 117 | */ 118 | static inline void 119 | set_time_bomb_allocator_malloc_count(rcutils_allocator_t & time_bomb_allocator, int count) 120 | { 121 | ((__time_bomb_allocator_state *)time_bomb_allocator.state)->malloc_count_until_failure = count; 122 | } 123 | 124 | static inline void 125 | set_time_bomb_allocator_realloc_count(rcutils_allocator_t & time_bomb_allocator, int count) 126 | { 127 | ((__time_bomb_allocator_state *)time_bomb_allocator.state)->realloc_count_until_failure = count; 128 | } 129 | 130 | static inline void 131 | set_time_bomb_allocator_free_count(rcutils_allocator_t & time_bomb_allocator, int count) 132 | { 133 | ((__time_bomb_allocator_state *)time_bomb_allocator.state)->free_count_until_failure = count; 134 | } 135 | 136 | static inline void 137 | set_time_bomb_allocator_calloc_count(rcutils_allocator_t & time_bomb_allocator, int count) 138 | { 139 | ((__time_bomb_allocator_state *)time_bomb_allocator.state)->calloc_count_until_failure = count; 140 | } 141 | 142 | #ifdef __cplusplus 143 | } 144 | #endif 145 | 146 | #endif // TIME_BOMB_ALLOCATOR_TESTING_UTILS_H_ 147 | --------------------------------------------------------------------------------