27 Commits

Author SHA1 Message Date
792d289541 range.primitive: Add missing rparen to the docs 2018-03-27 05:19:14 +02:00
92f21a95cf Add hashing pointers 2018-03-27 05:18:46 +02:00
72140a8583 Add documentation for the hash function 2018-03-27 05:09:44 +02:00
442fa5b46a Fix hashing scalar types 2018-03-27 05:09:22 +02:00
0d6d8f6a91 Add hash combining for ranges 2018-03-27 05:09:09 +02:00
cefc4e24b5 Add FNV-1a test vectors 2018-03-27 05:08:55 +02:00
1adc4cd868 Add hash.lookup module 2018-03-27 05:08:28 +02:00
8faccbada4 Deprecate meta.trait.hasMember 2018-03-26 20:38:57 +02:00
9fb043ba65 Fix typeof(null) being a pointer for isPointer 2018-03-25 09:19:35 +02:00
162db622ea Add assignable-, lvalue- and swappable checks
... for ranges.

Also adds "put" for the output ranges.

Fix #34.
2018-03-23 08:49:24 +01:00
a7c1e642e9 Implement moveFront, moveBack, moveAt
... and hasMobileElements.
2018-03-22 10:44:58 +01:00
7829b1fe06 Remove static std.range import 2018-03-22 10:44:52 +01:00
cb742eec82 meta.trait: Deprecate one-liner
These one-liners are useful for meta-programming but they can be easely
implemented. It isn't possible to implement all possible variants in a
generic library, so it is better they are defined in the user code.

Deprecated traits:
- isPOD
- sizeOf
- alignOf
- isSame
- isTemplate
- isInterface
- isClass
- isStruct
- isEnum
2018-03-21 10:10:55 +01:00
341068488d meta.trait: Make unittest structs static 2018-03-21 10:04:05 +01:00
9b0bc77b7a async: Remove unused imports 2018-03-21 08:30:47 +01:00
c9e4871fb5 algorithm.mutation: Fix param name in the docs 2018-03-21 08:15:58 +01:00
1f4ab88254 typecons.Pair: Add better documentation unittests 2018-03-21 08:14:52 +01:00
7af5b4db72 metafunction: Make Set and Tuple to structs
It allows to use alias this to access the elements by index.
2018-03-20 17:20:13 +01:00
363ebbe3df Extend release policy 2018-03-18 05:53:38 +01:00
ecd74cbf1e Describe NogcD subset 2018-03-17 08:17:51 +01:00
80a177179d Add hash table to the "Current status" branches 2018-03-15 05:46:42 +01:00
2532d49105 Ignore .lib files 2018-03-11 11:40:46 +01:00
abfccc35a2 Merge remote-tracking branch 'origin/feature/queue-dlist'
Fix #31.
2018-03-10 07:41:02 +01:00
629071f934 Add information that DList can be used as a queue 2018-03-10 07:17:43 +01:00
17cb592b13 Replace Queue with DList 2018-03-09 08:19:17 +01:00
82f41844b1 container.list: Document front/back preconditions 2018-03-09 08:00:28 +01:00
8fa033a49f Fix #32 2018-03-09 05:27:32 +01:00
31 changed files with 1698 additions and 156 deletions

1
.gitignore vendored
View File

@ -1,6 +1,7 @@
# Binary # Binary
*.[oa] *.[oa]
*.exe *.exe
*.lib
# D # D
.dub .dub

View File

@ -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,12 +147,31 @@ 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 | |
@ -159,22 +182,40 @@ There are more containers in the `tanya.container` package.
Following modules are under development: Following modules are under development:
| Feature | Branch | Build status | | Feature | Branch | Build status |
|----------|:---------:|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| |------------|:---------:|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| BitArray | bitvector | [![bitvector](https://travis-ci.org/caraus-ecms/tanya.svg?branch=bitvector)](https://travis-ci.org/caraus-ecms/tanya) [![bitvector](https://ci.appveyor.com/api/projects/status/djkmverdfsylc7ti/branch/bitvector?svg=true)](https://ci.appveyor.com/project/belka-ew/tanya/branch/bitvector) | | Hash table | bitvector | [![bitvector](https://travis-ci.org/caraus-ecms/tanya.svg?branch=bitvector)](https://travis-ci.org/caraus-ecms/tanya) [![bitvector](https://ci.appveyor.com/api/projects/status/djkmverdfsylc7ti/branch/bitvector?svg=true)](https://ci.appveyor.com/project/belka-ew/tanya/branch/bitvector) |
| TLS | crypto | [![crypto](https://travis-ci.org/caraus-ecms/tanya.svg?branch=crypto)](https://travis-ci.org/caraus-ecms/tanya) [![crypto](https://ci.appveyor.com/api/projects/status/djkmverdfsylc7ti/branch/crypto?svg=true)](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

View File

@ -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"]
} }

View File

@ -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
{ {

View File

@ -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)

View File

@ -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)

View File

@ -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:

View File

@ -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)

View File

@ -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);
} }
} }
} }

View File

@ -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)

View File

@ -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();

View File

@ -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)

View File

@ -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)

View File

@ -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)

View File

@ -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);
} }
} }
} }

View File

@ -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)

View File

@ -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)

View File

@ -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)

View File

@ -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

View File

@ -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)

View File

@ -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;

View File

@ -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)

View File

@ -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
View 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);
}

View 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;

View File

@ -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)));
} }
/** /**

View File

@ -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)

View File

@ -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;

View File

@ -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)

View File

@ -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);
}

View File

@ -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)));