Pagini recente » Cod sursa (job #1132947) | Cod sursa (job #1482185) | Cod sursa (job #930395) | Cod sursa (job #100414) | Cod sursa (job #1359228)
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
/**
* Duplicates a string (in memory).
*
* @param str
* @return
*/
char *str_dup(char *str)
{
char *ret = malloc((strlen(str) + 1) * sizeof(char));
//assert(ret != NULL);
strcpy(ret, str);
return ret;
}
/**
* Stores a JSON variable.
* A JSON variable consists of a key and a value (both strings).
*/
typedef struct {
char *key, *value;
} json_var_t;
/**
* Stores a JSON dictionary.
* A JSON dictionary consists of multiple JSON variables.
*/
typedef struct {
int len, cap;
json_var_t **data;
} json_dictionary_t;
/**
* Creates a new variable and returns it.
*
* @param key
* @param value
* @return
*/
json_var_t* var_new(char *key, char *value)
{
json_var_t *var = malloc(sizeof(json_var_t));
var->key = str_dup(key);
var->value = str_dup(value);
return var;
}
/**
* Deletes the variable (frees all of its memory).
*
* @param var
*/
void var_delete(json_var_t *var)
{
if (!var) {
return;
}
free(var->key);
free(var->value);
free(var);
}
/**
* Initializes a new dictionary and returns it.
*
* @param cap Initial capacity.
* @return
*/
json_dictionary_t* dictionary_new(int cap)
{
json_dictionary_t *dict = malloc(sizeof(json_dictionary_t));
dict->len = 0;
dict->cap = cap;
dict->data = malloc(dict->cap * sizeof(json_var_t*));
//assert(dict->data != NULL);
return dict;
}
/**
* Deletes a dictionary (frees all of its memory).
*
* @param dict
*/
void dictionary_delete(json_dictionary_t *dict)
{
if (!dict) {
return;
}
for (int i = 0; i < dict->len; ++i) {
var_delete(dict->data[i]);
}
free(dict);
}
/**
* Adds a new value in a dictionary.
*
* @param dict
* @param value
*/
void dictionary_add(json_dictionary_t *dict, json_var_t *value)
{
if (dict->len == dict->cap) {
dict->cap <<= 1;
dict->data = realloc(dict->data, dict->cap * sizeof(json_var_t*));
//assert(dict->data != NULL);
}
dict->data[dict->len++] = value;
}
/**
* Dumps the dictionary.
*
* @param dict
*/
void dictionary_dump(FILE *out, json_dictionary_t *dict)
{
static int isFirst = 1; // TODO
if (isFirst) {
for (int i = 0; i < dict->len; ++i) {
fprintf(out, "%s,", dict->data[i]->key);
}
fprintf(out, "\n");
isFirst = 0;
}
for (int i = 0; i < dict->len; ++i) {
fprintf(out, "%s,", dict->data[i]->value);
}
fprintf(out, "\n");
}
/**
* Checks if a character is a digit.
*
* @param ch
* @return
*/
int is_digit(char ch)
{
return ((ch >= '0') && (ch <= '9'));
}
/**
* Parses the JSON file from `in` and outputs CSV to `out`.
*
* @param in
* @param out
*/
void json_to_csv(FILE *in, FILE *out)
{
// Imi pare rau pentru codul urat de mai jos, dar testul 8 si limita de
// timp / memorie, omoara orice speranta la ceva mai frumos. :(
int key_pos, value_pos;
char key[1024], value[1024];
json_dictionary_t *dict = NULL;
while (1) {
char ch = fgetc(in);
if (ch == '"') {
// Reading key.
key[0] = fgetc(in);
for (key_pos = 1; key[key_pos - 1] != '"'; ++key_pos) {
key[key_pos] = fgetc(in);
}
// Looking for key-value delimiter (':').
while (fgetc(in) != ':');
int is_str = 0;
// Determining value type.
while ((ch = fgetc(in))) {
if (ch == '"') {
is_str = 1;
break;
} else if (is_digit(ch)) {
break;
}
}
// Reading value.
if (is_str) {
value[0] = fgetc(in);
for (value_pos = 1; value[value_pos - 1] != '"'; ++value_pos) {
value[value_pos] = fgetc(in);
}
} else {
value[0] = ch;
for (value_pos = 1; is_digit(value[value_pos - 1]); ++value_pos) {
value[value_pos] = fgetc(in);
}
}
// Wrapping the strings (and sometimes the dictionary too).
int dictionary_finished = value[value_pos - 1] == '}';
key[key_pos - 1] = value[value_pos - 1] = 0;
dictionary_add(dict, var_new(key, value));
if (dictionary_finished) {
// When reading integer values, the '}' that finishes current
// dictionary is read too.
dictionary_dump(out, dict);
}
} else if (ch == '{') {
// New dictionary started.
dictionary_delete(dict);
dict = dictionary_new(512);
} else if (ch == '}') {
// Dictionary ended.
dictionary_dump(out, dict);
} else if (ch == ']') {
// Array ended.
break;
}
}
}
int main()
{
FILE *fin = fopen("convertor.in", "r");
//assert(fin != NULL);
FILE *fout = fopen("convertor.out", "w");
//assert(fout != NULL);
json_to_csv(fin, fout);
return 0;
}