1247738Sbapt
2247738Sbapt#include "yaml_private.h"
3247738Sbapt
4247738Sbapt/*
5247738Sbapt * Declarations.
6247738Sbapt */
7247738Sbapt
8247738Sbaptstatic int
9247738Sbaptyaml_emitter_set_writer_error(yaml_emitter_t *emitter, const char *problem);
10247738Sbapt
11247738SbaptYAML_DECLARE(int)
12247738Sbaptyaml_emitter_flush(yaml_emitter_t *emitter);
13247738Sbapt
14247738Sbapt/*
15247738Sbapt * Set the writer error and return 0.
16247738Sbapt */
17247738Sbapt
18247738Sbaptstatic int
19247738Sbaptyaml_emitter_set_writer_error(yaml_emitter_t *emitter, const char *problem)
20247738Sbapt{
21247738Sbapt    emitter->error = YAML_WRITER_ERROR;
22247738Sbapt    emitter->problem = problem;
23247738Sbapt
24247738Sbapt    return 0;
25247738Sbapt}
26247738Sbapt
27247738Sbapt/*
28247738Sbapt * Flush the output buffer.
29247738Sbapt */
30247738Sbapt
31247738SbaptYAML_DECLARE(int)
32247738Sbaptyaml_emitter_flush(yaml_emitter_t *emitter)
33247738Sbapt{
34247738Sbapt    int low, high;
35247738Sbapt
36247738Sbapt    assert(emitter);    /* Non-NULL emitter object is expected. */
37247738Sbapt    assert(emitter->write_handler); /* Write handler must be set. */
38247738Sbapt    assert(emitter->encoding);  /* Output encoding must be set. */
39247738Sbapt
40247738Sbapt    emitter->buffer.last = emitter->buffer.pointer;
41247738Sbapt    emitter->buffer.pointer = emitter->buffer.start;
42247738Sbapt
43247738Sbapt    /* Check if the buffer is empty. */
44247738Sbapt
45247738Sbapt    if (emitter->buffer.start == emitter->buffer.last) {
46247738Sbapt        return 1;
47247738Sbapt    }
48247738Sbapt
49247738Sbapt    /* If the output encoding is UTF-8, we don't need to recode the buffer. */
50247738Sbapt
51247738Sbapt    if (emitter->encoding == YAML_UTF8_ENCODING)
52247738Sbapt    {
53247738Sbapt        if (emitter->write_handler(emitter->write_handler_data,
54247738Sbapt                    emitter->buffer.start,
55247738Sbapt                    emitter->buffer.last - emitter->buffer.start)) {
56247738Sbapt            emitter->buffer.last = emitter->buffer.start;
57247738Sbapt            emitter->buffer.pointer = emitter->buffer.start;
58247738Sbapt            return 1;
59247738Sbapt        }
60247738Sbapt        else {
61247738Sbapt            return yaml_emitter_set_writer_error(emitter, "write error");
62247738Sbapt        }
63247738Sbapt    }
64247738Sbapt
65247738Sbapt    /* Recode the buffer into the raw buffer. */
66247738Sbapt
67247738Sbapt    low = (emitter->encoding == YAML_UTF16LE_ENCODING ? 0 : 1);
68247738Sbapt    high = (emitter->encoding == YAML_UTF16LE_ENCODING ? 1 : 0);
69247738Sbapt
70247738Sbapt    while (emitter->buffer.pointer != emitter->buffer.last)
71247738Sbapt    {
72247738Sbapt        unsigned char octet;
73247738Sbapt        unsigned int width;
74247738Sbapt        unsigned int value;
75247738Sbapt        size_t k;
76247738Sbapt
77247738Sbapt        /*
78247738Sbapt         * See the "reader.c" code for more details on UTF-8 encoding.  Note
79247738Sbapt         * that we assume that the buffer contains a valid UTF-8 sequence.
80247738Sbapt         */
81247738Sbapt
82247738Sbapt        /* Read the next UTF-8 character. */
83247738Sbapt
84247738Sbapt        octet = emitter->buffer.pointer[0];
85247738Sbapt
86247738Sbapt        width = (octet & 0x80) == 0x00 ? 1 :
87247738Sbapt                (octet & 0xE0) == 0xC0 ? 2 :
88247738Sbapt                (octet & 0xF0) == 0xE0 ? 3 :
89247738Sbapt                (octet & 0xF8) == 0xF0 ? 4 : 0;
90247738Sbapt
91247738Sbapt        value = (octet & 0x80) == 0x00 ? octet & 0x7F :
92247738Sbapt                (octet & 0xE0) == 0xC0 ? octet & 0x1F :
93247738Sbapt                (octet & 0xF0) == 0xE0 ? octet & 0x0F :
94247738Sbapt                (octet & 0xF8) == 0xF0 ? octet & 0x07 : 0;
95247738Sbapt
96247738Sbapt        for (k = 1; k < width; k ++) {
97247738Sbapt            octet = emitter->buffer.pointer[k];
98247738Sbapt            value = (value << 6) + (octet & 0x3F);
99247738Sbapt        }
100247738Sbapt
101247738Sbapt        emitter->buffer.pointer += width;
102247738Sbapt
103247738Sbapt        /* Write the character. */
104247738Sbapt
105247738Sbapt        if (value < 0x10000)
106247738Sbapt        {
107247738Sbapt            emitter->raw_buffer.last[high] = value >> 8;
108247738Sbapt            emitter->raw_buffer.last[low] = value & 0xFF;
109247738Sbapt
110247738Sbapt            emitter->raw_buffer.last += 2;
111247738Sbapt        }
112247738Sbapt        else
113247738Sbapt        {
114247738Sbapt            /* Write the character using a surrogate pair (check "reader.c"). */
115247738Sbapt
116247738Sbapt            value -= 0x10000;
117247738Sbapt            emitter->raw_buffer.last[high] = 0xD8 + (value >> 18);
118247738Sbapt            emitter->raw_buffer.last[low] = (value >> 10) & 0xFF;
119247738Sbapt            emitter->raw_buffer.last[high+2] = 0xDC + ((value >> 8) & 0xFF);
120247738Sbapt            emitter->raw_buffer.last[low+2] = value & 0xFF;
121247738Sbapt
122247738Sbapt            emitter->raw_buffer.last += 4;
123247738Sbapt        }
124247738Sbapt    }
125247738Sbapt
126247738Sbapt    /* Write the raw buffer. */
127247738Sbapt
128247738Sbapt    if (emitter->write_handler(emitter->write_handler_data,
129247738Sbapt                emitter->raw_buffer.start,
130247738Sbapt                emitter->raw_buffer.last - emitter->raw_buffer.start)) {
131247738Sbapt        emitter->buffer.last = emitter->buffer.start;
132247738Sbapt        emitter->buffer.pointer = emitter->buffer.start;
133247738Sbapt        emitter->raw_buffer.last = emitter->raw_buffer.start;
134247738Sbapt        emitter->raw_buffer.pointer = emitter->raw_buffer.start;
135247738Sbapt        return 1;
136247738Sbapt    }
137247738Sbapt    else {
138247738Sbapt        return yaml_emitter_set_writer_error(emitter, "write error");
139247738Sbapt    }
140247738Sbapt}
141247738Sbapt
142