This is an automated email from the ASF dual-hosted git repository. pnoltes pushed a commit to branch feature/type_support_for_properties in repository https://gitbox.apache.org/repos/asf/celix.git
commit 2c5194ff1b254d88c8a112c28307233a044ca970 Author: Pepijn Noltes <[email protected]> AuthorDate: Wed Jan 4 20:21:32 2023 +0100 Add unit test for celix types properties and fix some mem issues --- libs/utils/gtest/src/PropertiesTestSuite.cc | 23 ++- libs/utils/gtest/src/VersionTestSuite.cc | 46 ++--- libs/utils/include/celix/Properties.h | 44 +++-- libs/utils/include/celix_properties.h | 26 ++- libs/utils/include/celix_utils.h | 16 +- libs/utils/include/celix_version.h | 8 +- libs/utils/src/properties.c | 281 ++++++++++++++-------------- libs/utils/src/utils.c | 19 +- libs/utils/src/version.c | 9 +- 9 files changed, 273 insertions(+), 199 deletions(-) diff --git a/libs/utils/gtest/src/PropertiesTestSuite.cc b/libs/utils/gtest/src/PropertiesTestSuite.cc index 1528ddb2..f0537f75 100644 --- a/libs/utils/gtest/src/PropertiesTestSuite.cc +++ b/libs/utils/gtest/src/PropertiesTestSuite.cc @@ -284,6 +284,7 @@ TEST_F(PropertiesTestSuite, getType) { EXPECT_EQ(CELIX_PROPERTIES_VALUE_TYPE_VERSION, celix_properties_getType(props, "version")); EXPECT_EQ(CELIX_PROPERTIES_VALUE_TYPE_UNSET, celix_properties_getType(props, "missing")); + celix_version_destroy(version); celix_properties_destroy(props); } @@ -326,6 +327,7 @@ TEST_F(PropertiesTestSuite, getEntry) { entry = celix_properties_getEntry(props, "key6"); EXPECT_EQ(CELIX_PROPERTIES_VALUE_TYPE_UNSET, entry.valueType); + celix_version_destroy(version); celix_properties_destroy(props); } @@ -403,13 +405,14 @@ TEST_F(PropertiesTestSuite, iterateOverProperties) { celix_properties_destroy(props); } -TEST_F(PropertiesTestSuite, getAsVersion) { +TEST_F(PropertiesTestSuite, getVersion) { auto* properties = celix_properties_create(); + auto* emptyVersion = celix_version_createEmptyVersion(); // Test getting a version property auto* expected = celix_version_createVersion(1, 2, 3, "test"); celix_properties_setVersion(properties, "key", expected); - const auto* actual = celix_properties_getAsVersion(properties, "key", nullptr); + const auto* actual = celix_properties_getVersion(properties, "key", nullptr); EXPECT_EQ(celix_version_getMajor(expected), celix_version_getMajor(actual)); EXPECT_EQ(celix_version_getMinor(expected), celix_version_getMinor(actual)); EXPECT_EQ(celix_version_getMicro(expected), celix_version_getMicro(actual)); @@ -417,16 +420,22 @@ TEST_F(PropertiesTestSuite, getAsVersion) { // Test getting a non-version property celix_properties_set(properties, "key2", "value"); - auto* emptyVersion = celix_version_createEmptyVersion(); - actual = celix_properties_getAsVersion(properties, "key2", emptyVersion); + actual = celix_properties_getVersion(properties, "key2", emptyVersion); EXPECT_EQ(celix_version_getMajor(actual), 0); EXPECT_EQ(celix_version_getMinor(actual), 0); EXPECT_EQ(celix_version_getMicro(actual), 0); EXPECT_STREQ(celix_version_getQualifier(actual), ""); + EXPECT_EQ(celix_properties_getVersion(properties, "non-existent", nullptr), nullptr); + celix_version_destroy(expected); - EXPECT_EQ(celix_properties_getAsVersion(properties, "non-existent", nullptr), nullptr); + // Test setting without copy + celix_properties_setVersionWithoutCopy(properties, "key3", celix_version_createVersion(3,3,3,"")); + actual = celix_properties_getVersion(properties, "key3", emptyVersion); + EXPECT_EQ(celix_version_getMajor(actual), 3); + EXPECT_EQ(celix_version_getMinor(actual), 3); + EXPECT_EQ(celix_version_getMicro(actual), 3); + EXPECT_STREQ(celix_version_getQualifier(actual), ""); - celix_version_destroy(expected); celix_version_destroy(emptyVersion); celix_properties_destroy(properties); -} \ No newline at end of file +} diff --git a/libs/utils/gtest/src/VersionTestSuite.cc b/libs/utils/gtest/src/VersionTestSuite.cc index a0874ecf..90e5e9f1 100644 --- a/libs/utils/gtest/src/VersionTestSuite.cc +++ b/libs/utils/gtest/src/VersionTestSuite.cc @@ -68,23 +68,25 @@ TEST_F(VersionTestSuite, create) { free(str); } -TEST_F(VersionTestSuite, clone) { - celix_version_t* version = nullptr; - celix_version_t* clone = nullptr; - char * str; - - str = celix_utils_strdup("abc"); - EXPECT_EQ(CELIX_SUCCESS, version_createVersion(1, 2, 3, str, &version)); - EXPECT_EQ(CELIX_SUCCESS, version_clone(version, &clone)); - EXPECT_TRUE(version != nullptr); - EXPECT_EQ(1, clone->major); - EXPECT_EQ(2, clone->minor); - EXPECT_EQ(3, clone->micro); - EXPECT_STREQ("abc", clone->qualifier); +TEST_F(VersionTestSuite, copy) { + auto* version = celix_version_create(1, 2, 3, "abc"); + auto* copy = celix_version_copy(version); + EXPECT_NE(nullptr, version); + EXPECT_NE(nullptr, copy); + EXPECT_EQ(1, celix_version_getMajor(copy)); + EXPECT_EQ(2, celix_version_getMinor(copy)); + EXPECT_EQ(3, celix_version_getMicro(copy)); + EXPECT_STREQ("abc", celix_version_getQualifier(copy)); + celix_version_destroy(copy); + celix_version_destroy(version); - version_destroy(clone); - version_destroy(version); - free(str); + copy = celix_version_copy(nullptr); //returns "empty" version + EXPECT_NE(nullptr, copy); + EXPECT_EQ(0, celix_version_getMajor(copy)); + EXPECT_EQ(0, celix_version_getMinor(copy)); + EXPECT_EQ(0, celix_version_getMicro(copy)); + EXPECT_STREQ("", celix_version_getQualifier(copy)); + celix_version_destroy(copy); } TEST_F(VersionTestSuite, createFromString) { @@ -277,8 +279,8 @@ TEST_F(VersionTestSuite, compare) { } TEST_F(VersionTestSuite, celix_version_compareToMajorMinor) { - celix_version_t *version1 = celix_version_createVersion(2, 2, 0, nullptr); - celix_version_t *version2 = celix_version_createVersion(2, 2, 4, "qualifier"); + auto* version1 = celix_version_create(2, 2, 0, nullptr); + auto* version2 = celix_version_create(2, 2, 4, "qualifier"); EXPECT_EQ(0, celix_version_compareToMajorMinor(version1, 2, 2)); EXPECT_EQ(0, celix_version_compareToMajorMinor(version2, 2, 2)); @@ -367,8 +369,8 @@ TEST_F(VersionTestSuite,semanticCompatibility) { TEST_F(VersionTestSuite, compareEmptyAndNullQualifier) { //nullptr or "" qualifier should be the same - auto* v1 = celix_version_createVersion(0, 0, 0, nullptr); - auto* v2 = celix_version_createVersion(0, 0, 0, ""); + auto* v1 = celix_version_create(0, 0, 0, nullptr); + auto* v2 = celix_version_create(0, 0, 0, ""); EXPECT_EQ(0, celix_version_compareTo(v1, v1)); EXPECT_EQ(0, celix_version_compareTo(v1, v2)); EXPECT_EQ(0, celix_version_compareTo(v2, v2)); @@ -379,7 +381,7 @@ TEST_F(VersionTestSuite, compareEmptyAndNullQualifier) { TEST_F(VersionTestSuite, fillString) { // Create a version object - celix_version_t* version = celix_version_createVersion(1, 2, 3, "alpha"); + auto* version = celix_version_create(1, 2, 3, "alpha"); // Test with buffer large enough to hold the formatted string char buffer[32]; @@ -392,4 +394,4 @@ TEST_F(VersionTestSuite, fillString) { EXPECT_FALSE(success); celix_version_destroy(version); -} \ No newline at end of file +} diff --git a/libs/utils/include/celix/Properties.h b/libs/utils/include/celix/Properties.h index 111c7fe4..682fe490 100644 --- a/libs/utils/include/celix/Properties.h +++ b/libs/utils/include/celix/Properties.h @@ -36,6 +36,7 @@ namespace celix { public: explicit PropertiesIterator(const celix_properties_t* props) { iter = celix_properties_begin(props); + setFields(); } PropertiesIterator& operator++() { @@ -60,27 +61,27 @@ namespace celix { void next() { celix_propertiesIterator_next(&iter); - if (celix_propertiesIterator_isEnd(&iter)) { - moveToEnd(); - } else { - first = iter.entry.key; - second = iter.entry.value; - end = false; - } + setFields(); } - //TODO try to remove moveToEnd void moveToEnd() { first = {}; second = {}; end = true; } - //TODO for C++17 try to update first and second to stringview std::string first{}; std::string second{}; - //TODO iter? private: + void setFields() { + if (celix_propertiesIterator_isEnd(&iter)) { + moveToEnd(); + } else { + first = iter.entry.key; + second = iter.entry.value; + } + } + celix_properties_iterator_t iter{.index = -1, .entry = {}, ._data = {}}; bool end{false}; }; @@ -130,8 +131,6 @@ namespace celix { } #endif - //TODO operator= with long, double, boolean and version - [[nodiscard]] const char* getValue() const { if (charKey == nullptr) { return celix_properties_get(props.get(), stringKey.c_str(), nullptr); @@ -140,6 +139,8 @@ namespace celix { } } + //TODO get typed value + operator std::string() const { auto *cstr = getValue(); return cstr == nullptr ? std::string{} : std::string{cstr}; @@ -290,6 +291,10 @@ namespace celix { return celix_properties_getAsBool(cProps.get(), key.data(), defaultValue); } + //TODO getType + + //TODO getAsVersion + /** * @brief Sets a T&& property. Will use (std::) to_string to convert the value to string. */ @@ -367,6 +372,8 @@ namespace celix { using namespace std; celix_properties_set(cProps.get(), key.c_str(), to_string(value).c_str()); } + + //TODO set long, double, boolean and version #endif /** @@ -382,7 +389,7 @@ namespace celix { [[nodiscard]] std::map<std::string, std::string> convertToMap() const { std::map<std::string, std::string> result{}; for (const auto& pair : *this) { - result[pair.first] = pair.second; + result[std::string{pair.first}] = pair.second; } return result; } @@ -393,7 +400,7 @@ namespace celix { [[nodiscard]] std::unordered_map<std::string, std::string> convertToUnorderedMap() const { std::unordered_map<std::string, std::string> result{}; for (const auto& pair : *this) { - result[pair.first] = pair.second; + result[std::string{pair.first}] = pair.second; } return result; } @@ -411,8 +418,13 @@ namespace celix { #endif - //TODO save - //TODO load + //TODO test + void store(const std::string& file, const std::string& header = {}) const { + celix_properties_store(cProps.get(), file.c_str(), header.empty() ? nullptr : header.c_str()); + } + + //TODO laod + private: explicit Properties(celix_properties_t* props) : cProps{props, [](celix_properties_t*) { /*nop*/ }} {} diff --git a/libs/utils/include/celix_properties.h b/libs/utils/include/celix_properties.h index 45846506..e484a436 100644 --- a/libs/utils/include/celix_properties.h +++ b/libs/utils/include/celix_properties.h @@ -284,14 +284,30 @@ void celix_properties_setDouble(celix_properties_t* properties, const char* key, double celix_properties_getAsDouble(const celix_properties_t* properties, const char* key, double defaultValue); /** - * @brief Sets the value of a property as a Celix version string. + * @brief Sets the value of a property as a Celix version. * - * @param properties The property set to modify. - * @param key The key of the property to set. - * @param version The value to set. + * This function will make a copy of the provided celix_version_t object and store it in the property set. + * + * @param[in] properties The property set to modify. + * @param[in] key The key of the property to set. + * @param[in] version The value to set. The function will make a copy of this object and store it in the property set. */ void celix_properties_setVersion(celix_properties_t* properties, const char* key, const celix_version_t* version); +/** + * @brief Sets the value of a property as a Celix version. + * + * This function will store a reference to the provided celix_version_t object in the property set and takes + * ownership of the provided version. + * + * @param[in] properties The property set to modify. + * @param[in] key The key of the property to set. + * @param[in] version The value to set. The function will store a reference to this object in the property set and + * takes ownership of the provided version. + */ +void celix_properties_setVersionWithoutCopy(celix_properties_t* properties, const char* key, celix_version_t* version); + + /** * @brief Gets the value of a property as a Celix version. * @@ -303,7 +319,7 @@ void celix_properties_setVersion(celix_properties_t* properties, const char* key * @return The value of the property if it is a Celix version, or the default value if the property is not set or the * value is not a Celix version. */ -const celix_version_t* celix_properties_getAsVersion( +const celix_version_t* celix_properties_getVersion( const celix_properties_t* properties, const char* key, const celix_version_t* defaultValue); diff --git a/libs/utils/include/celix_utils.h b/libs/utils/include/celix_utils.h index e0db2731..791d8f89 100644 --- a/libs/utils/include/celix_utils.h +++ b/libs/utils/include/celix_utils.h @@ -54,11 +54,23 @@ bool celix_utils_stringEquals(const char* a, const char* b); /** * @brief Returns a trimmed string. * - * The trim will remove eny leading and trailing whitespaces (' ', '\t', etc based on `isspace`)/ - * Caller is owner of the returned string. + * This function will remove any leading and trailing whitespaces (' ', '\t', etc based on isspace) from the + * input string. + * + * @param[in] string The input string to be trimmed. + * @return A trimmed version of the input string. The caller is responsible for freeing the memory of this string. */ char* celix_utils_trim(const char* string); +/** + * @brief Trims a string in place. + * + * The trim will remove any leading and trailing whitespaces (' ', '\t', etc based on isspace) from the input string. + * The input string is modified in place. + * @param[in,out] string The string to trim. + */ +void celix_utils_trimInPlace(char* string); + /** * @brief Check if a string is NULL or empty "". */ diff --git a/libs/utils/include/celix_version.h b/libs/utils/include/celix_version.h index be03aeef..f4cea390 100644 --- a/libs/utils/include/celix_version.h +++ b/libs/utils/include/celix_version.h @@ -42,7 +42,13 @@ typedef struct celix_version celix_version_t; * the empty string. * @return The created version or NULL if the input was incorrect */ -celix_version_t* celix_version_createVersion(int major, int minor, int micro, const char* qualifier); +celix_version_t* celix_version_create(int major, int minor, int micro, const char* qualifier); + +/** + * @brief Same as celix_version_create, but deprecated + */ +celix_version_t* celix_version_createVersion(int major, int minor, int micro, const char* qualifier) + __attribute__((deprecated(("celix_version_createVersion is deprecated use celix_version_create instead")))); void celix_version_destroy(celix_version_t* version); diff --git a/libs/utils/src/properties.c b/libs/utils/src/properties.c index 9185fa64..7be3e713 100644 --- a/libs/utils/src/properties.c +++ b/libs/utils/src/properties.c @@ -137,106 +137,6 @@ static void updateBuffers(char **key, char ** value, char **output, int outputPo } } -static void parseLine(const char* line, celix_properties_t *props) { - int linePos = 0; - bool precedingCharIsBackslash = false; - bool isComment = false; - int outputPos = 0; - char *output = NULL; - int key_len = MALLOC_BLOCK_SIZE; - int value_len = MALLOC_BLOCK_SIZE; - linePos = 0; - precedingCharIsBackslash = false; - isComment = false; - output = NULL; - outputPos = 0; - - //Ignore empty lines - if (line[0] == '\n' && line[1] == '\0') { - return; - } - - char *key = calloc(1, key_len); - char *value = calloc(1, value_len); - key[0] = '\0'; - value[0] = '\0'; - - while (line[linePos] != '\0') { - if (line[linePos] == ' ' || line[linePos] == '\t') { - if (output == NULL) { - //ignore - linePos += 1; - continue; - } - } - else { - if (output == NULL) { - output = key; - } - } - if (line[linePos] == '=' || line[linePos] == ':' || line[linePos] == '#' || line[linePos] == '!') { - if (precedingCharIsBackslash) { - //escaped special character - output[outputPos++] = line[linePos]; - updateBuffers(&key, &value, &output, outputPos, &key_len, &value_len); - precedingCharIsBackslash = false; - } - else { - if (line[linePos] == '#' || line[linePos] == '!') { - if (outputPos == 0) { - isComment = true; - break; - } - else { - output[outputPos++] = line[linePos]; - updateBuffers(&key, &value, &output, outputPos, &key_len, &value_len); - } - } - else { // = or : - if (output == value) { //already have a seperator - output[outputPos++] = line[linePos]; - updateBuffers(&key, &value, &output, outputPos, &key_len, &value_len); - } - else { - output[outputPos++] = '\0'; - updateBuffers(&key, &value, &output, outputPos, &key_len, &value_len); - output = value; - outputPos = 0; - } - } - } - } - else if (line[linePos] == '\\') { - if (precedingCharIsBackslash) { //double backslash -> backslash - output[outputPos++] = '\\'; - updateBuffers(&key, &value, &output, outputPos, &key_len, &value_len); - } - precedingCharIsBackslash = true; - } - else { //normal character - precedingCharIsBackslash = false; - output[outputPos++] = line[linePos]; - updateBuffers(&key, &value, &output, outputPos, &key_len, &value_len); - } - linePos += 1; - } - if (output != NULL) { - output[outputPos] = '\0'; - } - - if (!isComment) { - //printf("putting 'key'/'value' '%s'/'%s' in properties\n", utils_stringTrim(key), utils_stringTrim(value)); - celix_properties_set(props, utils_stringTrim(key), utils_stringTrim(value)); - } - if(key) { - free(key); - } - if(value) { - free(value); - } - -} - /** * Create a new string from the provided str by either using strup or storing the string the short properties * optimization string buffer. @@ -266,7 +166,7 @@ static celix_status_t celix_properties_fillEntry( const long* longValue, const double* doubleValue, const bool* boolValue, - const celix_version_t* versionValue) { + celix_version_t* versionValue) { char convertedValueBuffer[32]; entry->key = celix_properties_createString(properties, key); if (strValue != NULL) { @@ -302,8 +202,7 @@ static celix_status_t celix_properties_fillEntry( } else /*versionValue*/ { assert(versionValue != NULL); entry->valueType = CELIX_PROPERTIES_VALUE_TYPE_VERSION; - entry->typed.versionValue = celix_version_copy(versionValue); - + entry->typed.versionValue = versionValue; bool written = celix_version_fillString(versionValue, convertedValueBuffer, sizeof(convertedValueBuffer)); if (written) { entry->value = celix_properties_createString(properties, convertedValueBuffer); @@ -360,7 +259,7 @@ static celix_properties_entry_t* celix_properties_createEntry( const long* longValue, const double* doubleValue, const bool* boolValue, - const celix_version_t* versionValue) { + celix_version_t* versionValue) { celix_properties_entry_t* entry = celix_properties_allocEntry(properties); if (entry == NULL) { return NULL; @@ -386,7 +285,7 @@ static void celix_properties_createAndSetEntry( const long* longValue, const double* doubleValue, const bool* boolValue, - const celix_version_t* versionValue) { + celix_version_t* versionValue) { if (properties == NULL) { return; } @@ -415,6 +314,9 @@ static void celix_properties_removeEntryCallback(void* handle, const char* key _ celix_properties_entry_t* entry = val.ptrValue; celix_properties_freeString(properties, (char*)entry->key); celix_properties_freeString(properties, (char*)entry->value); + if (entry->valueType == CELIX_PROPERTIES_VALUE_TYPE_VERSION) { + celix_version_destroy(entry->typed.versionValue); + } if (entry >= properties->entriesBuffer && entry <= (properties->entriesBuffer + CELIX_SHORT_PROPERTIES_OPTIMIZATION_ENTRIES_SIZE)) { //entry is part of the properties entries buffer -> nop. @@ -423,7 +325,6 @@ static void celix_properties_removeEntryCallback(void* handle, const char* key _ } } - celix_properties_t* celix_properties_create(void) { celix_properties_t* props = malloc(sizeof(*props)); if (props != NULL) { @@ -456,38 +357,143 @@ celix_properties_t* celix_properties_load(const char *filename) { return props; } -celix_properties_t* celix_properties_loadWithStream(FILE *file) { - celix_properties_t *props = NULL; - - if (file != NULL ) { - char *saveptr; - char *filebuffer = NULL; - char *line = NULL; - size_t file_size = 0; - - props = celix_properties_create(); - fseek(file, 0, SEEK_END); - file_size = ftell(file); - fseek(file, 0, SEEK_SET); - - if (file_size > 0) { - filebuffer = calloc(file_size + 1, sizeof(char)); - if (filebuffer) { - size_t rs = fread(filebuffer, sizeof(char), file_size, file); - if (rs != file_size) { - fprintf(stderr,"fread read only %lu bytes out of %lu\n", (long unsigned int) rs, (long unsigned int) file_size); +static void parseLine(const char* line, celix_properties_t *props) { + int linePos = 0; + bool precedingCharIsBackslash = false; + bool isComment = false; + int outputPos = 0; + char *output = NULL; + int key_len = MALLOC_BLOCK_SIZE; + int value_len = MALLOC_BLOCK_SIZE; + linePos = 0; + precedingCharIsBackslash = false; + isComment = false; + output = NULL; + outputPos = 0; + + //Ignore empty lines + if (line[0] == '\n' && line[1] == '\0') { + return; + } + + char *key = calloc(1, key_len); + char *value = calloc(1, value_len); + key[0] = '\0'; + value[0] = '\0'; + + while (line[linePos] != '\0') { + if (line[linePos] == ' ' || line[linePos] == '\t') { + if (output == NULL) { + //ignore + linePos += 1; + continue; + } + } + else { + if (output == NULL) { + output = key; + } + } + if (line[linePos] == '=' || line[linePos] == ':' || line[linePos] == '#' || line[linePos] == '!') { + if (precedingCharIsBackslash) { + //escaped special character + output[outputPos++] = line[linePos]; + updateBuffers(&key, &value, &output, outputPos, &key_len, &value_len); + precedingCharIsBackslash = false; + } + else { + if (line[linePos] == '#' || line[linePos] == '!') { + if (outputPos == 0) { + isComment = true; + break; + } + else { + output[outputPos++] = line[linePos]; + updateBuffers(&key, &value, &output, outputPos, &key_len, &value_len); + } } - filebuffer[file_size]='\0'; - line = strtok_r(filebuffer, "\n", &saveptr); - while (line != NULL) { - parseLine(line, props); - line = strtok_r(NULL, "\n", &saveptr); + else { // = or : + if (output == value) { //already have a seperator + output[outputPos++] = line[linePos]; + updateBuffers(&key, &value, &output, outputPos, &key_len, &value_len); + } + else { + output[outputPos++] = '\0'; + updateBuffers(&key, &value, &output, outputPos, &key_len, &value_len); + output = value; + outputPos = 0; + } } - free(filebuffer); } } + else if (line[linePos] == '\\') { + if (precedingCharIsBackslash) { //double backslash -> backslash + output[outputPos++] = '\\'; + updateBuffers(&key, &value, &output, outputPos, &key_len, &value_len); + } + precedingCharIsBackslash = true; + } + else { //normal character + precedingCharIsBackslash = false; + output[outputPos++] = line[linePos]; + updateBuffers(&key, &value, &output, outputPos, &key_len, &value_len); + } + linePos += 1; + } + if (output != NULL) { + output[outputPos] = '\0'; } + if (!isComment) { + //printf("putting 'key'/'value' '%s'/'%s' in properties\n", utils_stringTrim(key), utils_stringTrim(value)); + celix_utils_trimInPlace(key); + celix_utils_trimInPlace(value); + celix_properties_setWithoutCopy(props, key, value); + } else { + free(key); + free(value); + } + + +} + +celix_properties_t* celix_properties_loadWithStream(FILE *file) { + if (file == NULL) { + return NULL; + } + + celix_properties_t *props = celix_properties_create(); + if (props == NULL) { + return NULL; + } + + fseek(file, 0, SEEK_END); + size_t fileSize = ftell(file); + fseek(file, 0, SEEK_SET); + if (fileSize == 0) { + return props; + } + + char* fileBuffer = malloc(fileSize + 1); + if (fileBuffer == NULL) { + celix_properties_destroy(props); + return NULL; + } + + size_t rs = fread(fileBuffer, sizeof(char), fileSize, file); + if (rs < fileSize) { + fprintf(stderr,"fread read only %zu bytes out of %zu\n", rs, fileSize); + } + fileBuffer[fileSize]='\0'; //ensure a '\0' at the end of the fileBuffer + + char* savePtr = NULL; + char* line = strtok_r(fileBuffer, "\n", &savePtr); + while (line != NULL) { + parseLine(line, props); + line = strtok_r(NULL, "\n", &savePtr); + } + free(fileBuffer); + return props; } @@ -692,7 +698,7 @@ void celix_properties_setBool(celix_properties_t *props, const char *key, bool v celix_properties_createAndSetEntry(props, key, NULL, NULL, NULL, &val, NULL); } -const celix_version_t* celix_properties_getAsVersion( +const celix_version_t* celix_properties_getVersion( const celix_properties_t* properties, const char* key, const celix_version_t* defaultValue) { @@ -703,10 +709,13 @@ const celix_version_t* celix_properties_getAsVersion( return defaultValue; } -void celix_properties_setVersion(celix_properties_t *props, const char *key, const celix_version_t* version) { - celix_properties_createAndSetEntry(props, key, NULL, NULL, NULL, NULL, version); +void celix_properties_setVersion(celix_properties_t *properties, const char *key, const celix_version_t* version) { + celix_properties_createAndSetEntry(properties, key, NULL, NULL, NULL, NULL, celix_version_copy(version)); } +void celix_properties_setVersionWithoutCopy(celix_properties_t* properties, const char* key, celix_version_t* version) { + celix_properties_createAndSetEntry(properties, key, NULL, NULL, NULL, NULL, version); +} int celix_properties_size(const celix_properties_t *properties) { return (int)celix_stringHashMap_size(properties->map); @@ -748,7 +757,7 @@ const char* celix_propertiesIterator_nextKey(celix_properties_iterator_t *iter) iter->index = (int)internalIter.mapIter.index; celix_properties_entry_t* entry = internalIter.mapIter.value.ptrValue; if (entry != NULL) { - memcpy(&iter->entry, iter, sizeof(iter->entry)); + memcpy(&iter->entry, entry, sizeof(iter->entry)); } else { memset(&iter->entry, 0, sizeof(iter->entry)); } diff --git a/libs/utils/src/utils.c b/libs/utils/src/utils.c index 7bbe2f4c..6ff882a8 100644 --- a/libs/utils/src/utils.c +++ b/libs/utils/src/utils.c @@ -82,12 +82,12 @@ char * string_ndup(const char *s, size_t n) { return ret; } -static char* celix_utilsTrimInternal(char *string) { +void celix_utils_trimInPlace(char* string) { if (string == NULL) { - return NULL; + return; } - char* begin = string; //save begin to correctly free in the end. + char* begin = string; //save begin to check in the end. char *end; // Trim leading space @@ -103,7 +103,7 @@ static char* celix_utilsTrimInternal(char *string) { } if (string != begin) { - //beginning whitespaces -> move char in copy to to begin string + //beginning whitespaces -> move chars to the beginning of string //This to ensure free still works on the same pointer. char* nstring = begin; while(*string != '\0') { @@ -111,16 +111,17 @@ static char* celix_utilsTrimInternal(char *string) { } (*nstring) = '\0'; } - - return begin; } char* celix_utils_trim(const char* string) { - return celix_utilsTrimInternal(celix_utils_strdup(string)); + char* result = celix_utils_strdup(string); + celix_utils_trimInPlace(result); + return result; } char* utils_stringTrim(char* string) { - return celix_utilsTrimInternal(string); + celix_utils_trimInPlace(string); + return string; } bool utils_isStringEmptyOrNull(const char * const str) { @@ -264,4 +265,4 @@ void celix_utils_extractLocalNameAndNamespaceFromFullyQualifiedName(const char * } else { *outNamespace = namespace; } -} \ No newline at end of file +} diff --git a/libs/utils/src/version.c b/libs/utils/src/version.c index f83fe655..3d0ee1ab 100644 --- a/libs/utils/src/version.c +++ b/libs/utils/src/version.c @@ -96,6 +96,10 @@ celix_status_t version_isCompatible(version_pt user, version_pt provider, bool* } celix_version_t* celix_version_createVersion(int major, int minor, int micro, const char* qualifier) { + return celix_version_create(major, minor, micro, qualifier); +} + +celix_version_t* celix_version_create(int major, int minor, int micro, const char* qualifier) { if (major < 0 || minor < 0 || micro < 0) { return NULL; } @@ -141,6 +145,9 @@ void celix_version_destroy(celix_version_t* version) { celix_version_t* celix_version_copy(const celix_version_t* version) { + if (version == NULL) { + return celix_version_createEmptyVersion(); + } return celix_version_createVersion(version->major, version->minor, version->micro, version->qualifier); } @@ -322,4 +329,4 @@ int celix_version_compareToMajorMinor(const celix_version_t* version, int majorV result = version->minor - minorVersionPart; } return result; -} \ No newline at end of file +}
