Nilorea Library
C utilities for networking, threading, graphics
Loading...
Searching...
No Matches
n_str.c
Go to the documentation of this file.
1
9#ifndef NO_NSTR
10
11#include "nilorea/n_common.h"
12#include "nilorea/n_log.h"
13#include "nilorea/n_str.h"
14
15#include <errno.h>
16#include <pthread.h>
17#include <math.h>
18#include <ctype.h>
19#include <stdio.h>
20#include <string.h>
21#include <limits.h>
22#include <stdlib.h>
23#include <dirent.h>
24
25#ifdef __windows__
32const char* strcasestr(const char* s1, const char* s2) {
33 __n_assert(s1, return NULL);
34 __n_assert(s2, return NULL);
35
36 size_t n = strlen(s2);
37 while (*s1) {
38 if (!strnicmp(s1++, s2, n))
39 return (s1 - 1);
40 }
41 return NULL;
42} /* strcasestr */
43#endif
44
49void free_nstr_ptr(void* ptr) {
50 N_STR* strptr = (N_STR*)ptr;
51 if (ptr && strptr) {
52 FreeNoLog(strptr->data);
53 FreeNoLog(strptr);
54 }
55} /* free_nstr_ptr( ... ) */
56
62int _free_nstr(N_STR** ptr) {
63 __n_assert(ptr && (*ptr), return FALSE);
64
65 FreeNoLog((*ptr)->data);
66 FreeNoLog((*ptr));
67
68 return TRUE;
69} /* free_nstr( ... ) */
70
77 if ((*ptr)) {
78 FreeNoLog((*ptr)->data);
79 FreeNoLog((*ptr));
80 }
81
82 return TRUE;
83} /* free_nstr( ... ) */
84
89void free_nstr_ptr_nolog(void* ptr) {
90 N_STR* strptr = (N_STR*)ptr;
91 if (strptr) {
92 FreeNoLog(strptr->data);
93 FreeNoLog(strptr);
94 }
95} /* free_nstr_ptr_nolog( ... ) */
96
102char* trim_nocopy(char* s) {
103 __n_assert(s, return NULL);
104
105 if (strlen(s) == 0)
106 return s;
107
108 char* start = s;
109
110 /* skip spaces at start */
111 while (*start && isspace(*start))
112 start++;
113
114 char* end = s + strlen(s) - 1;
115 /* iterate over the rest remebering last non-whitespace */
116 while (*end && isspace(*end) && end > s) {
117 end--;
118 }
119 end++;
120 /* write the terminating zero after last non-whitespace */
121 *end = 0;
122
123 return start;
124} /* trim_nocopy */
125
131char* trim(char* s) {
132 __n_assert(s, return NULL);
133
134 return strdup(trim_nocopy(s));
135} /* trim_nocopy */
136
144char* nfgets(char* buffer, NSTRBYTE size, FILE* stream) {
145 __n_assert(buffer, return NULL);
146 __n_assert(stream, return NULL);
147
148 if (size >= INT_MAX) {
149 n_log(LOG_ERR, "size of %zu too big, >INT_MAX for buffer %p", size, buffer);
150 return NULL;
151 }
152
153 if (!fgets(buffer, (int)size, stream)) {
154 return NULL;
155 }
156
157 return buffer;
158} /* nfgets(...) */
159
165int empty_nstr(N_STR* nstr) {
166 __n_assert(nstr, return FALSE);
167 __n_assert(nstr->data, return FALSE);
168
169 nstr->written = 0;
170 memset(nstr->data, 0, nstr->length);
171
172 return TRUE;
173}
174
181 N_STR* str = NULL;
182
183 Malloc(str, N_STR, 1);
184 __n_assert(str, return NULL);
185
186 str->written = 0;
187 if (size == 0) {
188 str->data = NULL;
189 str->length = 0;
190 } else {
191 Malloc(str->data, char, size + 1);
192 __n_assert(str->data, Free(str); return NULL);
193 str->length = size;
194 }
195 return str;
196} /* new_nstr(...) */
197
205int char_to_nstr_ex(const char* from, NSTRBYTE nboct, N_STR** to) {
206 if ((*to)) {
207 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");
208 n_log(LOG_ERR, "Data to copy: %s", _str(from));
209 return FALSE;
210 };
211
212 (*to) = new_nstr(nboct + 1);
213 __n_assert(to && (*to), return FALSE);
214 /* added a sizeof( void * ) to add a consistant and secure padding at the end */
215 __n_assert((*to)->data, Free((*to)); return FALSE);
216
217 memcpy((*to)->data, from, nboct);
218 (*to)->written = nboct;
219
220 return TRUE;
221} /* char_to_nstr(...) */
222
228N_STR* char_to_nstr(const char* src) {
229 __n_assert(src, return NULL);
230 N_STR* strptr = NULL;
231 size_t length = strlen(src);
232 char_to_nstr_ex(src, length, &strptr);
233 return strptr;
234} /* char_to_str(...) */
235
242 __n_assert(src, return NULL);
243
244 N_STR* to = NULL;
245 to = new_nstr(0);
246 __n_assert(to, return NULL);
247
248 to->data = src;
249 to->written = strlen(src);
250 to->length = to->written + 1; // include src end of string
251
252 return to;
253} /* char_to_str_nocopy(...) */
254
260N_STR* file_to_nstr(char* filename) {
261 N_STR* tmpstr = NULL;
262 struct stat filestat;
263 FILE* in = NULL;
264 int error = 0;
265
266 __n_assert(filename, n_log(LOG_ERR, "Unable to make a string from NULL filename"); return NULL);
267
268 int fd = open(filename, O_RDONLY);
269 error = errno;
270 if (fd == -1) {
271 n_log(LOG_ERR, "Unable to open %s for reading. Errno: %s", filename, strerror(error));
272 return NULL;
273 }
274
275 if (fstat(fd, &filestat) != 0) {
276 error = errno;
277#ifdef __linux__
278 if (error == EOVERFLOW) {
279 n_log(LOG_ERR, "%s size is too big ,EOVERFLOW)", filename);
280 } else {
281#endif
282 n_log(LOG_ERR, "Couldn't stat %s. Errno: %s", filename, strerror(error));
283#ifdef __linux__
284 }
285#endif
286 close(fd);
287 return NULL;
288 }
289
290 if ((filestat.st_size + 1) >= (pow(2, 32) - 1)) {
291 n_log(LOG_ERR, "file size >= 2GB is not possible yet. %s is %lld oct", filename, filestat.st_size);
292 return NULL;
293 }
294
295 n_log(LOG_DEBUG, "%s file size is: %lld", filename, (long long unsigned int)filestat.st_size);
296
297 in = fdopen(fd, "rb");
298 if (!in) {
299 n_log(LOG_ERR, "fdopen failed on %s (fd=%d)", filename, fd);
300 close(fd);
301 return NULL;
302 }
303
304 tmpstr = new_nstr((size_t)filestat.st_size + 1);
305 __n_assert(tmpstr, fclose(in); n_log(LOG_ERR, "Unable to get a new nstr of %ld octets", filestat.st_size + 1); return NULL);
306
307 tmpstr->written = (size_t)filestat.st_size;
308
309 if (fread(tmpstr->data, sizeof(char), tmpstr->written, in) == 0) {
310 n_log(LOG_ERR, "Couldn't read %s, fread return 0", filename);
311 free_nstr(&tmpstr);
312 fclose(in);
313 return NULL;
314 }
315 if (ferror(in)) {
316 n_log(LOG_ERR, "There were some errors when reading %s", filename);
317 free_nstr(&tmpstr);
318 fclose(in);
319 return NULL;
320 }
321
322 fclose(in);
323
324 return tmpstr;
325} /*file_to_nstr */
326
335/* Write a whole N_STR into a file */
336int nstr_to_fd(N_STR* str, FILE* out, int lock) {
337#ifdef __linux__
338 struct flock out_lock;
339#endif
340 __n_assert(out, return FALSE);
341 __n_assert(str, return FALSE);
342
343 int ret = TRUE;
344
345 if (lock == 1) {
346#ifdef __linux__
347 memset(&out_lock, 0, sizeof(out_lock));
348 out_lock.l_type = F_WRLCK;
349 /* Place a write lock on the file. */
350 fcntl(fileno(out), F_SETLKW, &out_lock);
351#else
352 lock = 2; /* compiler warning suppressor */
353#endif
354 }
355
356 size_t written_to_file = 0;
357 if ((written_to_file = fwrite(str->data, sizeof(char), str->written, out)) != (size_t)str->written) {
358 n_log(LOG_ERR, "Couldn't write file, fwrite %d of %d octets", written_to_file, str->written);
359 ret = FALSE;
360 }
361 if (ferror(out)) {
362 n_log(LOG_ERR, "There were some errors when writing to %d", fileno(out));
363 ret = FALSE;
364 }
365
366 if (lock == 1) {
367#ifdef __linux__
368 memset(&out_lock, 0, sizeof(out_lock));
369 out_lock.l_type = F_WRLCK;
370 /* Place a write lock on the file. */
371 fcntl(fileno(out), F_SETLKW, &out_lock);
372#else
373 lock = 2; /* compiler warning suppressor */
374#endif
375 }
376
377 return ret;
378} /* nstr_to_fd( ... ) */
379
386int nstr_to_file(N_STR* str, char* filename) {
387 __n_assert(str, return FALSE);
388 __n_assert(filename, return FALSE);
389
390 int fd = open(filename, O_CREAT | O_WRONLY | O_TRUNC, 0600); // Secure permissions: rw-------
391 if (fd == -1) {
392 n_log(LOG_ERR, "Couldn't open %s for writing (0600). Errno: %s", _str(filename), strerror(errno));
393 return FALSE;
394 }
395
396 FILE* out = NULL;
397 out = fdopen(fd, "wb");
398 if (!out) {
399 n_log(LOG_ERR, "fdopen failed for %s (fd=%d). Errno: %s", _str(filename), fd, strerror(errno));
400 close(fd);
401 return FALSE;
402 }
403
404 int ret = nstr_to_fd(str, out, 1);
405
406 fclose(out);
407
408 n_log(LOG_DEBUG, "%s file size is: %lld", _str(filename), (long long)str->written);
409
410 return ret;
411} /* nstr_to_file(...) */
412
424int str_to_int_ex(const char* s, NSTRBYTE start, NSTRBYTE end, int* i, const int base) {
425 char* tmpstr = NULL;
426 char* endstr = NULL;
427 long int l = 0;
428
429 __n_assert(s, return FALSE);
430
431 Malloc(tmpstr, char, sizeof(int) + end - start + 8);
432 __n_assert(tmpstr, n_log(LOG_ERR, "Unable to Malloc( tmpstr , char , sizeof( int ) + %d - %d )", end, start); return FALSE);
433
434 memcpy(tmpstr, s + start, end - start);
435
436 errno = 0;
437 l = strtol(tmpstr, &endstr, base);
438 if ((errno == ERANGE && l == LONG_MAX) || l > INT_MAX) {
439 n_log(LOG_ERR, "OVERFLOW reached when converting %s to int", tmpstr);
440 Free(tmpstr);
441 return FALSE;
442 }
443 if ((errno == ERANGE && l == LONG_MIN) || l < INT_MIN) {
444 n_log(LOG_ERR, "UNDERFLOW reached when converting %s to int", tmpstr);
445 Free(tmpstr);
446 return FALSE;
447 }
448 if (*endstr != '\0' && *endstr != '\n') {
449 n_log(LOG_ERR, "Impossible conversion for %s", tmpstr);
450 Free(tmpstr);
451 return FALSE;
452 }
453 Free(tmpstr);
454 *i = (int)l;
455 return TRUE;
456} /* str_to_int_ex( ... ) */
457
470int str_to_int_nolog(const char* s, NSTRBYTE start, NSTRBYTE end, int* i, const int base, N_STR** infos) {
471 char* tmpstr = NULL;
472 char* endstr = NULL;
473 long int l = 0;
474
475 __n_assert(s, return FALSE);
476
477 Malloc(tmpstr, char, sizeof(int) + end - start + 8);
478 __n_assert(tmpstr, n_log(LOG_ERR, "Unable to Malloc( tmpstr , char , sizeof( int ) + %d - %d )", end, start); return FALSE);
479
480 memcpy(tmpstr, s + start, end - start);
481
482 errno = 0;
483 l = strtol(tmpstr, &endstr, base);
484 if ((errno == ERANGE && l == LONG_MAX) || l > INT_MAX) {
485 nstrprintf((*infos), "OVERFLOW reached when converting %s to int", tmpstr);
486 Free(tmpstr);
487 return FALSE;
488 }
489 if ((errno == ERANGE && l == LONG_MIN) || l < INT_MIN) {
490 nstrprintf((*infos), "UNDERFLOW reached when converting %s to int", tmpstr);
491 Free(tmpstr);
492 return FALSE;
493 }
494 if (*endstr != '\0' && *endstr != '\n') {
495 nstrprintf((*infos), "Impossible conversion for %s", tmpstr);
496 Free(tmpstr);
497 return FALSE;
498 }
499 Free(tmpstr);
500 *i = (int)l;
501 return TRUE;
502} /* str_to_int_nolog( ... ) */
503
511int str_to_int(const char* s, int* i, const int base) {
512 int ret = FALSE;
513 if (s) {
514 ret = str_to_int_ex(s, 0, strlen(s), i, base);
515 }
516 return ret;
517} /* str_to_int(...) */
518
530int str_to_long_ex(const char* s, NSTRBYTE start, NSTRBYTE end, long int* i, const int base) {
531 char* tmpstr = NULL;
532 char* endstr = NULL;
533 long l = 0;
534
535 __n_assert(s, return FALSE);
536
537 Malloc(tmpstr, char, sizeof(int) + end - start + 8);
538 __n_assert(tmpstr, n_log(LOG_ERR, "Unable to Malloc( tmpstr , char , sizeof( int ) + %d - %d )", end, start); return FALSE);
539
540 memcpy(tmpstr, s + start, end - start);
541
542 errno = 0;
543 l = strtol(tmpstr, &endstr, base);
544 int error = errno;
545
546 /* test return to number and errno values */
547 if (tmpstr == endstr) {
548 n_log(LOG_ERR, " number : %lu invalid (no digits found, 0 returned)", l);
549 Free(tmpstr);
550 return FALSE;
551 } else if (error == ERANGE && l == LONG_MIN) {
552 n_log(LOG_ERR, " number : %lu invalid (underflow occurred)", l);
553 Free(tmpstr);
554 return FALSE;
555 } else if (error == ERANGE && l == LONG_MAX) {
556 n_log(LOG_ERR, " number : %lu invalid (overflow occurred)", l);
557 Free(tmpstr);
558 return FALSE;
559 } else if (error == EINVAL) /* not in all c99 implementations - gcc OK */
560 {
561 n_log(LOG_ERR, " number : %lu invalid (base contains unsupported value)", l);
562 Free(tmpstr);
563 return FALSE;
564 } else if (error != 0 && l == 0) {
565 n_log(LOG_ERR, " number : %lu invalid (unspecified error occurred)", l);
566 Free(tmpstr);
567 return FALSE;
568 } else if (error == 0 && tmpstr && !*endstr) {
569 n_log(LOG_DEBUG, " number : %lu valid (and represents all characters read)", l);
570 } else if (error == 0 && tmpstr && *endstr != 0) {
571 n_log(LOG_DEBUG, " number : %lu valid (but additional characters remain", l);
572 }
573 Free(tmpstr);
574 *i = l;
575 return TRUE;
576} /* str_to_long_ex( ... ) */
577
587int str_to_long_long_ex(const char* s, NSTRBYTE start, NSTRBYTE end, long long int* i, const int base) {
588 char* tmpstr = NULL;
589 char* endstr = NULL;
590 long long l = 0;
591
592 __n_assert(s, return FALSE);
593
594 Malloc(tmpstr, char, sizeof(int) + end - start + 8);
595 __n_assert(tmpstr, n_log(LOG_ERR, "Unable to Malloc( tmpstr , char , sizeof( int ) + %d - %d )", end, start); return FALSE);
596
597 memcpy(tmpstr, s + start, end - start);
598
599 errno = 0;
600 l = strtoll(tmpstr, &endstr, base);
601 int error = errno;
602
603 /* test return to number and errno values */
604 if (tmpstr == endstr) {
605 n_log(LOG_ERR, "number: '%s' invalid (no digits found, 0 returned)", s);
606 Free(tmpstr);
607 return FALSE;
608 } else if (error == ERANGE && l == LLONG_MIN) {
609 n_log(LOG_ERR, "number: '%s' invalid (underflow occurred)", s);
610 Free(tmpstr);
611 return FALSE;
612 } else if (error == ERANGE && l == LLONG_MAX) {
613 n_log(LOG_ERR, "number: 's' invalid (overflow occurred)", s);
614 Free(tmpstr);
615 return FALSE;
616 } else if (error == EINVAL) /* not in all c99 implementations - gcc OK */
617 {
618 n_log(LOG_ERR, "number: '%s' invalid (base contains unsupported value)", s);
619 Free(tmpstr);
620 return FALSE;
621 } else if (error != 0 && l == 0) {
622 n_log(LOG_ERR, "number: '%s' invalid (unspecified error occurred)", s);
623 Free(tmpstr);
624 return FALSE;
625 } else if (error == 0 && tmpstr && !*endstr) {
626 n_log(LOG_DEBUG, "number : '%llu' valid (and represents all characters read)", l);
627 } else if (error == 0 && tmpstr && *endstr != 0) {
628 n_log(LOG_DEBUG, " number : '%llu' valid (remaining characters: '%s')", l, s);
629 }
630 Free(tmpstr);
631 *i = l;
632 return TRUE;
633} /* str_to_long_long_ex( ... ) */
634
642int str_to_long(const char* s, long int* i, const int base) {
643 int ret = FALSE;
644 if (s) {
645 ret = str_to_long_ex(s, 0, strlen(s), i, base);
646 }
647 return ret;
648} /* str_to_long(...) */
649
657int str_to_long_long(const char* s, long long int* i, const int base) {
658 int ret = FALSE;
659 if (s) {
660 ret = str_to_long_long_ex(s, 0, strlen(s), i, base);
661 }
662 return ret;
663} /* str_to_long(...) */
664
671 N_STR* new_str = NULL;
672
673 __n_assert(str, return NULL);
674 __n_assert(str->data, return NULL);
675
676 new_str = new_nstr(str->length);
677 if (new_str) {
678 if (new_str->data) {
679 memcpy(new_str->data, str->data, str->written);
680 new_str->length = str->length;
681 new_str->written = str->written;
682 } else {
683 Free(new_str);
684 n_log(LOG_ERR, "Error duplicating N_STR %p -> data", str);
685 }
686 } else {
687 n_log(LOG_ERR, "Error duplicating N_STR %p", str);
688 }
689 return new_str;
690} /* nstrdup(...) */
691
701int skipw(char* string, char toskip, NSTRBYTE* iterator, int inc) {
702 int error_flag = 0;
703 // NSTRBYTE previous = 0 ;
704
705 __n_assert(string, return FALSE);
706
707 // previous = *iterator;
708 if (toskip == ' ') {
709 while (*iterator <= (NSTRBYTE)strlen(string) && isspace(string[*iterator])) {
710 if (inc < 0 && *iterator == 0) {
711 error_flag = 1;
712 break;
713 } else {
714 if (inc > 0)
715 *iterator = *iterator + (NSTRBYTE)inc;
716 else
717 *iterator = *iterator - (NSTRBYTE)inc;
718 }
719 }
720 } else {
721 while (*iterator <= (NSTRBYTE)strlen(string) && string[*iterator] == toskip) {
722 if (inc < 0 && *iterator == 0) {
723 error_flag = 1;
724 break;
725 } else {
726 if (inc > 0)
727 *iterator = *iterator + (NSTRBYTE)inc;
728 else
729 *iterator = *iterator - (NSTRBYTE)inc;
730 }
731 }
732 }
733 if (error_flag == 1 || *iterator > (NSTRBYTE)strlen(string)) {
734 //*iterator = previous ;
735 return FALSE;
736 }
737
738 return TRUE;
739} /*skipw(...)*/
740
750int skipu(char* string, char toskip, NSTRBYTE* iterator, int inc) {
751 int error_flag = 0;
752 // NSTRBYTE previous = 0 ;
753
754 __n_assert(string, return FALSE);
755
756 // previous = *iterator;
757 if (toskip == ' ') {
758 while (*iterator <= (NSTRBYTE)strlen(string) && !isspace(string[*iterator])) {
759 if (inc < 0 && *iterator == 0) {
760 error_flag = 1;
761 break;
762 } else {
763 if (inc > 0)
764 *iterator = *iterator + (NSTRBYTE)inc;
765 else
766 *iterator = *iterator - (NSTRBYTE)inc;
767 }
768 }
769 } else {
770 while (*iterator <= (NSTRBYTE)strlen(string) && string[*iterator] != toskip) {
771 if (inc < 0 && *iterator == 0) {
772 error_flag = 1;
773 break;
774 } else {
775 if (inc > 0)
776 *iterator = *iterator + (NSTRBYTE)inc;
777 else
778 *iterator = *iterator - (NSTRBYTE)inc;
779 }
780 }
781 }
782
783 if (error_flag == 1 || *iterator > (NSTRBYTE)strlen(string)) {
784 //*iterator = previous ;
785 return FALSE;
786 }
787
788 return TRUE;
789} /*Skipu(...)*/
790
798int strup(char* string, char* dest) {
799 NSTRBYTE it = 0;
800
801 __n_assert(string, return FALSE);
802 __n_assert(dest, return FALSE);
803
804 for (it = 0; it < (NSTRBYTE)strlen(string); it++)
805 dest[it] = (char)toupper(string[it]);
806
807 return TRUE;
808} /*strup(...)*/
809
817int strlo(char* string, char* dest) {
818 NSTRBYTE it = 0;
819
820 __n_assert(string, return FALSE);
821 __n_assert(dest, return FALSE);
822
823 for (it = 0; it < (NSTRBYTE)strlen(string); it++)
824 dest[it] = (char)tolower(string[it]);
825
826 return TRUE;
827} /*strlo(...)*/
828
838int strcpy_u(char* from, char* to, NSTRBYTE to_size, char split, NSTRBYTE* it) {
839 NSTRBYTE _it = 0;
840
841 __n_assert(from, return FALSE);
842 __n_assert(to, return FALSE);
843 __n_assert(it, return FALSE);
844
845 while (_it < to_size && from[(*it)] != '\0' && from[(*it)] != split) {
846 to[_it] = from[(*it)];
847 (*it) = (*it) + 1;
848 _it = _it + 1;
849 }
850
851 if (_it == to_size) {
852 _it--;
853 to[_it] = '\0';
854 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__);
855 return FALSE;
856 }
857
858 to[_it] = '\0';
859
860 if (from[(*it)] != split) {
861 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__);
862 return FALSE;
863 }
864 return TRUE;
865} /* strcpy_u(...) */
866
874char** split(const char* str, const char* delim, int empty) {
875 char** tab = NULL; /* result array */
876 char* ptr = NULL; /* tmp pointer */
877 char** tmp = NULL; /* temporary pointer for realloc */
878 size_t sizeStr = 0; /* string token size */
879 size_t sizeTab = 0; /* array size */
880 const char* largestring = NULL; /* pointer to start of string */
881
882 __n_assert(str, return NULL);
883 __n_assert(delim, return NULL);
884
885 size_t sizeDelim = strlen(delim);
886 largestring = str;
887
888 while ((ptr = strstr(largestring, delim)) != NULL) {
889 sizeStr = (size_t)(ptr - largestring);
890 if (empty == 1 || sizeStr != 0) {
891 sizeTab++;
892 tmp = (char**)realloc(tab, sizeof(char*) * sizeTab);
893 __n_assert(tmp, goto error);
894 tab = tmp;
895
896 Malloc(tab[sizeTab - 1], char, sizeof(char) * (sizeStr + 1));
897 __n_assert(tab[sizeTab - 1], goto error);
898
899 memcpy(tab[sizeTab - 1], largestring, sizeStr);
900 tab[sizeTab - 1][sizeStr] = '\0';
901 }
902 ptr = ptr + sizeDelim;
903 largestring = ptr;
904 }
905
906 /* adding last part if any */
907 if (strlen(largestring) != 0) {
908 sizeStr = strlen(largestring);
909 sizeTab++;
910
911 tmp = (char**)realloc(tab, sizeof(char*) * sizeTab);
912 __n_assert(tmp, goto error);
913 tab = tmp;
914
915 Malloc(tab[sizeTab - 1], char, sizeof(char) * (sizeStr + 1));
916 __n_assert(tab[sizeTab - 1], goto error);
917
918 memcpy(tab[sizeTab - 1], largestring, sizeStr);
919 tab[sizeTab - 1][sizeStr] = '\0';
920 } else {
921 if (empty == 1) {
922 sizeTab++;
923
924 tmp = (char**)realloc(tab, sizeof(char*) * sizeTab);
925 __n_assert(tmp, goto error);
926 tab = tmp;
927
928 Malloc(tab[sizeTab - 1], char, (int)(sizeof(char) * 1));
929 __n_assert(tab[sizeTab - 1], goto error);
930
931 tab[sizeTab - 1][0] = '\0';
932 }
933 }
934
935 /* on ajoute une case a null pour finir le tableau */
936 sizeTab++;
937 tmp = (char**)realloc(tab, sizeof(char*) * sizeTab);
938 __n_assert(tmp, goto error);
939 tab = tmp;
940 tab[sizeTab - 1] = NULL;
941
942 return tab;
943
944error:
945 free_split_result(&tab);
946 return NULL;
947} /* split( ... ) */
948
954int split_count(char** split_result) {
955 __n_assert(split_result, return -1);
956 __n_assert(split_result[0], return -1);
957
958 int it = 0;
959 while (split_result[it]) {
960 it++;
961 }
962 return it;
963} /* split_count(...) */
964
970int free_split_result(char*** tab) {
971 if (!(*tab))
972 return FALSE;
973
974 int it = 0;
975 while ((*tab)[it]) {
976 Free((*tab)[it]);
977 it++;
978 }
979 Free((*tab));
980
981 return TRUE;
982} /* free_split_result(...)*/
983
990char* join(char** splitresult, char* delim) {
991 size_t delim_length = 0;
992 if (delim)
993 delim_length = strlen(delim);
994 size_t total_length = 0;
995 int it = 0;
996 while (splitresult[it]) {
997 // n_log( LOG_DEBUG , "split entry %d: %s" , it , splitresult[ it ] );
998 total_length += strlen(splitresult[it]);
999 // if there is a delimitor and 'it' isn't the last entry
1000 if (delim && splitresult[it + 1])
1001 total_length += delim_length;
1002 it++;
1003 }
1004 char* result = NULL;
1005 Malloc(result, char, total_length + 1);
1006 size_t position = 0;
1007 it = 0;
1008 while (splitresult[it]) {
1009 size_t copy_size = strlen(splitresult[it]);
1010 memcpy(&result[position], splitresult[it], copy_size);
1011 position += copy_size;
1012 // if there is a delimitor and 'it' isn't the last entry
1013 if (delim && splitresult[it + 1]) {
1014 memcpy(&result[position], delim, delim_length);
1015 position += delim_length;
1016 }
1017 it++;
1018 }
1019 return result;
1020} /* join */
1021
1030N_STR* nstrcat_ex(N_STR** dest, void* src, NSTRBYTE size, int resize_flag) {
1031 char* ptr = NULL;
1032 __n_assert(src, return NULL);
1033
1034 if (resize_flag == 0) {
1035 if ((*dest)) {
1036 if (((*dest)->written + size + 1) > (*dest)->length) {
1037 n_log(LOG_ERR, "%p to %p: not enough space. Resize forbidden. %lld needed, %lld available", src, (*dest), (*dest)->written + size + 1, (*dest)->length);
1038 return NULL;
1039 }
1040 } else {
1041 n_log(LOG_ERR, "%p to %p: not enough space. Resize forbidden. %lld needed, destination is NULL", src, (*dest), size + 1);
1042 return NULL;
1043 }
1044 }
1045
1046 if (!(*dest)) {
1047 (*dest) = new_nstr(size + 1);
1048 }
1049
1050 if ((*dest)->length < (*dest)->written + size + 1) {
1051 (*dest)->length = (*dest)->written + size + 1;
1052 Reallocz((*dest)->data, char, (*dest)->written, (*dest)->length);
1053 __n_assert((*dest)->data, Free((*dest)); return FALSE);
1054 }
1055
1056 ptr = (*dest)->data + (*dest)->written;
1057 memcpy(ptr, src, size);
1058 (*dest)->written += size;
1059
1060 (*dest)->data[(*dest)->written] = '\0';
1061
1062 return (*dest);
1063} /* nstrcat_ex( ... ) */
1064
1072N_STR* nstrcat_bytes_ex(N_STR** dest, void* data, NSTRBYTE size) {
1073 __n_assert(dest, return NULL);
1074
1075 if (size <= 0) {
1076 n_log(LOG_ERR, "Could not copy 0 or less (%ld) octet!", size);
1077 return NULL;
1078 }
1079
1080 return nstrcat_ex(dest, data, size, 1);
1081} /* nstrcat_bytes_ex( ... )*/
1082
1093int write_and_fit_ex(char** dest, NSTRBYTE* size, NSTRBYTE* written, const char* src, NSTRBYTE src_size, NSTRBYTE additional_padding) {
1094 char* ptr = NULL;
1095 NSTRBYTE needed_size = (*written) + src_size + 1;
1096
1097 // realloc if needed , also if destination is not allocated
1098 if ((needed_size >= (*size)) || !(*dest)) {
1099 if (!(*dest)) {
1100 (*written) = 0;
1101 (*size) = 0;
1102 }
1103 Reallocz((*dest), char, (*size), needed_size + additional_padding);
1104 (*size) = needed_size;
1105 if (!(*dest)) {
1106 n_log(LOG_ERR, "reallocation error !!!!");
1107 return FALSE;
1108 }
1109 }
1110 ptr = (*dest) + (*written);
1111 memcpy(ptr, src, src_size);
1112 (*written) += src_size;
1113 (*dest)[(*written)] = '\0';
1114
1115 return TRUE;
1116} /* write_and_fit_ex( ...) */
1117
1126int write_and_fit(char** dest, NSTRBYTE* size, NSTRBYTE* written, const char* src) {
1127 return write_and_fit_ex(dest, size, written, src, strlen(src), 8);
1128} /* write_and_fit( ...) */
1129
1137int scan_dir(const char* dir, LIST* result, const int recurse) {
1138 return scan_dir_ex(dir, "*", result, recurse, 0);
1139}
1140
1150int scan_dir_ex(const char* dir, const char* pattern, LIST* result, const int recurse, const int mode) {
1151 DIR* dp = NULL;
1152 struct dirent* entry = NULL;
1153 struct stat statbuf;
1154
1155 if (!result)
1156 return FALSE;
1157
1158 if ((dp = opendir(dir)) == NULL) {
1159 n_log(LOG_ERR, "cannot open directory: %s", dir);
1160 return FALSE;
1161 }
1162
1163 N_STR* newname = NULL;
1164 while ((entry = readdir(dp)) != NULL) {
1165 nstrprintf(newname, "%s/%s", dir, entry->d_name);
1166
1167 if (stat(newname->data, &statbuf) >= 0) {
1168 if (S_ISDIR(statbuf.st_mode) != 0) {
1169 if (strcmp(".", entry->d_name) == 0 || strcmp("..", entry->d_name) == 0) {
1170 free_nstr(&newname);
1171 continue;
1172 }
1173
1174 /* Recurse */
1175 if (recurse != FALSE) {
1176 if (scan_dir_ex(newname->data, pattern, result, recurse, mode) != TRUE) {
1177 n_log(LOG_ERR, "scan_dir_ex( %s , %s , %p , %d , %d ) returned FALSE !", newname->data, pattern, result, recurse, mode);
1178 }
1179 }
1180 free_nstr(&newname);
1181 continue;
1182 } else if (S_ISREG(statbuf.st_mode) != 0) {
1183 if (wildmatcase(newname->data, pattern) == TRUE) {
1184 if (mode == 0) {
1185 char* file = strdup(newname->data);
1186 if (file) {
1187 list_push(result, file, &free);
1188 } else {
1189 n_log(LOG_ERR, "Error adding %s/%s to list", dir, entry->d_name);
1190 }
1191 } else if (mode == 1) {
1192 list_push(result, newname, &free_nstr_ptr);
1193 newname = NULL;
1194 }
1195 }
1196 }
1197 }
1198 if (newname)
1199 free_nstr(&newname);
1200 }
1201 closedir(dp);
1202 return TRUE;
1203} /*scan_dir(...) */
1204
1211int wildmat(register const char* text, register const char* p) {
1212 register int last = 0;
1213 register int matched = 0;
1214 register int reverse = 0;
1215
1216 for (; *p; text++, p++) {
1217 if (*text == '\0' && *p != '*')
1218 return WILDMAT_ABORT;
1219 switch (*p) {
1220 case '\\':
1221 /* Literal match with following character. */
1222 p++;
1223 /* FALLTHROUGH */
1224 default:
1225 if (*text != *p)
1226 return FALSE;
1227 continue;
1228 case '?':
1229 /* Match anything. */
1230 continue;
1231 case '*':
1232 while (*++p == '*')
1233 /* Consecutive stars act just like one. */
1234 continue;
1235 if (*p == '\0')
1236 /* Trailing star matches everything. */
1237 return TRUE;
1238 while (*text)
1239 if ((matched = wildmat(text++, p)) != FALSE)
1240 return matched;
1241 return WILDMAT_ABORT;
1242 case '[':
1243 reverse = p[1] == WILDMAT_NEGATE_CLASS ? TRUE : FALSE;
1244 if (reverse)
1245 /* Inverted character class. */
1246 p++;
1247 matched = FALSE;
1248 if (p[1] == ']' || p[1] == '-')
1249 if (*++p == *text)
1250 matched = TRUE;
1251 for (last = *p; *++p && *p != ']'; last = *p)
1252 /* This next line requires a good C compiler. */
1253 if (*p == '-' && p[1] != ']'
1254 ? *text <= *++p && *text >= last
1255 : *text == *p)
1256 matched = TRUE;
1257 if (matched == reverse)
1258 return FALSE;
1259 continue;
1260 }
1261 }
1262#ifdef WILDMAT_MATCH_TAR_PATTERN
1263 if (*text == '/')
1264 return TRUE;
1265#endif /* MATCH_TAR_ATTERN */
1266 return *text == '\0';
1267} /* wildmatch(...) */
1268
1275int wildmatcase(register const char* text, register const char* p) {
1276 register int last;
1277 register int matched;
1278 register int reverse;
1279
1280 for (; *p; text++, p++) {
1281 if (*text == '\0' && *p != '*')
1282 return WILDMAT_ABORT;
1283 switch (*p) {
1284 case '\\':
1285 /* Literal match with following character. */
1286 p++;
1287 /* FALLTHROUGH */
1288 default:
1289 if (toupper(*text) != toupper(*p))
1290 return FALSE;
1291 continue;
1292 case '?':
1293 /* Match anything. */
1294 continue;
1295 case '*':
1296 while (*++p == '*')
1297 /* Consecutive stars act just like one. */
1298 continue;
1299 if (*p == '\0')
1300 /* Trailing star matches everything. */
1301 return TRUE;
1302 while (*text)
1303 if ((matched = wildmatcase(text++, p)) != FALSE)
1304 return matched;
1305 return WILDMAT_ABORT;
1306 case '[':
1307 reverse = p[1] == WILDMAT_NEGATE_CLASS ? TRUE : FALSE;
1308 if (reverse)
1309 /* Inverted character class. */
1310 p++;
1311 matched = FALSE;
1312 if (p[1] == ']' || p[1] == '-')
1313 if (toupper(*++p) == toupper(*text))
1314 matched = TRUE;
1315 for (last = toupper(*p); *++p && *p != ']'; last = toupper(*p))
1316 if (*p == '-' && p[1] != ']'
1317 ? toupper(*text) <= toupper(*++p) && toupper(*text) >= last
1318 : toupper(*text) == toupper(*p))
1319 matched = TRUE;
1320 if (matched == reverse)
1321 return FALSE;
1322 continue;
1323 }
1324 }
1325#ifdef WILDMAT_MATCH_TAR_PATTERN
1326 if (*text == '/')
1327 return TRUE;
1328#endif /* MATCH_TAR_ATTERN */
1329 return *text == '\0';
1330} /* wildmatcase(...) */
1331
1341char* str_replace(const char* string, const char* substr, const char* replacement) {
1342 char* tok = NULL;
1343 char* newstr = NULL;
1344 char* oldstr = NULL;
1345 char* head = NULL;
1346
1347 /* if either substr or replacement is NULL, duplicate string a let caller handle it */
1348 if (substr == NULL || replacement == NULL)
1349 return strdup(string);
1350 newstr = strdup(string);
1351 head = newstr;
1352 while ((tok = strstr(head, substr))) {
1353 oldstr = newstr;
1354 Malloc(newstr, char, strlen(oldstr) - strlen(substr) + strlen(replacement) + 8);
1355 /*failed to alloc mem, free old string and return NULL */
1356 if (newstr == NULL) {
1357 free(oldstr);
1358 return NULL;
1359 }
1360 memcpy(newstr, oldstr, (size_t)(tok - oldstr));
1361 memcpy(newstr + (tok - oldstr), replacement, strlen(replacement));
1362 memcpy(newstr + (tok - oldstr) + strlen(replacement), tok + strlen(substr), strlen(oldstr) - strlen(substr) - (size_t)(tok - oldstr));
1363 memset(newstr + strlen(oldstr) - strlen(substr) + strlen(replacement), 0, 1);
1364 /* move back head right after the last replacement */
1365 head = newstr + (tok - oldstr) + strlen(replacement);
1366 free(oldstr);
1367 }
1368 return newstr;
1369}
1370
1380int str_sanitize_ex(char* string, const NSTRBYTE string_len, const char* mask, const NSTRBYTE masklen, const char replacement) {
1381 __n_assert(string, return FALSE);
1382 __n_assert(mask, return FALSE);
1383
1384 NSTRBYTE it = 0;
1385 for (it = 0; it < string_len; it++) {
1386 NSTRBYTE mask_it = 0;
1387 while (mask_it < masklen && mask[mask_it] != '\0') {
1388 if (string[it] == mask[mask_it])
1389 string[it] = replacement;
1390 mask_it++;
1391 }
1392 }
1393 return TRUE;
1394}
1395
1403int str_sanitize(char* string, const char* mask, const char replacement) {
1404 return str_sanitize_ex(string, strlen(string), mask, strlen(mask), replacement);
1405}
1406
1413int resize_nstr(N_STR* nstr, size_t size) {
1414 __n_assert(nstr, return FALSE);
1415 if (size == 0) {
1416 // Free the current buffer and reset fields
1417 Free(nstr->data);
1418 nstr->written = 0;
1419 nstr->length = 0;
1420 return TRUE;
1421 }
1422
1423 if (!nstr->data) {
1424 Malloc(nstr->data, char, size);
1425 } else {
1426 Reallocz(nstr->data, char, nstr->length, size);
1427 }
1428 __n_assert(nstr->data, return FALSE);
1429
1430 nstr->written = 0;
1431 nstr->length = size;
1432
1433 return TRUE;
1434}
1435
1443N_STR* nstrprintf_ex(N_STR** nstr_var, const char* format, ...) {
1444 __n_assert(format, return NULL);
1445
1446 va_list args;
1447 va_list args_copy;
1448 int needed_size = 0;
1449
1450 // Calculate the required size for the formatted string
1451 va_start(args, format);
1452 va_copy(args_copy, args); // Copy args for reuse
1453 needed_size = vsnprintf(NULL, 0, format, args);
1454 va_end(args);
1455
1456 if (needed_size < 0) {
1457 n_log(LOG_ERR, "there was an error while computing the new size according to format \"%s\" for N_STR %p", format, (*nstr_var));
1458 return NULL;
1459 }
1460
1461 size_t needed = (size_t)(needed_size + 1); // Include null-terminator
1462
1463 // Allocate or resize the N_STR object as needed
1464 if (!(*nstr_var)) {
1465 (*nstr_var) = new_nstr(needed);
1466 } else if (needed > (*nstr_var)->length) {
1467 if (resize_nstr((*nstr_var), needed) == FALSE) {
1468 n_log(LOG_ERR, "could not resize N_STR %p to size %zu", (*nstr_var), needed);
1469 return NULL;
1470 }
1471 }
1472
1473 // Write the formatted string into the buffer
1474 vsnprintf((*nstr_var)->data, needed, format, args_copy);
1475 va_end(args_copy);
1476
1477 (*nstr_var)->written = (size_t)needed_size;
1478 return (*nstr_var);
1479}
1480
1488N_STR* nstrprintf_cat_ex(N_STR** nstr_var, const char* format, ...) {
1489 __n_assert(format, return NULL);
1490
1491 va_list args;
1492 va_list args_copy;
1493 int needed_size = 0;
1494
1495 if (!(*nstr_var)) {
1496 // If the N_STR is not initialized, delegate to nstrprintf.
1497 va_start(args, format);
1498 va_copy(args_copy, args);
1499 (*nstr_var) = nstrprintf((*nstr_var), format, args_copy);
1500 va_end(args_copy);
1501 va_end(args);
1502 return (*nstr_var);
1503 }
1504
1505 // Calculate the size needed for the formatted string
1506 va_start(args, format);
1507 va_copy(args_copy, args);
1508 needed_size = vsnprintf(NULL, 0, format, args);
1509 va_end(args);
1510
1511 if (needed_size < 0) {
1512 n_log(LOG_ERR, "there was an error while computing the new size according to format \"%s\" for N_STR %p", format, (*nstr_var));
1513 va_end(args_copy);
1514 return NULL; // Nothing to concatenate
1515 }
1516
1517 size_t needed = (size_t)(needed_size + 1); // Include null-terminator
1518 size_t total_needed = (*nstr_var)->written + needed;
1519
1520 // Resize if necessary
1521 if (total_needed > (*nstr_var)->length) {
1522 resize_nstr((*nstr_var), total_needed);
1523 }
1524
1525 // Format and append to the buffer
1526 vsnprintf((*nstr_var)->data + (*nstr_var)->written, needed, format, args_copy);
1527 (*nstr_var)->written += (size_t)needed_size;
1528
1529 va_end(args_copy);
1530 return (*nstr_var);
1531}
1532
1533#endif /* #ifndef NOSTR */
#define FreeNoLog(__ptr)
Free Handler without log.
Definition n_common.h:251
#define Malloc(__ptr, __struct, __size)
Malloc Handler to get errors and set to 0.
Definition n_common.h:187
#define __n_assert(__ptr, __ret)
macro to assert things
Definition n_common.h:258
#define _str(__PTR)
define true
Definition n_common.h:176
#define Reallocz(__ptr, __struct, __old_size, __size)
Realloc + zero new memory zone Handler to get errors.
Definition n_common.h:227
#define Free(__ptr)
Free Handler to get errors.
Definition n_common.h:242
int list_push(LIST *list, void *ptr, void(*destructor)(void *ptr))
Add a pointer to the end of the list.
Definition n_list.c:199
Structure of a generic LIST container.
Definition n_list.h:39
#define n_log(__LEVEL__,...)
Logging function wrapper to get line and func.
Definition n_log.h:69
#define LOG_DEBUG
debug-level messages
Definition n_log.h:64
#define LOG_ERR
error conditions
Definition n_log.h:56
size_t written
size of the written data inside the string
Definition n_str.h:45
char * data
the string
Definition n_str.h:41
size_t length
length of string (in case we wanna keep information after the 0 end of string value)
Definition n_str.h:43
int str_to_long_long(const char *s, long long int *i, const int base)
Helper for string to integer.
Definition n_str.c:657
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:838
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:102
void free_nstr_ptr(void *ptr)
Free a N_STR pointer structure.
Definition n_str.c:49
size_t NSTRBYTE
N_STR base unit.
Definition n_str.h:36
#define free_nstr(__ptr)
free a N_STR structure and set the pointer to NULL
Definition n_str.h:176
int split_count(char **split_result)
Count split elements.
Definition n_str.c:954
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:1380
int nstr_to_file(N_STR *str, char *filename)
Write a N_STR content into a file.
Definition n_str.c:386
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:1150
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:587
N_STR * nstrdup(N_STR *str)
Duplicate a N_STR.
Definition n_str.c:670
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:1126
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:424
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:470
int resize_nstr(N_STR *nstr, size_t size)
reallocate a nstr internal buffer.
Definition n_str.c:1413
N_STR * char_to_nstr(const char *src)
Convert a char into a N_STR, short version.
Definition n_str.c:228
char * nfgets(char *buffer, NSTRBYTE size, FILE *stream)
try to fgets
Definition n_str.c:144
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:701
#define WILDMAT_ABORT
Abort code to sped up pattern matching.
Definition n_str.h:49
int empty_nstr(N_STR *nstr)
empty a N_STR string
Definition n_str.c:165
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:1275
#define WILDMAT_NEGATE_CLASS
What character marks an inverted character class?
Definition n_str.h:51
N_STR * new_nstr(NSTRBYTE size)
create a new N_STR string
Definition n_str.c:180
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:1341
#define nstrprintf(__nstr_var, __format,...)
Macro to quickly allocate and sprintf to N_STR.
Definition n_str.h:94
N_STR * 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:1072
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:1137
int str_sanitize(char *string, const char *mask, const char replacement)
clean a string by replacing evil characteres
Definition n_str.c:1403
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:874
int strup(char *string, char *dest)
Upper case a string.
Definition n_str.c:798
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:1211
int free_nstr_nolog(N_STR **ptr)
Free a N_STR structure and set the pointer to NULL.
Definition n_str.c:76
int str_to_long(const char *s, long int *i, const int base)
Helper for string to integer.
Definition n_str.c:642
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:205
N_STR * char_to_nstr_nocopy(char *src)
Convert a char into a N_STR, direct use of linked source pointer.
Definition n_str.c:241
int _free_nstr(N_STR **ptr)
Free a N_STR structure and set the pointer to NULL.
Definition n_str.c:62
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:1093
char * join(char **splitresult, char *delim)
join the array into a string
Definition n_str.c:990
N_STR * file_to_nstr(char *filename)
Load a whole file into a N_STR.
Definition n_str.c:260
int free_split_result(char ***tab)
Free a split result allocated array.
Definition n_str.c:970
void free_nstr_ptr_nolog(void *ptr)
Free a N_STR pointer structure.
Definition n_str.c:89
int str_to_int(const char *s, int *i, const int base)
Helper for string to integer.
Definition n_str.c:511
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:750
char * trim(char *s)
trim and put a \0 at the end, return new char *
Definition n_str.c:131
int strlo(char *string, char *dest)
Upper case a string.
Definition n_str.c:817
int nstr_to_fd(N_STR *str, FILE *out, int lock)
Write a N_STR content into a file.
Definition n_str.c:336
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:530
A box including a string and his lenght.
Definition n_str.h:39
Common headers and low-level functions & define.
Generic log system.
N_STR and string function declaration.