annotate 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
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
288
f9559a957be9 new signals and slots implementation
eldar
parents:
diff changeset
1 /**
f9559a957be9 new signals and slots implementation
eldar
parents:
diff changeset
2 * CTFE Integer routines.
f9559a957be9 new signals and slots implementation
eldar
parents:
diff changeset
3 *
f9559a957be9 new signals and slots implementation
eldar
parents:
diff changeset
4 * Authors: Daniel Keep <daniel.keep@gmail.com>
f9559a957be9 new signals and slots implementation
eldar
parents:
diff changeset
5 * Copyright: See LICENSE.
f9559a957be9 new signals and slots implementation
eldar
parents:
diff changeset
6 */
f9559a957be9 new signals and slots implementation
eldar
parents:
diff changeset
7 module qt.qtd.ctfe.Integer;
f9559a957be9 new signals and slots implementation
eldar
parents:
diff changeset
8
f9559a957be9 new signals and slots implementation
eldar
parents:
diff changeset
9 /**
f9559a957be9 new signals and slots implementation
eldar
parents:
diff changeset
10 * Formats an integer as a string. You can optionally specify a different
f9559a957be9 new signals and slots implementation
eldar
parents:
diff changeset
11 * base; any value between 2 and 16 inclusive is supported.
f9559a957be9 new signals and slots implementation
eldar
parents:
diff changeset
12 *
f9559a957be9 new signals and slots implementation
eldar
parents:
diff changeset
13 * Params:
f9559a957be9 new signals and slots implementation
eldar
parents:
diff changeset
14 * v = value to format.
f9559a957be9 new signals and slots implementation
eldar
parents:
diff changeset
15 * base = base to use; defaults to 10.
f9559a957be9 new signals and slots implementation
eldar
parents:
diff changeset
16 * Returns:
f9559a957be9 new signals and slots implementation
eldar
parents:
diff changeset
17 * integer formatted as a string.
f9559a957be9 new signals and slots implementation
eldar
parents:
diff changeset
18 */
f9559a957be9 new signals and slots implementation
eldar
parents:
diff changeset
19
f9559a957be9 new signals and slots implementation
eldar
parents:
diff changeset
20 string format_ctfe(intT)(intT v, int base = 10)
f9559a957be9 new signals and slots implementation
eldar
parents:
diff changeset
21 {
f9559a957be9 new signals and slots implementation
eldar
parents:
diff changeset
22 static if( !is( intT == ulong ) )
f9559a957be9 new signals and slots implementation
eldar
parents:
diff changeset
23 {
f9559a957be9 new signals and slots implementation
eldar
parents:
diff changeset
24 return (v < 0)
f9559a957be9 new signals and slots implementation
eldar
parents:
diff changeset
25 ? "-" ~ format_ctfe(cast(ulong) -v, base)
f9559a957be9 new signals and slots implementation
eldar
parents:
diff changeset
26 : format_ctfe(cast(ulong) v, base);
f9559a957be9 new signals and slots implementation
eldar
parents:
diff changeset
27 }
f9559a957be9 new signals and slots implementation
eldar
parents:
diff changeset
28 else
f9559a957be9 new signals and slots implementation
eldar
parents:
diff changeset
29 {
f9559a957be9 new signals and slots implementation
eldar
parents:
diff changeset
30 assert( 2 <= base && base <= 16,
f9559a957be9 new signals and slots implementation
eldar
parents:
diff changeset
31 "base must be between 2 and 16; got " ~ format_ctfe(base, 10) );
f9559a957be9 new signals and slots implementation
eldar
parents:
diff changeset
32
f9559a957be9 new signals and slots implementation
eldar
parents:
diff changeset
33 string r = "";
f9559a957be9 new signals and slots implementation
eldar
parents:
diff changeset
34 do
f9559a957be9 new signals and slots implementation
eldar
parents:
diff changeset
35 {
f9559a957be9 new signals and slots implementation
eldar
parents:
diff changeset
36 r = INT_CHARS[cast(size_t)(v % base)] ~ r;
f9559a957be9 new signals and slots implementation
eldar
parents:
diff changeset
37 v /= base;
f9559a957be9 new signals and slots implementation
eldar
parents:
diff changeset
38 }
f9559a957be9 new signals and slots implementation
eldar
parents:
diff changeset
39 while( v > 0 );
f9559a957be9 new signals and slots implementation
eldar
parents:
diff changeset
40 return r;
f9559a957be9 new signals and slots implementation
eldar
parents:
diff changeset
41 }
f9559a957be9 new signals and slots implementation
eldar
parents:
diff changeset
42 }
f9559a957be9 new signals and slots implementation
eldar
parents:
diff changeset
43
f9559a957be9 new signals and slots implementation
eldar
parents:
diff changeset
44 /**
f9559a957be9 new signals and slots implementation
eldar
parents:
diff changeset
45 * Parses an integer value from a string. You can optionally specify a
f9559a957be9 new signals and slots implementation
eldar
parents:
diff changeset
46 * different base; any value between 2 and 16 inclusive is supported.
f9559a957be9 new signals and slots implementation
eldar
parents:
diff changeset
47 *
f9559a957be9 new signals and slots implementation
eldar
parents:
diff changeset
48 * Note that this does not fail if it cannot consume the entire string;
f9559a957be9 new signals and slots implementation
eldar
parents:
diff changeset
49 * use returnUsed to determine the number of characters consumed.
f9559a957be9 new signals and slots implementation
eldar
parents:
diff changeset
50 *
f9559a957be9 new signals and slots implementation
eldar
parents:
diff changeset
51 * Params:
f9559a957be9 new signals and slots implementation
eldar
parents:
diff changeset
52 * str = string to parse.
f9559a957be9 new signals and slots implementation
eldar
parents:
diff changeset
53 * returnUsed = defaults to false; if set to true, returns the number of
f9559a957be9 new signals and slots implementation
eldar
parents:
diff changeset
54 * characters consumed from the string instead of the
f9559a957be9 new signals and slots implementation
eldar
parents:
diff changeset
55 * parsed value.
f9559a957be9 new signals and slots implementation
eldar
parents:
diff changeset
56 * base = base to use; defaults to 10.
f9559a957be9 new signals and slots implementation
eldar
parents:
diff changeset
57 * Returns:
f9559a957be9 new signals and slots implementation
eldar
parents:
diff changeset
58 * either the parsed integer or the number of characters consumed,
f9559a957be9 new signals and slots implementation
eldar
parents:
diff changeset
59 * depending on the value of returnUsed.
f9559a957be9 new signals and slots implementation
eldar
parents:
diff changeset
60 */
f9559a957be9 new signals and slots implementation
eldar
parents:
diff changeset
61
f9559a957be9 new signals and slots implementation
eldar
parents:
diff changeset
62 intT parse_ctfe(intT)(string str, bool returnUsed = false, int base = 10)
f9559a957be9 new signals and slots implementation
eldar
parents:
diff changeset
63 {
f9559a957be9 new signals and slots implementation
eldar
parents:
diff changeset
64 auto origStr = str;
f9559a957be9 new signals and slots implementation
eldar
parents:
diff changeset
65
f9559a957be9 new signals and slots implementation
eldar
parents:
diff changeset
66 assert( 2 <= base && base <= 16,
f9559a957be9 new signals and slots implementation
eldar
parents:
diff changeset
67 "base must be between 2 and 16; got " ~ format_ctfe(base, 10) );
f9559a957be9 new signals and slots implementation
eldar
parents:
diff changeset
68
f9559a957be9 new signals and slots implementation
eldar
parents:
diff changeset
69 bool neg = false;
f9559a957be9 new signals and slots implementation
eldar
parents:
diff changeset
70 if( str.length > 0 && str[0] == '-' )
f9559a957be9 new signals and slots implementation
eldar
parents:
diff changeset
71 {
f9559a957be9 new signals and slots implementation
eldar
parents:
diff changeset
72 neg = true;
f9559a957be9 new signals and slots implementation
eldar
parents:
diff changeset
73 str = str[1..$];
f9559a957be9 new signals and slots implementation
eldar
parents:
diff changeset
74 }
f9559a957be9 new signals and slots implementation
eldar
parents:
diff changeset
75
f9559a957be9 new signals and slots implementation
eldar
parents:
diff changeset
76 if( intT.min == 0 && neg )
f9559a957be9 new signals and slots implementation
eldar
parents:
diff changeset
77 assert(false, "underwhile while parsing \"" ~ origStr
f9559a957be9 new signals and slots implementation
eldar
parents:
diff changeset
78 ~ "\" as a " ~ intT.stringof ~ ": cannot represent negative "
f9559a957be9 new signals and slots implementation
eldar
parents:
diff changeset
79 ~ "values");
f9559a957be9 new signals and slots implementation
eldar
parents:
diff changeset
80
f9559a957be9 new signals and slots implementation
eldar
parents:
diff changeset
81 intT r = 0;
f9559a957be9 new signals and slots implementation
eldar
parents:
diff changeset
82 size_t used = 0;
f9559a957be9 new signals and slots implementation
eldar
parents:
diff changeset
83
f9559a957be9 new signals and slots implementation
eldar
parents:
diff changeset
84 foreach( c ; str )
f9559a957be9 new signals and slots implementation
eldar
parents:
diff changeset
85 {
f9559a957be9 new signals and slots implementation
eldar
parents:
diff changeset
86 int cv = -1;
f9559a957be9 new signals and slots implementation
eldar
parents:
diff changeset
87
f9559a957be9 new signals and slots implementation
eldar
parents:
diff changeset
88 if( '0' <= c && c <= '9' )
f9559a957be9 new signals and slots implementation
eldar
parents:
diff changeset
89 cv = c - '0';
f9559a957be9 new signals and slots implementation
eldar
parents:
diff changeset
90
f9559a957be9 new signals and slots implementation
eldar
parents:
diff changeset
91 else if( 'A' <= c && c <= 'Z' )
f9559a957be9 new signals and slots implementation
eldar
parents:
diff changeset
92 cv = 10 + c - 'A';
f9559a957be9 new signals and slots implementation
eldar
parents:
diff changeset
93
f9559a957be9 new signals and slots implementation
eldar
parents:
diff changeset
94 else if( 'a' <= c && c <= 'z' )
f9559a957be9 new signals and slots implementation
eldar
parents:
diff changeset
95 cv = 10 + c - 'a';
f9559a957be9 new signals and slots implementation
eldar
parents:
diff changeset
96
f9559a957be9 new signals and slots implementation
eldar
parents:
diff changeset
97 if( cv >= base || cv < 0 )
f9559a957be9 new signals and slots implementation
eldar
parents:
diff changeset
98 break;
f9559a957be9 new signals and slots implementation
eldar
parents:
diff changeset
99
f9559a957be9 new signals and slots implementation
eldar
parents:
diff changeset
100 auto oldR = r;
f9559a957be9 new signals and slots implementation
eldar
parents:
diff changeset
101 r = r*base + cast(intT) cv;
f9559a957be9 new signals and slots implementation
eldar
parents:
diff changeset
102 ++ used;
f9559a957be9 new signals and slots implementation
eldar
parents:
diff changeset
103
f9559a957be9 new signals and slots implementation
eldar
parents:
diff changeset
104 if( r < oldR )
f9559a957be9 new signals and slots implementation
eldar
parents:
diff changeset
105 assert(false, "overflow while parsing \"" ~ origStr
f9559a957be9 new signals and slots implementation
eldar
parents:
diff changeset
106 ~ "\" as a " ~ intT.stringof);
f9559a957be9 new signals and slots implementation
eldar
parents:
diff changeset
107 }
f9559a957be9 new signals and slots implementation
eldar
parents:
diff changeset
108
f9559a957be9 new signals and slots implementation
eldar
parents:
diff changeset
109 if( neg )
f9559a957be9 new signals and slots implementation
eldar
parents:
diff changeset
110 {
f9559a957be9 new signals and slots implementation
eldar
parents:
diff changeset
111 r = -r;
f9559a957be9 new signals and slots implementation
eldar
parents:
diff changeset
112 ++used;
f9559a957be9 new signals and slots implementation
eldar
parents:
diff changeset
113 }
f9559a957be9 new signals and slots implementation
eldar
parents:
diff changeset
114
f9559a957be9 new signals and slots implementation
eldar
parents:
diff changeset
115 if( returnUsed )
f9559a957be9 new signals and slots implementation
eldar
parents:
diff changeset
116 {
f9559a957be9 new signals and slots implementation
eldar
parents:
diff changeset
117 assert( used < intT.max, "overflow attempting to return "
f9559a957be9 new signals and slots implementation
eldar
parents:
diff changeset
118 ~ "number of characters consumed in a " ~ intT.stringof );
f9559a957be9 new signals and slots implementation
eldar
parents:
diff changeset
119
f9559a957be9 new signals and slots implementation
eldar
parents:
diff changeset
120 return used;
f9559a957be9 new signals and slots implementation
eldar
parents:
diff changeset
121 }
f9559a957be9 new signals and slots implementation
eldar
parents:
diff changeset
122 else
f9559a957be9 new signals and slots implementation
eldar
parents:
diff changeset
123 return r;
f9559a957be9 new signals and slots implementation
eldar
parents:
diff changeset
124 }
f9559a957be9 new signals and slots implementation
eldar
parents:
diff changeset
125
f9559a957be9 new signals and slots implementation
eldar
parents:
diff changeset
126 /**
f9559a957be9 new signals and slots implementation
eldar
parents:
diff changeset
127 * Like parse_ctfe, except it will raise an error if the provided string
f9559a957be9 new signals and slots implementation
eldar
parents:
diff changeset
128 * cannot be parsed in its entirety.
f9559a957be9 new signals and slots implementation
eldar
parents:
diff changeset
129 *
f9559a957be9 new signals and slots implementation
eldar
parents:
diff changeset
130 * Params:
f9559a957be9 new signals and slots implementation
eldar
parents:
diff changeset
131 * str = the string to parse.
f9559a957be9 new signals and slots implementation
eldar
parents:
diff changeset
132 * base = base to use; defaults to 10.
f9559a957be9 new signals and slots implementation
eldar
parents:
diff changeset
133 * Returns:
f9559a957be9 new signals and slots implementation
eldar
parents:
diff changeset
134 * the parsed integer.
f9559a957be9 new signals and slots implementation
eldar
parents:
diff changeset
135 */
f9559a957be9 new signals and slots implementation
eldar
parents:
diff changeset
136
f9559a957be9 new signals and slots implementation
eldar
parents:
diff changeset
137 intT parseAll_ctfe(intT)(string str, int base = 10)
f9559a957be9 new signals and slots implementation
eldar
parents:
diff changeset
138 {
f9559a957be9 new signals and slots implementation
eldar
parents:
diff changeset
139 auto used = parse_ctfe!(intT)(str, true, base);
f9559a957be9 new signals and slots implementation
eldar
parents:
diff changeset
140 assert( used == str.length, "could not parse entire string \"" ~ str
f9559a957be9 new signals and slots implementation
eldar
parents:
diff changeset
141 ~ "\"" );
f9559a957be9 new signals and slots implementation
eldar
parents:
diff changeset
142 return parse_ctfe!(int)(str, false, base);
f9559a957be9 new signals and slots implementation
eldar
parents:
diff changeset
143 }
f9559a957be9 new signals and slots implementation
eldar
parents:
diff changeset
144
f9559a957be9 new signals and slots implementation
eldar
parents:
diff changeset
145 private
f9559a957be9 new signals and slots implementation
eldar
parents:
diff changeset
146 {
f9559a957be9 new signals and slots implementation
eldar
parents:
diff changeset
147 const INT_CHARS = "0123456789abcdef";
f9559a957be9 new signals and slots implementation
eldar
parents:
diff changeset
148 }
f9559a957be9 new signals and slots implementation
eldar
parents:
diff changeset
149
f9559a957be9 new signals and slots implementation
eldar
parents:
diff changeset
150 version( Unittest )
f9559a957be9 new signals and slots implementation
eldar
parents:
diff changeset
151 {
f9559a957be9 new signals and slots implementation
eldar
parents:
diff changeset
152 static assert( format_ctfe(0) == "0", "got: " ~ format_ctfe(0) );
f9559a957be9 new signals and slots implementation
eldar
parents:
diff changeset
153 static assert( format_ctfe(1) == "1" );
f9559a957be9 new signals and slots implementation
eldar
parents:
diff changeset
154 static assert( format_ctfe(-1) == "-1" );
f9559a957be9 new signals and slots implementation
eldar
parents:
diff changeset
155 static assert( format_ctfe(42) == "42" );
f9559a957be9 new signals and slots implementation
eldar
parents:
diff changeset
156 static assert( format_ctfe(0xf00, 16) == "f00" );
f9559a957be9 new signals and slots implementation
eldar
parents:
diff changeset
157 static assert( format_ctfe(0123, 8) == "123" );
f9559a957be9 new signals and slots implementation
eldar
parents:
diff changeset
158
f9559a957be9 new signals and slots implementation
eldar
parents:
diff changeset
159 static assert( parse_ctfe!(long)("0") == 0 );
f9559a957be9 new signals and slots implementation
eldar
parents:
diff changeset
160 static assert( parse_ctfe!(long)("1") == 1 );
f9559a957be9 new signals and slots implementation
eldar
parents:
diff changeset
161 static assert( parse_ctfe!(long)("-1") == -1 );
f9559a957be9 new signals and slots implementation
eldar
parents:
diff changeset
162 static assert( parse_ctfe!(long)("42") == 42 );
f9559a957be9 new signals and slots implementation
eldar
parents:
diff changeset
163 static assert( parse_ctfe!(long)("f00", false, 16) == 0xf00 );
f9559a957be9 new signals and slots implementation
eldar
parents:
diff changeset
164 static assert( parse_ctfe!(long)("123", false, 8) == 0123 );
f9559a957be9 new signals and slots implementation
eldar
parents:
diff changeset
165 static assert( parse_ctfe!(long)("123ax", true) == 3 );
f9559a957be9 new signals and slots implementation
eldar
parents:
diff changeset
166 static assert( parse_ctfe!(long)("123ax", true, 16) == 4 );
f9559a957be9 new signals and slots implementation
eldar
parents:
diff changeset
167
f9559a957be9 new signals and slots implementation
eldar
parents:
diff changeset
168 static assert( parseAll_ctfe!(long)("123") == 123 );
f9559a957be9 new signals and slots implementation
eldar
parents:
diff changeset
169 }