UAP Common Extensions 4.0 Help

Properties

The UCX properties parser can be used to parse line-based key/value strings.

Supported Syntax

Key/value pairs must be line-based and separated by a single character delimiter. The parser supports up to three different characters which introduce comments. All characters starting with a comment character up to the end of the line are ignored. Blank lines are also ignored.

An example properties file looks like this:

# Comment line at start of file key1 = value1 key2 = value2 # next is a blank line and will be ignored keys_are_trimmed = and_so_are_values # also a comment key3 = value that \ is continued on the next line

Basic Parsing

The following listing shows the properties-parser API.

#include <cx/properties.h> typedef struct cx_properties_config_s { char delimiter; char comment1; char comment2; char comment3; char continuation; } CxPropertiesConfig; void cxPropertiesInit(CxProperties *prop, CxPropertiesConfig config); void cxPropertiesInitDefault(CxProperties *prop); void cxPropertiesDestroy(CxProperties *prop); void cxPropertiesReset(CxProperties *prop); int cxPropertiesFilln(CxProperties *prop, const char *buf, size_t len); int cxPropertiesFill(CxProperties *prop, AnyStr string); CxPropertiesStatus cxPropertiesNext(CxProperties *prop, cxstring *key, cxstring *value); void cxPropertiesUseStack(CxProperties *prop, char *buf, size_t capacity); CxPropertiesStatus cxPropertiesLoad( const CxAllocator *allocator, AnyStr filename, CxMap *target, CxPropertiesConfig config); CxPropertiesStatus cxPropertiesLoadDefault( const CxAllocator *allocator, AnyStr filename, CxMap *target);

The first step is to initialize a CxProperties structure with a call to cxPropertiesInit() using the desired config. The shorthand cxPropertiesInitDefault() creates a default configuration with the equals sign '=' as delimiter and the hash-symbol '#' as comment symbol (the other two comment symbols remain unused in the default config). The line continuation symbol is set to '\'. Note that leading spaces of a continuing line are ignored.

The actual parsing is an interleaving invocation of the cxPropertiesFill() (or cxPropertiesFilln()) and cxPropertiesNext() functions. The cxPropertiesFill() function is a convenience function that accepts UCX strings and normal zero-terminated C strings and behaves otherwise like cxPropertiesFilln().

Filling the input buffer is cost-free if there is no data already in the input buffer. In that case, the input buffer only stores the pointer to the original data without creating a copy. Calling cxPropertiesNext() will return with CX_PROPERTIES_NO_ERROR (= zero) for each key/value-pair that is successfully parsed and stores the pointers and lengths for both the key and the value into the structures pointed to by the key and value arguments.

When all the data from the input buffer was successfully consumed, cxPropertiesNext() returns CX_PROPERTIES_NO_DATA.

If cxPropertiesNext() returns CX_PROPERTIES_INCOMPLETE_DATA, the input buffer is exhausted, but the last line did not contain a full key/value pair. In that case, you can call cxPropertiesFill() again to add more data and continue with cxPropertiesNext().

Note that adding more data to a non-empty input buffer will lead to an allocation, unless you specified some stack memory with cxPropertiesUseStack(). The stack capacity must be large enough to contain the longest line in your data. If the internal buffer is not large enough to contain a single line, it is extended. If that is not possible for some reason, cxPropertiesNext() fails and returns CX_PROPERTIES_BUFFER_ALLOC_FAILED.

If you want to reuse a CxProperties structure with the same config, you can call cxPropertiesReset(), even if the last operation was a failure. Otherwise, you should always call cxPropertiesDestroy() when you are done with the parser.

All the above operations are combined in the function cxPropertiesLoad(), which opens the file designated by the filename and loads all properties from that file into the specified CxMap. The convenience macro cxPropertiesLoadDefault() uses the default parser configuration for this. The target map must either store pointers of type char* or elements of type cxmutstr. In either case, the specified allocator is used to allocate the memory for the value. If the function encounters an error, all properties that have been added to the map so far stay in the map; there is no rollback.

List of Status Codes

Below is a full list of status codes for cxPropertiesNext() and cxPropertiesLoad().

Status Code

Meaning

CX_PROPERTIES_NO_ERROR

A key/value pair was found and returned.

CX_PROPERTIES_NO_DATA

The input buffer does not contain data.

CX_PROPERTIES_INCOMPLETE_DATA

The input ends unexpectedly. This can happen when the last line does not terminate with a line break, or when the input ends with a parsed key but no value. Use cxPropertiesFill() to add more data before retrying.

CX_PROPERTIES_NULL_INPUT

The input buffer was never initialized. Probably you forgot to call cxPropertiesFill() at least once.

CX_PROPERTIES_INVALID_EMPTY_KEY

Only white-spaces were found on the left hand-side of the delimiter. Keys must not be empty.

CX_PROPERTIES_INVALID_MISSING_DELIMITER

A line contains data, but no delimiter.

CX_PROPERTIES_BUFFER_ALLOC_FAILED

More internal buffer was needed, but could not be allocated.

CX_PROPERTIES_FILE_ERROR

A file operation failed (only for cxPropertiesLoad()).

For cxPropertiesLoad() the status code CX_PROPERTIES_NO_ERROR means that at least one property was loaded into the map, while CX_PROPERTIES_NO_DATA means that the file is syntactically fine but does not contain any properties.

31 December 2025