dictionary.c 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239
  1. /* libanode: the Anode C reference implementation
  2. * Copyright (C) 2009-2010 Adam Ierymenko <[email protected]>
  3. *
  4. * This program is free software: you can redistribute it and/or modify
  5. * it under the terms of the GNU General Public License as published by
  6. * the Free Software Foundation, either version 3 of the License, or
  7. * (at your option) any later version.
  8. *
  9. * This program is distributed in the hope that it will be useful,
  10. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. * GNU General Public License for more details.
  13. *
  14. * You should have received a copy of the GNU General Public License
  15. * along with this program. If not, see <http://www.gnu.org/licenses/>. */
  16. #include <stdio.h>
  17. #include <stdlib.h>
  18. #include "dictionary.h"
  19. static const char *EMPTY_STR = "";
  20. void AnodeDictionary_clear(struct AnodeDictionary *d)
  21. {
  22. struct AnodeDictionaryEntry *e,*ne;
  23. int oldcs;
  24. unsigned int i;
  25. oldcs = d->case_sensitive;
  26. for(i=0;i<ANODE_DICTIONARY_FIXED_HASH_TABLE_SIZE;++i) {
  27. e = d->ht[i];
  28. while (e) {
  29. ne = e->next;
  30. if ((e->key)&&(e->key != EMPTY_STR)) free((void *)e->key);
  31. if ((e->value)&&(e->value != EMPTY_STR)) free((void *)e->value);
  32. free((void *)e);
  33. e = ne;
  34. }
  35. }
  36. Anode_zero((void *)d,sizeof(struct AnodeDictionary));
  37. d->case_sensitive = oldcs;
  38. }
  39. void AnodeDictionary_put(struct AnodeDictionary *d,const char *key,const char *value)
  40. {
  41. struct AnodeDictionaryEntry *e;
  42. char *p1;
  43. const char *p2;
  44. unsigned int bucket = (d->case_sensitive) ? AnodeDictionary__get_bucket(key) : AnodeDictionary__get_bucket_ci(key);
  45. unsigned int len,i;
  46. e = d->ht[bucket];
  47. while (e) {
  48. if (((d->case_sensitive) ? Anode_streq(key,e->key) : Anode_strcaseeq(key,e->key))) {
  49. if (!d->case_sensitive) {
  50. p1 = e->key;
  51. p2 = key;
  52. while (*p2) *(p1++) = *(p2++);
  53. }
  54. len = 0;
  55. while (value[len]) ++len;
  56. if (len) {
  57. if ((e->value)&&(e->value != EMPTY_STR))
  58. e->value = (char *)realloc((void *)e->value,len + 1);
  59. else e->value = (char *)malloc(len + 1);
  60. for(i=0;i<len;++i) e->value[i] = value[i];
  61. e->value[i] = (char)0;
  62. } else {
  63. if ((e->value)&&(e->value != EMPTY_STR)) free((void *)e->value);
  64. e->value = (char *)EMPTY_STR;
  65. }
  66. return;
  67. }
  68. e = e->next;
  69. }
  70. e = (struct AnodeDictionaryEntry *)malloc(sizeof(struct AnodeDictionaryEntry));
  71. len = 0;
  72. while (key[len]) ++len;
  73. if (len) {
  74. e->key = (char *)malloc(len + 1);
  75. for(i=0;i<len;++i) e->key[i] = key[i];
  76. e->key[i] = (char)0;
  77. } else e->key = (char *)EMPTY_STR;
  78. len = 0;
  79. while (value[len]) ++len;
  80. if (len) {
  81. e->value = (char *)malloc(len + 1);
  82. for(i=0;i<len;++i) e->value[i] = value[i];
  83. e->value[i] = (char)0;
  84. } else e->value = (char *)EMPTY_STR;
  85. e->next = d->ht[bucket];
  86. d->ht[bucket] = e;
  87. ++d->size;
  88. }
  89. void AnodeDictionary_read(
  90. struct AnodeDictionary *d,
  91. char *in,
  92. const char *line_breaks,
  93. const char *kv_breaks,
  94. const char *comment_chars,
  95. char escape_char,
  96. int trim_whitespace_from_keys,
  97. int trim_whitespace_from_values)
  98. {
  99. char *line = in;
  100. char *key;
  101. char *value;
  102. char *p1,*p2,*p3;
  103. char last = ~escape_char;
  104. int eof_state = 0;
  105. for(;;) {
  106. if ((!*in)||((Anode_strchr(line_breaks,*in))&&((last != escape_char)||(!escape_char)))) {
  107. if (!*in)
  108. eof_state = 1;
  109. else *in = (char)0;
  110. if ((*line)&&((comment_chars)&&(!Anode_strchr(comment_chars,*line)))) {
  111. key = line;
  112. while (*line) {
  113. if ((Anode_strchr(kv_breaks,*line))&&((last != escape_char)||(!escape_char))) {
  114. *(line++) = (char)0;
  115. break;
  116. } else last = *(line++);
  117. }
  118. while ((*line)&&(Anode_strchr(kv_breaks,*line))&&((last != escape_char)||(!escape_char)))
  119. last = *(line++);
  120. value = line;
  121. if (escape_char) {
  122. p1 = key;
  123. while (*p1) {
  124. if (*p1 == escape_char) {
  125. p2 = p1;
  126. p3 = p1 + 1;
  127. while (*p3)
  128. *(p2++) = *(p3++);
  129. *p2 = (char)0;
  130. }
  131. ++p1;
  132. }
  133. p1 = value;
  134. while (*p1) {
  135. if (*p1 == escape_char) {
  136. p2 = p1;
  137. p3 = p1 + 1;
  138. while (*p3)
  139. *(p2++) = *(p3++);
  140. *p2 = (char)0;
  141. }
  142. ++p1;
  143. }
  144. }
  145. if (trim_whitespace_from_keys)
  146. Anode_trim(key);
  147. if (trim_whitespace_from_values)
  148. Anode_trim(value);
  149. AnodeDictionary_put(d,key,value);
  150. }
  151. if (eof_state)
  152. break;
  153. else line = in + 1;
  154. }
  155. last = *(in++);
  156. }
  157. }
  158. long AnodeDictionary_write(
  159. struct AnodeDictionary *d,
  160. char *out,
  161. long out_size,
  162. const char *line_break,
  163. const char *kv_break)
  164. {
  165. struct AnodeDictionaryEntry *e;
  166. const char *tmp;
  167. long ptr = 0;
  168. unsigned int bucket;
  169. if (out_size <= 0)
  170. return -1;
  171. for(bucket=0;bucket<ANODE_DICTIONARY_FIXED_HASH_TABLE_SIZE;++bucket) {
  172. e = d->ht[bucket];
  173. while (e) {
  174. tmp = e->key;
  175. if (tmp) {
  176. while (*tmp) {
  177. out[ptr++] = *tmp++;
  178. if (ptr >= (out_size - 1)) return -1;
  179. }
  180. }
  181. tmp = kv_break;
  182. if (tmp) {
  183. while (*tmp) {
  184. out[ptr++] = *tmp++;
  185. if (ptr >= (out_size - 1)) return -1;
  186. }
  187. }
  188. tmp = e->value;
  189. if (tmp) {
  190. while (*tmp) {
  191. out[ptr++] = *tmp++;
  192. if (ptr >= (out_size - 1)) return -1;
  193. }
  194. }
  195. tmp = line_break;
  196. if (tmp) {
  197. while (*tmp) {
  198. out[ptr++] = *tmp++;
  199. if (ptr >= (out_size - 1)) return -1;
  200. }
  201. }
  202. e = e->next;
  203. }
  204. }
  205. out[ptr] = (char)0;
  206. return ptr;
  207. }