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

Revision 263, 3.6 KB checked in by xi, 7 years ago (diff)

Completed the first phase of API refactoring.

Line 
1
2#include "yaml_private.h"
3
4/*
5 * Declarations.
6 */
7
8YAML_DECLARE(int)
9yaml_emitter_flush(yaml_emitter_t *emitter);
10
11/*
12 * Flush the output buffer.
13 */
14
15YAML_DECLARE(int)
16yaml_emitter_flush(yaml_emitter_t *emitter)
17{
18    int low, high;
19
20    assert(emitter);    /* Non-NULL emitter object is expected. */
21    assert(emitter->writer);    /* Write handler must be set. */
22    assert(emitter->encoding);  /* Output encoding must be set. */
23
24    /* Check if the buffer is empty. */
25
26    if (!emitter->output.pointer) {
27        return 1;
28    }
29
30    /* Switch the pointer to the beginning of the buffer. */
31
32    emitter->output.capacity = emitter->output.pointer;
33    emitter->output.pointer = 0;
34
35    /* If the output encoding is UTF-8, we don't need to recode the buffer. */
36
37    if (emitter->encoding == YAML_UTF8_ENCODING)
38    {
39        if (emitter->writer(emitter->writer_data,
40                    emitter->output.buffer, emitter->output.capacity)) {
41            emitter->offset += emitter->output.capacity;
42            emitter->output.capacity = OUTPUT_BUFFER_CAPACITY;
43            return 1;
44        }
45        else {
46            return WRITER_ERROR_INIT(emitter, "Write error", emitter->offset);
47        }
48    }
49
50    /* Recode the buffer into the raw buffer. */
51
52    low = (emitter->encoding == YAML_UTF16LE_ENCODING ? 0 : 1);
53    high = (emitter->encoding == YAML_UTF16LE_ENCODING ? 1 : 0);
54
55    while (emitter->output.pointer != emitter->output.capacity)
56    {
57        unsigned char octet;
58        unsigned int width;
59        unsigned int value;
60        size_t idx;
61
62        /*
63         * See the "reader.c" code for more details on UTF-8 encoding.  Note
64         * that we assume that the buffer contains a valid UTF-8 sequence.
65         */
66
67        /* Read the next UTF-8 character. */
68
69        octet = OCTET(emitter->output);
70
71        width = (octet & 0x80) == 0x00 ? 1 :
72                (octet & 0xE0) == 0xC0 ? 2 :
73                (octet & 0xF0) == 0xE0 ? 3 :
74                (octet & 0xF8) == 0xF0 ? 4 : 0;
75
76        value = (octet & 0x80) == 0x00 ? octet & 0x7F :
77                (octet & 0xE0) == 0xC0 ? octet & 0x1F :
78                (octet & 0xF0) == 0xE0 ? octet & 0x0F :
79                (octet & 0xF8) == 0xF0 ? octet & 0x07 : 0;
80
81        for (idx = 1; idx < width; idx ++) {
82            octet = OCTET_AT(emitter->output, idx);
83            value = (value << 6) + (octet & 0x3F);
84        }
85
86        emitter->output.pointer += width;
87
88        /* Write the character. */
89
90        if (value < 0x10000)
91        {
92            OCTET_AT(emitter->raw_output, high) = value >> 8;
93            OCTET_AT(emitter->raw_output, low) = value & 0xFF;
94
95            emitter->raw_output.pointer += 2;
96        }
97        else
98        {
99            /* Write the character using a surrogate pair (check "reader.c"). */
100
101            value -= 0x10000;
102            OCTET_AT(emitter->raw_output, high) = 0xD8 + (value >> 18);
103            OCTET_AT(emitter->raw_output, low) = (value >> 10) & 0xFF;
104            OCTET_AT(emitter->raw_output, high+2) = 0xDC + ((value >> 8) & 0xFF);
105            OCTET_AT(emitter->raw_output, low+2) = value & 0xFF;
106
107            emitter->raw_output.pointer += 4;
108        }
109    }
110
111    /* Write the raw buffer. */
112
113    if (emitter->writer(emitter->writer_data,
114                emitter->raw_output.buffer, emitter->raw_output.pointer)) {
115        emitter->output.pointer = 0;
116        emitter->output.capacity = OUTPUT_BUFFER_CAPACITY;
117        emitter->offset += emitter->raw_output.pointer;
118        emitter->raw_output.pointer = 0;
119        return 1;
120    }
121    else {
122        return WRITER_ERROR_INIT(emitter, "Write error", emitter->offset);
123    }
124}
125
Note: See TracBrowser for help on using the repository browser.