trafi

Transducteurs finis
git clone git://git.asteride.xyz/trafi.git
Journaux | Fichiers | Références

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:
Ajson.c | 200+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Ajson.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