Beschreibung
  1 /*                       string.c             Copyright (c) Helmut Schellong  28.05.2021 */
  2 /* Zeichenklasse STRING                                                Stand: 27.06.2021 */
  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          /*memset((uchar*)name+CNTL, FILC1, sizeof(name)-CNTL);*/  \
 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       /* 0 */ "Kein 'STRING'-Objekt!",
128       /* 1 */ "Null-Pointer als Parameter!",
129       /* 2 */ "Typ-Breite zu gross.",
130       /* 3 */ "Potentielles Schreiben in gesperrte Bereiche.",
131       /* 4 */ "Laenge oder Offset zu gross.",
132       /* 5 */ "Ziel-Breite zu schmal.",
133       /* 6 */ "Falsche Breite.",
134       /* 7 */ "Breite in Byte keine Potenz von 2.",
135       /* 8 */ "Falscher Positionswert.",
136       /* 9 */ "Parameterwert zu gross.",
137       /*10 */ "Breiten ungleich.",
138       /*11 */ "Suchmuster zu lang.",
139       /*12 */ "Vorzeichenbehaftung ungleich.",
140       /*13 */ "String-Objekte sind identisch.",
141       /*14 */ "Potentielle Verursachung eines Datenloches.",
142       /*15 */ "Lesen potentiell nichtinitialisierter Daten.",
143       /*16 */ "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 // 0123456789012345678901234567890123456789
257 // 0         o=10      l=10      m=30
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 // 0123456789012345678901234567890123456789
311 // 0         o=10      l=10      m=30
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 // 0123456789012345678901234567890123456789
417 // 0         o=10      l=10      m=30
418 // |---------|---------|---------|  n=5
419 //  ----z    ----z----z----z
420 // ----q    ----q----q----q
421 // z----    z----z----z---- z----
422 //  q----    q----q----q---- q----
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 // 0123456789012345678901234567890123456789
468 // 0         o=10      l=10      m=30
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;                            // <  <  do 
507                   if (bn>=be)  goto NFND;                        // >= <  -1 
508                }                                                 // <  >= fnd
509                while (bn=b1, 1);                                 // >= >= fnd
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    //                 0123456789012345678901234567890123456789
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    // 266ms : 382ms : Faktor 1,44
874    // 2,9 GB/s
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    //stringset(q1, ts, 1, 50);
908    //stringrev(q1); stringput(q1,0,"\nrev:");
909 #  endif
910    #if 0
911    { double d=2.34; int i[2];
912      printf("0: %.15lf align=%llu\n", d, (unsigned long long)i&0xffu );
913      *(long*)i    = *(long*)&d;
914      ((int*)&d)[0]= i[0];
915      ((int*)&d)[1]= i[1];
916      printf("a: %.15lf\n", d);
917      printf("a: %hhu %hhu %hhu\n", ((uchar*)&d)[3],((uchar*)&d)[2],((uchar*)&d)[1]);
918      ((uchar*)&d)[2]+= 123;
919      printf("b: %.15lf\n", d);
920      printf("b: %hhu %hhu %hhu\n", ((uchar*)&d)[3],((uchar*)&d)[2],((uchar*)&d)[1]);
921      ((uchar*)&d)[2]+= 210;
922      printf("c: %.15lf\n", d);
923      printf("c: %hhu %hhu %hhu\n", ((uchar*)&d)[3],((uchar*)&d)[2],((uchar*)&d)[1]);
924    }
925    #endif
926    return 0;
927 }
928 
929 
930