Skip to content

Commit 9aa0794

Browse files
authored
feat: add AllFlags C binding (#128)
Introduces an `AllFlags` binding for C. The strategy chosen is to convert the `std::unordered_map` returned by C++ AllFlags into an `LDValue`, because we already have bindings for object iteration. Additionally, once we add serialization, this could be easily dumped to JSON. Minor changes: - Add `enum/struct` prefix to some C enums/structs - Renamed some `Ld` prefixes to `LD`
1 parent 9547f86 commit 9aa0794

File tree

5 files changed

+63
-20
lines changed

5 files changed

+63
-20
lines changed

libs/client-sdk/include/launchdarkly/client_side/bindings/c/sdk.h

Lines changed: 27 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -379,6 +379,30 @@ LDClientSDK_JsonVariationDetail(LDClientSDK sdk,
379379
LDValue default_value,
380380
LDEvalDetail* out_detail);
381381

382+
/**
383+
* Returns a map from feature flag keys to feature flag values for the current
384+
* context.
385+
*
386+
* In the example, all flags of type boolean are printed.
387+
* @code
388+
* LDValue all_flags = LDClientSDK_AllFlags(sdk);
389+
* LDValue_ObjectIter it;
390+
* for (it = LDValue_CreateObjectIter(all_flags);
391+
* !LDValue_ObjectIter_End(it); LDValue_ObjectIter_Next(it)) { char
392+
* const* flag_key = LDValue_ObjectIter_Key(it); LDValue flag_val_ref =
393+
* LDValue_ObjectIter_Value(it);
394+
*
395+
* if (LDValue_Type(flag_val_ref) == LDValueType_Bool) {
396+
* printf("%s: %d\n", flag_key, LDValue_GetBool(flag_val_ref));
397+
* }
398+
* }
399+
* @endcode
400+
* @param sdk SDK. Must not be NULL.
401+
* @return Value of type Object.
402+
*/
403+
LD_EXPORT(LDValue)
404+
LDClientSDK_AllFlags(LDClientSDK sdk);
405+
382406
/**
383407
* Frees the SDK's resources, shutting down any connections. May block.
384408
* @param sdk SDK.
@@ -548,7 +572,7 @@ enum LDDataSourceStatus_ErrorKind {
548572
* Get an enumerated value representing the overall current state of the data
549573
* source.
550574
*/
551-
LD_EXPORT(LDDataSourceStatus_State)
575+
LD_EXPORT(enum LDDataSourceStatus_State)
552576
LDDataSourceStatus_GetState(LDDataSourceStatus status);
553577

554578
/**
@@ -593,7 +617,7 @@ LD_EXPORT(time_t) LDDataSourceStatus_StateSince(LDDataSourceStatus status);
593617
/**
594618
* Get an enumerated value representing the general category of the error.
595619
*/
596-
LD_EXPORT(LDDataSourceStatus_ErrorKind)
620+
LD_EXPORT(enum LDDataSourceStatus_ErrorKind)
597621
LDDataSourceStatus_ErrorInfo_GetKind(LDDataSourceStatus_ErrorInfo info);
598622

599623
/**
@@ -660,7 +684,7 @@ struct LDDataSourceStatusListener {
660684
* @param listener Listener to initialize.
661685
*/
662686
LD_EXPORT(void)
663-
LDDataSourceStatusListener_Init(LDDataSourceStatusListener listener);
687+
LDDataSourceStatusListener_Init(struct LDDataSourceStatusListener listener);
664688

665689
/**
666690
* Listen for changes to the data source status.

libs/client-sdk/src/bindings/c/sdk.cpp

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -303,6 +303,21 @@ LDClientSDK_JsonVariationDetail(LDClientSDK sdk,
303303
})));
304304
}
305305

306+
LD_EXPORT(LDValue)
307+
LDClientSDK_AllFlags(LDClientSDK sdk) {
308+
LD_ASSERT_NOT_NULL(sdk);
309+
310+
std::unordered_map<std::string, Value> all_flags_unordered =
311+
TO_SDK(sdk)->AllFlags();
312+
313+
std::map<std::string, Value> all_flags_ordered{all_flags_unordered.begin(),
314+
all_flags_unordered.end()};
315+
316+
Value* val = new Value(Value::Object{std::move(all_flags_ordered)});
317+
318+
return reinterpret_cast<LDValue>(val);
319+
}
320+
306321
LD_EXPORT(void) LDClientSDK_Free(LDClientSDK sdk) {
307322
delete TO_SDK(sdk);
308323
}

libs/common/include/launchdarkly/bindings/c/value.h

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -206,12 +206,14 @@ LD_EXPORT(void) LDValue_ArrayIter_Next(LDValue_ArrayIter iter);
206206
LD_EXPORT(bool) LDValue_ArrayIter_End(LDValue_ArrayIter iter);
207207

208208
/**
209-
* Get the value for the array-type iterator.
209+
* Get the value for the array-type iterator. The value's lifetime is valid
210+
* only for as long as the iterator. To obtain a copy, call @ref
211+
* LDValue_NewValue.
210212
*
211213
* @param iter The iterator to get a value for. Must not be NULL.
212214
* @return The value.
213215
*/
214-
LD_EXPORT(LDValue) LdValue_ArrayIter_Value(LDValue_ArrayIter iter);
216+
LD_EXPORT(LDValue) LDValue_ArrayIter_Value(LDValue_ArrayIter iter);
215217

216218
/**
217219
* Destroy an array iterator.
@@ -247,12 +249,14 @@ LD_EXPORT(void) LDValue_ObjectIter_Next(LDValue_ObjectIter iter);
247249
LD_EXPORT(bool) LDValue_ObjectIter_End(LDValue_ObjectIter iter);
248250

249251
/**
250-
* Get the value for an object-type iterator.
252+
* Get the value for an object-type iterator. The value's lifetime is valid
253+
* only for as long as the iterator. To obtain a copy, call @ref
254+
* LDValue_NewValue.
251255
*
252256
* @param iter The iterator to get a value for. Must not be NULL.
253257
* @return The value.
254258
*/
255-
LD_EXPORT(LDValue) LdValue_ObjectIter_Value(LDValue_ObjectIter iter);
259+
LD_EXPORT(LDValue) LDValue_ObjectIter_Value(LDValue_ObjectIter iter);
256260

257261
/**
258262
* Get the key for an object-type iterator.
@@ -262,7 +266,7 @@ LD_EXPORT(LDValue) LdValue_ObjectIter_Value(LDValue_ObjectIter iter);
262266
* @param iter The iterator to get a key for. Must not be NULL.
263267
* @return The key.
264268
*/
265-
LD_EXPORT(char const*) LdValue_ObjectIter_Key(LDValue_ObjectIter iter);
269+
LD_EXPORT(char const*) LDValue_ObjectIter_Key(LDValue_ObjectIter iter);
266270

267271
/**
268272
* Destroy an object iterator.

libs/common/src/bindings/c/value.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -119,7 +119,7 @@ LD_EXPORT(bool) LDValue_ArrayIter_End(LDValue_ArrayIter iter) {
119119
return val_iter->End();
120120
}
121121

122-
LD_EXPORT(LDValue) LdValue_ArrayIter_Value(LDValue_ArrayIter iter) {
122+
LD_EXPORT(LDValue) LDValue_ArrayIter_Value(LDValue_ArrayIter iter) {
123123
LD_ASSERT_NOT_NULL(iter);
124124

125125
auto* val_iter = AS_ARR_ITER(iter);
@@ -157,14 +157,14 @@ LD_EXPORT(bool) LDValue_ObjectIter_End(LDValue_ObjectIter iter) {
157157
return val_iter->End();
158158
}
159159

160-
LD_EXPORT(LDValue) LdValue_ObjectIter_Value(LDValue_ObjectIter iter) {
160+
LD_EXPORT(LDValue) LDValue_ObjectIter_Value(LDValue_ObjectIter iter) {
161161
LD_ASSERT_NOT_NULL(iter);
162162

163163
auto* val_iter = AS_OBJ_ITER(iter);
164164
return AS_LDVALUE(const_cast<Value*>(&val_iter->iter->second));
165165
}
166166

167-
LD_EXPORT(char const*) LdValue_ObjectIter_Key(LDValue_ObjectIter iter) {
167+
LD_EXPORT(char const*) LDValue_ObjectIter_Key(LDValue_ObjectIter iter) {
168168
LD_ASSERT_NOT_NULL(iter);
169169

170170
auto* val_iter = AS_OBJ_ITER(iter);

libs/common/tests/bindings/value_test.cpp

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -80,21 +80,21 @@ TEST(ValueCBindingTests, CanCreateArray) {
8080
auto index = 0;
8181
while (!LDValue_ArrayIter_End(iter)) {
8282
if (index == 0) {
83-
auto* value_at = LdValue_ArrayIter_Value(iter);
83+
auto* value_at = LDValue_ArrayIter_Value(iter);
8484
EXPECT_EQ(LDValueType_Null, LDValue_Type(value_at));
8585
}
8686
if (index == 1) {
87-
auto* value_at = LdValue_ArrayIter_Value(iter);
87+
auto* value_at = LDValue_ArrayIter_Value(iter);
8888
EXPECT_EQ(LDValueType_Bool, LDValue_Type(value_at));
8989
EXPECT_TRUE(LDValue_GetBool(value_at));
9090
}
9191
if (index == 2) {
92-
auto* value_at = LdValue_ArrayIter_Value(iter);
92+
auto* value_at = LDValue_ArrayIter_Value(iter);
9393
EXPECT_EQ(LDValueType_Number, LDValue_Type(value_at));
9494
EXPECT_EQ(17, LDValue_GetNumber(value_at));
9595
}
9696
if (index == 3) {
97-
auto* value_at = LdValue_ArrayIter_Value(iter);
97+
auto* value_at = LDValue_ArrayIter_Value(iter);
9898
EXPECT_EQ(LDValueType_String, LDValue_Type(value_at));
9999
EXPECT_EQ(std::string("Potato"), LDValue_GetString(value_at));
100100
}
@@ -132,26 +132,26 @@ TEST(ValueCBindingTests, CanCreateObject) {
132132

133133
auto index = 0;
134134
while (!LDValue_ObjectIter_End(iter)) {
135-
auto const* key_at = LdValue_ObjectIter_Key(iter);
135+
auto const* key_at = LDValue_ObjectIter_Key(iter);
136136
if (strcmp(key_at, "null") == 0) {
137-
auto* value_at = LdValue_ObjectIter_Value(iter);
137+
auto* value_at = LDValue_ObjectIter_Value(iter);
138138
EXPECT_EQ(LDValueType_Null, LDValue_Type(value_at));
139139
index++;
140140
}
141141
if (strcmp(key_at, "bool") == 0) {
142-
auto* value_at = LdValue_ObjectIter_Value(iter);
142+
auto* value_at = LDValue_ObjectIter_Value(iter);
143143
EXPECT_EQ(LDValueType_Bool, LDValue_Type(value_at));
144144
EXPECT_TRUE(LDValue_GetBool(value_at));
145145
index++;
146146
}
147147
if (strcmp(key_at, "num") == 0) {
148-
auto* value_at = LdValue_ObjectIter_Value(iter);
148+
auto* value_at = LDValue_ObjectIter_Value(iter);
149149
EXPECT_EQ(LDValueType_Number, LDValue_Type(value_at));
150150
EXPECT_EQ(17, LDValue_GetNumber(value_at));
151151
index++;
152152
}
153153
if (strcmp(key_at, "str") == 0) {
154-
auto* value_at = LdValue_ObjectIter_Value(iter);
154+
auto* value_at = LDValue_ObjectIter_Value(iter);
155155
EXPECT_EQ(LDValueType_String, LDValue_Type(value_at));
156156
EXPECT_EQ(std::string("Potato"), LDValue_GetString(value_at));
157157
index++;

0 commit comments

Comments
 (0)