/* * File: json_array.c * Author: Arthur Brandao * * Created on 24 novembre 2018 */ #include #include #include #include "json.h" /* --- Fonctions privées parser --- */ /** * Compte le nombre valeur * @param char* La chaine JSON * @return int Le nombre de valeur */ 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 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) { this->mode = JSON_ARRAY_ENCODER; this->encoder = malloc(sizeof(JsonEncoder)); this->encoder->max = JSON_MAX_SIZE; this->encoder->pos = 1; memset(this->encoder->json, 0, this->encoder->max); this->encoder->json[0] = '['; } boolean add_array_value(JsonArray* this, char* str) { //Verification if (this->mode != JSON_ARRAY_ENCODER) { return false; } //Verif que l'on ne depasse pas (on retire 1 pour garder un \0 et on retire 1 autre pour pouvoir mettre ]) if(this->encoder->pos + strlen(str) >= this->encoder->max - 2){ return false; } //Ajoute for(int i = 0; i < strlen(str); i++){ this->encoder->json[this->encoder->pos++] = str[i]; } return true; } boolean add_array_string(JsonArray* this, char* val) { //Verification if (this->mode != JSON_ARRAY_ENCODER) { return false; } int length = strlen(val) + 2 + 2; //val + 2 guillemet + ", " //Verif que l'on ne depasse pas if(this->encoder->pos + length >= this->encoder->max - 2){ return false; } //Ajoute if(this->encoder->pos != 1){ //Si pas 1er valeur on ajoute un separateur this->encoder->json[this->encoder->pos++] = ','; this->encoder->json[this->encoder->pos++] = ' '; } this->encoder->json[this->encoder->pos++] = '"'; for(int i = 0; i < strlen(val); i++){ this->encoder->json[this->encoder->pos++] = val[i]; } this->encoder->json[this->encoder->pos++] = '"'; 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); //Creation chaine int length = strlen(nombre) + 2; //val + ", " //Verif que l'on ne depasse pas if(this->encoder->pos + length >= this->encoder->max - 2){ return false; } //Ajoute if(this->encoder->pos != 1){ //Si pas 1er valeur on ajoute un separateur this->encoder->json[this->encoder->pos++] = ','; this->encoder->json[this->encoder->pos++] = ' '; } for(int i = 0; i < strlen(nombre); i++){ this->encoder->json[this->encoder->pos++] = nombre[i]; } return true; } boolean add_array_integer(JsonArray* this, int val) { //Verification if (this->mode != JSON_ARRAY_ENCODER) { return false; } //Int en string char nombre[20]; memset(nombre, 0, 20); snprintf(nombre, 20, "%d", val); //Creation chaine int length = strlen(nombre) + 2; //val + ", " //Verif que l'on ne depasse pas if(this->encoder->pos + length >= this->encoder->max - 2){ return false; } //Ajoute if(this->encoder->pos != 1){ //Si pas 1er valeur on ajoute un separateur this->encoder->json[this->encoder->pos++] = ','; this->encoder->json[this->encoder->pos++] = ' '; } for(int i = 0; i < strlen(nombre); i++){ this->encoder->json[this->encoder->pos++] = nombre[i]; } 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]; memset(bool, 0, 6); if (val) { strncpy(bool, "true", 4); } else { strncpy(bool, "false", 5); } //Creation chaine int length = strlen(bool) + 2; //val + ", " //Verif que l'on ne depasse pas if(this->encoder->pos + length >= this->encoder->max - 2){ return false; } //Ajoute if(this->encoder->pos != 1){ //Si pas 1er valeur on ajoute un separateur this->encoder->json[this->encoder->pos++] = ','; this->encoder->json[this->encoder->pos++] = ' '; } for(int i = 0; i < strlen(bool); i++){ this->encoder->json[this->encoder->pos++] = bool[i]; } return true; } boolean add_array_array(JsonArray* this, JsonArray* val) { //Verification if (this->mode != JSON_ARRAY_ENCODER) { return false; } //Recup json char* json = json_encode_array(val); //Creation chaine int length = strlen(json) + 2; //val + ", " //Verif que l'on ne depasse pas if(this->encoder->pos + length >= this->encoder->max - 2){ return false; } //Ajoute if(this->encoder->pos != 1){ //Si pas 1er valeur on ajoute un separateur this->encoder->json[this->encoder->pos++] = ','; this->encoder->json[this->encoder->pos++] = ' '; } for(int i = 0; i < strlen(json); i++){ this->encoder->json[this->encoder->pos++] = json[i]; } //Nettoayge free(json); return true; } boolean add_array_object(JsonArray* this, JsonEncoder* val) { //Verification if (this->mode != JSON_ARRAY_ENCODER) { return false; } //Recup json char* json = json_encode(val); //Creation chaine int length = strlen(json) + 2; //val + ", " //Verif que l'on ne depasse pas if(this->encoder->pos + length >= this->encoder->max - 2){ return false; } //Ajoute if(this->encoder->pos != 1){ //Si pas 1er valeur on ajoute un separateur this->encoder->json[this->encoder->pos++] = ','; this->encoder->json[this->encoder->pos++] = ' '; } for(int i = 0; i < strlen(json); i++){ this->encoder->json[this->encoder->pos++] = json[i]; } //Nettoayge free(json); return true; } char* json_encode_array(JsonArray* this) { char* json; //Ajoute } fin this->encoder->json[this->encoder->pos] = ']'; //Creation chaine json = malloc(sizeof(char) * (this->encoder->pos + 2)); memset(json, 0, this->encoder->pos + 2); strncpy(json, this->encoder->json, this->encoder->pos + 1); //Retourne return json; } /* --- Fonctions publiques --- */ void clean_json_array(JsonArray* this) { if (this->mode == JSON_ARRAY_ENCODER) { free(this->encoder); ini_array_encoder(this); } 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; }