String routines to complement <string> && <cstring>:
strnum_test.cpp
Go to the documentation of this file.
1 // strnum_test.cpp (c) 2019 adolfo.dimare@gmail.com && eduardo.j.piza@gmail.com
2 // strnum_test.cpp (c) 2019 adolfo.dimare@gmail.com && eduardo.j.piza@gmail.com
3 
4 /** \file strnum_test.cpp
5  \brief Test program for \c strnum.cpp
6 
7  \author adolfo.dimare@gmail.com
8  \author eduardo.j.piza@gmail.com
9  \date 2019
10 */
11 
12 #include "strnum.h"
13 #include "uUnit.h" // assertTrue()
14 #include <iostream> // std::cout
15 
16 /// Test program.
17 int main( const int argc , const char* argv[] ) {
18  std::cout << remove_dir_name(argv[0]) << std::endl;
19 
20  /// Simple macro to define && execute a test
21  #define exec_TEST(t) void t(); t();
22  if (true) {
33  }
34  else {
35  }
36  #undef exec_TEST
37 }
38 
39 /// Shortcut macro to compare 2 C strings using strcmp()
40 #define eqstr(a,b) ( 0==strcmp(a,b) )
41 
42 /// \c test->atou_ndigit().
44 {{ // test::atou_ndigit()
45  char str[128] = "IMG_20190112_151835.jpg";
46  unsigned long num[12];
47  unsigned long chk[] = { 2019,01,12,15,18,35,0 };
48  const char *p = str; // str == error
49  unsigned i=1;
50  num[0] = atou_ndigit( &p,4 ); // [ & ] == Ughh
51  assertTrue( num[0] == 2019 );
52  while (*p!=0) {
53  num[i] = atou_ndigit( &p,2 ); // & !!!
54  assertTrue( chk[i] == num[i] );
55  ++i;
56  }
57  assertTrue( i==7 );
58  num[7] = atou_ndigit( &p,1 );
59  assertTrue( num[7]==0 && *p==0 );
60 }}
61 {
62  const char *p=0;
63  unsigned long res = atou_ndigit(&p,2);
64  assertTrue( 0 == res );
65 }
66 {
67  char str[128] = "IMG_2019.0112_151835.jpg";
68  const char *p=str;
69  assertTrue( 2019 == atou_ndigit(&p,8) );
70  assertTrue( 112 == atou_ndigit(&p,6) );
71  assertTrue( 151 == atou_ndigit(&p,3) );
72  assertTrue( 835 == atou_ndigit(&p,3) );
73  assertTrue( 0 == atou_ndigit(&p,1) );
74 }
75 {
76  char str[128] = "";
77  const char *p;
78  p=str; assertTrue( 0 == atou_ndigit(&p,8) );
79  p=(0); assertTrue( 0 == atou_ndigit(&p,8) );
80  p=NULL; assertTrue( 0 == atou_ndigit(&p,8) );
81  assertTrue( 0 == atou_ndigit(NULL,8) );
82  assertTrue( 0 == atou_ndigit( (0),8) );
83 }
84 {
85  char str[128] = "IMG_2018-02.bak";
86  const char *p=str;
87  assertTrue( 2018 == atou_ndigit(&p,8) );
88  assertTrue( 2 == atou_ndigit(&p,6) );
89  assertTrue( 0 == atou_ndigit(&p,3) );
90  assertTrue( 0 == atou_ndigit(&p,1) );
91 }
92 }
93 
94 
95 template <size_t DIM=12>
96 struct N_vec {
97  std::string str;
98  size_t N;
99  int vec[DIM];
100  bool check_ok() const;
101 };
102 
103 template <size_t DIM>
104 bool N_vec<DIM>:: check_ok() const {
105  size_t dim_ret = sizeof(vec)/sizeof(*vec);
106  intmax_t ret_vec[ dim_ret ];
107  size_t ret = atoi_vec(str.c_str(), ret_vec, dim_ret);
108  if ( ret!= N ) { return false; }
109  for ( size_t i=0; i<N; ++i ) {
110  if ( ret_vec[i] != vec[i] ) { return false; }
111  }
112  return true;
113 }
114 
115 /// test -> atoi_vec()
117  assertTrue( N_vec<12>( { "(5,4)->(N,lambda)", 2, {5,4} } ).check_ok() );
118  assertTrue( N_vec<>( { "[5,-00]->9", 3, { 5,0, 9 } } ).check_ok() );
119  assertTrue( N_vec<>( { "N,lambda->5,1 (1,1,2,2)->4", 7, { 5,1, 1,1,2,2, 4 } } ).check_ok() );
120 
121  assertTrue( N_vec<>( { "...(5,4)->(N,lambda)", 2, {5,4} } ).check_ok() );
122  assertTrue( N_vec<>( { "5,4]->9", 3, { 5,4, 9 } } ).check_ok() );
123  assertTrue( N_vec<>( { "55,101 (1,1,2,2)->4", 7, { 55,101, 1,1,2,2, 4 } } ).check_ok() );
124 
125  assertTrue( N_vec<>( { "oiOEI!&(*_)->-", 0, { 12,101, 1,1,2,2, 4 } } ).check_ok() );
126  assertTrue( N_vec<>( { "", 0, { 12,101, 1,1,2,2, 4 } } ).check_ok() );
127  assertTrue( N_vec<>( { "...(5,4)->(N,lambda)", 2, {5,4} } ).check_ok() );
128 
129  assertTrue( N_vec<>( { "5,-4->(N,lambda)", 2, {5,-4} } ).check_ok() );
130  assertTrue( N_vec<>( { "2019-09-23->9", 4, {2019,-9,-23,9} } ).check_ok() );
131  assertTrue( N_vec<>( { "x,-4->(N,lambda)", 1, {-4} } ).check_ok() );
132  assertTrue( N_vec<>( { "1 2 3 4 5 6 7 8 9 -0 -1 -2 -3", 12, {1,2,3,4,5,6,7,8,9,0,-1,-2} } ).check_ok() );
133 
134  {{{ }}}
135 
136  assertTrue( N_vec<>( { "(-005,-4)->(N,lambda)-", 2, {-5,-4} } ).check_ok() );
137  assertTrue( N_vec<>( { "[5,4]-9", 3, { 5,4, -9 } } ).check_ok() );
138  assertTrue( N_vec<>( { "N,lambda->5,1 (1,1,-2,2)->4", 7, { 5,1, 1,1,-2,2, 4 } } ).check_ok() );
139 
140  assertTrue( N_vec<>( { "..[-005,4)->(N,lambda)", 2, {-5,4} } ).check_ok() );
141  assertTrue( N_vec<>( { "005,4]->9", 3, { 5,4, 9 } } ).check_ok() );
142  assertTrue( N_vec<>( { "-00055,101 (1,1,2,2)->4", 7, { -55,101, 1,1,2,2, 4 } } ).check_ok() );
143 
144  assertTrue( N_vec<>( { "oiOEI*!&(*_)->", 0, { 12,101, 1,1,2,2, 4 } } ).check_ok() );
145  assertTrue( N_vec<>( { "", 0, { 12,101, 1,1,2,2, 4 } } ).check_ok() );
146  assertTrue( N_vec<>( { "...(5,4)->(N,lambda)", 2, {5,4} } ).check_ok() );
147 
148 {{ // test::atoi_vec()
149  char str[] = " 000 6 -21 \t 5 \r\n 5 5 - 3 3 3 2 -";
150  int RES[] = { 000,6,-21, 5, 5,5, 3,3,3,2 };
151  intmax_t VEC[24], N;
152  assertTrue( 24 == sizeof(VEC)/sizeof(*VEC) );
153  assertTrue( sizeof(RES) < sizeof(VEC) );
154 
155  const size_t dim_VEC = sizeof(VEC)/sizeof(*VEC);
156  const size_t dim_RES = sizeof(RES)/sizeof(*RES);
157 
158  for ( size_t i=0; i<((dim_VEC)); ++i ) { VEC[i] = 0; }
159  /*=/=*/ N = atoi_vec( str,VEC, dim_VEC );
160 
161  size_t i,k; {
162  for ( i=k=0; i<dim_RES; ++i,++k ) {
163  assertTrue( RES[i] == VEC[i] );
164  }
165  for ( i=k; i<((dim_VEC)); ++i ) {
166  assertTrue( VEC[i] == 0 );
167  }
168  assertTrue( N == dim_RES );
169  }
170 }}
171  {
172  intmax_t VEC[24], N=0;
173  const size_t dim_VEC = sizeof(VEC)/sizeof(*VEC);
174  char str[] = "0012345 \t \r\n \f 99 ";
175  /*=/=*/ N = atoi_vec( str,VEC, dim_VEC );
176  assertTrue( VEC[0] == 12345 );
177  assertTrue( VEC[1] == 99 );
178  assertTrue( N == 2 );
179 
180  char xtr[] = "0012345.. $)(*^@!_.. 99 ";
181  /*=/=*/ N = atoi_vec( xtr,VEC, dim_VEC );
182  assertTrue( VEC[0] == 12345 );
183  assertTrue( VEC[1] == 99 );
184  assertTrue( N == 2 );
185  }
186  { // check upper limit / dimension of VEC[]
187  const size_t DIM = 24, TEN=10;
188  intmax_t VEC[DIM];
189  for ( size_t i=0; i<DIM; ++i ) { VEC[i] = 0; }
190 
191  char str[] = "0,1,2,3,4,5,6,7,8,9 | -9 8 -7 6 -5 4 -3 2 1 -0 =";
192  size_t N;
193  /*=/=*/ N = atoi_vec( str,VEC, TEN );
194  assertTrue( TEN == N );
195 
196  for ( size_t i=0; i<TEN; ++i ) {
197  assertTrue( VEC[i] == intmax_t(i) );
198  }
199  for ( size_t i=TEN; i<DIM; ++i ) {
200  assertTrue( VEC[i] == 0 );
201  }
202  {
203  VEC[0] = 111;
204  /*=/=*/ N = atoi_vec( str,VEC, 0 );
205  assertTrue( VEC[0] == 111 );
206  }
207  }
208  {
209  bool ret=true;
210  N_vec<> t[12];
211 
212  t[0] = { "...(5,4)->(N,lambda)", 2, {5,4} };
213  t[1] = { "5,4]->9", 3, { 5,4, 9 } };
214  t[2] = { "55,101 (1,1,2,2)->4", 7, { 55,101, 1,1,2,2, 4 } };
215  {
216  assertTrue( ret == t[0].check_ok() );
217  assertTrue( ret == t[1].check_ok() );
218  assertTrue( ret == t[2].check_ok() );
219  }
220  }
221 }
222 
223 
224 #include "strnum.h" // atou_vec()
225 
226 struct N_vecU {
227  std::string str;
228  size_t N;
229  uintmax_t vec[12];
230  bool check_ok() const;
231 };
232 
233 bool N_vecU:: check_ok() const {
234  size_t dim_ret = sizeof(vec)/sizeof(*vec);
235  uintmax_t ret_vec[ dim_ret ];
236  size_t ret = atou_vec(str.c_str(), ret_vec, dim_ret);
237  if ( ret!= N ) { return false; }
238  for ( size_t i=0; i<N; ++i ) {
239  if ( ret_vec[i] != vec[i] ) { return false; }
240  }
241  return true;
242 }
243 
244 /// test -> atou_vec()
246  assertTrue( N_vecU( { "(5,4)->(N,lambda)", 2, {5,4} } ).check_ok() );
247  assertTrue( N_vecU( { "[5,4]->9", 3, { 5,4, 9 } } ).check_ok() );
248  assertTrue( N_vecU( { "N,lambda->5,1 (1,1,2,2)->4", 7, { 5,1, 1,1,2,2, 4 } } ).check_ok() );
249 
250  assertTrue( N_vecU( { "...(5,4)->(N,lambda)", 2, {5,4} } ).check_ok() );
251  assertTrue( N_vecU( { "5,4]->9", 3, { 5,4, 9 } } ).check_ok() );
252  assertTrue( N_vecU( { "55,101 (1,1,2,2)->4", 7, { 55,101, 1,1,2,2, 4 } } ).check_ok() );
253 
254  assertTrue( N_vecU( { "oiOEI*!&(*_)->", 0, { 12,101, 1,1,2,2, 4 } } ).check_ok() );
255  assertTrue( N_vecU( { "", 0, { 12,101, 1,1,2,2, 4 } } ).check_ok() );
256  assertTrue( N_vecU( { "...(5,4)->(N,lambda)", 2, {5,4} } ).check_ok() );
257 
258  assertTrue( N_vecU( { "5,-4->(N,lambda)", 2, {5,4} } ).check_ok() );
259  assertTrue( N_vecU( { "2019-09-23->9", 4, {2019,9,23,9} } ).check_ok() );
260  assertTrue( N_vecU( { "x,-4->(N,lambda)", 1, {4} } ).check_ok() );
261  assertTrue( N_vecU( { "1 2 3 4 5 6 7 8 9 -0 -1 -2 -3", 12, {1,2,3,4,5,6,7,8,9,0,1,2} } ).check_ok() );
262 {
263 {{ // test::get_numbers()
264  const size_t dim=12;
265  uintmax_t NUM[dim]; // returned value
266  char str[128] = "IMG_20190112_151835.jpg";
267  size_t len = atou_vec( str, NUM, dim );
268  assertTrue( len==2 );
269  assertTrue( NUM[0]==20190112 && NUM[1]==151835 );
270 }}
271 {
272  char str[128] = "IMG_2019-01/12_15:18.35.jpg";
273  uintmax_t NUM[6];
274  size_t len = atou_vec( str, NUM, 6 );
275  assertTrue( len==6 );
276  assertTrue( NUM[0]==2019 && NUM[1]== 1 && NUM[2]==12 );
277  assertTrue( NUM[3]==15 && NUM[4]==18 && NUM[5]==35 );
278 }
279 
280 {{ // test::atou_vec_extra()
281  const size_t dim=12;
282  uintmax_t NUM[dim]; // return vector
283  char str[128] = "IMG_20190112_151835.jpg";
284  size_t len = atou_vec( str, NUM, dim );
285  assertTrue( len==2 );
286  assertTrue( NUM[0]==20190112 && NUM[1]==151835 );
287 }}
288  char str[128] = "IMG_2019-01/12_15:18.35.jpg";
289  uintmax_t NUM[6];
290  size_t len = atou_vec( str, NUM, 6 );
291  assertTrue( len==6 );
292  assertTrue( NUM[0]==2019 && NUM[1]== 1 && NUM[2]==12 );
293  assertTrue( NUM[3]==15 && NUM[4]==18 && NUM[5]==35 );
294 }
295 
296 
297 {{ // test::atou_vec()
298  char str[] = " 000 6 -21 \t 5 \r\n 5 5 3 3 3 2 -";
299  size_t RES[] = { 000,6, 21, 5, 5,5,3,3,3,2 };
300  uintmax_t VEC[24], dim;
301  assertTrue( 24 == sizeof(VEC)/sizeof(*VEC) );
302  assertTrue( sizeof(RES) < sizeof(VEC) );
303 
304  const size_t dim_VEC = sizeof(VEC)/sizeof(*VEC);
305  const size_t dim_RES = sizeof(RES)/sizeof(*RES);
306 
307  for ( size_t i=0; i<((dim_VEC)); ++i ) { VEC[i] = 0; }
308 
309  /*=/=*/ dim = atou_vec( str,VEC, dim_VEC );
310 
311  size_t i,k; {
312  for ( i=k=0; i<dim_RES; ++i,++k ) {
313  assertTrue( RES[i] == VEC[i] );
314  }
315  for ( i=k; i<((dim_VEC)); ++i ) {
316  assertTrue( VEC[i] == 0 );
317  }
318  assertTrue( dim == dim_RES );
319  }
320 }}
321  {
322  uintmax_t VEC[24], dim=0;
323  const size_t dim_VEC = sizeof(VEC)/sizeof(*VEC);
324  char str[] = "0012345 \t \r\n \f 99 ";
325  /*=/=*/ dim = atou_vec( str,VEC, dim_VEC );
326  assertTrue( VEC[0] == 12345 );
327  assertTrue( VEC[1] == 99 );
328  assertTrue( dim == 2 );
329 
330  char xtr[] = "0012345.. $)(*^@!_.. 99 ";
331  /*=/=*/ dim = atou_vec( xtr,VEC, dim_VEC );
332  assertTrue( VEC[0] == 12345 );
333  assertTrue( VEC[1] == 99 );
334  assertTrue( dim == 2 );
335  }
336  { // check upper limit / dimension of VEC[]
337  const size_t DIM = 24, TEN=10;
338  uintmax_t VEC[DIM];
339  for ( size_t i=0; i<DIM; ++i ) { VEC[i] = 0; }
340 
341  char str[] = "0,1,2,3,4,5,6,7,8,9 | -9 8 -7 6 -5 4 -3 2 1 -0 =";
342  size_t N;
343  /*=/=*/ N = atou_vec( str,VEC, TEN );
344  assertTrue( TEN == N );
345 
346  for ( unsigned i=0; i<TEN; ++i ) {
347  assertTrue( VEC[i] == i );
348  }
349  for ( unsigned i=TEN; i<DIM; ++i ) {
350  assertTrue( VEC[i] == 0 );
351  }
352  {
353  VEC[0] = 111;
354  /*=/=*/ N = atou_vec( str,VEC, 0 );
355  assertTrue( VEC[0] == 111 );
356  }
357  }
358 }
359 
360 /// \c test->atouint().
361 void test_atouint() {
362 {{ // test::atouint()
363  assertTrue( 123 == atouint("+123" ) );
364  assertTrue( 123 == atouint(" 123" ) );
365  assertTrue( uintmax_t(-123) == atouint("-123" ) );
366  assertTrue( 0 == atouint("") );
367  assertTrue( 0 == atouint("+-") );
368  assertTrue( 2012 == atouint("2012.3.etc...") );
369 }}
370  assertTrue( uintmax_t(-2012) == atouint(" -2012.55 !_!#$^&$.3.etc... ") );
371  assertTrue( 0 == atouint("_!#$^&$..etc. -2012.55 !.. 3") );
372 }
373 
374 /// test->utoa_sz()
375 void test_utoa_sz() {
376 {{ // test::utoa_sz()
377  char *pDst;
378  { char dst5[5]; // { 1,2,3,4, 0==eos }
379  pDst = utoa_sz( 101, dst5 , 10 , (( sizeof(dst5) )) );
380  assertTrue( 0==strcmp( "101", pDst ) );
381  assertTrue( 0==strcmp( "0101" , dst5 ) );
382  }
383  { char dst7[7]; // { 1,2,3,4,5,6 0==eos }
384  pDst = utoa_sz( 987654321, dst7 , 10 , (( sizeof(dst7) )) );
385  assertTrue( 0==strcmp( "654321", pDst ) );
386  assertTrue( 0==strcmp( "654321" , dst7 ) );
387  }
388  { char dst32[32];
389  pDst = utoa_sz( 123, dst32 , 10 , ((4+1)) );
390  assertTrue( 0==strcmp( "123" , pDst) );
391  assertTrue( 0==strcmp( "0123" , dst32 ) );
392 
393  pDst = utoa_sz( 11, dst32 , ((3)), ((5+1)) );
394  assertTrue( 0==strcmp( "102" , pDst) );
395  assertTrue( 0==strcmp( "00102" , dst32 ) );
396 
397  pDst = utoa_sz( 0*0, dst32 , 16 , ((5+1)) );
398  assertTrue( 0==strcmp( "0", pDst ) );
399  assertTrue( 0==strcmp( "00000", dst32 ) );
400  }
401 }}
402  void cc_test_cc(); cc_test_cc(); // out of bounce tests
403 }
404 
405 // Class used to test when the function goes out of bounce
406 // - It has some memory before and after the array used as
407 // argument to a function.
408 template <unsigned N>
409 class cc_val_cc {
410  char m_prev[2*N];
411  char m_val [N];
412  char m_post[2*N];
413 public:
414  enum { chX='@' };
415  cc_val_cc() { set(); }
416  cc_val_cc( const char * v ) { set(v); }
417  bool check_ok() { // verify class invariant
418  for (unsigned i=0; i<2*N; ++i) {
419  if ( m_prev[i] != chX ) { return false; }
420  if ( m_post[i] != chX ) { return false; }
421  }
422  return true;
423  }
424  bool check_ok(unsigned n) { // verify first 'n' chars in m_val[]
425  if (n==0 || n>N) { return false; }
426  --n;
427  for ( unsigned i=0; i<n; ++i ) {
428  if ( m_val[i] == chX ) { return false; }
429  }
430  if (m_val[n] != 0) { return false; }
431  for ( unsigned i=n+1; i<2*N; ++i ) {
432  if ( m_val[i] != chX ) { return false; }
433  }
434  return check_ok();
435  }
436  char* c_str() { return m_val; }
437  void set( const char * v ) {
438  memset(m_prev, chX, 2*N);
439  memcpy(m_val, v, N );
440  memset(m_post, chX, 2*N);
441  }
442  void set() {
443  memset(m_prev, chX, sizeof(cc_val_cc));
444  }
445 };
446 
447 void cc_test_cc() {
448  const char * pDst;
449  cc_val_cc<8> dst;
450 
451  dst.set();
452  pDst = utoa_sz( 123, dst.c_str() , 10 , ((4+1)) );
453  assertTrue( 0==strcmp( "123" , pDst ) );
454  assertTrue( 0==strcmp( "0123" , dst.c_str() ) );
455  assertTrue( dst.check_ok( ((4+1)) ) );
456 
457  dst.set();
458  pDst = utoa_sz( 101, dst.c_str() , 10 , ((4+1)) );
459  assertTrue( 0==strcmp( "101" , pDst ) );
460  assertTrue( 0==strcmp( "0101" , dst.c_str() ) );
461  assertTrue( dst.check_ok( ((4+1)) ) );
462 
463  dst.set();
464  pDst = utoa_sz( 0, dst.c_str() , 10 , ((4+1)) );
465  assertTrue( 0==strcmp( "0" , pDst ) );
466  assertTrue( 0==strcmp( "0000" , dst.c_str() ) );
467  assertTrue( dst.check_ok( ((4+1)) ) );
468 
469  {
470  const long N = 8;
471  const char * pDst;
472  cc_val_cc<N> dst;
473  dst.set();
474  pDst = utoa_sz( 987654321, dst.c_str() , 10 , ((N)) );
475  assertTrue( 0==strcmp( "7654321" , pDst ) );
476  assertTrue( 0==strcmp( "7654321" , dst.c_str() ) );
477  assertTrue( dst.check_ok( ((N)) ) );
478  }
479  {
480  const long N = 2;
481  const char * pDst;
482  cc_val_cc<N> dst;
483  dst.set();
484  pDst = utoa_sz( 987654321, dst.c_str() , 10 , ((N)) );
485  assertTrue( 0==strcmp( "1" , pDst ) );
486  assertTrue( 0==strcmp( "1" , dst.c_str() ) );
487  assertTrue( dst.check_ok( ((N)) ) );
488  }
489  {
490  const long N = 1;
491  const char * pDst;
492  cc_val_cc<N> dst;
493  dst.set("");
494  pDst = utoa_sz( 987654321, dst.c_str() , 10 , ((N)) );
495  assertTrue( 0==strcmp( "" , pDst ) );
496  assertTrue( 0==strcmp( "" , dst.c_str() ) );
497  assertTrue( dst.check_ok( ((N)) ) );
498  }
499 }
500 
502 {{ // test::insnsep_Rupee()
503  char *first, num[insnsep_size];
504  strcpy( num , " " ); strcat(num," 32584729.25" );
505  first = insnsep_Rupee( num, ',' );
506  assertTrue( NULL!=first );
507  assertTrue( eqstr( num , "3,25,84,729.25" ) );
508 
509  // not enough space
510  strcpy( num , "" ); strcat(num," 32584729.25" );
511  assertTrue( NULL==insnsep_Rupee( num, ',' ) );
512  assertTrue( eqstr( num, " 32584729.25" ) );
513 }}
514  char *first, num[insnsep_size];
515 
516  strcpy( num , " " ); strcat(num," 32584729.25" );
517  first = insnsep_Rupee( num, '|' );
518  assertTrue( NULL!=first );
519  assertTrue( 0==strcmp( num , "3|25|84|729.25" ) );
520 
521  strcpy( num , "" );
522  assertTrue( NULL==insnsep_Rupee( num, ',' ) );
523  strcpy( num , "123" );
524  assertTrue( num==insnsep_Rupee( num, ',' ) );
525  assertTrue( 0==strcmp( num , "123" ) );
526  strcpy( num , "1234" );
527  assertTrue( NULL==insnsep_Rupee( num, ',' ) );
528  assertTrue( 0==strcmp( num , "1234" ) );
529  strcpy( num , " 1234" );
530  assertTrue( num==insnsep_Rupee( num, ',' ) );
531  assertTrue( 0==strcmp( num , "1,234" ) );
532 }
533 
535 {{ // test::insnsep_date8()
536  char *first, num[insnsep_size];
537  strcpy( num, "...**20191231.." );
538  /*=/=*/ first = insnsep_date8( num, '/', true );
539  assertTrue( eqstr(first, "2019/12/31.." ) );
540  assertTrue( eqstr(num, "...2019/12/31.." ) );
541 
542  strcpy( num, "...**12312019.." );
543  /*=/=*/ first = insnsep_date8( num,'-', false );
544  assertTrue( eqstr(first, "12-31-2019.." ) );
545  assertTrue( eqstr(num, "...12-31-2019.." ) );
546 
547  strcpy( num, "...**1234567.." ); // only 7 digits
548  assertTrue( NULL==insnsep_date8( num, '-', false ) );
549  assertTrue( eqstr(num, "...**1234567.." ) );
550 }}
551 }
552 
553 void test_insnsep() {
554 {{ // test::insnsep()
555  char *first, num[insnsep_size];
556 
557  strcpy( num, ".a.=|$+12345678.00" );
558  /*=/=*/ first = insnsep( num, ',' , 3 );
559  assertTrue( 0==strcmp(first, "+12,345,678.00" ) );
560  assertTrue( 0==strcmp(num, ".a.=+12,345,678.00" ) );
561  assertTrue( 4+(3)+(8)+3 == strlen(num) );
562  if (first!=num) { --first; *first = '$'; } // '$' sign
563  assertTrue( 0==strcmp(first, "$+12,345,678.00" ) );
564 
565  strcpy( num, ".|.|-12345.." ); // "$***" Example
566  /*=/=*/ first = insnsep( num, ',', 3 );
567  assertTrue( 0==strcmp(first, "-12,345.." ) );
568  assertTrue( 0==strcmp(num, ".|.-12,345.." ) );
569  if (first!=num ) { *num = '$';
570  while (--first!=num ) { *first='*'; }
571  }
572  assertTrue( 0==strcmp(first, "$**-12,345.." ) );
573 
574  strcpy( num, " -0" ); // 0 sign
575  assertTrue( num+1 == (first=insnsep( num, '?' , 1 )) );
576  assertTrue( 0==strcmp(num," -0" ) );
577  strcpy( num, " +000000" ); // 0 sign
578  assertTrue( num == (first=insnsep( num, ',' , 3 )) );
579  assertTrue( 0==strcmp(num,"+000,000" ) );
580 
581  assertTrue( NULL==insnsep( NULL,'|' , 1 ) ); // no string
582 
583  strcpy( num, "???.xx" ); // "No Change" examples
584  assertTrue( NULL==insnsep( num, '|' , 1 ) ); // no digits
585  strcpy( num, "123.00" );
586  assertTrue( NULL==insnsep( num, ':' , 0 ) ); // 0==w
587  assertTrue( NULL==insnsep( num, '-' , 2 ) ); // No room to insert
588  assertTrue( 0==strcmp( num, "123.00" ) );
589 }}
590 
591  // std::cout << num << std::endl;
592  // std::cout << first << std::endl;
593 // http://google.com/search?num=100&q=strins+%22c%22
594 // https://antti-juhani.kaijanaho.fi/darcs/publib-debian/strutil/
595 // ftp://ftp.broadinstitute.org/distribution/software/pedmanager/ansilib/strlib.c
596 
597  char *first, num[insnsep_size];
598  strcpy( num, "ab!...0000.00" );
599  /*==*/ first = insnsep( num, ',' , 1 );
600  assertTrue( 0==strcmp(first, "0,0,0,0.00" ) );
601  assertTrue( 0==strcmp(num, "ab!0,0,0,0.00" ) );
602  assertTrue( 3+3+(4)+3 == strlen(num) );
603 
604  strcpy( num, ".a.=$+123456.00" );
605  /*=/=*/ first = insnsep( num, ',' , 3 );
606  assertTrue( 0==strcmp(first, "+123,456.00" ) );
607  assertTrue( 0==strcmp(num, ".a.=+123,456.00" ) );
608  assertTrue( 4+(2)+(6)+3 == strlen(num) );
609  if (first>num) { --first; *first = '$'; } // '$' sign
610  assertTrue( 0==strcmp(first, "$+123,456.00" ) );
611 
612  strcpy( num, ".|.20191231.." ); // "Date" Example
613  /*=/=*/ first = insnsep( num, '/', 2 );
614  assertTrue( 0==strcmp(first, "20/19/12/31.." ) );
615  assertTrue( 0==strcmp(num, "20/19/12/31.." ) );
616  assertTrue( 3+(8)+2 == strlen(num) ); // 3x'?' + 8xDate + 2x'.'
617  memmove( first+2 ,first+3, 1+strlen(first+3) );
618  assertTrue( 0==strcmp(first, "2019/12/31.." ) ); // Date "How to"
619 
620  strcpy( num, ".|.20191231.." ); // "Date" Example
621  /*=/=*/ first = insnsep( num, '/', 4 );
622  assertTrue( 0==strcmp(first, "2019/1231.." ) );
623  assertTrue( 3+(8)+2 == strlen(num) ); // 3x'?' + 8xDate + 2x'.'
624  memmove( first-1 ,first, 7 ); --first; *(first+7) = '/';
625  assertTrue( 0==strcmp(first, "2019/12/31.." ) ); // Date "How to"
626  assertTrue( num == first-1 );
627 
628 { // Sign as separator
629  strcpy( num, " 2019-12-31.." );
630  first = insnsep( num, ',' , 3 );
631  assertTrue( 0!=strcmp(first, "2,019" ) );
632 
633  strcpy( num, " +2019-12-31.." );
634  first = insnsep( num, ',' , 3 );
635  assertTrue( 0!=strcmp(first, "-2,019" ) );
636 }
637  strcpy( num, " +0" ); // 0 sign
638  assertTrue( num+1 == (first=insnsep( num, ',' , 3 )) );
639  assertTrue( 0==strcmp(num," +0" ) );
640  strcpy( num, " -00" ); // 0 sign
641  assertTrue( num+1 == (first=insnsep( num, ',' , 3 )) );
642  assertTrue( 0==strcmp(num," -00" ) );
643  strcpy( num, " -000" ); // 0 sign
644  assertTrue( num+1 == (first=insnsep( num, ',' , 3 )) );
645  assertTrue( 0==strcmp(num," -000" ) );
646 
647  strcpy( num, "-" ); // no digits
648  assertTrue( NULL == insnsep( num, ',' , 3 ) );
649  strcpy( num, "-0" ); // no insertion
650  assertTrue( num == insnsep( num, ',' , 3 ) );
651  strcpy( num, "-00" ); // no insertion
652  assertTrue( num == insnsep( num, ',' , 3 ) );
653  strcpy( num, "-000" ); // no insertion
654  assertTrue( num == insnsep( num, ',' , 3 ) );
655 
656  strcpy( num, "-1" );
657  assertTrue( num == insnsep( num, ',' , 2 ) );
658  strcpy( num, "-12" );
659  assertTrue( num == insnsep( num, ',' , 2 ) );
660  strcpy( num, "-123" );
661  assertTrue( NULL == insnsep( num, ',' , 2 ) );
662  strcpy( num, " +123" ); // no insertion
663  assertTrue( num == insnsep( num, ',' , 2 ) );
664  assertTrue( 0==strcmp( num, "+1,23" ) );
665  strcpy( num, " +1234" );
666  assertTrue( num == insnsep( num, ',' , 2 ) );
667  assertTrue( 0==strcmp( num, "+12,34" ) );
668  strcpy( num, " +12345" ); // no insertion
669  assertTrue( NULL== insnsep( num, ',' , 2 ) );
670  strcpy( num, " +12345" ); // no insertion
671  assertTrue( num == insnsep( num, ',' , 2 ) );
672  strcpy( num, "+1,23,45" );
673 
674  strcpy( num, "-1" );
675  assertTrue( num == insnsep( num, ',' , 1 ) );
676  strcpy( num, "-12" );
677  assertTrue( NULL== insnsep( num, ',' , 1 ) );
678  strcpy( num, " -12" );
679  assertTrue( num == insnsep( num, ',' , 1 ) );
680  strcpy( num, "-1,2" );
681  strcpy( num, " +123" ); // no insertion
682  assertTrue( NULL == insnsep( num, ',' , 1 ) );
683  strcpy( num, " +123" ); // no insertion
684  assertTrue( num == insnsep( num, ',' , 1 ) );
685  assertTrue( 0==strcmp( num, "+1,2,3" ) );
686  strcpy( num, " +1234" );
687  assertTrue( NULL == insnsep( num, ',' , 1 ) );
688  strcpy( num, " +1234" );
689  assertTrue( num == insnsep( num, ',' , 1 ) );
690  assertTrue( 0==strcmp( num, "+1,2,3,4" ) );
691  strcpy( num, " +12345" );
692  assertTrue( NULL== insnsep( num, ',' , 1 ) );
693  strcpy( num, " +12345" );
694  assertTrue( num == insnsep( num, ',' , 1 ) );
695  strcpy( num, "+1,2,3,4,5" );
696  strcpy( num, " +123456" );
697  assertTrue( NULL== insnsep( num, ',' , 1 ) );
698  strcpy( num, " +123456" );
699  assertTrue( num == insnsep( num, ',' , 1 ) );
700  strcpy( num, "+1,2,3,4,5,6" );
701  strcpy( num, " +1234567" );
702  assertTrue( num == insnsep( num, ',' , 1 ) );
703  strcpy( num, "+1,2,3,4,5,6,7" );
704 
705  strcpy( num, "-0000" ); // // No room to insert
706  assertTrue( NULL == insnsep( num, ',' , 3 ) );
707  strcpy( num, " -0000" ); // sign + ','
708  assertTrue( num == insnsep( num, ',' , 3 ) );
709  assertTrue( 0==strcmp(num,"-0,000" ) );
710 
711  strcpy( num, " -0000" ); // 0 sign
712  assertTrue( num == (first=insnsep( num, ',' , 3 )) );
713  assertTrue( 0==strcmp(num,"-0,000" ) );
714  strcpy( num, " +00000" ); // 0 sign
715  assertTrue( num == (first=insnsep( num, ',' , 3 )) );
716  assertTrue( 0==strcmp(num,"+00,000" ) );
717 
718  strcpy( num, "" );
719  assertTrue( NULL==insnsep( num, '|' , 0 ) ); // no digits
720  strcpy( num, "...20191231.." );
721  assertTrue( num==insnsep( num, '\0' , 2 ) ); // 0==eos==sep
722  // std::cout << first << std::endl;
723  assertTrue( 0==strcmp(num+0, "20" ) ); // Inserting eos
724  assertTrue( 0==strcmp(num+3, "19" ) ); // -> eos == end of string
725  assertTrue( 0==strcmp(num+6, "12" ) );
726  assertTrue( 0==strcmp(num+9, "31.." ) );
727 
728  strcpy( num, ".123.00" );
729  first=insnsep( num, '-' , 2 );
730  assertTrue( 0==strcmp(first, "1-23.00" ) );
731  strcpy( num, "..123.00" );
732  first=insnsep( num, '|' , 1 );
733  assertTrue( 0==strcmp(first, "1|2|3.00" ) );
734  strcpy( num, "0.00" );
735  first = insnsep( num, ',' , 3 );
736  assertTrue( 0==strcmp(first, "0.00" ) );
737 
738  strcpy( num, "1" );
739  first = insnsep( num, ',' , 1 );
740  assertTrue( 0==strcmp(first,"1" ) );
741  strcpy( num, "9" );
742  first = insnsep( num, ',' , 9 );
743  assertTrue( 0==strcmp(first,"9" ) );
744  strcpy( num, "12" );
745  first = insnsep( num, ',' , 2 );
746  assertTrue( 0==strcmp(first,"12" ) );
747  strcpy( num, " 12" );
748  first = insnsep( num, ',' , 1 );
749  assertTrue( 0==strcmp(first,"1,2" ) );
750  strcpy( num, "123" );
751  first = insnsep( num, ',' , 1 );
752  assertTrue( 0==strcmp(first,"123" ) );
753  {
754  strcpy( num, "000000.00" );
755  first = insnsep( num, ',' , 3 );
756  assertTrue( first==NULL );
757 
758  strcpy( num, " 000000.00" );
759  first = insnsep( num, ':' , 3 );
760  assertTrue( first==num );
761  assertTrue( 0==strcmp(first,"000:000.00" ) );
762  }
763  strcpy( num, " 0...0...0...01.00" );
764  first = insnsep( num, ',' , 3 );
765  assertTrue( 0!=strcmp(first, "1.00" ) );
766 
767  strcpy( num, " ...... 0.00" );
768  first = insnsep( num, ',' , 1 );
769  assertTrue( 0==strcmp(first, "0.00" ) );
770 
771  strcpy( num, ".|.20191231.." ); // "Date" Example
772  /*=/=*/ first = insnsep( num, '/', 2 );
773  assertTrue( 0==strcmp(first, "20/19/12/31.." ) );
774  { // handle first '/'
775  *(first+2)=*(first+1);
776  *(first+1)=*(first+0);
777  ++first;
778  }
779  assertTrue( 0==strcmp(first, "2019/12/31.." ) ); // Date "How to"
780 
781  if (*first) {*num = *first; } // Run to cursor
782 }
783 
784 #include <string.h> // strcmp()
785 
786 #include <stdio.h> // snprintf(), scanf(), NULL
787 #include <stdint.h> // intmax_t
788 
789 /// \c test->PRIuMAX().
790 void test_PRIuMAX() {
791 {{ // test::PRIuMAX()
792  char str[ 40 ];
793  snprintf( str,40, "%llu", UINT64_MAX );
794  assertTrue( eqstr( "18446744073709551615", str ) );
795 
796  snprintf( str,40, "%" "lld", INT64_MIN );
797  assertTrue( eqstr( "-9223372036854775808", str ) );
798 }}
799 
800  char str[ 128 ];
801 
802  snprintf( str,64, "%u", sizeof(int64_t) );
803  assertTrue( eqstr( "8", str ) );
804 
805  snprintf( str,128, "%" "I64u", UINT64_MAX );
806  assertTrue( eqstr( "18446744073709551615", str ) );
807 
808  snprintf( str,128, "%lld", INT64_MIN );
809  assertTrue( eqstr( "-9223372036854775808", str ) );
810 
811  snprintf( str,128, "%" "I64i", INT64_MIN );
812  assertTrue( eqstr( "-9223372036854775808", str ) );
813 
814 // std::cout << '['<< str << ']' << std::endl;
815 // #define PRIuMAX "I64u"
816 // #define PRIiMAX "I64i"
817 // assertTrue( eqstr( PRIuMAX , "I64u" ) );
818 // assertTrue( eqstr( PRIiMAX , "I64i" ) );
819 #define PRIuMAX "I64u"
820 {{ // test::SepMaxInt()
821  char str[ insnsep_size ]; char *first;
822  memset( str,20, ' '); // pone blancos al principio de 'str[]'
823  snprintf( str+20,insnsep_size-20, "%" PRIuMAX, UINT64_MAX );
824  assertTrue( eqstr( "18446744073709551615", str+20 ) );
825 
826  /*=/=*/ first = insnsep( str, ',' , 3 );
827  assertTrue( first != NULL );
828  assertTrue( eqstr( "18,446,744,073,709,551,615", first ) );
829  assertTrue( strlen(first)==2+6*4 && 26==2+6*4 );
830 }}
831 #undef PRIuMAX
832 
833 {
834  char str[ insnsep_size ]; char *first;
835  memset( str,16, ' '); // pone blancos al principio de 'str[]'
836  strcpy( str+16, "340282366920938463463374607431768211456" );
837  first = insnsep( str, ',' , 3 );
838  assertTrue( eqstr( "340,282,366,920,938,463,463,374,607,431,768,211,456", first ) );
839  assertTrue( strlen(first)==51 && 51==13*4-1 );
840 }
841 { // sizeof(long double)
842  assertTrue( CHAR_BIT >= 8 );
843  if ( sizeof(double)==sizeof(long double) ) {
844  assertTrue( sizeof(double)==sizeof(long double) );
845  }
846  else {
847  assertTrue( sizeof(double) < sizeof(long double) );
848  assertTrue( 96/8 == sizeof(long double) );
849  assertFalse( 2 * sizeof(double) == sizeof(long double) );
850  // std::cout << "sizeof(long double)==" << CHAR_BIT * sizeof(long double) << " bits\n";
851  }
852 }
853 }
854 
855 // EOF: strnum_test.cpp
test_insnsep_Rupee
void test_insnsep_Rupee()
Definition: strnum_test.cpp:501
atou_vec
size_t atou_vec(const char *str, uintmax_t VEC[], size_t N)
Takes all leading numeric values from 'str' to fill up 'VEC[]'.
Definition: strnum.cpp:178
cc_val_cc
Definition: strnum_test.cpp:409
N_vecU::vec
uintmax_t vec[12]
Definition: strnum_test.cpp:229
utoa_sz
char * utoa_sz(uintmax_t val, char *dst, unsigned base, size_t sz)
Converts 'val' into the zero terminated C-string 'dst'.
Definition: strnum.cpp:303
strnum.h
Complement routines for <string> && <cstring>
cc_val_cc::set
void set()
Definition: strnum_test.cpp:442
cc_val_cc::m_post
char m_post[2 *N]
Definition: strnum_test.cpp:412
test_utoa_sz
void test_utoa_sz()
test->utoa_sz()
Definition: strnum_test.cpp:375
PRIuMAX
#define PRIuMAX
cc_val_cc::check_ok
bool check_ok()
Definition: strnum_test.cpp:417
cc_val_cc::check_ok
bool check_ok(unsigned n)
Definition: strnum_test.cpp:424
atouint
uintmax_t atouint(const char *str)
Converts 'str' into an unsigned number invoking strtoull()
Definition: strnum.h:40
N_vec::vec
int vec[DIM]
Definition: strnum_test.cpp:99
N_vecU::str
std::string str
Definition: strnum_test.cpp:227
cc_val_cc::c_str
char * c_str()
Definition: strnum_test.cpp:436
remove_dir_name
const T * remove_dir_name(const T *str)
"C:/DIR/SubDir/file_name.ext" ==> "file_name.ext"
cc_val_cc::chX
Definition: strnum_test.cpp:414
atoi_vec
size_t atoi_vec(const char *str, intmax_t VEC[], size_t N)
Take all numeric values from 'str' to fill up 'VEC[]'.
Definition: strnum.cpp:214
cc_val_cc::cc_val_cc
cc_val_cc()
Definition: strnum_test.cpp:415
test_insnsep
void test_insnsep()
Definition: strnum_test.cpp:553
assertTrue
#define assertTrue(cond)
(cond ? () : cout << "cond" )
Definition: uUnit.h:93
N_vec::N
size_t N
Definition: strnum_test.cpp:98
N_vecU
Definition: strnum_test.cpp:226
N_vecU::N
size_t N
Definition: strnum_test.cpp:228
cc_val_cc::m_prev
char m_prev[2 *N]
Definition: strnum_test.cpp:410
N_vec
Definition: strnum_test.cpp:96
cc_test_cc
void cc_test_cc()
Definition: strnum_test.cpp:447
N_vec::str
std::string str
Definition: strnum_test.cpp:97
assertFalse
#define assertFalse(cond)
(!(cond) ? () : cout << "!" << (cond)" )
Definition: uUnit.h:95
cc_val_cc::cc_val_cc
cc_val_cc(const char *v)
Definition: strnum_test.cpp:416
insnsep_Rupee
char * insnsep_Rupee(char *num, char sep)
Use 'insnsep()' to format a Rupee amount.
Definition: strnum.cpp:98
N_vecU::check_ok
bool check_ok() const
Definition: strnum_test.cpp:233
N_vec::check_ok
bool check_ok() const
Definition: strnum_test.cpp:104
test_PRIuMAX
void test_PRIuMAX()
test->PRIuMAX().
Definition: strnum_test.cpp:790
insnsep
char * insnsep(char *num, char sep, unsigned w)
Insert in place the separator 'sep' for a numeric string.
Definition: strnum.cpp:42
insnsep_date8
char * insnsep_date8(char *num, char sep, bool YMD)
Use 'insnsep()' to format a date.
Definition: strnum.cpp:134
uUnit.h
[u]Micro module for [Unit] program testing.
test_atouint
void test_atouint()
test->atouint().
Definition: strnum_test.cpp:361
insnsep_size
const size_t insnsep_size
Safe size for 'insnsep()'.
Definition: strnum.h:18
cc_val_cc::m_val
char m_val[N]
Definition: strnum_test.cpp:411
test_atou_vec
void test_atou_vec()
test -> atou_vec()
Definition: strnum_test.cpp:245
test_insnsep_date8
void test_insnsep_date8()
Definition: strnum_test.cpp:534
test_atou_ndigit
void test_atou_ndigit()
test->atou_ndigit().
Definition: strnum_test.cpp:43
eqstr
#define eqstr(a, b)
Shortcut macro to compare 2 C strings using strcmp()
Definition: strnum_test.cpp:40
atou_ndigit
uintmax_t atou_ndigit(const char **str, unsigned N)
Extract the next number of 'N' digits from '*str'.
Definition: strnum.cpp:260
exec_TEST
#define exec_TEST(t)
main
int main(const int argc, const char *argv[])
Test program.
Definition: strnum_test.cpp:17
test_atoi_vec
void test_atoi_vec()
test -> atoi_vec()
Definition: strnum_test.cpp:116
cc_val_cc::set
void set(const char *v)
Definition: strnum_test.cpp:437