1 | // SuperTux |
2 | // Copyright (C) 2006 Matthias Braun <matze@braunis.de> |
3 | // |
4 | // This program is free software: you can redistribute it and/or modify |
5 | // it under the terms of the GNU General Public License as published by |
6 | // the Free Software Foundation, either version 3 of the License, or |
7 | // (at your option) any later version. |
8 | // |
9 | // This program is distributed in the hope that it will be useful, |
10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of |
11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
12 | // GNU General Public License for more details. |
13 | // |
14 | // You should have received a copy of the GNU General Public License |
15 | // along with this program. If not, see <http://www.gnu.org/licenses/>. |
16 | |
17 | #include "squirrel/serialize.hpp" |
18 | |
19 | #include <iostream> |
20 | #include <sexp/value.hpp> |
21 | #include <sexp/util.hpp> |
22 | |
23 | #include "squirrel/squirrel_error.hpp" |
24 | #include "util/log.hpp" |
25 | #include "util/reader_mapping.hpp" |
26 | #include "util/writer.hpp" |
27 | |
28 | void load_squirrel_table(HSQUIRRELVM vm, SQInteger table_idx, const ReaderMapping& mapping) |
29 | { |
30 | if (table_idx < 0) |
31 | table_idx -= 2; |
32 | |
33 | auto const& arr = mapping.get_sexp().as_array(); |
34 | for (size_t i = 1; i < arr.size(); ++i) |
35 | { |
36 | auto const& pair = arr[i].as_array(); |
37 | |
38 | // Ignore key value pairs with invalid length |
39 | if (pair.size() < 2) |
40 | { |
41 | log_debug << "Found key/value pair with invalid length. Ignoring." << std::endl; |
42 | continue; |
43 | } |
44 | |
45 | const std::string& key = pair[0].as_string(); |
46 | auto const& value = pair[1]; |
47 | |
48 | // ignore empty / null values |
49 | if (value.is_nil()) |
50 | { |
51 | log_debug << "Found null value for key " << key << ". Ignoring." << std::endl; |
52 | continue; |
53 | } |
54 | // push the key |
55 | sq_pushstring(vm, key.c_str(), key.size()); |
56 | |
57 | // push the value |
58 | switch (value.get_type()) { |
59 | case sexp::Value::Type::ARRAY: |
60 | sq_newtable(vm); |
61 | load_squirrel_table(vm, sq_gettop(vm), ReaderMapping(mapping.get_doc(), arr[i])); |
62 | break; |
63 | case sexp::Value::Type::INTEGER: |
64 | sq_pushinteger(vm, value.as_int()); |
65 | break; |
66 | case sexp::Value::Type::REAL: |
67 | sq_pushfloat(vm, value.as_float()); |
68 | break; |
69 | case sexp::Value::Type::STRING: |
70 | sq_pushstring(vm, value.as_string().c_str(), -1); |
71 | break; |
72 | case sexp::Value::Type::BOOLEAN: |
73 | sq_pushbool(vm, value.as_bool() ? SQTrue : SQFalse); |
74 | break; |
75 | case sexp::Value::Type::SYMBOL: |
76 | log_fatal << "Unexpected symbol in file: " << value.as_string() << std::endl; |
77 | sq_pushnull(vm); |
78 | break; |
79 | default: |
80 | assert(false); |
81 | break; |
82 | } |
83 | |
84 | if (SQ_FAILED(sq_createslot(vm, table_idx))) |
85 | throw SquirrelError(vm, "Couldn't create new index" ); |
86 | } |
87 | } |
88 | |
89 | void save_squirrel_table(HSQUIRRELVM vm, SQInteger table_idx, Writer& writer) |
90 | { |
91 | // offset because of sq_pushnull |
92 | if (table_idx < 0) |
93 | table_idx -= 1; |
94 | |
95 | //iterator table |
96 | sq_pushnull(vm); |
97 | while (SQ_SUCCEEDED(sq_next(vm, table_idx))) { |
98 | if (sq_gettype(vm, -2) != OT_STRING) { |
99 | std::cerr << "Table contains non-string key\n" ; |
100 | continue; |
101 | } |
102 | const SQChar* key; |
103 | sq_getstring(vm, -2, &key); |
104 | |
105 | switch (sq_gettype(vm, -1)) { |
106 | case OT_INTEGER: { |
107 | SQInteger val; |
108 | sq_getinteger(vm, -1, &val); |
109 | writer.write(key, static_cast<int> (val)); |
110 | break; |
111 | } |
112 | case OT_FLOAT: { |
113 | SQFloat val; |
114 | sq_getfloat(vm, -1, &val); |
115 | writer.write(key, static_cast<float> (val)); |
116 | break; |
117 | } |
118 | case OT_BOOL: { |
119 | SQBool val; |
120 | if (SQ_SUCCEEDED(sq_getbool(vm, -1, &val))) |
121 | writer.write(key, val == SQTrue); |
122 | break; |
123 | } |
124 | case OT_STRING: { |
125 | const SQChar* str; |
126 | sq_getstring(vm, -1, &str); |
127 | writer.write(key, reinterpret_cast<const char*> (str)); |
128 | break; |
129 | } |
130 | case OT_TABLE: { |
131 | writer.start_list(key, true); |
132 | save_squirrel_table(vm, -1, writer); |
133 | writer.end_list(key); |
134 | break; |
135 | } |
136 | case OT_CLOSURE: |
137 | break; // ignore |
138 | case OT_NATIVECLOSURE: |
139 | break; |
140 | default: |
141 | std::cerr << "Can't serialize key '" << key << "' in table.\n" ; |
142 | break; |
143 | } |
144 | sq_pop(vm, 2); |
145 | } |
146 | sq_pop(vm, 1); |
147 | } |
148 | |
149 | /* EOF */ |
150 | |