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

Revision 211, 3.8 KB checked in by xi, 8 years ago (diff)

Add Emitter definitions and implement the Writer.

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