Compare commits
27 Commits
Author | SHA1 | Date | |
---|---|---|---|
792d289541 | |||
92f21a95cf | |||
72140a8583 | |||
442fa5b46a | |||
0d6d8f6a91 | |||
cefc4e24b5 | |||
1adc4cd868 | |||
8faccbada4 | |||
9fb043ba65 | |||
162db622ea | |||
a7c1e642e9 | |||
7829b1fe06 | |||
cb742eec82 | |||
341068488d | |||
9b0bc77b7a | |||
c9e4871fb5 | |||
1f4ab88254 | |||
7af5b4db72 | |||
363ebbe3df | |||
ecd74cbf1e | |||
80a177179d | |||
2532d49105 | |||
abfccc35a2 | |||
629071f934 | |||
17cb592b13 | |||
82f41844b1 | |||
8fa033a49f |
1
.gitignore
vendored
1
.gitignore
vendored
@ -1,6 +1,7 @@
|
|||||||
# Binary
|
# Binary
|
||||||
*.[oa]
|
*.[oa]
|
||||||
*.exe
|
*.exe
|
||||||
|
*.lib
|
||||||
|
|
||||||
# D
|
# D
|
||||||
.dub
|
.dub
|
||||||
|
77
README.md
77
README.md
@ -26,12 +26,13 @@ Tanya consists of the following packages and (top-level) modules:
|
|||||||
* `algorithm`: Collection of generic algorithms.
|
* `algorithm`: Collection of generic algorithms.
|
||||||
* `async`: Event loop (epoll, kqueue and IOCP).
|
* `async`: Event loop (epoll, kqueue and IOCP).
|
||||||
* `container`: Queue, Array, Singly and doubly linked lists, Buffers, UTF-8
|
* `container`: Queue, Array, Singly and doubly linked lists, Buffers, UTF-8
|
||||||
string, Hash set.
|
string, Hash table.
|
||||||
* `conv`: This module provides functions for converting between different
|
* `conv`: This module provides functions for converting between different
|
||||||
types.
|
types.
|
||||||
* `encoding`: This package provides tools to work with text encodings.
|
* `encoding`: This package provides tools to work with text encodings.
|
||||||
* `exception`: Common exceptions and errors.
|
* `exception`: Common exceptions and errors.
|
||||||
* `format`: Formatting and conversion functions.
|
* `format`: Formatting and conversion functions.
|
||||||
|
* `hash`: Hash algorithms.
|
||||||
* `math`: Arbitrary precision integer and a set of functions.
|
* `math`: Arbitrary precision integer and a set of functions.
|
||||||
* `memory`: Tools for manual memory management (allocators, smart pointers).
|
* `memory`: Tools for manual memory management (allocators, smart pointers).
|
||||||
* `meta`: Template metaprogramming. This package contains utilities to acquire
|
* `meta`: Template metaprogramming. This package contains utilities to acquire
|
||||||
@ -49,7 +50,10 @@ After finishing the new socket implementation will land in the `net` package and
|
|||||||
ones.
|
ones.
|
||||||
|
|
||||||
|
|
||||||
## Basic usage
|
## NogcD
|
||||||
|
|
||||||
|
To achieve programming without the Garbage Collection tanya uses a subset of D:
|
||||||
|
NogcD.
|
||||||
|
|
||||||
### Allocators
|
### Allocators
|
||||||
|
|
||||||
@ -113,7 +117,7 @@ catch (Exception e)
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
### Containers
|
### Built-in array operations and containers
|
||||||
|
|
||||||
Arrays are commonly used in programming. D's built-in arrays often rely on the
|
Arrays are commonly used in programming. D's built-in arrays often rely on the
|
||||||
GC. It is inconvenient to change their size, reserve memory for future use and
|
GC. It is inconvenient to change their size, reserve memory for future use and
|
||||||
@ -143,38 +147,75 @@ int i = arr[7]; // Access 8th element.
|
|||||||
There are more containers in the `tanya.container` package.
|
There are more containers in the `tanya.container` package.
|
||||||
|
|
||||||
|
|
||||||
|
### Immutability
|
||||||
|
|
||||||
|
Immutability doesn't play nice with manual memory management since the
|
||||||
|
allocated storage should be initialized (mutated) and then released (mutated).
|
||||||
|
`immutable` is used only for non-local immutable declarations (that are
|
||||||
|
evaluated at compile time), static immutable data, strings (`immutable(char)[]`,
|
||||||
|
`immutable(wchar)[]` and `immutable(dchar)[]`).
|
||||||
|
|
||||||
|
|
||||||
|
### Unsupported features
|
||||||
|
|
||||||
|
The following features depend on GC and aren't supported:
|
||||||
|
|
||||||
|
- `lazy` parameters (allocate a closure which is evaluated when then the
|
||||||
|
parameter is used)
|
||||||
|
|
||||||
|
- `synchronized` blocks
|
||||||
|
|
||||||
|
|
||||||
## Development
|
## Development
|
||||||
|
|
||||||
### Supported compilers
|
### Supported compilers
|
||||||
|
|
||||||
| DMD | GCC |
|
| DMD | GCC |
|
||||||
|:-------:|:--------------:|
|
|:-------:|:---------:|
|
||||||
| 2.079.0 | *master* |
|
| 2.079.0 | *master* |
|
||||||
| 2.078.3 | |
|
| 2.078.3 | |
|
||||||
| 2.077.1 | |
|
| 2.077.1 | |
|
||||||
| 2.076.1 | |
|
| 2.076.1 | |
|
||||||
|
|
||||||
### Current status
|
### Current status
|
||||||
|
|
||||||
Following modules are under development:
|
Following modules are under development:
|
||||||
|
|
||||||
| Feature | Branch | Build status |
|
| Feature | Branch | Build status |
|
||||||
|----------|:---------:|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
|------------|:---------:|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
||||||
| BitArray | bitvector | [](https://travis-ci.org/caraus-ecms/tanya) [](https://ci.appveyor.com/project/belka-ew/tanya/branch/bitvector) |
|
| Hash table | bitvector | [](https://travis-ci.org/caraus-ecms/tanya) [](https://ci.appveyor.com/project/belka-ew/tanya/branch/bitvector) |
|
||||||
| TLS | crypto | [](https://travis-ci.org/caraus-ecms/tanya) [](https://ci.appveyor.com/project/belka-ew/tanya/branch/crypto) |
|
|
||||||
|
|
||||||
### Release management
|
### Release management
|
||||||
|
|
||||||
Deprecated features are removed after one release that includes these deprecations.
|
Tanya is still under active development and it isn't possible to provide great
|
||||||
|
backwards-compatibility at this stage. This won't change until 1.0.0. Almost
|
||||||
|
every release contains new features or API changes alongside bug fixes. Thus:
|
||||||
|
|
||||||
|
- Patch releases add new functionality and bug fixes in a backwards-compatible
|
||||||
|
manner
|
||||||
|
|
||||||
|
- Minor releases contain API breakages
|
||||||
|
|
||||||
|
- Major release number is always the same: `0.x.x`
|
||||||
|
|
||||||
|
Deprecated functionality is where possible marked as such before getting
|
||||||
|
removed. It is left in the library for one release: If 0.8.1 deprecates some
|
||||||
|
feature, it is removed in the next release: 0.9.0.
|
||||||
|
|
||||||
## Further characteristics
|
## Further characteristics
|
||||||
|
|
||||||
* Tanya is a native D library
|
- Tanya is a native D library
|
||||||
|
|
||||||
* Tanya is cross-platform. The development happens on a 64-bit Linux, but it
|
- Tanya is cross-platform. The development happens on a 64-bit Linux, but it
|
||||||
is being tested on Windows and FreeBSD as well.
|
is being tested on Windows and FreeBSD as well
|
||||||
|
|
||||||
* The library isn't thread-safe yet.
|
- Tanya favours generic algorithms therefore there is no auto-decoding. Char
|
||||||
|
arrays are handled as any other array type
|
||||||
|
|
||||||
|
- The library isn't thread-safe yet
|
||||||
|
|
||||||
|
- Complex numbers (`cfloat`, `cdouble`, `creal`, `ifloat`, `idouble`, `ireal`)
|
||||||
|
aren't supported
|
||||||
|
|
||||||
|
|
||||||
## Feedback
|
## Feedback
|
||||||
|
7
dub.json
7
dub.json
@ -1,8 +1,8 @@
|
|||||||
{
|
{
|
||||||
"name": "tanya",
|
"name": "tanya",
|
||||||
"description": "General purpose, @nogc library. Containers, networking, metaprogramming, memory management, utilities",
|
"description": "@nogc library. Containers, networking, metaprogramming, memory management, utilities",
|
||||||
"license": "MPL-2.0",
|
"license": "MPL-2.0",
|
||||||
"copyright": "(c) Eugene Wissner <info@caraus.de>",
|
"copyright": "© Eugene Wissner <info@caraus.de>",
|
||||||
"authors": [
|
"authors": [
|
||||||
"Eugene Wissner"
|
"Eugene Wissner"
|
||||||
],
|
],
|
||||||
@ -10,7 +10,7 @@
|
|||||||
"targetType": "library",
|
"targetType": "library",
|
||||||
|
|
||||||
"dependencies-linux": {
|
"dependencies-linux": {
|
||||||
"mir-linux-kernel": "~>1.0.0",
|
"mir-linux-kernel": "~>1.0.0"
|
||||||
},
|
},
|
||||||
|
|
||||||
"configurations": [
|
"configurations": [
|
||||||
@ -33,5 +33,6 @@
|
|||||||
"versions": ["TanyaNative"]
|
"versions": ["TanyaNative"]
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
|
||||||
"libs-windows": ["advapi32"]
|
"libs-windows": ["advapi32"]
|
||||||
}
|
}
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
/**
|
/**
|
||||||
* Algorithms that modify its arguments.
|
* Algorithms that modify its arguments.
|
||||||
*
|
*
|
||||||
* Copyright: Eugene Wissner 2017.
|
* Copyright: Eugene Wissner 2017-2018.
|
||||||
* 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).
|
||||||
* Authors: $(LINK2 mailto:info@caraus.de, Eugene Wissner)
|
* Authors: $(LINK2 mailto:info@caraus.de, Eugene Wissner)
|
||||||
@ -255,7 +255,7 @@ T move(T)(ref T source) @trusted
|
|||||||
*
|
*
|
||||||
* Params:
|
* Params:
|
||||||
* a = The first object.
|
* a = The first object.
|
||||||
* a = The second object.
|
* b = The second object.
|
||||||
*/
|
*/
|
||||||
void swap(T)(ref T a, ref T b) @trusted
|
void swap(T)(ref T a, ref T b) @trusted
|
||||||
{
|
{
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
/**
|
/**
|
||||||
* Collection of generic algorithms.
|
* Collection of generic algorithms.
|
||||||
*
|
*
|
||||||
* Copyright: Eugene Wissner 2017.
|
* Copyright: Eugene Wissner 2017-2018.
|
||||||
* 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).
|
||||||
* Authors: $(LINK2 mailto:info@caraus.de, Eugene Wissner)
|
* Authors: $(LINK2 mailto:info@caraus.de, Eugene Wissner)
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
/**
|
/**
|
||||||
* Event loop implementation for Linux.
|
* Event loop implementation for Linux.
|
||||||
*
|
*
|
||||||
* Copyright: Eugene Wissner 2016-2017.
|
* Copyright: Eugene Wissner 2016-2018.
|
||||||
* 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).
|
||||||
* Authors: $(LINK2 mailto:info@caraus.de, Eugene Wissner)
|
* Authors: $(LINK2 mailto:info@caraus.de, Eugene Wissner)
|
||||||
@ -162,7 +162,7 @@ final class EpollLoop : SelectorLoop
|
|||||||
}
|
}
|
||||||
else if (transport.output.length)
|
else if (transport.output.length)
|
||||||
{
|
{
|
||||||
pendings.enqueue(transport);
|
pendings.insertBack(transport);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (events[i].events & EPOLLOUT)
|
if (events[i].events & EPOLLOUT)
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
/**
|
/**
|
||||||
* Event loop implementation for Windows.
|
* Event loop implementation for Windows.
|
||||||
*
|
*
|
||||||
* Copyright: Eugene Wissner 2016-2017.
|
* Copyright: Eugene Wissner 2016-2018.
|
||||||
* 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).
|
||||||
* Authors: $(LINK2 mailto:info@caraus.de, Eugene Wissner)
|
* Authors: $(LINK2 mailto:info@caraus.de, Eugene Wissner)
|
||||||
@ -273,7 +273,7 @@ final class IOCPLoop : Loop
|
|||||||
transport.socket.shutdown();
|
transport.socket.shutdown();
|
||||||
defaultAllocator.dispose(transport.socket);
|
defaultAllocator.dispose(transport.socket);
|
||||||
transport.exception = exception;
|
transport.exception = exception;
|
||||||
pendings.enqueue(transport);
|
pendings.insertBack(transport);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -296,7 +296,8 @@ final class IOCPLoop : Loop
|
|||||||
return; // Timeout
|
return; // Timeout
|
||||||
}
|
}
|
||||||
|
|
||||||
auto overlapped = (cast(SocketState) ((cast(void*) overlap) - 8));
|
enum size_t offset = size_t.sizeof * 2;
|
||||||
|
auto overlapped = cast(SocketState) ((cast(void*) overlap) - offset);
|
||||||
assert(overlapped !is null);
|
assert(overlapped !is null);
|
||||||
scope (failure)
|
scope (failure)
|
||||||
{
|
{
|
||||||
@ -315,11 +316,11 @@ final class IOCPLoop : Loop
|
|||||||
auto socket = listener.endAccept(overlapped);
|
auto socket = listener.endAccept(overlapped);
|
||||||
auto transport = defaultAllocator.make!StreamTransport(socket);
|
auto transport = defaultAllocator.make!StreamTransport(socket);
|
||||||
|
|
||||||
connection.incoming.enqueue(transport);
|
connection.incoming.insertBack(transport);
|
||||||
|
|
||||||
reify(transport, EventMask(Event.none), EventMask(Event.read, Event.write));
|
reify(transport, EventMask(Event.none), EventMask(Event.read, Event.write));
|
||||||
|
|
||||||
pendings.enqueue(connection);
|
pendings.insertBack(connection);
|
||||||
listener.beginAccept(overlapped);
|
listener.beginAccept(overlapped);
|
||||||
break;
|
break;
|
||||||
case OverlappedSocketEvent.read:
|
case OverlappedSocketEvent.read:
|
||||||
@ -359,7 +360,7 @@ final class IOCPLoop : Loop
|
|||||||
{
|
{
|
||||||
transport.socket.beginReceive(transport.output[], overlapped);
|
transport.socket.beginReceive(transport.output[], overlapped);
|
||||||
}
|
}
|
||||||
pendings.enqueue(transport);
|
pendings.insertBack(transport);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case OverlappedSocketEvent.write:
|
case OverlappedSocketEvent.write:
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
/*
|
/*
|
||||||
* Event loop implementation for *BSD.
|
* Event loop implementation for *BSD.
|
||||||
*
|
*
|
||||||
* Copyright: Eugene Wissner 2016-2017.
|
* Copyright: Eugene Wissner 2016-2018.
|
||||||
* 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).
|
||||||
* Authors: $(LINK2 mailto:info@caraus.de, Eugene Wissner)
|
* Authors: $(LINK2 mailto:info@caraus.de, Eugene Wissner)
|
||||||
@ -279,7 +279,7 @@ final class KqueueLoop : SelectorLoop
|
|||||||
}
|
}
|
||||||
else if (transport.output.length)
|
else if (transport.output.length)
|
||||||
{
|
{
|
||||||
pendings.enqueue(transport);
|
pendings.insertBack(transport);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (events[i].filter == EVFILT_WRITE)
|
else if (events[i].filter == EVFILT_WRITE)
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
/*
|
/*
|
||||||
* This module contains base implementations for reactor event loops.
|
* This module contains base implementations for reactor event loops.
|
||||||
*
|
*
|
||||||
* Copyright: Eugene Wissner 2016-2017.
|
* Copyright: Eugene Wissner 2016-2018.
|
||||||
* 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).
|
||||||
* Authors: $(LINK2 mailto:info@caraus.de, Eugene Wissner)
|
* Authors: $(LINK2 mailto:info@caraus.de, Eugene Wissner)
|
||||||
@ -218,12 +218,12 @@ abstract class SelectorLoop : Loop
|
|||||||
this() @nogc
|
this() @nogc
|
||||||
{
|
{
|
||||||
super();
|
super();
|
||||||
connections = Array!SocketWatcher(maxEvents);
|
this.connections = Array!SocketWatcher(maxEvents);
|
||||||
}
|
}
|
||||||
|
|
||||||
~this() @nogc
|
~this() @nogc
|
||||||
{
|
{
|
||||||
foreach (ref connection; connections)
|
foreach (ref connection; this.connections[])
|
||||||
{
|
{
|
||||||
// We want to free only the transports. ConnectionWatcher are
|
// We want to free only the transports. ConnectionWatcher are
|
||||||
// created by the user and should be freed by himself.
|
// created by the user and should be freed by himself.
|
||||||
@ -266,7 +266,7 @@ abstract class SelectorLoop : Loop
|
|||||||
transport.socket.shutdown();
|
transport.socket.shutdown();
|
||||||
defaultAllocator.dispose(transport.socket);
|
defaultAllocator.dispose(transport.socket);
|
||||||
transport.exception = exception;
|
transport.exception = exception;
|
||||||
pendings.enqueue(transport);
|
pendings.insertBack(transport);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -394,12 +394,12 @@ abstract class SelectorLoop : Loop
|
|||||||
}
|
}
|
||||||
|
|
||||||
reify(transport, EventMask(Event.none), EventMask(Event.read, Event.write));
|
reify(transport, EventMask(Event.none), EventMask(Event.read, Event.write));
|
||||||
connection.incoming.enqueue(transport);
|
connection.incoming.insertBack(transport);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!connection.incoming.empty)
|
if (!connection.incoming.empty)
|
||||||
{
|
{
|
||||||
pendings.enqueue(connection);
|
pendings.insertBack(connection);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
*
|
*
|
||||||
* Note: Available only on Windows.
|
* Note: Available only on Windows.
|
||||||
*
|
*
|
||||||
* Copyright: Eugene Wissner 2016-2017.
|
* Copyright: Eugene Wissner 2016-2018.
|
||||||
* 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).
|
||||||
* Authors: $(LINK2 mailto:info@caraus.de, Eugene Wissner)
|
* Authors: $(LINK2 mailto:info@caraus.de, Eugene Wissner)
|
||||||
@ -53,4 +53,4 @@ class State
|
|||||||
|
|
||||||
/// For keeping events or event masks.
|
/// For keeping events or event masks.
|
||||||
int event;
|
int event;
|
||||||
}
|
}
|
||||||
|
@ -60,7 +60,7 @@
|
|||||||
* }
|
* }
|
||||||
* ---
|
* ---
|
||||||
*
|
*
|
||||||
* Copyright: Eugene Wissner 2016-2017.
|
* Copyright: Eugene Wissner 2016-2018.
|
||||||
* 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).
|
||||||
* Authors: $(LINK2 mailto:info@caraus.de, Eugene Wissner)
|
* Authors: $(LINK2 mailto:info@caraus.de, Eugene Wissner)
|
||||||
@ -70,13 +70,11 @@
|
|||||||
module tanya.async.loop;
|
module tanya.async.loop;
|
||||||
|
|
||||||
import core.time;
|
import core.time;
|
||||||
import std.algorithm.iteration;
|
|
||||||
import std.algorithm.mutation;
|
|
||||||
import std.typecons;
|
import std.typecons;
|
||||||
import tanya.async.transport;
|
import tanya.async.transport;
|
||||||
import tanya.async.watcher;
|
import tanya.async.watcher;
|
||||||
import tanya.container.buffer;
|
import tanya.container.buffer;
|
||||||
import tanya.container.queue;
|
import tanya.container.list;
|
||||||
import tanya.memory;
|
import tanya.memory;
|
||||||
import tanya.network.socket;
|
import tanya.network.socket;
|
||||||
|
|
||||||
@ -163,7 +161,7 @@ abstract class Loop
|
|||||||
private bool done = true;
|
private bool done = true;
|
||||||
|
|
||||||
/// Pending watchers.
|
/// Pending watchers.
|
||||||
protected Queue!Watcher pendings;
|
protected DList!Watcher pendings;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns: Maximal event count can be got at a time
|
* Returns: Maximal event count can be got at a time
|
||||||
@ -188,7 +186,6 @@ abstract class Loop
|
|||||||
*/
|
*/
|
||||||
this() @nogc
|
this() @nogc
|
||||||
{
|
{
|
||||||
pendings = Queue!Watcher();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -196,9 +193,9 @@ abstract class Loop
|
|||||||
*/
|
*/
|
||||||
~this() @nogc
|
~this() @nogc
|
||||||
{
|
{
|
||||||
foreach (w; pendings)
|
for (; !this.pendings.empty; this.pendings.removeFront())
|
||||||
{
|
{
|
||||||
defaultAllocator.dispose(w);
|
defaultAllocator.dispose(this.pendings.front);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -213,9 +210,9 @@ abstract class Loop
|
|||||||
poll();
|
poll();
|
||||||
|
|
||||||
// Invoke pendings
|
// Invoke pendings
|
||||||
foreach (ref w; this.pendings)
|
for (; !this.pendings.empty; this.pendings.removeFront())
|
||||||
{
|
{
|
||||||
w.invoke();
|
this.pendings.front.invoke();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
while (!this.done);
|
while (!this.done);
|
||||||
@ -244,7 +241,7 @@ abstract class Loop
|
|||||||
{
|
{
|
||||||
auto loop = defaultAllocator.make!TestLoop;
|
auto loop = defaultAllocator.make!TestLoop;
|
||||||
auto watcher = defaultAllocator.make!DummyWatcher;
|
auto watcher = defaultAllocator.make!DummyWatcher;
|
||||||
loop.pendings.enqueue(watcher);
|
loop.pendings.insertBack(watcher);
|
||||||
|
|
||||||
assert(!watcher.invoked);
|
assert(!watcher.invoked);
|
||||||
loop.run();
|
loop.run();
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
/**
|
/**
|
||||||
* This package provides asynchronous capabilities.
|
* This package provides asynchronous capabilities.
|
||||||
*
|
*
|
||||||
* Copyright: Eugene Wissner 2016-2017.
|
* Copyright: Eugene Wissner 2016-2018.
|
||||||
* 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).
|
||||||
* Authors: $(LINK2 mailto:info@caraus.de, Eugene Wissner)
|
* Authors: $(LINK2 mailto:info@caraus.de, Eugene Wissner)
|
||||||
|
@ -9,7 +9,7 @@
|
|||||||
* When an event from the network arrives, a protocol method gets
|
* When an event from the network arrives, a protocol method gets
|
||||||
* called and can respond to the event.
|
* called and can respond to the event.
|
||||||
*
|
*
|
||||||
* Copyright: Eugene Wissner 2016-2017.
|
* Copyright: Eugene Wissner 2016-2018.
|
||||||
* 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).
|
||||||
* Authors: $(LINK2 mailto:info@caraus.de, Eugene Wissner)
|
* Authors: $(LINK2 mailto:info@caraus.de, Eugene Wissner)
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
* This module contains transports which are responsible for data dilvery
|
* This module contains transports which are responsible for data dilvery
|
||||||
* between two parties of an asynchronous communication.
|
* between two parties of an asynchronous communication.
|
||||||
*
|
*
|
||||||
* Copyright: Eugene Wissner 2016-2017.
|
* Copyright: Eugene Wissner 2016-2018.
|
||||||
* 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).
|
||||||
* Authors: $(LINK2 mailto:info@caraus.de, Eugene Wissner)
|
* Authors: $(LINK2 mailto:info@caraus.de, Eugene Wissner)
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
/**
|
/**
|
||||||
* Watchers register user's interest in some event.
|
* Watchers register user's interest in some event.
|
||||||
*
|
*
|
||||||
* Copyright: Eugene Wissner 2016-2017.
|
* Copyright: Eugene Wissner 2016-2018.
|
||||||
* 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).
|
||||||
* Authors: $(LINK2 mailto:info@caraus.de, Eugene Wissner)
|
* Authors: $(LINK2 mailto:info@caraus.de, Eugene Wissner)
|
||||||
@ -14,13 +14,11 @@
|
|||||||
*/
|
*/
|
||||||
module tanya.async.watcher;
|
module tanya.async.watcher;
|
||||||
|
|
||||||
import std.exception;
|
|
||||||
import std.functional;
|
|
||||||
import tanya.async.loop;
|
import tanya.async.loop;
|
||||||
import tanya.async.protocol;
|
import tanya.async.protocol;
|
||||||
import tanya.async.transport;
|
import tanya.async.transport;
|
||||||
import tanya.container.buffer;
|
import tanya.container.buffer;
|
||||||
import tanya.container.queue;
|
import tanya.container.list;
|
||||||
import tanya.memory;
|
import tanya.memory;
|
||||||
import tanya.network.socket;
|
import tanya.network.socket;
|
||||||
|
|
||||||
@ -91,7 +89,7 @@ abstract class SocketWatcher : Watcher
|
|||||||
class ConnectionWatcher : SocketWatcher
|
class ConnectionWatcher : SocketWatcher
|
||||||
{
|
{
|
||||||
/// Incoming connection queue.
|
/// Incoming connection queue.
|
||||||
Queue!DuplexTransport incoming;
|
DList!DuplexTransport incoming;
|
||||||
|
|
||||||
private Protocol delegate() @nogc protocolFactory;
|
private Protocol delegate() @nogc protocolFactory;
|
||||||
|
|
||||||
@ -102,7 +100,6 @@ class ConnectionWatcher : SocketWatcher
|
|||||||
this(Socket socket) @nogc
|
this(Socket socket) @nogc
|
||||||
{
|
{
|
||||||
super(socket);
|
super(socket);
|
||||||
incoming = Queue!DuplexTransport();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -124,10 +121,10 @@ class ConnectionWatcher : SocketWatcher
|
|||||||
}
|
}
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
foreach (transport; incoming)
|
for (; !this.incoming.empty; this.incoming.removeFront())
|
||||||
{
|
{
|
||||||
transport.protocol = protocolFactory();
|
this.incoming.front.protocol = protocolFactory();
|
||||||
transport.protocol.connected(transport);
|
this.incoming.front.protocol.connected(this.incoming.front);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
/**
|
/**
|
||||||
* Single-dimensioned array.
|
* Single-dimensioned array.
|
||||||
*
|
*
|
||||||
* Copyright: Eugene Wissner 2016-2017.
|
* Copyright: Eugene Wissner 2016-2018.
|
||||||
* 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).
|
||||||
* Authors: $(LINK2 mailto:info@caraus.de, Eugene Wissner)
|
* Authors: $(LINK2 mailto:info@caraus.de, Eugene Wissner)
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
/**
|
/**
|
||||||
* This module contains buffers designed for C-style input/output APIs.
|
* This module contains buffers designed for C-style input/output APIs.
|
||||||
*
|
*
|
||||||
* Copyright: Eugene Wissner 2016-2017.
|
* Copyright: Eugene Wissner 2016-2018.
|
||||||
* 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).
|
||||||
* Authors: $(LINK2 mailto:info@caraus.de, Eugene Wissner)
|
* Authors: $(LINK2 mailto:info@caraus.de, Eugene Wissner)
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
/*
|
/*
|
||||||
* Internal package used by containers that rely on entries/nodes.
|
* Internal package used by containers that rely on entries/nodes.
|
||||||
*
|
*
|
||||||
* Copyright: Eugene Wissner 2016-2017.
|
* Copyright: Eugene Wissner 2016-2018.
|
||||||
* 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).
|
||||||
* Authors: $(LINK2 mailto:info@caraus.de, Eugene Wissner)
|
* Authors: $(LINK2 mailto:info@caraus.de, Eugene Wissner)
|
||||||
|
@ -3,9 +3,10 @@
|
|||||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Linked list.
|
* This module contains singly-linked ($(D_PSYMBOL SList)) and doubly-linked
|
||||||
|
* ($(D_PSYMBOL DList)) lists.
|
||||||
*
|
*
|
||||||
* Copyright: Eugene Wissner 2016-2017.
|
* Copyright: Eugene Wissner 2016-2018.
|
||||||
* 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).
|
||||||
* Authors: $(LINK2 mailto:info@caraus.de, Eugene Wissner)
|
* Authors: $(LINK2 mailto:info@caraus.de, Eugene Wissner)
|
||||||
@ -313,6 +314,8 @@ struct SList(T)
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns: First element.
|
* Returns: First element.
|
||||||
|
*
|
||||||
|
* Precondition: $(D_INLINECODE !empty).
|
||||||
*/
|
*/
|
||||||
@property ref inout(T) front() inout
|
@property ref inout(T) front() inout
|
||||||
in
|
in
|
||||||
@ -922,7 +925,7 @@ struct SList(T)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Forward range for the $(D_PSYMBOL DList).
|
* Bidirectional range for the $(D_PSYMBOL DList).
|
||||||
*
|
*
|
||||||
* Params:
|
* Params:
|
||||||
* L = List type.
|
* L = List type.
|
||||||
@ -1012,6 +1015,17 @@ struct DRange(L)
|
|||||||
/**
|
/**
|
||||||
* Doubly-linked list.
|
* Doubly-linked list.
|
||||||
*
|
*
|
||||||
|
* $(D_PSYMBOL DList) can be also used as a queue. Elements can be enqueued
|
||||||
|
* with $(D_PSYMBOL DList.insertBack). To process the queue a `for`-loop comes
|
||||||
|
* in handy:
|
||||||
|
*
|
||||||
|
* ---
|
||||||
|
* for (; !dlist.empty; dlist.removeFront())
|
||||||
|
* {
|
||||||
|
* do_something_with(dlist.front);
|
||||||
|
* }
|
||||||
|
* ---
|
||||||
|
*
|
||||||
* Params:
|
* Params:
|
||||||
* T = Content type.
|
* T = Content type.
|
||||||
*/
|
*/
|
||||||
@ -1247,6 +1261,8 @@ struct DList(T)
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns: First element.
|
* Returns: First element.
|
||||||
|
*
|
||||||
|
* Precondition: $(D_INLINECODE !empty).
|
||||||
*/
|
*/
|
||||||
@property ref inout(T) front() inout
|
@property ref inout(T) front() inout
|
||||||
in
|
in
|
||||||
@ -1260,6 +1276,8 @@ struct DList(T)
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns: Last element.
|
* Returns: Last element.
|
||||||
|
*
|
||||||
|
* Precondition: $(D_INLINECODE !empty).
|
||||||
*/
|
*/
|
||||||
@property ref inout(T) back() inout
|
@property ref inout(T) back() inout
|
||||||
in
|
in
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
/**
|
/**
|
||||||
* Abstract data types whose instances are collections of other objects.
|
* Abstract data types whose instances are collections of other objects.
|
||||||
*
|
*
|
||||||
* Copyright: Eugene Wissner 2016-2017.
|
* Copyright: Eugene Wissner 2016-2018.
|
||||||
* 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).
|
||||||
* Authors: $(LINK2 mailto:info@caraus.de, Eugene Wissner)
|
* Authors: $(LINK2 mailto:info@caraus.de, Eugene Wissner)
|
||||||
|
@ -5,13 +5,14 @@
|
|||||||
/**
|
/**
|
||||||
* FIFO queue.
|
* FIFO queue.
|
||||||
*
|
*
|
||||||
* Copyright: Eugene Wissner 2016-2017.
|
* Copyright: Eugene Wissner 2016-2018.
|
||||||
* 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).
|
||||||
* Authors: $(LINK2 mailto:info@caraus.de, Eugene Wissner)
|
* Authors: $(LINK2 mailto:info@caraus.de, Eugene Wissner)
|
||||||
* Source: $(LINK2 https://github.com/caraus-ecms/tanya/blob/master/source/tanya/container/queue.d,
|
* Source: $(LINK2 https://github.com/caraus-ecms/tanya/blob/master/source/tanya/container/queue.d,
|
||||||
* tanya/container/queue.d)
|
* tanya/container/queue.d)
|
||||||
*/
|
*/
|
||||||
|
deprecated("Use tanya.container.list.DList instead")
|
||||||
module tanya.container.queue;
|
module tanya.container.queue;
|
||||||
|
|
||||||
import tanya.algorithm.mutation;
|
import tanya.algorithm.mutation;
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
* This module implements a $(D_PSYMBOL Set) container that stores unique
|
* This module implements a $(D_PSYMBOL Set) container that stores unique
|
||||||
* values without any particular order.
|
* values without any particular order.
|
||||||
*
|
*
|
||||||
* Copyright: Eugene Wissner 2017.
|
* Copyright: Eugene Wissner 2017-2018.
|
||||||
* 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).
|
||||||
* Authors: $(LINK2 mailto:info@caraus.de, Eugene Wissner)
|
* Authors: $(LINK2 mailto:info@caraus.de, Eugene Wissner)
|
||||||
|
@ -17,7 +17,7 @@
|
|||||||
* Internally $(D_PSYMBOL String) is represented by a sequence of
|
* Internally $(D_PSYMBOL String) is represented by a sequence of
|
||||||
* $(D_KEYWORD char)s.
|
* $(D_KEYWORD char)s.
|
||||||
*
|
*
|
||||||
* Copyright: Eugene Wissner 2017.
|
* Copyright: Eugene Wissner 2017-2018.
|
||||||
* 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).
|
||||||
* Authors: $(LINK2 mailto:info@caraus.de, Eugene Wissner)
|
* Authors: $(LINK2 mailto:info@caraus.de, Eugene Wissner)
|
||||||
@ -29,7 +29,6 @@ module tanya.container.string;
|
|||||||
import std.algorithm.comparison;
|
import std.algorithm.comparison;
|
||||||
import std.algorithm.mutation : bringToFront, copy;
|
import std.algorithm.mutation : bringToFront, copy;
|
||||||
import std.algorithm.searching;
|
import std.algorithm.searching;
|
||||||
static import std.range;
|
|
||||||
import tanya.algorithm.mutation;
|
import tanya.algorithm.mutation;
|
||||||
import tanya.memory;
|
import tanya.memory;
|
||||||
import tanya.meta.trait;
|
import tanya.meta.trait;
|
||||||
@ -759,7 +758,7 @@ struct String
|
|||||||
}
|
}
|
||||||
dchar d = (range[0] - 0xd800) | ((range[1] - 0xdc00) >> 10);
|
dchar d = (range[0] - 0xd800) | ((range[1] - 0xdc00) >> 10);
|
||||||
|
|
||||||
std.range.popFrontN(range, 2);
|
popFrontN(range, 2);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -1527,7 +1526,7 @@ struct String
|
|||||||
assert(s.length == 38);
|
assert(s.length == 38);
|
||||||
|
|
||||||
auto byCodePoint = s.byCodePoint();
|
auto byCodePoint = s.byCodePoint();
|
||||||
std.range.popFrontN(byCodePoint, 8);
|
popFrontN(byCodePoint, 8);
|
||||||
|
|
||||||
assert(s.remove(byCodePoint).count == 0);
|
assert(s.remove(byCodePoint).count == 0);
|
||||||
assert(s == "Из слова");
|
assert(s == "Из слова");
|
||||||
|
622
source/tanya/hash/lookup.d
Normal file
622
source/tanya/hash/lookup.d
Normal file
@ -0,0 +1,622 @@
|
|||||||
|
/* 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/. */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Non-cryptographic, lookup hash functions.
|
||||||
|
*
|
||||||
|
* Copyright: Eugene Wissner 2018.
|
||||||
|
* 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/hash/lookup.d,
|
||||||
|
* tanya/hash/lookup.d)
|
||||||
|
*/
|
||||||
|
module tanya.hash.lookup;
|
||||||
|
|
||||||
|
import tanya.meta.trait;
|
||||||
|
import tanya.range.primitive;
|
||||||
|
|
||||||
|
private struct FNV
|
||||||
|
{
|
||||||
|
static if (size_t.sizeof == 4)
|
||||||
|
{
|
||||||
|
enum uint offsetBasis = 2166136261;
|
||||||
|
enum uint prime = 16777619;
|
||||||
|
}
|
||||||
|
else static if (size_t.sizeof == 8)
|
||||||
|
{
|
||||||
|
enum ulong offsetBasis = 14695981039346656037UL;
|
||||||
|
enum ulong prime = 1099511628211UL;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
static assert(false, "FNV requires at least 32-bit hash length");
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t hash = offsetBasis;
|
||||||
|
|
||||||
|
void opCall(T)(auto ref T key)
|
||||||
|
{
|
||||||
|
static if (is(typeof(key.toHash()) == size_t))
|
||||||
|
{
|
||||||
|
opCall(key.toHash()); // Combine user-defined hashes
|
||||||
|
}
|
||||||
|
else static if (isScalarType!T || isPointer!T)
|
||||||
|
{
|
||||||
|
(() @trusted => add((cast(const ubyte*) &key)[0 .. T.sizeof]))();
|
||||||
|
}
|
||||||
|
else static if (isArray!T && isScalarType!(ElementType!T))
|
||||||
|
{
|
||||||
|
add(cast(const ubyte[]) key);
|
||||||
|
}
|
||||||
|
else static if (is(T == typeof(null)))
|
||||||
|
{
|
||||||
|
add(key);
|
||||||
|
}
|
||||||
|
else static if (isInputRange!T && !isInfinite!T)
|
||||||
|
{
|
||||||
|
foreach (e; key)
|
||||||
|
{
|
||||||
|
opCall(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
static assert(false, "Hash function is not available");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void add(const ubyte[] key) @nogc nothrow pure @safe
|
||||||
|
{
|
||||||
|
foreach (c; key)
|
||||||
|
{
|
||||||
|
this.hash = (this.hash ^ c) * prime;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Takes an a argument of an arbitrary type $(D_PARAM T) and calculates the hash value.
|
||||||
|
*
|
||||||
|
* Hash calculation is supported for all scalar types. Aggregate types, like
|
||||||
|
*$(D_KEYWORD struct)s should implement `toHash`-function:
|
||||||
|
* ---
|
||||||
|
* size_t toHash() const
|
||||||
|
* {
|
||||||
|
* return hash;
|
||||||
|
* }
|
||||||
|
* ---
|
||||||
|
*
|
||||||
|
* For scalar types FNV-1a (Fowler-Noll-Vo) hash function is used internally.
|
||||||
|
* If the type provides a `toHash`-function, only `toHash()` is called and its
|
||||||
|
* result is returned.
|
||||||
|
*
|
||||||
|
* This function also accepts input ranges that contain hashable elements.
|
||||||
|
* Individual values are combined then and the resulting hash is returned.
|
||||||
|
*
|
||||||
|
* Params:
|
||||||
|
* T = Hashable type.
|
||||||
|
* key = Hashable value.
|
||||||
|
*
|
||||||
|
* Returns: Calculated hash value.
|
||||||
|
*
|
||||||
|
* See_Also: $(LINK http://www.isthe.com/chongo/tech/comp/fnv/).
|
||||||
|
*/
|
||||||
|
size_t hash(T)(auto ref T key)
|
||||||
|
{
|
||||||
|
static if (is(typeof(key.toHash()) == size_t))
|
||||||
|
{
|
||||||
|
return key.toHash();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
FNV fnv;
|
||||||
|
fnv(key);
|
||||||
|
return fnv.hash;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
version (unittest)
|
||||||
|
{
|
||||||
|
enum string r10(string x) = x ~ x ~ x ~ x ~ x ~ x ~ x ~ x ~ x ~ x;
|
||||||
|
enum string r100(string x) = r10!x ~ r10!x ~ r10!x ~ r10!x ~ r10!x
|
||||||
|
~ r10!x ~ r10!x ~ r10!x ~ r10!x ~ r10!x;
|
||||||
|
enum string r500(string x) = r100!x ~ r100!x ~ r100!x ~ r100!x ~ r100!x;
|
||||||
|
|
||||||
|
private struct ToHash
|
||||||
|
{
|
||||||
|
size_t toHash() const @nogc nothrow pure @safe
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private struct HashRange
|
||||||
|
{
|
||||||
|
string fo = "fo";
|
||||||
|
|
||||||
|
@property ubyte front() const @nogc nothrow pure @safe
|
||||||
|
{
|
||||||
|
return this.fo[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
void popFront() @nogc nothrow pure @safe
|
||||||
|
{
|
||||||
|
this.fo = this.fo[1 .. $];
|
||||||
|
}
|
||||||
|
|
||||||
|
@property bool empty() const @nogc nothrow pure @safe
|
||||||
|
{
|
||||||
|
return this.fo.length == 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private struct ToHashRange
|
||||||
|
{
|
||||||
|
bool empty_;
|
||||||
|
|
||||||
|
@property ToHash front() const @nogc nothrow pure @safe
|
||||||
|
{
|
||||||
|
return ToHash();
|
||||||
|
}
|
||||||
|
|
||||||
|
void popFront() @nogc nothrow pure @safe
|
||||||
|
{
|
||||||
|
this.empty_ = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@property bool empty() const @nogc nothrow pure @safe
|
||||||
|
{
|
||||||
|
return this.empty_;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Tests that work for any hash size
|
||||||
|
@nogc nothrow pure @safe unittest
|
||||||
|
{
|
||||||
|
assert(hash(null) == FNV.offsetBasis);
|
||||||
|
assert(hash(ToHash()) == 0U);
|
||||||
|
}
|
||||||
|
|
||||||
|
static if (size_t.sizeof == 4) @nogc nothrow pure @safe unittest
|
||||||
|
{
|
||||||
|
assert(hash('a') == 0xe40c292cU);
|
||||||
|
assert(hash(HashRange()) == 0x6222e842U);
|
||||||
|
assert(hash(ToHashRange()) == 1268118805U);
|
||||||
|
}
|
||||||
|
static if (size_t.sizeof == 8) @nogc nothrow pure @safe unittest
|
||||||
|
{
|
||||||
|
assert(hash('a') == 0xaf63dc4c8601ec8cUL);
|
||||||
|
assert(hash(HashRange()) == 0x08985907b541d342UL);
|
||||||
|
assert(hash(ToHashRange()) == 12161962213042174405UL);
|
||||||
|
}
|
||||||
|
|
||||||
|
static if (size_t.sizeof == 4) @nogc nothrow pure @system unittest
|
||||||
|
{
|
||||||
|
assert(hash(cast(void*) 0x6e6f6863) == 0xac297727U);
|
||||||
|
}
|
||||||
|
static if (size_t.sizeof == 8) @nogc nothrow pure @system unittest
|
||||||
|
{
|
||||||
|
assert(hash(cast(void*) 0x77206f676e6f6863) == 0xd1edd10b507344d0UL);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* These are official FNV-1a test vectors and they are in the public domain.
|
||||||
|
*/
|
||||||
|
// FNV-1a 32 bit test vectors
|
||||||
|
static if (size_t.sizeof == 4) @nogc nothrow pure @safe unittest
|
||||||
|
{
|
||||||
|
assert(hash("") == 0x811c9dc5U);
|
||||||
|
assert(hash("a") == 0xe40c292cU);
|
||||||
|
assert(hash("b") == 0xe70c2de5U);
|
||||||
|
assert(hash("c") == 0xe60c2c52U);
|
||||||
|
assert(hash("d") == 0xe10c2473U);
|
||||||
|
assert(hash("e") == 0xe00c22e0U);
|
||||||
|
assert(hash("f") == 0xe30c2799U);
|
||||||
|
assert(hash("fo") == 0x6222e842U);
|
||||||
|
assert(hash("foo") == 0xa9f37ed7U);
|
||||||
|
assert(hash("foob") == 0x3f5076efU);
|
||||||
|
assert(hash("fooba") == 0x39aaa18aU);
|
||||||
|
assert(hash("foobar") == 0xbf9cf968U);
|
||||||
|
assert(hash("\0") == 0x050c5d1fU);
|
||||||
|
assert(hash("a\0") == 0x2b24d044U);
|
||||||
|
assert(hash("b\0") == 0x9d2c3f7fU);
|
||||||
|
assert(hash("c\0") == 0x7729c516U);
|
||||||
|
assert(hash("d\0") == 0xb91d6109U);
|
||||||
|
assert(hash("e\0") == 0x931ae6a0U);
|
||||||
|
assert(hash("f\0") == 0x052255dbU);
|
||||||
|
assert(hash("fo\0") == 0xbef39fe6U);
|
||||||
|
assert(hash("foo\0") == 0x6150ac75U);
|
||||||
|
assert(hash("foob\0") == 0x9aab3a3dU);
|
||||||
|
assert(hash("fooba\0") == 0x519c4c3eU);
|
||||||
|
assert(hash("foobar\0") == 0x0c1c9eb8U);
|
||||||
|
assert(hash("ch") == 0x5f299f4eU);
|
||||||
|
assert(hash("cho") == 0xef8580f3U);
|
||||||
|
assert(hash("chon") == 0xac297727U);
|
||||||
|
assert(hash("chong") == 0x4546b9c0U);
|
||||||
|
assert(hash("chongo") == 0xbd564e7dU);
|
||||||
|
assert(hash("chongo ") == 0x6bdd5c67U);
|
||||||
|
assert(hash("chongo w") == 0xdd77ed30U);
|
||||||
|
assert(hash("chongo wa") == 0xf4ca9683U);
|
||||||
|
assert(hash("chongo was") == 0x4aeb9bd0U);
|
||||||
|
assert(hash("chongo was ") == 0xe0e67ad0U);
|
||||||
|
assert(hash("chongo was h") == 0xc2d32fa8U);
|
||||||
|
assert(hash("chongo was he") == 0x7f743fb7U);
|
||||||
|
assert(hash("chongo was her") == 0x6900631fU);
|
||||||
|
assert(hash("chongo was here") == 0xc59c990eU);
|
||||||
|
assert(hash("chongo was here!") == 0x448524fdU);
|
||||||
|
assert(hash("chongo was here!\n") == 0xd49930d5U);
|
||||||
|
assert(hash("ch\0") == 0x1c85c7caU);
|
||||||
|
assert(hash("cho\0") == 0x0229fe89U);
|
||||||
|
assert(hash("chon\0") == 0x2c469265U);
|
||||||
|
assert(hash("chong\0") == 0xce566940U);
|
||||||
|
assert(hash("chongo\0") == 0x8bdd8ec7U);
|
||||||
|
assert(hash("chongo \0") == 0x34787625U);
|
||||||
|
assert(hash("chongo w\0") == 0xd3ca6290U);
|
||||||
|
assert(hash("chongo wa\0") == 0xddeaf039U);
|
||||||
|
assert(hash("chongo was\0") == 0xc0e64870U);
|
||||||
|
assert(hash("chongo was \0") == 0xdad35570U);
|
||||||
|
assert(hash("chongo was h\0") == 0x5a740578U);
|
||||||
|
assert(hash("chongo was he\0") == 0x5b004d15U);
|
||||||
|
assert(hash("chongo was her\0") == 0x6a9c09cdU);
|
||||||
|
assert(hash("chongo was here\0") == 0x2384f10aU);
|
||||||
|
assert(hash("chongo was here!\0") == 0xda993a47U);
|
||||||
|
assert(hash("chongo was here!\n\0") == 0x8227df4fU);
|
||||||
|
assert(hash("cu") == 0x4c298165U);
|
||||||
|
assert(hash("cur") == 0xfc563735U);
|
||||||
|
assert(hash("curd") == 0x8cb91483U);
|
||||||
|
assert(hash("curds") == 0x775bf5d0U);
|
||||||
|
assert(hash("curds ") == 0xd5c428d0U);
|
||||||
|
assert(hash("curds a") == 0x34cc0ea3U);
|
||||||
|
assert(hash("curds an") == 0xea3b4cb7U);
|
||||||
|
assert(hash("curds and") == 0x8e59f029U);
|
||||||
|
assert(hash("curds and ") == 0x2094de2bU);
|
||||||
|
assert(hash("curds and w") == 0xa65a0ad4U);
|
||||||
|
assert(hash("curds and wh") == 0x9bbee5f4U);
|
||||||
|
assert(hash("curds and whe") == 0xbe836343U);
|
||||||
|
assert(hash("curds and whey") == 0x22d5344eU);
|
||||||
|
assert(hash("curds and whey\n") == 0x19a1470cU);
|
||||||
|
assert(hash("cu\0") == 0x4a56b1ffU);
|
||||||
|
assert(hash("cur\0") == 0x70b8e86fU);
|
||||||
|
assert(hash("curd\0") == 0x0a5b4a39U);
|
||||||
|
assert(hash("curds\0") == 0xb5c3f670U);
|
||||||
|
assert(hash("curds \0") == 0x53cc3f70U);
|
||||||
|
assert(hash("curds a\0") == 0xc03b0a99U);
|
||||||
|
assert(hash("curds an\0") == 0x7259c415U);
|
||||||
|
assert(hash("curds and\0") == 0x4095108bU);
|
||||||
|
assert(hash("curds and \0") == 0x7559bdb1U);
|
||||||
|
assert(hash("curds and w\0") == 0xb3bf0bbcU);
|
||||||
|
assert(hash("curds and wh\0") == 0x2183ff1cU);
|
||||||
|
assert(hash("curds and whe\0") == 0x2bd54279U);
|
||||||
|
assert(hash("curds and whey\0") == 0x23a156caU);
|
||||||
|
assert(hash("curds and whey\n\0") == 0x64e2d7e4U);
|
||||||
|
assert(hash("hi") == 0x683af69aU);
|
||||||
|
assert(hash("hi\0") == 0xaed2346eU);
|
||||||
|
assert(hash("hello") == 0x4f9f2cabU);
|
||||||
|
assert(hash("hello\0") == 0x02935131U);
|
||||||
|
assert(hash("\xff\x00\x00\x01") == 0xc48fb86dU);
|
||||||
|
assert(hash("\x01\x00\x00\xff") == 0x2269f369U);
|
||||||
|
assert(hash("\xff\x00\x00\x02") == 0xc18fb3b4U);
|
||||||
|
assert(hash("\x02\x00\x00\xff") == 0x50ef1236U);
|
||||||
|
assert(hash("\xff\x00\x00\x03") == 0xc28fb547U);
|
||||||
|
assert(hash("\x03\x00\x00\xff") == 0x96c3bf47U);
|
||||||
|
assert(hash("\xff\x00\x00\x04") == 0xbf8fb08eU);
|
||||||
|
assert(hash("\x04\x00\x00\xff") == 0xf3e4d49cU);
|
||||||
|
assert(hash("\x40\x51\x4e\x44") == 0x32179058U);
|
||||||
|
assert(hash("\x44\x4e\x51\x40") == 0x280bfee6U);
|
||||||
|
assert(hash("\x40\x51\x4e\x4a") == 0x30178d32U);
|
||||||
|
assert(hash("\x4a\x4e\x51\x40") == 0x21addaf8U);
|
||||||
|
assert(hash("\x40\x51\x4e\x54") == 0x4217a988U);
|
||||||
|
assert(hash("\x54\x4e\x51\x40") == 0x772633d6U);
|
||||||
|
assert(hash("127.0.0.1") == 0x08a3d11eU);
|
||||||
|
assert(hash("127.0.0.1\0") == 0xb7e2323aU);
|
||||||
|
assert(hash("127.0.0.2") == 0x07a3cf8bU);
|
||||||
|
assert(hash("127.0.0.2\0") == 0x91dfb7d1U);
|
||||||
|
assert(hash("127.0.0.3") == 0x06a3cdf8U);
|
||||||
|
assert(hash("127.0.0.3\0") == 0x6bdd3d68U);
|
||||||
|
assert(hash("64.81.78.68") == 0x1d5636a7U);
|
||||||
|
assert(hash("64.81.78.68\0") == 0xd5b808e5U);
|
||||||
|
assert(hash("64.81.78.74") == 0x1353e852U);
|
||||||
|
assert(hash("64.81.78.74\0") == 0xbf16b916U);
|
||||||
|
assert(hash("64.81.78.84") == 0xa55b89edU);
|
||||||
|
assert(hash("64.81.78.84\0") == 0x3c1a2017U);
|
||||||
|
assert(hash("feedface") == 0x0588b13cU);
|
||||||
|
assert(hash("feedface\0") == 0xf22f0174U);
|
||||||
|
assert(hash("feedfacedaffdeed") == 0xe83641e1U);
|
||||||
|
assert(hash("feedfacedaffdeed\0") == 0x6e69b533U);
|
||||||
|
assert(hash("feedfacedeadbeef") == 0xf1760448U);
|
||||||
|
assert(hash("feedfacedeadbeef\0") == 0x64c8bd58U);
|
||||||
|
assert(hash("line 1\nline 2\nline 3") == 0x97b4ea23U);
|
||||||
|
assert(hash("chongo <Landon Curt Noll> /\\../\\") == 0x9a4e92e6U);
|
||||||
|
assert(hash("chongo <Landon Curt Noll> /\\../\\\0") == 0xcfb14012U);
|
||||||
|
assert(hash("chongo (Landon Curt Noll) /\\../\\") == 0xf01b2511U);
|
||||||
|
assert(hash("chongo (Landon Curt Noll) /\\../\\\0") == 0x0bbb59c3U);
|
||||||
|
assert(hash("http://antwrp.gsfc.nasa.gov/apod/astropix.html") == 0xce524afaU);
|
||||||
|
assert(hash("http://en.wikipedia.org/wiki/Fowler_Noll_Vo_hash") == 0xdd16ef45U);
|
||||||
|
assert(hash("http://epod.usra.edu/") == 0x60648bb3U);
|
||||||
|
assert(hash("http://exoplanet.eu/") == 0x7fa4bcfcU);
|
||||||
|
assert(hash("http://hvo.wr.usgs.gov/cam3/") == 0x5053ae17U);
|
||||||
|
assert(hash("http://hvo.wr.usgs.gov/cams/HMcam/") == 0xc9302890U);
|
||||||
|
assert(hash("http://hvo.wr.usgs.gov/kilauea/update/deformation.html") == 0x956ded32U);
|
||||||
|
assert(hash("http://hvo.wr.usgs.gov/kilauea/update/images.html") == 0x9136db84U);
|
||||||
|
assert(hash("http://hvo.wr.usgs.gov/kilauea/update/maps.html") == 0xdf9d3323U);
|
||||||
|
assert(hash("http://hvo.wr.usgs.gov/volcanowatch/current_issue.html") == 0x32bb6cd0U);
|
||||||
|
assert(hash("http://neo.jpl.nasa.gov/risk/") == 0xc8f8385bU);
|
||||||
|
assert(hash("http://norvig.com/21-days.html") == 0xeb08bfbaU);
|
||||||
|
assert(hash("http://primes.utm.edu/curios/home.php") == 0x62cc8e3dU);
|
||||||
|
assert(hash("http://slashdot.org/") == 0xc3e20f5cU);
|
||||||
|
assert(hash("http://tux.wr.usgs.gov/Maps/155.25-19.5.html") == 0x39e97f17U);
|
||||||
|
assert(hash("http://volcano.wr.usgs.gov/kilaueastatus.php") == 0x7837b203U);
|
||||||
|
assert(hash("http://www.avo.alaska.edu/activity/Redoubt.php") == 0x319e877bU);
|
||||||
|
assert(hash("http://www.dilbert.com/fast/") == 0xd3e63f89U);
|
||||||
|
assert(hash("http://www.fourmilab.ch/gravitation/orbits/") == 0x29b50b38U);
|
||||||
|
assert(hash("http://www.fpoa.net/") == 0x5ed678b8U);
|
||||||
|
assert(hash("http://www.ioccc.org/index.html") == 0xb0d5b793U);
|
||||||
|
assert(hash("http://www.isthe.com/cgi-bin/number.cgi") == 0x52450be5U);
|
||||||
|
assert(hash("http://www.isthe.com/chongo/bio.html") == 0xfa72d767U);
|
||||||
|
assert(hash("http://www.isthe.com/chongo/index.html") == 0x95066709U);
|
||||||
|
assert(hash("http://www.isthe.com/chongo/src/calc/lucas-calc") == 0x7f52e123U);
|
||||||
|
assert(hash("http://www.isthe.com/chongo/tech/astro/venus2004.html") == 0x76966481U);
|
||||||
|
assert(hash("http://www.isthe.com/chongo/tech/astro/vita.html") == 0x063258b0U);
|
||||||
|
assert(hash("http://www.isthe.com/chongo/tech/comp/c/expert.html") == 0x2ded6e8aU);
|
||||||
|
assert(hash("http://www.isthe.com/chongo/tech/comp/calc/index.html") == 0xb07d7c52U);
|
||||||
|
assert(hash("http://www.isthe.com/chongo/tech/comp/fnv/index.html") == 0xd0c71b71U);
|
||||||
|
assert(hash("http://www.isthe.com/chongo/tech/math/number/howhigh.html") == 0xf684f1bdU);
|
||||||
|
assert(hash("http://www.isthe.com/chongo/tech/math/number/number.html") == 0x868ecfa8U);
|
||||||
|
assert(hash("http://www.isthe.com/chongo/tech/math/prime/mersenne.html") == 0xf794f684U);
|
||||||
|
assert(hash("http://www.isthe.com/chongo/tech/math/prime/mersenne.html#largest") == 0xd19701c3U);
|
||||||
|
assert(hash("http://www.lavarnd.org/cgi-bin/corpspeak.cgi") == 0x346e171eU);
|
||||||
|
assert(hash("http://www.lavarnd.org/cgi-bin/haiku.cgi") == 0x91f8f676U);
|
||||||
|
assert(hash("http://www.lavarnd.org/cgi-bin/rand-none.cgi") == 0x0bf58848U);
|
||||||
|
assert(hash("http://www.lavarnd.org/cgi-bin/randdist.cgi") == 0x6317b6d1U);
|
||||||
|
assert(hash("http://www.lavarnd.org/index.html") == 0xafad4c54U);
|
||||||
|
assert(hash("http://www.lavarnd.org/what/nist-test.html") == 0x0f25681eU);
|
||||||
|
assert(hash("http://www.macosxhints.com/") == 0x91b18d49U);
|
||||||
|
assert(hash("http://www.mellis.com/") == 0x7d61c12eU);
|
||||||
|
assert(hash("http://www.nature.nps.gov/air/webcams/parks/havoso2alert/havoalert.cfm") == 0x5147d25cU);
|
||||||
|
assert(hash("http://www.nature.nps.gov/air/webcams/parks/havoso2alert/timelines_24.cfm") == 0x9a8b6805U);
|
||||||
|
assert(hash("http://www.paulnoll.com/") == 0x4cd2a447U);
|
||||||
|
assert(hash("http://www.pepysdiary.com/") == 0x1e549b14U);
|
||||||
|
assert(hash("http://www.sciencenews.org/index/home/activity/view") == 0x2fe1b574U);
|
||||||
|
assert(hash("http://www.skyandtelescope.com/") == 0xcf0cd31eU);
|
||||||
|
assert(hash("http://www.sput.nl/~rob/sirius.html") == 0x6c471669U);
|
||||||
|
assert(hash("http://www.systemexperts.com/") == 0x0e5eef1eU);
|
||||||
|
assert(hash("http://www.tq-international.com/phpBB3/index.php") == 0x2bed3602U);
|
||||||
|
assert(hash("http://www.travelquesttours.com/index.htm") == 0xb26249e0U);
|
||||||
|
assert(hash("http://www.wunderground.com/global/stations/89606.html") == 0x2c9b86a4U);
|
||||||
|
assert(hash(r10!"21701") == 0xe415e2bbU);
|
||||||
|
assert(hash(r10!"M21701") == 0x18a98d1dU);
|
||||||
|
assert(hash(r10!"2^21701-1") == 0xb7df8b7bU);
|
||||||
|
assert(hash(r10!"\x54\xc5") == 0x241e9075U);
|
||||||
|
assert(hash(r10!"\xc5\x54") == 0x063f70ddU);
|
||||||
|
assert(hash(r10!"23209") == 0x0295aed9U);
|
||||||
|
assert(hash(r10!"M23209") == 0x56a7f781U);
|
||||||
|
assert(hash(r10!"2^23209-1") == 0x253bc645U);
|
||||||
|
assert(hash(r10!"\x5a\xa9") == 0x46610921U);
|
||||||
|
assert(hash(r10!"\xa9\x5a") == 0x7c1577f9U);
|
||||||
|
assert(hash(r10!"391581216093") == 0x512b2851U);
|
||||||
|
assert(hash(r10!"391581*2^216093-1") == 0x76823999U);
|
||||||
|
assert(hash(r10!"\x05\xf9\x9d\x03\x4c\x81") == 0xc0586935U);
|
||||||
|
assert(hash(r10!"FEDCBA9876543210") == 0xf3415c85U);
|
||||||
|
assert(hash(r10!"\xfe\xdc\xba\x98\x76\x54\x32\x10") == 0x0ae4ff65U);
|
||||||
|
assert(hash(r10!"EFCDAB8967452301") == 0x58b79725U);
|
||||||
|
assert(hash(r10!"\xef\xcd\xab\x89\x67\x45\x23\x01") == 0xdea43aa5U);
|
||||||
|
assert(hash(r10!"0123456789ABCDEF") == 0x2bb3be35U);
|
||||||
|
assert(hash(r10!"\x01\x23\x45\x67\x89\xab\xcd\xef") == 0xea777a45U);
|
||||||
|
assert(hash(r10!"1032547698BADCFE") == 0x8f21c305U);
|
||||||
|
assert(hash(r10!"\x10\x32\x54\x76\x98\xba\xdc\xfe") == 0x5c9d0865U);
|
||||||
|
assert(hash(r500!"\x00") == 0xfa823dd5U);
|
||||||
|
assert(hash(r500!"\x07") == 0x21a27271U);
|
||||||
|
assert(hash(r500!"~") == 0x83c5c6d5U);
|
||||||
|
assert(hash(r500!"\x7f") == 0x813b0881U);
|
||||||
|
}
|
||||||
|
|
||||||
|
// FNV-1a 64 bit test vectors
|
||||||
|
static if (size_t.sizeof == 8) @nogc nothrow pure @safe unittest
|
||||||
|
{
|
||||||
|
assert(hash("") == 0xcbf29ce484222325UL);
|
||||||
|
assert(hash("a") == 0xaf63dc4c8601ec8cUL);
|
||||||
|
assert(hash("b") == 0xaf63df4c8601f1a5UL);
|
||||||
|
assert(hash("c") == 0xaf63de4c8601eff2UL);
|
||||||
|
assert(hash("d") == 0xaf63d94c8601e773UL);
|
||||||
|
assert(hash("e") == 0xaf63d84c8601e5c0UL);
|
||||||
|
assert(hash("f") == 0xaf63db4c8601ead9UL);
|
||||||
|
assert(hash("fo") == 0x08985907b541d342UL);
|
||||||
|
assert(hash("foo") == 0xdcb27518fed9d577UL);
|
||||||
|
assert(hash("foob") == 0xdd120e790c2512afUL);
|
||||||
|
assert(hash("fooba") == 0xcac165afa2fef40aUL);
|
||||||
|
assert(hash("foobar") == 0x85944171f73967e8UL);
|
||||||
|
assert(hash("\0") == 0xaf63bd4c8601b7dfUL);
|
||||||
|
assert(hash("a\0") == 0x089be207b544f1e4UL);
|
||||||
|
assert(hash("b\0") == 0x08a61407b54d9b5fUL);
|
||||||
|
assert(hash("c\0") == 0x08a2ae07b54ab836UL);
|
||||||
|
assert(hash("d\0") == 0x0891b007b53c4869UL);
|
||||||
|
assert(hash("e\0") == 0x088e4a07b5396540UL);
|
||||||
|
assert(hash("f\0") == 0x08987c07b5420ebbUL);
|
||||||
|
assert(hash("fo\0") == 0xdcb28a18fed9f926UL);
|
||||||
|
assert(hash("foo\0") == 0xdd1270790c25b935UL);
|
||||||
|
assert(hash("foob\0") == 0xcac146afa2febf5dUL);
|
||||||
|
assert(hash("fooba\0") == 0x8593d371f738acfeUL);
|
||||||
|
assert(hash("foobar\0") == 0x34531ca7168b8f38UL);
|
||||||
|
assert(hash("ch") == 0x08a25607b54a22aeUL);
|
||||||
|
assert(hash("cho") == 0xf5faf0190cf90df3UL);
|
||||||
|
assert(hash("chon") == 0xf27397910b3221c7UL);
|
||||||
|
assert(hash("chong") == 0x2c8c2b76062f22e0UL);
|
||||||
|
assert(hash("chongo") == 0xe150688c8217b8fdUL);
|
||||||
|
assert(hash("chongo ") == 0xf35a83c10e4f1f87UL);
|
||||||
|
assert(hash("chongo w") == 0xd1edd10b507344d0UL);
|
||||||
|
assert(hash("chongo wa") == 0x2a5ee739b3ddb8c3UL);
|
||||||
|
assert(hash("chongo was") == 0xdcfb970ca1c0d310UL);
|
||||||
|
assert(hash("chongo was ") == 0x4054da76daa6da90UL);
|
||||||
|
assert(hash("chongo was h") == 0xf70a2ff589861368UL);
|
||||||
|
assert(hash("chongo was he") == 0x4c628b38aed25f17UL);
|
||||||
|
assert(hash("chongo was her") == 0x9dd1f6510f78189fUL);
|
||||||
|
assert(hash("chongo was here") == 0xa3de85bd491270ceUL);
|
||||||
|
assert(hash("chongo was here!") == 0x858e2fa32a55e61dUL);
|
||||||
|
assert(hash("chongo was here!\n") == 0x46810940eff5f915UL);
|
||||||
|
assert(hash("ch\0") == 0xf5fadd190cf8edaaUL);
|
||||||
|
assert(hash("cho\0") == 0xf273ed910b32b3e9UL);
|
||||||
|
assert(hash("chon\0") == 0x2c8c5276062f6525UL);
|
||||||
|
assert(hash("chong\0") == 0xe150b98c821842a0UL);
|
||||||
|
assert(hash("chongo\0") == 0xf35aa3c10e4f55e7UL);
|
||||||
|
assert(hash("chongo \0") == 0xd1ed680b50729265UL);
|
||||||
|
assert(hash("chongo w\0") == 0x2a5f0639b3dded70UL);
|
||||||
|
assert(hash("chongo wa\0") == 0xdcfbaa0ca1c0f359UL);
|
||||||
|
assert(hash("chongo was\0") == 0x4054ba76daa6a430UL);
|
||||||
|
assert(hash("chongo was \0") == 0xf709c7f5898562b0UL);
|
||||||
|
assert(hash("chongo was h\0") == 0x4c62e638aed2f9b8UL);
|
||||||
|
assert(hash("chongo was he\0") == 0x9dd1a8510f779415UL);
|
||||||
|
assert(hash("chongo was her\0") == 0xa3de2abd4911d62dUL);
|
||||||
|
assert(hash("chongo was here\0") == 0x858e0ea32a55ae0aUL);
|
||||||
|
assert(hash("chongo was here!\0") == 0x46810f40eff60347UL);
|
||||||
|
assert(hash("chongo was here!\n\0") == 0xc33bce57bef63eafUL);
|
||||||
|
assert(hash("cu") == 0x08a24307b54a0265UL);
|
||||||
|
assert(hash("cur") == 0xf5b9fd190cc18d15UL);
|
||||||
|
assert(hash("curd") == 0x4c968290ace35703UL);
|
||||||
|
assert(hash("curds") == 0x07174bd5c64d9350UL);
|
||||||
|
assert(hash("curds ") == 0x5a294c3ff5d18750UL);
|
||||||
|
assert(hash("curds a") == 0x05b3c1aeb308b843UL);
|
||||||
|
assert(hash("curds an") == 0xb92a48da37d0f477UL);
|
||||||
|
assert(hash("curds and") == 0x73cdddccd80ebc49UL);
|
||||||
|
assert(hash("curds and ") == 0xd58c4c13210a266bUL);
|
||||||
|
assert(hash("curds and w") == 0xe78b6081243ec194UL);
|
||||||
|
assert(hash("curds and wh") == 0xb096f77096a39f34UL);
|
||||||
|
assert(hash("curds and whe") == 0xb425c54ff807b6a3UL);
|
||||||
|
assert(hash("curds and whey") == 0x23e520e2751bb46eUL);
|
||||||
|
assert(hash("curds and whey\n") == 0x1a0b44ccfe1385ecUL);
|
||||||
|
assert(hash("cu\0") == 0xf5ba4b190cc2119fUL);
|
||||||
|
assert(hash("cur\0") == 0x4c962690ace2baafUL);
|
||||||
|
assert(hash("curd\0") == 0x0716ded5c64cda19UL);
|
||||||
|
assert(hash("curds\0") == 0x5a292c3ff5d150f0UL);
|
||||||
|
assert(hash("curds \0") == 0x05b3e0aeb308ecf0UL);
|
||||||
|
assert(hash("curds a\0") == 0xb92a5eda37d119d9UL);
|
||||||
|
assert(hash("curds an\0") == 0x73ce41ccd80f6635UL);
|
||||||
|
assert(hash("curds and\0") == 0xd58c2c132109f00bUL);
|
||||||
|
assert(hash("curds and \0") == 0xe78baf81243f47d1UL);
|
||||||
|
assert(hash("curds and w\0") == 0xb0968f7096a2ee7cUL);
|
||||||
|
assert(hash("curds and wh\0") == 0xb425a84ff807855cUL);
|
||||||
|
assert(hash("curds and whe\0") == 0x23e4e9e2751b56f9UL);
|
||||||
|
assert(hash("curds and whey\0") == 0x1a0b4eccfe1396eaUL);
|
||||||
|
assert(hash("curds and whey\n\0") == 0x54abd453bb2c9004UL);
|
||||||
|
assert(hash("hi") == 0x08ba5f07b55ec3daUL);
|
||||||
|
assert(hash("hi\0") == 0x337354193006cb6eUL);
|
||||||
|
assert(hash("hello") == 0xa430d84680aabd0bUL);
|
||||||
|
assert(hash("hello\0") == 0xa9bc8acca21f39b1UL);
|
||||||
|
assert(hash("\xff\x00\x00\x01") == 0x6961196491cc682dUL);
|
||||||
|
assert(hash("\x01\x00\x00\xff") == 0xad2bb1774799dfe9UL);
|
||||||
|
assert(hash("\xff\x00\x00\x02") == 0x6961166491cc6314UL);
|
||||||
|
assert(hash("\x02\x00\x00\xff") == 0x8d1bb3904a3b1236UL);
|
||||||
|
assert(hash("\xff\x00\x00\x03") == 0x6961176491cc64c7UL);
|
||||||
|
assert(hash("\x03\x00\x00\xff") == 0xed205d87f40434c7UL);
|
||||||
|
assert(hash("\xff\x00\x00\x04") == 0x6961146491cc5faeUL);
|
||||||
|
assert(hash("\x04\x00\x00\xff") == 0xcd3baf5e44f8ad9cUL);
|
||||||
|
assert(hash("\x40\x51\x4e\x44") == 0xe3b36596127cd6d8UL);
|
||||||
|
assert(hash("\x44\x4e\x51\x40") == 0xf77f1072c8e8a646UL);
|
||||||
|
assert(hash("\x40\x51\x4e\x4a") == 0xe3b36396127cd372UL);
|
||||||
|
assert(hash("\x4a\x4e\x51\x40") == 0x6067dce9932ad458UL);
|
||||||
|
assert(hash("\x40\x51\x4e\x54") == 0xe3b37596127cf208UL);
|
||||||
|
assert(hash("\x54\x4e\x51\x40") == 0x4b7b10fa9fe83936UL);
|
||||||
|
assert(hash("127.0.0.1") == 0xaabafe7104d914beUL);
|
||||||
|
assert(hash("127.0.0.1\0") == 0xf4d3180b3cde3edaUL);
|
||||||
|
assert(hash("127.0.0.2") == 0xaabafd7104d9130bUL);
|
||||||
|
assert(hash("127.0.0.2\0") == 0xf4cfb20b3cdb5bb1UL);
|
||||||
|
assert(hash("127.0.0.3") == 0xaabafc7104d91158UL);
|
||||||
|
assert(hash("127.0.0.3\0") == 0xf4cc4c0b3cd87888UL);
|
||||||
|
assert(hash("64.81.78.68") == 0xe729bac5d2a8d3a7UL);
|
||||||
|
assert(hash("64.81.78.68\0") == 0x74bc0524f4dfa4c5UL);
|
||||||
|
assert(hash("64.81.78.74") == 0xe72630c5d2a5b352UL);
|
||||||
|
assert(hash("64.81.78.74\0") == 0x6b983224ef8fb456UL);
|
||||||
|
assert(hash("64.81.78.84") == 0xe73042c5d2ae266dUL);
|
||||||
|
assert(hash("64.81.78.84\0") == 0x8527e324fdeb4b37UL);
|
||||||
|
assert(hash("feedface") == 0x0a83c86fee952abcUL);
|
||||||
|
assert(hash("feedface\0") == 0x7318523267779d74UL);
|
||||||
|
assert(hash("feedfacedaffdeed") == 0x3e66d3d56b8caca1UL);
|
||||||
|
assert(hash("feedfacedaffdeed\0") == 0x956694a5c0095593UL);
|
||||||
|
assert(hash("feedfacedeadbeef") == 0xcac54572bb1a6fc8UL);
|
||||||
|
assert(hash("feedfacedeadbeef\0") == 0xa7a4c9f3edebf0d8UL);
|
||||||
|
assert(hash("line 1\nline 2\nline 3") == 0x7829851fac17b143UL);
|
||||||
|
assert(hash("chongo <Landon Curt Noll> /\\../\\") == 0x2c8f4c9af81bcf06UL);
|
||||||
|
assert(hash("chongo <Landon Curt Noll> /\\../\\\0") == 0xd34e31539740c732UL);
|
||||||
|
assert(hash("chongo (Landon Curt Noll) /\\../\\") == 0x3605a2ac253d2db1UL);
|
||||||
|
assert(hash("chongo (Landon Curt Noll) /\\../\\\0") == 0x08c11b8346f4a3c3UL);
|
||||||
|
assert(hash("http://antwrp.gsfc.nasa.gov/apod/astropix.html") == 0x6be396289ce8a6daUL);
|
||||||
|
assert(hash("http://en.wikipedia.org/wiki/Fowler_Noll_Vo_hash") == 0xd9b957fb7fe794c5UL);
|
||||||
|
assert(hash("http://epod.usra.edu/") == 0x05be33da04560a93UL);
|
||||||
|
assert(hash("http://exoplanet.eu/") == 0x0957f1577ba9747cUL);
|
||||||
|
assert(hash("http://hvo.wr.usgs.gov/cam3/") == 0xda2cc3acc24fba57UL);
|
||||||
|
assert(hash("http://hvo.wr.usgs.gov/cams/HMcam/") == 0x74136f185b29e7f0UL);
|
||||||
|
assert(hash("http://hvo.wr.usgs.gov/kilauea/update/deformation.html") == 0xb2f2b4590edb93b2UL);
|
||||||
|
assert(hash("http://hvo.wr.usgs.gov/kilauea/update/images.html") == 0xb3608fce8b86ae04UL);
|
||||||
|
assert(hash("http://hvo.wr.usgs.gov/kilauea/update/maps.html") == 0x4a3a865079359063UL);
|
||||||
|
assert(hash("http://hvo.wr.usgs.gov/volcanowatch/current_issue.html") == 0x5b3a7ef496880a50UL);
|
||||||
|
assert(hash("http://neo.jpl.nasa.gov/risk/") == 0x48fae3163854c23bUL);
|
||||||
|
assert(hash("http://norvig.com/21-days.html") == 0x07aaa640476e0b9aUL);
|
||||||
|
assert(hash("http://primes.utm.edu/curios/home.php") == 0x2f653656383a687dUL);
|
||||||
|
assert(hash("http://slashdot.org/") == 0xa1031f8e7599d79cUL);
|
||||||
|
assert(hash("http://tux.wr.usgs.gov/Maps/155.25-19.5.html") == 0xa31908178ff92477UL);
|
||||||
|
assert(hash("http://volcano.wr.usgs.gov/kilaueastatus.php") == 0x097edf3c14c3fb83UL);
|
||||||
|
assert(hash("http://www.avo.alaska.edu/activity/Redoubt.php") == 0xb51ca83feaa0971bUL);
|
||||||
|
assert(hash("http://www.dilbert.com/fast/") == 0xdd3c0d96d784f2e9UL);
|
||||||
|
assert(hash("http://www.fourmilab.ch/gravitation/orbits/") == 0x86cd26a9ea767d78UL);
|
||||||
|
assert(hash("http://www.fpoa.net/") == 0xe6b215ff54a30c18UL);
|
||||||
|
assert(hash("http://www.ioccc.org/index.html") == 0xec5b06a1c5531093UL);
|
||||||
|
assert(hash("http://www.isthe.com/cgi-bin/number.cgi") == 0x45665a929f9ec5e5UL);
|
||||||
|
assert(hash("http://www.isthe.com/chongo/bio.html") == 0x8c7609b4a9f10907UL);
|
||||||
|
assert(hash("http://www.isthe.com/chongo/index.html") == 0x89aac3a491f0d729UL);
|
||||||
|
assert(hash("http://www.isthe.com/chongo/src/calc/lucas-calc") == 0x32ce6b26e0f4a403UL);
|
||||||
|
assert(hash("http://www.isthe.com/chongo/tech/astro/venus2004.html") == 0x614ab44e02b53e01UL);
|
||||||
|
assert(hash("http://www.isthe.com/chongo/tech/astro/vita.html") == 0xfa6472eb6eef3290UL);
|
||||||
|
assert(hash("http://www.isthe.com/chongo/tech/comp/c/expert.html") == 0x9e5d75eb1948eb6aUL);
|
||||||
|
assert(hash("http://www.isthe.com/chongo/tech/comp/calc/index.html") == 0xb6d12ad4a8671852UL);
|
||||||
|
assert(hash("http://www.isthe.com/chongo/tech/comp/fnv/index.html") == 0x88826f56eba07af1UL);
|
||||||
|
assert(hash("http://www.isthe.com/chongo/tech/math/number/howhigh.html") == 0x44535bf2645bc0fdUL);
|
||||||
|
assert(hash("http://www.isthe.com/chongo/tech/math/number/number.html") == 0x169388ffc21e3728UL);
|
||||||
|
assert(hash("http://www.isthe.com/chongo/tech/math/prime/mersenne.html") == 0xf68aac9e396d8224UL);
|
||||||
|
assert(hash("http://www.isthe.com/chongo/tech/math/prime/mersenne.html#largest") == 0x8e87d7e7472b3883UL);
|
||||||
|
assert(hash("http://www.lavarnd.org/cgi-bin/corpspeak.cgi") == 0x295c26caa8b423deUL);
|
||||||
|
assert(hash("http://www.lavarnd.org/cgi-bin/haiku.cgi") == 0x322c814292e72176UL);
|
||||||
|
assert(hash("http://www.lavarnd.org/cgi-bin/rand-none.cgi") == 0x8a06550eb8af7268UL);
|
||||||
|
assert(hash("http://www.lavarnd.org/cgi-bin/randdist.cgi") == 0xef86d60e661bcf71UL);
|
||||||
|
assert(hash("http://www.lavarnd.org/index.html") == 0x9e5426c87f30ee54UL);
|
||||||
|
assert(hash("http://www.lavarnd.org/what/nist-test.html") == 0xf1ea8aa826fd047eUL);
|
||||||
|
assert(hash("http://www.macosxhints.com/") == 0x0babaf9a642cb769UL);
|
||||||
|
assert(hash("http://www.mellis.com/") == 0x4b3341d4068d012eUL);
|
||||||
|
assert(hash("http://www.nature.nps.gov/air/webcams/parks/havoso2alert/havoalert.cfm") == 0xd15605cbc30a335cUL);
|
||||||
|
assert(hash("http://www.nature.nps.gov/air/webcams/parks/havoso2alert/timelines_24.cfm") == 0x5b21060aed8412e5UL);
|
||||||
|
assert(hash("http://www.paulnoll.com/") == 0x45e2cda1ce6f4227UL);
|
||||||
|
assert(hash("http://www.pepysdiary.com/") == 0x50ae3745033ad7d4UL);
|
||||||
|
assert(hash("http://www.sciencenews.org/index/home/activity/view") == 0xaa4588ced46bf414UL);
|
||||||
|
assert(hash("http://www.skyandtelescope.com/") == 0xc1b0056c4a95467eUL);
|
||||||
|
assert(hash("http://www.sput.nl/~rob/sirius.html") == 0x56576a71de8b4089UL);
|
||||||
|
assert(hash("http://www.systemexperts.com/") == 0xbf20965fa6dc927eUL);
|
||||||
|
assert(hash("http://www.tq-international.com/phpBB3/index.php") == 0x569f8383c2040882UL);
|
||||||
|
assert(hash("http://www.travelquesttours.com/index.htm") == 0xe1e772fba08feca0UL);
|
||||||
|
assert(hash("http://www.wunderground.com/global/stations/89606.html") == 0x4ced94af97138ac4UL);
|
||||||
|
assert(hash(r10!"21701") == 0xc4112ffb337a82fbUL);
|
||||||
|
assert(hash(r10!"M21701") == 0xd64a4fd41de38b7dUL);
|
||||||
|
assert(hash(r10!"2^21701-1") == 0x4cfc32329edebcbbUL);
|
||||||
|
assert(hash(r10!"\x54\xc5") == 0x0803564445050395UL);
|
||||||
|
assert(hash(r10!"\xc5\x54") == 0xaa1574ecf4642ffdUL);
|
||||||
|
assert(hash(r10!"23209") == 0x694bc4e54cc315f9UL);
|
||||||
|
assert(hash(r10!"M23209") == 0xa3d7cb273b011721UL);
|
||||||
|
assert(hash(r10!"2^23209-1") == 0x577c2f8b6115bfa5UL);
|
||||||
|
assert(hash(r10!"\x5a\xa9") == 0xb7ec8c1a769fb4c1UL);
|
||||||
|
assert(hash(r10!"\xa9\x5a") == 0x5d5cfce63359ab19UL);
|
||||||
|
assert(hash(r10!"391581216093") == 0x33b96c3cd65b5f71UL);
|
||||||
|
assert(hash(r10!"391581*2^216093-1") == 0xd845097780602bb9UL);
|
||||||
|
assert(hash(r10!"\x05\xf9\x9d\x03\x4c\x81") == 0x84d47645d02da3d5UL);
|
||||||
|
assert(hash(r10!"FEDCBA9876543210") == 0x83544f33b58773a5UL);
|
||||||
|
assert(hash(r10!"\xfe\xdc\xba\x98\x76\x54\x32\x10") == 0x9175cbb2160836c5UL);
|
||||||
|
assert(hash(r10!"EFCDAB8967452301") == 0xc71b3bc175e72bc5UL);
|
||||||
|
assert(hash(r10!"\xef\xcd\xab\x89\x67\x45\x23\x01") == 0x636806ac222ec985UL);
|
||||||
|
assert(hash(r10!"0123456789ABCDEF") == 0xb6ef0e6950f52ed5UL);
|
||||||
|
assert(hash(r10!"\x01\x23\x45\x67\x89\xab\xcd\xef") == 0xead3d8a0f3dfdaa5UL);
|
||||||
|
assert(hash(r10!"1032547698BADCFE") == 0x922908fe9a861ba5UL);
|
||||||
|
assert(hash(r10!"\x10\x32\x54\x76\x98\xba\xdc\xfe") == 0x6d4821de275fd5c5UL);
|
||||||
|
assert(hash(r500!"\x00") == 0x1fe3fce62bd816b5UL);
|
||||||
|
assert(hash(r500!"\x07") == 0xc23e9fccd6f70591UL);
|
||||||
|
assert(hash(r500!"~") == 0xc1af12bdfe16b5b5UL);
|
||||||
|
assert(hash(r500!"\x7f") == 0x39e9f18f2f85e221UL);
|
||||||
|
}
|
15
source/tanya/hash/package.d
Normal file
15
source/tanya/hash/package.d
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
/* 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/. */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Copyright: Eugene Wissner 2018.
|
||||||
|
* 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/hash/package.d,
|
||||||
|
* tanya/hash/package.d)
|
||||||
|
*/
|
||||||
|
module tanya.hash;
|
||||||
|
|
||||||
|
public import tanya.hash.lookup;
|
@ -9,7 +9,7 @@
|
|||||||
* It contains different algorithms for iterating, searching and modifying
|
* It contains different algorithms for iterating, searching and modifying
|
||||||
* template arguments.
|
* template arguments.
|
||||||
*
|
*
|
||||||
* Copyright: Eugene Wissner 2017.
|
* Copyright: Eugene Wissner 2017-2018.
|
||||||
* 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).
|
||||||
* Authors: $(LINK2 mailto:info@caraus.de, Eugene Wissner)
|
* Authors: $(LINK2 mailto:info@caraus.de, Eugene Wissner)
|
||||||
@ -232,19 +232,21 @@ if (Tuples.length > 0
|
|||||||
*
|
*
|
||||||
* See_Also: $(D_PSYMBOL AliasSeq).
|
* See_Also: $(D_PSYMBOL AliasSeq).
|
||||||
*/
|
*/
|
||||||
template Tuple(Args...)
|
struct Tuple(Args...)
|
||||||
{
|
{
|
||||||
/// Elements in this tuple as $(D_PSYMBOL AliasSeq).
|
/// Elements in this tuple as $(D_PSYMBOL AliasSeq).
|
||||||
alias Seq = Args;
|
alias Seq = Args;
|
||||||
|
|
||||||
/// The length of the tuple.
|
/// The length of the tuple.
|
||||||
enum size_t length = Args.length;
|
enum size_t length = Args.length;
|
||||||
|
|
||||||
|
alias Seq this;
|
||||||
}
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
@nogc nothrow pure @safe unittest
|
@nogc nothrow pure @safe unittest
|
||||||
{
|
{
|
||||||
alias A = Tuple!(short);
|
alias A = Tuple!short;
|
||||||
alias B = Tuple!(3, 8, 9);
|
alias B = Tuple!(3, 8, 9);
|
||||||
alias C = Tuple!(A, B);
|
alias C = Tuple!(A, B);
|
||||||
|
|
||||||
@ -263,20 +265,22 @@ template Tuple(Args...)
|
|||||||
/**
|
/**
|
||||||
* Unordered sequence of unique aliases.
|
* Unordered sequence of unique aliases.
|
||||||
*
|
*
|
||||||
* $(D_PARAM Args) can contain duplicates, but they will be filteredout, so
|
* $(D_PARAM Args) can contain duplicates, but they will be filtered out, so
|
||||||
* $(D_PSYMBOL Set) contains only unique items. $(D_PSYMBOL isEqual) is used
|
* $(D_PSYMBOL Set) contains only unique items. $(D_PSYMBOL isEqual) is used
|
||||||
* for determining if two items are equal.
|
* for determining if two items are equal.
|
||||||
*
|
*
|
||||||
* Params:
|
* Params:
|
||||||
* Args = Elements of this $(D_PSYMBOL Tuple).
|
* Args = Elements of this $(D_PSYMBOL Tuple).
|
||||||
*/
|
*/
|
||||||
template Set(Args...)
|
struct Set(Args...)
|
||||||
{
|
{
|
||||||
/// Elements in this set as $(D_PSYMBOL AliasSeq).
|
/// Elements in this set as $(D_PSYMBOL AliasSeq).
|
||||||
alias Seq = NoDuplicates!Args;
|
alias Seq = NoDuplicates!Args;
|
||||||
|
|
||||||
/// The length of the set.
|
/// The length of the set.
|
||||||
enum size_t length = Seq.length;
|
enum size_t length = Seq.length;
|
||||||
|
|
||||||
|
alias Seq this;
|
||||||
}
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
@ -682,7 +686,7 @@ if (Args.length == 2)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Instantiates the template $(D_PARAM T) with $(D_PARAM ARGS).
|
* Instantiates the template $(D_PARAM T) with $(D_PARAM Args).
|
||||||
*
|
*
|
||||||
* Params:
|
* Params:
|
||||||
* T = Template.
|
* T = Template.
|
||||||
@ -1634,7 +1638,8 @@ template Filter(alias pred, L...)
|
|||||||
///
|
///
|
||||||
@nogc nothrow pure @safe unittest
|
@nogc nothrow pure @safe unittest
|
||||||
{
|
{
|
||||||
static assert(is(Filter!(isIntegral, real, int, bool, uint) == AliasSeq!(int, uint)));
|
alias Given = AliasSeq!(real, int, bool, uint);
|
||||||
|
static assert(is(Filter!(isIntegral, Given) == AliasSeq!(int, uint)));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -1661,8 +1666,8 @@ template NoDuplicates(L...)
|
|||||||
///
|
///
|
||||||
@nogc nothrow pure @safe unittest
|
@nogc nothrow pure @safe unittest
|
||||||
{
|
{
|
||||||
alias Types = AliasSeq!(int, uint, int, short, short, uint);
|
alias Given = AliasSeq!(int, uint, int, short, short, uint);
|
||||||
static assert(is(NoDuplicates!Types == AliasSeq!(int, uint, short)));
|
static assert(is(NoDuplicates!Given == AliasSeq!(int, uint, short)));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -9,7 +9,7 @@
|
|||||||
* to transform from one type to another. It has also different algorithms for
|
* to transform from one type to another. It has also different algorithms for
|
||||||
* iterating, searching and modifying template arguments.
|
* iterating, searching and modifying template arguments.
|
||||||
*
|
*
|
||||||
* Copyright: Eugene Wissner 2017.
|
* Copyright: Eugene Wissner 2017-2018.
|
||||||
* 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).
|
||||||
* Authors: $(LINK2 mailto:info@caraus.de, Eugene Wissner)
|
* Authors: $(LINK2 mailto:info@caraus.de, Eugene Wissner)
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
* Templates in this module are used to obtain type information at compile
|
* Templates in this module are used to obtain type information at compile
|
||||||
* time.
|
* time.
|
||||||
*
|
*
|
||||||
* Copyright: Eugene Wissner 2017.
|
* Copyright: Eugene Wissner 2017-2018.
|
||||||
* 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).
|
||||||
* Authors: $(LINK2 mailto:info@caraus.de, Eugene Wissner)
|
* Authors: $(LINK2 mailto:info@caraus.de, Eugene Wissner)
|
||||||
@ -160,6 +160,7 @@ enum bool isComplex(T) = is(Unqual!(OriginalType!T) == cfloat)
|
|||||||
* Returns: $(D_KEYWORD true) if $(D_PARAM T) is a POD type,
|
* Returns: $(D_KEYWORD true) if $(D_PARAM T) is a POD type,
|
||||||
* $(D_KEYWORD false) otherwise.
|
* $(D_KEYWORD false) otherwise.
|
||||||
*/
|
*/
|
||||||
|
deprecated("Use __traits(isPOD) instead")
|
||||||
enum bool isPOD(T) = __traits(isPOD, T);
|
enum bool isPOD(T) = __traits(isPOD, T);
|
||||||
|
|
||||||
///
|
///
|
||||||
@ -196,6 +197,7 @@ enum bool isPOD(T) = __traits(isPOD, T);
|
|||||||
*
|
*
|
||||||
* Returns: Size of the type $(D_PARAM T).
|
* Returns: Size of the type $(D_PARAM T).
|
||||||
*/
|
*/
|
||||||
|
deprecated("Use T.sizeof instead")
|
||||||
enum size_t sizeOf(T) = T.sizeof;
|
enum size_t sizeOf(T) = T.sizeof;
|
||||||
|
|
||||||
///
|
///
|
||||||
@ -217,6 +219,7 @@ enum size_t sizeOf(T) = T.sizeof;
|
|||||||
*
|
*
|
||||||
* Returns: Alignment of the type $(D_PARAM T).
|
* Returns: Alignment of the type $(D_PARAM T).
|
||||||
*/
|
*/
|
||||||
|
deprecated("Use T.alignof instead")
|
||||||
enum size_t alignOf(T) = T.alignof;
|
enum size_t alignOf(T) = T.alignof;
|
||||||
|
|
||||||
///
|
///
|
||||||
@ -236,6 +239,7 @@ enum size_t alignOf(T) = T.alignof;
|
|||||||
* Returns: $(D_KEYWORD true) if $(D_PARAM Args) are the same symbol,
|
* Returns: $(D_KEYWORD true) if $(D_PARAM Args) are the same symbol,
|
||||||
* $(D_KEYWORD false) otherwise.
|
* $(D_KEYWORD false) otherwise.
|
||||||
*/
|
*/
|
||||||
|
deprecated("Use __traits(isSame) instead")
|
||||||
template isSame(Args...)
|
template isSame(Args...)
|
||||||
if (Args.length == 2)
|
if (Args.length == 2)
|
||||||
{
|
{
|
||||||
@ -263,12 +267,13 @@ if (Args.length == 2)
|
|||||||
* Returns: $(D_KEYWORD true) if $(D_PARAM T) is a template,
|
* Returns: $(D_KEYWORD true) if $(D_PARAM T) is a template,
|
||||||
* $(D_KEYWORD false) otherwise.
|
* $(D_KEYWORD false) otherwise.
|
||||||
*/
|
*/
|
||||||
|
deprecated("Use __traits(isTemplate) instead")
|
||||||
enum bool isTemplate(alias T) = __traits(isTemplate, T);
|
enum bool isTemplate(alias T) = __traits(isTemplate, T);
|
||||||
|
|
||||||
///
|
///
|
||||||
@nogc nothrow pure @safe unittest
|
@nogc nothrow pure @safe unittest
|
||||||
{
|
{
|
||||||
struct S(T)
|
static struct S(T)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
static assert(isTemplate!S);
|
static assert(isTemplate!S);
|
||||||
@ -284,6 +289,7 @@ enum bool isTemplate(alias T) = __traits(isTemplate, T);
|
|||||||
* Returns: $(D_KEYWORD true) if $(D_PARAM T) is an interface,
|
* Returns: $(D_KEYWORD true) if $(D_PARAM T) is an interface,
|
||||||
* $(D_KEYWORD false) otherwise.
|
* $(D_KEYWORD false) otherwise.
|
||||||
*/
|
*/
|
||||||
|
deprecated("Use is(T == interface) instead")
|
||||||
enum bool isInterface(T) = is(T == interface);
|
enum bool isInterface(T) = is(T == interface);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -295,6 +301,7 @@ enum bool isInterface(T) = is(T == interface);
|
|||||||
* Returns: $(D_KEYWORD true) if $(D_PARAM T) is a class,
|
* Returns: $(D_KEYWORD true) if $(D_PARAM T) is a class,
|
||||||
* $(D_KEYWORD false) otherwise.
|
* $(D_KEYWORD false) otherwise.
|
||||||
*/
|
*/
|
||||||
|
deprecated("Use is(T == class) instead")
|
||||||
enum bool isClass(T) = is(T == class);
|
enum bool isClass(T) = is(T == class);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -306,6 +313,7 @@ enum bool isClass(T) = is(T == class);
|
|||||||
* Returns: $(D_KEYWORD true) if $(D_PARAM T) is a struct,
|
* Returns: $(D_KEYWORD true) if $(D_PARAM T) is a struct,
|
||||||
* $(D_KEYWORD false) otherwise.
|
* $(D_KEYWORD false) otherwise.
|
||||||
*/
|
*/
|
||||||
|
deprecated("Use is(T == struct) instead")
|
||||||
enum bool isStruct(T) = is(T == struct);
|
enum bool isStruct(T) = is(T == struct);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -317,6 +325,7 @@ enum bool isStruct(T) = is(T == struct);
|
|||||||
* Returns: $(D_KEYWORD true) if $(D_PARAM T) is an enum,
|
* Returns: $(D_KEYWORD true) if $(D_PARAM T) is an enum,
|
||||||
* $(D_KEYWORD false) otherwise.
|
* $(D_KEYWORD false) otherwise.
|
||||||
*/
|
*/
|
||||||
|
deprecated("Use is(T == enum) instead")
|
||||||
enum bool isEnum(T) = is(T == enum);
|
enum bool isEnum(T) = is(T == enum);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -352,7 +361,7 @@ enum bool isPolymorphicType(T) = is(T == class) || is(T == interface);
|
|||||||
*/
|
*/
|
||||||
template hasStaticMember(T, string member)
|
template hasStaticMember(T, string member)
|
||||||
{
|
{
|
||||||
static if (hasMember!(T, member))
|
static if (__traits(hasMember, T, member))
|
||||||
{
|
{
|
||||||
alias Member = Alias!(__traits(getMember, T, member));
|
alias Member = Alias!(__traits(getMember, T, member));
|
||||||
|
|
||||||
@ -375,7 +384,7 @@ template hasStaticMember(T, string member)
|
|||||||
///
|
///
|
||||||
@nogc nothrow pure @safe unittest
|
@nogc nothrow pure @safe unittest
|
||||||
{
|
{
|
||||||
struct S
|
static struct S
|
||||||
{
|
{
|
||||||
int member1;
|
int member1;
|
||||||
void member2()
|
void member2()
|
||||||
@ -599,14 +608,14 @@ enum bool isBoolean(T) = is(Unqual!(OriginalType!T) == bool);
|
|||||||
}
|
}
|
||||||
static assert(isBoolean!E);
|
static assert(isBoolean!E);
|
||||||
|
|
||||||
struct S1
|
static struct S1
|
||||||
{
|
{
|
||||||
bool b;
|
bool b;
|
||||||
alias b this;
|
alias b this;
|
||||||
}
|
}
|
||||||
static assert(!isBoolean!S1);
|
static assert(!isBoolean!S1);
|
||||||
|
|
||||||
struct S2
|
static struct S2
|
||||||
{
|
{
|
||||||
bool opCast(T : bool)()
|
bool opCast(T : bool)()
|
||||||
{
|
{
|
||||||
@ -726,7 +735,7 @@ template isPointer(T)
|
|||||||
{
|
{
|
||||||
static if (is(T U : U*))
|
static if (is(T U : U*))
|
||||||
{
|
{
|
||||||
enum bool isPointer = true;
|
enum bool isPointer = !is(Unqual!(OriginalType!T) == typeof(null));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -743,6 +752,19 @@ template isPointer(T)
|
|||||||
static assert(!isPointer!bool);
|
static assert(!isPointer!bool);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// typeof(null) is not a pointer.
|
||||||
|
@nogc nothrow pure @safe unittest
|
||||||
|
{
|
||||||
|
static assert(!isPointer!(typeof(null)));
|
||||||
|
static assert(!isPointer!(const shared typeof(null)));
|
||||||
|
|
||||||
|
enum typeOfNull : typeof(null)
|
||||||
|
{
|
||||||
|
null_ = null,
|
||||||
|
}
|
||||||
|
static assert(!isPointer!typeOfNull);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Determines whether $(D_PARAM T) is an array type (dynamic or static, but
|
* Determines whether $(D_PARAM T) is an array type (dynamic or static, but
|
||||||
* not an associative one).
|
* not an associative one).
|
||||||
@ -924,7 +946,7 @@ enum bool isAggregateType(T) = is(T == struct)
|
|||||||
///
|
///
|
||||||
@nogc nothrow pure @safe unittest
|
@nogc nothrow pure @safe unittest
|
||||||
{
|
{
|
||||||
struct S;
|
static struct S;
|
||||||
class C;
|
class C;
|
||||||
interface I;
|
interface I;
|
||||||
union U;
|
union U;
|
||||||
@ -1146,20 +1168,20 @@ enum bool isCopyable(T) = is(typeof({ T s1 = T.init; T s2 = s1; }));
|
|||||||
///
|
///
|
||||||
@nogc nothrow pure @safe unittest
|
@nogc nothrow pure @safe unittest
|
||||||
{
|
{
|
||||||
struct S1
|
static struct S1
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
struct S2
|
static struct S2
|
||||||
{
|
{
|
||||||
this(this)
|
this(this)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
struct S3
|
static struct S3
|
||||||
{
|
{
|
||||||
@disable this(this);
|
@disable this(this);
|
||||||
}
|
}
|
||||||
struct S4
|
static struct S4
|
||||||
{
|
{
|
||||||
S3 s;
|
S3 s;
|
||||||
}
|
}
|
||||||
@ -1254,7 +1276,7 @@ enum bool isTypeTuple(Args...) = allSatisfy!(isType, Args);
|
|||||||
union U
|
union U
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
struct T()
|
static struct T()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1664,7 +1686,7 @@ if (F.length == 1)
|
|||||||
///
|
///
|
||||||
@nogc nothrow pure @safe unittest
|
@nogc nothrow pure @safe unittest
|
||||||
{
|
{
|
||||||
struct S
|
static struct S
|
||||||
{
|
{
|
||||||
void opCall()
|
void opCall()
|
||||||
{
|
{
|
||||||
@ -1689,7 +1711,7 @@ if (F.length == 1)
|
|||||||
|
|
||||||
@nogc nothrow pure @safe unittest
|
@nogc nothrow pure @safe unittest
|
||||||
{
|
{
|
||||||
struct S
|
static struct S
|
||||||
{
|
{
|
||||||
@property int opCall()
|
@property int opCall()
|
||||||
{
|
{
|
||||||
@ -1709,12 +1731,13 @@ if (F.length == 1)
|
|||||||
* Returns: $(D_KEYWORD true) if $(D_PARAM T) defines a symbol
|
* Returns: $(D_KEYWORD true) if $(D_PARAM T) defines a symbol
|
||||||
* $(D_PARAM member), $(D_KEYWORD false) otherwise.
|
* $(D_PARAM member), $(D_KEYWORD false) otherwise.
|
||||||
*/
|
*/
|
||||||
|
deprecated("Use __traits(hasMember) instead")
|
||||||
enum bool hasMember(T, string member) = __traits(hasMember, T, member);
|
enum bool hasMember(T, string member) = __traits(hasMember, T, member);
|
||||||
|
|
||||||
///
|
///
|
||||||
@nogc nothrow pure @safe unittest
|
@nogc nothrow pure @safe unittest
|
||||||
{
|
{
|
||||||
struct S
|
static struct S
|
||||||
{
|
{
|
||||||
int member1;
|
int member1;
|
||||||
void member2()
|
void member2()
|
||||||
@ -1769,7 +1792,7 @@ template isMutable(T)
|
|||||||
///
|
///
|
||||||
@nogc nothrow pure @safe unittest
|
@nogc nothrow pure @safe unittest
|
||||||
{
|
{
|
||||||
struct S
|
static struct S
|
||||||
{
|
{
|
||||||
void method()
|
void method()
|
||||||
{
|
{
|
||||||
@ -1907,7 +1930,7 @@ if (isCallable!F)
|
|||||||
}
|
}
|
||||||
static assert(is(FunctionTypeOf!(I.prop) == function));
|
static assert(is(FunctionTypeOf!(I.prop) == function));
|
||||||
|
|
||||||
struct S
|
static struct S
|
||||||
{
|
{
|
||||||
void opCall()
|
void opCall()
|
||||||
{
|
{
|
||||||
@ -1928,7 +1951,7 @@ if (isCallable!F)
|
|||||||
|
|
||||||
@nogc nothrow pure @safe unittest
|
@nogc nothrow pure @safe unittest
|
||||||
{
|
{
|
||||||
struct S2
|
static struct S2
|
||||||
{
|
{
|
||||||
@property int opCall()
|
@property int opCall()
|
||||||
{
|
{
|
||||||
@ -1981,7 +2004,7 @@ alias TemplateOf(alias T : Base!Args, alias Base, Args...) = Base;
|
|||||||
///
|
///
|
||||||
@nogc nothrow pure @safe unittest
|
@nogc nothrow pure @safe unittest
|
||||||
{
|
{
|
||||||
struct S(T)
|
static struct S(T)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
static assert(isSame!(TemplateOf!(S!int), S));
|
static assert(isSame!(TemplateOf!(S!int), S));
|
||||||
@ -2037,7 +2060,7 @@ template isInstanceOf(alias T, alias I)
|
|||||||
///
|
///
|
||||||
@nogc nothrow pure @safe unittest
|
@nogc nothrow pure @safe unittest
|
||||||
{
|
{
|
||||||
struct S(T)
|
static struct S(T)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
static assert(isInstanceOf!(S, S!int));
|
static assert(isInstanceOf!(S, S!int));
|
||||||
@ -2296,23 +2319,22 @@ template isAssignable(Lhs, Rhs = Lhs)
|
|||||||
///
|
///
|
||||||
@nogc nothrow pure @safe unittest
|
@nogc nothrow pure @safe unittest
|
||||||
{
|
{
|
||||||
struct S1
|
static struct S1
|
||||||
{
|
{
|
||||||
@disable this();
|
@disable this();
|
||||||
@disable this(this);
|
@disable this(this);
|
||||||
}
|
}
|
||||||
struct S2
|
static struct S2
|
||||||
{
|
{
|
||||||
void opAssign(S1 s) pure nothrow @safe @nogc
|
void opAssign(S1 s) pure nothrow @safe @nogc
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
struct S3
|
static struct S3
|
||||||
{
|
{
|
||||||
void opAssign(ref S1 s) pure nothrow @safe @nogc
|
void opAssign(ref S1 s) pure nothrow @safe @nogc
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
static assert(isAssignable!(S2, S1));
|
static assert(isAssignable!(S2, S1));
|
||||||
static assert(!isAssignable!(S3, S1));
|
static assert(!isAssignable!(S3, S1));
|
||||||
@ -2867,7 +2889,7 @@ if (is(T == class))
|
|||||||
}
|
}
|
||||||
static assert(classInstanceAlignment!C1 == C1.alignof);
|
static assert(classInstanceAlignment!C1 == C1.alignof);
|
||||||
|
|
||||||
struct S
|
static struct S
|
||||||
{
|
{
|
||||||
align(8)
|
align(8)
|
||||||
uint s;
|
uint s;
|
||||||
@ -2907,12 +2929,12 @@ template ifTestable(T, alias pred = a => a)
|
|||||||
{
|
{
|
||||||
static assert(ifTestable!int);
|
static assert(ifTestable!int);
|
||||||
|
|
||||||
struct S1
|
static struct S1
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
static assert(!ifTestable!S1);
|
static assert(!ifTestable!S1);
|
||||||
|
|
||||||
struct S2
|
static struct S2
|
||||||
{
|
{
|
||||||
bool opCast(T : bool)()
|
bool opCast(T : bool)()
|
||||||
{
|
{
|
||||||
@ -2979,7 +3001,7 @@ alias getUDAs(alias symbol) = AliasSeq!(__traits(getAttributes, symbol));
|
|||||||
///
|
///
|
||||||
@nogc nothrow pure @safe unittest
|
@nogc nothrow pure @safe unittest
|
||||||
{
|
{
|
||||||
struct Attr
|
static struct Attr
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
}
|
}
|
||||||
@ -2998,7 +3020,7 @@ alias getUDAs(alias symbol) = AliasSeq!(__traits(getAttributes, symbol));
|
|||||||
static assert(getUDAs!(c, "String").length == 0);
|
static assert(getUDAs!(c, "String").length == 0);
|
||||||
static assert(getUDAs!(c, 4).length == 0);
|
static assert(getUDAs!(c, 4).length == 0);
|
||||||
|
|
||||||
struct T(U)
|
static struct T(U)
|
||||||
{
|
{
|
||||||
enum U s = 7;
|
enum U s = 7;
|
||||||
U i;
|
U i;
|
||||||
@ -3034,10 +3056,10 @@ template hasUDA(alias symbol, alias attr)
|
|||||||
///
|
///
|
||||||
@nogc nothrow pure @safe unittest
|
@nogc nothrow pure @safe unittest
|
||||||
{
|
{
|
||||||
struct Attr1
|
static struct Attr1
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
struct Attr2
|
static struct Attr2
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
@Attr1 int a;
|
@Attr1 int a;
|
||||||
|
@ -9,7 +9,7 @@
|
|||||||
* types. They take some type as argument and return a different type after
|
* types. They take some type as argument and return a different type after
|
||||||
* perfoming the specified transformation.
|
* perfoming the specified transformation.
|
||||||
*
|
*
|
||||||
* Copyright: Eugene Wissner 2017.
|
* Copyright: Eugene Wissner 2017-2018.
|
||||||
* 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).
|
||||||
* Authors: $(LINK2 mailto:info@caraus.de, Eugene Wissner)
|
* Authors: $(LINK2 mailto:info@caraus.de, Eugene Wissner)
|
||||||
|
@ -14,6 +14,7 @@
|
|||||||
*/
|
*/
|
||||||
module tanya.range.primitive;
|
module tanya.range.primitive;
|
||||||
|
|
||||||
|
import tanya.algorithm.mutation;
|
||||||
import tanya.math;
|
import tanya.math;
|
||||||
import tanya.meta.trait;
|
import tanya.meta.trait;
|
||||||
import tanya.meta.transform;
|
import tanya.meta.transform;
|
||||||
@ -809,6 +810,114 @@ template isRandomAccessRange(R)
|
|||||||
static assert(!isRandomAccessRange!Range4);
|
static assert(!isRandomAccessRange!Range4);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Puts $(D_PARAM e) into the $(D_PARAM range).
|
||||||
|
*
|
||||||
|
* $(D_PSYMBOL R) should be an output range for $(D_PARAM E).
|
||||||
|
*
|
||||||
|
* $(D_PARAM range) is advanced after putting an element into it if all of the
|
||||||
|
* following conditions are met:
|
||||||
|
*
|
||||||
|
* $(OL
|
||||||
|
* $(LI $(D_PSYMBOL R) is an input range)
|
||||||
|
* $(LI $(D_PSYMBOL R) doesn't define a `put`-method)
|
||||||
|
* $(LI $(D_PARAM e) can be assigned to $(D_INLINECODE range.front))
|
||||||
|
* )
|
||||||
|
*
|
||||||
|
* Params:
|
||||||
|
* R = Target range type.
|
||||||
|
* E = Source element type.
|
||||||
|
* range = Target range.
|
||||||
|
* e = Source element.
|
||||||
|
*
|
||||||
|
* See_Also: $(D_PSYMBOL isOutputRange).
|
||||||
|
*/
|
||||||
|
void put(R, E)(ref R range, auto ref E e)
|
||||||
|
{
|
||||||
|
static if (__traits(hasMember, R, "put")
|
||||||
|
&& is(typeof((R r, E e) => r.put(e))))
|
||||||
|
{
|
||||||
|
range.put(e);
|
||||||
|
}
|
||||||
|
else static if (isInputRange!R
|
||||||
|
&& is(typeof((R r, E e) => r.front = e)))
|
||||||
|
{
|
||||||
|
range.front = e;
|
||||||
|
range.popFront();
|
||||||
|
}
|
||||||
|
else static if (is(typeof((R r, E e) => r(e))))
|
||||||
|
{
|
||||||
|
range(e);
|
||||||
|
}
|
||||||
|
else static if (isInputRange!E)
|
||||||
|
{
|
||||||
|
for (; !e.empty; e.popFront())
|
||||||
|
{
|
||||||
|
put(range, e.front);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
static assert(false, R.stringof ~ " is not an output range for "
|
||||||
|
~ E.stringof);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
@nogc nothrow pure @safe unittest
|
||||||
|
{
|
||||||
|
int[2] actual;
|
||||||
|
auto slice = actual[];
|
||||||
|
|
||||||
|
put(slice, 2);
|
||||||
|
assert(actual == [2, 0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
@nogc nothrow pure @safe unittest
|
||||||
|
{
|
||||||
|
static struct Put
|
||||||
|
{
|
||||||
|
int e;
|
||||||
|
|
||||||
|
void put(int e)
|
||||||
|
{
|
||||||
|
this.e = e;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Put p;
|
||||||
|
put(p, 2);
|
||||||
|
assert(p.e == 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
@nogc nothrow pure @safe unittest
|
||||||
|
{
|
||||||
|
static struct OpCall
|
||||||
|
{
|
||||||
|
int e;
|
||||||
|
|
||||||
|
void opCall(int e)
|
||||||
|
{
|
||||||
|
this.e = e;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
OpCall oc;
|
||||||
|
put(oc, 2);
|
||||||
|
assert(oc.e == 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
@nogc nothrow pure @safe unittest
|
||||||
|
{
|
||||||
|
int[2] actual;
|
||||||
|
int[2] expected = [2, 3];
|
||||||
|
auto slice = actual[];
|
||||||
|
|
||||||
|
put(slice, expected[]);
|
||||||
|
assert(actual == expected);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Determines whether $(D_PARAM R) is an output range for the elemens of type
|
* Determines whether $(D_PARAM R) is an output range for the elemens of type
|
||||||
* $(D_PARAM E).
|
* $(D_PARAM E).
|
||||||
@ -854,26 +963,7 @@ template isRandomAccessRange(R)
|
|||||||
* Returns: $(D_KEYWORD true) if $(D_PARAM R) is an output range for the
|
* Returns: $(D_KEYWORD true) if $(D_PARAM R) is an output range for the
|
||||||
* elements of the type $(D_PARAM E), $(D_KEYWORD false) otherwise.
|
* elements of the type $(D_PARAM E), $(D_KEYWORD false) otherwise.
|
||||||
*/
|
*/
|
||||||
template isOutputRange(R, E)
|
enum bool isOutputRange(R, E) = is(typeof((ref R r, ref E e) => put(r, e)));
|
||||||
{
|
|
||||||
private enum bool doPut(E) = is(typeof((R r, E e) => r.put(e)))
|
|
||||||
|| (isInputRange!R
|
|
||||||
&& is(typeof((R r, E e) => r.front = e)))
|
|
||||||
|| is(typeof((R r, E e) => r(e)));
|
|
||||||
|
|
||||||
static if (doPut!E)
|
|
||||||
{
|
|
||||||
enum bool isOutputRange = true;
|
|
||||||
}
|
|
||||||
else static if (isInputRange!E)
|
|
||||||
{
|
|
||||||
enum bool isOutputRange = doPut!(ElementType!E);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
enum bool isOutputRange = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
///
|
///
|
||||||
@nogc nothrow pure @safe unittest
|
@nogc nothrow pure @safe unittest
|
||||||
@ -1355,3 +1445,727 @@ if (isBidirectionalRange!R)
|
|||||||
assert(range.empty);
|
assert(range.empty);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Moves the front element of an input range.
|
||||||
|
*
|
||||||
|
* The front element is left in a valid but unspecified state.
|
||||||
|
* $(D_PSYMBOL moveFront) doesn't advances the range, so `popFront` should be
|
||||||
|
* probably called after this function.
|
||||||
|
*
|
||||||
|
* Params:
|
||||||
|
* R = Type of the range.
|
||||||
|
* range = Input range.
|
||||||
|
*
|
||||||
|
* Returns: The front element of the $(D_PSYMBOL range).
|
||||||
|
*
|
||||||
|
* See_Also: $(D_PSYMBOL move).
|
||||||
|
*/
|
||||||
|
ElementType!R moveFront(R)(R range)
|
||||||
|
if (isInputRange!R)
|
||||||
|
{
|
||||||
|
static if (__traits(hasMember, R, "moveFront"))
|
||||||
|
{
|
||||||
|
return range.moveFront();
|
||||||
|
}
|
||||||
|
else static if (!hasElaborateCopyConstructor!(ElementType!R))
|
||||||
|
{
|
||||||
|
return range.front;
|
||||||
|
}
|
||||||
|
else static if (is(typeof(((ref ElementType!R e) => e)(range.front))))
|
||||||
|
{
|
||||||
|
return move(range.front);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
static assert(false, "Front element cannot be moved");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
@nogc nothrow pure @safe unittest
|
||||||
|
{
|
||||||
|
// Defines moveFront.
|
||||||
|
static struct R1
|
||||||
|
{
|
||||||
|
enum bool empty = false;
|
||||||
|
|
||||||
|
int moveFront() @nogc nothrow pure @safe
|
||||||
|
{
|
||||||
|
return 5;
|
||||||
|
}
|
||||||
|
alias front = moveFront;
|
||||||
|
|
||||||
|
void popFront() @nogc nothrow pure @safe
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
assert(moveFront(R1()) == 5);
|
||||||
|
|
||||||
|
// Has elements without a postblit constructor.
|
||||||
|
static struct R2
|
||||||
|
{
|
||||||
|
enum bool empty = false;
|
||||||
|
|
||||||
|
int front() const @nogc nothrow pure @safe
|
||||||
|
{
|
||||||
|
return 5;
|
||||||
|
}
|
||||||
|
|
||||||
|
void popFront() @nogc nothrow pure @safe
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
assert(moveFront(R2()) == 5);
|
||||||
|
|
||||||
|
static struct Element
|
||||||
|
{
|
||||||
|
this(this)
|
||||||
|
{
|
||||||
|
assert(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Returns its elements by reference.
|
||||||
|
static struct R3
|
||||||
|
{
|
||||||
|
Element element;
|
||||||
|
enum bool empty = false;
|
||||||
|
|
||||||
|
ref Element front() @nogc nothrow pure @safe
|
||||||
|
{
|
||||||
|
return element;
|
||||||
|
}
|
||||||
|
|
||||||
|
void popFront() @nogc nothrow pure @safe
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
static assert(is(typeof(moveFront(R3()))));
|
||||||
|
|
||||||
|
// Returns elements with a postblit constructor by value. moveFront fails.
|
||||||
|
static struct R4
|
||||||
|
{
|
||||||
|
enum bool empty = false;
|
||||||
|
|
||||||
|
Element front() @nogc nothrow pure @safe
|
||||||
|
{
|
||||||
|
return Element();
|
||||||
|
}
|
||||||
|
|
||||||
|
void popFront() @nogc nothrow pure @safe
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
static assert(!is(typeof(moveFront(R4()))));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Moves the back element of a bidirectional range.
|
||||||
|
*
|
||||||
|
* The back element is left in a valid but unspecified state.
|
||||||
|
* $(D_PSYMBOL moveBack) doesn't advances the range, so `popBack` should be
|
||||||
|
* probably called after this function.
|
||||||
|
*
|
||||||
|
* Params:
|
||||||
|
* R = Type of the range.
|
||||||
|
* range = Bidirectional range.
|
||||||
|
*
|
||||||
|
* Returns: The back element of the $(D_PSYMBOL range).
|
||||||
|
*
|
||||||
|
* See_Also: $(D_PSYMBOL move).
|
||||||
|
*/
|
||||||
|
ElementType!R moveBack(R)(R range)
|
||||||
|
if (isBidirectionalRange!R)
|
||||||
|
{
|
||||||
|
static if (__traits(hasMember, R, "moveBack"))
|
||||||
|
{
|
||||||
|
return range.moveBack();
|
||||||
|
}
|
||||||
|
else static if (!hasElaborateCopyConstructor!(ElementType!R))
|
||||||
|
{
|
||||||
|
return range.back;
|
||||||
|
}
|
||||||
|
else static if (is(typeof(((ref ElementType!R e) => e)(range.back))))
|
||||||
|
{
|
||||||
|
return move(range.back);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
static assert(false, "Back element cannot be moved");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
@nogc nothrow pure @safe unittest
|
||||||
|
{
|
||||||
|
// Defines moveBack.
|
||||||
|
static struct R1
|
||||||
|
{
|
||||||
|
enum bool empty = false;
|
||||||
|
|
||||||
|
int moveBack() @nogc nothrow pure @safe
|
||||||
|
{
|
||||||
|
return 5;
|
||||||
|
}
|
||||||
|
alias back = moveBack;
|
||||||
|
alias front = moveBack;
|
||||||
|
|
||||||
|
void popBack() @nogc nothrow pure @safe
|
||||||
|
{
|
||||||
|
}
|
||||||
|
alias popFront = popBack;
|
||||||
|
|
||||||
|
R1 save() @nogc nothrow pure @safe
|
||||||
|
{
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
assert(moveBack(R1()) == 5);
|
||||||
|
|
||||||
|
// Has elements without a postblit constructor.
|
||||||
|
static struct R2
|
||||||
|
{
|
||||||
|
enum bool empty = false;
|
||||||
|
|
||||||
|
int back() const @nogc nothrow pure @safe
|
||||||
|
{
|
||||||
|
return 5;
|
||||||
|
}
|
||||||
|
alias front = back;
|
||||||
|
|
||||||
|
void popBack() @nogc nothrow pure @safe
|
||||||
|
{
|
||||||
|
}
|
||||||
|
alias popFront = popBack;
|
||||||
|
|
||||||
|
R2 save() @nogc nothrow pure @safe
|
||||||
|
{
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
assert(moveBack(R2()) == 5);
|
||||||
|
|
||||||
|
static struct Element
|
||||||
|
{
|
||||||
|
this(this)
|
||||||
|
{
|
||||||
|
assert(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Returns its elements by reference.
|
||||||
|
static struct R3
|
||||||
|
{
|
||||||
|
Element element;
|
||||||
|
enum bool empty = false;
|
||||||
|
|
||||||
|
ref Element back() @nogc nothrow pure @safe
|
||||||
|
{
|
||||||
|
return element;
|
||||||
|
}
|
||||||
|
alias front = back;
|
||||||
|
|
||||||
|
void popBack() @nogc nothrow pure @safe
|
||||||
|
{
|
||||||
|
}
|
||||||
|
alias popFront = popBack;
|
||||||
|
|
||||||
|
R3 save() @nogc nothrow pure @safe
|
||||||
|
{
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
static assert(is(typeof(moveBack(R3()))));
|
||||||
|
|
||||||
|
// Returns elements with a postblit constructor by value. moveBack fails.
|
||||||
|
static struct R4
|
||||||
|
{
|
||||||
|
enum bool empty = false;
|
||||||
|
|
||||||
|
Element back() @nogc nothrow pure @safe
|
||||||
|
{
|
||||||
|
return Element();
|
||||||
|
}
|
||||||
|
alias front = back;
|
||||||
|
|
||||||
|
void popBack() @nogc nothrow pure @safe
|
||||||
|
{
|
||||||
|
}
|
||||||
|
alias popFront = popBack;
|
||||||
|
|
||||||
|
R4 save() @nogc nothrow pure @safe
|
||||||
|
{
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
static assert(!is(typeof(moveBack(R4()))));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Moves the element at the position $(D_PARAM n) out of the range.
|
||||||
|
*
|
||||||
|
* The moved element is left in a valid but unspecified state.
|
||||||
|
*
|
||||||
|
* Params:
|
||||||
|
* R = Range type.
|
||||||
|
* range = Random-access range.
|
||||||
|
* n = Element position.
|
||||||
|
*
|
||||||
|
* Returns: The element at the position $(D_PARAM n).
|
||||||
|
*
|
||||||
|
* See_Also: $(D_PSYMBOL move).
|
||||||
|
*/
|
||||||
|
ElementType!R moveAt(R)(R range, size_t n)
|
||||||
|
if (isRandomAccessRange!R)
|
||||||
|
{
|
||||||
|
static if (__traits(hasMember, R, "moveAt"))
|
||||||
|
{
|
||||||
|
return range.moveAt(n);
|
||||||
|
}
|
||||||
|
else static if (!hasElaborateCopyConstructor!(ElementType!R))
|
||||||
|
{
|
||||||
|
return range[n];
|
||||||
|
}
|
||||||
|
else static if (is(typeof(((ref ElementType!R e) => e)(range[0]))))
|
||||||
|
{
|
||||||
|
return move(range[n]);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
static assert(false, "Back element cannot be moved");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
@nogc nothrow pure @safe unittest
|
||||||
|
{
|
||||||
|
// Defines moveAt.
|
||||||
|
static struct R1
|
||||||
|
{
|
||||||
|
enum bool empty = false;
|
||||||
|
|
||||||
|
int front() @nogc nothrow pure @safe
|
||||||
|
{
|
||||||
|
return 5;
|
||||||
|
}
|
||||||
|
|
||||||
|
void popFront() @nogc nothrow pure @safe
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
int moveAt(size_t) @nogc nothrow pure @safe
|
||||||
|
{
|
||||||
|
return 5;
|
||||||
|
}
|
||||||
|
alias opIndex = moveAt;
|
||||||
|
}
|
||||||
|
assert(moveAt(R1(), 0) == 5);
|
||||||
|
|
||||||
|
// Has elements without a postblit constructor.
|
||||||
|
static struct R2
|
||||||
|
{
|
||||||
|
enum bool empty = false;
|
||||||
|
|
||||||
|
int front() const @nogc nothrow pure @safe
|
||||||
|
{
|
||||||
|
return 5;
|
||||||
|
}
|
||||||
|
|
||||||
|
void popFront() @nogc nothrow pure @safe
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
int opIndex(size_t) const @nogc nothrow pure @safe
|
||||||
|
{
|
||||||
|
return 5;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
assert(moveAt(R2(), 0) == 5);
|
||||||
|
|
||||||
|
static struct Element
|
||||||
|
{
|
||||||
|
this(this)
|
||||||
|
{
|
||||||
|
assert(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Returns its elements by reference.
|
||||||
|
static struct R3
|
||||||
|
{
|
||||||
|
Element element;
|
||||||
|
enum bool empty = false;
|
||||||
|
|
||||||
|
ref Element front() @nogc nothrow pure @safe
|
||||||
|
{
|
||||||
|
return element;
|
||||||
|
}
|
||||||
|
|
||||||
|
void popFront() @nogc nothrow pure @safe
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
ref Element opIndex(size_t)
|
||||||
|
{
|
||||||
|
return element;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
static assert(is(typeof(moveAt(R3(), 0))));
|
||||||
|
|
||||||
|
// Returns elements with a postblit constructor by value. moveAt fails.
|
||||||
|
static struct R4
|
||||||
|
{
|
||||||
|
enum bool empty = false;
|
||||||
|
|
||||||
|
Element front() @nogc nothrow pure @safe
|
||||||
|
{
|
||||||
|
return Element();
|
||||||
|
}
|
||||||
|
|
||||||
|
void popFront() @nogc nothrow pure @safe
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
Element opIndex() @nogc nothrow pure @safe
|
||||||
|
{
|
||||||
|
return Element();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
static assert(!is(typeof(moveAt(R4(), 0))));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determines whether $(D_PSYMBOL R) is a range containing mobile elements,
|
||||||
|
* i.e. elements that can be moved out of the range.
|
||||||
|
*
|
||||||
|
* Having mobile elements means for an input range to support
|
||||||
|
* $(D_PSYMBOL moveFront), for a bidirectional range - both,
|
||||||
|
* $(D_PSYMBOL moveFront) and $(D_PSYMBOL moveBack), for a random-access
|
||||||
|
* range - $(D_PSYMBOL moveFront) and $(D_PSYMBOL moveAt).
|
||||||
|
*
|
||||||
|
* Params:
|
||||||
|
* R = Range type.
|
||||||
|
*
|
||||||
|
* Returns: $(D_KEYWORD true) if $(D_PSYMBOL R) has mobile elements,
|
||||||
|
* $(D_KEYWORD false) otherwise.
|
||||||
|
*
|
||||||
|
* See_Also: $(D_PSYMBOL moveFront), $(D_PSYMBOL moveBack),
|
||||||
|
* $(D_PSYMBOL moveAt).
|
||||||
|
*/
|
||||||
|
template hasMobileElements(R)
|
||||||
|
{
|
||||||
|
static if (isRandomAccessRange!R)
|
||||||
|
{
|
||||||
|
enum bool hasMobileElements = is(typeof((R r) => moveFront(r)))
|
||||||
|
&& is(typeof((R r) => moveAt(r, 0)));
|
||||||
|
}
|
||||||
|
else static if (isBidirectionalRange!R)
|
||||||
|
{
|
||||||
|
enum bool hasMobileElements = is(typeof((R r) => moveFront(r)))
|
||||||
|
&& is(typeof((R r) => moveBack(r)));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
enum bool hasMobileElements = is(typeof((R r) => moveFront(r)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
@nogc nothrow pure @safe unittest
|
||||||
|
{
|
||||||
|
// Input range with elements without a postblit constructor.
|
||||||
|
// These can be moved.
|
||||||
|
static struct InputRange
|
||||||
|
{
|
||||||
|
enum bool empty = false;
|
||||||
|
|
||||||
|
int front() @nogc nothrow pure @safe
|
||||||
|
{
|
||||||
|
return 5;
|
||||||
|
}
|
||||||
|
|
||||||
|
void popFront() @nogc nothrow pure @safe
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
static assert(hasMobileElements!InputRange);
|
||||||
|
|
||||||
|
static struct Element
|
||||||
|
{
|
||||||
|
this(this)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Bidirectional range, whose elements cannot be moved. The range defines
|
||||||
|
// only moveFront, but not moveBack. So it doesn't have mobile elements.
|
||||||
|
static struct BidirectionalRange
|
||||||
|
{
|
||||||
|
enum bool empty = false;
|
||||||
|
|
||||||
|
Element front() @nogc nothrow pure @safe
|
||||||
|
{
|
||||||
|
return Element();
|
||||||
|
}
|
||||||
|
alias back = front;
|
||||||
|
alias moveFront = front;
|
||||||
|
|
||||||
|
void popFront() @nogc nothrow pure @safe
|
||||||
|
{
|
||||||
|
}
|
||||||
|
alias popBack = popFront;
|
||||||
|
|
||||||
|
BidirectionalRange save() @nogc nothrow pure @safe
|
||||||
|
{
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
static assert(!hasMobileElements!BidirectionalRange);
|
||||||
|
|
||||||
|
// Access-random range, whose elements cannot be moved, but the range
|
||||||
|
// defines both, moveFront and moveAt.
|
||||||
|
static struct RandomAccessRange
|
||||||
|
{
|
||||||
|
enum bool empty = false;
|
||||||
|
|
||||||
|
Element front() @nogc nothrow pure @safe
|
||||||
|
{
|
||||||
|
return Element();
|
||||||
|
}
|
||||||
|
alias moveFront = front;
|
||||||
|
|
||||||
|
void popFront() @nogc nothrow pure @safe
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
Element opIndex(size_t) @nogc nothrow pure @safe
|
||||||
|
{
|
||||||
|
return Element();
|
||||||
|
}
|
||||||
|
alias moveAt = opIndex;
|
||||||
|
}
|
||||||
|
static assert(hasMobileElements!RandomAccessRange);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determines whether $(D_PARAM R) provides access to its elements by
|
||||||
|
* reference.
|
||||||
|
*
|
||||||
|
* Params:
|
||||||
|
* R = Range type.
|
||||||
|
*
|
||||||
|
* Returns: $(D_KEYWORD true) if $(D_PARAM R) has lvalue elements,
|
||||||
|
* $(D_KEYWORD false) otherwise.
|
||||||
|
*/
|
||||||
|
template hasLvalueElements(R)
|
||||||
|
{
|
||||||
|
private alias refDg = (ref ElementType!R e) => e;
|
||||||
|
|
||||||
|
static if (isRandomAccessRange!R)
|
||||||
|
{
|
||||||
|
enum bool hasLvalueElements = is(typeof(refDg(R.init.front)))
|
||||||
|
&& is(typeof(refDg(R.init[0])));
|
||||||
|
}
|
||||||
|
else static if (isBidirectionalRange!R)
|
||||||
|
{
|
||||||
|
enum bool hasLvalueElements = is(typeof(refDg(R.init.front)))
|
||||||
|
&& is(typeof(refDg(R.init.back)));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
enum bool hasLvalueElements = is(typeof(refDg(R.init.front)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
@nogc nothrow pure @safe unittest
|
||||||
|
{
|
||||||
|
static struct R1
|
||||||
|
{
|
||||||
|
enum bool empty = false;
|
||||||
|
|
||||||
|
int front() @nogc nothrow pure @safe
|
||||||
|
{
|
||||||
|
return 5;
|
||||||
|
}
|
||||||
|
|
||||||
|
void popFront() @nogc nothrow pure @safe
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
static assert(!hasLvalueElements!R1);
|
||||||
|
|
||||||
|
static struct R2
|
||||||
|
{
|
||||||
|
int element;
|
||||||
|
enum bool empty = false;
|
||||||
|
|
||||||
|
ref const(int) front() const @nogc nothrow pure @safe
|
||||||
|
{
|
||||||
|
return element;
|
||||||
|
}
|
||||||
|
|
||||||
|
void popFront() @nogc nothrow pure @safe
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
ref const(int) opIndex(size_t) const @nogc nothrow pure @safe
|
||||||
|
{
|
||||||
|
return element;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
static assert(hasLvalueElements!R2);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determines whether the elements of $(D_PARAM R) are assignable.
|
||||||
|
*
|
||||||
|
* Params:
|
||||||
|
* R = Range type.
|
||||||
|
*
|
||||||
|
* Returns: $(D_KEYWORD true) if the elements of $(D_PARAM R) are assignable
|
||||||
|
* $(D_KEYWORD false) otherwise.
|
||||||
|
*/
|
||||||
|
template hasAssignableElements(R)
|
||||||
|
{
|
||||||
|
static if (isRandomAccessRange!R)
|
||||||
|
{
|
||||||
|
enum bool assignable = is(typeof({R.init.front = R.init.front;}))
|
||||||
|
&& is(typeof({R.init[0] = R.init[0];}));
|
||||||
|
}
|
||||||
|
else static if (isBidirectionalRange!R)
|
||||||
|
{
|
||||||
|
enum bool assignable = is(typeof({R.init.front = R.init.front;}))
|
||||||
|
&& is(typeof({R.init.back = R.init.back;}));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
enum bool assignable = is(typeof({R.init.front = R.init.front;}));
|
||||||
|
}
|
||||||
|
enum bool hasAssignableElements = assignable;
|
||||||
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
@nogc nothrow pure @safe unittest
|
||||||
|
{
|
||||||
|
static struct R1
|
||||||
|
{
|
||||||
|
int element;
|
||||||
|
enum bool empty = false;
|
||||||
|
|
||||||
|
ref int front() @nogc nothrow pure @safe
|
||||||
|
{
|
||||||
|
return element;
|
||||||
|
}
|
||||||
|
alias back = front;
|
||||||
|
|
||||||
|
void popFront() @nogc nothrow pure @safe
|
||||||
|
{
|
||||||
|
}
|
||||||
|
alias popBack = popFront;
|
||||||
|
|
||||||
|
R1 save() const @nogc nothrow pure @safe
|
||||||
|
{
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
static assert(hasAssignableElements!R1);
|
||||||
|
|
||||||
|
static struct R2
|
||||||
|
{
|
||||||
|
int element;
|
||||||
|
enum bool empty = false;
|
||||||
|
|
||||||
|
ref const(int) front() const @nogc nothrow pure @safe
|
||||||
|
{
|
||||||
|
return element;
|
||||||
|
}
|
||||||
|
alias back = front;
|
||||||
|
|
||||||
|
void popFront() @nogc nothrow pure @safe
|
||||||
|
{
|
||||||
|
}
|
||||||
|
alias popBack = popFront;
|
||||||
|
|
||||||
|
R2 save() const @nogc nothrow pure @safe
|
||||||
|
{
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
static assert(!hasAssignableElements!R2);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determines whether the elements of $(D_PSYMBOL R) can be swapped with
|
||||||
|
* $(D_PSYMBOL swap).
|
||||||
|
*
|
||||||
|
* Params:
|
||||||
|
* R = Range type.
|
||||||
|
*
|
||||||
|
* Returns: $(D_KEYWORD true) if $(D_PARAM R) has swappable elements,
|
||||||
|
* $(D_KEYWORD false) otherwise.
|
||||||
|
*/
|
||||||
|
template hasSwappableElements(R)
|
||||||
|
{
|
||||||
|
static if (isRandomAccessRange!R)
|
||||||
|
{
|
||||||
|
enum bool hasSwappableElements = is(typeof(swap(R.init.front, R.init.front)))
|
||||||
|
&& is(typeof(swap(R.init[0], R.init[0])));
|
||||||
|
}
|
||||||
|
else static if (isBidirectionalRange!R)
|
||||||
|
{
|
||||||
|
enum bool hasSwappableElements = is(typeof(swap(R.init.front, R.init.front)))
|
||||||
|
&& is(typeof(swap(R.init.back, R.init.back)));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
enum bool hasSwappableElements = is(typeof(swap(R.init.front, R.init.front)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
@nogc nothrow pure @safe unittest
|
||||||
|
{
|
||||||
|
static struct R1
|
||||||
|
{
|
||||||
|
int element;
|
||||||
|
enum bool empty = false;
|
||||||
|
|
||||||
|
ref int front() @nogc nothrow pure @safe
|
||||||
|
{
|
||||||
|
return element;
|
||||||
|
}
|
||||||
|
alias back = front;
|
||||||
|
|
||||||
|
void popFront() @nogc nothrow pure @safe
|
||||||
|
{
|
||||||
|
}
|
||||||
|
alias popBack = popFront;
|
||||||
|
|
||||||
|
R1 save() const @nogc nothrow pure @safe
|
||||||
|
{
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
static assert(hasSwappableElements!R1);
|
||||||
|
|
||||||
|
static struct R2
|
||||||
|
{
|
||||||
|
int element;
|
||||||
|
enum bool empty = false;
|
||||||
|
|
||||||
|
int front() const @nogc nothrow pure @safe
|
||||||
|
{
|
||||||
|
return element;
|
||||||
|
}
|
||||||
|
alias back = front;
|
||||||
|
|
||||||
|
void popFront() @nogc nothrow pure @safe
|
||||||
|
{
|
||||||
|
}
|
||||||
|
alias popBack = popFront;
|
||||||
|
|
||||||
|
R2 save() const @nogc nothrow pure @safe
|
||||||
|
{
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
static assert(!hasSwappableElements!R2);
|
||||||
|
}
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
* This module contains templates that allow to build new types from the
|
* This module contains templates that allow to build new types from the
|
||||||
* available ones.
|
* available ones.
|
||||||
*
|
*
|
||||||
* Copyright: Eugene Wissner 2017.
|
* Copyright: Eugene Wissner 2017-2018.
|
||||||
* 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).
|
||||||
* Authors: $(LINK2 mailto:info@caraus.de, Eugene Wissner)
|
* Authors: $(LINK2 mailto:info@caraus.de, Eugene Wissner)
|
||||||
@ -36,7 +36,7 @@ import tanya.meta.metafunction;
|
|||||||
*/
|
*/
|
||||||
template Pair(Specs...)
|
template Pair(Specs...)
|
||||||
{
|
{
|
||||||
template parseSpecs(int fieldCount, Specs...)
|
template parseSpecs(size_t fieldCount, Specs...)
|
||||||
{
|
{
|
||||||
static if (Specs.length == 0)
|
static if (Specs.length == 0)
|
||||||
{
|
{
|
||||||
@ -47,13 +47,13 @@ template Pair(Specs...)
|
|||||||
static if (is(typeof(Specs[1]) == string))
|
static if (is(typeof(Specs[1]) == string))
|
||||||
{
|
{
|
||||||
alias parseSpecs
|
alias parseSpecs
|
||||||
= AliasSeq!(Specs[0],
|
= AliasSeq!(Tuple!(Specs[0], Specs[1]),
|
||||||
parseSpecs!(fieldCount + 1, Specs[2 .. $]));
|
parseSpecs!(fieldCount + 1, Specs[2 .. $]));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
alias parseSpecs
|
alias parseSpecs
|
||||||
= AliasSeq!(Specs[0],
|
= AliasSeq!(Tuple!(Specs[0]),
|
||||||
parseSpecs!(fieldCount + 1, Specs[1 .. $]));
|
parseSpecs!(fieldCount + 1, Specs[1 .. $]));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -63,25 +63,24 @@ template Pair(Specs...)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
alias ChooseType(alias T) = T.Seq[0];
|
||||||
|
alias ParsedSpecs = parseSpecs!(0, Specs);
|
||||||
|
|
||||||
|
static assert(ParsedSpecs.length == 2, "Invalid argument count");
|
||||||
|
|
||||||
struct Pair
|
struct Pair
|
||||||
{
|
{
|
||||||
/// Field types.
|
/// Field types.
|
||||||
alias Types = parseSpecs!(0, Specs);
|
alias Types = Map!(ChooseType, ParsedSpecs);
|
||||||
|
|
||||||
static assert(Types.length == 2, "Invalid argument count.");
|
|
||||||
|
|
||||||
// Create field aliases.
|
// Create field aliases.
|
||||||
static if (is(typeof(Specs[1]) == string))
|
static if (ParsedSpecs[0].length == 2)
|
||||||
{
|
{
|
||||||
mixin("alias " ~ Specs[1] ~ " = expand[0];");
|
mixin("alias " ~ ParsedSpecs[0][1] ~ " = expand[0];");
|
||||||
}
|
}
|
||||||
static if (is(typeof(Specs[2]) == string))
|
static if (ParsedSpecs[1].length == 2)
|
||||||
{
|
{
|
||||||
mixin("alias " ~ Specs[2] ~ " = expand[1];");
|
mixin("alias " ~ ParsedSpecs[1][1] ~ " = expand[1];");
|
||||||
}
|
|
||||||
else static if (is(typeof(Specs[3]) == string))
|
|
||||||
{
|
|
||||||
mixin("alias " ~ Specs[3] ~ " = expand[1];");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Represents the values of the $(D_PSYMBOL Pair) as a list of values.
|
/// Represents the values of the $(D_PSYMBOL Pair) as a list of values.
|
||||||
@ -92,6 +91,15 @@ template Pair(Specs...)
|
|||||||
}
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
|
@nogc nothrow pure @safe unittest
|
||||||
|
{
|
||||||
|
auto pair = Pair!(int, "first", string, "second")(1, "second");
|
||||||
|
assert(pair.first == 1);
|
||||||
|
assert(pair[0] == 1);
|
||||||
|
assert(pair.second == "second");
|
||||||
|
assert(pair[1] == "second");
|
||||||
|
}
|
||||||
|
|
||||||
@nogc nothrow pure @safe unittest
|
@nogc nothrow pure @safe unittest
|
||||||
{
|
{
|
||||||
static assert(is(Pair!(int, int)));
|
static assert(is(Pair!(int, int)));
|
||||||
|
Reference in New Issue
Block a user