Compare commits
22 Commits
Author | SHA1 | Date | |
---|---|---|---|
a188f8b6e2 | |||
9355c54163 | |||
e8dd6e3217 | |||
94a7fdbb91 | |||
afd3c42c5f | |||
1d91bb4df9 | |||
a5026e48d8 | |||
64f2295d1a | |||
dea0eb9a37 | |||
7c2abadb90 | |||
e6b28468ca | |||
2934bb16d7 | |||
ed92e3993e | |||
1a4d1238a1 | |||
04864559e2 | |||
40e43c1465 | |||
5d145f524c | |||
51ade45108 | |||
3afb40e09e | |||
a9cc135318 | |||
1389b03842 | |||
a37c9b162e |
@ -7,11 +7,9 @@ os:
|
|||||||
language: d
|
language: d
|
||||||
|
|
||||||
d:
|
d:
|
||||||
- dmd-2.075.0
|
- dmd-2.075.1
|
||||||
- dmd-2.074.1
|
- dmd-2.074.1
|
||||||
- dmd-2.073.2
|
- dmd-2.073.2
|
||||||
- dmd-2.072.2
|
|
||||||
- dmd-2.071.2
|
|
||||||
|
|
||||||
env:
|
env:
|
||||||
matrix:
|
matrix:
|
||||||
@ -24,15 +22,12 @@ addons:
|
|||||||
- gcc-multilib
|
- gcc-multilib
|
||||||
|
|
||||||
before_script:
|
before_script:
|
||||||
- if [ "$PS1" = '(dmd-2.075.0)' ]; then
|
- if [ "$PS1" = '(dmd-2.075.1)' ]; then
|
||||||
export UNITTEST="unittest-cov";
|
export UNITTEST="unittest-cov";
|
||||||
fi
|
fi
|
||||||
|
|
||||||
script:
|
script:
|
||||||
- dub test -b ${UNITTEST:-unittest} --arch=$ARCH --compiler=$DC
|
- dub test -b ${UNITTEST:-unittest} --arch=$ARCH --compiler=$DC
|
||||||
- if [ "$UNITTEST" = "unittest-cov" -a "$ARCH" = "x86_64" -a "$TRAVIS_OS_NAME" = "linux" ]; then
|
|
||||||
dub fetch dscanner && dub run dscanner -- -Isource --styleCheck;
|
|
||||||
fi
|
|
||||||
|
|
||||||
after_success:
|
after_success:
|
||||||
- test "$UNITTEST" = "unittest-cov" && bash <(curl -s https://codecov.io/bash)
|
- test "$UNITTEST" = "unittest-cov" && bash <(curl -s https://codecov.io/bash)
|
||||||
|
@ -127,7 +127,7 @@ foreach (el; arr[0 .. 5])
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
int i = arr[7]; // Access 7th element.
|
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.
|
||||||
@ -139,11 +139,9 @@ There are more containers in the `tanya.container` package.
|
|||||||
|
|
||||||
| dmd |
|
| dmd |
|
||||||
|:-------:|
|
|:-------:|
|
||||||
| 2.075.0 |
|
| 2.075.1 |
|
||||||
| 2.074.1 |
|
| 2.074.1 |
|
||||||
| 2.073.2 |
|
| 2.073.2 |
|
||||||
| 2.072.2 |
|
|
||||||
| 2.071.2 |
|
|
||||||
|
|
||||||
### Current status
|
### Current status
|
||||||
|
|
||||||
|
22
appveyor.yml
22
appveyor.yml
@ -4,10 +4,10 @@ os: Visual Studio 2015
|
|||||||
environment:
|
environment:
|
||||||
matrix:
|
matrix:
|
||||||
- DC: dmd
|
- DC: dmd
|
||||||
DVersion: 2.075.0
|
DVersion: 2.075.1
|
||||||
arch: x64
|
arch: x64
|
||||||
- DC: dmd
|
- DC: dmd
|
||||||
DVersion: 2.075.0
|
DVersion: 2.075.1
|
||||||
arch: x86
|
arch: x86
|
||||||
- DC: dmd
|
- DC: dmd
|
||||||
DVersion: 2.074.1
|
DVersion: 2.074.1
|
||||||
@ -21,18 +21,6 @@ environment:
|
|||||||
- DC: dmd
|
- DC: dmd
|
||||||
DVersion: 2.073.2
|
DVersion: 2.073.2
|
||||||
arch: x86
|
arch: x86
|
||||||
- DC: dmd
|
|
||||||
DVersion: 2.072.2
|
|
||||||
arch: x64
|
|
||||||
- DC: dmd
|
|
||||||
DVersion: 2.072.2
|
|
||||||
arch: x86
|
|
||||||
- DC: dmd
|
|
||||||
DVersion: 2.071.2
|
|
||||||
arch: x64
|
|
||||||
- DC: dmd
|
|
||||||
DVersion: 2.071.2
|
|
||||||
arch: x86
|
|
||||||
|
|
||||||
skip_tags: true
|
skip_tags: true
|
||||||
|
|
||||||
@ -49,12 +37,6 @@ install:
|
|||||||
}
|
}
|
||||||
- ps: SetUpDCompiler
|
- ps: SetUpDCompiler
|
||||||
|
|
||||||
- ps: if($env:DVersion -eq "2.071.2"){
|
|
||||||
Invoke-WebRequest "http://code.dlang.org/files/dub-1.2.1-windows-x86.zip" -OutFile "dub.zip";
|
|
||||||
7z x dub.zip -odub > $null;
|
|
||||||
Move-Item "dub/dub.exe" "C:\dmd2\windows\bin"
|
|
||||||
}
|
|
||||||
|
|
||||||
before_build:
|
before_build:
|
||||||
- ps: if($env:arch -eq "x86"){
|
- ps: if($env:arch -eq "x86"){
|
||||||
$env:compilersetupargs = "x86";
|
$env:compilersetupargs = "x86";
|
||||||
|
@ -2,13 +2,15 @@
|
|||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
* 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/. */
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
/*
|
/**
|
||||||
* Event loop implementation for Linux.
|
* Event loop implementation for Linux.
|
||||||
*
|
*
|
||||||
* Copyright: Eugene Wissner 2016-2017.
|
* Copyright: Eugene Wissner 2016-2017.
|
||||||
* License: $(LINK2 https://www.mozilla.org/en-US/MPL/2.0/,
|
* License: $(LINK2 https://www.mozilla.org/en-US/MPL/2.0/,
|
||||||
* Mozilla Public License, v. 2.0).
|
* Mozilla Public License, v. 2.0).
|
||||||
* 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/async/event/epoll.d,
|
||||||
|
* tanya/async/event/epoll.d)
|
||||||
*/
|
*/
|
||||||
module tanya.async.event.epoll;
|
module tanya.async.event.epoll;
|
||||||
|
|
||||||
|
@ -2,13 +2,15 @@
|
|||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
* 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/. */
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
/*
|
/**
|
||||||
* Event loop implementation for Windows.
|
* Event loop implementation for Windows.
|
||||||
*
|
*
|
||||||
* Copyright: Eugene Wissner 2016-2017.
|
* Copyright: Eugene Wissner 2016-2017.
|
||||||
* License: $(LINK2 https://www.mozilla.org/en-US/MPL/2.0/,
|
* License: $(LINK2 https://www.mozilla.org/en-US/MPL/2.0/,
|
||||||
* Mozilla Public License, v. 2.0).
|
* Mozilla Public License, v. 2.0).
|
||||||
* 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/async/event/iocp.d,
|
||||||
|
* tanya/async/event/iocp.d)
|
||||||
*/
|
*/
|
||||||
module tanya.async.event.iocp;
|
module tanya.async.event.iocp;
|
||||||
|
|
||||||
|
@ -9,6 +9,8 @@
|
|||||||
* 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/async/event/kqueue.d,
|
||||||
|
* tanya/async/event/kqueue.d)
|
||||||
*/
|
*/
|
||||||
module tanya.async.event.kqueue;
|
module tanya.async.event.kqueue;
|
||||||
|
|
||||||
|
@ -9,6 +9,8 @@
|
|||||||
* 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/async/event/selector.d,
|
||||||
|
* tanya/async/event/selector.d)
|
||||||
*/
|
*/
|
||||||
module tanya.async.event.selector;
|
module tanya.async.event.selector;
|
||||||
|
|
||||||
|
@ -11,6 +11,8 @@
|
|||||||
* 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/async/iocp.d,
|
||||||
|
* tanya/async/iocp.d)
|
||||||
*/
|
*/
|
||||||
module tanya.async.iocp;
|
module tanya.async.iocp;
|
||||||
|
|
||||||
|
@ -64,6 +64,8 @@
|
|||||||
* 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/async/loop.d,
|
||||||
|
* tanya/async/loop.d)
|
||||||
*/
|
*/
|
||||||
module tanya.async.loop;
|
module tanya.async.loop;
|
||||||
|
|
||||||
|
@ -9,6 +9,8 @@
|
|||||||
* 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/async/package.d,
|
||||||
|
* tanya/async/package.d)
|
||||||
*/
|
*/
|
||||||
module tanya.async;
|
module tanya.async;
|
||||||
|
|
||||||
|
@ -13,6 +13,8 @@
|
|||||||
* 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/async/protocol.d,
|
||||||
|
* tanya/async/protocol.d)
|
||||||
*/
|
*/
|
||||||
module tanya.async.protocol;
|
module tanya.async.protocol;
|
||||||
|
|
||||||
|
@ -10,6 +10,8 @@
|
|||||||
* 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/async/transport.d,
|
||||||
|
* tanya/async/transport.d)
|
||||||
*/
|
*/
|
||||||
module tanya.async.transport;
|
module tanya.async.transport;
|
||||||
|
|
||||||
|
@ -9,6 +9,8 @@
|
|||||||
* 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/async/watcher.d,
|
||||||
|
* tanya/async/watcher.d)
|
||||||
*/
|
*/
|
||||||
module tanya.async.watcher;
|
module tanya.async.watcher;
|
||||||
|
|
||||||
|
@ -9,6 +9,8 @@
|
|||||||
* 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/array.d,
|
||||||
|
* tanya/container/array.d)
|
||||||
*/
|
*/
|
||||||
module tanya.container.array;
|
module tanya.container.array;
|
||||||
|
|
||||||
|
@ -9,6 +9,8 @@
|
|||||||
* 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/buffer.d,
|
||||||
|
* tanya/container/buffer.d)
|
||||||
*/
|
*/
|
||||||
module tanya.container.buffer;
|
module tanya.container.buffer;
|
||||||
|
|
||||||
|
@ -9,6 +9,8 @@
|
|||||||
* 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/entry.d,
|
||||||
|
* tanya/container/entry.d)
|
||||||
*/
|
*/
|
||||||
module tanya.container.entry;
|
module tanya.container.entry;
|
||||||
|
|
||||||
@ -53,11 +55,6 @@ package enum BucketStatus : byte
|
|||||||
|
|
||||||
package struct Bucket(T)
|
package struct Bucket(T)
|
||||||
{
|
{
|
||||||
this(ref T content)
|
|
||||||
{
|
|
||||||
this.content = content;
|
|
||||||
}
|
|
||||||
|
|
||||||
@property void content(ref T content)
|
@property void content(ref T content)
|
||||||
{
|
{
|
||||||
this.content_ = content;
|
this.content_ = content;
|
||||||
@ -78,7 +75,7 @@ package struct Bucket(T)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool opEquals(ref T content) const
|
bool opEquals(ref const T content) const
|
||||||
{
|
{
|
||||||
if (this.status == BucketStatus.used && this.content == content)
|
if (this.status == BucketStatus.used && this.content == content)
|
||||||
{
|
{
|
||||||
|
@ -9,6 +9,8 @@
|
|||||||
* 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/list.d,
|
||||||
|
* tanya/container/list.d)
|
||||||
*/
|
*/
|
||||||
module tanya.container.list;
|
module tanya.container.list;
|
||||||
|
|
||||||
|
@ -9,6 +9,8 @@
|
|||||||
* 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/package.d,
|
||||||
|
* tanya/container/package.d)
|
||||||
*/
|
*/
|
||||||
module tanya.container;
|
module tanya.container;
|
||||||
|
|
||||||
|
@ -9,6 +9,8 @@
|
|||||||
* 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,
|
||||||
|
* tanya/container/queue.d)
|
||||||
*/
|
*/
|
||||||
module tanya.container.queue;
|
module tanya.container.queue;
|
||||||
|
|
||||||
|
@ -10,6 +10,8 @@
|
|||||||
* 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/set.d,
|
||||||
|
* tanya/container/set.d)
|
||||||
*/
|
*/
|
||||||
module tanya.container.set;
|
module tanya.container.set;
|
||||||
|
|
||||||
@ -349,7 +351,8 @@ struct Set(T)
|
|||||||
/// The maximum number of buckets the container can have.
|
/// The maximum number of buckets the container can have.
|
||||||
enum size_t maxBucketCount = primes[$ - 1];
|
enum size_t maxBucketCount = primes[$ - 1];
|
||||||
|
|
||||||
static private size_t calculateHash(ref T value)
|
static private size_t calculateHash(U)(ref const U value)
|
||||||
|
if (is(U == Unqual!T))
|
||||||
{
|
{
|
||||||
static if (isIntegral!T || isSomeChar!T || is(T == bool))
|
static if (isIntegral!T || isSomeChar!T || is(T == bool))
|
||||||
{
|
{
|
||||||
@ -361,11 +364,26 @@ struct Set(T)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static private size_t locateBucket(ref const DataType buckets, size_t hash)
|
static private size_t locateBucket(ref const DataType buckets,
|
||||||
|
const size_t hash)
|
||||||
|
in
|
||||||
|
{
|
||||||
|
assert(buckets.length > 0);
|
||||||
|
}
|
||||||
|
body
|
||||||
{
|
{
|
||||||
return hash % buckets.length;
|
return hash % buckets.length;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Returns bucket position for `hash`. `0` may mean the 0th position or an
|
||||||
|
* empty `buckets` array.
|
||||||
|
*/
|
||||||
|
private size_t locateBucket(const size_t hash) const
|
||||||
|
{
|
||||||
|
return this.data.length == 0 ? 0 : locateBucket(this.data, hash);
|
||||||
|
}
|
||||||
|
|
||||||
private enum InsertStatus : byte
|
private enum InsertStatus : byte
|
||||||
{
|
{
|
||||||
found = -1,
|
found = -1,
|
||||||
@ -376,7 +394,8 @@ struct Set(T)
|
|||||||
/*
|
/*
|
||||||
* Inserts the value in an empty or deleted bucket. If the value is
|
* Inserts the value in an empty or deleted bucket. If the value is
|
||||||
* already in there, does nothing and returns InsertStatus.found. If the
|
* already in there, does nothing and returns InsertStatus.found. If the
|
||||||
* hash array is full returns InsertStatus.failed.
|
* hash array is full returns InsertStatus.failed. Otherwise,
|
||||||
|
* InsertStatus.added is returned.
|
||||||
*/
|
*/
|
||||||
private InsertStatus insertInUnusedBucket(ref T value)
|
private InsertStatus insertInUnusedBucket(ref T value)
|
||||||
{
|
{
|
||||||
@ -456,12 +475,7 @@ struct Set(T)
|
|||||||
*/
|
*/
|
||||||
size_t remove(T value)
|
size_t remove(T value)
|
||||||
{
|
{
|
||||||
if (this.data.length == 0)
|
auto bucketPosition = locateBucket(calculateHash(value));
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto bucketPosition = locateBucket(this.data, calculateHash(value));
|
|
||||||
foreach (ref e; this.data[bucketPosition .. $])
|
foreach (ref e; this.data[bucketPosition .. $])
|
||||||
{
|
{
|
||||||
if (e == value) // Found.
|
if (e == value) // Found.
|
||||||
@ -478,7 +492,7 @@ struct Set(T)
|
|||||||
}
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
unittest
|
@nogc unittest
|
||||||
{
|
{
|
||||||
Set!int set;
|
Set!int set;
|
||||||
assert(8 !in set);
|
assert(8 !in set);
|
||||||
@ -500,14 +514,9 @@ struct Set(T)
|
|||||||
* Returns: $(D_KEYWORD true) if the given element exists in the container,
|
* Returns: $(D_KEYWORD true) if the given element exists in the container,
|
||||||
* $(D_KEYWORD false) otherwise.
|
* $(D_KEYWORD false) otherwise.
|
||||||
*/
|
*/
|
||||||
bool opBinaryRight(string op : "in")(auto ref T value)
|
bool opBinaryRight(string op : "in")(auto ref const T value) const
|
||||||
{
|
{
|
||||||
if (this.data.length == 0)
|
auto bucketPosition = locateBucket(calculateHash(value));
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto bucketPosition = locateBucket(this.data, calculateHash(value));
|
|
||||||
foreach (ref e; this.data[bucketPosition .. $])
|
foreach (ref e; this.data[bucketPosition .. $])
|
||||||
{
|
{
|
||||||
if (e == value) // Found.
|
if (e == value) // Found.
|
||||||
@ -522,37 +531,15 @@ struct Set(T)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Ditto.
|
|
||||||
bool opBinaryRight(string op : "in")(auto ref const T value) const
|
|
||||||
{
|
|
||||||
if (this.data.length == 0)
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto bucketPosition = locateBucket(this.data, calculateHash(value));
|
|
||||||
foreach (ref e; this.data[bucketPosition .. $])
|
|
||||||
{
|
|
||||||
if (e.status == BucketStatus.used && e.content == value) // Found.
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
else if (e.status == BucketStatus.empty)
|
|
||||||
{
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
///
|
///
|
||||||
unittest
|
@nogc unittest
|
||||||
{
|
{
|
||||||
Set!int set;
|
Set!int set;
|
||||||
|
|
||||||
assert(5 !in set);
|
assert(5 !in set);
|
||||||
set.insert(5);
|
set.insert(5);
|
||||||
assert(5 in set);
|
assert(5 in set);
|
||||||
|
assert(8 !in set);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -633,7 +620,7 @@ struct Set(T)
|
|||||||
}
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
unittest
|
@nogc unittest
|
||||||
{
|
{
|
||||||
Set!int set;
|
Set!int set;
|
||||||
assert(set[].empty);
|
assert(set[].empty);
|
||||||
@ -647,13 +634,34 @@ struct Set(T)
|
|||||||
assert(set[].empty);
|
assert(set[].empty);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private @nogc unittest
|
||||||
|
{
|
||||||
|
const Set!int set;
|
||||||
|
assert(set[].empty);
|
||||||
|
}
|
||||||
|
|
||||||
|
private @nogc unittest
|
||||||
|
{
|
||||||
|
Set!int set;
|
||||||
|
set.insert(8);
|
||||||
|
|
||||||
|
auto r1 = set[];
|
||||||
|
auto r2 = r1.save();
|
||||||
|
|
||||||
|
r1.popFront();
|
||||||
|
assert(r1.empty);
|
||||||
|
|
||||||
|
r2.popBack();
|
||||||
|
assert(r2.empty);
|
||||||
|
}
|
||||||
|
|
||||||
private alias DataType = Array!(Bucket!T);
|
private alias DataType = Array!(Bucket!T);
|
||||||
private DataType data;
|
private DataType data;
|
||||||
private size_t lengthIndex;
|
private size_t lengthIndex;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Basic insertion logic.
|
// Basic insertion logic.
|
||||||
private unittest
|
private @nogc unittest
|
||||||
{
|
{
|
||||||
Set!int set;
|
Set!int set;
|
||||||
|
|
||||||
|
@ -21,6 +21,8 @@
|
|||||||
* 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/string.d,
|
||||||
|
* tanya/container/string.d)
|
||||||
*/
|
*/
|
||||||
module tanya.container.string;
|
module tanya.container.string;
|
||||||
|
|
||||||
|
@ -9,10 +9,13 @@
|
|||||||
* 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/format/conv.d,
|
||||||
|
* tanya/format/conv.d)
|
||||||
*/
|
*/
|
||||||
module tanya.format.conv;
|
module tanya.format.conv;
|
||||||
|
|
||||||
import std.traits;
|
import std.traits;
|
||||||
|
import tanya.container.string;
|
||||||
import tanya.memory;
|
import tanya.memory;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -273,18 +276,23 @@ private @nogc unittest
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Converts a number to a boolean.
|
* Converts $(D_PARAM from) to a boolean.
|
||||||
|
*
|
||||||
|
* If $(D_PARAM From) is a numeric type, then `1` becomes $(D_KEYWORD true),
|
||||||
|
* `0` $(D_KEYWORD false). Otherwise $(D_PSYMBOL ConvException) is thrown.
|
||||||
|
*
|
||||||
|
* If $(D_PARAM To) is a string (built-in string or $(D_PSYMBOL String)),
|
||||||
|
* then `"true"` or `"false"` are converted to the appropriate boolean value.
|
||||||
|
* Otherwise $(D_PSYMBOL ConvException) is thrown.
|
||||||
*
|
*
|
||||||
* Params:
|
* Params:
|
||||||
* From = Source type.
|
* From = Source type.
|
||||||
* To = Target type.
|
* To = Target type.
|
||||||
* from = Source value.
|
* from = Source value.
|
||||||
*
|
*
|
||||||
* Returns: $(D_KEYWORD true) if $(D_INLINECODE from > 0 && from <= 1),
|
* Returns: $(D_KEYWORD from) converted to a boolean.
|
||||||
* otherwise $(D_KEYWORD false).
|
|
||||||
*
|
*
|
||||||
* Throws: $(D_PSYMBOL ConvException) if $(D_PARAM from) is greater than `1` or
|
* Throws: $(D_PSYMBOL ConvException) if $(D_PARAM from) isn't convertible.
|
||||||
* less than `0`.
|
|
||||||
*/
|
*/
|
||||||
To to(To, From)(From from)
|
To to(To, From)(From from)
|
||||||
if (isNumeric!From && is(Unqual!To == bool) && !is(Unqual!To == Unqual!From))
|
if (isNumeric!From && is(Unqual!To == bool) && !is(Unqual!To == Unqual!From))
|
||||||
@ -306,15 +314,16 @@ if (isNumeric!From && is(Unqual!To == bool) && !is(Unqual!To == Unqual!From))
|
|||||||
"Positive number overflow");
|
"Positive number overflow");
|
||||||
}
|
}
|
||||||
|
|
||||||
private @nogc unittest
|
///
|
||||||
|
@nogc unittest
|
||||||
{
|
{
|
||||||
assert(0.0.to!bool == false);
|
assert(!0.0.to!bool);
|
||||||
assert(0.2.to!bool == true);
|
assert(0.2.to!bool);
|
||||||
assert(0.5.to!bool == true);
|
assert(0.5.to!bool);
|
||||||
assert(1.0.to!bool == true);
|
assert(1.0.to!bool);
|
||||||
|
|
||||||
assert(0.to!bool == false);
|
assert(!0.to!bool);
|
||||||
assert(1.to!bool == true);
|
assert(1.to!bool);
|
||||||
}
|
}
|
||||||
|
|
||||||
private @nogc unittest
|
private @nogc unittest
|
||||||
@ -322,7 +331,7 @@ private @nogc unittest
|
|||||||
ConvException exception;
|
ConvException exception;
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
assert((-1).to!bool == true);
|
assert((-1).to!bool);
|
||||||
}
|
}
|
||||||
catch (ConvException e)
|
catch (ConvException e)
|
||||||
{
|
{
|
||||||
@ -337,7 +346,48 @@ private @nogc unittest
|
|||||||
ConvException exception;
|
ConvException exception;
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
assert(2.to!bool == true);
|
assert(2.to!bool);
|
||||||
|
}
|
||||||
|
catch (ConvException e)
|
||||||
|
{
|
||||||
|
exception = e;
|
||||||
|
}
|
||||||
|
assert(exception !is null);
|
||||||
|
defaultAllocator.dispose(exception);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Ditto.
|
||||||
|
To to(To, From)(auto ref const From from)
|
||||||
|
if ((is(From == String) || isSomeString!From) && is(Unqual!To == bool))
|
||||||
|
{
|
||||||
|
if (from == "true")
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else if (from == "false")
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
throw make!ConvException(defaultAllocator,
|
||||||
|
"String doesn't contain a boolean value");
|
||||||
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
@nogc unittest
|
||||||
|
{
|
||||||
|
assert("true".to!bool);
|
||||||
|
assert(!"false".to!bool);
|
||||||
|
assert(String("true").to!bool);
|
||||||
|
assert(!String("false").to!bool);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private @nogc unittest
|
||||||
|
{
|
||||||
|
ConvException exception;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
assert("1".to!bool);
|
||||||
}
|
}
|
||||||
catch (ConvException e)
|
catch (ConvException e)
|
||||||
{
|
{
|
||||||
@ -348,17 +398,22 @@ private @nogc unittest
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Converts a boolean to a number. $(D_KEYWORD true) is `1`, $(D_KEYWORD false)
|
* Converts a boolean to $(D_PARAM To).
|
||||||
* is `0`.
|
*
|
||||||
|
* If $(D_PARAM To) is a numeric type, then $(D_KEYWORD true) becomes `1`,
|
||||||
|
* $(D_KEYWORD false) `0`.
|
||||||
|
*
|
||||||
|
* If $(D_PARAM To) is a $(D_PSYMBOL String), then `"true"` or `"false"`
|
||||||
|
* is returned.
|
||||||
*
|
*
|
||||||
* Params:
|
* Params:
|
||||||
* From = Source type.
|
* From = Source type.
|
||||||
* To = Target type.
|
* To = Target type.
|
||||||
* from = Source value.
|
* from = Source value.
|
||||||
*
|
*
|
||||||
* Returns: `1` if $(D_PARAM from) is $(D_KEYWORD true), otherwise `0`.
|
* Returns: $(D_PARAM from) converted to $(D_PARAM To).
|
||||||
*/
|
*/
|
||||||
To to(To, From)(From from)
|
To to(To, From)(const From from)
|
||||||
if (is(Unqual!From == bool) && isNumeric!To && !is(Unqual!To == Unqual!From))
|
if (is(Unqual!From == bool) && isNumeric!To && !is(Unqual!To == Unqual!From))
|
||||||
{
|
{
|
||||||
return from;
|
return from;
|
||||||
@ -386,6 +441,26 @@ pure nothrow @safe @nogc unittest
|
|||||||
assert(false.to!int == 0);
|
assert(false.to!int == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Ditto.
|
||||||
|
To to(To, From)(const From from)
|
||||||
|
if (is(Unqual!From == bool) && is(Unqual!To == String))
|
||||||
|
{
|
||||||
|
return String(from ? "true" : "false");
|
||||||
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
@nogc unittest
|
||||||
|
{
|
||||||
|
assert(true.to!String == "true");
|
||||||
|
assert(false.to!String == "false");
|
||||||
|
}
|
||||||
|
|
||||||
|
private @nogc unittest
|
||||||
|
{
|
||||||
|
static assert(is(typeof((const String("true")).to!bool)));
|
||||||
|
static assert(is(typeof(false.to!(const String) == "false")));
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Converts a floating point number to an integral type.
|
* Converts a floating point number to an integral type.
|
||||||
*
|
*
|
||||||
@ -486,7 +561,6 @@ private @nogc unittest
|
|||||||
*
|
*
|
||||||
* Throws: $(D_PSYMBOL ConvException) if $(D_PARAM from) is not a member of
|
* Throws: $(D_PSYMBOL ConvException) if $(D_PARAM from) is not a member of
|
||||||
* $(D_PSYMBOL To).
|
* $(D_PSYMBOL To).
|
||||||
|
|
||||||
*/
|
*/
|
||||||
To to(To, From)(From from)
|
To to(To, From)(From from)
|
||||||
if (isIntegral!From && is(To == enum))
|
if (isIntegral!From && is(To == enum))
|
||||||
@ -535,3 +609,102 @@ private @nogc unittest
|
|||||||
assert(exception !is null);
|
assert(exception !is null);
|
||||||
defaultAllocator.dispose(exception);
|
defaultAllocator.dispose(exception);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
package char[] number2String(T)(const T number, char[] buffer)
|
||||||
|
{
|
||||||
|
// abs the integer.
|
||||||
|
ulong n64 = number < 0 ? -cast(long) number : number;
|
||||||
|
|
||||||
|
char[20] rightAligned;
|
||||||
|
char* start = rightAligned.ptr + rightAligned.sizeof;
|
||||||
|
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
// Do in 32-bit chunks (avoid lots of 64-bit divides even with constant
|
||||||
|
// denominators).
|
||||||
|
char* o = start - 8;
|
||||||
|
uint n;
|
||||||
|
if (n64 >= 100000000)
|
||||||
|
{
|
||||||
|
n = n64 % 100000000;
|
||||||
|
n64 /= 100000000;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
n = cast(uint) n64;
|
||||||
|
n64 = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (n)
|
||||||
|
{
|
||||||
|
*--start = cast(char) (n % 10) + '0';
|
||||||
|
n /= 10;
|
||||||
|
}
|
||||||
|
// Ignore the leading zero if it was the last part of the integer.
|
||||||
|
if (n64 == 0)
|
||||||
|
{
|
||||||
|
if ((start[0] == '0')
|
||||||
|
&& (start != (rightAligned.ptr + rightAligned.sizeof)))
|
||||||
|
{
|
||||||
|
++start;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
// Copy leading zeros if it wasn't the most significant part of the
|
||||||
|
// integer.
|
||||||
|
while (start != o)
|
||||||
|
{
|
||||||
|
*--start = '0';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get the length that we copied.
|
||||||
|
auto l = cast(uint) ((rightAligned.ptr + rightAligned.sizeof) - start);
|
||||||
|
if (l == 0)
|
||||||
|
{
|
||||||
|
*--start = '0';
|
||||||
|
l = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Write the string.
|
||||||
|
char* bp = buffer.ptr;
|
||||||
|
|
||||||
|
// Set sign.
|
||||||
|
if (number < 0)
|
||||||
|
{
|
||||||
|
*bp++ = '-';
|
||||||
|
}
|
||||||
|
|
||||||
|
// Copy the string into the target buffer.
|
||||||
|
uint n = l;
|
||||||
|
while (n)
|
||||||
|
{
|
||||||
|
int i = n;
|
||||||
|
n -= i;
|
||||||
|
|
||||||
|
while (i >= 4)
|
||||||
|
{
|
||||||
|
*cast(uint*) bp = *cast(uint*) start;
|
||||||
|
bp += 4;
|
||||||
|
start += 4;
|
||||||
|
i -= 4;
|
||||||
|
}
|
||||||
|
while (i)
|
||||||
|
{
|
||||||
|
*bp++ = *start++;
|
||||||
|
--i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return buffer[0 .. bp - buffer.ptr];
|
||||||
|
}
|
||||||
|
|
||||||
|
private @nogc unittest
|
||||||
|
{
|
||||||
|
char[21] buf;
|
||||||
|
|
||||||
|
assert(number2String(80, buf) == "80");
|
||||||
|
assert(number2String(-80, buf) == "-80");
|
||||||
|
assert(number2String(0, buf) == "0");
|
||||||
|
assert(number2String(uint.max, buf) == "4294967295");
|
||||||
|
assert(number2String(int.min, buf) == "-2147483648");
|
||||||
|
}
|
||||||
|
@ -9,6 +9,8 @@
|
|||||||
* 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/format/package.d,
|
||||||
|
* tanya/format/package.d)
|
||||||
*/
|
*/
|
||||||
module tanya.format;
|
module tanya.format;
|
||||||
|
|
||||||
|
@ -9,6 +9,8 @@
|
|||||||
* 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/math/mp.d,
|
||||||
|
* tanya/math/mp.d)
|
||||||
*/
|
*/
|
||||||
module tanya.math.mp;
|
module tanya.math.mp;
|
||||||
|
|
||||||
|
@ -9,6 +9,8 @@
|
|||||||
* 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/math/package.d,
|
||||||
|
* tanya/math/package.d)
|
||||||
*/
|
*/
|
||||||
module tanya.math;
|
module tanya.math;
|
||||||
|
|
||||||
|
@ -9,6 +9,8 @@
|
|||||||
* 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/math/random.d,
|
||||||
|
* tanya/math/random.d)
|
||||||
*/
|
*/
|
||||||
module tanya.math.random;
|
module tanya.math.random;
|
||||||
|
|
||||||
|
@ -12,6 +12,8 @@
|
|||||||
* 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/memory/allocator.d,
|
||||||
|
* tanya/memory/allocator.d)
|
||||||
*/
|
*/
|
||||||
module tanya.memory.allocator;
|
module tanya.memory.allocator;
|
||||||
|
|
||||||
|
441
source/tanya/memory/arch/x86_64.d
Normal file
441
source/tanya/memory/arch/x86_64.d
Normal file
@ -0,0 +1,441 @@
|
|||||||
|
/* 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/. */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Implementions of functions found in $(D_PSYMBOL tanya.memory.op) for x64.
|
||||||
|
*
|
||||||
|
* Copyright: Eugene Wissner 2017.
|
||||||
|
* License: $(LINK2 https://www.mozilla.org/en-US/MPL/2.0/,
|
||||||
|
* Mozilla Public License, v. 2.0).
|
||||||
|
* Authors: $(LINK2 mailto:info@caraus.de, Eugene Wissner)
|
||||||
|
* Source: $(LINK2 https://github.com/caraus-ecms/tanya/blob/master/source/tanya/memory/arch/x86_64.d,
|
||||||
|
* tanya/memory/arch/x86_64.d)
|
||||||
|
*/
|
||||||
|
module tanya.memory.arch.x86_64;
|
||||||
|
|
||||||
|
import tanya.memory.op;
|
||||||
|
|
||||||
|
version (D_InlineAsm_X86_64):
|
||||||
|
|
||||||
|
pragma(inline, true)
|
||||||
|
package (tanya.memory) void copy(const void[] source, void[] target)
|
||||||
|
pure nothrow @system @nogc
|
||||||
|
{
|
||||||
|
asm pure nothrow @nogc
|
||||||
|
{
|
||||||
|
naked;
|
||||||
|
|
||||||
|
// RDI and RSI should be preserved.
|
||||||
|
mov RAX, RDI;
|
||||||
|
mov R8, RSI;
|
||||||
|
}
|
||||||
|
// Set the registers for movsb/movsq.
|
||||||
|
version (Windows) asm pure nothrow @nogc
|
||||||
|
{
|
||||||
|
// RDX - source.
|
||||||
|
// RCX - target.
|
||||||
|
|
||||||
|
mov RDI, [ RCX + 8 ];
|
||||||
|
mov RSI, [ RDX + 8 ];
|
||||||
|
mov RDX, [ RDX ];
|
||||||
|
}
|
||||||
|
else asm pure nothrow @nogc
|
||||||
|
{
|
||||||
|
// RDX - source length.
|
||||||
|
// RCX - source data.
|
||||||
|
// RDI - target length
|
||||||
|
// RSI - target data.
|
||||||
|
|
||||||
|
mov RDI, RSI;
|
||||||
|
mov RSI, RCX;
|
||||||
|
}
|
||||||
|
asm pure nothrow @nogc
|
||||||
|
{
|
||||||
|
cmp RDX, 0x08;
|
||||||
|
jc aligned_1;
|
||||||
|
test EDI, 0x07;
|
||||||
|
jz aligned_8;
|
||||||
|
|
||||||
|
naligned:
|
||||||
|
movsb;
|
||||||
|
dec RDX;
|
||||||
|
test EDI, 0x07;
|
||||||
|
jnz naligned;
|
||||||
|
|
||||||
|
aligned_8:
|
||||||
|
mov RCX, RDX;
|
||||||
|
shr RCX, 0x03;
|
||||||
|
rep;
|
||||||
|
movsq;
|
||||||
|
and EDX, 0x07;
|
||||||
|
jz end;
|
||||||
|
|
||||||
|
aligned_1:
|
||||||
|
// Write the remaining bytes.
|
||||||
|
mov RCX, RDX;
|
||||||
|
rep;
|
||||||
|
movsb;
|
||||||
|
|
||||||
|
end: // Restore registers.
|
||||||
|
mov RSI, R8;
|
||||||
|
mov RDI, RAX;
|
||||||
|
|
||||||
|
ret;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
package (tanya.memory) template fill(ubyte Byte)
|
||||||
|
{
|
||||||
|
private enum const(char[]) MovArrayPointer(string Destination)()
|
||||||
|
{
|
||||||
|
string asmCode = "asm pure nothrow @nogc { mov ";
|
||||||
|
version (Windows)
|
||||||
|
{
|
||||||
|
asmCode ~= Destination ~ ", [ RCX + 8 ];";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
asmCode ~= Destination ~ ", RSI;";
|
||||||
|
}
|
||||||
|
return asmCode ~ "}";
|
||||||
|
}
|
||||||
|
|
||||||
|
pragma(inline, true)
|
||||||
|
void fill(void[] memory)
|
||||||
|
{
|
||||||
|
asm pure nothrow @nogc
|
||||||
|
{
|
||||||
|
naked;
|
||||||
|
}
|
||||||
|
version (Windows) asm pure nothrow @nogc
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* RCX - array.
|
||||||
|
*/
|
||||||
|
mov R8, [ RCX ];
|
||||||
|
}
|
||||||
|
else asm pure nothrow @nogc
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* RSI - pointer.
|
||||||
|
* RDI - length.
|
||||||
|
*/
|
||||||
|
mov R8, RDI;
|
||||||
|
}
|
||||||
|
mixin(MovArrayPointer!"R9");
|
||||||
|
|
||||||
|
asm pure nothrow @nogc
|
||||||
|
{
|
||||||
|
// Check for zero length.
|
||||||
|
test R8, R8;
|
||||||
|
jz end;
|
||||||
|
}
|
||||||
|
// Set 128- and 64-bit registers to values we want to fill with.
|
||||||
|
static if (Byte == 0)
|
||||||
|
{
|
||||||
|
asm pure nothrow @nogc
|
||||||
|
{
|
||||||
|
xor RAX, RAX;
|
||||||
|
pxor XMM0, XMM0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
enum ulong FilledBytes = FilledBytes!Byte;
|
||||||
|
asm pure nothrow @nogc
|
||||||
|
{
|
||||||
|
mov RAX, FilledBytes;
|
||||||
|
movq XMM0, RAX;
|
||||||
|
movlhps XMM0, XMM0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
asm pure nothrow @nogc
|
||||||
|
{
|
||||||
|
// Check if the pointer is aligned to a 16-byte boundary.
|
||||||
|
and R9, -0x10;
|
||||||
|
}
|
||||||
|
// Compute the number of misaligned bytes.
|
||||||
|
mixin(MovArrayPointer!"R10");
|
||||||
|
asm pure nothrow @nogc
|
||||||
|
{
|
||||||
|
sub R10, R9;
|
||||||
|
|
||||||
|
test R10, R10;
|
||||||
|
jz aligned;
|
||||||
|
|
||||||
|
// Get the number of bytes to be written until we are aligned.
|
||||||
|
mov RDX, 0x10;
|
||||||
|
sub RDX, R10;
|
||||||
|
}
|
||||||
|
mixin(MovArrayPointer!"R9");
|
||||||
|
asm pure nothrow @nogc
|
||||||
|
{
|
||||||
|
naligned:
|
||||||
|
mov [ R9 ], AL; // Write a byte.
|
||||||
|
|
||||||
|
// Advance the pointer. Decrease the total number of bytes
|
||||||
|
// and the misaligned ones.
|
||||||
|
inc R9;
|
||||||
|
dec RDX;
|
||||||
|
dec R8;
|
||||||
|
|
||||||
|
// Checks if we are aligned.
|
||||||
|
test RDX, RDX;
|
||||||
|
jnz naligned;
|
||||||
|
|
||||||
|
aligned:
|
||||||
|
// Checks if we're done writing bytes.
|
||||||
|
test R8, R8;
|
||||||
|
jz end;
|
||||||
|
|
||||||
|
// Write 1 byte at a time.
|
||||||
|
cmp R8, 8;
|
||||||
|
jl aligned_1;
|
||||||
|
|
||||||
|
// Write 8 bytes at a time.
|
||||||
|
cmp R8, 16;
|
||||||
|
jl aligned_8;
|
||||||
|
|
||||||
|
// Write 16 bytes at a time.
|
||||||
|
cmp R8, 32;
|
||||||
|
jl aligned_16;
|
||||||
|
|
||||||
|
// Write 32 bytes at a time.
|
||||||
|
cmp R8, 64;
|
||||||
|
jl aligned_32;
|
||||||
|
|
||||||
|
aligned_64:
|
||||||
|
movdqa [ R9 ], XMM0;
|
||||||
|
movdqa [ R9 + 16 ], XMM0;
|
||||||
|
movdqa [ R9 + 32 ], XMM0;
|
||||||
|
movdqa [ R9 + 48 ], XMM0;
|
||||||
|
|
||||||
|
add R9, 64;
|
||||||
|
sub R8, 64;
|
||||||
|
|
||||||
|
cmp R8, 64;
|
||||||
|
jge aligned_64;
|
||||||
|
|
||||||
|
// Checks if we're done writing bytes.
|
||||||
|
test R8, R8;
|
||||||
|
jz end;
|
||||||
|
|
||||||
|
// Write 1 byte at a time.
|
||||||
|
cmp R8, 8;
|
||||||
|
jl aligned_1;
|
||||||
|
|
||||||
|
// Write 8 bytes at a time.
|
||||||
|
cmp R8, 16;
|
||||||
|
jl aligned_8;
|
||||||
|
|
||||||
|
// Write 16 bytes at a time.
|
||||||
|
cmp R8, 32;
|
||||||
|
jl aligned_16;
|
||||||
|
|
||||||
|
aligned_32:
|
||||||
|
movdqa [ R9 ], XMM0;
|
||||||
|
movdqa [ R9 + 16 ], XMM0;
|
||||||
|
|
||||||
|
add R9, 32;
|
||||||
|
sub R8, 32;
|
||||||
|
|
||||||
|
// Checks if we're done writing bytes.
|
||||||
|
test R8, R8;
|
||||||
|
jz end;
|
||||||
|
|
||||||
|
// Write 1 byte at a time.
|
||||||
|
cmp R8, 8;
|
||||||
|
jl aligned_1;
|
||||||
|
|
||||||
|
// Write 8 bytes at a time.
|
||||||
|
cmp R8, 16;
|
||||||
|
jl aligned_8;
|
||||||
|
|
||||||
|
aligned_16:
|
||||||
|
movdqa [ R9 ], XMM0;
|
||||||
|
|
||||||
|
add R9, 16;
|
||||||
|
sub R8, 16;
|
||||||
|
|
||||||
|
// Checks if we're done writing bytes.
|
||||||
|
test R8, R8;
|
||||||
|
jz end;
|
||||||
|
|
||||||
|
// Write 1 byte at a time.
|
||||||
|
cmp R8, 8;
|
||||||
|
jl aligned_1;
|
||||||
|
|
||||||
|
aligned_8:
|
||||||
|
mov [ R9 ], RAX;
|
||||||
|
|
||||||
|
add R9, 8;
|
||||||
|
sub R8, 8;
|
||||||
|
|
||||||
|
// Checks if we're done writing bytes.
|
||||||
|
test R8, R8;
|
||||||
|
jz end;
|
||||||
|
|
||||||
|
aligned_1:
|
||||||
|
mov [ R9 ], AL;
|
||||||
|
|
||||||
|
inc R9;
|
||||||
|
dec R8;
|
||||||
|
|
||||||
|
test R8, R8;
|
||||||
|
jnz aligned_1;
|
||||||
|
|
||||||
|
end:
|
||||||
|
ret;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pragma(inline, true)
|
||||||
|
package (tanya.memory) void copyBackward(const void[] source, void[] target)
|
||||||
|
pure nothrow @system @nogc
|
||||||
|
{
|
||||||
|
asm pure nothrow @nogc
|
||||||
|
{
|
||||||
|
naked;
|
||||||
|
|
||||||
|
// Save the registers should be restored.
|
||||||
|
mov R8, RSI;
|
||||||
|
mov R9, RDI;
|
||||||
|
}
|
||||||
|
// Prepare the registers for movsb.
|
||||||
|
version (Windows) asm pure nothrow @nogc
|
||||||
|
{
|
||||||
|
// RDX - source.
|
||||||
|
// RCX - target.
|
||||||
|
|
||||||
|
mov RAX, [ RCX + 8 ];
|
||||||
|
mov R10, [ RDX + 8 ];
|
||||||
|
mov RCX, [ RDX ];
|
||||||
|
|
||||||
|
lea RDI, [ RAX + RCX - 1 ];
|
||||||
|
lea RSI, [ R10 + RCX - 1 ];
|
||||||
|
}
|
||||||
|
else asm pure nothrow @nogc
|
||||||
|
{
|
||||||
|
// RDX - source length.
|
||||||
|
// RCX - source data.
|
||||||
|
// RDI - target length
|
||||||
|
// RSI - target data.
|
||||||
|
|
||||||
|
lea RDI, [ RSI + RDX - 1 ];
|
||||||
|
lea RSI, [ RCX + RDX - 1 ];
|
||||||
|
mov RCX, RDX;
|
||||||
|
}
|
||||||
|
asm pure nothrow @nogc
|
||||||
|
{
|
||||||
|
std; // Set the direction flag.
|
||||||
|
|
||||||
|
rep;
|
||||||
|
movsb;
|
||||||
|
|
||||||
|
cld; // Clear the direction flag.
|
||||||
|
|
||||||
|
// Restore registers.
|
||||||
|
mov RDI, R9;
|
||||||
|
mov RSI, R8;
|
||||||
|
|
||||||
|
ret;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pragma(inline, true)
|
||||||
|
package (tanya.memory) int cmp(const void[] r1, const void[] r2)
|
||||||
|
pure nothrow @system @nogc
|
||||||
|
{
|
||||||
|
asm pure nothrow @nogc
|
||||||
|
{
|
||||||
|
naked;
|
||||||
|
|
||||||
|
// RDI and RSI should be preserved.
|
||||||
|
mov R9, RDI;
|
||||||
|
mov R8, RSI;
|
||||||
|
}
|
||||||
|
// Set the registers for cmpsb/cmpsq.
|
||||||
|
version (Windows) asm pure nothrow @nogc
|
||||||
|
{
|
||||||
|
// RDX - r1.
|
||||||
|
// RCX - r2.
|
||||||
|
|
||||||
|
mov RDI, [ RCX + 8 ];
|
||||||
|
mov RSI, [ RDX + 8 ];
|
||||||
|
mov RDX, [ RDX ];
|
||||||
|
mov RCX, [ RCX ];
|
||||||
|
}
|
||||||
|
else asm pure nothrow @nogc
|
||||||
|
{
|
||||||
|
// RDX - r1 length.
|
||||||
|
// RCX - r1 data.
|
||||||
|
// RDI - r2 length
|
||||||
|
// RSI - r2 data.
|
||||||
|
|
||||||
|
mov RSI, RCX;
|
||||||
|
mov RCX, RDI;
|
||||||
|
mov RDI, R8;
|
||||||
|
}
|
||||||
|
asm pure nothrow @nogc
|
||||||
|
{
|
||||||
|
// Compare the lengths.
|
||||||
|
cmp RDX, RCX;
|
||||||
|
jl less;
|
||||||
|
jg greater;
|
||||||
|
|
||||||
|
// Check if we're aligned.
|
||||||
|
cmp RDX, 0x08;
|
||||||
|
jc aligned_1;
|
||||||
|
test EDI, 0x07;
|
||||||
|
jz aligned_8;
|
||||||
|
|
||||||
|
naligned:
|
||||||
|
cmpsb;
|
||||||
|
jl less;
|
||||||
|
jg greater;
|
||||||
|
|
||||||
|
dec RDX;
|
||||||
|
test EDI, 0x07;
|
||||||
|
jnz naligned;
|
||||||
|
|
||||||
|
aligned_8:
|
||||||
|
mov RCX, RDX;
|
||||||
|
shr RCX, 0x03;
|
||||||
|
|
||||||
|
repe;
|
||||||
|
cmpsq;
|
||||||
|
jl less;
|
||||||
|
jg greater;
|
||||||
|
|
||||||
|
and EDX, 0x07;
|
||||||
|
jz equal;
|
||||||
|
|
||||||
|
aligned_1: // Compare the remaining bytes.
|
||||||
|
mov RCX, RDX;
|
||||||
|
|
||||||
|
repe;
|
||||||
|
cmpsb;
|
||||||
|
jl less;
|
||||||
|
jg greater;
|
||||||
|
|
||||||
|
equal:
|
||||||
|
xor RAX, RAX; // Return 0.
|
||||||
|
jmp end;
|
||||||
|
|
||||||
|
greater:
|
||||||
|
mov RAX, 1;
|
||||||
|
jmp end;
|
||||||
|
|
||||||
|
less:
|
||||||
|
mov RAX, -1;
|
||||||
|
jmp end;
|
||||||
|
|
||||||
|
end: // Restore registers.
|
||||||
|
mov RSI, R8;
|
||||||
|
mov RDI, R9;
|
||||||
|
|
||||||
|
ret;
|
||||||
|
}
|
||||||
|
}
|
@ -9,6 +9,8 @@
|
|||||||
* 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/memory/mallocator.d,
|
||||||
|
* tanya/memory/mallocator.d)
|
||||||
*/
|
*/
|
||||||
module tanya.memory.mallocator;
|
module tanya.memory.mallocator;
|
||||||
|
|
||||||
|
@ -9,6 +9,8 @@
|
|||||||
* 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/memory/mmappool.d,
|
||||||
|
* tanya/memory/mmappool.d)
|
||||||
*/
|
*/
|
||||||
module tanya.memory.mmappool;
|
module tanya.memory.mmappool;
|
||||||
|
|
||||||
|
404
source/tanya/memory/op.d
Normal file
404
source/tanya/memory/op.d
Normal file
@ -0,0 +1,404 @@
|
|||||||
|
/* 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/. */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set of operations on memory blocks.
|
||||||
|
*
|
||||||
|
* Copyright: Eugene Wissner 2017.
|
||||||
|
* License: $(LINK2 https://www.mozilla.org/en-US/MPL/2.0/,
|
||||||
|
* Mozilla Public License, v. 2.0).
|
||||||
|
* Authors: $(LINK2 mailto:info@caraus.de, Eugene Wissner)
|
||||||
|
* Source: $(LINK2 https://github.com/caraus-ecms/tanya/blob/master/source/tanya/memory/op.d,
|
||||||
|
* tanya/memory/op.d)
|
||||||
|
*/
|
||||||
|
module tanya.memory.op;
|
||||||
|
|
||||||
|
version (D_InlineAsm_X86_64)
|
||||||
|
{
|
||||||
|
static import tanya.memory.arch.x86_64;
|
||||||
|
}
|
||||||
|
|
||||||
|
private enum alignMask = size_t.sizeof - 1;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Copies $(D_PARAM source) into $(D_PARAM target).
|
||||||
|
*
|
||||||
|
* $(D_PARAM source) and $(D_PARAM target) shall not overlap so that
|
||||||
|
* $(D_PARAM source) points ahead of $(D_PARAM target).
|
||||||
|
*
|
||||||
|
* $(D_PARAM target) shall have enough space for $(D_INLINECODE source.length)
|
||||||
|
* elements.
|
||||||
|
*
|
||||||
|
* Params:
|
||||||
|
* source = Memory to copy from.
|
||||||
|
* target = Destination memory.
|
||||||
|
*
|
||||||
|
* See_Also: $(D_PSYMBOL copyBackward).
|
||||||
|
*
|
||||||
|
* Precondition: $(D_INLINECODE source.length <= target.length).
|
||||||
|
*/
|
||||||
|
void copy(const void[] source, void[] target) pure nothrow @trusted @nogc
|
||||||
|
in
|
||||||
|
{
|
||||||
|
assert(source.length <= target.length);
|
||||||
|
}
|
||||||
|
body
|
||||||
|
{
|
||||||
|
version (D_InlineAsm_X86_64)
|
||||||
|
{
|
||||||
|
tanya.memory.arch.x86_64.copy(source, target);
|
||||||
|
}
|
||||||
|
else // Naive implementation.
|
||||||
|
{
|
||||||
|
auto source1 = cast(const(ubyte)*) source;
|
||||||
|
auto target1 = cast(ubyte*) target;
|
||||||
|
auto count = source.length;
|
||||||
|
|
||||||
|
// Check if the pointers are aligned or at least can be aligned
|
||||||
|
// properly.
|
||||||
|
ushort naligned = (cast(size_t) source.ptr) & alignMask;
|
||||||
|
if (naligned == ((cast(size_t) target.ptr) & alignMask))
|
||||||
|
{
|
||||||
|
// Align the pointers if possible.
|
||||||
|
if (naligned != 0)
|
||||||
|
{
|
||||||
|
count -= naligned;
|
||||||
|
while (naligned--)
|
||||||
|
{
|
||||||
|
*target1++ = *source1++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Copy size_t.sizeof bytes at once.
|
||||||
|
auto longSource = cast(const(size_t)*) source1;
|
||||||
|
auto longTarget = cast(size_t*) target1;
|
||||||
|
for (; count >= size_t.sizeof; count -= size_t.sizeof)
|
||||||
|
{
|
||||||
|
*longTarget++ = *longSource++;
|
||||||
|
}
|
||||||
|
// Adjust the original pointers.
|
||||||
|
source1 = cast(const(ubyte)*) longSource;
|
||||||
|
target1 = cast(ubyte*) longTarget;
|
||||||
|
}
|
||||||
|
// Copy the remaining bytes by one.
|
||||||
|
while (count--)
|
||||||
|
{
|
||||||
|
*target1++ = *source1++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
pure nothrow @safe @nogc unittest
|
||||||
|
{
|
||||||
|
ubyte[9] source = [1, 2, 3, 4, 5, 6, 7, 8, 9];
|
||||||
|
ubyte[9] target;
|
||||||
|
source.copy(target);
|
||||||
|
assert(cmp(source, target) == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
private pure nothrow @safe @nogc unittest
|
||||||
|
{
|
||||||
|
{
|
||||||
|
ubyte[0] source, target;
|
||||||
|
source.copy(target);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
ubyte[1] source = [1];
|
||||||
|
ubyte[1] target;
|
||||||
|
source.copy(target);
|
||||||
|
assert(target[0] == 1);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
ubyte[8] source = [1, 2, 3, 4, 5, 6, 7, 8];
|
||||||
|
ubyte[8] target;
|
||||||
|
source.copy(target);
|
||||||
|
assert(cmp(source, target) == 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* size_t value each of which bytes is set to `Byte`.
|
||||||
|
*/
|
||||||
|
package template FilledBytes(ubyte Byte, ubyte I = 0)
|
||||||
|
{
|
||||||
|
static if (I == size_t.sizeof)
|
||||||
|
{
|
||||||
|
enum size_t FilledBytes = Byte;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
enum size_t FilledBytes = (FilledBytes!(Byte, I + 1) << 8) | Byte;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fills $(D_PARAM memory) with single $(D_PARAM Byte)s.
|
||||||
|
*
|
||||||
|
* Param:
|
||||||
|
* Byte = The value to fill $(D_PARAM memory) with.
|
||||||
|
* memory = Memory block.
|
||||||
|
*/
|
||||||
|
void fill(ubyte Byte = 0)(void[] memory) @trusted
|
||||||
|
{
|
||||||
|
version (D_InlineAsm_X86_64)
|
||||||
|
{
|
||||||
|
tanya.memory.arch.x86_64.fill!Byte(memory);
|
||||||
|
}
|
||||||
|
else // Naive implementation.
|
||||||
|
{
|
||||||
|
auto n = memory.length;
|
||||||
|
ubyte* vp = cast(ubyte*) memory.ptr;
|
||||||
|
|
||||||
|
// Align.
|
||||||
|
while (((cast(size_t) vp) & alignMask) != 0)
|
||||||
|
{
|
||||||
|
*vp++ = Byte;
|
||||||
|
--n;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set size_t.sizeof bytes at ones.
|
||||||
|
auto sp = cast(size_t*) vp;
|
||||||
|
while (n / size_t.sizeof > 0)
|
||||||
|
{
|
||||||
|
*sp++ = FilledBytes!Byte;
|
||||||
|
n -= size_t.sizeof;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Write the remaining bytes.
|
||||||
|
vp = cast(ubyte*) sp;
|
||||||
|
while (n--)
|
||||||
|
{
|
||||||
|
*vp = Byte;
|
||||||
|
++vp;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
pure nothrow @safe @nogc unittest
|
||||||
|
{
|
||||||
|
ubyte[9] memory = [1, 2, 3, 4, 5, 6, 7, 8, 9];
|
||||||
|
memory.fill!0();
|
||||||
|
foreach (ubyte v; memory)
|
||||||
|
{
|
||||||
|
assert(v == 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Stress test. Checks that `fill` can handle unaligned pointers and different
|
||||||
|
// lengths.
|
||||||
|
pure nothrow @safe @nogc private unittest
|
||||||
|
{
|
||||||
|
ubyte[192] memory;
|
||||||
|
|
||||||
|
foreach (j; 0 .. 192)
|
||||||
|
{
|
||||||
|
foreach (ubyte i, ref ubyte v; memory[j .. $])
|
||||||
|
{
|
||||||
|
v = i;
|
||||||
|
}
|
||||||
|
fill(memory[j .. $]);
|
||||||
|
foreach (ubyte v; memory[j .. $])
|
||||||
|
{
|
||||||
|
assert(v == 0);
|
||||||
|
}
|
||||||
|
fill!1(memory[j .. $]);
|
||||||
|
foreach (ubyte v; memory[j .. $])
|
||||||
|
{
|
||||||
|
assert(v == 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Copies starting from the end of $(D_PARAM source) into the end of
|
||||||
|
* $(D_PARAM target).
|
||||||
|
*
|
||||||
|
* $(D_PSYMBOL copyBackward) copies the elements in reverse order, but the
|
||||||
|
* order of elements in the $(D_PARAM target) is exactly the same as in the
|
||||||
|
* $(D_PARAM source).
|
||||||
|
*
|
||||||
|
* $(D_PARAM source) and $(D_PARAM target) shall not overlap so that
|
||||||
|
* $(D_PARAM target) points ahead of $(D_PARAM source).
|
||||||
|
*
|
||||||
|
* $(D_PARAM target) shall have enough space for $(D_INLINECODE source.length)
|
||||||
|
* elements.
|
||||||
|
*
|
||||||
|
* Params:
|
||||||
|
* source = Memory to copy from.
|
||||||
|
* target = Destination memory.
|
||||||
|
*
|
||||||
|
* See_Also: $(D_PSYMBOL copy).
|
||||||
|
*
|
||||||
|
* Precondition: $(D_INLINECODE source.length <= target.length).
|
||||||
|
*/
|
||||||
|
void copyBackward(const void[] source, void[] target) pure nothrow @trusted @nogc
|
||||||
|
in
|
||||||
|
{
|
||||||
|
assert(source.length <= target.length);
|
||||||
|
}
|
||||||
|
body
|
||||||
|
{
|
||||||
|
version (D_InlineAsm_X86_64)
|
||||||
|
{
|
||||||
|
tanya.memory.arch.x86_64.copyBackward(source, target);
|
||||||
|
}
|
||||||
|
else // Naive implementation.
|
||||||
|
{
|
||||||
|
auto count = source.length;
|
||||||
|
|
||||||
|
// Try to align the pointers if possible.
|
||||||
|
if (((cast(size_t) source.ptr) & alignMask) == ((cast(size_t) target.ptr) & alignMask))
|
||||||
|
{
|
||||||
|
while (((cast(size_t) (source.ptr + count)) & alignMask) != 0)
|
||||||
|
{
|
||||||
|
if (!count--)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
(cast(ubyte[]) target)[count]
|
||||||
|
= (cast(const(ubyte)[]) source)[count];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Write as long we're aligned.
|
||||||
|
for (; count >= size_t.sizeof; count -= size_t.sizeof)
|
||||||
|
{
|
||||||
|
*(cast(size_t*) (target.ptr + count - size_t.sizeof))
|
||||||
|
= *(cast(const(size_t)*) (source.ptr + count - size_t.sizeof));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Write the remaining bytes.
|
||||||
|
while (count--)
|
||||||
|
{
|
||||||
|
(cast(ubyte[]) target)[count]
|
||||||
|
= (cast(const(ubyte)[]) source)[count];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
pure nothrow @safe @nogc unittest
|
||||||
|
{
|
||||||
|
ubyte[6] mem = [ 'a', 'a', 'b', 'b', 'c', 'c' ];
|
||||||
|
ubyte[6] expected = [ 'a', 'a', 'a', 'a', 'b', 'b' ];
|
||||||
|
|
||||||
|
copyBackward(mem[0 .. 4], mem[2 .. $]);
|
||||||
|
assert(cmp(expected, mem) == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
private nothrow @safe @nogc unittest
|
||||||
|
{
|
||||||
|
ubyte[9] r1 = [ 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i' ];
|
||||||
|
ubyte[9] r2;
|
||||||
|
|
||||||
|
copyBackward(r1, r2);
|
||||||
|
assert(cmp(r1, r2) == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Compares two memory areas $(D_PARAM r1) and $(D_PARAM r2).
|
||||||
|
*
|
||||||
|
* $(D_PSYMBOL cmp) returns a positive integer if
|
||||||
|
* $(D_INLINECODE r1.length > r2.length) or the first `n` compared bytes of
|
||||||
|
* $(D_PARAM r1) found to be greater than the first `n` bytes of $(D_PARAM r2),
|
||||||
|
*
|
||||||
|
* $(D_PSYMBOL cmp) returns a negative integer if
|
||||||
|
* $(D_INLINECODE r2.length > r1.length) or the first `n` compared bytes of
|
||||||
|
* $(D_PARAM r1) found to be less than the first `n` bytes of $(D_PARAM r2),
|
||||||
|
*
|
||||||
|
* `0` is returned otherwise.
|
||||||
|
*
|
||||||
|
* Returns: Positive integer if $(D_INLINECODE r1 > r2),
|
||||||
|
* negative integer if $(D_INLINECODE r2 > r1),
|
||||||
|
* `0` if $(D_INLINECODE r1 == r2).
|
||||||
|
*/
|
||||||
|
int cmp(const void[] r1, const void[] r2) pure nothrow @trusted @nogc
|
||||||
|
{
|
||||||
|
version (D_InlineAsm_X86_64)
|
||||||
|
{
|
||||||
|
return tanya.memory.arch.x86_64.cmp(r1, r2);
|
||||||
|
}
|
||||||
|
else // Naive implementation.
|
||||||
|
{
|
||||||
|
if (r1.length > r2.length)
|
||||||
|
{
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
else if (r1.length < r2.length)
|
||||||
|
{
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
auto p1 = cast(const(ubyte)*) r1;
|
||||||
|
auto p2 = cast(const(ubyte)*) r2;
|
||||||
|
auto count = r1.length;
|
||||||
|
|
||||||
|
// Check if the pointers are aligned or at least can be aligned
|
||||||
|
// properly.
|
||||||
|
if (((cast(size_t) p1) & alignMask) == ((cast(size_t) p2) & alignMask))
|
||||||
|
{
|
||||||
|
// Align the pointers if possible.
|
||||||
|
for (; ((cast(size_t) p1) & alignMask) != 0; ++p1, ++p2, --count)
|
||||||
|
{
|
||||||
|
if (*p1 != *p2)
|
||||||
|
{
|
||||||
|
return *p1 - *p2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Compare size_t.sizeof bytes at once.
|
||||||
|
for (; count >= size_t.sizeof; count -= size_t.sizeof)
|
||||||
|
{
|
||||||
|
if (*(cast(const(size_t)*) p1) > *(cast(const(size_t)*) p2))
|
||||||
|
{
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
else if (*(cast(const(size_t)*) p1) < *(cast(const(size_t)*) p2))
|
||||||
|
{
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
p1 += size_t.sizeof;
|
||||||
|
p2 += size_t.sizeof;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Compare the remaining bytes by one.
|
||||||
|
for (; count--; ++p1, ++p2)
|
||||||
|
{
|
||||||
|
if (*p1 != *p2)
|
||||||
|
{
|
||||||
|
return *p1 - *p2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
pure nothrow @safe @nogc unittest
|
||||||
|
{
|
||||||
|
ubyte[4] r1 = [ 'a', 'b', 'c', 'd' ];
|
||||||
|
ubyte[3] r2 = [ 'c', 'a', 'b' ];
|
||||||
|
|
||||||
|
assert(cmp(r1[0 .. 3], r2[]) < 0);
|
||||||
|
assert(cmp(r2[], r1[0 .. 3]) > 0);
|
||||||
|
|
||||||
|
assert(cmp(r1, r2) > 0);
|
||||||
|
assert(cmp(r2, r1) < 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
private pure nothrow @safe @nogc unittest
|
||||||
|
{
|
||||||
|
ubyte[16] r1 = [
|
||||||
|
'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h',
|
||||||
|
'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p',
|
||||||
|
];
|
||||||
|
ubyte[16] r2 = [
|
||||||
|
'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h',
|
||||||
|
'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p',
|
||||||
|
];
|
||||||
|
|
||||||
|
assert(cmp(r1, r2) == 0);
|
||||||
|
assert(cmp(r1[1 .. $], r2[1 .. $]) == 0);
|
||||||
|
assert(cmp(r1[0 .. $ - 1], r2[0 .. $ - 1]) == 0);
|
||||||
|
assert(cmp(r1[0 .. 8], r2[0 .. 8]) == 0);
|
||||||
|
}
|
@ -9,6 +9,8 @@
|
|||||||
* 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/memory/package.d,
|
||||||
|
* tanya/memory/package.d)
|
||||||
*/
|
*/
|
||||||
module tanya.memory;
|
module tanya.memory;
|
||||||
|
|
||||||
@ -178,7 +180,7 @@ pure nothrow @safe @nogc
|
|||||||
return (size - 1) / alignment * alignment + alignment;
|
return (size - 1) / alignment * alignment + alignment;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/*
|
||||||
* Internal function used to create, resize or destroy a dynamic array. It
|
* Internal function used to create, resize or destroy a dynamic array. It
|
||||||
* may throw $(D_PSYMBOL OutOfMemoryError). The new
|
* may throw $(D_PSYMBOL OutOfMemoryError). The new
|
||||||
* allocated part of the array isn't initialized. This function can be trusted
|
* allocated part of the array isn't initialized. This function can be trusted
|
||||||
@ -381,10 +383,7 @@ in
|
|||||||
}
|
}
|
||||||
body
|
body
|
||||||
{
|
{
|
||||||
T ret;
|
auto mem = (() @trusted => allocator.allocate(stateSize!T))();
|
||||||
const size = stateSize!T;
|
|
||||||
|
|
||||||
auto mem = (() @trusted => allocator.allocate(size))();
|
|
||||||
if (mem is null)
|
if (mem is null)
|
||||||
{
|
{
|
||||||
onOutOfMemoryError();
|
onOutOfMemoryError();
|
||||||
@ -394,9 +393,7 @@ body
|
|||||||
() @trusted { allocator.deallocate(mem); }();
|
() @trusted { allocator.deallocate(mem); }();
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = emplace!T(mem[0 .. size], args);
|
return emplace!T(mem[0 .. stateSize!T], args);
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -425,10 +422,7 @@ in
|
|||||||
}
|
}
|
||||||
body
|
body
|
||||||
{
|
{
|
||||||
typeof(return) ret;
|
auto mem = (() @trusted => allocator.allocate(stateSize!T))();
|
||||||
const size = stateSize!T;
|
|
||||||
|
|
||||||
auto mem = (() @trusted => allocator.allocate(size))();
|
|
||||||
if (mem is null)
|
if (mem is null)
|
||||||
{
|
{
|
||||||
onOutOfMemoryError();
|
onOutOfMemoryError();
|
||||||
@ -438,10 +432,8 @@ body
|
|||||||
() @trusted { allocator.deallocate(mem); }();
|
() @trusted { allocator.deallocate(mem); }();
|
||||||
}
|
}
|
||||||
|
|
||||||
auto ptr = (() @trusted => (cast(T*) mem[0 .. size].ptr))();
|
auto ptr = (() @trusted => (cast(T*) mem[0 .. stateSize!T].ptr))();
|
||||||
ret = emplace!T(ptr, args);
|
return emplace!T(ptr, args);
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
@ -453,12 +445,12 @@ unittest
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructs a new array with $(D_PARAM size) elements.
|
* Constructs a new array with $(D_PARAM n) elements.
|
||||||
*
|
*
|
||||||
* Params:
|
* Params:
|
||||||
* T = Array type.
|
* T = Array type.
|
||||||
* allocator = Allocator.
|
* allocator = Allocator.
|
||||||
* size = Array size.
|
* n = Array size.
|
||||||
*
|
*
|
||||||
* Returns: Newly created array.
|
* Returns: Newly created array.
|
||||||
*
|
*
|
||||||
|
@ -12,6 +12,8 @@
|
|||||||
* 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/memory/smartref.d,
|
||||||
|
* tanya/memory/smartref.d)
|
||||||
*/
|
*/
|
||||||
module tanya.memory.smartref;
|
module tanya.memory.smartref;
|
||||||
|
|
||||||
|
453
source/tanya/meta/metafunction.d
Normal file
453
source/tanya/meta/metafunction.d
Normal file
@ -0,0 +1,453 @@
|
|||||||
|
/* 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/. */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This module contains functions that manipulate template type lists as well
|
||||||
|
* as algorithms to perform arbitrary compile-time computations.
|
||||||
|
*
|
||||||
|
* Copyright: Eugene Wissner 2017.
|
||||||
|
* License: $(LINK2 https://www.mozilla.org/en-US/MPL/2.0/,
|
||||||
|
* Mozilla Public License, v. 2.0).
|
||||||
|
* Authors: $(LINK2 mailto:info@caraus.de, Eugene Wissner)
|
||||||
|
* Source: $(LINK2 https://github.com/caraus-ecms/tanya/blob/master/source/tanya/meta/metafunction.d,
|
||||||
|
* tanya/meta/metafunction.d)
|
||||||
|
*/
|
||||||
|
module tanya.meta.metafunction;
|
||||||
|
|
||||||
|
version (unittest)
|
||||||
|
{
|
||||||
|
import tanya.meta.trait;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates an alias for $(D_PARAM T).
|
||||||
|
*
|
||||||
|
* In contrast to the $(D_KEYWORD alias)-keyword $(D_PSYMBOL Alias) can alias
|
||||||
|
* any kind of D symbol that can be used as argument to template alias
|
||||||
|
* parameters.
|
||||||
|
*
|
||||||
|
* $(UL
|
||||||
|
* $(LI Types)
|
||||||
|
* $(LI Local and global names)
|
||||||
|
* $(LI Module names)
|
||||||
|
* $(LI Template names)
|
||||||
|
* $(LI Template instance names)
|
||||||
|
* $(LI Literals)
|
||||||
|
* )
|
||||||
|
*
|
||||||
|
* Params:
|
||||||
|
* T = A symbol.
|
||||||
|
*
|
||||||
|
* Returns: An alias for $(D_PARAM T).
|
||||||
|
*
|
||||||
|
* See_Also: $(LINK2 https://dlang.org/spec/template.html#aliasparameters,
|
||||||
|
* Template Alias Parameters).
|
||||||
|
*/
|
||||||
|
alias Alias(alias T) = T;
|
||||||
|
|
||||||
|
/// Ditto.
|
||||||
|
alias Alias(T) = T;
|
||||||
|
|
||||||
|
///
|
||||||
|
pure nothrow @safe @nogc unittest
|
||||||
|
{
|
||||||
|
static assert(is(Alias!int));
|
||||||
|
|
||||||
|
static assert(is(typeof(Alias!5)));
|
||||||
|
static assert(is(typeof(Alias!(() {}))));
|
||||||
|
|
||||||
|
int i;
|
||||||
|
static assert(is(typeof(Alias!i)));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Params:
|
||||||
|
* Args = List of symbols.
|
||||||
|
*
|
||||||
|
* Returns: An alias for sequence $(D_PARAM Args).
|
||||||
|
*
|
||||||
|
* See_Also: $(D_PSYMBOL Alias).
|
||||||
|
*/
|
||||||
|
alias AliasSeq(Args...) = Args;
|
||||||
|
|
||||||
|
///
|
||||||
|
pure nothrow @safe @nogc unittest
|
||||||
|
{
|
||||||
|
static assert(is(typeof({ alias T = AliasSeq!(short, 5); })));
|
||||||
|
static assert(is(typeof({ alias T = AliasSeq!(int, short, 5); })));
|
||||||
|
static assert(is(typeof({ alias T = AliasSeq!(() {}, short, 5); })));
|
||||||
|
static assert(is(typeof({ alias T = AliasSeq!(); })));
|
||||||
|
|
||||||
|
static assert(AliasSeq!().length == 0);
|
||||||
|
static assert(AliasSeq!(int, short, 5).length == 3);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests whether all the items of $(D_PARAM L) satisfy the condition
|
||||||
|
* $(D_PARAM F).
|
||||||
|
*
|
||||||
|
* $(D_PARAM F) is a template that accepts one parameter and returns a boolean,
|
||||||
|
* so $(D_INLINECODE F!([0]) && F!([1])) and so on, can be called.
|
||||||
|
*
|
||||||
|
* Params:
|
||||||
|
* F = Template predicate.
|
||||||
|
* L = List of items to test.
|
||||||
|
*
|
||||||
|
* Returns: $(D_KEYWORD true) if all the items of $(D_PARAM L) satisfy
|
||||||
|
* $(D_PARAM F), $(D_KEYWORD false) otherwise.
|
||||||
|
*/
|
||||||
|
template allSatisfy(alias F, L...)
|
||||||
|
{
|
||||||
|
static if (L.length == 0)
|
||||||
|
{
|
||||||
|
enum bool allSatisfy = true;
|
||||||
|
}
|
||||||
|
else static if (F!(L[0]))
|
||||||
|
{
|
||||||
|
enum bool allSatisfy = allSatisfy!(F, L[1 .. $]);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
enum bool allSatisfy = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
pure nothrow @safe @nogc unittest
|
||||||
|
{
|
||||||
|
static assert(allSatisfy!(isSigned, int, short, byte, long));
|
||||||
|
static assert(!allSatisfy!(isUnsigned, uint, ushort, float, ulong));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests whether any of the items of $(D_PARAM L) satisfy the condition
|
||||||
|
* $(D_PARAM F).
|
||||||
|
*
|
||||||
|
* $(D_PARAM F) is a template that accepts one parameter and returns a boolean,
|
||||||
|
* so $(D_INLINECODE F!([0]) && F!([1])) and so on, can be called.
|
||||||
|
*
|
||||||
|
* Params:
|
||||||
|
* F = Template predicate.
|
||||||
|
* L = List of items to test.
|
||||||
|
*
|
||||||
|
* Returns: $(D_KEYWORD true) if any of the items of $(D_PARAM L) satisfy
|
||||||
|
* $(D_PARAM F), $(D_KEYWORD false) otherwise.
|
||||||
|
*/
|
||||||
|
template anySatisfy(alias F, L...)
|
||||||
|
{
|
||||||
|
static if (L.length == 0)
|
||||||
|
{
|
||||||
|
enum bool anySatisfy = false;
|
||||||
|
}
|
||||||
|
else static if (F!(L[0]))
|
||||||
|
{
|
||||||
|
enum bool anySatisfy = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
enum bool anySatisfy = anySatisfy!(F, L[1 .. $]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
pure nothrow @safe @nogc unittest
|
||||||
|
{
|
||||||
|
static assert(anySatisfy!(isSigned, int, short, byte, long));
|
||||||
|
static assert(anySatisfy!(isUnsigned, uint, ushort, float, ulong));
|
||||||
|
static assert(!anySatisfy!(isSigned, uint, ushort, ulong));
|
||||||
|
}
|
||||||
|
|
||||||
|
private template indexOf(ptrdiff_t i, Args...)
|
||||||
|
if (Args.length > 0)
|
||||||
|
{
|
||||||
|
static if (Args.length == 1)
|
||||||
|
{
|
||||||
|
enum ptrdiff_t indexOf = -1;
|
||||||
|
}
|
||||||
|
else static if (is(Args[0] == Args[1])
|
||||||
|
|| (is(typeof(Args[0] == Args[1])) && (Args[0] == Args[1])))
|
||||||
|
{
|
||||||
|
enum ptrdiff_t indexOf = i;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
enum ptrdiff_t indexOf = indexOf!(i + 1,
|
||||||
|
AliasSeq!(Args[0], Args[2 .. $]));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the index of the first occurrence of $(D_PARAM T) in $(D_PARAM L).
|
||||||
|
* `-1` is returned if $(D_PARAM T) is not found.
|
||||||
|
*
|
||||||
|
* Params:
|
||||||
|
* T = The type to search for.
|
||||||
|
* L = Type list.
|
||||||
|
*
|
||||||
|
* Returns: The index of the first occurence of $(D_PARAM T) in $(D_PARAM L).
|
||||||
|
*/
|
||||||
|
template staticIndexOf(T, L...)
|
||||||
|
{
|
||||||
|
enum ptrdiff_t staticIndexOf = indexOf!(0, AliasSeq!(T, L));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Ditto.
|
||||||
|
template staticIndexOf(alias T, L...)
|
||||||
|
{
|
||||||
|
enum ptrdiff_t staticIndexOf = indexOf!(0, AliasSeq!(T, L));
|
||||||
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
pure nothrow @safe @nogc unittest
|
||||||
|
{
|
||||||
|
static assert(staticIndexOf!(int) == -1);
|
||||||
|
static assert(staticIndexOf!(int, int) == 0);
|
||||||
|
static assert(staticIndexOf!(int, float, double, int, real) == 2);
|
||||||
|
static assert(staticIndexOf!(3, () {}, uint, 5, 3) == 3);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Instantiates the template $(D_PARAM T) with $(D_PARAM ARGS).
|
||||||
|
*
|
||||||
|
* Params:
|
||||||
|
* T = Template.
|
||||||
|
* Args = Template parameters.
|
||||||
|
*
|
||||||
|
* Returns: Instantiated template.
|
||||||
|
*/
|
||||||
|
alias Instantiate(alias T, Args...) = T!Args;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Combines multiple templates with logical AND. So $(D_PSYMBOL templateAnd)
|
||||||
|
* evaluates to $(D_INLINECODE Preds[0] && Preds[1] && Preds[2]) and so on.
|
||||||
|
*
|
||||||
|
* Empty $(D_PARAM Preds) evaluates to $(D_KEYWORD true).
|
||||||
|
*
|
||||||
|
* Params:
|
||||||
|
* Preds = Template predicates.
|
||||||
|
*
|
||||||
|
* Returns: The constructed template.
|
||||||
|
*/
|
||||||
|
template templateAnd(Preds...)
|
||||||
|
{
|
||||||
|
template templateAnd(T...)
|
||||||
|
{
|
||||||
|
static if (Preds.length == 0)
|
||||||
|
{
|
||||||
|
enum bool templateAnd = true;
|
||||||
|
}
|
||||||
|
else static if (Instantiate!(Preds[0], T))
|
||||||
|
{
|
||||||
|
alias templateAnd = Instantiate!(.templateAnd!(Preds[1 .. $]), T);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
enum bool templateAnd = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
pure nothrow @safe @nogc unittest
|
||||||
|
{
|
||||||
|
alias isMutableInt = templateAnd!(isIntegral, isMutable);
|
||||||
|
static assert(isMutableInt!int);
|
||||||
|
static assert(!isMutableInt!(const int));
|
||||||
|
static assert(!isMutableInt!float);
|
||||||
|
|
||||||
|
alias alwaysTrue = templateAnd!();
|
||||||
|
static assert(alwaysTrue!int);
|
||||||
|
|
||||||
|
alias isIntegral = templateAnd!(.isIntegral);
|
||||||
|
static assert(isIntegral!int);
|
||||||
|
static assert(isIntegral!(const int));
|
||||||
|
static assert(!isIntegral!float);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Combines multiple templates with logical OR. So $(D_PSYMBOL templateOr)
|
||||||
|
* evaluates to $(D_INLINECODE Preds[0] || Preds[1] || Preds[2]) and so on.
|
||||||
|
*
|
||||||
|
* Empty $(D_PARAM Preds) evaluates to $(D_KEYWORD false).
|
||||||
|
*
|
||||||
|
* Params:
|
||||||
|
* Preds = Template predicates.
|
||||||
|
*
|
||||||
|
* Returns: The constructed template.
|
||||||
|
*/
|
||||||
|
template templateOr(Preds...)
|
||||||
|
{
|
||||||
|
template templateOr(T...)
|
||||||
|
{
|
||||||
|
static if (Preds.length == 0)
|
||||||
|
{
|
||||||
|
enum bool templateOr = false;
|
||||||
|
}
|
||||||
|
else static if (Instantiate!(Preds[0], T))
|
||||||
|
{
|
||||||
|
enum bool templateOr = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
alias templateOr = Instantiate!(.templateOr!(Preds[1 .. $]), T);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
pure nothrow @safe @nogc unittest
|
||||||
|
{
|
||||||
|
alias isMutableOrInt = templateOr!(isIntegral, isMutable);
|
||||||
|
static assert(isMutableOrInt!int);
|
||||||
|
static assert(isMutableOrInt!(const int));
|
||||||
|
static assert(isMutableOrInt!float);
|
||||||
|
static assert(!isMutableOrInt!(const float));
|
||||||
|
|
||||||
|
alias alwaysFalse = templateOr!();
|
||||||
|
static assert(!alwaysFalse!int);
|
||||||
|
|
||||||
|
alias isIntegral = templateOr!(.isIntegral);
|
||||||
|
static assert(isIntegral!int);
|
||||||
|
static assert(isIntegral!(const int));
|
||||||
|
static assert(!isIntegral!float);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Params:
|
||||||
|
* pred = Template predicate.
|
||||||
|
*
|
||||||
|
* Returns: Negated $(D_PARAM pred).
|
||||||
|
*/
|
||||||
|
template templateNot(alias pred)
|
||||||
|
{
|
||||||
|
enum bool templateNot(T...) = !pred!T;
|
||||||
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
pure nothrow @safe @nogc unittest
|
||||||
|
{
|
||||||
|
alias isNotIntegral = templateNot!isIntegral;
|
||||||
|
static assert(!isNotIntegral!int);
|
||||||
|
static assert(isNotIntegral!(char[]));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests whether $(D_PARAM L) is sorted in ascending order according to
|
||||||
|
* $(D_PARAM cmp).
|
||||||
|
*
|
||||||
|
* $(D_PARAM cmp) can evaluate to:
|
||||||
|
* $(UL
|
||||||
|
* $(LI $(D_KEYWORD bool): $(D_KEYWORD true) means
|
||||||
|
* $(D_INLINECODE a[i] < a[i + 1]).)
|
||||||
|
* $(LI $(D_KEYWORD int): a negative number means that
|
||||||
|
* $(D_INLINECODE a[i] < a[i + 1]), a positive number that
|
||||||
|
* $(D_INLINECODE a[i] > a[i + 1]), `0` if they equal.)
|
||||||
|
* )
|
||||||
|
*
|
||||||
|
* Params:
|
||||||
|
* cmp = Comparison template.
|
||||||
|
* L = Arguments.
|
||||||
|
*
|
||||||
|
* Returns: $(D_KEYWORD true) if $(D_PARAM L) is sorted, $(D_KEYWORD false)
|
||||||
|
* if not.
|
||||||
|
*/
|
||||||
|
template staticIsSorted(alias cmp, L...)
|
||||||
|
{
|
||||||
|
static if (L.length <= 1)
|
||||||
|
{
|
||||||
|
enum bool staticIsSorted = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// `L` is sorted if the both halves are sorted.
|
||||||
|
enum bool halves = staticIsSorted!(cmp, L[0 .. $ / 2])
|
||||||
|
&& staticIsSorted!(cmp, L[$ / 2 .. $]);
|
||||||
|
// Compare the boundary values of the havles.
|
||||||
|
enum result = cmp!(L[$ / 2], L[$ / 2 - 1]);
|
||||||
|
static if (is(typeof(result) == bool))
|
||||||
|
{
|
||||||
|
enum bool staticIsSorted = !result && halves;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
enum bool staticIsSorted = result >= 0 && halves;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
pure nothrow @safe @nogc unittest
|
||||||
|
{
|
||||||
|
enum cmp(T, U) = T.sizeof < U.sizeof;
|
||||||
|
static assert(staticIsSorted!(cmp));
|
||||||
|
static assert(staticIsSorted!(cmp, byte));
|
||||||
|
static assert(staticIsSorted!(cmp, byte, ubyte, short, uint));
|
||||||
|
static assert(!staticIsSorted!(cmp, long, byte, ubyte, short, uint));
|
||||||
|
}
|
||||||
|
|
||||||
|
private pure nothrow @safe @nogc unittest
|
||||||
|
{
|
||||||
|
enum cmp(int x, int y) = x - y;
|
||||||
|
static assert(staticIsSorted!(cmp));
|
||||||
|
static assert(staticIsSorted!(cmp, 1));
|
||||||
|
static assert(staticIsSorted!(cmp, 1, 2, 2));
|
||||||
|
static assert(staticIsSorted!(cmp, 1, 2, 2, 4));
|
||||||
|
static assert(staticIsSorted!(cmp, 1, 2, 2, 4, 8));
|
||||||
|
static assert(!staticIsSorted!(cmp, 32, 2, 2, 4, 8));
|
||||||
|
static assert(staticIsSorted!(cmp, 32, 32));
|
||||||
|
}
|
||||||
|
|
||||||
|
private pure nothrow @safe @nogc unittest
|
||||||
|
{
|
||||||
|
enum cmp(int x, int y) = x < y;
|
||||||
|
static assert(staticIsSorted!(cmp));
|
||||||
|
static assert(staticIsSorted!(cmp, 1));
|
||||||
|
static assert(staticIsSorted!(cmp, 1, 2, 2));
|
||||||
|
static assert(staticIsSorted!(cmp, 1, 2, 2, 4));
|
||||||
|
static assert(staticIsSorted!(cmp, 1, 2, 2, 4, 8));
|
||||||
|
static assert(!staticIsSorted!(cmp, 32, 2, 2, 4, 8));
|
||||||
|
static assert(staticIsSorted!(cmp, 32, 32));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Params:
|
||||||
|
* T = A template.
|
||||||
|
* Args = The first arguments for $(D_PARAM T).
|
||||||
|
*
|
||||||
|
* Returns: $(D_PARAM T) with $(D_PARAM Args) applied to it as its first
|
||||||
|
* arguments.
|
||||||
|
*/
|
||||||
|
template ApplyLeft(alias T, Args...)
|
||||||
|
{
|
||||||
|
alias ApplyLeft(U...) = T!(Args, U);
|
||||||
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
pure nothrow @safe @nogc unittest
|
||||||
|
{
|
||||||
|
alias allAreIntegral = ApplyLeft!(allSatisfy, isIntegral);
|
||||||
|
static assert(allAreIntegral!(int, uint));
|
||||||
|
static assert(!allAreIntegral!(int, float, uint));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Params:
|
||||||
|
* T = A template.
|
||||||
|
* Args = The last arguments for $(D_PARAM T).
|
||||||
|
*
|
||||||
|
* Returns: $(D_PARAM T) with $(D_PARAM Args) applied to it as itslast
|
||||||
|
* arguments.
|
||||||
|
*/
|
||||||
|
template ApplyRight(alias T, Args...)
|
||||||
|
{
|
||||||
|
alias ApplyRight(U...) = T!(U, Args);
|
||||||
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
pure nothrow @safe @nogc unittest
|
||||||
|
{
|
||||||
|
alias intIs = ApplyRight!(allSatisfy, int);
|
||||||
|
static assert(intIs!(isIntegral));
|
||||||
|
static assert(!intIs!(isUnsigned));
|
||||||
|
}
|
19
source/tanya/meta/package.d
Normal file
19
source/tanya/meta/package.d
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
/* 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/. */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Template metaprogramming.
|
||||||
|
*
|
||||||
|
* Copyright: Eugene Wissner 2017.
|
||||||
|
* License: $(LINK2 https://www.mozilla.org/en-US/MPL/2.0/,
|
||||||
|
* Mozilla Public License, v. 2.0).
|
||||||
|
* Authors: $(LINK2 mailto:info@caraus.de, Eugene Wissner)
|
||||||
|
* Source: $(LINK2 https://github.com/caraus-ecms/tanya/blob/master/source/tanya/meta/package.d,
|
||||||
|
* tanya/meta/package.d)
|
||||||
|
*/
|
||||||
|
module tanya.meta;
|
||||||
|
|
||||||
|
public import tanya.meta.metafunction;
|
||||||
|
public import tanya.meta.trait;
|
||||||
|
public import tanya.meta.transform;
|
1707
source/tanya/meta/trait.d
Normal file
1707
source/tanya/meta/trait.d
Normal file
File diff suppressed because it is too large
Load Diff
475
source/tanya/meta/transform.d
Normal file
475
source/tanya/meta/transform.d
Normal file
@ -0,0 +1,475 @@
|
|||||||
|
/* 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/. */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Type transformations.
|
||||||
|
*
|
||||||
|
* Templates in this module can be used to modify type qualifiers or transform
|
||||||
|
* types.
|
||||||
|
*
|
||||||
|
* Copyright: Eugene Wissner 2017.
|
||||||
|
* License: $(LINK2 https://www.mozilla.org/en-US/MPL/2.0/,
|
||||||
|
* Mozilla Public License, v. 2.0).
|
||||||
|
* Authors: $(LINK2 mailto:info@caraus.de, Eugene Wissner)
|
||||||
|
* Source: $(LINK2 https://github.com/caraus-ecms/tanya/blob/master/source/tanya/meta/transform.d,
|
||||||
|
* tanya/meta/transform.d)
|
||||||
|
*/
|
||||||
|
module tanya.meta.transform;
|
||||||
|
|
||||||
|
import tanya.meta.trait;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Removes any type qualifiers from $(D_PARAM T).
|
||||||
|
*
|
||||||
|
* Removed qualifiers are:
|
||||||
|
* $(UL
|
||||||
|
* $(LI const)
|
||||||
|
* $(LI immutable)
|
||||||
|
* $(LI inout)
|
||||||
|
* $(LI shared)
|
||||||
|
* )
|
||||||
|
* and combinations of these.
|
||||||
|
*
|
||||||
|
* If the type $(D_PARAM T) doesn't have any qualifieres,
|
||||||
|
* $(D_INLINECODE Unqual!T) becomes an alias for $(D_PARAM T).
|
||||||
|
*
|
||||||
|
* Params:
|
||||||
|
* T = A type.
|
||||||
|
*
|
||||||
|
* Returns: $(D_PARAM T) without any type qualifiers.
|
||||||
|
*/
|
||||||
|
template Unqual(T)
|
||||||
|
{
|
||||||
|
static if (is(T U == const U)
|
||||||
|
|| is(T U == immutable U)
|
||||||
|
|| is(T U == inout U)
|
||||||
|
|| is(T U == inout const U)
|
||||||
|
|| is(T U == shared U)
|
||||||
|
|| is(T U == shared const U)
|
||||||
|
|| is(T U == shared inout U)
|
||||||
|
|| is(T U == shared inout const U))
|
||||||
|
{
|
||||||
|
alias Unqual = U;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
alias Unqual = T;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
pure nothrow @safe @nogc unittest
|
||||||
|
{
|
||||||
|
static assert(is(Unqual!bool == bool));
|
||||||
|
static assert(is(Unqual!(immutable bool) == bool));
|
||||||
|
static assert(is(Unqual!(inout bool) == bool));
|
||||||
|
static assert(is(Unqual!(inout const bool) == bool));
|
||||||
|
static assert(is(Unqual!(shared bool) == bool));
|
||||||
|
static assert(is(Unqual!(shared const bool) == bool));
|
||||||
|
static assert(is(Unqual!(shared inout const bool) == bool));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If $(D_PARAM T) is an $(D_KEYWORD enum), $(D_INLINECODE OriginalType!T)
|
||||||
|
* evaluates to the most base type of that $(D_KEYWORD enum) and to
|
||||||
|
* $(D_PARAM T) otherwise.
|
||||||
|
*
|
||||||
|
* Params:
|
||||||
|
* T = A type.
|
||||||
|
*
|
||||||
|
* Returns: Base type of the $(D_KEYWORD enum) $(D_PARAM T) or $(D_PARAM T)
|
||||||
|
* itself.
|
||||||
|
*/
|
||||||
|
template OriginalType(T)
|
||||||
|
{
|
||||||
|
static if (is(T U == enum))
|
||||||
|
{
|
||||||
|
alias OriginalType = OriginalType!U;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
alias OriginalType = T;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
pure nothrow @safe @nogc unittest
|
||||||
|
{
|
||||||
|
enum E1 : const(int)
|
||||||
|
{
|
||||||
|
n = 0,
|
||||||
|
}
|
||||||
|
enum E2 : bool
|
||||||
|
{
|
||||||
|
t = true,
|
||||||
|
}
|
||||||
|
enum E3 : E2
|
||||||
|
{
|
||||||
|
t = E2.t,
|
||||||
|
}
|
||||||
|
enum E4 : const(E2)
|
||||||
|
{
|
||||||
|
t = E2.t,
|
||||||
|
}
|
||||||
|
|
||||||
|
static assert(is(OriginalType!E1 == const int));
|
||||||
|
static assert(is(OriginalType!E2 == bool));
|
||||||
|
static assert(is(OriginalType!E3 == bool));
|
||||||
|
static assert(is(OriginalType!E4 == bool));
|
||||||
|
static assert(is(OriginalType!(const E4) == bool));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Copies constness of $(D_PARAM From) to $(D_PARAM To).
|
||||||
|
*
|
||||||
|
* The following type qualifiers affect the constness and hence are copied:
|
||||||
|
* $(UL
|
||||||
|
* $(LI const)
|
||||||
|
* $(LI immutable)
|
||||||
|
* $(LI inout)
|
||||||
|
* $(LI inout const)
|
||||||
|
* )
|
||||||
|
*
|
||||||
|
* Params:
|
||||||
|
* From = Source type.
|
||||||
|
* To = Target type.
|
||||||
|
*
|
||||||
|
* Returns: $(D_PARAM To) with the constness of $(D_PARAM From).
|
||||||
|
*
|
||||||
|
* See_Also: $(D_PSYMBOL CopyTypeQualifiers).
|
||||||
|
*/
|
||||||
|
template CopyConstness(From, To)
|
||||||
|
{
|
||||||
|
static if (is(From T == immutable T))
|
||||||
|
{
|
||||||
|
alias CopyConstness = immutable To;
|
||||||
|
}
|
||||||
|
else static if (is(From T == const T) || is(From T == shared const T))
|
||||||
|
{
|
||||||
|
alias CopyConstness = const To;
|
||||||
|
}
|
||||||
|
else static if (is(From T == inout T) || is(From T == shared inout T))
|
||||||
|
{
|
||||||
|
alias CopyConstness = inout To;
|
||||||
|
}
|
||||||
|
else static if (is(From T == inout const T)
|
||||||
|
|| is(From T == shared inout const T))
|
||||||
|
{
|
||||||
|
alias CopyConstness = inout const To;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
alias CopyConstness = To;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
pure nothrow @safe @nogc unittest
|
||||||
|
{
|
||||||
|
static assert(is(CopyConstness!(int, char) == char));
|
||||||
|
static assert(is(CopyConstness!(const int, char) == const char));
|
||||||
|
static assert(is(CopyConstness!(immutable int, char) == immutable char));
|
||||||
|
static assert(is(CopyConstness!(inout int, char) == inout char));
|
||||||
|
static assert(is(CopyConstness!(inout const int, char) == inout const char));
|
||||||
|
|
||||||
|
static assert(is(CopyConstness!(shared int, char) == char));
|
||||||
|
static assert(is(CopyConstness!(shared const int, char) == const char));
|
||||||
|
static assert(is(CopyConstness!(shared inout int, char) == inout char));
|
||||||
|
static assert(is(CopyConstness!(shared inout const int, char) == inout const char));
|
||||||
|
|
||||||
|
static assert(is(CopyConstness!(const int, shared char) == shared const char));
|
||||||
|
static assert(is(CopyConstness!(const int, immutable char) == immutable char));
|
||||||
|
static assert(is(CopyConstness!(immutable int, const char) == immutable char));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Copies type qualifiers of $(D_PARAM From) to $(D_PARAM To).
|
||||||
|
*
|
||||||
|
* Type qualifiers copied are:
|
||||||
|
* $(UL
|
||||||
|
* $(LI const)
|
||||||
|
* $(LI immutable)
|
||||||
|
* $(LI inout)
|
||||||
|
* $(LI shared)
|
||||||
|
* )
|
||||||
|
* and combinations of these.
|
||||||
|
*
|
||||||
|
* Params:
|
||||||
|
* From = Source type.
|
||||||
|
* To = Target type.
|
||||||
|
*
|
||||||
|
* Returns: $(D_PARAM To) with the type qualifiers of $(D_PARAM From).
|
||||||
|
*
|
||||||
|
* See_Also: $(D_PSYMBOL CopyConstness).
|
||||||
|
*/
|
||||||
|
template CopyTypeQualifiers(From, To)
|
||||||
|
{
|
||||||
|
static if (is(From T == immutable T))
|
||||||
|
{
|
||||||
|
alias CopyTypeQualifiers = immutable To;
|
||||||
|
}
|
||||||
|
else static if (is(From T == const T))
|
||||||
|
{
|
||||||
|
alias CopyTypeQualifiers = const To;
|
||||||
|
}
|
||||||
|
else static if (is(From T == shared T))
|
||||||
|
{
|
||||||
|
alias CopyTypeQualifiers = shared To;
|
||||||
|
}
|
||||||
|
else static if (is(From T == shared const T))
|
||||||
|
{
|
||||||
|
alias CopyTypeQualifiers = shared const To;
|
||||||
|
}
|
||||||
|
else static if (is(From T == inout T))
|
||||||
|
{
|
||||||
|
alias CopyTypeQualifiers = inout To;
|
||||||
|
}
|
||||||
|
else static if (is(From T == shared inout T))
|
||||||
|
{
|
||||||
|
alias CopyTypeQualifiers = shared inout To;
|
||||||
|
}
|
||||||
|
else static if (is(From T == inout const T))
|
||||||
|
{
|
||||||
|
alias CopyTypeQualifiers = inout const To;
|
||||||
|
}
|
||||||
|
else static if (is(From T == shared inout const T))
|
||||||
|
{
|
||||||
|
alias CopyTypeQualifiers = shared inout const To;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
alias CopyTypeQualifiers = To;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
pure nothrow @safe @nogc unittest
|
||||||
|
{
|
||||||
|
static assert(is(CopyTypeQualifiers!(int, char) == char));
|
||||||
|
static assert(is(CopyTypeQualifiers!(const int, char) == const char));
|
||||||
|
static assert(is(CopyTypeQualifiers!(immutable int, char) == immutable char));
|
||||||
|
static assert(is(CopyTypeQualifiers!(inout int, char) == inout char));
|
||||||
|
static assert(is(CopyTypeQualifiers!(inout const int, char) == inout const char));
|
||||||
|
|
||||||
|
static assert(is(CopyTypeQualifiers!(shared int, char) == shared char));
|
||||||
|
static assert(is(CopyTypeQualifiers!(shared const int, char) == shared const char));
|
||||||
|
static assert(is(CopyTypeQualifiers!(shared inout int, char) == shared inout char));
|
||||||
|
static assert(is(CopyTypeQualifiers!(shared inout const int, char) == shared inout const char));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Evaluates to the unsigned counterpart of the integral type $(D_PARAM T) preserving all type qualifiers.
|
||||||
|
* If $(D_PARAM T) is already unsigned, $(D_INLINECODE Unsigned!T) aliases $(D_PARAM T).
|
||||||
|
*
|
||||||
|
* Params:
|
||||||
|
* T = A type.
|
||||||
|
*
|
||||||
|
* Returns: Unsigned counterpart of $(D_PARAM T).
|
||||||
|
*
|
||||||
|
* See_Also: $(D_PSYMBOL isSigned).
|
||||||
|
*/
|
||||||
|
template Unsigned(T)
|
||||||
|
if (isIntegral!T)
|
||||||
|
{
|
||||||
|
alias UnqualedType = Unqual!(OriginalType!T);
|
||||||
|
static if (is(UnqualedType == byte))
|
||||||
|
{
|
||||||
|
alias Unsigned = CopyTypeQualifiers!(T, ubyte);
|
||||||
|
}
|
||||||
|
else static if (is(UnqualedType == short))
|
||||||
|
{
|
||||||
|
alias Unsigned = CopyTypeQualifiers!(T, ushort);
|
||||||
|
}
|
||||||
|
else static if (is(UnqualedType == int))
|
||||||
|
{
|
||||||
|
alias Unsigned = CopyTypeQualifiers!(T, uint);
|
||||||
|
}
|
||||||
|
else static if (is(UnqualedType == long))
|
||||||
|
{
|
||||||
|
alias Unsigned = CopyTypeQualifiers!(T, ulong);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
alias Unsigned = T;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
pure nothrow @safe @nogc unittest
|
||||||
|
{
|
||||||
|
static assert(is(Unsigned!byte == ubyte));
|
||||||
|
static assert(is(Unsigned!short == ushort));
|
||||||
|
static assert(is(Unsigned!int == uint));
|
||||||
|
static assert(is(Unsigned!long == ulong));
|
||||||
|
|
||||||
|
static assert(is(Unsigned!(const byte) == const ubyte));
|
||||||
|
static assert(is(Unsigned!(shared byte) == shared ubyte));
|
||||||
|
static assert(is(Unsigned!(shared const byte) == shared const ubyte));
|
||||||
|
|
||||||
|
static assert(!is(Unsigned!float));
|
||||||
|
static assert(is(Unsigned!ubyte == ubyte));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Evaluates to the signed counterpart of the integral type $(D_PARAM T) preserving all type qualifiers.
|
||||||
|
* If $(D_PARAM T) is already signed, $(D_INLINECODE Signed!T) aliases $(D_PARAM T).
|
||||||
|
*
|
||||||
|
* Params:
|
||||||
|
* T = A type.
|
||||||
|
*
|
||||||
|
* Returns: Signed counterpart of $(D_PARAM T).
|
||||||
|
*
|
||||||
|
* See_Also: $(D_PSYMBOL isUnsigned).
|
||||||
|
*/
|
||||||
|
template Signed(T)
|
||||||
|
if (isIntegral!T)
|
||||||
|
{
|
||||||
|
alias UnqualedType = Unqual!(OriginalType!T);
|
||||||
|
static if (is(UnqualedType == ubyte))
|
||||||
|
{
|
||||||
|
alias Signed = CopyTypeQualifiers!(T, byte);
|
||||||
|
}
|
||||||
|
else static if (is(UnqualedType == ushort))
|
||||||
|
{
|
||||||
|
alias Signed = CopyTypeQualifiers!(T, short);
|
||||||
|
}
|
||||||
|
else static if (is(UnqualedType == uint))
|
||||||
|
{
|
||||||
|
alias Signed = CopyTypeQualifiers!(T, int);
|
||||||
|
}
|
||||||
|
else static if (is(UnqualedType == ulong))
|
||||||
|
{
|
||||||
|
alias Signed = CopyTypeQualifiers!(T, long);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
alias Signed = T;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
pure nothrow @safe @nogc unittest
|
||||||
|
{
|
||||||
|
static assert(is(Signed!ubyte == byte));
|
||||||
|
static assert(is(Signed!ushort == short));
|
||||||
|
static assert(is(Signed!uint == int));
|
||||||
|
static assert(is(Signed!ulong == long));
|
||||||
|
|
||||||
|
static assert(is(Signed!(const ubyte) == const byte));
|
||||||
|
static assert(is(Signed!(shared ubyte) == shared byte));
|
||||||
|
static assert(is(Signed!(shared const ubyte) == shared const byte));
|
||||||
|
|
||||||
|
static assert(!is(Signed!float));
|
||||||
|
static assert(is(Signed!byte == byte));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieves the target type `U` of a pointer `U*`.
|
||||||
|
*
|
||||||
|
* Params:
|
||||||
|
* T = Pointer type.
|
||||||
|
*
|
||||||
|
* Returns: Pointer target type.
|
||||||
|
*/
|
||||||
|
template PointerTarget(T)
|
||||||
|
{
|
||||||
|
static if (is(T U : U*))
|
||||||
|
{
|
||||||
|
alias PointerTarget = U;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
static assert(T.stringof ~ " isn't a pointer type");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
pure nothrow @safe @nogc unittest
|
||||||
|
{
|
||||||
|
static assert(is(PointerTarget!(bool*) == bool));
|
||||||
|
static assert(is(PointerTarget!(const bool*) == const bool));
|
||||||
|
static assert(is(PointerTarget!(const shared bool*) == const shared bool));
|
||||||
|
static assert(!is(PointerTarget!bool));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Params:
|
||||||
|
* T = The type of the associative array.
|
||||||
|
*
|
||||||
|
* Returns: The key type of the associative array $(D_PARAM T).
|
||||||
|
*/
|
||||||
|
template KeyType(T)
|
||||||
|
{
|
||||||
|
static if (is(T V : V[K], K))
|
||||||
|
{
|
||||||
|
alias KeyType = K;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
static assert(false, T.stringof ~ " isn't an associative array");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
pure nothrow @safe @nogc unittest
|
||||||
|
{
|
||||||
|
static assert(is(KeyType!(int[string]) == string));
|
||||||
|
static assert(!is(KeyType!(int[15])));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Params:
|
||||||
|
* T = The type of the associative array.
|
||||||
|
*
|
||||||
|
* Returns: The value type of the associative array $(D_PARAM T).
|
||||||
|
*/
|
||||||
|
template ValueType(T)
|
||||||
|
{
|
||||||
|
static if (is(T V : V[K], K))
|
||||||
|
{
|
||||||
|
alias ValueType = V;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
static assert(false, T.stringof ~ " isn't an associative array");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
pure nothrow @safe @nogc unittest
|
||||||
|
{
|
||||||
|
static assert(is(ValueType!(int[string]) == int));
|
||||||
|
static assert(!is(ValueType!(int[15])));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Params:
|
||||||
|
* T = Scalar type.
|
||||||
|
*
|
||||||
|
* Returns: The type $(D_PARAM T) will promote to.
|
||||||
|
*
|
||||||
|
* See_Also: $(LINK2 https://dlang.org/spec/type.html#integer-promotions,
|
||||||
|
* Integer Promotions).
|
||||||
|
*/
|
||||||
|
template Promoted(T)
|
||||||
|
if (isScalarType!T)
|
||||||
|
{
|
||||||
|
alias Promoted = CopyTypeQualifiers!(T, typeof(T.init + T.init));
|
||||||
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
pure nothrow @safe @nogc unittest
|
||||||
|
{
|
||||||
|
static assert(is(Promoted!bool == int));
|
||||||
|
static assert(is(Promoted!byte == int));
|
||||||
|
static assert(is(Promoted!ubyte == int));
|
||||||
|
static assert(is(Promoted!short == int));
|
||||||
|
static assert(is(Promoted!ushort == int));
|
||||||
|
static assert(is(Promoted!char == int));
|
||||||
|
static assert(is(Promoted!wchar == int));
|
||||||
|
static assert(is(Promoted!dchar == uint));
|
||||||
|
|
||||||
|
static assert(is(Promoted!(const bool) == const int));
|
||||||
|
static assert(is(Promoted!(shared bool) == shared int));
|
||||||
|
}
|
@ -9,6 +9,8 @@
|
|||||||
* 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/net/inet.d,
|
||||||
|
* tanya/net/inet.d)
|
||||||
*/
|
*/
|
||||||
module tanya.net.inet;
|
module tanya.net.inet;
|
||||||
|
|
||||||
|
@ -9,6 +9,8 @@
|
|||||||
* 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/net/package.d,
|
||||||
|
* tanya/net/package.d)
|
||||||
*/
|
*/
|
||||||
module tanya.net;
|
module tanya.net;
|
||||||
|
|
||||||
|
@ -9,6 +9,8 @@
|
|||||||
* 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/net/uri.d,
|
||||||
|
* tanya/net/uri.d)
|
||||||
*/
|
*/
|
||||||
module tanya.net.uri;
|
module tanya.net.uri;
|
||||||
|
|
||||||
|
@ -9,6 +9,8 @@
|
|||||||
* 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/network/package.d,
|
||||||
|
* tanya/network/package.d)
|
||||||
*/
|
*/
|
||||||
module tanya.network;
|
module tanya.network;
|
||||||
|
|
||||||
|
@ -9,6 +9,8 @@
|
|||||||
* 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/network/socket.d,
|
||||||
|
* tanya/network/socket.d)
|
||||||
*/
|
*/
|
||||||
module tanya.network.socket;
|
module tanya.network.socket;
|
||||||
|
|
||||||
|
@ -9,6 +9,8 @@
|
|||||||
* 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/os/error.d,
|
||||||
|
* tanya/os/error.d)
|
||||||
*/
|
*/
|
||||||
module tanya.os.error;
|
module tanya.os.error;
|
||||||
|
|
||||||
|
@ -10,6 +10,8 @@
|
|||||||
* 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/os/package.d,
|
||||||
|
* tanya/os/package.d)
|
||||||
*/
|
*/
|
||||||
module tanya.os;
|
module tanya.os;
|
||||||
|
|
||||||
|
@ -12,6 +12,8 @@
|
|||||||
* 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/typecons.d,
|
||||||
|
* tanya/typecons.d)
|
||||||
*/
|
*/
|
||||||
module tanya.typecons;
|
module tanya.typecons;
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user