diff --git a/libs/client-sdk/include/launchdarkly/client_side/bindings/c/sdk.h b/libs/client-sdk/include/launchdarkly/client_side/bindings/c/sdk.h index c9291d5f9..c80ee2e72 100644 --- a/libs/client-sdk/include/launchdarkly/client_side/bindings/c/sdk.h +++ b/libs/client-sdk/include/launchdarkly/client_side/bindings/c/sdk.h @@ -379,6 +379,30 @@ LDClientSDK_JsonVariationDetail(LDClientSDK sdk, LDValue default_value, LDEvalDetail* out_detail); +/** + * Returns a map from feature flag keys to feature flag values for the current + * context. + * + * In the example, all flags of type boolean are printed. + * @code + * LDValue all_flags = LDClientSDK_AllFlags(sdk); + * LDValue_ObjectIter it; + * for (it = LDValue_CreateObjectIter(all_flags); + * !LDValue_ObjectIter_End(it); LDValue_ObjectIter_Next(it)) { char + * const* flag_key = LDValue_ObjectIter_Key(it); LDValue flag_val_ref = + * LDValue_ObjectIter_Value(it); + * + * if (LDValue_Type(flag_val_ref) == LDValueType_Bool) { + * printf("%s: %d\n", flag_key, LDValue_GetBool(flag_val_ref)); + * } + * } + * @endcode + * @param sdk SDK. Must not be NULL. + * @return Value of type Object. + */ +LD_EXPORT(LDValue) +LDClientSDK_AllFlags(LDClientSDK sdk); + /** * Frees the SDK's resources, shutting down any connections. May block. * @param sdk SDK. @@ -548,7 +572,7 @@ enum LDDataSourceStatus_ErrorKind { * Get an enumerated value representing the overall current state of the data * source. */ -LD_EXPORT(LDDataSourceStatus_State) +LD_EXPORT(enum LDDataSourceStatus_State) LDDataSourceStatus_GetState(LDDataSourceStatus status); /** @@ -593,7 +617,7 @@ LD_EXPORT(time_t) LDDataSourceStatus_StateSince(LDDataSourceStatus status); /** * Get an enumerated value representing the general category of the error. */ -LD_EXPORT(LDDataSourceStatus_ErrorKind) +LD_EXPORT(enum LDDataSourceStatus_ErrorKind) LDDataSourceStatus_ErrorInfo_GetKind(LDDataSourceStatus_ErrorInfo info); /** @@ -660,7 +684,7 @@ struct LDDataSourceStatusListener { * @param listener Listener to initialize. */ LD_EXPORT(void) -LDDataSourceStatusListener_Init(LDDataSourceStatusListener listener); +LDDataSourceStatusListener_Init(struct LDDataSourceStatusListener listener); /** * Listen for changes to the data source status. diff --git a/libs/client-sdk/src/bindings/c/sdk.cpp b/libs/client-sdk/src/bindings/c/sdk.cpp index e5bc2d6de..ec68b396a 100644 --- a/libs/client-sdk/src/bindings/c/sdk.cpp +++ b/libs/client-sdk/src/bindings/c/sdk.cpp @@ -303,6 +303,21 @@ LDClientSDK_JsonVariationDetail(LDClientSDK sdk, }))); } +LD_EXPORT(LDValue) +LDClientSDK_AllFlags(LDClientSDK sdk) { + LD_ASSERT_NOT_NULL(sdk); + + std::unordered_map all_flags_unordered = + TO_SDK(sdk)->AllFlags(); + + std::map all_flags_ordered{all_flags_unordered.begin(), + all_flags_unordered.end()}; + + Value* val = new Value(Value::Object{std::move(all_flags_ordered)}); + + return reinterpret_cast(val); +} + LD_EXPORT(void) LDClientSDK_Free(LDClientSDK sdk) { delete TO_SDK(sdk); } diff --git a/libs/common/include/launchdarkly/bindings/c/value.h b/libs/common/include/launchdarkly/bindings/c/value.h index dc5d58a75..4d9a29388 100644 --- a/libs/common/include/launchdarkly/bindings/c/value.h +++ b/libs/common/include/launchdarkly/bindings/c/value.h @@ -206,12 +206,14 @@ LD_EXPORT(void) LDValue_ArrayIter_Next(LDValue_ArrayIter iter); LD_EXPORT(bool) LDValue_ArrayIter_End(LDValue_ArrayIter iter); /** - * Get the value for the array-type iterator. + * Get the value for the array-type iterator. The value's lifetime is valid + * only for as long as the iterator. To obtain a copy, call @ref + * LDValue_NewValue. * * @param iter The iterator to get a value for. Must not be NULL. * @return The value. */ -LD_EXPORT(LDValue) LdValue_ArrayIter_Value(LDValue_ArrayIter iter); +LD_EXPORT(LDValue) LDValue_ArrayIter_Value(LDValue_ArrayIter iter); /** * Destroy an array iterator. @@ -247,12 +249,14 @@ LD_EXPORT(void) LDValue_ObjectIter_Next(LDValue_ObjectIter iter); LD_EXPORT(bool) LDValue_ObjectIter_End(LDValue_ObjectIter iter); /** - * Get the value for an object-type iterator. + * Get the value for an object-type iterator. The value's lifetime is valid + * only for as long as the iterator. To obtain a copy, call @ref + * LDValue_NewValue. * * @param iter The iterator to get a value for. Must not be NULL. * @return The value. */ -LD_EXPORT(LDValue) LdValue_ObjectIter_Value(LDValue_ObjectIter iter); +LD_EXPORT(LDValue) LDValue_ObjectIter_Value(LDValue_ObjectIter iter); /** * Get the key for an object-type iterator. @@ -262,7 +266,7 @@ LD_EXPORT(LDValue) LdValue_ObjectIter_Value(LDValue_ObjectIter iter); * @param iter The iterator to get a key for. Must not be NULL. * @return The key. */ -LD_EXPORT(char const*) LdValue_ObjectIter_Key(LDValue_ObjectIter iter); +LD_EXPORT(char const*) LDValue_ObjectIter_Key(LDValue_ObjectIter iter); /** * Destroy an object iterator. diff --git a/libs/common/src/bindings/c/value.cpp b/libs/common/src/bindings/c/value.cpp index dc1bec436..0c6ccb7ea 100644 --- a/libs/common/src/bindings/c/value.cpp +++ b/libs/common/src/bindings/c/value.cpp @@ -119,7 +119,7 @@ LD_EXPORT(bool) LDValue_ArrayIter_End(LDValue_ArrayIter iter) { return val_iter->End(); } -LD_EXPORT(LDValue) LdValue_ArrayIter_Value(LDValue_ArrayIter iter) { +LD_EXPORT(LDValue) LDValue_ArrayIter_Value(LDValue_ArrayIter iter) { LD_ASSERT_NOT_NULL(iter); auto* val_iter = AS_ARR_ITER(iter); @@ -157,14 +157,14 @@ LD_EXPORT(bool) LDValue_ObjectIter_End(LDValue_ObjectIter iter) { return val_iter->End(); } -LD_EXPORT(LDValue) LdValue_ObjectIter_Value(LDValue_ObjectIter iter) { +LD_EXPORT(LDValue) LDValue_ObjectIter_Value(LDValue_ObjectIter iter) { LD_ASSERT_NOT_NULL(iter); auto* val_iter = AS_OBJ_ITER(iter); return AS_LDVALUE(const_cast(&val_iter->iter->second)); } -LD_EXPORT(char const*) LdValue_ObjectIter_Key(LDValue_ObjectIter iter) { +LD_EXPORT(char const*) LDValue_ObjectIter_Key(LDValue_ObjectIter iter) { LD_ASSERT_NOT_NULL(iter); auto* val_iter = AS_OBJ_ITER(iter); diff --git a/libs/common/tests/bindings/value_test.cpp b/libs/common/tests/bindings/value_test.cpp index faf250444..87a130388 100644 --- a/libs/common/tests/bindings/value_test.cpp +++ b/libs/common/tests/bindings/value_test.cpp @@ -80,21 +80,21 @@ TEST(ValueCBindingTests, CanCreateArray) { auto index = 0; while (!LDValue_ArrayIter_End(iter)) { if (index == 0) { - auto* value_at = LdValue_ArrayIter_Value(iter); + auto* value_at = LDValue_ArrayIter_Value(iter); EXPECT_EQ(LDValueType_Null, LDValue_Type(value_at)); } if (index == 1) { - auto* value_at = LdValue_ArrayIter_Value(iter); + auto* value_at = LDValue_ArrayIter_Value(iter); EXPECT_EQ(LDValueType_Bool, LDValue_Type(value_at)); EXPECT_TRUE(LDValue_GetBool(value_at)); } if (index == 2) { - auto* value_at = LdValue_ArrayIter_Value(iter); + auto* value_at = LDValue_ArrayIter_Value(iter); EXPECT_EQ(LDValueType_Number, LDValue_Type(value_at)); EXPECT_EQ(17, LDValue_GetNumber(value_at)); } if (index == 3) { - auto* value_at = LdValue_ArrayIter_Value(iter); + auto* value_at = LDValue_ArrayIter_Value(iter); EXPECT_EQ(LDValueType_String, LDValue_Type(value_at)); EXPECT_EQ(std::string("Potato"), LDValue_GetString(value_at)); } @@ -132,26 +132,26 @@ TEST(ValueCBindingTests, CanCreateObject) { auto index = 0; while (!LDValue_ObjectIter_End(iter)) { - auto const* key_at = LdValue_ObjectIter_Key(iter); + auto const* key_at = LDValue_ObjectIter_Key(iter); if (strcmp(key_at, "null") == 0) { - auto* value_at = LdValue_ObjectIter_Value(iter); + auto* value_at = LDValue_ObjectIter_Value(iter); EXPECT_EQ(LDValueType_Null, LDValue_Type(value_at)); index++; } if (strcmp(key_at, "bool") == 0) { - auto* value_at = LdValue_ObjectIter_Value(iter); + auto* value_at = LDValue_ObjectIter_Value(iter); EXPECT_EQ(LDValueType_Bool, LDValue_Type(value_at)); EXPECT_TRUE(LDValue_GetBool(value_at)); index++; } if (strcmp(key_at, "num") == 0) { - auto* value_at = LdValue_ObjectIter_Value(iter); + auto* value_at = LDValue_ObjectIter_Value(iter); EXPECT_EQ(LDValueType_Number, LDValue_Type(value_at)); EXPECT_EQ(17, LDValue_GetNumber(value_at)); index++; } if (strcmp(key_at, "str") == 0) { - auto* value_at = LdValue_ObjectIter_Value(iter); + auto* value_at = LDValue_ObjectIter_Value(iter); EXPECT_EQ(LDValueType_String, LDValue_Type(value_at)); EXPECT_EQ(std::string("Potato"), LDValue_GetString(value_at)); index++;