cae5ab17e24788d5da3e81dde61c04d4af3bfc29
[demo.git] / vnfs / VES5.0 / evel / evel-library / code / evel_library / evel_json_buffer.c
1 /*************************************************************************//**
2  *
3  * Copyright © 2017 AT&T Intellectual Property. All rights reserved.
4  *
5  * Unless otherwise specified, all software contained herein is
6  * Licensed under the Apache License, Version 2.0 (the "License");
7  * you may not use this file except in compliance with the License.
8  * You may obtain a copy of the License at
9  *        http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and 
15  * limitations under the License.
16  * ECOMP is a trademark and service mark of AT&T Intellectual Property.
17  ****************************************************************************/
18
19 /**************************************************************************//**
20  * @file
21  * Source module relating to internal EVEL_JSON_BUFFER manipulation functions.
22  *
23  ****************************************************************************/
24
25 #include <assert.h>
26 #include <string.h>
27
28 #include "evel_throttle.h"
29
30 /*****************************************************************************/
31 /* Local prototypes.                                                         */
32 /*****************************************************************************/
33 static char * evel_json_kv_comma(EVEL_JSON_BUFFER * jbuf);
34
35 /**************************************************************************//**
36  * Initialize a ::EVEL_JSON_BUFFER.
37  *
38  * @param jbuf          Pointer to the ::EVEL_JSON_BUFFER to initialise.
39  * @param json          Pointer to the underlying working buffer to use.
40  * @param max_size      Size of storage available in the JSON buffer.
41  * @param throttle_spec Pointer to throttle specification. Can be NULL.
42  *****************************************************************************/
43 void evel_json_buffer_init(EVEL_JSON_BUFFER * jbuf,
44                            char * const json,
45                            const int max_size,
46                            EVEL_THROTTLE_SPEC * throttle_spec)
47 {
48   EVEL_ENTER();
49
50   assert(jbuf != NULL);
51   assert(json != NULL);
52   jbuf->json = json;
53   jbuf->max_size = max_size;
54   jbuf->offset = 0;
55   jbuf->throttle_spec = throttle_spec;
56   jbuf->depth = 0;
57   jbuf->checkpoint = -1;
58
59   EVEL_EXIT();
60 }
61
62 /**************************************************************************//**
63  * Encode an integer value to a JSON buffer.
64  *
65  * @param jbuf          Pointer to working ::EVEL_JSON_BUFFER.
66  * @param value         The integer to add to it.
67  *****************************************************************************/
68 void evel_enc_int(EVEL_JSON_BUFFER * jbuf,
69                   const int value)
70 {
71   EVEL_ENTER();
72
73   /***************************************************************************/
74   /* Check preconditions.                                                    */
75   /***************************************************************************/
76   assert(jbuf != NULL);
77
78   jbuf->offset += snprintf(jbuf->json + jbuf->offset,
79                            jbuf->max_size - jbuf->offset,
80                            "%d", value);
81
82   EVEL_EXIT();
83 }
84
85 /**************************************************************************//**
86  * Encode a string key and string value to a ::EVEL_JSON_BUFFER.
87  *
88  * @param jbuf          Pointer to working ::EVEL_JSON_BUFFER.
89  * @param key           Pointer to the key to encode.
90  * @param option        Pointer to holder of the corresponding value to encode.
91  * @return true if the key, value was added, false if it was suppressed.
92  *****************************************************************************/
93 bool evel_enc_kv_opt_string(EVEL_JSON_BUFFER * jbuf,
94                             const char * const key,
95                             const EVEL_OPTION_STRING * const option)
96 {
97   bool added = false;
98
99   EVEL_ENTER();
100
101   /***************************************************************************/
102   /* Check preconditions.                                                    */
103   /***************************************************************************/
104   assert(option != NULL);
105
106   if (option->is_set)
107   {
108     if ((jbuf->depth == EVEL_THROTTLE_FIELD_DEPTH) &&
109         (jbuf->throttle_spec != NULL) &&
110         evel_throttle_suppress_field(jbuf->throttle_spec, key))
111     {
112       EVEL_INFO("Suppressed: %s, %s", key, option->value);
113     }
114     else
115     {
116       EVEL_DEBUG("Encoded: %s, %s", key, option->value);
117       evel_enc_kv_string(jbuf, key, option->value);
118       added = true;
119     }
120   }
121
122   EVEL_EXIT();
123
124   return added;
125 }
126
127 /**************************************************************************//**
128  * Encode a string key and string value to a ::EVEL_JSON_BUFFER.
129  *
130  * @param jbuf          Pointer to working ::EVEL_JSON_BUFFER.
131  * @param key           Pointer to the key to encode.
132  * @param value         Pointer to the corresponding value to encode.
133  *****************************************************************************/
134 void evel_enc_kv_string(EVEL_JSON_BUFFER * jbuf,
135                         const char * const key,
136                         const char * const value)
137 {
138   int index;
139   int length;
140
141   EVEL_ENTER();
142
143   /***************************************************************************/
144   /* Check preconditions.                                                    */
145   /***************************************************************************/
146   assert(jbuf != NULL);
147   assert(key != NULL);
148
149   jbuf->offset += snprintf(jbuf->json + jbuf->offset,
150                            jbuf->max_size - jbuf->offset,
151                            "%s\"%s\": \"",
152                            evel_json_kv_comma(jbuf),
153                            key);
154
155   /***************************************************************************/
156   /* We need to escape quotation marks and backslashes in the value.         */
157   /***************************************************************************/
158   length = strlen(value);
159
160   for (index = 0; index < length; index++)
161   {
162     /*************************************************************************/
163     /* Drop out if no more space.                                            */
164     /*************************************************************************/
165     if (jbuf->max_size - jbuf->offset < 2)
166     {
167       break;
168     }
169
170     /*************************************************************************/
171     /* Add an escape character if necessary, then write the character        */
172     /* itself.                                                               */
173     /*************************************************************************/
174     if ((value[index] == '\"') || (value[index] == '\\'))
175     {
176       jbuf->json[jbuf->offset] = '\\';
177       jbuf->offset++;
178     }
179
180     jbuf->json[jbuf->offset] = value[index];
181     jbuf->offset++;
182   }
183
184   jbuf->offset += snprintf(jbuf->json + jbuf->offset,
185                            jbuf->max_size - jbuf->offset,
186                            "\"");
187
188   EVEL_EXIT();
189 }
190
191
192 /**************************************************************************//**
193  * Encode a string key and integer value to a ::EVEL_JSON_BUFFER.
194  *
195  * @param jbuf          Pointer to working ::EVEL_JSON_BUFFER.
196  * @param key           Pointer to the key to encode.
197  * @param option        Pointer to holder of the corresponding value to encode.
198  * @return true if the key, value was added, false if it was suppressed.
199  *****************************************************************************/
200 bool evel_enc_kv_opt_int(EVEL_JSON_BUFFER * jbuf,
201                          const char * const key,
202                          const EVEL_OPTION_INT * const option)
203 {
204   bool added = false;
205
206   EVEL_ENTER();
207
208   /***************************************************************************/
209   /* Check preconditions.                                                    */
210   /***************************************************************************/
211   assert(option != NULL);
212
213   if (option->is_set)
214   {
215     if ((jbuf->depth == EVEL_THROTTLE_FIELD_DEPTH) &&
216         (jbuf->throttle_spec != NULL) &&
217         evel_throttle_suppress_field(jbuf->throttle_spec, key))
218     {
219       EVEL_INFO("Suppressed: %s, %d", key, option->value);
220     }
221     else
222     {
223       EVEL_DEBUG("Encoded: %s, %d", key, option->value);
224       evel_enc_kv_int(jbuf, key, option->value);
225       added = true;
226     }
227   }
228
229   EVEL_EXIT();
230
231   return added;
232 }
233
234 /**************************************************************************//**
235  * Encode a string key and integer value to a ::EVEL_JSON_BUFFER.
236  *
237  * @param jbuf          Pointer to working ::EVEL_JSON_BUFFER.
238  * @param key           Pointer to the key to encode.
239  * @param value         The corresponding value to encode.
240  *****************************************************************************/
241 void evel_enc_kv_int(EVEL_JSON_BUFFER * jbuf,
242                      const char * const key,
243                      const int value)
244 {
245   EVEL_ENTER();
246
247   /***************************************************************************/
248   /* Check preconditions.                                                    */
249   /***************************************************************************/
250   assert(jbuf != NULL);
251   assert(key != NULL);
252
253   jbuf->offset += snprintf(jbuf->json + jbuf->offset,
254                            jbuf->max_size - jbuf->offset,
255                            "%s\"%s\": %d",
256                            evel_json_kv_comma(jbuf),
257                            key,
258                            value);
259
260   EVEL_EXIT();
261 }
262
263 /**************************************************************************//**
264  * Encode a string key and json object value to a ::EVEL_JSON_BUFFER.
265  *
266  * @param jbuf          Pointer to working ::EVEL_JSON_BUFFER.
267  * @param key           Pointer to the key to encode.
268  * @param value         The corresponding json string to encode.
269  *****************************************************************************/
270 void evel_enc_kv_object(EVEL_JSON_BUFFER * jbuf,
271                      const char * const key,
272                      const char * value)
273 {
274   EVEL_ENTER();
275
276   /***************************************************************************/
277   /* Check preconditions.                                                    */
278   /***************************************************************************/
279   assert(jbuf != NULL);
280   assert(key != NULL);
281
282   jbuf->offset += snprintf(jbuf->json + jbuf->offset,
283                            jbuf->max_size - jbuf->offset,
284                            "%s\"%s\": %s",
285                            evel_json_kv_comma(jbuf),
286                            key,
287                            value);
288
289   EVEL_EXIT();
290 }
291
292 /**************************************************************************//**
293  * Encode a string key and double value to a ::EVEL_JSON_BUFFER.
294  *
295  * @param jbuf          Pointer to working ::EVEL_JSON_BUFFER.
296  * @param key           Pointer to the key to encode.
297  * @param option        Pointer to holder of the corresponding value to encode.
298  * @return true if the key, value was added, false if it was suppressed.
299  *****************************************************************************/
300 bool evel_enc_kv_opt_double(EVEL_JSON_BUFFER * jbuf,
301                             const char * const key,
302                             const EVEL_OPTION_DOUBLE * const option)
303 {
304   bool added = false;
305
306   EVEL_ENTER();
307
308   /***************************************************************************/
309   /* Check preconditions.                                                    */
310   /***************************************************************************/
311   assert(option != NULL);
312
313   if (option->is_set)
314   {
315     if ((jbuf->depth == EVEL_THROTTLE_FIELD_DEPTH) &&
316         (jbuf->throttle_spec != NULL) &&
317         evel_throttle_suppress_field(jbuf->throttle_spec, key))
318     {
319       EVEL_INFO("Suppressed: %s, %1f", key, option->value);
320     }
321     else
322     {
323       EVEL_DEBUG("Encoded: %s, %1f", key, option->value);
324       evel_enc_kv_double(jbuf, key, option->value);
325       added = true;
326     }
327   }
328
329   EVEL_EXIT();
330
331   return added;
332 }
333
334 /**************************************************************************//**
335  * Encode a string key and double value to a ::EVEL_JSON_BUFFER.
336  *
337  * @param jbuf          Pointer to working ::EVEL_JSON_BUFFER.
338  * @param key           Pointer to the key to encode.
339  * @param value         The corresponding value to encode.
340  *****************************************************************************/
341 void evel_enc_kv_double(EVEL_JSON_BUFFER * jbuf,
342                         const char * const key,
343                         const double value)
344 {
345   EVEL_ENTER();
346
347   /***************************************************************************/
348   /* Check preconditions.                                                    */
349   /***************************************************************************/
350   assert(jbuf != NULL);
351   assert(key != NULL);
352
353   jbuf->offset += snprintf(jbuf->json + jbuf->offset,
354                            jbuf->max_size - jbuf->offset,
355                            "%s\"%s\": %1f",
356                            evel_json_kv_comma(jbuf),
357                            key,
358                            value);
359
360   EVEL_EXIT();
361 }
362
363 /**************************************************************************//**
364  * Encode a string key and unsigned long long value to a ::EVEL_JSON_BUFFER.
365  *
366  * @param jbuf          Pointer to working ::EVEL_JSON_BUFFER.
367  * @param key           Pointer to the key to encode.
368  * @param option        Pointer to holder of the corresponding value to encode.
369  * @return true if the key, value was added, false if it was suppressed.
370  *****************************************************************************/
371 bool evel_enc_kv_opt_ull(EVEL_JSON_BUFFER * jbuf,
372                          const char * const key,
373                          const EVEL_OPTION_ULL * const option)
374 {
375   bool added = false;
376
377   EVEL_ENTER();
378
379   /***************************************************************************/
380   /* Check preconditions.                                                    */
381   /***************************************************************************/
382   assert(option != NULL);
383
384   if (option->is_set)
385   {
386     if ((jbuf->depth == EVEL_THROTTLE_FIELD_DEPTH) &&
387         (jbuf->throttle_spec != NULL) &&
388         evel_throttle_suppress_field(jbuf->throttle_spec, key))
389     {
390       EVEL_INFO("Suppressed: %s, %1lu", key, option->value);
391     }
392     else
393     {
394       EVEL_DEBUG("Encoded: %s, %1lu", key, option->value);
395       evel_enc_kv_ull(jbuf, key, option->value);
396       added = true;
397     }
398   }
399
400   EVEL_EXIT();
401
402   return added;
403 }
404
405 /**************************************************************************//**
406  * Encode a string key and unsigned long long value to a ::EVEL_JSON_BUFFER.
407  *
408  * @param jbuf          Pointer to working ::EVEL_JSON_BUFFER.
409  * @param key           Pointer to the key to encode.
410  * @param value         The corresponding value to encode.
411  *****************************************************************************/
412 void evel_enc_kv_ull(EVEL_JSON_BUFFER * jbuf,
413                      const char * const key,
414                      const unsigned long long value)
415 {
416   EVEL_ENTER();
417
418   /***************************************************************************/
419   /* Check preconditions.                                                    */
420   /***************************************************************************/
421   assert(jbuf != NULL);
422   assert(key != NULL);
423
424   jbuf->offset += snprintf(jbuf->json + jbuf->offset,
425                            jbuf->max_size - jbuf->offset,
426                            "%s\"%s\": %llu",
427                            evel_json_kv_comma(jbuf),
428                            key,
429                            value);
430
431   EVEL_EXIT();
432 }
433
434 /**************************************************************************//**
435  * Encode a string key and time value to a ::EVEL_JSON_BUFFER.
436  *
437  * @param jbuf          Pointer to working ::EVEL_JSON_BUFFER.
438  * @param key           Pointer to the key to encode.
439  * @param option        Pointer to holder of the corresponding value to encode.
440  * @return true if the key, value was added, false if it was suppressed.
441  *****************************************************************************/
442 bool evel_enc_kv_opt_time(EVEL_JSON_BUFFER * jbuf,
443                           const char * const key,
444                           const EVEL_OPTION_TIME * const option)
445 {
446   bool added = false;
447
448   EVEL_ENTER();
449
450   /***************************************************************************/
451   /* Check preconditions.                                                    */
452   /***************************************************************************/
453   assert(option != NULL);
454
455   if (option->is_set)
456   {
457     if ((jbuf->depth == EVEL_THROTTLE_FIELD_DEPTH) &&
458         (jbuf->throttle_spec != NULL) &&
459         evel_throttle_suppress_field(jbuf->throttle_spec, key))
460     {
461       EVEL_INFO("Suppressed time: %s", key);
462     }
463     else
464     {
465       EVEL_DEBUG("Encoded time: %s", key);
466       evel_enc_kv_time(jbuf, key, &option->value);
467       added = true;
468     }
469   }
470
471   EVEL_EXIT();
472
473   return added;
474 }
475
476 /**************************************************************************//**
477  * Encode a string key and time value to a ::EVEL_JSON_BUFFER.
478  *
479  * @param jbuf          Pointer to working ::EVEL_JSON_BUFFER.
480  * @param key           Pointer to the key to encode.
481  * @param time          Pointer to the time to encode.
482  *****************************************************************************/
483 void evel_enc_kv_time(EVEL_JSON_BUFFER * jbuf,
484                       const char * const key,
485                       const time_t * time)
486 {
487   EVEL_ENTER();
488
489   /***************************************************************************/
490   /* Check preconditions.                                                    */
491   /***************************************************************************/
492   assert(jbuf != NULL);
493   assert(key != NULL);
494   assert(time != NULL);
495
496   jbuf->offset += snprintf(jbuf->json + jbuf->offset,
497                            jbuf->max_size - jbuf->offset,
498                            "%s\"%s\": \"",
499                            evel_json_kv_comma(jbuf),
500                            key);
501   jbuf->offset += strftime(jbuf->json + jbuf->offset,
502                            jbuf->max_size - jbuf->offset,
503                            EVEL_RFC2822_STRFTIME_FORMAT,
504                            localtime(time));
505   jbuf->offset += snprintf(jbuf->json + jbuf->offset,
506                            jbuf->max_size - jbuf->offset,
507                            "\"");
508   EVEL_EXIT();
509 }
510
511 /**************************************************************************//**
512  * Encode a key and version.
513  *
514  * @param jbuf          Pointer to working ::EVEL_JSON_BUFFER.
515  * @param key           Pointer to the key to encode.
516  * @param major_version The major version to encode.
517  * @param minor_version The minor version to encode.
518  *****************************************************************************/
519 void evel_enc_version(EVEL_JSON_BUFFER * jbuf,
520                       const char * const key,
521                       const int major_version,
522                       const int minor_version)
523 {
524   EVEL_ENTER();
525
526   /***************************************************************************/
527   /* Check preconditions.                                                    */
528   /***************************************************************************/
529   assert(jbuf != NULL);
530   assert(key != NULL);
531
532   evel_enc_kv_int(jbuf, key, major_version);
533   if (minor_version != 0)
534   {
535     jbuf->offset += snprintf(jbuf->json + jbuf->offset,
536                              jbuf->max_size - jbuf->offset,
537                              ".%d",
538                              minor_version);
539   }
540
541   EVEL_EXIT();
542 }
543
544 /**************************************************************************//**
545  * Add the key and opening bracket of an optional named list to a JSON buffer.
546  *
547  * @param jbuf          Pointer to working ::EVEL_JSON_BUFFER.
548  * @param key           Pointer to the key to encode.
549  * @return true if the list was opened, false if it was suppressed.
550  *****************************************************************************/
551 bool evel_json_open_opt_named_list(EVEL_JSON_BUFFER * jbuf,
552                                    const char * const key)
553 {
554   bool opened = false;
555
556   EVEL_ENTER();
557
558   /***************************************************************************/
559   /* Check preconditions.                                                    */
560   /***************************************************************************/
561   assert(jbuf != NULL);
562   assert(key != NULL);
563
564   if ((jbuf->depth == EVEL_THROTTLE_FIELD_DEPTH) &&
565       (jbuf->throttle_spec != NULL) &&
566       evel_throttle_suppress_field(jbuf->throttle_spec, key))
567   {
568     EVEL_INFO("Suppressed: %s", key);
569     opened = false;
570   }
571   else
572   {
573     evel_json_open_named_list(jbuf, key);
574     opened = true;
575   }
576
577   EVEL_EXIT();
578
579   return opened;
580 }
581
582 /**************************************************************************//**
583  * Add the key and opening bracket of a named list to a JSON buffer.
584  *
585  * @param jbuf          Pointer to working ::EVEL_JSON_BUFFER.
586  * @param key           Pointer to the key to encode.
587  *****************************************************************************/
588 void evel_json_open_named_list(EVEL_JSON_BUFFER * jbuf,
589                                const char * const key)
590 {
591   EVEL_ENTER();
592
593   /***************************************************************************/
594   /* Check preconditions.                                                    */
595   /***************************************************************************/
596   assert(jbuf != NULL);
597   assert(key != NULL);
598
599   jbuf->offset += snprintf(jbuf->json + jbuf->offset,
600                            jbuf->max_size - jbuf->offset,
601                            "%s\"%s\": [",
602                            evel_json_kv_comma(jbuf),
603                            key);
604   jbuf->depth++;
605
606   EVEL_EXIT();
607 }
608
609 /**************************************************************************//**
610  * Add the closing bracket of a list to a JSON buffer.
611  *
612  * @param jbuf          Pointer to working ::EVEL_JSON_BUFFER.
613  *****************************************************************************/
614 void evel_json_close_list(EVEL_JSON_BUFFER * jbuf)
615 {
616   EVEL_ENTER();
617
618   /***************************************************************************/
619   /* Check preconditions.                                                    */
620   /***************************************************************************/
621   assert(jbuf != NULL);
622
623   jbuf->offset += snprintf(jbuf->json + jbuf->offset,
624                            jbuf->max_size - jbuf->offset,
625                            "]");
626   jbuf->depth--;
627
628   EVEL_EXIT();
629 }
630
631 /**************************************************************************//**
632  * Encode a list item with format and param list to a ::EVEL_JSON_BUFFER.
633  *
634  * @param jbuf          Pointer to working ::EVEL_JSON_BUFFER.
635  * @param format        Format string in standard printf format.
636  * @param ...           Variable parameters for format string.
637  *****************************************************************************/
638 void evel_enc_list_item(EVEL_JSON_BUFFER * jbuf,
639                         const char * const format,
640                         ...)
641 {
642   va_list largs;
643
644   EVEL_ENTER();
645
646   /***************************************************************************/
647   /* Check preconditions.                                                    */
648   /***************************************************************************/
649   assert(jbuf != NULL);
650   assert(format != NULL);
651
652   /***************************************************************************/
653   /* Add a comma unless we're at the start of the list.                      */
654   /***************************************************************************/
655   if (jbuf->json[jbuf->offset - 1] != '[')
656   {
657     jbuf->offset += snprintf(jbuf->json + jbuf->offset,
658                              jbuf->max_size - jbuf->offset,
659                              ", ");
660   }
661
662   va_start(largs, format);
663   jbuf->offset += vsnprintf(jbuf->json + jbuf->offset,
664                             jbuf->max_size - jbuf->offset,
665                             format,
666                             largs);
667   va_end(largs);
668
669   EVEL_EXIT();
670 }
671
672 /**************************************************************************//**
673  * Add the opening bracket of an optional named object to a JSON buffer.
674  *
675  * @param jbuf          Pointer to working ::EVEL_JSON_BUFFER.
676  * @param key           Pointer to the key to encode.
677  *****************************************************************************/
678 bool evel_json_open_opt_named_object(EVEL_JSON_BUFFER * jbuf,
679                                      const char * const key)
680 {
681   bool opened = false;
682
683   EVEL_ENTER();
684
685   /***************************************************************************/
686   /* Check preconditions.                                                    */
687   /***************************************************************************/
688   assert(jbuf != NULL);
689   assert(key != NULL);
690
691   if ((jbuf->depth == EVEL_THROTTLE_FIELD_DEPTH) &&
692       (jbuf->throttle_spec != NULL) &&
693       evel_throttle_suppress_field(jbuf->throttle_spec, key))
694   {
695     EVEL_INFO("Suppressed: %s", key);
696     opened = false;
697   }
698   else
699   {
700     evel_json_open_named_object(jbuf, key);
701     opened = true;
702   }
703
704   EVEL_EXIT();
705
706   return opened;
707 }
708
709 /**************************************************************************//**
710  * Add the opening bracket of an object to a JSON buffer.
711  *
712  * @param jbuf          Pointer to working ::EVEL_JSON_BUFFER.
713  * @param key           Pointer to the key to encode.
714  * @return true if the object was opened, false if it was suppressed.
715  *****************************************************************************/
716 void evel_json_open_named_object(EVEL_JSON_BUFFER * jbuf,
717                                  const char * const key)
718 {
719   EVEL_ENTER();
720
721   /***************************************************************************/
722   /* Check preconditions.                                                    */
723   /***************************************************************************/
724   assert(jbuf != NULL);
725   assert(key != NULL);
726
727   jbuf->offset += snprintf(jbuf->json + jbuf->offset,
728                            jbuf->max_size - jbuf->offset,
729                            "%s\"%s\": {",
730                            evel_json_kv_comma(jbuf),
731                            key);
732   jbuf->depth++;
733
734   EVEL_EXIT();
735 }
736
737 /**************************************************************************//**
738  * Add the opening bracket of an object to a JSON buffer.
739  *
740  * @param jbuf          Pointer to working ::EVEL_JSON_BUFFER.
741  *****************************************************************************/
742 void evel_json_open_object(EVEL_JSON_BUFFER * jbuf)
743 {
744   char * comma;
745
746   EVEL_ENTER();
747
748   /***************************************************************************/
749   /* Check preconditions.                                                    */
750   /***************************************************************************/
751   assert(jbuf != NULL);
752
753   if ((jbuf->offset != 0) && (jbuf->json[jbuf->offset-1] == '}'))
754   {
755     comma = ", ";
756   }
757   else
758   {
759     comma = "";
760   }
761
762   jbuf->offset += snprintf(jbuf->json + jbuf->offset,
763                            jbuf->max_size - jbuf->offset,
764                            "%s{",
765                            comma);
766   jbuf->depth++;
767
768   EVEL_EXIT();
769 }
770
771 /**************************************************************************//**
772  * Add the closing bracket of an object to a JSON buffer.
773  *
774  * @param jbuf          Pointer to working ::EVEL_JSON_BUFFER.
775  *****************************************************************************/
776 void evel_json_close_object(EVEL_JSON_BUFFER * jbuf)
777 {
778   EVEL_ENTER();
779
780   /***************************************************************************/
781   /* Check preconditions.                                                    */
782   /***************************************************************************/
783   assert(jbuf != NULL);
784
785   jbuf->offset += snprintf(jbuf->json + jbuf->offset,
786                            jbuf->max_size - jbuf->offset,
787                            "}");
788   jbuf->depth--;
789
790   EVEL_EXIT();
791 }
792
793 /**************************************************************************//**
794  * Determine whether to add a comma when adding a key-value pair.
795  *
796  * @param jbuf          Pointer to working ::EVEL_JSON_BUFFER.
797  * @returns A string containing the comma if it is required.
798  *****************************************************************************/
799 char * evel_json_kv_comma(EVEL_JSON_BUFFER * jbuf)
800 {
801   char * result;
802
803   EVEL_ENTER();
804
805   /***************************************************************************/
806   /* Check preconditions.                                                    */
807   /***************************************************************************/
808   assert(jbuf != NULL);
809
810   if ((jbuf->offset == 0) ||
811       (jbuf->json[jbuf->offset-1] == '{') ||
812       (jbuf->json[jbuf->offset-1] == '['))
813   {
814     result = "";
815   }
816   else
817   {
818     result = ", ";
819   }
820
821   EVEL_EXIT();
822
823   return result;
824 }
825
826 /**************************************************************************//**
827  * Add a checkpoint - a stake in the ground to which we can rewind.
828  *
829  * @param jbuf          Pointer to working ::EVEL_JSON_BUFFER.
830  *****************************************************************************/
831 void evel_json_checkpoint(EVEL_JSON_BUFFER * jbuf)
832 {
833   EVEL_ENTER();
834
835   /***************************************************************************/
836   /* Check preconditions.                                                    */
837   /***************************************************************************/
838   assert(jbuf != NULL);
839
840   /***************************************************************************/
841   /* Store the current offset.                                               */
842   /***************************************************************************/
843   jbuf->checkpoint = jbuf->offset;
844
845   EVEL_EXIT();
846 }
847
848 /**************************************************************************//**
849  * Rewind to the latest checkoint.
850  *
851  * @param jbuf          Pointer to working ::EVEL_JSON_BUFFER.
852  *****************************************************************************/
853 void evel_json_rewind(EVEL_JSON_BUFFER * jbuf)
854 {
855   EVEL_ENTER();
856
857   /***************************************************************************/
858   /* Check preconditions.                                                    */
859   /***************************************************************************/
860   assert(jbuf != NULL);
861   assert(jbuf->checkpoint >= 0);
862   assert(jbuf->checkpoint <= jbuf->offset);
863
864   /***************************************************************************/
865   /* Reinstate the offset from the last checkpoint.                          */
866   /***************************************************************************/
867   jbuf->offset = jbuf->checkpoint;
868   jbuf->checkpoint = -1;
869
870   EVEL_EXIT();
871 }