prometheus-client-mmap 0.20.3-arm64-darwin

Sign up to get free protection for your applications and to get access to all the features.
Files changed (92) hide show
  1. checksums.yaml +7 -0
  2. data/README.md +253 -0
  3. data/ext/fast_mmaped_file/extconf.rb +30 -0
  4. data/ext/fast_mmaped_file/fast_mmaped_file.c +122 -0
  5. data/ext/fast_mmaped_file/file_format.c +5 -0
  6. data/ext/fast_mmaped_file/file_format.h +11 -0
  7. data/ext/fast_mmaped_file/file_parsing.c +195 -0
  8. data/ext/fast_mmaped_file/file_parsing.h +27 -0
  9. data/ext/fast_mmaped_file/file_reading.c +102 -0
  10. data/ext/fast_mmaped_file/file_reading.h +30 -0
  11. data/ext/fast_mmaped_file/globals.h +14 -0
  12. data/ext/fast_mmaped_file/mmap.c +427 -0
  13. data/ext/fast_mmaped_file/mmap.h +61 -0
  14. data/ext/fast_mmaped_file/rendering.c +199 -0
  15. data/ext/fast_mmaped_file/rendering.h +8 -0
  16. data/ext/fast_mmaped_file/utils.c +56 -0
  17. data/ext/fast_mmaped_file/utils.h +22 -0
  18. data/ext/fast_mmaped_file/value_access.c +242 -0
  19. data/ext/fast_mmaped_file/value_access.h +15 -0
  20. data/ext/fast_mmaped_file_rs/.cargo/config.toml +23 -0
  21. data/ext/fast_mmaped_file_rs/Cargo.lock +790 -0
  22. data/ext/fast_mmaped_file_rs/Cargo.toml +30 -0
  23. data/ext/fast_mmaped_file_rs/README.md +52 -0
  24. data/ext/fast_mmaped_file_rs/extconf.rb +30 -0
  25. data/ext/fast_mmaped_file_rs/src/error.rs +174 -0
  26. data/ext/fast_mmaped_file_rs/src/file_entry.rs +579 -0
  27. data/ext/fast_mmaped_file_rs/src/file_info.rs +190 -0
  28. data/ext/fast_mmaped_file_rs/src/lib.rs +79 -0
  29. data/ext/fast_mmaped_file_rs/src/macros.rs +14 -0
  30. data/ext/fast_mmaped_file_rs/src/map.rs +492 -0
  31. data/ext/fast_mmaped_file_rs/src/mmap.rs +151 -0
  32. data/ext/fast_mmaped_file_rs/src/parser.rs +346 -0
  33. data/ext/fast_mmaped_file_rs/src/raw_entry.rs +473 -0
  34. data/ext/fast_mmaped_file_rs/src/testhelper.rs +222 -0
  35. data/ext/fast_mmaped_file_rs/src/util.rs +121 -0
  36. data/lib/2.7/fast_mmaped_file.bundle +0 -0
  37. data/lib/2.7/fast_mmaped_file_rs.bundle +0 -0
  38. data/lib/3.0/fast_mmaped_file.bundle +0 -0
  39. data/lib/3.0/fast_mmaped_file_rs.bundle +0 -0
  40. data/lib/3.1/fast_mmaped_file.bundle +0 -0
  41. data/lib/3.1/fast_mmaped_file_rs.bundle +0 -0
  42. data/lib/3.2/fast_mmaped_file.bundle +0 -0
  43. data/lib/3.2/fast_mmaped_file_rs.bundle +0 -0
  44. data/lib/prometheus/client/configuration.rb +23 -0
  45. data/lib/prometheus/client/counter.rb +27 -0
  46. data/lib/prometheus/client/formats/text.rb +118 -0
  47. data/lib/prometheus/client/gauge.rb +40 -0
  48. data/lib/prometheus/client/helper/entry_parser.rb +132 -0
  49. data/lib/prometheus/client/helper/file_locker.rb +50 -0
  50. data/lib/prometheus/client/helper/json_parser.rb +23 -0
  51. data/lib/prometheus/client/helper/metrics_processing.rb +45 -0
  52. data/lib/prometheus/client/helper/metrics_representation.rb +51 -0
  53. data/lib/prometheus/client/helper/mmaped_file.rb +64 -0
  54. data/lib/prometheus/client/helper/plain_file.rb +29 -0
  55. data/lib/prometheus/client/histogram.rb +80 -0
  56. data/lib/prometheus/client/label_set_validator.rb +86 -0
  57. data/lib/prometheus/client/metric.rb +80 -0
  58. data/lib/prometheus/client/mmaped_dict.rb +79 -0
  59. data/lib/prometheus/client/mmaped_value.rb +154 -0
  60. data/lib/prometheus/client/page_size.rb +17 -0
  61. data/lib/prometheus/client/push.rb +203 -0
  62. data/lib/prometheus/client/rack/collector.rb +88 -0
  63. data/lib/prometheus/client/rack/exporter.rb +96 -0
  64. data/lib/prometheus/client/registry.rb +65 -0
  65. data/lib/prometheus/client/simple_value.rb +31 -0
  66. data/lib/prometheus/client/summary.rb +69 -0
  67. data/lib/prometheus/client/support/unicorn.rb +35 -0
  68. data/lib/prometheus/client/uses_value_type.rb +20 -0
  69. data/lib/prometheus/client/version.rb +5 -0
  70. data/lib/prometheus/client.rb +58 -0
  71. data/lib/prometheus.rb +3 -0
  72. data/vendor/c/hashmap/.gitignore +52 -0
  73. data/vendor/c/hashmap/LICENSE +21 -0
  74. data/vendor/c/hashmap/README.md +90 -0
  75. data/vendor/c/hashmap/_config.yml +1 -0
  76. data/vendor/c/hashmap/src/hashmap.c +692 -0
  77. data/vendor/c/hashmap/src/hashmap.h +267 -0
  78. data/vendor/c/hashmap/test/Makefile +22 -0
  79. data/vendor/c/hashmap/test/hashmap_test.c +608 -0
  80. data/vendor/c/jsmn/.travis.yml +4 -0
  81. data/vendor/c/jsmn/LICENSE +20 -0
  82. data/vendor/c/jsmn/Makefile +41 -0
  83. data/vendor/c/jsmn/README.md +168 -0
  84. data/vendor/c/jsmn/example/jsondump.c +126 -0
  85. data/vendor/c/jsmn/example/simple.c +76 -0
  86. data/vendor/c/jsmn/jsmn.c +314 -0
  87. data/vendor/c/jsmn/jsmn.h +76 -0
  88. data/vendor/c/jsmn/library.json +16 -0
  89. data/vendor/c/jsmn/test/test.h +27 -0
  90. data/vendor/c/jsmn/test/tests.c +407 -0
  91. data/vendor/c/jsmn/test/testutil.h +94 -0
  92. metadata +243 -0
@@ -0,0 +1,168 @@
1
+ JSMN
2
+ ====
3
+
4
+ [![Build Status](https://travis-ci.org/zserge/jsmn.svg?branch=master)](https://travis-ci.org/zserge/jsmn)
5
+
6
+ jsmn (pronounced like 'jasmine') is a minimalistic JSON parser in C. It can be
7
+ easily integrated into resource-limited or embedded projects.
8
+
9
+ You can find more information about JSON format at [json.org][1]
10
+
11
+ Library sources are available at https://github.com/zserge/jsmn
12
+
13
+ The web page with some information about jsmn can be found at
14
+ [http://zserge.com/jsmn.html][2]
15
+
16
+ Philosophy
17
+ ----------
18
+
19
+ Most JSON parsers offer you a bunch of functions to load JSON data, parse it
20
+ and extract any value by its name. jsmn proves that checking the correctness of
21
+ every JSON packet or allocating temporary objects to store parsed JSON fields
22
+ often is an overkill.
23
+
24
+ JSON format itself is extremely simple, so why should we complicate it?
25
+
26
+ jsmn is designed to be **robust** (it should work fine even with erroneous
27
+ data), **fast** (it should parse data on the fly), **portable** (no superfluous
28
+ dependencies or non-standard C extensions). And of course, **simplicity** is a
29
+ key feature - simple code style, simple algorithm, simple integration into
30
+ other projects.
31
+
32
+ Features
33
+ --------
34
+
35
+ * compatible with C89
36
+ * no dependencies (even libc!)
37
+ * highly portable (tested on x86/amd64, ARM, AVR)
38
+ * about 200 lines of code
39
+ * extremely small code footprint
40
+ * API contains only 2 functions
41
+ * no dynamic memory allocation
42
+ * incremental single-pass parsing
43
+ * library code is covered with unit-tests
44
+
45
+ Design
46
+ ------
47
+
48
+ The rudimentary jsmn object is a **token**. Let's consider a JSON string:
49
+
50
+ '{ "name" : "Jack", "age" : 27 }'
51
+
52
+ It holds the following tokens:
53
+
54
+ * Object: `{ "name" : "Jack", "age" : 27}` (the whole object)
55
+ * Strings: `"name"`, `"Jack"`, `"age"` (keys and some values)
56
+ * Number: `27`
57
+
58
+ In jsmn, tokens do not hold any data, but point to token boundaries in JSON
59
+ string instead. In the example above jsmn will create tokens like: Object
60
+ [0..31], String [3..7], String [12..16], String [20..23], Number [27..29].
61
+
62
+ Every jsmn token has a type, which indicates the type of corresponding JSON
63
+ token. jsmn supports the following token types:
64
+
65
+ * Object - a container of key-value pairs, e.g.:
66
+ `{ "foo":"bar", "x":0.3 }`
67
+ * Array - a sequence of values, e.g.:
68
+ `[ 1, 2, 3 ]`
69
+ * String - a quoted sequence of chars, e.g.: `"foo"`
70
+ * Primitive - a number, a boolean (`true`, `false`) or `null`
71
+
72
+ Besides start/end positions, jsmn tokens for complex types (like arrays
73
+ or objects) also contain a number of child items, so you can easily follow
74
+ object hierarchy.
75
+
76
+ This approach provides enough information for parsing any JSON data and makes
77
+ it possible to use zero-copy techniques.
78
+
79
+ Install
80
+ -------
81
+
82
+ To clone the repository you should have Git installed. Just run:
83
+
84
+ $ git clone https://github.com/zserge/jsmn
85
+
86
+ Repository layout is simple: jsmn.c and jsmn.h are library files, tests are in
87
+ the jsmn\_test.c, you will also find README, LICENSE and Makefile files inside.
88
+
89
+ To build the library, run `make`. It is also recommended to run `make test`.
90
+ Let me know, if some tests fail.
91
+
92
+ If build was successful, you should get a `libjsmn.a` library.
93
+ The header file you should include is called `"jsmn.h"`.
94
+
95
+ API
96
+ ---
97
+
98
+ Token types are described by `jsmntype_t`:
99
+
100
+ typedef enum {
101
+ JSMN_UNDEFINED = 0,
102
+ JSMN_OBJECT = 1,
103
+ JSMN_ARRAY = 2,
104
+ JSMN_STRING = 3,
105
+ JSMN_PRIMITIVE = 4
106
+ } jsmntype_t;
107
+
108
+ **Note:** Unlike JSON data types, primitive tokens are not divided into
109
+ numbers, booleans and null, because one can easily tell the type using the
110
+ first character:
111
+
112
+ * <code>'t', 'f'</code> - boolean
113
+ * <code>'n'</code> - null
114
+ * <code>'-', '0'..'9'</code> - number
115
+
116
+ Token is an object of `jsmntok_t` type:
117
+
118
+ typedef struct {
119
+ jsmntype_t type; // Token type
120
+ int start; // Token start position
121
+ int end; // Token end position
122
+ int size; // Number of child (nested) tokens
123
+ } jsmntok_t;
124
+
125
+ **Note:** string tokens point to the first character after
126
+ the opening quote and the previous symbol before final quote. This was made
127
+ to simplify string extraction from JSON data.
128
+
129
+ All job is done by `jsmn_parser` object. You can initialize a new parser using:
130
+
131
+ jsmn_parser parser;
132
+ jsmntok_t tokens[10];
133
+
134
+ jsmn_init(&parser);
135
+
136
+ // js - pointer to JSON string
137
+ // tokens - an array of tokens available
138
+ // 10 - number of tokens available
139
+ jsmn_parse(&parser, js, strlen(js), tokens, 10);
140
+
141
+ This will create a parser, and then it tries to parse up to 10 JSON tokens from
142
+ the `js` string.
143
+
144
+ A non-negative return value of `jsmn_parse` is the number of tokens actually
145
+ used by the parser.
146
+ Passing NULL instead of the tokens array would not store parsing results, but
147
+ instead the function will return the value of tokens needed to parse the given
148
+ string. This can be useful if you don't know yet how many tokens to allocate.
149
+
150
+ If something goes wrong, you will get an error. Error will be one of these:
151
+
152
+ * `JSMN_ERROR_INVAL` - bad token, JSON string is corrupted
153
+ * `JSMN_ERROR_NOMEM` - not enough tokens, JSON string is too large
154
+ * `JSMN_ERROR_PART` - JSON string is too short, expecting more JSON data
155
+
156
+ If you get `JSON_ERROR_NOMEM`, you can re-allocate more tokens and call
157
+ `jsmn_parse` once more. If you read json data from the stream, you can
158
+ periodically call `jsmn_parse` and check if return value is `JSON_ERROR_PART`.
159
+ You will get this error until you reach the end of JSON data.
160
+
161
+ Other info
162
+ ----------
163
+
164
+ This software is distributed under [MIT license](http://www.opensource.org/licenses/mit-license.php),
165
+ so feel free to integrate it in your commercial products.
166
+
167
+ [1]: http://www.json.org/
168
+ [2]: http://zserge.com/jsmn.html
@@ -0,0 +1,126 @@
1
+ #include <stdio.h>
2
+ #include <stdlib.h>
3
+ #include <unistd.h>
4
+ #include <string.h>
5
+ #include <errno.h>
6
+ #include "../jsmn.h"
7
+
8
+ /* Function realloc_it() is a wrapper function for standart realloc()
9
+ * with one difference - it frees old memory pointer in case of realloc
10
+ * failure. Thus, DO NOT use old data pointer in anyway after call to
11
+ * realloc_it(). If your code has some kind of fallback algorithm if
12
+ * memory can't be re-allocated - use standart realloc() instead.
13
+ */
14
+ static inline void *realloc_it(void *ptrmem, size_t size) {
15
+ void *p = realloc(ptrmem, size);
16
+ if (!p) {
17
+ free (ptrmem);
18
+ fprintf(stderr, "realloc(): errno=%d\n", errno);
19
+ }
20
+ return p;
21
+ }
22
+
23
+ /*
24
+ * An example of reading JSON from stdin and printing its content to stdout.
25
+ * The output looks like YAML, but I'm not sure if it's really compatible.
26
+ */
27
+
28
+ static int dump(const char *js, jsmntok_t *t, size_t count, int indent) {
29
+ int i, j, k;
30
+ if (count == 0) {
31
+ return 0;
32
+ }
33
+ if (t->type == JSMN_PRIMITIVE) {
34
+ printf("%.*s", t->end - t->start, js+t->start);
35
+ return 1;
36
+ } else if (t->type == JSMN_STRING) {
37
+ printf("'%.*s'", t->end - t->start, js+t->start);
38
+ return 1;
39
+ } else if (t->type == JSMN_OBJECT) {
40
+ printf("\n");
41
+ j = 0;
42
+ for (i = 0; i < t->size; i++) {
43
+ for (k = 0; k < indent; k++) printf(" ");
44
+ j += dump(js, t+1+j, count-j, indent+1);
45
+ printf(": ");
46
+ j += dump(js, t+1+j, count-j, indent+1);
47
+ printf("\n");
48
+ }
49
+ return j+1;
50
+ } else if (t->type == JSMN_ARRAY) {
51
+ j = 0;
52
+ printf("\n");
53
+ for (i = 0; i < t->size; i++) {
54
+ for (k = 0; k < indent-1; k++) printf(" ");
55
+ printf(" - ");
56
+ j += dump(js, t+1+j, count-j, indent+1);
57
+ printf("\n");
58
+ }
59
+ return j+1;
60
+ }
61
+ return 0;
62
+ }
63
+
64
+ int main() {
65
+ int r;
66
+ int eof_expected = 0;
67
+ char *js = NULL;
68
+ size_t jslen = 0;
69
+ char buf[BUFSIZ];
70
+
71
+ jsmn_parser p;
72
+ jsmntok_t *tok;
73
+ size_t tokcount = 2;
74
+
75
+ /* Prepare parser */
76
+ jsmn_init(&p);
77
+
78
+ /* Allocate some tokens as a start */
79
+ tok = malloc(sizeof(*tok) * tokcount);
80
+ if (tok == NULL) {
81
+ fprintf(stderr, "malloc(): errno=%d\n", errno);
82
+ return 3;
83
+ }
84
+
85
+ for (;;) {
86
+ /* Read another chunk */
87
+ r = fread(buf, 1, sizeof(buf), stdin);
88
+ if (r < 0) {
89
+ fprintf(stderr, "fread(): %d, errno=%d\n", r, errno);
90
+ return 1;
91
+ }
92
+ if (r == 0) {
93
+ if (eof_expected != 0) {
94
+ return 0;
95
+ } else {
96
+ fprintf(stderr, "fread(): unexpected EOF\n");
97
+ return 2;
98
+ }
99
+ }
100
+
101
+ js = realloc_it(js, jslen + r + 1);
102
+ if (js == NULL) {
103
+ return 3;
104
+ }
105
+ strncpy(js + jslen, buf, r);
106
+ jslen = jslen + r;
107
+
108
+ again:
109
+ r = jsmn_parse(&p, js, jslen, tok, tokcount);
110
+ if (r < 0) {
111
+ if (r == JSMN_ERROR_NOMEM) {
112
+ tokcount = tokcount * 2;
113
+ tok = realloc_it(tok, sizeof(*tok) * tokcount);
114
+ if (tok == NULL) {
115
+ return 3;
116
+ }
117
+ goto again;
118
+ }
119
+ } else {
120
+ dump(js, tok, p.toknext, 0);
121
+ eof_expected = 1;
122
+ }
123
+ }
124
+
125
+ return EXIT_SUCCESS;
126
+ }
@@ -0,0 +1,76 @@
1
+ #include <stdio.h>
2
+ #include <stdlib.h>
3
+ #include <string.h>
4
+ #include "../jsmn.h"
5
+
6
+ /*
7
+ * A small example of jsmn parsing when JSON structure is known and number of
8
+ * tokens is predictable.
9
+ */
10
+
11
+ static const char *JSON_STRING =
12
+ "{\"user\": \"johndoe\", \"admin\": false, \"uid\": 1000,\n "
13
+ "\"groups\": [\"users\", \"wheel\", \"audio\", \"video\"]}";
14
+
15
+ static int jsoneq(const char *json, jsmntok_t *tok, const char *s) {
16
+ if (tok->type == JSMN_STRING && (int) strlen(s) == tok->end - tok->start &&
17
+ strncmp(json + tok->start, s, tok->end - tok->start) == 0) {
18
+ return 0;
19
+ }
20
+ return -1;
21
+ }
22
+
23
+ int main() {
24
+ int i;
25
+ int r;
26
+ jsmn_parser p;
27
+ jsmntok_t t[128]; /* We expect no more than 128 tokens */
28
+
29
+ jsmn_init(&p);
30
+ r = jsmn_parse(&p, JSON_STRING, strlen(JSON_STRING), t, sizeof(t)/sizeof(t[0]));
31
+ if (r < 0) {
32
+ printf("Failed to parse JSON: %d\n", r);
33
+ return 1;
34
+ }
35
+
36
+ /* Assume the top-level element is an object */
37
+ if (r < 1 || t[0].type != JSMN_OBJECT) {
38
+ printf("Object expected\n");
39
+ return 1;
40
+ }
41
+
42
+ /* Loop over all keys of the root object */
43
+ for (i = 1; i < r; i++) {
44
+ if (jsoneq(JSON_STRING, &t[i], "user") == 0) {
45
+ /* We may use strndup() to fetch string value */
46
+ printf("- User: %.*s\n", t[i+1].end-t[i+1].start,
47
+ JSON_STRING + t[i+1].start);
48
+ i++;
49
+ } else if (jsoneq(JSON_STRING, &t[i], "admin") == 0) {
50
+ /* We may additionally check if the value is either "true" or "false" */
51
+ printf("- Admin: %.*s\n", t[i+1].end-t[i+1].start,
52
+ JSON_STRING + t[i+1].start);
53
+ i++;
54
+ } else if (jsoneq(JSON_STRING, &t[i], "uid") == 0) {
55
+ /* We may want to do strtol() here to get numeric value */
56
+ printf("- UID: %.*s\n", t[i+1].end-t[i+1].start,
57
+ JSON_STRING + t[i+1].start);
58
+ i++;
59
+ } else if (jsoneq(JSON_STRING, &t[i], "groups") == 0) {
60
+ int j;
61
+ printf("- Groups:\n");
62
+ if (t[i+1].type != JSMN_ARRAY) {
63
+ continue; /* We expect groups to be an array of strings */
64
+ }
65
+ for (j = 0; j < t[i+1].size; j++) {
66
+ jsmntok_t *g = &t[i+j+2];
67
+ printf(" * %.*s\n", g->end - g->start, JSON_STRING + g->start);
68
+ }
69
+ i += t[i+1].size + 1;
70
+ } else {
71
+ printf("Unexpected key: %.*s\n", t[i].end-t[i].start,
72
+ JSON_STRING + t[i].start);
73
+ }
74
+ }
75
+ return EXIT_SUCCESS;
76
+ }
@@ -0,0 +1,314 @@
1
+ #include "jsmn.h"
2
+
3
+ /**
4
+ * Allocates a fresh unused token from the token pull.
5
+ */
6
+ static jsmntok_t *jsmn_alloc_token(jsmn_parser *parser,
7
+ jsmntok_t *tokens, size_t num_tokens) {
8
+ jsmntok_t *tok;
9
+ if (parser->toknext >= num_tokens) {
10
+ return NULL;
11
+ }
12
+ tok = &tokens[parser->toknext++];
13
+ tok->start = tok->end = -1;
14
+ tok->size = 0;
15
+ #ifdef JSMN_PARENT_LINKS
16
+ tok->parent = -1;
17
+ #endif
18
+ return tok;
19
+ }
20
+
21
+ /**
22
+ * Fills token type and boundaries.
23
+ */
24
+ static void jsmn_fill_token(jsmntok_t *token, jsmntype_t type,
25
+ int start, int end) {
26
+ token->type = type;
27
+ token->start = start;
28
+ token->end = end;
29
+ token->size = 0;
30
+ }
31
+
32
+ /**
33
+ * Fills next available token with JSON primitive.
34
+ */
35
+ static int jsmn_parse_primitive(jsmn_parser *parser, const char *js,
36
+ size_t len, jsmntok_t *tokens, size_t num_tokens) {
37
+ jsmntok_t *token;
38
+ int start;
39
+
40
+ start = parser->pos;
41
+
42
+ for (; parser->pos < len && js[parser->pos] != '\0'; parser->pos++) {
43
+ switch (js[parser->pos]) {
44
+ #ifndef JSMN_STRICT
45
+ /* In strict mode primitive must be followed by "," or "}" or "]" */
46
+ case ':':
47
+ #endif
48
+ case '\t' : case '\r' : case '\n' : case ' ' :
49
+ case ',' : case ']' : case '}' :
50
+ goto found;
51
+ }
52
+ if (js[parser->pos] < 32 || js[parser->pos] >= 127) {
53
+ parser->pos = start;
54
+ return JSMN_ERROR_INVAL;
55
+ }
56
+ }
57
+ #ifdef JSMN_STRICT
58
+ /* In strict mode primitive must be followed by a comma/object/array */
59
+ parser->pos = start;
60
+ return JSMN_ERROR_PART;
61
+ #endif
62
+
63
+ found:
64
+ if (tokens == NULL) {
65
+ parser->pos--;
66
+ return 0;
67
+ }
68
+ token = jsmn_alloc_token(parser, tokens, num_tokens);
69
+ if (token == NULL) {
70
+ parser->pos = start;
71
+ return JSMN_ERROR_NOMEM;
72
+ }
73
+ jsmn_fill_token(token, JSMN_PRIMITIVE, start, parser->pos);
74
+ #ifdef JSMN_PARENT_LINKS
75
+ token->parent = parser->toksuper;
76
+ #endif
77
+ parser->pos--;
78
+ return 0;
79
+ }
80
+
81
+ /**
82
+ * Fills next token with JSON string.
83
+ */
84
+ static int jsmn_parse_string(jsmn_parser *parser, const char *js,
85
+ size_t len, jsmntok_t *tokens, size_t num_tokens) {
86
+ jsmntok_t *token;
87
+
88
+ int start = parser->pos;
89
+
90
+ parser->pos++;
91
+
92
+ /* Skip starting quote */
93
+ for (; parser->pos < len && js[parser->pos] != '\0'; parser->pos++) {
94
+ char c = js[parser->pos];
95
+
96
+ /* Quote: end of string */
97
+ if (c == '\"') {
98
+ if (tokens == NULL) {
99
+ return 0;
100
+ }
101
+ token = jsmn_alloc_token(parser, tokens, num_tokens);
102
+ if (token == NULL) {
103
+ parser->pos = start;
104
+ return JSMN_ERROR_NOMEM;
105
+ }
106
+ jsmn_fill_token(token, JSMN_STRING, start+1, parser->pos);
107
+ #ifdef JSMN_PARENT_LINKS
108
+ token->parent = parser->toksuper;
109
+ #endif
110
+ return 0;
111
+ }
112
+
113
+ /* Backslash: Quoted symbol expected */
114
+ if (c == '\\' && parser->pos + 1 < len) {
115
+ int i;
116
+ parser->pos++;
117
+ switch (js[parser->pos]) {
118
+ /* Allowed escaped symbols */
119
+ case '\"': case '/' : case '\\' : case 'b' :
120
+ case 'f' : case 'r' : case 'n' : case 't' :
121
+ break;
122
+ /* Allows escaped symbol \uXXXX */
123
+ case 'u':
124
+ parser->pos++;
125
+ for(i = 0; i < 4 && parser->pos < len && js[parser->pos] != '\0'; i++) {
126
+ /* If it isn't a hex character we have an error */
127
+ if(!((js[parser->pos] >= 48 && js[parser->pos] <= 57) || /* 0-9 */
128
+ (js[parser->pos] >= 65 && js[parser->pos] <= 70) || /* A-F */
129
+ (js[parser->pos] >= 97 && js[parser->pos] <= 102))) { /* a-f */
130
+ parser->pos = start;
131
+ return JSMN_ERROR_INVAL;
132
+ }
133
+ parser->pos++;
134
+ }
135
+ parser->pos--;
136
+ break;
137
+ /* Unexpected symbol */
138
+ default:
139
+ parser->pos = start;
140
+ return JSMN_ERROR_INVAL;
141
+ }
142
+ }
143
+ }
144
+ parser->pos = start;
145
+ return JSMN_ERROR_PART;
146
+ }
147
+
148
+ /**
149
+ * Parse JSON string and fill tokens.
150
+ */
151
+ int jsmn_parse(jsmn_parser *parser, const char *js, size_t len,
152
+ jsmntok_t *tokens, unsigned int num_tokens) {
153
+ int r;
154
+ int i;
155
+ jsmntok_t *token;
156
+ int count = parser->toknext;
157
+
158
+ for (; parser->pos < len && js[parser->pos] != '\0'; parser->pos++) {
159
+ char c;
160
+ jsmntype_t type;
161
+
162
+ c = js[parser->pos];
163
+ switch (c) {
164
+ case '{': case '[':
165
+ count++;
166
+ if (tokens == NULL) {
167
+ break;
168
+ }
169
+ token = jsmn_alloc_token(parser, tokens, num_tokens);
170
+ if (token == NULL)
171
+ return JSMN_ERROR_NOMEM;
172
+ if (parser->toksuper != -1) {
173
+ tokens[parser->toksuper].size++;
174
+ #ifdef JSMN_PARENT_LINKS
175
+ token->parent = parser->toksuper;
176
+ #endif
177
+ }
178
+ token->type = (c == '{' ? JSMN_OBJECT : JSMN_ARRAY);
179
+ token->start = parser->pos;
180
+ parser->toksuper = parser->toknext - 1;
181
+ break;
182
+ case '}': case ']':
183
+ if (tokens == NULL)
184
+ break;
185
+ type = (c == '}' ? JSMN_OBJECT : JSMN_ARRAY);
186
+ #ifdef JSMN_PARENT_LINKS
187
+ if (parser->toknext < 1) {
188
+ return JSMN_ERROR_INVAL;
189
+ }
190
+ token = &tokens[parser->toknext - 1];
191
+ for (;;) {
192
+ if (token->start != -1 && token->end == -1) {
193
+ if (token->type != type) {
194
+ return JSMN_ERROR_INVAL;
195
+ }
196
+ token->end = parser->pos + 1;
197
+ parser->toksuper = token->parent;
198
+ break;
199
+ }
200
+ if (token->parent == -1) {
201
+ if(token->type != type || parser->toksuper == -1) {
202
+ return JSMN_ERROR_INVAL;
203
+ }
204
+ break;
205
+ }
206
+ token = &tokens[token->parent];
207
+ }
208
+ #else
209
+ for (i = parser->toknext - 1; i >= 0; i--) {
210
+ token = &tokens[i];
211
+ if (token->start != -1 && token->end == -1) {
212
+ if (token->type != type) {
213
+ return JSMN_ERROR_INVAL;
214
+ }
215
+ parser->toksuper = -1;
216
+ token->end = parser->pos + 1;
217
+ break;
218
+ }
219
+ }
220
+ /* Error if unmatched closing bracket */
221
+ if (i == -1) return JSMN_ERROR_INVAL;
222
+ for (; i >= 0; i--) {
223
+ token = &tokens[i];
224
+ if (token->start != -1 && token->end == -1) {
225
+ parser->toksuper = i;
226
+ break;
227
+ }
228
+ }
229
+ #endif
230
+ break;
231
+ case '\"':
232
+ r = jsmn_parse_string(parser, js, len, tokens, num_tokens);
233
+ if (r < 0) return r;
234
+ count++;
235
+ if (parser->toksuper != -1 && tokens != NULL)
236
+ tokens[parser->toksuper].size++;
237
+ break;
238
+ case '\t' : case '\r' : case '\n' : case ' ':
239
+ break;
240
+ case ':':
241
+ parser->toksuper = parser->toknext - 1;
242
+ break;
243
+ case ',':
244
+ if (tokens != NULL && parser->toksuper != -1 &&
245
+ tokens[parser->toksuper].type != JSMN_ARRAY &&
246
+ tokens[parser->toksuper].type != JSMN_OBJECT) {
247
+ #ifdef JSMN_PARENT_LINKS
248
+ parser->toksuper = tokens[parser->toksuper].parent;
249
+ #else
250
+ for (i = parser->toknext - 1; i >= 0; i--) {
251
+ if (tokens[i].type == JSMN_ARRAY || tokens[i].type == JSMN_OBJECT) {
252
+ if (tokens[i].start != -1 && tokens[i].end == -1) {
253
+ parser->toksuper = i;
254
+ break;
255
+ }
256
+ }
257
+ }
258
+ #endif
259
+ }
260
+ break;
261
+ #ifdef JSMN_STRICT
262
+ /* In strict mode primitives are: numbers and booleans */
263
+ case '-': case '0': case '1' : case '2': case '3' : case '4':
264
+ case '5': case '6': case '7' : case '8': case '9':
265
+ case 't': case 'f': case 'n' :
266
+ /* And they must not be keys of the object */
267
+ if (tokens != NULL && parser->toksuper != -1) {
268
+ jsmntok_t *t = &tokens[parser->toksuper];
269
+ if (t->type == JSMN_OBJECT ||
270
+ (t->type == JSMN_STRING && t->size != 0)) {
271
+ return JSMN_ERROR_INVAL;
272
+ }
273
+ }
274
+ #else
275
+ /* In non-strict mode every unquoted value is a primitive */
276
+ default:
277
+ #endif
278
+ r = jsmn_parse_primitive(parser, js, len, tokens, num_tokens);
279
+ if (r < 0) return r;
280
+ count++;
281
+ if (parser->toksuper != -1 && tokens != NULL)
282
+ tokens[parser->toksuper].size++;
283
+ break;
284
+
285
+ #ifdef JSMN_STRICT
286
+ /* Unexpected char in strict mode */
287
+ default:
288
+ return JSMN_ERROR_INVAL;
289
+ #endif
290
+ }
291
+ }
292
+
293
+ if (tokens != NULL) {
294
+ for (i = parser->toknext - 1; i >= 0; i--) {
295
+ /* Unmatched opened object or array */
296
+ if (tokens[i].start != -1 && tokens[i].end == -1) {
297
+ return JSMN_ERROR_PART;
298
+ }
299
+ }
300
+ }
301
+
302
+ return count;
303
+ }
304
+
305
+ /**
306
+ * Creates a new parser based over a given buffer with an array of tokens
307
+ * available.
308
+ */
309
+ void jsmn_init(jsmn_parser *parser) {
310
+ parser->pos = 0;
311
+ parser->toknext = 0;
312
+ parser->toksuper = -1;
313
+ }
314
+