Mercurial > projects > qtd
diff qt/qtd/ctfe/Integer.d @ 288:f9559a957be9 signals
new signals and slots implementation
author | eldar |
---|---|
date | Sun, 08 Nov 2009 19:28:01 +0000 |
parents | |
children |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/qt/qtd/ctfe/Integer.d Sun Nov 08 19:28:01 2009 +0000 @@ -0,0 +1,169 @@ +/** + * CTFE Integer routines. + * + * Authors: Daniel Keep <daniel.keep@gmail.com> + * Copyright: See LICENSE. + */ +module qt.qtd.ctfe.Integer; + +/** + * Formats an integer as a string. You can optionally specify a different + * base; any value between 2 and 16 inclusive is supported. + * + * Params: + * v = value to format. + * base = base to use; defaults to 10. + * Returns: + * integer formatted as a string. + */ + +string format_ctfe(intT)(intT v, int base = 10) +{ + static if( !is( intT == ulong ) ) + { + return (v < 0) + ? "-" ~ format_ctfe(cast(ulong) -v, base) + : format_ctfe(cast(ulong) v, base); + } + else + { + assert( 2 <= base && base <= 16, + "base must be between 2 and 16; got " ~ format_ctfe(base, 10) ); + + string r = ""; + do + { + r = INT_CHARS[cast(size_t)(v % base)] ~ r; + v /= base; + } + while( v > 0 ); + return r; + } +} + +/** + * Parses an integer value from a string. You can optionally specify a + * different base; any value between 2 and 16 inclusive is supported. + * + * Note that this does not fail if it cannot consume the entire string; + * use returnUsed to determine the number of characters consumed. + * + * Params: + * str = string to parse. + * returnUsed = defaults to false; if set to true, returns the number of + * characters consumed from the string instead of the + * parsed value. + * base = base to use; defaults to 10. + * Returns: + * either the parsed integer or the number of characters consumed, + * depending on the value of returnUsed. + */ + +intT parse_ctfe(intT)(string str, bool returnUsed = false, int base = 10) +{ + auto origStr = str; + + assert( 2 <= base && base <= 16, + "base must be between 2 and 16; got " ~ format_ctfe(base, 10) ); + + bool neg = false; + if( str.length > 0 && str[0] == '-' ) + { + neg = true; + str = str[1..$]; + } + + if( intT.min == 0 && neg ) + assert(false, "underwhile while parsing \"" ~ origStr + ~ "\" as a " ~ intT.stringof ~ ": cannot represent negative " + ~ "values"); + + intT r = 0; + size_t used = 0; + + foreach( c ; str ) + { + int cv = -1; + + if( '0' <= c && c <= '9' ) + cv = c - '0'; + + else if( 'A' <= c && c <= 'Z' ) + cv = 10 + c - 'A'; + + else if( 'a' <= c && c <= 'z' ) + cv = 10 + c - 'a'; + + if( cv >= base || cv < 0 ) + break; + + auto oldR = r; + r = r*base + cast(intT) cv; + ++ used; + + if( r < oldR ) + assert(false, "overflow while parsing \"" ~ origStr + ~ "\" as a " ~ intT.stringof); + } + + if( neg ) + { + r = -r; + ++used; + } + + if( returnUsed ) + { + assert( used < intT.max, "overflow attempting to return " + ~ "number of characters consumed in a " ~ intT.stringof ); + + return used; + } + else + return r; +} + +/** + * Like parse_ctfe, except it will raise an error if the provided string + * cannot be parsed in its entirety. + * + * Params: + * str = the string to parse. + * base = base to use; defaults to 10. + * Returns: + * the parsed integer. + */ + +intT parseAll_ctfe(intT)(string str, int base = 10) +{ + auto used = parse_ctfe!(intT)(str, true, base); + assert( used == str.length, "could not parse entire string \"" ~ str + ~ "\"" ); + return parse_ctfe!(int)(str, false, base); +} + +private +{ + const INT_CHARS = "0123456789abcdef"; +} + +version( Unittest ) +{ + static assert( format_ctfe(0) == "0", "got: " ~ format_ctfe(0) ); + static assert( format_ctfe(1) == "1" ); + static assert( format_ctfe(-1) == "-1" ); + static assert( format_ctfe(42) == "42" ); + static assert( format_ctfe(0xf00, 16) == "f00" ); + static assert( format_ctfe(0123, 8) == "123" ); + + static assert( parse_ctfe!(long)("0") == 0 ); + static assert( parse_ctfe!(long)("1") == 1 ); + static assert( parse_ctfe!(long)("-1") == -1 ); + static assert( parse_ctfe!(long)("42") == 42 ); + static assert( parse_ctfe!(long)("f00", false, 16) == 0xf00 ); + static assert( parse_ctfe!(long)("123", false, 8) == 0123 ); + static assert( parse_ctfe!(long)("123ax", true) == 3 ); + static assert( parse_ctfe!(long)("123ax", true, 16) == 4 ); + + static assert( parseAll_ctfe!(long)("123") == 123 ); +}