1 /*
2 Copyright (C) 2001-2006, William Joseph.
3 All Rights Reserved.
4
5 This file is part of GtkRadiant.
6
7 GtkRadiant is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
11
12 GtkRadiant is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with GtkRadiant; if not, write to the Free Software
19 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
20 */
21
22 #if !defined (INCLUDED_STRINGIO_H)
23 #define INCLUDED_STRINGIO_H
24
25 #include <stdlib.h>
26 #include <cctype>
27
28 #include "math/Vector3.h"
29 #include "iscriplib.h"
30 #include "string/string.h"
31 #include "generic/callback.h"
32
buffer_parse_floating_literal(const char * & buffer)33 inline double buffer_parse_floating_literal (const char*& buffer)
34 {
35 return strtod(buffer, const_cast<char**> (&buffer));
36 }
37
buffer_parse_signed_decimal_integer_literal(const char * & buffer)38 inline int buffer_parse_signed_decimal_integer_literal (const char*& buffer)
39 {
40 return strtol(buffer, const_cast<char**> (&buffer), 10);
41 }
42
buffer_parse_unsigned_decimal_integer_literal(const char * & buffer)43 inline int buffer_parse_unsigned_decimal_integer_literal (const char*& buffer)
44 {
45 return strtoul(buffer, const_cast<char**> (&buffer), 10);
46 }
47
48 // [+|-][nnnnn][.nnnnn][e|E[+|-]nnnnn]
string_parse_float(const char * string,float & f)49 inline bool string_parse_float (const char* string, float& f)
50 {
51 if (string_empty(string)) {
52 return false;
53 }
54 f = float(buffer_parse_floating_literal(string));
55 return string_empty(string);
56 }
57
58 // format same as float
string_parse_double(const char * string,double & f)59 inline bool string_parse_double (const char* string, double& f)
60 {
61 if (string_empty(string)) {
62 return false;
63 }
64 f = buffer_parse_floating_literal(string);
65 return string_empty(string);
66 }
67
68 // <float><space><float><space><float>
69 template<typename Element>
string_parse_vector3(const std::string & str,BasicVector3<Element> & v)70 inline bool string_parse_vector3 (const std::string& str, BasicVector3<Element>& v)
71 {
72 if (str.empty() || str[0] == ' ') {
73 return false;
74 }
75
76 const char* string = str.c_str();
77 v[0] = float(buffer_parse_floating_literal(string));
78 if (*string++ != ' ') {
79 return false;
80 }
81 v[1] = float(buffer_parse_floating_literal(string));
82 if (*string++ != ' ') {
83 return false;
84 }
85 v[2] = float(buffer_parse_floating_literal(string));
86 return string_empty(string);
87 }
88
89 // decimal signed integer
string_parse_int(const std::string & str,int & i)90 inline bool string_parse_int (const std::string& str, int& i)
91 {
92 if (str.empty()) {
93 return false;
94 }
95 const char* string = str.c_str();
96 i = buffer_parse_signed_decimal_integer_literal(string);
97 return string_empty(string);
98 }
99
100 // decimal unsigned integer
string_parse_size(const std::string & str,std::size_t & i)101 inline bool string_parse_size (const std::string& str, std::size_t& i)
102 {
103 if (str.empty()) {
104 return false;
105 }
106 const char* string = str.c_str();
107 i = buffer_parse_unsigned_decimal_integer_literal(string);
108 return string_empty(string);
109 }
110
Tokeniser_unexpectedError(Tokeniser & tokeniser,const std::string & token,const std::string & expected)111 inline void Tokeniser_unexpectedError (Tokeniser& tokeniser, const std::string& token, const std::string& expected)
112 {
113 globalErrorStream() << string::toString(tokeniser.getLine()) << ":" << string::toString(tokeniser.getColumn())
114 << ": parse error at '" << (token.length() ? token : "#EOF") << "': expected '" << expected << "'\n";
115 }
116
Tokeniser_getFloat(Tokeniser & tokeniser,float & f)117 inline bool Tokeniser_getFloat (Tokeniser& tokeniser, float& f)
118 {
119 const std::string token = tokeniser.getToken();
120 if (token.length() && string_parse_float(token.c_str(), f)) {
121 return true;
122 }
123 Tokeniser_unexpectedError(tokeniser, token, "#number");
124 return false;
125 }
126
Tokeniser_getDouble(Tokeniser & tokeniser,double & f)127 inline bool Tokeniser_getDouble (Tokeniser& tokeniser, double& f)
128 {
129 const std::string token = tokeniser.getToken();
130 if (token.length() && string_parse_double(token.c_str(), f)) {
131 return true;
132 }
133 Tokeniser_unexpectedError(tokeniser, token, "#number");
134 return false;
135 }
136
Tokeniser_getSize(Tokeniser & tokeniser,std::size_t & i)137 inline bool Tokeniser_getSize (Tokeniser& tokeniser, std::size_t& i)
138 {
139 const std::string token = tokeniser.getToken();
140 if (token.length() && string_parse_size(token.c_str(), i)) {
141 return true;
142 }
143 Tokeniser_unexpectedError(tokeniser, token, "#unsigned-integer");
144 return false;
145 }
146
Tokeniser_parseToken(Tokeniser & tokeniser,const char * expected)147 inline bool Tokeniser_parseToken (Tokeniser& tokeniser, const char* expected)
148 {
149 const std::string token = tokeniser.getToken();
150 if (token.length() && string_equal(token, expected)) {
151 return true;
152 }
153 Tokeniser_unexpectedError(tokeniser, token, expected);
154 return false;
155 }
156
Tokeniser_nextTokenIsDigit(Tokeniser & tokeniser)157 inline bool Tokeniser_nextTokenIsDigit (Tokeniser& tokeniser)
158 {
159 const std::string token = tokeniser.getToken();
160 if (token.empty()) {
161 return false;
162 }
163 char c = *token.c_str();
164 tokeniser.ungetToken();
165 return std::isdigit(c) != 0;
166 }
167
168 template<typename TextOutputStreamType>
ostream_write(TextOutputStreamType & outputStream,const Vector3 & v)169 inline TextOutputStreamType& ostream_write (TextOutputStreamType& outputStream, const Vector3& v)
170 {
171 return outputStream << "(" << v.x() << " " << v.y() << " " << v.z() << ")";
172 }
173
StdString_importString(std::string & self,const char * string)174 inline void StdString_importString (std::string& self, const char* string)
175 {
176 self = string;
177 }
178 typedef ReferenceCaller1<std::string, const char*, StdString_importString> StringImportStringCaller;
StdString_exportString(const std::string & self,const StringImportCallback & importer)179 inline void StdString_exportString (const std::string& self, const StringImportCallback& importer)
180 {
181 importer(self.c_str());
182 }
183 typedef ConstReferenceCaller1<std::string, const StringImportCallback&, StdString_exportString>
184 StringExportStringCaller;
185
Bool_importString(bool & self,const char * string)186 inline void Bool_importString (bool& self, const char* string)
187 {
188 self = string_equal(string, "true");
189 }
190 typedef ReferenceCaller1<bool, const char*, Bool_importString> BoolImportStringCaller;
Bool_exportString(const bool & self,const StringImportCallback & importer)191 inline void Bool_exportString (const bool& self, const StringImportCallback& importer)
192 {
193 importer(self ? "true" : "false");
194 }
195 typedef ConstReferenceCaller1<bool, const StringImportCallback&, Bool_exportString> BoolExportStringCaller;
196
Int_importString(int & self,const char * string)197 inline void Int_importString (int& self, const char* string)
198 {
199 if (!string_parse_int(string, self)) {
200 self = 0;
201 }
202 }
203 typedef ReferenceCaller1<int, const char*, Int_importString> IntImportStringCaller;
Int_exportString(const int & self,const StringImportCallback & importer)204 inline void Int_exportString (const int& self, const StringImportCallback& importer)
205 {
206 char buffer[16];
207 sprintf(buffer, "%d", self);
208 importer(buffer);
209 }
210 typedef ConstReferenceCaller1<int, const StringImportCallback&, Int_exportString> IntExportStringCaller;
211
Size_importString(std::size_t & self,const char * string)212 inline void Size_importString (std::size_t& self, const char* string)
213 {
214 int i;
215 if (string_parse_int(string, i) && i >= 0) {
216 self = i;
217 } else {
218 self = 0;
219 }
220 }
221 typedef ReferenceCaller1<std::size_t, const char*, Size_importString> SizeImportStringCaller;
Size_exportString(const std::size_t & self,const StringImportCallback & importer)222 inline void Size_exportString (const std::size_t& self, const StringImportCallback& importer)
223 {
224 char buffer[16];
225 sprintf(buffer, "%u", Unsigned(self));
226 importer(buffer);
227 }
228 typedef ConstReferenceCaller1<std::size_t, const StringImportCallback&, Size_exportString> SizeExportStringCaller;
229
Float_importString(float & self,const char * string)230 inline void Float_importString (float& self, const char* string)
231 {
232 if (!string_parse_float(string, self)) {
233 self = 0;
234 }
235 }
236 typedef ReferenceCaller1<float, const char*, Float_importString> FloatImportStringCaller;
Float_exportString(const float & self,const StringImportCallback & importer)237 inline void Float_exportString (const float& self, const StringImportCallback& importer)
238 {
239 char buffer[16];
240 sprintf(buffer, "%g", self);
241 importer(buffer);
242 }
243 typedef ConstReferenceCaller1<float, const StringImportCallback&, Float_exportString> FloatExportStringCaller;
244
Vector3_importString(Vector3 & self,const char * string)245 inline void Vector3_importString (Vector3& self, const char* string)
246 {
247 //self(std::string(string));
248 if (!string_parse_vector3(string, self)) {
249 self = Vector3(0, 0, 0);
250 }
251 }
252 typedef ReferenceCaller1<Vector3, const char*, Vector3_importString> Vector3ImportStringCaller;
Vector3_exportString(const Vector3 & self,const StringImportCallback & importer)253 inline void Vector3_exportString (const Vector3& self, const StringImportCallback& importer)
254 {
255 char buffer[64];
256 sprintf(buffer, "%g %g %g", self[0], self[1], self[2]);
257 importer(buffer);
258 }
259 typedef ConstReferenceCaller1<Vector3, const StringImportCallback&, Vector3_exportString> Vector3ExportStringCaller;
260
261 template<typename FirstArgument, typename Caller, typename FirstConversion>
262 class ImportConvert1
263 {
264 public:
thunk(void * environment,FirstArgument firstArgument)265 static void thunk (void* environment, FirstArgument firstArgument)
266 {
267 Caller::thunk(environment, FirstConversion(firstArgument));
268 }
269 };
270
271 class BoolFromString
272 {
273 bool m_value;
274 public:
BoolFromString(const char * string)275 BoolFromString (const char* string)
276 {
277 Bool_importString(m_value, string);
278 }
279 operator bool () const
280 {
281 return m_value;
282 }
283 };
284
Bool_toString(const StringImportCallback & self,bool value)285 inline void Bool_toString (const StringImportCallback& self, bool value)
286 {
287 Bool_exportString(value, self);
288 }
289 typedef ConstReferenceCaller1<StringImportCallback, bool, Bool_toString> BoolToString;
290
291 template<typename Caller>
makeBoolStringImportCallback(const Caller & caller)292 inline StringImportCallback makeBoolStringImportCallback (const Caller& caller)
293 {
294 return StringImportCallback(caller.getEnvironment(), ImportConvert1<StringImportCallback::first_argument_type,
295 Caller, BoolFromString>::thunk);
296 }
297
298 template<typename Caller>
makeBoolStringExportCallback(const Caller & caller)299 inline StringExportCallback makeBoolStringExportCallback (const Caller& caller)
300 {
301 return StringExportCallback(caller.getEnvironment(), ImportConvert1<StringExportCallback::first_argument_type,
302 Caller, BoolToString>::thunk);
303 }
304
305 class IntFromString
306 {
307 int m_value;
308 public:
IntFromString(const char * string)309 IntFromString (const char* string)
310 {
311 Int_importString(m_value, string);
312 }
313 operator int () const
314 {
315 return m_value;
316 }
317 };
318
Int_toString(const StringImportCallback & self,int value)319 inline void Int_toString (const StringImportCallback& self, int value)
320 {
321 Int_exportString(value, self);
322 }
323 typedef ConstReferenceCaller1<StringImportCallback, int, Int_toString> IntToString;
324
325 template<typename Caller>
makeIntStringImportCallback(const Caller & caller)326 inline StringImportCallback makeIntStringImportCallback (const Caller& caller)
327 {
328 return StringImportCallback(caller.getEnvironment(), ImportConvert1<StringImportCallback::first_argument_type,
329 Caller, IntFromString>::thunk);
330 }
331
332 template<typename Caller>
makeIntStringExportCallback(const Caller & caller)333 inline StringExportCallback makeIntStringExportCallback (const Caller& caller)
334 {
335 return StringExportCallback(caller.getEnvironment(), ImportConvert1<StringExportCallback::first_argument_type,
336 Caller, IntToString>::thunk);
337 }
338
339 class SizeFromString
340 {
341 std::size_t m_value;
342 public:
SizeFromString(const char * string)343 SizeFromString (const char* string)
344 {
345 Size_importString(m_value, string);
346 }
size_t()347 operator std::size_t () const
348 {
349 return m_value;
350 }
351 };
352
Size_toString(const StringImportCallback & self,std::size_t value)353 inline void Size_toString (const StringImportCallback& self, std::size_t value)
354 {
355 Size_exportString(value, self);
356 }
357 typedef ConstReferenceCaller1<StringImportCallback, std::size_t, Size_toString> SizeToString;
358
359 template<typename Caller>
makeSizeStringImportCallback(const Caller & caller)360 inline StringImportCallback makeSizeStringImportCallback (const Caller& caller)
361 {
362 return StringImportCallback(caller.getEnvironment(), ImportConvert1<StringImportCallback::first_argument_type,
363 Caller, SizeFromString>::thunk);
364 }
365
366 template<typename Caller>
makeSizeStringExportCallback(const Caller & caller)367 inline StringExportCallback makeSizeStringExportCallback (const Caller& caller)
368 {
369 return StringExportCallback(caller.getEnvironment(), ImportConvert1<StringExportCallback::first_argument_type,
370 Caller, SizeToString>::thunk);
371 }
372
373 #endif
374