From 20b817ac21147e0a8edbf23ef071c2f4ce6c2b95 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Wed, 27 Feb 2013 18:39:37 -0500 Subject: [PATCH] [buffer] Implement buffer deserialization for format=json Using a ragel machine. --- src/Makefile.am | 2 + src/hb-buffer-deserialize-json.rl | 129 ++++++++++++++++++++++++++++++++++++++ src/hb-buffer-deserialize-text.rl | 52 +-------------- src/hb-buffer-serialize.cc | 45 +++++++++++-- src/hb-private.hh | 6 +- src/hb-shape.cc | 2 - src/test-buffer-serialize.cc | 4 +- 7 files changed, 179 insertions(+), 61 deletions(-) create mode 100644 src/hb-buffer-deserialize-json.rl diff --git a/src/Makefile.am b/src/Makefile.am index f666d5e..269fabe 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -258,12 +258,14 @@ arabic-table: gen-arabic-table.py ArabicShaping.txt UnicodeData.txt .PHONY: unicode-tables arabic-table indic-table BUILT_SOURCES += \ + hb-buffer-deserialize-json.hh \ hb-buffer-deserialize-text.hh \ hb-ot-shape-complex-indic-machine.hh \ hb-ot-shape-complex-myanmar-machine.hh \ hb-ot-shape-complex-sea-machine.hh \ $(NULL) EXTRA_DIST += \ + hb-buffer-deserialize-json.rl \ hb-buffer-deserialize-text.rl \ hb-ot-shape-complex-indic-machine.rl \ hb-ot-shape-complex-myanmar-machine.rl \ diff --git a/src/hb-buffer-deserialize-json.rl b/src/hb-buffer-deserialize-json.rl new file mode 100644 index 0000000..d93765a --- /dev/null +++ b/src/hb-buffer-deserialize-json.rl @@ -0,0 +1,129 @@ +/* + * Copyright © 2013 Google, Inc. + * + * This is part of HarfBuzz, a text shaping library. + * + * Permission is hereby granted, without written agreement and without + * license or royalty fees, to use, copy, modify, and distribute this + * software and its documentation for any purpose, provided that the + * above copyright notice and the following two paragraphs appear in + * all copies of this software. + * + * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES + * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN + * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH + * DAMAGE. + * + * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, + * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + * + * Google Author(s): Behdad Esfahbod + */ + +#ifndef HB_BUFFER_DESERIALIZE_JSON_HH +#define HB_BUFFER_DESERIALIZE_JSON_HH + +#include "hb-private.hh" + +%%{ + +machine deserialize_json; +alphtype unsigned char; +write data; + +action clear_item { + memset (&info, 0, sizeof (info)); + memset (&pos , 0, sizeof (pos )); +} + +action add_item { + buffer->add_info (info); + if (buffer->in_error) + return false; + buffer->pos[buffer->len - 1] = pos; + *end_ptr = p; +} + +action tok { + tok = p; +} + +action parse_glyph { + if (!hb_font_glyph_from_string (font, + tok, p - tok, + &info.codepoint)) + return false; +} + +action parse_gid { if (!parse_uint (tok, p, &info.codepoint)) return false; } +action parse_cluster { if (!parse_uint (tok, p, &info.cluster )) return false; } +action parse_x_offset { if (!parse_int (tok, p, &pos.x_offset )) return false; } +action parse_y_offset { if (!parse_int (tok, p, &pos.y_offset )) return false; } +action parse_x_advance { if (!parse_int (tok, p, &pos.x_advance)) return false; } +action parse_y_advance { if (!parse_int (tok, p, &pos.y_advance)) return false; } + +unum = '0' | [1-9] digit*; +num = '-'? unum; + +comma = space* ',' space*; +colon = space* ':' space*; + +glyph_name = '"' (alnum+ >tok %parse_glyph) '"'; +glyph_number = (unum >tok %parse_gid); + +glyph = "\"g\"" colon (glyph_name | glyph_number); +cluster = "\"cl\"" colon (unum >tok %parse_cluster); +xoffset = "\"dx\"" colon (num >tok %parse_x_offset); +yoffset = "\"dy\"" colon (num >tok %parse_y_offset); +xadvance= "\"ax\"" colon (num >tok %parse_x_advance); +yadvance= "\"ay\"" colon (num >tok %parse_y_advance); + +element = glyph | cluster | xoffset | yoffset | xadvance | yadvance; +item = + ( '{' space* element (comma element)* space* '}') + >clear_item + @add_item + ; + +main := space* item (comma item)* space* (','|']')?; + +}%% + +static hb_bool_t +_hb_buffer_deserialize_glyphs_json (hb_buffer_t *buffer, + const char *buf, + unsigned int buf_len, + const char **end_ptr, + hb_font_t *font) +{ + const char *p = buf, *pe = buf + buf_len; + + /* Ensure we have positions. */ + (void) hb_buffer_get_glyph_positions (buffer, NULL); + + while (p < pe && ISSPACE (*p)) + p++; + if (p < pe && *p == (buffer->len ? ',' : '[')) + { + *end_ptr = ++p; + } + + const char *tok = NULL; + int cs; + hb_glyph_info_t info; + hb_glyph_position_t pos; + %%{ + write init; + write exec; + }%% + + *end_ptr = p; + + return p == pe && *(p-1) != ']'; +} + +#endif /* HB_BUFFER_DESERIALIZE_JSON_HH */ diff --git a/src/hb-buffer-deserialize-text.rl b/src/hb-buffer-deserialize-text.rl index 7c370e7..5272690 100644 --- a/src/hb-buffer-deserialize-text.rl +++ b/src/hb-buffer-deserialize-text.rl @@ -30,54 +30,10 @@ #include "hb-private.hh" %%{ - machine deserialize_text; - alphtype unsigned char; - write data; -}%% - -static hb_bool_t -parse_uint (const char *pp, const char *end, uint32_t *pv) -{ - char buf[32]; - unsigned int len = MIN (ARRAY_LENGTH (buf) - 1, (unsigned int) (end - pp)); - strncpy (buf, pp, len); - buf[len] = '\0'; - - char *p = buf; - char *pend = p; - uint32_t v; - - errno = 0; - v = strtol (p, &pend, 10); - if (errno || p == pend || pend - p != end - pp) - return false; - - *pv = v; - return true; -} -static hb_bool_t -parse_int (const char *pp, const char *end, int32_t *pv) -{ - char buf[32]; - unsigned int len = MIN (ARRAY_LENGTH (buf) - 1, (unsigned int) (end - pp)); - strncpy (buf, pp, len); - buf[len] = '\0'; - - char *p = buf; - char *pend = p; - int32_t v; - - errno = 0; - v = strtol (p, &pend, 10); - if (errno || p == pend || pend - p != end - pp) - return false; - - *pv = v; - return true; -} - -%%{ +machine deserialize_text; +alphtype unsigned char; +write data; action clear_item { memset (&info, 0, sizeof (info)); @@ -143,10 +99,8 @@ _hb_buffer_deserialize_glyphs_text (hb_buffer_t *buffer, /* Ensure we have positions. */ (void) hb_buffer_get_glyph_positions (buffer, NULL); -#define ISSPACE(c) ((c)==' '||(c)=='\f'||(c)=='\n'||(c)=='\r'||(c)=='\t'||(c)=='\v') while (p < pe && ISSPACE (*p)) p++; -#undef ISSPACE if (p < pe && *p == (buffer->len ? '|' : '[')) { *end_ptr = ++p; diff --git a/src/hb-buffer-serialize.cc b/src/hb-buffer-serialize.cc index 0271547..dc47ba7 100644 --- a/src/hb-buffer-serialize.cc +++ b/src/hb-buffer-serialize.cc @@ -242,15 +242,48 @@ hb_buffer_serialize_glyphs (hb_buffer_t *buffer, static hb_bool_t -_hb_buffer_deserialize_glyphs_json (hb_buffer_t *buffer, - const char *buf, - unsigned int buf_len, - const char **end_ptr, - hb_font_t *font) +parse_uint (const char *pp, const char *end, uint32_t *pv) { - return false; + char buf[32]; + unsigned int len = MIN (ARRAY_LENGTH (buf) - 1, (unsigned int) (end - pp)); + strncpy (buf, pp, len); + buf[len] = '\0'; + + char *p = buf; + char *pend = p; + uint32_t v; + + errno = 0; + v = strtol (p, &pend, 10); + if (errno || p == pend || pend - p != end - pp) + return false; + + *pv = v; + return true; +} + +static hb_bool_t +parse_int (const char *pp, const char *end, int32_t *pv) +{ + char buf[32]; + unsigned int len = MIN (ARRAY_LENGTH (buf) - 1, (unsigned int) (end - pp)); + strncpy (buf, pp, len); + buf[len] = '\0'; + + char *p = buf; + char *pend = p; + int32_t v; + + errno = 0; + v = strtol (p, &pend, 10); + if (errno || p == pend || pend - p != end - pp) + return false; + + *pv = v; + return true; } +#include "hb-buffer-deserialize-json.hh" #include "hb-buffer-deserialize-text.hh" hb_bool_t diff --git a/src/hb-private.hh b/src/hb-private.hh index 91bce9b..0f652ad 100644 --- a/src/hb-private.hh +++ b/src/hb-private.hh @@ -516,10 +516,12 @@ static inline uint32_t hb_uint32_swap (const uint32_t v) /* ASCII tag/character handling */ -static inline unsigned char ISALPHA (unsigned char c) +static inline bool ISALPHA (unsigned char c) { return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z'); } -static inline unsigned char ISALNUM (unsigned char c) +static inline bool ISALNUM (unsigned char c) { return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9'); } +static inline bool ISSPACE (unsigned char c) +{ return c == ' ' || c =='\f'|| c =='\n'|| c =='\r'|| c =='\t'|| c =='\v'; } static inline unsigned char TOUPPER (unsigned char c) { return (c >= 'a' && c <= 'z') ? c - 'a' + 'A' : c; } static inline unsigned char TOLOWER (unsigned char c) diff --git a/src/hb-shape.cc b/src/hb-shape.cc index e38f59f..67ef7e6 100644 --- a/src/hb-shape.cc +++ b/src/hb-shape.cc @@ -38,10 +38,8 @@ static void parse_space (const char **pp, const char *end) { char c; -#define ISSPACE(c) ((c)==' '||(c)=='\f'||(c)=='\n'||(c)=='\r'||(c)=='\t'||(c)=='\v') while (*pp < end && (c = **pp, ISSPACE (c))) (*pp)++; -#undef ISSPACE } static hb_bool_t diff --git a/src/test-buffer-serialize.cc b/src/test-buffer-serialize.cc index 71bb431..3577dbf 100644 --- a/src/test-buffer-serialize.cc +++ b/src/test-buffer-serialize.cc @@ -106,14 +106,14 @@ main (int argc, char **argv) while (hb_buffer_deserialize_glyphs (buf, p, -1, &p, font, - HB_BUFFER_SERIALIZE_FORMAT_TEXT)) + HB_BUFFER_SERIALIZE_FORMAT_JSON)) ; if (*p && *p != '\n') ret = false; hb_buffer_serialize_glyphs (buf, 0, hb_buffer_get_length (buf), out, sizeof (out), NULL, - font, HB_BUFFER_SERIALIZE_FORMAT_TEXT, + font, HB_BUFFER_SERIALIZE_FORMAT_JSON, HB_BUFFER_SERIALIZE_FLAGS_DEFAULT); puts (out); } -- 2.7.4