1 /*
2 * gensi.cpp
3 * by pts@fazekas.hu at Tue Feb 26 13:28:12 CET 2002
4 */
5
6 #ifdef __GNUC__
7 #ifndef __clang__
8 #pragma implementation
9 #endif
10 #endif
11
12 #include "gensi.hpp"
13 #include <string.h> /* strlen() */
14 // #include <stdarg.h> /* va_list */
15
iter_char_sub(char const * beg,slen_t len,void * data)16 void GenBuffer::iter_char_sub(char const*beg, slen_t len, void *data) {
17 while (len--!=0) (1[(block_char_t**)data][0])(*beg++, 0[(void**)data]);
18 }
19
20 struct copydata_t {
21 char *to;
22 slen_t cfrom;
23 slen_t clen;
24 slen_t sumlen;
25 };
26 #define CD static_cast<copydata_t*>(data)
iter_copy_sub(char const * beg,slen_t len,void * data)27 static void iter_copy_sub(char const*beg, slen_t len, void *data) {
28 slen_t i;
29 CD->sumlen+=len;
30 if (CD->clen==0) return;
31 i=CD->cfrom;
32 if (i>=len) { CD->cfrom-=len; return; }
33 if (i>0) { CD->cfrom=0; beg+=i; len-=i; }
34 if (len>=CD->clen) { memcpy(CD->to, beg, CD->clen); CD->clen=0; return; }
35 memcpy(CD->to, beg, len);
36 CD->to+=len; CD->clen-=len;
37 }
38 // #include <stdio.h>
copyRange(char * to,slen_t cfrom,slen_t clen) const39 slen_t GenBuffer::copyRange(char *to, slen_t cfrom, slen_t clen) const {
40 if (clen==0) return getLength();
41 copydata_t cd= { to, cfrom, clen, 0 };
42 each_sub(iter_copy_sub, &cd);
43 #if 1
44 while (cd.clen--!=0) *cd.to++='\0'; /* padding */
45 #else
46 fprintf(stderr,"cd.clen=%d\n", cd.clen);
47 while (cd.clen--!=0) {
48 fprintf(stderr,"padded.\n");
49 *cd.to++='\0'; /* padding */
50 }
51 #endif
52 return cd.sumlen;
53 }
54
55 #if HAVE_LONG_LONG && NEED_LONG_LONG
56 # define LONGEXT PTS_CFG_LONGEST
57 #else
58 # define LONGEXT long
59 #endif
60
61 /* Imp: ensure reentrace. Maybe vi_write wants to output a number which would
62 * overwrite ours...
63 */
64 static char numtmp[sizeof(LONGEXT)*3+2];
65
toBool(bool & dst)66 bool GenBuffer::toBool(bool &dst) {
67 /* on 1 true yes ja igen igaz be oui vrai: 1tyjibov */
68 /* off 0 false no nein nem hamis ki non -- : 0fnhk */
69 slen_t len=copyRange(numtmp, 0, 3);
70 numtmp[0]|=32; numtmp[1]|=32; numtmp[2]|=32; /* poor man's uppercase */
71 dst=true;
72 if (len==0) return true;
73 if ((numtmp[0]=='o' && numtmp[1]=='f' && numtmp[2]=='f')
74 || numtmp[0]=='0' || numtmp[0]=='f' || numtmp[0]=='n' || numtmp[0]=='h'
75 || numtmp[0]=='k') dst=false;
76 else if ((numtmp[0]<'0' || numtmp[0]>'9') && (numtmp[0]<'a' || numtmp[0]>'z')) return true;
77 return false;
78 }
79
80 // #include <stdio.h>
81
toInteger(unsigned long & dst)82 bool GenBuffer::toInteger(unsigned long &dst) {
83 /* Imp: several bases (2, 8, 10 and 16), ignore _too_long_ */
84 /* Imp: check for overflow! */
85 slen_t len=copyRange(numtmp, 0, sizeof(numtmp));
86 // fprintf(stderr,"len=%d\n", len);
87 if (len>=sizeof(numtmp)) return true; /* too long */
88 /* ASSERT(numtmp null-terminated) */
89 char *p=numtmp;
90 if (*p=='+') p++;
91 unsigned long i=0;
92 while (1) {
93 // fprintf(stderr,"toInteger'%c'\n", *p);
94 if (*p<'0' || *p>'9') break;
95 i=10*i+(*p-'0');
96 p++;
97 }
98 dst=i;
99 return *p!='\0'; /* a non-digit arrived */
100 }
toInteger(signed long & dst)101 bool GenBuffer::toInteger(signed long &dst) {
102 /* Imp: several bases (2, 8, 10 and 16), ignore _too_long_ */
103 slen_t len=copyRange(numtmp, 0, sizeof(numtmp));
104 if (len>=sizeof(numtmp)) return true; /* too long */
105 /* ASSERT(numtmp null-terminated) */
106 char *p=numtmp;
107 bool neg=false;
108 if (*p=='+') p++;
109 else if (*p=='-') { neg=true; p++; }
110 unsigned long i=0;
111 while (1) {
112 if (*p<'0' || *p>'9') break;
113 i=10*i+(*p-'0');
114 p++;
115 }
116 dst=neg?-(long)i:i;
117 return *p!='\0'; /* a non-digit arrived */
118 }
119 #if HAVE_LONG_LONG && NEED_LONG_LONG
toInteger(unsigned PTS_CFG_LONGEST & dst)120 bool GenBuffer::toInteger(unsigned PTS_CFG_LONGEST &dst) {
121 /* Imp: several bases (2, 8, 10 and 16), ignore _too_long_ */
122 slen_t len=copyRange(numtmp, 0, sizeof(numtmp));
123 if (len>=sizeof(numtmp)) return true; /* too long */
124 /* ASSERT(numtmp null-terminated) */
125 char *p=numtmp;
126 if (*p=='+') p++;
127 unsigned PTS_CFG_LONGEST i=0;
128 while (1) {
129 if (*p<'0' || *p>'9') break;
130 i=10*i+(*p-'0');
131 p++;
132 }
133 dst=i;
134 return *p!='\0'; /* a non-digit arrived */
135 }
toInteger(signed PTS_CFG_LONGEST & dst)136 bool GenBuffer::toInteger(signed PTS_CFG_LONGEST &dst) {
137 /* Imp: several bases (2, 8, 10 and 16), ignore _too_long_ */
138 slen_t len=copyRange(numtmp, 0, sizeof(numtmp));
139 if (len>=sizeof(numtmp)) return true; /* too long */
140 /* ASSERT(numtmp null-terminated) */
141 char *p=numtmp;
142 bool neg=false;
143 if (*p=='+') p++;
144 else if (*p=='-') { neg=true; p++; }
145 unsigned PTS_CFG_LONGEST i=0;
146 while (1) {
147 if (*p<'0' || *p>'9') break;
148 i=10*i+(*p-'0');
149 p++;
150 }
151 dst=neg?-i:i;
152 return *p!='\0'; /* a non-digit arrived */
153 }
154 #endif
toCString(char * & dst)155 bool GenBuffer::toCString(char *&dst) {
156 slen_t len=getLength();
157 dst=new char[len+1];
158 copyRange(dst, 0, len+1); /* copies the terminating '\0' automatically. */
159 return false;
160 }
161
cmp(GenBuffer const & s2) const162 int GenBuffer::cmp(GenBuffer const& s2) const {
163 Sub u1, u2;
164 slen_t m;
165 int i;
166 first_sub(u1);
167 s2.first_sub(u2);
168 while (1) {
169 if (u1.len==0 && u2.len==0) return 0; /* (*this) == s2 */
170 else if (u1.len==0) return -1; /* (*this) < s2 */
171 else if (u2.len==0) return 1; /* (*this) > s2 */
172 m=(u1.len<u2.len)?u1.len:u2.len;
173 if (0!=(i=memcmp(u1.beg,u2.beg,m))) return i;
174 if (0==(u1.len-=m)) next_sub(u1); else u1.beg+=m;
175 if (0==(u2.len-=m)) s2.next_sub(u2); else u2.beg+=m;
176 }
177 }
178
cmp(char const * u2beg,slen_t u2len) const179 int GenBuffer::cmp(char const* u2beg, slen_t u2len) const {
180 Sub u1;
181 slen_t m;
182 int i;
183 first_sub(u1);
184 while (1) {
185 if (u1.len==0 && u2len==0) return 0; /* (*this) == s2 */
186 else if (u1.len==0) return -1; /* (*this) < s2 */
187 else if (u2len ==0) return 1; /* (*this) > s2 */
188 m=(u1.len<u2len)?u1.len:u2len;
189 if (0!=(i=memcmp(u1.beg,u2beg,m))) return i;
190 if (0==(u1.len-=m)) next_sub(u1); else u1.beg+=m;
191 u2len-=m; u2beg+=m;
192 }
193 }
194
cmp(char const * u2beg) const195 int GenBuffer::cmp(char const* u2beg) const {
196 return cmp(u2beg, strlen(u2beg));
197 }
198
199 /* --- */
200
equal_content(GenBuffer::Readable & other)201 bool GenBuffer::Readable::equal_content(GenBuffer::Readable &other) {
202 int i1, i2;
203 while (((i1=vi_getcc())&255) == ((i2=other.vi_getcc())&255) && i1!=-1) ;
204 return i1==i2;
205 }
206
vi_read(char * to_buf,slen_t max)207 slen_t GenBuffer::Readable::vi_read(char *to_buf, slen_t max) {
208 register char *p=to_buf;
209 char *end=to_buf+max;
210 int c;
211 while (p!=end && 0<=(c=vi_getcc())) *p++=c;
212 return p-to_buf;
213 }
214
readFill(char * to_buf,slen_t max)215 int GenBuffer::Readable::readFill(char *to_buf, slen_t max) {
216 slen_t got, sum=0;
217 while (max>0 && 0<(got=vi_read(to_buf, max))) { to_buf+=got; sum+=got; max-=got; }
218 return sum;
219 }
220
221 /* --- */
222
iter_write_sub(char const * beg,slen_t len,void * data)223 void GenBuffer::Writable::iter_write_sub(char const*beg, slen_t len, void *data) {
224 if (len!=0) static_cast<GenBuffer::Writable*>(data)->vi_write(beg, len);
225 }
226
operator <<(char const * cstr)227 GenBuffer::Writable& GenBuffer::Writable::operator <<(char const*cstr) {
228 assert(cstr!=0);
229 vi_write(cstr, strlen(cstr));
230 return*this;
231 }
232
operator <<(void const * ptr)233 GenBuffer::Writable& GenBuffer::Writable::operator <<(void const*ptr) {
234 if (ptr==0) vi_write("(null)", 6);
235 else {
236 vi_write("(0d", 3);
237 /* Imp: hexadecimal pointer output */
238 *this << (PTS_INTP_T)ptr;
239 vi_putcc(')');
240 }
241 return*this;
242 }
243
write_num(unsigned long n,unsigned zdigits)244 void GenBuffer::Writable::write_num(unsigned long n, unsigned zdigits) {
245 if (zdigits>=sizeof(numtmp)) {
246 memset(numtmp,'0',sizeof(numtmp));
247 while (zdigits>2*sizeof(numtmp)) {
248 vi_write(numtmp, sizeof(numtmp));
249 zdigits-=sizeof(numtmp);
250 }
251 vi_write(numtmp, zdigits-sizeof(numtmp));
252 zdigits=sizeof(numtmp);
253 }
254 char *j=numtmp+sizeof(numtmp), *jend=j-zdigits;
255 while (j!=jend) { *--j='0'+n%10; n/=10; }
256 vi_write(j, zdigits);
257 }
258 #if HAVE_LONG_LONG && NEED_LONG_LONG
write_num(unsigned PTS_CFG_LONGEST n,unsigned zdigits)259 void GenBuffer::Writable::write_num(unsigned PTS_CFG_LONGEST n, unsigned zdigits) {
260 if (zdigits>=sizeof(numtmp)) {
261 memset(numtmp,'0',sizeof(numtmp));
262 while (zdigits>2*sizeof(numtmp)) {
263 vi_write(numtmp, sizeof(numtmp));
264 zdigits-=sizeof(numtmp);
265 }
266 vi_write(numtmp, zdigits-sizeof(numtmp));
267 zdigits=sizeof(numtmp);
268 }
269 char *j=numtmp+sizeof(numtmp), *jend=j-zdigits;
270 while (j!=jend) { *--j='0'+n%10; n/=10; }
271 vi_write(j, zdigits);
272 }
273 #endif
274
write_num(unsigned long n)275 void GenBuffer::Writable::write_num(unsigned long n) {
276 char *j=numtmp+sizeof(numtmp);
277 do *--j='0'+n%10; while ((n/=10)!=0);
278 vi_write(j, numtmp+sizeof(numtmp)-j);
279 }
write_num(signed long nn)280 void GenBuffer::Writable::write_num(signed long nn) {
281 register unsigned long n;
282 char *j=numtmp+sizeof(numtmp);
283 if (nn<0) {
284 n=-nn; do *--j='0'+n%10; while ((n/=10)!=0);
285 *--j='-';
286 } else {
287 n=nn; do *--j='0'+n%10; while ((n/=10)!=0);
288 }
289 vi_write(j, numtmp+sizeof(numtmp)-j);
290 }
291 #if HAVE_LONG_LONG && NEED_LONG_LONG
write_num(unsigned PTS_CFG_LONGEST n)292 void GenBuffer::Writable::write_num(unsigned PTS_CFG_LONGEST n) {
293 char *j=numtmp+sizeof(numtmp);
294 do *--j='0'+n%10; while ((n/=10)!=0);
295 vi_write(j, numtmp+sizeof(numtmp)-j);
296 }
write_num(signed PTS_CFG_LONGEST nn)297 void GenBuffer::Writable::write_num(signed PTS_CFG_LONGEST nn) {
298 register unsigned PTS_CFG_LONGEST n;
299 char *j=numtmp+sizeof(numtmp);
300 if (nn<0) {
301 n=-nn; do *--j='0'+n%10; while ((n/=10)!=0);
302 *--j='-';
303 } else {
304 n=nn;
305 do *--j='0'+n%10; while ((n/=10)!=0);
306 }
307 vi_write(j, numtmp+sizeof(numtmp)-j);
308 }
309 #endif
310
vformat(slen_t n,char const * fmt,va_list ap)311 GenBuffer::Writable& GenBuffer::Writable::vformat(slen_t n, char const *fmt, va_list ap) {
312 SimBuffer::B buf;
313 buf.vformat(n, fmt, ap);
314 vi_write(buf(), buf.getLength());
315 return*this;
316 }
vformat(char const * fmt,va_list ap)317 GenBuffer::Writable& GenBuffer::Writable::vformat(char const *fmt, va_list ap) {
318 SimBuffer::B buf;
319 buf.vformat(fmt, ap);
320 vi_write(buf(), buf.getLength());
321 return*this;
322 }
format(slen_t n,char const * fmt,...)323 GenBuffer::Writable& GenBuffer::Writable::format(slen_t n, char const *fmt, ...) {
324 va_list ap;
325 PTS_va_start(ap, fmt);
326 vformat(n, fmt, ap);
327 va_end(ap);
328 return *this;
329 }
format(char const * fmt,...)330 GenBuffer::Writable& GenBuffer::Writable::format(char const *fmt, ...) {
331 va_list ap;
332 PTS_va_start(ap, fmt);
333 vformat(fmt, ap);
334 va_end(ap);
335 return *this;
336 }
337
338 /* --- */
339
copyRange(char * to,slen_t cfrom,slen_t clen) const340 slen_t SimBuffer::Flat::copyRange(char *to, slen_t cfrom, slen_t clen) const {
341 if (cfrom<len) { /* added padding BUGFIX at Fri Mar 7 20:30:07 CET 2003 */
342 slen_t dlen;
343 memcpy(to, beg+cfrom, dlen=cfrom+clen>len ? len-cfrom : clen);
344 to+=dlen;
345 }
346 while (clen--!=0) *to++='\0'; /* padding */
347 return len;
348 }
349
findLast(char const c) const350 slen_t SimBuffer::Flat::findLast(char const c) const {
351 char const*p;
352 for (p=beg+len;p>=beg;p--) if (*p==c) return p-beg;
353 return len;
354 }
355
findFirst(char const c) const356 slen_t SimBuffer::Flat::findFirst(char const c) const {
357 char const*p, *end=beg+len;
358 for (p=beg;p!=end;p++) if (*p==c) return p-beg;
359 return len;
360 }
361
findFirst(char const * s,slen_t slen) const362 slen_t SimBuffer::Flat::findFirst(char const* s, slen_t slen) const {
363 if (slen==0) return 0; /* found */
364 if (slen>len) return len; /* not found */
365 char const c=*s;
366 char const*p=beg, *end=beg+len-slen+1;
367 if (slen==1) {
368 for (;p!=end;p++) if (*p==c) return p-beg;
369 } else {
370 for (;p!=end;p++) if (*p==c && 0==memcmp(p,s,slen)) return p-beg;
371 }
372 return len;
373 }
374
cmpFlat(SimBuffer::Flat const & s2) const375 int SimBuffer::Flat::cmpFlat(SimBuffer::Flat const& s2) const {
376 return memcmp(beg, s2.beg, len<s2.len?len:s2.len) || (len>s2.len)-(len<s2.len);
377 }
378
cmp(char const * s2beg,slen_t s2len) const379 int SimBuffer::Flat::cmp(char const* s2beg, slen_t s2len) const {
380 return memcmp(beg, s2beg, len<s2len?len:s2len) || (len>s2len)-(len<s2len);
381 }
382
383 /* --- */
384
Static(char const * cstr)385 SimBuffer::Static::Static(char const*cstr) { beg=cstr; len=strlen(cstr); }
386
387 /* --- */
388
vi_write(char const * str,slen_t slen)389 void SimBuffer::Appendable::vi_write(char const*str, slen_t slen) {
390 if (slen>0) {
391 char *p=vi_mkend(slen);
392 memcpy(p, str, slen);
393 }
394 }
prepend(char const * str,slen_t slen)395 void SimBuffer::Appendable::prepend(char const*str, slen_t slen) {
396 if (slen>0) {
397 char *p=vi_mkbeg(slen);
398 memcpy(p, str, slen);
399 }
400 }
401
402 /* inlined.
403 void SimBuffer::Appendable::vi_putcc(char c) {
404 vi_mkend(1)[0]=c;
405 }*/
406
407 /* --- */
408
~Linked()409 SimBuffer::Linked::~Linked() {
410 Node *n;
411 while (first!=0) {
412 if (first->beg!=(char*)(first+1)) delete [] first->beg;
413 n=first->next; delete [] first; first=n;
414 }
415 }
416
getLength() const417 slen_t SimBuffer::Linked::getLength() const {
418 slen_t len=0;
419 Node *n=first;
420 while (n!=0) { len+=n->len; n=n->next; }
421 return len;
422 }
423
Linked(GenBuffer const & other)424 SimBuffer::Linked::Linked(GenBuffer const& other) {
425 slen_t len=other.getLength();
426 Node *n=static_cast<Node*>(static_cast<void*>(new char[sizeof(Node)+len]));
427 n->beg=(char*)(n+1);
428 other.copyRange(n->beg, 0, len);
429 n->len=len;
430 n->next=0;
431 first=last=n;
432 }
Linked(char const * str)433 SimBuffer::Linked::Linked(char const*str) {
434 slen_t len=strlen(str);
435 Node *n=static_cast<Node*>(static_cast<void*>(new char[sizeof(Node)+len]));
436 n->beg=(char*)(n+1);
437 memcpy(n->beg, str, len);
438 n->len=len;
439 n->next=0;
440 first=last=n;
441 }
operator =(GenBuffer const & other)442 SimBuffer::Linked& SimBuffer::Linked::operator=(GenBuffer const& other) {
443 slen_t len=other.getLength();
444 Node *n=static_cast<Node*>(static_cast<void*>(new char[sizeof(Node)+len]));
445 n->beg=(char*)(n+1);
446 other.copyRange(n->beg, 0, len);
447 n->len=len;
448 n->next=0;
449 first=last=n;
450 return *this;
451 }
operator =(SimBuffer::Linked const & other)452 SimBuffer::Linked& SimBuffer::Linked::operator=(SimBuffer::Linked const& other) {
453 /* Imp: avoid code repeat */
454 slen_t len=other.getLength();
455 Node *n=static_cast<Node*>(static_cast<void*>(new char[sizeof(Node)+len]));
456 n->beg=(char*)(n+1);
457 other.copyRange(n->beg, 0, len);
458 n->len=len;
459 n->next=0;
460 first=last=n;
461 return *this;
462 }
463
each_sub(GenBuffer::block_sub_t block,void * data) const464 void SimBuffer::Linked::each_sub(GenBuffer::block_sub_t block, void *data) const {
465 Node *n=first;
466 while (n!=0) { block(n->beg, n->len, data); n=n->next; }
467 }
first_sub(Sub & sub) const468 void SimBuffer::Linked::first_sub(Sub &sub) const {
469 if (first!=0) {
470 sub.data=first->next;
471 sub.beg=first->beg;
472 sub.len=first->len;
473 } else sub.len=0;
474 }
next_sub(Sub & sub) const475 void SimBuffer::Linked::next_sub(Sub &sub) const {
476 if (sub.data!=0) {
477 sub.beg=static_cast<Node*>(sub.data)->beg;
478 sub.len=static_cast<Node*>(sub.data)->len;
479 sub.data=static_cast<Node*>(sub.data)->next;
480 } else sub.len=0;
481 }
vi_mkend(slen_t len)482 char *SimBuffer::Linked::vi_mkend(slen_t len) {
483 Node *n=static_cast<Node*>(static_cast<void*>(new char[sizeof(Node)+len]));
484 n->beg=(char*)(n+1);
485 n->len=len;
486 n->next=0;
487 if (last==0) first=last=n;
488 else { last->next=n; last=n; }
489 return n->beg;
490 }
vi_mkbeg(slen_t len)491 char *SimBuffer::Linked::vi_mkbeg(slen_t len) {
492 Node *n=static_cast<Node*>(static_cast<void*>(new char[sizeof(Node)+len]));
493 n->beg=(char*)(n+1);
494 n->len=len;
495 n->next=first;
496 first=n;
497 if (last==0) last=n;
498 return n->beg;
499 }
500
501 /* --- */
502
operator =(GenBuffer const & s2)503 SimBuffer::Resizable& SimBuffer::Resizable::operator=(GenBuffer const& s2) {
504 vi_grow2(0, s2.getLength()-getLength(), 0, 0);
505 assert(getLength()==s2.getLength());
506
507 Sub u1, u2;
508 slen_t m;
509 first_sub(u1);
510 s2.first_sub(u2);
511 assert(!((u1.len==0) ^ (u2.len==0))); /* s1 and s2 end in the same time */
512 while (u1.len!=0) {
513 m=(u1.len<u2.len)?u1.len:u2.len;
514 memcpy(const_cast<char*>(u1.beg), u2.beg, m);
515 if (0==(u1.len-=m)) next_sub(u1); else u1.beg+=m;
516 if (0==(u2.len-=m)) s2.next_sub(u2); else u2.beg+=m;
517 assert(!((u1.len==0) ^ (u2.len==0))); /* s1 and s2 end in the same time */
518 }
519 return*this;
520 }
521
522 //void SimBuffer::Resizable::clear() { /* Inlined. */
523 // vi_grow2(0, -getLength(), 0, 0);
524 //}
525
keepLeft(slen_t howmuch)526 void SimBuffer::Resizable::keepLeft(slen_t howmuch) {
527 slen_t len=getLength();
528 vi_grow2(0, len>howmuch?0-len+howmuch:-(slendiff_t)len, 0, 0);
529 /* ^^^ BUGFIX at Tue Jun 11 19:57:03 CEST 2002 */
530 }
keepRight(slen_t howmuch)531 void SimBuffer::Resizable::keepRight(slen_t howmuch) {
532 slen_t len=getLength();
533 vi_grow2(len>howmuch?0-len+howmuch:-(slendiff_t)len, 0, 0, 0);
534 /* ^^^ BUGFIX at Tue Jun 11 19:57:03 CEST 2002 */
535 }
keepSubstr(slen_t from_offset,slen_t slen)536 void SimBuffer::Resizable::keepSubstr(slen_t from_offset, slen_t slen) {
537 slen_t len=getLength();
538 if (from_offset>=len) vi_grow2(0, -(slendiff_t)len, 0, 0);
539 else if (from_offset+slen>=len) vi_grow2(-(slendiff_t)from_offset, 0, 0, 0);
540 else vi_grow2(-(slendiff_t)from_offset, len-from_offset-slen, 0, 0);
541 }
542
543 /* --- */
544
vi_grow2(slendiff_t left,slendiff_t right,char ** lbeg,char ** rbeg)545 void SimBuffer::B::vi_grow2(slendiff_t left, slendiff_t right, char **lbeg, char **rbeg) {
546 assert(alloced>=len);
547 char *origbeg=const_cast<char*>(beg);
548 if (left<0) { if (len<=(slen_t)-left) len=0; else beg-=left; left=0; } /* ! */
549 if (right<0) { if (len<=(slen_t)-right)len=0; else len+=right;right=0; }
550 /* ^^^ BUGFIX at Tue Jun 11 16:07:56 CEST 2002 */
551 assert(left>=0);
552 assert(right>=0);
553 slen_t newlen=left+right+len;
554 assert(newlen>=len);
555 char *newbeg;
556 assert(alloced>=sizeof(small)/1);
557 if (beg==small) {
558 assert(alloced==sizeof(small));
559 if (newlen>sizeof(small)) {
560 assert(newlen>len);
561 newbeg=new char[alloced=2*newlen];
562 memcpy(newbeg+left, beg, len);
563 beg=newbeg;
564 }
565 } else { /* beg!=small */
566 // assert(len>=alloced/2); /* -- may not always be true, especially not after appending a `long' */
567 if (newlen<alloced/2) { /* shrink */
568 // assert(newlen<=len); /* filled-expectations are true _after_ vi_grow2, not before */
569 if (newlen>sizeof(small)) {
570 newbeg=new char[alloced=newlen];
571 memcpy(newbeg+left, beg, len);
572 } else {
573 memcpy((newbeg=small)+left, beg, len);
574 delete [] origbeg;
575 alloced=sizeof(small);
576 }
577 beg=newbeg;
578 } else if (newlen>alloced) { /* grow */
579 assert(newlen>sizeof(small));
580 assert(newlen>len);
581 newbeg=new char[alloced=2*newlen];
582 memcpy(newbeg+left, beg, len);
583 delete [] origbeg;
584 beg=newbeg;
585 } else if (beg!=origbeg) { /* called with negative `left' @param */
586 assert(left==0);
587 memmove(origbeg, beg, len); /* Slow, may move the whole buffer. */
588 }
589 }
590 // fprintf(stderr, "newlen=%u\n", newlen);
591 len=newlen;
592 if (lbeg) *lbeg=const_cast<char*>(beg);
593 if (rbeg) *rbeg=const_cast<char*>(beg+newlen-right);
594 assert(alloced==sizeof(small) || (alloced>sizeof(small) && len>=alloced/2));
595 assert(alloced>=len);
596 }
597
B(char const * cstr)598 SimBuffer::B::B(char const* cstr): alloced(sizeof(small)) {
599 beg=small;
600 slen_t len_=strlen(cstr);
601 if (len_>sizeof(small)) { len=0; vi_grow2(0, len_, 0, 0); }
602 else len=len_;
603 assert(len==len_);
604 memcpy(const_cast<char*>(beg), cstr, len);
605 }
606
B(char const * str,slen_t len_)607 SimBuffer::B::B(char const* str, slen_t len_): alloced(sizeof(small)) {
608 beg=small;
609 if (len_>sizeof(small)) { len=0; vi_grow2(0, len_, 0, 0); }
610 else len=len_;
611 assert(len==len_);
612 memcpy(const_cast<char*>(beg), str, len);
613 }
614
B(SimBuffer::B const & other)615 SimBuffer::B::B(SimBuffer::B const& other): GenBuffer(), SimBuffer::Resizable(), SimBuffer::Flat(), alloced(sizeof(small)) {
616 beg=small;
617 if (other.len>sizeof(small)) { len=0; vi_grow2(0, other.len, 0, 0); }
618 else len=other.len;
619 assert(len==other.len);
620 memcpy(const_cast<char*>(beg), other.beg, len);
621 }
622
B(SimBuffer::Flat const & other)623 SimBuffer::B::B(SimBuffer::Flat const& other): alloced(sizeof(small)) {
624 beg=small;
625 if (other.len>sizeof(small)) { len=0; vi_grow2(0, other.len, 0, 0); }
626 else len=other.len;
627 assert(len==other.len);
628 memcpy(const_cast<char*>(beg), other.beg, len);
629 }
630
B(SimBuffer::Flat const & other,int)631 SimBuffer::B::B(SimBuffer::Flat const& other,int): alloced(sizeof(small)) {
632 beg=small;
633 if (other.len>=sizeof(small)) { len=0; vi_grow2(0, other.len+1, 0, 0); len--; }
634 else len=other.len;
635 assert(len==other.len);
636 memcpy(const_cast<char*>(beg), other.beg, len);
637 const_cast<char*>(beg)[len]='\0';
638 }
639
B(SimBuffer::Flat const & other,slen_t from_offset,slen_t len_)640 SimBuffer::B::B(SimBuffer::Flat const& other, slen_t from_offset, slen_t len_): alloced(sizeof(small)) {
641 /* substr */
642 beg=small;
643 if (from_offset<other.len) {
644 if (from_offset+len_>other.len) len_=other.len-from_offset;
645 if (len_>sizeof(small)) { len=0; vi_grow2(0, len_, 0, 0); }
646 else len=len_;
647 assert(len==len_);
648 memcpy(const_cast<char*>(beg), other.beg+from_offset, len);
649 } else len=0;
650 }
651
B(GenBuffer const & other)652 SimBuffer::B::B(GenBuffer const& other): alloced(sizeof(small)) {
653 slen_t len_=other.getLength();
654 beg=small;
655 if (len_>sizeof(small)) { len=0; vi_grow2(0, len_, 0, 0); }
656 else len=len_;
657 assert(len==len_);
658 other.copyRange(const_cast<char*>(beg), 0, len_);
659 }
660
661 /** Constructor: copy (consume) data from a readable stream. */
B(GenBuffer::Readable & other)662 SimBuffer::B::B(GenBuffer::Readable &other): alloced(sizeof(small)) {
663 beg=small;
664 len=0;
665 #if 000
666 operator <<(other);
667 #else
668 B_append(other);
669 #endif
670 }
671
B(char const * as,slen_t al,char const * bs,slen_t bl)672 SimBuffer::B::B(char const* as,slen_t al, char const* bs,slen_t bl): alloced(sizeof(small)) {
673 slen_t len_=al+bl;
674 beg=small;
675 if (len_>sizeof(small)) { len=0; vi_grow2(0, len_, 0, 0); }
676 else len=len_;
677 assert(len==len_);
678 memcpy(const_cast<char*>(beg), as, al);
679 memcpy(const_cast<char*>(beg)+al, bs, bl);
680 }
681
B(char const * as,slen_t al,char const * bs,slen_t bl,int)682 SimBuffer::B::B(char const* as,slen_t al, char const* bs,slen_t bl,int): alloced(sizeof(small)) {
683 slen_t len_=al+bl;
684 beg=small;
685 if (len_>=sizeof(small)) { len=0; vi_grow2(0, len_+1, 0, 0); len--; }
686 else len=len_;
687 assert(len==len_);
688 memcpy(const_cast<char*>(beg), as, al);
689 memcpy(const_cast<char*>(beg)+al, bs, bl);
690 const_cast<char*>(beg)[al+bl]='\0';
691 }
692
B(GenBuffer const & a,GenBuffer const & b)693 SimBuffer::B::B(GenBuffer const& a, GenBuffer const& b): alloced(sizeof(small)) {
694 slen_t al=a.getLength();
695 slen_t bl=b.getLength();
696 slen_t len_=al+bl;
697 beg=small;
698 if (len_>sizeof(small)) { len=0; vi_grow2(0, len_, 0, 0); }
699 else len=len_;
700 assert(len==len_);
701 a.copyRange(const_cast<char*>(beg), 0, al);
702 b.copyRange(const_cast<char*>(beg)+al, 0, bl);
703 }
704
B(GenBuffer const & a,GenBuffer const & b,GenBuffer const & c)705 SimBuffer::B::B(GenBuffer const& a, GenBuffer const& b, GenBuffer const& c): alloced(sizeof(small)) {
706 slen_t al=a.getLength();
707 slen_t bl=b.getLength();
708 slen_t cl=c.getLength();
709 slen_t len_=al+bl;
710 beg=small;
711 if (len_>sizeof(small)) { len=0; vi_grow2(0, len_, 0, 0); }
712 else len=len_;
713 assert(len==len_);
714 a.copyRange(const_cast<char*>(beg), 0, al);
715 b.copyRange(const_cast<char*>(beg)+al, 0, bl);
716 c.copyRange(const_cast<char*>(beg)+al+bl, 0, cl);
717 }
718
B(char const * as,slen_t al,char const * bs,slen_t bl,char const * cs,slen_t cl)719 SimBuffer::B::B(char const* as,slen_t al, char const* bs,slen_t bl, char const* cs,slen_t cl): alloced(sizeof(small)) {
720 slen_t len_=al+bl+cl;
721 beg=small;
722 if (len_>sizeof(small)) { len=0; vi_grow2(0, len_, 0, 0); }
723 else len=len_;
724 assert(len==len_);
725 memcpy(const_cast<char*>(beg), as, al);
726 memcpy(const_cast<char*>(beg)+al, bs, bl);
727 memcpy(const_cast<char*>(beg)+al+bl, cs, cl);
728 }
729
B(Flat const & b,char const * cs)730 SimBuffer::B::B(Flat const&b, char const*cs): alloced(sizeof(small)) {
731 slen_t cl=strlen(cs);
732 slen_t len_=b.len+cl;
733 beg=small;
734 if (len_>sizeof(small)) { len=0; vi_grow2(0, len_, 0, 0); }
735 else len=len_;
736 assert(len==len_);
737 memcpy(const_cast<char*>(beg), b.beg, b.len);
738 memcpy(const_cast<char*>(beg)+b.len, cs, cl);
739 }
740
B(char const * as,Flat const & b,char const * cs)741 SimBuffer::B::B(char const*as, Flat const&b, char const*cs): alloced(sizeof(small)) {
742 slen_t al=strlen(as);
743 slen_t cl=strlen(cs);
744 slen_t len_=al+b.len+cl;
745 beg=small;
746 if (len_>sizeof(small)) { len=0; vi_grow2(0, len_, 0, 0); }
747 else len=len_;
748 assert(len==len_);
749 memcpy(const_cast<char*>(beg), as, al);
750 memcpy(const_cast<char*>(beg)+al, b.beg, b.len);
751 memcpy(const_cast<char*>(beg)+al+b.len, cs, cl);
752 }
753
754 /* SimBuffer::B& operator<<(SimBuffer::B& self, GenBuffer::Readable &stream); */
B_append(GenBuffer::Readable & stream)755 SimBuffer::B& SimBuffer::B::B_append(GenBuffer::Readable &stream) {
756 assert(alloced>=len);
757 slen_t oldlen, ask;
758 ask=stream.vi_availh();
759 if (ask>0) { oldlen=len; vi_grow2(0, ask+1, 0, 0); len=oldlen; }
760 if (alloced!=len) len+=stream.readFill(const_cast<char*>(beg+len), alloced-len);
761 while (alloced==len) { /* more data to be read */
762 oldlen=len; vi_grow2(0, alloced, 0, 0); len=oldlen;
763 stream.readFill(const_cast<char*>(beg+len), alloced-len);
764 }
765 return *this;
766 }
767
term0()768 SimBuffer::B& SimBuffer::B::term0() {
769 if (len==alloced) { vi_grow2(0,1,0,0); len--; }
770 const_cast<char*>(beg)[len]='\0';
771 return *this;
772 }
773
grow_set0_by(slendiff_t lendiff)774 void SimBuffer::B::grow_set0_by(slendiff_t lendiff) {
775 char *rbeg;
776 vi_grow2(0, lendiff, 0, &rbeg);
777 if (lendiff>0) memset(rbeg, '\0', lendiff);
778 }
779
getAt(slen_t idx)780 char SimBuffer::B::getAt(slen_t idx) {
781 if (idx<len) return beg[idx];
782 /* grow_set0_by(idx+1-len); */
783 char *rbeg;
784 vi_grow2(0, idx-len+1, 0, &rbeg);
785 memset(rbeg, '\0', idx-len+1);
786 return '\0';
787 }
788
operator =(SimBuffer::Flat const & other)789 SimBuffer::B& SimBuffer::B::operator=(SimBuffer::Flat const& other) {
790 if (&other!=this) {
791 len=0;
792 vi_grow2(0, other.len, 0, 0);
793 memcpy(const_cast<char*>(beg), other.beg, len);
794 }
795 return*this;
796 }
797
operator =(SimBuffer::B const & other)798 SimBuffer::B& SimBuffer::B::operator=(SimBuffer::B const& other) {
799 if (&other!=this) {
800 len=0;
801 vi_grow2(0, other.len, 0, 0);
802 memcpy(const_cast<char*>(beg), other.beg, len);
803 }
804 return*this;
805 }
806
operator =(char const * cstr)807 SimBuffer::B& SimBuffer::B::operator=(char const* cstr) {
808 slen_t slen=strlen(cstr);
809 len=0;
810 vi_grow2(0, slen, 0, 0);
811 memcpy(const_cast<char*>(beg), cstr, slen);
812 return*this;
813 }
814
substr(slen_t first,slen_t howmuch) const815 SimBuffer::B SimBuffer::B::substr(slen_t first, slen_t howmuch) const {
816 return SimBuffer::B(*this, first, howmuch);
817 }
substr(slen_t first) const818 SimBuffer::B SimBuffer::B::substr(slen_t first) const {
819 /* Actually, this will probably be shorter than end-begin */
820 return SimBuffer::B(*this, first, len);
821 }
right(slen_t howmuch) const822 SimBuffer::B SimBuffer::B::right(slen_t howmuch) const {
823 return SimBuffer::B(*this, len<=howmuch?0:len-howmuch, howmuch);
824 }
left(slen_t howmuch) const825 SimBuffer::B SimBuffer::B::left(slen_t howmuch) const {
826 return SimBuffer::B(*this, 0, howmuch);
827 }
828
829 #if 0
830 void SimBuffer::B::append(char const*s, const slen_t len_) {
831 char *rbeg;
832 vi_grow2(0, len_, 0, &rbeg);
833 memcpy(rbeg, s, len_);
834 }
835 #endif
836
operator +(const SimBuffer::Flat & s1,const SimBuffer::Flat & s2)837 SimBuffer::B operator+(const SimBuffer::Flat& s1, const SimBuffer::Flat& s2) {
838 return SimBuffer::B(s1.beg, s1.len, s2.beg, s2.len);
839 }
operator +(const char * s1,const SimBuffer::Flat & s2)840 SimBuffer::B operator+(const char *s1, const SimBuffer::Flat& s2) {
841 return SimBuffer::B(s1, strlen(s1), s2.beg, s2.len);
842 }
operator +(const SimBuffer::Flat & s1,const char * s2)843 SimBuffer::B operator+(const SimBuffer::Flat& s1, const char *s2) {
844 return SimBuffer::B(s1.beg, s1.len, s2, strlen(s2));
845 }
846
operator <<(SimBuffer::Flat const & other)847 SimBuffer::B& SimBuffer::B::operator<<(SimBuffer::Flat const& other) {
848 char *d;
849 vi_grow2(0, other.len, 0, &d);
850 memcpy(d,other.beg,other.len);
851 return*this;
852 }
853
operator <<(char c)854 SimBuffer::B& SimBuffer::B::operator<<(char c) {
855 if (len==alloced) { vi_grow2(0, 1, 0, 0); const_cast<char*>(beg)[len-1]=c; }
856 else const_cast<char*>(beg)[len++]=c;
857 return*this;
858 }
operator <<(char const * s)859 SimBuffer::B& SimBuffer::B::operator<<(char const *s) {
860 char *d;
861 slen_t slen=strlen(s);
862 vi_grow2(0, slen, 0, &d);
863 memcpy(d,s,slen);
864 return*this;
865 }
vi_write(char const * str,slen_t slen)866 void SimBuffer::B::vi_write(char const*str, slen_t slen) {
867 if (slen>0) {
868 char *p; vi_grow2(0, slen, 0, &p);
869 memcpy(p, str, slen);
870 }
871 }
872
873 #define USGE(a,b) ((unsigned char)(a))>=((unsigned char)(b))
is_path(char const c)874 static inline bool is_path(char const c) {
875 return c=='-' || c=='.' || c=='_' || c=='/'
876 || USGE('z'-'a',c-'a')
877 || USGE('Z'-'A',c-'A')
878 || USGE('9'-'0',c-'0');
879 }
is_safe_c(char const c)880 static inline bool is_safe_c(char const c) {
881 return c!='\\' && c!='\'' && c!='\"' && USGE('~'-' ',c-' ');
882 }
is_safe_ps(char const c)883 static inline bool is_safe_ps(char const c) {
884 return c!='\\' && c!='(' && c!=')' && USGE('~'-' ',c-' ');
885 }
886
appendDump(const char c,bool dq)887 SimBuffer::B& SimBuffer::B::appendDump(const char c, bool dq) {
888 char t[7]; register char *p=t;
889 if (dq) *p++='\'';
890 if (is_path(c)) {
891 *p++=c;
892 } else {
893 *p++='\\';
894 *p++=('0'+((c>>6)&3));
895 *p++=('0'+((c>>3)&7));
896 *p++=('0'+(c&7));
897 }
898 if (dq) *p++='\'';
899 vi_write(t, p-t);
900 return*this;
901 }
902
903
appendDump(const SimBuffer::Flat & other,bool dq)904 SimBuffer::B& SimBuffer::B::appendDump(const SimBuffer::Flat &other, bool dq) {
905 slen_t rlen=dq?2:0;
906 register char c; register char const*p;
907 char const *pend; char *dst;
908 for (p=other.beg,pend=p+other.len; p!=pend; p++) rlen+=is_path(*p)?1:4;
909 vi_grow2(0, rlen, 0, &dst);
910 if (dq) *dst++='"';
911 for (p=other.beg,pend=p+other.len; p!=pend; p++) {
912 if (is_path(c=*p)) {
913 *dst++=c;
914 } else {
915 *dst++='\\';
916 *dst++=('0'+((c>>6)&3));
917 *dst++=('0'+((c>>3)&7));
918 *dst++=('0'+(c&7));
919 }
920 }
921 if (dq) *dst++='"';
922 assert(dst==end_());
923 return*this;
924 }
925
appendNpmq(const SimBuffer::Flat & other,bool dq)926 SimBuffer::B& SimBuffer::B::appendNpmq(const SimBuffer::Flat &other, bool dq) {
927 slen_t rlen=dq?2:0;
928 register char c; register char const*p;
929 char const *pend; char *dst;
930 for (p=other.beg,pend=p+other.len; p!=pend; p++) rlen+=is_path(*p)?1:2;
931 vi_grow2(0, rlen, 0, &dst);
932 if (dq) *dst++='"';
933 for (p=other.beg,pend=p+other.len; p!=pend; p++) {
934 if (is_path(c=*p)) {
935 *dst++=c;
936 } else {
937 *dst++='\\';
938 *dst++=c;
939 }
940 }
941 if (dq) *dst++='"';
942 assert(dst==end_());
943 return*this;
944 }
945
appendDumpC(const SimBuffer::Flat & other,bool dq)946 SimBuffer::B& SimBuffer::B::appendDumpC (const SimBuffer::Flat &other, bool dq) {
947 slen_t rlen=dq?2:0;
948 register char c; register char const*p;
949 char const *pend; char *dst;
950 for (p=other.beg,pend=p+other.len; p!=pend; p++) rlen+=is_safe_c(*p)?1:4;
951 vi_grow2(0, rlen, 0, &dst);
952 if (dq) *dst++='"';
953 for (p=other.beg,pend=p+other.len; p!=pend; p++) {
954 if (is_safe_c(c=*p)) {
955 *dst++=c;
956 } else {
957 *dst++='\\';
958 *dst++=('0'+((c>>6)&3));
959 *dst++=('0'+((c>>3)&7));
960 *dst++=('0'+(c&7));
961 }
962 }
963 if (dq) *dst++='"';
964 assert(dst==end_());
965 return*this;
966 }
967
appendFnq(const SimBuffer::Flat & other,bool preminus)968 SimBuffer::B& SimBuffer::B::appendFnq(const SimBuffer::Flat &other, bool preminus) {
969 slen_t rlen=0;
970 register char c; register char const*p;
971 char const *pend; char *dst;
972 if (OS_COTY==COTY_WINNT || OS_COTY==COTY_WIN9X) {
973 for (p=other.beg,pend=p+other.len; p!=pend; p++) {
974 if ('\0'==(c=*p) || c=='"') break;
975 rlen++;
976 }
977 if (preminus && rlen!=0 && other.beg[0]=='-') rlen+=2; /* .\ */
978 vi_grow2(0, rlen+2, 0, &dst);
979 *dst++='"'; /* Dat: "ab"c" ""def" is perfectly legal and parses to: `abc def' */
980 p=other.beg;
981 if (preminus && other.beg[0]=='-') { *dst++='.'; *dst++='\\'; }
982 for (p=other.beg,pend=p+other.len; p!=pend; p++) {
983 if ('\0'==(c=*p) || c=='"') break;
984 *dst++=c;
985 }
986 *dst++='"';
987 } else { /* Everything else is treated as UNIX */
988 for (p=other.beg,pend=p+other.len; p!=pend; p++) {
989 if ('\0'==(c=*p)) break;
990 rlen+=is_path(c)?1: c=='\n'?3:2;
991 }
992 if (preminus && rlen!=0 && other.beg[0]=='-') rlen+=2; /* ./ */
993 vi_grow2(0, rlen, 0, &dst);
994 if (preminus && other.beg[0]=='-') { *dst++='.'; *dst++='/'; }
995 for (p=other.beg,pend=p+other.len; p!=pend; p++) {
996 if ('\0'==(c=*p)) break;
997 if (is_path(c)) *dst++=c;
998 else if (c=='\n') { *dst++='"'; *dst++='\n'; *dst++='"'; }
999 else { *dst++='\\'; *dst++=c; }
1000 }
1001 } /* IF OS_COTY... */
1002 assert(dst==end_());
1003 return*this;
1004 }
1005
appendDumpPS(const SimBuffer::Flat & other,bool dq)1006 SimBuffer::B& SimBuffer::B::appendDumpPS (const SimBuffer::Flat &other, bool dq) {
1007 slen_t rlen=dq?2:0;
1008 register char c; register char const*p;
1009 char const *pend;
1010 for (p=other.beg,pend=p+other.len; p!=pend; p++) rlen+=is_safe_ps(*p)?1:4;
1011 char *dst; vi_grow2(0, rlen, 0, &dst);
1012 if (dq) *dst++='(';
1013 for (p=other.beg,pend=p+other.len; p!=pend; p++) {
1014 if (is_safe_ps(c=*p)) {
1015 *dst++=c;
1016 } else {
1017 *dst++='\\';
1018 *dst++=('0'+((c>>6)&3));
1019 *dst++=('0'+((c>>3)&7));
1020 *dst++=('0'+(c&7));
1021 }
1022 }
1023 if (dq) *dst++=')';
1024 assert(dst==end_());
1025 return*this;
1026 }
1027
appendHppq(const SimBuffer::Flat & other)1028 SimBuffer::B& SimBuffer::B::appendHppq(const SimBuffer::Flat &other) {
1029 vi_grow2(0, other.len, 0, 0);
1030 char *pend=const_cast<char*>(beg)+len;
1031 register char c, *p=pend-other.len;
1032 memcpy(p, other.beg, other.len);
1033 for (;p!=pend;pend++) {
1034 c=*p;
1035 *p++=(
1036 (c>='a' && c<='z') ? (char)(c-'a'+'A') :
1037 (c>='A' && c<='Z') ? c :
1038 '_'
1039 );
1040 }
1041 return *this;
1042 }
1043
appendUnslash(const SimBuffer::Flat & other,int iniq)1044 SimBuffer::B& SimBuffer::B::appendUnslash(const SimBuffer::Flat &other, int iniq) {
1045 slen_t rlen=0;
1046 slen_t left=other.len;
1047 register char c; register char const*p=other.beg;
1048 if (iniq<=256) {
1049 if (left<2 || *p!=iniq || p[left-1]!=iniq) return*this;
1050 /* ^^^ return empty string */
1051 p++; left-=2;
1052 }
1053 while (0!=left) { /* Calculate lengths */
1054 c=*p++;
1055 if (c!='\\' || left==1) { rlen++; left--; continue; }
1056 c=*p++;
1057 if (c>='0' && c<='7') {
1058 rlen++;
1059 if (left>=3 && p[0]>='0' && p[0]<='7') {
1060 if (left>=4 && p[1]>='0' && p[1]<='7') { p+=2; left-=4; }
1061 else { p+=1; left-=3; }
1062 } else left-=2;
1063 } else if ((c=='x' || c=='X') && left>=3 && 16!=(hexc2n(p[0]))) {
1064 rlen++;
1065 if (left>=4 && 16!=(hexc2n(p[1]))) { p+=2; left-=4; }
1066 else { p+=1; left-=2; }
1067 } else if ((c=='c' || c=='C') && left>=4 && (p[0]=='-' || p[0]=='[')) {
1068 rlen++; left-=4; p+=2;
1069 } else if (c=='l' && left>=3) {
1070 rlen++; left-=3; p++;
1071 } else if (c=='u' && left>=3) {
1072 rlen++; left-=3; p++;
1073 } else if (c=='\n') {
1074 left-=2;
1075 } else { /* backslash is used for escaping a single char */
1076 rlen++; left-=2;
1077 }
1078 }
1079
1080 char *dst; vi_grow2(0, rlen, 0, &dst);
1081 unsigned tmp1, tmp2;
1082 left=other.len; p=other.beg;
1083 if (iniq<=256) {
1084 assert(!(left<2 || *p!=iniq || p[left-1]!=iniq));
1085 p++; left-=2;
1086 }
1087 while (0!=left) {
1088 c=*p++;
1089 if (c!='\\' || left==1) { *dst++=(c); left--; continue; }
1090 c=*p++;
1091 if (c>='0' && c<='7') {
1092 if (left>=3 && p[0]>='0' && p[0]<='7') {
1093 if (left>=4 && p[1]>='0' && p[1]<='7') {
1094 *dst++=((char)((c<<6)+(p[0]<<3)+p[1]-'0'*73));
1095 p+=2; left-=4;
1096 } else {
1097 *dst++=((char)((c<<3)+p[0]-'0'*9));
1098 p+=1; left-=3;
1099 }
1100 } else {
1101 *dst++=((char)(c-'0'));
1102 left-=2;
1103 }
1104 } else if ((c=='x' || c=='X') && left>=3 && 16!=(tmp1=hexc2n(p[0]))) {
1105 if (left>=4 && 16!=(tmp2=hexc2n(p[1]))) {
1106 *dst++=((char)((tmp1<<4)+tmp2));
1107 p+=2; left-=4;
1108 } else {
1109 *dst++=((char)tmp1);
1110 p+=1; left-=2;
1111 }
1112 } else if ((c=='c' || c=='C') && left>=4 && (p[0]=='-' || p[0]=='[')) {
1113 *dst++=((char)(p[1]>='a' && p[1]<='z' ? (p[1]+'A'-'a')^64 : p[1]^64));
1114 left-=4; p+=2;
1115 } else if (c=='l' && left>=3) {
1116 *dst++=((char)(p[0]>='A' && p[0]<='Z' ? p[0]+'a'-'A' : p[0]));
1117 left-=3; p++;
1118 } else if (c=='u' && left>=3) {
1119 *dst++=((char)(p[0]>='a' && p[0]<='z' ? p[0]+'A'-'a' : p[0]));
1120 left-=3; p++;
1121 } else if (c=='\n') {
1122 left-=2;
1123 } else { /* backslash is used for escaping a single char */
1124 if (c=='a') c=007; // \x07 (alarm bell)
1125 else if (c=='b') c=010; // \x08 (backspace) (_not_ alarm bell)
1126 else if (c=='e') c=033; // \x1B (escape)
1127 else if (c=='f') c=014; // \x0C (form feed)
1128 else if (c=='n') c=012; // \x0A (newline, line feed)
1129 else if (c=='r') c=015; // \x0D (carriage return)
1130 else if (c=='t') c=011; // \x09 (horizontal tab)
1131 else if (c=='v') c=013; // \x0B (vertical tab)
1132 *dst++=(c); left-=2;
1133 // if (0!=left--) { *dst++=(*p++); left--; } /* already escaped 1 */
1134 }
1135 }
1136 return*this;
1137 }
1138
space_pad_cpy(char * dst,char const * src,slen_t pad)1139 void SimBuffer::B::space_pad_cpy(char *dst, char const*src, slen_t pad) {
1140 while (pad!=0 && src[0]!='\0') { *dst++=*src++; pad--; }
1141 while (pad--!=0) *dst++=' ';
1142 }
1143
1144 // #include <stdio.h>
1145
substr_grow(slen_t first,slen_t oldmuch,slen_t newmuch)1146 char *SimBuffer::B::substr_grow(slen_t first, slen_t oldmuch, slen_t newmuch) {
1147 slen_t idx=first;
1148 if (first<len) {
1149 if (first+oldmuch>len) oldmuch=len-first;
1150 if (newmuch<oldmuch) { first+=newmuch; oldmuch-=newmuch; newmuch=0; }
1151 else if (newmuch>oldmuch) { first+=oldmuch; newmuch-=oldmuch; oldmuch=0; }
1152 else return const_cast<char*>(beg)+first;
1153 } else {
1154 len=first=idx=oldmuch=0;
1155 if (newmuch==0) { vi_grow2(0,0,0,0); return const_cast<char*>(beg); }
1156 }
1157 // fprintf(stderr, "newmuch=%u oldmuch=%u len=%u\n", newmuch, oldmuch, len);
1158 if (newmuch>0) {
1159 vi_grow2(0,newmuch,0,0);
1160 char *p=const_cast<char*>(beg)+first; /* after vi_grow2() */
1161 memmove(p+newmuch, p, len-first-newmuch);
1162 } else if (oldmuch>0) {
1163 char *p=const_cast<char*>(beg)+first; /* before vi_grow2() */
1164 memmove(p, p+oldmuch, len-first-oldmuch);
1165 vi_grow2(0,-(slendiff_t)oldmuch,0,0);
1166 } else assert(0);
1167 // fprintf(stderr, "len=%u oldmuch=%u\n", len, oldmuch);
1168 return const_cast<char*>(beg)+idx;
1169 }
1170
1171 /* --- Tue Jul 2 10:47:14 CEST 2002 */
1172
tolower_memcpy(char * dst,char const * s,slen_t slen)1173 void GenBuffer::tolower_memcpy(char *dst, char const*s, slen_t slen) {
1174 while (slen--!=0) *dst++=USGE('Z'-'A',*s-'A') ? *s+++'a'-'A' : *s++;
1175 }
toupper_memcpy(char * dst,char const * s,slen_t slen)1176 void GenBuffer::toupper_memcpy(char *dst, char const*s, slen_t slen) {
1177 while (slen--!=0) *dst++=USGE('z'-'a',*s-'a') ? *s+++'A'-'a' : *s++;
1178 }
1179
nocase_memcmp(char const * a,char const * s,slen_t slen)1180 int GenBuffer::nocase_memcmp(char const*a, char const *s, slen_t slen) {
1181 int i;
1182 while (slen--!=0) {
1183 i=(USGE('Z'-'A',*a-'A') ? *a+++'a'-'A' : *a++)
1184 -(USGE('Z'-'A',*s-'A') ? *s+++'a'-'A' : *s++);
1185 if (i>0) return 1;
1186 if (i<0) return -1;
1187 }
1188 return 0;
1189 }
nocase_strcmp(char const * a,char const * b)1190 int GenBuffer::nocase_strcmp(char const*a, char const*b) {
1191 slen_t alen=strlen(a), blen=strlen(b), min=alen<blen?alen:blen;
1192 int ret=nocase_memcmp(a, b, min);
1193 return ret!=0 || alen==blen ? ret : alen<blen ? -1 : 1;
1194 }
1195
parseBool(char const * s,slen_t slen)1196 bool GenBuffer::parseBool(char const *s, slen_t slen) {
1197 if (slen==0) return true;
1198 char c=s[0];
1199 if ((slen==2 && (c=='o' || c=='O') && (s[1]=='n' || s[1]=='N'))
1200 || (slen==3 && (c=='o' || c=='O') && (s[1]=='u' || s[1]=='U'))
1201 ) return true;
1202 /* on true yes ja igen oui enable 1 true vrai? right sure allowed
1203 * off false no nein nem non disable 0 false faux? wrong nope disallowed
1204 */
1205 return c!='f' && c!='n' && c!='d' && c!='w' && c!='0'
1206 && c!='F' && c!='N' && c!='D' && c!='W';
1207 }
1208
strbegins(char const * a,char const * with)1209 bool GenBuffer::strbegins(char const*a, char const *with) {
1210 while (*with!='\0') if (*a++!=*with++) return false;
1211 return true;
1212 }
1213
nocase_strbegins(char const * a,char const * with)1214 bool GenBuffer::nocase_strbegins(char const*a, char const *with) {
1215 while (*with!='\0')
1216 if ((USGE('Z'-'A',*a-'A') ? *a+++'a'-'A' : *a++)
1217 !=(USGE('Z'-'A',*with-'A') ? *with+++'a'-'A' : *with++)
1218 ) return false;
1219 return true;
1220 }
1221
1222 /* __END__ */
1223