11/*
2- * Special thanks to Christopher Wellons (aka skeeto) for giving valuable
2+ * Special thanks to Christopher Wellons (aka skeeto) for giving valuable
33 * feedback that helped improve this lib.
44 *
55 * See: https://www.reddit.com/r/C_Programming/comments/sf95m3/comment/huojrjn
@@ -237,26 +237,28 @@ _jsonb_eval_state(enum jsonbstate state)
237237#define DECORATOR (d ) d
238238#endif /* JSONB_DEBUG */
239239
240+ #define STACK_HEAD (b , state ) *(b)->top = (state)
240241#define STACK_PUSH (b , state ) TRACE(*(b)->top, *++(b)->top = (state))
241242#define STACK_POP (b ) TRACE(*(b)->top, DECORATOR(*)--(b)->top)
242- #define STACK_HEAD (b , state ) TRACE(*(b)->top, *(b)->top = (state))
243243
244244#define BUFFER_COPY_CHAR (b , c , _pos , buf , bufsize ) \
245245 do { \
246- if ((b)->pos + (_pos) + 1 > (bufsize)) { \
246+ if ((b)->pos + (_pos) + 1 + 1 > (bufsize)) { \
247247 return JSONB_ERROR_NOMEM; \
248248 } \
249249 (buf)[(b)->pos + (_pos)++] = (c); \
250+ (buf)[(b)->pos + (_pos)] = '\0'; \
250251 } while (0)
251252#define BUFFER_COPY (b , value , len , _pos , buf , bufsize ) \
252253 do { \
253254 size_t i; \
254- if ((b)->pos + (_pos) + (len) > (bufsize)) { \
255+ if ((b)->pos + (_pos) + (len) + 1 > (bufsize)) { \
255256 return JSONB_ERROR_NOMEM; \
256257 } \
257258 for (i = 0; i < (len); ++i) \
258259 (buf)[(b)->pos + (_pos) + i] = (value)[i]; \
259260 (_pos) += (len); \
261+ (buf)[(b)->pos + (_pos)] = '\0'; \
260262 } while (0)
261263
262264void
@@ -270,23 +272,22 @@ jsonb_init(jsonb *b)
270272jsonbcode
271273jsonb_push_object (jsonb * b , char buf [], size_t bufsize )
272274{
273- enum jsonbstate next_state ;
275+ enum jsonbstate new_state ;
274276 size_t pos = 0 ;
275- if (b -> top - b -> stack >= JSONB_MAX_DEPTH )
276- return JSONB_ERROR_STACK ;
277+ if (b -> top - b -> stack >= JSONB_MAX_DEPTH ) return JSONB_ERROR_STACK ;
277278 switch (* b -> top ) {
278279 case JSONB_ARRAY_NEXT_VALUE_OR_CLOSE :
279280 BUFFER_COPY_CHAR (b , ',' , pos , buf , bufsize );
280281 /* fall-through */
281282 case JSONB_OBJECT_VALUE :
282283 case JSONB_ARRAY_VALUE_OR_CLOSE :
283284 if (* b -> top <= JSONB_OBJECT_NEXT_KEY_OR_CLOSE )
284- next_state = JSONB_OBJECT_NEXT_KEY_OR_CLOSE ;
285+ new_state = JSONB_OBJECT_NEXT_KEY_OR_CLOSE ;
285286 else if (* b -> top <= JSONB_ARRAY_NEXT_VALUE_OR_CLOSE )
286- next_state = JSONB_ARRAY_NEXT_VALUE_OR_CLOSE ;
287+ new_state = JSONB_ARRAY_NEXT_VALUE_OR_CLOSE ;
287288 break ;
288289 case JSONB_ARRAY_OR_OBJECT_OR_VALUE :
289- next_state = JSONB_DONE ;
290+ new_state = JSONB_DONE ;
290291 break ;
291292 default :
292293 STACK_HEAD (b , JSONB_ERROR );
@@ -296,7 +297,7 @@ jsonb_push_object(jsonb *b, char buf[], size_t bufsize)
296297 return JSONB_ERROR_INPUT ;
297298 }
298299 BUFFER_COPY_CHAR (b , '{' , pos , buf , bufsize );
299- STACK_HEAD (b , next_state );
300+ STACK_HEAD (b , new_state );
300301 STACK_PUSH (b , JSONB_OBJECT_KEY_OR_CLOSE );
301302 b -> pos += pos ;
302303 return JSONB_OK ;
@@ -308,16 +309,14 @@ jsonb_pop_object(jsonb *b, char buf[], size_t bufsize)
308309 enum jsonbcode code ;
309310 size_t pos = 0 ;
310311 switch (* b -> top ) {
311- case JSONB_DONE :
312- code = JSONB_END ;
313- break ;
314312 case JSONB_OBJECT_KEY_OR_CLOSE :
315313 case JSONB_OBJECT_NEXT_KEY_OR_CLOSE :
316- code = JSONB_OK ;
314+ code = b -> top - 1 == b -> stack ? JSONB_END : JSONB_OK ;
317315 break ;
318316 default :
319317 STACK_HEAD (b , JSONB_ERROR );
320318 /* fall-through */
319+ case JSONB_DONE :
321320 case JSONB_ERROR :
322321 return JSONB_ERROR_INPUT ;
323322 }
@@ -419,23 +418,22 @@ jsonb_push_key(
419418jsonbcode
420419jsonb_push_array (jsonb * b , char buf [], size_t bufsize )
421420{
422- enum jsonbstate next_state ;
421+ enum jsonbstate new_state ;
423422 size_t pos = 0 ;
424- if (b -> top - b -> stack >= JSONB_MAX_DEPTH )
425- return JSONB_ERROR_STACK ;
423+ if (b -> top - b -> stack >= JSONB_MAX_DEPTH ) return JSONB_ERROR_STACK ;
426424 switch (* b -> top ) {
427425 case JSONB_ARRAY_NEXT_VALUE_OR_CLOSE :
428426 BUFFER_COPY_CHAR (b , ',' , pos , buf , bufsize );
429427 /* fall-through */
430428 case JSONB_OBJECT_VALUE :
431429 case JSONB_ARRAY_VALUE_OR_CLOSE :
432430 if (* b -> top <= JSONB_OBJECT_NEXT_KEY_OR_CLOSE )
433- next_state = JSONB_OBJECT_NEXT_KEY_OR_CLOSE ;
431+ new_state = JSONB_OBJECT_NEXT_KEY_OR_CLOSE ;
434432 else if (* b -> top <= JSONB_ARRAY_NEXT_VALUE_OR_CLOSE )
435- next_state = JSONB_ARRAY_NEXT_VALUE_OR_CLOSE ;
433+ new_state = JSONB_ARRAY_NEXT_VALUE_OR_CLOSE ;
436434 break ;
437435 case JSONB_ARRAY_OR_OBJECT_OR_VALUE :
438- next_state = JSONB_DONE ;
436+ new_state = JSONB_DONE ;
439437 break ;
440438 default :
441439 STACK_HEAD (b , JSONB_ERROR );
@@ -444,7 +442,7 @@ jsonb_push_array(jsonb *b, char buf[], size_t bufsize)
444442 return JSONB_ERROR_INPUT ;
445443 }
446444 BUFFER_COPY_CHAR (b , '[' , pos , buf , bufsize );
447- STACK_HEAD (b , next_state );
445+ STACK_HEAD (b , new_state );
448446 STACK_PUSH (b , JSONB_ARRAY_VALUE_OR_CLOSE );
449447 b -> pos += pos ;
450448 return JSONB_OK ;
@@ -456,16 +454,14 @@ jsonb_pop_array(jsonb *b, char buf[], size_t bufsize)
456454 enum jsonbcode code ;
457455 size_t pos = 0 ;
458456 switch (* b -> top ) {
459- case JSONB_DONE :
460- code = JSONB_END ;
461- break ;
462457 case JSONB_ARRAY_VALUE_OR_CLOSE :
463458 case JSONB_ARRAY_NEXT_VALUE_OR_CLOSE :
464- code = JSONB_OK ;
459+ code = b -> top - 1 == b -> stack ? JSONB_END : JSONB_OK ;
465460 break ;
466461 default :
467462 STACK_HEAD (b , JSONB_ERROR );
468463 /* fall-through */
464+ case JSONB_DONE :
469465 case JSONB_ERROR :
470466 return JSONB_ERROR_INPUT ;
471467 }
0 commit comments