Merge pull request #8360 from WebFreak001/is-some-finite-char-input-range

add isSomeFiniteCharInputRange as simplification

Signed-off-by: Nicholas Wilson <thewilsonator@users.noreply.github.com>
Merged-on-behalf-of: Nicholas Wilson <thewilsonator@users.noreply.github.com>
This commit is contained in:
The Dlang Bot 2022-01-16 01:48:19 +00:00 committed by GitHub
commit 263652cee6
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
8 changed files with 110 additions and 96 deletions

View file

@ -50,7 +50,7 @@ module std.conv;
public import std.ascii : LetterCase; public import std.ascii : LetterCase;
import std.meta; import std.meta;
import std.range.primitives; import std.range;
import std.traits; import std.traits;
import std.typecons : Flag, Yes, No, tuple, isTuple; import std.typecons : Flag, Yes, No, tuple, isTuple;
@ -1996,7 +1996,7 @@ if (isInputRange!S && isSomeChar!(ElementEncodingType!S) &&
/// ditto /// ditto
private T toImpl(T, S)(S value, uint radix) private T toImpl(T, S)(S value, uint radix)
if (isInputRange!S && !isInfinite!S && isSomeChar!(ElementEncodingType!S) && if (isSomeFiniteCharInputRange!S &&
isIntegral!T && is(typeof(parse!T(value, radix)))) isIntegral!T && is(typeof(parse!T(value, radix))))
{ {
scope(success) scope(success)

View file

@ -89,7 +89,7 @@ import std.datetime.date : DateTime;
import std.datetime.systime : Clock, SysTime, unixTimeToStdTime; import std.datetime.systime : Clock, SysTime, unixTimeToStdTime;
import std.internal.cstring; import std.internal.cstring;
import std.meta; import std.meta;
import std.range.primitives; import std.range;
import std.traits; import std.traits;
import std.typecons; import std.typecons;
@ -313,8 +313,7 @@ Throws: $(LREF FileException) on error.
*/ */
void[] read(R)(R name, size_t upTo = size_t.max) void[] read(R)(R name, size_t upTo = size_t.max)
if (isInputRange!R && isSomeChar!(ElementEncodingType!R) && !isInfinite!R && if (isSomeFiniteCharInputRange!R && !isConvertibleToString!R)
!isConvertibleToString!R)
{ {
static if (isNarrowString!R && is(immutable ElementEncodingType!R == immutable char)) static if (isNarrowString!R && is(immutable ElementEncodingType!R == immutable char))
return readImpl(name, name.tempCString!FSChar(), upTo); return readImpl(name, name.tempCString!FSChar(), upTo);
@ -500,7 +499,7 @@ version (linux) @safe unittest
$(REF UTFException, std, utf) on UTF decoding error. $(REF UTFException, std, utf) on UTF decoding error.
+/ +/
S readText(S = string, R)(auto ref R name) S readText(S = string, R)(auto ref R name)
if (isSomeString!S && (isInputRange!R && !isInfinite!R && isSomeChar!(ElementType!R) || is(StringTypeOf!R))) if (isSomeString!S && (isSomeFiniteCharInputRange!R || is(StringTypeOf!R)))
{ {
import std.algorithm.searching : startsWith; import std.algorithm.searching : startsWith;
import std.encoding : getBOM, BOM; import std.encoding : getBOM, BOM;
@ -736,8 +735,7 @@ Throws: $(LREF FileException) on error.
See_also: $(REF toFile, std,stdio) See_also: $(REF toFile, std,stdio)
*/ */
void write(R)(R name, const void[] buffer) void write(R)(R name, const void[] buffer)
if ((isInputRange!R && !isInfinite!R && isSomeChar!(ElementEncodingType!R) || isSomeString!R) && if ((isSomeFiniteCharInputRange!R || isSomeString!R) && !isConvertibleToString!R)
!isConvertibleToString!R)
{ {
static if (isNarrowString!R && is(immutable ElementEncodingType!R == immutable char)) static if (isNarrowString!R && is(immutable ElementEncodingType!R == immutable char))
writeImpl(name, name.tempCString!FSChar(), buffer, false); writeImpl(name, name.tempCString!FSChar(), buffer, false);
@ -785,8 +783,7 @@ Params:
Throws: $(LREF FileException) on error. Throws: $(LREF FileException) on error.
*/ */
void append(R)(R name, const void[] buffer) void append(R)(R name, const void[] buffer)
if ((isInputRange!R && !isInfinite!R && isSomeChar!(ElementEncodingType!R) || isSomeString!R) && if ((isSomeFiniteCharInputRange!R || isSomeString!R) && !isConvertibleToString!R)
!isConvertibleToString!R)
{ {
static if (isNarrowString!R && is(immutable ElementEncodingType!R == immutable char)) static if (isNarrowString!R && is(immutable ElementEncodingType!R == immutable char))
writeImpl(name, name.tempCString!FSChar(), buffer, true); writeImpl(name, name.tempCString!FSChar(), buffer, true);
@ -915,10 +912,8 @@ version (Windows) private void writeImpl(scope const(char)[] name, scope const(F
* Throws: $(LREF FileException) on error. * Throws: $(LREF FileException) on error.
*/ */
void rename(RF, RT)(RF from, RT to) void rename(RF, RT)(RF from, RT to)
if ((isInputRange!RF && !isInfinite!RF && isSomeChar!(ElementEncodingType!RF) || isSomeString!RF) if ((isSomeFiniteCharInputRange!RF || isSomeString!RF) && !isConvertibleToString!RF &&
&& !isConvertibleToString!RF && (isSomeFiniteCharInputRange!RT || isSomeString!RT) && !isConvertibleToString!RT)
(isInputRange!RT && !isInfinite!RT && isSomeChar!(ElementEncodingType!RT) || isSomeString!RT)
&& !isConvertibleToString!RT)
{ {
// Place outside of @trusted block // Place outside of @trusted block
auto fromz = from.tempCString!FSChar(); auto fromz = from.tempCString!FSChar();
@ -1027,8 +1022,7 @@ Params:
Throws: $(LREF FileException) on error. Throws: $(LREF FileException) on error.
*/ */
void remove(R)(R name) void remove(R)(R name)
if (isInputRange!R && !isInfinite!R && isSomeChar!(ElementEncodingType!R) && if (isSomeFiniteCharInputRange!R && !isConvertibleToString!R)
!isConvertibleToString!R)
{ {
static if (isNarrowString!R && is(immutable ElementEncodingType!R == immutable char)) static if (isNarrowString!R && is(immutable ElementEncodingType!R == immutable char))
removeImpl(name, name.tempCString!FSChar()); removeImpl(name, name.tempCString!FSChar());
@ -1082,7 +1076,7 @@ private void removeImpl(scope const(char)[] name, scope const(FSChar)* namez) @t
} }
version (Windows) private WIN32_FILE_ATTRIBUTE_DATA getFileAttributesWin(R)(R name) version (Windows) private WIN32_FILE_ATTRIBUTE_DATA getFileAttributesWin(R)(R name)
if (isInputRange!R && !isInfinite!R && isSomeChar!(ElementEncodingType!R)) if (isSomeFiniteCharInputRange!R)
{ {
auto namez = name.tempCString!FSChar(); auto namez = name.tempCString!FSChar();
@ -1137,8 +1131,7 @@ Throws:
$(LREF FileException) on error (e.g., file not found). $(LREF FileException) on error (e.g., file not found).
*/ */
ulong getSize(R)(R name) ulong getSize(R)(R name)
if (isInputRange!R && !isInfinite!R && isSomeChar!(ElementEncodingType!R) && if (isSomeFiniteCharInputRange!R && !isConvertibleToString!R)
!isConvertibleToString!R)
{ {
version (Windows) version (Windows)
{ {
@ -1233,8 +1226,7 @@ private SysTime statTimeToStdTime(char which)(ref const stat_t statbuf)
void getTimes(R)(R name, void getTimes(R)(R name,
out SysTime accessTime, out SysTime accessTime,
out SysTime modificationTime) out SysTime modificationTime)
if (isInputRange!R && !isInfinite!R && isSomeChar!(ElementEncodingType!R) && if (isSomeFiniteCharInputRange!R && !isConvertibleToString!R)
!isConvertibleToString!R)
{ {
version (Windows) version (Windows)
{ {
@ -1378,8 +1370,9 @@ version (StdDdoc)
out SysTime fileCreationTime, out SysTime fileCreationTime,
out SysTime fileAccessTime, out SysTime fileAccessTime,
out SysTime fileModificationTime) out SysTime fileModificationTime)
if (isInputRange!R && !isInfinite!R && isSomeChar!(ElementEncodingType!R) && if (isSomeFiniteCharInputRange!R || isConvertibleToString!R);
!isConvertibleToString!R); // above line contains both constraints for docs
// (so users know how it can be called)
} }
else version (Windows) else version (Windows)
{ {
@ -1387,8 +1380,7 @@ else version (Windows)
out SysTime fileCreationTime, out SysTime fileCreationTime,
out SysTime fileAccessTime, out SysTime fileAccessTime,
out SysTime fileModificationTime) out SysTime fileModificationTime)
if (isInputRange!R && !isInfinite!R && isSomeChar!(ElementEncodingType!R) && if (isSomeFiniteCharInputRange!R && !isConvertibleToString!R)
!isConvertibleToString!R)
{ {
import std.datetime.systime : FILETIMEToSysTime; import std.datetime.systime : FILETIMEToSysTime;
@ -1509,8 +1501,7 @@ private
void setTimes(R)(R name, void setTimes(R)(R name,
SysTime accessTime, SysTime accessTime,
SysTime modificationTime) SysTime modificationTime)
if (isInputRange!R && !isInfinite!R && isSomeChar!(ElementEncodingType!R) && if (isSomeFiniteCharInputRange!R && !isConvertibleToString!R)
!isConvertibleToString!R)
{ {
auto namez = name.tempCString!FSChar(); auto namez = name.tempCString!FSChar();
static if (isNarrowString!R && is(immutable ElementEncodingType!R == immutable char)) static if (isNarrowString!R && is(immutable ElementEncodingType!R == immutable char))
@ -1657,8 +1648,7 @@ private void setTimesImpl(scope const(char)[] names, scope const(FSChar)* namez,
$(LREF FileException) if the given file does not exist. $(LREF FileException) if the given file does not exist.
+/ +/
SysTime timeLastModified(R)(R name) SysTime timeLastModified(R)(R name)
if (isInputRange!R && !isInfinite!R && isSomeChar!(ElementEncodingType!R) && if (isSomeFiniteCharInputRange!R && !isConvertibleToString!R)
!isConvertibleToString!R)
{ {
version (Windows) version (Windows)
{ {
@ -1742,7 +1732,7 @@ else
-------------------- --------------------
+/ +/
SysTime timeLastModified(R)(R name, SysTime returnIfMissing) SysTime timeLastModified(R)(R name, SysTime returnIfMissing)
if (isInputRange!R && !isInfinite!R && isSomeChar!(ElementEncodingType!R)) if (isSomeFiniteCharInputRange!R)
{ {
version (Windows) version (Windows)
{ {
@ -1902,8 +1892,7 @@ version (OSX) {} else
* true if the file _name specified as input _exists * true if the file _name specified as input _exists
*/ */
bool exists(R)(R name) bool exists(R)(R name)
if (isInputRange!R && !isInfinite!R && isSomeChar!(ElementEncodingType!R) && if (isSomeFiniteCharInputRange!R && !isConvertibleToString!R)
!isConvertibleToString!R)
{ {
return existsImpl(name.tempCString!FSChar()); return existsImpl(name.tempCString!FSChar());
} }
@ -2004,8 +1993,7 @@ private bool existsImpl(scope const(FSChar)* namez) @trusted nothrow @nogc
Throws: $(LREF FileException) on error. Throws: $(LREF FileException) on error.
+/ +/
uint getAttributes(R)(R name) uint getAttributes(R)(R name)
if (isInputRange!R && !isInfinite!R && isSomeChar!(ElementEncodingType!R) && if (isSomeFiniteCharInputRange!R && !isConvertibleToString!R)
!isConvertibleToString!R)
{ {
version (Windows) version (Windows)
{ {
@ -2105,8 +2093,7 @@ if (isConvertibleToString!R)
$(LREF FileException) on error. $(LREF FileException) on error.
+/ +/
uint getLinkAttributes(R)(R name) uint getLinkAttributes(R)(R name)
if (isInputRange!R && !isInfinite!R && isSomeChar!(ElementEncodingType!R) && if (isSomeFiniteCharInputRange!R && !isConvertibleToString!R)
!isConvertibleToString!R)
{ {
version (Windows) version (Windows)
{ {
@ -2214,8 +2201,7 @@ if (isConvertibleToString!R)
$(LREF FileException) if the given file does not exist. $(LREF FileException) if the given file does not exist.
+/ +/
void setAttributes(R)(R name, uint attributes) void setAttributes(R)(R name, uint attributes)
if (isInputRange!R && !isInfinite!R && isSomeChar!(ElementEncodingType!R) && if (isSomeFiniteCharInputRange!R && !isConvertibleToString!R)
!isConvertibleToString!R)
{ {
version (Windows) version (Windows)
{ {
@ -2323,8 +2309,7 @@ if (isConvertibleToString!R)
$(LREF FileException) if the given file does not exist. $(LREF FileException) if the given file does not exist.
+/ +/
@property bool isDir(R)(R name) @property bool isDir(R)(R name)
if (isInputRange!R && !isInfinite!R && isSomeChar!(ElementEncodingType!R) && if (isSomeFiniteCharInputRange!R && !isConvertibleToString!R)
!isConvertibleToString!R)
{ {
version (Windows) version (Windows)
{ {
@ -2503,8 +2488,7 @@ bool attrIsDir(uint attributes) @safe pure nothrow @nogc
$(LREF FileException) if the given file does not exist. $(LREF FileException) if the given file does not exist.
+/ +/
@property bool isFile(R)(R name) @property bool isFile(R)(R name)
if (isInputRange!R && !isInfinite!R && isSomeChar!(ElementEncodingType!R) && if (isSomeFiniteCharInputRange!R && !isConvertibleToString!R)
!isConvertibleToString!R)
{ {
version (Windows) version (Windows)
return !name.isDir; return !name.isDir;
@ -2679,8 +2663,7 @@ bool attrIsFile(uint attributes) @safe pure nothrow @nogc
$(LREF FileException) if the given file does not exist. $(LREF FileException) if the given file does not exist.
+/ +/
@property bool isSymlink(R)(R name) @property bool isSymlink(R)(R name)
if (isInputRange!R && !isInfinite!R && isSomeChar!(ElementEncodingType!R) && if (isSomeFiniteCharInputRange!R && !isConvertibleToString!R)
!isConvertibleToString!R)
{ {
version (Windows) version (Windows)
return (getAttributes(name) & FILE_ATTRIBUTE_REPARSE_POINT) != 0; return (getAttributes(name) & FILE_ATTRIBUTE_REPARSE_POINT) != 0;
@ -2860,8 +2843,7 @@ Params:
Throws: $(LREF FileException) on error. Throws: $(LREF FileException) on error.
*/ */
void chdir(R)(R pathname) void chdir(R)(R pathname)
if (isInputRange!R && !isInfinite!R && isSomeChar!(ElementEncodingType!R) && if (isSomeFiniteCharInputRange!R && !isConvertibleToString!R)
!isConvertibleToString!R)
{ {
// Place outside of @trusted block // Place outside of @trusted block
auto pathz = pathname.tempCString!FSChar(); auto pathz = pathname.tempCString!FSChar();
@ -2931,8 +2913,7 @@ Throws:
if an error occured. if an error occured.
*/ */
void mkdir(R)(R pathname) void mkdir(R)(R pathname)
if (isInputRange!R && !isInfinite!R && isSomeChar!(ElementEncodingType!R) && if (isSomeFiniteCharInputRange!R && !isConvertibleToString!R)
!isConvertibleToString!R)
{ {
// Place outside of @trusted block // Place outside of @trusted block
const pathz = pathname.tempCString!FSChar(); const pathz = pathname.tempCString!FSChar();
@ -3135,8 +3116,7 @@ Params:
Throws: $(LREF FileException) on error. Throws: $(LREF FileException) on error.
*/ */
void rmdir(R)(R pathname) void rmdir(R)(R pathname)
if (isInputRange!R && !isInfinite!R && isSomeChar!(ElementEncodingType!R) && if (isSomeFiniteCharInputRange!R && !isConvertibleToString!R)
!isConvertibleToString!R)
{ {
// Place outside of @trusted block // Place outside of @trusted block
auto pathz = pathname.tempCString!FSChar(); auto pathz = pathname.tempCString!FSChar();
@ -3202,15 +3182,11 @@ if (isConvertibleToString!R)
exists). exists).
+/ +/
version (StdDdoc) void symlink(RO, RL)(RO original, RL link) version (StdDdoc) void symlink(RO, RL)(RO original, RL link)
if ((isInputRange!RO && !isInfinite!RO && isSomeChar!(ElementEncodingType!RO) || if ((isSomeFiniteCharInputRange!RO || isConvertibleToString!RO) &&
isConvertibleToString!RO) && (isSomeFiniteCharInputRange!RL || isConvertibleToString!RL));
(isInputRange!RL && !isInfinite!RL && isSomeChar!(ElementEncodingType!RL) ||
isConvertibleToString!RL));
else version (Posix) void symlink(RO, RL)(RO original, RL link) else version (Posix) void symlink(RO, RL)(RO original, RL link)
if ((isInputRange!RO && !isInfinite!RO && isSomeChar!(ElementEncodingType!RO) || if ((isSomeFiniteCharInputRange!RO || isConvertibleToString!RO) &&
isConvertibleToString!RO) && (isSomeFiniteCharInputRange!RL || isConvertibleToString!RL))
(isInputRange!RL && !isInfinite!RL && isSomeChar!(ElementEncodingType!RL) ||
isConvertibleToString!RL))
{ {
static if (isConvertibleToString!RO || isConvertibleToString!RL) static if (isConvertibleToString!RO || isConvertibleToString!RL)
{ {
@ -3291,11 +3267,9 @@ version (Posix) @safe unittest
$(LREF FileException) on error. $(LREF FileException) on error.
+/ +/
version (StdDdoc) string readLink(R)(R link) version (StdDdoc) string readLink(R)(R link)
if (isInputRange!R && !isInfinite!R && isSomeChar!(ElementEncodingType!R) || if (isSomeFiniteCharInputRange!R || isConvertibleToString!R);
isConvertibleToString!R);
else version (Posix) string readLink(R)(R link) else version (Posix) string readLink(R)(R link)
if (isInputRange!R && !isInfinite!R && isSomeChar!(ElementEncodingType!R) || if (isSomeFiniteCharInputRange!R || isConvertibleToString!R)
isConvertibleToString!R)
{ {
static if (isConvertibleToString!R) static if (isConvertibleToString!R)
{ {
@ -4216,8 +4190,8 @@ Params:
Throws: $(LREF FileException) on error. Throws: $(LREF FileException) on error.
*/ */
void copy(RF, RT)(RF from, RT to, PreserveAttributes preserve = preserveAttributesDefault) void copy(RF, RT)(RF from, RT to, PreserveAttributes preserve = preserveAttributesDefault)
if (isInputRange!RF && !isInfinite!RF && isSomeChar!(ElementEncodingType!RF) && !isConvertibleToString!RF && if (isSomeFiniteCharInputRange!RF && !isConvertibleToString!RF &&
isInputRange!RT && !isInfinite!RT && isSomeChar!(ElementEncodingType!RT) && !isConvertibleToString!RT) isSomeFiniteCharInputRange!RT && !isConvertibleToString!RT)
{ {
// Place outside of @trusted block // Place outside of @trusted block
auto fromz = from.tempCString!FSChar(); auto fromz = from.tempCString!FSChar();
@ -4781,7 +4755,7 @@ private struct DirIteratorImpl
} }
this(R)(R pathname, SpanMode mode, bool followSymlink) this(R)(R pathname, SpanMode mode, bool followSymlink)
if (isInputRange!R && isSomeChar!(ElementEncodingType!R)) if (isSomeFiniteCharInputRange!R)
{ {
_mode = mode; _mode = mode;
_followSymlink = followSymlink; _followSymlink = followSymlink;

View file

@ -19,7 +19,7 @@ module std.json;
import std.array; import std.array;
import std.conv; import std.conv;
import std.range.primitives; import std.range;
import std.traits; import std.traits;
/// ///
@ -929,7 +929,7 @@ Params:
options = enable decoding string representations of NaN/Inf as float values options = enable decoding string representations of NaN/Inf as float values
*/ */
JSONValue parseJSON(T)(T json, int maxDepth = -1, JSONOptions options = JSONOptions.none) JSONValue parseJSON(T)(T json, int maxDepth = -1, JSONOptions options = JSONOptions.none)
if (isInputRange!T && !isInfinite!T && isSomeChar!(ElementEncodingType!T)) if (isSomeFiniteCharInputRange!T)
{ {
import std.ascii : isDigit, isHexDigit, toUpper, toLower; import std.ascii : isDigit, isHexDigit, toUpper, toLower;
import std.typecons : Nullable, Yes; import std.typecons : Nullable, Yes;
@ -1437,7 +1437,7 @@ Params:
options = enable decoding string representations of NaN/Inf as float values options = enable decoding string representations of NaN/Inf as float values
*/ */
JSONValue parseJSON(T)(T json, JSONOptions options) JSONValue parseJSON(T)(T json, JSONOptions options)
if (isInputRange!T && !isInfinite!T && isSomeChar!(ElementEncodingType!T)) if (isSomeFiniteCharInputRange!T)
{ {
return parseJSON!T(json, -1, options); return parseJSON!T(json, -1, options);
} }

View file

@ -98,7 +98,7 @@ module std.path;
import std.file : getcwd; import std.file : getcwd;
static import std.meta; static import std.meta;
import std.range.primitives; import std.range;
import std.traits; import std.traits;
version (OSX) version (OSX)
@ -262,8 +262,7 @@ version (Windows)
from a path. from a path.
*/ */
private auto ltrimDirSeparators(R)(R path) private auto ltrimDirSeparators(R)(R path)
if (isInputRange!R && !isInfinite!R && isSomeChar!(ElementType!R) || if (isSomeFiniteCharInputRange!R || isNarrowString!R)
isNarrowString!R)
{ {
static if (isRandomAccessRange!R && hasSlicing!R || isNarrowString!R) static if (isRandomAccessRange!R && hasSlicing!R || isNarrowString!R)
{ {
@ -3213,12 +3212,8 @@ int filenameCharCmp(CaseSensitive cs = CaseSensitive.osDefault)(dchar a, dchar b
*/ */
int filenameCmp(CaseSensitive cs = CaseSensitive.osDefault, Range1, Range2) int filenameCmp(CaseSensitive cs = CaseSensitive.osDefault, Range1, Range2)
(Range1 filename1, Range2 filename2) (Range1 filename1, Range2 filename2)
if (isInputRange!Range1 && !isInfinite!Range1 && if (isSomeFiniteCharInputRange!Range1 && !isConvertibleToString!Range1 &&
isSomeChar!(ElementEncodingType!Range1) && isSomeFiniteCharInputRange!Range2 && !isConvertibleToString!Range2)
!isConvertibleToString!Range1 &&
isInputRange!Range2 && !isInfinite!Range2 &&
isSomeChar!(ElementEncodingType!Range2) &&
!isConvertibleToString!Range2)
{ {
alias C1 = Unqual!(ElementEncodingType!Range1); alias C1 = Unqual!(ElementEncodingType!Range1);
alias C2 = Unqual!(ElementEncodingType!Range2); alias C2 = Unqual!(ElementEncodingType!Range2);

View file

@ -106,9 +106,8 @@ version (Windows)
} }
import std.internal.cstring; import std.internal.cstring;
import std.range.primitives; import std.range;
import std.stdio; import std.stdio;
import std.traits : isSomeChar;
version (OSX) version (OSX)
version = Darwin; version = Darwin;
@ -1527,7 +1526,7 @@ package(std) string searchPathFor(scope const(char)[] executable)
// current user. // current user.
version (Posix) version (Posix)
private bool isExecutable(R)(R path) @trusted nothrow @nogc private bool isExecutable(R)(R path) @trusted nothrow @nogc
if (isInputRange!R && isSomeChar!(ElementEncodingType!R)) if (isSomeFiniteCharInputRange!R)
{ {
return (access(path.tempCString(), X_OK) == 0); return (access(path.tempCString(), X_OK) == 0);
} }

View file

@ -13521,3 +13521,49 @@ pure @safe unittest
assert([1, 2, 3, 4].padRight(0, 10)[7 .. 9].equal([0, 0])); assert([1, 2, 3, 4].padRight(0, 10)[7 .. 9].equal([0, 0]));
} }
/**
This simplifies a commonly used idiom in phobos for accepting any kind of string
parameter. The type `R` can for example be a simple string, chained string using
$(REF chain, std,range), $(REF chainPath, std,path) or any other input range of
characters.
Only finite length character ranges are allowed with this constraint.
This template is equivalent to:
---
isInputRange!R && !isInfinite!R && isSomeChar!(ElementEncodingType!R)
---
See_Also:
$(REF isInputRange, std,range,primitives),
$(REF isInfinite, std,range,primitives),
$(LREF isSomeChar),
$(REF ElementEncodingType, std,range,primitives)
*/
template isSomeFiniteCharInputRange(R)
{
import std.traits : isSomeChar;
enum isSomeFiniteCharInputRange = isInputRange!R && !isInfinite!R
&& isSomeChar!(ElementEncodingType!R);
}
///
@safe unittest
{
import std.path : chainPath;
import std.range : chain;
void someLibraryMethod(R)(R argument)
if (isSomeFiniteCharInputRange!R)
{
// implementation detail, would iterate over each character of argument
}
someLibraryMethod("simple strings work");
someLibraryMethod(chain("chained", " ", "strings", " ", "work"));
someLibraryMethod(chainPath("chained", "paths", "work"));
// you can also use custom structs implementing a char range
}

View file

@ -50,8 +50,8 @@ import core.stdc.stddef : wchar_t;
public import core.stdc.stdio; public import core.stdc.stdio;
import std.algorithm.mutation : copy; import std.algorithm.mutation : copy;
import std.meta : allSatisfy; import std.meta : allSatisfy;
import std.range.primitives : ElementEncodingType, empty, front, import std.range : ElementEncodingType, empty, front, isBidirectionalRange,
isBidirectionalRange, isInputRange, put; isInputRange, isSomeFiniteCharInputRange, put;
import std.traits : isSomeChar, isSomeString, Unqual, isPointer; import std.traits : isSomeChar, isSomeString, Unqual, isPointer;
import std.typecons : Flag, No, Yes; import std.typecons : Flag, No, Yes;
@ -555,7 +555,7 @@ Throws: `ErrnoException` if the file could not be opened.
/// ditto /// ditto
this(R1, R2)(R1 name) this(R1, R2)(R1 name)
if (isInputRange!R1 && isSomeChar!(ElementEncodingType!R1)) if (isSomeFiniteCharInputRange!R1)
{ {
import std.conv : to; import std.conv : to;
this(name.to!string, "rb"); this(name.to!string, "rb");
@ -563,8 +563,8 @@ Throws: `ErrnoException` if the file could not be opened.
/// ditto /// ditto
this(R1, R2)(R1 name, R2 mode) this(R1, R2)(R1 name, R2 mode)
if (isInputRange!R1 && isSomeChar!(ElementEncodingType!R1) && if (isSomeFiniteCharInputRange!R1 &&
isInputRange!R2 && isSomeChar!(ElementEncodingType!R2)) isSomeFiniteCharInputRange!R2)
{ {
import std.conv : to; import std.conv : to;
this(name.to!string, mode.to!string); this(name.to!string, mode.to!string);
@ -4642,8 +4642,8 @@ if (isSomeChar!C && is(Unqual!C == C) && !is(C == enum) &&
* with appropriately-constructed C-style strings. * with appropriately-constructed C-style strings.
*/ */
private FILE* _fopen(R1, R2)(R1 name, R2 mode = "r") private FILE* _fopen(R1, R2)(R1 name, R2 mode = "r")
if ((isInputRange!R1 && isSomeChar!(ElementEncodingType!R1) || isSomeString!R1) && if ((isSomeFiniteCharInputRange!R1 || isSomeString!R1) &&
(isInputRange!R2 && isSomeChar!(ElementEncodingType!R2) || isSomeString!R2)) (isSomeFiniteCharInputRange!R2 || isSomeString!R2))
{ {
import std.internal.cstring : tempCString; import std.internal.cstring : tempCString;
@ -4684,8 +4684,8 @@ version (Posix)
* with appropriately-constructed C-style strings. * with appropriately-constructed C-style strings.
*/ */
FILE* _popen(R1, R2)(R1 name, R2 mode = "r") @trusted nothrow @nogc FILE* _popen(R1, R2)(R1 name, R2 mode = "r") @trusted nothrow @nogc
if ((isInputRange!R1 && isSomeChar!(ElementEncodingType!R1) || isSomeString!R1) && if ((isSomeFiniteCharInputRange!R1 || isSomeString!R1) &&
(isInputRange!R2 && isSomeChar!(ElementEncodingType!R2) || isSomeString!R2)) (isSomeFiniteCharInputRange!R2 || isSomeString!R2))
{ {
import std.internal.cstring : tempCString; import std.internal.cstring : tempCString;

View file

@ -65,9 +65,9 @@ module std.utf;
import std.exception : basicExceptionCtors; import std.exception : basicExceptionCtors;
import core.exception : UnicodeException; import core.exception : UnicodeException;
import std.meta : AliasSeq; import std.meta : AliasSeq;
import std.range.primitives; import std.range;
import std.traits : isAutodecodableString, isPointer, isSomeChar, import std.traits : isAutodecodableString, isConvertibleToString, isPointer,
isSomeString, isStaticArray, Unqual, isConvertibleToString; isSomeChar, isSomeString, isStaticArray, Unqual;
import std.typecons : Flag, Yes, No; import std.typecons : Flag, Yes, No;
@ -2809,7 +2809,7 @@ if (isSomeChar!C)
The number of code units in `input` when encoded to `C` The number of code units in `input` when encoded to `C`
+/ +/
size_t codeLength(C, InputRange)(InputRange input) size_t codeLength(C, InputRange)(InputRange input)
if (isInputRange!InputRange && !isInfinite!InputRange && isSomeChar!(ElementType!InputRange)) if (isSomeFiniteCharInputRange!InputRange)
{ {
alias EncType = Unqual!(ElementEncodingType!InputRange); alias EncType = Unqual!(ElementEncodingType!InputRange);
static if (isSomeString!InputRange && is(EncType == C) && is(typeof(input.length))) static if (isSomeString!InputRange && is(EncType == C) && is(typeof(input.length)))
@ -2961,7 +2961,7 @@ if (isSomeString!S)
* For a lazy, non-allocating version of these functions, see $(LREF byUTF). * For a lazy, non-allocating version of these functions, see $(LREF byUTF).
*/ */
string toUTF8(S)(S s) string toUTF8(S)(S s)
if (isInputRange!S && !isInfinite!S && isSomeChar!(ElementEncodingType!S)) if (isSomeFiniteCharInputRange!S)
{ {
return toUTFImpl!string(s); return toUTFImpl!string(s);
} }
@ -3003,7 +3003,7 @@ if (isInputRange!S && !isInfinite!S && isSomeChar!(ElementEncodingType!S))
* For a lazy, non-allocating version of these functions, see $(LREF byUTF). * For a lazy, non-allocating version of these functions, see $(LREF byUTF).
*/ */
wstring toUTF16(S)(S s) wstring toUTF16(S)(S s)
if (isInputRange!S && !isInfinite!S && isSomeChar!(ElementEncodingType!S)) if (isSomeFiniteCharInputRange!S)
{ {
return toUTFImpl!wstring(s); return toUTFImpl!wstring(s);
} }
@ -3047,7 +3047,7 @@ if (isInputRange!S && !isInfinite!S && isSomeChar!(ElementEncodingType!S))
* For a lazy, non-allocating version of these functions, see $(LREF byUTF). * For a lazy, non-allocating version of these functions, see $(LREF byUTF).
*/ */
dstring toUTF32(S)(scope S s) dstring toUTF32(S)(scope S s)
if (isInputRange!S && !isInfinite!S && isSomeChar!(ElementEncodingType!S)) if (isSomeFiniteCharInputRange!S)
{ {
return toUTFImpl!dstring(s); return toUTFImpl!dstring(s);
} }