Add buffer serialization / deserialization API

Two output formats for now: TEXT, and JSON.  For example:

  hb-shape --output-format=json

Deserialization API is added, but not implemented yet.
diff --git a/util/options.cc b/util/options.cc
index ca621bf..44c9173 100644
--- a/util/options.cc
+++ b/util/options.cc
@@ -615,46 +615,23 @@
 void
 format_options_t::serialize_glyphs (hb_buffer_t *buffer,
 				    hb_font_t   *font,
-				    hb_bool_t    utf8_clusters,
+				    hb_buffer_serialize_format_t output_format,
+				    hb_buffer_serialize_flags_t flags,
 				    GString     *gs)
 {
-  unsigned int num_glyphs = hb_buffer_get_length (buffer);
-  hb_glyph_info_t *info = hb_buffer_get_glyph_infos (buffer, NULL);
-  hb_glyph_position_t *pos = hb_buffer_get_glyph_positions (buffer, NULL);
-  hb_direction_t direction = hb_buffer_get_direction (buffer);
-
   g_string_append_c (gs, '[');
-  for (unsigned int i = 0; i < num_glyphs; i++)
-  {
-    if (i)
-      g_string_append_c (gs, '|');
+  unsigned int num_glyphs = hb_buffer_get_length (buffer);
+  unsigned int start = 0;
 
-    char glyph_name[128];
-    if (show_glyph_names) {
-      hb_font_glyph_to_string (font, info->codepoint, glyph_name, sizeof (glyph_name));
-      g_string_append_printf (gs, "%s", glyph_name);
-    } else
-      g_string_append_printf (gs, "%u", info->codepoint);
-
-    if (show_clusters) {
-      g_string_append_printf (gs, "=%u", info->cluster);
-      if (utf8_clusters)
-	g_string_append (gs, "u8");
-    }
-
-    if (show_positions && (pos->x_offset || pos->y_offset)) {
-      g_string_append_printf (gs, "@%d,%d", pos->x_offset, pos->y_offset);
-    }
-    if (show_positions) {
-      g_string_append_c (gs, '+');
-      if (HB_DIRECTION_IS_HORIZONTAL (direction) || pos->x_advance)
-	g_string_append_printf (gs, "%d", pos->x_advance);
-      if (HB_DIRECTION_IS_VERTICAL (direction) || pos->y_advance)
-	g_string_append_printf (gs, ",%d", pos->y_advance);
-    }
-
-    info++;
-    pos++;
+  while (start < num_glyphs) {
+    char buf[1024];
+    unsigned int consumed;
+    start += hb_buffer_serialize_glyphs (buffer, start, num_glyphs,
+					 buf, sizeof (buf), &consumed,
+					 font, output_format, flags);
+    if (!consumed)
+      break;
+    g_string_append (gs, buf);
   }
   g_string_append_c (gs, ']');
 }
@@ -671,7 +648,6 @@
 					    const char   *text,
 					    unsigned int  text_len,
 					    hb_font_t    *font,
-					    hb_bool_t     utf8_clusters,
 					    GString      *gs)
 {
   if (show_text) {
@@ -703,10 +679,11 @@
 					      const char   *text,
 					      unsigned int  text_len,
 					      hb_font_t    *font,
-					      hb_bool_t     utf8_clusters,
+					      hb_buffer_serialize_format_t output_format,
+					      hb_buffer_serialize_flags_t format_flags,
 					      GString      *gs)
 {
   serialize_line_no (line_no, gs);
-  serialize_glyphs (buffer, font, utf8_clusters, gs);
+  serialize_glyphs (buffer, font, output_format, format_flags, gs);
   g_string_append_c (gs, '\n');
 }