commit 25a42e388d2c55c45e994c5b4ff516122fad8593
parent 62f9b67456ede24a390d8918d943718a007c2c16
Author: Remy Noulin <loader2x@gmail.com>
Date: Sun, 7 Jul 2019 14:39:55 +0200
add support array and negative indexes in json paths, add isIntOdd, isIntEven, cBa, BSLH and macros for casting numbers (I64, F64,...)
completion.txt | 14 +
documentation.md | 52 +-
release/json/libsheepyCSmallJson.h | 111 ++-
release/libsheepy.c | 2 +-
release/libsheepy.h | 22 +-
release/libsheepyObject.h | 6 +
src/json/libsheepyCSmallJson.c | 1293 +++++++++-----------------------
src/json/libsheepyCSmallJson.h | 111 ++-
src/json/libsheepyCSmallJsonInternal.h | 93 ++-
src/json/libsheepyObjectTest.c | 92 ++-
src/libsheepy.c | 2 +-
src/libsheepy.h | 22 +-
src/libsheepyObject.h | 6 +
13 files changed, 845 insertions(+), 981 deletions(-)
Diffstat:
13 files changed, 845 insertions(+), 981 deletions(-)
diff --git a/completion.txt b/completion.txt
@@ -44,6 +44,16 @@ u32
u64
f32
f64
+I8(value)
+I16(value)
+I32(value)
+I64(value)
+U8(value)
+U16(value)
+U32(value)
+U64(value)
+F32(value)
+F64(value)
MAX(a, b)
MIN(a, b)
MIN3(a, b, c)
@@ -64,6 +74,8 @@ maxV(a, b)
minV(a, b)
absV(a)
FIELD_SIZEOF(t, f)
+isIntOdd(value)
+isIntEven(value)
typ
ret
elif
@@ -2617,6 +2629,7 @@ toUnsignedType(var)
convertToUnsignedType(var)
castS(casted, toCast)
_
+BSLH
ssGet(obj)
sjGet(obj)
replaceSO_max(obj,olds,news)
@@ -2969,6 +2982,7 @@ aLoad(obj)
aCompareExchangeStrong(obj, expected, desired)
aFetchAdd(obj, valueToAdd)
aFetchSub(obj, valueToSub)
+#if (!__OpenBSD__) && ! defined(__TINYC__) && (__GNUC__ > 4)
aStaticArrayT(typeName, element, MAXCOUNT)
aStaticArrayInit(name)
aStaticArrayAcquire(name)
diff --git a/documentation.md b/documentation.md
@@ -73,6 +73,16 @@ u32
u64
f32
f64
+I8(value)
+I16(value)
+I32(value)
+I64(value)
+U8(value)
+U16(value)
+U32(value)
+U64(value)
+F32(value)
+F64(value)
MAX(a, b)
MIN(a, b)
MIN3(a, b, c)
@@ -93,6 +103,8 @@ maxV(a, b)
minV(a, b)
absV(a)
FIELD_SIZEOF(t, f)
+isIntOdd(value)
+isIntEven(value)
typ
ret
elif
@@ -1477,6 +1489,19 @@ extern jmp_buf tryJumpBuffers[maxTryThrowCount];
#define u64 uint64_t
#define f32 float
#define f64 double
+/*
+ * type cast
+ */
+#define I8(value) (i8)(value)
+#define I16(value) (i16)(value)
+#define I32(value) (i32)(value)
+#define I64(value) (i64)(value)
+#define U8(value) (u8)(value)
+#define U16(value) (u16)(value)
+#define U32(value) (u32)(value)
+#define U64(value) (u64)(value)
+#define F32(value) (f32)(value)
+#define F64(value) (f64)(value)
#define MAX(a, b) (((a) > (b)) ? (a) : (b))
#define MIN(a, b) (((a) < (b)) ? (a) : (b))
#define MIN3(a, b, c) MIN((typeof(a))MIN(a, b), c)
@@ -1541,6 +1566,10 @@ extern jmp_buf tryJumpBuffers[maxTryThrowCount];
* declared instance of @t.
*/
#define FIELD_SIZEOF(t, f) (sizeof(((t*)0)->f))
+/** true when value is odd integer */
+#define isIntOdd(value) (value&1)
+/** true when value is even integer */
+#define isIntEven(value) (!(value&1))
/*
* typ definition as alternative to typedef
*/
@@ -16024,6 +16053,7 @@ toUnsignedType(var)
convertToUnsignedType(var)
castS(casted, toCast)
_
+BSLH
ssGet(obj)
sjGet(obj)
replaceSO_max(obj,olds,news)
@@ -16376,6 +16406,7 @@ aLoad(obj)
aCompareExchangeStrong(obj, expected, desired)
aFetchAdd(obj, valueToAdd)
aFetchSub(obj, valueToSub)
+#if (!__OpenBSD__) && ! defined(__TINYC__) && (__GNUC__ > 4)
aStaticArrayT(typeName, element, MAXCOUNT)
aStaticArrayInit(name)
aStaticArrayAcquire(name)
@@ -17209,6 +17240,7 @@ bool areAllEBytes (smallArrayt *self);
Class SmallJson
+enum {KEY_IS_NULL=0, NOT_A_PATH, ARRAY_PATH, DICT_PATH} jsonPathRest;
void free (smallJsont *self);
void terminate (smallJsont **self);
char* toString (smallJsont *self);
@@ -17281,6 +17313,13 @@ smallBoolt* getTopSmallBool (smallJsont *self);
smallDoublet* getTopSmallDouble(smallJsont *self);
smallIntt* getTopSmallInt (smallJsont *self);
smallStringt* getTopSmallString(smallJsont *self);
+jsonPathRest keyIs (smallJsont *self, const char *key);
+const char* keyIsS (smallJsont *self, const char *key);
+char* makeKey (smallJsont *self, const char *key);
+char* iMakeKey (smallJsont *self, char **key);
+char* bMakeKey (smallJsont *self, char *dest, const char *key);
+char* bLMakeKey (smallJsont *self, char *dest, size_t size, const char *key);
+size_t makeKeyLen(smallJsont *self, const char *key);
smallJsont* set (smallJsont *self, const char *key, baset *value);
smallJsont* setUndefined(smallJsont *self, const char *key);
smallJsont* setBool (smallJsont *self, const char *key, bool value);
@@ -52058,11 +52097,7 @@ smallDoublet* duplicateSmallDoubleG (smallDoublet *self);
*/
smallIntt* duplicateSmallInt (smallIntt *self);
smallIntt* duplicateSmallIntG (smallIntt *self);
-/*
- * help text for this class
- * It is public declaration so that child classes can add their help text easily:
- * ret "Child help text \n\n" helpTextSmallJson;
- */
+/* array to convert jsonPathRest to string */
smallJsont* duplicateSmallJson (smallJsont *self);
smallJsont* duplicateSmallJsonG (smallJsont *self);
/*
@@ -52870,14 +52905,14 @@ void disposeSmallDict (smallDictt *self);
* self becomes empty.
*
* Useful when the objects are shared
- */
+ */
void disposeSmallJson (smallJsont *self);
/*
* free index but not the elements
* self becomes empty.
*
* Useful when the objects are shared
- */
+ */
void disposeSmallJson (smallJsont *self);
#define helpO(self) (self)->f->help(self)
#define helpG helpO
@@ -71505,6 +71540,8 @@ smallStringt* insertNFreeSmallString (smallStringt *self, intmax_t index, smallS
* "\"a\".\"bsd\""
*/
#define _ "\""
+/** Back Slash string to escape back slash, use in for example json path with get, set... */
+#define BSLH "\\"
/*
* get a pointer to the string in the smallString object
*
@@ -72748,6 +72785,7 @@ baset *toBaset(smallt *obj);
/*
* base type for atomic staticArrays
*/
+#if (!__OpenBSD__) && ! defined(__TINYC__) && (__GNUC__ > 4)
/*
* declares type for atomic staticArray
*
diff --git a/release/json/libsheepyCSmallJson.h b/release/json/libsheepyCSmallJson.h
@@ -50,6 +50,15 @@ typedef struct smallJson smallJsont;
// for object inheriting smallJson, cast to smallJson to be able to use this class functions and generics
#define cJs(self) ( (smallJsont*) self )
+/** json Path Result
+ * enum type for key type
+ * NOT_A_PATH is a dictionary key
+ */
+typedef enum {KEY_IS_NULL=0, NOT_A_PATH, ARRAY_PATH, DICT_PATH} jsonPathRest;
+
+/** array to convert jsonPathRest to string */
+extern const char *jsonPathResS[];
+
typedef void (*freeSmallJsonFt) (smallJsont *self);
typedef void (*terminateSmallJsonFt) (smallJsont **self);
typedef char* (*toStringSmallJsonFt) (smallJsont *self);
@@ -60,7 +69,7 @@ typedef smallJsont* (*duplicateSmallJsonFt) (smallJsont *self);
* self becomes empty.
*
* Useful when the objects are shared
- */
+ */
typedef void (*disposeSmallJsonFt) (smallJsont *self);
/**
@@ -239,6 +248,99 @@ typedef smallIntt* (*getTopSmallIntSmallJsonFt) (smallJsont *self);
typedef smallStringt* (*getTopSmallStringSmallJsonFt)(smallJsont *self);
/**
+ * keyIs
+ * determine json key type: dictionary key, json path starting from an array or json path starting from a dictionary
+ *
+ * use the jsonPathResS[] array to convert the result to string (or use keyIsS to get the result as string directly)
+ *
+ * \param
+ * key any key or path in self
+ * \return
+ * key type (enum int)
+ * 0 (KEY_IS_NULL in enum) when key is NULL
+ */
+typedef jsonPathRest (*keyIsSmallJsonFt) (smallJsont *self, const char *key);
+
+/**
+ * keyIs returning result as string
+ * determine json key type: dictionary key, json path starting from an array or json path starting from a dictionary
+ *
+ * \param
+ * key any key or path in self
+ * \return
+ * key type
+ * NULL when key is NULL
+ */
+typedef const char* (*keyIsSSmallJsonFt) (smallJsont *self, const char *key);
+
+/**
+ * make json key
+ * escape " and \ characters and add quotes to prevent misinterpreting the key as a json path
+ *
+ * \param
+ * key key to transform
+ * \return
+ * new dictionary key (you must free this buffer)
+ * NULL when key is NULL
+ */
+typedef char* (*makeKeySmallJsonFt) (smallJsont *self, const char *key);
+
+/**
+ * make json key
+ * escape " and \ characters and add quotes to prevent misinterpreting the key as a json path
+ *
+ * \param
+ * key pointer to key to transform (this parameter is reallocated)
+ * \return
+ * new dictionary key (you must free this buffer)
+ * NULL when key is NULL
+ */
+typedef char* (*iMakeKeySmallJsonFt) (smallJsont *self, char **key);
+
+/**
+ * make json key
+ * escape " and \ characters and add quotes to prevent misinterpreting the key as a json path
+ * the result is stored dest, dest must be big enough (at least makeKeyLen+1)
+ *
+ * \param
+ * key key to transform
+ * \param
+ * dest result buffer
+ * \return
+ * dictionary key in dest
+ * NULL when key is NULL
+ */
+typedef char* (*bMakeKeySmallJsonFt) (smallJsont *self, char *dest, const char *key);
+
+/**
+ * make json key
+ * escape " and \ characters and add quotes to prevent misinterpreting the key as a json path
+ * the result is stored dest, dest size must be big enough (at least makeKeyLen+1)
+ *
+ * \param
+ * key key to transform
+ * \param
+ * dest result buffer
+ * \param
+ * size dest buffer size
+ * \return
+ * dictionary key in dest
+ * NULL when key is NULL
+ */
+typedef char* (*bLMakeKeySmallJsonFt) (smallJsont *self, char *dest, size_t size, const char *key);
+
+/**
+ * return key length after running makeKey
+ *
+ * \param
+ * key key to transform
+ * \return
+ * dictionary key length
+ * 0 when key is NULL
+ */
+typedef size_t (*makeKeyLenSmallJsonFt)(smallJsont *self, const char *key);
+
+/**
* set element
*
* When the sObject pointer is updated by realloc, the sObject
@@ -2402,6 +2504,13 @@ typedef bool (*areAllEBytesSmallJsonFt) (smallJsont *self);
getTopSmallDoubleSmallJsonFt getTopSmallDouble;\
getTopSmallIntSmallJsonFt getTopSmallInt;\
getTopSmallStringSmallJsonFt getTopSmallString;\
+ keyIsSmallJsonFt keyIs;\
+ keyIsSSmallJsonFt keyIsS;\
+ makeKeySmallJsonFt makeKey;\
+ iMakeKeySmallJsonFt iMakeKey;\
+ bMakeKeySmallJsonFt bMakeKey;\
+ bLMakeKeySmallJsonFt bLMakeKey;\
+ makeKeyLenSmallJsonFt makeKeyLen;\
setSmallJsonFt set;\
setUndefinedSmallJsonFt setUndefined;\
setBoolSmallJsonFt setBool;\
diff --git a/release/libsheepy.c b/release/libsheepy.c
@@ -54015,10 +54015,10 @@ void scheduler(void) {
+#if ((__GNUC__ > 4))
/**
* return monotonic time in nanoseconds
*/
-#if ((__GNUC__ > 4))
uint64_t getMonotonicTime(void) {
struct timespec ts;
diff --git a/release/libsheepy.h b/release/libsheepy.h
@@ -96,7 +96,7 @@
// version accoring to the version package: Release.Major.minor.patch
// https://noulin.net/version/file/README.md.html
-#define LIBSHEEPY_VERSION "1.0.5.1"
+#define LIBSHEEPY_VERSION "1.0.6"
#ifndef SH_PREFIX
#define SH_PREFIX(NAME) NAME
@@ -301,6 +301,20 @@ extern jmp_buf tryJumpBuffers[maxTryThrowCount];
#define f32 float
#define f64 double
+/**
+ * type cast
+ */
+#define I8(value) (i8)(value)
+#define I16(value) (i16)(value)
+#define I32(value) (i32)(value)
+#define I64(value) (i64)(value)
+#define U8(value) (u8)(value)
+#define U16(value) (u16)(value)
+#define U32(value) (u32)(value)
+#define U64(value) (u64)(value)
+#define F32(value) (f32)(value)
+#define F64(value) (f64)(value)
+
#define MAX(a, b) (((a) > (b)) ? (a) : (b))
#define MIN(a, b) (((a) < (b)) ? (a) : (b))
#define MIN3(a, b, c) MIN((typeof(a))MIN(a, b), c)
@@ -401,6 +415,12 @@ extern jmp_buf tryJumpBuffers[maxTryThrowCount];
*/
#define FIELD_SIZEOF(t, f) (sizeof(((t*)0)->f))
+/** true when value is odd integer */
+#define isIntOdd(value) (value&1)
+
+/** true when value is even integer */
+#define isIntEven(value) (!(value&1))
+
/**
* typ definition as alternative to typedef
*/
diff --git a/release/libsheepyObject.h b/release/libsheepyObject.h
@@ -8349,6 +8349,9 @@ void finishManyOF(void *paramType, ...);
*/
typedef struct base baset;
+// for object inheriting baset, cast to baset to be able to use this class functions and generics
+#define cBa(self) ( (baset*) self )
+
// Functions
/**
@@ -8551,6 +8554,9 @@ extern smallContainert* rtSmallContainert;
*/
#define _ "\""
+/** Back Slash string to escape back slash, use in for example json path with get, set... */
+#define BSLH "\\"
+
/**
* get a pointer to the string in the smallString object
*
diff --git a/src/json/libsheepyCSmallJson.c b/src/json/libsheepyCSmallJson.c
@@ -123,6 +123,15 @@ internal smallBoolt* getTopSmallBoolSmallJson(smallJsont *self);
internal smallDoublet* getTopSmallDoubleSmallJson(smallJsont *self);
internal smallIntt* getTopSmallIntSmallJson(smallJsont *self);
internal smallStringt* getTopSmallStringSmallJson(smallJsont *self);
+internal bool isPythonIndex(const char *start, size_t len);
+internal jsonPathRest keyIsSmallJson(smallJsont *self UNUSED, const char *key);
+internal const char* keyIsSSmallJson(smallJsont *self UNUSED, const char *key);
+internal char* makeKeySmallJson(smallJsont *self UNUSED, const char *key);
+internal char* iMakeKeySmallJson(smallJsont *self UNUSED, char **key);
+internal char* bMakeKeySmallJson(smallJsont *self UNUSED, char *dest, const char *key);
+internal char* bLMakeKeySmallJson(smallJsont *self UNUSED, char *dest, size_t size, const char *key);
+internal size_t makeKeyLenSmallJson(smallJsont *self UNUSED, const char *key);
+internal void unescapeKey(char *dest, char *key, size_t length);
internal smallJsont* setSmallJson(smallJsont *self, const char *key, baset *value);
internal smallJsont* setUndefinedSmallJson(smallJsont *self, const char *key);
internal smallJsont* setBoolSmallJson(smallJsont *self, const char *key, bool value);
@@ -1571,6 +1580,8 @@ bool appendTextJsonSmallJsonG(smallJsont *self, smallJsont *filePath);
enum {SMALLJSON_IS_EMPTY, TOP_IS_UNDEFINED, TOP_IS_BOOL, TOP_IS_DOUBLE, TOP_IS_INT, TOP_IS_STRING, TOP_IS_DICT, TOP_IS_ARRAY};
+const char *jsonPathResS[] = {"KEY_IS_NULL", "NOT_A_PATH", "ARRAY_PATH", "DICT_PATH", NULL};
+
#define eprintf shEPrintfS
void initiateSmallJson(smallJsont *self) {
@@ -1670,6 +1681,13 @@ void registerMethodsSmallJson(smallJsonFunctionst *f) {
f->getTopSmallDouble = getTopSmallDoubleSmallJson;
f->getTopSmallInt = getTopSmallIntSmallJson;
f->getTopSmallString = getTopSmallStringSmallJson;
+ f->keyIs = keyIsSmallJson;
+ f->keyIsS = keyIsSSmallJson;
+ f->makeKey = makeKeySmallJson;
+ f->iMakeKey = iMakeKeySmallJson;
+ f->bMakeKey = bMakeKeySmallJson;
+ f->bLMakeKey = bLMakeKeySmallJson;
+ f->makeKeyLen = makeKeyLenSmallJson;
f->set = setSmallJson;
f->setUndefined = setUndefinedSmallJson;
f->setBool = setBoolSmallJson;
@@ -3516,1034 +3534,541 @@ internal smallStringt* getTopSmallStringSmallJson(smallJsont *self) {
}
-internal smallJsont* setSmallJson(smallJsont *self, const char *key, baset *value) {
- smallt *o = NULL;
-
- if (self->topIsA != SMALLJSON_IS_EMPTY && self->topIsA != TOP_IS_DICT) {
- return(NULL);
- }
-
- if (!key) {
- return(NULL);
- }
+internal bool isPythonIndex(const char *start, size_t len) {
- switch(self->topIsA) {
- case SMALLJSON_IS_EMPTY:
- self->topIsA = TOP_IS_DICT;
- case TOP_IS_DICT:
- if (!value) {
- o = (smallt *)allocSUndefined();
- }
- else {
- o = toSmallt(value);
- }
- setJsonPath;
- break;
- }
- return(self);
+ char s[len+1];
+ memcpy(s, start, len);
+ s[len] = 0;
+ return(isInt(s));
}
-internal smallJsont* setUndefinedSmallJson(smallJsont *self, const char *key) {
- smallt *o = NULL;
-
- if (self->topIsA != SMALLJSON_IS_EMPTY && self->topIsA != TOP_IS_DICT) {
- return(NULL);
- }
+internal jsonPathRest keyIsSmallJson(smallJsont *self UNUSED, const char *key) {
if (!key) {
- return(NULL);
- }
+ return(KEY_IS_NULL);
+ }
+
+ /* detect if key is a dict key or a path */
+ /* path must start with " or [ */
+ /* the chars between [ and ] must be integers */
+ /* key chars must be surrounded with " */
+ /* invalid path are dict keys */
+ /* escape \" \\ */
+
+ jsonPathRest keyIs = NOT_A_PATH;
+
+ enum {SEARCH, IN_STRING, IN_INDEX};
+ int state = SEARCH;
+
+ if (key[0]=='"' || key[0]=='[') {
+ /* path must start with " or [ */
+ bool escape = false;
+ const char *start = NULL;
+ size_t startIdx = 0;
+ for (size_t i = 0 ; key[i] ; i++) {
+ if (escape) {
+ escape = false;
+ continue;
+ }
+
+ switch (key[i]) {
+ case '"':
+ /* key chars must be surrounded with " */
+ switch(state) {
+ case SEARCH:
+ state = IN_STRING;
+ break;
+ case IN_STRING:
+ state = SEARCH;
+ break;
+ default:
+ goto endKeyParse;
+ }
+ break;
+ case '[':
+ switch(state) {
+ case SEARCH:
+ state = IN_INDEX;
+ start = &key[i+1];
+ startIdx = i+1;
+ break;
+ case IN_INDEX:
+ /* 2 [ following each other, not a path */
+ goto endKeyParse;
+ }
+ break;
+ case ']':
+ switch(state) {
+ case IN_INDEX:
+ state = SEARCH;
+ /* check if there is an int between the [] */
+ if (!isPythonIndex(start, i-startIdx)) {
+ goto endKeyParse;
+ }
+ break;
+ case SEARCH:
+ /* missing [, not a path */
+ goto endKeyParse;
+ }
+ break;
+ default:
+ switch(state) {
+ case SEARCH:
+ if (key[i]!='.') {
+ goto endKeyParse;
+ }
+ break;
+ case IN_INDEX:
+ /* the chars between [ and ] must be integers */
+ if (!isdigit(key[i]) && key[i]!=']' && key[i]!='-') {
+ goto endKeyParse;
+ }
+ break;
+ case IN_STRING:
+ /* escape \" \\ */
+ if (key[i]=='\\') {
+ escape = true;
+ }
+ break;
+ }
+ break;
+ }
+ }
- switch(self->topIsA) {
- case SMALLJSON_IS_EMPTY:
- self->topIsA = TOP_IS_DICT;
- case TOP_IS_DICT:
- o = (smallt *) allocSUndefined();
- setJsonPath;
- break;
+ if (state==SEARCH) {
+ /* all path elements must be closed */
+ switch(key[0]) {
+ case '"':
+ keyIs = DICT_PATH;
+ break;
+ case '[':
+ keyIs = ARRAY_PATH;
+ break;
+ }
}
- return(self);
-}
+ }
-internal smallJsont* setBoolSmallJson(smallJsont *self, const char *key, bool value) {
- smallt *o = NULL;
+ endKeyParse:
+ return(keyIs);
+}
- if (self->topIsA != SMALLJSON_IS_EMPTY && self->topIsA != TOP_IS_DICT) {
- return(NULL);
- }
+internal const char* keyIsSSmallJson(smallJsont *self UNUSED, const char *key) {
if (!key) {
return(NULL);
}
- switch(self->topIsA) {
- case SMALLJSON_IS_EMPTY:
- self->topIsA = TOP_IS_DICT;
- case TOP_IS_DICT:
- o = (smallt *) allocSBool(value);
- setJsonPath;
- break;
- }
- return(self);
-}
+ jsonPathRest keyIs = keyIsSmallJson(self, key);
-internal smallJsont* setDoubleSmallJson(smallJsont *self, const char *key, double value) {
- smallt *o = NULL;
+ return(jsonPathResS[keyIs]);
+}
- if (self->topIsA != SMALLJSON_IS_EMPTY && self->topIsA != TOP_IS_DICT) {
- return(NULL);
- }
+internal char* makeKeySmallJson(smallJsont *self UNUSED, const char *key) {
if (!key) {
return(NULL);
}
- switch(self->topIsA) {
- case SMALLJSON_IS_EMPTY:
- self->topIsA = TOP_IS_DICT;
- case TOP_IS_DICT:
- o = (smallt *) allocSDouble(value);
- setJsonPath;
- break;
- }
- return(self);
-}
-
-internal smallJsont* setIntSmallJson(smallJsont *self, const char *key, int64_t value) {
- smallt *o = NULL;
-
- if (self->topIsA != SMALLJSON_IS_EMPTY && self->topIsA != TOP_IS_DICT) {
- return(NULL);
- }
+ char *r = strdup(_);
- if (!key) {
- return(NULL);
+ for (size_t i = 0 ; key[i] ; i++) {
+ if (key[i]=='"' || key[i]=='\\') {
+ iAppendS(&r, BSLH);
+ }
+ iAppendCharS(&r, key[i]);
}
- switch(self->topIsA) {
- case SMALLJSON_IS_EMPTY:
- self->topIsA = TOP_IS_DICT;
- case TOP_IS_DICT:
- o = (smallt *) allocSInt(value);
- setJsonPath;
- break;
- }
- return(self);
+ // close quote
+ iAppendS(&r, _);
+ return(r);
}
-internal smallJsont* setSSmallJson(smallJsont *self, const char *key, const char *string) {
- smallt *o = NULL;
-
- if (self->topIsA != SMALLJSON_IS_EMPTY && self->topIsA != TOP_IS_DICT) {
- return(NULL);
- }
+internal char* iMakeKeySmallJson(smallJsont *self UNUSED, char **key) {
- if (!key) {
+ if (!key && !*key) {
return(NULL);
}
- if (!string) {
- // set empty string when NULL
- o = (smallt *) allocSStringTiny("");
- }
- else {
- o = (smallt *) allocSStringTiny(string);
- }
-
- switch(self->topIsA) {
- case SMALLJSON_IS_EMPTY:
- self->topIsA = TOP_IS_DICT;
- case TOP_IS_DICT:
- setJsonPath;
- break;
- }
- return(self);
+ char *r = makeKeySmallJson(self, *key);
+ free(*key);
+ *key = r;
+ return(r);
}
-internal smallJsont* setCharSmallJson(smallJsont *self, const char *key, char c) {
+internal char* bMakeKeySmallJson(smallJsont *self UNUSED, char *dest, const char *key) {
- if (self->topIsA != SMALLJSON_IS_EMPTY && self->topIsA != TOP_IS_DICT) {
+ if (!key || !dest) {
return(NULL);
}
- if (!key) {
- return(NULL);
+ size_t di = 0;
+ dest[di++] = '"';
+
+ for (size_t i = 0 ; key[i] ; i++) {
+ if (key[i]=='"' || key[i]=='\\') {
+ dest[di++] = '\\';
+ }
+ dest[di++] = key[i];
}
- charToS(s, c);
- return(setSSmallJson(self, key, s));
+ // close quote
+ dest[di++] = '"';
+ dest[di] = 0;
+ return(dest);
}
-internal smallJsont* setDictSmallJson(smallJsont *self, const char *key, smallDictt *dict) {
- smallt *o = NULL;
+internal char* bLMakeKeySmallJson(smallJsont *self UNUSED, char *dest, size_t size, const char *key) {
- if (self->topIsA != SMALLJSON_IS_EMPTY && self->topIsA != TOP_IS_DICT) {
+ if (!key || !dest || !size) {
return(NULL);
}
- if (!key) {
+ if (makeKeyLenSmallJson(self, key)+1 > size) {
return(NULL);
}
- if (checkObjectTypes && dict && !isOSmallDict(dict)) {
+ size_t di = 0;
+ dest[di++] = '"';
+ if (di >= size) {
return(NULL);
}
- if (!dict) {
- o = (smallt *) allocSDict();
- }
- else {
- if (!dict->d) {
- dict->d = allocSDict();
+ for (size_t i = 0 ; key[i] ; i++) {
+ if (key[i]=='"' || key[i]=='\\') {
+ dest[di++] = '\\';
+ if (di >= size) {
+ return(NULL);
}
- o = (smallt *)dict->d;
+ }
+ dest[di++] = key[i];;
+ if (di >= size) {
+ return(NULL);
}
+ }
- switch(self->topIsA) {
- case SMALLJSON_IS_EMPTY:
- self->topIsA = TOP_IS_DICT;
- case TOP_IS_DICT:
- setJsonPath;
- break;
+ // close quote
+ dest[di++] = '"';
+ if (di >= size) {
+ return(NULL);
}
- return(self);
+ dest[di] = 0;
+ return(dest);
}
-internal smallJsont* setArraySmallJson(smallJsont *self, const char *key, smallArrayt *array) {
- smallt *o = NULL;
-
- if (self->topIsA != SMALLJSON_IS_EMPTY && self->topIsA != TOP_IS_DICT) {
- return(NULL);
- }
+internal size_t makeKeyLenSmallJson(smallJsont *self UNUSED, const char *key) {
if (!key) {
- return(NULL);
+ return(0);
}
- if (checkObjectTypes && array && !isOSmallArray(array)) {
- return(NULL);
- }
+ size_t r = 1;
- if (!array) {
- o = (smallt *) allocSArray();
- }
- else {
- if (!array->a) {
- // allocate empty array
- array->a = allocSArray();
+ for (size_t i = 0 ; key[i] ; i++) {
+ if (key[i]=='"' || key[i]=='\\') {
+ r++;
}
- o = (smallt *)array->a;
+ r++;
}
- switch(self->topIsA) {
- case SMALLJSON_IS_EMPTY:
- self->topIsA = TOP_IS_DICT;
- case TOP_IS_DICT:
- setJsonPath;
- break;
- }
- return(self);
+ // close quote
+ r++;
+ return(r);
}
-internal smallJsont* setArraycSmallJson(smallJsont *self, const char *key, char **array) {
- smallt *o = NULL;
+internal void unescapeKey(char *dest, char *key, size_t length) {
- if (self->topIsA != SMALLJSON_IS_EMPTY && self->topIsA != TOP_IS_DICT) {
- return(NULL);
+ bool skipped = false;
+ size_t j = 0;
+ range(i, length) {
+ if (skipped) {
+ skipped = false;
+ if (key[i-1] == '\\') {
+ goto keepBackSlash;
+ }
+ }
+ if (key[i] == '\\' && !skipped) {
+ skipped = true;
+ }
+ keepBackSlash:
+ if (!skipped) {
+ dest[j++] = key[i];
+ }
}
+ dest[j] = 0;
+}
- if (!key) {
- return(NULL);
- }
- if (!array) {
- o = (smallt *) allocSArray();
- }
- else {
- sArrayt *a = allocSArray();
- forEachCharP(array, e) {
- sStringt *s = allocSStringTiny(*e);
- sArrayPushTiny(&a, (smallt *) s);
- }
- o = (smallt *)a;
- }
+internal smallJsont* setSmallJson(smallJsont *self, const char *key, baset *value) {
- switch(self->topIsA) {
- case SMALLJSON_IS_EMPTY:
- self->topIsA = TOP_IS_DICT;
- case TOP_IS_DICT:
- setJsonPath;
- break;
- }
- return(self);
+ mainSetJsonPath(/*initValue*/, o=!value?(smallt*)allocSUndefined():toSmallt(value)/*allocValue*/, setJsonPath/*subSetJsonPath*/);
+ // cg_c bug
}
-internal smallJsont* setSmallBoolSmallJson(smallJsont *self, const char *key, smallBoolt *value) {
- smallt *o = NULL;
+internal smallJsont* setUndefinedSmallJson(smallJsont *self, const char *key) {
- if (self->topIsA != SMALLJSON_IS_EMPTY && self->topIsA != TOP_IS_DICT) {
- return(NULL);
- }
+ mainSetJsonPath(/*initValue*/, o=(smallt*)allocSUndefined()/*allocValue*/, setJsonPath/*subSetJsonPath*/);
+ // cg_c bug
+}
- if (!key) {
- return(NULL);
- }
+internal smallJsont* setBoolSmallJson(smallJsont *self, const char *key, bool value) {
- if (checkObjectTypes && value && !isOSmallBool(value)) {
- return(NULL);
- }
+ mainSetJsonPath(/*initValue*/, o=(smallt*)allocSBool(value)/*allocValue*/, setJsonPath/*subSetJsonPath*/);
+ // cg_c bug
+}
- if (!value) {
- o = (smallt *) allocSUndefined();
- }
- else {
- o = (smallt *) value->value;
- }
+internal smallJsont* setDoubleSmallJson(smallJsont *self, const char *key, double value) {
- switch(self->topIsA) {
- case SMALLJSON_IS_EMPTY:
- self->topIsA = TOP_IS_DICT;
- case TOP_IS_DICT:
- setJsonPath;
- break;
- }
- return(self);
+ mainSetJsonPath(/*initValue*/, o=(smallt*)allocSDouble(value)/*allocValue*/, setJsonPath/*subSetJsonPath*/);
+ // cg_c bug
}
-internal smallJsont* setSmallBytesSmallJson(smallJsont *self, const char *key, smallBytest *value) {
- smallt *o = NULL;
+internal smallJsont* setIntSmallJson(smallJsont *self, const char *key, int64_t value) {
- if (self->topIsA != SMALLJSON_IS_EMPTY && self->topIsA != TOP_IS_DICT) {
- return(NULL);
- }
+ mainSetJsonPath(/*initValue*/, o=(smallt*)allocSInt(value)/*allocValue*/, setJsonPath/*subSetJsonPath*/);
+ // cg_c bug
+}
- if (!key) {
- return(NULL);
- }
+internal smallJsont* setSSmallJson(smallJsont *self, const char *key, const char *string) {
- if (checkObjectTypes && value && !isOSmallBytes(value)) {
- return(NULL);
- }
+ mainSetJsonPath(o=!string?/*set empty string when NULL*/(smallt*)allocSStringTiny(""):(smallt*)allocSStringTiny(string)/*initValue*/, /*allocValue*/, setJsonPath/*subSetJsonPath*/);
+ // cg_c bug
+}
- if (!value || !value->B) {
- o = (smallt *) allocSUndefined();
- }
- else {
- o = (smallt *) value->B;
- }
+internal smallJsont* setCharSmallJson(smallJsont *self, const char *key, char c) {
- switch(self->topIsA) {
- case SMALLJSON_IS_EMPTY:
- self->topIsA = TOP_IS_DICT;
- case TOP_IS_DICT:
- setJsonPath;
- break;
- }
- return(self);
+ charToS(s, c);
+ return(setSSmallJson(self, key, s));
}
-internal smallJsont* setSmallDoubleSmallJson(smallJsont *self, const char *key, smallDoublet *value) {
- smallt *o = NULL;
-
- if (self->topIsA != SMALLJSON_IS_EMPTY && self->topIsA != TOP_IS_DICT) {
- return(NULL);
- }
-
- if (!key) {
- return(NULL);
- }
+internal smallJsont* setDictSmallJson(smallJsont *self, const char *key, smallDictt *dict) {
- if (checkObjectTypes && value && !isOSmallDouble(value)) {
- return(NULL);
- }
+ mainSetJsonPath(if (checkObjectTypes && dict && !isOSmallDict(dict)) return NULL;if (!dict) o = (smallt *) allocSDict(); else{if (!dict->d) dict->d = allocSDict();o = (smallt *)dict->d;}/*initValue*/,/*allocValue*/, setJsonPath/*subSetJsonPath*/);
+ // cg_c bug
+}
- if (!value) {
- o = (smallt *) allocSUndefined();
- }
- else {
- o = (smallt *) value->value;
- }
+internal smallJsont* setArraySmallJson(smallJsont *self, const char *key, smallArrayt *array) {
- switch(self->topIsA) {
- case SMALLJSON_IS_EMPTY:
- self->topIsA = TOP_IS_DICT;
- case TOP_IS_DICT:
- setJsonPath;
- break;
- }
- return(self);
+ mainSetJsonPath(if (checkObjectTypes && array && !isOSmallArray(array)) return NULL; if (!array) o = (smallt *) allocSArray(); else {if (!array->a) /*allocate empty array*/ array->a = allocSArray(); o = (smallt *)array->a;}/*initValue*/, /*allocValue*/, setJsonPath/*subSetJsonPath*/);
+ // cg_c bug
}
-internal smallJsont* setSmallIntSmallJson(smallJsont *self, const char *key, smallIntt *value) {
- smallt *o = NULL;
+internal smallJsont* setArraycSmallJson(smallJsont *self, const char *key, char **array) {
- if (self->topIsA != SMALLJSON_IS_EMPTY && self->topIsA != TOP_IS_DICT) {
- return(NULL);
- }
+ mainSetJsonPath(if (!array) o = (smallt *) allocSArray(); else {sArrayt *a = allocSArray();forEachCharP(array, e){sStringt *s = allocSStringTiny(*e);sArrayPushTiny(&a, (smallt *) s);}o = (smallt *)a;}/*initValue*/, /*allocValue*/, setJsonPath/*subSetJsonPath*/);
+ // cg_c bug
+}
- if (!key) {
- return(NULL);
- }
+internal smallJsont* setSmallBoolSmallJson(smallJsont *self, const char *key, smallBoolt *value) {
- if (checkObjectTypes && value && !isOSmallInt(value)) {
- return(NULL);
- }
+ mainSetJsonPath(if (checkObjectTypes && value && !isOSmallBool(value)) return NULL; o = !value?(smallt*)allocSUndefined():(smallt*)value->value/*initValue*/, /*allocValue*/, setJsonPath/*subSetJsonPath*/);
+ // cg_c bug
+}
- if (!value) {
- o = (smallt *) allocSUndefined();
- }
- else {
- o = (smallt *) value->value;
- }
+internal smallJsont* setSmallBytesSmallJson(smallJsont *self, const char *key, smallBytest *value) {
- switch(self->topIsA) {
- case SMALLJSON_IS_EMPTY:
- self->topIsA = TOP_IS_DICT;
- case TOP_IS_DICT:
- setJsonPath;
- break;
- }
- return(self);
+ mainSetJsonPath(if (checkObjectTypes && value && !isOSmallBytes(value)) return NULL; o = (!value||!value->B)?(smallt*)allocSUndefined():(smallt*)value->B/*initValue*/, /*allocValue*/, setJsonPath/*subSetJsonPath*/);
+ // cg_c bug
}
-internal smallJsont* setSmallJsonSmallJson(smallJsont *self, const char *key, smallJsont *value) {
-
- if (self->topIsA != SMALLJSON_IS_EMPTY && self->topIsA != TOP_IS_DICT) {
- return(NULL);
- }
+internal smallJsont* setSmallDoubleSmallJson(smallJsont *self, const char *key, smallDoublet *value) {
- if (!key) {
- return(NULL);
- }
+ mainSetJsonPath(if (checkObjectTypes && value && !isOSmallDouble(value)) return NULL; o = !value?(smallt*)allocSUndefined():(smallt*)value->value/*initValue*/, /*allocValue*/, setJsonPath/*subSetJsonPath*/);
+ // cg_c bug
+}
- if (checkObjectTypes && value && !isOSmallJson(value)) {
- return(NULL);
- }
+internal smallJsont* setSmallIntSmallJson(smallJsont *self, const char *key, smallIntt *value) {
- smallt *o;
- if (!value) {
- o = (smallt *) allocSUndefined();
- }
- else {
- switch(value->topIsA){
- case SMALLJSON_IS_EMPTY:
- o = (smallt *) allocSUndefined();
- break;
- case TOP_IS_UNDEFINED:
- o = (smallt *) value->topU;
- break;
- case TOP_IS_BOOL:
- o = (smallt *) value->topB;
- break;
- case TOP_IS_DOUBLE:
- o = (smallt *) value->topD;
- break;
- case TOP_IS_INT:
- o = (smallt *) value->topI;
- break;
- case TOP_IS_STRING:
- o = (smallt *) value->topS;
- break;
- case TOP_IS_DICT:
- o = (smallt *) value->top;
- break;
- case TOP_IS_ARRAY:
- o = (smallt *) value->topA;
- break;
- }
- }
+ mainSetJsonPath(if (checkObjectTypes && value && !isOSmallInt(value)) return NULL; o = !value?(smallt*)allocSUndefined():(smallt*)value->value/*initValue*/, /*allocValue*/, setJsonPath/*subSetJsonPath*/);
+ // cg_c bug
+}
- switch(self->topIsA) {
- case SMALLJSON_IS_EMPTY:
- self->topIsA = TOP_IS_DICT;
- case TOP_IS_DICT:
- setJsonPath;
- break;
- }
+internal smallJsont* setSmallJsonSmallJson(smallJsont *self, const char *key, smallJsont *value) {
- return(self);
+ mainSetJsonPath(if (checkObjectTypes && value && !isOSmallJson(value)) return NULL; if (!value) o = (smallt *) allocSUndefined(); else {switch(value->topIsA){case SMALLJSON_IS_EMPTY:o = (smallt *) allocSUndefined();break;case TOP_IS_UNDEFINED:o = (smallt *) value->topU;break;case TOP_IS_BOOL:o = (smallt *) value->topB;break;case TOP_IS_DOUBLE:o = (smallt *) value->topD;break;case TOP_IS_INT:o = (smallt *) value->topI;break;case TOP_IS_STRING:o = (smallt *) value->topS;break;case TOP_IS_DICT:o = (smallt *) value->top;break;case TOP_IS_ARRAY:o = (smallt *) value->topA;break;}}/*initValue*/, /*allocValue*/, setJsonPath/*subSetJsonPath*/);
+ // cg_c bug
}
internal smallJsont* setSmallStringSmallJson(smallJsont *self, const char *key, smallStringt *string) {
- smallt *o = NULL;
-
- if (self->topIsA != SMALLJSON_IS_EMPTY && self->topIsA != TOP_IS_DICT) {
- return(NULL);
- }
-
- if (!key) {
- return(NULL);
- }
-
- if (checkObjectTypes && string && !isOSmallString(string)) {
- return(NULL);
- }
-
- if (!string || !string->data) {
- o = (smallt *) allocSStringTiny("");
- }
- else {
- o = (smallt *) string->data;
- }
- switch(self->topIsA) {
- case SMALLJSON_IS_EMPTY:
- self->topIsA = TOP_IS_DICT;
- case TOP_IS_DICT:
- setJsonPath;
- break;
- }
- return(self);
+ mainSetJsonPath(if (checkObjectTypes && string && !isOSmallString(string)) return NULL; o = (!string||!string->data)?(smallt*)allocSUndefined():(smallt*)string->data/*initValue*/, /*allocValue*/, setJsonPath/*subSetJsonPath*/);
+ // cg_c bug
}
internal smallJsont* setSmallContainerSmallJson(smallJsont *self, const char *key, smallContainert *container) {
- smallt *o = NULL;
-
- if (self->topIsA != SMALLJSON_IS_EMPTY && self->topIsA != TOP_IS_DICT) {
- return(NULL);
- }
-
- if (!key) {
- return(NULL);
- }
-
- if (checkObjectTypes && container && !isOSmallContainer(container)) {
- return(NULL);
- }
-
- if (!container) {
- o = (smallt *) allocSUndefined();
- }
- else {
- if (!container->data) {
- o = (smallt *) allocSContainer(NULL);
- }
- else {
- o = (smallt *) container->data;
- }
- }
- switch(self->topIsA) {
- case SMALLJSON_IS_EMPTY:
- self->topIsA = TOP_IS_DICT;
- case TOP_IS_DICT:
- setJsonPath;
- break;
- }
- return(self);
+ mainSetJsonPath(if (checkObjectTypes && container && !isOSmallContainer(container)) return NULL; if (!container) o = (smallt *) allocSUndefined(); else {if (!container->data) o = (smallt *) allocSContainer(NULL); else o = (smallt *) container->data;}/*initValue*/, /*allocValue*/, setJsonPath/*subSetJsonPath*/);
+ // cg_c bug
}
internal smallJsont* setNFreeSmallJson(smallJsont *self, const char *key, baset *value) {
- if (self->topIsA != SMALLJSON_IS_EMPTY && self->topIsA != TOP_IS_DICT) {
- return(NULL);
+ smallJsont *r = setSmallJson(self, key, value);
+ if (r) {
+ /* free parameter only when successfully stored in self */
+ finishO(value);
}
-
- setSmallJson(self, key, value);
- finishO(value);
return(self);
}
internal smallJsont* setNFreeUndefinedSmallJson(smallJsont *self, const char *key, undefinedt *undefined) {
- if (self->topIsA != SMALLJSON_IS_EMPTY && self->topIsA != TOP_IS_DICT) {
- return(NULL);
+ smallJsont *r = setUndefinedSmallJson(self, key);
+ if (r) {
+ /* free parameter only when successfully stored in self */
+ terminateO(undefined);
}
-
- setUndefinedSmallJson(self, key);
- terminateO(undefined);
return(self);
}
internal smallJsont* setNFreeSSmallJson(smallJsont *self, const char *key, char *string) {
- if (self->topIsA != SMALLJSON_IS_EMPTY && self->topIsA != TOP_IS_DICT) {
- return(NULL);
+ smallJsont *r = setSSmallJson(self, key, string);
+ if (r) {
+ /* free parameter only when successfully stored in self */
+ free(string);
}
-
- setSSmallJson(self, key, string);
- free(string);
return(self);
}
internal smallJsont* setNFreeDictSmallJson(smallJsont *self, const char *key, smallDictt *dict) {
- if (self->topIsA != SMALLJSON_IS_EMPTY && self->topIsA != TOP_IS_DICT) {
- return(NULL);
- }
-
smallJsont *r = setDictSmallJson(self, key, dict);
if (r) {
+ /* free parameter only when successfully stored in self */
finishO(dict);
}
- else {
- terminateO(dict);
- }
return(r);
}
internal smallJsont* setNFreeArraySmallJson(smallJsont *self, const char *key, smallArrayt *array) {
- if (self->topIsA != SMALLJSON_IS_EMPTY && self->topIsA != TOP_IS_DICT) {
- return(NULL);
- }
-
smallJsont *r = setArraySmallJson(self, key, array);
if (r) {
+ /* free parameter only when successfully stored in self */
finishO(array);
}
- else {
- terminateO(array);
- }
return(r);
}
internal smallJsont* setNFreeArraycSmallJson(smallJsont *self, const char *key, char **array) {
- if (self->topIsA != SMALLJSON_IS_EMPTY && self->topIsA != TOP_IS_DICT) {
- return(NULL);
+ smallJsont *r = setArraycSmallJson(self, key, array);
+ if (r) {
+ listFreeS(array);
}
-
- setArraycSmallJson(self, key, array);
- listFreeS(array);
return(self);
}
internal smallJsont* setNFreeSmallBoolSmallJson(smallJsont *self, const char *key, smallBoolt *value) {
- if (self->topIsA != SMALLJSON_IS_EMPTY && self->topIsA != TOP_IS_DICT) {
- return(NULL);
- }
-
smallJsont *r = setSmallBoolSmallJson(self, key, value);
if (r) {
finishO(value);
}
- else {
- terminateO(value);
- }
return(r);
}
internal smallJsont* setNFreeSmallBytesSmallJson(smallJsont *self, const char *key, smallBytest *value) {
- if (self->topIsA != SMALLJSON_IS_EMPTY && self->topIsA != TOP_IS_DICT) {
- return(NULL);
- }
-
smallJsont *r = setSmallBytesSmallJson(self, key, value);
if (r) {
finishO(value);
}
- else {
- terminateO(value);
- }
return(r);
}
internal smallJsont* setNFreeSmallDoubleSmallJson(smallJsont *self, const char *key, smallDoublet *value) {
- if (self->topIsA != SMALLJSON_IS_EMPTY && self->topIsA != TOP_IS_DICT) {
- return(NULL);
- }
-
smallJsont *r = setSmallDoubleSmallJson(self, key, value);
if (r) {
finishO(value);
}
- else {
- terminateO(value);
- }
return(r);
}
internal smallJsont* setNFreeSmallIntSmallJson(smallJsont *self, const char *key, smallIntt *value) {
- if (self->topIsA != SMALLJSON_IS_EMPTY && self->topIsA != TOP_IS_DICT) {
- return(NULL);
- }
-
- smallJsont *r = setSmallIntSmallJson(self, key, value);
- if (r) {
- finishO(value);
- }
- else {
- terminateO(value);
- }
- return(r);
-}
-
-internal smallJsont* setNFreeSmallJsonSmallJson(smallJsont *self, const char *key, smallJsont *value) {
-
- if (self->topIsA != SMALLJSON_IS_EMPTY && self->topIsA != TOP_IS_DICT) {
- return(NULL);
- }
-
- smallJsont *r = setSmallJsonSmallJson(self, key, value);
- if (r) {
- finishO(value);
- }
- else {
- terminateO(value);
- }
- return(r);
-}
-
-internal smallJsont* setNFreeSmallStringSmallJson(smallJsont *self, const char *key, smallStringt *string) {
-
- if (self->topIsA != SMALLJSON_IS_EMPTY && self->topIsA != TOP_IS_DICT) {
- return(NULL);
- }
-
- smallJsont *r = setSmallStringSmallJson(self, key, string);
- if (r) {
- finishO(string);
- }
- else {
- terminateO(string);
- }
- return(r);
-}
-
-internal smallJsont* setNFreeSmallContainerSmallJson(smallJsont *self, const char *key, smallContainert *container) {
-
- if (self->topIsA != SMALLJSON_IS_EMPTY && self->topIsA != TOP_IS_DICT) {
- return(NULL);
- }
-
- smallJsont *r = setSmallContainerSmallJson(self, key, container);
- if (r) {
- finishO(container);
- }
- else {
- terminateO(container);
- }
- return(r);
-}
-
-internal smallJsont* setPDictSmallJson(smallJsont *self, const char *key, smallDictt *dict) {
-
- if (self->topIsA != SMALLJSON_IS_EMPTY && self->topIsA != TOP_IS_DICT) {
- return(NULL);
- }
-
- if (!key) {
- return(NULL);
- }
-
- if (checkObjectTypes && dict && !isOSmallDict(dict)) {
- return(NULL);
- }
-
- if (!dict) {
- sDictSetP(&(self->top), key, (smallt *)allocSDict());
- return(self);
- }
-
- if (!dict->d) {
- dict->d = allocSDict();;
- }
-
- switch(self->topIsA) {
- case SMALLJSON_IS_EMPTY:
- self->topIsA = TOP_IS_DICT;
- case TOP_IS_DICT:
- setPJsonPath((smallt *)dict->d);
- break;
- }
- return(self);
-}
-
-internal smallJsont* setPArraySmallJson(smallJsont *self, const char *key, smallArrayt *array) {
-
- if (self->topIsA != SMALLJSON_IS_EMPTY && self->topIsA != TOP_IS_DICT) {
- return(NULL);
- }
-
- if (!key) {
- return(NULL);
- }
-
- if (checkObjectTypes && !isOSmallArray(array)) {
- return(NULL);
- }
-
- if (!array) {
- sDictSetP(&(self->top), key, (smallt *)allocSArray());
- return(self);
- }
-
- if (!array->a) {
- // allocate empty array
- array->a = allocSArray();
- }
-
- switch(self->topIsA) {
- case SMALLJSON_IS_EMPTY:
- self->topIsA = TOP_IS_DICT;
- case TOP_IS_DICT:
- setPJsonPath((smallt *)array->a);
- break;
- }
- return(self);
-}
-
-internal smallJsont* setPSmallJsonSmallJson(smallJsont *self, const char *key, smallJsont *value) {
-
- if (self->topIsA != SMALLJSON_IS_EMPTY && self->topIsA != TOP_IS_DICT) {
- return(NULL);
- }
-
- if (!key) {
- return(NULL);
- }
-
- if (checkObjectTypes && value && !isOSmallJson(value)) {
- return(NULL);
- }
-
- smallt *o;
- if (!value) {
- o = (smallt *) allocSUndefined();
- }
- else {
- switch(value->topIsA){
- case SMALLJSON_IS_EMPTY:
- o = (smallt *) allocSUndefined();
- break;
- case TOP_IS_UNDEFINED:
- o = (smallt *) value->topU;
- break;
- case TOP_IS_BOOL:
- o = (smallt *) value->topB;
- break;
- case TOP_IS_DOUBLE:
- o = (smallt *) value->topD;
- break;
- case TOP_IS_INT:
- o = (smallt *) value->topI;
- break;
- case TOP_IS_STRING:
- o = (smallt *) value->topS;
- break;
- case TOP_IS_DICT:
- o = (smallt *) value->top;
- break;
- case TOP_IS_ARRAY:
- o = (smallt *) value->topA;
- break;
- }
- }
- switch(self->topIsA) {
- case SMALLJSON_IS_EMPTY:
- self->topIsA = TOP_IS_DICT;
- case TOP_IS_DICT:
- setPJsonPath(o);
- break;
- }
- return(self);
-}
-
-internal smallJsont* setPSmallStringSmallJson(smallJsont *self, const char *key, smallStringt *string) {
-
- if (self->topIsA != SMALLJSON_IS_EMPTY && self->topIsA != TOP_IS_DICT) {
- return(NULL);
- }
-
- if (!key) {
- return(NULL);
- }
-
- if (checkObjectTypes && string && !isOSmallString(string)) {
- return(NULL);
- }
-
- smallt *o;
- if (!string || !string->data) {
- // set empty string when NULL
- o = (smallt *) allocSStringTiny("");
- }
- else {
- o = (smallt *) string->data;
- }
- switch(self->topIsA) {
- case SMALLJSON_IS_EMPTY:
- self->topIsA = TOP_IS_DICT;
- case TOP_IS_DICT:
- setPJsonPath(o);
- break;
- }
- return(self);
-}
-
-internal smallJsont* setNFreePDictSmallJson(smallJsont *self, const char *key, smallDictt *dict) {
-
- if (self->topIsA != SMALLJSON_IS_EMPTY && self->topIsA != TOP_IS_DICT) {
- return(NULL);
- }
-
- if (!key) {
- terminateO(dict);
- return(NULL);
- }
-
- if (checkObjectTypes && dict && !isOSmallDict(dict)) {
- terminateO(dict);
- return(NULL);
- }
-
- if (!dict) {
- sDictSetP(&(self->top), key, (smallt *)allocSDict());
- return(self);
- }
-
- if (!dict->d) {
- dict->d = allocSDict();;
- }
-
- switch(self->topIsA) {
- case SMALLJSON_IS_EMPTY:
- self->topIsA = TOP_IS_DICT;
- case TOP_IS_DICT:
- setPNFreeJsonPath((smallt *)dict->d, finishO(dict));
- break;
- }
- finishO(dict);
- return(self);
+ smallJsont *r = setSmallIntSmallJson(self, key, value);
+ if (r) {
+ finishO(value);
+ }
+ return(r);
}
-internal smallJsont* setNFreePArraySmallJson(smallJsont *self, const char *key, smallArrayt *array) {
+internal smallJsont* setNFreeSmallJsonSmallJson(smallJsont *self, const char *key, smallJsont *value) {
- if (self->topIsA != SMALLJSON_IS_EMPTY && self->topIsA != TOP_IS_DICT) {
- return(NULL);
+ smallJsont *r = setSmallJsonSmallJson(self, key, value);
+ if (r) {
+ finishO(value);
}
+ return(r);
+}
- if (!key) {
- terminateO(array);
- return(NULL);
- }
+internal smallJsont* setNFreeSmallStringSmallJson(smallJsont *self, const char *key, smallStringt *string) {
- if (checkObjectTypes && array && !isOSmallArray(array)) {
- terminateO(array);
- return(NULL);
+ smallJsont *r = setSmallStringSmallJson(self, key, string);
+ if (r) {
+ finishO(string);
}
+ return(r);
+}
- if (!array) {
- sDictSetP(&(self->top), key, (smallt *)allocSArray());
- return(self);
- }
+internal smallJsont* setNFreeSmallContainerSmallJson(smallJsont *self, const char *key, smallContainert *container) {
- if (!array->a) {
- // allocate empty array
- array->a = allocSArray();
+ smallJsont *r = setSmallContainerSmallJson(self, key, container);
+ if (r) {
+ finishO(container);
}
-
- switch(self->topIsA) {
- case SMALLJSON_IS_EMPTY:
- self->topIsA = TOP_IS_DICT;
- case TOP_IS_DICT:
- setPNFreeJsonPath((smallt *)array->a, finishO(array));
- break;
- }
- return(self);
+ return(r);
}
-internal smallJsont* setNFreePSmallJsonSmallJson(smallJsont *self, const char *key, smallJsont *value) {
+internal smallJsont* setPDictSmallJson(smallJsont *self, const char *key, smallDictt *dict) {
- if (self->topIsA != SMALLJSON_IS_EMPTY && self->topIsA != TOP_IS_DICT) {
- return(NULL);
- }
+ mainSetJsonPath(if (checkObjectTypes && dict && !isOSmallDict(dict)) return NULL;if (!dict) o = (smallt *) allocSDict(); else o = (smallt *)dict->d/*initValue*/,/*allocValue*/, setPJsonPath(o)/*subSetJsonPath*/);
+ // cg_c bug
+}
- if (!key) {
- terminateO(value);
- return(NULL);
- }
+internal smallJsont* setPArraySmallJson(smallJsont *self, const char *key, smallArrayt *array) {
- if (checkObjectTypes && value && !isOSmallJson(value)) {
- terminateO(value);
- return(NULL);
- }
+ mainSetJsonPath(if (checkObjectTypes && array && !isOSmallArray(array)) return NULL; if (!array) o = (smallt *) allocSArray(); else o = (smallt *)array->a/*initValue*/, /*allocValue*/, setPJsonPath(o)/*subSetJsonPath*/);
+ // cg_c bug
+}
- smallt *o;
- if (!value) {
- o = (smallt *) allocSUndefined();
- }
- else {
- switch(value->topIsA){
- case SMALLJSON_IS_EMPTY:
- o = (smallt *) allocSUndefined();
- break;
- case TOP_IS_UNDEFINED:
- o = (smallt *) value->topU;
- break;
- case TOP_IS_BOOL:
- o = (smallt *) value->topB;
- break;
- case TOP_IS_DOUBLE:
- o = (smallt *) value->topD;
- break;
- case TOP_IS_INT:
- o = (smallt *) value->topI;
- break;
- case TOP_IS_STRING:
- o = (smallt *) value->topS;
- break;
- case TOP_IS_DICT:
- o = (smallt *) value->top;
- break;
- case TOP_IS_ARRAY:
- o = (smallt *) value->topA;
- break;
- }
- }
+internal smallJsont* setPSmallJsonSmallJson(smallJsont *self, const char *key, smallJsont *value) {
- switch(self->topIsA) {
- case SMALLJSON_IS_EMPTY:
- self->topIsA = TOP_IS_DICT;
- case TOP_IS_DICT:
- setPNFreeJsonPath(o, finishO(value));
- break;
- }
- finishO(value);
- return(self);
+ mainSetJsonPath(if (checkObjectTypes && value && !isOSmallJson(value)) return NULL; if (!value) o = (smallt *) allocSUndefined(); else {switch(value->topIsA){case SMALLJSON_IS_EMPTY:o = (smallt *) allocSUndefined();break;case TOP_IS_UNDEFINED:o = (smallt *) value->topU;break;case TOP_IS_BOOL:o = (smallt *) value->topB;break;case TOP_IS_DOUBLE:o = (smallt *) value->topD;break;case TOP_IS_INT:o = (smallt *) value->topI;break;case TOP_IS_STRING:o = (smallt *) value->topS;break;case TOP_IS_DICT:o = (smallt *) value->top;break;case TOP_IS_ARRAY:o = (smallt *) value->topA;break;}}/*initValue*/, /*allocValue*/, setPJsonPath(o)/*subSetJsonPath*/);
+ // cg_c bug
}
-internal smallJsont* setNFreePSmallStringSmallJson(smallJsont *self, const char *key, smallStringt *string) {
+internal smallJsont* setPSmallStringSmallJson(smallJsont *self, const char *key, smallStringt *string) {
- if (self->topIsA != SMALLJSON_IS_EMPTY && self->topIsA != TOP_IS_DICT) {
- return(NULL);
- }
+ mainSetJsonPath(if (checkObjectTypes && string && !isOSmallString(string)) return NULL; o = (!string||!string->data)?(smallt*)allocSUndefined():(smallt*)string->data/*initValue*/, /*allocValue*/, setPJsonPath(o)/*subSetJsonPath*/);
+ // cg_c bug
+}
- if (!key) {
- terminateO(string);
- return(NULL);
- }
+internal smallJsont* setNFreePDictSmallJson(smallJsont *self, const char *key, smallDictt *dict) {
- if (checkObjectTypes && string && !isOSmallString(string)) {
- terminateO(string);
- return(NULL);
- }
+ mainSetJsonPath(if (checkObjectTypes && dict && !isOSmallDict(dict)) return NULL;if (!dict) o = (smallt *) allocSDict(); else o = (smallt *)dict->d/*initValue*/,/*allocValue*/, setPNFreeJsonPath(o,finishO(dict));finishO(dict)/*subSetJsonPath*/);
+ // cg_c bug
+}
- if (!string) {
- sDictSetP(&(self->top), key, (smallt *)allocSStringTiny(""));
- return(self);
- }
+internal smallJsont* setNFreePArraySmallJson(smallJsont *self, const char *key, smallArrayt *array) {
- if (!string->data) {
- string->data = allocSStringTiny("");
- }
+ mainSetJsonPath(if (checkObjectTypes && array && !isOSmallArray(array)) return NULL; if (!array) o = (smallt *) allocSArray(); else o = (smallt *)array->a/*initValue*/, /*allocValue*/, setPNFreeJsonPath(o,finishO(array));finishO(array)/*subSetJsonPath*/);
+ // cg_c bug
+}
- switch(self->topIsA) {
- case SMALLJSON_IS_EMPTY:
- self->topIsA = TOP_IS_DICT;
- case TOP_IS_DICT:
- setPNFreeJsonPath((smallt *)string->data, finishO(string));
- break;
- }
- finishO(string);
- return(self);
+internal smallJsont* setNFreePSmallJsonSmallJson(smallJsont *self, const char *key, smallJsont *value) {
+
+ mainSetJsonPath(if (checkObjectTypes && value && !isOSmallJson(value)) return NULL; if (!value) o = (smallt *) allocSUndefined(); else {switch(value->topIsA){case SMALLJSON_IS_EMPTY:o = (smallt *) allocSUndefined();break;case TOP_IS_UNDEFINED:o = (smallt *) value->topU;break;case TOP_IS_BOOL:o = (smallt *) value->topB;break;case TOP_IS_DOUBLE:o = (smallt *) value->topD;break;case TOP_IS_INT:o = (smallt *) value->topI;break;case TOP_IS_STRING:o = (smallt *) value->topS;break;case TOP_IS_DICT:o = (smallt *) value->top;break;case TOP_IS_ARRAY:o = (smallt *) value->topA;break;}}/*initValue*/, /*allocValue*/, setPNFreeJsonPath(o,finishO(value));finishO(value)/*subSetJsonPath*/);
+ // cg_c bug
}
+internal smallJsont* setNFreePSmallStringSmallJson(smallJsont *self, const char *key, smallStringt *string) {
+
+ mainSetJsonPath(if (checkObjectTypes && string && !isOSmallString(string)) return NULL; o = (!string||!string->data)?(smallt*)allocSUndefined():(smallt*)string->data/*initValue*/, /*allocValue*/, setPNFreeJsonPath(o,finishO(string));finishO(string)/*subSetJsonPath*/);
+ // cg_c bug
+}
internal smallJsont* setAtSmallJson(smallJsont *self, intmax_t index, baset *value) {
@@ -16260,10 +15785,6 @@ internal intmax_t iterStepSmallJson(smallJsont *self) {
internal baset* getSmallJson(smallJsont *self, const char *key) {
- if (!key) {
- return(NULL);
- }
-
smallt *o = NULL;
getJsonPath;
return(toBaset(o));
@@ -16599,10 +16120,6 @@ internal smallContainert* getSmallContainerSmallJson(smallJsont *self, const cha
//getNDup
internal baset* getNDupSmallJson(smallJsont *self, const char *key) {
- if (!key) {
- return(NULL);
- }
-
smallt *o = NULL;
getNDupJsonPath;
return(toBaset(sDuplicate(o)));
@@ -17470,9 +16987,7 @@ internal double getNumAtSmallJson(smallJsont *self, intmax_t index) {
internal smallJsont* delElemSmallJson(smallJsont *self, const char *key) {
- if (self->topIsA == TOP_IS_DICT && key && self->top) {
- delJsonPath;
- }
+ delJsonPath;
return(self);
}
@@ -19288,21 +18803,14 @@ internal bool appendTextJsonSmallJson(smallJsont *self, smallJsont *filePath) {
internal const char* typeStringSmallJson(smallJsont *self, const char *key) {
- if (self->topIsA == TOP_IS_DICT) {
- if (!self->top) {
- return(NULL);
- }
-
- smallt *o = NULL;
- typeStringJsonPath;
-
- if (!o) {
- return(NULL);
- }
+ smallt *o = NULL;
+ typeStringJsonPath;
- return(SMALL_TYPE_NAMES[(size_t)o->type]);
+ if (!o) {
+ return(NULL);
}
- return(NULL);
+
+ return(SMALL_TYPE_NAMES[(size_t)o->type]);
}
internal smallStringt* typeSmallStringSmallJson(smallJsont *self, const char *key) {
@@ -19334,21 +18842,14 @@ internal smallStringt* typeSmallStringKCharSmallJson(smallJsont *self, char key)
internal char typeSmallJson(smallJsont *self, const char *key) {
- if (self->topIsA == TOP_IS_DICT) {
- if (!self->top) {
- return(0);
- }
-
- smallt *o = NULL;
- typeJsonPath;
-
- if (!o) {
- return(0);
- }
+ smallt *o = NULL;
+ typeJsonPath;
- return(o->type);
+ if (!o) {
+ return(0);
}
- return(0);
+
+ return(o->type);
}
internal char typeKCharSmallJson(smallJsont *self, char key) {
@@ -19541,11 +19042,7 @@ internal bool isEBytesAtSmallJson(smallJsont *self, intmax_t index) {
internal bool isETypeSmallJson(smallJsont *self, const char *key, const char *type) {
- if (self->topIsA != TOP_IS_DICT) {
- return(false);
- }
-
- if (!self->top or !type) {
+ if (!type) {
return(false);
}
@@ -19561,14 +19058,6 @@ internal bool isETypeSmallJson(smallJsont *self, const char *key, const char *ty
internal bool isEUndefinedSmallJson(smallJsont *self, const char *key) {
- if (self->topIsA != TOP_IS_DICT) {
- return(false);
- }
-
- if (!self->top) {
- return(false);
- }
-
smallt *o = NULL;
isEJsonPath(eqS(SMALL_TYPE_NAMES[(size_t)o->type], "undefined"));
@@ -19581,14 +19070,6 @@ internal bool isEUndefinedSmallJson(smallJsont *self, const char *key) {
internal bool isEBoolSmallJson(smallJsont *self, const char *key) {
- if (self->topIsA != TOP_IS_DICT) {
- return(false);
- }
-
- if (!self->top) {
- return(false);
- }
-
smallt *o = NULL;
isEJsonPath(eqS(SMALL_TYPE_NAMES[(size_t)o->type], "bool"));
@@ -19601,14 +19082,6 @@ internal bool isEBoolSmallJson(smallJsont *self, const char *key) {
internal bool isEContainerSmallJson(smallJsont *self, const char *key) {
- if (self->topIsA != TOP_IS_DICT) {
- return(false);
- }
-
- if (!self->top) {
- return(false);
- }
-
smallt *o = NULL;
isEJsonPath(eqS(SMALL_TYPE_NAMES[(size_t)o->type], "container"));
@@ -19621,14 +19094,6 @@ internal bool isEContainerSmallJson(smallJsont *self, const char *key) {
internal bool isEDictSmallJson(smallJsont *self, const char *key) {
- if (self->topIsA != TOP_IS_DICT) {
- return(false);
- }
-
- if (!self->top) {
- return(false);
- }
-
smallt *o = NULL;
isEJsonPath(eqS(SMALL_TYPE_NAMES[(size_t)o->type], "dict"));
@@ -19641,14 +19106,6 @@ internal bool isEDictSmallJson(smallJsont *self, const char *key) {
internal bool isEDoubleSmallJson(smallJsont *self, const char *key) {
- if (self->topIsA != TOP_IS_DICT) {
- return(false);
- }
-
- if (!self->top) {
- return(false);
- }
-
smallt *o = NULL;
isEJsonPath(eqS(SMALL_TYPE_NAMES[(size_t)o->type], "double"));
@@ -19661,14 +19118,6 @@ internal bool isEDoubleSmallJson(smallJsont *self, const char *key) {
internal bool isEIntSmallJson(smallJsont *self, const char *key) {
- if (self->topIsA != TOP_IS_DICT) {
- return(false);
- }
-
- if (!self->top) {
- return(false);
- }
-
smallt *o = NULL;
isEJsonPath(eqS(SMALL_TYPE_NAMES[(size_t)o->type], "int"));
@@ -19681,14 +19130,6 @@ internal bool isEIntSmallJson(smallJsont *self, const char *key) {
internal bool isEStringSmallJson(smallJsont *self, const char *key) {
- if (self->topIsA != TOP_IS_DICT) {
- return(false);
- }
-
- if (!self->top) {
- return(false);
- }
-
smallt *o = NULL;
isEJsonPath(eqS(SMALL_TYPE_NAMES[(size_t)o->type], "string"));
@@ -19701,14 +19142,6 @@ internal bool isEStringSmallJson(smallJsont *self, const char *key) {
internal bool isEFaststringSmallJson(smallJsont *self, const char *key) {
- if (self->topIsA != TOP_IS_DICT) {
- return(false);
- }
-
- if (!self->top) {
- return(false);
- }
-
smallt *o = NULL;
isEJsonPath(eqS(SMALL_TYPE_NAMES[(size_t)o->type], "faststring"));
@@ -19721,14 +19154,6 @@ internal bool isEFaststringSmallJson(smallJsont *self, const char *key) {
internal bool isEArraySmallJson(smallJsont *self, const char *key) {
- if (self->topIsA != TOP_IS_DICT) {
- return(false);
- }
-
- if (!self->top) {
- return(false);
- }
-
smallt *o = NULL;
isEJsonPath(eqS(SMALL_TYPE_NAMES[(size_t)o->type], "array"));
@@ -19741,14 +19166,6 @@ internal bool isEArraySmallJson(smallJsont *self, const char *key) {
internal bool isEBytesSmallJson(smallJsont *self, const char *key) {
- if (self->topIsA != TOP_IS_DICT) {
- return(false);
- }
-
- if (!self->top) {
- return(false);
- }
-
smallt *o = NULL;
isEJsonPath(eqS(SMALL_TYPE_NAMES[(size_t)o->type], "bytes"));
diff --git a/src/json/libsheepyCSmallJson.h b/src/json/libsheepyCSmallJson.h
@@ -50,6 +50,15 @@ typedef struct smallJson smallJsont;
// for object inheriting smallJson, cast to smallJson to be able to use this class functions and generics
#define cJs(self) ( (smallJsont*) self )
+/** json Path Result
+ * enum type for key type
+ * NOT_A_PATH is a dictionary key
+ */
+typedef enum {KEY_IS_NULL=0, NOT_A_PATH, ARRAY_PATH, DICT_PATH} jsonPathRest;
+
+/** array to convert jsonPathRest to string */
+extern const char *jsonPathResS[];
+
typedef void (*freeSmallJsonFt) (smallJsont *self);
typedef void (*terminateSmallJsonFt) (smallJsont **self);
typedef char* (*toStringSmallJsonFt) (smallJsont *self);
@@ -60,7 +69,7 @@ typedef smallJsont* (*duplicateSmallJsonFt) (smallJsont *self);
* self becomes empty.
*
* Useful when the objects are shared
- */
+ */
typedef void (*disposeSmallJsonFt) (smallJsont *self);
/**
@@ -239,6 +248,99 @@ typedef smallIntt* (*getTopSmallIntSmallJsonFt) (smallJsont *self);
typedef smallStringt* (*getTopSmallStringSmallJsonFt)(smallJsont *self);
/**
+ * keyIs
+ * determine json key type: dictionary key, json path starting from an array or json path starting from a dictionary
+ *
+ * use the jsonPathResS[] array to convert the result to string (or use keyIsS to get the result as string directly)
+ *
+ * \param
+ * key any key or path in self
+ * \return
+ * key type (enum int)
+ * 0 (KEY_IS_NULL in enum) when key is NULL
+ */
+typedef jsonPathRest (*keyIsSmallJsonFt) (smallJsont *self, const char *key);
+
+/**
+ * keyIs returning result as string
+ * determine json key type: dictionary key, json path starting from an array or json path starting from a dictionary
+ *
+ * \param
+ * key any key or path in self
+ * \return
+ * key type
+ * NULL when key is NULL
+ */
+typedef const char* (*keyIsSSmallJsonFt) (smallJsont *self, const char *key);
+
+/**
+ * make json key
+ * escape " and \ characters and add quotes to prevent misinterpreting the key as a json path
+ *
+ * \param
+ * key key to transform
+ * \return
+ * new dictionary key (you must free this buffer)
+ * NULL when key is NULL
+ */
+typedef char* (*makeKeySmallJsonFt) (smallJsont *self, const char *key);
+
+/**
+ * make json key
+ * escape " and \ characters and add quotes to prevent misinterpreting the key as a json path
+ *
+ * \param
+ * key pointer to key to transform (this parameter is reallocated)
+ * \return
+ * new dictionary key (you must free this buffer)
+ * NULL when key is NULL
+ */
+typedef char* (*iMakeKeySmallJsonFt) (smallJsont *self, char **key);
+
+/**
+ * make json key
+ * escape " and \ characters and add quotes to prevent misinterpreting the key as a json path
+ * the result is stored dest, dest must be big enough (at least makeKeyLen+1)
+ *
+ * \param
+ * key key to transform
+ * \param
+ * dest result buffer
+ * \return
+ * dictionary key in dest
+ * NULL when key is NULL
+ */
+typedef char* (*bMakeKeySmallJsonFt) (smallJsont *self, char *dest, const char *key);
+
+/**
+ * make json key
+ * escape " and \ characters and add quotes to prevent misinterpreting the key as a json path
+ * the result is stored dest, dest size must be big enough (at least makeKeyLen+1)
+ *
+ * \param
+ * key key to transform
+ * \param
+ * dest result buffer
+ * \param
+ * size dest buffer size
+ * \return
+ * dictionary key in dest
+ * NULL when key is NULL
+ */
+typedef char* (*bLMakeKeySmallJsonFt) (smallJsont *self, char *dest, size_t size, const char *key);
+
+/**
+ * return key length after running makeKey
+ *
+ * \param
+ * key key to transform
+ * \return
+ * dictionary key length
+ * 0 when key is NULL
+ */
+typedef size_t (*makeKeyLenSmallJsonFt)(smallJsont *self, const char *key);
+
+/**
* set element
*
* When the sObject pointer is updated by realloc, the sObject
@@ -2402,6 +2504,13 @@ typedef bool (*areAllEBytesSmallJsonFt) (smallJsont *self);
getTopSmallDoubleSmallJsonFt getTopSmallDouble;\
getTopSmallIntSmallJsonFt getTopSmallInt;\
getTopSmallStringSmallJsonFt getTopSmallString;\
+ keyIsSmallJsonFt keyIs;\
+ keyIsSSmallJsonFt keyIsS;\
+ makeKeySmallJsonFt makeKey;\
+ iMakeKeySmallJsonFt iMakeKey;\
+ bMakeKeySmallJsonFt bMakeKey;\
+ bLMakeKeySmallJsonFt bLMakeKey;\
+ makeKeyLenSmallJsonFt makeKeyLen;\
setSmallJsonFt set;\
setUndefinedSmallJsonFt setUndefined;\
setBoolSmallJsonFt setBool;\
diff --git a/src/json/libsheepyCSmallJsonInternal.h b/src/json/libsheepyCSmallJsonInternal.h
@@ -33,31 +33,47 @@ declareRecycle(smallJsont);
#endif // recycleContainers
#define walkJsonPath(getSmallObj, arrayCode, dictCode, returnFail, directHit, keyErrorReturn)\
- if (!findS(key, "\"") && !findS(key, "[")) {\
+ ;/*avoid error: a label can only be part of a statement and a declaration is not a statement */\
+ if (!key) return keyErrorReturn;\
+ /* check key type */\
+ jsonPathRest keyType = keyIsSmallJson(self, key);\
+ if (keyType == NOT_A_PATH) {\
returnFail;\
directHit;\
}\
\
- sDictt **d = &(self->top);\
- sArrayt **a = &(self->topA);\
- smallt **oo = NULL;\
- int status = 0;\
+ sDictt **d = &(self->top);\
+ sArrayt **a = &(self->topA);\
+ smallt **oo = NULL;\
+ int status = 0;\
+ bool escape = false;\
+ size_t keyIdx = 0;\
\
for(size_t i = 0 ; key[i] ; i++) {\
+ if (escape) {\
+ escape = false;\
+ continue;\
+ }\
if (key[i] == '[') {\
/* array index */\
- char *next = findS((key+i+1), "]");\
+ const char *next = findS((key+i+1), "]");\
if (next) {\
size_t keyLen = next - (key+i+1);\
char *keyInPath = sliceS((key+i+1), 0, keyLen);\
\
- if (oo)\
+ if (oo) {\
/* oo is from the smallJson and is an array */\
a = (sArrayt **) oo;\
/* verify that d is an sArray */\
if ((*a)->type != ARRAY) {free(keyInPath);return keyErrorReturn;}\
+ }\
\
- uint32_t idx = parseInt(keyInPath);\
+ int64_t idx = parseInt(keyInPath);\
+ /* convert python index (negative index) */\
+ int64_t len = (*a)->count;\
+ if (idx >= len) {free(keyInPath);return keyErrorReturn;}\
+ if (idx < -len) {free(keyInPath);return keyErrorReturn;}\
+ if (idx < 0) {idx = len + idx;}\
if (!*(next+1)) {\
arrayCode;\
free(keyInPath);\
@@ -75,21 +91,18 @@ declareRecycle(smallJsont);
if (status == 1) {\
/* found closing quote */\
status = 0;\
- continue;\
- }\
- /* dict key */\
- status = 1;\
- char *next = findS((key+i+1), "\"");\
- if (next) {\
- size_t keyLen = next - (key+i+1);\
- char *keyInPath = sliceS((key+i+1), 0, keyLen);\
+ const char *next = key+i;\
+ size_t keyLen = i - keyIdx;\
+ char *keyInPath = sliceS((key+keyIdx), 0, keyLen);\
\
- if (oo)\
+ if (oo) {\
/* oo is from the smallJson and is a dict */\
d = (sDictt **) oo;\
/* verify that d is an sDict */\
if ((*d)->type != DICT) {free(keyInPath);return keyErrorReturn;}\
+ }\
\
+ unescapeKey(keyInPath, keyInPath, keyLen);\
if (!*(next+1)) {\
dictCode;\
free(keyInPath);\
@@ -100,33 +113,61 @@ declareRecycle(smallJsont);
getSmallObj;\
}\
free(keyInPath);\
+ continue;\
}\
+ /* dict key */\
+ status = 1;\
+ keyIdx = i+1;\
}\
+ if (key[i] == '\\' && status == 1) escape = true;\
}
#define setJsonPath\
- walkJsonPath(, sArraySetTiny(*a, idx, o), sDictSetTiny(d, keyInPath, o), , sDictSetTiny(&(self->top), key, o); return self, NULL)
+ walkJsonPath(if (!oo) {free(keyInPath);return NULL;}/*getSmallObj*/, sArraySetTiny(*a, idx, o)/*arrayCode*/, sDictSetTiny(d, keyInPath, o)/*dictCode*/, /*returnFail*/, sDictSetTiny(&(self->top), key, o); return self/*directHit*/, NULL/*keyErrorReturn*/)
#define setPJsonPath(objP)\
- walkJsonPath(, sArraySetP(*a, idx, objP), sDictSetP(d, keyInPath, objP), , sDictSetP(&(self->top), key, objP); return self, NULL)
+ walkJsonPath(if (!oo) {free(keyInPath);return NULL;}/*getSmallObj*/, sArraySetP(*a, idx, objP)/*arrayCode*/, sDictSetP(d, keyInPath, objP)/*dictCode*/, /*returnFail*/, sDictSetP(&(self->top), key, objP); return self/*directHit*/, NULL/*keyErrorReturn*/)
#define setPNFreeJsonPath(objP, finishArg)\
- walkJsonPath(, sArraySetP(*a, idx, objP), sDictSetP(d, keyInPath, objP), , sDictSetP(&(self->top), key, objP); finishArg ; return self, NULL)
+ walkJsonPath(if (!oo) {free(keyInPath);return NULL;}/*getSmallObj*/, sArraySetP(*a, idx, objP)/*arrayCode*/, sDictSetP(d, keyInPath, objP)/*dictCode*/, /*returnFail*/, sDictSetP(&(self->top), key, objP); finishArg ; return self/*directHit*/, NULL/*keyErrorReturn*/)
#define getJsonPath\
- walkJsonPath(if (!oo) {free(keyInPath);return NULL;} o = *oo, o = sArrayGetTiny(*a, idx), o = sDictGetTiny(*d, keyInPath), if (!self->top) return NULL, return toBaset(sDictGetTiny(self->top, key)), NULL)
+ walkJsonPath(if (!oo) {free(keyInPath);return NULL;} o = *oo/*getSmallObj*/, if (!*a) {free(keyInPath);return NULL;} o = sArrayGetTiny(*a, idx)/*arrayCode*/, if (!*d) {free(keyInPath);return NULL;} o = sDictGetTiny(*d, keyInPath)/*dictCode*/, if (!self->top) return NULL/*returnFail*/, return toBaset(sDictGetTiny(self->top, key))/*directHit*/, NULL/*keyErrorReturn*/)
#define getNDupJsonPath\
- walkJsonPath(if (!oo) {free(keyInPath);return NULL;} o = *oo, o = sArrayGetTiny(*a, idx), o = sDictGetTiny(*d, keyInPath), if (!self->top) return NULL, return toBaset(sDuplicate(sDictGetTiny(self->top, key))), NULL)
+ walkJsonPath(if (!oo) {free(keyInPath);return NULL;} o = *oo/*getSmallObj*/, if (!*a) {free(keyInPath);return NULL;} o = sArrayGetTiny(*a, idx)/*arrayCode*/, if (!*d) {free(keyInPath);return NULL;} o = sDictGetTiny(*d, keyInPath)/*dictCode*/, if (!self->top) return NULL/*returnFail*/, return toBaset(sDuplicate(sDictGetTiny(self->top, key)))/*directHit*/, NULL/*keyErrorReturn*/)
#define delJsonPath\
- walkJsonPath(, sArrayDelTiny(*a, idx), sDictDelTiny(*d, keyInPath), if (!self->top) return NULL, sDictDelTiny(self->top, key) ; return self, NULL)
+ walkJsonPath(if (!oo) {free(keyInPath);return NULL;}/*getSmallObj*/, if (!*a) {free(keyInPath);return NULL;} sArrayDelTiny(*a, idx)/*arrayCode*/, if (!*d) {free(keyInPath);return NULL;} sDictDelTiny(*d, keyInPath)/*dictCode*/, if (!self->top) return NULL/*returnFail*/, sDictDelTiny(self->top, key) ; return self/*directHit*/, NULL/*keyErrorReturn*/)
#define typeStringJsonPath\
- walkJsonPath(, o = sArrayGetTiny(*a, idx), o = sDictGetTiny(*d, keyInPath), if (!self->top) return NULL, o = sDictGet(self->top, key) ; if (!o) return NULL; return SMALL_TYPE_NAMES[(size_t)o->type], NULL)
+ walkJsonPath(if (!oo) {free(keyInPath);return NULL;}/*getSmallObj*/, if (!*a) {free(keyInPath);return NULL;} o = sArrayGetTiny(*a, idx)/*arrayCode*/, if (!*d) {free(keyInPath);return NULL;} o = sDictGetTiny(*d, keyInPath)/*dictCode*/, if (!self->top) return NULL/*returnFail*/, o = sDictGet(self->top, key) ; if (!o) return NULL; return SMALL_TYPE_NAMES[(size_t)o->type]/*directHit*/, NULL/*keyErrorReturn*/)
#define typeJsonPath\
- walkJsonPath(, o = sArrayGetTiny(*a, idx), o = sDictGetTiny(*d, keyInPath), if (!self->top) return 0, o = sDictGet(self->top, key) ; if (!o) return 0; return o->type, 0)
+ walkJsonPath(if (!oo) {free(keyInPath);return 0;}/*getSmallObj*/, if (!*a) {free(keyInPath);return 0;} o = sArrayGetTiny(*a, idx)/*arrayCode*/, if (!*d) {free(keyInPath);return 0;} o = sDictGetTiny(*d, keyInPath)/*dictCode*/, if (!self->top) return 0/*returnFail*/, o = sDictGet(self->top, key) ; if (!o) return 0; return o->type/*directHit*/, 0/*keyErrorReturn*/)
#define isEJsonPath(test)\
- walkJsonPath(, o = sArrayGetTiny(*a, idx), o = sDictGetTiny(*d, keyInPath), if (!self->top) return 0, o = sDictGet(self->top, key) ; if (!o) return false; return test, 0)
+ walkJsonPath(if (!oo) {free(keyInPath);return 0;}/*getSmallObj*/, if (!*a) {free(keyInPath);return 0;} o = sArrayGetTiny(*a, idx)/*arrayCode*/, if (!*d) {free(keyInPath);return 0;} o = sDictGetTiny(*d, keyInPath)/*dictCode*/, if (!self->top) return 0/*returnFail*/, o = sDictGet(self->top, key) ; if (!o) return false; return test/*directHit*/, 0/*keyErrorReturn*/)
+
+#define mainSetJsonPath(initValue, allocValue, subSetJsonPath) \
+ smallt *o = NULL;\
+ if (!key)\
+ return NULL;\
+ jsonPathRest keyType = keyIsSmallJson(self, key);\
+ if (self->topIsA != SMALLJSON_IS_EMPTY && ((keyType == ARRAY_PATH && (self->topIsA != TOP_IS_ARRAY && self->topIsA != SMALLJSON_IS_EMPTY)) || ((keyType == NOT_A_PATH || keyType == DICT_PATH) && (self->topIsA != TOP_IS_DICT && self->topIsA != SMALLJSON_IS_EMPTY))))\
+ return NULL;\
+ initValue;\
+ switch(self->topIsA) {\
+ case SMALLJSON_IS_EMPTY:\
+ if (keyType == NOT_A_PATH || keyType == DICT_PATH)\
+ self->topIsA = TOP_IS_DICT;\
+ else if (keyType == ARRAY_PATH)\
+ self->topIsA = TOP_IS_ARRAY;\
+ case TOP_IS_ARRAY:\
+ case TOP_IS_DICT:;\
+ allocValue;\
+ subSetJsonPath;\
+ break;\
+ }\
+ return self
+
diff --git a/src/json/libsheepyObjectTest.c b/src/json/libsheepyObjectTest.c
@@ -667,16 +667,14 @@ START_TEST(cSmallJsonT)
ck_assert_ptr_eq(in, NULL);
// missing " at the end
in = (smallIntt *) obj2->f->get(obj2, "\"dict\".\"int2");
- ck_assert(isOType(in, "smallDict"));
- finishO(in);
+ ck_assert_ptr_eq(in, NULL);
// get array element
in = (smallIntt *) obj2->f->get(obj2, "\"array\"[0]");
ck_assert(in->value->value == 123);
smashO(in);
// missing ] at the end
in = (smallIntt *) obj2->f->get(obj2, "\"array\"[0");
- ck_assert(isOType(in, "smallArray"));
- finishO(in);
+ ck_assert_ptr_eq(in, NULL);
// json array
createAllocateSmallJson(json);
createAllocateSmallInt(oInt4);
@@ -686,6 +684,92 @@ START_TEST(cSmallJsonT)
in = (smallIntt *) json->f->get(json, "[0]");
ck_assert(in->value->value == 345);
smashO(in);
+ // set get json path
+ createSmallJson(jpath);
+ // dict is top
+ jpath.f->parse(&jpath, "{ \"a\": {\"a\": true}, \"b\": 234, \"c\": [\"qwe\",32]}");
+ // get non existing element in 'c' array
+ b = jpath.f->get(&jpath,"\"c\"[3]");
+ ck_assert_ptr_eq(b, NULL);
+ finishO(b);
+ // dictionary keys should not be unescaped
+ createSmallBool(ba);
+ jpath.f->set(&jpath, "b\\\\", cBa(&ba));
+ jBool = (smallBoolt*)jpath.f->get(&jpath,"b\\\\");
+ ck_assert(jBool->value->value == false);
+ finishO(jBool);
+ // keys in json paths should be unescaped
+ createSmallBool(bb);
+ bb.f->set(&bb, true);
+ jpath.f->set(&jpath, "\"b\\\\\"", (baset*)&bb);
+ jBool = (smallBoolt*)jpath.f->get(&jpath,"\"b\\\\\"");
+ ck_assert(jBool->value->value == true);
+ finishO(jBool);
+ freeO(&jpath);
+ // array is top
+ // get dict in dict
+ jpath.f->parse(&jpath, "[1,{\"a\": {\"a\": true}, \"b\": 234, \"c\": [\"qwe\",32]}, [[11],22,33]]");
+ b = jpath.f->get(&jpath,"[1].\"a\"");
+ ck_assert_str_eq(b->type, "smallDict");
+ finishO(b);
+ // get bool in dict
+ jBool = (smallBoolt*)jpath.f->get(&jpath,"[1]\"a\"\"a\"");
+ ck_assert(jBool->value->value == true);
+ finishO(jBool);
+ // get array in array
+ jArray = (smallArrayt*)jpath.f->get(&jpath,"[2][0]");
+ ck_assert_str_eq(jArray->type, "smallArray");
+ ck_assert_uint_eq(lenO(jArray), 1);
+ finishG(jArray);
+ // get element in array
+ in = (smallIntt*)(jpath.f->get(&jpath,"[2][0][0]"));
+ ck_assert_uint_eq(in->value->value, 11);
+ finishG(in);
+ // set element in array with negative index
+ createSmallBool(be);
+ jpath.f->set(&jpath, "[-1][0][0]", (baset*)&be);
+ // get element in array with negative index
+ jBool = (smallBoolt*)jpath.f->get(&jpath,"[-1][0][0]");
+ ck_assert(jBool->value->value == false);
+ finishG(jBool);
+ // set new element in dict
+ createSmallBool(b2);
+ o2 = jpath.f->set(&jpath, "[1]\"a\"\"b\\\"\"", (baset*)&b2);
+ ck_assert_ptr_ne(o2, NULL);
+ jBool = (smallBoolt*)jpath.f->get(&jpath,"[1]\"a\"\"b\\\"\"");
+ ck_assert(jBool->value->value == false);
+ finishG(jBool);
+ createSmallBool(b3);
+ o2 = jpath.f->set(&jpath, "[1]\"a\"\"b\\\\\"", (baset*)&b3);
+ ck_assert_ptr_ne(o2, NULL);
+ jBool = (smallBoolt*)jpath.f->get(&jpath,"[1]\"a\"\"b\\\\\"");
+ ck_assert(jBool->value->value == false);
+ finishG(jBool);
+ // escape key in json path
+ // \\\""
+ char *ks = jpath.f->makeKey(&jpath, "\\\\\\\"\"");
+ ck_assert_str_eq(ks, "\"\\\\\\\\\\\\\\\"\\\"\"");
+ createSmallBool(b4);
+ iPrependS(&ks, "[1]");
+ o2 = jpath.f->set(&jpath, ks, (baset*)&b4);
+ ck_assert_ptr_ne(o2, NULL);
+ jBool = (smallBoolt*)jpath.f->get(&jpath,ks);
+ ck_assert(jBool->value->value == false);
+ finishG(jBool);
+ free(ks);
+ // wrong path
+ b = jpath.f->get(&jpath,"[3][0][0]");
+ ck_assert_ptr_eq(b, NULL);
+ finishG(b);
+ // missing index
+ b = jpath.f->get(&jpath,"[][0][0]");
+ ck_assert_ptr_eq(b, NULL);
+ finishG(b);
+ // try to assign dictionary key to array, wrong
+ createSmallBool(b0);
+ o2 = jpath.f->set(&jpath, "[2][0]\"sdf\\\"", (baset*)&b0);
+ ck_assert_ptr_eq(o2, NULL);
+ freeO(&jpath);
// len
initiateAllocateSmallJson(&o);
ck_assert_uint_eq(o->f->len(o), 0);
diff --git a/src/libsheepy.c b/src/libsheepy.c
@@ -54071,10 +54071,10 @@ void scheduler(void) {
+#if ((__GNUC__ > 4))
/**
* return monotonic time in nanoseconds
*/
-#if ((__GNUC__ > 4))
uint64_t getMonotonicTime(void) {
struct timespec ts;
diff --git a/src/libsheepy.h b/src/libsheepy.h
@@ -96,7 +96,7 @@
// version accoring to the version package: Release.Major.minor.patch
// https://noulin.net/version/file/README.md.html
-#define LIBSHEEPY_VERSION "1.0.5.1"
+#define LIBSHEEPY_VERSION "1.0.6"
#ifndef SH_PREFIX
#define SH_PREFIX(NAME) NAME
@@ -301,6 +301,20 @@ extern jmp_buf tryJumpBuffers[maxTryThrowCount];
#define f32 float
#define f64 double
+/**
+ * type cast
+ */
+#define I8(value) (i8)(value)
+#define I16(value) (i16)(value)
+#define I32(value) (i32)(value)
+#define I64(value) (i64)(value)
+#define U8(value) (u8)(value)
+#define U16(value) (u16)(value)
+#define U32(value) (u32)(value)
+#define U64(value) (u64)(value)
+#define F32(value) (f32)(value)
+#define F64(value) (f64)(value)
+
#define MAX(a, b) (((a) > (b)) ? (a) : (b))
#define MIN(a, b) (((a) < (b)) ? (a) : (b))
#define MIN3(a, b, c) MIN((typeof(a))MIN(a, b), c)
@@ -401,6 +415,12 @@ extern jmp_buf tryJumpBuffers[maxTryThrowCount];
*/
#define FIELD_SIZEOF(t, f) (sizeof(((t*)0)->f))
+/** true when value is odd integer */
+#define isIntOdd(value) (value&1)
+
+/** true when value is even integer */
+#define isIntEven(value) (!(value&1))
+
/**
* typ definition as alternative to typedef
*/
diff --git a/src/libsheepyObject.h b/src/libsheepyObject.h
@@ -8349,6 +8349,9 @@ void finishManyOF(void *paramType, ...);
*/
typedef struct base baset;
+// for object inheriting baset, cast to baset to be able to use this class functions and generics
+#define cBa(self) ( (baset*) self )
+
// Functions
/**
@@ -8551,6 +8554,9 @@ extern smallContainert* rtSmallContainert;
*/
#define _ "\""
+/** Back Slash string to escape back slash, use in for example json path with get, set... */
+#define BSLH "\\"
+
/**
* get a pointer to the string in the smallString object
*