077a3f6158d33ce40b979c07916c2ce628069e04
[external/ragel.git] / common / common.h
1 /*
2  *  Copyright 2001-2006 Adrian Thurston <thurston@cs.queensu.ca>
3  */
4
5 /*  This file is part of Ragel.
6  *
7  *  Ragel 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  *  Ragel 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 Ragel; if not, write to the Free Software
19  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA 
20  */
21
22 #ifndef _COMMON_H
23 #define _COMMON_H
24
25 #include <climits>
26
27 typedef unsigned long long Size;
28
29 struct Key
30 {
31 private:
32         long key;
33
34 public:
35         friend inline Key operator+(const Key key1, const Key key2);
36         friend inline Key operator-(const Key key1, const Key key2);
37         friend inline Key operator/(const Key key1, const Key key2);
38         friend inline long operator&(const Key key1, const Key key2);
39
40         friend inline bool operator<( const Key key1, const Key key2 );
41         friend inline bool operator<=( const Key key1, const Key key2 );
42         friend inline bool operator>( const Key key1, const Key key2 );
43         friend inline bool operator>=( const Key key1, const Key key2 );
44         friend inline bool operator==( const Key key1, const Key key2 );
45         friend inline bool operator!=( const Key key1, const Key key2 );
46
47         friend struct KeyOps;
48         
49         Key( ) {}
50         Key( const Key &key ) : key(key.key) {}
51         Key( long key ) : key(key) {}
52
53         /* Returns the value used to represent the key. This value must be
54          * interpreted based on signedness. */
55         long getVal() const { return key; };
56
57         /* Returns the key casted to a long long. This form of the key does not
58          * require and signedness interpretation. */
59         long long getLongLong() const;
60
61         bool isUpper() const { return ( 'A' <= key && key <= 'Z' ); }
62         bool isLower() const { return ( 'a' <= key && key <= 'z' ); }
63         bool isPrintable() const { return ( 32 <= key && key < 127 ); }
64
65         Key toUpper() const
66                 { return Key( 'A' + ( key - 'a' ) ); }
67         Key toLower() const
68                 { return Key( 'a' + ( key - 'A' ) ); }
69
70         void operator+=( const Key other )
71         {
72                 /* FIXME: must be made aware of isSigned. */
73                 key += other.key;
74         }
75
76         void operator-=( const Key other )
77         {
78                 /* FIXME: must be made aware of isSigned. */
79                 key -= other.key;
80         }
81
82         void operator|=( const Key other )
83         {
84                 /* FIXME: must be made aware of isSigned. */
85                 key |= other.key;
86         }
87
88         /* Decrement. Needed only for ranges. */
89         inline void decrement();
90         inline void increment();
91 };
92
93 struct HostType
94 {
95         char *data1;
96         char *data2;
97         bool isSigned;
98         long long minVal;
99         long long maxVal;
100         unsigned int size;
101 };
102
103 struct HostLang
104 {
105         HostType *hostTypes;
106         int numHostTypes;
107         HostType *defaultAlphType;
108         bool explicitUnsigned;
109 };
110
111
112 /* Target language. */
113 enum HostLangType
114 {
115         CCode,
116         DCode,
117         JavaCode
118 };
119
120 extern HostLang *hostLang;
121 extern HostLangType hostLangType;
122
123 extern HostLang hostLangC;
124 extern HostLang hostLangD;
125 extern HostLang hostLangJava;
126
127 /* An abstraction of the key operators that manages key operations such as
128  * comparison and increment according the signedness of the key. */
129 struct KeyOps
130 {
131         /* Default to signed alphabet. */
132         KeyOps() :
133                 isSigned(true),
134                 alphType(0)
135         {}
136
137         /* Default to signed alphabet. */
138         KeyOps( bool isSigned ) 
139                 :isSigned(isSigned) {}
140
141         bool isSigned;
142         Key minKey, maxKey;
143         HostType *alphType;
144
145         void setAlphType( HostType *alphType )
146         {
147                 this->alphType = alphType;
148                 isSigned = alphType->isSigned;
149                 if ( isSigned ) {
150                         minKey = (long) alphType->minVal;
151                         maxKey = (long) alphType->maxVal;
152                 }
153                 else {
154                         minKey = (long) (unsigned long) alphType->minVal; 
155                         maxKey = (long) (unsigned long) alphType->maxVal;
156                 }
157         }
158
159         /* Compute the distance between two keys. */
160         Size span( Key key1, Key key2 )
161         {
162                 return isSigned ? 
163                         (unsigned long long)(
164                                 (long long)key2.key - 
165                                 (long long)key1.key + 1) : 
166                         (unsigned long long)(
167                                 (unsigned long)key2.key) - 
168                                 (unsigned long long)((unsigned long)key1.key) + 1;
169         }
170
171         Size alphSize()
172                 { return span( minKey, maxKey ); }
173
174         HostType *typeSubsumes( long long maxVal )
175         {
176                 for ( int i = 0; i < hostLang->numHostTypes; i++ ) {
177                         if ( maxVal <= hostLang->hostTypes[i].maxVal )
178                                 return hostLang->hostTypes + i;
179                 }
180                 return 0;
181         }
182
183         HostType *typeSubsumes( bool isSigned, long long maxVal )
184         {
185                 for ( int i = 0; i < hostLang->numHostTypes; i++ ) {
186                         if ( ( isSigned && hostLang->hostTypes[i].isSigned || !isSigned ) &&
187                                         maxVal <= hostLang->hostTypes[i].maxVal )
188                                 return hostLang->hostTypes + i;
189                 }
190                 return 0;
191         }
192 };
193
194 extern KeyOps *keyOps;
195
196 inline bool operator<( const Key key1, const Key key2 )
197 {
198         return keyOps->isSigned ? key1.key < key2.key : 
199                 (unsigned long)key1.key < (unsigned long)key2.key;
200 }
201
202 inline bool operator<=( const Key key1, const Key key2 )
203 {
204         return keyOps->isSigned ?  key1.key <= key2.key : 
205                 (unsigned long)key1.key <= (unsigned long)key2.key;
206 }
207
208 inline bool operator>( const Key key1, const Key key2 )
209 {
210         return keyOps->isSigned ? key1.key > key2.key : 
211                 (unsigned long)key1.key > (unsigned long)key2.key;
212 }
213
214 inline bool operator>=( const Key key1, const Key key2 )
215 {
216         return keyOps->isSigned ? key1.key >= key2.key : 
217                 (unsigned long)key1.key >= (unsigned long)key2.key;
218 }
219
220 inline bool operator==( const Key key1, const Key key2 )
221 {
222         return key1.key == key2.key;
223 }
224
225 inline bool operator!=( const Key key1, const Key key2 )
226 {
227         return key1.key != key2.key;
228 }
229
230 /* Decrement. Needed only for ranges. */
231 inline void Key::decrement()
232 {
233         key = keyOps->isSigned ? key - 1 : ((unsigned long)key)-1;
234 }
235
236 /* Increment. Needed only for ranges. */
237 inline void Key::increment()
238 {
239         key = keyOps->isSigned ? key+1 : ((unsigned long)key)+1;
240 }
241
242 inline long long Key::getLongLong() const
243 {
244         return keyOps->isSigned ? (long long)key : (long long)(unsigned long)key;
245 }
246
247 inline Key operator+(const Key key1, const Key key2)
248 {
249         /* FIXME: must be made aware of isSigned. */
250         return Key( key1.key + key2.key );
251 }
252
253 inline Key operator-(const Key key1, const Key key2)
254 {
255         /* FIXME: must be made aware of isSigned. */
256         return Key( key1.key - key2.key );
257 }
258
259 inline long operator&(const Key key1, const Key key2)
260 {
261         /* FIXME: must be made aware of isSigned. */
262         return key1.key & key2.key;
263 }
264
265 inline Key operator/(const Key key1, const Key key2)
266 {
267         /* FIXME: must be made aware of isSigned. */
268         return key1.key / key2.key;
269 }
270
271 #endif /* _COMMON_H */