1 /*************************************************************************//**
3 * Copyright © 2017 AT&T Intellectual Property. All rights reserved.
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
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 ****************************************************************************/
19 /**************************************************************************//**
21 * Source module relating to internal EVEL_JSON_BUFFER manipulation functions.
23 ****************************************************************************/
28 #include "evel_throttle.h"
30 /*****************************************************************************/
31 /* Local prototypes. */
32 /*****************************************************************************/
33 static char * evel_json_kv_comma(EVEL_JSON_BUFFER * jbuf);
35 /**************************************************************************//**
36 * Initialize a ::EVEL_JSON_BUFFER.
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,
46 EVEL_THROTTLE_SPEC * throttle_spec)
53 jbuf->max_size = max_size;
55 jbuf->throttle_spec = throttle_spec;
57 jbuf->checkpoint = -1;
62 /**************************************************************************//**
63 * Encode an integer value to a JSON buffer.
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,
73 /***************************************************************************/
74 /* Check preconditions. */
75 /***************************************************************************/
78 jbuf->offset += snprintf(jbuf->json + jbuf->offset,
79 jbuf->max_size - jbuf->offset,
85 /**************************************************************************//**
86 * Encode a string key and string value to a ::EVEL_JSON_BUFFER.
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)
101 /***************************************************************************/
102 /* Check preconditions. */
103 /***************************************************************************/
104 assert(option != NULL);
108 if ((jbuf->depth == EVEL_THROTTLE_FIELD_DEPTH) &&
109 (jbuf->throttle_spec != NULL) &&
110 evel_throttle_suppress_field(jbuf->throttle_spec, key))
112 EVEL_INFO("Suppressed: %s, %s", key, option->value);
116 EVEL_DEBUG("Encoded: %s, %s", key, option->value);
117 evel_enc_kv_string(jbuf, key, option->value);
127 /**************************************************************************//**
128 * Encode a string key and string value to a ::EVEL_JSON_BUFFER.
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)
143 /***************************************************************************/
144 /* Check preconditions. */
145 /***************************************************************************/
146 assert(jbuf != NULL);
149 jbuf->offset += snprintf(jbuf->json + jbuf->offset,
150 jbuf->max_size - jbuf->offset,
152 evel_json_kv_comma(jbuf),
155 /***************************************************************************/
156 /* We need to escape quotation marks and backslashes in the value. */
157 /***************************************************************************/
158 length = strlen(value);
160 for (index = 0; index < length; index++)
162 /*************************************************************************/
163 /* Drop out if no more space. */
164 /*************************************************************************/
165 if (jbuf->max_size - jbuf->offset < 2)
170 /*************************************************************************/
171 /* Add an escape character if necessary, then write the character */
173 /*************************************************************************/
174 if ((value[index] == '\"') || (value[index] == '\\'))
176 jbuf->json[jbuf->offset] = '\\';
180 jbuf->json[jbuf->offset] = value[index];
184 jbuf->offset += snprintf(jbuf->json + jbuf->offset,
185 jbuf->max_size - jbuf->offset,
192 /**************************************************************************//**
193 * Encode a string key and integer value to a ::EVEL_JSON_BUFFER.
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)
208 /***************************************************************************/
209 /* Check preconditions. */
210 /***************************************************************************/
211 assert(option != NULL);
215 if ((jbuf->depth == EVEL_THROTTLE_FIELD_DEPTH) &&
216 (jbuf->throttle_spec != NULL) &&
217 evel_throttle_suppress_field(jbuf->throttle_spec, key))
219 EVEL_INFO("Suppressed: %s, %d", key, option->value);
223 EVEL_DEBUG("Encoded: %s, %d", key, option->value);
224 evel_enc_kv_int(jbuf, key, option->value);
234 /**************************************************************************//**
235 * Encode a string key and integer value to a ::EVEL_JSON_BUFFER.
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,
247 /***************************************************************************/
248 /* Check preconditions. */
249 /***************************************************************************/
250 assert(jbuf != NULL);
253 jbuf->offset += snprintf(jbuf->json + jbuf->offset,
254 jbuf->max_size - jbuf->offset,
256 evel_json_kv_comma(jbuf),
263 /**************************************************************************//**
264 * Encode a string key and json object value to a ::EVEL_JSON_BUFFER.
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,
276 /***************************************************************************/
277 /* Check preconditions. */
278 /***************************************************************************/
279 assert(jbuf != NULL);
282 jbuf->offset += snprintf(jbuf->json + jbuf->offset,
283 jbuf->max_size - jbuf->offset,
285 evel_json_kv_comma(jbuf),
292 /**************************************************************************//**
293 * Encode a string key and double value to a ::EVEL_JSON_BUFFER.
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)
308 /***************************************************************************/
309 /* Check preconditions. */
310 /***************************************************************************/
311 assert(option != NULL);
315 if ((jbuf->depth == EVEL_THROTTLE_FIELD_DEPTH) &&
316 (jbuf->throttle_spec != NULL) &&
317 evel_throttle_suppress_field(jbuf->throttle_spec, key))
319 EVEL_INFO("Suppressed: %s, %1f", key, option->value);
323 EVEL_DEBUG("Encoded: %s, %1f", key, option->value);
324 evel_enc_kv_double(jbuf, key, option->value);
334 /**************************************************************************//**
335 * Encode a string key and double value to a ::EVEL_JSON_BUFFER.
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,
347 /***************************************************************************/
348 /* Check preconditions. */
349 /***************************************************************************/
350 assert(jbuf != NULL);
353 jbuf->offset += snprintf(jbuf->json + jbuf->offset,
354 jbuf->max_size - jbuf->offset,
356 evel_json_kv_comma(jbuf),
363 /**************************************************************************//**
364 * Encode a string key and unsigned long long value to a ::EVEL_JSON_BUFFER.
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)
379 /***************************************************************************/
380 /* Check preconditions. */
381 /***************************************************************************/
382 assert(option != NULL);
386 if ((jbuf->depth == EVEL_THROTTLE_FIELD_DEPTH) &&
387 (jbuf->throttle_spec != NULL) &&
388 evel_throttle_suppress_field(jbuf->throttle_spec, key))
390 EVEL_INFO("Suppressed: %s, %1lu", key, option->value);
394 EVEL_DEBUG("Encoded: %s, %1lu", key, option->value);
395 evel_enc_kv_ull(jbuf, key, option->value);
405 /**************************************************************************//**
406 * Encode a string key and unsigned long long value to a ::EVEL_JSON_BUFFER.
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)
418 /***************************************************************************/
419 /* Check preconditions. */
420 /***************************************************************************/
421 assert(jbuf != NULL);
424 jbuf->offset += snprintf(jbuf->json + jbuf->offset,
425 jbuf->max_size - jbuf->offset,
427 evel_json_kv_comma(jbuf),
434 /**************************************************************************//**
435 * Encode a string key and time value to a ::EVEL_JSON_BUFFER.
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)
450 /***************************************************************************/
451 /* Check preconditions. */
452 /***************************************************************************/
453 assert(option != NULL);
457 if ((jbuf->depth == EVEL_THROTTLE_FIELD_DEPTH) &&
458 (jbuf->throttle_spec != NULL) &&
459 evel_throttle_suppress_field(jbuf->throttle_spec, key))
461 EVEL_INFO("Suppressed time: %s", key);
465 EVEL_DEBUG("Encoded time: %s", key);
466 evel_enc_kv_time(jbuf, key, &option->value);
476 /**************************************************************************//**
477 * Encode a string key and time value to a ::EVEL_JSON_BUFFER.
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,
489 /***************************************************************************/
490 /* Check preconditions. */
491 /***************************************************************************/
492 assert(jbuf != NULL);
494 assert(time != NULL);
496 jbuf->offset += snprintf(jbuf->json + jbuf->offset,
497 jbuf->max_size - jbuf->offset,
499 evel_json_kv_comma(jbuf),
501 jbuf->offset += strftime(jbuf->json + jbuf->offset,
502 jbuf->max_size - jbuf->offset,
503 EVEL_RFC2822_STRFTIME_FORMAT,
505 jbuf->offset += snprintf(jbuf->json + jbuf->offset,
506 jbuf->max_size - jbuf->offset,
511 /**************************************************************************//**
512 * Encode a key and version.
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)
526 /***************************************************************************/
527 /* Check preconditions. */
528 /***************************************************************************/
529 assert(jbuf != NULL);
532 evel_enc_kv_int(jbuf, key, major_version);
533 if (minor_version != 0)
535 jbuf->offset += snprintf(jbuf->json + jbuf->offset,
536 jbuf->max_size - jbuf->offset,
544 /**************************************************************************//**
545 * Add the key and opening bracket of an optional named list to a JSON buffer.
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)
558 /***************************************************************************/
559 /* Check preconditions. */
560 /***************************************************************************/
561 assert(jbuf != NULL);
564 if ((jbuf->depth == EVEL_THROTTLE_FIELD_DEPTH) &&
565 (jbuf->throttle_spec != NULL) &&
566 evel_throttle_suppress_field(jbuf->throttle_spec, key))
568 EVEL_INFO("Suppressed: %s", key);
573 evel_json_open_named_list(jbuf, key);
582 /**************************************************************************//**
583 * Add the key and opening bracket of a named list to a JSON buffer.
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)
593 /***************************************************************************/
594 /* Check preconditions. */
595 /***************************************************************************/
596 assert(jbuf != NULL);
599 jbuf->offset += snprintf(jbuf->json + jbuf->offset,
600 jbuf->max_size - jbuf->offset,
602 evel_json_kv_comma(jbuf),
609 /**************************************************************************//**
610 * Add the closing bracket of a list to a JSON buffer.
612 * @param jbuf Pointer to working ::EVEL_JSON_BUFFER.
613 *****************************************************************************/
614 void evel_json_close_list(EVEL_JSON_BUFFER * jbuf)
618 /***************************************************************************/
619 /* Check preconditions. */
620 /***************************************************************************/
621 assert(jbuf != NULL);
623 jbuf->offset += snprintf(jbuf->json + jbuf->offset,
624 jbuf->max_size - jbuf->offset,
631 /**************************************************************************//**
632 * Encode a list item with format and param list to a ::EVEL_JSON_BUFFER.
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,
646 /***************************************************************************/
647 /* Check preconditions. */
648 /***************************************************************************/
649 assert(jbuf != NULL);
650 assert(format != NULL);
652 /***************************************************************************/
653 /* Add a comma unless we're at the start of the list. */
654 /***************************************************************************/
655 if (jbuf->json[jbuf->offset - 1] != '[')
657 jbuf->offset += snprintf(jbuf->json + jbuf->offset,
658 jbuf->max_size - jbuf->offset,
662 va_start(largs, format);
663 jbuf->offset += vsnprintf(jbuf->json + jbuf->offset,
664 jbuf->max_size - jbuf->offset,
672 /**************************************************************************//**
673 * Add the opening bracket of an optional named object to a JSON buffer.
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)
685 /***************************************************************************/
686 /* Check preconditions. */
687 /***************************************************************************/
688 assert(jbuf != NULL);
691 if ((jbuf->depth == EVEL_THROTTLE_FIELD_DEPTH) &&
692 (jbuf->throttle_spec != NULL) &&
693 evel_throttle_suppress_field(jbuf->throttle_spec, key))
695 EVEL_INFO("Suppressed: %s", key);
700 evel_json_open_named_object(jbuf, key);
709 /**************************************************************************//**
710 * Add the opening bracket of an object to a JSON buffer.
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)
721 /***************************************************************************/
722 /* Check preconditions. */
723 /***************************************************************************/
724 assert(jbuf != NULL);
727 jbuf->offset += snprintf(jbuf->json + jbuf->offset,
728 jbuf->max_size - jbuf->offset,
730 evel_json_kv_comma(jbuf),
737 /**************************************************************************//**
738 * Add the opening bracket of an object to a JSON buffer.
740 * @param jbuf Pointer to working ::EVEL_JSON_BUFFER.
741 *****************************************************************************/
742 void evel_json_open_object(EVEL_JSON_BUFFER * jbuf)
748 /***************************************************************************/
749 /* Check preconditions. */
750 /***************************************************************************/
751 assert(jbuf != NULL);
753 if ((jbuf->offset != 0) && (jbuf->json[jbuf->offset-1] == '}'))
762 jbuf->offset += snprintf(jbuf->json + jbuf->offset,
763 jbuf->max_size - jbuf->offset,
771 /**************************************************************************//**
772 * Add the closing bracket of an object to a JSON buffer.
774 * @param jbuf Pointer to working ::EVEL_JSON_BUFFER.
775 *****************************************************************************/
776 void evel_json_close_object(EVEL_JSON_BUFFER * jbuf)
780 /***************************************************************************/
781 /* Check preconditions. */
782 /***************************************************************************/
783 assert(jbuf != NULL);
785 jbuf->offset += snprintf(jbuf->json + jbuf->offset,
786 jbuf->max_size - jbuf->offset,
793 /**************************************************************************//**
794 * Determine whether to add a comma when adding a key-value pair.
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)
805 /***************************************************************************/
806 /* Check preconditions. */
807 /***************************************************************************/
808 assert(jbuf != NULL);
810 if ((jbuf->offset == 0) ||
811 (jbuf->json[jbuf->offset-1] == '{') ||
812 (jbuf->json[jbuf->offset-1] == '['))
826 /**************************************************************************//**
827 * Add a checkpoint - a stake in the ground to which we can rewind.
829 * @param jbuf Pointer to working ::EVEL_JSON_BUFFER.
830 *****************************************************************************/
831 void evel_json_checkpoint(EVEL_JSON_BUFFER * jbuf)
835 /***************************************************************************/
836 /* Check preconditions. */
837 /***************************************************************************/
838 assert(jbuf != NULL);
840 /***************************************************************************/
841 /* Store the current offset. */
842 /***************************************************************************/
843 jbuf->checkpoint = jbuf->offset;
848 /**************************************************************************//**
849 * Rewind to the latest checkoint.
851 * @param jbuf Pointer to working ::EVEL_JSON_BUFFER.
852 *****************************************************************************/
853 void evel_json_rewind(EVEL_JSON_BUFFER * jbuf)
857 /***************************************************************************/
858 /* Check preconditions. */
859 /***************************************************************************/
860 assert(jbuf != NULL);
861 assert(jbuf->checkpoint >= 0);
862 assert(jbuf->checkpoint <= jbuf->offset);
864 /***************************************************************************/
865 /* Reinstate the offset from the last checkpoint. */
866 /***************************************************************************/
867 jbuf->offset = jbuf->checkpoint;
868 jbuf->checkpoint = -1;