2 Copyright (C) 2001-2006, William Joseph.
5 This file is part of GtkRadiant.
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.
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.
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
22 #if !defined (INCLUDED_STRINGIO_H)
23 #define INCLUDED_STRINGIO_H
28 #include "generic/vector.h"
29 #include "iscriplib.h"
30 #include "string/string.h"
31 #include "generic/callback.h"
33 inline float string_read_float(const char* string)
35 return static_cast<float>(atof(string));
38 inline int string_read_int(const char* string)
43 inline bool char_is_whitespace(char c)
45 return c == ' ' || c == '\t';
48 inline const char* string_remove_whitespace(const char* string)
52 if(!char_is_whitespace(*string))
61 inline const char* string_remove_zeros(const char* string)
75 inline const char* string_remove_sign(const char* string)
77 if(*string == '-' || *string == '+') // signed zero - acceptable
84 inline bool string_is_unsigned_zero(const char* string)
86 for(;*string != '\0'; ++string)
96 inline bool string_is_signed_zero(const char* string)
98 return string_is_unsigned_zero(string_remove_sign(string));
101 //[whitespaces][+|-][nnnnn][.nnnnn][e|E[+|-]nnnn]
102 //(where whitespaces are any tab or space character and nnnnn may be any number of digits)
103 inline bool string_is_float_zero(const char* string)
105 string = string_remove_whitespace(string);
106 if(string_empty(string))
111 string = string_remove_sign(string);
112 if(string_empty(string))
114 // no whole number or fraction part
119 string = string_remove_zeros(string);
120 if(string_empty(string))
122 // no fraction or exponent
133 string = string_remove_zeros(++string);
134 if(string_empty(string))
140 if(*string == 'e' || *string == 'E')
143 string = string_remove_sign(++string);
149 string = string_remove_zeros(++string);
150 if(string_empty(string))
152 // no trailing whitespace
156 string = string_remove_whitespace(string);
157 return string_empty(string);
160 inline double buffer_parse_floating_literal(const char*& buffer)
162 return strtod(buffer, const_cast<char**>(&buffer));
165 inline int buffer_parse_signed_decimal_integer_literal(const char*& buffer)
167 return strtol(buffer, const_cast<char**>(&buffer), 10);
170 inline int buffer_parse_unsigned_decimal_integer_literal(const char*& buffer)
172 return strtoul(buffer, const_cast<char**>(&buffer), 10);
175 // [+|-][nnnnn][.nnnnn][e|E[+|-]nnnnn]
176 inline bool string_parse_float(const char* string, float& f)
178 if(string_empty(string))
182 f = float(buffer_parse_floating_literal(string));
183 return string_empty(string);
186 // format same as float
187 inline bool string_parse_double(const char* string, double& f)
189 if(string_empty(string))
193 f = buffer_parse_floating_literal(string);
194 return string_empty(string);
197 // <float><space><float><space><float>
198 template<typename Element>
199 inline bool string_parse_vector3(const char* string, BasicVector3<Element>& v)
201 if(string_empty(string) || *string == ' ')
205 v[0] = float(buffer_parse_floating_literal(string));
210 v[1] = float(buffer_parse_floating_literal(string));
215 v[2] = float(buffer_parse_floating_literal(string));
216 return string_empty(string);
219 template<typename Float>
220 inline bool string_parse_vector(const char* string, Float* first, Float* last)
222 if(first != last && (string_empty(string) || *string == ' '))
228 *first = float(buffer_parse_floating_literal(string));
231 return string_empty(string);
240 // decimal signed integer
241 inline bool string_parse_int(const char* string, int& i)
243 if(string_empty(string))
247 i = buffer_parse_signed_decimal_integer_literal(string);
248 return string_empty(string);
251 // decimal unsigned integer
252 inline bool string_parse_size(const char* string, std::size_t& i)
254 if(string_empty(string))
258 i = buffer_parse_unsigned_decimal_integer_literal(string);
259 return string_empty(string);
263 #define RETURN_FALSE_IF_FAIL(expression) if(!expression) return false; else
265 inline void Tokeniser_unexpectedError(Tokeniser& tokeniser, const char* token, const char* expected)
267 globalErrorStream() << Unsigned(tokeniser.getLine()) << ":" << Unsigned(tokeniser.getColumn()) << ": parse error at '" << (token != 0 ? token : "#EOF") << "': expected '" << expected << "'\n";
271 inline bool Tokeniser_getFloat(Tokeniser& tokeniser, float& f)
273 const char* token = tokeniser.getToken();
274 if(token != 0 && string_parse_float(token, f))
278 Tokeniser_unexpectedError(tokeniser, token, "#number");
282 inline bool Tokeniser_getDouble(Tokeniser& tokeniser, double& f)
284 const char* token = tokeniser.getToken();
285 if(token != 0 && string_parse_double(token, f))
289 Tokeniser_unexpectedError(tokeniser, token, "#number");
293 inline bool Tokeniser_getInteger(Tokeniser& tokeniser, int& i)
295 const char* token = tokeniser.getToken();
296 if(token != 0 && string_parse_int(token, i))
300 Tokeniser_unexpectedError(tokeniser, token, "#integer");
304 inline bool Tokeniser_getSize(Tokeniser& tokeniser, std::size_t& i)
306 const char* token = tokeniser.getToken();
307 if(token != 0 && string_parse_size(token, i))
311 Tokeniser_unexpectedError(tokeniser, token, "#unsigned-integer");
315 inline bool Tokeniser_parseToken(Tokeniser& tokeniser, const char* expected)
317 const char* token = tokeniser.getToken();
318 if(token != 0 && string_equal(token, expected))
322 Tokeniser_unexpectedError(tokeniser, token, expected);
326 inline bool Tokeniser_nextTokenIsDigit(Tokeniser& tokeniser)
328 const char* token = tokeniser.getToken();
334 tokeniser.ungetToken();
335 return std::isdigit(c) != 0;
338 template<typename TextOutputStreamType>
339 inline TextOutputStreamType& ostream_write(TextOutputStreamType& outputStream, const Vector3& v)
341 return outputStream << '(' << v.x() << ' ' << v.y() << ' ' << v.z() << ')';
347 inline void CopiedString_importString(CopiedString& self, const char* string)
351 typedef ReferenceCaller1<CopiedString, const char*, CopiedString_importString> CopiedStringImportStringCaller;
352 inline void CopiedString_exportString(const CopiedString& self, const StringImportCallback& importer)
354 importer(self.c_str());
356 typedef ConstReferenceCaller1<CopiedString, const StringImportCallback&, CopiedString_exportString> CopiedStringExportStringCaller;
358 inline void Bool_importString(bool& self, const char* string)
360 self = string_equal(string, "true");
362 typedef ReferenceCaller1<bool, const char*, Bool_importString> BoolImportStringCaller;
363 inline void Bool_exportString(const bool& self, const StringImportCallback& importer)
365 importer(self ? "true" : "false");
367 typedef ConstReferenceCaller1<bool, const StringImportCallback&, Bool_exportString> BoolExportStringCaller;
369 inline void Int_importString(int& self, const char* string)
371 if(!string_parse_int(string, self))
376 typedef ReferenceCaller1<int, const char*, Int_importString> IntImportStringCaller;
377 inline void Int_exportString(const int& self, const StringImportCallback& importer)
380 sprintf(buffer, "%d", self);
383 typedef ConstReferenceCaller1<int, const StringImportCallback&, Int_exportString> IntExportStringCaller;
385 inline void Size_importString(std::size_t& self, const char* string)
388 if(string_parse_int(string, i) && i >= 0)
397 typedef ReferenceCaller1<std::size_t, const char*, Size_importString> SizeImportStringCaller;
398 inline void Size_exportString(const std::size_t& self, const StringImportCallback& importer)
401 sprintf(buffer, "%u", Unsigned(self));
404 typedef ConstReferenceCaller1<std::size_t, const StringImportCallback&, Size_exportString> SizeExportStringCaller;
406 inline void Float_importString(float& self, const char* string)
408 if(!string_parse_float(string, self))
413 typedef ReferenceCaller1<float, const char*, Float_importString> FloatImportStringCaller;
414 inline void Float_exportString(const float& self, const StringImportCallback& importer)
417 sprintf(buffer, "%g", self);
420 typedef ConstReferenceCaller1<float, const StringImportCallback&, Float_exportString> FloatExportStringCaller;
422 inline void Vector3_importString(Vector3& self, const char* string)
424 if(!string_parse_vector3(string, self))
426 self = Vector3(0, 0, 0);
429 typedef ReferenceCaller1<Vector3, const char*, Vector3_importString> Vector3ImportStringCaller;
430 inline void Vector3_exportString(const Vector3& self, const StringImportCallback& importer)
433 sprintf(buffer, "%g %g %g", self[0], self[1], self[2]);
436 typedef ConstReferenceCaller1<Vector3, const StringImportCallback&, Vector3_exportString> Vector3ExportStringCaller;
440 template<typename FirstArgument, typename Caller, typename FirstConversion>
444 static void thunk(void* environment, FirstArgument firstArgument)
446 Caller::thunk(environment, FirstConversion(firstArgument));
455 BoolFromString(const char* string)
457 Bool_importString(m_value, string);
459 operator bool() const
465 inline void Bool_toString(const StringImportCallback& self, bool value)
467 Bool_exportString(value, self);
469 typedef ConstReferenceCaller1<StringImportCallback, bool, Bool_toString> BoolToString;
472 template<typename Caller>
473 inline StringImportCallback makeBoolStringImportCallback(const Caller& caller)
475 return StringImportCallback(caller.getEnvironment(), ImportConvert1<StringImportCallback::first_argument_type, Caller, BoolFromString>::thunk);
478 template<typename Caller>
479 inline StringExportCallback makeBoolStringExportCallback(const Caller& caller)
481 return StringExportCallback(caller.getEnvironment(), ImportConvert1<StringExportCallback::first_argument_type, Caller, BoolToString>::thunk);
489 IntFromString(const char* string)
491 Int_importString(m_value, string);
499 inline void Int_toString(const StringImportCallback& self, int value)
501 Int_exportString(value, self);
503 typedef ConstReferenceCaller1<StringImportCallback, int, Int_toString> IntToString;
506 template<typename Caller>
507 inline StringImportCallback makeIntStringImportCallback(const Caller& caller)
509 return StringImportCallback(caller.getEnvironment(), ImportConvert1<StringImportCallback::first_argument_type, Caller, IntFromString>::thunk);
512 template<typename Caller>
513 inline StringExportCallback makeIntStringExportCallback(const Caller& caller)
515 return StringExportCallback(caller.getEnvironment(), ImportConvert1<StringExportCallback::first_argument_type, Caller, IntToString>::thunk);
524 SizeFromString(const char* string)
526 Size_importString(m_value, string);
528 operator std::size_t() const
534 inline void Size_toString(const StringImportCallback& self, std::size_t value)
536 Size_exportString(value, self);
538 typedef ConstReferenceCaller1<StringImportCallback, std::size_t, Size_toString> SizeToString;
541 template<typename Caller>
542 inline StringImportCallback makeSizeStringImportCallback(const Caller& caller)
544 return StringImportCallback(caller.getEnvironment(), ImportConvert1<StringImportCallback::first_argument_type, Caller, SizeFromString>::thunk);
547 template<typename Caller>
548 inline StringExportCallback makeSizeStringExportCallback(const Caller& caller)
550 return StringExportCallback(caller.getEnvironment(), ImportConvert1<StringExportCallback::first_argument_type, Caller, SizeToString>::thunk);