Copyright (C) Kevin Larke 2009-2020

This file is part of libcm.

libcm is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.

libcm is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.

See the GNU General Public License distributed with the libcm package or look here: .


cmJson : JSON reader and writer

Limitations:

  1. Accpets two digit hex sequences with the \u escape command. JSON specifies 4 digits.

  2. The scientific notation for real numbers is limited to exponent prefixes: e,E,e-,E-. The prefixes e+ and E+ are not recognized by cmLex.

Extensions:

  1. Will accept C style identifiers where JSON demands quoted strings.

  2. Will accept C style hex notation (0xddd) for integer values.



// JSON data type flags
enum
{
  kInvalidTId = 0x0000,
  kObjectTId  = 0x0001,    // children are pairs
  kPairTId    = 0x0002,    // children are string : value pairs
  kArrayTId   = 0x0004,    // children may be of any type
  kStringTId  = 0x0008,    // terminal
  kNullTId    = 0x0040,    // terminal
  kIntTId     = 0x0010,    // terminal
  kRealTId    = 0x0020,    // terminal
  kTrueTId    = 0x0080,    // terminal
  kFalseTId   = 0x0100,    // terminal
  
  kMaskTId    = 0x01ff, 
  
  kOptArgJsFl = 0x0800,   // only used by cmJsonVMemberValues()
  kTempJsFl   = 0x1000,   // used internally
  
  kNumericTId = kIntTId  | kRealTId | kTrueTId | kFalseTId,
  kBoolTId    = kTrueTId | kFalseTId
  
};

enum
{
  kOkJsRC,
  kMemAllocErrJsRC,
  kLexErrJsRC,
  kSyntaxErrJsRC,
  kFileOpenErrJsRC,
  kFileCreateErrJsRC,
  kFileReadErrJsRC,
  kFileSeekErrJsRC,
  kFileCloseErrJsRC,
  kInvalidHexEscapeJsRC,
  kSerialErrJsRC,
  kNodeNotFoundJsRC,
  kNodeCannotCvtJsRC,
  kCannotRemoveLabelJsRC,
  kInvalidNodeTypeJsRC,
  kValidateFailJsRC,
  kCsvErrJsRC,
  kBufTooSmallJsRC
};

typedef unsigned cmJsRC_t;

typedef cmHandle_t cmJsonH_t;

// JSON tree node
typedef struct cmJsonNode_str
{
  
  unsigned               typeId;       // id of this node
  struct cmJsonNode_str* siblingPtr;   // next ele in array or member list
  struct cmJsonNode_str* ownerPtr;     // parent node ptr
  
  union
  {
    // childPtr usage:
    // object: first pair
    // array:  first element
    // pair:   string    
    struct cmJsonNode_str* childPtr;   
    int                    intVal;      // valid if typeId == kIntTId
    double                 realVal;     // valid if typeId == kRealTId
    char*                  stringVal;   // valid if typeId == kStringTId
    bool                   boolVal;     // valid if typeId == kTrueTId || kFalseTId
  } u;
  
} cmJsonNode_t;

extern cmJsonH_t cmJsonNullHandle;

// Initialize a json parser/tree object
cmJsRC_t      cmJsonInitialize( cmJsonH_t* hp, cmCtx_t* ctx );

// Equivalent to cmJsonInitialize() followed by cmJsonParseFile()
cmJsRC_t      cmJsonInitializeFromFile( cmJsonH_t* hp, const char* fn, cmCtx_t* ctx );

// Equivalent to cmJsonInitialize() followed by cmJsonParse(h,buf,cnt,NULL).
cmJsRC_t      cmJsonInitializeFromBuf( cmJsonH_t* hp, cmCtx_t* ctx, const char* buf, unsigned bufByteCnt );

// Release all the resources held by the tree.
cmJsRC_t      cmJsonFinalize(   cmJsonH_t* hp );

// Returns true if 'h' is a valid cmJsonH_t handle.
bool          cmJsonIsValid(    cmJsonH_t h );

// Returns true if the tree has been modified since it was initialized.
// If changes to the tree are done directly on the nodes, rather than using
// the API functions, then this function may not indicate the actual
// modification state of the tree.
bool          cmJsonIsModified( cmJsonH_t h );

// Build the internal tree by parsing a text buffer. 
// altRootPtr is an optional alternate root ptr which can be used
// append to an existing tree. Set to altRootPtr to
// NULL to append the tree to the internal root.
// If altRootPtr is given it must point ot either an array or
// object node.
cmJsRC_t      cmJsonParse(      cmJsonH_t h, const char* buf, unsigned bufCharCnt, cmJsonNode_t* altRootPtr );

// Fills a text buffer from a file and calls cmJsonParse().
cmJsRC_t      cmJsonParseFile(  cmJsonH_t h, const char* fn, cmJsonNode_t* altRootPtr );

// Return the root node of the internal tree.
cmJsonNode_t* cmJsonRoot(       cmJsonH_t h );

// Return the tree to the post initialize state by clearing the  internal tree.
cmJsRC_t      cmJsonClearTree(      cmJsonH_t h );

// Node type predicates.
bool cmJsonIsObject( const cmJsonNode_t* np );
bool cmJsonIsArray(  const cmJsonNode_t* np );
bool cmJsonIsPair(   const cmJsonNode_t* np );
bool cmJsonIsString( const cmJsonNode_t* np );
bool cmJsonIsInt(    const cmJsonNode_t* np );
bool cmJsonIsReal(   const cmJsonNode_t* np );
bool cmJsonIsBool(   const cmJsonNode_t* np );


// Return the count of child nodes of 'np'. 
// Note that only object,array, and pair nodes have children.
unsigned      cmJsonChildCount( const cmJsonNode_t* np );

// Return the node at 'index' from an element array. 
// 'np must point to an array element.
cmJsonNode_t* cmJsonArrayElement( cmJsonNode_t* np, unsigned index );
const cmJsonNode_t* cmJsonArrayElementC( const cmJsonNode_t* np, unsigned index );

// Return the child value node of a pair with a label node equal to 'label'.
// Set 'root' to NULL to begin the search at the internal tree root node. 
// Set 'typeIdMask' with all type flags to match.
// If 'typeIdMask' is equal to kInvalidTId then all types will match.
cmJsonNode_t* cmJsonFindValue(    cmJsonH_t h, const char* label, const cmJsonNode_t* root, unsigned typeIdMask );

// Return the value node of a pair at the end of an object path.
// 'path' is a '/' seperated list of object names where the final
// object specifies the pair label for the value to return.
const cmJsonNode_t* cmJsonFindPathValueC( cmJsonH_t h, const char* path, const cmJsonNode_t* root, unsigned typeIdMask );
cmJsonNode_t*       cmJsonFindPathValue(  cmJsonH_t h, const char* path, const cmJsonNode_t* root, unsigned typeIdMask );


// Return the node value. If 'np' does not point to the same type as
// specified in '*retPtr' then the value is converted if possible.
// If the value cannot be converted function returns a 'kNodeCannotCvtJsRC'
// error
cmJsRC_t cmJsonUIntValue(   const cmJsonNode_t* np, unsigned*       retPtr );
cmJsRC_t cmJsonIntValue(    const cmJsonNode_t* np, int*            retPtr );
cmJsRC_t cmJsonRealValue(   const cmJsonNode_t* np, double*         retPtr );
cmJsRC_t cmJsonBoolValue(   const cmJsonNode_t* np, bool*           retPtr );
cmJsRC_t cmJsonStringValue( const cmJsonNode_t* np, const char **   retPtrPtr );  
cmJsRC_t cmJsonPairNode(    const cmJsonNode_t* vp, cmJsonNode_t ** retPtrPtr );
cmJsRC_t cmJsonArrayNode(   const cmJsonNode_t* vp, cmJsonNode_t ** retPtrPtr );
cmJsRC_t cmJsonObjectNode(  const cmJsonNode_t* vp, cmJsonNode_t ** retPtrPtr );  


// Return the label from a pair object.
const char*   cmJsonPairLabel(  const cmJsonNode_t* pairPtr );
unsigned      cmJsonPairTypeId( const cmJsonNode_t* pairPtr );
cmJsonNode_t* cmJsonPairValue( cmJsonNode_t* pairPtr );

// Return a labelled pair node from an object.
cmJsonNode_t* cmJsonFindPair( const cmJsonNode_t* objectNodePtr, const char* label );

// Return the type of a member value.
cmJsRC_t     cmJsonMemberType( const cmJsonNode_t* objectNodePtr, const char* label, unsigned* typeIdRef );

// Return the pair at the specified index.  Use cmJsonChildCount() to get the count of pairs in the object.
cmJsonNode_t* cmJsonMemberAtIndex( cmJsonNode_t* objNodePtr, unsigned idx );

// Return values associated with the member values in the object
// pointed to by object objectNodePtr.
cmJsRC_t      cmJsonUIntMember(   const cmJsonNode_t* objectNodePtr, const char* label, unsigned* retPtr );
cmJsRC_t      cmJsonIntMember(    const cmJsonNode_t* objectNodePtr, const char* label, int* retPtr );
cmJsRC_t      cmJsonRealMember(   const cmJsonNode_t* objectNodePtr, const char* label, double* retPtr );
cmJsRC_t      cmJsonBoolMember(   const cmJsonNode_t* objectNodePtr, const char* label, bool* retPtr );
cmJsRC_t      cmJsonStringMember( const cmJsonNode_t* objectNodePtr, const char* label, const char** retPtrPtr );

// Returns array or object nodes.
cmJsRC_t      cmJsonNodeMember(   const cmJsonNode_t* objectNodePtr, const char* label, cmJsonNode_t** nodePtrPtr );

// Returns the value of the member pair named by 'label' or NULL if the 
// named pair does not exist.
cmJsonNode_t* cmJsonNodeMemberValue( const cmJsonNode_t* np, const char* label );

// Return values for specified pairs from an object node.
//
// The var args syntax is: &ltlabel&gt,&lttypeId&gt,&ltvaluePtr&gt.
// This functionis implemented in terms of cmJsonXXXMember().
// 
// Add kOptArgJsFl to &lttypeId&gt if the member may not exist in
// the object - otherwise the function will fail with a
// kNodeNotFoundJsRC error and errLabelPtr will have the name of the missing pair.
//
// Terminate the var args list with NULL.
//
// Object,Array, and Pair members are returned as node pointers.
// 
// Since kBoolTId does not exist use kTrueTId or kFalseTId to
// return bool values.

cmJsRC_t      cmJsonVMemberValues(const cmJsonNode_t* objectNodePtr, const char** errLabelPtrPtr, va_list vl );
cmJsRC_t      cmJsonMemberValues( const cmJsonNode_t* objectNodePtr, const char** errLabelPtrPtr, ... );

// If objectNodePtr is set to NULL then the  tree root is used as the base for the search.
// pathPrefix may be set to NULL.
cmJsRC_t cmJsonPathToValueNode( cmJsonH_t h, const cmJsonNode_t* objectNodePtr, const char* pathPrefix, const char* path, const cmJsonNode_t** nodePtrPtr );
cmJsRC_t cmJsonPathToBool(   cmJsonH_t h, const cmJsonNode_t* objectNodePtr, const char* pathPrefix, const char* path, bool* retValPtr );
cmJsRC_t cmJsonPathToInt(    cmJsonH_t h, const cmJsonNode_t* objectNodePtr, const char* pathPrefix, const char* path, int* retValPtr );
cmJsRC_t cmJsonPathToUInt(   cmJsonH_t h, const cmJsonNode_t* objectNodePtr, const char* pathPrefix, const char* path, unsigned* retValPtr );
cmJsRC_t cmJsonPathToReal(   cmJsonH_t h, const cmJsonNode_t* objectNodePtr, const char* pathPrefix, const char* path, double* retValPtr );
cmJsRC_t cmJsonPathToString( cmJsonH_t h, const cmJsonNode_t* objectNodePtr, const char* pathPrefix, const char* path, const char** retValPtr );
cmJsRC_t cmJsonPathToPair(   cmJsonH_t h, const cmJsonNode_t* objectNodePtr, const char* pathPrefix, const char* path, cmJsonNode_t** retValPtr );
cmJsRC_t cmJsonPathToArray(  cmJsonH_t h, const cmJsonNode_t* objectNodePtr, const char* pathPrefix, const char* path, cmJsonNode_t** retValPtr );
cmJsRC_t cmJsonPathToObject( cmJsonH_t h, const cmJsonNode_t* objectNodePtr, const char* pathPrefix, const char* path, cmJsonNode_t** retValPtr );


// Same as cmJsonMemberValues() except labels may be paths to a given variable.
// These paths are equivalent to those used in cmJsonFindPathValue()
// If objectNodePtr is NULL then the JSON tree root is used as the
// base reference object.
// If pathPrefix is non-NULL then it is appended to each of the
// individual paths.
cmJsRC_t      cmJsonVPathValues(cmJsonH_t h, const char* pathPrefix, const cmJsonNode_t* objectNodePtr, const char** errLabelPtrPtr, va_list vl );
cmJsRC_t      cmJsonPathValues( cmJsonH_t h, const char* pathPrefix, const cmJsonNode_t* objectNodePtr, const char** errLabelPtrPtr, ... );


// Set 'typeId' to the type of the new node.
// Use 'intVal' for the value of int nodes.
// Use 'realVal' for the value of real nodes.
// Use 'stringVal' for the label of pairs and the value of string nodes.
// 'retNodePtrPtr' is optional
cmJsRC_t      cmJsonCreate( cmJsonH_t h, cmJsonNode_t* parentPtr, unsigned typeId, const char* stringVal, int intVal, double realVal, cmJsonNode_t** newNodePtrPtr );

// Insert new nodes in the tree.  If the tree is empty then the first
// inserted node will become the root (this must be an object or array node.).
cmJsonNode_t* cmJsonCreateObject( cmJsonH_t h, cmJsonNode_t* parentPtr );
cmJsonNode_t* cmJsonCreateArray(  cmJsonH_t h, cmJsonNode_t* parentPtr );
cmJsonNode_t* cmJsonCreatePair(   cmJsonH_t h, cmJsonNode_t* parentPtr, const char* label );
cmJsRC_t      cmJsonCreateString( cmJsonH_t h, cmJsonNode_t* parentPtr, const char* stringValue );
cmJsRC_t      cmJsonCreateStringN(cmJsonH_t h, cmJsonNode_t* parentPtr, const char* stringValue, unsigned stringCharCnt );
cmJsRC_t      cmJsonCreateInt(    cmJsonH_t h, cmJsonNode_t* parentPtr, int value );
cmJsRC_t      cmJsonCreateReal(   cmJsonH_t h, cmJsonNode_t* parentPtr, double value );
cmJsRC_t      cmJsonCreateBool(   cmJsonH_t h, cmJsonNode_t* parentPtr, bool value );
cmJsRC_t      cmJsonCreateNull(   cmJsonH_t h, cmJsonNode_t* parentPtr );

cmJsRC_t      cmJsonCreateStringArray( cmJsonH_t h, cmJsonNode_t* parentPtr, unsigned n, const char** values );
cmJsRC_t      cmJsonCreateIntArray(    cmJsonH_t h, cmJsonNode_t* parentPtr, unsigned n, const int* values );
cmJsRC_t      cmJsonCreateRealArray(   cmJsonH_t h, cmJsonNode_t* parentPtr, unsigned n, const double* values );
cmJsRC_t      cmJsonCreateBoolArray(   cmJsonH_t h, cmJsonNode_t* parentPtr, unsigned n, const bool* values );



// // Tree creation helper functiosn //
cmJsRC_t cmJsonSetInt( cmJsonH_t h, cmJsonNode_t* np, int ival ); cmJsRC_t cmJsonSetReal( cmJsonH_t h, cmJsonNode_t * np, double rval ); cmJsRC_t cmJsonSetBool( cmJsonH_t h, cmJsonNode_t * np, bool bval ); cmJsRC_t cmJsonSetString( cmJsonH_t h, cmJsonNode_t* np, const char* sval ); // Insert a pair with a value indicated by 'typeId'. // 'stringVal','intVal' and 'realVal' are used as in cmJsonCreate(). // Return a pointer to the new pair. cmJsonNode_t* cmJsonInsertPair( cmJsonH_t h, cmJsonNode_t* objectNodePtr, const char* label, unsigned typeId, const char* stringVal, int intVal, double realVal ); // Create a pair node and the associated label and value nodes and insert the pair in a parent object. // The object,array and pair creation functions return pointers to the pair value node. // These are helper functions that are implemented in terms of cmJsonCreateXXX() function. cmJsonNode_t* cmJsonInsertPairObject( cmJsonH_t h, cmJsonNode_t* objectNodePtr, const char* label ); cmJsonNode_t* cmJsonInsertPairArray( cmJsonH_t h, cmJsonNode_t* objectNodePtr, const char* label ); cmJsonNode_t* cmJsonInsertPairPair( cmJsonH_t h, cmJsonNode_t* objectNodePtr, const char* label, const char* pairLabel ); cmJsRC_t cmJsonInsertPairInt( cmJsonH_t h, cmJsonNode_t* objectNodePtr, const char* label, int intVal ); cmJsRC_t cmJsonInsertPairReal( cmJsonH_t h, cmJsonNode_t* objectNodePtr, const char* label, double realVal ); cmJsRC_t cmJsonInsertPairString( cmJsonH_t h, cmJsonNode_t* objectNodePtr, const char* label, const char* string ); cmJsRC_t cmJsonInsertPairStringN(cmJsonH_t h, cmJsonNode_t* objectNodePtr, const char* label, const char* string, unsigned stringCharCnt ); cmJsRC_t cmJsonInsertPairBool( cmJsonH_t h, cmJsonNode_t* objectNodePtr, const char* label, bool boolVal ); cmJsRC_t cmJsonInsertPairNull( cmJsonH_t h, cmJsonNode_t* objectNodePtr, const char* label ); cmJsRC_t cmJsonInsertPairIntArray( cmJsonH_t h, cmJsonNode_t* objectNodePtr, const char* label, unsigned n, const int* values ); cmJsRC_t cmJsonInsertPairRealArray( cmJsonH_t h, cmJsonNode_t* objectNodePtr, const char* label, unsigned n, const double* values ); cmJsRC_t cmJsonInsertPairStringArray( cmJsonH_t h, cmJsonNode_t* objectNodePtr, const char* label, unsigned n, const char** values ); cmJsRC_t cmJsonInsertPairBoolArray( cmJsonH_t h, cmJsonNode_t* objectNodePtr, const char* label, unsigned n, const bool* values ); // Returns pair pointer cmJsonNode_t* cmJsonInsertPairIntArray2( cmJsonH_t h, cmJsonNode_t* objectNodePtr, const char* label, unsigned n, const int* values ); cmJsonNode_t* cmJsonInsertPairRealArray2( cmJsonH_t h, cmJsonNode_t* objectNodePtr, const char* label, unsigned n, const double* values ); cmJsonNode_t* cmJsonInsertPairStringArray2( cmJsonH_t h, cmJsonNode_t* objectNodePtr, const char* label, unsigned n, const char** values ); cmJsonNode_t* cmJsonInsertPairBoolArray2( cmJsonH_t h, cmJsonNode_t* objectNodePtr, const char* label, unsigned n, const bool* values ); // Insert a pair (same as cmJsonInsertPair()) or if a pair // with a matching label/type already exists then replace the // existing value with a the new value. // // Set matchTypeMask with the type id's of all pair value types // which sould be considered a match. If matchTypeMask is set to // kInvalidTId then all value types will match. // // Return a pointer to the new or existing pair. // // When newTypeId == kObjectTId or kArrayTId then 'nv' may optionally be set to an object or array // to be set as the new value node for the selected pair. If 'nv' is NULL then an empty array or // object is created as the pair value node. // // When newTypeId == kPairTId then we are inserting/replacing a pair as the value of the selected pair. // In this case sv must be set to the new pair label. 'nv' may be optionally // set to a new pair value node. If 'nv' is NULL then the the new pair will have a value of type kNullTId cmJsonNode_t* cmJsonInsertOrReplacePair( cmJsonH_t h, cmJsonNode_t* objectNodePtr, const char* label, unsigned matchTypeMask, unsigned newTypeId, const char* sv, int iv, double dv, cmJsonNode_t* nv ); // Returns pointer to object node. cmJsonNode_t* cmJsonInsertOrReplacePairObject( cmJsonH_t h, cmJsonNode_t* objectNodePtr, const char* label, unsigned matchTypeMask, cmJsonNode_t* newObjNodePtr ); // Returns pointer to array node. cmJsonNode_t* cmJsonInsertOrReplacePairArray( cmJsonH_t h, cmJsonNode_t* objectNodePtr, const char* label, unsigned matchTypeMask, cmJsonNode_t* newArrayNodePtr ); // Returns pointer to child pair node cmJsonNode_t* cmJsonInsertOrReplacePairPair( cmJsonH_t h, cmJsonNode_t* objectNodePtr, const char* label, unsigned matchTypeMask, const char* newPairLabel, cmJsonNode_t* newPairValNodePtr ); cmJsRC_t cmJsonInsertOrReplacePairInt( cmJsonH_t h, cmJsonNode_t* objectNodePtr, const char* label, unsigned matchTypeMask, int intVal ); cmJsRC_t cmJsonInsertOrReplacePairReal( cmJsonH_t h, cmJsonNode_t* objectNodePtr, const char* label, unsigned matchTypeMask, double realVal ); cmJsRC_t cmJsonInsertOrReplacePairString( cmJsonH_t h, cmJsonNode_t* objectNodePtr, const char* label, unsigned matchTypeMask, const char* string ); cmJsRC_t cmJsonInsertOrReplacePairBool( cmJsonH_t h, cmJsonNode_t* objectNodePtr, const char* label, unsigned matchTypeMask, bool boolVal ); cmJsRC_t cmJsonInsertOrReplacePairNull( cmJsonH_t h, cmJsonNode_t* objectNodePtr, const char* label, unsigned matchTypeMask ); // Same as the above cmJsonInsertOrReplaceXXX() functions except // the function fails if a matching pair is not found. // // Replace a pair with the same name/type and return a pointer to the // effected pair. If a pair with the same name and type are not // found then no change is made and the function returns NULL. // For newTypeId=kObjectTId,kArrayTId,kPairTId the replaced pair node is blank, // in other words it will have no child nodes. cmJsonNode_t* cmJsonReplacePair( cmJsonH_t h, cmJsonNode_t* objectNodePtr, const char* label, unsigned matchTypeMask, unsigned newTypeId, const char* sv, int iv, double dv, cmJsonNode_t* nv ); // Returns pointer to object node. cmJsonNode_t* cmJsonReplacePairObject( cmJsonH_t h, cmJsonNode_t* objectNodePtr, const char* label, unsigned matchTypeMask, cmJsonNode_t* newObjNodePtr ); // Return pointer to array node. cmJsonNode_t* cmJsonReplacePairArray( cmJsonH_t h, cmJsonNode_t* objectNodePtr, const char* label, unsigned matchTypeMask, cmJsonNode_t* newArrayNodePtr ); // Returns pointer to child pair node. cmJsonNode_t* cmJsonReplacePairPair( cmJsonH_t h, cmJsonNode_t* objectNodePtr, const char* label, unsigned matchTypeMask, const char* newPairLabel, cmJsonNode_t* newPairValueNodePtr ); cmJsRC_t cmJsonReplacePairInt( cmJsonH_t h, cmJsonNode_t* objectNodePtr, const char* label, unsigned matchTypeMask, int intVal ); cmJsRC_t cmJsonReplacePairReal( cmJsonH_t h, cmJsonNode_t* objectNodePtr, const char* label, unsigned matchTypeMask, double realVal ); cmJsRC_t cmJsonReplacePairString( cmJsonH_t h, cmJsonNode_t* objectNodePtr, const char* label, unsigned matchTypeMask, const char* string ); cmJsRC_t cmJsonReplacePairBool( cmJsonH_t h, cmJsonNode_t* objectNodePtr, const char* label, unsigned matchTypeMask, bool boolVal ); cmJsRC_t cmJsonReplacePairNull( cmJsonH_t h, cmJsonNode_t* objectNodePtr, const char* label, unsigned matchTypeMask ); // Insert multiple pairs in a parent object. Terminate the pair sets with NULL. // Note that pair,int,real,bool, and string pairs are specified with 3 args: &ltlabel&gt,&lttypeId&gt,&ltvalue&gt // all others are specified with 2 args: &ltlabel&gt,&lttypeId&gt. // The last argument in this function must always be NULL. cmJsRC_t cmJsonVInsertPairs( cmJsonH_t h, cmJsonNode_t* objectNodePtr, va_list vl ); cmJsRC_t cmJsonInsertPairs( cmJsonH_t h, cmJsonNode_t* objectNodePtr, ... ); // Create an object node, fill it with the specified pairs, and return a pointer to // the new object node. // This function uses same var args syntax as cmJsonInsertPairs() cmJsonNode_t* cmJsonVCreateFilledObject( cmJsonH_t h, cmJsonNode_t* parentPtr, va_list vl ); cmJsonNode_t* cmJsonCreateFilledObject( cmJsonH_t h, cmJsonNode_t* parentPtr, ... );
// Remove a node from the tree by unlinking it from its // parent and siblings. // Set the freeFl to true if the node memory should also // be released. // // If 'freeFl' is false then np-&gtownerPtr and // np-&gtsiblingPtr remain valid when the function returns. // Even with the valid pointer however be careful // not to use the node in a way that it depends // on existing in the tree since the parent and // siblings will no longer know about it. // // If np is the root then the internal tree will be // cleared (i.e. cmJsonRoot(h) == NULL). // // This function will fail if 'np' points to the label value // of a pair node. Pair labels cannot be removed because this // would result in an invalid tree (all pairs must have two // child nodes where the first node is a string value). If 'np' // points to a pair value node then the value node is replaced // with a null node to maintain a valid pair structure. cmJsRC_t cmJsonRemoveNode( cmJsonH_t h, cmJsonNode_t* np, bool freeFl );
// Duplicate the subtree pointed to by 'np' and attach it as a child // of the node pointed to by 'parentPtr'. This function performs a // deep copy of the subtree pointed to by np and returns the pointer // to the duplicated subtree. // // 'parentPtr' must be a legal parent for the sub-tree or NULL to not // attach the duplicate tree to any parent. // // The returned value is a pointer to the new subtree. // // If an error occurs the return value is NULL and cmJsonErrorCode() // can be used to obtain the code associated with the error. cmJsonNode_t* cmJsonDuplicateNode( cmJsonH_t h, const cmJsonNode_t* np, cmJsonNode_t* parentPtr );
// Copy any pairs not found in the destintaion object from the // source object. // If an error occurs during merging the destination object is // returned unmodified. The most likely cause of an error is a // destination pair with the same name but different type // than a source pair. cmJsRC_t cmJsonMergeObjectNodes( cmJsonH_t h, cmJsonNode_t* destObjNodePtr, const cmJsonNode_t* srcObjNodePtr );
// Validate the tree. cmJsRC_t cmJsonValidateTree( cmJsonH_t h ); // Validate the tree beginning with np. Note that this function does // not print an error on failure but simply returns kValidateFailJsRC. cmJsRC_t cmJsonValidate( const cmJsonNode_t* np ); // Get the count of bytes required to serialize the tree rooted at 'np'. unsigned cmJsonSerialByteCount( const cmJsonNode_t* np ); // Serialize the tree rooted at 'np' into the buffer buf[bufByteCnt]. cmJsRC_t cmJsonSerialize( const cmJsonNode_t* np, void* buf, unsigned bufByteCnt ); // Serialize the subtree indicated by 'np' or the entire tree // if 'np' is NULL. The buffer created by this call will exist // for the life of 'h' or until the next call to cmJsonSerialize(). // This function is implemented in terms of cmJsonSerialByteCount() // and cmJsonSerializeTree(). cmJsRC_t cmJsonSerializeTree( cmJsonH_t h, const cmJsonNode_t* np, void** bufPtrPtr, unsigned* bufByteCntPtr); // Recreate the objects previously serialzed via cmJsonSerialize(). // The tree held in the buffer will be reconstructed as a child of // altRootPtr (if it is non-NULL) or the internal root. // If altRootPtr is given then it must point to an array // or object node. cmJsRC_t cmJsonDeserialize( cmJsonH_t h, const void* bufPtr, cmJsonNode_t* altRootPtr ); // Return a string/int/real/null/bool node as a string value. cmJsRC_t cmJsonLeafToString( const cmJsonNode_t* np, cmChar_t* buf, unsigned bufCharCnt ); // Given a CSV file convert it to an array of JSON objects. // The first line of the CSV file must contain a comma seperated lists of types. // The type labels must be from the set: 'int','real','string','true','false'. // Note that either 'true' or 'false' can be use for boolean columns. // The seocnd line contains the field names as comma separated quoted strings. // For example &quotcolumn1&quot,&quotcolumn2&quot,&quotcolumn3&quot // The data is presented as comma separated fields. // If parentNodePtr is NULL then the array will be created unattached to // the tree. // if arrayNodePtrPtr is non-NULL then the array node ptr will be returned. cmJsRC_t cmJsonFromCSV( cmJsonH_t h, const char* iFn, cmJsonNode_t* parentPtr, cmJsonNode_t** arrayNodePtrPtr ); // Write a CSV file from an array of objects. // arrayNodePtr must point to an array of objects. cmJsRC_t cmJsonToCSV( cmJsonH_t h, const char* oFn, const cmJsonNode_t* arrayNodePtr ); // Print the subtree using 'np as the root. void cmJsonPrintTree( const cmJsonNode_t* np, cmRpt_t* rpt ); // Print the subtree using 'np' as the root to a file. // 'np' is optional and defaults to cmJsonRoot(). cmJsRC_t cmJsonWrite( cmJsonH_t h, const cmJsonNode_t* np, const cmChar_t* fn ); // Return the code of the last error generated. This is useful for the // the cmJsonCreateXXX() functions which do not return error codes but // may still fail. cmJsRC_t cmJsonErrorCode( cmJsonH_t h ); void cmJsonClearErrorCode( cmJsonH_t h ); // Validate the tree and print all the nodes. cmJsRC_t cmJsonReport( cmJsonH_t h ); // Testing stub. cmJsRC_t cmJsonTest( const char* fn, cmCtx_t* ctx );