Add String.reserve and shrink
This commit is contained in:
parent
074d027629
commit
885fca9b5e
@ -3,6 +3,8 @@
|
|||||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* UTF-8 string.
|
||||||
|
*
|
||||||
* Copyright: Eugene Wissner 2016-2017.
|
* Copyright: Eugene Wissner 2016-2017.
|
||||||
* License: $(LINK2 https://www.mozilla.org/en-US/MPL/2.0/,
|
* License: $(LINK2 https://www.mozilla.org/en-US/MPL/2.0/,
|
||||||
* Mozilla Public License, v. 2.0).
|
* Mozilla Public License, v. 2.0).
|
||||||
@ -12,6 +14,7 @@ module tanya.container.string;
|
|||||||
|
|
||||||
import core.exception;
|
import core.exception;
|
||||||
import core.stdc.string;
|
import core.stdc.string;
|
||||||
|
import std.algorithm.comparison;
|
||||||
import tanya.memory;
|
import tanya.memory;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -19,26 +22,27 @@ import tanya.memory;
|
|||||||
*/
|
*/
|
||||||
struct String
|
struct String
|
||||||
{
|
{
|
||||||
private char[] data;
|
|
||||||
private size_t length_;
|
private size_t length_;
|
||||||
|
private char* data;
|
||||||
|
private size_t capacity_;
|
||||||
|
|
||||||
invariant
|
invariant
|
||||||
{
|
{
|
||||||
assert(length_ <= data.length);
|
assert(length_ <= capacity_);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Ditto.
|
/**
|
||||||
|
* Params:
|
||||||
|
* str = Initial string.
|
||||||
|
* allocator = Allocator.
|
||||||
|
*/
|
||||||
this(const(char)[] str, shared Allocator allocator = defaultAllocator)
|
this(const(char)[] str, shared Allocator allocator = defaultAllocator)
|
||||||
nothrow @trusted @nogc
|
nothrow @trusted @nogc
|
||||||
{
|
{
|
||||||
this(allocator);
|
this(allocator);
|
||||||
|
reserve(str.length);
|
||||||
data = cast(char[]) allocator.allocate(str.length);
|
length_ = str.length;
|
||||||
if (str.length > 0 && data is null)
|
memcpy(data, str.ptr, length_);
|
||||||
{
|
|
||||||
onOutOfMemoryErrorNoGC();
|
|
||||||
}
|
|
||||||
memcpy(data.ptr, str.ptr, str.length);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Ditto.
|
/// Ditto.
|
||||||
@ -46,7 +50,6 @@ struct String
|
|||||||
nothrow @trusted @nogc
|
nothrow @trusted @nogc
|
||||||
{
|
{
|
||||||
this(allocator);
|
this(allocator);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Ditto.
|
/// Ditto.
|
||||||
@ -68,9 +71,108 @@ struct String
|
|||||||
allocator_ = allocator;
|
allocator_ = allocator;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Destroys the string.
|
||||||
|
*/
|
||||||
~this() nothrow @trusted @nogc
|
~this() nothrow @trusted @nogc
|
||||||
{
|
{
|
||||||
allocator.deallocate(data);
|
allocator.deallocate(data[0 .. capacity_]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reserves $(D_PARAM size) bytes for the string.
|
||||||
|
*
|
||||||
|
* If $(D_PARAM size) is less than or equal to the $(D_PSYMBOL capacity), the
|
||||||
|
* function call does not cause a reallocation and the string capacity is not
|
||||||
|
* affected.
|
||||||
|
*
|
||||||
|
* Params:
|
||||||
|
* size = Desired size in bytes.
|
||||||
|
*/
|
||||||
|
void reserve(in size_t size) nothrow @trusted @nogc
|
||||||
|
{
|
||||||
|
if (capacity_ >= size)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
void[] buf = data[0 .. capacity_];
|
||||||
|
if (!allocator.reallocate(buf, size))
|
||||||
|
{
|
||||||
|
onOutOfMemoryErrorNoGC();
|
||||||
|
}
|
||||||
|
data = cast(char*) buf;
|
||||||
|
capacity_ = size;
|
||||||
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
@nogc @safe unittest
|
||||||
|
{
|
||||||
|
String s;
|
||||||
|
assert(s.capacity == 0);
|
||||||
|
|
||||||
|
s.reserve(3);
|
||||||
|
assert(s.capacity == 3);
|
||||||
|
|
||||||
|
s.reserve(3);
|
||||||
|
assert(s.capacity == 3);
|
||||||
|
|
||||||
|
s.reserve(1);
|
||||||
|
assert(s.capacity == 3);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Requests the string to reduce its capacity to fit the $(D_PARAM size).
|
||||||
|
*
|
||||||
|
* The request is non-binding. The string won't become smaller than the
|
||||||
|
* string byte length.
|
||||||
|
*
|
||||||
|
* Params:
|
||||||
|
* size = Desired size.
|
||||||
|
*/
|
||||||
|
void shrink(in size_t size) nothrow @trusted @nogc
|
||||||
|
{
|
||||||
|
if (capacity_ <= size)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
immutable n = max(length_, size);
|
||||||
|
void[] buf = data[0 .. capacity_];
|
||||||
|
if (allocator.reallocate(buf, size))
|
||||||
|
{
|
||||||
|
capacity_ = n;
|
||||||
|
data = cast(char*) buf;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
@nogc @safe unittest
|
||||||
|
{
|
||||||
|
auto s = String("Die Alten lasen laut.");
|
||||||
|
assert(s.capacity == 21);
|
||||||
|
|
||||||
|
s.reserve(30);
|
||||||
|
s.shrink(25);
|
||||||
|
assert(s.capacity == 25);
|
||||||
|
|
||||||
|
s.shrink(18);
|
||||||
|
assert(s.capacity == 21);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns: String capacity in bytes.
|
||||||
|
*/
|
||||||
|
@property size_t capacity() const pure nothrow @safe @nogc
|
||||||
|
{
|
||||||
|
return capacity_;
|
||||||
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
@nogc @safe unittest
|
||||||
|
{
|
||||||
|
auto s = String("In allem Schreiben ist Schamlosigkeit.");
|
||||||
|
assert(s.capacity == 38);
|
||||||
}
|
}
|
||||||
|
|
||||||
mixin DefaultAllocator;
|
mixin DefaultAllocator;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user