source: libyaml/trunk/src/reader.c @ 263

Revision 263, 15.7 KB checked in by xi, 6 years ago (diff)

Completed the first phase of API refactoring.

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