json.c (4361B)
1 #include <assert.h> 2 #include <stdlib.h> 3 #include <string.h> 4 #include <unistd.h> 5 6 #include <stdio.h> 7 8 #include "json.h" 9 #include "tampex.h" 10 11 /* c est un espace? */ 12 #define ESPACE(c) ((c) == ' ' || \ 13 (c) == '\t' || \ 14 (c) == '\n' || \ 15 (c) == '\r') 16 17 /* c peut être dans un nombre? */ 18 #define DANSNOMB(c) ((c) == '-' || \ 19 (c) == '+' || \ 20 (c) == '.' || \ 21 ((c) >= '0' && (c) <= '9') || \ 22 (c) == 'e' || \ 23 (c) == 'E') 24 25 /* Lire dans le tampex *jeton une chaîne de caractères commençant à *texte et 26 * devant se terminer avant fin. 27 * Renvoie le nombre de caractères écrits dans *jeton, ou -1 en cas 28 * d’erreur. */ 29 static ssize_t lire_ccar(char **texte, char *fin, char **jeton); 30 31 /* Lire dans le tampex *jeton un nombre en commençant à *texte et devant se 32 * terminer avant fin. 33 * Renvoie le nombre de caractères écrits dans *jeton, ou -1 en cas 34 * d’erreur. */ 35 static ssize_t lire_nomb(char **texte, char *fin, char **jeton); 36 37 /* Échapper dans *jeton le ou les caractères dans *texte et devant se terminer 38 * avant fin. Augmente cecr du nombre de caractères échappés. 39 * Renvoie 0, ou -1 en cas d’erreur. */ 40 static int echapper(char **texte, char *fin, char **jeton, size_t *cecr); 41 42 ssize_t 43 json_segmenter(char **json, size_t *reste, char **jeton, int *type) 44 { 45 char *pos; /* Position dans *json. */ 46 char *fin; /* Fin de *json. */ 47 size_t vr; /* Valeur de renvoi. */ 48 49 assert(json); 50 assert(*json); 51 assert(reste); 52 assert(jeton); 53 assert(*jeton); 54 55 fin = *json + *reste; 56 57 /* Manger les espaces. */ 58 for (pos = *json; ESPACE(*pos) && pos != fin; pos++) ; 59 60 if (pos == fin) return 0; 61 assert(pos < fin); 62 63 vr = 1; 64 65 /* Détecter le type du jeton selon le premier caractère. */ 66 switch (*pos++) { 67 case '[': 68 *type = JSON_T_CRCH_GCH; break; 69 case ']': 70 *type = JSON_T_CRCH_DRT; break; 71 case '{': 72 *type = JSON_T_ACCO_GCH; break; 73 case '}': 74 *type = JSON_T_ACCO_DRT; break; 75 case ':': 76 *type = JSON_T_DPTS; break; 77 case ',': 78 *type = JSON_T_VIRG; break; 79 case '"': 80 *type = JSON_T_CCAR; 81 vr = lire_ccar(&pos, fin, jeton); 82 break; 83 case '-': case '.': case '0': case '1': case '2': case '3': case '4': 84 case '5': case '6': case '7': case '8': case '9': 85 pos--; 86 *type = JSON_T_NOMB; 87 vr = lire_nomb(&pos, fin, jeton); 88 break; 89 case 't': 90 *type = JSON_T_VRAI; 91 if (fin - pos < 3) return -1; 92 pos += 3; 93 break; 94 case 'f': 95 *type = JSON_T_FAUX; 96 if (fin - pos < 3) return -1; 97 pos += 4; 98 break; 99 case 'n': 100 *type = JSON_T_NULL; 101 if (fin - pos < 3) return -1; 102 pos += 3; 103 break; 104 default: 105 return -1; 106 } 107 108 *reste = fin - pos; 109 *json = pos; 110 111 return vr; 112 } 113 114 static ssize_t 115 lire_ccar(char **texte, char *fin, char **jeton) 116 { 117 size_t cecr; /* Nombre de caractères écrits. */ 118 char *pos; /* Position dans texte. */ 119 120 assert(texte); 121 assert(*texte); 122 assert(fin), 123 assert(jeton); 124 assert(*jeton); 125 126 cecr = 0; 127 pos = *texte; 128 129 while (*pos != '"') { 130 if (pos >= fin) return -1; 131 if (*pos == '\\') { 132 pos++; 133 if (echapper(&pos, fin, jeton, &cecr) < 0) return -1; 134 continue; 135 } 136 if (tampex_minim((void **)jeton, cecr) < 0) return -1; 137 (*jeton)[cecr++] = *pos++; 138 } 139 140 *texte = pos + 1; 141 return cecr; 142 } 143 144 static int 145 echapper(char **texte, char *fin, char **jeton, size_t *cecr) 146 { 147 char *pos; 148 char c; 149 150 assert(texte); 151 assert(*texte); 152 assert(fin), 153 assert(jeton); 154 assert(*jeton); 155 156 pos = *texte; 157 158 if (pos >= fin) 159 return -1; 160 161 switch (*pos) { 162 case 'u': return -1; /* À implémenter. */ 163 case 'b': c = '\b'; break; 164 case 'f': c = '\f'; break; 165 case 'n': c = '\n'; break; 166 case 'r': c = '\r'; break; 167 case 't': c = '\t'; break; 168 default: c = *pos; /* Les autres caractères restent. */ 169 } 170 171 if (tampex_minim((void **)jeton, *cecr) < 0) return -1; 172 (*jeton)[(*cecr)++] = c; 173 174 *texte = pos + 1; 175 176 return 0; 177 } 178 179 static ssize_t 180 lire_nomb(char **texte, char *fin, char **jeton) 181 { 182 size_t cecr; /* Nombre de caractères écrits. */ 183 char *pos; /* Position dans texte. */ 184 185 assert(texte); 186 assert(*texte); 187 assert(fin), 188 assert(jeton); 189 assert(*jeton); 190 191 192 cecr = 0; 193 pos = *texte; 194 195 while (DANSNOMB(*pos)) { 196 if (pos >= fin) return -1; 197 if (tampex_minim((void **)jeton, cecr) < 0) return -1; 198 (*jeton)[cecr++] = *pos++; 199 } 200 201 *texte = pos; 202 return cecr; 203 }