split_string.h 1.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899
  1. #ifndef BADVPN_SPLIT_STRING_H
  2. #define BADVPN_SPLIT_STRING_H
  3. #include <string.h>
  4. #include <stdlib.h>
  5. #include <stdint.h>
  6. #include <limits.h>
  7. #include <misc/balloc.h>
  8. #include <misc/debug.h>
  9. static char ** split_string (const char *str, char del)
  10. {
  11. size_t len = strlen(str);
  12. // count parts
  13. size_t num_parts = 0;
  14. size_t i = 0;
  15. while (1) {
  16. size_t j = i;
  17. while (j < len && str[j] != del) j++;
  18. num_parts++;
  19. if (num_parts == SIZE_MAX) { // need to allocate +1 pointer
  20. goto fail0;
  21. }
  22. if (j == len) {
  23. break;
  24. }
  25. i = j + 1;
  26. }
  27. // allocate array for part pointers
  28. char **result = BAllocArray(num_parts + 1, sizeof(*result));
  29. if (!result) {
  30. goto fail0;
  31. }
  32. num_parts = 0;
  33. i = 0;
  34. while (1) {
  35. size_t j = i;
  36. while (j < len && str[j] != del) j++;
  37. if (!(result[num_parts] = malloc(j - i + 1))) {
  38. goto fail1;
  39. }
  40. memcpy(result[num_parts], str + i, j - i);
  41. result[num_parts][j - i] = '\0';
  42. num_parts++;
  43. if (j == len) {
  44. break;
  45. }
  46. i = j + 1;
  47. }
  48. result[num_parts] = NULL;
  49. return result;
  50. fail1:
  51. while (num_parts-- > 0) {
  52. free(result[num_parts]);
  53. }
  54. BFree(result);
  55. fail0:
  56. return NULL;
  57. }
  58. static size_t count_strings (char **names)
  59. {
  60. ASSERT(names)
  61. size_t i;
  62. for (i = 0; names[i]; i++);
  63. return i;
  64. }
  65. static void free_strings (char **names)
  66. {
  67. ASSERT(names)
  68. size_t i = count_strings(names);
  69. while (i-- > 0) {
  70. free(names[i]);
  71. }
  72. BFree(names);
  73. }
  74. #endif