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