diff --git a/source/environment/include/environment/environment_variable_path.h b/source/environment/include/environment/environment_variable_path.h index d5492d8f6..5f3a17ba4 100644 --- a/source/environment/include/environment/environment_variable_path.h +++ b/source/environment/include/environment/environment_variable_path.h @@ -52,7 +52,29 @@ extern "C" { /* -- Methods -- */ -ENVIRONMENT_API char *environment_variable_path_create(const char *name, const char *default_path, size_t default_path_size, size_t *env_size); +/** + * @brief + * If the value of @name exists as an environment variable, return a live string of its value, otherwise return a live value of @default_path or "/". + * @name should not be NULL. + * If @default_path is not NULL, @default_path_size must be set to <= the length (including null-terminator) of the @default_path string. + * If @env_size is not NULL, the length (including null-terminator) of the returned string will be set to it. + * + * @param[in] name + * The environment variable name to look up. + * + * @param[in] default_path + * If the environment variable value is not found, the value to return instead. + * + * @param[in] default_path_size + * The length (including null-terminator) of @default_path in chars. + * + * @param[out] env_size + * Pointer to a size_t to write the length of the returned string to (optional). + * + * @return + * The allocated string containing the environment variable value or the default or "/". + */ +ENVIRONMENT_API char *environment_variable_path_create(const char *const name, const char *const default_path, const size_t default_path_size, size_t *const env_size); ENVIRONMENT_API void environment_variable_path_destroy(char *variable_path); diff --git a/source/environment/source/environment_variable_path.c b/source/environment/source/environment_variable_path.c index 53f492dc3..813112a80 100644 --- a/source/environment/source/environment_variable_path.c +++ b/source/environment/source/environment_variable_path.c @@ -43,59 +43,53 @@ /* -- Methods -- */ -char *environment_variable_path_create(const char *name, const char *default_path, size_t default_path_size, size_t *env_size) +char *environment_variable_path_create(const char *const name, const char *const default_path, const size_t default_path_size, size_t *const env_size) { - const char *path_ptr = getenv(name); + const char *env_variable = getenv(name); char *path; - size_t length, size, last, end; + size_t size, alloc_size; - if (path_ptr == NULL) + if (env_variable) { - if (default_path == NULL) - { - static const char empty_path[] = ""; - - default_path = empty_path; - default_path_size = sizeof(empty_path); - } - - path_ptr = default_path; - length = default_path_size - 1; + size = strlen(env_variable) + 1; + } + else if (default_path) + { + env_variable = default_path; + size = default_path_size; } else { - length = strlen(path_ptr); + env_variable = ENVIRONMENT_VARIABLE_PATH_SEPARATOR_STR; + size = sizeof(ENVIRONMENT_VARIABLE_PATH_SEPARATOR_STR); } - last = length - 1; + alloc_size = size; - if (ENVIRONMENT_VARIABLE_PATH_SEPARATOR(path_ptr[last])) - { - end = length; - size = length + 1; - } - else + if (size > 1) { - last = length; - end = length + 1; - size = length + 2; + alloc_size += !ENVIRONMENT_VARIABLE_PATH_SEPARATOR(env_variable[size - 2]); } - path = malloc(sizeof(char) * size); + path = malloc(sizeof(char) * alloc_size); if (path == NULL) { return NULL; } - strncpy(path, path_ptr, length); + memcpy(path, env_variable, sizeof(char) * size); + + if (size > 1) + { + path[alloc_size - 2] = ENVIRONMENT_VARIABLE_PATH_SEPARATOR_C; + } - path[last] = ENVIRONMENT_VARIABLE_PATH_SEPARATOR_C; - path[end] = '\0'; + path[alloc_size - 1] = '\0'; - if (env_size != NULL) + if (env_size) { - *env_size = size; + *env_size = alloc_size; } return path; diff --git a/source/portability/include/portability/portability_path.h b/source/portability/include/portability/portability_path.h index 79ff0761b..38e743fbf 100644 --- a/source/portability/include/portability/portability_path.h +++ b/source/portability/include/portability/portability_path.h @@ -109,9 +109,58 @@ extern "C" { /* -- Methods -- */ -PORTABILITY_API size_t portability_path_get_name(const char *path, size_t path_size, char *name, size_t name_size); +/** + * @brief + * Get the file name portion out of a path and strip away the file extension if any. + * If @path is NULL this will return an empty string. + * If @name is NULL or @name_size is 0 this will return the size it requires in order to write @name. + * If @path or @name are not NULL, then @path_size or @name_size, respectively, must be set to <= the length (including null-terminator) of the memory regions pointed to by @path and @name. + * + * @param[in] path + * The full path to extract the name from. + * + * @param[in] path_size + * The length (including null-terminator) of @path in chars. + * + * @param[out] name + * The memory location to write the extracted name to. If NULL the size required will be returned instead of the size written. + * + * @param[in] name_size + * The size of the memory location pointed to by @name. + * + * @return + * The size of the name. + */ +PORTABILITY_API size_t portability_path_get_name(const char *const path, const size_t path_size, char *const name, const size_t name_size); -PORTABILITY_API size_t portability_path_get_name_canonical(const char *path, size_t path_size, char *name, size_t name_size); +/** + * @brief + * Get the file name portion out of a path and strip away any amount of file extensions. + * When called with `"/foo/bar.baz.qux"`: + * + * - `portability_path_get_name` will produce the string `"bar.baz"` + * - `portability_path_get_name_canonical` will produce the string `"bar"` + * + * If @path is NULL this will return an empty string. + * If @name is NULL or @name_size is 0 this will return the size it requires in order to write @name. + * If @path or @name are not NULL, then @path_size or @name_size, respectively, must be set to <= the length (including null-terminator) of the memory regions pointed to by @path and @name. + * + * @param[in] path + * The full path to extract the name from. + * + * @param[in] path_size + * The length (including null-terminator) of @path in chars. + * + * @param[out] name + * The memory location to write the extracted name to. If NULL the size required will be returned instead of the size written. + * + * @param[in] name_size + * The size of the memory location pointed to by @name. + * + * @return + * The size of the name. + */ +PORTABILITY_API size_t portability_path_get_name_canonical(const char *const path, const size_t path_size, char *const name, const size_t name_size); PORTABILITY_API size_t portability_path_get_fullname(const char *path, size_t path_size, char *name, size_t name_size); diff --git a/source/portability/source/portability_path.c b/source/portability/source/portability_path.c index 9606a7d69..207a9cf29 100644 --- a/source/portability/source/portability_path.c +++ b/source/portability/source/portability_path.c @@ -25,107 +25,136 @@ /* Define separator checking for any platform */ #define PORTABILITY_PATH_SEPARATOR_ALL(chr) (chr == '\\' || chr == '/') -size_t portability_path_get_name(const char *path, size_t path_size, char *name, size_t name_size) +static size_t portability_path_basename_offset(const char *const path, const size_t path_size) { - size_t i, count, last; + size_t offset = path_size; - if (path == NULL || name == NULL) + while (offset > 0 && !PORTABILITY_PATH_SEPARATOR(path[offset - 1])) { - return 0; + --offset; } - for (i = 0, count = 0, last = 0; path[i] != '\0' && i < path_size && count < name_size; ++i) - { - name[count++] = path[i]; + return offset; +} - if (PORTABILITY_PATH_SEPARATOR(path[i])) - { - count = 0; - } - else if (path[i] == '.') +size_t portability_path_get_name(const char *const path, const size_t path_size, char *const name, const size_t name_size) +{ + size_t name_start, rightmost_dot, length, size; + + if (path == NULL) + { + if (name == NULL || name_size == 0) { - if (i > 0 && path[i - 1] == '.') - { - last = 0; - count = 0; - } - else - { - if (count > 0) - { - last = count - 1; - } - else - { - last = 0; - } - } + return 0; } + + name[0] = '\0'; + + return 1; + } + + /* Find rightmost path separator */ + name_start = portability_path_basename_offset(path, path_size); + + /* Find rightmost dot */ + rightmost_dot = path_size; + + while (rightmost_dot != name_start && path[rightmost_dot - 1] != '.') + { + --rightmost_dot; } - if ((last == 0 && count > 1) || last > count) + /* No dots found, or name starts with dot and is non-empty, use whole name */ + if (rightmost_dot == name_start || (rightmost_dot == name_start + 1 && rightmost_dot != path_size - 1)) { - last = count; + rightmost_dot = path_size - 1; } - name[last] = '\0'; + /* Remove all consecutive dots at the end */ + while (rightmost_dot != name_start && path[rightmost_dot - 1] == '.') + { + --rightmost_dot; + } - return last + 1; + length = rightmost_dot - name_start; + size = length + 1; + + /* Return required size */ + if (name == NULL || size > name_size) + { + return size; + } + + if (length > 0) + { + memcpy(name, path + name_start, length); + } + + name[length] = '\0'; + + return size; } -size_t portability_path_get_name_canonical(const char *path, size_t path_size, char *name, size_t name_size) +size_t portability_path_get_name_canonical(const char *const path, const size_t path_size, char *const name, const size_t name_size) { - if (path == NULL || name == NULL) + size_t name_start, leftmost_dot, length, size; + + if (path == NULL) { - return 0; + if (name == NULL || name_size == 0) + { + return 0; + } + + name[0] = '\0'; + + return 1; } - size_t i, count, last; + /* Find rightmost path separator */ + name_start = portability_path_basename_offset(path, path_size); + + /* Find leftmost dot */ + leftmost_dot = name_start; - for (i = 0, count = 0, last = 0; path[i] != '\0' && i < path_size && count < name_size; ++i) + while (leftmost_dot < path_size && path[leftmost_dot] != '.') { - name[count++] = path[i]; + ++leftmost_dot; + } - if (PORTABILITY_PATH_SEPARATOR(path[i])) - { - count = 0; - } - else if (path[i] == '.') + /* No dots found, use whole name */ + if (leftmost_dot == path_size) + { + --leftmost_dot; + } + + /* Name starts with dot, use the following dot instead */ + if (leftmost_dot == name_start) + { + do { - if (i > 0 && path[i - 1] == '.') - { - last = 0; - count = 0; - } - else - { - if (count > 0) - { - last = count - 1; - } - else - { - last = 0; - } + ++leftmost_dot; - /* This function is the same as portability_path_get_name but - returns the name of the file without any extension, for example: - - portability_path_get_name of libnode.so.72 is libnode.so - - portability_path_get_name_canonical of libnode.so.72 is libnode - */ - break; - } - } + } while (leftmost_dot < path_size && path[leftmost_dot] != '.'); + } + + length = leftmost_dot - name_start; + size = length + 1; + + /* Return required size */ + if (name == NULL || size > name_size) + { + return size; } - if (last == 0 && count > 1) + if (length > 0) { - last = count; + memcpy(name, path + name_start, length); } - name[last] = '\0'; + name[length] = '\0'; - return last + 1; + return size; } size_t portability_path_get_fullname(const char *path, size_t path_size, char *name, size_t name_size) diff --git a/source/ports/cxx_port/CMakeLists.txt b/source/ports/cxx_port/CMakeLists.txt index e3e79398a..13657ce94 100644 --- a/source/ports/cxx_port/CMakeLists.txt +++ b/source/ports/cxx_port/CMakeLists.txt @@ -34,30 +34,29 @@ include(SecurityFlags) # Sources # -set(inline_path "${CMAKE_CURRENT_SOURCE_DIR}/inline/metacall") set(include_path "${CMAKE_CURRENT_SOURCE_DIR}/include/metacall") set(source_path "${CMAKE_CURRENT_SOURCE_DIR}/source") -set(inlines - ${inline_path}/metacall.inl -) - set(headers ${include_path}/metacall.hpp ) +set(inline + ${include_path}/metacall.inl +) + set(sources ${source_path}/metacall.cpp ) # Group source files -set(inline_group "Inline Files") set(header_group "Header Files (API)") +set(inline_group "Inline Files") set(source_group "Source Files") -source_group_by_path(${inline_path} "\\\\.inl$" - ${inline_group} ${inlines}) source_group_by_path(${include_path} "\\\\.h$|\\\\.hpp$" ${header_group} ${headers}) +source_group_by_path(${include_path} "\\\\.inl$" + ${inline_group} ${inlines}) source_group_by_path(${source_path} "\\\\.cpp$|\\\\.c$|\\\\.h$|\\\\.hpp$" ${source_group} ${sources}) @@ -67,9 +66,9 @@ source_group_by_path(${source_path} "\\\\.cpp$|\\\\.c$|\\\\.h$|\\\\.hpp$" # Build library add_library(${target} - ${inlines} ${sources} ${headers} + ${inline} ) # Create namespaced alias @@ -104,10 +103,6 @@ target_include_directories(${target} ${CMAKE_CURRENT_SOURCE_DIR}/include ${CMAKE_CURRENT_BINARY_DIR}/include - ${PROJECT_BINARY_DIR}/source/inline - ${CMAKE_CURRENT_SOURCE_DIR}/inline - ${CMAKE_CURRENT_BINARY_DIR}/inline - PUBLIC ${DEFAULT_INCLUDE_DIRECTORIES} @@ -115,11 +110,6 @@ target_include_directories(${target} $ $ $ - - - $ - $ - $ ) # @@ -165,6 +155,15 @@ target_compile_options(${target} INTERFACE ) +# +# Compile features +# + +target_compile_features(${target} + PRIVATE + cxx_std_17 +) + # # Linker options # @@ -187,9 +186,3 @@ install(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/include/metacall DESTINATION ${INSTALL_INCLUDE} COMPONENT dev ) - -# Inline files -install(DIRECTORY - ${CMAKE_CURRENT_SOURCE_DIR}/inline/metacall DESTINATION ${INSTALL_INCLUDE} - COMPONENT dev -) diff --git a/source/ports/cxx_port/include/metacall/metacall.hpp b/source/ports/cxx_port/include/metacall/metacall.hpp index afecc0fa6..9092bbfe9 100644 --- a/source/ports/cxx_port/include/metacall/metacall.hpp +++ b/source/ports/cxx_port/include/metacall/metacall.hpp @@ -72,8 +72,8 @@ class METACALL_API value : public value_base } } - explicit value(void *value_ptr) : - value_base(value_ptr, &value_base::noop_destructor) + explicit value(void *value_ptr, void (*destructor)(void *) = &value_base::noop_destructor) : + value_base(value_ptr, destructor) { if (metacall_value_id(value_ptr) != id()) { @@ -86,7 +86,6 @@ class METACALL_API value : public value_base throw std::runtime_error("Unsupported MetaCall value"); } -private: // Type-specific creation (calls specialized version below) static void *create(const T &v); @@ -336,7 +335,124 @@ inline std::nullptr_t value::to_value() const return nullptr; } -// TODO: Array, Map, Future, Function, Class, Object, Exception, Throwable... +// TODO: Future, Function, Class, Object, Exception, Throwable... + +class METACALL_API value_ref +{ +public: + explicit value_ref(void *ptr) : + ptr(ptr) {} + + template + T as() const + { + return value(ptr).to_value(); + } + +private: + void *ptr; +}; + +class METACALL_API array : public value_base +{ +public: + template + explicit array(Args &&...args) : + value_base(create(std::forward(args)...), &metacall_value_destroy) + { + if (value_ptr == nullptr) + { + throw std::runtime_error("Failed to create MetaCall array"); + } + } + + explicit array(void *array_value) : + value_base(array_value, &value_base::noop_destructor) {} + + void **to_value() const + { + void **array_ptr = metacall_value_to_array(value_ptr.get()); + + if (array_ptr == NULL) + { + throw std::runtime_error("Invalid MetaCall array"); + } + + return array_ptr; + } + + template + T get(std::size_t index) const + { + void **array_ptr = to_value(); + + return value(array_ptr[index]).to_value(); + } + + value_ref operator[](std::size_t index) const + { + void **array_ptr = to_value(); + + return value_ref(array_ptr[index]); + } + + static enum metacall_value_id id() + { + return METACALL_ARRAY; + } + +private: + // Recursive function to create and fill the MetaCall array + template + static void *create(Args &&...args) + { + constexpr std::size_t size = sizeof...(Args); + + // Create the array with null data initially + void *array_value = metacall_value_create_array(NULL, size); + + if (array_value == NULL) + { + throw std::runtime_error("Failed to create MetaCall value array"); + } + + // Get the internal C array + void **array_ptr = metacall_value_to_array(array_value); + + // Helper to unpack the args into array + create_array(array_ptr, 0, std::forward(args)...); + + return array_value; + } + + // Recursive unpacking using fold expression (C++17+) + template + static void create_array(void **array_ptr, std::size_t index, Args &&...args) + { + // Use initializer list trick to expand the pack + (( + array_ptr[index++] = value>::create(std::forward(args))), + ...); + } +}; + +template <> +inline void *value::create(const array &v) +{ + return metacall_value_copy(v.to_raw()); +} + +template <> +inline enum metacall_value_id value::id() +{ + return METACALL_ARRAY; +} + +template <> +inline array value::to_value() const +{ + return array(to_raw()); +} template class METACALL_API map : public value_base @@ -386,6 +502,17 @@ class METACALL_API map : public value_base rehash(); } + V operator[](const K &key) const + { + return m.at(key).second.to_value(); + } + + static enum metacall_value_id id() + { + return METACALL_MAP; + } + +protected: void rehash() { void *ptr = value_ptr.get(); @@ -406,41 +533,57 @@ class METACALL_API map : public value_base } } - V operator[](const K &key) const +private: + std::unordered_map m; +}; + +namespace detail +{ +template +constexpr bool is_value_base = std::is_base_of_v>>; + +template +value_base to_value_base(T &&arg) +{ + if constexpr (is_value_base) { - return m.at(key).second.to_value(); + return std::move(arg); + } + else + { + return value>(std::forward(arg)); } +} -private: - /* - // Case 1: value is value_base (e.g. nested metacall map value) - template - static typename std::enable_if::value, value>::type - wrap_value(const T &v) +} /* namespace detail */ + +template +METACALL_API Ret metacall(std::string name, Args &&...args) +{ + constexpr std::size_t size = sizeof...(Args); + std::array value_args = { { detail::to_value_base(std::forward(args))... } }; + void *raw_args[size]; + + for (std::size_t i = 0; i < size; ++i) { - return const_cast(v); + raw_args[i] = value_args[i].to_raw(); } - // Case 2: value is a plain type - template - static typename std::enable_if::value, value>::type - wrap_value(const T &v) + void *ret = metacallv_s(name.c_str(), raw_args, size); + + if (ret == NULL) { - value val(v); - return val; + throw std::runtime_error("MetaCall invokation to '" + name + "' has failed by returning NULL"); } - */ - std::unordered_map m; -}; + value result(ret, &metacall_value_destroy); -template -METACALL_API int metacall(std::string name, Ts... ts); + return result.to_value(); +} } /* namespace metacall */ -// TODO: Move everything to metacall.inl - +// TODO: Move implementations to metacall.inl #include #endif /* METACALL_HPP */ diff --git a/source/ports/cxx_port/inline/metacall/metacall.inl b/source/ports/cxx_port/include/metacall/metacall.inl similarity index 82% rename from source/ports/cxx_port/inline/metacall/metacall.inl rename to source/ports/cxx_port/include/metacall/metacall.inl index 8223b5be0..81a48f839 100644 --- a/source/ports/cxx_port/inline/metacall/metacall.inl +++ b/source/ports/cxx_port/include/metacall/metacall.inl @@ -1,40 +1,31 @@ -/* - * Format Library by Parra Studios - * A cross-platform library for supporting formatted input / output. - * - * Copyright (C) 2016 - 2025 Vicente Eduardo Ferrer Garcia - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#ifndef METACALL_INL -#define METACALL_INL 1 - -/* -- Headers -- */ - -#include - -#include - -namespace metacall -{ -template -METACALL_API int metacall(std::string name, Ts... ts) -{ - return 0; -} - -} /* namespace metacall */ - -#endif /* METACALL_INL */ +/* + * Format Library by Parra Studios + * A cross-platform library for supporting formatted input / output. + * + * Copyright (C) 2016 - 2025 Vicente Eduardo Ferrer Garcia + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#ifndef METACALL_INL +#define METACALL_INL 1 + +/* -- Headers -- */ + +namespace metacall +{ + +} /* namespace metacall */ + +#endif /* METACALL_INL */ diff --git a/source/tests/metacall_cxx_port_test/source/metacall_cxx_port_test.cpp b/source/tests/metacall_cxx_port_test/source/metacall_cxx_port_test.cpp index 72912ecf5..23998054e 100644 --- a/source/tests/metacall_cxx_port_test/source/metacall_cxx_port_test.cpp +++ b/source/tests/metacall_cxx_port_test/source/metacall_cxx_port_test.cpp @@ -46,22 +46,79 @@ void *cxx_map_test(size_t argc, void *args[], void *data) return metacall_value_create_null(); } +void *cxx_array_test(size_t argc, void *args[], void *data) +{ + array a(args[0]); + + (void)argc; + (void)data; + + EXPECT_EQ((float)a[0].as(), (int)3); + EXPECT_EQ((float)a[1].as(), (float)4.0f); + + EXPECT_EQ((float)a.get(0), (int)3); + EXPECT_EQ((float)a.get(1), (float)4.0f); + + printf("a[0] => %d\n", a[0].as()); + printf("a[1] => %f\n", a[1].as()); + fflush(stdout); + + return metacall_value_create_null(); +} + +void *cxx_map_array_test(size_t argc, void *args[], void *data) +{ + map m(args[0]); + + (void)argc; + (void)data; + + EXPECT_STREQ(m["includes"][0].as().c_str(), "/a/path"); + EXPECT_STREQ(m["includes"][1].as().c_str(), "/another/path"); + + EXPECT_STREQ(m["libraries"][0].as().c_str(), "/a/path"); + EXPECT_STREQ(m["libraries"][1].as().c_str(), "/another/path"); + + printf("m['includes'][0] => %s\n", m["includes"][0].as().c_str()); + printf("m['includes'][1] => %s\n", m["includes"][1].as().c_str()); + + printf("m['libraries'][0] => %s\n", m["libraries"][0].as().c_str()); + printf("m['libraries'][1] => %s\n", m["libraries"][1].as().c_str()); + + return metacall_value_create_null(); +} + +// TODO: +/* void *cxx_recursive_map_test(size_t argc, void *args[], void *data) { - map m(args[0]); + map> m(args[0]); (void)argc; (void)data; - EXPECT_EQ((float)m["hello"], (float)3.0f); - EXPECT_EQ((float)m["world"], (float)4.0f); + EXPECT_EQ((float)m["hello"]["world"], (float)4.0f); - printf("hello => %f\n", m["hello"]); - printf("world => %f\n", m["world"]); + printf("hello => %f\n", m["hello"]["world"]); fflush(stdout); return metacall_value_create_null(); } +*/ + +void *cxx_float_int_int_test(size_t argc, void *args[], void *data) +{ + value a0(args[0]); + value a1(args[1]); + + (void)argc; + (void)data; + + EXPECT_EQ(a0.to_value(), 7); + EXPECT_EQ(a1.to_value(), 8); + + return metacall_value_create_float(3.0f); +} TEST_F(metacall_cxx_port_test, DefaultConstructor) { @@ -73,42 +130,48 @@ TEST_F(metacall_cxx_port_test, DefaultConstructor) { "world", 4.0f } }; - void *args[] = { - m.to_raw() - }; - metacall_register("cxx_map_test", cxx_map_test, NULL, METACALL_NULL, 1, METACALL_MAP); - void *ret = metacallv_s("cxx_map_test", args, 1); + EXPECT_EQ(nullptr, metacall::metacall("cxx_map_test", m)); + } - EXPECT_NE((void *)NULL, (void *)ret); + { + array a(3, 4.0f); - EXPECT_EQ((enum metacall_value_id)metacall_value_id(ret), (enum metacall_value_id)METACALL_NULL); + metacall_register("cxx_array_test", cxx_array_test, NULL, METACALL_NULL, 1, METACALL_ARRAY); - metacall_value_destroy(ret); + EXPECT_EQ(nullptr, metacall::metacall("cxx_array_test", a)); } - /* { - map> m = { - { "hello", { "world", 4.0f } }, + map m = { + { "includes", array("/a/path", "/another/path") }, + { "libraries", array("/a/path", "/another/path") } }; - void *args[] = { - m.to_raw() + metacall_register("cxx_map_array_test", cxx_map_array_test, NULL, METACALL_NULL, 1, METACALL_MAP); + + EXPECT_EQ(nullptr, metacall::metacall("cxx_map_array_test", m)); + } + + // TODO: + /* + { + map> m = { + { "hello", { "world", 4.0f } } }; metacall_register("cxx_recursive_map_test", cxx_recursive_map_test, NULL, METACALL_NULL, 1, METACALL_MAP); - void *ret = metacallv_s("cxx_recursive_map_test", args, 1); - - EXPECT_NE((void *)NULL, (void *)ret); + EXPECT_EQ(nullptr, metacall::metacall("cxx_recursive_map_test", m)); + } + */ - EXPECT_EQ((enum metacall_value_id)metacall_value_id(ret), (enum metacall_value_id)METACALL_NULL); + { + metacall_register("cxx_float_int_int_test", cxx_float_int_int_test, NULL, METACALL_FLOAT, 2, METACALL_INT, METACALL_INT); - metacall_value_destroy(ret); + EXPECT_EQ(3.0f, metacall::metacall("cxx_float_int_int_test", 7, 8)); } - */ /* Print inspect information */ { diff --git a/source/tests/portability_path_test/source/portability_path_test.cpp b/source/tests/portability_path_test/source/portability_path_test.cpp index 15534b235..f4c638c2f 100644 --- a/source/tests/portability_path_test/source/portability_path_test.cpp +++ b/source/tests/portability_path_test/source/portability_path_test.cpp @@ -68,6 +68,33 @@ TEST_F(portability_path_test, portability_path_test_path_get_module_name_with_ra EXPECT_EQ((char)'\0', (char)result[size - 1]); } +TEST_F(portability_path_test, portability_path_test_path_get_name_null) +{ + static const char result[] = ""; + + string_name name; + + size_t size = portability_path_get_name(NULL, 0, name, NAME_SIZE); + + EXPECT_STREQ(name, result); + EXPECT_EQ((size_t)size, (size_t)sizeof(result)); + EXPECT_EQ((char)'\0', (char)result[size - 1]); +} + +TEST_F(portability_path_test, portability_path_test_path_get_name_empty) +{ + static const char base[] = ""; + static const char result[] = ""; + + string_name name; + + size_t size = portability_path_get_name(base, sizeof(base), name, NAME_SIZE); + + EXPECT_STREQ(name, result); + EXPECT_EQ((size_t)size, (size_t)sizeof(result)); + EXPECT_EQ((char)'\0', (char)result[size - 1]); +} + TEST_F(portability_path_test, portability_path_test_path_get_name) { static const char base[] = "/a/b/c/asd.txt"; @@ -110,6 +137,34 @@ TEST_F(portability_path_test, portability_path_test_path_get_name_without_dot) EXPECT_EQ((char)'\0', (char)result[size - 1]); } +TEST_F(portability_path_test, portability_path_test_path_get_name_dot_in_path) +{ + static const char base[] = "/a/b.c/d/asd"; + static const char result[] = "asd"; + + string_name name; + + size_t size = portability_path_get_name(base, sizeof(base), name, NAME_SIZE); + + EXPECT_STREQ(name, result); + EXPECT_EQ((size_t)size, (size_t)sizeof(result)); + EXPECT_EQ((char)'\0', (char)result[size - 1]); +} + +TEST_F(portability_path_test, portability_path_test_path_get_name_dot_in_path_and_name) +{ + static const char base[] = "/a/b.c/d/asd.txt"; + static const char result[] = "asd"; + + string_name name; + + size_t size = portability_path_get_name(base, sizeof(base), name, NAME_SIZE); + + EXPECT_STREQ(name, result); + EXPECT_EQ((size_t)size, (size_t)sizeof(result)); + EXPECT_EQ((char)'\0', (char)result[size - 1]); +} + TEST_F(portability_path_test, portability_path_test_path_get_name_only_separator_dot) { static const char base[] = "/.";