Beschreibung
1
2
3
4 # include <stdlib.h>
5 # include <stddef.h>
6 # include <stdint.h>
7 # include <stdio.h>
8 # include <stdarg.h>
9 # include <wchar.h>
10 # include <string.h>
11
12
13 # define uchar unsigned char
14 # define ushort unsigned short
15 # define uint unsigned
16
17 typedef size_t CTLTYP;
18
19 # define MAXVAL (~(CTLTYP)0)
20 # define FILC1 '+'
21 # define FILC2 '.'
22 # define MAG1 19
23 # define MAG2 236
24 # define Xt sizeof(XT)
25 # define AL 16
26 # define MAXWID sizeof(long long)
27 # define CTLWID sizeof(CTLTYP)
28 # define CNTL (offsetof(STRING,buf))
29 # define OBJSZ(ne) ( ( (((ne)<Xt?Xt:(ne))+0)*(1) + CNTL + 2*AL-1)&~(AL-1) )
30
31 # define STRING_DEF(name,ne) \
32 unsigned char _Alignas(AL) name[ OBJSZ(ne) ]
33
34 # define STRING_INI(name) \
35 ((CTLTYP*)name)[0]= sizeof(name)-AL, \
36 stringlen(name)= 0, \
37 stringoff(name)= 0, \
38 stringswid(name)= 0, \
39 stringcntl(name)= 0, \
40 stringfilc(name)= FILC2, \
41 CNTLP(name)->text= 1, \
42 CNTLP(name)->ofil= 1, \
43 ((uchar*)name)[CTLWID+0]= MAG1, \
44 ((uchar*)name)[CTLWID+7]= MAG2, \
45 stringshft(name)= string_widthtoshift(1), \
46 stringwid( name)= 1
47
48 # define STRING_DuI(name,ne) \
49 STRING_DEF(name,ne); \
50 \
51 STRING_INI(name)
52
53 #if AL!=64 && AL!=32 && AL!=16 && AL!=8
54 # error "Falscher Wert in AL !"
55 #endif
56
57 typedef uchar CP1T;
58 typedef struct { uchar cp[ 2]; } CP2T;
59 typedef struct { uchar cp[ 4]; } CP4T;
60 typedef struct { uchar cp[ 8]; } CP8T;
61 typedef struct { uchar cp[16]; } CP16T;
62 typedef struct { uchar cp[32]; } CP32T;
63 typedef struct { uchar cp[64]; } CP64T;
64
65 typedef union { char ch[8];
66 uint8_t u1[8];
67 int8_t s1[8];
68 uint16_t u2[4];
69 int16_t s2[4];
70 uint32_t u4[2];
71 int32_t s4[2];
72 uint64_t u8[1];
73 int64_t s8[1];
74 float f4[2];
75 double f8[1]; } XT;
76
77 # define ACHT mag1, wid, shft, swid, cntl, _5, filc, mag2
78 typedef struct { CTLTYP size; uchar ACHT; CTLTYP off, len; XT _Alignas(AL) buf; } STRING;
79 # undef ACHT
80
81 typedef struct { uchar sign:1, text:1, lfil:1, ofil:1, ro:1, _5:1,_6:1,_7:1; } CNTLB;
82
83 # define CNTLP(name) ( (CNTLB*)&stringcntl(name) )
84
85 # define STRINGP(name) ( (STRING*)name )
86
87 # define stringbuf( name) ((uchar*)name+CNTL)
88 # define stringfub( name) ((uchar*)name-CNTL)
89 # define stringsize(name) (((CTLTYP*)name)[0]+0)
90 # define stringlen( name) ((CTLTYP*)((uchar*)name+2*CTLWID+8))[0]
91 # define stringoff( name) ((CTLTYP*)((uchar*)name+1*CTLWID+8))[0]
92 # define stringwid( name) ((uchar*)name)[CTLWID+1]
93 # define stringshft(name) ((uchar*)name)[CTLWID+2]
94 # define stringswid(name) ((uchar*)name)[CTLWID+3]
95 # define stringcntl(name) ((uchar*)name)[CTLWID+4]
96 # define stringfilc(name) ((uchar*)name)[CTLWID+6]
97 # define stringmag1(name) ( ((uchar*)name)[CTLWID+0]+0 )
98 # define stringmag2(name) ( ((uchar*)name)[CTLWID+7]+0 )
99 # define stringbufsz(name) ( ((CTLTYP*)name)[0]-CNTL )
100 # define stringlenmax(name) ( stringbufsz(name) >> stringshft(name) )
101
102
103 static _Noreturn void string_err(int, const char *);
104 static uchar string_widthtoshift(uchar);
105 void string0t(void *);
106 static CTLTYP string_len0t(void *, uint);
107 static int string_align2(CTLTYP, CTLTYP, uchar *, uchar *);
108 static CTLTYP string_copy2(CTLTYP, CTLTYP, CTLTYP, CTLTYP, void *, const void *);
109 static void string_fill(void *, CTLTYP, CTLTYP);
110 void stringsetlen(void *, CTLTYP);
111 void stringsetoff(void *, CTLTYP);
112 void stringsetwid(void *, uchar);
113 CTLTYP stringset(void *, void *, CTLTYP, CTLTYP);
114 void stringrev(void *);
115 void stringmov(void *, CTLTYP, CTLTYP, CTLTYP);
116 ssize_t stringstr(const void *, const void *, ssize_t [3]);
117 ssize_t stringcmp(const void *, const void *);
118 void stringcpy(void *, const void *);
119 CTLTYP stringcats(void *, const void *, ...);
120 void stringinfo(const void *, FILE *, const char *);
121 ssize_t stringput(const void *, FILE *, const char *);
122
123
124 static _Noreturn void string_err(int e, const char *fu)
125 {
126 static const char * const es[]= {
127 "Kein 'STRING'-Objekt!",
128 "Null-Pointer als Parameter!",
129 "Typ-Breite zu gross.",
130 "Potentielles Schreiben in gesperrte Bereiche.",
131 "Laenge oder Offset zu gross.",
132 "Ziel-Breite zu schmal.",
133 "Falsche Breite.",
134 "Breite in Byte keine Potenz von 2.",
135 "Falscher Positionswert.",
136 "Parameterwert zu gross.",
137 "Breiten ungleich.",
138 "Suchmuster zu lang.",
139 "Vorzeichenbehaftung ungleich.",
140 "String-Objekte sind identisch.",
141 "Potentielle Verursachung eines Datenloches.",
142 "Lesen potentiell nichtinitialisierter Daten.",
143 "Schreiben ist gesperrt (read only).",
144 };
145 fprintf(stderr, "\tstring:%s(): %s\n", fu, es[e]);
146 exit(e+1);
147 }
148
149
150 static uchar string_widthtoshift(uchar wid)
151 {
152 uchar shft, nb;
153 if (wid>MAXWID) string_err(6, __func__);
154 for (nb=shft=0; wid; wid>>=1,++shft) nb+= wid&1;
155 if (nb!=1) string_err(7, __func__);
156 return shft-1;
157 }
158
159
160 void string0t(void *dst)
161 {
162 if (!dst) string_err(1, __func__);
163 if ( stringmag1(dst) != MAG1
164 ||stringmag2(dst) != MAG2) string_err(0, __func__);
165 uchar wid= stringwid(dst);
166 dst= stringbuf(dst) + (stringlen(dst) << stringshft(dst));
167 while (wid) ((uchar*)dst)[--wid]= 0;
168 return;
169 }
170
171
172 static CTLTYP string_len0t(void *str, uint wid)
173 {
174 CTLTYP l=0;
175 if (!str) string_err(1, __func__);
176 switch (wid) {
177 default: string_err(6, __func__); break;
178 case 1: while ( ((uint8_t *)str)[l] ) ++l; break;
179 case 2: while ( ((uint16_t*)str)[l] ) ++l; break;
180 case 4: while ( ((uint32_t*)str)[l] ) ++l; break;
181 case 8: while ( ((uint64_t*)str)[l] ) ++l; break;
182 }
183 return l;
184 }
185
186
187 static int string_align2(CTLTYP dn, CTLTYP sn, uchar *eins, uchar *mask)
188 {
189 uchar one, msk, dm, sm;
190 msk= AL-1; one= AL+1;
191 do {
192 dm= dn&msk; sm= sn&msk;
193 if (dm==sm) one= (msk+1-dm)&msk;
194 else msk>>=1;
195 }
196 while (one>AL && msk);
197 *eins= one;
198 *mask= msk;
199 return !msk;
200 }
201
202
203 static CTLTYP string_copy2(CTLTYP dn, CTLTYP sn, CTLTYP dsz, CTLTYP ssz,
204 void *dst, const void *src)
205 {
206 uchar mask, eins;
207 if (string_align2(dn, sn, &eins, &mask)) goto COPY1;
208 while (eins && dn<dsz && sn<ssz)
209 ((CP1T*)dst)[dn++]= ((CP1T*)src)[sn++], --eins;
210 switch (mask) {
211 default:
212 case 63: for (; dn+63<dsz && sn+63<ssz; dn+=64,sn+=64)
213 ((CP64T*)dst)[dn>>6]= ((CP64T*)src)[sn>>6];
214 case 31:
215 for (; dn+31<dsz && sn+31<ssz; dn+=32,sn+=32)
216 ((CP32T*)dst)[dn>>5]= ((CP32T*)src)[sn>>5];
217 case 15:
218 for (; dn+15<dsz && sn+15<ssz; dn+=16,sn+=16)
219 ((CP16T*)dst)[dn>>4]= ((CP16T*)src)[sn>>4];
220 case 7:
221 for (; dn+7<dsz && sn+7<ssz; dn+=8,sn+=8)
222 ((CP8T*)dst)[dn>>3]= ((CP8T*)src)[sn>>3];
223 case 3:
224 for (; dn+3<dsz && sn+3<ssz; dn+=4,sn+=4)
225 ((CP4T*)dst)[dn>>2]= ((CP4T*)src)[sn>>2];
226 break;
227 case 1: for (; dn+1<dsz && sn+1<ssz; dn+=2,sn+=2)
228 ((CP2T*)dst)[dn>>1]= ((CP2T*)src)[sn>>1];
229 break;
230 }
231 COPY1:;
232 while (dn<dsz && sn<ssz) ((CP1T*)dst)[dn++]= ((CP1T*)src)[sn++];
233 return dn;
234 }
235
236
237 static void string_fill(void *dst, CTLTYP oldpos, CTLTYP newpos)
238 {
239 uchar shft, filc, eins;
240 CTLTYP i, e, fill;
241 shft= stringshft(dst);
242 filc= stringfilc(dst);
243 for (fill=0,i=CTLWID; i; --i) fill<<=8, fill|= filc;
244 i= oldpos << shft;
245 e= newpos << shft;
246 shft= string_widthtoshift(CTLWID);
247 eins= CTLWID-(i&CTLWID-1)&CTLWID-1;
248 dst = stringbuf(dst);
249 while (eins && i < e) ((uint8_t*)dst)[i++]= filc, --eins;
250 while (i+CTLWID-1 < e) ((CTLTYP *)dst)[i>>shft]= fill, i+=CTLWID;
251 while ( i < e) ((uint8_t*)dst)[i++]= filc;
252 return;
253 }
254
255
256
257
258
259
260 void stringsetlen(void *dst, CTLTYP len)
261 {
262 if (!dst) string_err(1, __func__);
263 if ( stringmag1(dst) != MAG1
264 ||stringmag2(dst) != MAG2) string_err(0, __func__);
265 if (stringlenmax(dst)-stringoff(dst) < len) string_err(4, __func__);
266 if (stringlen(dst) < len && CNTLP(dst)->lfil)
267 string_fill(dst, stringoff(dst)+stringlen(dst), stringoff(dst)+len);
268 stringlen(dst)= len;
269 return;
270 }
271
272 void stringsetoff(void *dst, CTLTYP off)
273 {
274 CTLTYP len, len0, off0, max;
275 if (!dst) string_err(1, __func__);
276 if ( stringmag1(dst) != MAG1
277 ||stringmag2(dst) != MAG2) string_err(0, __func__);
278 max= stringlenmax(dst);
279 if (max < off) string_err(4, __func__);
280 off0= stringoff(dst);
281 len0= stringlen(dst);
282 if (off0 < off) {
283 len= off-off0 >= len0 ? 0 : len0 - (off-off0);
284 if (CNTLP(dst)->ofil && off+len <= max && off+len > off0+len0)
285 string_fill(dst, off0+len0, off+len);
286 }
287 else len= len0 + (off0-off);
288 if (off+len > max) string_err(4, __func__);
289 stringlen(dst)= len;
290 stringoff(dst)= off;
291 return;
292 }
293
294 void stringsetwid(void *dst, uchar wid)
295 {
296 uchar dsh, wsh;
297 if (!dst) string_err(1, __func__);
298 if ( stringmag1(dst) != MAG1
299 ||stringmag2(dst) != MAG2) string_err(0, __func__);
300 wsh= string_widthtoshift(wid);
301 dsh= stringshft(dst);
302 if (wsh>dsh) stringlen(dst)>>= wsh-dsh, stringoff(dst)>>= wsh-dsh;
303 if (wsh<dsh) stringlen(dst)<<= dsh-wsh, stringoff(dst)<<= dsh-wsh;
304 stringwid( dst)= wid;
305 stringshft(dst)= string_widthtoshift(wid);
306 return;
307 }
308
309
310
311
312
313
314 CTLTYP stringset(void *dst, void *str, CTLTYP widval, CTLTYP nval)
315 {
316 CTLTYP i, l, off;
317 void *dst0= dst;
318 uchar wid;
319 if (!dst) string_err(1, __func__);
320 if ( stringmag1(dst) != MAG1
321 ||stringmag2(dst) != MAG2) string_err(0, __func__);
322 if (CNTLP(dst)->ro) string_err(16, __func__);
323 wid= stringwid(dst);
324 off= stringoff(dst);
325 if (str) {
326 if (wid < widval) string_err(5, __func__);
327 l= nval==MAXVAL ? string_len0t(str, widval) : nval;
328 if (stringlenmax(dst)-off < l) string_err(3, __func__);
329 }
330 else l= stringlenmax(dst)-off;
331 if (l==0) return 0;
332 dst= stringbuf(dst);
333 dst= (uchar*)dst + (off<<stringshft(dst));
334 i= 0;
335 if (!str) {
336 if (nval > l) string_err(9, __func__);
337 switch (wid) {
338 case 1: while (i<nval) ((uint8_t *)dst)[i++]= widval; break;
339 case 2: while (i<nval) ((uint16_t*)dst)[i++]= widval; break;
340 case 4: while (i<nval) ((uint32_t*)dst)[i++]= widval; break;
341 case 8: while (i<nval) ((uint64_t*)dst)[i++]= widval; break;
342 }
343 }
344 else {
345 switch (wid) {
346 case 1: while (i<l) ((uint8_t *)dst)[i]= ((uint8_t *)str)[i], ++i; break;
347 case 2:
348 switch (widval) {
349 case 1: while (i<l) ((uint16_t*)dst)[i]= ((uint8_t *)str)[i], ++i; break;
350 case 2: while (i<l) ((uint16_t*)dst)[i]= ((uint16_t*)str)[i], ++i; break;
351 }
352 break;
353 case 4:
354 switch (widval) {
355 case 1: while (i<l) ((uint32_t*)dst)[i]= ((uint8_t *)str)[i], ++i; break;
356 case 2: while (i<l) ((uint32_t*)dst)[i]= ((uint16_t*)str)[i], ++i; break;
357 case 4: while (i<l) ((uint32_t*)dst)[i]= ((uint32_t*)str)[i], ++i; break;
358 }
359 break;
360 case 8:
361 switch (widval) {
362 case 1: while (i<l) ((uint64_t*)dst)[i]= ((uint8_t *)str)[i], ++i; break;
363 case 2: while (i<l) ((uint64_t*)dst)[i]= ((uint16_t*)str)[i], ++i; break;
364 case 4: while (i<l) ((uint64_t*)dst)[i]= ((uint32_t*)str)[i], ++i; break;
365 case 8: while (i<l) ((uint64_t*)dst)[i]= ((uint64_t*)str)[i], ++i; break;
366 }
367 break;
368 }
369 }
370 stringlen(dst0)= i;
371 return i;
372 }
373
374
375 void stringrev(void *sp)
376 {
377 CTLTYP len, u, o;
378 uchar wid;
379 if (!sp) string_err(1, __func__);
380 if ( stringmag1(sp) != MAG1
381 ||stringmag2(sp) != MAG2) string_err(0, __func__);
382 if (CNTLP(sp)->ro) string_err(16, __func__);
383 len= stringlen(sp);
384 if (len<2) return;
385 wid= stringwid(sp);
386 sp = stringbuf(sp) + (stringoff(sp) << stringshft(sp));
387 u = 0;
388 o = len-1;
389 switch (wid) { CP1T t1; CP2T t2; CP4T t4; CP8T t8;
390 default: string_err(6, __func__);
391 case 1: do t1 = ((CP1T*)sp)[u],
392 ((CP1T*)sp)[u] = ((CP1T*)sp)[o],
393 ((CP1T*)sp)[o] = t1;
394 while (--o > ++u);
395 break;
396 case 2: do t2 = ((CP2T*)sp)[u],
397 ((CP2T*)sp)[u] = ((CP2T*)sp)[o],
398 ((CP2T*)sp)[o] = t2;
399 while (--o > ++u);
400 break;
401 case 4: do t4 = ((CP4T*)sp)[u],
402 ((CP4T*)sp)[u] = ((CP4T*)sp)[o],
403 ((CP4T*)sp)[o] = t4;
404 while (--o > ++u);
405 break;
406 case 8: do t8 = ((CP8T*)sp)[u],
407 ((CP8T*)sp)[u] = ((CP8T*)sp)[o],
408 ((CP8T*)sp)[o] = t8;
409 while (--o > ++u);
410 break;
411 }
412 return;
413 }
414
415
416
417
418
419
420
421
422
423
424 void stringmov(void *zq, CTLTYP zp, CTLTYP qp, CTLTYP ne)
425 {
426 CTLTYP len, off, max;
427 uchar wid; signed char a;
428 _Bool dwn;
429 if (!zq) string_err(1, __func__);
430 if ( stringmag1(zq)!=MAG1
431 ||stringmag2(zq)!=MAG2) string_err(0, __func__);
432 if (CNTLP(zq)->ro) string_err(16, __func__);
433 if (zp == qp || !ne) return;
434 wid= stringwid(zq);
435 len= stringlen(zq);
436 off= stringoff(zq);
437 max= stringlenmax(zq);
438 zp+= off;
439 qp+= off;
440 dwn= zp < qp;
441 a= dwn?+1:-1;
442 if (!dwn) {
443 if (zp < off+ne-1 || zp >= max) string_err(3, __func__);
444 if (zp > off+len+ne-1 ) string_err(14, __func__);
445 if (qp < ne-1 || qp >= off+len) string_err(15, __func__);
446 len= zp+1;
447 }
448 else {
449 if (zp < off || zp+ne-1 >= max) string_err(3, __func__);
450 if (zp > off+len ) string_err(14, __func__);
451 if (qp+ne-1 >= off+len ) string_err(15, __func__);
452 len= zp+ne;
453 }
454 if (len > stringlen(zq)) stringlen(zq)= len;
455 zq = stringbuf(zq);
456 switch (wid) {
457 default: string_err(6, __func__);
458 case 1: for (; ne; --ne,zp+=a,qp+=a) ((CP1T*)zq)[zp] = ((CP1T*)zq)[qp]; break;
459 case 2: for (; ne; --ne,zp+=a,qp+=a) ((CP2T*)zq)[zp] = ((CP2T*)zq)[qp]; break;
460 case 4: for (; ne; --ne,zp+=a,qp+=a) ((CP4T*)zq)[zp] = ((CP4T*)zq)[qp]; break;
461 case 8: for (; ne; --ne,zp+=a,qp+=a) ((CP8T*)zq)[zp] = ((CP8T*)zq)[qp]; break;
462 }
463 return;
464 }
465
466
467
468
469
470
471 ssize_t stringstr(const void *buf, const void *str, ssize_t poa[3])
472 {
473 CTLTYP bn,b1, sn,s1, be, se, len;
474 ssize_t pos;
475 uchar wid;
476 if (!buf||!str) string_err(1, __func__);
477 if ( stringmag1(buf)!=MAG1||stringmag1(str)!=MAG1
478 ||stringmag2(buf)!=MAG2||stringmag2(str)!=MAG2) string_err(0, __func__);
479 wid= stringwid(buf);
480 len= stringlen(str);
481 pos= !poa||!poa[0] ? stringoff(buf) : poa[0];
482 if (wid != stringwid(str) ) string_err(10, __func__);
483 if (len > stringlen(buf) ) string_err(11, __func__);
484 if ( pos < 0 || pos >= stringoff(buf) + stringlen(buf)
485 || pos && pos < stringoff(buf) ) string_err( 8, __func__);
486 if (len < 1 || buf == str) goto LEN0;
487 if (stringoff(buf) + stringlen(buf) - pos < len) goto NFND;
488 bn = pos;
489 sn = stringoff(str); s1= sn+1;
490 be = stringlen(buf) + stringoff(buf);
491 se = stringlen(str) + sn;
492 buf= stringbuf(buf);
493 str= stringbuf(str);
494 switch (wid) { uint8_t e1; uint16_t e2;
495 uint32_t e4; uint64_t e8;
496 default: string_err(6, __func__);
497 case 1: e1= ((uint8_t*)str)[sn];
498 do {
499 for (; bn<be; ++bn) {
500 if (e1 == ((uint8_t*)buf)[bn]) break;
501 }
502 if (bn>=be) goto NFND;
503 for (b1=++bn,sn=s1; bn<be && sn<se; ++bn,++sn) {
504 if (((uint8_t*)str)[sn] != ((uint8_t*)buf)[bn]) break;
505 }
506 if (sn>=se) break;
507 if (bn>=be) goto NFND;
508 }
509 while (bn=b1, 1);
510 break;
511 case 2: e2= ((uint16_t*)str)[sn];
512 do {
513 for (; bn<be; ++bn) {
514 if (e2 == ((uint16_t*)buf)[bn]) break;
515 }
516 if (bn>=be) goto NFND;
517 for (b1=++bn,sn=s1; bn<be && sn<se; ++bn,++sn) {
518 if (((uint16_t*)str)[sn] != ((uint16_t*)buf)[bn]) break;
519 }
520 if (sn>=se) break;
521 if (bn>=be) goto NFND;
522 }
523 while (bn=b1, 1);
524 break;
525 case 4: e4= ((uint32_t*)str)[sn];
526 do {
527 for (; bn<be; ++bn) {
528 if (e4 == ((uint32_t*)buf)[bn]) break;
529 }
530 if (bn>=be) goto NFND;
531 for (b1=++bn,sn=s1; bn<be && sn<se; ++bn,++sn) {
532 if (((uint32_t*)str)[sn] != ((uint32_t*)buf)[bn]) break;
533 }
534 if (sn>=se) break;
535 if (bn>=be) goto NFND;
536 }
537 while (bn=b1, 1);
538 break;
539 case 8: e8= ((uint64_t*)str)[sn];
540 do {
541 for (; bn<be; ++bn) {
542 if (e8 == ((uint64_t*)buf)[bn]) break;
543 }
544 if (bn>=be) goto NFND;
545 for (b1=++bn,sn=s1; bn<be && sn<se; ++bn,++sn) {
546 if (((uint64_t*)str)[sn] != ((uint64_t*)buf)[bn]) break;
547 }
548 if (sn>=se) break;
549 if (bn>=be) goto NFND;
550 }
551 while (bn=b1, 1);
552 break;
553 }
554 if (poa) poa[0]= b1-1, poa[1]= be-bn>=len ? bn : -1, poa[2]= len;
555 return b1-1;
556 LEN0:;
557 if (poa) poa[0]= pos , poa[1]= -1, poa[2]= len;
558 return pos;
559 NFND:;
560 if (poa) poa[0]= -1 , poa[1]= -1, poa[2]= len;
561 return -1;
562 }
563
564
565 ssize_t stringcmp(const void *ac, const void *bc)
566 {
567 CTLTYP ai, bi, ae, be;
568 ssize_t d= 2;
569 uchar wid;
570 _Bool sign;
571 if (!ac||!bc) string_err(1, __func__);
572 if ( stringmag1(ac)!=MAG1||stringmag1(bc)!=MAG1
573 ||stringmag2(ac)!=MAG2||stringmag2(bc)!=MAG2) string_err(0, __func__);
574 wid= stringwid(ac);
575 sign= CNTLP(ac)->sign;
576 if ( wid != stringwid(bc) ) string_err(10, __func__);
577 if (sign != CNTLP(bc)->sign) string_err(12, __func__);
578 if (ac == bc) return 0;
579 ai= stringoff(ac);
580 bi= stringoff(bc);
581 ae= stringlen(ac) + ai;
582 be= stringlen(bc) + bi;
583 ac= stringbuf(ac);
584 bc= stringbuf(bc);
585 if (sign) goto SIGN;
586 switch (wid) {
587 default: string_err(6, __func__);
588 case 1:
589 for (; ai<ae && bi<be; ++ai,++bi) {
590 d= ((uint8_t*)ac)[ai] - ((uint8_t*)bc)[bi];
591 if (d) return d;
592 }
593 if (ai>=ae) if (bi>=be) d= 0;
594 else d= -((uint8_t*)bc)[bi];
595 else if (bi>=be) d= +((uint8_t*)ac)[ai];
596 break;
597 case 2:
598 for (; ai<ae && bi<be; ++ai,++bi) {
599 d= ((uint16_t*)ac)[ai] - ((uint16_t*)bc)[bi];
600 if (d) return d;
601 }
602 if (ai>=ae) if (bi>=be) d= 0;
603 else d= -((uint16_t*)bc)[bi];
604 else if (bi>=be) d= +((uint16_t*)ac)[ai];
605 break;
606 case 4:
607 for (; ai<ae && bi<be; ++ai,++bi) {
608 if (((uint32_t*)ac)[ai] > ((uint32_t*)bc)[bi]) return +1;
609 if (((uint32_t*)ac)[ai] < ((uint32_t*)bc)[bi]) return -1;
610 }
611 D011:;
612 if (ai>=ae) if (bi>=be) d= 0;
613 else d= -1;
614 else if (bi>=be) d= +1;
615 break;
616 case 8:
617 for (; ai<ae && bi<be; ++ai,++bi) {
618 if (((uint64_t*)ac)[ai] > ((uint64_t*)bc)[bi]) return +1;
619 if (((uint64_t*)ac)[ai] < ((uint64_t*)bc)[bi]) return -1;
620 }
621 goto D011;
622 }
623 return d;
624 SIGN:;
625 switch (wid) {
626 default: string_err(6, __func__);
627 case 1:
628 for (; ai<ae && bi<be; ++ai,++bi) {
629 d= (( int8_t*)ac)[ai] - (( int8_t*)bc)[bi];
630 if (d) return d;
631 }
632 if (ai>=ae) if (bi>=be) d= 0;
633 else d= -(( int8_t*)bc)[bi];
634 else if (bi>=be) d= +(( int8_t*)ac)[ai];
635 break;
636 case 2:
637 for (; ai<ae && bi<be; ++ai,++bi) {
638 d= (( int16_t*)ac)[ai] - (( int16_t*)bc)[bi];
639 if (d) return d;
640 }
641 if (ai>=ae) if (bi>=be) d= 0;
642 else d= -(( int16_t*)bc)[bi];
643 else if (bi>=be) d= +(( int16_t*)ac)[ai];
644 break;
645 case 4:
646 for (; ai<ae && bi<be; ++ai,++bi) {
647 if ((( int32_t*)ac)[ai] > (( int32_t*)bc)[bi]) return +1;
648 if ((( int32_t*)ac)[ai] < (( int32_t*)bc)[bi]) return -1;
649 }
650 D011s:;
651 if (ai>=ae) if (bi>=be) d= 0;
652 else d= -1;
653 else if (bi>=be) d= +1;
654 break;
655 case 8:
656 for (; ai<ae && bi<be; ++ai,++bi) {
657 if ((( int64_t*)ac)[ai] > (( int64_t*)bc)[bi]) return +1;
658 if ((( int64_t*)ac)[ai] < (( int64_t*)bc)[bi]) return -1;
659 }
660 goto D011s;
661 }
662 return d;
663 }
664
665
666 void stringcpy(void *dst, const void *src)
667 {
668 CTLTYP dsz, ssz, n;
669 if (!dst||!src) string_err(1, __func__);
670 if ( stringmag1(dst)!=MAG1||stringmag1(src)!=MAG1
671 ||stringmag2(dst)!=MAG2||stringmag2(src)!=MAG2) string_err(0, __func__);
672 if (CNTLP(dst)->ro) string_err(16, __func__);
673 if (dst == src) return;
674 dsz= stringsize(dst);
675 ssz= (stringlen(src) << stringshft(src)) + CNTL;
676 n = (ssz+AL-1)/AL;
677 if (dsz/AL < n) string_err(3, __func__);
678 switch (AL) {
679 default: string_err(6, __func__);
680 case 64: do --n, ((CP64T*)dst)[n] = ((CP64T*)src)[n]; while (n>0); break;
681 case 32: do --n, ((CP32T*)dst)[n] = ((CP32T*)src)[n]; while (n>0); break;
682 case 16: do --n, ((CP16T*)dst)[n] = ((CP16T*)src)[n]; while (n>0); break;
683 case 8: do --n, ((CP8T *)dst)[n] = ((CP8T *)src)[n]; while (n>0); break;
684 case 4: do --n, ((CP4T *)dst)[n] = ((CP4T *)src)[n]; while (n>0); break;
685 }
686 *(CTLTYP*)dst= dsz;
687 return;
688 }
689
690
691 CTLTYP stringcats(void *dst, const void *src, ...)
692 {
693 const void *a; va_list ap;
694 CTLTYP dsz, ssz, dn, sn, dn0;
695 if (!dst||!src) string_err(1, __func__);
696 if ( stringmag1(dst)!=MAG1||stringmag1(src)!=MAG1
697 ||stringmag2(dst)!=MAG2||stringmag2(src)!=MAG2) string_err(0, __func__);
698 if (CNTLP(dst)->ro) string_err(16, __func__);
699 dsz= stringbufsz(dst);
700 dn = stringoff(dst) << stringshft(dst);
701 dst= stringbuf(dst);
702 dn0= dn;
703 for (a=src,va_start(ap,src); a; a=va_arg(ap,void*)) {
704 if (stringmag1(a)!=MAG1||stringmag2(a)!=MAG2) string_err(0, __func__);
705 if (a == stringfub(dst)) string_err(13, __func__);
706 ssz= stringlen(a) << stringshft(a);
707 if (dn+ssz > dsz) string_err(3, __func__);
708 sn = stringoff(a) << stringshft(a);
709 a = stringbuf(a);
710 dn = string_copy2(dn, sn, dsz, ssz, dst, a);
711 }
712 va_end(ap);
713 dst= stringfub(dst);
714 stringlen(dst)= (dn-dn0) >> stringshft(dst);
715 return dn-dn0;
716 }
717
718
719 void stringinfo(const void *src, FILE *fp, const char *info)
720 {
721 if (!src) string_err(1, __func__);
722 if ( stringmag1(src) != MAG1
723 ||stringmag2(src) != MAG2) string_err(0, __func__);
724 if (!fp) fp= stdout;
725 fprintf(fp, "\t%s%s%ssize=%zu\tlen=%zu\toff=%zu\twid=%hhu\n",
726 info?info:"", info?":":"", info?"\t":"",
727 stringsize(src), stringlen(src), stringoff(src), stringwid(src));
728 return;
729 }
730
731
732 ssize_t stringput(const void *src, FILE *fp, const char *info)
733 {
734 CTLTYP n; ssize_t r=0;
735 uchar wid;
736 if (!src) string_err(1, __func__);
737 if ( stringmag1(src) != MAG1
738 ||stringmag2(src) != MAG2) string_err(0, __func__);
739 if (!fp) fp= stdout;
740 if (info) fprintf(fp, "%s", info);
741 wid= stringwid(src);
742 n = stringlen(src);
743 src= stringbuf(src) + (stringoff(src) << stringshft(src));
744 switch (wid) {
745 default: r=-2; break;
746 case 1: r= fwrite(src, 1, n, fp);
747 if (r!=n) r=-1;
748 break;
749 case sizeof(wchar_t):
750 r= fwprintf(fp, L"%.*ls", (int)n, src);
751 if (r!=n) r=-1;
752 break;
753 }
754 return r;
755 }
756
757
758
759 static char ts[]= "jdgkaeuipoefeihfuwegyeuwfuireqhgoeqrjfwqiphruieqrrssgqjnqdgsfvbj";
760
761 static CTLTYP string_test(void)
762 {
763 CTLTYP n;
764 STRING_DuI(q1,100);
765 STRING_DuI(q2,150);
766 STRING_DuI(z1,1500);
767 STRING_DuI(z2,15000);
768 STRING_DuI(z3,150000);
769 STRING_DuI(z4,1500000);
770 STRING_DuI(z5,15000000);
771 STRING_DuI(z6,15000000);
772 STRING_DuI(z7,15000000);
773 STRING_DuI(z8,15000000);
774 STRING_DuI(z9,15000000);
775 stringset(q1, ts, 1, 50);
776 stringcats(q2, q1, q1, (void*)0);
777 stringcats(z1, q2,q2,q2,q2,q2,q2,q2,q2,q2,q2, (void*)0);
778 stringcats(z2, z1,z1,z1,z1,z1,z1,z1,z1,z1,z1, (void*)0);
779 stringcats(z3, z2,z2,z2,z2,z2,z2,z2,z2,z2,z2, (void*)0);
780 stringcats(z4, z3,z3,z3,z3,z3,z3,z3,z3,z3,z3, (void*)0);
781 n= stringcats(z5, z4,z4,z4,z4,z4,z4,z4,z4,z4,z4, (void*)0);
782 stringcpy(z6, z5);
783 stringcpy(z7, z5);
784 stringcpy(z8, z5);
785 stringcpy(z9, z5);
786 return n;
787 }
788
789 static CTLTYP str_test(void)
790 {
791 char q1[100];
792 char q2[150];
793 char z1[1500];
794 char z2[15000];
795 char z3[150000];
796 char z4[1500000];
797 char z5[15000000];
798 char z6[15000000];
799 char z7[15000000];
800 char z8[15000000];
801 char z9[15000000];
802 z5[0]=z4[0]=z3[0]=z2[0]=z1[0]=q2[0]=q1[0]= 0;
803 strncat(q1, ts, 50);
804 strcat(strcat(q2,q1), q1);
805 strcat(strcat(strcat(strcat(strcat(strcat(strcat(strcat(strcat(
806 strcat(z1,q2),q2),q2),q2),q2),q2),q2),q2),q2), q2);
807 strcat(strcat(strcat(strcat(strcat(strcat(strcat(strcat(strcat(
808 strcat(z2,z1),z1),z1),z1),z1),z1),z1),z1),z1), z1);
809 strcat(strcat(strcat(strcat(strcat(strcat(strcat(strcat(strcat(
810 strcat(z3,z2),z2),z2),z2),z2),z2),z2),z2),z2), z2);
811 strcat(strcat(strcat(strcat(strcat(strcat(strcat(strcat(strcat(
812 strcat(z4,z3),z3),z3),z3),z3),z3),z3),z3),z3), z3);
813 strcat(strcat(strcat(strcat(strcat(strcat(strcat(strcat(strcat(
814 strcat(z5,z4),z4),z4),z4),z4),z4),z4),z4),z4), z4);
815 strcpy(z6, z5);
816 strcpy(z7, z5);
817 strcpy(z8, z5);
818 strcpy(z9, z5);
819 return strlen(z9);
820 }
821
822 static ssize_t stringstr_test(void)
823 {
824
825 static char s1[]= "toga.....togatog..togatoga..togatoga";
826 static char s2[]= ".toga....togatog..togatoga.togatoga.";
827 static char s3[]= ".toga....togatog..togatoga...toga...";
828 static char s4[]= ".toga....togatog..togatoga..toga....";
829 static char ss[]= "toga";
830 STRING_DuI(dat,200);
831 STRING_DuI(str,150);
832 ssize_t pos[3];
833 STRING *sp;
834 sp= (STRING*)dat;
835 stringset(dat, s4, 1, MAXVAL);
836 stringset(str, ss, 1, MAXVAL);
837 string0t(dat);
838 pos[0]=0;
839 do {
840 stringstr(dat, str, pos);
841 printf("\t%zd %zd %zd\t%s\n", pos[0],pos[1],pos[2],
842 pos[0]>0?sp->buf.ch+pos[0]:"");
843 pos[0]= pos[1];
844 } while (pos[1]>0);
845 return 0;
846 }
847
848 # include <sys/time.h>
849
850 # define TIME(ca,cb) (long long) \
851 ((ca.it_value.tv_sec*1000000+ca.it_value.tv_usec) \
852 -(cb.it_value.tv_sec*1000000+cb.it_value.tv_usec))
853
854 # if defined(_______)
855 static STRING_DEF(file,1000);
856 # endif
857
858 int main(void)
859 {
860 # if defined(_______)
861 CTLTYP na, nb, i;
862 struct itimerval ca, cb, cc;
863 ca.it_value.tv_sec=1000, ca.it_value.tv_usec=0;
864 ca.it_interval.tv_sec=0, ca.it_interval.tv_usec=0;
865 setitimer(ITIMER_VIRTUAL, &ca, 0);
866 getitimer(ITIMER_VIRTUAL, &ca);
867 for (i=10; i; --i) na= string_test();
868 getitimer(ITIMER_VIRTUAL, &cb);
869 for (i=10; i; --i) nb= str_test();
870 getitimer(ITIMER_VIRTUAL, &cc);
871 printf("\t%zu\t%lldms\n", na, TIME(ca,cb)/1000);
872 printf("\t%zu\t%lldms\n", nb, TIME(cb,cc)/1000);
873
874
875 # endif
876 # if !defined(_______)
877 stringstr_test();
878 # endif
879
880 # if defined(_______)
881 STRING *sp;
882 CTLTYP n;
883 STRING_INI(file);
884 static STRING_DuI(cat,500);
885 STRING_DuI(ziel,200);
886 STRING_DuI(quelle,150);
887 sp= (STRING*)ziel;
888 stringset(ziel, 0, 'B', 100);
889 stringset(quelle, "ifuiyg3qwruqiweidwgh2rhb", 1, MAXVAL);
890 printf("a:%.*s\n'a:%zu'\n", (int)sp->len, sp->buf.u1, sp->len);
891
892 stringcpy(ziel, quelle);
893 stringput(ziel, 0, "ziel:");
894 printf("\nb:%.*s\n'b:%zu'\n", (int)sp->len, sp->buf.u1, sp->len);
895 stringinfo(ziel, 0, "ziel");
896 n= stringcats(cat, quelle, ziel, (void*)NULL);
897 stringinfo(quelle, 0, "quelle");
898 stringinfo(ziel, 0, "ziel");
899 stringinfo(cat, 0, "cat");
900 stringput(cat , 0, "cat:");
901 printf("\n'c:%zu'-d:%zu-\n", STRINGP(cat)->size, n);
902 n= stringcats(file, cat, quelle, ziel, (void*)NULL);
903 stringinfo(file, 0, "file");
904 stringput(file, 0, "file:");
905 printf("\n'e:%zu'-f:%zu-\n", STRINGP(file)->size, n);
906 printf("%zu %zu %zu %zu\n", sizeof(file), STRINGP(file)->size, sizeof(STRING), CNTL);
907
908
909 # endif
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926 return 0;
927 }
928
929
930