Mercurial > projects > dang
comparison src/basic/conv.d @ 207:e0551773a005
Added the correct version.
author | Anders Johnsen <skabet@gmail.com> |
---|---|
date | Tue, 12 Aug 2008 18:19:34 +0200 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
206:d3c148ca429b | 207:e0551773a005 |
---|---|
1 | |
2 // Written in the D programming language. | |
3 | |
4 /* | |
5 * Copyright (C) 2002-2006 by Digital Mars, www.digitalmars.com | |
6 * Written by Walter Bright | |
7 * Some parts contributed by David L. Davis | |
8 * | |
9 * This software is provided 'as-is', without any express or implied | |
10 * warranty. In no event will the authors be held liable for any damages | |
11 * arising from the use of this software. | |
12 * | |
13 * Permission is granted to anyone to use this software for any purpose, | |
14 * including commercial applications, and to alter it and redistribute it | |
15 * freely, subject to the following restrictions: | |
16 * | |
17 * o The origin of this software must not be misrepresented; you must not | |
18 * claim that you wrote the original software. If you use this software | |
19 * in a product, an acknowledgment in the product documentation would be | |
20 * appreciated but is not required. | |
21 * o Altered source versions must be plainly marked as such, and must not | |
22 * be misrepresented as being the original software. | |
23 * o This notice may not be removed or altered from any source | |
24 * distribution. | |
25 */ | |
26 | |
27 /*********** | |
28 * Conversion building blocks. These differ from the C equivalents | |
29 * <tt>atoi()</tt> and <tt>atol()</tt> by | |
30 * checking for overflow and not allowing whitespace. | |
31 * | |
32 * For conversion to signed types, the grammar recognized is: | |
33 * <pre> | |
34 $(I Integer): | |
35 $(I Sign UnsignedInteger) | |
36 $(I UnsignedInteger) | |
37 | |
38 $(I Sign): | |
39 $(B +) | |
40 $(B -) | |
41 * </pre> | |
42 * For conversion to signed types, the grammar recognized is: | |
43 * <pre> | |
44 $(I UnsignedInteger): | |
45 $(I DecimalDigit) | |
46 $(I DecimalDigit) $(I UnsignedInteger) | |
47 * </pre> | |
48 * Macros: | |
49 * WIKI=Phobos/StdConv | |
50 */ | |
51 | |
52 | |
53 /************************* | |
54 Changed to be used next to tango. | |
55 | |
56 Unittests removed. | |
57 *************************/ | |
58 | |
59 module basic.conv; | |
60 | |
61 private import tango.text.Util; // for atof(), toString() | |
62 private import tango.stdc.stringz; | |
63 private import tango.stdc.ctype; | |
64 private import tango.stdc.stdlib; | |
65 private import tango.stdc.errno; | |
66 //private import std.c.stdlib; | |
67 //private import std.math; // for fabs(), isnan() | |
68 | |
69 private | |
70 { | |
71 extern (C) int getErrno(); | |
72 extern (C) int setErrno(int); | |
73 } | |
74 | |
75 //debug=conv; // uncomment to turn on debugging printf's | |
76 | |
77 /* ************* Exceptions *************** */ | |
78 | |
79 /** | |
80 * Thrown on conversion errors, which happens on deviation from the grammar. | |
81 */ | |
82 class ConvError : Exception | |
83 { | |
84 this(char[] s) | |
85 { | |
86 super("conversion " ~ s); | |
87 } | |
88 } | |
89 | |
90 private void conv_error(char[] s) | |
91 { | |
92 throw new ConvError(s); | |
93 } | |
94 | |
95 /** | |
96 * Thrown on conversion overflow errors. | |
97 */ | |
98 class ConvOverflowError : Exception | |
99 { | |
100 this(char[] s) | |
101 { | |
102 super("Error: overflow " ~ s); | |
103 } | |
104 } | |
105 | |
106 private void conv_overflow(char[] s) | |
107 { | |
108 throw new ConvOverflowError(s); | |
109 } | |
110 | |
111 /*************************************************************** | |
112 * Convert character string to the return type. | |
113 */ | |
114 | |
115 int toInt(char[] s) | |
116 { | |
117 int length = s.length; | |
118 | |
119 if (!length) | |
120 goto Lerr; | |
121 | |
122 int sign = 0; | |
123 int v = 0; | |
124 | |
125 for (int i = 0; i < length; i++) | |
126 { | |
127 char c = s[i]; | |
128 if (c >= '0' && c <= '9') | |
129 { | |
130 if (v < int.max/10 || (v == int.max/10 && c + sign <= '7')) | |
131 v = v * 10 + (c - '0'); | |
132 else | |
133 goto Loverflow; | |
134 } | |
135 else if (c == '-' && i == 0) | |
136 { | |
137 sign = -1; | |
138 if (length == 1) | |
139 goto Lerr; | |
140 } | |
141 else if (c == '+' && i == 0) | |
142 { | |
143 if (length == 1) | |
144 goto Lerr; | |
145 } | |
146 else | |
147 goto Lerr; | |
148 } | |
149 if (sign == -1) | |
150 { | |
151 if (cast(uint)v > 0x80000000) | |
152 goto Loverflow; | |
153 v = -v; | |
154 } | |
155 else | |
156 { | |
157 if (cast(uint)v > 0x7FFFFFFF) | |
158 goto Loverflow; | |
159 } | |
160 return v; | |
161 | |
162 Loverflow: | |
163 conv_overflow(s); | |
164 | |
165 Lerr: | |
166 conv_error(s); | |
167 return 0; | |
168 } | |
169 | |
170 /******************************************************* | |
171 * ditto | |
172 */ | |
173 | |
174 uint toUint(char[] s) | |
175 { | |
176 int length = s.length; | |
177 | |
178 if (!length) | |
179 goto Lerr; | |
180 | |
181 uint v = 0; | |
182 | |
183 for (int i = 0; i < length; i++) | |
184 { | |
185 char c = s[i]; | |
186 if (c >= '0' && c <= '9') | |
187 { | |
188 if (v < uint.max/10 || (v == uint.max/10 && c <= '5')) | |
189 v = v * 10 + (c - '0'); | |
190 else | |
191 goto Loverflow; | |
192 } | |
193 else | |
194 goto Lerr; | |
195 } | |
196 return v; | |
197 | |
198 Loverflow: | |
199 conv_overflow(s); | |
200 | |
201 Lerr: | |
202 conv_error(s); | |
203 return 0; | |
204 } | |
205 | |
206 /******************************************************* | |
207 * ditto | |
208 */ | |
209 | |
210 long toLong(char[] s) | |
211 { | |
212 int length = s.length; | |
213 | |
214 if (!length) | |
215 goto Lerr; | |
216 | |
217 int sign = 0; | |
218 long v = 0; | |
219 | |
220 for (int i = 0; i < length; i++) | |
221 { | |
222 char c = s[i]; | |
223 if (c >= '0' && c <= '9') | |
224 { | |
225 if (v < long.max/10 || (v == long.max/10 && c + sign <= '7')) | |
226 v = v * 10 + (c - '0'); | |
227 else | |
228 goto Loverflow; | |
229 } | |
230 else if (c == '-' && i == 0) | |
231 { | |
232 sign = -1; | |
233 if (length == 1) | |
234 goto Lerr; | |
235 } | |
236 else if (c == '+' && i == 0) | |
237 { | |
238 if (length == 1) | |
239 goto Lerr; | |
240 } | |
241 else | |
242 goto Lerr; | |
243 } | |
244 if (sign == -1) | |
245 { | |
246 if (cast(ulong)v > 0x8000000000000000) | |
247 goto Loverflow; | |
248 v = -v; | |
249 } | |
250 else | |
251 { | |
252 if (cast(ulong)v > 0x7FFFFFFFFFFFFFFF) | |
253 goto Loverflow; | |
254 } | |
255 return v; | |
256 | |
257 Loverflow: | |
258 conv_overflow(s); | |
259 | |
260 Lerr: | |
261 conv_error(s); | |
262 return 0; | |
263 } | |
264 | |
265 /******************************************************* | |
266 * ditto | |
267 */ | |
268 | |
269 ulong toUlong(char[] s) | |
270 { | |
271 int length = s.length; | |
272 | |
273 if (!length) | |
274 goto Lerr; | |
275 | |
276 ulong v = 0; | |
277 | |
278 for (int i = 0; i < length; i++) | |
279 { | |
280 char c = s[i]; | |
281 if (c >= '0' && c <= '9') | |
282 { | |
283 if (v < ulong.max/10 || (v == ulong.max/10 && c <= '5')) | |
284 v = v * 10 + (c - '0'); | |
285 else | |
286 goto Loverflow; | |
287 } | |
288 else | |
289 goto Lerr; | |
290 } | |
291 return v; | |
292 | |
293 Loverflow: | |
294 conv_overflow(s); | |
295 | |
296 Lerr: | |
297 conv_error(s); | |
298 return 0; | |
299 } | |
300 | |
301 /******************************************************* | |
302 * ditto | |
303 */ | |
304 | |
305 short toShort(char[] s) | |
306 { | |
307 int v = toInt(s); | |
308 | |
309 if (v != cast(short)v) | |
310 goto Loverflow; | |
311 | |
312 return cast(short)v; | |
313 | |
314 Loverflow: | |
315 conv_overflow(s); | |
316 return 0; | |
317 } | |
318 | |
319 /******************************************************* | |
320 * ditto | |
321 */ | |
322 | |
323 ushort toUshort(char[] s) | |
324 { | |
325 uint v = toUint(s); | |
326 | |
327 if (v != cast(ushort)v) | |
328 goto Loverflow; | |
329 | |
330 return cast(ushort)v; | |
331 | |
332 Loverflow: | |
333 conv_overflow(s); | |
334 return 0; | |
335 } | |
336 | |
337 /******************************************************* | |
338 * ditto | |
339 */ | |
340 | |
341 byte toByte(char[] s) | |
342 { | |
343 int v = toInt(s); | |
344 | |
345 if (v != cast(byte)v) | |
346 goto Loverflow; | |
347 | |
348 return cast(byte)v; | |
349 | |
350 Loverflow: | |
351 conv_overflow(s); | |
352 return 0; | |
353 } | |
354 | |
355 /******************************************************* | |
356 * ditto | |
357 */ | |
358 | |
359 ubyte toUbyte(char[] s) | |
360 { | |
361 uint v = toUint(s); | |
362 | |
363 if (v != cast(ubyte)v) | |
364 goto Loverflow; | |
365 | |
366 return cast(ubyte)v; | |
367 | |
368 Loverflow: | |
369 conv_overflow(s); | |
370 return 0; | |
371 } | |
372 | |
373 /******************************************************* | |
374 * ditto | |
375 */ | |
376 | |
377 float toFloat(in char[] s) | |
378 { | |
379 float f; | |
380 char* endptr; | |
381 char* sz; | |
382 | |
383 //writefln("toFloat('%s')", s); | |
384 sz = toStringz(s); | |
385 if (tango.stdc.ctype.isspace(*sz)) | |
386 goto Lerr; | |
387 | |
388 // BUG: should set __locale_decpoint to "." for DMC | |
389 | |
390 setErrno(0); | |
391 f = strtof(sz, &endptr); | |
392 if (getErrno() == ERANGE) | |
393 goto Lerr; | |
394 if (endptr && (endptr == sz || *endptr != 0)) | |
395 goto Lerr; | |
396 | |
397 return f; | |
398 | |
399 Lerr: | |
400 conv_error(s ~ " not representable as a float"); | |
401 assert(0); | |
402 } | |
403 | |
404 /******************************************************* | |
405 * ditto | |
406 */ | |
407 | |
408 double toDouble(in char[] s) | |
409 { | |
410 double f; | |
411 char* endptr; | |
412 char* sz; | |
413 | |
414 //writefln("toDouble('%s')", s); | |
415 sz = toStringz(s); | |
416 if (tango.stdc.ctype.isspace(*sz)) | |
417 goto Lerr; | |
418 | |
419 // BUG: should set __locale_decpoint to "." for DMC | |
420 | |
421 setErrno(0); | |
422 f = strtod(sz, &endptr); | |
423 if (getErrno() == ERANGE) | |
424 goto Lerr; | |
425 if (endptr && (endptr == sz || *endptr != 0)) | |
426 goto Lerr; | |
427 | |
428 return f; | |
429 | |
430 Lerr: | |
431 conv_error(s ~ " not representable as a double"); | |
432 assert(0); | |
433 } | |
434 | |
435 /******************************************************* | |
436 * ditto | |
437 */ | |
438 real toReal(in char[] s) | |
439 { | |
440 real f; | |
441 char* endptr; | |
442 char* sz; | |
443 | |
444 //writefln("toReal('%s')", s); | |
445 sz = toStringz(s); | |
446 if (tango.stdc.ctype.isspace(*sz)) | |
447 goto Lerr; | |
448 | |
449 // BUG: should set __locale_decpoint to "." for DMC | |
450 | |
451 setErrno(0); | |
452 f = strtold(sz, &endptr); | |
453 if (getErrno() == ERANGE) | |
454 goto Lerr; | |
455 if (endptr && (endptr == sz || *endptr != 0)) | |
456 goto Lerr; | |
457 | |
458 return f; | |
459 | |
460 Lerr: | |
461 conv_error(s ~ " not representable as a real"); | |
462 assert(0); | |
463 } | |
464 |