@@ -330,6 +330,68 @@ jsonb_pop_object(jsonb *b, char buf[], size_t bufsize)
330330 return code ;
331331}
332332
333+ static long
334+ _jsonb_escape (
335+ size_t * pos , char buf [], size_t bufsize , const char str [], size_t len )
336+ {
337+ char * esc_tok = NULL , _esc_tok [8 ] = "\\u00" ;
338+ char * esc_buf = NULL ;
339+ int extra_bytes = 0 ;
340+ size_t i ;
341+ second_iter :
342+ /* 1st iteration, esc_buf is NULL and count extra_bytes needed for escaping
343+ * 2st iteration, esc_buf is not NULL, and does escaping. */
344+ for (i = 0 ; i < len ; ++ i ) {
345+ unsigned char c = str [i ];
346+ esc_tok = NULL ;
347+ switch (c ) {
348+ case 0x22 : esc_tok = "\\\"" ; break ;
349+ case 0x5C : esc_tok = "\\\\" ; break ;
350+ case '\b' : esc_tok = "\\b" ; break ;
351+ case '\f' : esc_tok = "\\f" ; break ;
352+ case '\n' : esc_tok = "\\n" ; break ;
353+ case '\r' : esc_tok = "\\r" ; break ;
354+ case '\t' : esc_tok = "\\t" ; break ;
355+ default : if (c <= 0x1F ) {
356+ static const char tohex [] = "0123456789abcdef" ;
357+ _esc_tok [4 ] = tohex [c >> 4 ];
358+ _esc_tok [5 ] = tohex [c & 0xF ];
359+ _esc_tok [6 ] = 0 ;
360+ esc_tok = _esc_tok ;
361+ }
362+ }
363+ if (esc_tok ) {
364+ int j ;
365+ for (j = 0 ; esc_tok [j ]; j ++ ) {
366+ if (!esc_buf ) /* count how many extra bytes are needed */
367+ continue ;
368+ * esc_buf ++ = esc_tok [j ];
369+ }
370+ extra_bytes += j - 1 ;
371+ }
372+ else if (esc_buf ) {
373+ * esc_buf ++ = c ;
374+ }
375+ }
376+
377+ if (* pos + len + extra_bytes > bufsize ) return JSONB_ERROR_NOMEM ;
378+
379+ if (esc_buf ) {
380+ * pos += len + extra_bytes ;
381+ return JSONB_OK ;
382+ }
383+ if (!extra_bytes ) {
384+ size_t j ;
385+ for (j = 0 ; j < len ; ++ j )
386+ buf [* pos + j ] = str [j ];
387+ * pos += len ;
388+ return JSONB_OK ;
389+ }
390+ esc_buf = buf + * pos ;
391+ extra_bytes = 0 ;
392+ goto second_iter ;
393+ }
394+
333395jsonbcode
334396jsonb_push_key (
335397 jsonb * b , char buf [], size_t bufsize , const char key [], size_t len )
@@ -339,12 +401,14 @@ jsonb_push_key(
339401 case JSONB_OBJECT_NEXT_KEY_OR_CLOSE :
340402 BUFFER_COPY_CHAR (b , ',' , pos , buf , bufsize );
341403 /* fall-through */
342- case JSONB_OBJECT_KEY_OR_CLOSE :
404+ case JSONB_OBJECT_KEY_OR_CLOSE : {
405+ enum jsonbcode ret ;
343406 BUFFER_COPY_CHAR (b , '"' , pos , buf , bufsize );
344- BUFFER_COPY (b , key , len , pos , buf , bufsize );
407+ ret = _jsonb_escape (& pos , buf + b -> pos , bufsize , key , len );
408+ if (ret != JSONB_OK ) return ret ;
345409 BUFFER_COPY (b , "\":" , 2 , pos , buf , bufsize );
346410 STACK_HEAD (b , JSONB_OBJECT_VALUE );
347- break ;
411+ } break ;
348412 default :
349413 STACK_HEAD (b , JSONB_ERROR );
350414 /* fall-through */
@@ -466,68 +530,6 @@ jsonb_push_null(jsonb *b, char buf[], size_t bufsize)
466530 return jsonb_push_token (b , buf , bufsize , "null" , 4 );
467531}
468532
469- static long
470- _jsonb_escape (
471- size_t * pos , char buf [], size_t bufsize , const char str [], size_t len )
472- {
473- char * esc_tok = NULL , _esc_tok [8 ] = "\\u00" ;
474- char * esc_buf = NULL ;
475- int extra_bytes = 0 ;
476- size_t i ;
477- second_iter :
478- /* 1st iteration, esc_buf is NULL and count extra_bytes needed for escaping
479- * 2st iteration, esc_buf is not NULL, and does escaping. */
480- for (i = 0 ; i < len ; ++ i ) {
481- unsigned char c = str [i ];
482- esc_tok = NULL ;
483- switch (c ) {
484- case 0x22 : esc_tok = "\\\"" ; break ;
485- case 0x5C : esc_tok = "\\\\" ; break ;
486- case '\b' : esc_tok = "\\b" ; break ;
487- case '\f' : esc_tok = "\\f" ; break ;
488- case '\n' : esc_tok = "\\n" ; break ;
489- case '\r' : esc_tok = "\\r" ; break ;
490- case '\t' : esc_tok = "\\t" ; break ;
491- default : if (c <= 0x1F ) {
492- static const char tohex [] = "0123456789abcdef" ;
493- _esc_tok [4 ] = tohex [c >> 4 ];
494- _esc_tok [5 ] = tohex [c & 0xF ];
495- _esc_tok [6 ] = 0 ;
496- esc_tok = _esc_tok ;
497- }
498- }
499- if (esc_tok ) {
500- int j ;
501- for (j = 0 ; esc_tok [j ]; j ++ ) {
502- if (!esc_buf ) /* count how many extra bytes are needed */
503- continue ;
504- * esc_buf ++ = esc_tok [j ];
505- }
506- extra_bytes += j - 1 ;
507- }
508- else if (esc_buf ) {
509- * esc_buf ++ = c ;
510- }
511- }
512-
513- if (* pos + len + extra_bytes > bufsize ) return JSONB_ERROR_NOMEM ;
514-
515- if (esc_buf ) {
516- * pos += len + extra_bytes ;
517- return JSONB_OK ;
518- }
519- if (!extra_bytes ) {
520- size_t j ;
521- for (j = 0 ; j < len ; ++ j )
522- buf [* pos + j ] = str [j ];
523- * pos += len ;
524- return JSONB_OK ;
525- }
526- esc_buf = buf + * pos ;
527- extra_bytes = 0 ;
528- goto second_iter ;
529- }
530-
531533jsonbcode
532534jsonb_push_string (
533535 jsonb * b , char buf [], size_t bufsize , const char str [], size_t len )
0 commit comments