From 31c963070245c2c89ae287283f49fc77425c45df Mon Sep 17 00:00:00 2001 From: Walter Bright Date: Tue, 21 Jul 2015 22:39:32 -0700 Subject: [PATCH] add std.traits.isAutodecodableString() to fix Issue 14765 --- std/traits.d | 33 +++++++++++++++++++++++++++++++++ std/utf.d | 43 ++++++++++++++++++++++++++++++------------- 2 files changed, 63 insertions(+), 13 deletions(-) diff --git a/std/traits.d b/std/traits.d index 65bdf40353b..e4f07799a32 100644 --- a/std/traits.d +++ b/std/traits.d @@ -85,6 +85,7 @@ * $(LREF isFloatingPoint) * $(LREF isIntegral) * $(LREF isNarrowString) + * $(LREF isAutodecodableString) * $(LREF isNumeric) * $(LREF isPointer) * $(LREF isScalarType) @@ -5236,6 +5237,38 @@ unittest } } + +/** + * Detect whether type $(D T) is a string that will be autodecoded. + * + * All arrays that use char, wchar, and their qualified versions are narrow + * strings. (Those include string and wstring). + * Aggregates that implicitly cast to narrow strings are included. + * + * Params: + * T = type to be tested + * + * Returns: + * true if T represents a string that is subject to autodecoding + * + * See Also: + * $(LREF isNarrowString) + */ +enum bool isAutodecodableString(T) = (is(T : const char[]) || is(T : const wchar[])) && !isStaticArray!T; + +/// +unittest +{ + static struct Stringish + { + string s; + alias s this; + } + assert(isAutodecodableString!wstring); + assert(isAutodecodableString!Stringish); + assert(!isAutodecodableString!dstring); +} + /** * Detect whether type $(D T) is a static array. */ diff --git a/std/utf.d b/std/utf.d index ce2d6af87c7..bab162e04c5 100644 --- a/std/utf.d +++ b/std/utf.d @@ -3079,7 +3079,7 @@ enum dchar replacementDchar = '\uFFFD'; * input range */ -auto byCodeUnit(R)(R r) if (isNarrowString!R) +auto byCodeUnit(R)(R r) if (isAutodecodableString!R) { /* Turn an array into an InputRange. */ @@ -3102,9 +3102,12 @@ auto byCodeUnit(R)(R r) if (isNarrowString!R) r = r[0 .. $-1]; } - auto opSlice(size_t lower, size_t upper) + static if (!isAggregateType!R) { - return ByCodeUnitImpl(r[lower..upper]); + auto opSlice(size_t lower, size_t upper) + { + return ByCodeUnitImpl(r[lower..upper]); + } } @property size_t length() const @@ -3113,23 +3116,26 @@ auto byCodeUnit(R)(R r) if (isNarrowString!R) } alias opDollar = length; - @property auto save() + static if (!isAggregateType!R) { - return ByCodeUnitImpl(r.save); + @property auto save() + { + return ByCodeUnitImpl(r.save); + } } private: R r; } - static assert(isRandomAccessRange!ByCodeUnitImpl); + static assert(isAggregateType!R || isRandomAccessRange!ByCodeUnitImpl); return ByCodeUnitImpl(r); } /// Ditto auto ref byCodeUnit(R)(R r) - if (!isNarrowString!R && isInputRange!R && isSomeChar!(ElementEncodingType!R)) + if (!isAutodecodableString!R && isInputRange!R && isSomeChar!(ElementEncodingType!R)) { // byCodeUnit for ranges and dchar[] is a no-op return r; @@ -3204,6 +3210,17 @@ pure nothrow @nogc unittest ret.popFront(); assert(ret.front == 'μ'); } + { + static struct Stringish + { + string s; + alias s this; + } + + auto fn = Stringish("test.d"); + auto x = fn.byCodeUnit(); + assert(x.front == 't'); + } } /**************************** @@ -3220,7 +3237,7 @@ pure nothrow @nogc unittest * input range */ -auto byChar(R)(R r) if (isNarrowString!R) +auto byChar(R)(R r) if (isAutodecodableString!R) { /* This and the following two serve as adapters to convert arrays to ranges, * so the following three @@ -3239,7 +3256,7 @@ auto byChar(R)(R r) if (isNarrowString!R) } /// Ditto -auto byWchar(R)(R r) if (isNarrowString!R) +auto byWchar(R)(R r) if (isAutodecodableString!R) { alias tchar = Unqual!(ElementEncodingType!R); @@ -3254,7 +3271,7 @@ auto byWchar(R)(R r) if (isNarrowString!R) } /// Ditto -auto byDchar(R)(R r) if (isNarrowString!R) +auto byDchar(R)(R r) if (isAutodecodableString!R) { alias tchar = Unqual!(ElementEncodingType!R); @@ -3264,7 +3281,7 @@ auto byDchar(R)(R r) if (isNarrowString!R) /// Ditto auto ref byChar(R)(R r) - if (!isNarrowString!R && isInputRange!R && isSomeChar!(ElementEncodingType!R)) + if (!isAutodecodableString!R && isInputRange!R && isSomeChar!(ElementEncodingType!R)) { alias tchar = Unqual!(ElementEncodingType!R); @@ -3427,7 +3444,7 @@ pure nothrow @nogc unittest /// Ditto auto ref byWchar(R)(R r) - if (!isNarrowString!R && isInputRange!R && isSomeChar!(ElementEncodingType!R)) + if (!isAutodecodableString!R && isInputRange!R && isSomeChar!(ElementEncodingType!R)) { alias tchar = Unqual!(ElementEncodingType!R); @@ -3564,7 +3581,7 @@ pure nothrow @nogc unittest /// Ditto auto ref byDchar(R)(R r) - if (!isNarrowString!R && isInputRange!R && isSomeChar!(ElementEncodingType!R)) + if (!isAutodecodableString!R && isInputRange!R && isSomeChar!(ElementEncodingType!R)) { alias tchar = Unqual!(ElementEncodingType!R);