Make intToString -> readString more generic
Make readString work with any char range and unsigned integral type.
This commit is contained in:
parent
c663703221
commit
7561b964d3
@ -20,6 +20,8 @@ import tanya.memory;
|
|||||||
import tanya.memory.op;
|
import tanya.memory.op;
|
||||||
import tanya.meta.trait;
|
import tanya.meta.trait;
|
||||||
import tanya.meta.transform;
|
import tanya.meta.transform;
|
||||||
|
import tanya.range.array;
|
||||||
|
import tanya.range.primitive;
|
||||||
|
|
||||||
version (unittest)
|
version (unittest)
|
||||||
{
|
{
|
||||||
@ -264,30 +266,102 @@ final class ConvException : Exception
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
package bool stringToInt(R)(R range, ref ushort n)
|
package bool readString(T, R)(ref R range, out T n)
|
||||||
|
if (isForwardRange!R && isSomeChar!(ElementType!R)
|
||||||
|
&& isIntegral!T && isUnsigned!T)
|
||||||
{
|
{
|
||||||
import tanya.encoding.ascii;
|
import tanya.encoding.ascii : isDigit;
|
||||||
import tanya.range.array;
|
|
||||||
|
|
||||||
size_t i = 1;
|
enum T boundary = T.max / 10;
|
||||||
uint lPort;
|
if (range.empty)
|
||||||
|
|
||||||
for (; !range.empty && range.front.isDigit() && i <= 6; ++i, range.popFront())
|
|
||||||
{
|
|
||||||
lPort = lPort * 10 + (range.front - '0');
|
|
||||||
}
|
|
||||||
if (i != 1 && (range.empty || range.front == '/'))
|
|
||||||
{
|
|
||||||
if (lPort > ushort.max)
|
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
n = cast(ushort) lPort;
|
|
||||||
|
while (n <= boundary)
|
||||||
|
{
|
||||||
|
if (!range.front.isDigit)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
n = cast(T) (n * 10 + (range.front - '0'));
|
||||||
|
range.popFront();
|
||||||
|
|
||||||
|
if (range.empty)
|
||||||
|
{
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
if (range.length > 1)
|
||||||
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int digit = range.front - '0';
|
||||||
|
if (n > cast(T) ((T.max - digit) / 10))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
n = cast(T) (n * 10 + digit);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// reads ubyte.max
|
||||||
|
@nogc nothrow pure @safe unittest
|
||||||
|
{
|
||||||
|
ubyte n;
|
||||||
|
string number = "255";
|
||||||
|
assert(readString(number, n));
|
||||||
|
assert(n == 255);
|
||||||
|
assert(number.empty);
|
||||||
|
}
|
||||||
|
|
||||||
|
// detects integer overflow
|
||||||
|
@nogc nothrow pure @safe unittest
|
||||||
|
{
|
||||||
|
ubyte n;
|
||||||
|
string number = "500";
|
||||||
|
assert(!readString(number, n));
|
||||||
|
assert(number.front == '0');
|
||||||
|
assert(number.length == 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// stops on a non-digit
|
||||||
|
@nogc nothrow pure @safe unittest
|
||||||
|
{
|
||||||
|
ubyte n;
|
||||||
|
string number = "10-";
|
||||||
|
assert(!readString(number, n));
|
||||||
|
assert(number.front == '-');
|
||||||
|
}
|
||||||
|
|
||||||
|
// returns false if the number string is empty
|
||||||
|
@nogc nothrow pure @safe unittest
|
||||||
|
{
|
||||||
|
ubyte n;
|
||||||
|
string number = "";
|
||||||
|
assert(!readString(number, n));
|
||||||
|
assert(number.empty);
|
||||||
|
}
|
||||||
|
|
||||||
|
@nogc nothrow pure @safe unittest
|
||||||
|
{
|
||||||
|
ubyte n;
|
||||||
|
string number = "29";
|
||||||
|
assert(readString(number, n));
|
||||||
|
assert(n == 29);
|
||||||
|
assert(number.empty);
|
||||||
|
}
|
||||||
|
|
||||||
|
@nogc nothrow pure @safe unittest
|
||||||
|
{
|
||||||
|
ubyte n;
|
||||||
|
string number = "25467";
|
||||||
|
assert(!readString(number, n));
|
||||||
|
assert(number.front == '6');
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* If the source type $(D_PARAM From) and the target type $(D_PARAM To) are
|
* If the source type $(D_PARAM From) and the target type $(D_PARAM To) are
|
||||||
* equal, does nothing. If $(D_PARAM From) can be implicitly converted to
|
* equal, does nothing. If $(D_PARAM From) can be implicitly converted to
|
||||||
|
@ -305,7 +305,8 @@ struct URL
|
|||||||
*/
|
*/
|
||||||
private bool parsePort(const(char)[] port) @nogc nothrow pure @safe
|
private bool parsePort(const(char)[] port) @nogc nothrow pure @safe
|
||||||
{
|
{
|
||||||
return stringToInt(port[1 .. $], this.port);
|
auto portNumber = port[1 .. $];
|
||||||
|
return readString(portNumber, this.port) || portNumber[0] == '/';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user