aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/rcl/rcl.h1
-rw-r--r--src/rcl/rcl_emitter.c253
2 files changed, 216 insertions, 38 deletions
diff --git a/src/rcl/rcl.h b/src/rcl/rcl.h
index 545dd19f9..8d49cc8ad 100644
--- a/src/rcl/rcl.h
+++ b/src/rcl/rcl.h
@@ -54,6 +54,7 @@ enum rspamd_cl_type {
enum rspamd_cl_emitter {
RSPAMD_CL_EMIT_JSON = 0,
+ RSPAMD_CL_EMIT_JSON_COMPACT,
RSPAMD_CL_EMIT_CONFIG
};
diff --git a/src/rcl/rcl_emitter.c b/src/rcl/rcl_emitter.c
index c8edf0d9e..05ca87da6 100644
--- a/src/rcl/rcl_emitter.c
+++ b/src/rcl/rcl_emitter.c
@@ -31,8 +31,9 @@
*/
-static void rspamd_cl_elt_write_json (rspamd_cl_object_t *obj, GString *buf, guint tabs, gboolean start_tabs);
-static void rspamd_cl_obj_write_json (rspamd_cl_object_t *obj, GString *buf, guint tabs, gboolean start_tabs);
+static void rspamd_cl_elt_write_json (rspamd_cl_object_t *obj, GString *buf, guint tabs, gboolean start_tabs, gboolean compact);
+static void rspamd_cl_obj_write_json (rspamd_cl_object_t *obj, GString *buf, guint tabs, gboolean start_tabs, gboolean compact);
+static void rspamd_cl_elt_write_rcl (rspamd_cl_object_t *obj, GString *buf, guint tabs, gboolean start_tabs, gboolean is_top);
/**
* Add tabulation to the output buffer
@@ -40,9 +41,9 @@ static void rspamd_cl_obj_write_json (rspamd_cl_object_t *obj, GString *buf, gui
* @param tabs number of tabs to add
*/
static inline void
-rspamd_cl_add_tabs (GString *buf, guint tabs)
+rspamd_cl_add_tabs (GString *buf, guint tabs, gboolean compact)
{
- while (tabs--) {
+ while (!compact && tabs--) {
g_string_append_len (buf, " ", 4);
}
}
@@ -96,27 +97,42 @@ rspamd_cl_elt_string_write_json (const gchar *str, GString *buf)
* @param buf target buffer
*/
static void
-rspamd_cl_elt_obj_write_json (rspamd_cl_object_t *obj, GString *buf, guint tabs, gboolean start_tabs)
+rspamd_cl_elt_obj_write_json (rspamd_cl_object_t *obj, GString *buf, guint tabs, gboolean start_tabs, gboolean compact)
{
rspamd_cl_object_t *cur, *tmp;
if (start_tabs) {
- rspamd_cl_add_tabs (buf, tabs);
+ rspamd_cl_add_tabs (buf, tabs, compact);
+ }
+ if (compact) {
+ g_string_append_c (buf, '{');
+ }
+ else {
+ g_string_append_len (buf, "{\n", 2);
}
- g_string_append_len (buf, "{\n", 2);
HASH_ITER (hh, obj, cur, tmp) {
- rspamd_cl_add_tabs (buf, tabs + 1);
+ rspamd_cl_add_tabs (buf, tabs + 1, compact);
rspamd_cl_elt_string_write_json (cur->key, buf);
- g_string_append_len (buf, ": ", 2);
- rspamd_cl_obj_write_json (cur, buf, tabs + 1, FALSE);
- if (cur->hh.next != NULL) {
- g_string_append_len (buf, ",\n", 2);
+ if (compact) {
+ g_string_append_c (buf, ':');
}
else {
+ g_string_append_len (buf, ": ", 2);
+ }
+ rspamd_cl_obj_write_json (cur, buf, tabs + 1, FALSE, compact);
+ if (cur->hh.next != NULL) {
+ if (compact) {
+ g_string_append_c (buf, ',');
+ }
+ else {
+ g_string_append_len (buf, ",\n", 2);
+ }
+ }
+ else if (!compact) {
g_string_append_c (buf, '\n');
}
}
- rspamd_cl_add_tabs (buf, tabs);
+ rspamd_cl_add_tabs (buf, tabs, compact);
g_string_append_c (buf, '}');
}
@@ -126,25 +142,35 @@ rspamd_cl_elt_obj_write_json (rspamd_cl_object_t *obj, GString *buf, guint tabs,
* @param buf target buffer
*/
static void
-rspamd_cl_elt_array_write_json (rspamd_cl_object_t *obj, GString *buf, guint tabs, gboolean start_tabs)
+rspamd_cl_elt_array_write_json (rspamd_cl_object_t *obj, GString *buf, guint tabs, gboolean start_tabs, gboolean compact)
{
rspamd_cl_object_t *cur = obj;
if (start_tabs) {
- rspamd_cl_add_tabs (buf, tabs);
+ rspamd_cl_add_tabs (buf, tabs, compact);
+ }
+ if (compact) {
+ g_string_append_c (buf, '[');
+ }
+ else {
+ g_string_append_len (buf, "[\n", 2);
}
- g_string_append_len (buf, "[\n", 2);
while (cur) {
- rspamd_cl_elt_write_json (cur, buf, tabs + 1, TRUE);
+ rspamd_cl_elt_write_json (cur, buf, tabs + 1, TRUE, compact);
if (cur->next != NULL) {
- g_string_append_len (buf, ",\n", 2);
+ if (compact) {
+ g_string_append_c (buf, ',');
+ }
+ else {
+ g_string_append_len (buf, ",\n", 2);
+ }
}
- else {
+ else if (!compact) {
g_string_append_c (buf, '\n');
}
cur = cur->next;
}
- rspamd_cl_add_tabs (buf, tabs);
+ rspamd_cl_add_tabs (buf, tabs, compact);
g_string_append_c (buf, ']');
}
@@ -154,44 +180,44 @@ rspamd_cl_elt_array_write_json (rspamd_cl_object_t *obj, GString *buf, guint tab
* @param buf buffer
*/
static void
-rspamd_cl_elt_write_json (rspamd_cl_object_t *obj, GString *buf, guint tabs, gboolean start_tabs)
+rspamd_cl_elt_write_json (rspamd_cl_object_t *obj, GString *buf, guint tabs, gboolean start_tabs, gboolean compact)
{
switch (obj->type) {
case RSPAMD_CL_INT:
if (start_tabs) {
- rspamd_cl_add_tabs (buf, tabs);
+ rspamd_cl_add_tabs (buf, tabs, compact);
}
g_string_append_printf (buf, "%ld", (long int)rspamd_cl_obj_toint (obj));
break;
case RSPAMD_CL_FLOAT:
if (start_tabs) {
- rspamd_cl_add_tabs (buf, tabs);
+ rspamd_cl_add_tabs (buf, tabs, compact);
}
g_string_append_printf (buf, "%lf", rspamd_cl_obj_todouble (obj));
break;
case RSPAMD_CL_TIME:
if (start_tabs) {
- rspamd_cl_add_tabs (buf, tabs);
+ rspamd_cl_add_tabs (buf, tabs, compact);
}
g_string_append_printf (buf, "%lf", rspamd_cl_obj_todouble (obj));
break;
case RSPAMD_CL_BOOLEAN:
if (start_tabs) {
- rspamd_cl_add_tabs (buf, tabs);
+ rspamd_cl_add_tabs (buf, tabs, compact);
}
g_string_append_printf (buf, "%s", rspamd_cl_obj_toboolean (obj) ? "true" : "false");
break;
case RSPAMD_CL_STRING:
if (start_tabs) {
- rspamd_cl_add_tabs (buf, tabs);
+ rspamd_cl_add_tabs (buf, tabs, compact);
}
rspamd_cl_elt_string_write_json (rspamd_cl_obj_tostring (obj), buf);
break;
case RSPAMD_CL_OBJECT:
- rspamd_cl_elt_obj_write_json (obj->value.ov, buf, tabs, start_tabs);
+ rspamd_cl_elt_obj_write_json (obj->value.ov, buf, tabs, start_tabs, compact);
break;
case RSPAMD_CL_ARRAY:
- rspamd_cl_elt_array_write_json (obj->value.ov, buf, tabs, start_tabs);
+ rspamd_cl_elt_array_write_json (obj->value.ov, buf, tabs, start_tabs, compact);
break;
}
}
@@ -202,7 +228,7 @@ rspamd_cl_elt_write_json (rspamd_cl_object_t *obj, GString *buf, guint tabs, gbo
* @param buf target buffer
*/
static void
-rspamd_cl_obj_write_json (rspamd_cl_object_t *obj, GString *buf, guint tabs, gboolean start_tabs)
+rspamd_cl_obj_write_json (rspamd_cl_object_t *obj, GString *buf, guint tabs, gboolean start_tabs, gboolean compact)
{
rspamd_cl_object_t *cur;
gboolean is_array = (obj->next != NULL);
@@ -210,23 +236,31 @@ rspamd_cl_obj_write_json (rspamd_cl_object_t *obj, GString *buf, guint tabs, gbo
if (is_array) {
/* This is an array actually */
if (start_tabs) {
- rspamd_cl_add_tabs (buf, tabs);
+ rspamd_cl_add_tabs (buf, tabs, compact);
+ }
+
+ if (compact) {
+ g_string_append_c (buf, '[');
+ }
+ else {
+ g_string_append_len (buf, "[\n", 2);
}
- g_string_append_len (buf, "[\n", 2);
cur = obj;
while (cur != NULL) {
- rspamd_cl_elt_write_json (cur, buf, tabs + 1, TRUE);
+ rspamd_cl_elt_write_json (cur, buf, tabs + 1, TRUE, compact);
if (cur->next) {
g_string_append_c (buf, ',');
}
- g_string_append_c (buf, '\n');
+ if (!compact) {
+ g_string_append_c (buf, '\n');
+ }
cur = cur->next;
}
- rspamd_cl_add_tabs (buf, tabs);
+ rspamd_cl_add_tabs (buf, tabs, compact);
g_string_append_c (buf, ']');
}
else {
- rspamd_cl_elt_write_json (obj, buf, tabs, start_tabs);
+ rspamd_cl_elt_write_json (obj, buf, tabs, start_tabs, compact);
}
}
@@ -237,7 +271,144 @@ rspamd_cl_obj_write_json (rspamd_cl_object_t *obj, GString *buf, guint tabs, gbo
* @return json output (should be freed after using)
*/
static guchar *
-rspamd_cl_object_emit_json (rspamd_cl_object_t *obj)
+rspamd_cl_object_emit_json (rspamd_cl_object_t *obj, gboolean compact)
+{
+ GString *buf;
+ guchar *res;
+
+ /* Allocate large enough buffer */
+ buf = g_string_sized_new (BUFSIZ);
+
+ rspamd_cl_obj_write_json (obj, buf, 0, FALSE, compact);
+
+ res = buf->str;
+ g_string_free (buf, FALSE);
+
+ return res;
+}
+
+/**
+ * Write a single object to the buffer
+ * @param obj object to write
+ * @param buf target buffer
+ */
+static void
+rspamd_cl_elt_obj_write_rcl (rspamd_cl_object_t *obj, GString *buf, guint tabs, gboolean start_tabs, gboolean is_top)
+{
+ rspamd_cl_object_t *cur, *tmp;
+
+ if (start_tabs) {
+ rspamd_cl_add_tabs (buf, tabs, is_top);
+ }
+ if (!is_top) {
+ g_string_append_len (buf, "{\n", 2);
+ }
+
+ while (obj) {
+ HASH_ITER (hh, obj, cur, tmp) {
+ rspamd_cl_add_tabs (buf, tabs + 1, is_top);
+ g_string_append (buf, cur->key);
+ if (cur->type != RSPAMD_CL_OBJECT && cur->type != RSPAMD_CL_ARRAY) {
+ g_string_append_len (buf, " = ", 3);
+ }
+ else {
+ g_string_append_c (buf, ' ');
+ }
+ rspamd_cl_elt_write_rcl (cur, buf, is_top ? tabs : tabs + 1, FALSE, FALSE);
+ if (cur->type != RSPAMD_CL_OBJECT && cur->type != RSPAMD_CL_ARRAY) {
+ g_string_append_len (buf, ";\n", 2);
+ }
+ else {
+ g_string_append_c (buf, '\n');
+ }
+ }
+ obj = obj->next;
+ }
+ rspamd_cl_add_tabs (buf, tabs, is_top);
+ if (!is_top) {
+ g_string_append_c (buf, '}');
+ }
+}
+
+/**
+ * Write a single array to the buffer
+ * @param obj array to write
+ * @param buf target buffer
+ */
+static void
+rspamd_cl_elt_array_write_rcl (rspamd_cl_object_t *obj, GString *buf, guint tabs, gboolean start_tabs, gboolean is_top)
+{
+ rspamd_cl_object_t *cur = obj;
+
+ if (start_tabs) {
+ rspamd_cl_add_tabs (buf, tabs, FALSE);
+ }
+
+ g_string_append_len (buf, "[\n", 2);
+ while (cur) {
+ rspamd_cl_elt_write_rcl (cur, buf, tabs + 1, TRUE, FALSE);
+ g_string_append_len (buf, ",\n", 2);
+ cur = cur->next;
+ }
+ rspamd_cl_add_tabs (buf, tabs, FALSE);
+ g_string_append_c (buf, ']');
+}
+
+/**
+ * Emit a single element
+ * @param obj object
+ * @param buf buffer
+ */
+static void
+rspamd_cl_elt_write_rcl (rspamd_cl_object_t *obj, GString *buf, guint tabs, gboolean start_tabs, gboolean is_top)
+{
+ switch (obj->type) {
+ case RSPAMD_CL_INT:
+ if (start_tabs) {
+ rspamd_cl_add_tabs (buf, tabs, FALSE);
+ }
+ g_string_append_printf (buf, "%ld", (long int)rspamd_cl_obj_toint (obj));
+ break;
+ case RSPAMD_CL_FLOAT:
+ if (start_tabs) {
+ rspamd_cl_add_tabs (buf, tabs, FALSE);
+ }
+ g_string_append_printf (buf, "%.4lf", rspamd_cl_obj_todouble (obj));
+ break;
+ case RSPAMD_CL_TIME:
+ if (start_tabs) {
+ rspamd_cl_add_tabs (buf, tabs, FALSE);
+ }
+ g_string_append_printf (buf, "%.4lf", rspamd_cl_obj_todouble (obj));
+ break;
+ case RSPAMD_CL_BOOLEAN:
+ if (start_tabs) {
+ rspamd_cl_add_tabs (buf, tabs, FALSE);
+ }
+ g_string_append_printf (buf, "%s", rspamd_cl_obj_toboolean (obj) ? "true" : "false");
+ break;
+ case RSPAMD_CL_STRING:
+ if (start_tabs) {
+ rspamd_cl_add_tabs (buf, tabs, FALSE);
+ }
+ rspamd_cl_elt_string_write_json (rspamd_cl_obj_tostring (obj), buf);
+ break;
+ case RSPAMD_CL_OBJECT:
+ rspamd_cl_elt_obj_write_rcl (obj->value.ov, buf, tabs, start_tabs, is_top);
+ break;
+ case RSPAMD_CL_ARRAY:
+ rspamd_cl_elt_array_write_rcl (obj->value.ov, buf, tabs, start_tabs, is_top);
+ break;
+ }
+}
+
+/**
+ * Emit an object to rcl
+ * @param obj object
+ * @return rcl output (should be freed after using)
+ */
+static guchar *
+rspamd_cl_object_emit_rcl (rspamd_cl_object_t *obj)
{
GString *buf;
guchar *res;
@@ -245,7 +416,7 @@ rspamd_cl_object_emit_json (rspamd_cl_object_t *obj)
/* Allocate large enough buffer */
buf = g_string_sized_new (BUFSIZ);
- rspamd_cl_obj_write_json (obj, buf, 0, FALSE);
+ rspamd_cl_elt_write_rcl (obj, buf, 0, FALSE, TRUE);
res = buf->str;
g_string_free (buf, FALSE);
@@ -257,7 +428,13 @@ guchar *
rspamd_cl_object_emit (rspamd_cl_object_t *obj, enum rspamd_cl_emitter emit_type)
{
if (emit_type == RSPAMD_CL_EMIT_JSON) {
- return rspamd_cl_object_emit_json (obj);
+ return rspamd_cl_object_emit_json (obj, FALSE);
+ }
+ else if (emit_type == RSPAMD_CL_EMIT_JSON_COMPACT) {
+ return rspamd_cl_object_emit_json (obj, TRUE);
+ }
+ else {
+ return rspamd_cl_object_emit_rcl (obj);
}
return NULL;