mirror of
https://github.com/dlang/phobos.git
synced 2025-05-13 07:39:15 +03:00
Made Appender instantiable with string and other arrays with immutable elements. Also now Appender appends ranges to arrays wherever applicable.
This commit is contained in:
parent
2a1def14ff
commit
e112df9d98
1 changed files with 50 additions and 69 deletions
119
std/array.d
119
std/array.d
|
@ -4,12 +4,8 @@ module std.array;
|
||||||
|
|
||||||
import std.c.stdio;
|
import std.c.stdio;
|
||||||
import core.memory;
|
import core.memory;
|
||||||
import std.contracts;
|
import std.algorithm, std.contracts, std.conv, std.encoding, std.range,
|
||||||
import std.traits;
|
std.string, std.traits, std.typecons;
|
||||||
import std.string;
|
|
||||||
import std.algorithm;
|
|
||||||
import std.encoding;
|
|
||||||
import std.typecons;
|
|
||||||
version(unittest) private import std.stdio;
|
version(unittest) private import std.stdio;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -430,7 +426,7 @@ recommended over $(D a ~= data) because it is more efficient.
|
||||||
|
|
||||||
Example:
|
Example:
|
||||||
----
|
----
|
||||||
auto arr = new char[0];
|
string arr;
|
||||||
auto app = appender(&arr);
|
auto app = appender(&arr);
|
||||||
string b = "abcdefg";
|
string b = "abcdefg";
|
||||||
foreach (char c; b) app.put(c);
|
foreach (char c; b) app.put(c);
|
||||||
|
@ -447,7 +443,7 @@ assert(app2.data == [ 1, 2, 3, 4, 5, 6 ]);
|
||||||
struct Appender(A : T[], T)
|
struct Appender(A : T[], T)
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
T[] * pArray;
|
Unqual!(T)[] * pArray;
|
||||||
size_t _capacity;
|
size_t _capacity;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
@ -459,10 +455,9 @@ will allocate and use a new array.
|
||||||
*/
|
*/
|
||||||
this(T[] * p)
|
this(T[] * p)
|
||||||
{
|
{
|
||||||
pArray = p;
|
pArray = cast(Unqual!(T)[] *) p;
|
||||||
if (!pArray) pArray = (new typeof(*pArray)[1]).ptr;
|
if (!pArray) pArray = (new typeof(*pArray)[1]).ptr;
|
||||||
_capacity = GC.sizeOf(pArray.ptr) / T.sizeof;
|
_capacity = GC.sizeOf(pArray.ptr) / T.sizeof;
|
||||||
//_capacity = .capacity(pArray.ptr) / T.sizeof;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -470,7 +465,7 @@ Returns the managed array.
|
||||||
*/
|
*/
|
||||||
T[] data()
|
T[] data()
|
||||||
{
|
{
|
||||||
return pArray ? *pArray : null;
|
return cast(typeof(return)) (pArray ? *pArray : null);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -478,82 +473,68 @@ Returns the capacity of the array (the maximum number of elements the
|
||||||
managed array can accommodate before triggering a reallocation).
|
managed array can accommodate before triggering a reallocation).
|
||||||
*/
|
*/
|
||||||
size_t capacity() const { return _capacity; }
|
size_t capacity() const { return _capacity; }
|
||||||
|
|
||||||
static if (is(const(T) : T))
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
An alias for the accepted type to be appended.
|
|
||||||
*/
|
|
||||||
alias const(T) AcceptedElementType;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
alias T AcceptedElementType;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Appends one item to the managed array.
|
Appends one item to the managed array.
|
||||||
*/
|
*/
|
||||||
void put(AcceptedElementType item)
|
void put(U)(U item) if (isImplicitlyConvertible!(U, T) ||
|
||||||
|
isSomeString!(T[]) && isSomeString!(U[]))
|
||||||
{
|
{
|
||||||
if (!pArray) pArray = (new typeof(*pArray)[1]).ptr;
|
static if (isSomeString!(T[]) && T.sizeof != U.sizeof)
|
||||||
if (pArray.length < _capacity)
|
|
||||||
{
|
{
|
||||||
// Should do in-place construction here
|
// must do some transcoding around here
|
||||||
pArray.ptr[pArray.length] = item;
|
encode!(T)(item, this);
|
||||||
*pArray = pArray.ptr[0 .. pArray.length + 1];
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Time to reallocate, do it and cache capacity
|
if (!pArray) pArray = (new typeof(*pArray)[1]).ptr;
|
||||||
*pArray ~= item;
|
if (pArray.length < _capacity)
|
||||||
//_capacity = .capacity(pArray.ptr) / T.sizeof;
|
{
|
||||||
_capacity = GC.sizeOf(pArray.ptr) / T.sizeof;
|
// Should do in-place construction here
|
||||||
|
pArray.ptr[pArray.length] = item;
|
||||||
|
*pArray = pArray.ptr[0 .. pArray.length + 1];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Time to reallocate, do it and cache capacity
|
||||||
|
*pArray ~= item;
|
||||||
|
_capacity = GC.sizeOf(pArray.ptr) / T.sizeof;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Appends another array to the managed array.
|
Appends an entire range to the managed array.
|
||||||
*/
|
*/
|
||||||
void put(AcceptedElementType[] items)
|
void put(Range)(Range items) if (isForwardRange!Range
|
||||||
|
&& is(typeof(Appender.init.put(ElementType!(Range).init))))
|
||||||
{
|
{
|
||||||
for (; !items.empty(); items.popFront()) {
|
// @@@ UNCOMMENT WHEN BUG 2912 IS FIXED @@@
|
||||||
put(items.front());
|
// static if (is(typeof(*cast(T[]*) pArray ~= items)))
|
||||||
}
|
// {
|
||||||
}
|
// if (!pArray) pArray = (new typeof(*pArray)[1]).ptr;
|
||||||
|
// *pArray ~= items;
|
||||||
|
// }
|
||||||
|
// else
|
||||||
|
// {
|
||||||
|
// // Generic input range
|
||||||
|
// for (; !items.empty; items.popFront)
|
||||||
|
// {
|
||||||
|
// put(items.front());
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
static if (is(Unqual!(T) == wchar) || is(Unqual!(T) == dchar))
|
// @@@ Doctored version taking BUG 2912 into account @@@
|
||||||
{
|
static if (is(typeof(*cast(T[]*) pArray ~= items)) &&
|
||||||
/**
|
T.sizeof == ElementType!Range.sizeof)
|
||||||
In case the managed array has type $(D char[]), $(D wchar[]), or $(D
|
|
||||||
dchar[]), all other character widths and arrays thereof are also
|
|
||||||
accepted.
|
|
||||||
*/
|
|
||||||
void put(in char c) { encode!(T)((&c)[0 .. 1], this); }
|
|
||||||
/// Ditto
|
|
||||||
void put(in char[] cs)
|
|
||||||
{
|
{
|
||||||
encode!(T)(cs, this);
|
if (!pArray) pArray = (new typeof(*pArray)[1]).ptr;
|
||||||
|
*pArray ~= items;
|
||||||
}
|
}
|
||||||
}
|
else
|
||||||
static if (is(Unqual!(T) == char) || is(Unqual!(T) == dchar))
|
|
||||||
{
|
|
||||||
/// Ditto
|
|
||||||
void put(in wchar dc) { assert(false); }
|
|
||||||
/// Ditto
|
|
||||||
void put(in wchar[] dcs)
|
|
||||||
{
|
{
|
||||||
encode!(T)(dcs, this);
|
// Generic input range
|
||||||
}
|
foreach (e; items) put(e);
|
||||||
}
|
|
||||||
static if (is(Unqual!(T) == char) || is(Unqual!(T) == wchar))
|
|
||||||
{
|
|
||||||
/// Ditto
|
|
||||||
void put(in dchar dc) { std.utf.encode(*pArray, dc); }
|
|
||||||
/// Ditto
|
|
||||||
void put(in dchar[] wcs)
|
|
||||||
{
|
|
||||||
encode!(T)(wcs, this);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -589,7 +570,7 @@ unittest
|
||||||
int[] a = [ 1, 2 ];
|
int[] a = [ 1, 2 ];
|
||||||
auto app2 = appender(&a);
|
auto app2 = appender(&a);
|
||||||
app2.put(3);
|
app2.put(3);
|
||||||
app2.put([ 4, 5, 6 ]);
|
app2.put([ 4, 5, 6 ][]);
|
||||||
assert(app2.data == [ 1, 2, 3, 4, 5, 6 ]);
|
assert(app2.data == [ 1, 2, 3, 4, 5, 6 ]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue