# HG changeset patch # User Anders Johnsen # Date 1211723293 -7200 # Node ID d03b011c50e96623e737f83bfaa5337e3865d02a # Parent c658172ca8a0a747fd4a9547347fc788956217e7 Added missing file. This file is from the phobos source, with some modifications so that it can run in tango. Also slimed out unittests. diff -r c658172ca8a0 -r d03b011c50e9 basic/conv.d --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/basic/conv.d Sun May 25 15:48:13 2008 +0200 @@ -0,0 +1,464 @@ + +// Written in the D programming language. + +/* + * Copyright (C) 2002-2006 by Digital Mars, www.digitalmars.com + * Written by Walter Bright + * Some parts contributed by David L. Davis + * + * This software is provided 'as-is', without any express or implied + * warranty. In no event will the authors be held liable for any damages + * arising from the use of this software. + * + * Permission is granted to anyone to use this software for any purpose, + * including commercial applications, and to alter it and redistribute it + * freely, subject to the following restrictions: + * + * o The origin of this software must not be misrepresented; you must not + * claim that you wrote the original software. If you use this software + * in a product, an acknowledgment in the product documentation would be + * appreciated but is not required. + * o Altered source versions must be plainly marked as such, and must not + * be misrepresented as being the original software. + * o This notice may not be removed or altered from any source + * distribution. + */ + +/*********** + * Conversion building blocks. These differ from the C equivalents + * atoi() and atol() by + * checking for overflow and not allowing whitespace. + * + * For conversion to signed types, the grammar recognized is: + *
+$(I Integer):
+    $(I Sign UnsignedInteger)
+    $(I UnsignedInteger)
+
+$(I Sign):
+    $(B +)
+    $(B -)
+ * 
+ * For conversion to signed types, the grammar recognized is: + *
+$(I UnsignedInteger):
+    $(I DecimalDigit)
+    $(I DecimalDigit) $(I UnsignedInteger)
+ * 
+ * Macros: + * WIKI=Phobos/StdConv + */ + + +/************************* + Changed to be used next to tango. + + Unittests removed. + *************************/ + +module basic.conv; + +private import tango.text.Util; // for atof(), toString() +private import tango.stdc.stringz; +private import tango.stdc.ctype; +private import tango.stdc.stdlib; +private import tango.stdc.errno; +//private import std.c.stdlib; +//private import std.math; // for fabs(), isnan() + +private +{ + extern (C) int getErrno(); + extern (C) int setErrno(int); +} + +//debug=conv; // uncomment to turn on debugging printf's + +/* ************* Exceptions *************** */ + +/** + * Thrown on conversion errors, which happens on deviation from the grammar. + */ +class ConvError : Exception +{ + this(char[] s) + { + super("conversion " ~ s); + } +} + +private void conv_error(char[] s) +{ + throw new ConvError(s); +} + +/** + * Thrown on conversion overflow errors. + */ +class ConvOverflowError : Exception +{ + this(char[] s) + { + super("Error: overflow " ~ s); + } +} + +private void conv_overflow(char[] s) +{ + throw new ConvOverflowError(s); +} + +/*************************************************************** + * Convert character string to the return type. + */ + +int toInt(char[] s) +{ + int length = s.length; + + if (!length) + goto Lerr; + + int sign = 0; + int v = 0; + + for (int i = 0; i < length; i++) + { + char c = s[i]; + if (c >= '0' && c <= '9') + { + if (v < int.max/10 || (v == int.max/10 && c + sign <= '7')) + v = v * 10 + (c - '0'); + else + goto Loverflow; + } + else if (c == '-' && i == 0) + { + sign = -1; + if (length == 1) + goto Lerr; + } + else if (c == '+' && i == 0) + { + if (length == 1) + goto Lerr; + } + else + goto Lerr; + } + if (sign == -1) + { + if (cast(uint)v > 0x80000000) + goto Loverflow; + v = -v; + } + else + { + if (cast(uint)v > 0x7FFFFFFF) + goto Loverflow; + } + return v; + +Loverflow: + conv_overflow(s); + +Lerr: + conv_error(s); + return 0; +} + +/******************************************************* + * ditto + */ + +uint toUint(char[] s) +{ + int length = s.length; + + if (!length) + goto Lerr; + + uint v = 0; + + for (int i = 0; i < length; i++) + { + char c = s[i]; + if (c >= '0' && c <= '9') + { + if (v < uint.max/10 || (v == uint.max/10 && c <= '5')) + v = v * 10 + (c - '0'); + else + goto Loverflow; + } + else + goto Lerr; + } + return v; + +Loverflow: + conv_overflow(s); + +Lerr: + conv_error(s); + return 0; +} + +/******************************************************* + * ditto + */ + +long toLong(char[] s) +{ + int length = s.length; + + if (!length) + goto Lerr; + + int sign = 0; + long v = 0; + + for (int i = 0; i < length; i++) + { + char c = s[i]; + if (c >= '0' && c <= '9') + { + if (v < long.max/10 || (v == long.max/10 && c + sign <= '7')) + v = v * 10 + (c - '0'); + else + goto Loverflow; + } + else if (c == '-' && i == 0) + { + sign = -1; + if (length == 1) + goto Lerr; + } + else if (c == '+' && i == 0) + { + if (length == 1) + goto Lerr; + } + else + goto Lerr; + } + if (sign == -1) + { + if (cast(ulong)v > 0x8000000000000000) + goto Loverflow; + v = -v; + } + else + { + if (cast(ulong)v > 0x7FFFFFFFFFFFFFFF) + goto Loverflow; + } + return v; + +Loverflow: + conv_overflow(s); + +Lerr: + conv_error(s); + return 0; +} + +/******************************************************* + * ditto + */ + +ulong toUlong(char[] s) +{ + int length = s.length; + + if (!length) + goto Lerr; + + ulong v = 0; + + for (int i = 0; i < length; i++) + { + char c = s[i]; + if (c >= '0' && c <= '9') + { + if (v < ulong.max/10 || (v == ulong.max/10 && c <= '5')) + v = v * 10 + (c - '0'); + else + goto Loverflow; + } + else + goto Lerr; + } + return v; + +Loverflow: + conv_overflow(s); + +Lerr: + conv_error(s); + return 0; +} + +/******************************************************* + * ditto + */ + +short toShort(char[] s) +{ + int v = toInt(s); + + if (v != cast(short)v) + goto Loverflow; + + return cast(short)v; + +Loverflow: + conv_overflow(s); + return 0; +} + +/******************************************************* + * ditto + */ + +ushort toUshort(char[] s) +{ + uint v = toUint(s); + + if (v != cast(ushort)v) + goto Loverflow; + + return cast(ushort)v; + +Loverflow: + conv_overflow(s); + return 0; +} + +/******************************************************* + * ditto + */ + +byte toByte(char[] s) +{ + int v = toInt(s); + + if (v != cast(byte)v) + goto Loverflow; + + return cast(byte)v; + +Loverflow: + conv_overflow(s); + return 0; +} + +/******************************************************* + * ditto + */ + +ubyte toUbyte(char[] s) +{ + uint v = toUint(s); + + if (v != cast(ubyte)v) + goto Loverflow; + + return cast(ubyte)v; + +Loverflow: + conv_overflow(s); + return 0; +} + +/******************************************************* + * ditto + */ + +float toFloat(in char[] s) +{ + float f; + char* endptr; + char* sz; + + //writefln("toFloat('%s')", s); + sz = toStringz(s); + if (tango.stdc.ctype.isspace(*sz)) + goto Lerr; + + // BUG: should set __locale_decpoint to "." for DMC + + setErrno(0); + f = strtof(sz, &endptr); + if (getErrno() == ERANGE) + goto Lerr; + if (endptr && (endptr == sz || *endptr != 0)) + goto Lerr; + + return f; + + Lerr: + conv_error(s ~ " not representable as a float"); + assert(0); +} + +/******************************************************* + * ditto + */ + +double toDouble(in char[] s) +{ + double f; + char* endptr; + char* sz; + + //writefln("toDouble('%s')", s); + sz = toStringz(s); + if (tango.stdc.ctype.isspace(*sz)) + goto Lerr; + + // BUG: should set __locale_decpoint to "." for DMC + + setErrno(0); + f = strtod(sz, &endptr); + if (getErrno() == ERANGE) + goto Lerr; + if (endptr && (endptr == sz || *endptr != 0)) + goto Lerr; + + return f; + + Lerr: + conv_error(s ~ " not representable as a double"); + assert(0); +} + +/******************************************************* + * ditto + */ +real toReal(in char[] s) +{ + real f; + char* endptr; + char* sz; + + //writefln("toReal('%s')", s); + sz = toStringz(s); + if (tango.stdc.ctype.isspace(*sz)) + goto Lerr; + + // BUG: should set __locale_decpoint to "." for DMC + + setErrno(0); + f = strtold(sz, &endptr); + if (getErrno() == ERANGE) + goto Lerr; + if (endptr && (endptr == sz || *endptr != 0)) + goto Lerr; + + return f; + + Lerr: + conv_error(s ~ " not representable as a real"); + assert(0); +} +