]>
Commit | Line | Data |
---|---|---|
b1a54000 KS |
1 | |
2 | #include "yaml_private.h" | |
3 | ||
4 | /* | |
5 | * Declarations. | |
6 | */ | |
7 | ||
8 | static int | |
9 | yaml_emitter_set_writer_error(yaml_emitter_t *emitter, const char *problem); | |
10 | ||
11 | YAML_DECLARE(int) | |
12 | yaml_emitter_flush(yaml_emitter_t *emitter); | |
13 | ||
14 | /* | |
15 | * Set the writer error and return 0. | |
16 | */ | |
17 | ||
18 | static int | |
19 | yaml_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 | ||
31 | YAML_DECLARE(int) | |
32 | yaml_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 |