]> andersk Git - libyaml.git/blob - src/reader.c
ac11323c06b0b1d07cf166bec6f42245fef71d7d
[libyaml.git] / src / reader.c
1
2 #if HAVE_CONFIG_H
3 #include <config.h>
4 #endif
5
6 #include <yaml/yaml.h>
7
8 #include <assert.h>
9
10 /*
11  * Set the reader error and return 0.
12  */
13
14 int
15 yaml_parser_set_reader_error(yaml_parser_t *parser, const char *problem,
16         size_t offset, int value)
17 {
18     parser->error = YAML_READER_ERROR;
19     parser->problem = problem;
20     parser->problem_offset = offset;
21     parser->problem_value = value;
22
23     return 0;
24 }
25
26
27 /*
28  * Ensure that the buffer contains at least length characters.
29  * Return 1 on success, 0 on failure.
30  *
31  * The length is supposed to be significantly less that the buffer size.
32  */
33
34 int
35 yaml_parser_update_buffer(yaml_parser_t *parser, size_t length)
36 {
37     /* If the EOF flag is set and the raw buffer is empty, do nothing. */
38
39     if (parser->eof && !parser->raw_unread)
40         return 1;
41
42     /* Return if the buffer contains enough characters. */
43
44     if (parser->unread >= length)
45         return 1;
46
47     /* Determine the input encoding if it is not known yet. */
48
49     if (!parser->encoding) {
50         if (!yaml_parser_determine_encoding(parser))
51             return 0;
52     }
53
54     /* Move the unread characters to the beginning of the buffer. */
55
56     if (parser->buffer < parser->pointer
57             && parser->pointer < parser->buffer_end) {
58         size_t size = parser->buffer_end - parser->pointer;
59         memmove(parser->buffer, parser->pointer, size);
60         parser->pointer = parser->buffer;
61         parser->buffer_end -= size;
62     }
63     else if (parser->pointer == parser->buffer_end) {
64         parser->pointer = parser->buffer;
65         parser->buffer_end = parser->buffer;
66     }
67
68     /* Fill the buffer until it has enough characters. */
69
70     while (parser->unread < length)
71     {
72         /* Fill the raw buffer. */
73
74         if (!yaml_parser_update_raw_buffer(parser)) return 0;
75
76         /* Decode the raw buffer. */
77
78         while (parser->raw_unread)
79         {
80             unsigned int value, value2;
81             int incomplete = 0;
82             unsigned char octet;
83             unsigned int width;
84             int k, low, high;
85
86             /* Decode the next character. */
87
88             switch (parser->encoding)
89             {
90                 case YAML_UTF8_ENCODING:
91
92                     /*
93                      * Decode a UTF-8 character.  Check RFC 3629
94                      * (http://www.ietf.org/rfc/rfc3629.txt) for more details.
95                      *
96                      * The following table (taken from the RFC) is used for
97                      * decoding.
98                      *
99                      *    Char. number range |        UTF-8 octet sequence
100                      *      (hexadecimal)    |              (binary)
101                      *   --------------------+------------------------------------
102                      *   0000 0000-0000 007F | 0xxxxxxx
103                      *   0000 0080-0000 07FF | 110xxxxx 10xxxxxx
104                      *   0000 0800-0000 FFFF | 1110xxxx 10xxxxxx 10xxxxxx
105                      *   0001 0000-0010 FFFF | 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
106                      *
107                      * Additionally, the characters in the range 0xD800-0xDFFF
108                      * are prohibited as they are reserved for use with UTF-16
109                      * surrogate pairs.
110                      */
111
112                     /* Determine the length of the UTF-8 sequence. */
113
114                     octet = parser->raw_pointer[0];
115                     width = (octet & 0x80) == 0x00 ? 1 :
116                             (octet & 0xE0) == 0xC0 ? 2 :
117                             (octet & 0xF0) == 0xE0 ? 3 :
118                             (octet & 0xF8) == 0xF0 ? 4 : 0;
119
120                     /* Check if the leading octet is valid. */
121
122                     if (!width)
123                         return yaml_parser_set_reader_error(parser,
124                                 "Invalid leading UTF-8 octet",
125                                 parser->offset, octet);
126
127                     /* Check if the raw buffer contains an incomplete character. */
128
129                     if (width > parser->raw_unread) {
130                         if (parser->eof) {
131                             return yaml_parser_set_reader_error(parser,
132                                     "Incomplete UTF-8 octet sequence",
133                                     parser->offset, -1);
134                         }
135                         incomplete = 1;
136                         break;
137                     }
138
139                     /* Decode the leading octet. */
140
141                     value = (octet & 0x80) == 0x00 ? octet & 0x7F :
142                             (octet & 0xE0) == 0xC0 ? octet & 0x1F :
143                             (octet & 0xF0) == 0xE0 ? octet & 0x0F :
144                             (octet & 0xF8) == 0xF0 ? octet & 0x07 : 0;
145
146                     /* Check and decode the trailing octets. */
147
148                     for (k = 1; k < width; k ++)
149                     {
150                         octet = parser->raw_pointer[k];
151
152                         /* Check if the octet is valid. */
153
154                         if ((octet & 0xC0) != 0x80)
155                             return yaml_parser_set_reader_error(parser,
156                                     "Invalid trailing UTF-8 octet",
157                                     parser->offset+k, octet);
158
159                         /* Decode the octet. */
160
161                         value = (value << 6) + (octet & 0x3F);
162                     }
163
164                     /* Check the length of the sequence against the value. */
165
166                     if (!((width == 1) ||
167                             (width == 2 && value >= 0x80) ||
168                             (width == 3 && value >= 0x800) ||
169                             (width == 4 && value >= 0x10000)))
170                         return yaml_parser_set_reader_error(parser,
171                                 "Invalid length of a UTF-8 sequence",
172                                 parser->offset, -1);
173
174                     /* Check the range of the value. */
175
176                     if ((value >= 0xD800 && value <= 0xDFFF) || value > 0x10FFFF)
177                         return yaml_parser_set_reader_error(parser,
178                                 "Invalid Unicode character",
179                                 parser->offset, value);
180
181                     break;
182                 
183                 case YAML_UTF16LE_ENCODING:
184                 case YAML_UTF16BE_ENCODING:
185
186                     low = (parser->encoding == YAML_UTF16LE_ENCODING ? 0 : 1);
187                     high = (parser->encoding == YAML_UTF16LE_ENCODING ? 1 : 0);
188
189                     /*
190                      * The UTF-16 encoding is not as simple as one might
191                      * naively think.  Check RFC 2781
192                      * (http://www.ietf.org/rfc/rfc2781.txt).
193                      *
194                      * Normally, two subsequent bytes describe a Unicode
195                      * character.  However a special technique (called a
196                      * surrogate pair) is used for specifying character
197                      * values larger than 0xFFFF.
198                      *
199                      * A surrogate pair consists of two pseudo-characters:
200                      *      high surrogate area (0xD800-0xDBFF)
201                      *      low surrogate area (0xDC00-0xDFFF)
202                      *
203                      * The following formulas are used for decoding
204                      * and encoding characters using surrogate pairs:
205                      * 
206                      *  U  = U' + 0x10000   (0x01 00 00 <= U <= 0x10 FF FF)
207                      *  U' = yyyyyyyyyyxxxxxxxxxx   (0 <= U' <= 0x0F FF FF)
208                      *  W1 = 110110yyyyyyyyyy
209                      *  W2 = 110111xxxxxxxxxx
210                      *
211                      * where U is the character value, W1 is the high surrogate
212                      * area, W2 is the low surrogate area.
213                      */
214
215                     /* Check for incomplete UTF-16 character. */
216
217                     if (parser->raw_unread < 2) {
218                         if (parser->eof) {
219                             return yaml_parser_set_reader_error(parser,
220                                     "Incomplete UTF-16 character",
221                                     parser->offset, -1);
222                         }
223                         incomplete = 1;
224                         break;
225                     }
226
227                     /* Get the character. */
228
229                     value = parser->raw_pointer[low]
230                         + (parser->raw_pointer[high] << 8);
231
232                     /* Check for unexpected low surrogate area. */
233
234                     if ((value & 0xFC00) == 0xDC00)
235                         return yaml_parser_set_reader_error(parser,
236                                 "Unexpected low surrogate area",
237                                 parser->offset, value);
238
239                     /* Check for a high surrogate area. */
240
241                     if ((value & 0xFC00) == 0xD800) {
242
243                         width = 4;
244
245                         /* Check for incomplete surrogate pair. */
246
247                         if (parser->raw_unread < 4) {
248                             if (parser->eof) {
249                                 return yaml_parser_set_reader_error(parser,
250                                         "Incomplete UTF-16 surrogate pair",
251                                         parser->offset, -1);
252                             }
253                             incomplete = 1;
254                             break;
255                         }
256
257                         /* Get the next character. */
258
259                         unsigned int value2 = parser->raw_pointer[low+2]
260                             + (parser->raw_pointer[high+2] << 8);
261
262                         /* Check for a low surrogate area. */
263
264                         if ((value2 & 0xFC00) != 0xDC00)
265                             return yaml_parser_set_reader_error(parser,
266                                     "Expected low surrogate area",
267                                     parser->offset+2, value2);
268
269                         /* Generate the value of the surrogate pair. */
270
271                         value = 0x10000 + ((value & 0x3FF) << 10) + (value2 & 0x3FF);
272                     }
273
274                     else {
275                         width = 2;
276                     }
277
278                     break;
279             }
280
281             /* Check if the raw buffer contains enough bytes to form a character. */
282
283             if (incomplete) break;
284
285             /*
286              * Check if the character is in the allowed range:
287              *      #x9 | #xA | #xD | [#x20-#x7E]               (8 bit)
288              *      | #x85 | [#xA0-#xD7FF] | [#xE000-#xFFFD]    (16 bit)
289              *      | [#x10000-#x10FFFF]                        (32 bit)
290              */
291
292             if (! (value == 0x09 || value == 0x0A || value == 0x0D
293                         || (value >= 0x20 && value <= 0x7E)
294                         || (value == 0x85) || (value >= 0xA0 && value <= 0xD7FF)
295                         || (value >= 0xE000 && value <= 0xFFFD)
296                         || (value >= 0x10000 && value <= 0x10FFFF)))
297                 return yaml_parser_set_reader_error(parser,
298                         "Control characters are not allowed",
299                         parser->offset, value);
300
301             /* Move the raw pointers. */
302
303             parser->raw_pointer += width;
304             parser->raw_unread -= width;
305             parser->offset += width;
306
307             /* Finally put the character into the buffer. */
308
309             /* 0000 0000-0000 007F -> 0xxxxxxx */
310             if (value <= 0x7F) {
311                 *(parser->buffer_end++) = value;
312             }
313             /* 0000 0080-0000 07FF -> 110xxxxx 10xxxxxx */
314             else if (value <= 0x7FF) {
315                 *(parser->buffer_end++) = 0xC0 + (value >> 6);
316                 *(parser->buffer_end++) = 0x80 + (value & 0x3F);
317             }
318             /* 0000 0800-0000 FFFF -> 1110xxxx 10xxxxxx 10xxxxxx */
319             else if (value <= 0xFFFF) {
320                 *(parser->buffer_end++) = 0xE0 + (value >> 12);
321                 *(parser->buffer_end++) = 0x80 + ((value >> 6) & 0x3F);
322                 *(parser->buffer_end++) = 0x80 + (value & 0x3F);
323             }
324             /* 0001 0000-0010 FFFF -> 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx */
325             else {
326                 *(parser->buffer_end++) = 0xF0 + (value >> 18);
327                 *(parser->buffer_end++) = 0x80 + ((value >> 12) & 0x3F);
328                 *(parser->buffer_end++) = 0x80 + ((value >> 6) & 0x3F);
329                 *(parser->buffer_end++) = 0x80 + (value & 0x3F);
330             }
331
332             parser->unread ++;
333         }
334
335         /* On EOF, put NUL into the buffer and return. */
336
337         if (parser->eof) {
338             *(parser->buffer_end++) = '\0';
339             parser->unread ++;
340             return 1;
341         }
342
343     }
344
345     return 1;
346 }
347
348 /*
349  * Determine the input stream encoding by checking the BOM symbol. If no BOM is
350  * found, the UTF-8 encoding is assumed. Return 1 on success, 0 on failure.
351  */
352
353 #define BOM_UTF8    "\xef\xbb\xbf"
354 #define BOM_UTF16LE "\xff\xfe"
355 #define BOM_UTF16BE "\xfe\xff"
356
357 int
358 yaml_parser_determine_encoding(yaml_parser_t *parser)
359 {
360     /* Ensure that we had enough bytes in the raw buffer. */
361
362     while (!parser->eof && parser->raw_unread < 3) {
363         if (!yaml_parser_update_raw_buffer(parser)) {
364             return 0;
365         }
366     }
367
368     /* Determine the encoding. */
369
370     if (parser->raw_unread >= 2
371             && !memcmp(parser->raw_pointer, BOM_UTF16LE, 2)) {
372         parser->encoding = YAML_UTF16LE_ENCODING;
373         parser->raw_pointer += 2;
374         parser->raw_unread -= 2;
375         parser->offset += 2;
376     }
377     else if (parser->raw_unread >= 2
378             && !memcmp(parser->raw_pointer, BOM_UTF16BE, 2)) {
379         parser->encoding = YAML_UTF16BE_ENCODING;
380         parser->raw_pointer += 2;
381         parser->raw_unread -= 2;
382         parser->offset += 2;
383     }
384     else if (parser->raw_unread >= 3
385             && !memcmp(parser->raw_pointer, BOM_UTF8, 3)) {
386         parser->encoding = YAML_UTF8_ENCODING;
387         parser->raw_pointer += 3;
388         parser->raw_unread -= 3;
389         parser->offset += 3;
390     }
391     else {
392         parser->encoding = YAML_UTF8_ENCODING;
393     }
394
395     return 1;
396 }
397
398 /*
399  * Update the raw buffer.
400  */
401
402 int
403 yaml_parser_update_raw_buffer(yaml_parser_t *parser)
404 {
405     size_t size_read = 0;
406
407     /* Return if the raw buffer is full. */
408
409     if (parser->raw_unread == YAML_RAW_BUFFER_SIZE) return 1;
410
411     /* Return on EOF. */
412
413     if (parser->eof) return 1;
414
415     /* Move the remaining bytes in the raw buffer to the beginning. */
416
417     if (parser->raw_unread && parser->raw_buffer < parser->raw_pointer) {
418         memmove(parser->raw_buffer, parser->raw_pointer, parser->raw_unread);
419     }
420     parser->raw_pointer = parser->raw_buffer;
421
422     /* Call the read handler to fill the buffer. */
423
424     if (!parser->read_handler(parser->read_handler_data,
425                 parser->raw_buffer + parser->raw_unread,
426                 YAML_RAW_BUFFER_SIZE - parser->raw_unread,
427                 &size_read)) {
428         return yaml_parser_set_reader_error(parser, "Input error",
429                 parser->offset, -1);
430     }
431     parser->raw_unread += size_read;
432     if (!size_read) {
433         parser->eof = 1;
434     }
435
436     return 1;
437 }
438
This page took 1.317205 seconds and 3 git commands to generate.