Mercurial > projects > dang
view basic/conv.d @ 162:0f38f1a0f06f
Fixed symbol for a functions members.
author | Anders Johnsen <skabet@gmail.com> |
---|---|
date | Tue, 22 Jul 2008 16:22:58 +0200 |
parents | d03b011c50e9 |
children |
line wrap: on
line source
// 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 * <tt>atoi()</tt> and <tt>atol()</tt> by * checking for overflow and not allowing whitespace. * * For conversion to signed types, the grammar recognized is: * <pre> $(I Integer): $(I Sign UnsignedInteger) $(I UnsignedInteger) $(I Sign): $(B +) $(B -) * </pre> * For conversion to signed types, the grammar recognized is: * <pre> $(I UnsignedInteger): $(I DecimalDigit) $(I DecimalDigit) $(I UnsignedInteger) * </pre> * 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); }