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)
527 /***************************************************************************/
528 /* Check preconditions. */
529 /***************************************************************************/
530 assert(jbuf != NULL);
533 ver = (float)major_version + (float)minor_version/10.0;
535 jbuf->offset += snprintf(jbuf->json + jbuf->offset,
536 jbuf->max_size - jbuf->offset,
538 evel_json_kv_comma(jbuf),
545 /**************************************************************************//**
546 * Add the key and opening bracket of an optional named list to a JSON buffer.
548 * @param jbuf Pointer to working ::EVEL_JSON_BUFFER.
549 * @param key Pointer to the key to encode.
550 * @return true if the list was opened, false if it was suppressed.
551 *****************************************************************************/
552 bool evel_json_open_opt_named_list(EVEL_JSON_BUFFER * jbuf,
553 const char * const key)
559 /***************************************************************************/
560 /* Check preconditions. */
561 /***************************************************************************/
562 assert(jbuf != NULL);
565 if ((jbuf->depth == EVEL_THROTTLE_FIELD_DEPTH) &&
566 (jbuf->throttle_spec != NULL) &&
567 evel_throttle_suppress_field(jbuf->throttle_spec, key))
569 EVEL_INFO("Suppressed: %s", key);
574 evel_json_open_named_list(jbuf, key);
583 /**************************************************************************//**
584 * Add the key and opening bracket of a named list to a JSON buffer.
586 * @param jbuf Pointer to working ::EVEL_JSON_BUFFER.
587 * @param key Pointer to the key to encode.
588 *****************************************************************************/
589 void evel_json_open_named_list(EVEL_JSON_BUFFER * jbuf,
590 const char * const key)
594 /***************************************************************************/
595 /* Check preconditions. */
596 /***************************************************************************/
597 assert(jbuf != NULL);
600 jbuf->offset += snprintf(jbuf->json + jbuf->offset,
601 jbuf->max_size - jbuf->offset,
603 evel_json_kv_comma(jbuf),
610 /**************************************************************************//**
611 * Add the closing bracket of a list to a JSON buffer.
613 * @param jbuf Pointer to working ::EVEL_JSON_BUFFER.
614 *****************************************************************************/
615 void evel_json_close_list(EVEL_JSON_BUFFER * jbuf)
619 /***************************************************************************/
620 /* Check preconditions. */
621 /***************************************************************************/
622 assert(jbuf != NULL);
624 jbuf->offset += snprintf(jbuf->json + jbuf->offset,
625 jbuf->max_size - jbuf->offset,
632 /**************************************************************************//**
633 * Encode a list item with format and param list to a ::EVEL_JSON_BUFFER.
635 * @param jbuf Pointer to working ::EVEL_JSON_BUFFER.
636 * @param format Format string in standard printf format.
637 * @param ... Variable parameters for format string.
638 *****************************************************************************/
639 void evel_enc_list_item(EVEL_JSON_BUFFER * jbuf,
640 const char * const format,
647 /***************************************************************************/
648 /* Check preconditions. */
649 /***************************************************************************/
650 assert(jbuf != NULL);
651 assert(format != NULL);
653 /***************************************************************************/
654 /* Add a comma unless we're at the start of the list. */
655 /***************************************************************************/
656 if (jbuf->json[jbuf->offset - 1] != '[')
658 jbuf->offset += snprintf(jbuf->json + jbuf->offset,
659 jbuf->max_size - jbuf->offset,
663 va_start(largs, format);
664 jbuf->offset += vsnprintf(jbuf->json + jbuf->offset,
665 jbuf->max_size - jbuf->offset,
673 /**************************************************************************//**
674 * Add the opening bracket of an optional named object to a JSON buffer.
676 * @param jbuf Pointer to working ::EVEL_JSON_BUFFER.
677 * @param key Pointer to the key to encode.
678 *****************************************************************************/
679 bool evel_json_open_opt_named_object(EVEL_JSON_BUFFER * jbuf,
680 const char * const key)
686 /***************************************************************************/
687 /* Check preconditions. */
688 /***************************************************************************/
689 assert(jbuf != NULL);
692 if ((jbuf->depth == EVEL_THROTTLE_FIELD_DEPTH) &&
693 (jbuf->throttle_spec != NULL) &&
694 evel_throttle_suppress_field(jbuf->throttle_spec, key))
696 EVEL_INFO("Suppressed: %s", key);
701 evel_json_open_named_object(jbuf, key);
710 /**************************************************************************//**
711 * Add the opening bracket of an object to a JSON buffer.
713 * @param jbuf Pointer to working ::EVEL_JSON_BUFFER.
714 * @param key Pointer to the key to encode.
715 * @return true if the object was opened, false if it was suppressed.
716 *****************************************************************************/
717 void evel_json_open_named_object(EVEL_JSON_BUFFER * jbuf,
718 const char * const key)
722 /***************************************************************************/
723 /* Check preconditions. */
724 /***************************************************************************/
725 assert(jbuf != NULL);
728 jbuf->offset += snprintf(jbuf->json + jbuf->offset,
729 jbuf->max_size - jbuf->offset,
731 evel_json_kv_comma(jbuf),
738 /**************************************************************************//**
739 * Add the opening bracket of an object to a JSON buffer.
741 * @param jbuf Pointer to working ::EVEL_JSON_BUFFER.
742 *****************************************************************************/
743 void evel_json_open_object(EVEL_JSON_BUFFER * jbuf)
749 /***************************************************************************/
750 /* Check preconditions. */
751 /***************************************************************************/
752 assert(jbuf != NULL);
754 if ((jbuf->offset != 0) && (jbuf->json[jbuf->offset-1] == '}'))
763 jbuf->offset += snprintf(jbuf->json + jbuf->offset,
764 jbuf->max_size - jbuf->offset,
772 /**************************************************************************//**
773 * Add the closing bracket of an object to a JSON buffer.
775 * @param jbuf Pointer to working ::EVEL_JSON_BUFFER.
776 *****************************************************************************/
777 void evel_json_close_object(EVEL_JSON_BUFFER * jbuf)
781 /***************************************************************************/
782 /* Check preconditions. */
783 /***************************************************************************/
784 assert(jbuf != NULL);
786 jbuf->offset += snprintf(jbuf->json + jbuf->offset,
787 jbuf->max_size - jbuf->offset,
794 /**************************************************************************//**
795 * Determine whether to add a comma when adding a key-value pair.
797 * @param jbuf Pointer to working ::EVEL_JSON_BUFFER.
798 * @returns A string containing the comma if it is required.
799 *****************************************************************************/
800 char * evel_json_kv_comma(EVEL_JSON_BUFFER * jbuf)
806 /***************************************************************************/
807 /* Check preconditions. */
808 /***************************************************************************/
809 assert(jbuf != NULL);
811 if ((jbuf->offset == 0) ||
812 (jbuf->json[jbuf->offset-1] == '{') ||
813 (jbuf->json[jbuf->offset-1] == '['))
827 /**************************************************************************//**
828 * Add a checkpoint - a stake in the ground to which we can rewind.
830 * @param jbuf Pointer to working ::EVEL_JSON_BUFFER.
831 *****************************************************************************/
832 void evel_json_checkpoint(EVEL_JSON_BUFFER * jbuf)
836 /***************************************************************************/
837 /* Check preconditions. */
838 /***************************************************************************/
839 assert(jbuf != NULL);
841 /***************************************************************************/
842 /* Store the current offset. */
843 /***************************************************************************/
844 jbuf->checkpoint = jbuf->offset;
849 /**************************************************************************//**
850 * Rewind to the latest checkoint.
852 * @param jbuf Pointer to working ::EVEL_JSON_BUFFER.
853 *****************************************************************************/
854 void evel_json_rewind(EVEL_JSON_BUFFER * jbuf)
858 /***************************************************************************/
859 /* Check preconditions. */
860 /***************************************************************************/
861 assert(jbuf != NULL);
862 assert(jbuf->checkpoint >= 0);
863 assert(jbuf->checkpoint <= jbuf->offset);
865 /***************************************************************************/
866 /* Reinstate the offset from the last checkpoint. */
867 /***************************************************************************/
868 jbuf->offset = jbuf->checkpoint;
869 jbuf->checkpoint = -1;