split_string.h 2.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126
  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. #include <misc/expstring.h>
  10. static char ** split_string (const char *str, char del)
  11. {
  12. size_t len = strlen(str);
  13. // count parts
  14. size_t num_parts = 0;
  15. size_t i = 0;
  16. while (1) {
  17. size_t j = i;
  18. while (j < len && str[j] != del) j++;
  19. num_parts++;
  20. if (num_parts == SIZE_MAX) { // need to allocate +1 pointer
  21. goto fail0;
  22. }
  23. if (j == len) {
  24. break;
  25. }
  26. i = j + 1;
  27. }
  28. // allocate array for part pointers
  29. char **result = BAllocArray(num_parts + 1, sizeof(*result));
  30. if (!result) {
  31. goto fail0;
  32. }
  33. num_parts = 0;
  34. i = 0;
  35. while (1) {
  36. size_t j = i;
  37. while (j < len && str[j] != del) j++;
  38. if (!(result[num_parts] = malloc(j - i + 1))) {
  39. goto fail1;
  40. }
  41. memcpy(result[num_parts], str + i, j - i);
  42. result[num_parts][j - i] = '\0';
  43. num_parts++;
  44. if (j == len) {
  45. break;
  46. }
  47. i = j + 1;
  48. }
  49. result[num_parts] = NULL;
  50. return result;
  51. fail1:
  52. while (num_parts-- > 0) {
  53. free(result[num_parts]);
  54. }
  55. BFree(result);
  56. fail0:
  57. return NULL;
  58. }
  59. static size_t count_strings (char **names)
  60. {
  61. ASSERT(names)
  62. size_t i;
  63. for (i = 0; names[i]; i++);
  64. return i;
  65. }
  66. static void free_strings (char **names)
  67. {
  68. ASSERT(names)
  69. size_t i = count_strings(names);
  70. while (i-- > 0) {
  71. free(names[i]);
  72. }
  73. BFree(names);
  74. }
  75. static char * implode_strings (char **names, char del)
  76. {
  77. ASSERT(names)
  78. ExpString str;
  79. if (!ExpString_Init(&str)) {
  80. goto fail0;
  81. }
  82. for (size_t i = 0; names[i]; i++) {
  83. if (i > 0 && !ExpString_AppendChar(&str, del)) {
  84. goto fail1;
  85. }
  86. if (!ExpString_Append(&str, names[i])) {
  87. goto fail1;
  88. }
  89. }
  90. return ExpString_Get(&str);
  91. fail1:
  92. ExpString_Free(&str);
  93. fail0:
  94. return NULL;
  95. }
  96. #endif