11/*
22 * Enregistrement des bindings GrnGame (JSON) dans la VM Lua.
33 */
4+ #include " sol/forward.hpp"
5+ #include " sol/table.hpp"
46#include < sol/sol.hpp>
7+ #include < string>
58
69extern " C" {
710#include " ../../moteur/json/json.h"
11+ #include " ../../moteur/logging/logging.h"
812#include < lauxlib.h>
913#include < lua.h>
1014#include < lualib.h>
@@ -30,31 +34,85 @@ void lua_sauvegarder_json_fichier(const std::string &filename) {
3034void lua_supprimer_json_fichier (const std::string &filename) {
3135 supprimer_fichier_json (filename.c_str ());
3236}
37+ /* ecrit recursivement du json */
38+ void ecrire_recursif_json (const std::string &filename, sol::object data,
39+ std::string chemin_actuel) {
40+ /* si la donnee est une table on boucle a linterieur */
41+ if (data.is <sol::table>()) {
42+ sol::table tbl = data.as <sol::table>();
43+ for (auto &elem : tbl) {
44+ std::string cle;
3345
34- /* ecrit une variable dans le json en detectant automatiquement le type */
35- void lua_ecrire_variable (const std::string &filename, const std::string &varName,
36- sol::object value) {
37- if (value.is <bool >()) {
38- ecrire_int_json (filename.c_str (), varName.c_str (), value.as <bool >() ? 1 : 0 );
39- } else if (value.is <std::string>()) {
40- ecrire_string_json (filename.c_str (), varName.c_str (), value.as <std::string>().c_str ());
41- } else if (value.is <double >()) {
42- double val = value.as <double >();
43- if (val == (int )val) {
44- ecrire_int_json (filename.c_str (), varName.c_str (), (int )val);
45- } else {
46- ecrire_double_json (filename.c_str (), varName.c_str (), val);
46+ /* securite : on convertit la cle en string (pour eviter les crashs avec les tableaux
47+ * lua) */
48+ if (elem.first .is <std::string>()) {
49+ cle = elem.first .as <std::string>();
50+ } else if (elem.first .is <int >()) {
51+ cle = std::to_string (elem.first .as <int >());
52+ } else {
53+ continue ; /* on ignore les cles non supportees */
54+ }
55+
56+ sol::object valeur = elem.second ;
57+ std::string nouveau_chemin;
58+
59+ /* on construit le chemin en fonction de sil est vide ou pas */
60+ if (chemin_actuel.empty ()) {
61+ nouveau_chemin = cle;
62+ } else {
63+ nouveau_chemin = chemin_actuel + " ." + cle;
64+ }
65+
66+ /* appel recursif avec le nouveau chemin */
67+ ecrire_recursif_json (filename, valeur, nouveau_chemin);
68+ }
69+ }
70+ /* sinon cest une valeur simple on letablit au bout du chemin */
71+ else {
72+ /* on ne peut pas ecrire une valeur simple a la racine sans chemin */
73+ if (chemin_actuel.empty ())
74+ return ;
75+
76+ if (data.is <bool >()) {
77+ ecrire_int_json (filename.c_str (), chemin_actuel.c_str (), data.as <bool >() ? 1 : 0 );
78+ } else if (data.is <std::string>()) {
79+ ecrire_string_json (filename.c_str (), chemin_actuel.c_str (),
80+ data.as <std::string>().c_str ());
81+ } else if (data.is <double >()) {
82+ double val = data.as <double >();
83+ if (val == (int )val) {
84+ ecrire_int_json (filename.c_str (), chemin_actuel.c_str (), (int )val);
85+ } else {
86+ ecrire_double_json (filename.c_str (), chemin_actuel.c_str (), val);
87+ }
4788 }
4889 }
4990}
5091
92+ /* expose a lua : ecrit une variable ou une table dans le json */
93+ void lua_ecrire_variable (const std::string &filename, sol::object arg1,
94+ sol::optional<sol::object> arg2) {
95+
96+ /* cas 1 : on donne un chemin en argument 1 et une valeur en argument 2 (peut etre une table) */
97+ if (arg1.is <std::string>() && arg2.has_value ()) {
98+ std::string chemin = arg1.as <std::string>();
99+ sol::object valeur = arg2.value ();
100+ ecrire_recursif_json (filename, valeur, chemin);
101+ }
102+ /* cas 2 : argument 1 est une table lua donc on ne donne pas dargument 2 */
103+ else if (arg1.is <sol::table>()) {
104+ ecrire_recursif_json (filename, arg1, " " );
105+ }
106+ /* cas derreur : mauvais arguments depuis lua */
107+ else {
108+ log_fmt (NiveauLogErreur, " you give wrong arguments in json.writeVariable" );
109+ }
110+ }
51111/* Recupere une variable depuis le json avec detection auto */
52112sol::object lua_lire_variable (const std::string &filename, const std::string &varName,
53113 sol::this_state s) {
54114 sol::state_view lua (s);
55-
56115 int type = recuperer_type_json (filename.c_str (), varName.c_str ());
57-
58116 switch (type) {
59117 case JSON_TYPE_NOMBRE : {
60118 double val = recuperer_double_json (filename.c_str (), varName.c_str ());
@@ -65,17 +123,67 @@ sol::object lua_lire_variable(const std::string &filename, const std::string &va
65123 }
66124 case JSON_TYPE_STRING : {
67125 char *val = recuperer_string_json (filename.c_str (), varName.c_str ());
68- if (val)
69- return sol::make_object (lua, std::string (val));
126+ if (val) {
127+ sol::object obj = sol::make_object (lua, std::string (val));
128+ return obj;
129+ }
130+ break ;
131+ }
132+ case JSON_TYPE_OBJECT : {
133+ /* recupere les chemins a partir du chemin de base */
134+ cJSON *tab = lister_tous_les_chemins (filename.c_str (), varName.c_str ());
135+ /* table lua */
136+ sol::table table_resultat = lua.create_table ();
137+ if (tab != NULL && cJSON_IsArray (tab)) {
138+ cJSON *element = NULL ;
139+ /* parcours tableau cJSON */
140+ cJSON_ArrayForEach (element, tab) {
141+ if (cJSON_IsString (element) && element->valuestring ) {
142+ std::string sous_chemin = element->valuestring ;
143+ /* chemin complet ou la on peut recuperer la variable */
144+ std::string chemin_complet =
145+ varName.empty () ? sous_chemin : varName + " ." + sous_chemin;
146+
147+ sol::object valeur_finale = lua_lire_variable (filename, chemin_complet, s);
148+ /* gestion de la table lua */
149+ std::stringstream ss (sous_chemin);
150+ std::string token;
151+ std::vector<std::string> cles;
152+ while (std::getline (ss, token, ' .' )) {
153+ cles.push_back (token);
154+ }
155+ sol::table curseur = table_resultat;
156+ for (size_t i = 0 ; i < cles.size (); ++i) {
157+ if (i == cles.size () - 1 ) {
158+ curseur[cles[i]] = valeur_finale;
159+ } else {
160+ sol::object enfant = curseur[cles[i]];
161+ if (!enfant.is <sol::table>()) {
162+ curseur[cles[i]] = lua.create_table ();
163+ }
164+ curseur = curseur[cles[i]];
165+ }
166+ }
167+ }
168+ }
169+ /* liberation du tableau cJSON obligatoire */
170+ cJSON_Delete (tab);
171+ return table_resultat;
172+ } else {
173+ log_fmt (NiveauLogErreur, " Path error '%s' invalid in %s" , varName.c_str (),
174+ filename.c_str ());
175+ if (tab)
176+ cJSON_Delete (tab);
177+ }
70178 break ;
71179 }
72- default :
73- /* affiche lerreur si le chemin nest pas valide */
180+ default : {
181+ /* affiche l'erreur si le chemin n'est pas valide, essaye double par defaut */
74182 double val = recuperer_double_json (filename.c_str (), varName.c_str ());
75- /* essaye de renvoyer la valeur quand meme */
76183 return sol::make_object (lua, val);
77- break ;
78184 }
185+ }
186+
79187 return sol::make_object (lua, sol::nil);
80188}
81189
0 commit comments