//| Copyright: (C) 2009-2020 Kevin Larke //| License: GNU GPL version 3.0 or above. See the accompanying LICENSE file. #ifndef cmJson_h #define cmJson_h #ifdef __cplusplus extern "C" { #endif //( { file_desc: "JSON reader and writer" kw:[file] } // // 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: