THIS IS A TEST INSTANCE ONLY! REPOSITORIES CAN BE DELETED AT ANY TIME!

Git Source Code Mirror - This is a publish-only repository and all pull requests are ignored. Please follow Documentation/SubmittingPatches procedure for any of your improvements.
git
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

311 lines
7.3 KiB

  1. #include "cache.h"
  2. #include "string-list.h"
  3. void string_list_init(struct string_list *list, int strdup_strings)
  4. {
  5. memset(list, 0, sizeof(*list));
  6. list->strdup_strings = strdup_strings;
  7. }
  8. /* if there is no exact match, point to the index where the entry could be
  9. * inserted */
  10. static int get_entry_index(const struct string_list *list, const char *string,
  11. int *exact_match)
  12. {
  13. int left = -1, right = list->nr;
  14. compare_strings_fn cmp = list->cmp ? list->cmp : strcmp;
  15. while (left + 1 < right) {
  16. int middle = (left + right) / 2;
  17. int compare = cmp(string, list->items[middle].string);
  18. if (compare < 0)
  19. right = middle;
  20. else if (compare > 0)
  21. left = middle;
  22. else {
  23. *exact_match = 1;
  24. return middle;
  25. }
  26. }
  27. *exact_match = 0;
  28. return right;
  29. }
  30. /* returns -1-index if already exists */
  31. static int add_entry(int insert_at, struct string_list *list, const char *string)
  32. {
  33. int exact_match = 0;
  34. int index = insert_at != -1 ? insert_at : get_entry_index(list, string, &exact_match);
  35. if (exact_match)
  36. return -1 - index;
  37. if (list->nr + 1 >= list->alloc) {
  38. list->alloc += 32;
  39. REALLOC_ARRAY(list->items, list->alloc);
  40. }
  41. if (index < list->nr)
  42. memmove(list->items + index + 1, list->items + index,
  43. (list->nr - index)
  44. * sizeof(struct string_list_item));
  45. list->items[index].string = list->strdup_strings ?
  46. xstrdup(string) : (char *)string;
  47. list->items[index].util = NULL;
  48. list->nr++;
  49. return index;
  50. }
  51. struct string_list_item *string_list_insert(struct string_list *list, const char *string)
  52. {
  53. int index = add_entry(-1, list, string);
  54. if (index < 0)
  55. index = -1 - index;
  56. return list->items + index;
  57. }
  58. int string_list_has_string(const struct string_list *list, const char *string)
  59. {
  60. int exact_match;
  61. get_entry_index(list, string, &exact_match);
  62. return exact_match;
  63. }
  64. int string_list_find_insert_index(const struct string_list *list, const char *string,
  65. int negative_existing_index)
  66. {
  67. int exact_match;
  68. int index = get_entry_index(list, string, &exact_match);
  69. if (exact_match)
  70. index = -1 - (negative_existing_index ? index : 0);
  71. return index;
  72. }
  73. struct string_list_item *string_list_lookup(struct string_list *list, const char *string)
  74. {
  75. int exact_match, i = get_entry_index(list, string, &exact_match);
  76. if (!exact_match)
  77. return NULL;
  78. return list->items + i;
  79. }
  80. void string_list_remove_duplicates(struct string_list *list, int free_util)
  81. {
  82. if (list->nr > 1) {
  83. int src, dst;
  84. compare_strings_fn cmp = list->cmp ? list->cmp : strcmp;
  85. for (src = dst = 1; src < list->nr; src++) {
  86. if (!cmp(list->items[dst - 1].string, list->items[src].string)) {
  87. if (list->strdup_strings)
  88. free(list->items[src].string);
  89. if (free_util)
  90. free(list->items[src].util);
  91. } else
  92. list->items[dst++] = list->items[src];
  93. }
  94. list->nr = dst;
  95. }
  96. }
  97. int for_each_string_list(struct string_list *list,
  98. string_list_each_func_t fn, void *cb_data)
  99. {
  100. int i, ret = 0;
  101. for (i = 0; i < list->nr; i++)
  102. if ((ret = fn(&list->items[i], cb_data)))
  103. break;
  104. return ret;
  105. }
  106. void filter_string_list(struct string_list *list, int free_util,
  107. string_list_each_func_t want, void *cb_data)
  108. {
  109. int src, dst = 0;
  110. for (src = 0; src < list->nr; src++) {
  111. if (want(&list->items[src], cb_data)) {
  112. list->items[dst++] = list->items[src];
  113. } else {
  114. if (list->strdup_strings)
  115. free(list->items[src].string);
  116. if (free_util)
  117. free(list->items[src].util);
  118. }
  119. }
  120. list->nr = dst;
  121. }
  122. static int item_is_not_empty(struct string_list_item *item, void *unused)
  123. {
  124. return *item->string != '\0';
  125. }
  126. void string_list_remove_empty_items(struct string_list *list, int free_util) {
  127. filter_string_list(list, free_util, item_is_not_empty, NULL);
  128. }
  129. void string_list_clear(struct string_list *list, int free_util)
  130. {
  131. if (list->items) {
  132. int i;
  133. if (list->strdup_strings) {
  134. for (i = 0; i < list->nr; i++)
  135. free(list->items[i].string);
  136. }
  137. if (free_util) {
  138. for (i = 0; i < list->nr; i++)
  139. free(list->items[i].util);
  140. }
  141. free(list->items);
  142. }
  143. list->items = NULL;
  144. list->nr = list->alloc = 0;
  145. }
  146. void string_list_clear_func(struct string_list *list, string_list_clear_func_t clearfunc)
  147. {
  148. if (list->items) {
  149. int i;
  150. if (clearfunc) {
  151. for (i = 0; i < list->nr; i++)
  152. clearfunc(list->items[i].util, list->items[i].string);
  153. }
  154. if (list->strdup_strings) {
  155. for (i = 0; i < list->nr; i++)
  156. free(list->items[i].string);
  157. }
  158. free(list->items);
  159. }
  160. list->items = NULL;
  161. list->nr = list->alloc = 0;
  162. }
  163. void print_string_list(const struct string_list *p, const char *text)
  164. {
  165. int i;
  166. if ( text )
  167. printf("%s\n", text);
  168. for (i = 0; i < p->nr; i++)
  169. printf("%s:%p\n", p->items[i].string, p->items[i].util);
  170. }
  171. struct string_list_item *string_list_append_nodup(struct string_list *list,
  172. char *string)
  173. {
  174. struct string_list_item *retval;
  175. ALLOC_GROW(list->items, list->nr + 1, list->alloc);
  176. retval = &list->items[list->nr++];
  177. retval->string = string;
  178. retval->util = NULL;
  179. return retval;
  180. }
  181. struct string_list_item *string_list_append(struct string_list *list,
  182. const char *string)
  183. {
  184. return string_list_append_nodup(
  185. list,
  186. list->strdup_strings ? xstrdup(string) : (char *)string);
  187. }
  188. /* Yuck */
  189. static compare_strings_fn compare_for_qsort;
  190. /* Only call this from inside string_list_sort! */
  191. static int cmp_items(const void *a, const void *b)
  192. {
  193. const struct string_list_item *one = a;
  194. const struct string_list_item *two = b;
  195. return compare_for_qsort(one->string, two->string);
  196. }
  197. void string_list_sort(struct string_list *list)
  198. {
  199. compare_for_qsort = list->cmp ? list->cmp : strcmp;
  200. qsort(list->items, list->nr, sizeof(*list->items), cmp_items);
  201. }
  202. struct string_list_item *unsorted_string_list_lookup(struct string_list *list,
  203. const char *string)
  204. {
  205. struct string_list_item *item;
  206. compare_strings_fn cmp = list->cmp ? list->cmp : strcmp;
  207. for_each_string_list_item(item, list)
  208. if (!cmp(string, item->string))
  209. return item;
  210. return NULL;
  211. }
  212. int unsorted_string_list_has_string(struct string_list *list,
  213. const char *string)
  214. {
  215. return unsorted_string_list_lookup(list, string) != NULL;
  216. }
  217. void unsorted_string_list_delete_item(struct string_list *list, int i, int free_util)
  218. {
  219. if (list->strdup_strings)
  220. free(list->items[i].string);
  221. if (free_util)
  222. free(list->items[i].util);
  223. list->items[i] = list->items[list->nr-1];
  224. list->nr--;
  225. }
  226. int string_list_split(struct string_list *list, const char *string,
  227. int delim, int maxsplit)
  228. {
  229. int count = 0;
  230. const char *p = string, *end;
  231. if (!list->strdup_strings)
  232. die("internal error in string_list_split(): "
  233. "list->strdup_strings must be set");
  234. for (;;) {
  235. count++;
  236. if (maxsplit >= 0 && count > maxsplit) {
  237. string_list_append(list, p);
  238. return count;
  239. }
  240. end = strchr(p, delim);
  241. if (end) {
  242. string_list_append_nodup(list, xmemdupz(p, end - p));
  243. p = end + 1;
  244. } else {
  245. string_list_append(list, p);
  246. return count;
  247. }
  248. }
  249. }
  250. int string_list_split_in_place(struct string_list *list, char *string,
  251. int delim, int maxsplit)
  252. {
  253. int count = 0;
  254. char *p = string, *end;
  255. if (list->strdup_strings)
  256. die("internal error in string_list_split_in_place(): "
  257. "list->strdup_strings must not be set");
  258. for (;;) {
  259. count++;
  260. if (maxsplit >= 0 && count > maxsplit) {
  261. string_list_append(list, p);
  262. return count;
  263. }
  264. end = strchr(p, delim);
  265. if (end) {
  266. *end = '\0';
  267. string_list_append(list, p);
  268. p = end + 1;
  269. } else {
  270. string_list_append(list, p);
  271. return count;
  272. }
  273. }
  274. }