/* * File: json_array.c * Author: Arthur Brandao * * Created on 24 novembre 2018 */ #include #include #include #include "json.h" /* --- Fonctions privées parser --- */ int val_counter(char* json) { char* tmp = json + 1; int nbElt = 0; boolean empty = true; //Parours la chaine while (*tmp != ']' && *tmp) { //printf("%c\n", *tmp); fflush(stdout); //Si on croise autre chose que du vide if (empty && *tmp != ' ' && *tmp != ']') { empty = false; } //Si on croise un tableau ou un objet else if (*tmp == '[' || *tmp == '{') { //Saute int jump; if (*tmp == '{') { jump = skip_object(tmp); } else { jump = skip_array(tmp); } tmp += jump; //Si se termine mal if (!*tmp) { return JSON_ERROR; } } //On compte les ',' separatrice else if (*tmp == ',') { nbElt++; } tmp++; } //Si non vide if (!empty) { nbElt++; } //Retourne le nombre d'element trouvé return nbElt; } /** * 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_array_val(JsonArray* 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->parser->val[index] = json - compteur; this->parser->val_length[index] = compteur; this->parser->type[index] = JSON_STRING; break; //Boolean case 't': compteur = 4; this->parser->val[index] = json; this->parser->val_length[index] = compteur; this->parser->type[index] = JSON_BOOLEAN; break; case 'f': compteur = 5; this->parser->val[index] = json; this->parser->val_length[index] = compteur; this->parser->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->parser->val[index] = json - compteur; this->parser->val_length[index] = compteur; this->parser->type[index] = JSON_NUMBER; break; //Tableau case '[': compteur = skip_array(json) + 1; this->parser->val[index] = json; this->parser->val_length[index] = compteur; this->parser->type[index] = JSON_ARRAY; break; //Objet case '{': compteur = skip_object(json) + 1; this->parser->val[index] = json; this->parser->val_length[index] = compteur; this->parser->type[index] = JSON_OBJECT; break; //Autre default: return JSON_ERROR; } //Retour return ++compteur; } /* --- Fonctions privées encoder --- */ /** * Ajout un noeud au JsonArrayEncoder * @param JsonArrayEncoder* La structure pour encoder * @param char* La chaine à mettre dans le noeud */ void add_json_array_node(JsonArray* this, char* str) { //Création node JsonNode* node; node = malloc(sizeof (JsonNode)); //Allocation node int length = strlen(str) + 1; node->str = malloc(length * sizeof (char)); memset(node->str, 0, length); strncpy(node->str, str, length - 1); //Si 1er node if (this->encoder->tab == NULL) { this->encoder->tab = node; node->prev = NULL; } else { node->prev = this->encoder->last; node->prev->next = node; } this->encoder->last = node; node->next = NULL; } /** * Supprimme un noeud * @param JsonNode* Le noeud à supprimer */ void delete_json_array_node(JsonNode* node) { free(node->str); } /* --- Fonctions publiques parser --- */ void ini_array_parser(JsonArray* this) { //Initialisation en mode encoder this->mode = JSON_ARRAY_PARSER; this->parser = malloc(sizeof (JsonArrayParser)); } int json_parse_array(JsonArray* this, char* json) { int length, jump, index = 0, compteur = 1; //Verification if (this->mode != JSON_ARRAY_PARSER) { return JSON_ERROR; } if (json[0] != '[') { return JSON_ERROR; } //Compte le nombre d'éléments this->parser->length = val_counter(json); if (this->parser->length == JSON_ERROR) { return JSON_ERROR; } length = strlen(json) + 1; this->parser->str = malloc(sizeof (char) * length); memset(this->parser->str, 0, length); strncpy(this->parser->str, json, length - 1); //Si vide if (this->parser->length == 0) { return 0; } //Initialisation this->parser->val = malloc(sizeof (char*) * this->parser->length); this->parser->val_length = malloc(sizeof (int) * this->parser->length); this->parser->type = malloc(sizeof (int) * this->parser->length); //Sinon on parse les valeurs json++; while (*json != ']' && *json) { if (*json != ' ' && *json != ',') { jump = parse_array_val(this, index, this->parser->str + compteur); if (jump == JSON_ERROR) { clean_json_array(this); return JSON_ERROR; } json += jump; compteur += jump; index++; } json++; compteur++; } //Retourne le nombre d'element return this->parser->length; } int get_array_length(JsonArray* this) { //Verification if (this->mode != JSON_ARRAY_PARSER) { return JSON_ERROR; } //Retour return this->parser->length; } int get_array_type(JsonArray* this, int index) { //Verification if (this->mode != JSON_ARRAY_PARSER) { return JSON_ERROR; } if (index < 0 || index >= this->parser->length) { return JSON_ERROR; } //Retourne le type return this->parser->type[index]; } char* get_array_index(JsonArray* this, int index) { //Verification if (this->mode != JSON_ARRAY_PARSER) { return NULL; } if (index < 0 || index >= this->parser->length) { return NULL; } //Creation string d'accueil char* val; val = malloc((this->parser->val_length[index] + 1) * sizeof (char)); //+1 pour \0 memset(val, 0, this->parser->val_length[index] + 1); //Copie valeur strncpy(val, this->parser->val[index], this->parser->val_length[index]); //Retour return val; } char* get_array_value(JsonArray* this, int index) { //Verification if (this->mode != JSON_ARRAY_PARSER) { return NULL; } if (index < 0 || index >= this->parser->length) { return NULL; } //Retour return get_array_index(this, index); } char* get_array_string(JsonArray* this, int index) { //Verification if (this->mode != JSON_ARRAY_PARSER) { return NULL; } if (index < 0 || index >= this->parser->length) { return NULL; } //Retour if (this->parser->type[index] != JSON_STRING) { return NULL; } return get_array_index(this, index); } double get_array_number(JsonArray* this, int index) { //Verification if (this->mode != JSON_ARRAY_PARSER) { return JSON_ERROR; } if (index < 0 || index >= this->parser->length) { return JSON_ERROR; } //Retour if (this->parser->type[index] != JSON_NUMBER) { return JSON_ERROR; } char* val; val = get_array_index(this, index); double res; res = atof(val); free(val); return res; } int get_array_integer(JsonArray* this, int index) { //Verification if (this->mode != JSON_ARRAY_PARSER) { return JSON_ERROR; } if (index < 0 || index >= this->parser->length) { return JSON_ERROR; } //Retour if (this->parser->type[index] != JSON_NUMBER) { return JSON_ERROR; } char* val; val = get_array_index(this, index); int res; res = atoi(val); free(val); return res; } boolean get_array_boolean(JsonArray* this, int index) { //Verification if (this->mode != JSON_ARRAY_PARSER) { return false; } if (index < 0 || index >= this->parser->length) { return false; } //Verif type if (this->parser->type[index] != JSON_BOOLEAN) { return false; } //Recup valeur char* val; val = get_array_index(this, index); //Cast et retour if (val[0] == 't') { return true; } return false; } JsonArray* get_array_array(JsonArray* this, int index) { //Verification if (this->mode != JSON_ARRAY_PARSER) { return NULL; } if (index < 0 || index >= this->parser->length) { return NULL; } //Verif type if (this->parser->type[index] != JSON_ARRAY) { return NULL; } //Recup valeur char* val; val = get_array_index(this, index); //Parse JsonArray* json; json = malloc(sizeof (JsonArray)); ini_array_parser(json); if (json_parse_array(json, val) == JSON_ERROR) { return NULL; } //Retour JSON utilisable free(val); return json; } JsonParser* get_array_object(JsonArray* this, int index) { //Verification if (this->mode != JSON_ARRAY_PARSER) { return NULL; } if (index < 0 || index >= this->parser->length) { return NULL; } //Verif type if (this->parser->type[index] != JSON_OBJECT) { return NULL; } //Recup valeur char* val; val = get_array_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; } /* --- Fonctions publiques encoder --- */ void ini_array_encoder(JsonArray* this) { //Initialisation en mode encoder this->mode = JSON_ARRAY_ENCODER; this->encoder = malloc(sizeof (JsonArrayEncoder)); this->encoder->tab = NULL; } boolean add_array_value(JsonArray* this, char* str) { //Verification if (this->mode != JSON_ARRAY_ENCODER) { return false; } //Ajoute la longueur de la chaine au total this->encoder->length += strlen(str) + 2; //Chaine + ", " //Ajoute le noeud add_json_array_node(this, str); return true; } boolean add_array_string(JsonArray* this, char* val) { //Verification if (this->mode != JSON_ARRAY_ENCODER) { return false; } //Creation chaine int index = 0, length = strlen(val) + 2 + 1; //val + 2 guillemet + \0 char* str = malloc(length * sizeof (char)); memset(str, 0, length); //Copie str[index++] = '"'; for(int i = 0; i < strlen(val); i++, index++){ str[index] = val[i]; } str[index++] = '"'; //Ajout add_array_value(this, str); free(str); return true; } boolean add_array_number(JsonArray* this, double ndigit, int val) { //Verification if (this->mode != JSON_ARRAY_ENCODER) { return false; } //Double en string char nombre[20]; memset(nombre, 0, 20); ftoa(val, nombre, ndigit); //Ajout add_array_value(this, nombre); return true; } boolean add_array_integer(JsonArray* this, int val) { //Verification if (this->mode != JSON_ARRAY_ENCODER) { return false; } //Creation chaine int length = ceil(val / 10.0) + 1; //val + \0 char* str = malloc(length * sizeof (char)); memset(str, 0, length); snprintf(str, length, "%d", val); //Ajout add_array_value(this, str); free(str); return true; } boolean add_array_boolean(JsonArray* this, boolean val) { //Verification if (this->mode != JSON_ARRAY_ENCODER) { return false; } //On determine le boolean char bool[6]; if (val) { strcpy(bool, "true"); } else { strcpy(bool, "false"); } //Ajout add_array_value(this, bool); return true; } boolean add_array_array(JsonArray* this, JsonArray* val) { char* json; //Verification if (this->mode != JSON_ARRAY_ENCODER) { return false; } //Ajout json = json_encode_array(val); add_array_value(this, json); free(json); return true; } boolean add_array_object(JsonArray* this, JsonEncoder* val) { char* json; //Verification if (this->mode != JSON_ARRAY_ENCODER) { return false; } //Ajout json = json_encode(val); add_array_value(this, json); free(json); return true; } char* json_encode_array(JsonArray* this) { //Verification if (this->mode != JSON_ARRAY_ENCODER) { return false; } boolean first = true; int length, index = 0; //Allocation chaine char* str; str = malloc((this->encoder->length + 2) * sizeof (char)); // La chaine + [] memset(str, 0, this->encoder->length + 2); //Creation de la chaine JsonNode* node; node = this->encoder->tab; str[index++] = '['; while (node != NULL) { if(!first){ str[index++] = ','; str[index++] = ' '; } length = strlen(node->str); for(int i = 0; i < length; i++, index++){ str[index] = node->str[i]; } if(first){ first = false; } /*if (first) { sprintf(str, "%s%s", str, node->str); first = false; } else { sprintf(str, "%s, %s", str, node->str); }*/ node = node->next; } str[index++] = ']'; //Retour return str; } /* --- Fonctions publiques --- */ void clean_json_array(JsonArray* this) { if (this->mode == JSON_ARRAY_ENCODER) { JsonNode* node, * tmp; node = this->encoder->tab; while (node != NULL) { tmp = node->next; delete_json_array_node(node); free(node); node = tmp; } free(this->encoder); } else { //Parser free(this->parser->type); free(this->parser->val_length); free(this->parser->val); free(this->parser->str); free(this->parser); } this->mode = -1; }