root/trunk/lua/utils.d

Revision 314, 7.4 kB (checked in by xammy, 3 weeks ago)

Bugfixes for LuaLib (package library, thread destruction)

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