xref: /netbsd/external/gpl3/gcc/dist/gcc/d/dmd/root/outbuffer.c (revision ed2d4fca)
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 
extractData()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 
reserve(size_t nbytes)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 
reset()35 void OutBuffer::reset()
36 {
37     offset = 0;
38 }
39 
setsize(size_t size)40 void OutBuffer::setsize(size_t size)
41 {
42     offset = size;
43 }
44 
write(const void * data,size_t nbytes)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 
writebstring(utf8_t * string)65 void OutBuffer::writebstring(utf8_t *string)
66 {
67     write(string,*string + 1);
68 }
69 
writestring(const char * string)70 void OutBuffer::writestring(const char *string)
71 {
72     write(string,strlen(string));
73 }
74 
prependstring(const char * string)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 
writenl()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 
writeByte(unsigned b)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 
writeUTF8(unsigned b)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 
prependbyte(unsigned b)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 
writewchar(unsigned w)176 void OutBuffer::writewchar(unsigned w)
177 {
178 #if _WIN32
179     writeword(w);
180 #else
181     write4(w);
182 #endif
183 }
184 
writeword(unsigned w)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 
writeUTF16(unsigned w)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 
write4(unsigned w)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 
write(OutBuffer * buf)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 
write(RootObject * obj)263 void OutBuffer::write(RootObject *obj)
264 {
265     if (obj)
266     {
267         writestring(obj->toChars());
268     }
269 }
270 
fill0(size_t nbytes)271 void OutBuffer::fill0(size_t nbytes)
272 {
273     reserve(nbytes);
274     memset(data + offset,0,nbytes);
275     offset += nbytes;
276 }
277 
vprintf(const char * format,va_list args)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 
printf(const char * format,...)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 /**************************************
329  * Convert `u` to a string and append it to the buffer.
330  * Params:
331  *  u = integral value to append
332  */
print(unsigned long long u)333 void OutBuffer::print(unsigned long long u)
334 {
335     unsigned long long value = u;
336     char buf[20];
337     const unsigned radix = 10;
338 
339     size_t i = sizeof(buf);
340     do
341     {
342         if (value < radix)
343         {
344             unsigned char x = (unsigned char)value;
345             buf[--i] = (char)(x + '0');
346             break;
347         }
348         else
349         {
350             unsigned char x = (unsigned char)(value % radix);
351             value = value / radix;
352             buf[--i] = (char)(x + '0');
353         }
354     } while (value);
355 
356     write(buf + i, sizeof(buf) - i);
357 }
358 
bracket(char left,char right)359 void OutBuffer::bracket(char left, char right)
360 {
361     reserve(2);
362     memmove(data + 1, data, offset);
363     data[0] = left;
364     data[offset + 1] = right;
365     offset += 2;
366 }
367 
368 /******************
369  * Insert left at i, and right at j.
370  * Return index just past right.
371  */
372 
bracket(size_t i,const char * left,size_t j,const char * right)373 size_t OutBuffer::bracket(size_t i, const char *left, size_t j, const char *right)
374 {
375     size_t leftlen = strlen(left);
376     size_t rightlen = strlen(right);
377     reserve(leftlen + rightlen);
378     insert(i, left, leftlen);
379     insert(j + leftlen, right, rightlen);
380     return j + leftlen + rightlen;
381 }
382 
spread(size_t offset,size_t nbytes)383 void OutBuffer::spread(size_t offset, size_t nbytes)
384 {
385     reserve(nbytes);
386     memmove(data + offset + nbytes, data + offset,
387         this->offset - offset);
388     this->offset += nbytes;
389 }
390 
391 /****************************************
392  * Returns: offset + nbytes
393  */
394 
insert(size_t offset,const void * p,size_t nbytes)395 size_t OutBuffer::insert(size_t offset, const void *p, size_t nbytes)
396 {
397     spread(offset, nbytes);
398     memmove(data + offset, p, nbytes);
399     return offset + nbytes;
400 }
401 
remove(size_t offset,size_t nbytes)402 void OutBuffer::remove(size_t offset, size_t nbytes)
403 {
404     memmove(data + offset, data + offset + nbytes, this->offset - (offset + nbytes));
405     this->offset -= nbytes;
406 }
407 
peekString()408 char *OutBuffer::peekString()
409 {
410     if (!offset || data[offset-1] != '\0')
411     {
412         writeByte(0);
413         offset--; // allow appending more
414     }
415     return (char *)data;
416 }
417 
extractString()418 char *OutBuffer::extractString()
419 {
420     if (!offset || data[offset-1] != '\0')
421         writeByte(0);
422     return extractData();
423 }
424