/src/moddable/xs/tools/yaml/writer.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* |
2 | | * Copyright (c) 2006-2016 Kirill Simonov |
3 | | * |
4 | | * Permission is hereby granted, free of charge, to any person obtaining a copy of |
5 | | * this software and associated documentation files (the "Software"), to deal in |
6 | | * the Software without restriction, including without limitation the rights to |
7 | | * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies |
8 | | * of the Software, and to permit persons to whom the Software is furnished to do |
9 | | * so, subject to the following conditions: |
10 | | * |
11 | | * The above copyright notice and this permission notice shall be included in all |
12 | | * copies or substantial portions of the Software. |
13 | | * |
14 | | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
15 | | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
16 | | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
17 | | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
18 | | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
19 | | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE |
20 | | * SOFTWARE. |
21 | | * |
22 | | */ |
23 | | |
24 | | #include "yaml_private.h" |
25 | | |
26 | | /* |
27 | | * Declarations. |
28 | | */ |
29 | | |
30 | | static int |
31 | | yaml_emitter_set_writer_error(yaml_emitter_t *emitter, const char *problem); |
32 | | |
33 | | YAML_DECLARE(int) |
34 | | yaml_emitter_flush(yaml_emitter_t *emitter); |
35 | | |
36 | | /* |
37 | | * Set the writer error and return 0. |
38 | | */ |
39 | | |
40 | | static int |
41 | | yaml_emitter_set_writer_error(yaml_emitter_t *emitter, const char *problem) |
42 | 0 | { |
43 | 0 | emitter->error = YAML_WRITER_ERROR; |
44 | 0 | emitter->problem = problem; |
45 | |
|
46 | 0 | return 0; |
47 | 0 | } |
48 | | |
49 | | /* |
50 | | * Flush the output buffer. |
51 | | */ |
52 | | |
53 | | YAML_DECLARE(int) |
54 | | yaml_emitter_flush(yaml_emitter_t *emitter) |
55 | 0 | { |
56 | 0 | int low, high; |
57 | |
|
58 | 0 | assert(emitter); /* Non-NULL emitter object is expected. */ |
59 | 0 | assert(emitter->write_handler); /* Write handler must be set. */ |
60 | 0 | assert(emitter->encoding); /* Output encoding must be set. */ |
61 | | |
62 | 0 | emitter->buffer.last = emitter->buffer.pointer; |
63 | 0 | emitter->buffer.pointer = emitter->buffer.start; |
64 | | |
65 | | /* Check if the buffer is empty. */ |
66 | |
|
67 | 0 | if (emitter->buffer.start == emitter->buffer.last) { |
68 | 0 | return 1; |
69 | 0 | } |
70 | | |
71 | | /* If the output encoding is UTF-8, we don't need to recode the buffer. */ |
72 | | |
73 | 0 | if (emitter->encoding == YAML_UTF8_ENCODING) |
74 | 0 | { |
75 | 0 | if (emitter->write_handler(emitter->write_handler_data, |
76 | 0 | emitter->buffer.start, |
77 | 0 | emitter->buffer.last - emitter->buffer.start)) { |
78 | 0 | emitter->buffer.last = emitter->buffer.start; |
79 | 0 | emitter->buffer.pointer = emitter->buffer.start; |
80 | 0 | return 1; |
81 | 0 | } |
82 | 0 | else { |
83 | 0 | return yaml_emitter_set_writer_error(emitter, "write error"); |
84 | 0 | } |
85 | 0 | } |
86 | | |
87 | | /* Recode the buffer into the raw buffer. */ |
88 | | |
89 | 0 | low = (emitter->encoding == YAML_UTF16LE_ENCODING ? 0 : 1); |
90 | 0 | high = (emitter->encoding == YAML_UTF16LE_ENCODING ? 1 : 0); |
91 | |
|
92 | 0 | while (emitter->buffer.pointer != emitter->buffer.last) |
93 | 0 | { |
94 | 0 | unsigned char octet; |
95 | 0 | unsigned int width; |
96 | 0 | unsigned int value; |
97 | 0 | size_t k; |
98 | | |
99 | | /* |
100 | | * See the "reader.c" code for more details on UTF-8 encoding. Note |
101 | | * that we assume that the buffer contains a valid UTF-8 sequence. |
102 | | */ |
103 | | |
104 | | /* Read the next UTF-8 character. */ |
105 | |
|
106 | 0 | octet = emitter->buffer.pointer[0]; |
107 | |
|
108 | 0 | width = (octet & 0x80) == 0x00 ? 1 : |
109 | 0 | (octet & 0xE0) == 0xC0 ? 2 : |
110 | 0 | (octet & 0xF0) == 0xE0 ? 3 : |
111 | 0 | (octet & 0xF8) == 0xF0 ? 4 : 0; |
112 | |
|
113 | 0 | value = (octet & 0x80) == 0x00 ? octet & 0x7F : |
114 | 0 | (octet & 0xE0) == 0xC0 ? octet & 0x1F : |
115 | 0 | (octet & 0xF0) == 0xE0 ? octet & 0x0F : |
116 | 0 | (octet & 0xF8) == 0xF0 ? octet & 0x07 : 0; |
117 | |
|
118 | 0 | for (k = 1; k < width; k ++) { |
119 | 0 | octet = emitter->buffer.pointer[k]; |
120 | 0 | value = (value << 6) + (octet & 0x3F); |
121 | 0 | } |
122 | |
|
123 | 0 | emitter->buffer.pointer += width; |
124 | | |
125 | | /* Write the character. */ |
126 | |
|
127 | 0 | if (value < 0x10000) |
128 | 0 | { |
129 | 0 | emitter->raw_buffer.last[high] = value >> 8; |
130 | 0 | emitter->raw_buffer.last[low] = value & 0xFF; |
131 | |
|
132 | 0 | emitter->raw_buffer.last += 2; |
133 | 0 | } |
134 | 0 | else |
135 | 0 | { |
136 | | /* Write the character using a surrogate pair (check "reader.c"). */ |
137 | |
|
138 | 0 | value -= 0x10000; |
139 | 0 | emitter->raw_buffer.last[high] = 0xD8 + (value >> 18); |
140 | 0 | emitter->raw_buffer.last[low] = (value >> 10) & 0xFF; |
141 | 0 | emitter->raw_buffer.last[high+2] = 0xDC + ((value >> 8) & 0xFF); |
142 | 0 | emitter->raw_buffer.last[low+2] = value & 0xFF; |
143 | |
|
144 | 0 | emitter->raw_buffer.last += 4; |
145 | 0 | } |
146 | 0 | } |
147 | | |
148 | | /* Write the raw buffer. */ |
149 | |
|
150 | 0 | if (emitter->write_handler(emitter->write_handler_data, |
151 | 0 | emitter->raw_buffer.start, |
152 | 0 | emitter->raw_buffer.last - emitter->raw_buffer.start)) { |
153 | 0 | emitter->buffer.last = emitter->buffer.start; |
154 | 0 | emitter->buffer.pointer = emitter->buffer.start; |
155 | 0 | emitter->raw_buffer.last = emitter->raw_buffer.start; |
156 | 0 | emitter->raw_buffer.pointer = emitter->raw_buffer.start; |
157 | 0 | return 1; |
158 | 0 | } |
159 | 0 | else { |
160 | 0 | return yaml_emitter_set_writer_error(emitter, "write error"); |
161 | 0 | } |
162 | 0 | } |
163 | | |