root/trunk/lua/utils.d

Revision 324, 7.6 kB (checked in by Trass3r, 3 years ago)

+ D2 compatibility!
+ precompiled lua 5.1.4
+ Exceptions support file and line arguments
* changed file encoding to UTF-8
* several bugfixes

Line 
1 /*******************************************************************************
2
3     copyright:      Copyright (c) 2008 Matthias Walter. All rights reserved
4
5     authors:        Matthias Walter, Andreas Hollandt
6     
7     Many functions already exist in Tango, Phobos or even both. But most of
8     them are needed at compile time! E.g. Tangos text.convert.Integers
9     conversion functionality is not (yet) available at compile time, so
10     integer conversions are implemented here.
11
12 *******************************************************************************/
13
14 module lua.utils;
15 private import lua.common;
16 private import lua.error;
17
18 /*******************************************************************************
19
20     Function to convert a digit to its character representation.
21
22     Remarks:
23     Can be evaluated at compile time.
24
25 *******************************************************************************/
26
27 public static char int2digit (uint d)
28 {
29     assert (d < 16);
30
31     if (d < 10)
32         return cast (char) '0' + d;
33     else
34         return cast (char) 'a' + (d-10);
35 }
36
37 /*******************************************************************************
38
39     Function to convert a character to a digit, representing it. Returns
40     0 .. 15 for digits, -1 for a minus, -2 for a dot and -3 else.
41     
42     Params:
43     d = the
44     
45     Remarks:
46     Can be evaluated at compile time.
47
48 *******************************************************************************/
49
50 public static byte digit2int (char c)
51 {
52     if (c >= '0' && c <= '9')
53         return (c - '0');
54     else if (c >= 'a' && c <= 'f')
55         return (c - 'a' + 10);
56     else if (c >= 'A' && c <= 'F')
57         return (c - 'A' + 10);
58     else if (c == '-')
59         return -1;
60     else if (c == '.')
61         return -2;
62     else
63         return -3;
64 }
65
66 /*******************************************************************************
67
68     Function template to convert an integer to a string in a number system.
69
70     Params:
71     i = Number to convert.
72     radix = Base of the number system.
73
74     Remarks:
75     Can be evaluated at compile time.
76
77 *******************************************************************************/
78
79 public static istring int2string (T) (T i, int radix = 10)
80 {
81     if (i < 0)
82         return "-" ~ int2string !(ulong) (-i, radix);
83     else if (i >= radix)
84         return int2string !(ulong) (i / radix, radix) ~ int2digit (i % radix);
85     else
86         return "" ~ int2digit (i % radix);
87 }
88
89 unittest
90 {
91     assert (int2string (long.min) == "-9223372036854775808");
92     assert (int2string (long.max) == "9223372036854775807");
93     assert (int2string (ulong.min) == "0");
94     assert (int2string (ulong.max) == "18446744073709551615");
95     assert (int2string (long.max, 16) == "7fffffffffffffff");
96     assert (int2string (ulong.max, 16) == "ffffffffffffffff");
97 }
98
99 /*******************************************************************************
100
101     Function template to parse an integer string and return the integer.
102     
103     Params:
104     str = String, containing an integer.
105     read = How many bytes have been converted, negative if overflow.
106     radix = Base of the number system.
107
108     Remarks:
109     Can be evaluated at compile time.
110
111 *******************************************************************************/
112
113 public static T parseInt (T) (cstring str, out int read, uint radix = 10)
114 {
115     read = 0;
116     if (str.length == 0)
117         return 0;
118
119     ulong value = 0;
120     int d = digit2int (str[0]);
121     byte start = 0;
122
123     if (d == -1)
124     {
125         start = 1;
126         read++;
127     }
128     else if (d < -1 || d >= radix)
129         return 0;
130    
131     foreach (c; str[start .. $])
132     {
133         d = digit2int (c);
134         if (d >= 0 && d < radix)
135         {
136             value = radix * value + d;
137             read++;
138         }
139         else
140             break;
141     }
142
143     static if (T.min == 0)
144     {
145         // overflow
146         if ((start == 1 && value > 0) || (value > T.max))
147         {
148             read = -1;
149             return 0;
150         }
151         else
152             return value;
153     }
154     else
155     {
156         if ((start == 1 && value > -cast (long) T.min) || (start == 0 && value > T.max))
157         {
158             read = -1;
159             return 0;
160         }
161         else
162             return cast (T) (start == 0 ? value : -value); 
163     }
164 }
165
166 /*******************************************************************************
167
168     Function template to convert an integer string to the integer.
169
170     Params:
171     str = String, containing an integer.
172     radix = Base of the number system.
173
174     Remarks:
175     Can be evaluated at compile time.
176
177 *******************************************************************************/
178
179 public static T string2int (T = long) (cstring str, uint radix = 10)
180 {
181     int read;
182     T result = parseInt ! (T) (str, read, radix);
183     if (read == str.length)
184         return result;
185     else if (read < 0)
186         throw new ExtendedException (cast(istring) ("Parse error in '" ~ str ~ "': Integer overflow."), __FILE__, __LINE__);
187     else
188         throw new ExtendedException (cast(istring) ("Parse error in '" ~ str ~ "' at position " ~ int2string (read)), __FILE__, __LINE__);
189 }
190
191 unittest
192 {
193     assert (string2int !(byte) ("0") == 0);
194     assert (string2int !(byte) ("127") == 127);
195     assert (string2int !(byte) ("-128") == -128);
196     try
197     {
198         string2int !(byte) ("128");
199         assert (false);
200     }
201     catch (Exception e) { }
202     try
203     {
204         string2int !(byte) ("-129");
205         assert (false);
206     }
207     catch (Exception e) { }
208     assert (string2int ("9223372036854775807") == long.max);
209     assert (string2int ("-9223372036854775808") == long.min);
210     try
211     {
212         string2int ("-9223372036854775809");
213         assert (false);
214     }
215     catch (Exception e) { }
216     try
217     {
218         string2int ("9223372036854775808");
219         assert (false);
220     }
221     catch (Exception e) { }
222     assert (string2int !(ulong) ("18446744073709551615") == ulong.max);
223 }
224
225 /*******************************************************************************
226
227     Function to find the first occurence of a character in a given string.
228
229     Remarks:
230     Can be evaluated at compile time.
231
232 *******************************************************************************/
233
234 public static int find (cstring str, char c)
235 {
236     foreach (int i, char ch; str)
237     {
238         if (ch == c)
239             return i;
240     }
241     return -1;
242 }
243
244 /*******************************************************************************
245
246     Function to find the last occurence of a character in a given string.
247
248     Remarks:
249     Can be evaluated at compile time.
250
251 *******************************************************************************/
252
253 public static int rfind (cstring str, char c)
254 {
255     foreach_reverse (int i, char ch; str)
256     {
257         if (ch == c)
258             return i;
259     }
260     return -1;
261 }
262
263 /*******************************************************************************
264
265     Function to create a '\0'-terminated string from a given string.
266
267 *******************************************************************************/
268
269 public static char* toStringz (cstring s)
270 {
271     if (s.ptr)
272     {
273         if (! (s.length && s[$-1] is 0))
274             s = s ~ '\0';
275     }
276     return cast(char*) s.ptr;
277 }
278
279 /*******************************************************************************
280
281     Returns the length of a '\0'-terminated string.
282
283 *******************************************************************************/
284
285 public static size_t strlenz (cchar* s)
286 {
287     size_t i;
288
289     if (s)
290     {
291         while (*s++)
292             i++;
293     }
294     return i;
295 }
296
297
298 public static cstring ltrim (cstring str, cstring chars)
299 {
300     foreach (i, c; str)
301     {
302         bool match = false;
303         foreach (t; chars)
304         {
305             if (c == t)
306             {
307                 match = true;
308                 break;
309             }
310         }
311         if (!match)
312         {
313             return str[i .. $];
314         }
315     }
316     return [];
317 }
318
319 public static T removeFirst (T) (ref T[] array)
320 {
321     assert (array.length > 0);
322
323     T result = array[0];
324     array = array[1 .. $];
325     return result;
326 }
327
328 public static T[] removeFirst (T) (ref T[] array, uint amount)
329 {
330     assert (amount <= array.length);
331
332     T[] result = array[0 .. amount];
333     array = array[amount .. $];
334     return result;
335 }
336
337 public static T[] join (T) (T[] split, T[][] array)
338 {
339     T[] result;
340     foreach (i, a; array)
341     {
342         if (i > 0)
343             result ~= split ~ a;
344         else
345             result = a;
346     }
347     return result;
348 }
Note: See TracBrowser for help on using the browser.