aboutsummaryrefslogtreecommitdiffstats
path: root/vnfs/VES/code/evel_library/evel_json_buffer.c
diff options
context:
space:
mode:
Diffstat (limited to 'vnfs/VES/code/evel_library/evel_json_buffer.c')
-rw-r--r--vnfs/VES/code/evel_library/evel_json_buffer.c853
1 files changed, 853 insertions, 0 deletions
diff --git a/vnfs/VES/code/evel_library/evel_json_buffer.c b/vnfs/VES/code/evel_library/evel_json_buffer.c
new file mode 100644
index 00000000..7ae3453b
--- /dev/null
+++ b/vnfs/VES/code/evel_library/evel_json_buffer.c
@@ -0,0 +1,853 @@
+/**************************************************************************//**
+ * @file
+ * Source module relating to internal EVEL_JSON_BUFFER manipulation functions.
+ *
+ * License
+ * -------
+ *
+ * Copyright(c) <2016>, AT&T Intellectual Property. All other rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement: This product includes
+ * software developed by the AT&T.
+ * 4. Neither the name of AT&T nor the names of its contributors may be used to
+ * endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY AT&T INTELLECTUAL PROPERTY ''AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL AT&T INTELLECTUAL PROPERTY BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *****************************************************************************/
+
+#include <assert.h>
+#include <string.h>
+
+#include "evel_throttle.h"
+
+/*****************************************************************************/
+/* Local prototypes. */
+/*****************************************************************************/
+static char * evel_json_kv_comma(EVEL_JSON_BUFFER * jbuf);
+
+/**************************************************************************//**
+ * Initialize a ::EVEL_JSON_BUFFER.
+ *
+ * @param jbuf Pointer to the ::EVEL_JSON_BUFFER to initialise.
+ * @param json Pointer to the underlying working buffer to use.
+ * @param max_size Size of storage available in the JSON buffer.
+ * @param throttle_spec Pointer to throttle specification. Can be NULL.
+ *****************************************************************************/
+void evel_json_buffer_init(EVEL_JSON_BUFFER * jbuf,
+ char * const json,
+ const int max_size,
+ EVEL_THROTTLE_SPEC * throttle_spec)
+{
+ EVEL_ENTER();
+
+ assert(jbuf != NULL);
+ assert(json != NULL);
+ jbuf->json = json;
+ jbuf->max_size = max_size;
+ jbuf->offset = 0;
+ jbuf->throttle_spec = throttle_spec;
+ jbuf->depth = 0;
+ jbuf->checkpoint = -1;
+
+ EVEL_EXIT();
+}
+
+/**************************************************************************//**
+ * Encode an integer value to a JSON buffer.
+ *
+ * @param jbuf Pointer to working ::EVEL_JSON_BUFFER.
+ * @param value The integer to add to it.
+ *****************************************************************************/
+void evel_enc_int(EVEL_JSON_BUFFER * jbuf,
+ const int value)
+{
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions. */
+ /***************************************************************************/
+ assert(jbuf != NULL);
+
+ jbuf->offset += snprintf(jbuf->json + jbuf->offset,
+ jbuf->max_size - jbuf->offset,
+ "%d", value);
+
+ EVEL_EXIT();
+}
+
+/**************************************************************************//**
+ * Encode a string key and string value to a ::EVEL_JSON_BUFFER.
+ *
+ * @param jbuf Pointer to working ::EVEL_JSON_BUFFER.
+ * @param key Pointer to the key to encode.
+ * @param option Pointer to holder of the corresponding value to encode.
+ * @return true if the key, value was added, false if it was suppressed.
+ *****************************************************************************/
+bool evel_enc_kv_opt_string(EVEL_JSON_BUFFER * jbuf,
+ const char * const key,
+ const EVEL_OPTION_STRING * const option)
+{
+ bool added = false;
+
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions. */
+ /***************************************************************************/
+ assert(option != NULL);
+
+ if (option->is_set)
+ {
+ if ((jbuf->depth == EVEL_THROTTLE_FIELD_DEPTH) &&
+ (jbuf->throttle_spec != NULL) &&
+ evel_throttle_suppress_field(jbuf->throttle_spec, key))
+ {
+ EVEL_INFO("Suppressed: %s, %s", key, option->value);
+ }
+ else
+ {
+ EVEL_DEBUG("Encoded: %s, %s", key, option->value);
+ evel_enc_kv_string(jbuf, key, option->value);
+ added = true;
+ }
+ }
+
+ EVEL_EXIT();
+
+ return added;
+}
+
+/**************************************************************************//**
+ * Encode a string key and string value to a ::EVEL_JSON_BUFFER.
+ *
+ * @param jbuf Pointer to working ::EVEL_JSON_BUFFER.
+ * @param key Pointer to the key to encode.
+ * @param value Pointer to the corresponding value to encode.
+ *****************************************************************************/
+void evel_enc_kv_string(EVEL_JSON_BUFFER * jbuf,
+ const char * const key,
+ const char * const value)
+{
+ int index;
+ int length;
+
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions. */
+ /***************************************************************************/
+ assert(jbuf != NULL);
+ assert(key != NULL);
+
+ jbuf->offset += snprintf(jbuf->json + jbuf->offset,
+ jbuf->max_size - jbuf->offset,
+ "%s\"%s\": \"",
+ evel_json_kv_comma(jbuf),
+ key);
+
+ /***************************************************************************/
+ /* We need to escape quotation marks and backslashes in the value. */
+ /***************************************************************************/
+ length = strlen(value);
+
+ for (index = 0; index < length; index++)
+ {
+ /*************************************************************************/
+ /* Drop out if no more space. */
+ /*************************************************************************/
+ if (jbuf->max_size - jbuf->offset < 2)
+ {
+ break;
+ }
+
+ /*************************************************************************/
+ /* Add an escape character if necessary, then write the character */
+ /* itself. */
+ /*************************************************************************/
+ if ((value[index] == '\"') || (value[index] == '\\'))
+ {
+ jbuf->json[jbuf->offset] = '\\';
+ jbuf->offset++;
+ }
+
+ jbuf->json[jbuf->offset] = value[index];
+ jbuf->offset++;
+ }
+
+ jbuf->offset += snprintf(jbuf->json + jbuf->offset,
+ jbuf->max_size - jbuf->offset,
+ "\"");
+
+ EVEL_EXIT();
+}
+
+/**************************************************************************//**
+ * Encode a string key and integer value to a ::EVEL_JSON_BUFFER.
+ *
+ * @param jbuf Pointer to working ::EVEL_JSON_BUFFER.
+ * @param key Pointer to the key to encode.
+ * @param option Pointer to holder of the corresponding value to encode.
+ * @return true if the key, value was added, false if it was suppressed.
+ *****************************************************************************/
+bool evel_enc_kv_opt_int(EVEL_JSON_BUFFER * jbuf,
+ const char * const key,
+ const EVEL_OPTION_INT * const option)
+{
+ bool added = false;
+
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions. */
+ /***************************************************************************/
+ assert(option != NULL);
+
+ if (option->is_set)
+ {
+ if ((jbuf->depth == EVEL_THROTTLE_FIELD_DEPTH) &&
+ (jbuf->throttle_spec != NULL) &&
+ evel_throttle_suppress_field(jbuf->throttle_spec, key))
+ {
+ EVEL_INFO("Suppressed: %s, %d", key, option->value);
+ }
+ else
+ {
+ EVEL_DEBUG("Encoded: %s, %d", key, option->value);
+ evel_enc_kv_int(jbuf, key, option->value);
+ added = true;
+ }
+ }
+
+ EVEL_EXIT();
+
+ return added;
+}
+
+/**************************************************************************//**
+ * Encode a string key and integer value to a ::EVEL_JSON_BUFFER.
+ *
+ * @param jbuf Pointer to working ::EVEL_JSON_BUFFER.
+ * @param key Pointer to the key to encode.
+ * @param value The corresponding value to encode.
+ *****************************************************************************/
+void evel_enc_kv_int(EVEL_JSON_BUFFER * jbuf,
+ const char * const key,
+ const int value)
+{
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions. */
+ /***************************************************************************/
+ assert(jbuf != NULL);
+ assert(key != NULL);
+
+ jbuf->offset += snprintf(jbuf->json + jbuf->offset,
+ jbuf->max_size - jbuf->offset,
+ "%s\"%s\": %d",
+ evel_json_kv_comma(jbuf),
+ key,
+ value);
+
+ EVEL_EXIT();
+}
+
+/**************************************************************************//**
+ * Encode a string key and double value to a ::EVEL_JSON_BUFFER.
+ *
+ * @param jbuf Pointer to working ::EVEL_JSON_BUFFER.
+ * @param key Pointer to the key to encode.
+ * @param option Pointer to holder of the corresponding value to encode.
+ * @return true if the key, value was added, false if it was suppressed.
+ *****************************************************************************/
+bool evel_enc_kv_opt_double(EVEL_JSON_BUFFER * jbuf,
+ const char * const key,
+ const EVEL_OPTION_DOUBLE * const option)
+{
+ bool added = false;
+
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions. */
+ /***************************************************************************/
+ assert(option != NULL);
+
+ if (option->is_set)
+ {
+ if ((jbuf->depth == EVEL_THROTTLE_FIELD_DEPTH) &&
+ (jbuf->throttle_spec != NULL) &&
+ evel_throttle_suppress_field(jbuf->throttle_spec, key))
+ {
+ EVEL_INFO("Suppressed: %s, %1f", key, option->value);
+ }
+ else
+ {
+ EVEL_DEBUG("Encoded: %s, %1f", key, option->value);
+ evel_enc_kv_double(jbuf, key, option->value);
+ added = true;
+ }
+ }
+
+ EVEL_EXIT();
+
+ return added;
+}
+
+/**************************************************************************//**
+ * Encode a string key and double value to a ::EVEL_JSON_BUFFER.
+ *
+ * @param jbuf Pointer to working ::EVEL_JSON_BUFFER.
+ * @param key Pointer to the key to encode.
+ * @param value The corresponding value to encode.
+ *****************************************************************************/
+void evel_enc_kv_double(EVEL_JSON_BUFFER * jbuf,
+ const char * const key,
+ const double value)
+{
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions. */
+ /***************************************************************************/
+ assert(jbuf != NULL);
+ assert(key != NULL);
+
+ jbuf->offset += snprintf(jbuf->json + jbuf->offset,
+ jbuf->max_size - jbuf->offset,
+ "%s\"%s\": %1f",
+ evel_json_kv_comma(jbuf),
+ key,
+ value);
+
+ EVEL_EXIT();
+}
+
+/**************************************************************************//**
+ * Encode a string key and unsigned long long value to a ::EVEL_JSON_BUFFER.
+ *
+ * @param jbuf Pointer to working ::EVEL_JSON_BUFFER.
+ * @param key Pointer to the key to encode.
+ * @param option Pointer to holder of the corresponding value to encode.
+ * @return true if the key, value was added, false if it was suppressed.
+ *****************************************************************************/
+bool evel_enc_kv_opt_ull(EVEL_JSON_BUFFER * jbuf,
+ const char * const key,
+ const EVEL_OPTION_ULL * const option)
+{
+ bool added = false;
+
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions. */
+ /***************************************************************************/
+ assert(option != NULL);
+
+ if (option->is_set)
+ {
+ if ((jbuf->depth == EVEL_THROTTLE_FIELD_DEPTH) &&
+ (jbuf->throttle_spec != NULL) &&
+ evel_throttle_suppress_field(jbuf->throttle_spec, key))
+ {
+ EVEL_INFO("Suppressed: %s, %1lu", key, option->value);
+ }
+ else
+ {
+ EVEL_DEBUG("Encoded: %s, %1lu", key, option->value);
+ evel_enc_kv_ull(jbuf, key, option->value);
+ added = true;
+ }
+ }
+
+ EVEL_EXIT();
+
+ return added;
+}
+
+/**************************************************************************//**
+ * Encode a string key and unsigned long long value to a ::EVEL_JSON_BUFFER.
+ *
+ * @param jbuf Pointer to working ::EVEL_JSON_BUFFER.
+ * @param key Pointer to the key to encode.
+ * @param value The corresponding value to encode.
+ *****************************************************************************/
+void evel_enc_kv_ull(EVEL_JSON_BUFFER * jbuf,
+ const char * const key,
+ const unsigned long long value)
+{
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions. */
+ /***************************************************************************/
+ assert(jbuf != NULL);
+ assert(key != NULL);
+
+ jbuf->offset += snprintf(jbuf->json + jbuf->offset,
+ jbuf->max_size - jbuf->offset,
+ "%s\"%s\": %llu",
+ evel_json_kv_comma(jbuf),
+ key,
+ value);
+
+ EVEL_EXIT();
+}
+
+/**************************************************************************//**
+ * Encode a string key and time value to a ::EVEL_JSON_BUFFER.
+ *
+ * @param jbuf Pointer to working ::EVEL_JSON_BUFFER.
+ * @param key Pointer to the key to encode.
+ * @param option Pointer to holder of the corresponding value to encode.
+ * @return true if the key, value was added, false if it was suppressed.
+ *****************************************************************************/
+bool evel_enc_kv_opt_time(EVEL_JSON_BUFFER * jbuf,
+ const char * const key,
+ const EVEL_OPTION_TIME * const option)
+{
+ bool added = false;
+
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions. */
+ /***************************************************************************/
+ assert(option != NULL);
+
+ if (option->is_set)
+ {
+ if ((jbuf->depth == EVEL_THROTTLE_FIELD_DEPTH) &&
+ (jbuf->throttle_spec != NULL) &&
+ evel_throttle_suppress_field(jbuf->throttle_spec, key))
+ {
+ EVEL_INFO("Suppressed time: %s", key);
+ }
+ else
+ {
+ EVEL_DEBUG("Encoded time: %s", key);
+ evel_enc_kv_time(jbuf, key, &option->value);
+ added = true;
+ }
+ }
+
+ EVEL_EXIT();
+
+ return added;
+}
+
+/**************************************************************************//**
+ * Encode a string key and time value to a ::EVEL_JSON_BUFFER.
+ *
+ * @param jbuf Pointer to working ::EVEL_JSON_BUFFER.
+ * @param key Pointer to the key to encode.
+ * @param time Pointer to the time to encode.
+ *****************************************************************************/
+void evel_enc_kv_time(EVEL_JSON_BUFFER * jbuf,
+ const char * const key,
+ const time_t * time)
+{
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions. */
+ /***************************************************************************/
+ assert(jbuf != NULL);
+ assert(key != NULL);
+ assert(time != NULL);
+
+ jbuf->offset += snprintf(jbuf->json + jbuf->offset,
+ jbuf->max_size - jbuf->offset,
+ "%s\"%s\": \"",
+ evel_json_kv_comma(jbuf),
+ key);
+ jbuf->offset += strftime(jbuf->json + jbuf->offset,
+ jbuf->max_size - jbuf->offset,
+ EVEL_RFC2822_STRFTIME_FORMAT,
+ localtime(time));
+ jbuf->offset += snprintf(jbuf->json + jbuf->offset,
+ jbuf->max_size - jbuf->offset,
+ "\"");
+ EVEL_EXIT();
+}
+
+/**************************************************************************//**
+ * Encode a key and version.
+ *
+ * @param jbuf Pointer to working ::EVEL_JSON_BUFFER.
+ * @param key Pointer to the key to encode.
+ * @param major_version The major version to encode.
+ * @param minor_version The minor version to encode.
+ *****************************************************************************/
+void evel_enc_version(EVEL_JSON_BUFFER * jbuf,
+ const char * const key,
+ const int major_version,
+ const int minor_version)
+{
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions. */
+ /***************************************************************************/
+ assert(jbuf != NULL);
+ assert(key != NULL);
+
+ evel_enc_kv_int(jbuf, key, major_version);
+ if (minor_version != 0)
+ {
+ jbuf->offset += snprintf(jbuf->json + jbuf->offset,
+ jbuf->max_size - jbuf->offset,
+ ".%d",
+ minor_version);
+ }
+
+ EVEL_EXIT();
+}
+
+/**************************************************************************//**
+ * Add the key and opening bracket of an optional named list to a JSON buffer.
+ *
+ * @param jbuf Pointer to working ::EVEL_JSON_BUFFER.
+ * @param key Pointer to the key to encode.
+ * @return true if the list was opened, false if it was suppressed.
+ *****************************************************************************/
+bool evel_json_open_opt_named_list(EVEL_JSON_BUFFER * jbuf,
+ const char * const key)
+{
+ bool opened = false;
+
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions. */
+ /***************************************************************************/
+ assert(jbuf != NULL);
+ assert(key != NULL);
+
+ if ((jbuf->depth == EVEL_THROTTLE_FIELD_DEPTH) &&
+ (jbuf->throttle_spec != NULL) &&
+ evel_throttle_suppress_field(jbuf->throttle_spec, key))
+ {
+ EVEL_INFO("Suppressed: %s", key);
+ opened = false;
+ }
+ else
+ {
+ evel_json_open_named_list(jbuf, key);
+ opened = true;
+ }
+
+ EVEL_EXIT();
+
+ return opened;
+}
+
+/**************************************************************************//**
+ * Add the key and opening bracket of a named list to a JSON buffer.
+ *
+ * @param jbuf Pointer to working ::EVEL_JSON_BUFFER.
+ * @param key Pointer to the key to encode.
+ *****************************************************************************/
+void evel_json_open_named_list(EVEL_JSON_BUFFER * jbuf,
+ const char * const key)
+{
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions. */
+ /***************************************************************************/
+ assert(jbuf != NULL);
+ assert(key != NULL);
+
+ jbuf->offset += snprintf(jbuf->json + jbuf->offset,
+ jbuf->max_size - jbuf->offset,
+ "%s\"%s\": [",
+ evel_json_kv_comma(jbuf),
+ key);
+ jbuf->depth++;
+
+ EVEL_EXIT();
+}
+
+/**************************************************************************//**
+ * Add the closing bracket of a list to a JSON buffer.
+ *
+ * @param jbuf Pointer to working ::EVEL_JSON_BUFFER.
+ *****************************************************************************/
+void evel_json_close_list(EVEL_JSON_BUFFER * jbuf)
+{
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions. */
+ /***************************************************************************/
+ assert(jbuf != NULL);
+
+ jbuf->offset += snprintf(jbuf->json + jbuf->offset,
+ jbuf->max_size - jbuf->offset,
+ "]");
+ jbuf->depth--;
+
+ EVEL_EXIT();
+}
+
+/**************************************************************************//**
+ * Encode a list item with format and param list to a ::EVEL_JSON_BUFFER.
+ *
+ * @param jbuf Pointer to working ::EVEL_JSON_BUFFER.
+ * @param format Format string in standard printf format.
+ * @param ... Variable parameters for format string.
+ *****************************************************************************/
+void evel_enc_list_item(EVEL_JSON_BUFFER * jbuf,
+ const char * const format,
+ ...)
+{
+ va_list largs;
+
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions. */
+ /***************************************************************************/
+ assert(jbuf != NULL);
+ assert(format != NULL);
+
+ /***************************************************************************/
+ /* Add a comma unless we're at the start of the list. */
+ /***************************************************************************/
+ if (jbuf->json[jbuf->offset - 1] != '[')
+ {
+ jbuf->offset += snprintf(jbuf->json + jbuf->offset,
+ jbuf->max_size - jbuf->offset,
+ ", ");
+ }
+
+ va_start(largs, format);
+ jbuf->offset += vsnprintf(jbuf->json + jbuf->offset,
+ jbuf->max_size - jbuf->offset,
+ format,
+ largs);
+ va_end(largs);
+
+ EVEL_EXIT();
+}
+
+/**************************************************************************//**
+ * Add the opening bracket of an optional named object to a JSON buffer.
+ *
+ * @param jbuf Pointer to working ::EVEL_JSON_BUFFER.
+ * @param key Pointer to the key to encode.
+ *****************************************************************************/
+bool evel_json_open_opt_named_object(EVEL_JSON_BUFFER * jbuf,
+ const char * const key)
+{
+ bool opened = false;
+
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions. */
+ /***************************************************************************/
+ assert(jbuf != NULL);
+ assert(key != NULL);
+
+ if ((jbuf->depth == EVEL_THROTTLE_FIELD_DEPTH) &&
+ (jbuf->throttle_spec != NULL) &&
+ evel_throttle_suppress_field(jbuf->throttle_spec, key))
+ {
+ EVEL_INFO("Suppressed: %s", key);
+ opened = false;
+ }
+ else
+ {
+ evel_json_open_named_object(jbuf, key);
+ opened = true;
+ }
+
+ EVEL_EXIT();
+
+ return opened;
+}
+
+/**************************************************************************//**
+ * Add the opening bracket of an object to a JSON buffer.
+ *
+ * @param jbuf Pointer to working ::EVEL_JSON_BUFFER.
+ * @param key Pointer to the key to encode.
+ * @return true if the object was opened, false if it was suppressed.
+ *****************************************************************************/
+void evel_json_open_named_object(EVEL_JSON_BUFFER * jbuf,
+ const char * const key)
+{
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions. */
+ /***************************************************************************/
+ assert(jbuf != NULL);
+ assert(key != NULL);
+
+ jbuf->offset += snprintf(jbuf->json + jbuf->offset,
+ jbuf->max_size - jbuf->offset,
+ "%s\"%s\": {",
+ evel_json_kv_comma(jbuf),
+ key);
+ jbuf->depth++;
+
+ EVEL_EXIT();
+}
+
+/**************************************************************************//**
+ * Add the opening bracket of an object to a JSON buffer.
+ *
+ * @param jbuf Pointer to working ::EVEL_JSON_BUFFER.
+ *****************************************************************************/
+void evel_json_open_object(EVEL_JSON_BUFFER * jbuf)
+{
+ char * comma;
+
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions. */
+ /***************************************************************************/
+ assert(jbuf != NULL);
+
+ if ((jbuf->offset != 0) && (jbuf->json[jbuf->offset-1] == '}'))
+ {
+ comma = ", ";
+ }
+ else
+ {
+ comma = "";
+ }
+
+ jbuf->offset += snprintf(jbuf->json + jbuf->offset,
+ jbuf->max_size - jbuf->offset,
+ "%s{",
+ comma);
+ jbuf->depth++;
+
+ EVEL_EXIT();
+}
+
+/**************************************************************************//**
+ * Add the closing bracket of an object to a JSON buffer.
+ *
+ * @param jbuf Pointer to working ::EVEL_JSON_BUFFER.
+ *****************************************************************************/
+void evel_json_close_object(EVEL_JSON_BUFFER * jbuf)
+{
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions. */
+ /***************************************************************************/
+ assert(jbuf != NULL);
+
+ jbuf->offset += snprintf(jbuf->json + jbuf->offset,
+ jbuf->max_size - jbuf->offset,
+ "}");
+ jbuf->depth--;
+
+ EVEL_EXIT();
+}
+
+/**************************************************************************//**
+ * Determine whether to add a comma when adding a key-value pair.
+ *
+ * @param jbuf Pointer to working ::EVEL_JSON_BUFFER.
+ * @returns A string containing the comma if it is required.
+ *****************************************************************************/
+char * evel_json_kv_comma(EVEL_JSON_BUFFER * jbuf)
+{
+ char * result;
+
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions. */
+ /***************************************************************************/
+ assert(jbuf != NULL);
+
+ if ((jbuf->offset == 0) ||
+ (jbuf->json[jbuf->offset-1] == '{') ||
+ (jbuf->json[jbuf->offset-1] == '['))
+ {
+ result = "";
+ }
+ else
+ {
+ result = ", ";
+ }
+
+ EVEL_EXIT();
+
+ return result;
+}
+
+/**************************************************************************//**
+ * Add a checkpoint - a stake in the ground to which we can rewind.
+ *
+ * @param jbuf Pointer to working ::EVEL_JSON_BUFFER.
+ *****************************************************************************/
+void evel_json_checkpoint(EVEL_JSON_BUFFER * jbuf)
+{
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions. */
+ /***************************************************************************/
+ assert(jbuf != NULL);
+
+ /***************************************************************************/
+ /* Store the current offset. */
+ /***************************************************************************/
+ jbuf->checkpoint = jbuf->offset;
+
+ EVEL_EXIT();
+}
+
+/**************************************************************************//**
+ * Rewind to the latest checkoint.
+ *
+ * @param jbuf Pointer to working ::EVEL_JSON_BUFFER.
+ *****************************************************************************/
+void evel_json_rewind(EVEL_JSON_BUFFER * jbuf)
+{
+ EVEL_ENTER();
+
+ /***************************************************************************/
+ /* Check preconditions. */
+ /***************************************************************************/
+ assert(jbuf != NULL);
+ assert(jbuf->checkpoint >= 0);
+ assert(jbuf->checkpoint <= jbuf->offset);
+
+ /***************************************************************************/
+ /* Reinstate the offset from the last checkpoint. */
+ /***************************************************************************/
+ jbuf->offset = jbuf->checkpoint;
+ jbuf->checkpoint = -1;
+
+ EVEL_EXIT();
+}