summaryrefslogtreecommitdiff
path: root/source
diff options
context:
space:
mode:
authorEugen Wissner <belka@caraus.de>2017-11-27 15:10:17 +0100
committerEugen Wissner <belka@caraus.de>2017-11-27 15:10:17 +0100
commit3a24e9e462b7319419d06610a08e15db2e8c9b98 (patch)
treea5672e441f3fc07a322c68f1609fae4bafd43697 /source
parentf334e6a1a0812714592157fe0dc2c60e81a94600 (diff)
downloadtanya-3a24e9e462b7319419d06610a08e15db2e8c9b98.tar.gz
Make pointer to string conversion safer
Diffstat (limited to 'source')
-rw-r--r--source/tanya/format/package.d254
1 files changed, 96 insertions, 158 deletions
diff --git a/source/tanya/format/package.d b/source/tanya/format/package.d
index 6d37f47..44c079c 100644
--- a/source/tanya/format/package.d
+++ b/source/tanya/format/package.d
@@ -14,10 +14,12 @@
*/
module tanya.format;
-import core.stdc.stdarg;
+import tanya.container.string;
+import tanya.encoding.ascii;
public import tanya.format.conv;
import tanya.memory.op;
import tanya.meta.metafunction;
+import tanya.meta.trait;
import tanya.range.array;
private enum special = 0x7000;
@@ -106,8 +108,6 @@ private static const double[13] negativeTopError = [
private enum ulong tenTo19th = 1000000000000000000UL;
-package static const string hex = "0123456789abcdefxp";
-
private void ddmultlo(A, B, C, D, E, F)(ref A oh,
ref B ol,
ref C xh,
@@ -135,7 +135,7 @@ private void ddrenorm(T, U)(ref T oh, ref U ol)
private void raise2Power10(double* ohi,
double* olo,
double d,
- int power) pure nothrow @nogc
+ int power) @nogc nothrow pure
{
double ph, pl;
if ((power >= 0) && (power <= 22))
@@ -232,7 +232,7 @@ private int real2String(ref const(char)* start,
char* out_,
out int decimalPos,
double value,
- uint fracDigits) pure nothrow @nogc
+ uint fracDigits) @nogc nothrow pure
{
long bits = 0;
int e, tens;
@@ -426,7 +426,7 @@ private int real2String(ref const(char)* start,
}
private void leadSign(bool negative, ref char[8] sign)
-pure nothrow @nogc
+@nogc nothrow pure
{
sign[0] = 0;
if (negative)
@@ -448,7 +448,7 @@ private void copyFp(T, U)(ref T dest, ref U src)
private void ddmulthi(ref double oh,
ref double ol,
ref double xh,
- const ref double yh) pure nothrow @nogc
+ const ref double yh) @nogc nothrow pure
{
double ahi, bhi;
long bt;
@@ -464,11 +464,10 @@ private void ddmulthi(ref double oh,
ol = ((ahi * bhi - oh) + ahi * blo + alo * bhi) + alo * blo;
}
-private char[] vsprintf(string fmt, Args...)(return char[] buf, va_list va)
-pure nothrow @nogc
+package(tanya) String format(string fmt, Args...)(char[] buf, Args args)
{
+ String result;
char* bf = buf.ptr;
- int tlen;
// Ok, we have a percent, read the modifiers first.
int precision = -1;
@@ -488,65 +487,24 @@ pure nothrow @nogc
int decimalPos;
const(char)* sn;
- static if (fmt[0] == 's') // String
+ static if (isSomeString!(Args[0])) // String
{
- // Get the string.
- s = va_arg!(char[])(va).ptr;
- if (s is null)
- {
- s = cast(char*) "null";
- }
- // Get the length.
- sn = s;
- for (;;)
+ if (args[0] is null)
{
- if (((cast(size_t) sn) & 3) == 0)
- {
- break;
- }
- lchk:
- if (sn[0] == 0)
- {
- goto ld;
- }
- ++sn;
+ result.insertBack("null");
}
- n = 0xffffffff;
- while (n)
+ else
{
- uint v = *cast(uint*) sn;
- if ((v - 0x01010101) & (~v) & 0x80808080UL)
- {
- goto lchk;
- }
- sn += 4;
- --n;
+ result.insertBack(args[0]);
}
- goto lchk;
-
- ld:
- l = cast(uint) (sn - s);
-
- lead[0] = 0;
- tail[0] = 0;
- precision = 0;
- decimalPos = 0;
- // Copy the string in.
}
- else static if (fmt[0] == 'c') // Char
+ else static if (isSomeChar!(Args[0])) // Char
{
- // Get the character.
- s = num.ptr + num.length - 1;
- *s = cast(char) va_arg!int(va);
- l = 1;
- lead[0] = 0;
- tail[0] = 0;
- precision = 0;
- decimalPos = 0;
+ result.insertBack(args[0]);
}
- else static if (fmt[0] == 'g') // Float
+ else static if (isFloatingPoint!(Args[0])) // Float
{
- fv = va_arg!double(va);
+ fv = args[0];
if (precision == -1)
{
precision = 6;
@@ -642,7 +600,7 @@ pure nothrow @nogc
tz = precision - (l - 1);
precision = 0;
// Dump the exponent.
- tail[1] = hex[0xe];
+ tail[1] = 'e';
decimalPos -= 1;
if (decimalPos < 0)
{
@@ -808,65 +766,49 @@ pure nothrow @nogc
l = cast(uint) (s - (num.ptr + 64));
s = num.ptr + 64;
}
- else static if (fmt[0] == 'p') // Pointer
+ else static if (isPointer!(Args[0])) // Pointer
{
- l = (4 << 4) | (4 << 8);
- lead[0] = 2;
- lead[1] = '0';
- lead[2] = 'x';
-
// Get the number.
- static if (size_t.sizeof == 8)
- {
- n64 = va_arg!ulong(va);
- }
- else
- {
- n64 = va_arg!uint(va);
- }
+ n64 = cast(size_t) args[0];
+ size_t position = num.length;
- s = num.ptr + num.length;
- decimalPos = 0;
- // Clear tail, and clear leading if value is zero.
- tail[0] = 0;
- if (n64 == 0)
- {
- lead[0] = 0;
- }
- // Convert to string.
- for (;;)
+ do // Write at least "0" if the pointer is null.
{
- *--s = hex[cast(size_t) (n64 & ((1 << (l >> 8)) - 1))];
- n64 >>= l >> 8;
- if (n64 == 0)
- {
- break;
- }
+ num[--position] = lowerHexDigits[cast(size_t) (n64 & 15)];
+ n64 >>= 4;
}
- // Get the length that we copied.
- l = cast(uint)((num.ptr + num.length) - s);
+ while (n64 != 0);
+
+ result.insertBack("0x");
+ result.insertBack(num[position .. $]);
}
- else static if (fmt[0] == 'u' || fmt[0] == 'i' || fmt[0] == 'l') // Integer
+ else static if (isIntegral!(Args[0])) // Integer
{
// Get the integer and abs it.
- if (fmt[0] == 'l')
+ static if (Args[0].sizeof == 8)
{
- long i64 = va_arg!long(va);
- n64 = cast(ulong) i64;
- if ((fmt[0] != 'u') && (i64 < 0))
+ long k64 = args[0];
+ n64 = cast(ulong) k64;
+ static if (isSigned!(Args[0]))
{
- n64 = cast(ulong) -i64;
- negative = true;
+ if (k64 < 0)
+ {
+ n64 = cast(ulong) -k64;
+ negative = true;
+ }
}
}
else
{
- int i = va_arg!int(va);
- n64 = cast(uint) i;
- if ((fmt[0] != 'u') && (i < 0))
+ int k = args[0];
+ n64 = cast(uint) k;
+ static if (isSigned!(Args[0]))
{
- n64 = cast(uint) -i;
- negative = true;
+ if (k < 0)
+ {
+ n64 = cast(uint) -k;
+ negative = true;
+ }
}
}
@@ -934,6 +876,10 @@ pure nothrow @nogc
static assert(false);
}
+ if (result.length > 0)
+ {
+ return result;
+ }
scopy:
// Get fw=leading/trailing space, precision=leading zeros.
if (precision < cast(int) l)
@@ -1057,76 +1003,68 @@ scopy:
}
*bf = 0;
- return buf[0 .. tlen + cast(int) (bf - buf.ptr)];
-}
-
-char[] format(string fmt, Args...)(return char[] buf, ...)
-nothrow
-{
- va_list va;
- va_start(va, buf);
- auto result = vsprintf!(fmt, Args)(buf, va);
- va_end(va);
+ result = String(buf[0 .. cast(int) (bf - buf.ptr)]);
return result;
}
-nothrow unittest
+@nogc pure unittest
{
char[318] buffer;
// Modifiers.
- assert(format!("g", double)(buffer, 8.5) == "8.5");
- assert(format!("g", double)(buffer, 8.6) == "8.6");
- assert(format!("i", int)(buffer, 1000) == "1000");
- assert(format!("i", int)(buffer, 1) == "1");
- assert(format!("g", double)(buffer, 10.25) == "10.25");
- assert(format!("i", int)(buffer, 1) == "1");
- assert(format!("g", double)(buffer, 0.01) == "0.01");
+ assert(format!("{}")(buffer, 8.5) == "8.5");
+ assert(format!("{}")(buffer, 8.6) == "8.6");
+ assert(format!("{}")(buffer, 1000) == "1000");
+ assert(format!("{}")(buffer, 1) == "1");
+ assert(format!("{}")(buffer, 10.25) == "10.25");
+ assert(format!("{}")(buffer, 1) == "1");
+ assert(format!("{}")(buffer, 0.01) == "0.01");
// Integer size.
- assert(format!("i", short)(buffer, 10) == "10");
- assert(format!("l", long)(buffer, 10L) == "10");
+ assert(format!("{}")(buffer, 10) == "10");
+ assert(format!("{}")(buffer, 10L) == "10");
// String printing.
- assert(format!("s", string)(buffer, "Some weired string") == "Some weired string");
- assert(format!("s", string)(buffer, cast(string) null) == "null");
- assert(format!("c", char)(buffer, 'c') == "c");
+ assert(format!("{}")(buffer, "Some weired string") == "Some weired string");
+ assert(format!("{}")(buffer, cast(string) null) == "null");
+ assert(format!("{}")(buffer, 'c') == "c");
// Integer conversions.
- assert(format!("i", int)(buffer, 8) == "8");
- assert(format!("i", int)(buffer, 8) == "8");
- assert(format!("i", int)(buffer, -8) == "-8");
- assert(format!("l", long)(buffer, -8L) == "-8");
- assert(format!("u", uint)(buffer, 8) == "8");
- assert(format!("i", int)(buffer, 100000001) == "100000001");
- assert(format!("i", int)(buffer, 99999999L) == "99999999");
+ assert(format!("{}")(buffer, 8) == "8");
+ assert(format!("{}")(buffer, 8) == "8");
+ assert(format!("{}")(buffer, -8) == "-8");
+ assert(format!("{}")(buffer, -8L) == "-8");
+ assert(format!("{}")(buffer, 8) == "8");
+ assert(format!("{}")(buffer, 100000001) == "100000001");
+ assert(format!("{}")(buffer, 99999999L) == "99999999");
// Floating point conversions.
- assert(format!("g", double)(buffer, 0.1234) == "0.1234");
- assert(format!("g", double)(buffer, 0.3) == "0.3");
- assert(format!("g", double)(buffer, 0.333333333333) == "0.333333");
- assert(format!("g", double)(buffer, 38234.1234) == "38234.1");
- assert(format!("g", double)(buffer, -0.3) == "-0.3");
- assert(format!("g", double)(buffer, 0.000000000000000006) == "6e-18");
- assert(format!("g", double)(buffer, 0.0) == "0");
- assert(format!("g", double)(buffer, double.init) == "NaN");
- assert(format!("g", double)(buffer, -double.init) == "-NaN");
- assert(format!("g", double)(buffer, double.infinity) == "Inf");
- assert(format!("g", double)(buffer, -double.infinity) == "-Inf");
- assert(format!("g", double)(buffer, 0.000000000000000000000000003) == "3e-27");
- assert(format!("g", double)(buffer, 0.23432e304) == "2.3432e+303");
- assert(format!("g", double)(buffer, -0.23432e8) == "-2.3432e+07");
- assert(format!("g", double)(buffer, 1e-307) == "1e-307");
- assert(format!("g", double)(buffer, 1e+8) == "1e+08");
- assert(format!("g", double)(buffer, 111234.1) == "111234");
- assert(format!("g", double)(buffer, 0.999) == "0.999");
- assert(format!("g", double)(buffer, 0x1p-16382L)); // "6.95336e-310"
- assert(format!("g", double)(buffer, 1e+3) == "1000");
- assert(format!("g", double)(buffer, 38234.1234) == "38234.1");
+ assert(format!("{}")(buffer, 0.1234) == "0.1234");
+ assert(format!("{}")(buffer, 0.3) == "0.3");
+ assert(format!("{}")(buffer, 0.333333333333) == "0.333333");
+ assert(format!("{}")(buffer, 38234.1234) == "38234.1");
+ assert(format!("{}")(buffer, -0.3) == "-0.3");
+ assert(format!("{}")(buffer, 0.000000000000000006) == "6e-18");
+ assert(format!("{}")(buffer, 0.0) == "0");
+ assert(format!("{}")(buffer, double.init) == "NaN");
+ assert(format!("{}")(buffer, -double.init) == "-NaN");
+ assert(format!("{}")(buffer, double.infinity) == "Inf");
+ assert(format!("{}")(buffer, -double.infinity) == "-Inf");
+ assert(format!("{}")(buffer, 0.000000000000000000000000003) == "3e-27");
+ assert(format!("{}")(buffer, 0.23432e304) == "2.3432e+303");
+ assert(format!("{}")(buffer, -0.23432e8) == "-2.3432e+07");
+ assert(format!("{}")(buffer, 1e-307) == "1e-307");
+ assert(format!("{}")(buffer, 1e+8) == "1e+08");
+ assert(format!("{}")(buffer, 111234.1) == "111234");
+ assert(format!("{}")(buffer, 0.999) == "0.999");
+ assert(format!("{}")(buffer, 0x1p-16382L) == "0");
+ assert(format!("{}")(buffer, 1e+3) == "1000");
+ assert(format!("{}")(buffer, 38234.1234) == "38234.1");
// Pointer convesions.
- assert(format!("p", void*)(buffer, cast(void*) 1) == "0x1");
- assert(format!("p", void*)(buffer, cast(void*) 20) == "0x14");
+ assert(format!("{}")(buffer, cast(void*) 1) == "0x1");
+ assert(format!("{}")(buffer, cast(void*) 20) == "0x14");
+ assert(format!("{}")(buffer, cast(void*) null) == "0x0");
}
private struct FormatSpec