summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas Haller <thaller@redhat.com>2019-05-09 14:25:10 +0200
committerThomas Haller <thaller@redhat.com>2019-05-22 21:24:56 +0200
commitdccaea0755ef0e2f42e25bce99da7ecbd6ff4fca (patch)
tree7ec54b62810dbcf5fc4cdc45b6955672e77d87b6
parenta0de3fdcaa5d76d4118a105653c6e1f46c51878c (diff)
downloadNetworkManager-dccaea0755ef0e2f42e25bce99da7ecbd6ff4fca.tar.gz
shared: add nm_json_aux_gstr_append_*() helper
-rw-r--r--shared/nm-glib-aux/nm-json-aux.c127
-rw-r--r--shared/nm-glib-aux/nm-json-aux.h36
2 files changed, 163 insertions, 0 deletions
diff --git a/shared/nm-glib-aux/nm-json-aux.c b/shared/nm-glib-aux/nm-json-aux.c
index f7ec100df0..6f04ef2b44 100644
--- a/shared/nm-glib-aux/nm-json-aux.c
+++ b/shared/nm-glib-aux/nm-json-aux.c
@@ -20,3 +20,130 @@
#include "nm-default.h"
#include "nm-json-aux.h"
+
+/*****************************************************************************/
+
+static void
+_gstr_append_string_len (GString *gstr,
+ const char *str,
+ gsize len)
+{
+ g_string_append_c (gstr, '\"');
+
+ while (len > 0) {
+ gsize n;
+ const char *end;
+ gboolean valid;
+
+ nm_assert (len > 0);
+
+ valid = g_utf8_validate (str, len, &end);
+
+ nm_assert ( end
+ && end >= str
+ && end <= &str[len]);
+
+ if (end > str) {
+ const char *s;
+
+ for (s = str; s < end; s++) {
+ nm_assert (s[0] != '\0');
+
+ if (s[0] < 0x20) {
+ const char *text;
+
+ switch (s[0]) {
+ case '\\': text = "\\\\"; break;
+ case '\"': text = "\\\""; break;
+ case '\b': text = "\\b"; break;
+ case '\f': text = "\\f"; break;
+ case '\n': text = "\\n"; break;
+ case '\r': text = "\\r"; break;
+ case '\t': text = "\\t"; break;
+ default:
+ g_string_append_printf (gstr, "\\u%04X", (guint) s[0]);
+ continue;
+ }
+ g_string_append (gstr, text);
+ continue;
+ }
+
+ if (NM_IN_SET (s[0], '\\', '\"'))
+ g_string_append_c (gstr, '\\');
+ g_string_append_c (gstr, s[0]);
+ }
+ } else
+ nm_assert (!valid);
+
+ if (valid) {
+ nm_assert (end == &str[len]);
+ break;
+ }
+
+ nm_assert (end < &str[len]);
+
+ if (end[0] == '\0') {
+ /* there is a NUL byte in the string. Technically this is valid UTF-8, so we
+ * encode it there. However, this will likely result in a truncated string when
+ * parsing. */
+ g_string_append (gstr, "\\u0000");
+ } else {
+ /* the character is not valid UTF-8. There is nothing we can do about it, because
+ * JSON can only contain UTF-8 and even the escape sequences can only escape Unicode
+ * codepoints (but not binary).
+ *
+ * The argument is not a a string (in any known encoding), hence we cannot represent
+ * it as a JSON string (which are unicode strings).
+ *
+ * Print an underscore instead of the invalid char :) */
+ g_string_append_c (gstr, '_');
+ }
+
+ n = str - end;
+ nm_assert (n < len);
+ n++;
+ str += n;
+ len -= n;
+ }
+
+ g_string_append_c (gstr, '\"');
+}
+
+void
+nm_json_aux_gstr_append_string_len (GString *gstr,
+ const char *str,
+ gsize n)
+{
+ g_return_if_fail (gstr);
+
+ _gstr_append_string_len (gstr, str, n);
+}
+
+void
+nm_json_aux_gstr_append_string (GString *gstr,
+ const char *str)
+{
+ g_return_if_fail (gstr);
+
+ if (!str)
+ g_string_append (gstr, "null");
+ else
+ _gstr_append_string_len (gstr, str, strlen (str));
+}
+
+void
+nm_json_aux_gstr_append_obj_name (GString *gstr,
+ const char *key,
+ char start_container)
+{
+ g_return_if_fail (gstr);
+ g_return_if_fail (key);
+
+ nm_json_aux_gstr_append_string (gstr, key);
+
+ if (start_container != '\0') {
+ nm_assert (NM_IN_SET (start_container, '[', '{'));
+ g_string_append_printf (gstr, ": %c ", start_container);
+ } else
+ g_string_append (gstr, ": ");
+}
diff --git a/shared/nm-glib-aux/nm-json-aux.h b/shared/nm-glib-aux/nm-json-aux.h
index 0a3496c4db..8d6c2c4f46 100644
--- a/shared/nm-glib-aux/nm-json-aux.h
+++ b/shared/nm-glib-aux/nm-json-aux.h
@@ -20,4 +20,40 @@
#ifndef __NM_JSON_AUX_H__
#define __NM_JSON_AUX_H__
+/*****************************************************************************/
+
+static inline GString *
+nm_json_aux_gstr_append_delimiter (GString *gstr)
+{
+ g_string_append (gstr, ", ");
+ return gstr;
+}
+
+void nm_json_aux_gstr_append_string_len (GString *gstr,
+ const char *str,
+ gsize n);
+
+void nm_json_aux_gstr_append_string (GString *gstr,
+ const char *str);
+
+static inline void
+nm_json_aux_gstr_append_bool (GString *gstr,
+ gboolean v)
+{
+ g_string_append (gstr, v ? "true" : "false");
+}
+
+static inline void
+nm_json_aux_gstr_append_int64 (GString *gstr,
+ gint64 v)
+{
+ g_string_append_printf (gstr, "%"G_GINT64_FORMAT, v);
+}
+
+void nm_json_aux_gstr_append_obj_name (GString *gstr,
+ const char *key,
+ char start_container);
+
+/*****************************************************************************/
+
#endif /* __NM_JSON_AUX_H__ */