Add algorithm package with move and moveEmplace
This commit is contained in:
parent
414d7a11a8
commit
7a2768340e
@ -15,7 +15,6 @@ Garbage Collector heap. Everything in the library is usable in @nogc code.
|
||||
Tanya extends Phobos functionality and provides alternative implementations for
|
||||
data structures and utilities that depend on the Garbage Collector in Phobos.
|
||||
|
||||
* [Bug tracker](https://issues.caraus.io/projects/tanya/issues)
|
||||
* [API Documentation](https://docs.caraus.io/tanya)
|
||||
* [Contribution guidelines](CONTRIBUTING.md)
|
||||
|
||||
@ -24,6 +23,7 @@ data structures and utilities that depend on the Garbage Collector in Phobos.
|
||||
|
||||
Tanya consists of the following packages and (top-level) modules:
|
||||
|
||||
* `algorithm`: Collection of generic algorithms.
|
||||
* `async`: Event loop (epoll, kqueue and IOCP).
|
||||
* `container`: Queue, Array, Singly and doubly linked lists, Buffers, UTF-8
|
||||
string, Hash set.
|
||||
|
164
source/tanya/algorithm/mutation.d
Normal file
164
source/tanya/algorithm/mutation.d
Normal file
@ -0,0 +1,164 @@
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
/**
|
||||
* Algorithms that modify its arguments.
|
||||
*
|
||||
* Copyright: Eugene Wissner 2017.
|
||||
* License: $(LINK2 https://www.mozilla.org/en-US/MPL/2.0/,
|
||||
* Mozilla Public License, v. 2.0).
|
||||
* Authors: $(LINK2 mailto:info@caraus.de, Eugene Wissner)
|
||||
* Source: $(LINK2 https://github.com/caraus-ecms/tanya/blob/master/source/tanya/algorithm/mutation.d,
|
||||
* tanya/algorithm/mutation.d)
|
||||
*/
|
||||
module tanya.algorithm.mutation;
|
||||
|
||||
import tanya.memory.op;
|
||||
import tanya.meta.trait;
|
||||
|
||||
/**
|
||||
* Moves $(D_PARAM source) into $(D_PARAM target) assuming that
|
||||
* $(D_PARAM target) isn't initialized.
|
||||
*
|
||||
* Moving the $(D_PARAM source) copies it into the $(D_PARAM target) and places
|
||||
* the $(D_PARAM source) into a valid but unspecified state, which means that
|
||||
* after moving $(D_PARAM source) can be destroyed or assigned a new value, but
|
||||
* accessing it yields an unspecified value. No postblits or destructors are
|
||||
* called. If the $(D_PARAM target) should be destroyed before, use
|
||||
* $(D_PSYMBOL move).
|
||||
*
|
||||
* $(D_PARAM source) and $(D_PARAM target) must be different objects.
|
||||
*
|
||||
* Params:
|
||||
* T = Object type.
|
||||
* source = Source object.
|
||||
* target = Target object.
|
||||
*
|
||||
* See_Also: $(D_PSYMBOL move),
|
||||
* $(D_PSYMBOL hasElaborateCopyConstructor),
|
||||
* $(D_PSYMBOL hasElaborateDestructor).
|
||||
*
|
||||
* Precondition: `&source !is &target`.
|
||||
*/
|
||||
void moveEmplace(T)(ref T source, ref T target) @system
|
||||
in
|
||||
{
|
||||
assert(&source !is &target, "Source and target must be different");
|
||||
}
|
||||
body
|
||||
{
|
||||
static if (is(T == struct))
|
||||
{
|
||||
copy((&source)[0 .. 1], (&target)[0 .. 1]);
|
||||
|
||||
static if (hasElaborateCopyConstructor!T || hasElaborateDestructor!T)
|
||||
{
|
||||
static const T init = T.init;
|
||||
|
||||
static if (isNested!T)
|
||||
{
|
||||
// Don't override the context pointer.
|
||||
enum size_t size = T.sizeof - (void*).sizeof;
|
||||
copy((cast(void*) &init)[0 .. size], (&source)[0 .. 1]);
|
||||
}
|
||||
else
|
||||
{
|
||||
copy((&init)[0 .. 1], (&source)[0 .. 1]);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
target = source;
|
||||
}
|
||||
}
|
||||
|
||||
///
|
||||
@nogc nothrow pure @system unittest
|
||||
{
|
||||
static struct S
|
||||
{
|
||||
int member = 5;
|
||||
|
||||
this(this) @nogc nothrow pure @safe
|
||||
{
|
||||
assert(false);
|
||||
}
|
||||
}
|
||||
S source, target = void;
|
||||
moveEmplace(source, target);
|
||||
assert(target.member == 5);
|
||||
|
||||
int x1 = 5, x2;
|
||||
moveEmplace(x1, x2);
|
||||
assert(x2 == 5);
|
||||
}
|
||||
|
||||
/**
|
||||
* Moves $(D_PARAM source) into $(D_PARAM target) assuming that
|
||||
* $(D_PARAM target) isn't initialized.
|
||||
*
|
||||
* Moving the $(D_PARAM source) copies it into the $(D_PARAM target) and places
|
||||
* the $(D_PARAM source) into a valid but unspecified state, which means that
|
||||
* after moving $(D_PARAM source) can be destroyed or assigned a new value, but
|
||||
* accessing it yields an unspecified value. $(D_PARAM target) is destroyed before
|
||||
* the new value is assigned. If $(D_PARAM target) isn't initialized and
|
||||
* therefore shouldn't be destroyed, $(D_PSYMBOL moveEmplace) can be used.
|
||||
*
|
||||
* If $(D_PARAM target) isn't specified, $(D_PSYMBOL move) returns the source
|
||||
* as rvalue without calling its copy constructor or destructor.
|
||||
*
|
||||
* $(D_PARAM source) and $(D_PARAM target) are the same object,
|
||||
* $(D_PSYMBOL move) does nothing.
|
||||
*
|
||||
* Params:
|
||||
* T = Object type.
|
||||
* source = Source object.
|
||||
* target = Target object.
|
||||
*
|
||||
* See_Also: $(D_PSYMBOL moveEmplace).
|
||||
*/
|
||||
void move(T)(ref T source, ref T target)
|
||||
{
|
||||
if ((() @trusted => &source is &target)())
|
||||
{
|
||||
return;
|
||||
}
|
||||
static if (hasElaborateDestructor!T)
|
||||
{
|
||||
target.__xdtor();
|
||||
}
|
||||
(() @trusted => moveEmplace(source, target))();
|
||||
}
|
||||
|
||||
/// ditto
|
||||
T move(T)(ref T source)
|
||||
{
|
||||
T target = void;
|
||||
(() @trusted => moveEmplace(source, target))();
|
||||
return target;
|
||||
}
|
||||
|
||||
///
|
||||
@nogc nothrow pure @safe unittest
|
||||
{
|
||||
static struct S
|
||||
{
|
||||
int member = 5;
|
||||
|
||||
this(this) @nogc nothrow pure @safe
|
||||
{
|
||||
assert(false);
|
||||
}
|
||||
}
|
||||
S source, target = void;
|
||||
move(source, target);
|
||||
assert(target.member == 5);
|
||||
assert(move(target).member == 5);
|
||||
|
||||
int x1 = 5, x2;
|
||||
move(x1, x2);
|
||||
assert(x2 == 5);
|
||||
assert(move(x2) == 5);
|
||||
}
|
17
source/tanya/algorithm/package.d
Normal file
17
source/tanya/algorithm/package.d
Normal file
@ -0,0 +1,17 @@
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
/**
|
||||
* Collection of generic algorithms.
|
||||
*
|
||||
* Copyright: Eugene Wissner 2017.
|
||||
* License: $(LINK2 https://www.mozilla.org/en-US/MPL/2.0/,
|
||||
* Mozilla Public License, v. 2.0).
|
||||
* Authors: $(LINK2 mailto:info@caraus.de, Eugene Wissner)
|
||||
* Source: $(LINK2 https://github.com/caraus-ecms/tanya/blob/master/source/tanya/algorithm/package.d,
|
||||
* tanya/algorithm/package.d)
|
||||
*/
|
||||
module tanya.algorithm;
|
||||
|
||||
public import tanya.algorithm.mutation;
|
@ -16,8 +16,16 @@ module tanya.container.array;
|
||||
|
||||
import core.checkedint;
|
||||
import std.algorithm.comparison;
|
||||
import std.algorithm.mutation;
|
||||
import std.algorithm.mutation : bringToFront,
|
||||
copy,
|
||||
fill,
|
||||
initializeAll,
|
||||
moveEmplaceAll,
|
||||
moveAll,
|
||||
swap,
|
||||
uninitializedFill;
|
||||
import std.meta;
|
||||
import tanya.algorithm.mutation;
|
||||
import tanya.exception;
|
||||
import tanya.memory;
|
||||
import tanya.meta.trait;
|
||||
|
@ -15,11 +15,13 @@
|
||||
module tanya.container.list;
|
||||
|
||||
import std.algorithm.comparison;
|
||||
import std.algorithm.mutation;
|
||||
import std.algorithm.mutation : swap;
|
||||
import std.algorithm.searching;
|
||||
import tanya.algorithm.mutation;
|
||||
import tanya.container.entry;
|
||||
import tanya.memory;
|
||||
import tanya.meta.trait;
|
||||
import tanya.meta.transform;
|
||||
import tanya.range.array;
|
||||
import tanya.range.primitive;
|
||||
|
||||
|
@ -14,7 +14,7 @@
|
||||
*/
|
||||
module tanya.container.queue;
|
||||
|
||||
import std.algorithm.mutation;
|
||||
import tanya.algorithm.mutation;
|
||||
import tanya.container.entry;
|
||||
import tanya.exception;
|
||||
import tanya.memory;
|
||||
|
@ -15,7 +15,8 @@
|
||||
*/
|
||||
module tanya.container.set;
|
||||
|
||||
import std.algorithm.mutation;
|
||||
import std.algorithm.mutation : swap;
|
||||
import tanya.algorithm.mutation;
|
||||
import tanya.container;
|
||||
import tanya.container.entry;
|
||||
import tanya.memory;
|
||||
|
@ -27,9 +27,10 @@
|
||||
module tanya.container.string;
|
||||
|
||||
import std.algorithm.comparison;
|
||||
import std.algorithm.mutation;
|
||||
import std.algorithm.mutation : bringToFront, copy, swap;
|
||||
import std.algorithm.searching;
|
||||
static import std.range;
|
||||
import tanya.algorithm.mutation;
|
||||
import tanya.memory;
|
||||
import tanya.meta.trait;
|
||||
import tanya.meta.transform;
|
||||
|
@ -14,11 +14,13 @@
|
||||
*/
|
||||
module tanya.math.mp;
|
||||
|
||||
import std.algorithm;
|
||||
import std.algorithm.comparison;
|
||||
import std.algorithm.mutation;
|
||||
import std.range;
|
||||
import tanya.container.array;
|
||||
import tanya.encoding.ascii;
|
||||
import tanya.memory;
|
||||
static import tanya.memory.op;
|
||||
import tanya.meta.trait;
|
||||
import tanya.meta.transform;
|
||||
|
||||
@ -207,7 +209,7 @@ struct Integer
|
||||
this(this) @nogc nothrow pure @safe
|
||||
{
|
||||
auto tmp = allocator.resize!digit(null, this.size);
|
||||
this.rep[0 .. this.size].copy(tmp);
|
||||
tanya.memory.op.copy(this.rep[0 .. this.size], tmp);
|
||||
this.rep = tmp;
|
||||
}
|
||||
|
||||
@ -340,7 +342,8 @@ struct Integer
|
||||
if (is(Unqual!T == Integer))
|
||||
{
|
||||
this.rep = allocator.resize(this.rep, value.size);
|
||||
value.rep[0 .. value.size].copy(this.rep[0 .. value.size]);
|
||||
tanya.memory.op.copy(value.rep[0 .. value.size],
|
||||
this.rep[0 .. value.size]);
|
||||
this.size = value.size;
|
||||
this.sign = value.sign;
|
||||
|
||||
@ -1023,7 +1026,10 @@ struct Integer
|
||||
Integer opUnary(string op : "~")() const
|
||||
{
|
||||
auto ret = Integer(this, allocator);
|
||||
ret.rep[0 .. ret.size].each!((ref a) => a = ~a & mask);
|
||||
foreach (ref a; ret.rep[0 .. ret.size])
|
||||
{
|
||||
a = ~a & mask;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user