145
|
1
|
|
2 /* Copyright (C) 1999-2019 by The D Language Foundation, All Rights Reserved
|
|
3 * http://www.digitalmars.com
|
|
4 * Distributed under the Boost Software License, Version 1.0.
|
|
5 * (See accompanying file LICENSE or copy at http://www.boost.org/LICENSE_1_0.txt)
|
|
6 * https://github.com/D-Programming-Language/dmd/blob/master/src/root/outbuffer.c
|
|
7 */
|
|
8
|
|
9 #include "dsystem.h"
|
|
10 #include "outbuffer.h"
|
|
11 #include "object.h"
|
|
12
|
|
13 char *OutBuffer::extractData()
|
|
14 {
|
|
15 char *p;
|
|
16
|
|
17 p = (char *)data;
|
|
18 data = NULL;
|
|
19 offset = 0;
|
|
20 size = 0;
|
|
21 return p;
|
|
22 }
|
|
23
|
|
24 void OutBuffer::reserve(size_t nbytes)
|
|
25 {
|
|
26 //printf("OutBuffer::reserve: size = %d, offset = %d, nbytes = %d\n", size, offset, nbytes);
|
|
27 if (size - offset < nbytes)
|
|
28 {
|
|
29 size = (offset + nbytes) * 2;
|
|
30 size = (size + 15) & ~15;
|
|
31 data = (unsigned char *)mem.xrealloc(data, size);
|
|
32 }
|
|
33 }
|
|
34
|
|
35 void OutBuffer::reset()
|
|
36 {
|
|
37 offset = 0;
|
|
38 }
|
|
39
|
|
40 void OutBuffer::setsize(size_t size)
|
|
41 {
|
|
42 offset = size;
|
|
43 }
|
|
44
|
|
45 void OutBuffer::write(const void *data, size_t nbytes)
|
|
46 {
|
|
47 if (doindent && !notlinehead)
|
|
48 {
|
|
49 if (level)
|
|
50 {
|
|
51 reserve(level);
|
|
52 for (int i = 0; i < level; i++)
|
|
53 {
|
|
54 this->data[offset] = '\t';
|
|
55 offset++;
|
|
56 }
|
|
57 }
|
|
58 notlinehead = 1;
|
|
59 }
|
|
60 reserve(nbytes);
|
|
61 memcpy(this->data + offset, data, nbytes);
|
|
62 offset += nbytes;
|
|
63 }
|
|
64
|
|
65 void OutBuffer::writebstring(utf8_t *string)
|
|
66 {
|
|
67 write(string,*string + 1);
|
|
68 }
|
|
69
|
|
70 void OutBuffer::writestring(const char *string)
|
|
71 {
|
|
72 write(string,strlen(string));
|
|
73 }
|
|
74
|
|
75 void OutBuffer::prependstring(const char *string)
|
|
76 {
|
|
77 size_t len = strlen(string);
|
|
78 reserve(len);
|
|
79 memmove(data + len, data, offset);
|
|
80 memcpy(data, string, len);
|
|
81 offset += len;
|
|
82 }
|
|
83
|
|
84 void OutBuffer::writenl()
|
|
85 {
|
|
86 #if _WIN32
|
|
87 writeword(0x0A0D); // newline is CR,LF on Microsoft OS's
|
|
88 #else
|
|
89 writeByte('\n');
|
|
90 #endif
|
|
91 if (doindent)
|
|
92 notlinehead = 0;
|
|
93 }
|
|
94
|
|
95 void OutBuffer::writeByte(unsigned b)
|
|
96 {
|
|
97 if (doindent && !notlinehead
|
|
98 && b != '\n')
|
|
99 {
|
|
100 if (level)
|
|
101 {
|
|
102 reserve(level);
|
|
103 for (int i = 0; i < level; i++)
|
|
104 {
|
|
105 this->data[offset] = '\t';
|
|
106 offset++;
|
|
107 }
|
|
108 }
|
|
109 notlinehead = 1;
|
|
110 }
|
|
111 reserve(1);
|
|
112 this->data[offset] = (unsigned char)b;
|
|
113 offset++;
|
|
114 }
|
|
115
|
|
116 void OutBuffer::writeUTF8(unsigned b)
|
|
117 {
|
|
118 reserve(6);
|
|
119 if (b <= 0x7F)
|
|
120 {
|
|
121 this->data[offset] = (unsigned char)b;
|
|
122 offset++;
|
|
123 }
|
|
124 else if (b <= 0x7FF)
|
|
125 {
|
|
126 this->data[offset + 0] = (unsigned char)((b >> 6) | 0xC0);
|
|
127 this->data[offset + 1] = (unsigned char)((b & 0x3F) | 0x80);
|
|
128 offset += 2;
|
|
129 }
|
|
130 else if (b <= 0xFFFF)
|
|
131 {
|
|
132 this->data[offset + 0] = (unsigned char)((b >> 12) | 0xE0);
|
|
133 this->data[offset + 1] = (unsigned char)(((b >> 6) & 0x3F) | 0x80);
|
|
134 this->data[offset + 2] = (unsigned char)((b & 0x3F) | 0x80);
|
|
135 offset += 3;
|
|
136 }
|
|
137 else if (b <= 0x1FFFFF)
|
|
138 {
|
|
139 this->data[offset + 0] = (unsigned char)((b >> 18) | 0xF0);
|
|
140 this->data[offset + 1] = (unsigned char)(((b >> 12) & 0x3F) | 0x80);
|
|
141 this->data[offset + 2] = (unsigned char)(((b >> 6) & 0x3F) | 0x80);
|
|
142 this->data[offset + 3] = (unsigned char)((b & 0x3F) | 0x80);
|
|
143 offset += 4;
|
|
144 }
|
|
145 else if (b <= 0x3FFFFFF)
|
|
146 {
|
|
147 this->data[offset + 0] = (unsigned char)((b >> 24) | 0xF8);
|
|
148 this->data[offset + 1] = (unsigned char)(((b >> 18) & 0x3F) | 0x80);
|
|
149 this->data[offset + 2] = (unsigned char)(((b >> 12) & 0x3F) | 0x80);
|
|
150 this->data[offset + 3] = (unsigned char)(((b >> 6) & 0x3F) | 0x80);
|
|
151 this->data[offset + 4] = (unsigned char)((b & 0x3F) | 0x80);
|
|
152 offset += 5;
|
|
153 }
|
|
154 else if (b <= 0x7FFFFFFF)
|
|
155 {
|
|
156 this->data[offset + 0] = (unsigned char)((b >> 30) | 0xFC);
|
|
157 this->data[offset + 1] = (unsigned char)(((b >> 24) & 0x3F) | 0x80);
|
|
158 this->data[offset + 2] = (unsigned char)(((b >> 18) & 0x3F) | 0x80);
|
|
159 this->data[offset + 3] = (unsigned char)(((b >> 12) & 0x3F) | 0x80);
|
|
160 this->data[offset + 4] = (unsigned char)(((b >> 6) & 0x3F) | 0x80);
|
|
161 this->data[offset + 5] = (unsigned char)((b & 0x3F) | 0x80);
|
|
162 offset += 6;
|
|
163 }
|
|
164 else
|
|
165 assert(0);
|
|
166 }
|
|
167
|
|
168 void OutBuffer::prependbyte(unsigned b)
|
|
169 {
|
|
170 reserve(1);
|
|
171 memmove(data + 1, data, offset);
|
|
172 data[0] = (unsigned char)b;
|
|
173 offset++;
|
|
174 }
|
|
175
|
|
176 void OutBuffer::writewchar(unsigned w)
|
|
177 {
|
|
178 #if _WIN32
|
|
179 writeword(w);
|
|
180 #else
|
|
181 write4(w);
|
|
182 #endif
|
|
183 }
|
|
184
|
|
185 void OutBuffer::writeword(unsigned w)
|
|
186 {
|
|
187 #if _WIN32
|
|
188 unsigned newline = 0x0A0D;
|
|
189 #else
|
|
190 unsigned newline = '\n';
|
|
191 #endif
|
|
192 if (doindent && !notlinehead
|
|
193 && w != newline)
|
|
194 {
|
|
195 if (level)
|
|
196 {
|
|
197 reserve(level);
|
|
198 for (int i = 0; i < level; i++)
|
|
199 {
|
|
200 this->data[offset] = '\t';
|
|
201 offset++;
|
|
202 }
|
|
203 }
|
|
204 notlinehead = 1;
|
|
205 }
|
|
206 reserve(2);
|
|
207 *(unsigned short *)(this->data + offset) = (unsigned short)w;
|
|
208 offset += 2;
|
|
209 }
|
|
210
|
|
211 void OutBuffer::writeUTF16(unsigned w)
|
|
212 {
|
|
213 reserve(4);
|
|
214 if (w <= 0xFFFF)
|
|
215 {
|
|
216 *(unsigned short *)(this->data + offset) = (unsigned short)w;
|
|
217 offset += 2;
|
|
218 }
|
|
219 else if (w <= 0x10FFFF)
|
|
220 {
|
|
221 *(unsigned short *)(this->data + offset) = (unsigned short)((w >> 10) + 0xD7C0);
|
|
222 *(unsigned short *)(this->data + offset + 2) = (unsigned short)((w & 0x3FF) | 0xDC00);
|
|
223 offset += 4;
|
|
224 }
|
|
225 else
|
|
226 assert(0);
|
|
227 }
|
|
228
|
|
229 void OutBuffer::write4(unsigned w)
|
|
230 {
|
|
231 #if _WIN32
|
|
232 bool notnewline = w != 0x000A000D;
|
|
233 #else
|
|
234 bool notnewline = true;
|
|
235 #endif
|
|
236 if (doindent && !notlinehead && notnewline)
|
|
237 {
|
|
238 if (level)
|
|
239 {
|
|
240 reserve(level);
|
|
241 for (int i = 0; i < level; i++)
|
|
242 {
|
|
243 this->data[offset] = '\t';
|
|
244 offset++;
|
|
245 }
|
|
246 }
|
|
247 notlinehead = 1;
|
|
248 }
|
|
249 reserve(4);
|
|
250 *(unsigned *)(this->data + offset) = w;
|
|
251 offset += 4;
|
|
252 }
|
|
253
|
|
254 void OutBuffer::write(OutBuffer *buf)
|
|
255 {
|
|
256 if (buf)
|
|
257 { reserve(buf->offset);
|
|
258 memcpy(data + offset, buf->data, buf->offset);
|
|
259 offset += buf->offset;
|
|
260 }
|
|
261 }
|
|
262
|
|
263 void OutBuffer::write(RootObject *obj)
|
|
264 {
|
|
265 if (obj)
|
|
266 {
|
|
267 writestring(obj->toChars());
|
|
268 }
|
|
269 }
|
|
270
|
|
271 void OutBuffer::fill0(size_t nbytes)
|
|
272 {
|
|
273 reserve(nbytes);
|
|
274 memset(data + offset,0,nbytes);
|
|
275 offset += nbytes;
|
|
276 }
|
|
277
|
|
278 void OutBuffer::vprintf(const char *format, va_list args)
|
|
279 {
|
|
280 int count;
|
|
281
|
|
282 if (doindent)
|
|
283 write(NULL, 0); // perform indent
|
|
284 int psize = 128;
|
|
285 for (;;)
|
|
286 {
|
|
287 reserve(psize);
|
|
288 #if _WIN32
|
|
289 count = _vsnprintf((char *)data + offset,psize,format,args);
|
|
290 if (count != -1)
|
|
291 break;
|
|
292 psize *= 2;
|
|
293 #elif POSIX
|
|
294 va_list va;
|
|
295 va_copy(va, args);
|
|
296 /*
|
|
297 The functions vprintf(), vfprintf(), vsprintf(), vsnprintf()
|
|
298 are equivalent to the functions printf(), fprintf(), sprintf(),
|
|
299 snprintf(), respectively, except that they are called with a
|
|
300 va_list instead of a variable number of arguments. These
|
|
301 functions do not call the va_end macro. Consequently, the value
|
|
302 of ap is undefined after the call. The application should call
|
|
303 va_end(ap) itself afterwards.
|
|
304 */
|
|
305 count = vsnprintf((char *)data + offset,psize,format,va);
|
|
306 va_end(va);
|
|
307 if (count == -1)
|
|
308 psize *= 2;
|
|
309 else if (count >= psize)
|
|
310 psize = count + 1;
|
|
311 else
|
|
312 break;
|
|
313 #else
|
|
314 assert(0);
|
|
315 #endif
|
|
316 }
|
|
317 offset += count;
|
|
318 }
|
|
319
|
|
320 void OutBuffer::printf(const char *format, ...)
|
|
321 {
|
|
322 va_list ap;
|
|
323 va_start(ap, format);
|
|
324 vprintf(format,ap);
|
|
325 va_end(ap);
|
|
326 }
|
|
327
|
|
328 void OutBuffer::bracket(char left, char right)
|
|
329 {
|
|
330 reserve(2);
|
|
331 memmove(data + 1, data, offset);
|
|
332 data[0] = left;
|
|
333 data[offset + 1] = right;
|
|
334 offset += 2;
|
|
335 }
|
|
336
|
|
337 /******************
|
|
338 * Insert left at i, and right at j.
|
|
339 * Return index just past right.
|
|
340 */
|
|
341
|
|
342 size_t OutBuffer::bracket(size_t i, const char *left, size_t j, const char *right)
|
|
343 {
|
|
344 size_t leftlen = strlen(left);
|
|
345 size_t rightlen = strlen(right);
|
|
346 reserve(leftlen + rightlen);
|
|
347 insert(i, left, leftlen);
|
|
348 insert(j + leftlen, right, rightlen);
|
|
349 return j + leftlen + rightlen;
|
|
350 }
|
|
351
|
|
352 void OutBuffer::spread(size_t offset, size_t nbytes)
|
|
353 {
|
|
354 reserve(nbytes);
|
|
355 memmove(data + offset + nbytes, data + offset,
|
|
356 this->offset - offset);
|
|
357 this->offset += nbytes;
|
|
358 }
|
|
359
|
|
360 /****************************************
|
|
361 * Returns: offset + nbytes
|
|
362 */
|
|
363
|
|
364 size_t OutBuffer::insert(size_t offset, const void *p, size_t nbytes)
|
|
365 {
|
|
366 spread(offset, nbytes);
|
|
367 memmove(data + offset, p, nbytes);
|
|
368 return offset + nbytes;
|
|
369 }
|
|
370
|
|
371 void OutBuffer::remove(size_t offset, size_t nbytes)
|
|
372 {
|
|
373 memmove(data + offset, data + offset + nbytes, this->offset - (offset + nbytes));
|
|
374 this->offset -= nbytes;
|
|
375 }
|
|
376
|
|
377 char *OutBuffer::peekString()
|
|
378 {
|
|
379 if (!offset || data[offset-1] != '\0')
|
|
380 {
|
|
381 writeByte(0);
|
|
382 offset--; // allow appending more
|
|
383 }
|
|
384 return (char *)data;
|
|
385 }
|
|
386
|
|
387 char *OutBuffer::extractString()
|
|
388 {
|
|
389 if (!offset || data[offset-1] != '\0')
|
|
390 writeByte(0);
|
|
391 return extractData();
|
|
392 }
|