Improvements to replicate(); documented splitter() for strings; renamed replace() in place to replaceInPlace(); removed replace() that takes void* in the last position; moved replace() from string to array and generalized it; attached constraint to functional.not; more cleanup of std.string; improved std.algorithm.util and count to accept ranges; improved constraint in std.algorithm.remove

This commit is contained in:
Andrei Alexandrescu 2011-01-21 08:39:39 +00:00
parent 6c89581e2f
commit 272ceaa9a6
5 changed files with 173 additions and 161 deletions

View file

@ -805,10 +805,9 @@ assert(r1 == [ 2.5 ]);
*/ */
template filter(alias pred) template filter(alias pred)
{ {
Filter!(unaryFun!(pred), Range) auto filter(Range)(Range rs)
filter(Range)(Range rs)
{ {
return typeof(return)(rs); return Filter!(unaryFun!(pred), Range)(rs);
} }
} }
@ -1790,7 +1789,7 @@ if(!is(isTerminator))
_input.popFront(); _input.popFront();
} }
assert(!_input.empty && !_isTerminator(_input.front)); assert(!_input.empty && !_isTerminator(_input.front));
// Prime _end // Prepare _end
_end = 1; _end = 1;
while (_end < _input.length && !_isTerminator(_input[_end])) while (_end < _input.length && !_isTerminator(_input[_end]))
{ {
@ -1967,7 +1966,6 @@ if (isForwardRange!RoR && isInputRange!(ElementType!RoR)
if (!_current.empty) return; if (!_current.empty) return;
useSeparator(); useSeparator();
} }
// We need to re-prime the range
} }
static if (isForwardRange!RoR && isForwardRange!(ElementType!RoR)) static if (isForwardRange!RoR && isForwardRange!(ElementType!RoR))
@ -2009,7 +2007,7 @@ if (isInputRange!RoR && isInputRange!(ElementType!RoR))
private: private:
RoR _items; RoR _items;
ElementType!RoR _current; ElementType!RoR _current;
void prime() void prepare()
{ {
for (;; _items.popFront()) for (;; _items.popFront())
{ {
@ -2023,7 +2021,7 @@ if (isInputRange!RoR && isInputRange!(ElementType!RoR))
this(RoR r) this(RoR r)
{ {
_items = r; _items = r;
prime(); prepare();
} }
static if (isInfinite!(ElementType!RoR)) static if (isInfinite!(ElementType!RoR))
{ {
@ -2045,7 +2043,7 @@ if (isInputRange!RoR && isInputRange!(ElementType!RoR))
{ {
assert(!_current.empty); assert(!_current.empty);
_current.popFront(); _current.popFront();
if (_current.empty) prime(); if (_current.empty) prepare();
} }
static if (isForwardRange!RoR && isForwardRange!(ElementType!RoR)) static if (isForwardRange!RoR && isForwardRange!(ElementType!RoR))
{ {
@ -2565,7 +2563,7 @@ if (isRandomAccessRange!R1 && isForwardRange!R2 && !isBidirectionalRange!R2
} }
else else
{ {
// Prime the search with needle's first element // Prepare the search with needle's first element
if (needle.empty) return haystack; if (needle.empty) return haystack;
haystack = .find!pred(haystack, needle.front); haystack = .find!pred(haystack, needle.front);
if (haystack.empty) return haystack; if (haystack.empty) return haystack;
@ -3200,7 +3198,7 @@ struct Until(alias pred, Range, Sentinel) if (isInputRange!Range)
static if (is(Sentinel == void)) static if (is(Sentinel == void))
return unaryFun!pred(_input.front); return unaryFun!pred(_input.front);
else else
return binaryFun!pred(_input.front, _sentinel); return startsWith!pred(_input, _sentinel);
} }
void popFront() void popFront()
@ -3274,6 +3272,7 @@ unittest
static assert(isForwardRange!(typeof(until!"a == 2"(a, OpenRight.no)))); static assert(isForwardRange!(typeof(until!"a == 2"(a, OpenRight.no))));
assert(equal(a.until(7), [1, 2, 4][])); assert(equal(a.until(7), [1, 2, 4][]));
assert(equal(a.until([7, 2]), [1, 2, 4, 7][]));
assert(equal(a.until(7, OpenRight.no), [1, 2, 4, 7][])); assert(equal(a.until(7, OpenRight.no), [1, 2, 4, 7][]));
assert(equal(until!"a == 2"(a, OpenRight.no), [1, 2][])); assert(equal(until!"a == 2"(a, OpenRight.no), [1, 2][]));
} }
@ -3736,18 +3735,33 @@ unittest
// count // count
/** /**
Counts the number of elements $(D x) in $(D r) for which $(D pred(x, The first version counts the number of elements $(D x) in $(D r) for
value)) is $(D true). $(D pred) defaults to equality. Performs $(BIGOH which $(D pred(x, value)) is $(D true). $(D pred) defaults to
r.length) evaluations of $(D pred). equality. Performs $(BIGOH r.length) evaluations of $(D pred).
The second version returns the number of times $(D needle) occurs in
$(D haystack). Throws an exception if $(D needle.empty), as the _count
of the empty range in any range would be infinite. Overlapped counts
are not considered, for example $(D count("aaa", "aa")) is $(D 1), not
$(D 2).
The third version counts the elements for which $(D pred(x)) is $(D
true). Performs $(BIGOH r.length) evaluations of $(D pred).
Example: Example:
---- ----
// count elements in range
int[] a = [ 1, 2, 4, 3, 2, 5, 3, 2, 4 ]; int[] a = [ 1, 2, 4, 3, 2, 5, 3, 2, 4 ];
assert(count(a, 2) == 3); assert(count(a, 2) == 3);
assert(count!("a > b")(a, 2) == 5); assert(count!("a > b")(a, 2) == 5);
// count range in range
assert(count("abcadfabf", "ab") == 2);
assert(count("ababab", "abab") == 1);
assert(count("ababab", "abx") == 0);
// count predicate in range
assert(count!("a > 1")(a) == 8);
---- ----
*/ */
size_t count(alias pred = "a == b", Range, E)(Range r, E value) size_t count(alias pred = "a == b", Range, E)(Range r, E value)
if (isInputRange!Range && is(typeof(binaryFun!pred(r.front, value)) == bool)) if (isInputRange!Range && is(typeof(binaryFun!pred(r.front, value)) == bool))
{ {
@ -3773,20 +3787,15 @@ unittest
assert(count!("a == '語'")("日本語"d) == 1); assert(count!("a == '語'")("日本語"d) == 1);
} }
/** unittest
* Returns the number of times $(D needle) occurs in $(D {
* haystack). Throws an exception if $(D needle.empty), as the _count debug(std_algorithm) printf("algorithm.count.unittest\n");
* of the empty range in any range would be infinite. Overlapped string s = "This is a fofofof list";
* counts are not considered, for example $(D count("aaa", "aa")) is string sub = "fof";
* $(D 1), not $(D 2). assert(count(s, sub) == 2);
* }
* Example:
---- /// Ditto
assert(count("abcadfabf", "ab") == 2);
assert(count("ababab", "abab") == 1);
assert(count("ababab", "abx") == 0);
----
*/
size_t count(alias pred = "a == b", R1, R2)(R1 haystack, R2 needle) size_t count(alias pred = "a == b", R1, R2)(R1 haystack, R2 needle)
if (isInputRange!R1 && isForwardRange!R2 && is(typeof(binaryFun!pred(haystack, needle)) == bool)) if (isInputRange!R1 && isForwardRange!R2 && is(typeof(binaryFun!pred(haystack, needle)) == bool))
{ {
@ -3805,16 +3814,7 @@ unittest
assert(count("ababab", "abx") == 0); assert(count("ababab", "abx") == 0);
} }
/** /// Ditto
Counts the number of elements $(D x) in $(D r) for which $(D pred(x))
is $(D true). Performs $(BIGOH r.length) evaluations of $(D pred).
Example:
----
int[] a = [ 1, 2, 4, 3, 2, 5, 3, 2, 4 ];
assert(count!("a > 1")(a) == 8);
----
*/
size_t count(alias pred = "true", Range)(Range r) if (isInputRange!(Range)) size_t count(alias pred = "true", Range)(Range r) if (isInputRange!(Range))
{ {
size_t result; size_t result;
@ -5045,7 +5045,8 @@ cases.))
Range remove Range remove
(SwapStrategy s = SwapStrategy.stable, Range, Offset...) (SwapStrategy s = SwapStrategy.stable, Range, Offset...)
(Range range, Offset offset) (Range range, Offset offset)
if (isBidirectionalRange!Range && hasLength!Range && s != SwapStrategy.stable) if (isBidirectionalRange!Range && hasLength!Range && s != SwapStrategy.stable
&& Offset.length >= 1)
{ {
enum bool tupleLeft = is(typeof(offset[0][0])) enum bool tupleLeft = is(typeof(offset[0][0]))
&& is(typeof(offset[0][1])); && is(typeof(offset[0][1]));
@ -5150,8 +5151,9 @@ if (isBidirectionalRange!Range && hasLength!Range && s != SwapStrategy.stable)
Range remove Range remove
(SwapStrategy s = SwapStrategy.stable, Range, Offset...) (SwapStrategy s = SwapStrategy.stable, Range, Offset...)
(Range range, Offset offset) (Range range, Offset offset)
if (isForwardRange!Range && !isBidirectionalRange!Range if ((isForwardRange!Range && !isBidirectionalRange!Range
|| !hasLength!Range || s == SwapStrategy.stable) || !hasLength!Range || s == SwapStrategy.stable)
&& Offset.length >= 1)
{ {
auto result = range; auto result = range;
auto src = range, tgt = range; auto src = range, tgt = range;

View file

@ -5,6 +5,8 @@ Copyright: Copyright Andrei Alexandrescu 2008-.
License: $(WEB boost.org/LICENSE_1_0.txt, Boost License 1.0). License: $(WEB boost.org/LICENSE_1_0.txt, Boost License 1.0).
Authors: $(WEB erdani.org, Andrei Alexandrescu) Authors: $(WEB erdani.org, Andrei Alexandrescu)
Functions and types that manipulate built-in arrays.
*/ */
module std.array; module std.array;
@ -190,12 +192,14 @@ assert(b is a);
Implements the range interface primitive $(D popFront) for built-in Implements the range interface primitive $(D popFront) for built-in
arrays. Due to the fact that nonmember functions can be called with arrays. Due to the fact that nonmember functions can be called with
the first argument using the dot notation, $(D array.popFront) is the first argument using the dot notation, $(D array.popFront) is
equivalent to $(D popFront(array)). equivalent to $(D popFront(array)). For $(GLOSSARY narrow strings),
$(D popFront) automaticaly advances to the next $(GLOSSARY code
point).
Example: Example:
---- ----
int[] a = [ 1, 2, 3 ]; int[] a = [ 1, 2, 3 ];
a.popFront; a.popFront();
assert(a == [ 2, 3 ]); assert(a == [ 2, 3 ]);
---- ----
*/ */
@ -217,6 +221,7 @@ unittest
static assert(!__traits(compiles, popFront!(void[]))); static assert(!__traits(compiles, popFront!(void[])));
} }
// Specialization for narrow strings
void popFront(A)(ref A a) void popFront(A)(ref A a)
if (isNarrowString!A && isMutable!A) if (isNarrowString!A && isMutable!A)
{ {
@ -243,7 +248,8 @@ unittest
Implements the range interface primitive $(D popBack) for built-in Implements the range interface primitive $(D popBack) for built-in
arrays. Due to the fact that nonmember functions can be called with arrays. Due to the fact that nonmember functions can be called with
the first argument using the dot notation, $(D array.popBack) is the first argument using the dot notation, $(D array.popBack) is
equivalent to $(D popBack(array)). equivalent to $(D popBack(array)). For $(GLOSSARY narrow strings), $(D
popFront) automaticaly eliminates the last $(GLOSSARY code point).
Example: Example:
@ -270,6 +276,7 @@ unittest
static assert(!__traits(compiles, popBack!(void[]))); static assert(!__traits(compiles, popBack!(void[])));
} }
// Specialization for arrays of char
@trusted void popBack(A)(ref A a) @trusted void popBack(A)(ref A a)
if (is(A : const(char)[]) && isMutable!A) if (is(A : const(char)[]) && isMutable!A)
{ {
@ -311,6 +318,7 @@ unittest
static assert(!__traits(compiles, popBack!(immutable char[]))); static assert(!__traits(compiles, popBack!(immutable char[])));
} }
// Specialization for arrays of wchar
@trusted void popBack(A)(ref A a) @trusted void popBack(A)(ref A a)
if (is(A : const(wchar)[]) && isMutable!A) if (is(A : const(wchar)[]) && isMutable!A)
{ {
@ -338,7 +346,9 @@ unittest
Implements the range interface primitive $(D front) for built-in Implements the range interface primitive $(D front) for built-in
arrays. Due to the fact that nonmember functions can be called with arrays. Due to the fact that nonmember functions can be called with
the first argument using the dot notation, $(D array.front) is the first argument using the dot notation, $(D array.front) is
equivalent to $(D front(array)). equivalent to $(D front(array)). For $(GLOSSARY narrow strings), $(D
front) automaticaly returns the first $(GLOSSARY code point) as a $(D
dchar).
Example: Example:
@ -373,7 +383,9 @@ unittest
Implements the range interface primitive $(D back) for built-in Implements the range interface primitive $(D back) for built-in
arrays. Due to the fact that nonmember functions can be called with arrays. Due to the fact that nonmember functions can be called with
the first argument using the dot notation, $(D array.back) is the first argument using the dot notation, $(D array.back) is
equivalent to $(D back(array)). equivalent to $(D back(array)). For $(GLOSSARY narrow strings), $(D
back) automaticaly returns the last $(GLOSSARY code point) as a $(D
dchar).
Example: Example:
---- ----
@ -381,9 +393,7 @@ int[] a = [ 1, 2, 3 ];
assert(a.back == 3); assert(a.back == 3);
---- ----
*/ */
ref typeof(A.init[0]) back(A)(A a) ref T back(T)(T[] a) if (!isNarrowString!(T[]))
if (isDynamicArray!A && !isNarrowString!A
&& !is(typeof(A.init[0]) : const(void)))
{ {
assert(a.length, "Attempting to fetch the back of an empty array"); assert(a.length, "Attempting to fetch the back of an empty array");
return a[$ - 1]; return a[$ - 1];
@ -397,36 +407,35 @@ unittest
assert(a.back == 7); assert(a.back == 7);
} }
// Specialization for strings
dchar back(A)(A a) dchar back(A)(A a)
if (isDynamicArray!A && isNarrowString!A) if (isDynamicArray!A && isNarrowString!A)
{ {
assert(a.length, "Attempting to fetch the back of an empty array");
auto n = a.length; auto n = a.length;
const p = a.ptr + n; const p = a.ptr + n;
if (n >= 1 && (p[-1] & 0b1100_0000) != 0b1000_0000) if (n >= 1 && (p[-1] & 0b1100_0000) != 0b1000_0000)
{ {
--n; --n;
return decode(a, n);
} }
else if (n >= 2 && (p[-2] & 0b1100_0000) != 0b1000_0000) else if (n >= 2 && (p[-2] & 0b1100_0000) != 0b1000_0000)
{ {
n -= 2; n -= 2;
return decode(a, n);
} }
else if (n >= 3 && (p[-3] & 0b1100_0000) != 0b1000_0000) else if (n >= 3 && (p[-3] & 0b1100_0000) != 0b1000_0000)
{ {
n -= 3; n -= 3;
return decode(a, n);
} }
else if (n >= 4 && (p[-4] & 0b1100_0000) != 0b1000_0000) else if (n >= 4 && (p[-4] & 0b1100_0000) != 0b1000_0000)
{ {
n -= 4; n -= 4;
return decode(a, n);
} }
else else
{ {
throw new UtfException("Invalid UTF character at end of string"); throw new UtfException(a.length
? "Invalid UTF character at end of string"
: "Attempting to fetch the back of an empty array");
} }
return decode(a, n);
} }
// overlap // overlap
@ -448,8 +457,8 @@ assert(overlap(a, b).empty);
*/ */
T[] overlap(T)(T[] r1, T[] r2) @trusted pure nothrow T[] overlap(T)(T[] r1, T[] r2) @trusted pure nothrow
{ {
T* max(T* a, T* b) nothrow { return a > b ? a : b; } static T* max(T* a, T* b) nothrow { return a > b ? a : b; }
T* min(T* a, T* b) nothrow { return a < b ? a : b; } static T* min(T* a, T* b) nothrow { return a < b ? a : b; }
auto b = max(r1.ptr, r2.ptr); auto b = max(r1.ptr, r2.ptr);
auto e = min(r1.ptr + r1.length, r2.ptr + r2.length); auto e = min(r1.ptr + r1.length, r2.ptr + r2.length);
return b < e ? b[0 .. e - b] : null; return b < e ? b[0 .. e - b] : null;
@ -471,18 +480,14 @@ unittest
} }
/** /**
Inserts $(D stuff) in $(D container) at position $(D pos). Inserts $(D stuff) (which must be an input range or a single item) in
$(D array) at position $(D pos).
*/ */
void insert(T, Range)(ref T[] array, size_t pos, Range stuff) void insert(T, Range)(ref T[] array, size_t pos, Range stuff)
if (isInputRange!Range && is(ElementEncodingType!Range : T)) if (isInputRange!Range && is(ElementEncodingType!Range : T))
{ {
static if (hasLength!Range) static if (hasLength!Range)
{ {
// @@@BUG 2130@@@
// immutable
// size_t delta = toInsert.length,
// size_t oldLength = array.length,
// size_t newLength = oldLength + delta;
immutable immutable
delta = stuff.length, delta = stuff.length,
oldLength = array.length, oldLength = array.length,
@ -535,10 +540,12 @@ pure bool sameHead(T)(in T[] lhs, in T[] rhs)
} }
/******************************************** /********************************************
* Return an array that consists of $(D s) (which must be an input Returns an array that consists of $(D s) (which must be an input
* range) repeated $(D n) times. range) repeated $(D n) times. This function allocates, fills, and
returns a new array. For a lazy version, refer to $(XREF
range,repeat).
*/ */
S replicate(S)(S s, size_t n) if (isSomeString!S) S replicate(S)(S s, size_t n) if (isDynamicArray!S)
{ {
// Optimization for return join(std.range.repeat(s, n)); // Optimization for return join(std.range.repeat(s, n));
if (n == 0) if (n == 0)
@ -550,8 +557,8 @@ S replicate(S)(S s, size_t n) if (isSomeString!S)
r[] = s[0]; r[] = s[0];
else else
{ {
auto len = s.length; immutable len = s.length, nlen = n * len;
for (size_t i = 0; i < n * len; i += len) for (size_t i = 0; i < nlen; i += len)
{ {
r[i .. i + len] = s[]; r[i .. i + len] = s[];
} }
@ -560,7 +567,7 @@ S replicate(S)(S s, size_t n) if (isSomeString!S)
} }
ElementType!S[] replicate(S)(S s, size_t n) ElementType!S[] replicate(S)(S s, size_t n)
if (isInputRange!S && !isSomeString!S) if (isInputRange!S && !isDynamicArray!S)
{ {
return join(std.range.repeat(s, n)); return join(std.range.repeat(s, n));
} }
@ -590,7 +597,9 @@ unittest
} }
/************************************** /**************************************
Split $(D s[]) into an array of words, using whitespace as delimiter. Split the string $(D s) into an array of words, using whitespace as
delimiter. Runs of whitespace are merged together (no empty words are
produced).
*/ */
S[] split(S)(S s) if (isSomeString!S) S[] split(S)(S s) if (isSomeString!S)
@ -629,22 +638,21 @@ unittest
foreach (S; TypeTuple!(string, wstring, dstring)) foreach (S; TypeTuple!(string, wstring, dstring))
{ {
debug(string) printf("string.split1\n"); debug(string) printf("string.split1\n");
S s = " \t\npeter paul\tjerry \n";
S s = " peter paul\tjerry "; assert(equal(split(s), [ to!S("peter"), to!S("paul"), to!S("jerry") ]));
S[] words;
int i;
words = split(s);
assert(words.length == 3);
i = cmp(words[0], "peter");
assert(i == 0);
i = cmp(words[1], "paul");
assert(i == 0);
i = cmp(words[2], "jerry");
assert(i == 0);
} }
} }
/**
Splits a string by whitespace.
Example:
----
auto a = " a bcd ef gh ";
assert(equal(splitter(a), ["", "a", "bcd", "ef", "gh"][]));
----
*/
auto splitter(String)(String s) if (isSomeString!String) auto splitter(String)(String s) if (isSomeString!String)
{ {
return std.algorithm.splitter!isspace(s); return std.algorithm.splitter!isspace(s);
@ -659,7 +667,7 @@ unittest
} }
/************************************** /**************************************
* Split $(D r) into an array, using $(D delim) as the delimiter. * Splits $(D s) into an array, using $(D delim) as the delimiter.
*/ */
Unqual!(S1)[] split(S1, S2)(S1 s, S2 delim) Unqual!(S1)[] split(S1, S2)(S1 s, S2 delim)
if (isForwardRange!(Unqual!S1) && isForwardRange!S2) if (isForwardRange!(Unqual!S1) && isForwardRange!S2)
@ -810,7 +818,7 @@ Replaces elements from $(D array) with indices ranging from $(D from)
(inclusive) to $(D to) (exclusive) with the range $(D stuff). Expands (inclusive) to $(D to) (exclusive) with the range $(D stuff). Expands
or shrinks the array as needed. or shrinks the array as needed.
*/ */
void replace(T, Range)(ref T[] array, size_t from, size_t to, Range stuff) void replaceInPlace(T, Range)(ref T[] array, size_t from, size_t to, Range stuff)
if (isDynamicArray!Range && is(ElementType!Range : T)) if (isDynamicArray!Range && is(ElementType!Range : T))
{ {
if (overlap(array, stuff)) if (overlap(array, stuff))
@ -837,52 +845,45 @@ if (isDynamicArray!Range && is(ElementType!Range : T))
} }
} }
void replace(T, Range)(ref T[] array, size_t from, size_t to, Range stuff)
if (!is(ElementType!Range == T) && is(Unqual!Range == void*))
{
replace(array, from, to, cast(T[])[]);
}
unittest unittest
{ {
int[] a = [1, 4, 5]; int[] a = [1, 4, 5];
replace(a, 1u, 2u, [2, 3, 4]); replaceInPlace(a, 1u, 2u, [2, 3, 4]);
assert(a == [1, 2, 3, 4, 5]); assert(a == [1, 2, 3, 4, 5]);
replace(a, 1u, 2u, cast(int[])[]); replaceInPlace(a, 1u, 2u, cast(int[])[]);
assert(a == [1, 3, 4, 5]); assert(a == [1, 3, 4, 5]);
replace(a, 1u, 2u, null);
assert(a == [1, 4, 5]);
} }
/******************************************** /********************************************
* Replace occurrences of from[] with to[] in s[]. * Replace occurrences of $(D from) with $(D to) in $(D a). Returns a
* new array.
*/ */
C1[] replace(C1, C2, C3)(C1[] s, C2[] from, C3[] to) R1 replace(R1, R2, R3)(R1 subject, R2 from, R3 to)
//if (is(typeof(s[0] == from[0])) && is(typeof(to[0]) : C1)) if (isDynamicArray!R1 && isForwardRange!R2 && isForwardRange!R3)
{ {
if (from.length == 0) return s; if (from.empty) return subject;
typeof(s.dup) p; auto app = appender!R1();
for (;;) for (;;)
{ {
auto s1 = std.algorithm.find(s, from); auto balance = std.algorithm.find(subject, from.save);
if (!s1.length) if (balance.empty)
{ {
if (p is null) return s; if (app.data.empty) return subject;
p ~= s; app.put(subject);
break; break;
} }
p ~= s[0 .. s.length - s1.length]; app.put(subject[0 .. subject.length - balance.length]);
p ~= to; app.put(to.save);
s = s1[from.length .. $]; subject = balance[from.length .. $];
} }
return cast(C1[]) p; return app.data;
} }
unittest unittest
{ {
debug(string) printf("string.replace.unittest\n"); debug(string) printf("array.replace.unittest\n");
alias TypeTuple!(string, wstring, dstring, char[], wchar[], dchar[]) alias TypeTuple!(string, wstring, dstring, char[], wchar[], dchar[])
TestTypes; TestTypes;
@ -908,8 +909,8 @@ unittest
} }
/***************************** /*****************************
* Return an array that is $(D s[]) with $(D slice[]) replaced by $(D Return an array that is $(D s) with $(D slice) replaced by $(D
* replacement[]). replacement[]).
*/ */
T[] replaceSlice(T)(T[] s, in T[] slice, in T[] replacement) T[] replaceSlice(T)(T[] s, in T[] slice, in T[] replacement)
@ -1020,7 +1021,8 @@ done.
else else
{ {
// didn't work, must reallocate // didn't work, must reallocate
auto bi = GC.qalloc(newCapacity * T.sizeof, (typeid(T[]).next.flags & 1) ? 0 : GC.BlkAttr.NO_SCAN); auto bi = GC.qalloc(newCapacity * T.sizeof,
(typeid(T[]).next.flags & 1) ? 0 : GC.BlkAttr.NO_SCAN);
_data.capacity = bi.size / T.sizeof; _data.capacity = bi.size / T.sizeof;
if(len) if(len)
memcpy(bi.base, _data.arr.ptr, len * T.sizeof); memcpy(bi.base, _data.arr.ptr, len * T.sizeof);
@ -1071,7 +1073,8 @@ Returns the managed array.
else else
{ {
// didn't work, must reallocate // didn't work, must reallocate
auto bi = GC.qalloc(newlen * T.sizeof, (typeid(T[]).next.flags & 1) ? 0 : GC.BlkAttr.NO_SCAN); auto bi = GC.qalloc(newlen * T.sizeof,
(typeid(T[]).next.flags & 1) ? 0 : GC.BlkAttr.NO_SCAN);
_data.capacity = bi.size / T.sizeof; _data.capacity = bi.size / T.sizeof;
if(len) if(len)
memcpy(bi.base, _data.arr.ptr, len * T.sizeof); memcpy(bi.base, _data.arr.ptr, len * T.sizeof);

View file

@ -278,9 +278,9 @@ string a = " Hello, world!";
assert(find!(not!isspace)(a) == "Hello, world!"); assert(find!(not!isspace)(a) == "Hello, world!");
---- ----
*/ */
template not(alias pred) template not(alias pred) if (is(typeof(!unaryFun!pred(args))))
{ {
bool not(T...)(T args) { return !pred(args); } auto not(T...)(T args) { return !binaryFun!pred(args); }
} }
/** /**

View file

@ -80,7 +80,7 @@ version(Posix)
version (Windows) alias std.string.icmp fcmp; version (Windows) alias std.string.icmp fcmp;
version (Posix) alias std.string.cmp fcmp; version (Posix) alias std.algorithm.cmp fcmp;
/************************** /**************************
* Extracts the extension from a filename or path. * Extracts the extension from a filename or path.

View file

@ -8,31 +8,62 @@
are preferable because they don't exhibit undesired aliasing, thus are preferable because they don't exhibit undesired aliasing, thus
making code more robust. making code more robust.
Macros: Macros: WIKI = Phobos/StdString
WIKI = Phobos/StdString
Copyright: Copyright Digital Mars 2007-.
License: $(WEB boost.org/LICENSE_1_0.txt, Boost License 1.0).
Authors: $(WEB digitalmars.com, Walter Bright), $(WEB erdani.org,
Andrei Alexandrescu)
$(B $(RED IMPORTANT NOTE:)) Beginning with version 2.052, the
following symbols have been generalized beyond strings and moved to
different modules. This action was prompted by the fact that
generalized routines belong better in other places, although they
still work for strings as expected. In order to use moved symbols, you
will need to import the respective modules as follows:
$(BOOKTABLE ,
$(TR $(TH Symbol) $(TH Comment))
$(TR $(TD $(D cmp)) $(TD Moved to $(XREF algorithm, cmp) and
generalized to work for all input ranges and accept a custom
predicate.))
$(TR $(TD $(D count)) $(TD Moved to $(XREF algorithm, count) and
generalized to accept a custom predicate.))
$(TR $(TD $(D replace)) $(TD Moved to $(XREF array, replace).))
$(TR $(TD $(D ByCodeUnit)) $(TD Removed.))
$(TR $(TD $(D insert)) $(TD Use $(XREF array, insert) instead.))
$(TR $(TD $(D join)) $(TD Use $(XREF array, join) instead.))
$(TR $(TD $(D repeat)) $(TD Use $(XREF array, replicate) instead.))
$(TR $(TD $(D replace)) $(TD Use $(XREF array, replace) instead.))
$(TR $(TD $(D replaceSlice)) $(TD Use $(XREF array, replace) instead.))
$(TR $(TD $(D split)) $(TD Use $(XREF array, split) instead.))
)
Copyright: Copyright Digital Mars 2007 - 2009.
License: <a href="http: //www.boost.org/LICENSE_1_0.txt">Boost License 1.0</a>.
Authors: $(WEB digitalmars.com, Walter Bright),
$(WEB erdani.org, Andrei Alexandrescu)
*/
/*
Copyright Digital Mars 2007 - 2009.
Distributed under the Boost Software License, Version 1.0.
(See accompanying file LICENSE_1_0.txt or copy at
http: //www.boost.org/LICENSE_1_0.txt)
*/ */
module std.string; module std.string;
//debug=string; // uncomment to turn on debugging printf's //debug=string; // uncomment to turn on debugging printf's
private import core.exception : onRangeError; import core.exception : onRangeError;
import core.vararg, core.stdc.stdio, core.stdc.stdlib, import core.vararg, core.stdc.stdio, core.stdc.stdlib,
core.stdc.string, std.algorithm, core.stdc.string/*, std.algorithm*/,
std.conv, std.ctype, std.encoding, std.exception, std.format, std.conv, std.ctype, std.encoding, std.exception, std.format,
std.functional, std.metastrings, std.range, std.regex, std.stdio, std.functional, std.metastrings, std.range, std.regex, std.stdio,
std.traits, std.typetuple, std.uni, std.utf; std.traits, std.typetuple, std.uni, std.utf;
public import std.algorithm : startsWith, endsWith; public import std.algorithm : startsWith, endsWith, cmp, count;
public import std.array : join, split; public import std.array : join, split;
version(Windows) extern (C) version(Windows) extern (C)
@ -95,12 +126,6 @@ $(TR $(TD $(D > 0)) $(TD $(D s1 > s2)))
*/ */
alias std.algorithm.cmp cmp;
/*********************************
* ditto
*/
int icmp(alias pred = "a < b", S1, S2)(S1 s1, S2 s2) int icmp(alias pred = "a < b", S1, S2)(S1 s1, S2 s2)
if (is(Unqual!(ElementType!S1) == dchar) && is(Unqual!(ElementType!S2) == dchar)) if (is(Unqual!(ElementType!S1) == dchar) && is(Unqual!(ElementType!S2) == dchar))
{ {
@ -1557,24 +1582,6 @@ unittest
assert(i == 0); assert(i == 0);
} }
/***********************************************
* Count up all instances of sub[] in s[].
*/
alias std.algorithm.count count;
unittest
{
debug(string) printf("string.count.unittest\n");
string s = "This is a fofofof list";
string sub = "fof";
size_t i;
i = count(s, sub);
assert(i == 2);
}
/************************************************ /************************************************
* Replace tabs with the appropriate number of spaces. * Replace tabs with the appropriate number of spaces.
* tabsize is the distance between tab stops. * tabsize is the distance between tab stops.