ini.c 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236
  1. /*
  2. * ini.c
  3. */
  4. #include "private.h"
  5. #include "lub/string.h"
  6. #include <stdlib.h>
  7. #include <stdio.h>
  8. #include <string.h>
  9. #include <assert.h>
  10. #include <ctype.h>
  11. /*--------------------------------------------------------- */
  12. void lub_ini_init(lub_ini_t *this)
  13. {
  14. assert(this);
  15. memset(this, 0, sizeof(*this));
  16. this->list = lub_list_new(lub_pair_compare, lub_pair_free);
  17. }
  18. /*--------------------------------------------------------- */
  19. lub_ini_t *lub_ini_new(void)
  20. {
  21. lub_ini_t *this;
  22. this = malloc(sizeof(*this));
  23. if (this)
  24. lub_ini_init(this);
  25. return this;
  26. }
  27. /*--------------------------------------------------------- */
  28. void lub_ini_fini(lub_ini_t *this)
  29. {
  30. lub_list_free_all(this->list);
  31. }
  32. /*--------------------------------------------------------- */
  33. void lub_ini_free(lub_ini_t *this)
  34. {
  35. assert(this);
  36. lub_ini_fini(this);
  37. free(this);
  38. }
  39. /*--------------------------------------------------------- */
  40. void lub_ini_add(lub_ini_t *this, lub_pair_t *pair)
  41. {
  42. lub_list_node_t *node = NULL;
  43. lub_pair_t *pair_in_list = NULL;
  44. assert(this);
  45. node = lub_list_find_add(this->list, pair);
  46. if (!node)
  47. return; // Strange error
  48. // INI file can contain multiple strings with the same keys. We will
  49. // consider last entry as actual.
  50. pair_in_list = (lub_pair_t *)lub_list_node__get_data(node);
  51. // Check for duplicate entry
  52. if (pair_in_list != pair) {
  53. // Set actual value
  54. lub_pair__set_value(pair_in_list, lub_pair__get_value(pair));
  55. lub_pair_free(pair);
  56. }
  57. }
  58. /*--------------------------------------------------------- */
  59. /* Find pair by name */
  60. lub_pair_t *lub_ini_find_pair(const lub_ini_t *this, const char *name)
  61. {
  62. lub_list_node_t *iter;
  63. lub_pair_t *pair;
  64. if (!this || !name)
  65. return NULL;
  66. /* Iterate elements */
  67. for(iter = lub_list__get_head(this->list);
  68. iter; iter = lub_list_node__get_next(iter)) {
  69. int res;
  70. pair = (lub_pair_t *)lub_list_node__get_data(iter);
  71. res = strcmp(lub_pair__get_name(pair), name);
  72. if (!res)
  73. return pair;
  74. if (res > 0) /* No chance to find name */
  75. break;
  76. }
  77. return NULL;
  78. }
  79. /*--------------------------------------------------------- */
  80. /* Find pair by name */
  81. const char *lub_ini_find(const lub_ini_t *this, const char *name)
  82. {
  83. lub_pair_t *pair = lub_ini_find_pair(this, name);
  84. if (!pair)
  85. return NULL;
  86. return lub_pair__get_value(pair);
  87. }
  88. /*--------------------------------------------------------- */
  89. int lub_ini_parse_str(lub_ini_t *this, const char *ini)
  90. {
  91. char *buffer = NULL;
  92. char *saveptr = NULL;
  93. char *line = NULL;
  94. buffer = lub_string_dup(ini);
  95. /* Now loop though each line */
  96. for (line = strtok_r(buffer, "\n", &saveptr);
  97. line; line = strtok_r(NULL, "\n", &saveptr)) {
  98. char *str = NULL;
  99. char *name = NULL;
  100. char *value = NULL;
  101. char *savestr = NULL;
  102. char *ns = line;
  103. const char *begin = NULL;
  104. size_t len = 0;
  105. char *rname = NULL;
  106. char *rvalue = NULL;
  107. lub_pair_t *pair = NULL;
  108. if (!*ns) /* Empty */
  109. continue;
  110. while (*ns && isspace(*ns))
  111. ns++;
  112. if ('#' == *ns) /* Comment */
  113. continue;
  114. if ('=' == *ns) /* Broken string */
  115. continue;
  116. str = lub_string_dup(ns);
  117. name = strtok_r(str, "=", &savestr);
  118. if (!name) {
  119. lub_string_free(str);
  120. continue;
  121. }
  122. value = strtok_r(NULL, "=", &savestr);
  123. begin = lub_string_nextword(name, &len, NULL, NULL, NULL, NULL);
  124. rname = lub_string_dupn(begin, len);
  125. if (!value) /* Empty value */
  126. rvalue = NULL;
  127. else {
  128. begin = lub_string_nextword(value, &len, NULL, NULL,
  129. NULL, NULL);
  130. rvalue = lub_string_dupn(begin, len);
  131. }
  132. pair = lub_pair_new(rname, rvalue);
  133. lub_ini_add(this, pair);
  134. lub_string_free(rname);
  135. lub_string_free(rvalue);
  136. lub_string_free(str);
  137. }
  138. lub_string_free(buffer);
  139. return 0;
  140. }
  141. /*--------------------------------------------------------- */
  142. int lub_ini_parse_file(lub_ini_t *this, const char *fn)
  143. {
  144. int ret = -1;
  145. FILE *f;
  146. char *buf;
  147. unsigned int p = 0;
  148. const int chunk_size = 128;
  149. int size = chunk_size;
  150. if (!fn || !*fn)
  151. return -1;
  152. f = fopen(fn, "r");
  153. if (!f)
  154. return -1;
  155. buf = malloc(size);
  156. while (fgets(buf + p, size - p, f)) {
  157. char *tmp;
  158. if (feof(f) || strchr(buf + p, '\n') || strchr(buf + p, '\r')) {
  159. lub_ini_parse_str(this, buf);
  160. p = 0;
  161. continue;
  162. }
  163. p = size - 1;
  164. size += chunk_size;
  165. tmp = realloc(buf, size);
  166. if (!tmp)
  167. goto error;
  168. buf = tmp;
  169. }
  170. ret = 0;
  171. error:
  172. free(buf);
  173. fclose(f);
  174. return ret;
  175. }
  176. /*--------------------------------------------------------- */
  177. lub_ini_node_t *lub_ini__get_head(lub_ini_t *this)
  178. {
  179. return lub_list__get_head(this->list);
  180. }
  181. /*--------------------------------------------------------- */
  182. lub_ini_node_t *lub_ini__get_tail(lub_ini_t *this)
  183. {
  184. return lub_list__get_tail(this->list);
  185. }
  186. /*--------------------------------------------------------- */
  187. lub_ini_node_t *lub_ini__get_next(lub_ini_node_t *node)
  188. {
  189. return lub_list_node__get_next(node);
  190. }
  191. /*--------------------------------------------------------- */
  192. lub_ini_node_t *lub_ini__get_prev(lub_ini_node_t *node)
  193. {
  194. return lub_list_node__get_next(node);
  195. }
  196. /*--------------------------------------------------------- */
  197. lub_pair_t *lub_ini__iter_data(lub_ini_node_t *node)
  198. {
  199. return (lub_pair_t *)lub_list_node__get_data(node);
  200. }
  201. /*--------------------------------------------------------- */