Browse Source

Refactoring

master
Kirill Nikolaev 1 month ago
parent
commit
a2d9ac2ab5
Signed by: sokket <sokket@oceancraft.ru> GPG Key ID: 082FDA12D688C5C1
1 changed files with 139 additions and 102 deletions
  1. +139
    -102
      main.c

+ 139
- 102
main.c View File

@@ -3,6 +3,11 @@
#include <ctype.h>
#include <malloc.h>

// Configuration
#define XML_PARSE_ARRAY_SIZE 10
#define READ_BUFFER_SIZE 128
#define WHITE_SPACE "\t"

char *trim(char *s) {
while (isspace((unsigned char) *s)) s++;
if (*s) {
@@ -34,10 +39,24 @@ int count(char *str, char count) {
return c;
}

const int UNKNOWN = 1;
const int OPEN = 2;
const int CLOSE = 3;
const int VALUE = 4;
char *append(char *str, char c) {
if (!str) {
str = malloc(sizeof(char) * 2);
str[0] = c;
str[1] = '\0';
} else {
size_t len = strlen(str);
str = realloc(str, len + 2 * sizeof(char));
str[len] = c;
str[len + 1] = '\0';
}
return str;
}

#define UNKNOWN 1
#define OPEN 2
#define CLOSE 3
#define VALUE 4

typedef struct obj {
int depth;
@@ -46,80 +65,80 @@ typedef struct obj {
char *value;
} Obj;

void printWhiteSpace(int depth) {
void print_white_space(int depth) {
for (int i = 0; i < depth; i++)
printf(" ");
printf(WHITE_SPACE);
}

void printTag(Obj tag, int nextObjIsValue, int prevObjIsValue, int comma) {
if (tag.type == OPEN) {
printWhiteSpace(tag.depth);
printf("\"%s\": %s", tag.key, nextObjIsValue ? "" : "{\n");
} else if (tag.type == CLOSE && !prevObjIsValue) {
printWhiteSpace(tag.depth);
printf("%s\n", comma ? "}," : "}");
} else if (tag.type == VALUE && tag.value) {
if (count(tag.value, '\n') > 1) {
printf("\n");
int printStart = 0;
for (char *p = strtok(tag.value, "\n"); p;) {
printWhiteSpace(tag.depth);
if (!printStart) {
printf("\"");
printStart = 1;
void print_obj(Obj tag, int next_obj_is_val, int prev_obj_is_val, int comma) {
switch (tag.type) {
case OPEN:
print_white_space(tag.depth);
printf("\"%s\": %s", tag.key, next_obj_is_val ? "" : "{\n");
break;
case CLOSE:
if (!prev_obj_is_val) {
print_white_space(tag.depth);
printf("%s\n", comma ? "}," : "}");
}
break;
case VALUE:
if (tag.value) {
if (count(tag.value, '\n') > 1) {
printf("\n");
int printStart = 0;
for (char *p = strtok(tag.value, "\n"); p;) {
print_white_space(tag.depth);
if (!printStart) {
printf("\"");
printStart = 1;
}
printf("%s", trim(p));
p = strtok(0, "\n");
printf("%s\n", p ? "" : "\"");
}
} else {
char *text = trim(tag.value);
if (is_number(text) || !strcmp(text, "true") || !strcmp(text, "false"))
printf("%s%s\n", text, comma ? "," : "");
else
printf("\"%s\"%s\n", text, comma ? "," : "");
}
printf("%s", trim(p));
p = strtok(0, "\n");
printf("%s\n", p ? "" : "\"");
}
} else {
char *text = trim(tag.value);
if (is_number(text) || !strcmp(text, "true") || !strcmp(text, "false"))
printf("%s%s\n", text, comma ? "," : "");
else
printf("\"%s\"%s\n", text, comma ? "," : "");
}
}
}

int prevIsValue = 0;
int prev_is_val = 0;

void printObjBuffer(Obj *obj, int count) {
void print_obj_array(Obj *obj, int count) {
for (int i = 0; i < count; ++i) {
printTag(
print_obj(
obj[i],
i + 1 < count && obj[i + 1].type == VALUE,
prevIsValue,
prev_is_val,
obj[i].type == VALUE
? (i + 3 < count && obj[i + 3].depth == obj[i].depth)
: (i + 1 < count && obj[i + 1].depth == obj[i].depth)
);
prevIsValue = obj[i].type == VALUE;
}
}

char *append(char *str, char c) {
if (!str) {
str = malloc(sizeof(char) * 2);
str[0] = c;
str[1] = '\0';
} else {
size_t len = strlen(str);
str = realloc(str, len + 2 * sizeof(char));
str[len] = c;
str[len + 1] = '\0';
prev_is_val = obj[i].type == VALUE;
}
return str;
}

void initObj(Obj *obj) {
void init_obj(Obj *obj) {
obj->key = 0;
obj->value = 0;
obj->type = VALUE;
obj->depth = 0;
}

void cleanUpObj(Obj *obj) {
Obj *create_obj_array(int size) {
Obj *array = malloc(size * sizeof(Obj));
for (int i = 0; i < size; i++)
init_obj(&array[i]);
return array;
}

void free_obj(Obj *obj) {
if (obj->key) {
free(obj->key);
obj->key = 0;
@@ -132,76 +151,94 @@ void cleanUpObj(Obj *obj) {
obj->depth = 0;
}

Obj * reallocate_buffer(int *tag_buffer_pos, int *buffer_size, Obj **tag_buffer, int init_buffer_size) {
if (++(*tag_buffer_pos) == *buffer_size) {
if ((*tag_buffer)[*buffer_size - 1].type != VALUE
&& (*tag_buffer)[*buffer_size - 2].type != VALUE
&& (*tag_buffer)[*buffer_size - 3].type != VALUE
void free_obj_array(Obj *obj, int size) {
for (int i = 0; i < size; ++i)
free_obj(&obj[i]);
free(obj);
}

Obj *reallocate_obj_array(int *array_current_index, int *array_size, Obj **array, int init_array_size) {
if (++(*array_current_index) == *array_size) {
if ((*array)[*array_size - 1].type != VALUE
&& (*array)[*array_size - 2].type != VALUE
&& (*array)[*array_size - 3].type != VALUE
) {
printObjBuffer((*tag_buffer), *buffer_size);
for (int j = init_buffer_size; j < *buffer_size; ++j)
cleanUpObj(&(*tag_buffer)[j]);
*buffer_size = init_buffer_size;
*tag_buffer = realloc(*tag_buffer, *buffer_size * sizeof(Obj));
*tag_buffer_pos = 0;
print_obj_array((*array), *array_size);
for (int j = init_array_size; j < *array_size; ++j)
free_obj(&(*array)[j]);
*array_size = init_array_size;
*array = realloc(*array, *array_size * sizeof(Obj));
*array_current_index = 0;
} else {
*buffer_size += 3;
*tag_buffer = realloc(*tag_buffer, *buffer_size * sizeof(Obj));
for (int ib = *tag_buffer_pos; ib < *buffer_size; ib++)
initObj(&(*tag_buffer)[ib]);
*array_size += 3;
*array = realloc(*array, *array_size * sizeof(Obj));
for (int ib = *array_current_index; ib < *array_size; ib++)
init_obj(&(*array)[ib]);
}
}
Obj* tag = &(*tag_buffer)[*tag_buffer_pos];
cleanUpObj(tag);
Obj *tag = &(*array)[*array_current_index];
free_obj(tag);
return tag;
}

int main() {
FILE *file = fopen("/home/dragon/CLionProjects/untitled17/example.xml", "r");
if (file) {
char buffer[128];
int ignore_tag_options = 0;
int tag_buffer_pos = 0;
int depth = -1;
int init_buffer_size = 4;
int buffer_size = init_buffer_size;
Obj *tag_buffer = malloc(buffer_size * sizeof(Obj));
for (int i = 0; i < buffer_size; i++)
initObj(&tag_buffer[i]);
while (fgets(buffer, 128, file)) {
Obj *tag = &tag_buffer[tag_buffer_pos];
size_t len = strlen(buffer);
for (int i = 0; i < len; i++) {
if (buffer[i] == '<') {
void print_json(FILE *file) {
int ignore_tag_options = 0;
int depth = -1;

int init_array_size = XML_PARSE_ARRAY_SIZE;
int array_size = init_array_size;
int array_pos = 0;
Obj *array = create_obj_array(array_size);

char buffer[READ_BUFFER_SIZE];
while (fgets(buffer, READ_BUFFER_SIZE, file)) {
Obj *tag = &array[array_pos];
size_t len = strlen(buffer);
for (int i = 0; i < len; i++)
switch (buffer[i]) {
case '<':
if (tag->value && strlen(trim(tag->value)) != 0) {
tag->depth = depth + 1;
tag = reallocate_buffer(&tag_buffer_pos, &buffer_size, &tag_buffer, init_buffer_size);
tag = reallocate_obj_array(&array_pos, &array_size, &array, init_array_size);
}
tag->type = UNKNOWN;
ignore_tag_options = 0;
} else if (buffer[i] == '/') {
break;
case '/':
if (tag->type == UNKNOWN)
tag->type = CLOSE;
} else if (buffer[i] == '>') {
break;
case '>':
if (tag->type == UNKNOWN)
tag->type = OPEN;
if (tag->type == CLOSE)
tag->depth = depth--;
if (tag->type == OPEN)
tag->depth = ++depth;
tag = reallocate_buffer(&tag_buffer_pos, &buffer_size, &tag_buffer, init_buffer_size);
} else if (tag->type == UNKNOWN && buffer[i] == ' ')
ignore_tag_options = 1;
else if (tag->type == UNKNOWN && !ignore_tag_options)
tag->key = append(tag->key, buffer[i]);
else if (tag->type == VALUE)
tag->value = append(tag->value, buffer[i]);
tag = reallocate_obj_array(&array_pos, &array_size, &array, init_array_size);
break;
default:
if (tag->type == UNKNOWN && buffer[i] == ' ')
ignore_tag_options = 1;
else if (tag->type == UNKNOWN && !ignore_tag_options)
tag->key = append(tag->key, buffer[i]);
else if (tag->type == VALUE)
tag->value = append(tag->value, buffer[i]);
}
}
printObjBuffer(tag_buffer, tag_buffer_pos);
for (int i = 0; i < buffer_size; ++i)
cleanUpObj(&tag_buffer[i]);
free(tag_buffer);
}
print_obj_array(array, array_pos);
free_obj_array(array, array_size);
}

int main(int argc, char *args[]) {
if (argc < 2) {
printf("Usage:\n./xml2json <xml_file>\n");
} else {
FILE *file = fopen(args[1], "r");
if (file)
print_json(file);
else
printf("Can't open this file\n");
}
return 0;
}

Loading…
Cancel
Save