/* * File: json_parser.c * Author: Arthur Brandao * * Created on 28 octobre 2018 */ #include #include #include "json.h" /* --- Fonctions privées --- */ /** * Passe un objet json dans une chaine json * @param char* La chaine json * @return int Le nombre de caractères à passer */ int skip_object(char* json) { int compteur = 1; json++; //On compte le nombre caractere à sauter while (*json && *json != '}') { //Si on trouve un autre objet dans l'objet if (*json == '{') { skip_object(json); } compteur++; json++; } return compteur; } /** * Passe un tableau json dans une chaine json * @param char* La chaine json * @return int Le nombre de caractères à passer */ int skip_array(char* json) { int compteur = 1; json++; //On compte le nombre caractere à sauter while (*json && *json != ']') { json++; compteur++; } return compteur; } /** * Compte le nombre de clef d'une chaine json * @param char* La chaine json * @return int Le nombre de clef */ int key_counter(char* json){ //Declaration variable int compteur = 0; boolean key = true; //On parcours la chaine une 1er fois pour compter le nombre de clef while (*json && *json != '}') { //Si on trouve le debut d'une clef if (*json == '"' && key) { compteur++; key = false; } //Si on tombe sur un autre objet json else if (*json == '{' && !key) { json += skip_object(json); } //Si on tombe sur un tableau else if (*json == '[' && !key) { json += skip_array(json); } //Si on trouve un separateur de valeur else if (*json == ',' && !key) { //Le prochain element est une clefS key = true; } json++; } //Retour return compteur; } /** * Extraction d'une clef * @param JsonParser* La structure pour sauvegarder l'extraction * @param int La position dans la structure * @param char* La chaine json * @return int JSON_ERROR ou le nombre de caractère de la clef */ int parse_key(JsonParser* this, int index, char* json) { //Declaration variable int compteur = 0; //On parcours jusqu'a la fin de la clef json++; while (*json && *json != '"') { json++; compteur++; } //Si json mal formé if (!*json) { return JSON_ERROR; } //Setup les infos this->key[index] = json - compteur; this->key_length[index] = compteur; //Sinon retourne ok return ++compteur; } /** * Extraction d'une valeur * @param JsonParser* La structure pour sauvegarder l'extraction * @param int La position dans la structure * @param char* La chaine json * @return int JSON_ERROR ou le nombre de caractère de la valeur */ int parse_val(JsonParser* this, int index, char* json){ //Declaration variable int compteur = 0; //Regarde le type de valeur switch(*json){ //String case '"': //Cherche le guillement de fin json++; while (*json && *json != '"') { json++; compteur++; } //Si json mal formé if (!*json) { return JSON_ERROR; } //Setup les infos this->val[index] = json - compteur; this->val_length[index] = compteur; this->type[index] = JSON_STRING; break; //Boolean case 't': compteur = 4; this->val[index] = json; this->val_length[index] = compteur; this->type[index] = JSON_BOOLEAN; break; case 'f': compteur = 5; this->val[index] = json; this->val_length[index] = compteur; this->type[index] = JSON_BOOLEAN; break; //Nombre case '-': case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': //Cherche espace de fin ou fin json ou suite json while (*json && *json != ' ' && *json != '}' && *json != ',') { json++; compteur++; } //Si json mal formé if (!*json) { return JSON_ERROR; } //Setup les infos this->val[index] = json - compteur; this->val_length[index] = compteur; this->type[index] = JSON_NUMBER; break; //Tableau case '[': compteur = skip_array(json) + 1; this->val[index] = json; this->val_length[index] = compteur; this->type[index] = JSON_ARRAY; break; //Objet case '{': compteur = skip_object(json) + 1; this->val[index] = json; this->val_length[index] = compteur; this->type[index] = JSON_OBJECT; break; //Autre default: return JSON_ERROR; } //Retour return ++compteur; } /** * Erreur lors du la procedure de parse * Supprime la structure et retourne un code d'erreur * @param JsonParser* structure traitée pendant l'erreur * @return int JSON_ERROR */ int parse_error(JsonParser* this){ clean_json_parser(this); return JSON_ERROR; } /** * Cherche l'index d'une clef * @param JsonParser* La structure initialisé par json_parse * @param char* La clef à rechercher * @return int La position */ int search_index(JsonParser* this, char* key){ int length = strlen(key); //Cherche la clef for(int i = 0; i < this->elt; i++){ if(strncmp(this->key[i], key, length) == 0){ return i; } } //Si rien trouver return JSON_ERROR; } /* --- Fonctions publiques --- */ int json_parse(JsonParser* this, char* json) { //Declaration variable char* tmp; int temp, compteur; boolean key = true; //Compte le nombre de clef compteur = key_counter(json); //Allocation de la taille des tableaux this->str = malloc(strlen(json) * sizeof (char)); strcpy(this->str, json); this->elt = compteur; this->key = malloc(compteur * sizeof (char*)); this->key_length = malloc(compteur * sizeof (int)); this->val = malloc(compteur * sizeof (char*)); this->val_length = malloc(compteur * sizeof (int)); this->type = malloc(compteur * sizeof (int)); //On reparcours le tableau pour parser tmp = this->str; compteur = 0; while (*tmp && *tmp != '}') { //Si on trouve une clef if (*tmp == '"') { //Lecture clef de la clef if((temp = parse_key(this, compteur, tmp)) == JSON_ERROR){ return parse_error(this); } tmp += temp; key = false; } //Si on trouve une valeur else if(*tmp == ':'){ //Si pas de claf avant if(key){ return parse_error(this); } //Saute les espaces tmp++; while(*tmp == ' ') { tmp++; } //Lecture valeur if((temp = parse_val(this, compteur, tmp)) == JSON_ERROR){ return parse_error(this); } tmp += temp; key = true; compteur++; } tmp++; } //Si on s'arrete sur une clef if(!key){ return parse_error(this); } //Sinon ok return JSON_OK; } char* key_index(JsonParser* this, int index){ //Index incorrect if(index < 0 || index >= this->elt){ return NULL; } //Creation string d'accueil char* val; val = malloc((this->key_length[index] + 1) * sizeof(char)); //+1 pour \0 memset(val, 0, this->key_length[index] + 1); //Copie valeur strncpy(val, this->key[index], this->key_length[index]); //Retour return val; } char* get_index(JsonParser* this, int index){ //Index incorrect if(index < 0 || index >= this->elt){ return NULL; } //Creation string d'accueil char* val; val = malloc((this->val_length[index] +1) * sizeof(char)); //+1 pour \0 memset(val, 0, this->val_length[index] + 1); //Copie valeur strncpy(val, this->val[index], this->val_length[index]); //Retour return val; } int get_pos(JsonParser* this, char* key){ //Recup index int index; if((index = search_index(this, key)) == JSON_ERROR){ return JSON_ERROR; } return index; } int get_type(JsonParser* this, char* key){ //Recup index int index; if((index = search_index(this, key)) == JSON_ERROR){ return JSON_ERROR; } return this->type[index]; } char* get_value(JsonParser* this, char* key){ //Recup index int index; if((index = search_index(this, key)) == JSON_ERROR){ return NULL; } return get_index(this, index); } double get_number(JsonParser* this, char* key){ //Recup index int index; if((index = search_index(this, key)) == JSON_ERROR){ return JSON_ERROR; } //Verif type if(this->type[index] != JSON_NUMBER){ return JSON_ERROR; } //Recup valeur char* val; val = get_index(this, index); //Cast et retoure double res; res = atof(val); free(val); return res; } int get_integer(JsonParser* this, char* key){ //Recup index int index; if((index = search_index(this, key)) == JSON_ERROR){ return JSON_ERROR; } //Verif type if(this->type[index] != JSON_NUMBER){ return JSON_ERROR; } //Recup valeur char* val; val = get_index(this, index); //Cast et retoure int res; res = atoi(val); free(val); return res; } boolean get_boolean(JsonParser* this, char* key){ //Recup index int index; if((index = search_index(this, key)) == JSON_ERROR){ return false; } //Verif type if(this->type[index] != JSON_BOOLEAN){ return false; } //Recup valeur char* val; val = get_index(this, index); //Cast et retoure if(val[0] == 't'){ return true; } return false; } char* get_array(JsonParser* this, char* key){ //Recup index int index; if((index = search_index(this, key)) == JSON_ERROR){ return NULL; } //Verif type if(this->type[index] != JSON_ARRAY){ return NULL; } //Retour pas de gestion de tableau actuellement return get_index(this, index); } JsonParser* get_object(JsonParser* this, char* key){ //Recup index int index; if((index = search_index(this, key)) == JSON_ERROR){ return NULL; } //Verif type if(this->type[index] != JSON_OBJECT){ return NULL; } //Recup valeur char* val; val = get_index(this, index); //Parse JsonParser* json; json = malloc(sizeof(JsonParser)); if(json_parse(json, val) == JSON_ERROR){ return NULL; } //Retour JSON utilisable free(val); return json; } void clean_json_parser(JsonParser* this) { free(this->key); free(this->key_length); free(this->val); free(this->val_length); free(this->type); free(this->str); }