commit 5daada9ec6cd03582a74cfb1887b85b4490613c6
parent 1992fd6c95b5a9fd5ab3b0e23e8dfef4f8092879
Auteur: Loïc Daignault-Pichette <loic@asteride.xyz>
Date: Tue, 28 Apr 2026 15:56:27 -0400
Segmenter du json
Diffstat:
| A | json.c | | | 200 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
| A | json.h | | | 28 | ++++++++++++++++++++++++++++ |
2 fichiers modifiés, 228 insertions(+), 0 suppressions(-)
diff --git a/json.c b/json.c
@@ -0,0 +1,200 @@
+#include <assert.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <stdio.h>
+
+#include "json.h"
+#include "tampex.h"
+
+/* c est un espace? */
+#define ESPACE(c) ((c) == ' ' || \
+ (c) == '\t' || \
+ (c) == '\n' || \
+ (c) == '\r')
+
+/* c peut être dans un nombre? */
+#define DANSNOMB(c) ((c) == '-' || \
+ (c) == '+' || \
+ (c) == '.' || \
+ ((c) >= '0' && (c) <= '9') || \
+ (c) == 'e' || \
+ (c) == 'E')
+
+/* Lire dans le tampex *jeton une chaîne de caractères commençant à *texte et
+ * devant se terminer avant fin.
+ * Renvoie le nombre de caractères écrits dans *jeton, ou -1 en cas
+ * d’erreur. */
+static ssize_t lire_ccar(char **texte, char *fin, char **jeton);
+
+/* Lire dans le tampex *jeton un nombre en commençant à *texte et devant se
+ * terminer avant fin.
+ * Renvoie le nombre de caractères écrits dans *jeton, ou -1 en cas
+ * d’erreur. */
+static ssize_t lire_nomb(char **texte, char *fin, char **jeton);
+
+/* Échapper dans *jeton le ou les caractères dans *texte et devant se terminer
+ * avant fin. Augmente cecr du nombre de caractères échappés.
+ * Renvoie 0, ou -1 en cas d’erreur. */
+static int echapper(char **texte, char *fin, char **jeton, size_t *cecr);
+
+ssize_t
+json_segmenter(char **json, size_t *reste, char **jeton, int *type)
+{
+ char *pos; /* Position dans *json. */
+ char *fin; /* Fin de *json. */
+ size_t vr; /* Valeur de renvoi. */
+
+ assert(json);
+ assert(*json);
+ assert(reste);
+ assert(jeton);
+ assert(*jeton);
+
+ fin = *json + *reste;
+
+ /* Manger les espaces. */
+ for (pos = *json; ESPACE(*pos) && pos != fin; pos++) ;
+
+ if (pos == fin) return 0;
+ assert(pos < fin);
+
+ vr = 1;
+
+ /* Détecter le type du jeton selon le premier caractère. */
+ switch (*pos++) {
+ case '[':
+ *type = JSON_T_CRCH_GCH; break;
+ case ']':
+ *type = JSON_T_CRCH_DRT; break;
+ case '{':
+ *type = JSON_T_ACCO_GCH; break;
+ case '}':
+ *type = JSON_T_ACCO_DRT; break;
+ case ':':
+ *type = JSON_T_DPTS; break;
+ case ',':
+ *type = JSON_T_VIRG; break;
+ case '"':
+ *type = JSON_T_CCAR;
+ vr = lire_ccar(&pos, fin, jeton);
+ break;
+ case '-': case '.': case '0': case '1': case '2': case '3': case '4':
+ case '5': case '6': case '7': case '8': case '9':
+ pos--;
+ *type = JSON_T_NOMB;
+ vr = lire_nomb(&pos, fin, jeton);
+ break;
+ case 't':
+ *type = JSON_T_VRAI;
+ if (fin - pos < 3) return -1;
+ pos += 3;
+ break;
+ case 'f':
+ *type = JSON_T_FAUX;
+ if (fin - pos < 3) return -1;
+ pos += 4;
+ break;
+ case 'n':
+ *type = JSON_T_NULL;
+ if (fin - pos < 3) return -1;
+ pos += 3;
+ break;
+ default:
+ return -1;
+ }
+
+ *reste = fin - pos;
+ *json = pos;
+
+ return vr;
+}
+
+static ssize_t
+lire_ccar(char **texte, char *fin, char **jeton)
+{
+ size_t cecr; /* Nombre de caractères écrits. */
+ char *pos; /* Position dans texte. */
+
+ assert(texte);
+ assert(*texte);
+ assert(fin),
+ assert(jeton);
+ assert(*jeton);
+
+ cecr = 0;
+ pos = *texte;
+
+ while (*pos != '"') {
+ if (pos >= fin) return -1;
+ if (*pos == '\\') {
+ pos++;
+ if (echapper(&pos, fin, jeton, &cecr) < 0) return -1;
+ continue;
+ }
+ if (tampex_minim((void **)jeton, cecr) < 0) return -1;
+ (*jeton)[cecr++] = *pos++;
+ }
+
+ *texte = pos + 1;
+ return cecr;
+}
+
+static int
+echapper(char **texte, char *fin, char **jeton, size_t *cecr)
+{
+ char *pos;
+ char c;
+
+ assert(texte);
+ assert(*texte);
+ assert(fin),
+ assert(jeton);
+ assert(*jeton);
+
+ pos = *texte;
+
+ switch (*pos) {
+ case 'u': return -1; /* À implémenter. */
+ case 'b': c = '\b'; break;
+ case 'f': c = '\f'; break;
+ case 'n': c = '\n'; break;
+ case 'r': c = '\r'; break;
+ case 't': c = '\t'; break;
+ default: c = *pos; /* Les autres caractères restent. */
+ }
+
+ if (tampex_minim((void **)jeton, *cecr) < 0) return -1;
+ (*jeton)[(*cecr)++] = c;
+
+ *texte = pos + 1;
+
+ return 0;
+}
+
+static ssize_t
+lire_nomb(char **texte, char *fin, char **jeton)
+{
+ size_t cecr; /* Nombre de caractères écrits. */
+ char *pos; /* Position dans texte. */
+
+ assert(texte);
+ assert(*texte);
+ assert(fin),
+ assert(jeton);
+ assert(*jeton);
+
+
+ cecr = 0;
+ pos = *texte;
+
+ while (DANSNOMB(*pos)) {
+ if (pos >= fin) return -1;
+ if (tampex_minim((void **)jeton, cecr) < 0) return -1;
+ (*jeton)[cecr++] = *pos++;
+ }
+
+ *texte = pos;
+ return cecr;
+}
diff --git a/json.h b/json.h
@@ -0,0 +1,28 @@
+#ifndef JSON_H
+#define JSON_H
+
+#include <sys/types.h>
+
+#define JSON_T_CRCH_GCH 0
+#define JSON_T_CRCH_DRT 1
+#define JSON_T_ACCO_GCH 2
+#define JSON_T_ACCO_DRT 3
+#define JSON_T_DPTS 4
+#define JSON_T_VIRG 5
+#define JSON_T_CCAR 6
+#define JSON_T_NOMB 7
+#define JSON_T_VRAI 8
+#define JSON_T_FAUX 9
+#define JSON_T_NULL 10
+
+/* Obtenir le prochain jeton contenu dans le tampon *json, de taille *reste. Le
+ * type du jeton est placé dans *type. Si ce type est JSON_T_CCAR ou
+ * JSON_T_NOMB, le contenu de ce jeton est placé sous forme de chaîne de
+ * caractères dans le tampex *jeton. Chaque fois qu’un jeton est lu, *json est
+ * avancé jusqu’après le jeton lu et *reste est diminué d’autant.
+ * Si le type du jeton est JSON_T_CCAR ou JSON_T_NOMB, renvoie le nombre
+ * d’octets placés dans jeton; s’il est d’un type différent, renvoie 1; s’il
+ * json ne contient plus de jeton, renvoie 0; renvoie -1 en cas d’erreur. */
+ssize_t json_segmenter(char **json, size_t *reste, char **jeton, int *type);
+
+#endif