PageRenderTime 41ms CodeModel.GetById 14ms RepoModel.GetById 0ms app.codeStats 0ms

/tokenize_string.c

https://gitlab.com/fzwoch/fodquake
C | 260 lines | 189 code | 53 blank | 18 comment | 38 complexity | 0ffe20b3fadd1f9c290c0228fbc9da35 MD5 | raw file
Possible License(s): GPL-2.0
  1. #include <stdlib.h>
  2. #include <string.h>
  3. #include <ctype.h>
  4. #include "tokenize_string.h"
  5. /*
  6. * String Tokenizing
  7. */
  8. struct tokenized_string_temp
  9. {
  10. struct tokenized_string_temp *next;
  11. char *token;
  12. };
  13. static void delete_token_temp(struct tokenized_string_temp *list, int delete_tokens)
  14. {
  15. struct tokenized_string_temp *tlist;
  16. while (list)
  17. {
  18. tlist = list->next;
  19. if (delete_tokens)
  20. free(list->token);
  21. free(list);
  22. list = tlist;
  23. }
  24. }
  25. static struct tokenized_string *create_tokenized_string(struct tokenized_string_temp *tst, int count)
  26. {
  27. struct tokenized_string *ts;
  28. struct tokenized_string_temp *tstt;
  29. int i;
  30. ts = calloc(1, sizeof(struct tokenized_string));
  31. if (ts == NULL)
  32. {
  33. delete_token_temp(tst, 1);
  34. return NULL;
  35. }
  36. ts->tokens = calloc(count, sizeof(char *));
  37. if (ts->tokens == NULL)
  38. {
  39. delete_token_temp(tst, 1);
  40. free(ts);
  41. return NULL;
  42. }
  43. tstt = tst;
  44. for (i=0; i<count; i++)
  45. {
  46. ts->tokens[i] = tstt->token;
  47. tstt = tstt->next;
  48. }
  49. delete_token_temp(tst, 0);
  50. ts->count = count;
  51. return ts;
  52. }
  53. static int add_token_to_temp(struct tokenized_string_temp **list, char *token)
  54. {
  55. struct tokenized_string_temp *temp, *temp1;;
  56. temp = calloc(1, sizeof(struct tokenized_string_temp));
  57. if (temp == NULL)
  58. return 1;
  59. temp->token = token;
  60. if (*list == NULL)
  61. *list = temp;
  62. else
  63. {
  64. temp1 = *list;
  65. while (temp1->next)
  66. temp1 = temp1->next;
  67. temp1->next = temp;
  68. }
  69. return 0;
  70. }
  71. /*
  72. * These two functions should probably be merged into one to avoid code
  73. * duplication. Also there's lots of opportunities for doing things more
  74. * efficiently in this code. Instead of using a list, realloc could be used,
  75. * or maybe even a two-pass scan. Also some conditional checks in the code are
  76. * unnecessary, but nevermind :)
  77. *
  78. * As far as I can tell, this code will create an empty token if the string
  79. * ends with a space, and space is not the delimiter, or in the case of space
  80. * being the delimiter, if the string ends with two spaces.
  81. *
  82. * The token pointer is leaked in case add_token_to_temp() fails.
  83. *
  84. * - bigfoot
  85. */
  86. struct tokenized_string *Tokenize_String_Delimiter(char *string, char delimiter)
  87. {
  88. char *p_start, *p_end;
  89. struct tokenized_string_temp *tt = NULL;
  90. char *token;
  91. int len, i, count;
  92. p_start = string;
  93. p_end = p_start;
  94. len = strlen(p_start);
  95. count = 0;
  96. i = 0;
  97. while (*p_start && i < len)
  98. {
  99. while (*p_start == ' ')
  100. {
  101. p_start++;
  102. i++;
  103. }
  104. if (*p_start == delimiter)
  105. {
  106. p_start++;
  107. i++;
  108. }
  109. p_end = p_start;
  110. while (*p_end != delimiter && i < len)
  111. {
  112. p_end++;
  113. i++;
  114. }
  115. token = calloc(p_end - p_start + 1, sizeof(char));
  116. if (token == NULL)
  117. {
  118. delete_token_temp(tt, 1);
  119. return NULL;
  120. }
  121. memcpy(token, p_start, p_end - p_start);
  122. token[p_end - p_start] = '\0';
  123. if (add_token_to_temp(&tt, token))
  124. {
  125. delete_token_temp(tt, 1);
  126. return NULL;
  127. }
  128. p_start = p_end;
  129. p_start++;
  130. i++;
  131. count++;
  132. }
  133. return create_tokenized_string(tt, count);
  134. }
  135. struct tokenized_string *Tokenize_String(char *string)
  136. {
  137. char *p_start, *p_end;
  138. struct tokenized_string_temp *tt = NULL;
  139. char *token;
  140. int len, i, count;
  141. char end_token;
  142. p_start = string;
  143. p_end = p_start;
  144. len = strlen(p_start);
  145. count = 0;
  146. i = 0;
  147. while (*p_start && i < len)
  148. {
  149. while (*p_start == ' ')
  150. {
  151. p_start++;
  152. i++;
  153. }
  154. if (*p_start == '"')
  155. {
  156. end_token = '"';
  157. p_start++;
  158. i++;
  159. }
  160. else
  161. end_token = ' ';
  162. p_end = p_start;
  163. while (*p_end != end_token && i < len)
  164. {
  165. p_end++;
  166. i++;
  167. }
  168. token = calloc(p_end - p_start + 1, sizeof(char));
  169. if (token == NULL)
  170. {
  171. delete_token_temp(tt, 1);
  172. return NULL;
  173. }
  174. memcpy(token, p_start, p_end - p_start);
  175. token[p_end - p_start] = '\0';
  176. if (add_token_to_temp(&tt, token))
  177. {
  178. delete_token_temp(tt, 1);
  179. return NULL;
  180. }
  181. p_start = p_end;
  182. if (end_token == '"')
  183. {
  184. p_start++;
  185. p_end++;
  186. i++;
  187. }
  188. count++;
  189. }
  190. return create_tokenized_string(tt, count);
  191. }
  192. void Tokenize_String_Delete(struct tokenized_string *ts)
  193. {
  194. int i;
  195. for (i=0; i<ts->count; i++)
  196. {
  197. free(ts->tokens[i]);
  198. }
  199. free(ts->tokens);
  200. free(ts);
  201. }