ソースを参照

:sparkles: Ajout parser tableau JSON

Arthur Brandao 6 年 前
コミット
64e7d30a13
4 ファイル変更558 行追加45 行削除
  1. 117 2
      Serveur/json.h
  2. 369 3
      Serveur/json_array.c
  3. 48 39
      Serveur/json_parser.c
  4. 24 1
      Serveur/test.c

+ 117 - 2
Serveur/json.h

@@ -45,6 +45,7 @@ typedef struct{
     char* str; //La chaine
     char** val; //Pointeur vers les valeurs du tableau
     int* val_length; //Taille des valeurs
+    int* type; //Type de la valeur
     int length; //Taille du tableau
 }JsonArrayParser;
 
@@ -70,6 +71,20 @@ struct JsonNode{
 
 //JsonParser
 
+/**
+ * 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*);
+
+/**
+ * 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*);
+
 /**
  * Parse une chaine JSON en JsonParser
  * Initialise ou écrase les données du JsonParser
@@ -155,9 +170,9 @@ boolean get_boolean(JsonParser*, char*);
  * Retourne la valeur d'un element de type array
  * @param JsonParser* Le resultat de json_parse
  * @param char* La clef lié à la valeur
- * @return char* La valeur, NULL en cas d'erreur (type incorrect, clef introuvable)
+ * @return JsonArray* La valeur, NULL en cas d'erreur (type incorrect, clef introuvable)
  */
-char* get_array(JsonParser*, char*);
+JsonArray* get_array(JsonParser*, char*);
 
 /**
  * Retourne la valeur d'un element de type object
@@ -252,8 +267,99 @@ char* json_encode(JsonEncoder*);
 void clean_json_encoder(JsonEncoder*);
 
 //JsonArrayParser
+
+/**
+ * Initialise le JsonArray en mode Parser
+ * @param JsonArray* La structure à initialiser
+ */
+void ini_array_parser(JsonArray*);
+
+/**
+ * Parse un tableau JSON
+ * @param JsonArray* La structure initialisée en mode parser
+ * @param char* La chaine JSON
+ * @return int Le nombre d'élement dans le tableau ou JSON_ERROR
+ */
 int json_parse_array(JsonArray*, char*);
 
+/**
+ * Donne le nombre d'élément dans le tableau
+ * @param JsonArray* Le resultat de json_parse_array
+ * @return int Le nombre d'élémént
+ */
+int get_array_length(JsonArray*);
+/**
+ * Retourne le type de la valeur
+ * @param JsonArray* Le resultat de json_parse_array
+ * @param int La clef lié à la valeur
+ * @return int constante JSON_XXXX du type de la valeur
+ */
+int get_array_type(JsonArray*, int);
+
+/**
+ * Retourne la valeur à l'index donnée du tableau
+ * @param JsonArray* Le resultat de json_parse_array
+ * @param int L'index
+ * @return char* La valeur
+ */
+char* get_array_index(JsonArray*, int);
+
+/**
+ * Retourne la valeur d'un element
+ * @param JsonArray* Le resultat de json_parse_array
+ * @param int L'index
+ * @return char* La valeur, NULL en cas d'erreur (index introuvable)
+ */
+char* get_array_value(JsonArray*, int);
+
+/**
+ * Retourne la valeur d'un element de type string
+ * @param JsonArray* Le resultat de json_parse_array
+ * @param int L'index
+ * @return char* La valeur, NULL en cas d'erreur (type incorrect, index introuvable)
+ */
+char* get_array_string(JsonArray*, int);
+
+/**
+ * Retourne la valeur d'un element de type number
+ * @param JsonArray* Le resultat de json_parse_array
+ * @param int L'index
+ * @return double La valeur, JSON_ERROR en cas d'erreur (type incorrect, index introuvable)
+ */
+double get_array_number(JsonArray*, int);
+
+/**
+ * Retourne la valeur d'un element de type number
+ * @param JsonArray* Le resultat de json_parse_array
+ * @param int L'index
+ * @return int La valeur, JSON_ERROR en cas d'erreur (type incorrect, index introuvable)
+ */
+int get_array_integer(JsonArray*, int);
+
+/**
+ * Retourne la valeur d'un element de type boolean
+ * @param JsonArray* Le resultat de json_parse_array
+ * @param int L'index
+ * @return boolean La valeur, false en cas d'erreur (type incorrect, index introuvable)
+ */
+boolean get_array_boolean(JsonArray*, int);
+
+/**
+ * Retourne la valeur d'un element de type array
+ * @param @param JsonArray* Le resultat de json_parse_array
+ * @param int L'index
+ * @return JsonArray* La valeur, NULL en cas d'erreur (type incorrect, index introuvable)
+ */
+JsonArray* get_array_array(JsonArray*, int);
+
+/**
+ * Retourne la valeur d'un element de type object
+ * @param JsonArray* Le resultat de json_parse_array
+ * @param int L'index
+ * @return JsonParser* L'object json analysé, NULL en cas d'erreur (type incorrect, index introuvable, ...)
+ */
+JsonParser* get_array_object(JsonArray*, int);
+
 //JsonArrayEncoder
 
 /**
@@ -313,10 +419,19 @@ boolean add_array_array(JsonArray*, JsonArray*);
  */
 boolean add_array_object(JsonArray*, JsonEncoder*);
 
+/**
+ * Encode un tableau JSON
+ * @param JsonArray* La structure à encoder
+ * @return LA chaine JSON
+ */
 char* json_encode_array(JsonArray*);
 
 //JsonArray
 
+/**
+ * Vide une structure JsonArray
+ * @param JsonArray* La structure à vider
+ */
 void clean_json_array(JsonArray*);
 
 #endif /* JSON_H */

+ 369 - 3
Serveur/json_array.c

@@ -12,6 +12,135 @@
 
 /* --- 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 --- */
 
 /**
@@ -50,6 +179,239 @@ void delete_json_array_node(JsonNode* node) {
 
 /* --- 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) {
@@ -185,7 +547,6 @@ char* json_encode_array(JsonArray* this) {
 
 void clean_json_array(JsonArray* this) {
     if (this->mode) {
-        //Encoder
         JsonNode* node, * tmp;
         node = this->encoder->tab;
         while (node != NULL) {
@@ -194,10 +555,15 @@ void clean_json_array(JsonArray* this) {
             free(node);
             node = tmp;
         }
-        //Reset la structure
         free(this->encoder);
-        this->mode = -1;
+        
     } 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;
 }

+ 48 - 39
Serveur/json_parser.c

@@ -10,42 +10,6 @@
 
 /* --- 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 
@@ -229,6 +193,40 @@ int search_index(JsonParser* this, char* key){
 
 /* --- Fonctions publiques --- */
 
+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 == '{') {
+            int jump = skip_object(json);
+            json += jump;
+            compteur += jump;
+        }
+        compteur++;
+        json++;
+    }
+    return compteur;
+}
+
+int skip_array(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 == '[') {
+            int jump = skip_array(json);
+            json += jump;
+            compteur += jump;
+        }
+        json++;
+        compteur++;
+    }
+    return compteur;
+}
+
 int json_parse(JsonParser* this, char* json) {
     //Declaration variable
     char* tmp;
@@ -409,7 +407,7 @@ boolean get_boolean(JsonParser* this, char* key){
     return false;
 }
 
-char* get_array(JsonParser* this, char* key){
+JsonArray* get_array(JsonParser* this, char* key){
     //Recup index
     int index;
     if((index = search_index(this, key)) == JSON_ERROR){
@@ -419,8 +417,19 @@ char* get_array(JsonParser* this, char* key){
     if(this->type[index] != JSON_ARRAY){
         return NULL;
     }
-    //Retour pas de gestion de tableau actuellement
-    return get_index(this, index);
+    //Recup valeur
+    char* val;
+    val = get_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_object(JsonParser* this, char* key){

+ 24 - 1
Serveur/test.c

@@ -208,6 +208,28 @@ int array_encode(){
     return 1;
 }
 
+int array_parse(){
+    // "[4.000, \"String\", true, [4.000, \"String\", true, [1, 2, 3]]"
+    
+    JsonArray ja;
+    ini_array_parser(&ja);
+    int a = json_parse_array(&ja, "[4.000, \"String\", true, [4.000, \"String\", true, [1, 2, 3]], {\"aze\": \"rty\", \"tab\": [1, 2, 3]}]");
+    printf("Res : %d\n", a);
+    
+    printf("%f\n", get_array_number(&ja, 0));
+    printf("%s\n", get_array_string(&ja, 1));
+    printf("%d\n", get_array_boolean(&ja, 2));
+    printf("%s\n", get_array_value(&ja, 3));
+    
+    JsonParser* jp = get_array_object(&ja, 4);
+    printf("%s\n", get_string(jp, "aze"));
+    
+    JsonArray* ja2 = get_array(jp, "tab");
+    printf("%s\n", get_array_value(ja2, 1));
+    
+    return 1;
+}
+
 int main(){
     //return parse();
     //return encode();
@@ -234,5 +256,6 @@ int main(){
     //*/
     
     //return files();
-    return array_encode();
+    //return array_encode();
+    return array_parse();
 }