mirror of
https://github.com/dlang/phobos.git
synced 2025-04-28 22:21:09 +03:00
Merge pull request #6743 from n8sh/string-template-antibloat
Decrease template bloat for string functions merged-on-behalf-of: Jonathan M Davis <jmdavis@users.noreply.github.com>
This commit is contained in:
commit
8cef7b563e
3 changed files with 39 additions and 22 deletions
|
@ -2192,7 +2192,7 @@ the first argument using the dot notation, `array.save` is
|
||||||
equivalent to `save(array)`. The function does not duplicate the
|
equivalent to `save(array)`. The function does not duplicate the
|
||||||
content of the array, it simply returns its argument.
|
content of the array, it simply returns its argument.
|
||||||
*/
|
*/
|
||||||
@property T[] save(T)(T[] a) @safe pure nothrow @nogc
|
@property inout(T)[] save(T)(return scope inout(T)[] a) @safe pure nothrow @nogc
|
||||||
{
|
{
|
||||||
return a;
|
return a;
|
||||||
}
|
}
|
||||||
|
@ -2213,7 +2213,7 @@ equivalent to `popFront(array)`. For $(GLOSSARY narrow strings),
|
||||||
`popFront` automatically advances to the next $(GLOSSARY code
|
`popFront` automatically advances to the next $(GLOSSARY code
|
||||||
point).
|
point).
|
||||||
*/
|
*/
|
||||||
void popFront(T)(ref T[] a) @safe pure nothrow @nogc
|
void popFront(T)(scope ref inout(T)[] a) @safe pure nothrow @nogc
|
||||||
if (!isNarrowString!(T[]) && !is(T[] == void[]))
|
if (!isNarrowString!(T[]) && !is(T[] == void[]))
|
||||||
{
|
{
|
||||||
assert(a.length, "Attempting to popFront() past the end of an array of " ~ T.stringof);
|
assert(a.length, "Attempting to popFront() past the end of an array of " ~ T.stringof);
|
||||||
|
@ -2236,7 +2236,7 @@ if (!isNarrowString!(T[]) && !is(T[] == void[]))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// ditto
|
/// ditto
|
||||||
void popFront(C)(ref C[] str) @trusted pure nothrow
|
void popFront(C)(scope ref inout(C)[] str) @trusted pure nothrow
|
||||||
if (isNarrowString!(C[]))
|
if (isNarrowString!(C[]))
|
||||||
{
|
{
|
||||||
import std.algorithm.comparison : min;
|
import std.algorithm.comparison : min;
|
||||||
|
@ -2334,7 +2334,7 @@ the first argument using the dot notation, `array.popBack` is
|
||||||
equivalent to `popBack(array)`. For $(GLOSSARY narrow strings), $(D
|
equivalent to `popBack(array)`. For $(GLOSSARY narrow strings), $(D
|
||||||
popFront) automatically eliminates the last $(GLOSSARY code point).
|
popFront) automatically eliminates the last $(GLOSSARY code point).
|
||||||
*/
|
*/
|
||||||
void popBack(T)(ref T[] a) @safe pure nothrow @nogc
|
void popBack(T)(scope ref inout(T)[] a) @safe pure nothrow @nogc
|
||||||
if (!isNarrowString!(T[]) && !is(T[] == void[]))
|
if (!isNarrowString!(T[]) && !is(T[] == void[]))
|
||||||
{
|
{
|
||||||
assert(a.length);
|
assert(a.length);
|
||||||
|
@ -2357,7 +2357,7 @@ if (!isNarrowString!(T[]) && !is(T[] == void[]))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// ditto
|
/// ditto
|
||||||
void popBack(T)(ref T[] a) @safe pure
|
void popBack(T)(scope ref inout(T)[] a) @safe pure
|
||||||
if (isNarrowString!(T[]))
|
if (isNarrowString!(T[]))
|
||||||
{
|
{
|
||||||
import std.utf : strideBack;
|
import std.utf : strideBack;
|
||||||
|
@ -2401,8 +2401,15 @@ equivalent to `front(array)`. For $(GLOSSARY narrow strings), $(D
|
||||||
front) automatically returns the first $(GLOSSARY code point) as _a $(D
|
front) automatically returns the first $(GLOSSARY code point) as _a $(D
|
||||||
dchar).
|
dchar).
|
||||||
*/
|
*/
|
||||||
@property ref T front(T)(T[] a) @safe pure nothrow @nogc
|
@property ref T front(T)(return scope T[] a) @safe pure nothrow @nogc
|
||||||
if (!isNarrowString!(T[]) && !is(T[] == void[]))
|
if (!isNarrowString!(T[]) && !is(T[] == void[]))
|
||||||
|
// We would have preferred to write the function template
|
||||||
|
// ---
|
||||||
|
// @property ref inout(T) front(T)(return scope inout(T)[] a)
|
||||||
|
// if (/* same constraint */)
|
||||||
|
// ---
|
||||||
|
// as that would cause fewer distinct functions to be generated with
|
||||||
|
// IFTI, but that caused a linker error in the test suite on Win32_64.
|
||||||
{
|
{
|
||||||
assert(a.length, "Attempting to fetch the front of an empty array of " ~ T.stringof);
|
assert(a.length, "Attempting to fetch the front of an empty array of " ~ T.stringof);
|
||||||
return a[0];
|
return a[0];
|
||||||
|
@ -2430,7 +2437,7 @@ if (!isNarrowString!(T[]) && !is(T[] == void[]))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// ditto
|
/// ditto
|
||||||
@property dchar front(T)(T[] a) @safe pure
|
@property dchar front(T)(scope const(T)[] a) @safe pure
|
||||||
if (isNarrowString!(T[]))
|
if (isNarrowString!(T[]))
|
||||||
{
|
{
|
||||||
import std.utf : decode;
|
import std.utf : decode;
|
||||||
|
@ -2447,7 +2454,7 @@ equivalent to `back(array)`. For $(GLOSSARY narrow strings), $(D
|
||||||
back) automatically returns the last $(GLOSSARY code point) as _a $(D
|
back) automatically returns the last $(GLOSSARY code point) as _a $(D
|
||||||
dchar).
|
dchar).
|
||||||
*/
|
*/
|
||||||
@property ref T back(T)(T[] a) @safe pure nothrow @nogc
|
@property ref inout(T) back(T)(return scope inout(T)[] a) @safe pure nothrow @nogc
|
||||||
if (!isNarrowString!(T[]) && !is(T[] == void[]))
|
if (!isNarrowString!(T[]) && !is(T[] == void[]))
|
||||||
{
|
{
|
||||||
assert(a.length, "Attempting to fetch the back of an empty array of " ~ T.stringof);
|
assert(a.length, "Attempting to fetch the back of an empty array of " ~ T.stringof);
|
||||||
|
@ -2474,7 +2481,7 @@ if (!isNarrowString!(T[]) && !is(T[] == void[]))
|
||||||
|
|
||||||
/// ditto
|
/// ditto
|
||||||
// Specialization for strings
|
// Specialization for strings
|
||||||
@property dchar back(T)(T[] a) @safe pure
|
@property dchar back(T)(scope const(T)[] a) @safe pure
|
||||||
if (isNarrowString!(T[]))
|
if (isNarrowString!(T[]))
|
||||||
{
|
{
|
||||||
import std.utf : decode, strideBack;
|
import std.utf : decode, strideBack;
|
||||||
|
|
12
std/string.d
12
std/string.d
|
@ -219,7 +219,7 @@ class StringException : Exception
|
||||||
$(RED Important Note:) The returned array is a slice of the original buffer.
|
$(RED Important Note:) The returned array is a slice of the original buffer.
|
||||||
The original data is not changed and not copied.
|
The original data is not changed and not copied.
|
||||||
+/
|
+/
|
||||||
Char[] fromStringz(Char)(Char* cString) @nogc @system pure nothrow
|
inout(Char)[] fromStringz(Char)(return scope inout(Char)* cString) @nogc @system pure nothrow
|
||||||
if (isSomeChar!Char)
|
if (isSomeChar!Char)
|
||||||
{
|
{
|
||||||
import core.stdc.stddef : wchar_t;
|
import core.stdc.stddef : wchar_t;
|
||||||
|
@ -229,7 +229,7 @@ if (isSomeChar!Char)
|
||||||
else static if (is(Unqual!Char == wchar_t))
|
else static if (is(Unqual!Char == wchar_t))
|
||||||
import core.stdc.wchar_ : cstrlen = wcslen;
|
import core.stdc.wchar_ : cstrlen = wcslen;
|
||||||
else
|
else
|
||||||
static size_t cstrlen(const Char* s)
|
static size_t cstrlen(scope const Char* s)
|
||||||
{
|
{
|
||||||
const(Char)* p = s;
|
const(Char)* p = s;
|
||||||
while (*p)
|
while (*p)
|
||||||
|
@ -432,7 +432,7 @@ if (isInputRange!Range && isSomeChar!(ElementType!Range) && !isSomeString!Range)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Ditto
|
/// Ditto
|
||||||
ptrdiff_t indexOf(C)(C[] s, dchar c, CaseSensitive cs = Yes.caseSensitive)
|
ptrdiff_t indexOf(C)(scope const(C)[] s, dchar c, CaseSensitive cs = Yes.caseSensitive)
|
||||||
if (isSomeChar!C)
|
if (isSomeChar!C)
|
||||||
{
|
{
|
||||||
return _indexOf(s, c, cs);
|
return _indexOf(s, c, cs);
|
||||||
|
@ -446,7 +446,7 @@ if (isInputRange!Range && isSomeChar!(ElementType!Range) && !isSomeString!Range)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Ditto
|
/// Ditto
|
||||||
ptrdiff_t indexOf(C)(C[] s, dchar c, size_t startIdx, CaseSensitive cs = Yes.caseSensitive)
|
ptrdiff_t indexOf(C)(scope const(C)[] s, dchar c, size_t startIdx, CaseSensitive cs = Yes.caseSensitive)
|
||||||
if (isSomeChar!C)
|
if (isSomeChar!C)
|
||||||
{
|
{
|
||||||
return _indexOf(s, c, startIdx, cs);
|
return _indexOf(s, c, startIdx, cs);
|
||||||
|
@ -5300,7 +5300,7 @@ if (isSomeChar!C1 && isSomeString!S && isSomeChar!C2)
|
||||||
toRemove = The characters to remove from the string.
|
toRemove = The characters to remove from the string.
|
||||||
buffer = An output range to write the contents to.
|
buffer = An output range to write the contents to.
|
||||||
+/
|
+/
|
||||||
void translate(C1, C2 = immutable char, Buffer)(C1[] str,
|
void translate(C1, C2 = immutable char, Buffer)(const(C1)[] str,
|
||||||
in dchar[dchar] transTable,
|
in dchar[dchar] transTable,
|
||||||
const(C2)[] toRemove,
|
const(C2)[] toRemove,
|
||||||
Buffer buffer)
|
Buffer buffer)
|
||||||
|
@ -5356,7 +5356,7 @@ if (isSomeChar!C1 && isSomeString!S && isSomeChar!C2 && isOutputRange!(Buffer, S
|
||||||
translateImpl(str, transTable, toRemove, buffer);
|
translateImpl(str, transTable, toRemove, buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void translateImpl(C1, T, C2, Buffer)(C1[] str,
|
private void translateImpl(C1, T, C2, Buffer)(const(C1)[] str,
|
||||||
T transTable,
|
T transTable,
|
||||||
const(C2)[] toRemove,
|
const(C2)[] toRemove,
|
||||||
Buffer buffer)
|
Buffer buffer)
|
||||||
|
|
24
std/utf.d
24
std/utf.d
|
@ -1065,6 +1065,15 @@ if (isSomeChar!C)
|
||||||
/// Whether or not to replace invalid UTF with $(LREF replacementDchar)
|
/// Whether or not to replace invalid UTF with $(LREF replacementDchar)
|
||||||
alias UseReplacementDchar = Flag!"useReplacementDchar";
|
alias UseReplacementDchar = Flag!"useReplacementDchar";
|
||||||
|
|
||||||
|
// Reduce distinct instantiations of decodeImpl.
|
||||||
|
private template TypeForDecode(T)
|
||||||
|
{
|
||||||
|
static if (isDynamicArray!T && is(T : E[], E) && __traits(isArithmetic, E) && !is(E == shared))
|
||||||
|
alias TypeForDecode = const(Unqual!E)[];
|
||||||
|
else
|
||||||
|
alias TypeForDecode = T;
|
||||||
|
}
|
||||||
|
|
||||||
/++
|
/++
|
||||||
Decodes and returns the code point starting at `str[index]`. `index`
|
Decodes and returns the code point starting at `str[index]`. `index`
|
||||||
is advanced to one past the decoded code point. If the code point is not
|
is advanced to one past the decoded code point. If the code point is not
|
||||||
|
@ -1103,7 +1112,7 @@ do
|
||||||
if (str[index] < codeUnitLimit!S)
|
if (str[index] < codeUnitLimit!S)
|
||||||
return str[index++];
|
return str[index++];
|
||||||
else
|
else
|
||||||
return decodeImpl!(true, useReplacementDchar)(str, index);
|
return decodeImpl!(true, useReplacementDchar)(cast(TypeForDecode!S) str, index);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// ditto
|
/// ditto
|
||||||
|
@ -1123,7 +1132,7 @@ do
|
||||||
if (str[index] < codeUnitLimit!S)
|
if (str[index] < codeUnitLimit!S)
|
||||||
return str[index++];
|
return str[index++];
|
||||||
else
|
else
|
||||||
return decodeImpl!(true, useReplacementDchar)(str, index);
|
return decodeImpl!(true, useReplacementDchar)(cast(TypeForDecode!S) str, index);
|
||||||
}
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
|
@ -1200,7 +1209,7 @@ do
|
||||||
//is undesirable, since not all overloads of decodeImpl need it. So, it
|
//is undesirable, since not all overloads of decodeImpl need it. So, it
|
||||||
//should be moved back into decodeImpl once bug# 8521 has been fixed.
|
//should be moved back into decodeImpl once bug# 8521 has been fixed.
|
||||||
enum canIndex = isRandomAccessRange!S && hasSlicing!S && hasLength!S;
|
enum canIndex = isRandomAccessRange!S && hasSlicing!S && hasLength!S;
|
||||||
immutable retval = decodeImpl!(canIndex, useReplacementDchar)(str, numCodeUnits);
|
immutable retval = decodeImpl!(canIndex, useReplacementDchar)(cast(TypeForDecode!S) str, numCodeUnits);
|
||||||
|
|
||||||
// The other range types were already popped by decodeImpl.
|
// The other range types were already popped by decodeImpl.
|
||||||
static if (isRandomAccessRange!S && hasSlicing!S && hasLength!S)
|
static if (isRandomAccessRange!S && hasSlicing!S && hasLength!S)
|
||||||
|
@ -1233,7 +1242,7 @@ do
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
immutable retval = decodeImpl!(true, useReplacementDchar)(str, numCodeUnits);
|
immutable retval = decodeImpl!(true, useReplacementDchar)(cast(TypeForDecode!S) str, numCodeUnits);
|
||||||
str = str[numCodeUnits .. $];
|
str = str[numCodeUnits .. $];
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
@ -1307,7 +1316,7 @@ do
|
||||||
numCodeUnits = strideBack(str);
|
numCodeUnits = strideBack(str);
|
||||||
immutable newLength = str.length - numCodeUnits;
|
immutable newLength = str.length - numCodeUnits;
|
||||||
size_t index = newLength;
|
size_t index = newLength;
|
||||||
immutable retval = decodeImpl!(true, useReplacementDchar)(str, index);
|
immutable retval = decodeImpl!(true, useReplacementDchar)(cast(TypeForDecode!S) str, index);
|
||||||
str = str[0 .. newLength];
|
str = str[0 .. newLength];
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
@ -1341,7 +1350,7 @@ do
|
||||||
static if (isRandomAccessRange!S)
|
static if (isRandomAccessRange!S)
|
||||||
{
|
{
|
||||||
size_t index = str.length - numCodeUnits;
|
size_t index = str.length - numCodeUnits;
|
||||||
immutable retval = decodeImpl!(true, useReplacementDchar)(str, index);
|
immutable retval = decodeImpl!(true, useReplacementDchar)(cast(TypeForDecode!S) str, index);
|
||||||
str.popBackExactly(numCodeUnits);
|
str.popBackExactly(numCodeUnits);
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
@ -1357,7 +1366,8 @@ do
|
||||||
}
|
}
|
||||||
const Char[] codePoint = codeUnits[0 .. numCodeUnits];
|
const Char[] codePoint = codeUnits[0 .. numCodeUnits];
|
||||||
size_t index = 0;
|
size_t index = 0;
|
||||||
immutable retval = decodeImpl!(true, useReplacementDchar)(codePoint, index);
|
immutable retval = decodeImpl!(true, useReplacementDchar)(
|
||||||
|
cast(TypeForDecode!(typeof(codePoint))) codePoint, index);
|
||||||
str = tmp;
|
str = tmp;
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue