diff options
Diffstat (limited to '')
| -rw-r--r-- | lua_json.c | 34 | ||||
| -rw-r--r-- | strbuf.c | 4 | ||||
| -rw-r--r-- | strbuf.h | 14 |
3 files changed, 34 insertions, 18 deletions
| @@ -7,24 +7,18 @@ | |||
| 7 | * json.null. | 7 | * json.null. |
| 8 | * - Parsing comments is not support. According to json.org, this isn't | 8 | * - Parsing comments is not support. According to json.org, this isn't |
| 9 | * part of the spec. | 9 | * part of the spec. |
| 10 | * | ||
| 11 | * Note: lua_json_decode() probably spends significant time rehashing | ||
| 12 | * tables since it is difficult to know their size ahead of time. | ||
| 13 | * Earlier JSON libaries didn't have this problem but the intermediate | ||
| 14 | * storage (and their implementations) were much slower anyway.. | ||
| 10 | */ | 15 | */ |
| 11 | 16 | ||
| 12 | /* FIXME: | 17 | /* FIXME: |
| 13 | * - Ensure JSON data is UTF-8. Fail otherwise. | 18 | * - Ensure JSON data is UTF-8. Fail otherwise. |
| 14 | * - Alternatively, dynamically support Unicode in JSON string. Return current locale. | 19 | * - Alternatively, dynamically support Unicode in JSON string. Return current locale. |
| 15 | * - Use lua_checkstack() to ensure there is enough stack space left to | 20 | * - Consider implementing other Unicode standards. |
| 16 | * fulfill an operation. What happens if we don't, is that acceptible too? | ||
| 17 | * Does lua_checkstack grow the stack, or merely check if it is possible? | ||
| 18 | */ | ||
| 19 | |||
| 20 | /* FIXME: | ||
| 21 | * - Option to encode non-printable characters? Only \" \\ are required | 21 | * - Option to encode non-printable characters? Only \" \\ are required |
| 22 | * - Unicode? | ||
| 23 | */ | ||
| 24 | |||
| 25 | /* FIXME: | ||
| 26 | * - Review memory allocation handling and error returns. | ||
| 27 | * Ensure all memory is free. Including after exceptions. | ||
| 28 | */ | 22 | */ |
| 29 | 23 | ||
| 30 | #include <assert.h> | 24 | #include <assert.h> |
| @@ -94,13 +88,19 @@ static void json_append_string(lua_State *l, strbuf_t *json, int lindex) | |||
| 94 | 88 | ||
| 95 | str = lua_tolstring(l, lindex, &len); | 89 | str = lua_tolstring(l, lindex, &len); |
| 96 | 90 | ||
| 91 | /* Worst case is len * 6 (all unicode escapes). | ||
| 92 | * This buffer is reused constantly for small strings | ||
| 93 | * If there are any excess pages, they won't be hit anyway. | ||
| 94 | * This gains ~5% speedup. */ | ||
| 95 | strbuf_ensure_empty_length(json, len * 6); | ||
| 96 | |||
| 97 | strbuf_append_char(json, '\"'); | 97 | strbuf_append_char(json, '\"'); |
| 98 | for (i = 0; i < len; i++) { | 98 | for (i = 0; i < len; i++) { |
| 99 | p = json_escape_char(str[i]); | 99 | p = json_escape_char(str[i]); |
| 100 | if (p) | 100 | if (p) |
| 101 | strbuf_append_string(json, p); | 101 | strbuf_append_string(json, p); |
| 102 | else | 102 | else |
| 103 | strbuf_append_char(json, str[i]); | 103 | strbuf_append_char_unsafe(json, str[i]); |
| 104 | } | 104 | } |
| 105 | strbuf_append_char(json, '\"'); | 105 | strbuf_append_char(json, '\"'); |
| 106 | } | 106 | } |
| @@ -536,6 +536,10 @@ static void json_parse_object_context(lua_State *l, json_parse_t *json) | |||
| 536 | { | 536 | { |
| 537 | json_token_t token; | 537 | json_token_t token; |
| 538 | 538 | ||
| 539 | /* 3 slots required: | ||
| 540 | * .., table, key, value */ | ||
| 541 | luaL_checkstack(l, 3, "too many nested data structures"); | ||
| 542 | |||
| 539 | lua_newtable(l); | 543 | lua_newtable(l); |
| 540 | 544 | ||
| 541 | json_next_token(json, &token); | 545 | json_next_token(json, &token); |
| @@ -576,6 +580,10 @@ static void json_parse_array_context(lua_State *l, json_parse_t *json) | |||
| 576 | json_token_t token; | 580 | json_token_t token; |
| 577 | int i; | 581 | int i; |
| 578 | 582 | ||
| 583 | /* 2 slots required: | ||
| 584 | * .., table, value */ | ||
| 585 | luaL_checkstack(l, 2, "too many nested data structures"); | ||
| 586 | |||
| 579 | lua_newtable(l); | 587 | lua_newtable(l); |
| 580 | 588 | ||
| 581 | json_next_token(json, &token); | 589 | json_next_token(json, &token); |
| @@ -152,9 +152,7 @@ void strbuf_resize(strbuf_t *s, int len) | |||
| 152 | 152 | ||
| 153 | void strbuf_append_mem(strbuf_t *s, const char *c, int len) | 153 | void strbuf_append_mem(strbuf_t *s, const char *c, int len) |
| 154 | { | 154 | { |
| 155 | if (len > strbuf_empty_length(s)) | 155 | strbuf_ensure_empty_length(s, len); |
| 156 | strbuf_resize(s, s->length + len); | ||
| 157 | |||
| 158 | memcpy(s->buf + s->length, c, len); | 156 | memcpy(s->buf + s->length, c, len); |
| 159 | s->length += len; | 157 | s->length += len; |
| 160 | } | 158 | } |
| @@ -38,6 +38,7 @@ extern void strbuf_resize(strbuf_t *s, int len); | |||
| 38 | static int strbuf_empty_length(strbuf_t *s); | 38 | static int strbuf_empty_length(strbuf_t *s); |
| 39 | static int strbuf_length(strbuf_t *s); | 39 | static int strbuf_length(strbuf_t *s); |
| 40 | static char *strbuf_string(strbuf_t *s, int *len); | 40 | static char *strbuf_string(strbuf_t *s, int *len); |
| 41 | static void strbuf_ensure_empty_length(strbuf_t *s, int len); | ||
| 41 | 42 | ||
| 42 | /* Update */ | 43 | /* Update */ |
| 43 | extern void strbuf_append_fmt(strbuf_t *s, const char *format, ...); | 44 | extern void strbuf_append_fmt(strbuf_t *s, const char *format, ...); |
| @@ -53,6 +54,12 @@ static inline int strbuf_empty_length(strbuf_t *s) | |||
| 53 | return s->size - s->length - 1; | 54 | return s->size - s->length - 1; |
| 54 | } | 55 | } |
| 55 | 56 | ||
| 57 | static inline void strbuf_ensure_empty_length(strbuf_t *s, int len) | ||
| 58 | { | ||
| 59 | if (len > strbuf_empty_length(s)) | ||
| 60 | strbuf_resize(s, s->length + len); | ||
| 61 | } | ||
| 62 | |||
| 56 | static inline int strbuf_length(strbuf_t *s) | 63 | static inline int strbuf_length(strbuf_t *s) |
| 57 | { | 64 | { |
| 58 | return s->length; | 65 | return s->length; |
| @@ -60,9 +67,12 @@ static inline int strbuf_length(strbuf_t *s) | |||
| 60 | 67 | ||
| 61 | static inline void strbuf_append_char(strbuf_t *s, const char c) | 68 | static inline void strbuf_append_char(strbuf_t *s, const char c) |
| 62 | { | 69 | { |
| 63 | if (strbuf_empty_length(s) < 1) | 70 | strbuf_ensure_empty_length(s, 1); |
| 64 | strbuf_resize(s, s->length + 1); | 71 | s->buf[s->length++] = c; |
| 72 | } | ||
| 65 | 73 | ||
| 74 | static inline void strbuf_append_char_unsafe(strbuf_t *s, const char c) | ||
| 75 | { | ||
| 66 | s->buf[s->length++] = c; | 76 | s->buf[s->length++] = c; |
| 67 | } | 77 | } |
| 68 | 78 | ||
