Compare commits
39 Commits
Author | SHA1 | Date | |
---|---|---|---|
3567a6608e | |||
520bd399a3 | |||
d38e33593e | |||
34b79ad46e | |||
515bf619e8 | |||
617eaab9a2 | |||
d946b598fd | |||
e9d7e9eb73 | |||
4dbfbe9874 | |||
25d59ffdda | |||
2c064eb05b | |||
c9a4a2f651 | |||
0e99effaeb | |||
0f1e53b4b9 | |||
666d59c231 | |||
ce90b4865b | |||
beb5d6963b | |||
a188f8b6e2 | |||
9355c54163 | |||
e8dd6e3217 | |||
94a7fdbb91 | |||
afd3c42c5f | |||
1d91bb4df9 | |||
a5026e48d8 | |||
64f2295d1a | |||
dea0eb9a37 | |||
7c2abadb90 | |||
e6b28468ca | |||
2934bb16d7 | |||
ed92e3993e | |||
1a4d1238a1 | |||
04864559e2 | |||
40e43c1465 | |||
5d145f524c | |||
51ade45108 | |||
3afb40e09e | |||
a9cc135318 | |||
1389b03842 | |||
a37c9b162e |
2
.gitignore
vendored
2
.gitignore
vendored
@ -6,7 +6,7 @@
|
|||||||
.dub
|
.dub
|
||||||
__test__*__
|
__test__*__
|
||||||
__test__*__.core
|
__test__*__.core
|
||||||
/tanya-test-library*
|
/tanya-test-*
|
||||||
|
|
||||||
/docs/
|
/docs/
|
||||||
/docs.json
|
/docs.json
|
||||||
|
10
.travis.yml
10
.travis.yml
@ -7,11 +7,10 @@ os:
|
|||||||
language: d
|
language: d
|
||||||
|
|
||||||
d:
|
d:
|
||||||
- dmd-2.075.0
|
- dmd-2.076.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 +23,12 @@ addons:
|
|||||||
- gcc-multilib
|
- gcc-multilib
|
||||||
|
|
||||||
before_script:
|
before_script:
|
||||||
- if [ "$PS1" = '(dmd-2.075.0)' ]; then
|
- if [ "$PS1" = '(dmd-2.076.0)' ]; 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)
|
||||||
|
14
README.md
14
README.md
@ -16,7 +16,7 @@ Tanya extends Phobos functionality and provides alternative implementations for
|
|||||||
data structures and utilities that depend on the Garbage Collector in Phobos.
|
data structures and utilities that depend on the Garbage Collector in Phobos.
|
||||||
|
|
||||||
* [Bug tracker](https://issues.caraus.io/projects/tanya/issues)
|
* [Bug tracker](https://issues.caraus.io/projects/tanya/issues)
|
||||||
* [Documentation](https://docs.caraus.io/tanya)
|
* [API Documentation](https://docs.caraus.io/tanya)
|
||||||
* [Contribution guidelines](CONTRIBUTING.md)
|
* [Contribution guidelines](CONTRIBUTING.md)
|
||||||
|
|
||||||
|
|
||||||
@ -30,11 +30,16 @@ string, Hash set.
|
|||||||
* `format`: Formatting and conversion functions.
|
* `format`: Formatting and conversion functions.
|
||||||
* `math`: Arbitrary precision integer and a set of functions.
|
* `math`: Arbitrary precision integer and a set of functions.
|
||||||
* `memory`: Tools for manual memory management (allocators, smart pointers).
|
* `memory`: Tools for manual memory management (allocators, smart pointers).
|
||||||
|
* `meta`: Template metaprogramming. This package contains utilities to acquire
|
||||||
|
type information at compile-time, to transform from one type to another. It has
|
||||||
|
also different algorithms for iterating, searching and modifying template
|
||||||
|
arguments.
|
||||||
* `net`: URL-Parsing, network programming.
|
* `net`: URL-Parsing, network programming.
|
||||||
* `network`: Socket implementation. `network` is currently under rework.
|
* `network`: Socket implementation. `network` is currently under rework.
|
||||||
After finishing the new socket implementation will land in the `net` package and
|
After finishing the new socket implementation will land in the `net` package and
|
||||||
`network` will be deprecated.
|
`network` will be deprecated.
|
||||||
* `os`: Platform-independent interfaces to operating system functionality.
|
* `os`: Platform-independent interfaces to operating system functionality.
|
||||||
|
* `range`: Generic functions and templates for D ranges.
|
||||||
* `typecons`: Templates that allow to build new types based on the available
|
* `typecons`: Templates that allow to build new types based on the available
|
||||||
ones.
|
ones.
|
||||||
|
|
||||||
@ -127,7 +132,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 +144,10 @@ There are more containers in the `tanya.container` package.
|
|||||||
|
|
||||||
| dmd |
|
| dmd |
|
||||||
|:-------:|
|
|:-------:|
|
||||||
| 2.075.0 |
|
| 2.076.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
|
||||||
|
|
||||||
|
28
appveyor.yml
28
appveyor.yml
@ -4,10 +4,16 @@ os: Visual Studio 2015
|
|||||||
environment:
|
environment:
|
||||||
matrix:
|
matrix:
|
||||||
- DC: dmd
|
- DC: dmd
|
||||||
DVersion: 2.075.0
|
DVersion: 2.076.0
|
||||||
arch: x64
|
arch: x64
|
||||||
- DC: dmd
|
- DC: dmd
|
||||||
DVersion: 2.075.0
|
DVersion: 2.076.0
|
||||||
|
arch: x86
|
||||||
|
- DC: dmd
|
||||||
|
DVersion: 2.075.1
|
||||||
|
arch: x64
|
||||||
|
- DC: dmd
|
||||||
|
DVersion: 2.075.1
|
||||||
arch: x86
|
arch: x86
|
||||||
- DC: dmd
|
- DC: dmd
|
||||||
DVersion: 2.074.1
|
DVersion: 2.074.1
|
||||||
@ -21,18 +27,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 +43,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";
|
||||||
|
11
dub.json
11
dub.json
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "tanya",
|
"name": "tanya",
|
||||||
"description": "General purpose, @nogc library. Containers, networking, memory management, utilities",
|
"description": "General purpose, @nogc library. Containers, networking, metaprogramming, memory management, utilities",
|
||||||
"license": "MPL-2.0",
|
"license": "MPL-2.0",
|
||||||
"copyright": "(c) Eugene Wissner <info@caraus.de>",
|
"copyright": "(c) Eugene Wissner <info@caraus.de>",
|
||||||
"authors": [
|
"authors": [
|
||||||
@ -11,7 +11,14 @@
|
|||||||
|
|
||||||
"configurations": [
|
"configurations": [
|
||||||
{
|
{
|
||||||
"name": "library"
|
"name": "library",
|
||||||
|
"targetType": "library",
|
||||||
|
"versions": ["TanyaPhobos"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "native",
|
||||||
|
"targetType": "library",
|
||||||
|
"platforms": ["linux-x86_64"]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
@ -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;
|
||||||
|
|
||||||
@ -19,8 +21,9 @@ import std.algorithm.mutation;
|
|||||||
import std.conv;
|
import std.conv;
|
||||||
import std.range.primitives;
|
import std.range.primitives;
|
||||||
import std.meta;
|
import std.meta;
|
||||||
import std.traits;
|
|
||||||
import tanya.memory;
|
import tanya.memory;
|
||||||
|
import tanya.meta.trait;
|
||||||
|
import tanya.meta.transform;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Random-access range for the $(D_PSYMBOL Array).
|
* Random-access range for the $(D_PSYMBOL Array).
|
||||||
|
@ -9,11 +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/container/buffer.d,
|
||||||
|
* tanya/container/buffer.d)
|
||||||
*/
|
*/
|
||||||
module tanya.container.buffer;
|
module tanya.container.buffer;
|
||||||
|
|
||||||
import std.traits;
|
|
||||||
import tanya.memory;
|
import tanya.memory;
|
||||||
|
import tanya.meta.trait;
|
||||||
|
|
||||||
version (unittest)
|
version (unittest)
|
||||||
{
|
{
|
||||||
|
@ -9,10 +9,12 @@
|
|||||||
* 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;
|
||||||
|
|
||||||
import std.traits;
|
import tanya.meta.trait;
|
||||||
import tanya.typecons;
|
import tanya.typecons;
|
||||||
|
|
||||||
package struct SEntry(T)
|
package struct SEntry(T)
|
||||||
@ -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;
|
||||||
|
|
||||||
@ -16,9 +18,9 @@ import std.algorithm.comparison;
|
|||||||
import std.algorithm.mutation;
|
import std.algorithm.mutation;
|
||||||
import std.algorithm.searching;
|
import std.algorithm.searching;
|
||||||
import std.range.primitives;
|
import std.range.primitives;
|
||||||
import std.traits;
|
|
||||||
import tanya.container.entry;
|
import tanya.container.entry;
|
||||||
import tanya.memory;
|
import tanya.memory;
|
||||||
|
import tanya.meta.trait;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Forward range for the $(D_PSYMBOL SList).
|
* Forward range for the $(D_PSYMBOL SList).
|
||||||
|
@ -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,14 +9,16 @@
|
|||||||
* 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;
|
||||||
|
|
||||||
import core.exception;
|
import core.exception;
|
||||||
import std.traits;
|
|
||||||
import std.algorithm.mutation;
|
import std.algorithm.mutation;
|
||||||
import tanya.container.entry;
|
import tanya.container.entry;
|
||||||
import tanya.memory;
|
import tanya.memory;
|
||||||
|
import tanya.meta.trait;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* FIFO queue.
|
* FIFO queue.
|
||||||
|
@ -10,14 +10,17 @@
|
|||||||
* 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;
|
||||||
|
|
||||||
import std.algorithm.mutation;
|
import std.algorithm.mutation;
|
||||||
import std.traits;
|
|
||||||
import tanya.container;
|
import tanya.container;
|
||||||
import tanya.container.entry;
|
import tanya.container.entry;
|
||||||
import tanya.memory;
|
import tanya.memory;
|
||||||
|
import tanya.meta.trait;
|
||||||
|
import tanya.meta.transform;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Bidirectional range that iterates over the $(D_PSYMBOL Set)'s values.
|
* Bidirectional range that iterates over the $(D_PSYMBOL Set)'s values.
|
||||||
@ -349,7 +352,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 +365,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 +395,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 +476,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 +493,7 @@ struct Set(T)
|
|||||||
}
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
unittest
|
@nogc unittest
|
||||||
{
|
{
|
||||||
Set!int set;
|
Set!int set;
|
||||||
assert(8 !in set);
|
assert(8 !in set);
|
||||||
@ -500,14 +515,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 +532,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 +621,7 @@ struct Set(T)
|
|||||||
}
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
unittest
|
@nogc unittest
|
||||||
{
|
{
|
||||||
Set!int set;
|
Set!int set;
|
||||||
assert(set[].empty);
|
assert(set[].empty);
|
||||||
@ -647,13 +635,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;
|
||||||
|
|
||||||
@ -28,31 +30,12 @@ import core.exception;
|
|||||||
import std.algorithm.comparison;
|
import std.algorithm.comparison;
|
||||||
import std.algorithm.mutation;
|
import std.algorithm.mutation;
|
||||||
import std.algorithm.searching;
|
import std.algorithm.searching;
|
||||||
import std.range;
|
import std.range : isInfinite, isInputRange, ElementEncodingType, hasLength,
|
||||||
import std.traits;
|
popFrontN, empty;
|
||||||
import tanya.memory;
|
import tanya.memory;
|
||||||
|
import tanya.meta.trait;
|
||||||
private ref const(wchar) front(const wchar[] str)
|
import tanya.meta.transform;
|
||||||
pure nothrow @safe @nogc
|
import tanya.range.array;
|
||||||
in
|
|
||||||
{
|
|
||||||
assert(str.length > 0);
|
|
||||||
}
|
|
||||||
body
|
|
||||||
{
|
|
||||||
return str[0];
|
|
||||||
}
|
|
||||||
|
|
||||||
private void popFront(ref const(wchar)[] str, const size_t s = 1)
|
|
||||||
pure nothrow @safe @nogc
|
|
||||||
in
|
|
||||||
{
|
|
||||||
assert(str.length >= s);
|
|
||||||
}
|
|
||||||
body
|
|
||||||
{
|
|
||||||
str = str[s .. $];
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Thrown on encoding errors.
|
* Thrown on encoding errors.
|
||||||
@ -788,7 +771,7 @@ struct String
|
|||||||
}
|
}
|
||||||
dchar d = (range[0] - 0xd800) | ((range[1] - 0xdc00) >> 10);
|
dchar d = (range[0] - 0xd800) | ((range[1] - 0xdc00) >> 10);
|
||||||
|
|
||||||
range.popFront(2);
|
range.popFrontN(2);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -8,12 +8,17 @@
|
|||||||
* Copyright: Eugene Wissner 2017.
|
* Copyright: Eugene Wissner 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: Jeff Roberts, $(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 tanya.container.string;
|
||||||
import tanya.memory;
|
import tanya.memory;
|
||||||
|
import tanya.memory.op;
|
||||||
|
import tanya.meta.trait;
|
||||||
|
import tanya.meta.transform;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Thrown if a type conversion fails.
|
* Thrown if a type conversion fails.
|
||||||
@ -273,18 +278,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 +316,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 +333,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 +348,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 +400,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 +443,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 +563,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 +611,81 @@ private @nogc unittest
|
|||||||
assert(exception !is null);
|
assert(exception !is null);
|
||||||
defaultAllocator.dispose(exception);
|
defaultAllocator.dispose(exception);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Returns the last part of buffer with converted number.
|
||||||
|
package(tanya) char[] number2String(T)(const T number,
|
||||||
|
return ref char[21] buffer)
|
||||||
|
if (isIntegral!T)
|
||||||
|
{
|
||||||
|
// abs the integer.
|
||||||
|
ulong n64 = number < 0 ? -cast(long) number : number;
|
||||||
|
|
||||||
|
char* start = buffer[].ptr + buffer.sizeof - 1;
|
||||||
|
|
||||||
|
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 != (buffer[].ptr + buffer.sizeof -1)))
|
||||||
|
{
|
||||||
|
++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 have copied.
|
||||||
|
uint l = cast(uint) ((buffer[].ptr + buffer.sizeof - 1) - start);
|
||||||
|
if (l == 0)
|
||||||
|
{
|
||||||
|
*--start = '0';
|
||||||
|
l = 1;
|
||||||
|
}
|
||||||
|
else if (number < 0) // Set the sign.
|
||||||
|
{
|
||||||
|
*--start = '-';
|
||||||
|
++l;
|
||||||
|
}
|
||||||
|
|
||||||
|
return buffer[$ - l - 1 .. $ - 1];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Converting an integer to string.
|
||||||
|
private pure nothrow @system @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");
|
||||||
|
}
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -9,15 +9,18 @@
|
|||||||
* 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;
|
||||||
|
|
||||||
import std.algorithm;
|
import std.algorithm;
|
||||||
import std.ascii;
|
import std.ascii;
|
||||||
import std.range;
|
import std.range;
|
||||||
import std.traits;
|
|
||||||
import tanya.container.array;
|
import tanya.container.array;
|
||||||
import tanya.memory;
|
import tanya.memory;
|
||||||
|
import tanya.meta.trait;
|
||||||
|
import tanya.meta.transform;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Algebraic sign.
|
* Algebraic sign.
|
||||||
|
@ -9,12 +9,14 @@
|
|||||||
* 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;
|
||||||
|
|
||||||
import std.traits;
|
|
||||||
public import tanya.math.mp;
|
public import tanya.math.mp;
|
||||||
public import tanya.math.random;
|
public import tanya.math.random;
|
||||||
|
import tanya.meta.trait;
|
||||||
|
|
||||||
version (unittest)
|
version (unittest)
|
||||||
{
|
{
|
||||||
|
@ -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,9 +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/memory/mallocator.d,
|
||||||
|
* tanya/memory/mallocator.d)
|
||||||
*/
|
*/
|
||||||
module tanya.memory.mallocator;
|
module tanya.memory.mallocator;
|
||||||
|
|
||||||
|
version (TanyaPhobos):
|
||||||
|
|
||||||
import core.stdc.stdlib;
|
import core.stdc.stdlib;
|
||||||
import tanya.memory.allocator;
|
import tanya.memory.allocator;
|
||||||
|
|
||||||
|
@ -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;
|
||||||
|
|
||||||
@ -17,9 +19,9 @@ import std.algorithm.iteration;
|
|||||||
import std.algorithm.mutation;
|
import std.algorithm.mutation;
|
||||||
import std.conv;
|
import std.conv;
|
||||||
import std.range;
|
import std.range;
|
||||||
import std.traits;
|
|
||||||
public import tanya.memory.allocator;
|
public import tanya.memory.allocator;
|
||||||
import tanya.memory.mmappool;
|
import tanya.memory.mmappool;
|
||||||
|
import tanya.meta.trait;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The mixin generates common methods for classes and structs using
|
* The mixin generates common methods for classes and structs using
|
||||||
@ -135,17 +137,6 @@ body
|
|||||||
.allocator = allocator;
|
.allocator = allocator;
|
||||||
}
|
}
|
||||||
|
|
||||||
private nothrow @nogc unittest
|
|
||||||
{
|
|
||||||
import tanya.memory.mallocator;
|
|
||||||
|
|
||||||
auto oldAllocator = defaultAllocator;
|
|
||||||
defaultAllocator = Mallocator.instance;
|
|
||||||
assert(defaultAllocator is Mallocator.instance);
|
|
||||||
|
|
||||||
defaultAllocator = oldAllocator;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the size in bytes of the state that needs to be allocated to hold an
|
* Returns the size in bytes of the state that needs to be allocated to hold an
|
||||||
* object of type $(D_PARAM T).
|
* object of type $(D_PARAM T).
|
||||||
@ -178,7 +169,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 +372,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 +382,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 +411,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 +421,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 +434,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;
|
||||||
|
|
||||||
@ -20,8 +22,8 @@ import std.algorithm.comparison;
|
|||||||
import std.algorithm.mutation;
|
import std.algorithm.mutation;
|
||||||
import std.conv;
|
import std.conv;
|
||||||
import std.range;
|
import std.range;
|
||||||
import std.traits;
|
|
||||||
import tanya.memory;
|
import tanya.memory;
|
||||||
|
import tanya.meta.trait;
|
||||||
|
|
||||||
private template Payload(T)
|
private template Payload(T)
|
||||||
{
|
{
|
||||||
|
1780
source/tanya/meta/metafunction.d
Normal file
1780
source/tanya/meta/metafunction.d
Normal file
File diff suppressed because it is too large
Load Diff
23
source/tanya/meta/package.d
Normal file
23
source/tanya/meta/package.d
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
/* 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.
|
||||||
|
*
|
||||||
|
* This package contains utilities to acquire type information at compile-time,
|
||||||
|
* to transform from one type to another. It has also different algorithms for
|
||||||
|
* iterating, searching and modifying template arguments.
|
||||||
|
*
|
||||||
|
* Copyright: Eugene Wissner 2017.
|
||||||
|
* License: $(LINK2 https://www.mozilla.org/en-US/MPL/2.0/,
|
||||||
|
* Mozilla Public License, v. 2.0).
|
||||||
|
* Authors: $(LINK2 mailto:info@caraus.de, Eugene Wissner)
|
||||||
|
* Source: $(LINK2 https://github.com/caraus-ecms/tanya/blob/master/source/tanya/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;
|
3069
source/tanya/meta/trait.d
Normal file
3069
source/tanya/meta/trait.d
Normal file
File diff suppressed because it is too large
Load Diff
741
source/tanya/meta/transform.d
Normal file
741
source/tanya/meta/transform.d
Normal file
@ -0,0 +1,741 @@
|
|||||||
|
/* 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. They take some type as argument and return a different type after
|
||||||
|
* perfoming the specified transformation.
|
||||||
|
*
|
||||||
|
* 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;
|
||||||
|
|
||||||
|
version (TanyaPhobos)
|
||||||
|
{
|
||||||
|
public import std.traits : Unqual,
|
||||||
|
OriginalType,
|
||||||
|
CopyConstness,
|
||||||
|
CopyTypeQualifiers,
|
||||||
|
Unsigned,
|
||||||
|
Signed,
|
||||||
|
PointerTarget,
|
||||||
|
KeyType,
|
||||||
|
ValueType,
|
||||||
|
Promoted,
|
||||||
|
InoutOf,
|
||||||
|
ConstOf,
|
||||||
|
SharedOf,
|
||||||
|
SharedInoutOf,
|
||||||
|
SharedConstOf,
|
||||||
|
ImmutableOf,
|
||||||
|
QualifierOf;
|
||||||
|
}
|
||||||
|
else:
|
||||||
|
|
||||||
|
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));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds $(D_KEYWORD inout) qualifier to the type $(D_PARAM T).
|
||||||
|
*
|
||||||
|
* Params:
|
||||||
|
* T = A type.
|
||||||
|
*
|
||||||
|
* Returns: $(D_INLINECODE inout(T)).
|
||||||
|
*/
|
||||||
|
alias InoutOf(T) = inout(T);
|
||||||
|
|
||||||
|
///
|
||||||
|
pure nothrow @safe @nogc unittest
|
||||||
|
{
|
||||||
|
static assert(is(InoutOf!int == inout int));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds $(D_KEYWORD inout) qualifier to the type $(D_PARAM T).
|
||||||
|
*
|
||||||
|
* Params:
|
||||||
|
* T = A type.
|
||||||
|
*
|
||||||
|
* Returns: $(D_INLINECODE inout(T)).
|
||||||
|
*/
|
||||||
|
alias ConstOf(T) = const(T);
|
||||||
|
|
||||||
|
///
|
||||||
|
pure nothrow @safe @nogc unittest
|
||||||
|
{
|
||||||
|
static assert(is(ConstOf!int == const int));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds $(D_KEYWORD inout) qualifier to the type $(D_PARAM T).
|
||||||
|
*
|
||||||
|
* Params:
|
||||||
|
* T = A type.
|
||||||
|
*
|
||||||
|
* Returns: $(D_INLINECODE inout(T)).
|
||||||
|
*/
|
||||||
|
alias SharedOf(T) = shared(T);
|
||||||
|
|
||||||
|
///
|
||||||
|
pure nothrow @safe @nogc unittest
|
||||||
|
{
|
||||||
|
static assert(is(SharedOf!int == shared int));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds $(D_KEYWORD inout) qualifier to the type $(D_PARAM T).
|
||||||
|
*
|
||||||
|
* Params:
|
||||||
|
* T = A type.
|
||||||
|
*
|
||||||
|
* Returns: $(D_INLINECODE inout(T)).
|
||||||
|
*/
|
||||||
|
alias SharedInoutOf(T) = shared(inout T);
|
||||||
|
|
||||||
|
///
|
||||||
|
pure nothrow @safe @nogc unittest
|
||||||
|
{
|
||||||
|
static assert(is(SharedInoutOf!int == shared inout int));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds $(D_KEYWORD shared const) qualifier to the type $(D_PARAM T).
|
||||||
|
*
|
||||||
|
* Params:
|
||||||
|
* T = A type.
|
||||||
|
*
|
||||||
|
* Returns: $(D_INLINECODE shared(const T)).
|
||||||
|
*/
|
||||||
|
alias SharedConstOf(T) = shared(const T);
|
||||||
|
|
||||||
|
///
|
||||||
|
pure nothrow @safe @nogc unittest
|
||||||
|
{
|
||||||
|
static assert(is(SharedConstOf!int == shared const int));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds $(D_KEYWORD immutable) qualifier to the type $(D_PARAM T).
|
||||||
|
*
|
||||||
|
* Params:
|
||||||
|
* T = A type.
|
||||||
|
*
|
||||||
|
* Returns: $(D_INLINECODE immutable(T)).
|
||||||
|
*/
|
||||||
|
alias ImmutableOf(T) = immutable(T);
|
||||||
|
|
||||||
|
///
|
||||||
|
pure nothrow @safe @nogc unittest
|
||||||
|
{
|
||||||
|
static assert(is(ImmutableOf!int == immutable int));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds $(D_KEYWORD inout const) qualifier to the type $(D_PARAM T).
|
||||||
|
*
|
||||||
|
* Params:
|
||||||
|
* T = A type.
|
||||||
|
*
|
||||||
|
* Returns: $(D_INLINECODE inout(const T)).
|
||||||
|
*/
|
||||||
|
alias InoutConstOf(T) = inout(const T);
|
||||||
|
|
||||||
|
///
|
||||||
|
pure nothrow @safe @nogc unittest
|
||||||
|
{
|
||||||
|
static assert(is(InoutConstOf!int == inout const int));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds $(D_KEYWORD shared inout const) qualifier to the type $(D_PARAM T).
|
||||||
|
*
|
||||||
|
* Params:
|
||||||
|
* T = A type.
|
||||||
|
*
|
||||||
|
* Returns: $(D_INLINECODE shared(inout const T)).
|
||||||
|
*/
|
||||||
|
alias SharedInoutConstOf(T) = shared(inout const T);
|
||||||
|
|
||||||
|
///
|
||||||
|
pure nothrow @safe @nogc unittest
|
||||||
|
{
|
||||||
|
static assert(is(SharedInoutConstOf!int == shared inout const int));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a template with one argument which applies all qualifiers of
|
||||||
|
* $(D_PARAM T) on its argument if instantiated.
|
||||||
|
*
|
||||||
|
* Params:
|
||||||
|
* T = A type.
|
||||||
|
*
|
||||||
|
* Returns: $(D_INLINECODE shared(inout const T)).
|
||||||
|
*/
|
||||||
|
template QualifierOf(T)
|
||||||
|
{
|
||||||
|
static if (is(T U == const U))
|
||||||
|
{
|
||||||
|
alias QualifierOf = ConstOf;
|
||||||
|
}
|
||||||
|
else static if (is(T U == immutable U))
|
||||||
|
{
|
||||||
|
alias QualifierOf = ImmutableOf;
|
||||||
|
}
|
||||||
|
else static if (is(T U == inout U))
|
||||||
|
{
|
||||||
|
alias QualifierOf = InoutOf;
|
||||||
|
}
|
||||||
|
else static if (is(T U == inout const U))
|
||||||
|
{
|
||||||
|
alias QualifierOf = InoutConstOf;
|
||||||
|
}
|
||||||
|
else static if (is(T U == shared U))
|
||||||
|
{
|
||||||
|
alias QualifierOf = SharedOf;
|
||||||
|
}
|
||||||
|
else static if (is(T U == shared const U))
|
||||||
|
{
|
||||||
|
alias QualifierOf = SharedConstOf;
|
||||||
|
}
|
||||||
|
else static if (is(T U == shared inout U))
|
||||||
|
{
|
||||||
|
alias QualifierOf = SharedInoutOf;
|
||||||
|
}
|
||||||
|
else static if (is(T U == shared inout const U))
|
||||||
|
{
|
||||||
|
alias QualifierOf = SharedInoutConstOf;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
alias QualifierOf(T) = T;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
pure nothrow @safe @nogc unittest
|
||||||
|
{
|
||||||
|
alias MutableOf = QualifierOf!int;
|
||||||
|
static assert(is(MutableOf!uint == uint));
|
||||||
|
|
||||||
|
alias ConstOf = QualifierOf!(const int);
|
||||||
|
static assert(is(ConstOf!uint == const uint));
|
||||||
|
|
||||||
|
alias InoutOf = QualifierOf!(inout int);
|
||||||
|
static assert(is(InoutOf!uint == inout uint));
|
||||||
|
|
||||||
|
alias InoutConstOf = QualifierOf!(inout const int);
|
||||||
|
static assert(is(InoutConstOf!uint == inout const uint));
|
||||||
|
|
||||||
|
alias ImmutableOf = QualifierOf!(immutable int);
|
||||||
|
static assert(is(ImmutableOf!uint == immutable uint));
|
||||||
|
|
||||||
|
alias SharedOf = QualifierOf!(shared int);
|
||||||
|
static assert(is(SharedOf!uint == shared uint));
|
||||||
|
|
||||||
|
alias SharedConstOf = QualifierOf!(shared const int);
|
||||||
|
static assert(is(SharedConstOf!uint == shared const uint));
|
||||||
|
|
||||||
|
alias SharedInoutOf = QualifierOf!(shared inout int);
|
||||||
|
static assert(is(SharedInoutOf!uint == shared inout uint));
|
||||||
|
|
||||||
|
alias SharedInoutConstOf = QualifierOf!(shared inout const int);
|
||||||
|
static assert(is(SharedInoutConstOf!uint == shared inout const uint));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determines the type of $(D_PARAM T). If $(D_PARAM T) is already a type,
|
||||||
|
* $(D_PSYMBOL TypeOf) aliases itself to $(D_PARAM T).
|
||||||
|
*
|
||||||
|
* $(D_PSYMBOL TypeOf) evaluates to $(D_KEYWORD void) for template arguments.
|
||||||
|
*
|
||||||
|
* The symbols that don't have a type and aren't types cannot be used as
|
||||||
|
* arguments to $(D_PSYMBOL TypeOf).
|
||||||
|
*
|
||||||
|
* Params:
|
||||||
|
* T = Expression, type or template.
|
||||||
|
*
|
||||||
|
* Returns: The type of $(D_PARAM T).
|
||||||
|
*/
|
||||||
|
alias TypeOf(T) = T;
|
||||||
|
|
||||||
|
/// Ditto.
|
||||||
|
template TypeOf(alias T)
|
||||||
|
if (isExpressions!T || isTemplate!T)
|
||||||
|
{
|
||||||
|
alias TypeOf = typeof(T);
|
||||||
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
pure nothrow @safe @nogc unittest
|
||||||
|
{
|
||||||
|
struct S(T)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
static assert(is(TypeOf!S == void));
|
||||||
|
static assert(is(TypeOf!int == int));
|
||||||
|
static assert(is(TypeOf!true == bool));
|
||||||
|
static assert(!is(TypeOf!(tanya.meta)));
|
||||||
|
}
|
@ -9,26 +9,15 @@
|
|||||||
* 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;
|
||||||
|
|
||||||
import std.math;
|
import std.math;
|
||||||
import std.range.primitives;
|
import std.range.primitives;
|
||||||
import std.traits;
|
import tanya.meta.trait;
|
||||||
|
import tanya.meta.transform;
|
||||||
version (unittest)
|
|
||||||
{
|
|
||||||
version (Windows)
|
|
||||||
{
|
|
||||||
import core.sys.windows.winsock2;
|
|
||||||
version = PlattformUnittest;
|
|
||||||
}
|
|
||||||
else version (Posix)
|
|
||||||
{
|
|
||||||
import core.sys.posix.arpa.inet;
|
|
||||||
version = PlattformUnittest;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents an unsigned integer as an $(D_KEYWORD ubyte) range.
|
* Represents an unsigned integer as an $(D_KEYWORD ubyte) range.
|
||||||
@ -210,79 +199,6 @@ private unittest
|
|||||||
static assert(!is(NetworkOrder!1));
|
static assert(!is(NetworkOrder!1));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Tests against the system's htonl, htons.
|
|
||||||
version (PlattformUnittest)
|
|
||||||
{
|
|
||||||
private unittest
|
|
||||||
{
|
|
||||||
for (uint counter; counter <= 8 * uint.sizeof; ++counter)
|
|
||||||
{
|
|
||||||
const value = pow(2, counter) - 1;
|
|
||||||
const inNetworkOrder = htonl(value);
|
|
||||||
const p = cast(ubyte*) &inNetworkOrder;
|
|
||||||
auto networkOrder = NetworkOrder!4(value);
|
|
||||||
|
|
||||||
assert(networkOrder.length == 4);
|
|
||||||
assert(!networkOrder.empty);
|
|
||||||
assert(networkOrder.front == *p);
|
|
||||||
assert(networkOrder.back == *(p + 3));
|
|
||||||
|
|
||||||
networkOrder.popBack();
|
|
||||||
assert(networkOrder.length == 3);
|
|
||||||
assert(networkOrder.front == *p);
|
|
||||||
assert(networkOrder.back == *(p + 2));
|
|
||||||
|
|
||||||
networkOrder.popFront();
|
|
||||||
assert(networkOrder.length == 2);
|
|
||||||
assert(networkOrder.front == *(p + 1));
|
|
||||||
assert(networkOrder.back == *(p + 2));
|
|
||||||
|
|
||||||
networkOrder.popFront();
|
|
||||||
assert(networkOrder.length == 1);
|
|
||||||
assert(networkOrder.front == *(p + 2));
|
|
||||||
assert(networkOrder.back == *(p + 2));
|
|
||||||
|
|
||||||
networkOrder.popBack();
|
|
||||||
assert(networkOrder.length == 0);
|
|
||||||
assert(networkOrder.empty);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (ushort counter; counter <= 8 * ushort.sizeof; ++counter)
|
|
||||||
{
|
|
||||||
const value = cast(ushort) (pow(2, counter) - 1);
|
|
||||||
const inNetworkOrder = htons(value);
|
|
||||||
const p = cast(ubyte*) &inNetworkOrder;
|
|
||||||
|
|
||||||
auto networkOrder = NetworkOrder!2(value);
|
|
||||||
|
|
||||||
assert(networkOrder.length == 2);
|
|
||||||
assert(!networkOrder.empty);
|
|
||||||
assert(networkOrder.front == *p);
|
|
||||||
assert(networkOrder.back == *(p + 1));
|
|
||||||
|
|
||||||
networkOrder.popBack();
|
|
||||||
assert(networkOrder.length == 1);
|
|
||||||
assert(networkOrder.front == *p);
|
|
||||||
assert(networkOrder.back == *p);
|
|
||||||
|
|
||||||
networkOrder.popBack();
|
|
||||||
assert(networkOrder.length == 0);
|
|
||||||
assert(networkOrder.empty);
|
|
||||||
|
|
||||||
networkOrder = NetworkOrder!2(value);
|
|
||||||
|
|
||||||
networkOrder.popFront();
|
|
||||||
assert(networkOrder.length == 1);
|
|
||||||
assert(networkOrder.front == *(p + 1));
|
|
||||||
assert(networkOrder.back == *(p + 1));
|
|
||||||
|
|
||||||
networkOrder.popFront();
|
|
||||||
assert(networkOrder.length == 0);
|
|
||||||
assert(networkOrder.empty);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Converts the $(D_KEYWORD ubyte) input range $(D_PARAM range) to
|
* Converts the $(D_KEYWORD ubyte) input range $(D_PARAM range) to
|
||||||
* $(D_PARAM T).
|
* $(D_PARAM T).
|
||||||
@ -328,29 +244,3 @@ pure nothrow @safe @nogc unittest
|
|||||||
auto networkOrder = NetworkOrder!4(value);
|
auto networkOrder = NetworkOrder!4(value);
|
||||||
assert(networkOrder.toHostOrder() == value);
|
assert(networkOrder.toHostOrder() == value);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Tests against the system's htonl, htons.
|
|
||||||
version (PlattformUnittest)
|
|
||||||
{
|
|
||||||
private unittest
|
|
||||||
{
|
|
||||||
for (uint counter; counter <= 8 * uint.sizeof; ++counter)
|
|
||||||
{
|
|
||||||
const value = pow(2, counter) - 1;
|
|
||||||
const inNetworkOrder = htonl(value);
|
|
||||||
const p = cast(ubyte*) &inNetworkOrder;
|
|
||||||
auto networkOrder = NetworkOrder!4(value);
|
|
||||||
|
|
||||||
assert(p[0 .. uint.sizeof].toHostOrder() == value);
|
|
||||||
}
|
|
||||||
for (ushort counter; counter <= 8 * ushort.sizeof; ++counter)
|
|
||||||
{
|
|
||||||
const value = cast(ushort) (pow(2, counter) - 1);
|
|
||||||
const inNetworkOrder = htons(value);
|
|
||||||
const p = cast(ubyte*) &inNetworkOrder;
|
|
||||||
auto networkOrder = NetworkOrder!2(value);
|
|
||||||
|
|
||||||
assert(p[0 .. ushort.sizeof].toHostOrder() == value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
@ -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;
|
||||||
|
|
||||||
|
220
source/tanya/range/array.d
Normal file
220
source/tanya/range/array.d
Normal file
@ -0,0 +1,220 @@
|
|||||||
|
/* 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/. */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* $(D_PSYMBOL tanya.range.array) implements range primitives for built-in arrays.
|
||||||
|
*
|
||||||
|
* This module is a submodule of
|
||||||
|
* $(LINK2 https://github.com/caraus-ecms/tanya/blob/master/source/tanya/range/package.d, tanya.range).
|
||||||
|
*
|
||||||
|
* After importing of
|
||||||
|
* $(LINK2 https://github.com/caraus-ecms/tanya/blob/master/source/tanya/range/array.d, tanya/range/array.d)
|
||||||
|
* built-in arrays can act as bidirectional ranges. For that to work the module
|
||||||
|
* defines a set of functions that accept a built-in array of any type as their
|
||||||
|
* first argument, so thanks to UFCS (Uniform Function Call Syntax) they can be
|
||||||
|
* called as if they were array member functions. For example the arrays the
|
||||||
|
* `.length`-property, but no `.empty` property. So here can be find the
|
||||||
|
* $(D_PSYMBOL empty) function. Since $(D_INLINECODE empty(array)) and
|
||||||
|
* $(D_INLINECODE array.empty) are equal for the arrays, arrays get a faked
|
||||||
|
* property `empty`.
|
||||||
|
*
|
||||||
|
* The functions in this module don't change array elements or its underlying
|
||||||
|
* storage, but some functions alter the slice. Each array maintains a pointer
|
||||||
|
* to its data and the length and there can be several pointers which point to
|
||||||
|
* the same data. Array pointer can be advanced and the length can be reduced
|
||||||
|
* without changing the underlying storage. So slices offer the possibility to
|
||||||
|
* have multiple views into the same array, point to different positions inside
|
||||||
|
* it.
|
||||||
|
*
|
||||||
|
* Strings ($(D_INLINECODE char[]), (D_INLINECODE wchar[]) and
|
||||||
|
* (D_INLINECODE dchar[])) are treated as any other normal array, they aren't
|
||||||
|
* auto-decoded.
|
||||||
|
*
|
||||||
|
* 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/range/array.d,
|
||||||
|
* tanya/range/array.d)
|
||||||
|
*/
|
||||||
|
module tanya.range.array;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the first element of the $(D_PARAM array).
|
||||||
|
*
|
||||||
|
* The element is returned by reference, so $(D_PSYMBOL front) can be also used
|
||||||
|
* to change the first element of $(D_PARAM array) if it is mutable.
|
||||||
|
*
|
||||||
|
* Params:
|
||||||
|
* T = Element type of $(D_PARAM array).
|
||||||
|
* array = Built-in array.
|
||||||
|
*
|
||||||
|
* Returns: First element.
|
||||||
|
*
|
||||||
|
* Precondition: $(D_INLINECODE array.length > 0).
|
||||||
|
*/
|
||||||
|
@property ref T front(T)(T[] array)
|
||||||
|
in
|
||||||
|
{
|
||||||
|
assert(array.length > 0);
|
||||||
|
}
|
||||||
|
body
|
||||||
|
{
|
||||||
|
return array[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
pure nothrow @safe @nogc unittest
|
||||||
|
{
|
||||||
|
string s = "Wenn die Wunde nicht mehr wehtut, schmerzt die Narbe";
|
||||||
|
static assert(is(typeof(s.front) == immutable char));
|
||||||
|
assert(s.front == 'W');
|
||||||
|
|
||||||
|
wstring w = "Волны несутся, гремя и сверкая";
|
||||||
|
static assert(is(typeof(w.front) == immutable wchar));
|
||||||
|
assert(w.front == 'В');
|
||||||
|
|
||||||
|
dstring d = "Для писателя память - это почти все";
|
||||||
|
static assert(is(typeof(d.front) == immutable dchar));
|
||||||
|
assert(d.front == 'Д');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the last element of the $(D_PARAM array).
|
||||||
|
*
|
||||||
|
* The element is returned by reference, so $(D_PSYMBOL back) can be also used
|
||||||
|
* to change the last element of $(D_PARAM array) if it is mutable.
|
||||||
|
*
|
||||||
|
* Params:
|
||||||
|
* T = Element type of $(D_PARAM array).
|
||||||
|
* array = Built-in array.
|
||||||
|
*
|
||||||
|
* Returns: Last element.
|
||||||
|
*
|
||||||
|
* Precondition: $(D_INLINECODE array.length > 0).
|
||||||
|
*/
|
||||||
|
@property ref T back(T)(T[] array)
|
||||||
|
in
|
||||||
|
{
|
||||||
|
assert(array.length > 0);
|
||||||
|
}
|
||||||
|
body
|
||||||
|
{
|
||||||
|
return array[$ - 1];
|
||||||
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
pure nothrow @safe @nogc unittest
|
||||||
|
{
|
||||||
|
string s = "Brecht";
|
||||||
|
static assert(is(typeof(s.back) == immutable char));
|
||||||
|
assert(s.back == 't');
|
||||||
|
|
||||||
|
wstring w = "Тютчев";
|
||||||
|
static assert(is(typeof(w.back) == immutable wchar));
|
||||||
|
assert(w.back == 'в');
|
||||||
|
|
||||||
|
dstring d = "Паустовский";
|
||||||
|
static assert(is(typeof(d.back) == immutable dchar));
|
||||||
|
assert(d.back == 'й');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* $(D_PSYMBOL popFront) and $(D_PSYMBOL popBack) advance the $(D_PARAM array)
|
||||||
|
* and remove one element from its back, respectively.
|
||||||
|
*
|
||||||
|
* $(D_PSYMBOL popFront) and $(D_PSYMBOL popBack) don't alter the array
|
||||||
|
* storage, they only narrow the view into the array.
|
||||||
|
*
|
||||||
|
* Params:
|
||||||
|
* T = Element type of $(D_PARAM array).
|
||||||
|
* array = Built-in array.
|
||||||
|
*
|
||||||
|
* Precondition: $(D_INLINECODE array.length > 0).
|
||||||
|
*/
|
||||||
|
void popFront(T)(ref T[] array)
|
||||||
|
in
|
||||||
|
{
|
||||||
|
assert(array.length > 0);
|
||||||
|
}
|
||||||
|
body
|
||||||
|
{
|
||||||
|
array = array[1 .. $];
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Ditto.
|
||||||
|
void popBack(T)(ref T[] array)
|
||||||
|
in
|
||||||
|
{
|
||||||
|
assert(array.length > 0);
|
||||||
|
}
|
||||||
|
body
|
||||||
|
{
|
||||||
|
array = array[0 .. $ - 1];
|
||||||
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
pure nothrow @safe @nogc unittest
|
||||||
|
{
|
||||||
|
wstring array = "Der finstere Ozean der Metaphysik. Nietzsche";
|
||||||
|
|
||||||
|
array.popFront();
|
||||||
|
assert(array.length == 43);
|
||||||
|
assert(array.front == 'e');
|
||||||
|
|
||||||
|
array.popBack();
|
||||||
|
assert(array.length == 42);
|
||||||
|
assert(array.back == 'h');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests whether $(D_PARAM array) is empty.
|
||||||
|
*
|
||||||
|
* Params:
|
||||||
|
* T = Element type of $(D_PARAM array).
|
||||||
|
* array = Built-in array.
|
||||||
|
*
|
||||||
|
* Returns: $(D_KEYWORD true) if $(D_PARAM array) has no elements,
|
||||||
|
* $(D_KEYWORD false) otherwise.
|
||||||
|
*/
|
||||||
|
@property bool empty(T)(const T[] array)
|
||||||
|
{
|
||||||
|
return array.length == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
pure nothrow @safe @nogc unittest
|
||||||
|
{
|
||||||
|
int[1] array;
|
||||||
|
assert(!array.empty);
|
||||||
|
assert(array[1 .. 1].empty);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a copy of the slice $(D_PARAM array).
|
||||||
|
*
|
||||||
|
* $(D_PSYMBOL save) doesn't copy the array itself, but only the data pointer
|
||||||
|
* and the length.
|
||||||
|
*
|
||||||
|
* Params:
|
||||||
|
* T = Element type of $(D_PARAM array).
|
||||||
|
* array = Built-in array.
|
||||||
|
*
|
||||||
|
* Returns: A copy of the slice $(D_PARAM array).
|
||||||
|
*/
|
||||||
|
@property T[] save(T)(T[] array)
|
||||||
|
{
|
||||||
|
return array;
|
||||||
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
pure nothrow @safe @nogc unittest
|
||||||
|
{
|
||||||
|
ubyte[8] array;
|
||||||
|
auto slice = array.save;
|
||||||
|
|
||||||
|
assert(slice.length == array.length);
|
||||||
|
slice.popFront();
|
||||||
|
assert(slice.length < array.length);
|
||||||
|
}
|
18
source/tanya/range/package.d
Normal file
18
source/tanya/range/package.d
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
/* 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 package contains generic function and templates to be used with D
|
||||||
|
* ranges.
|
||||||
|
*
|
||||||
|
* 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/range/package.d,
|
||||||
|
* tanya/range/package.d)
|
||||||
|
*/
|
||||||
|
module tanya.range;
|
||||||
|
|
||||||
|
public import tanya.range.array;
|
@ -12,10 +12,12 @@
|
|||||||
* 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;
|
||||||
|
|
||||||
import std.meta;
|
import tanya.meta.metafunction;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* $(D_PSYMBOL Pair) can store two heterogeneous objects.
|
* $(D_PSYMBOL Pair) can store two heterogeneous objects.
|
||||||
|
Reference in New Issue
Block a user