Cod sursa(job #1358805)

Utilizator MrWhiteDELETEME MrWhite Data 24 februarie 2015 20:03:34
Problema Convertor Scor 100
Compilator c Status done
Runda rosedu_cdl_2015 Marime 4.76 kb
#include <stdio.h>
#include <string.h>
#include <stdlib.h>

#define MAX_KEY_LEN               1024
#define MAX_VALUE_LEN             1024

/**
 * 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 = strdup(key);
    var->value = strdup(value);
    return var;
}

/**
 * Deletes the variable by freeing 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 by freeing 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 *= 2;
        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 parse(FILE *in, FILE *out)
{
    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) {
                dictionary_dump(out, dict);
            }
        } else if (ch == '{') {
            dictionary_delete(dict);
            dict = dictionary_new(512);
        } else if (ch == '}') {
            dictionary_dump(out, dict);
        } else if (ch == ']') {
            break;
        }
    }
}

int main()
{
    FILE *fin = fopen("convertor.in", "r");
    //assert(fin != NULL);
    FILE *fout = fopen("convertor.out", "w");
    //assert(fout != NULL);
    parse(fin, fout);
    return 0;
}