C Client API

Reference

ROX C header

#import <rox/client.h>

rox_ prefix functions

All rox_ prefix functions provide your application with its primary interface for feature flags in the {PRODUCT} system. It manages the flag’s repository, handles communications with the server to obtain the latest values, provides experiment settings, and details for configurations. It provides a mechanism through which you can use the feature flags to control your application’s behavior. The repository manages RoxStringBase structures, which holds your application’s feature flags. Those variants will appear in your dashboard once the application is run.

The rox_ prefix functions also allow you to manage custom properties. These can be static settings of type string, boolean, integer, or double. Alternatively, you can use a generator function to provide a custom property that is dependent upon code state.

You can also use the RoxOptions struct to configure some aspects of all function behavior. You can set the custom platform, impression handler, fetch handler and more.

Rox

rox_setup

RoxStateCode rox_setup(const char *api_key, RoxOptions *options)

Configures the Rox object to work with the provided application.

ParameterModifier and TypeDescription

apiKey

const char *

The environment key provided in the dashboard

options

RoxOptions

A RoxOptions instance with the desired configuration for this application

Return value

typedef enum RoxStateCode {
    RoxUninitialized = 0,
    RoxSettingUp = 1,
    RoxInitialized = 2,
    RoxShuttingDown = 3,
    RoxErrorEmptyApiKey = -1,
    RoxErrorInvalidApiKey = -2,
    RoxErrorGenericSetupFailure = -1000
} RoxStateCode

In case of a successful call, rox_setup will return RoxInitialized code. Otherwise the application logs should be analyzed for errors and warnings. If rox_setup returned failure code, it may be called again after fixing all the errors.

rox_shutdown

void rox_shutdown()

Like everything in C, objects need to be released when the application exits.

rox_setup may be called again after rox_shutdown.

Example

// application start
rox_setup("ROLLOUT_API_KEY", NULL);

// application end
rox_shutdown();

Register

Registering feature flags is done by rox_add_flag for boolean flags and rox_add_variant for variants.

rox_add_flag

RoxStringBase *rox_add_flag(const char *name, bool default_value)
ParameterModifier and TypeDescription

name

const char *

The flag name

default_value

bool

The flag default value: true/false

rox_add_string

rox_add_string_with_options

RoxStringBase *rox_add_string(const char *name, const char *default_value)
RoxStringBase *rox_add_string_with_options(const char *name, const char *default_value, RoxList *options)
ParameterModifier and TypeDescription

name

const char *

The variant name

default_value

const char *

The variant default value

options

RoxList *

a list of all possible values for the defined RoxStringBase flag

RoxStringBase *rox_add_int(const char *name, int default_value)
RoxStringBase *rox_add_int_with_options(const char *name, int default_value, RoxList *options)
ParameterModifier and TypeDescription

name

const char *

The variant name

default_value

int

The variant default value

options

RoxList *

a list of all possible values for the defined RoxStringBase flag

RoxStringBase *rox_add_double(const char *name, double default_value)
RoxStringBase *rox_add_double_with_options(const char *name, double default_value, RoxList *options)
ParameterModifier and TypeDescription

name

const char *

The variant name

default_value

double

The variant default value

options

RoxList *

a list of all possible values for the defined RoxStringBase flag

Example

RoxStringBase *videoChat = rox_add_flag("demo.video_chat", false);
RoxStringBase *fontName = rox_add_string("fontName", "Arial");
RoxStringBase *titleColor = rox_add_string_with_options("titleColors", "red", ROX_LIST_COPY_STR("red", "blue", "green"));
RoxStringBase *titleSize = rox_add_int_with_options("titleSize", 14, ROX_INT_LIST(14, 18, 24));
RoxStringBase *priceVarient = rox_add_double_with_options("price", 19.99, ROX_DBL_LIST(19.99, 29.99, 40.5));

Flags and variants registered to the dashboard will have the names demo.video_chat, fontName, titleSize, and titleColors.

If you don’t need a namespace, you don’t have to specify it (like in titleColors example).

Freezing values

typedef enum RoxFreeze {
    RoxFreezeUntilLaunch = 1,
    RoxFreezeUntilForeground = 2,
    RoxFreezeNone = 3
} RoxFreeze;

By default, all flags have their freeze level set to RoxFreezeNone which means to fetch new flag value every time it’s accessed via rox_get_xxx or rox_is_enabled function. This can be altered by invoking the following functions.

rox_add_xxx_with_freeze - add a flag with custom freeze level

RoxStringBase *rox_add_flag_with_freeze(const char *name, bool default_value, RoxFreeze freeze)

RoxStringBase *rox_add_string_with_freeze(const char *name, const char *default_value, RoxFreeze freeze)

RoxStringBase *rox_add_string_with_freeze_and_options(const char *name, const char *default_value, RoxList *options, RoxFreeze freeze)

RoxStringBase *rox_add_int_with_freeze(const char *name, int default_value, RoxFreeze freeze)

RoxStringBase *rox_add_int_with_freeze_and_options(const char *name, int default_value, RoxList *options, RoxFreeze freeze)

RoxStringBase *rox_add_double_with_freeze(const char *name, double default_value, RoxFreeze freeze)

RoxStringBase *rox_add_double_with_freeze_and_options(const char *name, double default_value, RoxList *options, RoxFreeze freeze)
ParameterModifier and TypeDescription

name

const char *

The variant name

default_value

bool/string/int/double

The variant default value

options

RoxList *

a list of all possible values for the defined RoxStringBase flag

freeze

RoxFreeze

freeze level for the defined RoxStringBase flag

rox_freeze_flag - set freeze level for a flag

void rox_freeze_flag(RoxStringBase *flag, RoxFreeze freeze)

Sets the freeze level for the flag, if not set via the rox_add_xxx_with_freeze constructor.

rox_unfreeze_flag - unfreeze single flag value

void rox_unfreeze_flag(RoxStringBase *flag, RoxFreeze freeze)

Unlock the flag value from changes from the last time it was frozen.

rox_unfreeze(_ns) - unfreeze all flag values

void rox_unfreeze()
void rox_unfreeze_ns(const char *ns)

Unfreeze the state of all flags.

If a namespace was specified, this will affect only the flags in given namespace.

Overriding flag values

RoxFlagOverrides *rox_get_overrides()

RoxFlagOverrides is an opaque struct, and it acts as a handle for the flag overriding data.

Flag overrides are used to override a flag values locally, it is only for developers working on a feature in dev mode and shouldn’t be used in production builds.

It is the base API that is used to show the Flag update flow. Currently this SDK doesn’t have a UI support that wraps overrides. The only way to use overrides is via the code.

When you override an existing flag value using the rox_set_override function, the SDK will disregard existing configuration coming from the dashboard and will serialize the override on disk. This value will be loaded and override the flag right after you call rox_setup. To clear the override from the cache you need to call the rox_clear_override or rox_clear_overrides function.

rox_set_override

void rox_set_override(RoxFlagOverrides *overrides, const char *name, const char *value)

Sets an override value on a specific flag.

This function also saves the override value on the local device disk, so it is "remembered" for the next the SDK is loaded to production.

ParameterTypeDescription

name

const char*

The full flag name including the namespace, e.g. default.flagName.

value

const char*

The value of a flag, if this is a boolean flag the value should be "true" or "false".

rox_get_override

const char *rox_get_override(RoxFlagOverrides *overrides, const char *name)

Returns the overridden flag value or NULL, if not overridden yet.

ParameterTypeDescription

name

const char*

The full flag name including the namespace, e.g. default.flagName.

rox_has_override

bool rox_has_override(RoxFlagOverrides *overrides, const char *name)

Checks whether the flag value has been overridden.

ParameterTypeDescription

name

const char*

The full flag name including the namespace, e.g. default.flagName.

rox_clear_override

void rox_clear_override(RoxFlagOverrides *overrides, const char *name)

Clears the overridden flag value.

ParameterTypeDescription

name

const char*

The full flag name including the namespace, e.g. default.flagName.

rox_clear_overrides

void rox_clear_overrides(RoxFlagOverrides *overrides)

Clear all overridden flag values.

rox_peek_current_value

char *rox_peek_current_value(RoxStringBase *variant)

Retrieves the current flag value without freezing it, and without invoking impression.

rox_peek_original_value

char *rox_peek_original_value(RoxStringBase *variant)

Retrieves the original value with no overrides, no freeze, and without invoking impression.

Custom Properties

The role of the Custom Properties is to segment the audience and apply a set of flags for target group defined by these properties.

The Custom Properties can be these types:

  • bool

  • int

  • double

  • semver

  • string

There are simple (direct) custom properties and calculated ones, using RoxContext to be more dynamic.

Simple (direct) custom properties

rox_set_custom_boolean_property

void rox_set_custom_boolean_property(const char *name, bool value)

Sets a custom property representing a boolean value.

ParameterModifier and TypeDescription

name

const char *

The name of the property to create

value

bool

The value for the custom property: true/false

rox_set_custom_string_property

void rox_set_custom_string_property(const char *name, const char *value)

Sets a custom property representing a string value.

ParameterModifier and TypeDescription

name

const char *

The name of the property to create

value

const char *

The value for the custom property

rox_set_custom_double_property

void rox_set_custom_double_property(const char *name, double value)

Sets a custom property representing a double value.

ParameterModifier and TypeDescription

name

const char *

The name of the property to create

value

double

The value for the custom property

rox_set_custom_integer_property

void rox_set_custom_integer_property(const char *name, int value)

Sets a custom property representing an int value.

ParameterModifier and TypeDescription

name

const char *

The name of the property to create

value

int

The value for the custom property

rox_set_custom_semver_property

void rox_set_custom_semver_property(const char *name, const char *value)

Sets a custom property representing a semver value.

ParameterModifier and TypeDescription

name

const char *

The name of the property to create

value

const char *

The value for the custom property

Computed custom properties (using RoxContext)

rox_set_custom_computed_boolean_property

void rox_set_custom_computed_boolean_property(const char *name, void *target, rox_custom_property_value_generator generator)

Sets a computed boolean Custom Property on the Rox client. This is a computable boolean, with a function that generates the value for the property. The generator should be of type rox_custom_property_value_generator.

ParameterModifier and TypeDescription

name

const char *

The name of the property to create

target

void *

any pointer, will be forwarded to the generator

generator

rox_custom_property_value_generator

A rox_custom_property_value_generator type function

rox_set_custom_computed_string_property

void rox_set_custom_computed_string_property(const char *name, void *target, rox_custom_property_value_generator generator)

Sets a computed string Custom Property on the Rox client. This is a computable string, with a function that generates the value for the property. The generator should be a delegate of type rox_custom_property_value_generator.

ParameterModifier and TypeDescription

name

string

The name of the property to create

target

void *

any pointer, will be forwarded to the generator

generator

rox_custom_property_value_generator

A rox_custom_property_value_generator type function

rox_set_custom_computed_integer_property

void rox_set_custom_computed_integer_property(const char *name, void *target, rox_custom_property_value_generator generator)

Sets a computed integer Custom Property on the Rox client. This is a computable int, with a function that generates the value for the property. The generator should be a delegate of type rox_custom_property_value_generator.

ParameterModifier and TypeDescription

name

string

The name of the property to create

target

void *

any pointer, will be forwarded to the generator

generator

rox_custom_property_value_generator

A rox_custom_property_value_generator type function

rox_set_custom_computed_semver_property

void rox_set_custom_computed_semver_property(const char *name, void *target, rox_custom_property_value_generator generator)

Sets a computed semantic-versioned string Custom Property on the Rox client. This is a computable semantically-versioned string, with a function that generates the value for the property. The generator should be a delegate of type rox_custom_property_value_generator.

ParameterModifier and TypeDescription

name

string

The name of the property to create

target

void *

any pointer, will be forwarded to the generator

generator

rox_custom_property_value_generator

A rox_custom_property_value_generator type function

rox_set_custom_computed_double_property

void rox_set_custom_computed_double_property(         const char *name,         void *target,         rox_custom_property_value_generator generator)

Sets a computed double Custom Property on the Rox client. This is a computable double, with a function that generates the value for the property. The generator should be a delegate of type rox_custom_property_value_generator.

ParameterModifier and TypeDescription

name

string

The name of the property to create

target

void *

any pointer, will be forwarded to the generator

generator

rox_custom_property_value_generator

A rox_custom_property_value_generator type function

rox_set_context

void rox_set_context(RoxContext *context)

Sets a global context. This context will be available to all flags' evaluations (in addition to the specific call context).

rox_fetch

void rox_fetch()

Creates a network request for the latest configuration.

RoxOptions

RoxOptions cover configuration options for the Rox client. These include settings like configuration fetch interval, impression handler and more.

Instances of this struct should be created using rox_options_create.

Here is an example of setting up a new RoxOptions struct. This options object sets the version, provides an impression handler, and includes a fetch handler.

void rox_impression_h(
    void *target,
    RoxReportingValue *value,
    RoxExperiment *experiment,
  RoxContext *context) {
    // do something on impression
  }
}

RoxDynamicValue *dynamic_rule_h(const char *propName, void *target, RoxContext *context) {
  // return a value from the context, for ex:
  return rox_context_get(context, propName);
}

void test_configuration_fetched_h(void *target, RoxConfigurationFetchedArgs *args) {
    // do something when new configurations were set
    }
}

int main(int argc, char **argv) {
    RoxOptions *options = rox_options_create();

    rox_options_set_configuration_fetched_handler(options, NULL, &configuration_fetched_h);
    rox_options_set_dev_mode_key(options, DEFAULT_DEV_MODE_KEY);
    rox_options_set_dynamic_properties_rule(options, NULL, &dynamic_rule_h);
    rox_options_set_impression_handler(options, NULL, &rox_impression_h);
    rox_options_set_roxy_url(options, "http://localhost:4444");
    rox_options_set_version(options, "2.1.0");
    rox_options_set_fetch_interval(options, 100);

    rox_setup("ROLLOUT_KEY", options);
  rox_shutdown();
}

rox_options_set_version

void rox_options_set_version(RoxOptions *options, const char *version)

Sets the version of the service running {PRODUCT} SDK. This can be used on the dashboard for targeting filtering.

rox_options_set_fetch_interval

void rox_options_set_fetch_interval(RoxOptions *options, int fetch_interval)

Sets the polling interval for fetching configuration from the {PRODUCT} storage service.

rox_options_set_configuration_fetched_handler

void rox_options_set_configuration_fetched_handler(RoxOptions *options, void *target, rox_configuration_fetched_handler handler)

Sets the configuration event handler to add actions after configurations are fetched.

rox_options_set_impression_handler

void rox_options_set_impression_handler(RoxOptions *options, void *target, rox_impression_handler handler)

Sets the impression event handler to add actions after a flag evaluation.

rox_options_set_dynamic_properties_rule

void rox_options_set_dynamic_properties_rule(RoxOptions *options, void *target, rox_dynamic_properties_rule rule)

DynamicPropertiesRule is a:

RoxDynamicValue *(*rox_dynamic_properties_rule)(const char *prop_name, void *target, RoxContext *context)

The Dynamic Custom Property Generator is called when an explicit Custom Property definition does not exist on the client side.

If you do not set the rox_options_set_dynamic_properties_rule it will activate the default function, which tries to extract the value (by calling the name of the flag from context).

if (context != NULL) {
    return rox_context_get(context, prop_name);
}
return NULL;

rox_options_set_roxy_url

void rox_options_set_roxy_url(RoxOptions *options, const char *roxy_url)

rox_options_set_default_freeze

void rox_options_set_default_freeze(RoxOptions *options, RoxFreeze freeze)

Sets the default freeze level for all flags having no freeze level specified in the constructor function (not created with rox_add_xxx_with_freeze).

RoxStringBase

RoxStringBase is a feature flag struct. It represents a more complex flag type, which includes a list of all possible values and a default value (rox_add_string, rox_add_int, rox_add_double). This list of values will be used when selecting new values for the feature and will be available for override via the dashboard.

rox_is_enabled

bool rox_is_enabled(RoxStringBase *variant)

Returns the feature flag’s current value (or the default if no value was set).

rox_is_enabled_ctx

bool rox_is_enabled_ctx(RoxStringBase *variant, RoxContext *context)

Returns the feature flag current value (or the default if no value was set) considering the given context.

rox_get_xxx

char *rox_get_string(RoxStringBase *variant)
int rox_get_int(RoxStringBase *variant)
double rox_get_double(RoxStringBase *variant)

Returns the variant flag’s current value (or the default if no value was set).

rox_get_xxx_ctx

char *rox_get_string_ctx(RoxStringBase *variant, RoxContext *context)
int rox_get_int_ctx(RoxStringBase *variant, RoxContext *context)
double rox_get_double_ctx(RoxStringBase *variant, RoxContext *context)

Returns the variant current value (or the default if no value was set) considering the given context.

RoxContext

The context struct is used to pass data to the flag or variant evaluation. This struct is used by the registered Custom Properties to evaluate the experiment expression and return the value.

You can create a context using the rox_context_create_empty, sending a dictionary to its Build function.

rox_context_create_empty

RoxContext *rox_context_create_empty()

Creates an empty RoxContext.

rox_context_create_from_map

RoxContext *rox_context_create_from_map(RoxMap *map)

Creates a RoxContext from a RoxMap (see below). Keys are strings. Values are of RoxDynamicValue type.

rox_context_get

RoxDynamicValue *rox_context_get(RoxContext *context, const char *key)

Returns a value in the context (can be used in a set_computed__custom__…​_property handler). See RoxDynamicValue).

rox_context_free

void rox_context_free(RoxContext *context)

Frees the memory of the context after use is done.

Example

// create a generator for a custom property
RoxDynamicValue *get_user_id(void *target, RoxContext *context) {
  // getting the user id from the context used
    return rox_context_get(context, "userId");
}

int main() {
    // set custom property
    rox_set_custom_computed_string_property"id_property", NULL, &get_user_id);

    // creating a flag
    RoxStringBase *specialDiscount = rox_add_flag("billing.isSpecialDiscount", false);

    // creating context
    RoxContext *userContext = rox_context_create_from_map(
    ROX_MAP(ROX_COPY("userId"), rox_dynamic_value_create_int(555)));

    // evaluate a flag, using context
    bool isDiscounted = rox_is_enabled_ctx(specialDiscount, userContext);

  rox_context_free(userContext);
}

Using ConfigurationFetchedHandler

As seen in RoxOptions, rox_options_set_configuration_fetched_handler can be used to set ConfigurationFetchedHandler. This is how the handler looks:

typedef void (*rox_configuration_fetched_handler)(void *target, RoxConfigurationFetchedArgs *args)

The additional definitions used are:

RoxConfigurationFetchedArgs

typedef struct RoxConfigurationFetchedArgs {
    RoxFetchStatus fetcher_status;
    const char *creation_date;
    bool has_changes;
    RoxFetcherError error_details;
} RoxConfigurationFetchedArgs

The struct the configuration fetched handler gets:

RoxFetchStatus

typedef enum RoxFetchStatus {
    AppliedFromEmbedded = 1,
    AppliedFromLocalStorage,
    AppliedFromNetwork,
    ErrorFetchedFailed
} RoxFetchStatus

Enum represents the fetch source.

RoxFetcherError

typedef enum RoxFetcherError {
    NoError = 0,
    CorruptedJson = 1,
    EmptyJson,
    SignatureVerificationError,
    NetworkError,
    MismatchAppKey,
    UnknownError
} RoxFetcherError

In case the fetch failed, an Enum represents the error type.

For an example, see Configuration fetched handler.

Using ImpressionHandler

The impression Handler delegate/function (as seen in RoxOptions rox_options_set_impression_handler) has a couple of useful parameters which can help you decide on further actions. the handle signature is:

typedef void (*rox_impression_handler)(void *target, RoxReportingValue *value, RoxExperiment *experiment, RoxContext *context)

and the relevant additional definitions:

RoxReportingValue

typedef struct RoxReportingValue {const char *name; const char *value; } RoxReportingValue

The Impression flag name and the evaluated value.

RoxExperiment

typedef struct RoxExperiment {char *name; char *identifier; bool archived; RoxSet *labels; char *stickiness_property; } RoxExperiment

The relevant flag’s experiment.

For an example, see Impression handler.

RoxDynamicValue

RoxDynamicValue represents a dynamic value, which wraps a type value. Mostly used when working with RoxContext and custom properties.

rox_dynamic_value_create_int

RoxDynamicValue *rox_dynamic_value_create_int(int value)

Wrapping an int value into a RoxDynamicValue.

rox_dynamic_value_create_double

RoxDynamicValue *rox_dynamic_value_create_double(double value)

Wrapping a double value into a RoxDynamicValue.

rox_dynamic_value_create_double_ptr

RoxDynamicValue *rox_dynamic_value_create_double_ptr(double *value)

Wrapping a double pointer value into a RoxDynamicValue.

rox_dynamic_value_create_boolean

RoxDynamicValue *rox_dynamic_value_create_boolean(bool value)

Wrapping a bool value into a RoxDynamicValue.

rox_dynamic_value_create_string_copy

RoxDynamicValue *rox_dynamic_value_create_string_copy(const char *value)

Creating a RoxDynamicValue by copying the value that has to be freed after use.

rox_dynamic_value_create_string_ptr

RoxDynamicValue *rox_dynamic_value_create_string_ptr(char *value)

Wrapping a string value into a RoxDynamicValue.

String will be freed by calling dynamic_value_free().

rox_dynamic_value_create_list

RoxDynamicValue *rox_dynamic_value_create_list(RoxList *value)

Wrapping a RoxList value into a RoxDynamicValue.

List will be freed by calling dynamic_value_free().

rox_dynamic_value_create_map

RoxDynamicValue *rox_dynamic_value_create_map(RoxMap *value)

Wrapping a RoxMap value into a RoxDynamicValue

Map will be freed by calling dynamic_value_free().

rox_dynamic_value_create_map

RoxDynamicValue *rox_dynamic_value_create_null()

Creating a null value.

rox_dynamic_value_create_copy

RoxDynamicValue *rox_dynamic_value_create_copy(RoxDynamicValue *value)

Creating a copy of a RoxDynamicValue.

rox_dynamic_value_free

RoxDynamicValue *rox_dynamic_value_free(RoxDynamicValue *value)

Frees the RoxDynamicValue.

Should be called after rox_context_get.

rox_dynamic_value_is_int

bool rox_dynamic_value_is_int(RoxDynamicValue *value)

Returns true if a RoxDynamicValue is of type int.

rox_dynamic_value_is_double

bool rox_dynamic_value_is_double(RoxDynamicValue *value)

Returns true if a RoxDynamicValue is of type double.

rox_dynamic_value_is_boolean

bool rox_dynamic_value_is_boolean(RoxDynamicValue *value)

Returns true if a RoxDynamicValue is of type bool.

rox_dynamic_value_is_string

bool rox_dynamic_value_is_string(RoxDynamicValue *value)

Returns true if a RoxDynamicValue is of type string.

rox_dynamic_value_is_list

bool rox_dynamic_value_is_list(RoxDynamicValue *value)

Returns true if a RoxDynamicValue is of type RoxList.

rox_dynamic_value_is_map

bool rox_dynamic_value_is_map(RoxDynamicValue *value)

Returns true if a RoxDynamicValue is of type RoxMap.

rox_dynamic_value_is_undefined

bool rox_dynamic_value_is_undefined(RoxDynamicValue *value)

Returns true if a RoxDynamicValue is undefined.

rox_dynamic_value_is_null

bool rox_dynamic_value_is_null(RoxDynamicValue *value)

Returns true if a RoxDynamicValue is null.

rox_dynamic_value_get_int

int rox_dynamic_value_get_int(RoxDynamicValue *value)

Returns the int value of the RoxDynamicValue.

rox_dynamic_value_get_double

double rox_dynamic_value_get_double(RoxDynamicValue *value)

Returns the double value of the RoxDynamicValue.

rox_dynamic_value_get_boolean

bool rox_dynamic_value_get_boolean(RoxDynamicValue *value)

Returns the bool value of the RoxDynamicValue.

rox_dynamic_value_get_string

char *rox_dynamic_value_get_string(RoxDynamicValue *value)

Returns the string value of the RoxDynamicValue.

rox_dynamic_value_get_list

RoxList *rox_dynamic_value_get_list(RoxDynamicValue *value)

Returns the RoxList value of the RoxDynamicValue.

rox_dynamic_value_get_map

RoxMap *rox_dynamic_value_get_map(RoxDynamicValue *value)

Returns the RoxMap value of the RoxDynamicValue.

DynamicApi

DynamicApi is a way to evaluate flags and variant by name on the fly, without creating it before.

rox_dynamic_api

RoxDynamicApi *rox_dynamic_api()

Create a RoxDynamicApi, the proxy to all dynamic flags and variants evaluation.

rox_dynamic_api_is_enabled

bool rox_dynamic_api_is_enabled(RoxDynamicApi *api, const char *name, bool default_value, RoxContext *context)

Evaluate a flag by its name and context.

If no experiment was set via the dashboard, the default_value will be returned.

rox_dynamic_api_get_xxx(_ctx)

char *rox_dynamic_api_get_string(RoxDynamicApi *api, const char *name, char *default_value)

char *rox_dynamic_api_get_string_ctx(RoxDynamicApi *api, const char *name, char *default_value, RoxList *options, RoxContext *context)

int rox_dynamic_api_get_int(RoxDynamicApi *api, const char *name, int default_value)

int rox_dynamic_api_get_int_ctx(RoxDynamicApi *api, const char *name, int default_value, RoxList *options, RoxContext *context)

double rox_dynamic_api_get_double(RoxDynamicApi *api, const char *name, double default_value)

double rox_dynamic_api_get_double_ctx(RoxDynamicApi *api, const char *name, double default_value, RoxList *options, RoxContext *context)

Evaluate a flag by its name and context.

Options will be sent to the dashboard to allow an easy pick in the experiment. If no experiment was set via the dashboard, the default_value will be returned.

rox_dynamic_api_free

void rox_dynamic_api_free(RoxDynamicApi *api)

Frees the RoxDynamicApi that was created with rox_dynamic_api.

For an example, see Dynamic API.

Logging

Logging helps debug in case something behave unexpectedly.

To set up {PRODUCT} Logging use rox_logging_init.

If no logging was set, the default settings will be used, meaning printing to stdout errors level logs.

rox_logging_init

void rox_logging_init(RoxLoggingConfig *config)

Sets up a logging with RoxLoggingConfig.

RoxLoggingConfig

typedef struct RoxLoggingConfig {RoxLogLevel min_level; void *target; rox_logging_handler handler; bool print_time; } RoxLoggingConfig

Sets up logging configuration.

Setting up a rox_logging_handler will override the default handler that uses the other properties.

Configuration can be created using ROX_LOGGING_CONFIG_INITIALIZER, setting the log_level, and using default for all other properties.

ROX_LOGGING_CONFIG_INITIALIZER

#define ROX_LOGGING_CONFIG_INITIALIZER(log_level) {log_level, NULL, NULL, false}

RoxLogLevel

typedef enum RoxLogLevel {
    RoxLogLevelTrace = 1,
    RoxLogLevelDebug,
    RoxLogLevelWarning,
    RoxLogLevelError,
    RoxLogLevelNone
} RoxLogLevel

rox_logging_handler

typedef void (*rox_logging_handler)(void *target, RoxLogMessage *message)

Sets logging handler to handle the logging messages yourself.

RoxLogMessage

typedef struct RoxLogMessage {
    const char *file;
    int line;
    RoxLogLevel level;
    const char *level_name;
    const char *message;
} RoxLogMessage

For an example, see Turning on verbose logging.

Helpers

Types

RoxList

A list.

RoxSet

A hashset.

RoxMap

A hashtable.

Functions

ROX_LIST

#define ROX_LIST(...) rox_list_create_va(NULL, __VA_ARGS__, NULL)

Create a RoxList.

ROX_EMPTY_LIST

#define ROX_EMPTY_LIST ROX_LIST(NULL)

Create an empty RoxList.

ROX_LIST_COPY_STR

#define ROX_LIST_COPY_STR(...) rox_list_create_str_va(NULL, __VA_ARGS__, NULL)

Create a RoxList from strings, creating a copy for each string.

ROX_INT_LIST

#define ROX_INT_LIST(...) rox_list_create_int_va(NULL, __VA_ARGS__, INT_MIN)

Create a RoxList from integers.

ROX_DBL_LIST

#define ROX_DBL_LIST(...) rox_list_create_double_va(NULL, __VA_ARGS__, DBL_MIN)

Create a RoxList from values of type double.

ROX_SET

#define ROX_SET(...) rox_set_create_va(NULL, __VA_ARGS__, NULL)

Create a RoxSet.

ROX_EMPTY_SET

#define ROX_EMPTY_SET ROX_SET(NULL)

Create an empty RoxSet.

ROX_COPY

#define ROX_COPY(str) mem_copy_str(str)

Create a string copy.

ROX_MAP

#define ROX_MAP(...) rox_map_create_va(NULL, __VA_ARGS__, NULL)

Create a RoxSet.

ROX_EMPTY_MAP ROX_MAP

#define ROX_EMPTY_MAP ROX_MAP(NULL)

Create an empty RoxSet.