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.

219 lines
6.3 KiB

  1. #include <stdio.h>
  2. #include <string.h>
  3. #include <ctype.h>
  4. #include <malloc.h>
  5. char *trim(char *s) {
  6. while (isspace((unsigned char) *s)) s++;
  7. if (*s) {
  8. char *p = s;
  9. while (*p) p++;
  10. while (isspace((unsigned char) *(--p)));
  11. p[1] = '\0';
  12. }
  13. return s;
  14. }
  15. int str_contains(char *token, char s) {
  16. if (!token || s == '\0')
  17. return 0;
  18. for (; *token; token++)
  19. if (*token == s)
  20. return 1;
  21. return 0;
  22. }
  23. int is_number(char *s) {
  24. while (*s) {
  25. if (!isdigit(*s) && *s != '.')
  26. return 0;
  27. s++;
  28. }
  29. return 1;
  30. }
  31. int count(char *str, char count) {
  32. char *src = str;
  33. int c = 0;
  34. while (*src) {
  35. if (*src == count)
  36. c++;
  37. src++;
  38. }
  39. return c;
  40. }
  41. const int UNKNOWN = 1;
  42. const int OPEN = 2;
  43. const int CLOSE = 3;
  44. const int VALUE = 4;
  45. typedef struct obj {
  46. int depth;
  47. int type;
  48. char *key;
  49. char *value;
  50. } Obj;
  51. void printWhiteSpace(int depth) {
  52. for (int i = 0; i < depth; i++)
  53. printf(" ");
  54. }
  55. void printTag(Obj tag, int nextObjIsValue, int prevObjIsValue, int comma) {
  56. if (tag.type == OPEN) {
  57. printWhiteSpace(tag.depth);
  58. printf("\"%s\": %s", tag.key, nextObjIsValue ? "" : "{\n");
  59. } else if (tag.type == CLOSE && !prevObjIsValue) {
  60. printWhiteSpace(tag.depth);
  61. printf("%s\n", comma ? "}," : "}");
  62. } else if (tag.type == VALUE && tag.value) {
  63. if (count(tag.value, '\n') > 1) {
  64. printf("\n");
  65. int printStart = 0;
  66. for (char *p = strtok(tag.value, "\n"); p;) {
  67. printWhiteSpace(tag.depth);
  68. if (!printStart) {
  69. printf("\"");
  70. printStart = 1;
  71. }
  72. printf("%s", trim(p));
  73. p = strtok(0, "\n");
  74. printf("%s\n", p ? "" : "\"");
  75. }
  76. } else {
  77. char *text = trim(tag.value);
  78. if (is_number(text) || !strcmp(text, "true") || !strcmp(text, "false"))
  79. printf("%s%s\n", text, comma ? "," : "");
  80. else
  81. printf("\"%s\"%s\n", text, comma ? "," : "");
  82. }
  83. }
  84. }
  85. int prevIsValue = 0;
  86. void printObjBuffer(Obj *obj, int count) {
  87. for (int i = 0; i < count; ++i) {
  88. printTag(
  89. obj[i],
  90. i + 1 < count && obj[i + 1].type == VALUE,
  91. prevIsValue,
  92. obj[i].type == VALUE
  93. ? (i + 3 < count && obj[i + 3].depth == obj[i].depth)
  94. : (i + 1 < count && obj[i + 1].depth == obj[i].depth)
  95. );
  96. prevIsValue = obj[i].type == VALUE;
  97. }
  98. }
  99. char *append(char *str, char c) {
  100. if (!str) {
  101. str = malloc(sizeof(char) * 2);
  102. str[0] = c;
  103. str[1] = '\0';
  104. } else {
  105. size_t len = strlen(str);
  106. str = realloc(str, len + 2 * sizeof(char));
  107. str[len] = c;
  108. str[len + 1] = '\0';
  109. }
  110. return str;
  111. }
  112. void initObj(Obj *obj) {
  113. obj->key = 0;
  114. obj->value = 0;
  115. obj->type = VALUE;
  116. obj->depth = 0;
  117. }
  118. void cleanUpObj(Obj *obj) {
  119. if (obj->key) {
  120. free(obj->key);
  121. obj->key = 0;
  122. }
  123. if (obj->value) {
  124. free(obj->value);
  125. obj->value = 0;
  126. }
  127. obj->type = VALUE;
  128. obj->depth = 0;
  129. }
  130. Obj * reallocate_buffer(int *tag_buffer_pos, int *buffer_size, Obj **tag_buffer, int init_buffer_size) {
  131. if (++(*tag_buffer_pos) == *buffer_size) {
  132. if ((*tag_buffer)[*buffer_size - 1].type != VALUE
  133. && (*tag_buffer)[*buffer_size - 2].type != VALUE
  134. && (*tag_buffer)[*buffer_size - 3].type != VALUE
  135. ) {
  136. printObjBuffer((*tag_buffer), *buffer_size);
  137. for (int j = init_buffer_size; j < *buffer_size; ++j)
  138. cleanUpObj(&(*tag_buffer)[j]);
  139. *buffer_size = init_buffer_size;
  140. *tag_buffer = realloc(*tag_buffer, *buffer_size * sizeof(Obj));
  141. *tag_buffer_pos = 0;
  142. } else {
  143. *buffer_size += 3;
  144. *tag_buffer = realloc(*tag_buffer, *buffer_size * sizeof(Obj));
  145. for (int ib = *tag_buffer_pos; ib < *buffer_size; ib++)
  146. initObj(&(*tag_buffer)[ib]);
  147. }
  148. }
  149. Obj* tag = &(*tag_buffer)[*tag_buffer_pos];
  150. cleanUpObj(tag);
  151. return tag;
  152. }
  153. int main() {
  154. FILE *file = fopen("/home/dragon/CLionProjects/untitled17/example.xml", "r");
  155. if (file) {
  156. char buffer[128];
  157. int ignore_tag_options = 0;
  158. int tag_buffer_pos = 0;
  159. int depth = -1;
  160. int init_buffer_size = 4;
  161. int buffer_size = init_buffer_size;
  162. Obj *tag_buffer = malloc(buffer_size * sizeof(Obj));
  163. for (int i = 0; i < buffer_size; i++)
  164. initObj(&tag_buffer[i]);
  165. while (fgets(buffer, 128, file)) {
  166. Obj *tag = &tag_buffer[tag_buffer_pos];
  167. size_t len = strlen(buffer);
  168. for (int i = 0; i < len; i++) {
  169. if (buffer[i] == '<') {
  170. if (tag->value && strlen(trim(tag->value)) != 0) {
  171. tag->depth = depth + 1;
  172. tag = reallocate_buffer(&tag_buffer_pos, &buffer_size, &tag_buffer, init_buffer_size);
  173. }
  174. tag->type = UNKNOWN;
  175. ignore_tag_options = 0;
  176. } else if (buffer[i] == '/') {
  177. if (tag->type == UNKNOWN)
  178. tag->type = CLOSE;
  179. } else if (buffer[i] == '>') {
  180. if (tag->type == UNKNOWN)
  181. tag->type = OPEN;
  182. if (tag->type == CLOSE)
  183. tag->depth = depth--;
  184. if (tag->type == OPEN)
  185. tag->depth = ++depth;
  186. tag = reallocate_buffer(&tag_buffer_pos, &buffer_size, &tag_buffer, init_buffer_size);
  187. } else if (tag->type == UNKNOWN && buffer[i] == ' ')
  188. ignore_tag_options = 1;
  189. else if (tag->type == UNKNOWN && !ignore_tag_options)
  190. tag->key = append(tag->key, buffer[i]);
  191. else if (tag->type == VALUE)
  192. tag->value = append(tag->value, buffer[i]);
  193. }
  194. }
  195. printObjBuffer(tag_buffer, tag_buffer_pos);
  196. for (int i = 0; i < buffer_size; ++i)
  197. cleanUpObj(&tag_buffer[i]);
  198. free(tag_buffer);
  199. }
  200. return 0;
  201. }