|
|
@ -44,24 +44,25 @@ char const* json_getPropertyValue( json_t const* obj, char const* property ) { |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/* Internal prototypes: */ |
|
|
|
/* Internal prototypes: */ |
|
|
|
static char* _goWhiteSpace( char* str ); |
|
|
|
static char* goBlank( char* str ); |
|
|
|
static char* _goNum( char* str ); |
|
|
|
static bool isNum( unsigned char ch ); |
|
|
|
static json_t* _poolInit( jsonPool_t* pool ); |
|
|
|
static char* goNum( char* str ); |
|
|
|
static json_t* _poolNew( jsonPool_t* pool ); |
|
|
|
static json_t* poolInit( jsonPool_t* pool ); |
|
|
|
static char* _objValue( char* ptr, json_t* obj, jsonPool_t* pool ); |
|
|
|
static json_t* poolNew( jsonPool_t* pool ); |
|
|
|
static char* _setToNull( char* ch ); |
|
|
|
static char* objValue( char* ptr, json_t* obj, jsonPool_t* pool ); |
|
|
|
static bool _isEndOfPrimitive( char ch ); |
|
|
|
static char* setToNull( char* ch ); |
|
|
|
|
|
|
|
static bool isEndOfPrimitive( char ch ); |
|
|
|
|
|
|
|
|
|
|
|
/* Parse a string to get a json. */ |
|
|
|
/* Parse a string to get a json. */ |
|
|
|
json_t const* json_create( char* str, json_t mem[], unsigned int qty ) { |
|
|
|
json_t const* json_create( char* str, json_t mem[], unsigned int qty ) { |
|
|
|
char* ptr = _goWhiteSpace( str ); |
|
|
|
char* ptr = goBlank( str ); |
|
|
|
if ( !ptr || *ptr != '{' ) return 0; |
|
|
|
if ( !ptr || *ptr != '{' ) return 0; |
|
|
|
jsonPool_t pool = { .mem = mem, .qty = qty }; |
|
|
|
jsonPool_t pool = { .mem = mem, .qty = qty }; |
|
|
|
json_t* obj = _poolInit( &pool ); |
|
|
|
json_t* obj = poolInit( &pool ); |
|
|
|
obj->name = 0; |
|
|
|
obj->name = 0; |
|
|
|
obj->sibling = 0; |
|
|
|
obj->sibling = 0; |
|
|
|
obj->u.child = 0; |
|
|
|
obj->u.child = 0; |
|
|
|
ptr = _objValue( ptr, obj, &pool ); |
|
|
|
ptr = objValue( ptr, obj, &pool ); |
|
|
|
if ( !ptr ) return 0; |
|
|
|
if ( !ptr ) return 0; |
|
|
|
return obj; |
|
|
|
return obj; |
|
|
|
} |
|
|
|
} |
|
|
@ -70,7 +71,7 @@ json_t const* json_create( char* str, json_t mem[], unsigned int qty ) { |
|
|
|
* 'b' -> '\b', 'n' -> '\n', 't' -> '\t' |
|
|
|
* 'b' -> '\b', 'n' -> '\n', 't' -> '\t' |
|
|
|
* @param ch The escape character. |
|
|
|
* @param ch The escape character. |
|
|
|
* @return The character code. */ |
|
|
|
* @return The character code. */ |
|
|
|
static char _getEscape( char ch ) { |
|
|
|
static char getEscape( char ch ) { |
|
|
|
static struct { char ch; char code; } const pair[] = { |
|
|
|
static struct { char ch; char code; } const pair[] = { |
|
|
|
{ '\"', '\"' }, |
|
|
|
{ '\"', '\"' }, |
|
|
|
{ '\\', '\\' }, |
|
|
|
{ '\\', '\\' }, |
|
|
@ -89,7 +90,7 @@ static char _getEscape( char ch ) { |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/** Check if a character is a hexadecimal digit. */ |
|
|
|
/** Check if a character is a hexadecimal digit. */ |
|
|
|
static bool _isHexaDigit( unsigned char nibble ) { |
|
|
|
static bool isHexaDigit( unsigned char nibble ) { |
|
|
|
if ( nibble < '0' ) return false; |
|
|
|
if ( nibble < '0' ) return false; |
|
|
|
if ( nibble <= '9' ) return true; |
|
|
|
if ( nibble <= '9' ) return true; |
|
|
|
if ( nibble < 'A' ) return false; |
|
|
|
if ( nibble < 'A' ) return false; |
|
|
@ -103,10 +104,10 @@ static bool _isHexaDigit( unsigned char nibble ) { |
|
|
|
* @Param str Pointer to first digit. |
|
|
|
* @Param str Pointer to first digit. |
|
|
|
* @retval '?' If the four characters are hexadecimal digits. |
|
|
|
* @retval '?' If the four characters are hexadecimal digits. |
|
|
|
* @retcal '\0' In other cases. */ |
|
|
|
* @retcal '\0' In other cases. */ |
|
|
|
static char _getCharFromUnicode( char const* str ) { |
|
|
|
static char getCharFromUnicode( char const* str ) { |
|
|
|
unsigned int i; |
|
|
|
unsigned int i; |
|
|
|
for( i = 0; i < 4; ++i ) |
|
|
|
for( i = 0; i < 4; ++i ) |
|
|
|
if ( !_isHexaDigit( str[i] ) ) |
|
|
|
if ( !isHexaDigit( str[i] ) ) |
|
|
|
return '\0'; |
|
|
|
return '\0'; |
|
|
|
return '?'; |
|
|
|
return '?'; |
|
|
|
} |
|
|
|
} |
|
|
@ -116,7 +117,7 @@ static char _getCharFromUnicode( char const* str ) { |
|
|
|
* @param str Pointer to first character. |
|
|
|
* @param str Pointer to first character. |
|
|
|
* @retval Pointer to first non white space after the string. If success. |
|
|
|
* @retval Pointer to first non white space after the string. If success. |
|
|
|
* @retval Null pointer if any error occur. */ |
|
|
|
* @retval Null pointer if any error occur. */ |
|
|
|
static char* _parseString( char* str ) { |
|
|
|
static char* parseString( char* str ) { |
|
|
|
char* head = str; |
|
|
|
char* head = str; |
|
|
|
char* tail = str; |
|
|
|
char* tail = str; |
|
|
|
for( ; *head >= ' '; ++head, ++tail ) { |
|
|
|
for( ; *head >= ' '; ++head, ++tail ) { |
|
|
@ -126,13 +127,13 @@ static char* _parseString( char* str ) { |
|
|
|
} |
|
|
|
} |
|
|
|
if ( *head == '\\' ) { |
|
|
|
if ( *head == '\\' ) { |
|
|
|
if ( *++head == 'u' ) { |
|
|
|
if ( *++head == 'u' ) { |
|
|
|
char const ch = _getCharFromUnicode( ++head ); |
|
|
|
char const ch = getCharFromUnicode( ++head ); |
|
|
|
if ( ch == '\0' ) return 0; |
|
|
|
if ( ch == '\0' ) return 0; |
|
|
|
*tail = ch; |
|
|
|
*tail = ch; |
|
|
|
head += 3; |
|
|
|
head += 3; |
|
|
|
} |
|
|
|
} |
|
|
|
else { |
|
|
|
else { |
|
|
|
char const esc = _getEscape( *head ); |
|
|
|
char const esc = getEscape( *head ); |
|
|
|
if ( esc == '\0' ) return 0; |
|
|
|
if ( esc == '\0' ) return 0; |
|
|
|
*tail = esc; |
|
|
|
*tail = esc; |
|
|
|
} |
|
|
|
} |
|
|
@ -147,14 +148,14 @@ static char* _parseString( char* str ) { |
|
|
|
* @param property The property to assign the name. |
|
|
|
* @param property The property to assign the name. |
|
|
|
* @retval Pointer to first of property value. If success. |
|
|
|
* @retval Pointer to first of property value. If success. |
|
|
|
* @retval Null pointer if any error occur. */ |
|
|
|
* @retval Null pointer if any error occur. */ |
|
|
|
static char* _propertyName( char* ptr, json_t* property ) { |
|
|
|
static char* propertyName( char* ptr, json_t* property ) { |
|
|
|
property->name = ++ptr; |
|
|
|
property->name = ++ptr; |
|
|
|
ptr = _parseString( ptr ); |
|
|
|
ptr = parseString( ptr ); |
|
|
|
if ( !ptr ) return 0; |
|
|
|
if ( !ptr ) return 0; |
|
|
|
ptr = _goWhiteSpace( ptr ); |
|
|
|
ptr = goBlank( ptr ); |
|
|
|
if ( !ptr ) return 0; |
|
|
|
if ( !ptr ) return 0; |
|
|
|
if ( *ptr++ != ':' ) return 0; |
|
|
|
if ( *ptr++ != ':' ) return 0; |
|
|
|
return _goWhiteSpace( ptr ); |
|
|
|
return goBlank( ptr ); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/** Parse a string to get the value of a property when its type is JSON_TEXT.
|
|
|
|
/** Parse a string to get the value of a property when its type is JSON_TEXT.
|
|
|
@ -162,9 +163,9 @@ static char* _propertyName( char* ptr, json_t* property ) { |
|
|
|
* @param property The property to assign the name. |
|
|
|
* @param property The property to assign the name. |
|
|
|
* @retval Pointer to first non white space after the string. If success. |
|
|
|
* @retval Pointer to first non white space after the string. If success. |
|
|
|
* @retval Null pointer if any error occur. */ |
|
|
|
* @retval Null pointer if any error occur. */ |
|
|
|
static char* _textValue( char* ptr, json_t* property ) { |
|
|
|
static char* textValue( char* ptr, json_t* property ) { |
|
|
|
++property->u.value; |
|
|
|
++property->u.value; |
|
|
|
ptr = _parseString( ++ptr ); |
|
|
|
ptr = parseString( ++ptr ); |
|
|
|
if ( !ptr ) return 0; |
|
|
|
if ( !ptr ) return 0; |
|
|
|
property->type = JSON_TEXT; |
|
|
|
property->type = JSON_TEXT; |
|
|
|
return ptr; |
|
|
|
return ptr; |
|
|
@ -175,7 +176,7 @@ static char* _textValue( char* ptr, json_t* property ) { |
|
|
|
* @param str main string |
|
|
|
* @param str main string |
|
|
|
* @retval Pointer to next chraracter. |
|
|
|
* @retval Pointer to next chraracter. |
|
|
|
* @retval Null pointer if any error occur. */ |
|
|
|
* @retval Null pointer if any error occur. */ |
|
|
|
static char* _checkStr( char* ptr, char const* str ) { |
|
|
|
static char* checkStr( char* ptr, char const* str ) { |
|
|
|
while( *str ) |
|
|
|
while( *str ) |
|
|
|
if ( *ptr++ != *str++ ) |
|
|
|
if ( *ptr++ != *str++ ) |
|
|
|
return 0; |
|
|
|
return 0; |
|
|
@ -190,10 +191,10 @@ static char* _checkStr( char* ptr, char const* str ) { |
|
|
|
* @param type The code of the type. ( JSON_BOOLEAN or JSON_NULL ) |
|
|
|
* @param type The code of the type. ( JSON_BOOLEAN or JSON_NULL ) |
|
|
|
* @retval Pointer to first non white space after the string. If success. |
|
|
|
* @retval Pointer to first non white space after the string. If success. |
|
|
|
* @retval Null pointer if any error occur. */ |
|
|
|
* @retval Null pointer if any error occur. */ |
|
|
|
static char* _primitiveValue( char* ptr, json_t* property, char const* value, jsonType_t type ) { |
|
|
|
static char* primitiveValue( char* ptr, json_t* property, char const* value, jsonType_t type ) { |
|
|
|
ptr = _checkStr( ptr, value ); |
|
|
|
ptr = checkStr( ptr, value ); |
|
|
|
if ( !ptr || !_isEndOfPrimitive( *ptr ) ) return 0; |
|
|
|
if ( !ptr || !isEndOfPrimitive( *ptr ) ) return 0; |
|
|
|
ptr = _setToNull( ptr ); |
|
|
|
ptr = setToNull( ptr ); |
|
|
|
property->type = type; |
|
|
|
property->type = type; |
|
|
|
return ptr; |
|
|
|
return ptr; |
|
|
|
} |
|
|
|
} |
|
|
@ -204,8 +205,8 @@ static char* _primitiveValue( char* ptr, json_t* property, char const* value, js |
|
|
|
* @param property Property handler to set the value and the type, (true, false or null). |
|
|
|
* @param property Property handler to set the value and the type, (true, false or null). |
|
|
|
* @retval Pointer to first non white space after the string. If success. |
|
|
|
* @retval Pointer to first non white space after the string. If success. |
|
|
|
* @retval Null pointer if any error occur. */ |
|
|
|
* @retval Null pointer if any error occur. */ |
|
|
|
static char* _trueValue( char* ptr, json_t* property ) { |
|
|
|
static char* trueValue( char* ptr, json_t* property ) { |
|
|
|
return _primitiveValue( ptr, property, "true", JSON_BOOLEAN ); |
|
|
|
return primitiveValue( ptr, property, "true", JSON_BOOLEAN ); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/** Parser a string to get a false value.
|
|
|
|
/** Parser a string to get a false value.
|
|
|
@ -214,8 +215,8 @@ static char* _trueValue( char* ptr, json_t* property ) { |
|
|
|
* @param property Property handler to set the value and the type, (true, false or null). |
|
|
|
* @param property Property handler to set the value and the type, (true, false or null). |
|
|
|
* @retval Pointer to first non white space after the string. If success. |
|
|
|
* @retval Pointer to first non white space after the string. If success. |
|
|
|
* @retval Null pointer if any error occur. */ |
|
|
|
* @retval Null pointer if any error occur. */ |
|
|
|
static char* _falseValue( char* ptr, json_t* property ) { |
|
|
|
static char* falseValue( char* ptr, json_t* property ) { |
|
|
|
return _primitiveValue( ptr, property, "false", JSON_BOOLEAN ); |
|
|
|
return primitiveValue( ptr, property, "false", JSON_BOOLEAN ); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/** Parser a string to get a null value.
|
|
|
|
/** Parser a string to get a null value.
|
|
|
@ -224,61 +225,81 @@ static char* _falseValue( char* ptr, json_t* property ) { |
|
|
|
* @param property Property handler to set the value and the type, (true, false or null). |
|
|
|
* @param property Property handler to set the value and the type, (true, false or null). |
|
|
|
* @retval Pointer to first non white space after the string. If success. |
|
|
|
* @retval Pointer to first non white space after the string. If success. |
|
|
|
* @retval Null pointer if any error occur. */ |
|
|
|
* @retval Null pointer if any error occur. */ |
|
|
|
static char* _nullValue( char* ptr, json_t* property ) { |
|
|
|
static char* nullValue( char* ptr, json_t* property ) { |
|
|
|
return _primitiveValue( ptr, property, "null", JSON_NULL ); |
|
|
|
return primitiveValue( ptr, property, "null", JSON_NULL ); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
static bool _isNum( unsigned char ch ); |
|
|
|
/** Analyze the exponential part of a real number.
|
|
|
|
|
|
|
|
* @param str Pointer to first character. |
|
|
|
static char* _expValue( char* ptr, json_t* property ) { |
|
|
|
* @retval Pointer to first non numerical after the string. If success. |
|
|
|
|
|
|
|
* @retval Null pointer if any error occur. */ |
|
|
|
|
|
|
|
static char* expValue( char* ptr ) { |
|
|
|
if ( *ptr == '-' || *ptr == '+' ) ++ptr; |
|
|
|
if ( *ptr == '-' || *ptr == '+' ) ++ptr; |
|
|
|
if ( !_isNum( *ptr ) ) return 0; |
|
|
|
if ( !isNum( *ptr ) ) return 0; |
|
|
|
ptr = _goNum( ++ptr ); |
|
|
|
ptr = goNum( ++ptr ); |
|
|
|
property->type = JSON_REAL; |
|
|
|
|
|
|
|
return ptr; |
|
|
|
return ptr; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
static char* _fraqValue( char* ptr, json_t* property ) { |
|
|
|
/** Analyze the decimal part of a real number.
|
|
|
|
if ( !_isNum( *ptr ) ) return 0; |
|
|
|
* @param str Pointer to first character. |
|
|
|
ptr = _goNum( ++ptr ); |
|
|
|
* @retval Pointer to first non numerical after the string. If success. |
|
|
|
|
|
|
|
* @retval Null pointer if any error occur. */ |
|
|
|
|
|
|
|
static char* fraqValue( char* ptr ) { |
|
|
|
|
|
|
|
if ( !isNum( *ptr ) ) return 0; |
|
|
|
|
|
|
|
ptr = goNum( ++ptr ); |
|
|
|
if ( !ptr ) return 0; |
|
|
|
if ( !ptr ) return 0; |
|
|
|
if ( *ptr == 'e' || *ptr == 'E' ) return _expValue( ++ptr, property ); |
|
|
|
|
|
|
|
property->type = JSON_REAL; |
|
|
|
|
|
|
|
return ptr; |
|
|
|
return ptr; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/** Parser a string to get a numerial value.
|
|
|
|
/** Parser a string to get a numerical value.
|
|
|
|
* If the first character after the value is diferent of '}' or ']' is set to '\0'. |
|
|
|
* If the first character after the value is diferent of '}' or ']' is set to '\0'. |
|
|
|
* @param str Pointer to first character. |
|
|
|
* @param str Pointer to first character. |
|
|
|
* @param property Property handler to set the value and the type: JSON_REAL or JSON_INTEGER. |
|
|
|
* @param property Property handler to set the value and the type: JSON_REAL or JSON_INTEGER. |
|
|
|
* @retval Pointer to first non white space after the string. If success. |
|
|
|
* @retval Pointer to first non white space after the string. If success. |
|
|
|
* @retval Null pointer if any error occur. */ |
|
|
|
* @retval Null pointer if any error occur. */ |
|
|
|
static char* _numValue( char* ptr, json_t* property ) { |
|
|
|
static char* numValue( char* ptr, json_t* property ) { |
|
|
|
if ( *ptr == '-' ) ++ptr; |
|
|
|
if ( *ptr == '-' ) ++ptr; |
|
|
|
if ( *ptr != '0' ) { |
|
|
|
if ( *ptr != '0' ) { |
|
|
|
ptr = _goNum( ptr ); |
|
|
|
ptr = goNum( ptr ); |
|
|
|
if ( !ptr ) return 0; |
|
|
|
if ( !ptr ) return 0; |
|
|
|
} |
|
|
|
} |
|
|
|
else if ( _isNum( *++ptr ) ) return 0; |
|
|
|
else if ( isNum( *++ptr ) ) return 0; |
|
|
|
|
|
|
|
property->type = JSON_INTEGER; |
|
|
|
if ( *ptr == '.' ) { |
|
|
|
if ( *ptr == '.' ) { |
|
|
|
ptr = _fraqValue( ++ptr, property ); |
|
|
|
ptr = fraqValue( ++ptr ); |
|
|
|
if ( !ptr ) return 0; |
|
|
|
if ( !ptr ) return 0; |
|
|
|
|
|
|
|
property->type = JSON_REAL;
|
|
|
|
} |
|
|
|
} |
|
|
|
else if ( *ptr == 'e' || *ptr == 'E' ) { |
|
|
|
if ( *ptr == 'e' || *ptr == 'E' ) { |
|
|
|
ptr = _expValue( ++ptr, property ); |
|
|
|
ptr = expValue( ++ptr ); |
|
|
|
if ( !ptr ) return 0; |
|
|
|
if ( !ptr ) return 0; |
|
|
|
|
|
|
|
property->type = JSON_REAL;
|
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
if ( !isEndOfPrimitive( *ptr ) ) return 0;
|
|
|
|
|
|
|
|
if ( JSON_INTEGER == property->type ) { |
|
|
|
|
|
|
|
char const* value = property->u.value; |
|
|
|
|
|
|
|
bool const negative = *value == '-'; |
|
|
|
|
|
|
|
unsigned int const maxdigits = negative ? 20: 19; |
|
|
|
|
|
|
|
unsigned int const len = ptr - value; |
|
|
|
|
|
|
|
if ( len > maxdigits ) return 0; |
|
|
|
|
|
|
|
if ( len == maxdigits ) { |
|
|
|
|
|
|
|
char const tmp = *ptr; |
|
|
|
|
|
|
|
*ptr = '\0';
|
|
|
|
|
|
|
|
char const* const min = "-9223372036854775808"; |
|
|
|
|
|
|
|
char const* const max = "9223372036854775807"; |
|
|
|
|
|
|
|
char const* const threshold = negative ? min: max; |
|
|
|
|
|
|
|
if ( 0 > strcmp( threshold, value ) ) return 0;
|
|
|
|
|
|
|
|
*ptr = tmp; |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
else if ( _isEndOfPrimitive( *ptr ) ) |
|
|
|
ptr = setToNull( ptr ); |
|
|
|
property->type = JSON_INTEGER; |
|
|
|
|
|
|
|
else return 0; |
|
|
|
|
|
|
|
ptr = _setToNull( ptr ); |
|
|
|
|
|
|
|
return ptr; |
|
|
|
return ptr; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/** Add a property to a JSON object or array.
|
|
|
|
/** Add a property to a JSON object or array.
|
|
|
|
* @param obj The handler of the JSON object or array. |
|
|
|
* @param obj The handler of the JSON object or array. |
|
|
|
* @param property The handler of the property to be added. */ |
|
|
|
* @param property The handler of the property to be added. */ |
|
|
|
static void _add( json_t* obj, json_t* property ) { |
|
|
|
static void add( json_t* obj, json_t* property ) { |
|
|
|
property->sibling = 0; |
|
|
|
property->sibling = 0; |
|
|
|
if ( !obj->u.child ) obj->u.child = property; |
|
|
|
if ( !obj->u.child ) obj->u.child = property; |
|
|
|
else { |
|
|
|
else { |
|
|
@ -293,13 +314,13 @@ static void _add( json_t* obj, json_t* property ) { |
|
|
|
* @param pool The handler of a json pool for creating json instances. |
|
|
|
* @param pool The handler of a json pool for creating json instances. |
|
|
|
* @retval Pointer to first character after the value. If success. |
|
|
|
* @retval Pointer to first character after the value. If success. |
|
|
|
* @retval Null pointer if any error occur. */ |
|
|
|
* @retval Null pointer if any error occur. */ |
|
|
|
static char* _objValue( char* ptr, json_t* obj, jsonPool_t* pool ) { |
|
|
|
static char* objValue( char* ptr, json_t* obj, jsonPool_t* pool ) { |
|
|
|
obj->type = JSON_OBJ; |
|
|
|
obj->type = JSON_OBJ; |
|
|
|
obj->u.child = 0; |
|
|
|
obj->u.child = 0; |
|
|
|
obj->sibling = 0; |
|
|
|
obj->sibling = 0; |
|
|
|
ptr++; |
|
|
|
ptr++; |
|
|
|
for(;;) { |
|
|
|
for(;;) { |
|
|
|
ptr = _goWhiteSpace( ptr ); |
|
|
|
ptr = goBlank( ptr ); |
|
|
|
if ( !ptr ) return 0; |
|
|
|
if ( !ptr ) return 0; |
|
|
|
char const endchar = ( obj->type == JSON_OBJ )? '}': ']'; |
|
|
|
char const endchar = ( obj->type == JSON_OBJ )? '}': ']'; |
|
|
|
if ( *ptr == endchar ) { |
|
|
|
if ( *ptr == endchar ) { |
|
|
@ -312,18 +333,18 @@ static char* _objValue( char* ptr, json_t* obj, jsonPool_t* pool ) { |
|
|
|
continue; |
|
|
|
continue; |
|
|
|
} |
|
|
|
} |
|
|
|
if ( *ptr == ',' ) { |
|
|
|
if ( *ptr == ',' ) { |
|
|
|
ptr = _goWhiteSpace( ++ptr ); |
|
|
|
ptr = goBlank( ++ptr ); |
|
|
|
if ( !ptr ) return 0; |
|
|
|
if ( !ptr ) return 0; |
|
|
|
} |
|
|
|
} |
|
|
|
json_t* property = _poolNew( pool ); |
|
|
|
json_t* property = poolNew( pool ); |
|
|
|
if ( !property ) return 0; |
|
|
|
if ( !property ) return 0; |
|
|
|
if( obj->type != JSON_ARRAY ) { |
|
|
|
if( obj->type != JSON_ARRAY ) { |
|
|
|
if ( *ptr != '\"' ) return 0; |
|
|
|
if ( *ptr != '\"' ) return 0; |
|
|
|
ptr = _propertyName( ptr, property ); |
|
|
|
ptr = propertyName( ptr, property ); |
|
|
|
if ( !ptr ) return 0; |
|
|
|
if ( !ptr ) return 0; |
|
|
|
} |
|
|
|
} |
|
|
|
else property->name = 0; |
|
|
|
else property->name = 0; |
|
|
|
_add( obj, property ); |
|
|
|
add( obj, property ); |
|
|
|
property->u.value = ptr; |
|
|
|
property->u.value = ptr; |
|
|
|
switch( *ptr ) { |
|
|
|
switch( *ptr ) { |
|
|
|
case '{': |
|
|
|
case '{': |
|
|
@ -340,11 +361,11 @@ static char* _objValue( char* ptr, json_t* obj, jsonPool_t* pool ) { |
|
|
|
obj = property; |
|
|
|
obj = property; |
|
|
|
++ptr; |
|
|
|
++ptr; |
|
|
|
break; |
|
|
|
break; |
|
|
|
case '\"': ptr = _textValue( ptr, property ); break; |
|
|
|
case '\"': ptr = textValue( ptr, property ); break; |
|
|
|
case 't': ptr = _trueValue( ptr, property ); break; |
|
|
|
case 't': ptr = trueValue( ptr, property ); break; |
|
|
|
case 'f': ptr = _falseValue( ptr, property ); break; |
|
|
|
case 'f': ptr = falseValue( ptr, property ); break; |
|
|
|
case 'n': ptr = _nullValue( ptr, property ); break; |
|
|
|
case 'n': ptr = nullValue( ptr, property ); break; |
|
|
|
default: ptr = _numValue( ptr, property ); break; |
|
|
|
default: ptr = numValue( ptr, property ); break; |
|
|
|
} |
|
|
|
} |
|
|
|
if ( !ptr ) return 0; |
|
|
|
if ( !ptr ) return 0; |
|
|
|
} |
|
|
|
} |
|
|
@ -353,7 +374,7 @@ static char* _objValue( char* ptr, json_t* obj, jsonPool_t* pool ) { |
|
|
|
/** Initialize a json pool.
|
|
|
|
/** Initialize a json pool.
|
|
|
|
* @param pool The handler of the pool. |
|
|
|
* @param pool The handler of the pool. |
|
|
|
* @return a instace of a json. */ |
|
|
|
* @return a instace of a json. */ |
|
|
|
static json_t* _poolInit( jsonPool_t* pool ) { |
|
|
|
static json_t* poolInit( jsonPool_t* pool ) { |
|
|
|
pool->nextFree = 1; |
|
|
|
pool->nextFree = 1; |
|
|
|
return &pool->mem[0]; |
|
|
|
return &pool->mem[0]; |
|
|
|
} |
|
|
|
} |
|
|
@ -362,7 +383,7 @@ static json_t* _poolInit( jsonPool_t* pool ) { |
|
|
|
* @param pool The handler of the pool. |
|
|
|
* @param pool The handler of the pool. |
|
|
|
* @retval The handler of the new instance if success. |
|
|
|
* @retval The handler of the new instance if success. |
|
|
|
* @retval Null pointer if the pool was empty. */ |
|
|
|
* @retval Null pointer if the pool was empty. */ |
|
|
|
static json_t* _poolNew( jsonPool_t* pool ) { |
|
|
|
static json_t* poolNew( jsonPool_t* pool ) { |
|
|
|
if ( pool->nextFree >= pool->qty ) return 0; |
|
|
|
if ( pool->nextFree >= pool->qty ) return 0; |
|
|
|
return &pool->mem[pool->nextFree++]; |
|
|
|
return &pool->mem[pool->nextFree++]; |
|
|
|
} |
|
|
|
} |
|
|
@ -371,7 +392,7 @@ static json_t* _poolNew( jsonPool_t* pool ) { |
|
|
|
* @param ch Character value to be checked. |
|
|
|
* @param ch Character value to be checked. |
|
|
|
* @param set Set of characters. It is just a null-terminated string. |
|
|
|
* @param set Set of characters. It is just a null-terminated string. |
|
|
|
* @return true or false there is membership or not. */ |
|
|
|
* @return true or false there is membership or not. */ |
|
|
|
static bool _isOneOfThem( char ch, char const* set ) { |
|
|
|
static bool isOneOfThem( char ch, char const* set ) { |
|
|
|
while( *set != '\0' ) |
|
|
|
while( *set != '\0' ) |
|
|
|
if ( ch == *set++ ) |
|
|
|
if ( ch == *set++ ) |
|
|
|
return true; |
|
|
|
return true; |
|
|
@ -382,49 +403,52 @@ static bool _isOneOfThem( char ch, char const* set ) { |
|
|
|
* @param str The initial pointer value. |
|
|
|
* @param str The initial pointer value. |
|
|
|
* @param set Set of characters. It is just a null-terminated string. |
|
|
|
* @param set Set of characters. It is just a null-terminated string. |
|
|
|
* @return The final pointer value or null pointer if the null character was found. */ |
|
|
|
* @return The final pointer value or null pointer if the null character was found. */ |
|
|
|
static char* _goWhile( char* str, char const* set ) { |
|
|
|
static char* goWhile( char* str, char const* set ) { |
|
|
|
for(; *str != '\0'; ++str ) { |
|
|
|
for(; *str != '\0'; ++str ) { |
|
|
|
if ( !_isOneOfThem( *str, set ) ) |
|
|
|
if ( !isOneOfThem( *str, set ) ) |
|
|
|
return str; |
|
|
|
return str; |
|
|
|
} |
|
|
|
} |
|
|
|
return 0; |
|
|
|
return 0; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
static char const* const whitespace = " \n\r\t\f"; |
|
|
|
/** Set of characters that defines a blank. */ |
|
|
|
|
|
|
|
static char const* const blank = " \n\r\t\f"; |
|
|
|
|
|
|
|
|
|
|
|
/** Increases a pointer while it points to a white space character.
|
|
|
|
/** Increases a pointer while it points to a white space character.
|
|
|
|
* @param str The initial pointer value. |
|
|
|
* @param str The initial pointer value. |
|
|
|
* @return The final pointer value or null pointer if the null character was found. */ |
|
|
|
* @return The final pointer value or null pointer if the null character was found. */ |
|
|
|
static char* _goWhiteSpace( char* str ) { |
|
|
|
static char* goBlank( char* str ) { |
|
|
|
return _goWhile( str, whitespace ); |
|
|
|
return goWhile( str, blank ); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/** Checks if a character is a decimal digit. */ |
|
|
|
/** Checks if a character is a decimal digit. */ |
|
|
|
static bool _isNum( unsigned char ch ) { |
|
|
|
static bool isNum( unsigned char ch ) { |
|
|
|
return ch >= '0' && ch <= '9'; |
|
|
|
return ch >= '0' && ch <= '9'; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/** Increases a pointer while it points to a decimal digit character.
|
|
|
|
/** Increases a pointer while it points to a decimal digit character.
|
|
|
|
* @param str The initial pointer value. |
|
|
|
* @param str The initial pointer value. |
|
|
|
* @return The final pointer value or null pointer if the null character was found. */ |
|
|
|
* @return The final pointer value or null pointer if the null character was found. */ |
|
|
|
static char* _goNum( char* str ) { |
|
|
|
static char* goNum( char* str ) { |
|
|
|
for( ; *str != '\0'; ++str ) { |
|
|
|
for( ; *str != '\0'; ++str ) { |
|
|
|
if ( !_isNum( *str ) ) |
|
|
|
if ( !isNum( *str ) ) |
|
|
|
return str; |
|
|
|
return str; |
|
|
|
} |
|
|
|
} |
|
|
|
return 0; |
|
|
|
return 0; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** Set of characters that defines the end of an array or a JSON object. */ |
|
|
|
static char const* const endofblock = "}]"; |
|
|
|
static char const* const endofblock = "}]"; |
|
|
|
|
|
|
|
|
|
|
|
/** Set a char to '\0' and increase its pointer if the char is diferent to '}' or ']'.
|
|
|
|
/** Set a char to '\0' and increase its pointer if the char is diferent to '}' or ']'.
|
|
|
|
* @param ch Pointer to character. |
|
|
|
* @param ch Pointer to character. |
|
|
|
* @return Final value pointer. */ |
|
|
|
* @return Final value pointer. */ |
|
|
|
static char* _setToNull( char* ch ) { |
|
|
|
static char* setToNull( char* ch ) { |
|
|
|
if ( !_isOneOfThem( *ch, endofblock ) ) *ch++ = '\0'; |
|
|
|
if ( !isOneOfThem( *ch, endofblock ) ) *ch++ = '\0'; |
|
|
|
return ch; |
|
|
|
return ch; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
static bool _isEndOfPrimitive( char ch ) { |
|
|
|
/** Indicate if a character is the end of a primitive value. */ |
|
|
|
return ch == ',' || _isOneOfThem( ch, whitespace ) || _isOneOfThem( ch, endofblock );
|
|
|
|
static bool isEndOfPrimitive( char ch ) { |
|
|
|
|
|
|
|
return ch == ',' || isOneOfThem( ch, blank ) || isOneOfThem( ch, endofblock );
|
|
|
|
} |
|
|
|
} |