Nilorea Library
C utilities for networking, threading, graphics
n_str.c
Go to the documentation of this file.
1
10#ifndef NO_NSTR
11
12
13#include "nilorea/n_common.h"
14#include "nilorea/n_log.h"
15#include "nilorea/n_str.h"
16
17#include <errno.h>
18#include <pthread.h>
19#include <math.h>
20#include <ctype.h>
21#include <stdio.h>
22#include <string.h>
23#include <limits.h>
24#include <stdlib.h>
25#include <dirent.h>
26
27
28#ifdef __windows__
35const char *strcasestr(const char *s1, const char *s2)
36{
37 __n_assert( s1, return NULL );
38 __n_assert( s2, return NULL );
39
40 size_t n = strlen(s2);
41 while( *s1 )
42 {
43 if( !strnicmp( s1++, s2,n ) )
44 return ( s1-1 );
45 }
46 return NULL ;
47} /* strcasestr */
48#endif
49
50
55void free_nstr_ptr( void *ptr )
56{
57 N_STR *strptr = (N_STR *)ptr ;
58 if( ptr && strptr )
59 {
60 FreeNoLog( strptr -> data );
61 FreeNoLog( strptr );
62 }
63} /* free_nstr_ptr( ... ) */
64
65
66
72int _free_nstr( N_STR **ptr )
73{
74 __n_assert( ptr&&(*ptr), return FALSE );
75
76 FreeNoLog( (*ptr) -> data );
77 FreeNoLog( (*ptr) );
78
79 return TRUE ;
80} /* free_nstr( ... ) */
81
82
83
90{
91
92 if( (*ptr) )
93 {
94 FreeNoLog( (*ptr) -> data );
95 FreeNoLog( (*ptr) );
96 }
97
98 return TRUE ;
99} /* free_nstr( ... ) */
100
101
102
107void free_nstr_ptr_nolog( void *ptr )
108{
109 N_STR *strptr = (N_STR *)ptr ;
110 if( strptr )
111 {
112 FreeNoLog( strptr -> data );
113 FreeNoLog( strptr );
114 }
115} /* free_nstr_ptr_nolog( ... ) */
116
117
118
124char *trim_nocopy(char *s)
125{
126 __n_assert( s, return NULL );
127
128 if( strlen( s ) == 0 )
129 return s ;
130
131 char *start = s;
132
133 /* skip spaces at start */
134 while(*start && isspace(*start))
135 start++;
136
137 char *end = s + strlen( s ) - 1 ;
138 /* iterate over the rest remebering last non-whitespace */
139 while( *end && isspace( *end) && end > s )
140 {
141 end --;
142 }
143 end ++ ;
144 /* write the terminating zero after last non-whitespace */
145 *end = 0;
146
147 return start;
148} /* trim_nocopy */
149
150
156char *trim(char *s)
157{
158 __n_assert( s, return NULL );
159
160 return strdup( trim_nocopy( s ) );
161} /* trim_nocopy */
162
163
164
172char *nfgets( char *buffer, NSTRBYTE size, FILE *stream )
173{
174 __n_assert( buffer, return NULL );
175 __n_assert( stream, return NULL );
176
177 NSTRBYTE it = 0 ;
178
179 if( !fgets( buffer, size, stream ) )
180 {
181 return NULL ;
182 }
183
184 if( it == ( size - 1 ) )
185 {
186 n_log( LOG_DEBUG, "buffer %p size %d fully filled by fgets on stream %p", buffer, size, stream );
187 }
188
189 return buffer ;
190} /* nfgets(...) */
191
192
193
199int empty_nstr( N_STR *nstr )
200{
201 __n_assert( nstr, return FALSE );
202 __n_assert( nstr -> data, return FALSE );
203
204 nstr -> written = 0 ;
205 memset( nstr -> data, 0, nstr -> length );
206
207 return TRUE ;
208}
209
216{
217 N_STR *str = NULL ;
218
219 Malloc( str, N_STR, 1 );
220 __n_assert( str, return NULL );
221
222 str -> written = 0 ;
223 if( size <= 0 )
224 {
225 str -> data = NULL ;
226 str -> length = 0 ;
227 }
228 else
229 {
230 Malloc( str -> data, char, size + 1 );
231 __n_assert( str -> data, Free(str) ; return NULL );
232 str -> length = size ;
233 }
234 return str ;
235} /* new_nstr(...) */
236
237
238
246int char_to_nstr_ex( const char *from, NSTRBYTE nboct, N_STR **to )
247{
248 if( (*to) )
249 {
250 n_log( LOG_ERR, "destination N_STR **str is not NULL (%p), it contain (%s). You must provide an empty destination.", (*to), ((*to)&&(*to)->data)?(*to)->data:"DATA_IS_NULL" );
251 n_log( LOG_ERR, "Data to copy: %s", _str( from ) );
252 return FALSE ;
253 };
254
255 (*to) = new_nstr( nboct + 1 );
256 __n_assert( to&&(*to), return FALSE );
257 /* added a sizeof( void * ) to add a consistant and secure padding at the end */
258 __n_assert( (*to) -> data, Free( (*to) ); return FALSE );
259
260 memcpy( (*to) -> data, from, nboct );
261 (*to) -> written = nboct ;
262
263 return TRUE;
264} /* char_to_nstr(...) */
265
266
267
273N_STR *char_to_nstr( const char *src )
274{
275 N_STR *strptr = NULL ;
276 size_t length = strlen( src );
277 char_to_nstr_ex( src, length, &strptr ) ;
278 return strptr ;
279} /* char_to_str(...) */
280
281
289int char_to_nstr_nocopy_ex( char *from, NSTRBYTE nboct, N_STR **to )
290{
291 if( (*to) )
292 {
293 n_log( LOG_ERR, "destination N_STR **str is not NULL (%p), it contain (%s). You must provide an empty destination.", (*to), ((*to)&&(*to)->data)?(*to)->data:"DATA_IS_NULL" );
294 n_log( LOG_ERR, "Data to copy: %s", _str( from ) );
295 return FALSE ;
296 };
297
298 (*to) = new_nstr( nboct + 1 );
299
300 __n_assert( to&&(*to), return FALSE );
301 /* added a sizeof( void * ) to add a consistant and secure padding at the end */
302 __n_assert( (*to) -> data, Free( (*to) ); return FALSE );
303
304 (*to) -> data = from ;
305
306 (*to) -> written = nboct ;
307
308 return TRUE;
309} /* char_to_nstr_nocopy_ex(...) */
310
311
312
319{
320 N_STR *strptr = NULL ;
321 char_to_nstr_nocopy_ex( src, strlen( src ), &strptr ) ;
322 return strptr ;
323} /* char_to_str_nocopy(...) */
324
325
326
332N_STR *file_to_nstr( char *filename )
333{
334 N_STR *tmpstr = NULL ;
335 struct stat filestat ;
336 FILE *in = NULL ;
337
338 __n_assert( filename, n_log( LOG_ERR, "Unable to make a string from NULL filename") ; return NULL );
339
340 if( stat( filename, &filestat ) != 0 )
341 {
342#ifdef __linux__
343 if( errno == EOVERFLOW )
344 {
345 n_log( LOG_ERR, "%s size is too big ,EOVERFLOW)", filename );
346 }
347 else
348 {
349#endif
350 n_log( LOG_ERR, "Couldn't stat %s. Errno: %s", filename, strerror( errno ) );
351#ifdef __linux__
352 }
353#endif
354 return NULL ;
355 }
356 if( ( filestat . st_size + 1 ) >= ( pow( 2, 32 ) - 1 ) )
357 {
358 n_log( LOG_ERR, "file size >= 2GB is not possible yet. %s is %lld oct", filename, filestat . st_size );
359 return NULL ;
360 }
361
362 n_log( LOG_DEBUG, "%s file size is: %lld", filename, (long long unsigned int)filestat . st_size );
363
364 in = fopen( filename, "rb" );
365 __n_assert( in, n_log( LOG_ERR, "Unable to open %s", filename ); return NULL );
366
367 tmpstr = new_nstr( filestat . st_size + 1 );
368 __n_assert( tmpstr, fclose( in ); n_log( LOG_ERR, "Unable to get a new nstr of %ld octets", filestat . st_size + 1 ); return NULL );
369
370 tmpstr -> written = filestat . st_size ;
371
372 if( fread( tmpstr -> data, sizeof( char ), tmpstr -> written, in ) == 0 )
373 {
374 n_log( LOG_ERR, "Couldn't read %s, fread return 0", filename );
375 free_nstr( &tmpstr );
376 fclose( in );
377 return NULL ;
378 }
379 if( ferror( in ) )
380 {
381 n_log( LOG_ERR, "There were some errors when reading %s", filename );
382 free_nstr( &tmpstr );
383 fclose( in );
384 return NULL ;
385 }
386
387 fclose( in );
388
389 return tmpstr ;
390} /*file_to_nstr */
391
392
401/* Write a whole N_STR into a file */
402int nstr_to_fd( N_STR *str, FILE *out, int lock )
403{
404#ifdef __linux__
405 struct flock out_lock ;
406#endif
407 __n_assert( out, return FALSE );
408 __n_assert( str, return FALSE );
409
410 int ret = TRUE ;
411
412 if( lock == 1 )
413 {
414#ifdef __linux__
415 memset( &out_lock, 0, sizeof( out_lock ) );
416 out_lock.l_type = F_WRLCK ;
417 /* Place a write lock on the file. */
418 fcntl( fileno( out ), F_SETLKW, &out_lock );
419#else
420 lock = 2 ; /* compiler warning suppressor */
421#endif
422 }
423
424 size_t written_to_file = 0 ;
425 if( (written_to_file = fwrite( str -> data, sizeof( char ), str -> written, out ) ) != (size_t)str -> written )
426 {
427 n_log( LOG_ERR, "Couldn't write file, fwrite %d of %d octets", written_to_file, str -> written );
428 ret = FALSE ;
429 }
430 if( ferror( out ) )
431 {
432 n_log( LOG_ERR, "There were some errors when writing to %d", fileno( out ) );
433 ret = FALSE ;
434 }
435
436 if( lock == 1 )
437 {
438#ifdef __linux__
439 memset( &out_lock, 0, sizeof( out_lock ) );
440 out_lock.l_type = F_WRLCK ;
441 /* Place a write lock on the file. */
442 fcntl( fileno( out ), F_SETLKW, &out_lock );
443#else
444 lock = 2 ; /* compiler warning suppressor */
445#endif
446 }
447
448 return ret ;
449} /* nstr_to_fd( ... ) */
450
451
452
459int nstr_to_file( N_STR *str, char *filename )
460{
461 FILE *out = NULL ;
462
463 __n_assert( str, return FALSE );
464 __n_assert( filename, return FALSE );
465
466 out = fopen( filename, "wb" );
467
468 __n_assert( out, n_log( LOG_DEBUG, "Couldn't open %s", _str( filename ) ) ; return FALSE );
469
470 int ret = nstr_to_fd( str, out, 1 );
471
472 fclose( out );
473
474 n_log( LOG_DEBUG, "%s file size is: %lld", filename, str ->written );
475
476 return ret ;
477} /* nstr_to_file( ... ) */
478
479
480
492int str_to_int_ex( const char *s, NSTRBYTE start, NSTRBYTE end, int *i, const int base )
493{
494 char *tmpstr = NULL ;
495 char *endstr = NULL ;
496 long l = 0;
497
498 __n_assert( s, return FALSE );
499
500 Malloc( tmpstr, char, sizeof( int ) + end - start + 8 );
501 __n_assert( tmpstr, n_log( LOG_ERR, "Unable to Malloc( tmpstr , char , sizeof( int ) + %d - %d )", end, start ); return FALSE );
502
503 memcpy( tmpstr, s + start, end - start );
504
505 errno = 0;
506 l = strtol(tmpstr, &endstr, base);
507 if( ( errno == ERANGE && l == LONG_MAX) || l > INT_MAX )
508 {
509 n_log( LOG_ERR, "OVERFLOW reached when converting %s to int", tmpstr );
510 Free( tmpstr );
511 return FALSE;
512 }
513 if( ( errno == ERANGE && l == LONG_MIN) || l < INT_MIN )
514 {
515 n_log( LOG_ERR, "UNDERFLOW reached when converting %s to int", tmpstr );
516 Free( tmpstr );
517 return FALSE;
518 }
519 if( *endstr != '\0' && *endstr != '\n' )
520 {
521 n_log( LOG_ERR, "Impossible conversion for %s", tmpstr );
522 Free( tmpstr );
523 return FALSE;
524 }
525 Free( tmpstr );
526 *i = l;
527 return TRUE;
528}/* str_to_int_ex( ... ) */
529
530
531
532
545int str_to_int_nolog( const char *s, NSTRBYTE start, NSTRBYTE end, int *i, const int base, N_STR **infos )
546{
547 char *tmpstr = NULL ;
548 char *endstr = NULL ;
549 long l = 0;
550
551 __n_assert( s, return FALSE );
552
553 Malloc( tmpstr, char, sizeof( int ) + end - start + 8 );
554 __n_assert( tmpstr, n_log( LOG_ERR, "Unable to Malloc( tmpstr , char , sizeof( int ) + %d - %d )", end, start ); return FALSE );
555
556 memcpy( tmpstr, s + start, end - start );
557
558 errno = 0;
559 l = strtol(tmpstr, &endstr, base);
560 if( ( errno == ERANGE && l == LONG_MAX) || l > INT_MAX )
561 {
562 nstrprintf( (*infos), "OVERFLOW reached when converting %s to int", tmpstr );
563 Free( tmpstr );
564 return FALSE;
565 }
566 if( ( errno == ERANGE && l == LONG_MIN) || l < INT_MIN )
567 {
568 nstrprintf( (*infos), "UNDERFLOW reached when converting %s to int", tmpstr );
569 Free( tmpstr );
570 return FALSE;
571 }
572 if( *endstr != '\0' && *endstr != '\n' )
573 {
574 nstrprintf( (*infos), "Impossible conversion for %s", tmpstr );
575 Free( tmpstr );
576 return FALSE;
577 }
578 Free( tmpstr );
579 *i = l;
580 return TRUE;
581}/* str_to_int_nolog( ... ) */
582
583
584
592int str_to_int( const char *s, int *i, const int base )
593{
594 int ret = FALSE ;
595 if( s )
596 {
597 ret = str_to_int_ex( s, 0, strlen( s ), i, base );
598 }
599 return ret ;
600} /* str_to_int(...) */
601
602
603
615int str_to_long_ex( const char *s, NSTRBYTE start, NSTRBYTE end, long int *i, const int base )
616{
617 char *tmpstr = NULL ;
618 char *endstr = NULL ;
619 long l = 0;
620
621 __n_assert( s, return FALSE );
622
623 Malloc( tmpstr, char, sizeof( int ) + end - start + 8 );
624 __n_assert( tmpstr, n_log( LOG_ERR, "Unable to Malloc( tmpstr , char , sizeof( int ) + %d - %d )", end, start ); return FALSE );
625
626 memcpy( tmpstr, s + start, end - start );
627
628 errno = 0;
629 l = strtol(tmpstr, &endstr, base);
630 int error = errno ;
631
632 /* test return to number and errno values */
633 if (tmpstr == endstr)
634 {
635 n_log( LOG_ERR, " number : %lu invalid (no digits found, 0 returned)", l );
636 Free( tmpstr );
637 return FALSE;
638 }
639 else if (error == ERANGE && l == LONG_MIN)
640 {
641 n_log( LOG_ERR, " number : %lu invalid (underflow occurred)", l );
642 Free( tmpstr );
643 return FALSE;
644 }
645 else if (error == ERANGE && l == LONG_MAX)
646 {
647 n_log( LOG_ERR, " number : %lu invalid (overflow occurred)", l );
648 Free( tmpstr );
649 return FALSE;
650 }
651 else if (error == EINVAL) /* not in all c99 implementations - gcc OK */
652 {
653 n_log( LOG_ERR, " number : %lu invalid (base contains unsupported value)", l );
654 Free( tmpstr );
655 return FALSE;
656 }
657 else if (error != 0 && l == 0)
658 {
659
660 n_log( LOG_ERR, " number : %lu invalid (unspecified error occurred)", l );
661 Free( tmpstr );
662 return FALSE;
663 }
664 else if (error == 0 && tmpstr && !*endstr)
665 {
666 n_log( LOG_DEBUG, " number : %lu valid (and represents all characters read)", l );
667 }
668 else if (error == 0 && tmpstr && *endstr != 0)
669 {
670 n_log( LOG_DEBUG," number : %lu valid (but additional characters remain", l );
671 }
672 Free( tmpstr );
673 *i = l;
674 return TRUE;
675}/* str_to_long_ex( ... ) */
676
677
678
688int str_to_long_long_ex( const char *s, NSTRBYTE start, NSTRBYTE end, long long int *i, const int base )
689{
690 char *tmpstr = NULL ;
691 char *endstr = NULL ;
692 long long l = 0;
693
694 __n_assert( s, return FALSE );
695
696 Malloc( tmpstr, char, sizeof( int ) + end - start + 8 );
697 __n_assert( tmpstr, n_log( LOG_ERR, "Unable to Malloc( tmpstr , char , sizeof( int ) + %d - %d )", end, start ); return FALSE );
698
699 memcpy( tmpstr, s + start, end - start );
700
701 errno = 0;
702 l = strtoll(tmpstr, &endstr, base);
703 int error = errno ;
704
705 /* test return to number and errno values */
706 if (tmpstr == endstr)
707 {
708 n_log( LOG_ERR, "number: '%s' invalid (no digits found, 0 returned)", s );
709 Free( tmpstr );
710 return FALSE;
711 }
712 else if (error == ERANGE && l == LLONG_MIN)
713 {
714 n_log( LOG_ERR, "number: '%s' invalid (underflow occurred)", s );
715 Free( tmpstr );
716 return FALSE;
717 }
718 else if (error == ERANGE && l == LLONG_MAX)
719 {
720 n_log( LOG_ERR, "number: 's' invalid (overflow occurred)", s );
721 Free( tmpstr );
722 return FALSE;
723 }
724 else if (error == EINVAL) /* not in all c99 implementations - gcc OK */
725 {
726 n_log( LOG_ERR, "number: '%s' invalid (base contains unsupported value)", s );
727 Free( tmpstr );
728 return FALSE;
729 }
730 else if (error != 0 && l == 0)
731 {
732
733 n_log( LOG_ERR, "number: '%s' invalid (unspecified error occurred)", s );
734 Free( tmpstr );
735 return FALSE;
736 }
737 else if (error == 0 && tmpstr && !*endstr)
738 {
739 n_log( LOG_DEBUG, "number : '%llu' valid (and represents all characters read)", l );
740 }
741 else if (error == 0 && tmpstr && *endstr != 0)
742 {
743 n_log( LOG_DEBUG," number : '%llu' valid (remaining characters: '%s')", l , s );
744 }
745 Free( tmpstr );
746 *i = l;
747 return TRUE;
748}/* str_to_long_long_ex( ... ) */
749
750
751
759int str_to_long( const char *s, long int *i, const int base )
760{
761 int ret = FALSE ;
762 if( s )
763 {
764 ret = str_to_long_ex( s, 0, strlen( s ), i, base );
765 }
766 return ret ;
767} /* str_to_long(...) */
768
769
770
778int str_to_long_long( const char *s, long long int *i, const int base )
779{
780 int ret = FALSE ;
781 if( s )
782 {
783 ret = str_to_long_long_ex( s, 0, strlen( s ), i, base );
784 }
785 return ret ;
786} /* str_to_long(...) */
787
788
789
796{
797 N_STR *new_str = NULL ;
798
799 __n_assert( str, return NULL );
800 __n_assert( str -> data, return NULL );
801
802 new_str = new_nstr( str -> length );
803 if( new_str )
804 {
805 if( new_str -> data )
806 {
807 memcpy( new_str -> data, str -> data, str -> written );
808 new_str -> length = str -> length ;
809 new_str -> written = str -> written ;
810 }
811 else
812 {
813 Free( new_str );
814 n_log( LOG_ERR, "Error duplicating N_STR %p -> data", str );
815 }
816 }
817 else
818 {
819 n_log( LOG_ERR, "Error duplicating N_STR %p", str );
820 }
821 return new_str ;
822} /* nstrdup(...) */
823
824
825
835int skipw( char *string, char toskip, NSTRBYTE *iterator, int inc )
836{
837 int error_flag = 0 ;
838 //NSTRBYTE previous = 0 ;
839
840 __n_assert( string, return FALSE );
841
842 //previous = *iterator;
843 if( toskip == ' ' )
844 {
845 while( *iterator <= (NSTRBYTE)strlen ( string ) && isspace( string[ *iterator ] ) )
846 {
847 if( inc < 0 && *iterator == 0 )
848 {
849 error_flag = 1 ;
850 break ;
851 }
852 else
853 *iterator = *iterator + inc;
854 }
855 }
856 else
857 {
858 while( *iterator <= (NSTRBYTE)strlen( string ) && string[ *iterator ] == toskip )
859 {
860 if( inc < 0 && *iterator == 0 )
861 {
862 error_flag = 1 ;
863 break ;
864 }
865 else
866 *iterator = *iterator + inc;
867 }
868 }
869 if( error_flag == 1 || *iterator > (NSTRBYTE)strlen ( string ) )
870 {
871 //*iterator = previous ;
872 return FALSE;
873 }
874
875 return TRUE;
876} /*skipw(...)*/
877
878
879
889int skipu( char *string, char toskip, NSTRBYTE *iterator, int inc )
890{
891 int error_flag = 0 ;
892 //NSTRBYTE previous = 0 ;
893
894 __n_assert( string, return FALSE );
895
896 //previous = *iterator;
897 if( toskip == ' ' )
898 {
899 while( *iterator <= (NSTRBYTE)strlen ( string ) && !isspace( string[ *iterator ] ) )
900 {
901 if( inc < 0 && *iterator == 0 )
902 {
903 error_flag = 1 ;
904 break ;
905 }
906 else
907 *iterator = *iterator + inc;
908 }
909 }
910 else
911 {
912 while( *iterator <= (NSTRBYTE)strlen( string ) && string[ *iterator ] != toskip )
913 {
914 if( inc < 0 && *iterator == 0 )
915 {
916 error_flag = 1 ;
917 break ;
918 }
919 else
920 *iterator = *iterator + inc;
921 }
922 }
923
924 if( error_flag == 1 || *iterator > (NSTRBYTE)strlen ( string ) )
925 {
926 //*iterator = previous ;
927 return FALSE;
928 }
929
930 return TRUE;
931} /*Skipu(...)*/
932
933
934
942int strup( char *string, char *dest )
943{
944
945 NSTRBYTE it = 0 ;
946
947 __n_assert( string, return FALSE );
948 __n_assert( dest, return FALSE );
949
950 for( it = 0 ; it < (NSTRBYTE)strlen( string ) ; it++ )
951 dest[ it ] = toupper ( string[ it ] );
952
953 return TRUE;
954} /*strup(...)*/
955
956
957
965int strlo( char *string, char *dest )
966{
967
968 NSTRBYTE it = 0 ;
969
970 __n_assert( string, return FALSE );
971 __n_assert( dest, return FALSE );
972
973 for( it = 0 ; it < (NSTRBYTE)strlen( string ) ; it++ )
974 dest[ it ] = tolower ( string[ it ] );
975
976 return TRUE;
977} /*strlo(...)*/
978
979
980
990int strcpy_u( char *from, char *to, NSTRBYTE to_size, char split, NSTRBYTE *it )
991{
992 NSTRBYTE _it = 0;
993
994 __n_assert( from, return FALSE );
995 __n_assert( to, return FALSE );
996 __n_assert( it, return FALSE );
997
998 while( _it < to_size && from[ (*it) ] != '\0' && from[ (*it) ] != split )
999 {
1000 to[ _it ] = from[ (*it) ] ;
1001 (*it) = (*it) + 1 ;
1002 _it = _it +1 ;
1003 }
1004
1005 if( _it == to_size )
1006 {
1007 _it -- ;
1008 to[ _it ] = '\0' ;
1009 n_log( LOG_DEBUG, "strcpy_u: not enough space to write %d octet to dest (%d max) , %s: %d \n", _it, to_size, __FILE__, __LINE__ );
1010 return FALSE;
1011 }
1012
1013 to[ _it ] = '\0' ;
1014
1015 if( from[ (*it) ] != split )
1016 {
1017 n_log( LOG_DEBUG, "strcpy_u: split value not found, written %d octet to dest (%d max) , %s: %d \n", _it, to_size, __FILE__, __LINE__ );
1018 return FALSE;
1019 }
1020 return TRUE ;
1021} /* strcpy_u(...) */
1022
1023
1024
1032char** split( const char* str, const char* delim, int empty )
1033{
1034 char** tab=NULL; /* result array */
1035 char *ptr = NULL ; /* tmp pointer */
1036 int sizeStr=0; /* string token size */
1037 int sizeTab=0; /* array size */
1038 const char* largestring = NULL; /* pointer to start of string */
1039
1040 __n_assert( str, return NULL );
1041 __n_assert( delim, return NULL );
1042
1043 int sizeDelim=strlen(delim);
1044 largestring = str;
1045
1046 while( ( ptr = strstr( largestring, delim ) ) != NULL )
1047 {
1048 sizeStr=ptr-largestring;
1049 if( empty == 1 || sizeStr != 0 )
1050 {
1051 sizeTab++;
1052 tab= (char**) realloc(tab,sizeof(char*)*sizeTab);
1053
1054 Malloc( tab[sizeTab -1], char, (int)(sizeof(char)*(sizeStr+1)) );
1055 __n_assert( tab[ sizeTab - 1 ], goto error );
1056
1057 memcpy(tab[sizeTab-1],largestring,sizeStr);
1058 tab[sizeTab-1][sizeStr]='\0';
1059 }
1060 ptr=ptr+sizeDelim;
1061 largestring=ptr;
1062 }
1063
1064 /* adding last part if any */
1065 if( strlen(largestring) !=0 )
1066 {
1067 sizeStr=strlen(largestring);
1068 sizeTab++;
1069
1070 tab= (char**) realloc(tab,sizeof(char*)*sizeTab);
1071
1072 Malloc( tab[sizeTab-1], char,(int)( sizeof(char)*(sizeStr+1) ) );
1073 __n_assert( tab[ sizeTab - 1 ], goto error );
1074
1075 memcpy(tab[sizeTab-1],largestring,sizeStr);
1076 tab[sizeTab-1][sizeStr]='\0';
1077 }
1078 else
1079 {
1080 if( empty == 1 )
1081 {
1082 sizeTab++;
1083 tab= (char**) realloc(tab,sizeof(char*)*sizeTab);
1084
1085 Malloc( tab[sizeTab-1], char, (int)(sizeof(char)*1) );
1086 __n_assert( tab[ sizeTab - 1 ], goto error );
1087
1088 tab[sizeTab-1][0]='\0';
1089 }
1090 }
1091
1092 /* on ajoute une case a null pour finir le tableau */
1093 sizeTab++;
1094 tab= (char**) realloc(tab,sizeof(char*)*sizeTab);
1095 tab[sizeTab-1]=NULL;
1096
1097 return tab;
1098
1099error:
1100 free_split_result( &tab );
1101 return NULL;
1102} /* split( ... ) */
1103
1104
1105
1111int split_count( char **split_result )
1112{
1113 __n_assert( split_result, return -1 );
1114 __n_assert( split_result[ 0 ], return -1 );
1115
1116 int it = 0 ;
1117 while( split_result[ it ] )
1118 {
1119 it ++ ;
1120 }
1121 return it ;
1122} /* split_count(...) */
1123
1124
1125
1131int free_split_result( char ***tab )
1132{
1133 if( !(*tab) )
1134 return FALSE ;
1135
1136 int it = 0 ;
1137 while( (*tab)[ it ] )
1138 {
1139 Free( (*tab)[ it ] );
1140 it++;
1141 }
1142 Free( (*tab) );
1143
1144 return TRUE ;
1145}/* free_split_result(...)*/
1146
1153char* join( char** splitresult , char *delim )
1154{
1155 size_t delim_length = 0 ;
1156 if( delim )
1157 delim_length = strlen( delim );
1158 size_t total_length = 0 ;
1159 int it = 0 ;
1160 while( splitresult[ it ] )
1161 {
1162 //n_log( LOG_DEBUG , "split entry %d: %s" , it , splitresult[ it ] );
1163 total_length += strlen( splitresult[ it ] );
1164 //if there is a delimitor and 'it' isn't the last entry
1165 if( delim && splitresult[ it + 1 ] )
1166 total_length += delim_length ;
1167 it ++ ;
1168 }
1169 char *result = NULL ;
1170 Malloc( result , char , total_length + 1 );
1171 size_t position = 0 ;
1172 it = 0 ;
1173 while( splitresult[ it ] )
1174 {
1175 size_t copy_size = strlen( splitresult[ it ] );
1176 memcpy( &result[ position ] , splitresult[ it ] , copy_size );
1177 position += copy_size ;
1178 //if there is a delimitor and 'it' isn't the last entry
1179 if( delim && splitresult[ it + 1 ] )
1180 {
1181 memcpy( &result[ position ] , delim , delim_length );
1182 position += delim_length ;
1183 }
1184 it ++ ;
1185 }
1186 return result ;
1187} /* join */
1188
1189
1198int nstrcat_ex( N_STR *dest, void *src, NSTRBYTE size, int resize_flag )
1199{
1200 char *ptr = NULL ;
1201
1202 if( !src )
1203 {
1204 n_log( LOG_ERR, "src is NULL" );
1205 return FALSE ;
1206 }
1207
1208 if( dest )
1209 {
1210 if( ( dest -> written + size + 1 ) > dest -> length && resize_flag == 0 )
1211 {
1212 n_log( LOG_ERR, "%p to %p: not enough space. Resize forbidden. %lld needed, %lld available", dest, src, dest -> written + size + 1, dest -> length );
1213 return FALSE ;
1214 }
1215 }
1216 else
1217 {
1218 n_log( LOG_ERR, "dest is NULL" );
1219 return FALSE ;
1220 }
1221
1222 if( dest -> length < dest -> written + size + 1 )
1223 {
1224 dest -> length = dest -> written + size + 1 ;
1225 Reallocz( dest -> data, char, dest -> written , dest -> length );
1226 __n_assert( dest -> data, Free( dest ); return FALSE );
1227 }
1228
1229 ptr = dest -> data + dest -> written ;
1230 memcpy( ptr, src, size );
1231 dest -> written += size ;
1232
1233 dest -> data[ dest -> written ] = '\0' ;
1234
1235 return TRUE ;
1236} /* nstrcat_ex( ... ) */
1237
1238
1239
1246int nstrcat( N_STR *dst, N_STR *src )
1247{
1248 return nstrcat_ex( dst, src -> data, src -> written, 1 );
1249} /* nstrcat( ... ) */
1250
1251
1252
1260int nstrcat_bytes_ex( N_STR *dest, void *data, NSTRBYTE size )
1261{
1262 __n_assert( dest, return FALSE );
1263 __n_assert( data, return FALSE );
1264
1265 if( size <= 0 )
1266 {
1267 n_log( LOG_ERR, "Could not copy 0 or less (%ld) octet!", size );
1268 return FALSE ;
1269 }
1270
1271 return nstrcat_ex( dest, data, size, 1 );
1272} /* nstrcat_bytes_ex( ... )*/
1273
1274
1281int nstrcat_bytes( N_STR *dest, void *data )
1282{
1283 __n_assert( dest, return FALSE );
1284 __n_assert( data, return FALSE );
1285
1286 NSTRBYTE size = strlen( (char *)data );
1287 if( size <= 0 )
1288 {
1289 n_log( LOG_ERR, "Could not copy 0 or less (%ld) octet!", size );
1290 return FALSE ;
1291 }
1292 return nstrcat_bytes_ex( dest, data, size );
1293} /* nstrcat_bytes( ... )*/
1294
1295
1296
1297
1298
1299
1310int write_and_fit_ex( char **dest, NSTRBYTE *size, NSTRBYTE *written, const char *src, NSTRBYTE src_size, NSTRBYTE additional_padding )
1311{
1312 char *ptr = NULL ;
1313 NSTRBYTE needed_size = (*written) + src_size + 1 ;
1314
1315 // realloc if needed , also if destination is not allocated
1316 if( ( needed_size >= (*size) ) || !(*dest) )
1317 {
1318 if( !(*dest) )
1319 {
1320 (*written) = 0 ;
1321 (*size) = 0 ;
1322 }
1323 Reallocz( (*dest), char, (*size), needed_size + additional_padding );
1324 (*size) = needed_size ;
1325 if( !(*dest) )
1326 {
1327 n_log( LOG_ERR, "reallocation error !!!!" );
1328 return FALSE ;
1329 }
1330 }
1331 ptr = (*dest) + (*written) ;
1332 memcpy( ptr, src, src_size );
1333 (*written) += src_size ;
1334 (*dest)[ (*written) ] = '\0' ;
1335
1336 return TRUE ;
1337} /* write_and_fit_ex( ...) */
1338
1339
1340
1349int write_and_fit( char **dest, NSTRBYTE *size, NSTRBYTE *written, const char *src )
1350{
1351 return write_and_fit_ex( dest, size, written , src, strlen( src ) , 8 );
1352} /* write_and_fit( ...) */
1353
1354
1355
1363int scan_dir( const char *dir, LIST *result, const int recurse )
1364{
1365 return scan_dir_ex( dir, "*", result, recurse, 0 );
1366}
1367
1368
1369
1379int scan_dir_ex( const char *dir, const char *pattern, LIST *result, const int recurse, const int mode )
1380{
1381 DIR *dp = NULL ;
1382 struct dirent *entry = NULL;
1383 struct stat statbuf;
1384
1385 if( !result )
1386 return FALSE ;
1387
1388 if( ( dp = opendir( dir ) ) == NULL)
1389 {
1390 n_log( LOG_ERR, "cannot open directory: %s", dir );
1391 return FALSE ;
1392 }
1393
1394 N_STR *newname = NULL ;
1395 while( ( entry = readdir( dp ) ) != NULL )
1396 {
1397 nstrprintf( newname, "%s/%s", dir, entry -> d_name );
1398
1399 if( stat( newname -> data, &statbuf ) >= 0 )
1400 {
1401 if( S_ISDIR( statbuf . st_mode ) != 0 )
1402 {
1403 if( strcmp( ".", entry -> d_name ) == 0 || strcmp( "..", entry -> d_name ) == 0 )
1404 {
1405 free_nstr( &newname );
1406 continue;
1407 }
1408
1409 /* Recurse */
1410 if( recurse != FALSE )
1411 {
1412 if( scan_dir_ex( newname -> data, pattern, result, recurse, mode ) != TRUE )
1413 {
1414 n_log( LOG_ERR, "scan_dir_ex( %s , %s , %p , %d , %d ) returned FALSE !", newname -> data, pattern, result, recurse, mode );
1415 }
1416 }
1417 free_nstr( &newname );
1418 continue ;
1419 }
1420 else if( S_ISREG( statbuf . st_mode ) != 0 )
1421 {
1422 if( wildmatcase( newname -> data, pattern ) == TRUE )
1423 {
1424 if( mode == 0 )
1425 {
1426 char *file = strdup( newname -> data );
1427 if( file )
1428 {
1429 list_push( result, file, &free );
1430 }
1431 else
1432 {
1433 n_log( LOG_ERR, "Error adding %s/%s to list", dir, entry -> d_name );
1434 }
1435 }
1436 else if( mode == 1 )
1437 {
1438 list_push( result, newname, &free_nstr_ptr );
1439 newname = NULL ;
1440 }
1441 }
1442 }
1443 }
1444 if( newname )
1445 free_nstr( &newname );
1446 }
1447 closedir( dp );
1448 return TRUE ;
1449} /*scan_dir(...) */
1450
1451
1452
1459int wildmat(register const char *text, register const char *p)
1460{
1461 register int last = 0 ;
1462 register int matched = 0;
1463 register int reverse = 0;
1464
1465 for ( ; *p; text++, p++)
1466 {
1467 if (*text == '\0' && *p != '*')
1468 return WILDMAT_ABORT;
1469 switch (*p)
1470 {
1471 case '\\':
1472 /* Literal match with following character. */
1473 p++;
1474 /* FALLTHROUGH */
1475 default:
1476 if (*text != *p)
1477 return FALSE;
1478 continue;
1479 case '?':
1480 /* Match anything. */
1481 continue;
1482 case '*':
1483 while (*++p == '*')
1484 /* Consecutive stars act just like one. */
1485 continue;
1486 if (*p == '\0')
1487 /* Trailing star matches everything. */
1488 return TRUE;
1489 while (*text)
1490 if ((matched = wildmat(text++, p)) != FALSE)
1491 return matched;
1492 return WILDMAT_ABORT;
1493 case '[':
1494 reverse = p[1] == WILDMAT_NEGATE_CLASS ? TRUE : FALSE;
1495 if (reverse)
1496 /* Inverted character class. */
1497 p++;
1498 matched = FALSE;
1499 if (p[1] == ']' || p[1] == '-')
1500 if (*++p == *text)
1501 matched = TRUE;
1502 for (last = *p; *++p && *p != ']'; last = *p)
1503 /* This next line requires a good C compiler. */
1504 if (*p == '-' && p[1] != ']'
1505 ? *text <= *++p && *text >= last : *text == *p)
1506 matched = TRUE;
1507 if (matched == reverse)
1508 return FALSE;
1509 continue;
1510 }
1511 }
1512#ifdef WILDMAT_MATCH_TAR_PATTERN
1513 if (*text == '/')
1514 return TRUE;
1515#endif /* MATCH_TAR_ATTERN */
1516 return *text == '\0';
1517} /* wildmatch(...) */
1518
1519
1520
1527int wildmatcase(register const char *text, register const char *p)
1528{
1529 register int last;
1530 register int matched;
1531 register int reverse;
1532
1533 for ( ; *p; text++, p++)
1534 {
1535 if (*text == '\0' && *p != '*')
1536 return WILDMAT_ABORT;
1537 switch (*p)
1538 {
1539 case '\\':
1540 /* Literal match with following character. */
1541 p++;
1542 /* FALLTHROUGH */
1543 default:
1544 if (toupper(*text) != toupper(*p))
1545 return FALSE;
1546 continue;
1547 case '?':
1548 /* Match anything. */
1549 continue;
1550 case '*':
1551 while (*++p == '*')
1552 /* Consecutive stars act just like one. */
1553 continue;
1554 if (*p == '\0')
1555 /* Trailing star matches everything. */
1556 return TRUE;
1557 while (*text)
1558 if ((matched = wildmatcase(text++, p)) != FALSE)
1559 return matched;
1560 return WILDMAT_ABORT;
1561 case '[':
1562 reverse = p[1] == WILDMAT_NEGATE_CLASS ? TRUE : FALSE;
1563 if (reverse)
1564 /* Inverted character class. */
1565 p++;
1566 matched = FALSE;
1567 if (p[1] == ']' || p[1] == '-')
1568 if (toupper(*++p) == toupper(*text))
1569 matched = TRUE;
1570 for (last = toupper(*p); *++p && *p != ']'; last = toupper(*p))
1571 if (*p == '-' && p[1] != ']'
1572 ? toupper(*text) <= toupper(*++p) && toupper(*text) >= last : toupper(*text) == toupper(*p))
1573 matched = TRUE;
1574 if (matched == reverse)
1575 return FALSE;
1576 continue;
1577 }
1578 }
1579#ifdef WILDMAT_MATCH_TAR_PATTERN
1580 if (*text == '/')
1581 return TRUE;
1582#endif /* MATCH_TAR_ATTERN */
1583 return *text == '\0';
1584} /* wildmatcase(...) */
1585
1586
1587
1588
1598char *str_replace ( const char *string, const char *substr, const char *replacement )
1599{
1600 char *tok = NULL;
1601 char *newstr = NULL;
1602 char *oldstr = NULL;
1603 char *head = NULL;
1604
1605 /* if either substr or replacement is NULL, duplicate string a let caller handle it */
1606 if ( substr == NULL || replacement == NULL )
1607 return strdup (string);
1608 newstr = strdup (string);
1609 head = newstr;
1610 while ( (tok = strstr ( head, substr )))
1611 {
1612 oldstr = newstr;
1613 Malloc( newstr, char, strlen ( oldstr ) - strlen ( substr ) + strlen ( replacement ) + 8 );
1614 /*failed to alloc mem, free old string and return NULL */
1615 if ( newstr == NULL )
1616 {
1617 free (oldstr);
1618 return NULL;
1619 }
1620 memcpy ( newstr, oldstr, tok - oldstr );
1621 memcpy ( newstr + (tok - oldstr), replacement, strlen ( replacement ) );
1622 memcpy ( newstr + (tok - oldstr) + strlen( replacement ), tok + strlen ( substr ), strlen ( oldstr ) - strlen ( substr ) - ( tok - oldstr ) );
1623 memset ( newstr + strlen ( oldstr ) - strlen ( substr ) + strlen ( replacement ), 0, 1 );
1624 /* move back head right after the last replacement */
1625 head = newstr + (tok - oldstr) + strlen( replacement );
1626 free (oldstr);
1627 }
1628 return newstr;
1629}
1630
1640int str_sanitize_ex( char *string, const NSTRBYTE string_len, const char *mask, const NSTRBYTE masklen, const char replacement )
1641{
1642 __n_assert( string, return FALSE );
1643 __n_assert( mask, return FALSE );
1644
1645 NSTRBYTE it = 0 ;
1646 for( it = 0 ; it < string_len ; it ++ )
1647 {
1648 NSTRBYTE mask_it = 0 ;
1649 while( mask_it<masklen && mask[mask_it]!='\0')
1650 {
1651 if( string[ it ] == mask[ mask_it ] )
1652 string[ it ] = replacement ;
1653 mask_it ++ ;
1654 }
1655 }
1656 return TRUE ;
1657}
1658
1659
1667int str_sanitize( char *string, const char *mask, const char replacement )
1668{
1669 return str_sanitize_ex( string, strlen( string ), mask, strlen( mask ), replacement );
1670}
1671
1672
1673#endif /* #ifndef NOSTR */
1674
#define FreeNoLog(__ptr)
Free Handler without log.
Definition: n_common.h:268
#define Malloc(__ptr, __struct, __size)
Malloc Handler to get errors and set to 0.
Definition: n_common.h:183
#define __n_assert(__ptr, __ret)
macro to assert things
Definition: n_common.h:276
#define _str(__PTR)
define true
Definition: n_common.h:172
#define Reallocz(__ptr, __struct, __old_size, __size)
Realloc + zero new memory zone Handler to get errors.
Definition: n_common.h:236
#define Free(__ptr)
Free Handler to get errors.
Definition: n_common.h:256
int list_push(LIST *list, void *ptr, void(*destructor)(void *ptr))
Add a pointer to the end of the list.
Definition: n_list.c:244
Structure of a generic LIST container.
Definition: n_list.h:45
#define n_log(__LEVEL__,...)
Logging function wrapper to get line and func.
Definition: n_log.h:74
#define LOG_DEBUG
debug-level messages
Definition: n_log.h:66
#define LOG_ERR
error conditions
Definition: n_log.h:58
int str_to_long_long(const char *s, long long int *i, const int base)
Helper for string to integer.
Definition: n_str.c:778
int strcpy_u(char *from, char *to, NSTRBYTE to_size, char split, NSTRBYTE *it)
Copy from start to dest until from[ iterator ] == split.
Definition: n_str.c:990
int nstrcat(N_STR *dst, N_STR *src)
Add N_STR *src content to N_STR *dst, resizing it if needed.
Definition: n_str.c:1246
char * trim_nocopy(char *s)
trim and zero end the string, WARNING: keep and original pointer to delete the string correctly
Definition: n_str.c:124
void free_nstr_ptr(void *ptr)
Free a N_STR pointer structure.
Definition: n_str.c:55
size_t NSTRBYTE
N_STR base unit.
Definition: n_str.h:169
#define free_nstr(__ptr)
free a N_STR structure and set the pointer to NULL
Definition: n_str.h:222
int split_count(char **split_result)
Count split elements.
Definition: n_str.c:1111
#define nstrprintf(__nstr_var,...)
Macro to quickly allocate and sprintf to N_STR *.
Definition: n_str.h:97
int str_sanitize_ex(char *string, const NSTRBYTE string_len, const char *mask, const NSTRBYTE masklen, const char replacement)
clean a string by replacing evil characteres
Definition: n_str.c:1640
int nstr_to_file(N_STR *str, char *filename)
Write a N_STR content into a file.
Definition: n_str.c:459
int scan_dir_ex(const char *dir, const char *pattern, LIST *result, const int recurse, const int mode)
Scan a list of directory and return a list of char *file.
Definition: n_str.c:1379
int str_to_long_long_ex(const char *s, NSTRBYTE start, NSTRBYTE end, long long int *i, const int base)
Helper for string[start to end] to long long integer.
Definition: n_str.c:688
N_STR * nstrdup(N_STR *str)
Duplicate a N_STR.
Definition: n_str.c:795
int write_and_fit(char **dest, NSTRBYTE *size, NSTRBYTE *written, const char *src)
concatenate a copy of src of size strlen( src ) to dest, starting at dest[ written ],...
Definition: n_str.c:1349
int nstrcat_bytes_ex(N_STR *dest, void *data, NSTRBYTE size)
Append data into N_STR using internal N_STR size and cursor position.
Definition: n_str.c:1260
int nstrcat_bytes(N_STR *dest, void *data)
Append data into N_STR using internal N_STR size and cursor position.
Definition: n_str.c:1281
int str_to_int_ex(const char *s, NSTRBYTE start, NSTRBYTE end, int *i, const int base)
Helper for string[start to end] to integer.
Definition: n_str.c:492
int str_to_int_nolog(const char *s, NSTRBYTE start, NSTRBYTE end, int *i, const int base, N_STR **infos)
Helper for string[start to end] to integer.
Definition: n_str.c:545
int char_to_nstr_nocopy_ex(char *from, NSTRBYTE nboct, N_STR **to)
Convert a char into a N_STR, direct use of linked source pointer, extended version.
Definition: n_str.c:289
N_STR * char_to_nstr(const char *src)
Convert a char into a N_STR, short version.
Definition: n_str.c:273
char * nfgets(char *buffer, NSTRBYTE size, FILE *stream)
try to fgets
Definition: n_str.c:172
int skipw(char *string, char toskip, NSTRBYTE *iterator, int inc)
skip while 'toskip' occurence is found from 'iterator' to the next non 'toskip' position.
Definition: n_str.c:835
#define WILDMAT_ABORT
Abort code to sped up pattern matching.
Definition: n_str.h:58
int empty_nstr(N_STR *nstr)
empty a N_STR string
Definition: n_str.c:199
int wildmatcase(register const char *text, register const char *p)
Written by Rich Salz rsalz at osf.org, refurbished by me.
Definition: n_str.c:1527
#define WILDMAT_NEGATE_CLASS
What character marks an inverted character class?
Definition: n_str.h:60
N_STR * new_nstr(NSTRBYTE size)
create a new N_STR string
Definition: n_str.c:215
char * str_replace(const char *string, const char *substr, const char *replacement)
Replace "substr" by "replacement" inside string taken from http://coding.debuntu.org/c-implementing-s...
Definition: n_str.c:1598
int scan_dir(const char *dir, LIST *result, const int recurse)
Scan a list of directory and return a list of char *file.
Definition: n_str.c:1363
int str_sanitize(char *string, const char *mask, const char replacement)
clean a string by replacing evil characteres
Definition: n_str.c:1667
char ** split(const char *str, const char *delim, int empty)
split the strings into a an array of char *pointer , ended by a NULL one.
Definition: n_str.c:1032
int strup(char *string, char *dest)
Upper case a string.
Definition: n_str.c:942
int wildmat(register const char *text, register const char *p)
Written by Rich Salz rsalz at osf.org, refurbished by me.
Definition: n_str.c:1459
int free_nstr_nolog(N_STR **ptr)
Free a N_STR structure and set the pointer to NULL.
Definition: n_str.c:89
int str_to_long(const char *s, long int *i, const int base)
Helper for string to integer.
Definition: n_str.c:759
int nstrcat_ex(N_STR *dest, void *src, NSTRBYTE size, int resize_flag)
Append data into N_STR using internal N_STR size and cursor position.
Definition: n_str.c:1198
int char_to_nstr_ex(const char *from, NSTRBYTE nboct, N_STR **to)
Convert a char into a N_STR, extended version.
Definition: n_str.c:246
N_STR * char_to_nstr_nocopy(char *src)
Convert a char into a N_STR, direct use of linked source pointer, short version.
Definition: n_str.c:318
int _free_nstr(N_STR **ptr)
Free a N_STR structure and set the pointer to NULL.
Definition: n_str.c:72
int write_and_fit_ex(char **dest, NSTRBYTE *size, NSTRBYTE *written, const char *src, NSTRBYTE src_size, NSTRBYTE additional_padding)
concatenate a copy of src of size src_size to dest, starting at dest[ written ], updating written and...
Definition: n_str.c:1310
char * join(char **splitresult, char *delim)
join the array into a string
Definition: n_str.c:1153
N_STR * file_to_nstr(char *filename)
Load a whole file into a N_STR.
Definition: n_str.c:332
int free_split_result(char ***tab)
Free a split result allocated array.
Definition: n_str.c:1131
void free_nstr_ptr_nolog(void *ptr)
Free a N_STR pointer structure.
Definition: n_str.c:107
int str_to_int(const char *s, int *i, const int base)
Helper for string to integer.
Definition: n_str.c:592
int skipu(char *string, char toskip, NSTRBYTE *iterator, int inc)
skip until 'toskip' occurence is found from 'iterator' to the next 'toskip' value.
Definition: n_str.c:889
char * trim(char *s)
trim and put a \0 at the end, return new char *
Definition: n_str.c:156
int strlo(char *string, char *dest)
Upper case a string.
Definition: n_str.c:965
int nstr_to_fd(N_STR *str, FILE *out, int lock)
Write a N_STR content into a file.
Definition: n_str.c:402
int str_to_long_ex(const char *s, NSTRBYTE start, NSTRBYTE end, long int *i, const int base)
Helper for string[start to end] to long integer.
Definition: n_str.c:615
A box including a string and his lenght.
Definition: n_str.h:173
Common headers and low-level hugly functions & define.
Generic log system.
N_STR and string function declaration.