|
@@ -7,6 +7,15 @@
|
|
|
|
|
|
#include "hipack.h"
|
|
|
|
|
|
+/*
|
|
|
+ * Define FPCONV_H to avoid fpconv/src/fpconv.h being included.
|
|
|
+ * By making our own definition of the function here, it can be
|
|
|
+ * marked as "static inline".
|
|
|
+ */
|
|
|
+#define FPCONV_H 1
|
|
|
+static inline int fpconv_dtoa (double fp, char dest[24]);
|
|
|
+#include "fpconv/src/fpconv.c"
|
|
|
+
|
|
|
|
|
|
static inline bool
|
|
|
writechar (hipack_writer_t *writer, int ch)
|
|
@@ -28,6 +37,34 @@ writechar (hipack_writer_t *writer, int ch)
|
|
|
} while (0)
|
|
|
|
|
|
|
|
|
+static inline void
|
|
|
+moreindent (hipack_writer_t *writer)
|
|
|
+{
|
|
|
+ if (writer->indent != HIPACK_WRITER_COMPACT)
|
|
|
+ writer->indent++;
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+static inline void
|
|
|
+lessindent (hipack_writer_t *writer)
|
|
|
+{
|
|
|
+ if (writer->indent != HIPACK_WRITER_COMPACT)
|
|
|
+ writer->indent--;
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+static inline bool
|
|
|
+writeindent (hipack_writer_t *writer)
|
|
|
+{
|
|
|
+ int32_t num_spaces = (writer->indent != HIPACK_WRITER_COMPACT)
|
|
|
+ ? writer->indent * 2 : 0;
|
|
|
+ while (num_spaces--) {
|
|
|
+ CHECK_IO (writechar (writer, ' '));
|
|
|
+ }
|
|
|
+ return false;
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
static inline bool
|
|
|
writedata (hipack_writer_t *writer,
|
|
|
const char *data,
|
|
@@ -84,6 +121,35 @@ hipack_write_bool (hipack_writer_t *writer,
|
|
|
}
|
|
|
|
|
|
|
|
|
+bool
|
|
|
+hipack_write_integer (hipack_writer_t *writer,
|
|
|
+ const int32_t value)
|
|
|
+{
|
|
|
+ assert (writer);
|
|
|
+ if (value < 0) {
|
|
|
+ CHECK_IO (writechar (writer, '-'));
|
|
|
+ return formatint (writer, -value, 10);
|
|
|
+ } else {
|
|
|
+ return formatint (writer, value, 10);
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+bool
|
|
|
+hipack_write_float (hipack_writer_t *writer,
|
|
|
+ const double value)
|
|
|
+{
|
|
|
+ assert (writer);
|
|
|
+
|
|
|
+ char buf[24];
|
|
|
+ int nchars = fpconv_dtoa (value, buf);
|
|
|
+ for (int i = 0; i < nchars; i++) {
|
|
|
+ CHECK_IO (writechar (writer, buf[i]));
|
|
|
+ }
|
|
|
+ return false;
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
bool
|
|
|
hipack_write_string (hipack_writer_t *writer,
|
|
|
const hipack_string_t *hstr)
|
|
@@ -128,12 +194,134 @@ hipack_write_string (hipack_writer_t *writer,
|
|
|
}
|
|
|
|
|
|
|
|
|
+static bool
|
|
|
+write_keyval (hipack_writer_t *writer,
|
|
|
+ const hipack_dict_t *dict)
|
|
|
+{
|
|
|
+ const hipack_string_t *key;
|
|
|
+ hipack_value_t *value;
|
|
|
+ HIPACK_DICT_FOREACH (dict, key, value) {
|
|
|
+ writeindent (writer);
|
|
|
+ /* Key */
|
|
|
+ for (uint32_t i = 0; i < key->size; i++) {
|
|
|
+ CHECK_IO (writechar (writer, key->data[i]));
|
|
|
+ }
|
|
|
+
|
|
|
+ switch (value->type) {
|
|
|
+ case HIPACK_INTEGER:
|
|
|
+ case HIPACK_FLOAT:
|
|
|
+ case HIPACK_BOOL:
|
|
|
+ case HIPACK_STRING:
|
|
|
+ CHECK_IO (writechar (writer, ':'));
|
|
|
+ break;
|
|
|
+ case HIPACK_DICT:
|
|
|
+ case HIPACK_LIST:
|
|
|
+ /* No colon. */
|
|
|
+ break;
|
|
|
+ default:
|
|
|
+ assert (false);
|
|
|
+ }
|
|
|
+
|
|
|
+ if (writer->indent != HIPACK_WRITER_COMPACT) {
|
|
|
+ CHECK_IO (writechar (writer, ' '));
|
|
|
+ }
|
|
|
+
|
|
|
+ CHECK_IO (hipack_write_value (writer, value));
|
|
|
+ CHECK_IO (writechar (writer, ','));
|
|
|
+
|
|
|
+ if (writer->indent != HIPACK_WRITER_COMPACT) {
|
|
|
+ CHECK_IO (writechar (writer, '\n'));
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ return false;
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+bool
|
|
|
+hipack_write_list (hipack_writer_t *writer,
|
|
|
+ const hipack_list_t *list)
|
|
|
+{
|
|
|
+ assert (writer);
|
|
|
+ assert (list);
|
|
|
+
|
|
|
+ CHECK_IO (writechar (writer, '['));
|
|
|
+
|
|
|
+ if (writer->indent != HIPACK_WRITER_COMPACT) {
|
|
|
+ CHECK_IO (writechar (writer, '\n'));
|
|
|
+ }
|
|
|
+
|
|
|
+ moreindent (writer);
|
|
|
+ for (uint32_t i = 0; i < list->size; i++) {
|
|
|
+ CHECK_IO (writeindent (writer));
|
|
|
+ CHECK_IO (hipack_write_value (writer, &list->data[i]));
|
|
|
+ CHECK_IO (writechar (writer, ','));
|
|
|
+ if (writer->indent != HIPACK_WRITER_COMPACT) {
|
|
|
+ CHECK_IO (writechar (writer, '\n'));
|
|
|
+ }
|
|
|
+ }
|
|
|
+ lessindent (writer);
|
|
|
+
|
|
|
+ CHECK_IO (writechar (writer, ']'));
|
|
|
+ return false;
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+bool
|
|
|
+hipack_write_dict (hipack_writer_t *writer,
|
|
|
+ const hipack_dict_t *dict)
|
|
|
+{
|
|
|
+ CHECK_IO (writechar (writer, '{'));
|
|
|
+
|
|
|
+ if (writer->indent != HIPACK_WRITER_COMPACT) {
|
|
|
+ CHECK_IO (writechar (writer, '\n'));
|
|
|
+ }
|
|
|
+
|
|
|
+ moreindent (writer);
|
|
|
+ CHECK_IO (write_keyval (writer, dict));
|
|
|
+ lessindent (writer);
|
|
|
+
|
|
|
+ CHECK_IO (writeindent (writer));
|
|
|
+ CHECK_IO (writechar (writer, '}'));
|
|
|
+ return false;
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+bool
|
|
|
+hipack_write_value (hipack_writer_t *writer,
|
|
|
+ const hipack_value_t *value)
|
|
|
+{
|
|
|
+ assert (writer);
|
|
|
+ assert (value);
|
|
|
+
|
|
|
+ switch (value->type) {
|
|
|
+ case HIPACK_INTEGER:
|
|
|
+ return hipack_write_integer (writer, value->v_integer);
|
|
|
+ case HIPACK_FLOAT:
|
|
|
+ return hipack_write_float (writer, value->v_float);
|
|
|
+ case HIPACK_BOOL:
|
|
|
+ return hipack_write_bool (writer, value->v_bool);
|
|
|
+ case HIPACK_STRING:
|
|
|
+ return hipack_write_string (writer, value->v_string);
|
|
|
+ case HIPACK_LIST:
|
|
|
+ return hipack_write_list (writer, value->v_list);
|
|
|
+ case HIPACK_DICT:
|
|
|
+ return hipack_write_dict (writer, value->v_dict);
|
|
|
+ }
|
|
|
+
|
|
|
+ assert (false); /* Never reached. */
|
|
|
+ return false;
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
bool
|
|
|
hipack_write (hipack_writer_t *writer,
|
|
|
const hipack_dict_t *message)
|
|
|
{
|
|
|
assert (writer);
|
|
|
assert (message);
|
|
|
+ writer->indent = 0;
|
|
|
+ return write_keyval (writer, message);
|
|
|
}
|
|
|
|
|
|
|