ztring.c: A few important extension for <string.h>
 All Classes Files Functions Variables Enumerator Friends Macros
test_ztring.c
Go to the documentation of this file.
1 /* test_ztring.c (C) 2014 adolfo@di-mare.com */
2 
3 /** \file test_ztring.c
4  \brief Test program for ztring extensions to <string.h>
5  \author Adolfo Di Mare <adolfo@di-mare.com>
6  \date 2014
7 */
8 
9 #include "uUnit.h"
10 #include "ztring.h"
11 
12 #include <stdio.h>
13 
14 #define pr_str( NAME ) printf( "(%d)->" #NAME " == \"%s\"[%d]\n" ,\
15  __LINE__, (char*)(NAME), strlen(NAME) )
16 #define pr_num( NAME ) printf( "(%d)->" #NAME " == %d\n" , __LINE__, NAME )
17 
18 
19 /** a==b? */
20 int eqstr( const char* a, const char* b ) {
21  return 0==strcmp(a,b);
22 }
23 
24 /** test->ztrcpy() */
25 void test_ztrcpy() {
26 {{ /* test::ztrcpy() */
27  char s10[9+1]; /* No more than 9 chars get copied */
28  {
29  ztrcpy( sizeof(s10),s10 , "123456789.abcdefghi.");
30  assertTrue( eqstr( s10 , "123456789" ) );
31  }
32  #define ZS(x) sizeof(x),x /* Shortcut macro */
33  {
34  ztrcpy( ZS( s10 ), "123456789.abcdefghi.");
35  assertTrue( eqstr( s10 , "123456789" ) );
36  }
37  #undef ZS /* ZS() could make code more compatible with strcpy() */
38 }}
39 if ("BLOCKIFY this to avoid problems when MOVING code elsewhere") {
40  {{ /* test::BeUNsafe::SZ() */
41  #ifdef USE_ZTR
42  #define ZS(x) sizeof(x),x /* Shortcut macro */
43  #else
44  #define ZS(x) x
45  /* convert ztrcpy(ZS(dest),src) -> strcpy(dest,src) */
46  #define ztrcpy( dest, src) strcpy(dest,src)
47  /* convert ztrcat(ZS(dest),src) -> strcat(dest,src) */
48  #define ztrcat( dest, src) strcat(dest,src)
49  #endif
50  }}
51  { /* undo previous define's */
52  #undef ztrcpy
53  #undef ztrcat
54  #undef ZS
55  }
56 }
57 { /* some limit cases with small number of elements */
58  {
59  char s1[1]; /* only EOS fits in a single char vector */
60  ztrcpy( sizeof(s1),s1, "12...." );
61  assertTrue( eqstr( s1, "" ) );
62  }
63  {
64  char s2[2]; /* only a single letter */
65  ztrcpy( sizeof(s2),s2, "12...." );
66  assertTrue( eqstr( s2, "1" ) );
67  }
68  {
69  char s3[3]; /* 2 letters */
70  ztrcpy( sizeof(s3),s3, "12...." );
71  assertTrue( eqstr( s3, "12" ) );
72  }
73  {
74  char s5[5]; /* 4 letters */
75  ztrcpy( sizeof(s5),s5, "12345...." );
76  assertTrue( eqstr( s5, "1234" ) );
77  }
78  {
79  char s5[5];
80  ztrcpy( sizeof(s5),s5, "123" );
81  assertTrue( eqstr( s5, "123" ) );
82  }
83  {
84  char s5[5];
85  ztrcpy( sizeof(s5),s5, "12" );
86  assertTrue( eqstr( s5, "12" ) );
87  }
88  {
89  char s5[5];
90  ztrcpy( sizeof(s5),s5, "1" );
91  assertTrue( eqstr( s5, "1" ) );
92  }
93  {
94  char s15[15];
95  ztrcpy( sizeof(s15),s15, "12345...." );
96  assertTrue( eqstr( s15, "12345...." ) );
97  }
98  { /* test that 'dest' gets 0-terminated */
99  char s15[15];
100  ztrcpy( 5,s15, "12345...." );
101  assertTrue( eqstr( s15, "1234" ) );
102  }
103 }
104 }
105 
106 /** test->ztrcat() */
107 void test_ztrcat() {
108 {{ /* test::ztrcat() */
109  char s10[9+1]; s10[0] = 0;
110  ztrcat( sizeof(s10),s10 , "123456789.abcdefghi.");
111  assertTrue( eqstr( s10 , "123456789" ) );
112  {
113  s10[3] = '.'; s10[3+1] = 0;
114  assertTrue( eqstr( s10 , "123." ) );
115  ztrcat( sizeof(s10),s10 , "123456789.abcdefghi.");
116  assertTrue( eqstr( s10 , "123.12345" ) );
117  }
118  #define ZS(x) sizeof(x),x /* Shortcut macro */
119  {
120  s10[3] = '.'; s10[3+1] = 0;
121  assertTrue( eqstr( s10 , "123." ) );
122  ztrcat( ZS(s10), "123456789.abcdefghi.");
123  assertTrue( eqstr( s10 , "123.12345" ) );
124  }
125  #undef ZS /* ZS() could make code more compatible with strcat() */
126 }}
127  {
128  char s5[5]; /* can fit 4 letters */
129  ztrcpy( sizeof(s5),s5, "1234" );
130  ztrcat( sizeof(s5),s5, "56" );
131  assertTrue( eqstr( s5, "1234" ) );
132  }
133  {
134  char s5[5];
135  ztrcpy( sizeof(s5),s5, "123" );
136  ztrcat( sizeof(s5),s5, "456" );
137  assertTrue( eqstr( s5, "1234" ) );
138  }
139  {
140  char s5[5];
141  ztrcpy( sizeof(s5),s5, "12" );
142  ztrcat( sizeof(s5),s5, "3456" );
143  assertTrue( eqstr( s5, "1234" ) );
144  }
145  {
146  char s5[5];
147  ztrcpy( sizeof(s5),s5, "1" );
148  ztrcat( sizeof(s5),s5, "23456" );
149  assertTrue( eqstr( s5, "1234" ) );
150  }
151  {
152  char s5[5];
153  ztrcpy( sizeof(s5),s5, "" );
154  ztrcat( sizeof(s5),s5, "123456" );
155  assertTrue( eqstr( s5, "1234" ) );
156  }
157  { /* test that 'dest' gets 0-terminated */
158  char s15[15];
159  ztrcpy( sizeof(s15),s15, "" );
160  ztrcat( 5 ,s15, "123456" );
161  assertTrue( eqstr( s15, "1234" ) );
162  ztrcpy( sizeof(s15),s15, "abcdefghijlmnopqrstuvwxyz" );
163  ztrcat( 5 ,s15, "123456" );
164  assertTrue( eqstr( s15, "abcd" ) );
165  }
166 }
167 
168 /** test->ztrins() */
169 void test_ztrins() {
170 {{ /* test::ztrins() */
171  char s30[30]; /* 123456789.123456789.1 -> 21 chars */
172  ztrcpy( sizeof(s30),s30, "====!-----+.........+" );
173  { { ztrins( sizeof(s30),s30, 4, "_2_4_"); } } /* [4] <-> s30+(4) */
174  /* /!\ */
175  assertTrue( eqstr(s30, "====_2_4_!-----+.........+") );
176  assertTrue( 26 == strlen("====_2_4_!-----+.........+") );
177  { { { assertTrue( 21+strlen("_2_4_") == strlen(s30) ); } } }
178 
179  { /* replace JIM with ROMEO */
180  char *p; char poem[] = "JIM, JIM, JIM ... Where are you?";
181  while ( 0!=(p=strstr(poem,"JIM")) ) {
182  strdel( p, strlen("JIM") );
183  ztrins( sizeof(poem),poem, p-poem, "ROMEO" );
184  }
185  assertTrue( eqstr(poem,"ROMEO, ROMEO, ROMEO ... Where ar") );
186 
187  assertTrue( strlen("JIM")<strlen("ROMEO") ); /* -> truncation */
188  assertTrue( strlen("ROMEO, ROMEO, ROMEO ... Where ar") ==
189  strlen("JIM, JIM, JIM ... Where are you?") );
190  }
191 
192  ztrcpy( sizeof(s30),s30, "====!-----+.........+" ); /* -> 21 chars */
193  { { ztrins( sizeof(s30),s30, 00, "________18________"); } } /* [0] */
194  assertTrue( eqstr(s30, "________18________====!-----+") );
195  assertTrue( strlen(s30) == sizeof(s30)-1 ); /* max size */
196 
197  ztrcpy( sizeof(s30),s30, "0123456789" );
198  { { ztrins( /*size->*/1,s30, 0, "" ); } }
199  assertTrue( eqstr(s30, "") ); /* (size==1) ==> (s30[0]==0) */
200  assertTrue( eqstr(s30+1 , "123456789" ) );
201 }}
202  {
203  /* As "ROMEO" is shorter than "JIM" no truncation occurs */
204  char *p; char poem[] = "ROMEO, ROMEO, ROMEO ... Where are you?";
205  while ( 0!=(p=strstr(poem,"ROMEO")) ) {
206  strdel( p, strlen("ROMEO") );
207  ztrins( sizeof(poem),poem, p-poem, "JIM" );
208  }
209  assertTrue( eqstr(poem,"JIM, JIM, JIM ... Where are you?") );
210  }
211 {
212  char s30[30]; /* 123456789.123456789.1 -> 21 chars */
213  ztrcpy( sizeof(s30),s30, "====!-----+.........+" );
214  { { ztrins( sizeof(s30),s30, 20, "________18________"); } } /* [20] */
215  assertTrue( eqstr(s30, "====!-----+.........________1") );
216  assertTrue( strlen(s30) == sizeof(s30)-1 ); /* max size */
217 
218  ztrcpy( sizeof(s30),s30, "====!-----+.........+" ); /* -> 21 chars */
219  { { ztrins( /*size->*/1,s30, 0, "" ); } }
220  assertTrue( eqstr(s30, "") ); /* (size==1) ==> (s30[0]==0) */
221 
222  ztrcpy( sizeof(s30),s30, "====!-----+.........+" ); /* -> 21 chars */
223  { { ztrins( /*size->*/1,s30, 00, "________18________"); } }
224  assertTrue( eqstr(s30, "") ); /* (size==1) ==> (s30[0]==0) */
225 
226  ztrcpy( sizeof(s30),s30, "====!-----+.........+" ); /* -> 21 chars */
227  { { ztrins( /*size->*/1,s30, 0, "" ); } }
228  assertTrue( eqstr(s30, "") ); /* (size==1) ==> (s30[0]==0) */
229 }
230 { /* insertions at the beginning */
231  char s30[30]; /* 123456789.123456789.1 -> 21 */
232  ztrcpy( sizeof(s30),s30, "0123!-----+.........+" );
233  {{{ ztrins( sizeof(s30),s30, 00, "_2__5_"); }}}
234 
235  assertTrue( eqstr(s30, "_2__5_0123!-----+.........+") );
236  assertTrue( strlen(s30) < sizeof(s30) );
237 
238  {{{ ztrins( sizeof(s30),s30, 10, "" ); }}} /* insert nothing */
239  assertTrue( eqstr(s30, "_2__5_0123!-----+.........+") );
240 
241 /**/{{{ ztrins( sizeof(s30),s30, strlen(s30), "?"); }}} /* append letter */
242  assertTrue( eqstr(s30, "_2__5_0123!-----+.........+?") );
243 }
244 { /* insert a big string at the beginning */
245  char s30[30];
246  ztrcpy( sizeof(s30),s30, "0123!-----+.........+" );
247  {{{ ztrins( sizeof(s30),s30, 00, "________18________"); }}}
248 
249  assertTrue( eqstr(s30, "________18________0123!-----+") );
250  assertTrue( strlen(s30) < sizeof(s30) );
251  assertTrue( 30-1 == strlen(s30) );
252 }
253 { /* insert a 1 letter string in every posible position */
254  char str[2]; char s30[30]; char t30[30]; size_t i;
255  str[0]=0; str[1]=0;
256  s30[0]=t30[0]=0;
257 
258  for ( i=0; i<30-1; ++i ) {
259  str[0] = i+'a';
260  ztrcat( sizeof(s30),s30, str);
261  /**/ztrins( sizeof(t30),t30, strlen(t30), str );
262  assertTrue( eqstr(s30,t30) );
263  }
264  /* ztrins()'s at the end has the same effect as ztrcat() */
265 }
266 { /* always the empty string */
267  char s1[1]; /* no space for characters */
268  {
269  ztrcpy( sizeof(s1),s1, "12" );
270  ztrins( sizeof(s1),s1, 0, "a..." );
271  assertTrue( eqstr( s1,"" ) );
272  ztrins( sizeof(s1),s1, 1, "a..." );
273  assertTrue( eqstr( s1,"" ) );
274  ztrins( sizeof(s1),s1, 7, "a..." ); /* out of bounce */
275  assertTrue( eqstr( s1,"" ) );
276  }
277 }
278 { /* insert in every position in a 1 letter string */
279  char s2[2];
280  {
281  ztrcpy( sizeof(s2),s2, "12" );
282  ztrins( sizeof(s2),s2, 0, "a..." );
283  assertTrue( eqstr(s2,"a" ) );
284  }
285  {
286  ztrcpy( sizeof(s2),s2,"12" );
287  assertTrue( eqstr(s2,"1" ) );
288  /**/ztrins( sizeof(s2),s2, 1, "a..." ); /* (size-n)==0 */
289  assertTrue( eqstr(s2,"1" ) );
290  }
291  {
292  ztrcpy( sizeof(s2),s2,"12" );
293  ztrins( sizeof(s2),s2, 2, "a..." );
294  assertTrue( eqstr(s2,"1" ) );
295  }
296 }
297 { /* insert in every position in a 2 letter string */
298  char s3[3];
299  {
300  ztrcpy( sizeof(s3),s3,"12" );
301  assertTrue( eqstr(s3,"12" ) );
302  ztrins( sizeof(s3),s3, 0, "a" );
303  assertTrue( eqstr(s3,"a1" ) );
304  }
305  {
306  ztrcpy( sizeof(s3),s3,"12" );
307  ztrins( sizeof(s3),s3, 0, "ab" );
308  assertTrue( eqstr(s3,"ab" ) );
309  }
310  {
311  ztrcpy( sizeof(s3),s3,"12" );
312  ztrins( sizeof(s3),s3, 0, "ab...." );
313  assertTrue( eqstr(s3,"ab" ) );
314  }
315  {
316  ztrcpy( sizeof(s3),s3,"12" );
317  ztrins( sizeof(s3),s3, 1, "b" );
318  assertTrue( eqstr(s3,"1b" ) );
319  }
320  {
321  ztrcpy( sizeof(s3),s3,"12" );
322  ztrins( sizeof(s3),s3, 1, "bc" );
323  assertTrue( eqstr(s3,"1b" ) );
324  }
325  {
326  ztrcpy( sizeof(s3),s3,"12" );
327  ztrins( sizeof(s3),s3, 1, "bc...." );
328  assertTrue( eqstr(s3,"1b" ) );
329  }
330  { /* test that 'dest' gets 0-terminated */
331  char s15[15]; size_t i;
332  ztrcpy( sizeof(s15),s15, "" );
333  ztrins( 5 ,s15, 2, "123456" );
334  assertTrue( eqstr( s15, "" ) );
335  ztrins( 5 ,s15, 1, "123456" );
336  assertTrue( eqstr( s15, "" ) );
337  ztrins( 5 ,s15, 0, "123456" );
338  assertTrue( eqstr( s15, "1234" ) );
339 
340  ztrcpy( sizeof(s15),s15, "abcdefghijklmnopqrstuvwxyz" );
341  ztrins( 5 ,s15, 0, "" ); /* insert empty string */
342  assertTrue( eqstr( s15, "abcd" ) );
343 
344  ztrcpy( sizeof(s15),s15, "abcdefghijklmnopqrstuvwxyz" );
345  assertTrue( eqstr( s15, "abcdefghijklmn" ) );
346  ztrins( 5 ,s15, 2, "123456" );
347  assertTrue( eqstr( s15, "ab12" ) );
348 
349  ztrcpy( sizeof(s15),s15, "abcdefghijklmnopqrstuvwxyz" );
350  assertTrue( eqstr( s15, "abcdefghijklmn" ) );
351  ztrins( 5 ,s15, 22, "123456" );
352  assertTrue( eqstr( s15, "abcd" ) );
353 
354  for ( i=0; i<35; ++i ) {
355  ztrcpy( sizeof(s15),s15, "abcdefghijklmnopqrstuvwxyz" );
356  assertTrue( eqstr( s15, "abcdefghijklmn" ) );
357  ztrins( 5 ,s15, (5-1)+i, "123456" );
358  assertTrue( eqstr( s15, "abcd" ) );
359  }
360  }
361 }
362 if (1) { /* overlap! */
363  /* I wrote this for fun, as 'overlapping' isn't supporte */
364  char *p; char s20[20];
365  ztrcpy( sizeof(s20),s20, "string INS tail" );
366  p = strstr( s20, "rin");
367  assertTrue( p!=NULL );
368  {
369  {{{ ztrins( sizeof(s20),s20, p-s20 , p ); }}}
370  assertTrue( eqstr( s20, "string INS tailring") );
371  {
372  char t20[20];
373  ztrsub( sizeof(t20),t20, p, UINT_MAX );
374  {{{ ztrins( sizeof(s20),s20, p-s20 , p ); }}}
375  assertTrue( eqstr( s20, "string INS tailring") );
376  assertTrue( 19==strlen( "string INS tailring") );
377  /* no truncation: the tail is short */
378  }
379  /* It's strange: the implementation works */
380  /* when 'insert' is pointer inside 'dest' */
381  /* ************************************** */
382  /* It does NOT work if 'insert' contains 'dest' */
383  }
384 
385  ztrcpy( sizeof(s20),s20, "string INS tail" );
386  p = strstr( s20, "INS");
387  assertTrue( p!=NULL );
388  {
389  {{{ ztrins( sizeof(s20),s20, p-s20 , p ); }}}
390  assertTrue( eqstr( s20, "string INS tailINS ") );
391  assertTrue( 19==strlen( "string INS tailINS ") );
392  /* truncation: very long tail */
393  }
394 }
395 if (1) { /* overlap! */
396  /* I wrote this for fun, as 'overlapping' isn't supporte */
397  char *p; char s[55];
398  char t[55]; char sub[55];
399  char ABC[] = "abcdefghijklmno123456789";
400  size_t N,i,j; N = strlen( ABC );
401  ztrcpy( sizeof(s),s, ABC );
402 
403  for ( i=0; i<N; ++i ) {
404  for ( j=0; j<N; ++j ) {
405  ztrcpy( sizeof(s),s, ABC );
406  ztrcpy( sizeof(t),t, ABC );
407  p = s+j;
408  ztrsub( sizeof(sub),sub, p , UINT_MAX );
409  {{{ ztrins( sizeof(s),s, j , p ); }}}
410  {{{ ztrins( sizeof(t),t, j , sub ); }}}
411  assertTrue( eqstr( s,t ));
412  }
413 
414  for ( j=0; j<N; ++j ) {
415  ztrcpy( strlen(ABC)/2,s, ABC );
416  ztrcpy( strlen(ABC)/2,t, ABC );
417  p = s+j;
418  ztrsub( sizeof(sub),sub, p , UINT_MAX );
419  {{{ ztrins( sizeof(s),s, j , p ); }}}
420  {{{ ztrins( sizeof(t),t, j , sub ); }}}
421  assertTrue( eqstr( s,t ));
422  }
423  }
424 }
425 {
426  #define ZS(x) sizeof(x),x /* Shortcut macro */
427  char s30[30];
428  size_t i,j, N=sizeof(s30);
429  for ( i=0 ; i<N; ++i ) {
430  s30[0] = 0; /* empty string */
431  for ( j=0 ; j<i; ++j ) { /* append */
432  ztrins( ZS(s30), strlen(s30), "?" );
433  }
434  assertTrue( i==strlen(s30) );
435 
436  s30[0] = 0; /* push_front() */
437  for ( j=0 ; j<i; ++j ) { /* insert at front */
438  ztrins( ZS(s30), 0, "!" );
439  }
440  assertTrue( i==strlen(s30) );
441 
442  s30[0] = 0; /* middle -> insert 2 chars */
443  for ( j=0 ; j<i/2; ++j ) {
444  ztrins( ZS(s30), strlen(s30)/3, "?" );
445  ztrins( ZS(s30), strlen(s30)/5, "!" );
446  }
447  assertTrue( 2*(i/2)==strlen(s30) );
448 
449  s30[0] = 0; /* middle -> insert 2 chars */
450  for ( j=0 ; j<i/3; ++j ) {
451  ztrins( ZS(s30), strlen(s30)/7, "?" );
452  ztrins( ZS(s30), strlen(s30)/2, "&!" );
453  }
454  assertTrue( 3*(i/3)==strlen(s30) );
455  }
456  #undef ZS
457 }
458 {
459  char s[] = "mismo";
460  char s12[12];
461  ztrcpy( sizeof(s12),s12, "mismo");
462 
463  for (;;) {
464  ztrins( sizeof(s12),s12, 0, s );
465  if ( strlen(s12) == sizeof(s12)-1 ) { break; }
466  }
467 }
468 }
469 
470 /** test->strdel() */
471 void test_strdel() {
472 {{ /* test::strdel() */
473  char s10[9+1]; char *p; assertTrue( sizeof(s10)>9 );
474  { /* remove 5 leading chars from string 's10' */
475  ztrcpy( sizeof(s10),s10, "123456789.123456789.abcde" );
476  assertTrue( eqstr(s10, "123456789") );
477  { { strdel( s10, 5 ); } }
478  assertTrue( strlen(s10)==4 && eqstr( s10, "6789" ) );
479  }
480  { /* find leading '.' and remove up to it */
481  ztrcpy( sizeof(s10),s10, "1234.abcd.1234.abcd" );
482  if ( NULL!=(p=strchr(s10,'.')) ) { { strdel( s10 , 1+(p-s10) ); } }
483  assertTrue( eqstr( s10, "abcd" ) ); assertTrue( 4==(p-s10) );
484  /* (p-s10) -> length of prefix before '.' */
485  /* 1+(p-s10) -> remove also the '.' */
486  }
487  { /* remove in the middel of 's10' */
488  ztrcpy( sizeof(s10),s10, "0123..678" );
489  { { strdel( s10+4 , 2 ); } } /* s10+4 points inside 's10' */
490  assertTrue( eqstr( s10, "0123678" ) );
491  }
492 }}
493 if (1) {
494  char s10[9+1];
495  { /* remove no char */
496  ztrcpy( sizeof(s10),s10, "123456789.123456789.abcde" );
497  strdel( s10, 0 );
498  assertTrue( strlen(s10)==9 && eqstr( s10, "123456789" ) );
499  }
500  { /* remove every char */
501  ztrcpy( sizeof(s10),s10, "123456789.123456789.abcde" );
502  strdel( s10, UINT_MAX );
503  assertTrue( strlen(s10)==0 && eqstr( s10, "" ) );
504  }
505  { /* remove every char */
506  ztrcpy( sizeof(s10),s10, "123456789.123456789.abcde" );
507  strdel( s10, strlen(s10) );
508  assertTrue( strlen(s10)==0 && eqstr( s10, "" ) );
509  }
510  if (0) { /* this crashes sometimes */
511  /* the OS protects the memory block at address 0 (NULL) */
512  char *p=NULL;
513  ztrcpy( sizeof(s10),s10, NULL );
514  strdel( p, 0 );
515  assertTrue( memcmp( p,s10, sizeof(s10)-1 ) );
516  }
517 }
518 }
519 
520 /** test->ztrsub() */
521 void test_ztrsub() {
522 {{ /* test::ztrsub() .123456789 */
523  char str[] = ".123456789.abcdefghi.";
524  char sub[22];
525  assertTrue( strlen(str) == 21 && sizeof(sub)==22 );
526  { /* first 5 chars from 'str' */
527  ztrsub( sizeof(sub),sub , str,5 );
528  assertTrue( eqstr( sub , ".1234" ) );
529  }
530  { /* all chars from 'str' [similar to ztrcpy()] */
531  ztrsub( sizeof(sub),sub , str,UINT_MAX );
532  assertTrue( eqstr( sub , str ) );
533  }
534  { /* a substring taken from the middle of 'str' */
535  ztrsub( sizeof(sub),sub , str+10,7 );
536  assertTrue( eqstr( sub , ".abcdef" ) );
537  assertTrue( eqstr( str+10 , ".abcdefghi." ) );
538  assertTrue( 7 == strlen( ".abcdef" ) );
539  }
540  { /* 0 length substring produces the empty string */
541  ztrsub( sizeof(sub),sub , str,000 );
542  assertTrue( eqstr( sub , "" ) );
543  }
544 }}
545 
546 { /* 800 is out of bounce */
547  char s3[3];
548  ztrsub( sizeof(s3),s3, ".123456789.abcdefghi."+(7), 800 );
549  assertTrue( eqstr( s3 , "78" ) );
550 }
551 }
552 
553 /** test->strltrim() */
555 {{ /* test::strltrim() */
556  char s[] = " la mona es una loca ";
557  assertTrue( eqstr( "la mona es una loca " , strltrim( s, ' ' ) ) );
558  {
559  char t[] = "XXXla mona es una loca ";
560  assertTrue( eqstr( "la mona es una loca " , strltrim( t, 'X' ) ) );
561  assertTrue( eqstr( "XXXla mona es una loca " , t ) ); /* no change */
562  }
563 }}
564 {
565  char s[] = "la mona loca";
566  assertTrue( s==strltrim( s, ' ' ) );
567  assertTrue( s==strltrim( s, 000 ) );
568 }
569 }
570 
571 /** test->strrtrim() */
573 {{ /* test::strrtrim() */
574  char s[] = " la mona es una loca ";
575  assertTrue( eqstr( " la mona es una loca" , strrtrim( s, ' ' ) ) );
576  {
577  char t[] = " la mona es una loca XXX";
578  assertTrue( eqstr( " la mona es una loca " , strrtrim( t, 'X' ) ) );
579  assertFalse( eqstr( "XXXla mona es una loca ", t ) );
580  }
581 }}
582 {
583  char t[] = " la mona es una loca ";
584  assertTrue( eqstr( " la mona es una loca " , strrtrim( t, 'X' ) ) );
585  assertTrue( eqstr( " la mona es una loca " , strrtrim( t, 'l' ) ) );
586  assertTrue( eqstr( " la mona es una loca " , strrtrim( t, 'a' ) ) );
587 }
588 {
589  char t[] = " ";
590  assertTrue( eqstr( "" , strltrim( t, ' ' ) ) );
591  assertTrue( eqstr( " " , strrtrim( t, 'X' ) ) );
592  assertTrue( eqstr( "" , strrtrim( t, ' ' ) ) );
593 }
594 {
595  char t[] = " ";
596  assertTrue( eqstr( "" , strrtrim( t, ' ' ) ) );
597  assertTrue( eqstr( "" , strrtrim( t, 'X' ) ) );
598  assertTrue( eqstr( "" , strltrim( t, ' ' ) ) );
599 }
600 { /* 123. */
601  char t[] = " ";
602  char s[] = " "; s[0] = 0;
603  strrtrim( t, 'X' ); assertTrue( t[0] == ' ' );
604  strrtrim( t, ' ' ); assertTrue( t[0] == 0 );
605  assertTrue( 0 == memcmp( s,t , sizeof(s) ) );
606  assertTrue( sizeof(s) == 4 );
607 }
608 { /* 123. */
609  char s[] = " ";
610  char *t;
611  t = strltrim( s, 'X' ); assertTrue( t==s );
612  t = strltrim( s, ' ' ); assertTrue( t==s+3 );
613  assertTrue( sizeof(s) == 4 );
614 }
615 { /* 12. */
616  char t[] = " ";
617  char s[] = " "; s[0]=0;
618  strrtrim( t, 'X' ); assertTrue( t[0] == ' ' );
619  strrtrim( t, ' ' ); assertTrue( t[0] == 0 );
620  assertTrue( 0 == memcmp( s,t , sizeof(s) ) );
621  assertTrue( sizeof(s) == 3 );
622 }
623 { /* 12. */
624  char s[] = " ";
625  char *t;
626  t = strltrim( s, 'X' ); assertTrue( t==s );
627  t = strltrim( s, ' ' ); assertTrue( t==s+2 );
628  assertTrue( sizeof(s) == 3 );
629 }
630 { /* 1. */
631  char t[] = " ";
632  char s[] = " "; s[0]=0;
633  strrtrim( t, 'X' ); assertTrue( t[0] == ' ' );
634  strrtrim( t, ' ' ); assertTrue( t[0] == 0 );
635  assertTrue( 0 == memcmp( s,t , sizeof(s) ) );
636  assertTrue( sizeof(s) == 2 );
637 }
638 { /* 1.*/
639  char s[] = " ";
640  char *t;
641  t = strltrim( s, 'X' ); assertTrue( t==s );
642  t = strltrim( s, ' ' ); assertTrue( t==s+1 );
643  assertTrue( sizeof(s) == 2 );
644 }
645 {
646  char s[] = "1234567" ;
647  assertTrue( eqstr( strrtrim( s, 0 ), "1234567" ) );
648  assertTrue( sizeof(s) == 8 );
649 }
650 { /* 1. */
651  char s[] = " ";
652  assertTrue( s == strltrim( s, 0 ) );
653  assertTrue( NULL == strltrim( NULL,'X' ) );
654 
655  assertTrue( eqstr( strrtrim( s, 0 ), " " ) );
656  assertTrue( sizeof(s) == 2 );
657 }
658 }
659 
660 /** test->strtrim() */
661 void test_strtrim() {
662 {{ /* test::strtrim() */
663  char s[] = " la mona es una loca ";
664  assertTrue( eqstr( "la mona es una loca" , strtrim( s, ' ' ) ) );
665 }}
666 }
667 
668 /** Test->memczap() */
669 void test_memczap() {
670 {{ /* test::memczap() */
671  char m30[30]; size_t n;
672  strcpy( m30, "-!--!--!-" ); assertTrue( strlen(m30)==9 );
673  { /* 12345678 */
674  n = memczap(strlen(m30),m30, '-' ); /* ZAP '-' */
675  assertTrue( n==3 && 3==(9-6) );
676  assertTrue( 0==memcmp(m30, "!!!", strlen("!!!") ) );
677 
678  assertTrue( 0!=strcmp(m30, "!!!" ) );
679  /* ==> */ m30[n] = 0; /* <== */
680  assertTrue( 0==strcmp(m30, "!!!" ) );
681  }
682  strcpy( m30, "(*:**-*)" ); assertTrue( strlen(m30)==8 );
683  { /* 12345678 */
684  n = memczap(strlen(m30),m30, '*'); /* ZAP '*' */
685  assertTrue( n==4 && 4==(8-4) );
686  assertTrue( 0==memcmp(m30, "(:-)", strlen("(:-)") ) );
687  assertTrue( 0==memcmp(m30, "(:-)*-*)", strlen(m30) ) );
688  }
689  strcpy( m30, "*:**-*" ); assertTrue( strlen(m30)==6 );
690  { /* 123456 */
691  n = memczap(strlen(m30),m30, '*'); /* ZAP '*' */
692  assertTrue( n==2 && 2==(6-4) );
693  assertTrue( 0==memcmp(m30, ":-", strlen(":-") ) );
694  }
695 }}
696 {
697  char m30[30];
698  m30[0] = 0;
699  assertTrue( 0==memczap(strlen(m30),m30, '*') );
700  strcpy( m30, "*:**-*" );
701  assertTrue( strlen(m30)==memczap(strlen(m30),m30, '?') );
702 
703  memset( m30, '!', sizeof(m30) );
704  assertTrue( 0==memcmp(m30, "!!!" "!!!",3+3) );
705 
706  strcpy( m30, " " );
707  assertTrue( 0==memczap(strlen(m30),m30, ' ') );
708  assertTrue( 0==memcmp(m30, " \0",2) );
709  assertTrue( 0==memcmp(m30, " \0!" "!!!",3+3) );
710 
711  strcpy( m30, " " );
712  assertTrue( 0==memczap(strlen(m30),m30, ' ') );
713  assertTrue( 0==memcmp(m30, " \0",3) );
714  assertTrue( 0==memcmp(m30, " \0" "!!!",3+3) );
715 
716  memset( m30, 0, sizeof(m30) );
717  assertTrue( 0==memczap(strlen(m30),m30, 0) );
718  {
719  char m[] = "123456789" "\0" "123456789" "\0";
720  assertTrue( 21==sizeof(m));
721 
722  memcpy( m30, m, sizeof(m) );
723  assertTrue( 21-2==memczap(sizeof(m),m30, '1') );
724 
725  memcpy( m30, m, sizeof(m) );
726  assertTrue( 21-3==memczap(sizeof(m),m30, '\0') );
727  }
728  /* printf( "%d\n", memczap(m30, '1', sizeof(m))); |*/
729 }
730 }
731 
732 /** test->strpfx() */
733 void test_strpfx() {
734 {{ /* test::strpfx() */
735  assertTrue( strpfx( "123456789.123456789.", "12345678" ) );
736  assertTrue( strpfx( "123456789.123456789.", "" ) );
737 
738  assertFalse( strpfx( "12345678" , "123456789.123456789." ) );
739 }}
740  assertTrue( strpfx( "123456789.123456789.", "1" ) );
741 }
742 
743 /** test->strsffx() */
744 void test_strsffx() {
745 {{ /* test::strsffx() */
746  assertTrue( strsffx( "123456789.123456789.", "6789." ) );
747  assertTrue( strsffx( "123456789.123456789.", "" ) );
748 
749  assertFalse( strsffx( "6789.", "123456789.123456789." ) );
750 }}
751  assertTrue( strsffx( "123456789.123456789.", "." ) );
752 }
753 
754 /** test->strrspn() */
755 void test_strrspn() {
756 {{ /* test::strrspn( */
757  size_t leading_digits = strrspn( "123456789.123456789.", '0','9' );
758  assertTrue( 9 == leading_digits );
759  assertTrue( 15 == strrspn( "122333444455555.123456789.", '0','9' ) );
760 }}
761  assertTrue( 0 == strrspn( "123456789.123456789.", '9','0' ) );
762  assertTrue( 1 == strrspn( "123456789.123456789.", '1','1' ) );
763  assertTrue( 0 == strrspn( "", 'a','z' ) );
764 }
765 
766 /** test->strxltn1() */
768 {{ /* test::strxacct() */
769  char Atilde[] = "ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ";
770  char Asimple[] = "AAAAAAECEEEEIIIIDNOOOOOx0UUUUYPsaaaaaaeceeeeiiiidnooooo/0uuuuypy";
771 
772  char Astr[ sizeof(Atilde) ];
773  strcpy( Astr, Atilde );
774 
775  assertTrue( 0==strcmp( Asimple, strxacct(Astr) ) );
776 }}
777 {{ /* test::strxltn1() */
778  char Atilde[] = "ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ";
779  char Asimple[] = "AAAAAAECEEEEIIIIDNOOOOOx0UUUUYPsaaaaaaeceeeeiiiidnooooo/0uuuuypy";
780 
781  assertTrue( 'A' == strxltn1('Á') ); assertTrue( 'N' == strxltn1('Ñ') );
782  assertTrue( 'Y' == strxltn1('Ý') ); assertTrue( 'D' == strxltn1('Ð') );
783 
784  assertTrue( 's' == strxltn1('ß') ); assertTrue( 'P' == strxltn1('Þ') );
785  assertTrue( 'x' == strxltn1('×') ); assertTrue( '/' == strxltn1('÷') );
786  assertTrue( '0' == strxltn1('Ø') ); assertTrue( 'd' == strxltn1('ð') );
787 
788  assertTrue( Atilde != Asimple );
789 }}
790 {
791  /* Copia del código que está arriba */
792  const char *Atilde = "ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ";
793  const char *Asimple = "AAAAAAECEEEEIIIIDNOOOOOx0UUUUYPsaaaaaaeceeeeiiiidnooooo/0uuuuypy";
794 
795  char Astr[ 255-192+1 ]; *Astr = 0;
796  strcpy( Astr, Atilde );
797 
798  assertTrue( 0==strcmp( Asimple, strxacct(Astr) ) );
799  assertTrue( strlen(Asimple)==strlen(Astr) );
800 
801  #ifdef __GNUC__ /* Esto es raro ... */
802  assertTrue( (unsigned char)('À')==192 );
803  assertFalse( (char)('À')==192 );
804  assertFalse( (unsigned) ('À')==192 );
805  /* http://gcc.gnu.org/onlinedocs/cpp/Common-Predefined-Macros.html */
806  #endif
807 
808 /* std::cout << 'À' << "\n" << Atilde << "\n" << Astr << "\n"; */
809 }
810 {
811  /* verifica que la implementación de strxltn1(char) funciona */
812  const char *Atilde = "ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ";
813  const char *Asimple = "AAAAAAECEEEEIIIIDNOOOOOx0UUUUYPsaaaaaaeceeeeiiiidnooooo/0uuuuypy";
814 
815 
816  char Astr[ 255-192+1 ];
817  char* p = Astr;
818  strcpy( Astr, Atilde );
819 
820  while ( (*p)!=0 ) {
821  *p = strxltn1(*p) ;
822  ++p;
823  /* http://stackoverflow.com/questions/14094621/ */
824  }
825  assertTrue( 0==strcmp( Asimple, strxacct(Astr) ) );
826  assertTrue( strlen(Asimple)==strlen(Astr) );
827  assertTrue( 'n' == strxltn1('ñ') );
828 }
829 }
830 
831 /** test -> (size==1) ==> *dest=0 forall( ztr???() ) */
832 void test_zsize1() {
833 {{ /* test::zsize1() */
834  char dest[15];
835  {
836  ztrcpy( sizeof(dest),dest, "012345" );
837  assertTrue( eqstr( dest, "012345" ) );
838  ztrins( /*size->*/ 1,dest, 0, "abc" );
839  assertTrue( eqstr( dest, "" ) && eqstr( 1+dest, "12345" ) );
840  }
841  {
842  ztrcpy( sizeof(dest),dest, "012345" );
843  assertTrue( eqstr( dest, "012345" ) );
844  ztrins( /*size->*/ 3,dest, 0,"abc" );
845  assertTrue( eqstr( dest, "ab" ) && eqstr( 3+dest,"345" ) );
846  }
847 }}
848 {
849  char dest[15];
850  {/* ztrcpy() */
851  ztrcpy( sizeof(dest),dest, "012345" );
852  assertTrue( eqstr( dest, "012345" ) );
853  ztrcpy( (001)*(001),dest, "abc" );
854  assertTrue( eqstr( dest, "" ) && eqstr( 1+dest, "12345" ) );
855  }
856  {/* ztrcat() */
857  ztrcat( sizeof(dest),dest, "012345" );
858  assertTrue( eqstr( dest, "012345" ) );
859  ztrcat( (001)*(001),dest, "abc" );
860  assertTrue( eqstr( dest, "" ) && eqstr( 1+dest, "12345" ) );
861  }
862  {/* ztrins() */
863  ztrcpy( sizeof(dest),dest, "012345" );
864  assertTrue( eqstr( dest, "012345" ) );
865  ztrins( (001)*(001),dest, 0,"abc" );
866  assertTrue( eqstr( dest, "" ) && eqstr( 1+dest, "12345" ) );
867  }
868  {/* ztrsub() */
869  ztrcpy( sizeof(dest),dest, "012345" );
870  assertTrue( eqstr( dest, "012345" ) );
871  ztrsub( (001)*(001),dest, "abc",0 );
872  assertTrue( eqstr( dest, "" ) && eqstr( 1+dest, "12345" ) );
873  }
874 }
875 
876 { /* char[1] Mandatory string size compliance */
877  char s1[1];
878  s1[0]='?'; ztrcpy( sizeof(s1),s1, "1234" );
879 
880  s1[0]='?'; ztrcat( sizeof(s1),s1, "1234" );
881  assertTrue( s1[0]==0 );
882 
883  s1[0]='?'; ztrins( sizeof(s1),s1, 0,"1234" );
884  assertTrue( s1[0]==0 );
885 
886  s1[0]='?'; ztrsub( sizeof(s1),s1, "1234",17 );
887  assertTrue( s1[0]==0 );
888 }
889 
890 { /* char[2] Mandatory string size compliance */
891  char s2[2];
892  memset( s2, '?', sizeof(s2) );
893  ztrcpy( sizeof(s2),s2, "1234" );
894  assertTrue( s2[1]==0 );
895 
896  memset( s2, '?', sizeof(s2) );
897  ztrcat( sizeof(s2),s2, "1234" );
898  assertTrue( s2[1]==0 );
899 
900  memset( s2, '?', sizeof(s2) );
901  ztrins( sizeof(s2),s2, 0,"1234" );
902  assertTrue( s2[1]==0 );
903 
904  memset( s2, '?', sizeof(s2) );
905  ztrsub( sizeof(s2),s2, "1234",17 );
906  assertTrue( s2[1]==0 );
907 }
908 
909 { /* char[3] Mandatory string size compliance */
910  char s3[3];
911  memset( s3, '?', sizeof(s3) );
912  ztrcpy( sizeof(s3),s3, "1234" );
913  assertTrue( s3[2]==0 );
914 
915  memset( s3, '?', sizeof(s3) );
916  ztrcat( sizeof(s3),s3, "1234" );
917  assertTrue( s3[2]==0 );
918 
919  memset( s3, '?', sizeof(s3) );
920  ztrins( sizeof(s3),s3, 0,"1234" );
921  assertTrue( s3[2]==0 );
922 
923  memset( s3, '?', sizeof(s3) );
924  ztrsub( sizeof(s3),s3, "1234",17 );
925  assertTrue( s3[2]==0 );
926 }
927 
928 { /* char[7] Mandatory string size compliance */
929  char s7[7];
930  memset( s7, '?', sizeof(s7) );
931  ztrcpy( sizeof(s7),s7, "1234abcd" );
932  assertTrue( s7[6]==0 );
933 
934  memset( s7, '?', sizeof(s7) );
935  ztrcat( sizeof(s7),s7, "1234abcd" );
936  assertTrue( s7[6]==0 );
937 
938  memset( s7, '?', sizeof(s7) );
939  ztrins( sizeof(s7),s7, 0,"1234abcd" );
940  assertTrue( s7[6]==0 );
941 
942  memset( s7, '?', sizeof(s7) );
943  ztrsub( sizeof(s7),s7, "1234abcd",17 );
944  assertTrue( s7[6]==0 );
945 }
946 
947 }
948 
949 /** test -> "string"[0] == 's' ??? */
951 {{ /* test."string"[?] */
952  assertTrue( "string"[0] == 's' );
953 }}
954 {
955  assertTrue( "string"[1] == 't' );
956  assertTrue( "string"[2] == 'r' );
957  assertTrue( "string"[3] == 'i' );
958  assertTrue( "string"[4] == 'n' );
959  assertTrue( "string"[5] == 'g' );
960  assertTrue( "string"[6] == 000 );
961 }
962 {{ /* test::psz() */
963  char CHK[] = "Chuck";
964  char chk[] = { 'C', 'h', 'u', 'c', 'k', 0 };
965  assertTrue( sizeof(CHK) == sizeof(chk) );
966  assertTrue( strlen(CHK) == strlen(chk) );
967 
968  /* DIM() no se puede implementar con plantillas... */
969  #define DIM(V) (sizeof(V) / sizeof(*V)) /* *V == *(V+0) == V[0] */
970 
971  assertTrue( DIM(CHK) == DIM(chk) );
972  assertTrue( DIM(CHK) == 1+strlen(chk) );
973 }}
974  #undef DIM
975 }
976 
977 int main() {
978  printf( "test_ztring.c [uUnit.h] with CHAR_BIT==%d\n", CHAR_BIT );
979 
980  #define do_test( NAME ) printf( "test->" #NAME "()\n" ); test_##NAME()
981 
982  do_test( ztrcpy );
983  do_test( ztrcat );
984 
985  do_test( ztrins );
986  do_test( strdel );
987  do_test( ztrsub );
988 
989  do_test( strltrim );
990  do_test( strrtrim );
991  do_test( strtrim );
992 
993  do_test( memczap );
994 
995  do_test( strpfx );
996  do_test( strsffx );
997  do_test( strrspn );
998 
999  do_test( strxltn1 );
1000  do_test( zsize1 );
1001  do_test( subindex );
1002 
1003  return 0;
1004 }
1005 
1006 /* EOF: test_ztring.c */
#define do_test(NAME)
size_t memczap(size_t size, void *mem, int ch)
Removes every ocurrence of 'ch' from 'mem'.
Definition: ztring.c:306
void test_strdel()
test->strdel()
Definition: test_ztring.c:471
char * strtrim(char *str, char tr)
return strrtrim( strltrim(s,tr),tr ).
Definition: ztring.c:288
#define DIM(V)
char * strxacct(char *str)
Uses strxltn1() to convert all letters in 'str'.
Definition: ztring.c:445
#define assertTrue(cond)
(cond ? () : cout << "cond" )
Definition: uUnit.h:79
void test_strrtrim()
test->strrtrim()
Definition: test_ztring.c:572
void test_strtrim()
test->strtrim()
Definition: test_ztring.c:661
int strsffx(const char *str, const char *suffix)
Returns '1' if 'suffix' is a suffix of 'str'.
Definition: ztring.c:393
#define ztrcat(dest, src)
void test_ztrins()
test->ztrins()
Definition: test_ztring.c:169
size_t strrspn(const char *str, char a, char z)
Get span until character in character range '[a..z]'.
Definition: ztring.c:421
A few string functions to enhance C's <string.h> library.
int eqstr(const char *a, const char *b)
a==b?
Definition: test_ztring.c:20
#define ZS(x)
void test_ztrcpy()
test->ztrcpy()
Definition: test_ztring.c:25
#define assertFalse(cond)
(!(cond) ? () : cout << "!" << (cond)" )
Definition: uUnit.h:81
char * strrtrim(char *str, char tr)
Removes from 'str' all trailing characters that are equal to 'tr'.
Definition: ztring.c:260
void test_strxltn1()
test->strxltn1()
Definition: test_ztring.c:767
void test_ztrcat()
test->ztrcat()
Definition: test_ztring.c:107
void test_strsffx()
test->strsffx()
Definition: test_ztring.c:744
void test_memczap()
Test->memczap()
Definition: test_ztring.c:669
void test_subindex()
test -> "string"[0] == 's' ???
Definition: test_ztring.c:950
char * strdel(char *dest, size_t len)
Deletes the leading 'len' characters from 'str'.
Definition: ztring.c:200
char * strltrim(const char *str, char tr)
Returns a pointer to the first character in 'str' different from 'tr'.
Definition: ztring.c:244
char * ztrsub(size_t size, char *dest, const char *src, size_t len)
Copies the first 'len' characters from 'src' to 'dest'.
Definition: ztring.c:222
void test_zsize1()
test -> (size==1) ==> *dest=0 forall( ztr???() )
Definition: test_ztring.c:832
int main()
Definition: test_ztring.c:977
void test_strpfx()
test->strpfx()
Definition: test_ztring.c:733
int strpfx(const char *str, const char *prefix)
Returns '1' if 'prefix' is a prefix of 'str'.
Definition: ztring.c:380
void test_strltrim()
test->strltrim()
Definition: test_ztring.c:554
char strxltn1(char accented_latin_1)
Translates characters in range [192<–>192+63] into letters or ASCII symbols that look similar...
Definition: ztring.h:86
#define ztrcpy(dest, src)
char * ztrins(size_t size, char *dest, size_t i, const char *insert)
Inserts string 'insert' into 'dest' at position 'n'.
Definition: ztring.c:144
void test_strrspn()
test->strrspn()
Definition: test_ztring.c:755
[u]Micro module for [Unit] program testing.
void test_ztrsub()
test->ztrsub()
Definition: test_ztring.c:521