Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 23 additions & 14 deletions source/mir/format.d
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ Authors: Ilya Yaroshenko
module mir.format;

import std.traits;
import mir.primitives: isOutputRange;

/// `mir.conv: to` extension.
version(mir_test)
Expand Down Expand Up @@ -276,6 +277,7 @@ struct FormattedFloating(T)

///
void toString(C = char, W)(scope ref W w) scope const
if (isSomeChar!C && isOutputRange!(W, C))
{
C[512] buf = void;
auto n = printFloatingPoint(value, spec, buf);
Expand All @@ -302,6 +304,7 @@ struct HexAddress(T)

///
void toString(C = char, W)(scope ref W w) scope const
if (isSomeChar!C && isOutputRange!(W, C))
{
enum N = T.sizeof * 2;
static if(isFastBuffer!W)
Expand Down Expand Up @@ -337,6 +340,7 @@ enum escapeFormatQuote(EscapeFormat escapeFormat) = escapeFormat == EscapeFormat
/++
+/
ref W printEscaped(C, EscapeFormat escapeFormat = EscapeFormat.ion, W)(scope return ref W w, scope const(C)[] str)
if (isOutputRange!(W, C))
{
import mir.utility: _expect;
foreach (C c; str)
Expand Down Expand Up @@ -406,7 +410,6 @@ ref W printEscaped(C, EscapeFormat escapeFormat = EscapeFormat.ion, W)(scope ret
@safe pure nothrow @nogc
version (mir_test) unittest
{

import mir.format: stringBuf;
stringBuf w;
assert(w.printEscaped("Hi \a\v\0\f\t\b \\\r\n" ~ `"@nogc"`).data == `Hi \a\v\0\f\t\b \\\r\n\"@nogc\"`);
Expand All @@ -418,6 +421,7 @@ version (mir_test) unittest
Decodes `char` `c` to the form `u00XX`, where `XX` is 2 hexadecimal characters.
+/
ref W put_xXX(C = char, W)(scope return ref W w, char c)
if (isSomeChar!C && isOutputRange!(W, C))
{
ubyte[2] spl;
spl[0] = c >> 4;
Expand All @@ -434,6 +438,7 @@ ref W put_xXX(C = char, W)(scope return ref W w, char c)
Decodes `char` `c` to the form `u00XX`, where `XX` is 2 hexadecimal characters.
+/
ref W put_uXXXX(C = char, W)(scope return ref W w, char c)
if (isSomeChar!C && isOutputRange!(W, C))
{
ubyte[2] spl;
spl[0] = c >> 4;
Expand All @@ -452,6 +457,7 @@ ref W put_uXXXX(C = char, W)(scope return ref W w, char c)
Decodes ushort `c` to the form `uXXXX`, where `XXXX` is 2 hexadecimal characters.
+/
ref W put_uXXXX(C = char, W)(scope return ref W w, ushort c)
if (isSomeChar!C && isOutputRange!(W, C))
{
ubyte[4] spl;
spl[0] = (c >> 12) & 0xF;
Expand All @@ -470,7 +476,7 @@ ref W put_uXXXX(C = char, W)(scope return ref W w, ushort c)

///
ref W printElement(C, EscapeFormat escapeFormat = EscapeFormat.ion, W)(scope return ref W w, scope const(C)[] c)
if (isSomeChar!C)
if (isSomeChar!C && isOutputRange!(W, C))
{
static immutable C[1] quote = '\"';
return w
Expand All @@ -481,7 +487,7 @@ ref W printElement(C, EscapeFormat escapeFormat = EscapeFormat.ion, W)(scope ret

///
ref W printElement(C = char, EscapeFormat escapeFormat = EscapeFormat.ion, W, T)(scope return ref W w, scope auto ref const T c)
if (!isSomeString!T)
if (!isSomeString!T && isOutputRange!(W, C))
{
return w.print!C(c);
}
Expand All @@ -490,7 +496,7 @@ ref W printElement(C = char, EscapeFormat escapeFormat = EscapeFormat.ion, W, T)
Multiargument overload.
+/
ref W print(C = char, W, Args...)(scope return ref W w, scope auto ref const Args args)
if (Args.length > 1)
if (isSomeChar!C && isOutputRange!(W, C) && Args.length > 1)
{
foreach(i, ref c; args)
static if (i < Args.length - 1)
Expand All @@ -501,7 +507,7 @@ ref W print(C = char, W, Args...)(scope return ref W w, scope auto ref const Arg

/// Prints enums
ref W print(C = char, W, T)(scope return ref W w, const T c)
if (is(T == enum))
if (isSomeChar!C && isOutputRange!(W, C) && is(T == enum))
{
import mir.enums: getEnumIndex, enumStrings;
import mir.utility: _expect;
Expand Down Expand Up @@ -538,6 +544,7 @@ version (mir_test) unittest

/// Prints boolean
ref W print(C = char, W)(scope return ref W w, bool c)
if (isSomeChar!C && isOutputRange!(W, C))
{
enum N = 5;
static if(isFastBuffer!W)
Expand Down Expand Up @@ -567,6 +574,7 @@ version (mir_test) unittest
/// Prints associative array
pragma(inline, false)
ref W print(C = char, W, V, K)(scope return ref W w, scope const V[K] c)
if (isSomeChar!C && isOutputRange!(W, C))
{
enum C left = '[';
enum C right = ']';
Expand Down Expand Up @@ -601,7 +609,7 @@ version (mir_test) unittest
/// Prints array
pragma(inline, false)
ref W print(C = char, W, T)(scope return ref W w, scope const(T)[] c)
if (!isSomeChar!T)
if (isSomeChar!C && isOutputRange!(W, C) && !isSomeChar!T)
{
enum C left = '[';
enum C right = ']';
Expand Down Expand Up @@ -632,6 +640,7 @@ version (mir_test) unittest
/// Prints escaped character in the form `'c'`.
pragma(inline, false)
ref W print(C = char, W)(scope return ref W w, char c)
if (isSomeChar!C && isOutputRange!(W, C))
{
w.put('\'');
if (c >= 0x20)
Expand Down Expand Up @@ -687,15 +696,15 @@ version (mir_test) unittest

/// Prints some string
ref W print(C = char, W)(scope return ref W w, scope const(C)[] c)
if (isSomeChar!C)
if (isSomeChar!C && isOutputRange!(W, C))
{
w.put(c);
return w;
}

/// Prints integers
ref W print(C = char, W, I)(scope return ref W w, const I c)
if (isIntegral!I && !is(I == enum))
if (isSomeChar!C && isOutputRange!(W, C) && isIntegral!I && !is(I == enum))
{
static if (I.sizeof == 16)
enum N = 39;
Expand All @@ -715,7 +724,7 @@ ref W print(C = char, W, I)(scope return ref W w, const I c)

/// Prints floating point numbers
ref W print(C = char, W, T)(scope return ref W w, const T c, NumericSpec spec = NumericSpec.init)
if(is(T == float) || is(T == double) || is(T == real))
if(isSomeChar!C && isOutputRange!(W, C) && is(T == float) || is(T == double) || is(T == real))
{
import mir.bignum.decimal;
auto decimal = Decimal!(T.mant_dig < 64 ? 1 : 2)(c);
Expand Down Expand Up @@ -808,7 +817,7 @@ unittest
/// Prints structs and unions
pragma(inline, false)
ref W print(C = char, W, T)(scope return ref W w, ref const T c)
if (is(T == struct) || is(T == union) && !is(T : NumericSpec))
if (isSomeChar!C && isOutputRange!(W, C) && is(T == struct) || is(T == union) && !is(T : NumericSpec))
{
static if (__traits(hasMember, T, "toString"))
{
Expand Down Expand Up @@ -871,7 +880,7 @@ ref W print(C = char, W, T)(scope return ref W w, ref const T c)
// FUTURE: remove it
pragma(inline, false)
ref W print(C = char, W, T)(scope return ref W w, scope const T c)
if (is(T == struct) || is(T == union))
if (isSomeChar!C && isOutputRange!(W, C) && is(T == struct) || is(T == union))
{
return print!(C, W, T)(w, c);
}
Expand All @@ -894,7 +903,7 @@ version (mir_test) unittest
/// Prints classes and interfaces
pragma(inline, false)
ref W print(C = char, W, T)(scope return ref W w, scope const T c)
if (is(T == class) || is(T == interface))
if (isSomeChar!C && isOutputRange!(W, C) && is(T == class) || is(T == interface))
{
enum C[4] Null = "null";
static if (__traits(hasMember, T, "toString") || __traits(compiles, { scope const(C)[] string_of_c = c; }))
Expand Down Expand Up @@ -960,7 +969,7 @@ version (mir_test) unittest

///
ref W printStaticString(C, size_t N, W)(scope return ref W w, ref scope const C[N] c)
if (is(C == char) || is(C == wchar) || is(C == dchar))
if (isSomeChar!C && isOutputRange!(W, C) && is(C == char) || is(C == wchar) || is(C == dchar))
{
static if (isFastBuffer!W)
{
Expand Down Expand Up @@ -1008,7 +1017,7 @@ template isFastBuffer(W)

///
ref W printZeroPad(C = char, W, I)(scope return ref W w, const I c, size_t minimalLength)
if (isIntegral!I && !is(I == enum))
if (isSomeChar!C && isOutputRange!(W, C) && isIntegral!I && !is(I == enum))
{
static if (I.sizeof == 16)
enum N = 39;
Expand Down