xchange v0.9
Structured data exchange for C/C++
Loading...
Searching...
No Matches
xstruct.c File Reference

A collection of commonly used functions for generic structured data exchange. More...

Macros

#define __XCHANGE_INTERNAL_API__
 Use internal definitions.
 

Functions

void xClearStruct (XStructure *s)
 
char * xCopyIDToken (const char *id)
 
XFieldxCopyOfField (const XField *f)
 
XStructurexCopyOfStruct (const XStructure *s)
 
int xCountFields (const XStructure *s)
 
XFieldxCreate1DField (const char *name, XType type, int count, const void *values)
 
XFieldxCreateBooleanField (const char *name, boolean value)
 
XFieldxCreateDoubleField (const char *name, double value)
 
XFieldxCreateField (const char *name, XType type, int ndim, const int *sizes, const void *value)
 
XFieldxCreateIntField (const char *name, int value)
 
XFieldxCreateLongField (const char *name, long long value)
 
XFieldxCreateScalarField (const char *name, XType type, const void *value)
 
XFieldxCreateStringField (const char *name, const char *value)
 
XStructurexCreateStruct ()
 
long xDeepCountFields (const XStructure *s)
 
void xDestroyField (XField *f)
 
void xDestroyStruct (XStructure *s)
 
char * xGetAggregateID (const char *table, const char *key)
 
XFieldxGetField (const XStructure *s, const char *id)
 
int xGetFieldCount (const XField *f)
 
XStructurexGetSubstruct (const XStructure *s, const char *id)
 
int xInsertField (XStructure *s, XField *f)
 
boolean xIsFieldValid (const XField *f)
 
char * xLastSeparator (const char *id)
 
int xMatchNextID (const char *token, const char *id)
 
char * xNextIDToken (const char *id)
 
int xReduceAllDims (XStructure *s)
 
int xReduceDims (int *ndim, int *sizes)
 
XFieldxRemoveField (XStructure *s, const char *name)
 
int xReverseFieldOrder (XStructure *s, boolean recursive)
 
XFieldxSetField (XStructure *s, XField *f)
 
XFieldxSetSubstruct (XStructure *s, const char *name, XStructure *substruct)
 
int xSortFields (XStructure *s, int(*cmp)(const XField **f1, const XField **f2), boolean recursive)
 
int xSortFieldsByName (XStructure *s, boolean recursive)
 
int xSplitID (char *id, char **pKey)
 

Detailed Description

A collection of commonly used functions for generic structured data exchange.

Date
Nov 25, 2020
Author
Attila Kovacs

Function Documentation

◆ xClearStruct()

void xClearStruct ( XStructure s)

Destroys the contents of an X structure, leaving the structure empty.

Parameters
sPointer to the structure to be cleared.
See also
smaDestroyStruct()

References XStructure::firstField, XField::next, and xDestroyField().

◆ xCopyIDToken()

char * xCopyIDToken ( const char *  id)

Returns a copy of the next next component in a compound ID. Leading ID separators are ignored.

Parameters
idAggregate X ID.
Returns
Pointer to the start of the next compound ID token, or NULL if there is no more components in the ID.

References x_error(), X_SEP, X_SEP_LENGTH, and xNextIDToken().

◆ xCopyOfField()

XField * xCopyOfField ( const XField f)

Returns a deep copy of the supplied field. The returned copy is a standalone field, unlinked to another to avoid corrupting any structure in which the original field may reside in. Note, that this only works with vanilla xchange structures with native storage fields. For example, SMA-X structures store data in serialized forms, and therefore it needs its own implementation for making deep copies of fields!

Parameters
fPointer to the original field or NULL.
Returns
A fully independent (deep) copy of the argument or NULL if the input field is NULL.
See also
xCopyOfStruct()

References XStructure::firstField, XField::isSerialized, XField::name, XField::next, XField::type, XField::value, x_error(), X_RAW, X_STRING, X_STRUCT, x_trace_null(), xCopyOfStruct(), xDestroyField(), xElementSizeOf(), xGetFieldCount(), and xStringCopyOf().

◆ xCopyOfStruct()

XStructure * xCopyOfStruct ( const XStructure s)

Returns a deep copy of the supplied structure. Note that this only works with vanilla xchange structures with native storage fields. For example, SMA-X structures store data in serialized forms, and therefore it needs its own implementation for making deep copies of structs!

Parameters
sPointer to the original structure or NULL.
Returns
A fully independent (deep) copy of the argument or NULL if the input structure is NULL.
See also
xCopyOfField()

References XStructure::firstField, XField::next, XField::type, XField::value, x_error(), X_STRUCT, x_trace_null(), xCopyOfField(), xCreateStruct(), xDestroyStruct(), and xGetFieldCount().

◆ xCountFields()

int xCountFields ( const XStructure s)

Returns the number of fields contained inside the structure. It is not recursive.

Parameters
sPointer to the structure to investigate
Returns
the number of fields cotnained in the structure (but not counting fields in sub-structures).
See also
xDeepCountFields()

References XStructure::firstField, and XField::next.

◆ xCreate1DField()

XField * xCreate1DField ( const char *  name,
XType  type,
int  count,
const void *  values 
)

Creates a generic field for a 1D array of a given name and native data. The structure will hold a copy of the value that is pointed at.

Parameters
nameField name (it may not contain a separator X_SEP)
typeStorage type, e.g. X_INT.
countNumber of elements in array
valuesPointer to an array of native values.
Returns
A newly created field with the supplied data, or NULL if there was an error.

References x_trace_null(), and xCreateField().

◆ xCreateBooleanField()

XField * xCreateBooleanField ( const char *  name,
boolean  value 
)

Creates a field holding a single boolean value value.

Parameters
nameField name (it may not contain a separator X_SEP)
valueAssociated value
Returns
A newly created field with the supplied data, or NULL if there was an error.

References X_BOOLEAN, x_trace_null(), and xCreateScalarField().

◆ xCreateDoubleField()

XField * xCreateDoubleField ( const char *  name,
double  value 
)

Creates a field holding a single double-precision value value.

Parameters
nameField name (it may not contain a separator X_SEP)
valueAssociated value
Returns
A newly created field with the supplied data, or NULL if there was an error.

References X_DOUBLE, x_trace_null(), and xCreateScalarField().

◆ xCreateField()

XField * xCreateField ( const char *  name,
XType  type,
int  ndim,
const int *  sizes,
const void *  value 
)

Creates a generic field of a given name and type and dimensions using a copy of the specified native data, unless type is X_STRUCT in which case the value is referenced directly inside the field.

Parameters
nameField name (it may not contain a separator X_SEP)
typeStorage type, e.g. X_INT.
ndimNumber of dimensionas (1:20). If ndim < 1, it will be reinterpreted as ndim=1, size[0]=1;
sizesArray of sizes along each dimensions, with at least ndim elements, or NULL with ndim<1.
valuePointer to the native data location in memory, or NULL to leave unassigned for now.
Returns
A newly created field with the copy of the supplied data, or NULL if there was an error.

References XField::name, XField::ndim, XField::sizes, XField::type, XField::value, x_error(), X_MAX_DIMS, X_RAW, X_STRING, X_STRUCT, xDestroyField(), xElementSizeOf(), xGetElementCount(), xLastSeparator(), and xStringCopyOf().

◆ xCreateIntField()

XField * xCreateIntField ( const char *  name,
int  value 
)

Creates a field holding a single ineger value value.

Parameters
nameField name (it may not contain a separator X_SEP)
valueAssociated value
Returns
A newly created field with the supplied data, or NULL if there was an error.
See also
xCreateLongField()

References X_INT, x_trace_null(), and xCreateScalarField().

◆ xCreateLongField()

XField * xCreateLongField ( const char *  name,
long long  value 
)

Creates a field holding a single ineger value value.

Parameters
nameField name (it may not contain a separator X_SEP)
valueAssociated value
Returns
A newly created field with the supplied data, or NULL if there was an error.
See also
xCreateIntField()

References X_LONG, x_trace_null(), and xCreateScalarField().

◆ xCreateScalarField()

XField * xCreateScalarField ( const char *  name,
XType  type,
const void *  value 
)

Creates a generic scalar field of a given name and native value. The structure will hold a copy of the value that is pointed at.

Parameters
nameField name (it may not contain a separator X_SEP)
typeStorage type, e.g. X_INT.
valuePointer to the native data location in memory.
Returns
A newly created field with the supplied data, or NULL if there was an error.

References x_trace_null(), and xCreateField().

◆ xCreateStringField()

XField * xCreateStringField ( const char *  name,
const char *  value 
)

Creates a field holding a single string value.

Parameters
nameField name (it may not contain a separator X_SEP)
valueAssociated value. NULL values will be treated as empty strings.
Returns
A newly created field referencing the supplied string, or NULL if there was an error.

References X_STRING, x_trace_null(), and xCreateScalarField().

◆ xCreateStruct()

XStructure * xCreateStruct ( )

Creates a new empty XStructure.

See also
smaxDestroyStruct()

◆ xDeepCountFields()

long xDeepCountFields ( const XStructure s)

Counts the number of fields in a structure, including the field count for all embedded substructures also recursively.

Parameters
sPointer to a structure
Returns
The total number of fields present in the structure and all its sub-structures.
See also
xCountFields()

References XStructure::firstField, XField::name, XField::next, XField::type, XField::value, x_error(), X_STRUCT, x_trace(), xDeepCountFields(), and xGetFieldCount().

◆ xDestroyField()

void xDestroyField ( XField f)

Destroys an X structure field, freeing up resources used. For

Parameters
fPointer to the field to be destroyed.

References XField::name, XField::type, XField::value, X_STRUCT, xClearStruct(), and xGetFieldCount().

◆ xDestroyStruct()

void xDestroyStruct ( XStructure s)

Destroys an X structure, freeing up resources used by name and value.

Parameters
sPointer to the structure to be destroyed.

References xClearStruct().

◆ xGetAggregateID()

char * xGetAggregateID ( const char *  table,
const char *  key 
)

Returns the aggregated (hierarchical) <table>:<key> ID. The caller is responsible for calling free() on the returned string after use.

Parameters
tableSMA-X hastable name
keyThe lower-level id to concatenate.
Returns
The aggregated ID, or NULL if both arguments were NULL themselves.
See also
xSplitID()

References x_error(), X_SEP, X_SEP_LENGTH, and xStringCopyOf().

◆ xGetField()

XField * xGetField ( const XStructure s,
const char *  id 
)

Return the field by the specified name, or NULL if no such field exists.

Parameters
sStructure from which to retrieve a given field.
idName or aggregate ID of the field to retrieve
Returns
Matching field from the structure or NULL if there is no match or one of the arguments is NULL.
See also
xLookupField()
xSetField()
xGetSubstruct()

References XStructure::firstField, XField::name, XField::next, XField::type, x_error(), X_STRUCT, X_SUCCESS, xGetField(), xMatchNextID(), and xNextIDToken().

◆ xGetFieldCount()

int xGetFieldCount ( const XField f)

Returns the total number of primitive elements in a field.

Parameters
fThe field
Returns
The total number of primitive elements contained in the field.

References XField::ndim, XField::sizes, and xGetElementCount().

◆ xGetSubstruct()

XStructure * xGetSubstruct ( const XStructure s,
const char *  id 
)

Returns a substructure by the specified name, or NULL if no such sub-structure exists.

Parameters
sStructure from which to retrieve a given sub-structure.
idName or aggregate ID of the substructure to retrieve
Returns
Matching sub-structure from the structure or NULL if there is no match or one of the arguments is NULL.
See also
xSetSubstruct()
xGetField()

References XField::type, XField::value, X_STRUCT, and xGetField().

◆ xInsertField()

int xInsertField ( XStructure s,
XField f 
)

(expert) Inserts a field into the structure at its head position. That is, the specified field will become the first field in the structure. And, unlike xSetField(), this function does not check for (nor remove) previously present fields by the same name. Thus, it is left up to the caller to ensure that there are no duplicate field names added to the structure.

A note of caution: There is no safeguard against adding the same field to more than one structure, which will result in a corruption of the affected structures, since both structures would link to the field, but the field links to only one specific successive element. Therefore, the user is responsible to ensure that fields are assigned to structures uniquely, and if necessary remove the field from one structure before assigning it to another.

Parameters
sStructure to which to add the field
fField to be added.
See also
xSetField()
xReverseFieldOrder()

References XStructure::firstField, XField::name, XField::next, x_error(), X_NAME_INVALID, X_NULL, X_STRUCT_INVALID, X_SUCCESS, and xLastSeparator().

◆ xIsFieldValid()

boolean xIsFieldValid ( const XField f)

Checks if a given field has valid data.

Parameters
fPointer to the field to check.
Returns
TRUE is the field seems to contain valid data, otherwise FALSE.

References FALSE, XField::name, XField::ndim, XField::sizes, TRUE, XField::type, XField::value, X_STRUCT, xElementSizeOf(), and xLastSeparator().

◆ xLastSeparator()

char * xLastSeparator ( const char *  id)

Returns the string pointer to the begining of the last separator in the ID.

Parameters
idCompound SMA-X ID.
Returns
Pointer to the beginning of the last separator in the ID, or NULL if the ID does not contain a separator.
See also
xSplitID()

References x_error(), X_SEP, and X_SEP_LENGTH.

◆ xMatchNextID()

int xMatchNextID ( const char *  token,
const char *  id 
)

Checks if the next component in a compound id matches a given token.

Parameters
tokenFull token to check for
idCompount X ID.
Returns
X_SUCCESS if it's a match. Otherwise X_FAILURE or another X error if the arguments are invalid.

References x_error(), X_FAILURE, X_GROUP_INVALID, X_NAME_INVALID, X_NULL, X_SEP, X_SEP_LENGTH, and X_SUCCESS.

◆ xNextIDToken()

char * xNextIDToken ( const char *  id)

Returns a pointer to the beginning of the next component in a compound ID. Leading ID separators are ignored.

Parameters
idAggregate X ID.
Returns
Pointer to the start of the next compound ID token, or NULL if there is no more components in the ID.

References X_SEP, and X_SEP_LENGTH.

◆ xReduceAllDims()

int xReduceAllDims ( XStructure s)

Recursively eliminates unneccessary embedding of singular structures inside a structure as well as reduces the dimension of all array fields with xReduceDims().

Parameters
sPointer to a structure.
Returns
X_SUCCESS (0) if successful or else X_STRUCT_INVALID if the argument is NULL (errno is also set to EINVAL)
See also
xReduceDims()

References XStructure::firstField, XField::name, XField::ndim, XField::next, XStructure::parent, XField::sizes, XField::type, x_error(), X_STRUCT, X_STRUCT_INVALID, x_trace(), xGetFieldCount(), xReduceAllDims(), and xReduceDims().

◆ xReduceDims()

int xReduceDims ( int *  ndim,
int *  sizes 
)

Reduces the dimensions by eliminating axes that contain a singular elements. Thus a size of {1, 3, 1, 5} will reduce to {3, 5} containing the same number of elements, in fewer dimensions. If any of the dimensions are zero then it reduces to { 0 }.

Parameters
[in,out]ndimPointer to the dimensions (will be updated in situ)
[in,out]sizesArray of sizes along the dimensions (will be updated in situ)
Returns
X_SUCCESS (0) if successful or else X_SIZE_INVALID if the ndim argument is NULL, or if it is greater than zero but the sizes argument is NULL (errno set to EINVAL in both cases)
See also
xReduceAllDims()

References x_error(), X_SIZE_INVALID, and X_SUCCESS.

◆ xRemoveField()

XField * xRemoveField ( XStructure s,
const char *  name 
)

Removes as field from the structure, returning it if found.

Parameters
sPointer to structure
nameName of field to remove
Returns
Pointer to the removed field or else NULL if the was an error or if no matching field existed in the structure.

References XStructure::firstField, XField::name, XField::next, XStructure::parent, XField::type, XField::value, x_error(), X_STRUCT, and xGetFieldCount().

◆ xReverseFieldOrder()

int xReverseFieldOrder ( XStructure s,
boolean  recursive 
)

Reverse the order of fields in a structure.

Parameters
sThe structure, whose field order to reverse.
recursiveWhether to apply the reversal to all ebmbedded substructures also
Returns
X_SUCCESS (0) if successful, or else X_NULL if the structure is NULL.
See also
xSortFields()
xSortFieldsByName()
xInsertField()

References XStructure::firstField, XField::next, TRUE, XField::type, XField::value, x_error(), X_NULL, X_STRUCT, X_SUCCESS, xGetFieldCount(), and xReverseFieldOrder().

◆ xSetField()

XField * xSetField ( XStructure s,
XField f 
)

Adds or replaces a field in the structure with the specified field value, returning the previous value for the same field. It is up to the caller whether or not the old value should be destoyed or kept. Note though that you should check first to see if the replaced field is the same as the new one before attempting to destroy...

The field's name may not contain a compound ID. To add fields to embedded sub-structures, you may want to use xGetSubstruct() first to add the field directly to the relevant embedded component.

A note of caution: There is no safeguard against adding the same field to more than one structure, which will result in a corruption of the affected structures, since both structures would link to the field, but the field links to only one specific successive element. Therefore, the user is responsible to ensure that fields are assigned to structures uniquely, and if necessary remove the field from one structure before assigning it to another.

Parameters
sStructure to which to add the field
fField to be added.
Returns
Previous field by the same name, or NULL if the field is new or if there was an error (errno will be set to EINVAL)
See also
xInsertField()
xSetSubstruct()
xGetSubstruct()

References XStructure::firstField, XField::name, XField::next, and x_error().

◆ xSetSubstruct()

XField * xSetSubstruct ( XStructure s,
const char *  name,
XStructure substruct 
)

Inserts a structure within a parent structure, returning the old field that may have existed under the requested name before.

The name may not contain a compound ID. To add the structure to embedded sub-structures, you may want to use xGetSubstruct() first to add the new structure directly to the relevant embedded component.

Parameters
sPointer to the parent structure
nameName of the sub-structure
substructPointer to the sub-structure. It is added directly as a reference, without making a copy.

return The prior field stored under the same name or NULL. If there is an error then NULL is returned and errno is set to indicate the nature of the issue. (a message is also printed to stderr if xDebug is enabled.)

See also
xGetSubstruct()

References XStructure::parent, x_error(), X_STRUCT, x_trace_null(), xCreateScalarField(), and xSetField().

◆ xSortFields()

int xSortFields ( XStructure s,
int(*)(const XField **f1, const XField **f2)  cmp,
boolean  recursive 
)

Sort the fields in a structure using a specific comparator function.

Parameters
sThe structure, whose fields to sort
cmpThe comparator function. It takes two pointers to XField locations as arguments.
recursiveWhether to apply the sorting to all ebmbedded substructures also
Returns
X_SUCCESS (0) if successful, or else X_NULL if the structure or the comparator function is NULL.
See also
xSortFieldsByName()
xReverseFieldOrder()

References XStructure::firstField, XField::next, TRUE, XField::type, XField::value, x_error(), X_NULL, X_STRUCT, X_SUCCESS, xGetFieldCount(), and xSortFields().

◆ xSortFieldsByName()

int xSortFieldsByName ( XStructure s,
boolean  recursive 
)

Sorts the fields of a structure by field name, in ascending alphabetical order.

Parameters
sThe structure, whose fields to sort
recursiveWhether to apply the sorting to all ebmbedded substructures also
Returns
X_SUCCESS (0) if successful, or else X_NULL if the structure is NULL.
See also
xReverseFieldOrder()

References X_SUCCESS, and xSortFields().

◆ xSplitID()

int xSplitID ( char *  id,
char **  pKey 
)

Splits the id into two strings (sharing the same input buffer): (1) the id of the embedding structure, and (2) the embedded field name. The original input id is string terminated after the table name. And the pointer to the key part that follows after the last separator is returned in the second (optional argument).

Parameters
[in,out]idString containing an aggregate ID, which will be terminated after the last substructure.
[out]pKeyReturned pointer to the second component after the separator within the same buffer. This is not an independent pointer. Use xStringCopyOf() if you need an idependent string on which free() can be called! The returned value pointed to may be NULL if the ID could not be split. The argument may also be null, in which case the input string is just terminated at the stem, without returning the second part.
Returns
X_SUCCESS (0) if the ID was successfully split into two components. X_NULL if the id argument is NULL. X_NAME_INVALID if no separator was found
See also
xGetAggregateID()
xLastSeparator()

References x_error(), X_NAME_INVALID, X_NULL, X_SEP_LENGTH, X_SUCCESS, and xLastSeparator().