From 77f212aecbf885f1f79d6d2ae386875402ea4a31 Mon Sep 17 00:00:00 2001 From: Pepijn Noltes Date: Sat, 7 Oct 2023 19:24:23 +0200 Subject: [PATCH] #509: Remove deprecated macro (incl usage) CELIX_PROPERTIES_FOR_EACH --- .../src/pubsub_wire_protocol_common.c | 8 +- libs/framework/gtest/src/ManifestTestSuite.cc | 5 +- libs/framework/include/celix/Trackers.h | 2 +- .../include/celix/UseServiceBuilder.h | 4 +- .../include/celix/dm/DependencyManager_Impl.h | 6 +- .../include/celix/dm/ServiceDependency_Impl.h | 32 +------- libs/framework/src/celix_launcher.c | 32 ++++---- libs/framework/src/manifest.c | 5 +- libs/rcm/src/celix_capability.c | 43 ++++------ libs/rcm/src/celix_requirement.c | 56 +++++-------- .../utils/gtest/src/CxxPropertiesTestSuite.cc | 19 ++++- libs/utils/gtest/src/PropertiesTestSuite.cc | 51 ++++++------ libs/utils/include/celix/Properties.h | 19 ++++- libs/utils/include/celix_properties.h | 80 +++---------------- libs/utils/src/properties.c | 66 ++++++--------- 15 files changed, 161 insertions(+), 267 deletions(-) diff --git a/bundles/pubsub/pubsub_protocol/pubsub_protocol_lib/src/pubsub_wire_protocol_common.c b/bundles/pubsub/pubsub_protocol/pubsub_protocol_lib/src/pubsub_wire_protocol_common.c index 7b78cea07..88a9bbff5 100644 --- a/bundles/pubsub/pubsub_protocol/pubsub_protocol_lib/src/pubsub_wire_protocol_common.c +++ b/bundles/pubsub/pubsub_protocol/pubsub_protocol_lib/src/pubsub_wire_protocol_common.c @@ -101,19 +101,17 @@ celix_status_t pubsubProtocol_encodeMetadata(pubsub_protocol_message_t* message, *bufferInOut = newBuffer; *bufferLengthInOut = newLength; } - const char* key; if (metadataSize == 0) { encoded = true; continue; } celix_status_t status = CELIX_SUCCESS; - CELIX_PROPERTIES_FOR_EACH(message->metadata.metadata, key) { - const char *val = celix_properties_get(message->metadata.metadata, key, ""); + CELIX_PROPERTIES_ITERATE(message->metadata.metadata, iter) { if (status == CELIX_SUCCESS) { - status = pubsubProtocol_addNetstringEntryToBuffer(*bufferInOut, *bufferLengthInOut, &offset, key); + status = pubsubProtocol_addNetstringEntryToBuffer(*bufferInOut, *bufferLengthInOut, &offset, iter.key); } if (status == CELIX_SUCCESS) { - status = pubsubProtocol_addNetstringEntryToBuffer(*bufferInOut, *bufferLengthInOut, &offset, val); + status = pubsubProtocol_addNetstringEntryToBuffer(*bufferInOut, *bufferLengthInOut, &offset, iter.entry.value); } } if (status == CELIX_FILE_IO_EXCEPTION) { diff --git a/libs/framework/gtest/src/ManifestTestSuite.cc b/libs/framework/gtest/src/ManifestTestSuite.cc index 51cb2bf63..6cb668353 100644 --- a/libs/framework/gtest/src/ManifestTestSuite.cc +++ b/libs/framework/gtest/src/ManifestTestSuite.cc @@ -42,9 +42,8 @@ class ManifestTestSuite : public ::testing::Test { } void CheckPropertiesEqual(const celix_properties_t* prop1, const celix_properties_t* prop2) { EXPECT_EQ(celix_properties_size(prop1), celix_properties_size(prop2)); - const char* key = nullptr; - CELIX_PROPERTIES_FOR_EACH(prop1, key) { - EXPECT_STREQ(celix_properties_get(prop1, key, nullptr), celix_properties_get(prop2, key, nullptr)); + CELIX_PROPERTIES_ITERATE(prop1, iter) { + EXPECT_STREQ(celix_properties_get(prop1, iter.key, nullptr), celix_properties_get(prop2, iter.key, nullptr)); } } void CheckManifestEqual(const manifest_pt manifest1, const manifest_pt manifest2) { diff --git a/libs/framework/include/celix/Trackers.h b/libs/framework/include/celix/Trackers.h index 5498607ca..f702c958e 100644 --- a/libs/framework/include/celix/Trackers.h +++ b/libs/framework/include/celix/Trackers.h @@ -447,7 +447,7 @@ namespace celix { long svcId = celix_properties_getAsLong(cProps, OSGI_FRAMEWORK_SERVICE_ID, -1L); long svcRanking = celix_properties_getAsLong(cProps, OSGI_FRAMEWORK_SERVICE_RANKING, 0); auto svc = std::shared_ptr{static_cast(voidSvc), [](I*){/*nop*/}}; - auto props = celix::Properties::wrap(cProps); + auto props = std::make_shared(celix::Properties::wrap(cProps)); auto owner = std::make_shared(const_cast(cBnd)); return std::make_shared(svcId, svcRanking, svc, props, owner); } diff --git a/libs/framework/include/celix/UseServiceBuilder.h b/libs/framework/include/celix/UseServiceBuilder.h index 1e86cee6c..5f37f95af 100644 --- a/libs/framework/include/celix/UseServiceBuilder.h +++ b/libs/framework/include/celix/UseServiceBuilder.h @@ -164,10 +164,10 @@ namespace celix { func(*svc); } for (const auto& func : builder->callbacksWithProperties) { - func(*svc, *props); + func(*svc, props); } for (const auto& func : builder->callbacksWithOwner) { - func(*svc, *props, bnd); + func(*svc, props, bnd); } }; diff --git a/libs/framework/include/celix/dm/DependencyManager_Impl.h b/libs/framework/include/celix/dm/DependencyManager_Impl.h index 76157a4a6..e364d9f10 100644 --- a/libs/framework/include/celix/dm/DependencyManager_Impl.h +++ b/libs/framework/include/celix/dm/DependencyManager_Impl.h @@ -174,10 +174,8 @@ static celix::dm::DependencyManagerInfo createDepManInfoFromC(celix_dependency_m auto* cIntInfo = static_cast(celix_arrayList_get(cCmpInfo->interfaces, k)); celix::dm::InterfaceInfo intInfo{}; intInfo.serviceName = std::string{cIntInfo->name}; - const char* key; - CELIX_PROPERTIES_FOR_EACH(cIntInfo->properties, key) { - const char* val =celix_properties_get(cIntInfo->properties, key, ""); - intInfo.properties[std::string{key}] = std::string{val}; + CELIX_PROPERTIES_ITERATE(cIntInfo->properties, iter) { + intInfo.properties[std::string{iter.key}] = std::string{iter.entry.value}; } cmpInfo.interfacesInfo.emplace_back(std::move(intInfo)); } diff --git a/libs/framework/include/celix/dm/ServiceDependency_Impl.h b/libs/framework/include/celix/dm/ServiceDependency_Impl.h index 8fc501045..566ad53ed 100644 --- a/libs/framework/include/celix/dm/ServiceDependency_Impl.h +++ b/libs/framework/include/celix/dm/ServiceDependency_Impl.h @@ -237,20 +237,8 @@ void CServiceDependency::setupCallbacks() { template int CServiceDependency::invokeCallback(std::function fp, const celix_properties_t *props, const void* service) { - Properties properties {}; - const char* key {nullptr}; - const char* value {nullptr}; - - if (props != nullptr) { - CELIX_PROPERTIES_FOR_EACH(props, key) { - value = celix_properties_get(props, key, ""); //note. C++ does not allow nullptr entries for std::string - //std::cout << "got property " << key << "=" << value << "\n"; - properties[key] = value; - } - } - + auto properties = Properties::copy(props); const I* srv = (const I*) service; - fp(srv, std::move(properties)); return 0; } @@ -504,19 +492,7 @@ ServiceDependency& ServiceDependency::setStrategy(DependencyUpdateStra template int ServiceDependency::invokeCallback(std::function fp, const celix_properties_t *props, const void* service) { I *svc = (I*)service; - - Properties properties {}; - const char* key {nullptr}; - const char* value {nullptr}; - - if (props != nullptr) { - CELIX_PROPERTIES_FOR_EACH(props, key) { - value = celix_properties_get(props, key, ""); - //std::cout << "got property " << key << "=" << value << "\n"; - properties[key] = value; - } - } - + auto properties = celix::Properties::wrap(props); fp(svc, std::move(properties)); //explicit move of lvalue properties. return 0; } @@ -539,7 +515,7 @@ void ServiceDependency::setupCallbacks() { std::weak_ptr replacedSvc = dep->setService.first; std::weak_ptr replacedProps = dep->setService.second; auto svc = std::shared_ptr{static_cast(rawSvc), [](I*){/*nop*/}}; - auto props = rawProps ? celix::Properties::wrap(rawProps) : nullptr; + auto props = rawProps ? std::make_shared(celix::Properties::wrap(rawProps)) : nullptr; dep->setService = std::make_pair(std::move(svc), std::move(props)); dep->setFpUsingSharedPtr(dep->setService.first, dep->setService.second); dep->waitForExpired(replacedSvc, svcId, "service pointer"); @@ -556,7 +532,7 @@ void ServiceDependency::setupCallbacks() { rc = dep->invokeCallback(dep->addFp, rawProps, rawSvc); } if (dep->addFpUsingSharedPtr) { - auto props = celix::Properties::wrap(rawProps); + auto props = std::make_shared(celix::Properties::wrap(rawProps)); auto svc = std::shared_ptr{static_cast(rawSvc), [](I*){/*nop*/}}; auto svcId = props->getAsLong(celix::SERVICE_ID, -1); dep->addFpUsingSharedPtr(svc, props); diff --git a/libs/framework/src/celix_launcher.c b/libs/framework/src/celix_launcher.c index ca0b1d1b3..532e2c20f 100644 --- a/libs/framework/src/celix_launcher.c +++ b/libs/framework/src/celix_launcher.c @@ -193,17 +193,15 @@ static void celixLauncher_printUsage(char* progName) { } static void celixLauncher_printProperties(celix_properties_t *embeddedProps, const char *configFile) { - const char *key = NULL; celix_properties_t *keys = celix_properties_create(); //only to store the keys printf("Embedded properties:\n"); if (embeddedProps == NULL || celix_properties_size(embeddedProps) == 0) { printf("|- Empty!\n"); } else { - CELIX_PROPERTIES_FOR_EACH(embeddedProps, key) { - const char *val = celix_properties_get(embeddedProps, key, "!Error!"); - printf("|- %s=%s\n", key, val); - celix_properties_set(keys, key, NULL); + CELIX_PROPERTIES_ITERATE(embeddedProps, visit) { + printf("|- %s=%s\n", visit.key, visit.entry.value); + celix_properties_set(keys, visit.key, NULL); } } printf("\n"); @@ -216,11 +214,10 @@ static void celixLauncher_printProperties(celix_properties_t *embeddedProps, con if (runtimeProps == NULL || celix_properties_size(runtimeProps) == 0) { printf("|- Empty!\n"); } else { - CELIX_PROPERTIES_FOR_EACH(runtimeProps, key) { - const char *val = celix_properties_get(runtimeProps, key, "!Error!"); - printf("|- %s=%s\n", key, val); - celix_properties_set(keys, key, NULL); - } + CELIX_PROPERTIES_ITERATE(runtimeProps, visit) { + printf("|- %s=%s\n", visit.key, visit.entry.value); + celix_properties_set(keys, visit.key, NULL); + } } printf("\n"); @@ -229,13 +226,13 @@ static void celixLauncher_printProperties(celix_properties_t *embeddedProps, con if (celix_properties_size(keys) == 0) { printf("|- Empty!\n"); } else { - CELIX_PROPERTIES_FOR_EACH(keys, key) { - const char *valEm = celix_properties_get(embeddedProps, key, NULL); - const char *valRt = celix_properties_get(runtimeProps, key, NULL); - const char *envVal = getenv(key); + CELIX_PROPERTIES_ITERATE(keys, visit) { + const char *valEm = celix_properties_get(embeddedProps, visit.key, NULL); + const char *valRt = celix_properties_get(runtimeProps, visit.key, NULL); + const char *envVal = getenv(visit.key); const char *val = envVal != NULL ? envVal : valRt != NULL ? valRt : valEm; const char *source = envVal != NULL ? "environment" : valRt != NULL ? "runtime" : "embedded"; - printf("|- %s=%s (source %s)\n", key, val, source); + printf("|- %s=%s (source %s)\n", visit.key, val, source); } } printf("\n"); @@ -279,9 +276,8 @@ static int celixLauncher_createBundleCache(celix_properties_t* embeddedPropertie static void celixLauncher_combineProperties(celix_properties_t *original, const celix_properties_t *append) { if (original != NULL && append != NULL) { - const char *key = NULL; - CELIX_PROPERTIES_FOR_EACH(append, key) { - celix_properties_set(original, key, celix_properties_get(append, key, NULL)); + CELIX_PROPERTIES_ITERATE(append, visit) { + celix_properties_setEntry(original, visit.key, &visit.entry); } } } diff --git a/libs/framework/src/manifest.c b/libs/framework/src/manifest.c index 4f0884e90..1ba4f9abf 100644 --- a/libs/framework/src/manifest.c +++ b/libs/framework/src/manifest.c @@ -72,9 +72,8 @@ manifest_pt manifest_clone(manifest_pt manifest) { celix_auto(manifest_pt) clone = NULL; status = manifest_create(&clone); if (status == CELIX_SUCCESS) { - const char* key = NULL; - CELIX_PROPERTIES_FOR_EACH(manifest->mainAttributes, key) { - celix_properties_set(clone->mainAttributes, key, celix_properties_get(manifest->mainAttributes, key, NULL)); + CELIX_PROPERTIES_ITERATE(manifest->mainAttributes, visit) { + celix_properties_set(clone->mainAttributes, visit.key, visit.entry.value); } hash_map_iterator_t iter = hashMapIterator_construct(manifest->attributes); while (hashMapIterator_hasNext(&iter)) { diff --git a/libs/rcm/src/celix_capability.c b/libs/rcm/src/celix_capability.c index 93aeaf5b2..35be9a717 100644 --- a/libs/rcm/src/celix_capability.c +++ b/libs/rcm/src/celix_capability.c @@ -83,11 +83,9 @@ bool celix_capability_equals(const celix_capability_t* cap1, const celix_capabil //compare attributes bool equals = true; - const char* visit; - CELIX_PROPERTIES_FOR_EACH(cap1->attributes, visit) { - const char* value1 = celix_properties_get(cap1->attributes, visit, NULL); - const char* value2 = celix_properties_get(cap2->attributes, visit, NULL); - if (!celix_utils_stringEquals(value1, value2)) { + CELIX_PROPERTIES_ITERATE(cap1->attributes, visit) { + const char* value2 = celix_properties_get(cap2->attributes, visit.key, NULL); + if (!celix_utils_stringEquals(visit.entry.value, value2)) { equals = false; break; } @@ -95,10 +93,9 @@ bool celix_capability_equals(const celix_capability_t* cap1, const celix_capabil if (!equals) { return false; } - CELIX_PROPERTIES_FOR_EACH(cap1->directives, visit) { - const char* value1 = celix_properties_get(cap1->directives, visit, NULL); - const char* value2 = celix_properties_get(cap2->directives, visit, NULL); - if (!celix_utils_stringEquals(value1, value2)) { + CELIX_PROPERTIES_ITERATE(cap1->directives, visit) { + const char* value2 = celix_properties_get(cap2->directives, visit.key, NULL); + if (!celix_utils_stringEquals(visit.entry.value, value2)) { equals = false; break; } @@ -108,17 +105,13 @@ bool celix_capability_equals(const celix_capability_t* cap1, const celix_capabil unsigned int celix_capability_hashCode(const celix_capability_t* cap) { unsigned int hash = celix_utils_stringHash(cap->ns); - const char* visit; - - CELIX_PROPERTIES_FOR_EACH(cap->attributes, visit) { - const char* value = celix_properties_get(cap->attributes, visit, NULL); - hash += celix_utils_stringHash(visit); - hash += celix_utils_stringHash(value); + CELIX_PROPERTIES_ITERATE(cap->attributes, visit) { + hash += celix_utils_stringHash(visit.key); + hash += celix_utils_stringHash(visit.entry.value); } - CELIX_PROPERTIES_FOR_EACH(cap->directives, visit) { - const char* value = celix_properties_get(cap->directives, visit, NULL); - hash += celix_utils_stringHash(visit); - hash += celix_utils_stringHash(value); + CELIX_PROPERTIES_ITERATE(cap->directives, visit) { + hash += celix_utils_stringHash(visit.key); + hash += celix_utils_stringHash(visit.entry.value); } return hash; } @@ -152,10 +145,8 @@ void celix_capability_addAttribute(celix_capability_t* cap, const char* key, con } void celix_capability_addAttributes(celix_capability_t* cap, const celix_properties_t* attributes) { - const char* visit; - CELIX_PROPERTIES_FOR_EACH(attributes, visit) { - const char* value = celix_properties_get(attributes, visit, NULL); - celix_properties_set(cap->attributes, visit, value); + CELIX_PROPERTIES_ITERATE(attributes, visit) { + celix_properties_set(cap->attributes, visit.key, visit.entry.value); } } @@ -164,9 +155,7 @@ void celix_capability_addDirective(celix_capability_t* cap, const char* key, con } void celix_capability_addDirectives(celix_capability_t* cap, const celix_properties_t* directives) { - const char* visit; - CELIX_PROPERTIES_FOR_EACH(directives, visit) { - const char* value = celix_properties_get(directives, visit, NULL); - celix_properties_set(cap->directives, visit, value); + CELIX_PROPERTIES_ITERATE(directives, visit) { + celix_properties_set(cap->directives, visit.key, visit.entry.value); } } diff --git a/libs/rcm/src/celix_requirement.c b/libs/rcm/src/celix_requirement.c index 48f3dd452..a6480ca7c 100644 --- a/libs/rcm/src/celix_requirement.c +++ b/libs/rcm/src/celix_requirement.c @@ -89,45 +89,33 @@ bool celix_requirement_equals(const celix_requirement_t* req1, const celix_requi } //compare attributes - bool equals = true; - const char* visit; - CELIX_PROPERTIES_FOR_EACH(req1->attributes, visit) { - const char* val1 = celix_properties_get(req1->attributes, visit, NULL); - const char* val2 = celix_properties_get(req2->attributes, visit, NULL); - if (!celix_utils_stringEquals(val1, val2)) { - equals = false; - break; + CELIX_PROPERTIES_ITERATE(req1->attributes, visit) { + const char* val2 = celix_properties_get(req2->attributes, visit.key, NULL); + if (!celix_utils_stringEquals(visit.entry.value, val2)) { + return false; } } - if (!equals) { - return false; - } //compare directives - CELIX_PROPERTIES_FOR_EACH(req1->directives, visit) { - const char* val1 = celix_properties_get(req1->directives, visit, NULL); - const char* val2 = celix_properties_get(req2->directives, visit, NULL); - if (!celix_utils_stringEquals(val1, val2)) { - equals = false; - break; + CELIX_PROPERTIES_ITERATE(req1->directives, visit) { + const char* val2 = celix_properties_get(req2->directives, visit.key, NULL); + if (!celix_utils_stringEquals(visit.entry.value, val2)) { + return false; } } - return equals; + + return true; } unsigned int celix_requirement_hashCode(const celix_requirement_t* req) { unsigned int hash = celix_utils_stringHash(req->ns); - const char* visit; - - CELIX_PROPERTIES_FOR_EACH(req->attributes, visit) { - const char* val = celix_properties_get(req->attributes, visit, NULL); - hash += celix_utils_stringHash(visit); - hash += celix_utils_stringHash(val); + CELIX_PROPERTIES_ITERATE(req->attributes, visit) { + hash += celix_utils_stringHash(visit.key); + hash += celix_utils_stringHash(visit.entry.value); } - CELIX_PROPERTIES_FOR_EACH(req->directives, visit) { - const char* val = celix_properties_get(req->directives, visit, NULL); - hash += celix_utils_stringHash(visit); - hash += celix_utils_stringHash(val); + CELIX_PROPERTIES_ITERATE(req->directives, visit) { + hash += celix_utils_stringHash(visit.key); + hash += celix_utils_stringHash(visit.entry.value); } return hash; } @@ -169,17 +157,13 @@ void celix_requirement_addAttribute(celix_requirement_t* req, const char* key, c } void celix_requirement_addDirectives(celix_requirement_t* req, const celix_properties_t* directives) { - const char* visit; - CELIX_PROPERTIES_FOR_EACH(directives, visit) { - const char* val = celix_properties_get(directives, visit, NULL); - celix_requirement_addDirective(req, visit, val); + CELIX_PROPERTIES_ITERATE(directives, visit) { + celix_requirement_addDirective(req, visit.key, visit.entry.value); } } void celix_requirement_addAttributes(celix_requirement_t* req, const celix_properties_t* attributes) { - const char* visit; - CELIX_PROPERTIES_FOR_EACH(attributes, visit) { - const char* val = celix_properties_get(attributes, visit, NULL); - celix_requirement_addAttribute(req, visit, val); + CELIX_PROPERTIES_ITERATE(attributes, visit) { + celix_requirement_addAttribute(req, visit.key, visit.entry.value); } } diff --git a/libs/utils/gtest/src/CxxPropertiesTestSuite.cc b/libs/utils/gtest/src/CxxPropertiesTestSuite.cc index 7d4f35323..106040866 100644 --- a/libs/utils/gtest/src/CxxPropertiesTestSuite.cc +++ b/libs/utils/gtest/src/CxxPropertiesTestSuite.cc @@ -104,8 +104,23 @@ TEST_F(CxxPropertiesTestSuite, WrapTest) { EXPECT_EQ(1, celix_properties_size(props)); { auto cxxProps = celix::Properties::wrap(props); - EXPECT_EQ(1, cxxProps->size()); - EXPECT_EQ(props, cxxProps->getCProperties()); + EXPECT_EQ(1, cxxProps.size()); + EXPECT_EQ(props, cxxProps.getCProperties()); + } //NOTE cxxProps out of scope, but will not destroy celix_properties + EXPECT_EQ(1, celix_properties_size(props)); + + celix_properties_destroy(props); +} + +TEST_F(CxxPropertiesTestSuite, CopyCPropsTest) { + auto *props = celix_properties_create(); + celix_properties_set(props, "test", "test"); + + EXPECT_EQ(1, celix_properties_size(props)); + { + auto cxxProps = celix::Properties::copy(props); + EXPECT_EQ(1, cxxProps.size()); + EXPECT_NE(props, cxxProps.getCProperties()); } //NOTE cxxProps out of scope, but will not destroy celix_properties EXPECT_EQ(1, celix_properties_size(props)); diff --git a/libs/utils/gtest/src/PropertiesTestSuite.cc b/libs/utils/gtest/src/PropertiesTestSuite.cc index 40a36f59e..c03dcc383 100644 --- a/libs/utils/gtest/src/PropertiesTestSuite.cc +++ b/libs/utils/gtest/src/PropertiesTestSuite.cc @@ -316,9 +316,8 @@ TEST_F(PropertiesTestSuite, SizeAndIteratorTest) { EXPECT_EQ(4, celix_properties_size(props)); int count = 0; - const char *key; - CELIX_PROPERTIES_FOR_EACH(props, key) { - EXPECT_NE(key, nullptr); + CELIX_PROPERTIES_ITERATE(props, entry) { + EXPECT_NE(entry.key, nullptr); count++; } EXPECT_EQ(4, count); @@ -399,26 +398,6 @@ TEST_F(PropertiesTestSuite, GetEntryTest) { celix_properties_destroy(props); } -TEST_F(PropertiesTestSuite, IteratorNextKeyTest) { - auto* props = celix_properties_create(); - celix_properties_set(props, "key1", "value1"); - celix_properties_set(props, "key2", "value2"); - celix_properties_set(props, "key3", "value3"); - auto iter = celix_propertiesIterator_construct(props); - const char* key; - int count = 0; - while (celix_propertiesIterator_hasNext(&iter)) { - key = celix_propertiesIterator_nextKey(&iter); - EXPECT_NE(strstr(key, "key"), nullptr); - count++; - } - EXPECT_EQ(count, 3); - key = celix_propertiesIterator_nextKey(&iter); - EXPECT_EQ(nullptr, key) << "got key: " << key; - - celix_properties_destroy(props); -} - TEST_F(PropertiesTestSuite, IteratorNextTest) { auto* props = celix_properties_create(); celix_properties_set(props, "key1", "value1"); @@ -559,6 +538,32 @@ TEST_F(PropertiesTestSuite, SetWithCopyTest) { celix_properties_destroy(props); } +TEST_F(PropertiesTestSuite, SetEntryTest) { + auto* props1 = celix_properties_create(); + auto* props2 = celix_properties_create(); + celix_properties_set(props1, "key1", "value1"); + celix_properties_setLong(props1, "key2", 123); + celix_properties_setBool(props1, "key3", true); + celix_properties_setDouble(props1, "key4", 3.14); + auto* version = celix_version_create(1, 2, 3, nullptr); + celix_properties_setVersion(props1, "key5", version); + celix_version_destroy(version); + + CELIX_PROPERTIES_ITERATE(props1, visit) { + celix_properties_setEntry(props2, visit.key, &visit.entry); + } + + EXPECT_EQ(5, celix_properties_size(props2)); + EXPECT_STREQ("value1", celix_properties_get(props2, "key1", nullptr)); + EXPECT_EQ(123, celix_properties_getAsLong(props2, "key2", -1L)); + EXPECT_EQ(true, celix_properties_getAsBool(props2, "key3", false)); + EXPECT_EQ(3.14, celix_properties_getAsDouble(props2, "key4", -1.0)); + EXPECT_EQ(CELIX_PROPERTIES_VALUE_TYPE_VERSION, celix_properties_getType(props2, "key5")); + + celix_properties_destroy(props1); + celix_properties_destroy(props2); +} + TEST_F(PropertiesTestSuite, DeprecatedApiTest) { //Check if the deprecated api can still be used auto* props = properties_create(); diff --git a/libs/utils/include/celix/Properties.h b/libs/utils/include/celix/Properties.h index e451ddc1d..6e7a2c312 100644 --- a/libs/utils/include/celix/Properties.h +++ b/libs/utils/include/celix/Properties.h @@ -242,9 +242,17 @@ namespace celix { * @brief Wrap C properties and returns it as const in a shared_ptr, * but does not take ownership -> dtor will not destroy C properties. */ - static std::shared_ptr wrap(const celix_properties_t* wrapProps) { + static const Properties wrap(const celix_properties_t* wrapProps) { auto* cp = const_cast(wrapProps); - return std::shared_ptr{new Properties{cp, false}}; + return Properties{cp, false}; + } + + /** + * @brief Wrap C properties and returns it as const in a shared_ptr, + * but does not take ownership -> dtor will not destroy C properties. + */ + static const Properties wrap(celix_properties_t* wrapProps) { + return Properties{wrapProps, false}; } /** @@ -254,6 +262,13 @@ namespace celix { return Properties{wrapProps, true}; } + /** + * @brief Copy C properties and take ownership -> dtor will destroy C properties. + */ + static Properties copy(const celix_properties_t* copyProps) { + return Properties{celix_properties_copy(copyProps), true}; + } + /** * Get the C properties object. * diff --git a/libs/utils/include/celix_properties.h b/libs/utils/include/celix_properties.h index c839473ac..bf9ff2484 100644 --- a/libs/utils/include/celix_properties.h +++ b/libs/utils/include/celix_properties.h @@ -70,7 +70,7 @@ typedef enum celix_properties_value_type { } celix_properties_value_type_e; /** - * @brief A structure representing a single entry in a property set. + * @brief A structure representing a single value entry in a property set. */ typedef struct celix_properties_entry { const char* value; /**< The string value or string representation of a non-string @@ -221,6 +221,15 @@ CELIX_UTILS_EXPORT void celix_properties_set(celix_properties_t* properties, con */ CELIX_UTILS_EXPORT void celix_properties_setWithoutCopy(celix_properties_t* properties, char* key, char *value); +/** + * @brief Set the value of a property based on the provided property entry, maintaining underlying type. + * @param[in] properties The property set to modify. + * @param[in] key The key of the property to set. + * @param[in] entry The entry to set the property to. The entry will be copied, so it can be freed after calling + * this function. + */ +CELIX_UTILS_EXPORT void celix_properties_setEntry(celix_properties_t* properties, const char* key, const celix_properties_entry_t* entry); + /** * @brief Unset a property, removing it from the property set. * @@ -442,75 +451,6 @@ CELIX_UTILS_EXPORT bool celix_propertiesIterator_equals(const celix_properties_i for (celix_properties_iterator_t iterName = celix_properties_begin((props)); \ !celix_propertiesIterator_isEnd(&(iterName)); celix_propertiesIterator_next(&(iterName))) - -/**** Deprecated API *************************************************************************************************/ - -/** - * @brief Constructs a new properties iterator. - * @deprecated This function is deprecated, use celix_properties_begin, celix_propertiesIterator_next and celix_propertiesIterator_isEnd instead. - * - * Note: The iterator is initialized to be before the first entry. To advance to the first entry, - * call `celix_propertiesIterator_nextEntry`. - * - * @param[in] properties The properties object to iterate over. - * @return The newly constructed iterator. - */ -CELIX_UTILS_DEPRECATED_EXPORT celix_properties_iterator_t celix_propertiesIterator_construct(const celix_properties_t* properties); - -/** - * @brief Determines whether the iterator has more entries. - * @deprecated This function is deprecated, use celix_properties_begin, celix_propertiesIterator_next and celix_propertiesIterator_isEnd instead. - * - * @param[in] iter The iterator. - * @return true if the iterator has more entries, false otherwise. - */ -CELIX_UTILS_DEPRECATED_EXPORT bool celix_propertiesIterator_hasNext(celix_properties_iterator_t *iter); - -/** - * @brief Advances the iterator to the next entry and returns the key for the current entry. - * @deprecated This function is deprecated, use celix_properties_begin, celix_propertiesIterator_next and celix_propertiesIterator_isEnd instead. - * - * If the iterator has no more entries, this function returns NULL. - * - * @param[in, out] iter The iterator. - * @return The key for the current entry, or NULL if the iterator has no more entries. - */ -CELIX_UTILS_DEPRECATED_EXPORT const char* celix_propertiesIterator_nextKey(celix_properties_iterator_t* iter); - -/** - * @brief Macro for iterating over the properties in a property set. - * @deprecated This macro is deprecated, use CELIX_PROPERTIES_ITERATE instead. - * - * @param[in] properties The property set to iterate over. - * @param[out] key The variable to use for the current key in the loop. - * - * - * Example usage: - * @code{.c} - * celix_properties_t* properties = celix_properties_create(); - * celix_properties_set(properties, "key1", "value1"); - * celix_properties_set(properties, "key2", "value2"); - * celix_properties_set(properties, "key3", "value3"); - * - * const char* key; - * CELIX_PROPERTIES_FOR_EACH(properties, key) { - * printf("%s = %s\n", key, celix_properties_get(properties, key, "")); - * } - * @endcode - * - * Output: - * @code{.c} - * key1 = value1 - * key2 = value2 - * key3 = value3 - * @endcode -*/ -#define CELIX_PROPERTIES_FOR_EACH(props, key) _CELIX_PROPERTIES_FOR_EACH(CELIX_UNIQUE_ID(iter), props, key) - -#define _CELIX_PROPERTIES_FOR_EACH(iter, props, key) \ - for(celix_properties_iterator_t iter = celix_propertiesIterator_construct(props); \ - celix_propertiesIterator_hasNext(&iter), (key) = celix_propertiesIterator_nextKey(&iter);) - #ifdef __cplusplus } #endif diff --git a/libs/utils/src/properties.c b/libs/utils/src/properties.c index 6b208c3ab..7514c210e 100644 --- a/libs/utils/src/properties.c +++ b/libs/utils/src/properties.c @@ -317,6 +317,7 @@ static void celix_properties_createAndSetEntry( } celix_properties_entry_t* entry = celix_properties_createEntry(properties, key, strValue, longValue, doubleValue, boolValue, versionValue); + const char* mapKey = key; if (!celix_stringHashMap_hasKey(properties->map, key)) { //new entry, needs new allocated key; @@ -657,6 +658,28 @@ void celix_properties_setWithoutCopy(celix_properties_t *properties, char *key, } } +void celix_properties_setEntry(celix_properties_t* properties, const char* key, const celix_properties_entry_t* entry) { + if (properties != NULL && key != NULL && entry != NULL) { + switch (entry->valueType) { + case CELIX_PROPERTIES_VALUE_TYPE_LONG: + celix_properties_setLong(properties, key, entry->typed.longValue); + break; + case CELIX_PROPERTIES_VALUE_TYPE_DOUBLE: + celix_properties_setDouble(properties, key, entry->typed.doubleValue); + break; + case CELIX_PROPERTIES_VALUE_TYPE_BOOL: + celix_properties_setBool(properties, key, entry->typed.boolValue); + break; + case CELIX_PROPERTIES_VALUE_TYPE_VERSION: + celix_properties_setVersion(properties, key, entry->typed.versionValue); + break; + default: //STRING + celix_properties_set(properties, key, entry->value); + break; + } + } +} + void celix_properties_unset(celix_properties_t *properties, const char *key) { if (properties != NULL) { celix_stringHashMap_remove(properties->map, key); @@ -770,49 +793,6 @@ typedef struct { const celix_properties_t* props; } celix_properties_iterator_internal_t; -celix_properties_iterator_t celix_propertiesIterator_construct(const celix_properties_t *properties) { - celix_properties_iterator_internal_t internalIter; - internalIter.mapIter = celix_stringHashMap_begin(properties->map); - internalIter.props = properties; - - celix_properties_iterator_t iter; - iter.index = 0; - iter.key = NULL; - memset(&iter.entry, 0, sizeof(iter.entry)); - - CELIX_BUILD_ASSERT(sizeof(celix_properties_iterator_internal_t) <= sizeof(iter._data)); - memset(&iter._data, 0, sizeof(iter._data)); - memcpy(iter._data, &internalIter, sizeof(internalIter)); - return iter; -} - -bool celix_propertiesIterator_hasNext(celix_properties_iterator_t *iter) { - celix_properties_iterator_internal_t internalIter; - memcpy(&internalIter, iter->_data, sizeof(internalIter)); - return !celix_stringHashMapIterator_isEnd(&internalIter.mapIter); -} - -const char* celix_propertiesIterator_nextKey(celix_properties_iterator_t *iter) { - celix_properties_iterator_internal_t internalIter; - memcpy(&internalIter, iter->_data, sizeof(internalIter)); - - //note assigning key first and then move the next, because celix string hash map iter start at the beginning - const char* key = internalIter.mapIter.key; - iter->index = (int)internalIter.mapIter.index; - celix_properties_entry_t* entry = internalIter.mapIter.value.ptrValue; - if (entry != NULL) { - iter->key = internalIter.mapIter.key; - memcpy(&iter->entry, entry, sizeof(iter->entry)); - } else { - iter->key = NULL; - memset(&iter->entry, 0, sizeof(iter->entry)); - } - celix_stringHashMapIterator_next(&internalIter.mapIter); - - memcpy(iter->_data, &internalIter, sizeof(internalIter)); - return key; -} - celix_properties_iterator_t celix_properties_begin(const celix_properties_t* properties) { CELIX_BUILD_ASSERT(sizeof(celix_properties_iterator_internal_t) <= sizeof(celix_properties_iterator_t)); celix_properties_iterator_internal_t internalIter;