refactored some supertux mainloops
[supertux.git] / src / lisp / lisp.hpp
1 //  $Id$
2 //
3 //  TuxKart - a fun racing game with go-kart
4 //  Copyright (C) 2004 Matthias Braun <matze@braunis.de>
5 //  code in this file based on lispreader from Mark Probst
6 //
7 //  This program is free software; you can redistribute it and/or
8 //  modify it under the terms of the GNU General Public License
9 //  as published by the Free Software Foundation; either version 2
10 //  of the License, or (at your option) any later version.
11 //
12 //  This program 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 this program; if not, write to the Free Software
19 //  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
20 #ifndef __LISPREADER_H__
21 #define __LISPREADER_H__
22
23 #include <string>
24 #include <vector>
25
26 namespace lisp
27 {
28
29 class Lisp
30 {
31 public:
32   ~Lisp();
33     
34   enum LispType {
35     TYPE_CONS,
36     TYPE_SYMBOL,
37     TYPE_INTEGER,
38     TYPE_STRING,
39     TYPE_REAL,
40     TYPE_BOOLEAN
41   };
42
43   LispType get_type() const
44   { return type; } 
45
46   Lisp* get_car() const
47   { return v.cons.car; }
48   Lisp* get_cdr() const
49   { return v.cons.cdr; }
50   
51   bool get(std::string& val) const
52   { 
53     if(type != TYPE_STRING && type != TYPE_SYMBOL)
54       return false;
55     val = v.string;
56     return true;
57   }
58   
59   std::string get_string() const
60   {
61     assert(type == TYPE_STRING);
62     return v.string;
63   }
64   
65   bool get(unsigned int& val) const
66   {
67     if(type != TYPE_INTEGER)
68       return false;
69     val = v.integer;
70     return true;
71   }
72   
73   bool get(int& val) const
74   {
75     if(type != TYPE_INTEGER)
76       return false;
77     val = v.integer;
78     return true;
79   }
80
81   int get_int() const
82   {
83     assert(type == TYPE_INTEGER);
84     return v.integer;
85   }
86   
87   bool get(float& val) const
88   {
89     if(type != TYPE_REAL) {
90       if(type == TYPE_INTEGER) {
91         val = v.integer;
92         return true;
93       }
94       return false;
95     }
96     val = v.real;
97     return true;
98   }
99
100   float get_float() const
101   {
102     assert(type == TYPE_REAL);
103     return v.real;
104   }
105
106   bool get(bool& val) const
107   {
108     if(type != TYPE_BOOLEAN)
109       return false;
110     val = v.boolean;
111     return true;
112   }
113
114   bool get_bool() const
115   {
116     assert(type == TYPE_BOOLEAN);
117     return v.boolean;
118   }
119
120   /** conveniance functions which traverse the list until a child with a
121    * specified name is found. The value part is then interpreted in a specific
122    * way. The functions return true, if a child was found and could be
123    * interpreted correctly, otherwise false is returned and the variable value
124    * is not changed.
125    * (Please note that searching the lisp structure is O(n) so these functions
126    *  are no good idea for performance critical areas)
127    */
128   template<class T>
129   bool get(const char* name, T& val) const
130   {
131     const Lisp* lisp = get_lisp(name);
132     if(!lisp)
133       return false;
134
135     if(lisp->get_type() != TYPE_CONS)
136       return false;
137     lisp = lisp->get_car();
138     if(!lisp)
139       return false;
140     return lisp->get(val);
141   }
142
143   template<class T>
144   bool get_vector(const char* name, std::vector<T>& vec) const
145   {
146     vec.clear();
147     
148     const Lisp* child = get_lisp(name);
149     if(!child)
150       return false;
151     
152     for( ; child != 0; child = child->get_cdr()) {
153       T val;
154       if(!child->get_car())
155         continue;
156       if(child->get_car()->get(val)) {
157         vec.push_back(val);
158       }
159     }
160     
161     return true;
162   }
163   
164   Lisp* get_lisp(const char* name) const;
165   Lisp* get_lisp(const std::string& name) const
166   { return get_lisp(name.c_str()); }
167
168   // for debugging
169   void print(int indent = 0) const;
170
171 private:
172   friend class Parser;
173   Lisp(LispType newtype);
174
175   LispType type;
176   union
177   {
178     struct
179     {
180       Lisp* car;
181       Lisp* cdr;
182     } cons;
183
184     char* string;
185     int integer;
186     bool boolean;
187     float real;
188   } v;
189 };
190
191 } // end of namespace lisp
192
193 #endif
194