]>
Commit | Line | Data |
---|---|---|
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 | emitter->buffer.last = emitter->buffer.pointer; | |
41 | emitter->buffer.pointer = emitter->buffer.start; | |
42 | ||
43 | /* Check if the buffer is empty. */ | |
44 | ||
45 | if (emitter->buffer.start == emitter->buffer.last) { | |
46 | return 1; | |
47 | } | |
48 | ||
49 | /* If the output encoding is UTF-8, we don't need to recode the buffer. */ | |
50 | ||
51 | if (emitter->encoding == YAML_UTF8_ENCODING) | |
52 | { | |
53 | if (emitter->write_handler(emitter->write_handler_data, | |
54 | emitter->buffer.start, | |
55 | emitter->buffer.last - emitter->buffer.start)) { | |
56 | emitter->buffer.last = emitter->buffer.start; | |
57 | emitter->buffer.pointer = emitter->buffer.start; | |
58 | return 1; | |
59 | } | |
60 | else { | |
61 | return yaml_emitter_set_writer_error(emitter, "write error"); | |
62 | } | |
63 | } | |
64 | ||
65 | /* Recode the buffer into the raw buffer. */ | |
66 | ||
67 | low = (emitter->encoding == YAML_UTF16LE_ENCODING ? 0 : 1); | |
68 | high = (emitter->encoding == YAML_UTF16LE_ENCODING ? 1 : 0); | |
69 | ||
70 | while (emitter->buffer.pointer != emitter->buffer.last) | |
71 | { | |
72 | unsigned char octet; | |
73 | unsigned int width; | |
74 | unsigned int value; | |
75 | size_t k; | |
76 | ||
77 | /* | |
78 | * See the "reader.c" code for more details on UTF-8 encoding. Note | |
79 | * that we assume that the buffer contains a valid UTF-8 sequence. | |
80 | */ | |
81 | ||
82 | /* Read the next UTF-8 character. */ | |
83 | ||
84 | octet = emitter->buffer.pointer[0]; | |
85 | ||
86 | width = (octet & 0x80) == 0x00 ? 1 : | |
87 | (octet & 0xE0) == 0xC0 ? 2 : | |
88 | (octet & 0xF0) == 0xE0 ? 3 : | |
89 | (octet & 0xF8) == 0xF0 ? 4 : 0; | |
90 | ||
91 | value = (octet & 0x80) == 0x00 ? octet & 0x7F : | |
92 | (octet & 0xE0) == 0xC0 ? octet & 0x1F : | |
93 | (octet & 0xF0) == 0xE0 ? octet & 0x0F : | |
94 | (octet & 0xF8) == 0xF0 ? octet & 0x07 : 0; | |
95 | ||
96 | for (k = 1; k < width; k ++) { | |
97 | octet = emitter->buffer.pointer[k]; | |
98 | value = (value << 6) + (octet & 0x3F); | |
99 | } | |
100 | ||
101 | emitter->buffer.pointer += width; | |
102 | ||
103 | /* Write the character. */ | |
104 | ||
105 | if (value < 0x10000) | |
106 | { | |
107 | emitter->raw_buffer.last[high] = value >> 8; | |
108 | emitter->raw_buffer.last[low] = value & 0xFF; | |
109 | ||
110 | emitter->raw_buffer.last += 2; | |
111 | } | |
112 | else | |
113 | { | |
114 | /* Write the character using a surrogate pair (check "reader.c"). */ | |
115 | ||
116 | value -= 0x10000; | |
117 | emitter->raw_buffer.last[high] = 0xD8 + (value >> 18); | |
118 | emitter->raw_buffer.last[low] = (value >> 10) & 0xFF; | |
119 | emitter->raw_buffer.last[high+2] = 0xDC + ((value >> 8) & 0xFF); | |
120 | emitter->raw_buffer.last[low+2] = value & 0xFF; | |
121 | ||
122 | emitter->raw_buffer.last += 4; | |
123 | } | |
124 | } | |
125 | ||
126 | /* Write the raw buffer. */ | |
127 | ||
128 | if (emitter->write_handler(emitter->write_handler_data, | |
129 | emitter->raw_buffer.start, | |
130 | emitter->raw_buffer.last - emitter->raw_buffer.start)) { | |
131 | emitter->buffer.last = emitter->buffer.start; | |
132 | emitter->buffer.pointer = emitter->buffer.start; | |
133 | emitter->raw_buffer.last = emitter->raw_buffer.start; | |
134 | emitter->raw_buffer.pointer = emitter->raw_buffer.start; | |
135 | return 1; | |
136 | } | |
137 | else { | |
138 | return yaml_emitter_set_writer_error(emitter, "write error"); | |
139 | } | |
140 | } | |
141 |