Initial import of libdpf.
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
commit
e4e666f459
4563 changed files with 1690372 additions and 0 deletions
29
thirdparty/portable-snippets/.appveyor.yml
vendored
Normal file
29
thirdparty/portable-snippets/.appveyor.yml
vendored
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
environment:
|
||||
matrix:
|
||||
- GENERATOR: Visual Studio 14 2015 Win64
|
||||
- GENERATOR: Visual Studio 14 2015
|
||||
- GENERATOR: Visual Studio 12 2013 Win64
|
||||
- GENERATOR: Visual Studio 11 2012
|
||||
- GENERATOR: Visual Studio 10 2010 Win64
|
||||
- GENERATOR: Visual Studio 9 2008
|
||||
|
||||
branches:
|
||||
except:
|
||||
- /^(wip\/)?(travis|osx|ipp)(\-.+)?$/
|
||||
- /^master$/
|
||||
|
||||
before_build:
|
||||
- ps: |
|
||||
git submodule -q update --init --recursive
|
||||
cd tests
|
||||
mkdir build
|
||||
cd build
|
||||
cmake -G "$env:GENERATOR" .. -DENABLE_AGGRESSIVE_WARNINGS=yes -DFATAL_WARNINGS=yes
|
||||
|
||||
build_script:
|
||||
- ps: |
|
||||
cmake --build . --config Debug
|
||||
|
||||
test_script:
|
||||
- ps: |
|
||||
ctest --output-on-failure --interactive-debug-mode 0 -C Debug -V
|
||||
3
thirdparty/portable-snippets/.gitignore
vendored
Normal file
3
thirdparty/portable-snippets/.gitignore
vendored
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
*~
|
||||
*#
|
||||
*.bak
|
||||
3
thirdparty/portable-snippets/.gitmodules
vendored
Normal file
3
thirdparty/portable-snippets/.gitmodules
vendored
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
[submodule "tests/munit"]
|
||||
path = tests/munit
|
||||
url = https://github.com/nemequ/munit.git
|
||||
193
thirdparty/portable-snippets/.travis.yml
vendored
Normal file
193
thirdparty/portable-snippets/.travis.yml
vendored
Normal file
|
|
@ -0,0 +1,193 @@
|
|||
language: c
|
||||
sudo: false
|
||||
branches:
|
||||
except:
|
||||
- /^(wip\/)?(appveyor|msvc|mingw|windows)(\-.+)?$/
|
||||
- /^master$/
|
||||
matrix:
|
||||
include:
|
||||
###
|
||||
## Linux builds using various versions of GCC.
|
||||
###
|
||||
- env: C_COMPILER=gcc-6
|
||||
addons:
|
||||
apt:
|
||||
sources:
|
||||
- ubuntu-toolchain-r-test
|
||||
- george-edison55-precise-backports
|
||||
packages:
|
||||
- gcc-6
|
||||
- g++-6
|
||||
- cmake
|
||||
- cmake-data
|
||||
- env: C_COMPILER=gcc-5
|
||||
addons:
|
||||
apt:
|
||||
sources:
|
||||
- ubuntu-toolchain-r-test
|
||||
- george-edison55-precise-backports
|
||||
packages:
|
||||
- gcc-5
|
||||
- g++-5
|
||||
- cmake
|
||||
- cmake-data
|
||||
# - env: C_COMPILER=gcc-4.9
|
||||
# addons:
|
||||
# apt:
|
||||
# sources:
|
||||
# - ubuntu-toolchain-r-test
|
||||
# - george-edison55-precise-backports
|
||||
# packages:
|
||||
# - gcc-4.9
|
||||
# - g++-4.9
|
||||
# - cmake
|
||||
# - cmake-data
|
||||
- env: C_COMPILER=gcc-4.8
|
||||
addons:
|
||||
apt:
|
||||
sources:
|
||||
- ubuntu-toolchain-r-test
|
||||
- george-edison55-precise-backports
|
||||
packages:
|
||||
- gcc-4.8
|
||||
- g++-4.8
|
||||
- cmake
|
||||
- cmake-data
|
||||
# - env: C_COMPILER=gcc-4.7
|
||||
# addons:
|
||||
# apt:
|
||||
# sources:
|
||||
# - ubuntu-toolchain-r-test
|
||||
# - george-edison55-precise-backports
|
||||
# packages:
|
||||
# - gcc-4.7
|
||||
# - g++-4.7
|
||||
# - cmake
|
||||
# - cmake-data
|
||||
- env: C_COMPILER=gcc-4.6
|
||||
addons:
|
||||
apt:
|
||||
sources:
|
||||
- ubuntu-toolchain-r-test
|
||||
- george-edison55-precise-backports
|
||||
packages:
|
||||
- gcc-4.6
|
||||
- g++-4.6
|
||||
- cmake
|
||||
- cmake-data
|
||||
# - os: linux
|
||||
# env: C_COMPILER=gcc-4.5
|
||||
# addons:
|
||||
# apt:
|
||||
# sources:
|
||||
# - ubuntu-toolchain-r-test
|
||||
# - george-edison55-precise-backports
|
||||
# packages:
|
||||
# - gcc-4.5
|
||||
# - g++-4.5
|
||||
# - cmake
|
||||
# - cmake-data
|
||||
- env: C_COMPILER=gcc-4.4
|
||||
addons:
|
||||
apt:
|
||||
sources:
|
||||
- ubuntu-toolchain-r-test
|
||||
- george-edison55-precise-backports
|
||||
packages:
|
||||
- gcc-4.4
|
||||
- g++-4.4
|
||||
- cmake
|
||||
- cmake-data
|
||||
|
||||
###
|
||||
## clang on Linux
|
||||
###
|
||||
- env: C_COMPILER=clang-3.9
|
||||
addons:
|
||||
apt:
|
||||
sources:
|
||||
- llvm-toolchain-precise-3.9
|
||||
- ubuntu-toolchain-r-test
|
||||
- george-edison55-precise-backports
|
||||
packages:
|
||||
- clang-3.9
|
||||
- cmake
|
||||
- cmake-data
|
||||
# - env: C_COMPILER=clang-3.8
|
||||
# addons:
|
||||
# apt:
|
||||
# sources:
|
||||
# - llvm-toolchain-precise-3.8
|
||||
# - ubuntu-toolchain-r-test
|
||||
# - george-edison55-precise-backports
|
||||
# packages:
|
||||
# - clang-3.8
|
||||
# - cmake
|
||||
# - cmake-data
|
||||
- env: C_COMPILER=clang-3.7
|
||||
addons:
|
||||
apt:
|
||||
sources:
|
||||
- llvm-toolchain-precise-3.7
|
||||
- ubuntu-toolchain-r-test
|
||||
- george-edison55-precise-backports
|
||||
packages:
|
||||
- clang-3.7
|
||||
- cmake
|
||||
- cmake-data
|
||||
# - env: C_COMPILER=clang-3.6
|
||||
# addons:
|
||||
# apt:
|
||||
# sources:
|
||||
# - llvm-toolchain-precise-3.6
|
||||
# - ubuntu-toolchain-r-test
|
||||
# - george-edison55-precise-backports
|
||||
# packages:
|
||||
# - clang-3.6
|
||||
# - cmake
|
||||
# - cmake-data
|
||||
- env: C_COMPILER=clang-3.5
|
||||
addons:
|
||||
apt:
|
||||
sources:
|
||||
- llvm-toolchain-precise-3.5
|
||||
- ubuntu-toolchain-r-test
|
||||
- george-edison55-precise-backports
|
||||
packages:
|
||||
- clang-3.5
|
||||
- cmake
|
||||
- cmake-data
|
||||
|
||||
###
|
||||
## PGI
|
||||
###
|
||||
- env: C_COMPILER=pgcc ENABLE_OPENMP=y
|
||||
addons:
|
||||
apt:
|
||||
sources:
|
||||
- george-edison55-precise-backports
|
||||
packages:
|
||||
- cmake
|
||||
- cmake-data
|
||||
|
||||
###
|
||||
## OS X
|
||||
###
|
||||
# - os: osx
|
||||
|
||||
before_install:
|
||||
###
|
||||
## If we use the matrix to set CC/CXX Travis, overwrites the values,
|
||||
## so instead we use C/CXX_COMPILER, then copy the values to CC/CXX
|
||||
## here (after Travis has set CC/CXX).
|
||||
###
|
||||
- if [ "${C_COMPILER}" = "pgcc" ]; then wget -q -O /dev/stdout 'https://raw.githubusercontent.com/nemequ/pgi-travis/master/install-pgi.sh' | /bin/sh; fi
|
||||
- if [ -n "${C_COMPILER}" ]; then export CC="${C_COMPILER}"; fi
|
||||
- mkdir tests/build
|
||||
- cd tests/build
|
||||
|
||||
script:
|
||||
- cmake --version
|
||||
- cmake .. -DCMAKE_C_COMPILER="${C_COMPILER}" -DCMAKE_C_FLAGS="${CFLAGS}" -DENABLE_OPENMP="${ENABLE_OPENMP}" -DENABLE_AGGRESSIVE_WARNINGS=yes -DFATAL_WARNINGS=yes
|
||||
- make VERBOSE=1
|
||||
- ctest -V
|
||||
124
thirdparty/portable-snippets/COPYING.md
vendored
Normal file
124
thirdparty/portable-snippets/COPYING.md
vendored
Normal file
|
|
@ -0,0 +1,124 @@
|
|||
Each source file contains a preamble explaining the license situation
|
||||
for that file, which takes priority over this file. With the
|
||||
exception of some code pulled in from other repositories (such as
|
||||
µnit, an MIT-licensed project which is used for testing), the code is
|
||||
public domain, released using the CC0 1.0 Universal dedication, which
|
||||
is reproduced below:
|
||||
|
||||
# CC0 1.0 Universal Public Domain Dedication
|
||||
|
||||
The laws of most jurisdictions throughout the world automatically
|
||||
confer exclusive Copyright and Related Rights (defined below) upon the
|
||||
creator and subsequent owner(s) (each and all, an "owner") of an
|
||||
original work of authorship and/or a database (each, a "Work").
|
||||
|
||||
Certain owners wish to permanently relinquish those rights to a Work
|
||||
for the purpose of contributing to a commons of creative, cultural and
|
||||
scientific works ("Commons") that the public can reliably and without
|
||||
fear of later claims of infringement build upon, modify, incorporate
|
||||
in other works, reuse and redistribute as freely as possible in any
|
||||
form whatsoever and for any purposes, including without limitation
|
||||
commercial purposes. These owners may contribute to the Commons to
|
||||
promote the ideal of a free culture and the further production of
|
||||
creative, cultural and scientific works, or to gain reputation or
|
||||
greater distribution for their Work in part through the use and
|
||||
efforts of others.
|
||||
|
||||
For these and/or other purposes and motivations, and without any
|
||||
expectation of additional consideration or compensation, the person
|
||||
associating CC0 with a Work (the "Affirmer"), to the extent that he or
|
||||
she is an owner of Copyright and Related Rights in the Work,
|
||||
voluntarily elects to apply CC0 to the Work and publicly distribute
|
||||
the Work under its terms, with knowledge of his or her Copyright and
|
||||
Related Rights in the Work and the meaning and intended legal effect
|
||||
of CC0 on those rights.
|
||||
|
||||
1. **Copyright and Related Rights**. A Work made available under CC0
|
||||
may be protected by copyright and related or neighboring rights
|
||||
("Copyright and Related Rights"). Copyright and Related Rights
|
||||
include, but are not limited to, the following:
|
||||
|
||||
i. the right to reproduce, adapt, distribute, perform, display,
|
||||
communicate, and translate a Work;
|
||||
ii. moral rights retained by the original author(s) and/or
|
||||
performer(s);
|
||||
iii. publicity and privacy rights pertaining to a person's image or
|
||||
likeness depicted in a Work;
|
||||
iv. rights protecting against unfair competition in regards to a
|
||||
Work, subject to the limitations in paragraph 4(a), below;
|
||||
v. rights protecting the extraction, dissemination, use and reuse
|
||||
of data in a Work;
|
||||
vi. database rights (such as those arising under Directive 96/9/EC
|
||||
of the European Parliament and of the Council of 11 March 1996
|
||||
on the legal protection of databases, and under any national
|
||||
implementation thereof, including any amended or successor
|
||||
version of such directive); and
|
||||
vii. other similar, equivalent or corresponding rights throughout
|
||||
the world based on applicable law or treaty, and any national
|
||||
implementations thereof.
|
||||
|
||||
2. **Waiver**. To the greatest extent permitted by, but not in
|
||||
contravention of, applicable law, Affirmer hereby overtly, fully,
|
||||
permanently, irrevocably and unconditionally waives, abandons, and
|
||||
surrenders all of Affirmer's Copyright and Related Rights and
|
||||
associated claims and causes of action, whether now known or
|
||||
unknown (including existing as well as future claims and causes of
|
||||
action), in the Work (i) in all territories worldwide, (ii) for the
|
||||
maximum duration provided by applicable law or treaty (including
|
||||
future time extensions), (iii) in any current or future medium and
|
||||
for any number of copies, and (iv) for any purpose whatsoever,
|
||||
including without limitation commercial, advertising or promotional
|
||||
purposes (the "Waiver"). Affirmer makes the Waiver for the benefit
|
||||
of each member of the public at large and to the detriment of
|
||||
Affirmer's heirs and successors, fully intending that such Waiver
|
||||
shall not be subject to revocation, rescission, cancellation,
|
||||
termination, or any other legal or equitable action to disrupt the
|
||||
quiet enjoyment of the Work by the public as contemplated by
|
||||
Affirmer's express Statement of Purpose.
|
||||
|
||||
3. **Public License Fallback**. Should any part of the Waiver for any
|
||||
reason be judged legally invalid or ineffective under applicable
|
||||
law, then the Waiver shall be preserved to the maximum extent
|
||||
permitted taking into account Affirmer's express Statement of
|
||||
Purpose. In addition, to the extent the Waiver is so judged
|
||||
Affirmer hereby grants to each affected person a royalty-free, non
|
||||
transferable, non sublicensable, non exclusive, irrevocable and
|
||||
unconditional license to exercise Affirmer's Copyright and Related
|
||||
Rights in the Work (i) in all territories worldwide, (ii) for the
|
||||
maximum duration provided by applicable law or treaty (including
|
||||
future time extensions), (iii) in any current or future medium and
|
||||
for any number of copies, and (iv) for any purpose whatsoever,
|
||||
including without limitation commercial, advertising or promotional
|
||||
purposes (the "License"). The License shall be deemed effective as
|
||||
of the date CC0 was applied by Affirmer to the Work. Should any
|
||||
part of the License for any reason be judged legally invalid or
|
||||
ineffective under applicable law, such partial invalidity or
|
||||
ineffectiveness shall not invalidate the remainder of the License,
|
||||
and in such case Affirmer hereby affirms that he or she will not
|
||||
(i) exercise any of his or her remaining Copyright and Related
|
||||
Rights in the Work or (ii) assert any associated claims and causes
|
||||
of action with respect to the Work, in either case contrary to
|
||||
Affirmer's express Statement of Purpose.
|
||||
|
||||
4. **Limitations and Disclaimers**.
|
||||
|
||||
a. No trademark or patent rights held by Affirmer are waived,
|
||||
abandoned, surrendered, licensed or otherwise affected by this
|
||||
document.
|
||||
b. Affirmer offers the Work as-is and makes no representations or
|
||||
warranties of any kind concerning the Work, express, implied,
|
||||
statutory or otherwise, including without limitation warranties
|
||||
of title, merchantability, fitness for a particular purpose, non
|
||||
infringement, or the absence of latent or other defects,
|
||||
accuracy, or the present or absence of errors, whether or not
|
||||
discoverable, all to the greatest extent permissible under
|
||||
applicable law.
|
||||
c. Affirmer disclaims responsibility for clearing rights of other
|
||||
persons that may apply to the Work or any use thereof, including
|
||||
without limitation any person's Copyright and Related Rights in
|
||||
the Work. Further, Affirmer disclaims responsibility for
|
||||
obtaining any necessary consents, permissions or other rights
|
||||
required for any use of the Work.
|
||||
d. Affirmer understands and acknowledges that Creative Commons is
|
||||
not a party to this document and has no duty or obligation with
|
||||
respect to this CC0 or use of the Work.
|
||||
83
thirdparty/portable-snippets/README.md
vendored
Normal file
83
thirdparty/portable-snippets/README.md
vendored
Normal file
|
|
@ -0,0 +1,83 @@
|
|||
# Portable Snippets
|
||||
|
||||
This is a collection of public domain (CC0) code snippets written in C
|
||||
for performing various common tasks which are typically OS,
|
||||
architecture, and/or compiler-dependent. Basically, our goal is to
|
||||
move those annoying preprocessor conditionals from your code to ours.
|
||||
|
||||
Modules have no fixed target (such as C89) since that would preclude
|
||||
some functionality; instead, we simply try to provide the widest
|
||||
support we can for each module. If you have a platform which isn't
|
||||
supported for a particular feature but could be, please let us know;
|
||||
we'd be happy to try to work out a way to support it.
|
||||
|
||||
Everything is tested continuously with various versions of GCC, Clang,
|
||||
and PGI ([on Travis
|
||||
CI](https://travis-ci.org/nemequ/portable-snippets)), MSVC ([on
|
||||
AppVeyor](https://ci.appveyor.com/project/quixdb/portable-snippets)),
|
||||
and Emscripten (on
|
||||
[Codefresh](https://g.codefresh.io/repositories/nemequ/portable-snippets/builds?filter=trigger:build;branch:master;service:591f783d728f4b0001051d3e~portable-snippets)):
|
||||
|
||||
[](https://travis-ci.org/nemequ/portable-snippets) [](https://ci.appveyor.com/project/quixdb/portable-snippets/branch/master) [](https://g.codefresh.io/repositories/nemequ/portable-snippets/builds?filter=trigger:build;branch:master;service:591f783d728f4b0001051d3e~portable-snippets)
|
||||
|
||||
Currently ready-to-use modules include:
|
||||
|
||||
* [builtin](https://github.com/nemequ/portable-snippets/tree/master/builtin) —
|
||||
use compiler built-ins/intrinsics, or fall back on standard C
|
||||
* [endian](https://github.com/nemequ/portable-snippets/tree/master/endian) —
|
||||
endianness detection and swapping
|
||||
* [atomic](https://github.com/nemequ/portable-snippets/tree/master/atomic) —
|
||||
common atomic synchronization operations
|
||||
* [safe-math](https://github.com/nemequ/portable-snippets/tree/master/safe-math) —
|
||||
overflow-safe integer functions
|
||||
* [exact-int](https://github.com/nemequ/portable-snippets/tree/master/exact-int) —
|
||||
exact-width integer types (think `<stdint.h>`)
|
||||
* [clock](https://github.com/nemequ/portable-snippets/tree/master/clock) —
|
||||
cross-platform wall clock, CPU time, and monotonic time
|
||||
|
||||
There are also modules which may not yet be ready for widespread use, but
|
||||
would benefit greatly from testing:
|
||||
|
||||
* [unaligned](https://github.com/nemequ/portable-snippets/tree/master/unaligned) —
|
||||
fast unaligned loads & stores
|
||||
* [once](https://github.com/nemequ/portable-snippets/tree/master/once) —
|
||||
one-time initialization
|
||||
* [random](https://github.com/nemequ/portable-snippets/tree/master/random) —
|
||||
random number generation (3 flavors: cryptographic, reproducible, and fast)
|
||||
* [debug-trap](https://github.com/nemequ/portable-snippets/tree/master/debug-trap) —
|
||||
debugging traps and assertions
|
||||
* [check](https://github.com/nemequ/portable-snippets/tree/master/check) —
|
||||
assertion checking
|
||||
|
||||
Modules can be used in isolation, though some do work better together,
|
||||
so if you can keep the whole repository together instead of just
|
||||
copying a single file we recommend you do so.
|
||||
|
||||
Please don't be shy about filing issues about any of these; if you
|
||||
have problems it's likely others will, as well, so we would like to
|
||||
fix them.
|
||||
|
||||
If you have something you would like to contribute, please file an
|
||||
issue or pull request. If you'd like to help out by writing something
|
||||
new, take a look at the ["enhancement"
|
||||
issues](https://github.com/nemequ/portable-snippets/issues?q=is%3Aissue+is%3Aopen+label%3Aenhancement)
|
||||
in our issue tracker for ideas.
|
||||
|
||||
Some things don't really fit this repository, so here are a few
|
||||
small-ish projects for doing things portably which you may be
|
||||
interested in:
|
||||
|
||||
* [Hedley](https://nemequ.github.io/hedley/) — macros to enable
|
||||
compiler-specific features which make your code easier to use,
|
||||
harder to misuse, safer, faster, and more portable.
|
||||
* [parg](https://github.com/jibsen/parg) —
|
||||
Argument parsing similar to getopt/getopt_long. Public domain.
|
||||
* [TinyCThread](https://tinycthread.github.io/) — Implements the C11
|
||||
threads API on top of pthreads and the Windows API. zlib license.
|
||||
* [win-iconv](https://github.com/win-iconv/win-iconv) — Windows
|
||||
implementation of the iconv API (character set conversion).
|
||||
* [mman-win32](https://github.com/witwall/mman-win32) — `mman.h`
|
||||
(`mmap()`, *etc.*) implementation for Windows.
|
||||
|
||||
If there is a project you'd like to see added to the list, please file
|
||||
an issue or pull request.
|
||||
60
thirdparty/portable-snippets/atomic/README.md
vendored
Normal file
60
thirdparty/portable-snippets/atomic/README.md
vendored
Normal file
|
|
@ -0,0 +1,60 @@
|
|||
# Atomic Operations
|
||||
|
||||
This header provides atomic operations in a way which is portable to
|
||||
most platforms. Current back-ends include:
|
||||
|
||||
* C11
|
||||
* GCC-style __atomic_* builtins
|
||||
* Old-style GCC sync_* builtins
|
||||
* clang-style __c11_atomic_* builtins
|
||||
* MSVC-style Interlocked* intrinsics
|
||||
* OpenMP (using critical sections; there is no atomic CAS)
|
||||
|
||||
This is sufficient to support most modern, actively developed
|
||||
compilers. [PGI C/C++ Compiler](http://www.pgroup.com/), which
|
||||
[doesn't currently support
|
||||
atomics](http://www.pgroup.com/userforum/viewtopic.php?t=5504) but
|
||||
hopefully will soon, in the meantime you can use the OpenMP backend
|
||||
(just pass `-mp` to the compiler).
|
||||
|
||||
Most things are implemented with the preprocessor, but if they were
|
||||
functions the prototypes (the 64-bit versions, just s/64/32/ for the
|
||||
32-bit versions) would loo like:
|
||||
|
||||
```c
|
||||
psnip_int64_t psnip_atomic_int64_load(
|
||||
psnip_atomic_int64* object);
|
||||
|
||||
void psnip_atomic_int64_store(
|
||||
psnip_atomic_int64* object,
|
||||
psnip_int64_t desired);
|
||||
|
||||
_Bool psnip_atomic_int64_compare_exchange(
|
||||
psnip_atomic_int64* object,
|
||||
psnip_int64_t* expected,
|
||||
psnip_int64_t desired);
|
||||
|
||||
psnip_nonatomic_int64 psnip_atomic_int64_add(
|
||||
psnip_atomic_int64* object,
|
||||
psnip_int64_t operand);
|
||||
|
||||
psnip_nonatomic_int64 psnip_atomic_int64_sub(
|
||||
psnip_atomic_int64* object,
|
||||
psnip_int64_t operand);
|
||||
```
|
||||
|
||||
If no atomics are supported, `PSNIP_ATOMIC_NOT_FOUND` will be defined;
|
||||
you'll probably have to use locks (if you want a portable API for that
|
||||
you may be interested in
|
||||
[TinyCThread](https://github.com/tinycthread/tinycthread/)), or you
|
||||
could try the [atomic_ops](https://github.com/ivmai/libatomic_ops/)
|
||||
package.
|
||||
|
||||
## Dependencies
|
||||
|
||||
To maximize portability you should #include the exact-int module
|
||||
before including atomic.h, but if you don't want to add the extra
|
||||
file to your project you can omit it and this module will simply rely
|
||||
on <stdint.h>. As an alternative you may define `psnip_int32_t`, and
|
||||
`psnip_int64_t` to appropriate values yourself before including
|
||||
atomic.h.
|
||||
419
thirdparty/portable-snippets/atomic/atomic.h
vendored
Normal file
419
thirdparty/portable-snippets/atomic/atomic.h
vendored
Normal file
|
|
@ -0,0 +1,419 @@
|
|||
/* Atomic operations (v1)
|
||||
* Portable Snippets - https://github.com/nemequ/portable-snippets
|
||||
* Created by Evan Nemerson <evan@nemerson.com>
|
||||
*
|
||||
* To the extent possible under law, the authors have waived all
|
||||
* copyright and related or neighboring rights to this code. For
|
||||
* details, see the Creative Commons Zero 1.0 Universal license at
|
||||
* https://creativecommons.org/publicdomain/zero/1.0/
|
||||
*
|
||||
* This is a small abstraction layer for some common atomic operations
|
||||
* (load, store, add, subtract, and compare & swap) implemented using
|
||||
* various compiler-specific builtins.
|
||||
*
|
||||
* There are four types, 32-bit and 64-bit integers which are both
|
||||
* atomic and non-atomic. The atomic versions should be used for the
|
||||
* atomic variable, the non-atomic variables should be used to store
|
||||
* values read from or written to an atomic variable. For example, a
|
||||
* basic CAS loop:
|
||||
*
|
||||
* void square_dest(psnip_atomic_int64* value) {
|
||||
* psnip_int64_t expected;
|
||||
* do {
|
||||
* expected = psnip_atomic_int64_load(&value);
|
||||
* } while (!psnip_atomic_int64_compare_exchange(&value, &expected, expected * expected));
|
||||
* }
|
||||
*
|
||||
* Most things are implemented with the preprocessor, but if they were
|
||||
* functions the prototypes (the 64-bit versions, just s/64/32/ for
|
||||
* the 32-bit versions) would loo like:
|
||||
*
|
||||
* psnip_int64_t psnip_atomic_int64_load(
|
||||
* psnip_atomic_int64* object);
|
||||
* void psnip_atomic_int64_store(
|
||||
* psnip_atomic_int64* object,
|
||||
* psnip_int64_t desired);
|
||||
* _Bool psnip_atomic_int64_compare_exchange(
|
||||
* psnip_atomic_int64* object,
|
||||
* psnip_int64_t* expected,
|
||||
* psnip_int64_t desired);
|
||||
* psnip_int64_t psnip_atomic_int64_add(
|
||||
* psnip_atomic_int64* object,
|
||||
* psnip_int64_t operand);
|
||||
* psnip_int64_t psnip_atomic_int64_sub(
|
||||
* psnip_atomic_int64* object,
|
||||
* psnip_int64_t operand);
|
||||
*/
|
||||
|
||||
#if !defined(PSNIP_ATOMIC_H)
|
||||
#define PSNIP_ATOMIC_H
|
||||
|
||||
/* For maximum portability include the exact-int module from
|
||||
portable snippets. */
|
||||
#if \
|
||||
!defined(psnip_int64_t) || \
|
||||
!defined(psnip_int32_t)
|
||||
# include <stdint.h>
|
||||
# if !defined(psnip_int64_t)
|
||||
# define psnip_int64_t int64_t
|
||||
# endif
|
||||
# if !defined(psnip_int32_t)
|
||||
# define psnip_int32_t int32_t
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#if !defined(PSNIP_ATOMIC_STATIC_INLINE)
|
||||
# if defined(__GNUC__)
|
||||
# define PSNIP_ATOMIC__COMPILER_ATTRIBUTES __attribute__((__unused__))
|
||||
# else
|
||||
# define PSNIP_ATOMIC__COMPILER_ATTRIBUTES
|
||||
# endif
|
||||
|
||||
# if defined(HEDLEY_INLINE)
|
||||
# define PSNIP_ATOMIC__INLINE HEDLEY_INLINE
|
||||
# elif defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L
|
||||
# define PSNIP_ATOMIC__INLINE inline
|
||||
# elif defined(__GNUC_STDC_INLINE__)
|
||||
# define PSNIP_ATOMIC__INLINE __inline__
|
||||
# elif defined(_MSC_VER) && _MSC_VER >= 1200
|
||||
# define PSNIP_ATOMIC__INLINE __inline
|
||||
# else
|
||||
# define PSNIP_ATOMIC__INLINE
|
||||
# endif
|
||||
|
||||
# define PSNIP_ATOMIC__FUNCTION PSNIP_ATOMIC__COMPILER_ATTRIBUTES static PSNIP_ATOMIC__INLINE
|
||||
#endif
|
||||
|
||||
#if defined(__has_feature)
|
||||
# define PSNIP_ATOMIC_HAS_FEATURE(feature) __has_feature(feature)
|
||||
#else
|
||||
# define PSNIP_ATOMIC_HAS_FEATURE(feature) 0
|
||||
#endif
|
||||
|
||||
#define PSNIP_ATOMIC_IMPL_NONE 0
|
||||
#define PSNIP_ATOMIC_IMPL_GCC 1
|
||||
#define PSNIP_ATOMIC_IMPL_GCC_SYNC 2
|
||||
#define PSNIP_ATOMIC_IMPL_CLANG 3
|
||||
#define PSNIP_ATOMIC_IMPL_MS 4
|
||||
#define PSNIP_ATOMIC_IMPL_OPENMP 5
|
||||
#define PSNIP_ATOMIC_IMPL_C11 11
|
||||
|
||||
#if defined(__GNUC__) && ((__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 7))
|
||||
# define PSNIP_ATOMIC_IMPL PSNIP_ATOMIC_IMPL_GCC
|
||||
#elif !defined(__INTEL_COMPILER) && defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L) && !defined(__STDC_NO_ATOMICS__)
|
||||
/* GCC 4.7 and 4.8 sets __STDC_VERSION__ to C11 (if compiling in C11
|
||||
* mode) and didn't have stdatomic.h, but failed to set
|
||||
* __STDC_NO_ATOMICS__. Verions prior to 4.7 didn't set
|
||||
* __STDC_VERSION__ to C11. */
|
||||
# if defined(__GNUC__) && (__GNUC__ == 4) && (__GNUC_MINOR__ < 9)
|
||||
# define PSNIP_ATOMIC_IMPL PSNIP_ATOMIC_IMPL_GCC
|
||||
# else
|
||||
# define PSNIP_ATOMIC_IMPL PSNIP_ATOMIC_IMPL_C11
|
||||
# endif
|
||||
#elif defined(_MSC_VER)
|
||||
# define PSNIP_ATOMIC_IMPL PSNIP_ATOMIC_IMPL_MS
|
||||
#elif defined(__GNUC__) && ((__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 7))
|
||||
# define PSNIP_ATOMIC_IMPL PSNIP_ATOMIC_IMPL_GCC
|
||||
#elif PSNIP_ATOMIC_HAS_FEATURE(c_atomic)
|
||||
# define PSNIP_ATOMIC_IMPL PSNIP_ATOMIC_IMPL_CLANG
|
||||
#elif defined(__GNUC__) && ((__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 1))
|
||||
# define PSNIP_ATOMIC_IMPL PSNIP_ATOMIC_IMPL_GCC_SYNC
|
||||
#elif (defined(__SUNPRO_C) && (__SUNPRO_C >= 0x5140)) || (defined(__SUNPRO_CC) && (__SUNPRO_CC >= 0x5140))
|
||||
# define PSNIP_ATOMIC_IMPL PSNIP_ATOMIC_IMPL_GCC
|
||||
#elif defined(_OPENMP)
|
||||
# define PSNIP_ATOMIC_IMPL PSNIP_ATOMIC_IMPL_OPENMP
|
||||
#else
|
||||
# define PSNIP_ATOMIC_NOT_FOUND
|
||||
# define PSNIP_ATOMIC_IMPL PSNIP_ATOMIC_IMPL_NONE
|
||||
# warning No atomic implementation found
|
||||
#endif
|
||||
|
||||
#if !defined(PSNIP_ATOMIC_NOT_FOUND)
|
||||
|
||||
#if PSNIP_ATOMIC_IMPL == PSNIP_ATOMIC_IMPL_C11
|
||||
|
||||
#include <stdatomic.h>
|
||||
typedef atomic_int_fast64_t psnip_atomic_int64;
|
||||
typedef atomic_int_fast32_t psnip_atomic_int32;
|
||||
|
||||
#define PSNIP_ATOMIC_VAR_INIT(value) ATOMIC_VAR_INIT(value)
|
||||
|
||||
#define psnip_atomic_int64_load(object) \
|
||||
atomic_load(object)
|
||||
#define psnip_atomic_int64_store(object, desired) \
|
||||
atomic_store(object, desired)
|
||||
#define psnip_atomic_int64_compare_exchange(object, expected, desired) \
|
||||
atomic_compare_exchange_strong(object, expected, desired)
|
||||
#define psnip_atomic_int64_add(object, operand) \
|
||||
atomic_fetch_add(object, operand)
|
||||
#define psnip_atomic_int64_sub(object, operand) \
|
||||
atomic_fetch_sub(object, operand)
|
||||
#define psnip_atomic_fence() \
|
||||
atomic_thread_fence(memory_order_seq_cst)
|
||||
|
||||
#define PSNIP_ATOMIC_IS_TG
|
||||
|
||||
#elif PSNIP_ATOMIC_IMPL == PSNIP_ATOMIC_IMPL_CLANG
|
||||
|
||||
#include <stdint.h>
|
||||
typedef _Atomic psnip_int64_t psnip_atomic_int64;
|
||||
typedef _Atomic psnip_int32_t psnip_atomic_int32;
|
||||
|
||||
#define psnip_atomic_int64_load(object) \
|
||||
__c11_atomic_load(object, __ATOMIC_SEQ_CST)
|
||||
#define psnip_atomic_int64_store(object, desired) \
|
||||
__c11_atomic_store(object, desired, __ATOMIC_SEQ_CST)
|
||||
#define psnip_atomic_int64_compare_exchange(object, expected, desired) \
|
||||
__c11_atomic_compare_exchange_strong(object, expected, desired, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST)
|
||||
#define psnip_atomic_int64_add(object, operand) \
|
||||
__c11_atomic_fetch_add(object, operand, __ATOMIC_SEQ_CST)
|
||||
#define psnip_atomic_int64_sub(object, operand) \
|
||||
__c11_atomic_fetch_sub(object, operand, __ATOMIC_SEQ_CST)
|
||||
#define psnip_atomic_fence() \
|
||||
__c11_atomic_thread_fence(__ATOMIC_SEQ_CST)
|
||||
|
||||
#define PSNIP_ATOMIC_IS_TG
|
||||
|
||||
#elif PSNIP_ATOMIC_IMPL == PSNIP_ATOMIC_IMPL_GCC
|
||||
|
||||
#include <stdint.h>
|
||||
#if !defined(__INTEL_COMPILER) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 9)) && !defined(_OPENMP)
|
||||
typedef _Atomic psnip_int64_t psnip_atomic_int64;
|
||||
typedef _Atomic psnip_int32_t psnip_atomic_int32;
|
||||
#else
|
||||
typedef psnip_int64_t psnip_atomic_int64;
|
||||
typedef psnip_int32_t psnip_atomic_int32;
|
||||
#endif
|
||||
|
||||
#define psnip_atomic_int64_load(object) \
|
||||
__atomic_load_n(object, __ATOMIC_SEQ_CST)
|
||||
#define psnip_atomic_int64_store(object, desired) \
|
||||
__atomic_store_n(object, desired, __ATOMIC_SEQ_CST)
|
||||
#define psnip_atomic_int64_compare_exchange(object, expected, desired) \
|
||||
__atomic_compare_exchange_n(object, expected, desired, 0, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST)
|
||||
#define psnip_atomic_int64_add(object, operand) \
|
||||
__atomic_add_fetch(object, operand, __ATOMIC_SEQ_CST)
|
||||
#define psnip_atomic_int64_sub(object, operand) \
|
||||
__atomic_sub_fetch(object, operand, __ATOMIC_SEQ_CST)
|
||||
#define psnip_atomic_fence() \
|
||||
__atomic_thread_fence(__ATOMIC_SEQ_CST)
|
||||
|
||||
#define PSNIP_ATOMIC_IS_TG
|
||||
|
||||
#elif PSNIP_ATOMIC_IMPL == PSNIP_ATOMIC_IMPL_GCC_SYNC
|
||||
|
||||
#include <stdint.h>
|
||||
typedef psnip_int64_t psnip_atomic_int64;
|
||||
typedef psnip_int32_t psnip_atomic_int32;
|
||||
|
||||
PSNIP_ATOMIC__FUNCTION
|
||||
psnip_int64_t
|
||||
psnip_atomic_int64_load(psnip_atomic_int64* object) {
|
||||
__sync_synchronize();
|
||||
return (psnip_int64_t) *object;
|
||||
}
|
||||
|
||||
PSNIP_ATOMIC__FUNCTION
|
||||
void
|
||||
psnip_atomic_int64_store(psnip_atomic_int64* object, psnip_int64_t desired) {
|
||||
*object = desired;
|
||||
__sync_synchronize();
|
||||
}
|
||||
|
||||
#define psnip_atomic_int64_compare_exchange(object, expected, desired) \
|
||||
__sync_bool_compare_and_swap(object, *(expected), desired)
|
||||
#define psnip_atomic_int64_add(object, operand) \
|
||||
__sync_fetch_and_add(object, operand)
|
||||
#define psnip_atomic_int64_sub(object, operand) \
|
||||
__sync_fetch_and_sub(object, operand)
|
||||
|
||||
PSNIP_ATOMIC__FUNCTION
|
||||
psnip_int32_t
|
||||
psnip_atomic_int32_load(psnip_atomic_int32* object) {
|
||||
__sync_synchronize();
|
||||
return (psnip_int32_t) *object;
|
||||
}
|
||||
|
||||
PSNIP_ATOMIC__FUNCTION
|
||||
void
|
||||
psnip_atomic_int32_store(psnip_atomic_int32* object, psnip_int32_t desired) {
|
||||
*object = desired;
|
||||
__sync_synchronize();
|
||||
}
|
||||
|
||||
#define psnip_atomic_int32_compare_exchange(object, expected, desired) \
|
||||
__sync_bool_compare_and_swap(object, *(expected), desired)
|
||||
#define psnip_atomic_int32_add(object, operand) \
|
||||
__sync_fetch_and_add(object, operand)
|
||||
#define psnip_atomic_int32_sub(object, operand) \
|
||||
__sync_fetch_and_sub(object, operand)
|
||||
|
||||
#define psnip_atomic_fence() \
|
||||
__sync_synchronize()
|
||||
|
||||
#elif PSNIP_ATOMIC_IMPL == PSNIP_ATOMIC_IMPL_MS
|
||||
|
||||
#include <Windows.h>
|
||||
|
||||
typedef long long volatile psnip_atomic_int64;
|
||||
typedef long volatile psnip_atomic_int32;
|
||||
|
||||
#define psnip_atomic_int32_load(object) \
|
||||
__pragma(warning(push)) \
|
||||
__pragma(warning(disable:28112)) \
|
||||
(*(object)) \
|
||||
__pragma(warning(pop))
|
||||
#define psnip_atomic_int32_store(object, desired) \
|
||||
InterlockedExchange(object, desired)
|
||||
#define psnip_atomic_int32_compare_exchange(object, expected, desired) \
|
||||
InterlockedCompareExchange(object, desired, *(expected))
|
||||
#define psnip_atomic_int32_add(object, operand) \
|
||||
InterlockedExchangeAdd(object, operand)
|
||||
#define psnip_atomic_int32_sub(object, operand) \
|
||||
InterlockedExchangeAdd(object, -(operand))
|
||||
|
||||
#define psnip_atomic_int64_load(object) \
|
||||
__pragma(warning(push)) \
|
||||
__pragma(warning(disable:28112)) \
|
||||
(*(object)) \
|
||||
__pragma(warning(pop))
|
||||
#define psnip_atomic_int64_store(object, desired) \
|
||||
InterlockedExchange64(object, desired)
|
||||
#define psnip_atomic_int64_compare_exchange(object, expected, desired) \
|
||||
InterlockedCompareExchange64(object, desired, *(expected))
|
||||
#define psnip_atomic_int64_add(object, operand) \
|
||||
InterlockedExchangeAdd64(object, operand)
|
||||
#define psnip_atomic_int64_sub(object, operand) \
|
||||
InterlockedExchangeAdd64(object, -(operand))
|
||||
|
||||
#define psnip_atomic_fence() \
|
||||
MemoryBarrier()
|
||||
|
||||
#elif PSNIP_ATOMIC_IMPL == PSNIP_ATOMIC_IMPL_OPENMP
|
||||
|
||||
#include <stdint.h>
|
||||
typedef psnip_int64_t psnip_atomic_int64;
|
||||
typedef psnip_int32_t psnip_atomic_int32;
|
||||
|
||||
PSNIP_ATOMIC__FUNCTION
|
||||
psnip_int64_t
|
||||
psnip_atomic_int64_load(psnip_atomic_int64* object) {
|
||||
psnip_int64_t ret;
|
||||
#pragma omp critical(psnip_atomic)
|
||||
ret = *object;
|
||||
return ret;
|
||||
}
|
||||
|
||||
PSNIP_ATOMIC__FUNCTION
|
||||
void
|
||||
psnip_atomic_int64_store(psnip_atomic_int64* object, psnip_int64_t desired) {
|
||||
#pragma omp critical(psnip_atomic)
|
||||
*object = desired;
|
||||
}
|
||||
|
||||
PSNIP_ATOMIC__FUNCTION
|
||||
int
|
||||
psnip_atomic_int64_compare_exchange_(psnip_atomic_int64* object, psnip_int64_t* expected, psnip_int64_t desired) {
|
||||
int ret;
|
||||
#pragma omp critical(psnip_atomic)
|
||||
ret = (*object == *expected) ? ((*object = desired), 1) : 0;
|
||||
return ret;
|
||||
}
|
||||
|
||||
#define psnip_atomic_int64_compare_exchange(object, expected, desired) \
|
||||
psnip_atomic_int64_compare_exchange_(object, expected, desired)
|
||||
|
||||
PSNIP_ATOMIC__FUNCTION
|
||||
psnip_int64_t
|
||||
psnip_atomic_int64_add(psnip_atomic_int64* object, psnip_int64_t operand) {
|
||||
int ret;
|
||||
#pragma omp critical(psnip_atomic)
|
||||
*object = (ret = *object) + operand;
|
||||
return ret;
|
||||
}
|
||||
|
||||
PSNIP_ATOMIC__FUNCTION
|
||||
psnip_int64_t
|
||||
psnip_atomic_int64_sub(psnip_atomic_int64* object, psnip_int64_t operand) {
|
||||
int ret;
|
||||
#pragma omp critical(psnip_atomic)
|
||||
*object = (ret = *object) - operand;
|
||||
return ret;
|
||||
}
|
||||
PSNIP_ATOMIC__FUNCTION
|
||||
psnip_int32_t
|
||||
psnip_atomic_int32_load(psnip_atomic_int32* object) {
|
||||
psnip_int32_t ret;
|
||||
#pragma omp critical(psnip_atomic)
|
||||
ret = *object;
|
||||
return ret;
|
||||
}
|
||||
|
||||
PSNIP_ATOMIC__FUNCTION
|
||||
void
|
||||
psnip_atomic_int32_store(psnip_atomic_int32* object, psnip_int32_t desired) {
|
||||
#pragma omp critical(psnip_atomic)
|
||||
*object = desired;
|
||||
}
|
||||
|
||||
PSNIP_ATOMIC__FUNCTION
|
||||
int
|
||||
psnip_atomic_int32_compare_exchange_(psnip_atomic_int32* object, psnip_int32_t* expected, psnip_int32_t desired) {
|
||||
int ret = 1;
|
||||
#pragma omp critical(psnip_atomic)
|
||||
ret = (*object == *expected) ? ((*object = desired), 1) : 0;
|
||||
return ret;
|
||||
}
|
||||
|
||||
#define psnip_atomic_int32_compare_exchange(object, expected, desired) \
|
||||
psnip_atomic_int32_compare_exchange_(object, expected, desired)
|
||||
|
||||
PSNIP_ATOMIC__FUNCTION
|
||||
psnip_int32_t
|
||||
psnip_atomic_int32_add(psnip_atomic_int32* object, psnip_int32_t operand) {
|
||||
int ret;
|
||||
#pragma omp critical(psnip_atomic)
|
||||
*object = (ret = *object) + operand;
|
||||
return ret;
|
||||
}
|
||||
|
||||
PSNIP_ATOMIC__FUNCTION
|
||||
psnip_int32_t
|
||||
psnip_atomic_int32_sub(psnip_atomic_int32* object, psnip_int32_t operand) {
|
||||
int ret;
|
||||
#pragma omp critical(psnip_atomic)
|
||||
*object = (ret = *object) - operand;
|
||||
return ret;
|
||||
}
|
||||
|
||||
PSNIP_ATOMIC__FUNCTION
|
||||
void
|
||||
psnip_atomic_fence() {
|
||||
#pragma omp critical(psnip_atomic)
|
||||
{ }
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
#if !defined(PSNIP_ATOMIC_VAR_INIT)
|
||||
# define PSNIP_ATOMIC_VAR_INIT(value) (value)
|
||||
#endif
|
||||
|
||||
/* Most compilers have type-generic atomic implementations. */
|
||||
#if defined(PSNIP_ATOMIC_IS_TG)
|
||||
#define psnip_atomic_int32_load(object) \
|
||||
psnip_atomic_int64_load(object)
|
||||
#define psnip_atomic_int32_store(object, desired) \
|
||||
psnip_atomic_int64_store(object, desired)
|
||||
#define psnip_atomic_int32_compare_exchange(object, expected, desired) \
|
||||
psnip_atomic_int64_compare_exchange(object, expected, desired)
|
||||
#define psnip_atomic_int32_add(object, operand) \
|
||||
psnip_atomic_int64_add(object, operand)
|
||||
#define psnip_atomic_int32_sub(object, operand) \
|
||||
psnip_atomic_int64_sub(object, operand)
|
||||
#endif /* defined(PSNIP_ATOMIC_IS_TG) */
|
||||
|
||||
#endif /* !defined(PSNIP_ATOMIC_NOT_FOUND) */
|
||||
|
||||
#endif /* defined(PSNIP_ATOMIC_H) */
|
||||
158
thirdparty/portable-snippets/builtin/README.md
vendored
Normal file
158
thirdparty/portable-snippets/builtin/README.md
vendored
Normal file
|
|
@ -0,0 +1,158 @@
|
|||
# Built-Ins
|
||||
|
||||
This module provides portable implementations of many compiler
|
||||
builtins and intrinsics, allowing you to use builtins and intrinsics
|
||||
on compilers which don't support them. This includes other compilers
|
||||
(*e.g.*, GCC builtins on MSVC) and older versions of the same
|
||||
compiler.
|
||||
|
||||
We also provide exact-width variants of many builtins; no more calling
|
||||
different functions depending on the size of `int`, `long`, `long
|
||||
long`, etc. These are typically just aliases for the appropriate
|
||||
function, but if we can't find an appropriate type a portable
|
||||
implementation will be used.
|
||||
|
||||
If you define `PSNIP_BUILTIN_EMULATE_NATIVE` *before* `builtin.h` is
|
||||
included, this header will also define any missing native-style
|
||||
built-ins, allowing you to use the native names without regard for
|
||||
which compiler is actually in use (*i.e.*, you can use `__builtin_ffs`
|
||||
directly in MSVC, or any other compiler, including GCC < 3.3).
|
||||
|
||||
If the compiler already has the builtin, the psnip function will
|
||||
simply be defined to that builtin (*e.g.*,
|
||||
`#define psnip_builtin_clz __builtin_clz`). If the compiler does not
|
||||
have an implementation one will be provided using either a
|
||||
built-in/intrinsic the compiler *does* support (*e.g.*, using an MSVC
|
||||
intrinsic to implement a GCC built-in), inline assembly,
|
||||
architecture-specific functions, or a fully-portable pure C
|
||||
implementation.
|
||||
|
||||
For example, for GCC's `__builtin_ffs` builtin, we provide
|
||||
implementations which work everywhere (including versions of GCC prior
|
||||
to 3.3, when `__builtin_ffs` was introduced) of the following
|
||||
functions:
|
||||
|
||||
```c
|
||||
int psnip_builtin_ffs(int);
|
||||
int psnip_builtin_ffsl(long);
|
||||
int psnip_builtin_ffsll(long long);
|
||||
int psnip_builtin_ffs32(psnip_int32_t);
|
||||
int psnip_builtin_ffs64(psnip_int64_t);
|
||||
```
|
||||
|
||||
Additionally, when when PSNIP_BUILTIN_EMULATE_NATIVE is defined (and
|
||||
the compiler doesn't already provide them), we also provide
|
||||
|
||||
```c
|
||||
int __builtin_ffs(int);
|
||||
int __builtin_ffsl(long);
|
||||
int __builtin_ffsll(long long);
|
||||
```
|
||||
|
||||
Note that these are often provided as macros, the prototypes are for
|
||||
documentation only.
|
||||
|
||||
## Dependencies
|
||||
|
||||
To maximize portability you should #include the exact-int module
|
||||
before including builtin.h, but if you don't want to add the extra
|
||||
file to your project you can omit it and this module will simply rely
|
||||
on <stdint.h>. As an alternative you may define the following macros
|
||||
to appropriate values yourself:
|
||||
|
||||
* `psnip_int8_t`
|
||||
* `psnip_uint8_t`
|
||||
* `psnip_int16_t`
|
||||
* `psnip_uint16_t`
|
||||
* `psnip_int32_t`
|
||||
* `psnip_uint32_t`
|
||||
* `psnip_int64_t`
|
||||
* `psnip_uint64_t`
|
||||
|
||||
## Implementation Status
|
||||
|
||||
Virtually every generic builtin we can implement has been implemented.
|
||||
This should work almost everywhere, but every commit is tested before
|
||||
landing in the master branch on various versions of GCC, clang, MSVC,
|
||||
and PGI (thanks to [Travis
|
||||
CI](https://travis-ci.org/nemequ/portable-snippets) and
|
||||
[AppVeyor](https://ci.appveyor.com/project/quixdb/portable-snippets)).
|
||||
Sporadic testing is also done on ICC and Oracle Developer Studio.
|
||||
|
||||
GCC builtins:
|
||||
|
||||
- [x] ffs, ffsl, ffsll, ffs32, ffs64
|
||||
- [x] clz, clzl, clzll, clz32, clz64
|
||||
- [x] ctz, ctzl, ctzll, ctz32, ctz64
|
||||
- [x] clrsb, clrsbl, clrsbll, clrsb32, clrsb64
|
||||
- [x] popcount, popcountl, popcountll, popcount32, popcount64
|
||||
- [x] parity, parityl, parityll, parity32, parity64
|
||||
- [x] bswap16, bswap32, bswap64
|
||||
|
||||
Clang builtins:
|
||||
|
||||
- [x] bitreverse8, bitreverse16, bitreverse32, bitreverse64
|
||||
- [x] addcb, addcs, addc, addcl, addcll, addc8, addc16, addc32, addc64
|
||||
- [x] subcb, subcs, subc, subcl, subcll, subc8, subc16, subc32, subc64
|
||||
|
||||
MSVC intrinsics:
|
||||
|
||||
- [x] rotl8, rotl16, rotl, rotl64
|
||||
- [x] rotr8, rotr16, rotr, rotr64
|
||||
- [x] BitScanForward, BitScanForward64
|
||||
- [x] BitScanReverse, BitScanReverse64
|
||||
- [ ] mul128, umul128
|
||||
- [x] shiftleft128, shiftright128
|
||||
- [ ] mulh, umulh
|
||||
- [x] byteswap_ushort, byteswap_ulong, byteswap_uint64
|
||||
- [x] bittest, bittest64
|
||||
- [x] bittestandcomplement, bittestandcomplement64
|
||||
- [x] bittestandreset, bittestandreset64
|
||||
- [x] bittestandset, bittestandset64
|
||||
|
||||
If we are missing a function you feel should be included, please [file
|
||||
an issue](https://github.com/nemequ/portable-snippets/issues). Please
|
||||
keep in mind that some things are simply impossible to implement
|
||||
without compiler support.
|
||||
|
||||
## Alternatives & Supplements
|
||||
|
||||
For overflow-safe integer operations (i.e., `__builtin_*_overflow`),
|
||||
use [safe-math.h](../safe-math).
|
||||
|
||||
For bswap/byteswap functions, you should really use
|
||||
[endian.h](../endian), which depends on this module and handles
|
||||
endianness detection as well as providing easier to use APIs which
|
||||
integrate endianness detection logic.
|
||||
|
||||
For SIMD intrinsics (SSE, AVX, NEON, etc.), take a look at the
|
||||
[SIMDe](https://github.com/nemequ/simde/) project.
|
||||
|
||||
For things which are effectively compiler hints (such as
|
||||
`__builtin_expect`) as opposed to data manipulation functions, see
|
||||
[Hedley](https://nemequ.github.io/hedley/).
|
||||
|
||||
## Areas for future work
|
||||
|
||||
### Optimization
|
||||
|
||||
Performance should be pretty good but we're always open to shaving off
|
||||
a few operations, even if it means creating different variants for
|
||||
different compilers or architectures.
|
||||
|
||||
Creating implementations of one compiler's builtins using builtins
|
||||
from another is probably your best bet to improve performance.
|
||||
Another useful possibility is using architecture-specific builtins, or
|
||||
even embedded assembly, when they are available.
|
||||
|
||||
### Architecture-specific builtins
|
||||
|
||||
GCC and MSVC both have lots of architecture-specific builtins.
|
||||
Especially GCC, which supports many architectures. If you come across
|
||||
one which is useful and could be implemented with a portable fallback,
|
||||
let us know.
|
||||
|
||||
### Builtins from other compilers
|
||||
|
||||
We've looked at GCC, MSVC, and Clang, but we're happy to support
|
||||
builtins from other compilers, too.
|
||||
1503
thirdparty/portable-snippets/builtin/builtin.h
vendored
Normal file
1503
thirdparty/portable-snippets/builtin/builtin.h
vendored
Normal file
File diff suppressed because it is too large
Load diff
38
thirdparty/portable-snippets/check/README.md
vendored
Normal file
38
thirdparty/portable-snippets/check/README.md
vendored
Normal file
|
|
@ -0,0 +1,38 @@
|
|||
# Assertion Checking
|
||||
|
||||
This module provide a variety of assert()-style macros. Unlike the
|
||||
standard `assert()` macro from `<assert.h>`, most of these macros are
|
||||
typed so the input values can be propogated to the string output on
|
||||
failure.
|
||||
|
||||
For documentation, µnit offers very similar macros (this module was
|
||||
originally based off of the macros from µnit), most of
|
||||
[the documentation for them](https://nemequ.github.io/munit/#assertions)
|
||||
applies to this module's macros, just substitute the `munit_` namespace
|
||||
with `psnip_`.
|
||||
|
||||
Additionally, unless you define `PSNIP_CHECK_FAIL_DEFINED`, a failing
|
||||
assertion should be considered undefined behavior when `NDEBUG` and/or
|
||||
`PSNIP_NDEBUG` is defined. This allows the compiler to perform
|
||||
optimizations which would not otherwise be possible.
|
||||
|
||||
## Dependencies
|
||||
|
||||
To maximize portability you should #include the exact-int module
|
||||
before including check.h, but if you don't want to add the extra
|
||||
file to your project you can omit it and this module will simply rely
|
||||
on <stdint.h>. As an alternative you may define the following macros
|
||||
to appropriate values yourself:
|
||||
|
||||
* `psnip_int8_t`
|
||||
* `psnip_uint8_t`
|
||||
* `psnip_int16_t`
|
||||
* `psnip_uint16_t`
|
||||
* `psnip_int32_t`
|
||||
* `psnip_uint32_t`
|
||||
* `psnip_int64_t`
|
||||
* `psnip_uint64_t`
|
||||
|
||||
Including [Hedley](https://nemequ.github.io/hedley/) before check.h
|
||||
will significantly improve compiler support and may improve
|
||||
performance.
|
||||
376
thirdparty/portable-snippets/check/check.h
vendored
Normal file
376
thirdparty/portable-snippets/check/check.h
vendored
Normal file
|
|
@ -0,0 +1,376 @@
|
|||
/* Check (assertions)
|
||||
* Portable Snippets - https://github.com/nemequ/portable-snippets
|
||||
* Created by Evan Nemerson <evan@nemerson.com>
|
||||
*
|
||||
* To the extent possible under law, the authors have waived all
|
||||
* copyright and related or neighboring rights to this code. For
|
||||
* details, see the Creative Commons Zero 1.0 Universal license at
|
||||
* https://creativecommons.org/publicdomain/zero/1.0/
|
||||
*/
|
||||
|
||||
#if !defined(PSNIP_CHECK_H)
|
||||
#define PSNIP_CHECK_H
|
||||
|
||||
#if !defined(PSNIP_NDEBUG) && defined(NDEBUG) && !defined(PSNIP_DEBUG)
|
||||
# define PSNIP_NDEBUG 1
|
||||
#endif
|
||||
|
||||
#if !defined(PSNIP_CHECK_LIKELY)
|
||||
# if defined(HEDLEY_LIKELY)
|
||||
# define PSNIP_CHECK_LIKELY(expr) HEDLEY_LIKELY(expr)
|
||||
# elif defined(__GNUC__)
|
||||
# define PSNIP_CHECK_LIKELY(expr) (__builtin_expect(!!(expr), !0))
|
||||
# else
|
||||
# define PSNIP_CHECK_LIKELY(expr) (!!(expr))
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#if !defined(PSNIP_CHECK_UNLIKELY)
|
||||
# if defined(PSNIP_CHECK_UNLIKELY)
|
||||
# define PSNIP_CHECK_UNLIKELY(expr) PSNIP_CHECK_UNLIKELY(expr)
|
||||
# elif defined(__GNUC__)
|
||||
# define PSNIP_CHECK_UNLIKELY(expr) (__builtin_expect(!!(expr), !!0))
|
||||
# else
|
||||
# define PSNIP_CHECK_UNLIKELY(expr) (!!(expr))
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/* For maximum portability include the exact-int module from
|
||||
portable snippets. */
|
||||
#if \
|
||||
!defined(psnip_uint64_t) || \
|
||||
!defined(psnip_uint32_t) || \
|
||||
!defined(psnip_uint16_t) || \
|
||||
!defined(psnip_uint8_t) || \
|
||||
!defined(psnip_int64_t) || \
|
||||
!defined(psnip_int32_t) || \
|
||||
!defined(psnip_int16_t) || \
|
||||
!defined(psnip_int8_t)
|
||||
# include <stdint.h>
|
||||
# if !defined(psnip_uint64_t)
|
||||
# define psnip_uint64_t uint64_t
|
||||
# endif
|
||||
# if !defined(psnip_uint32_t)
|
||||
# define psnip_uint32_t uint32_t
|
||||
# endif
|
||||
# if !defined(psnip_uint16_t)
|
||||
# define psnip_uint16_t uint16_t
|
||||
# endif
|
||||
# if !defined(psnip_uint8_t)
|
||||
# define psnip_uint8_t uint8_t
|
||||
# endif
|
||||
# if !defined(psnip_int64_t)
|
||||
# define psnip_int64_t int64_t
|
||||
# endif
|
||||
# if !defined(psnip_int32_t)
|
||||
# define psnip_int32_t int32_t
|
||||
# endif
|
||||
# if !defined(psnip_int16_t)
|
||||
# define psnip_int16_t int16_t
|
||||
# endif
|
||||
# if !defined(psnip_int8_t)
|
||||
# define psnip_int8_t int8_t
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#if \
|
||||
!defined(PRIi8) || \
|
||||
!defined(PRIi16) || \
|
||||
!defined(PRIi32) || \
|
||||
!defined(PRIi64) || \
|
||||
!defined(PRId8) || \
|
||||
!defined(PRId16) || \
|
||||
!defined(PRId32) || \
|
||||
!defined(PRId64) || \
|
||||
!defined(PRIx8) || \
|
||||
!defined(PRIx16) || \
|
||||
!defined(PRIx32) || \
|
||||
!defined(PRIx64) || \
|
||||
!defined(PRIu8) || \
|
||||
!defined(PRIu16) || \
|
||||
!defined(PRIu32) || \
|
||||
!defined(PRIu64)
|
||||
# if defined(_MSC_VER) && (_MSC_VER < 1800)
|
||||
# if !defined(PRIi8)
|
||||
# define PRIi8 "i"
|
||||
# endif
|
||||
# if !defined(PRIi16)
|
||||
# define PRIi16 "i"
|
||||
# endif
|
||||
# if !defined(PRIi32)
|
||||
# define PRIi32 "i"
|
||||
# endif
|
||||
# if !defined(PRIi64)
|
||||
# define PRIi64 "I64i"
|
||||
# endif
|
||||
# if !defined(PRId8)
|
||||
# define PRId8 "d"
|
||||
# endif
|
||||
# if !defined(PRId16)
|
||||
# define PRId16 "d"
|
||||
# endif
|
||||
# if !defined(PRId32)
|
||||
# define PRId32 "d"
|
||||
# endif
|
||||
# if !defined(PRId64)
|
||||
# define PRId64 "I64d"
|
||||
# endif
|
||||
# if !defined(PRIx8)
|
||||
# define PRIx8 "x"
|
||||
# endif
|
||||
# if !defined(PRIx16)
|
||||
# define PRIx16 "x"
|
||||
# endif
|
||||
# if !defined(PRIx32)
|
||||
# define PRIx32 "x"
|
||||
# endif
|
||||
# if !defined(PRIx64)
|
||||
# define PRIx64 "I64x"
|
||||
# endif
|
||||
# if !defined(PRIu8)
|
||||
# define PRIu8 "u"
|
||||
# endif
|
||||
# if !defined(PRIu16)
|
||||
# define PRIu16 "u"
|
||||
# endif
|
||||
# if !defined(PRIu32)
|
||||
# define PRIu32 "u"
|
||||
# endif
|
||||
# if !defined(PRIu64)
|
||||
# define PRIu64 "I64u"
|
||||
# endif
|
||||
# else
|
||||
# include <inttypes.h>
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#if !defined(_WIN32)
|
||||
# define PSNIP_SIZE_MODIFIER "z"
|
||||
# define PSNIP_CHAR_MODIFIER "hh"
|
||||
# define PSNIP_SHORT_MODIFIER "h"
|
||||
#else
|
||||
# if defined(_M_X64) || defined(__amd64__)
|
||||
# define PSNIP_SIZE_MODIFIER "I64"
|
||||
# else
|
||||
# define PSNIP_SIZE_MODIFIER ""
|
||||
# endif
|
||||
# define PSNIP_CHAR_MODIFIER ""
|
||||
# define PSNIP_SHORT_MODIFIER ""
|
||||
#endif
|
||||
|
||||
#if defined(_MSC_VER) && (_MSC_VER >= 1500)
|
||||
# define PSNIP__PUSH_DISABLE_MSVC_C4127 __pragma(warning(push)) __pragma(warning(disable:4127))
|
||||
# define PSNIP__POP_DISABLE_MSVC_C4127 __pragma(warning(pop))
|
||||
#else
|
||||
# define PSNIP__PUSH_DISABLE_MSVC_C4127
|
||||
# define PSNIP__POP_DISABLE_MSVC_C4127
|
||||
#endif
|
||||
|
||||
#if !defined(psnip_errorf)
|
||||
# include <stdio.h>
|
||||
# include <stdlib.h>
|
||||
# define psnip_errorf(format, ...) (fprintf(stderr, format, __VA_ARGS__), abort())
|
||||
#endif
|
||||
|
||||
#define psnip_error(msg) psnip_errorf("%s", msg)
|
||||
|
||||
#if defined(PSNIP_NDEBUG)
|
||||
# if defined(PSNIP_CHECK_FAIL_DEFINED)
|
||||
# define psnip_assert(expr)
|
||||
# else
|
||||
# if defined(HEDLEY_ASSUME)
|
||||
# define psnip_assert(expr) HEDLEY_ASSUME(expr)
|
||||
# elif defined(__GNUC__)
|
||||
# define psnip_assert(expr) ((void) (!!(expr) ? 1 : (__builtin_unreachable(), 1)))
|
||||
# elif defined(_MSC_VER)
|
||||
# define psnip_assert(expr) __assume(expr)
|
||||
# else
|
||||
# define psnip_assert(expr)
|
||||
# endif
|
||||
# endif
|
||||
# define psnip_assert_true(expr) psnip_assert(expr)
|
||||
# define psnip_assert_false(expr) psnip_assert(!(expr))
|
||||
# define psnip_assert_type_full(prefix, suffix, T, fmt, a, op, b) psnip_assert(((a) op (b)))
|
||||
# define psnip_assert_double_equal(a, b, precision)
|
||||
# define psnip_assert_string_equal(a, b)
|
||||
# define psnip_assert_string_not_equal(a, b)
|
||||
# define psnip_assert_memory_equal(size, a, b)
|
||||
# define psnip_assert_memory_not_equal(size, a, b)
|
||||
#else
|
||||
# define psnip_assert(expr) \
|
||||
do { \
|
||||
if (!PSNIP_CHECK_LIKELY(expr)) { \
|
||||
psnip_error("assertion failed: " #expr "\n"); \
|
||||
} \
|
||||
PSNIP__PUSH_DISABLE_MSVC_C4127 \
|
||||
} while (0) \
|
||||
PSNIP__POP_DISABLE_MSVC_C4127
|
||||
|
||||
# define psnip_assert_true(expr) \
|
||||
do { \
|
||||
if (!PSNIP_CHECK_LIKELY(expr)) { \
|
||||
psnip_error("assertion failed: " #expr " is not true\n"); \
|
||||
} \
|
||||
PSNIP__PUSH_DISABLE_MSVC_C4127 \
|
||||
} while (0) \
|
||||
PSNIP__POP_DISABLE_MSVC_C4127
|
||||
|
||||
# define psnip_assert_false(expr) \
|
||||
do { \
|
||||
if (!PSNIP_CHECK_LIKELY(!(expr))) { \
|
||||
psnip_error("assertion failed: " #expr " is not false\n"); \
|
||||
} \
|
||||
PSNIP__PUSH_DISABLE_MSVC_C4127 \
|
||||
} while (0) \
|
||||
PSNIP__POP_DISABLE_MSVC_C4127
|
||||
|
||||
# define psnip_assert_type_full(prefix, suffix, T, fmt, a, op, b) \
|
||||
do { \
|
||||
T psnip_tmp_a_ = (a); \
|
||||
T psnip_tmp_b_ = (b); \
|
||||
if (!(psnip_tmp_a_ op psnip_tmp_b_)) { \
|
||||
psnip_errorf("assertion failed: %s %s %s (" prefix "%" fmt suffix " %s " prefix "%" fmt suffix ")\n", \
|
||||
#a, #op, #b, psnip_tmp_a_, #op, psnip_tmp_b_); \
|
||||
} \
|
||||
PSNIP__PUSH_DISABLE_MSVC_C4127 \
|
||||
} while (0) \
|
||||
PSNIP__POP_DISABLE_MSVC_C4127
|
||||
|
||||
# define psnip_assert_double_equal(a, b, precision) \
|
||||
do { \
|
||||
const double psnip_tmp_a_ = (a); \
|
||||
const double psnip_tmp_b_ = (b); \
|
||||
const double psnip_tmp_diff_ = ((psnip_tmp_a_ - psnip_tmp_b_) < 0) ? \
|
||||
-(psnip_tmp_a_ - psnip_tmp_b_) : \
|
||||
(psnip_tmp_a_ - psnip_tmp_b_); \
|
||||
if (PSNIP_CHECK_UNLIKELY(psnip_tmp_diff_ > 1e-##precision)) { \
|
||||
psnip_errorf("assertion failed: %s == %s (%0." #precision "g == %0." #precision "g)\n", \
|
||||
#a, #b, psnip_tmp_a_, psnip_tmp_b_); \
|
||||
} \
|
||||
PSNIP__PUSH_DISABLE_MSVC_C4127 \
|
||||
} while (0) \
|
||||
PSNIP__POP_DISABLE_MSVC_C4127
|
||||
|
||||
# include <string.h>
|
||||
# define psnip_assert_string_equal(a, b) \
|
||||
do { \
|
||||
const char* psnip_tmp_a_ = a; \
|
||||
const char* psnip_tmp_b_ = b; \
|
||||
if (PSNIP_CHECK_UNLIKELY(strcmp(psnip_tmp_a_, psnip_tmp_b_) != 0)) { \
|
||||
psnip_errorf("assertion failed: string %s == %s (\"%s\" == \"%s\")\n", \
|
||||
#a, #b, psnip_tmp_a_, psnip_tmp_b_); \
|
||||
} \
|
||||
PSNIP__PUSH_DISABLE_MSVC_C4127 \
|
||||
} while (0) \
|
||||
PSNIP__POP_DISABLE_MSVC_C4127
|
||||
|
||||
# define psnip_assert_string_not_equal(a, b) \
|
||||
do { \
|
||||
const char* psnip_tmp_a_ = a; \
|
||||
const char* psnip_tmp_b_ = b; \
|
||||
if (PSNIP_CHECK_UNLIKELY(strcmp(psnip_tmp_a_, psnip_tmp_b_) == 0)) { \
|
||||
psnip_errorf("assertion failed: string %s != %s (\"%s\" == \"%s\")\n", \
|
||||
#a, #b, psnip_tmp_a_, psnip_tmp_b_); \
|
||||
} \
|
||||
PSNIP__PUSH_DISABLE_MSVC_C4127 \
|
||||
} while (0) \
|
||||
PSNIP__POP_DISABLE_MSVC_C4127
|
||||
|
||||
# define psnip_assert_memory_equal(size, a, b) \
|
||||
do { \
|
||||
const unsigned char* psnip_tmp_a_ = (const unsigned char*) (a); \
|
||||
const unsigned char* psnip_tmp_b_ = (const unsigned char*) (b); \
|
||||
const size_t psnip_tmp_size_ = (size); \
|
||||
if (PSNIP_CHECK_UNLIKELY(memcmp(psnip_tmp_a_, psnip_tmp_b_, psnip_tmp_size_)) != 0) { \
|
||||
size_t psnip_tmp_pos_; \
|
||||
for (psnip_tmp_pos_ = 0 ; psnip_tmp_pos_ < psnip_tmp_size_ ; psnip_tmp_pos_++) { \
|
||||
if (psnip_tmp_a_[psnip_tmp_pos_] != psnip_tmp_b_[psnip_tmp_pos_]) { \
|
||||
psnip_errorf("assertion failed: memory %s == %s, at offset %" PSNIP_SIZE_MODIFIER "u\n", \
|
||||
#a, #b, psnip_tmp_pos_); \
|
||||
break; \
|
||||
} \
|
||||
} \
|
||||
} \
|
||||
PSNIP__PUSH_DISABLE_MSVC_C4127 \
|
||||
} while (0) \
|
||||
PSNIP__POP_DISABLE_MSVC_C4127
|
||||
|
||||
# define psnip_assert_memory_not_equal(size, a, b) \
|
||||
do { \
|
||||
const unsigned char* psnip_tmp_a_ = (const unsigned char*) (a); \
|
||||
const unsigned char* psnip_tmp_b_ = (const unsigned char*) (b); \
|
||||
const size_t psnip_tmp_size_ = (size); \
|
||||
if (PSNIP_CHECK_UNLIKELY(memcmp(psnip_tmp_a_, psnip_tmp_b_, psnip_tmp_size_)) == 0) { \
|
||||
psnip_errorf("assertion failed: memory %s != %s (%" PSNIP_SIZE_MODIFIER "u bytes)\n", \
|
||||
#a, #b, psnip_tmp_size_); \
|
||||
} \
|
||||
PSNIP__PUSH_DISABLE_MSVC_C4127 \
|
||||
} while (0) \
|
||||
PSNIP__POP_DISABLE_MSVC_C4127
|
||||
#endif
|
||||
|
||||
#define psnip_assert_type(T, fmt, a, op, b) \
|
||||
psnip_assert_type_full("", "", T, fmt, a, op, b)
|
||||
|
||||
#define psnip_assert_char(a, op, b) \
|
||||
psnip_assert_type_full("'\\x", "'", char, "02" PSNIP_CHAR_MODIFIER "x", a, op, b)
|
||||
#define psnip_assert_uchar(a, op, b) \
|
||||
psnip_assert_type_full("'\\x", "'", unsigned char, "02" PSNIP_CHAR_MODIFIER "x", a, op, b)
|
||||
#define psnip_assert_short(a, op, b) \
|
||||
psnip_assert_type(short, PSNIP_SHORT_MODIFIER "d", a, op, b)
|
||||
#define psnip_assert_ushort(a, op, b) \
|
||||
psnip_assert_type(unsigned short, PSNIP_SHORT_MODIFIER "u", a, op, b)
|
||||
#define psnip_assert_int(a, op, b) \
|
||||
psnip_assert_type(int, "d", a, op, b)
|
||||
#define psnip_assert_uint(a, op, b) \
|
||||
psnip_assert_type(unsigned int, "u", a, op, b)
|
||||
#define psnip_assert_long(a, op, b) \
|
||||
psnip_assert_type(long int, "ld", a, op, b)
|
||||
#define psnip_assert_ulong(a, op, b) \
|
||||
psnip_assert_type(unsigned long int, "lu", a, op, b)
|
||||
#define psnip_assert_llong(a, op, b) \
|
||||
psnip_assert_type(long long int, "lld", a, op, b)
|
||||
#define psnip_assert_ullong(a, op, b) \
|
||||
psnip_assert_type(unsigned long long int, "llu", a, op, b)
|
||||
|
||||
#define psnip_assert_size(a, op, b) \
|
||||
psnip_assert_type(size_t, PSNIP_SIZE_MODIFIER "u", a, op, b)
|
||||
|
||||
#define psnip_assert_float(a, op, b) \
|
||||
psnip_assert_type(float, "f", a, op, b)
|
||||
#define psnip_assert_double(a, op, b) \
|
||||
psnip_assert_type(double, "g", a, op, b)
|
||||
#define psnip_assert_ptr(a, op, b) \
|
||||
psnip_assert_type(const void*, "p", a, op, b)
|
||||
|
||||
#define psnip_assert_int8(a, op, b) \
|
||||
psnip_assert_type(psnip_int8_t, PRIi8, a, op, b)
|
||||
#define psnip_assert_uint8(a, op, b) \
|
||||
psnip_assert_type(psnip_uint8_t, PRIu8, a, op, b)
|
||||
#define psnip_assert_int16(a, op, b) \
|
||||
psnip_assert_type(psnip_int16_t, PRIi16, a, op, b)
|
||||
#define psnip_assert_uint16(a, op, b) \
|
||||
psnip_assert_type(psnip_uint16_t, PRIu16, a, op, b)
|
||||
#define psnip_assert_int32(a, op, b) \
|
||||
psnip_assert_type(psnip_int32_t, PRIi32, a, op, b)
|
||||
#define psnip_assert_uint32(a, op, b) \
|
||||
psnip_assert_type(psnip_uint32_t, PRIu32, a, op, b)
|
||||
#define psnip_assert_int64(a, op, b) \
|
||||
psnip_assert_type(psnip_int64_t, PRIi64, a, op, b)
|
||||
#define psnip_assert_uint64(a, op, b) \
|
||||
psnip_assert_type(psnip_uint64_t, PRIu64, a, op, b)
|
||||
|
||||
#define psnip_assert_ptr_equal(a, b) \
|
||||
psnip_assert_ptr(a, ==, b)
|
||||
#define psnip_assert_ptr_not_equal(a, b) \
|
||||
psnip_assert_ptr(a, !=, b)
|
||||
#define psnip_assert_null(ptr) \
|
||||
psnip_assert_ptr(ptr, ==, NULL)
|
||||
#define psnip_assert_not_null(ptr) \
|
||||
psnip_assert_ptr(ptr, !=, NULL)
|
||||
#define psnip_assert_ptr_null(ptr) \
|
||||
psnip_assert_ptr(ptr, ==, NULL)
|
||||
#define psnip_assert_ptr_not_null(ptr) \
|
||||
psnip_assert_ptr(ptr, !=, NULL)
|
||||
|
||||
#endif /* !defined(PSNIP_CHECK_H) */
|
||||
44
thirdparty/portable-snippets/clock/README.md
vendored
Normal file
44
thirdparty/portable-snippets/clock/README.md
vendored
Normal file
|
|
@ -0,0 +1,44 @@
|
|||
# Clock
|
||||
|
||||
This header provides a way to access time information. It's basically
|
||||
a more portable version of `clock_gettime` with fewer supported
|
||||
clocks. Currently supported clocks are:
|
||||
|
||||
* Wall clock
|
||||
* `clock_gettime`
|
||||
* `gettimeofday`
|
||||
* `time`
|
||||
* CPU clock
|
||||
* `clock_gettime`
|
||||
* `GetProcessTimes`
|
||||
* `getrusage`
|
||||
* Monotonic clock
|
||||
* `clock_gettime`
|
||||
* `mach_absolute_time`
|
||||
* `QueryPerformanceCounter`
|
||||
|
||||
If you are using a platform where a clock isn't provided, please let
|
||||
us know about it so we can try to figure out how to add support!
|
||||
|
||||
On some platforms, `clock_gettime` requires linking to librt. If you
|
||||
prefer, you can define `PSNIP_CLOCK_NO_LIBRT` prior to including
|
||||
`clock.h` and `clock_gettime` will only be used on platforms known to
|
||||
support using `clock_gettime` *without* linking against librt. The
|
||||
price will likely be lower-resolution CPU and wall clocks, and no
|
||||
monotonic clock.
|
||||
|
||||
Also, if you're compiling in a strict standard mode instead of a mode
|
||||
with GNU extensions (e.g., -std=c11 instead of -std=gnu11), POSIX
|
||||
extensions will not be enabled by default so you won't get to use the
|
||||
`clock_gettime` implementation; to avoid this, you can define
|
||||
`_POSIX_C_SOURCE` to `199309L` or greater prior to including
|
||||
`clock.h`, or just define `_GNU_SOURCE`.
|
||||
|
||||
## Dependencies
|
||||
|
||||
To maximize portability you should #include the exact-int module
|
||||
before including clock.h, but if you don't want to add the extra
|
||||
file to your project you can omit it and this module will simply rely
|
||||
on <stdint.h>. As an alternative you may define `psnip_uint64_t`,
|
||||
`psnip_uint32_t`, `psnip_int64_t`, `psnip_int32_t` to an appropriate
|
||||
value yourself before including clock.h.
|
||||
464
thirdparty/portable-snippets/clock/clock.h
vendored
Normal file
464
thirdparty/portable-snippets/clock/clock.h
vendored
Normal file
|
|
@ -0,0 +1,464 @@
|
|||
/* Clocks (v1)
|
||||
* Portable Snippets - https://github.com/nemequ/portable-snippets
|
||||
* Created by Evan Nemerson <evan@nemerson.com>
|
||||
*
|
||||
* To the extent possible under law, the authors have waived all
|
||||
* copyright and related or neighboring rights to this code. For
|
||||
* details, see the Creative Commons Zero 1.0 Universal license at
|
||||
* https://creativecommons.org/publicdomain/zero/1.0/
|
||||
*/
|
||||
|
||||
#if !defined(PSNIP_CLOCK_H)
|
||||
#define PSNIP_CLOCK_H
|
||||
|
||||
/* For maximum portability include the exact-int module from
|
||||
portable snippets. */
|
||||
#if !defined(psnip_uint64_t) || !defined(psnip_int32_t) || \
|
||||
!defined(psnip_uint32_t) || !defined(psnip_int32_t)
|
||||
# include <stdint.h>
|
||||
# if !defined(psnip_int64_t)
|
||||
# define psnip_int64_t int64_t
|
||||
# endif
|
||||
# if !defined(psnip_uint64_t)
|
||||
# define psnip_uint64_t uint64_t
|
||||
# endif
|
||||
# if !defined(psnip_int32_t)
|
||||
# define psnip_int32_t int32_t
|
||||
# endif
|
||||
# if !defined(psnip_uint32_t)
|
||||
# define psnip_uint32_t uint32_t
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#if !defined(PSNIP_CLOCK_STATIC_INLINE)
|
||||
# if defined(__GNUC__)
|
||||
# define PSNIP_CLOCK__COMPILER_ATTRIBUTES __attribute__((__unused__))
|
||||
# else
|
||||
# define PSNIP_CLOCK__COMPILER_ATTRIBUTES
|
||||
# endif
|
||||
|
||||
# define PSNIP_CLOCK__FUNCTION PSNIP_CLOCK__COMPILER_ATTRIBUTES static
|
||||
#endif
|
||||
|
||||
enum PsnipClockType {
|
||||
/* This clock provides the current time, in units since 1970-01-01
|
||||
* 00:00:00 UTC not including leap seconds. In other words, UNIX
|
||||
* time. Keep in mind that this clock doesn't account for leap
|
||||
* seconds, and can go backwards (think NTP adjustments). */
|
||||
PSNIP_CLOCK_TYPE_WALL = 1,
|
||||
/* The CPU time is a clock which increases only when the current
|
||||
* process is active (i.e., it doesn't increment while blocking on
|
||||
* I/O). */
|
||||
PSNIP_CLOCK_TYPE_CPU = 2,
|
||||
/* Monotonic time is always running (unlike CPU time), but it only
|
||||
ever moves forward unless you reboot the system. Things like NTP
|
||||
adjustments have no effect on this clock. */
|
||||
PSNIP_CLOCK_TYPE_MONOTONIC = 3
|
||||
};
|
||||
|
||||
struct PsnipClockTimespec {
|
||||
psnip_uint64_t seconds;
|
||||
psnip_uint64_t nanoseconds;
|
||||
};
|
||||
|
||||
/* Methods we support: */
|
||||
|
||||
#define PSNIP_CLOCK_METHOD_CLOCK_GETTIME 1
|
||||
#define PSNIP_CLOCK_METHOD_TIME 2
|
||||
#define PSNIP_CLOCK_METHOD_GETTIMEOFDAY 3
|
||||
#define PSNIP_CLOCK_METHOD_QUERYPERFORMANCECOUNTER 4
|
||||
#define PSNIP_CLOCK_METHOD_MACH_ABSOLUTE_TIME 5
|
||||
#define PSNIP_CLOCK_METHOD_CLOCK 6
|
||||
#define PSNIP_CLOCK_METHOD_GETPROCESSTIMES 7
|
||||
#define PSNIP_CLOCK_METHOD_GETRUSAGE 8
|
||||
#define PSNIP_CLOCK_METHOD_GETSYSTEMTIMEPRECISEASFILETIME 9
|
||||
#define PSNIP_CLOCK_METHOD_GETTICKCOUNT64 10
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
#if defined(HEDLEY_UNREACHABLE)
|
||||
# define PSNIP_CLOCK_UNREACHABLE() HEDLEY_UNREACHABLE()
|
||||
#else
|
||||
# define PSNIP_CLOCK_UNREACHABLE() assert(0)
|
||||
#endif
|
||||
|
||||
/* Choose an implementation */
|
||||
|
||||
/* #undef PSNIP_CLOCK_WALL_METHOD */
|
||||
/* #undef PSNIP_CLOCK_CPU_METHOD */
|
||||
/* #undef PSNIP_CLOCK_MONOTONIC_METHOD */
|
||||
|
||||
/* We want to be able to detect the libc implementation, so we include
|
||||
<limits.h> (<features.h> isn't available everywhere). */
|
||||
#if defined(__unix__) || defined(__unix) || defined(__linux__)
|
||||
# include <limits.h>
|
||||
# include <unistd.h>
|
||||
#endif
|
||||
|
||||
#if defined(_POSIX_TIMERS) && (_POSIX_TIMERS > 0)
|
||||
/* glibc 2.17+ and FreeBSD are known to work without librt. If you
|
||||
* know of others please let us know so we can add them. */
|
||||
# if \
|
||||
(defined(__GLIBC__) && (__GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 17))) || \
|
||||
(defined(__FreeBSD__)) || \
|
||||
!defined(PSNIP_CLOCK_NO_LIBRT)
|
||||
/* Even though glibc unconditionally sets _POSIX_TIMERS, it doesn't
|
||||
actually declare the relevant APIs unless _POSIX_C_SOURCE >=
|
||||
199309L, and if you compile in standard C mode (e.g., c11 instead
|
||||
of gnu11) _POSIX_C_SOURCE will be unset by default. */
|
||||
# if _POSIX_C_SOURCE >= 199309L
|
||||
# define PSNIP_CLOCK_HAVE_CLOCK_GETTIME
|
||||
# endif
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#if defined(_WIN32)
|
||||
# if !defined(PSNIP_CLOCK_CPU_METHOD)
|
||||
# define PSNIP_CLOCK_CPU_METHOD PSNIP_CLOCK_METHOD_GETPROCESSTIMES
|
||||
# endif
|
||||
# if !defined(PSNIP_CLOCK_MONOTONIC_METHOD)
|
||||
# define PSNIP_CLOCK_MONOTONIC_METHOD PSNIP_CLOCK_METHOD_QUERYPERFORMANCECOUNTER
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#if defined(__MACH__) && !defined(__gnu_hurd__)
|
||||
# if !defined(PSNIP_CLOCK_MONOTONIC_METHOD)
|
||||
# define PSNIP_CLOCK_MONOTONIC_METHOD PSNIP_CLOCK_METHOD_MACH_ABSOLUTE_TIME
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#if defined(PSNIP_CLOCK_HAVE_CLOCK_GETTIME)
|
||||
# include <time.h>
|
||||
# if !defined(PSNIP_CLOCK_WALL_METHOD)
|
||||
# if defined(CLOCK_REALTIME_PRECISE)
|
||||
# define PSNIP_CLOCK_WALL_METHOD PSNIP_CLOCK_METHOD_CLOCK_GETTIME
|
||||
# define PSNIP_CLOCK_CLOCK_GETTIME_WALL CLOCK_REALTIME_PRECISE
|
||||
# elif !defined(__sun)
|
||||
# define PSNIP_CLOCK_WALL_METHOD PSNIP_CLOCK_METHOD_CLOCK_GETTIME
|
||||
# define PSNIP_CLOCK_CLOCK_GETTIME_WALL CLOCK_REALTIME
|
||||
# endif
|
||||
# endif
|
||||
# if !defined(PSNIP_CLOCK_CPU_METHOD)
|
||||
# if defined(_POSIX_CPUTIME) || defined(CLOCK_PROCESS_CPUTIME_ID)
|
||||
# define PSNIP_CLOCK_CPU_METHOD PSNIP_CLOCK_METHOD_CLOCK_GETTIME
|
||||
# define PSNIP_CLOCK_CLOCK_GETTIME_CPU CLOCK_PROCESS_CPUTIME_ID
|
||||
# elif defined(CLOCK_VIRTUAL)
|
||||
# define PSNIP_CLOCK_CPU_METHOD PSNIP_CLOCK_METHOD_CLOCK_GETTIME
|
||||
# define PSNIP_CLOCK_CLOCK_GETTIME_CPU CLOCK_VIRTUAL
|
||||
# endif
|
||||
# endif
|
||||
# if !defined(PSNIP_CLOCK_MONOTONIC_METHOD)
|
||||
# if defined(_POSIX_MONOTONIC_CLOCK) || defined(CLOCK_MONOTONIC)
|
||||
# define PSNIP_CLOCK_MONOTONIC_METHOD PSNIP_CLOCK_METHOD_CLOCK_GETTIME
|
||||
# define PSNIP_CLOCK_CLOCK_GETTIME_MONOTONIC CLOCK_MONOTONIC
|
||||
# endif
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#if defined(_POSIX_VERSION) && (_POSIX_VERSION >= 200112L)
|
||||
# if !defined(PSNIP_CLOCK_WALL_METHOD)
|
||||
# define PSNIP_CLOCK_WALL_METHOD PSNIP_CLOCK_METHOD_GETTIMEOFDAY
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#if !defined(PSNIP_CLOCK_WALL_METHOD)
|
||||
# define PSNIP_CLOCK_WALL_METHOD PSNIP_CLOCK_METHOD_TIME
|
||||
#endif
|
||||
|
||||
#if !defined(PSNIP_CLOCK_CPU_METHOD)
|
||||
# define PSNIP_CLOCK_CPU_METHOD PSNIP_CLOCK_METHOD_CLOCK
|
||||
#endif
|
||||
|
||||
/* Primarily here for testing. */
|
||||
#if !defined(PSNIP_CLOCK_MONOTONIC_METHOD) && defined(PSNIP_CLOCK_REQUIRE_MONOTONIC)
|
||||
# error No monotonic clock found.
|
||||
#endif
|
||||
|
||||
/* Implementations */
|
||||
|
||||
#if \
|
||||
(defined(PSNIP_CLOCK_CPU_METHOD) && (PSNIP_CLOCK_CPU_METHOD == PSNIP_CLOCK_METHOD_CLOCK_GETTIME)) || \
|
||||
(defined(PSNIP_CLOCK_WALL_METHOD) && (PSNIP_CLOCK_WALL_METHOD == PSNIP_CLOCK_METHOD_CLOCK_GETTIME)) || \
|
||||
(defined(PSNIP_CLOCK_MONOTONIC_METHOD) && (PSNIP_CLOCK_MONOTONIC_METHOD == PSNIP_CLOCK_METHOD_CLOCK_GETTIME)) || \
|
||||
(defined(PSNIP_CLOCK_CPU_METHOD) && (PSNIP_CLOCK_CPU_METHOD == PSNIP_CLOCK_METHOD_CLOCK)) || \
|
||||
(defined(PSNIP_CLOCK_WALL_METHOD) && (PSNIP_CLOCK_WALL_METHOD == PSNIP_CLOCK_METHOD_CLOCK)) || \
|
||||
(defined(PSNIP_CLOCK_MONOTONIC_METHOD) && (PSNIP_CLOCK_MONOTONIC_METHOD == PSNIP_CLOCK_METHOD_CLOCK)) || \
|
||||
(defined(PSNIP_CLOCK_CPU_METHOD) && (PSNIP_CLOCK_CPU_METHOD == PSNIP_CLOCK_METHOD_TIME)) || \
|
||||
(defined(PSNIP_CLOCK_WALL_METHOD) && (PSNIP_CLOCK_WALL_METHOD == PSNIP_CLOCK_METHOD_TIME)) || \
|
||||
(defined(PSNIP_CLOCK_MONOTONIC_METHOD) && (PSNIP_CLOCK_MONOTONIC_METHOD == PSNIP_CLOCK_METHOD_TIME))
|
||||
# include <time.h>
|
||||
#endif
|
||||
|
||||
#if \
|
||||
(defined(PSNIP_CLOCK_CPU_METHOD) && (PSNIP_CLOCK_CPU_METHOD == PSNIP_CLOCK_METHOD_GETTIMEOFDAY)) || \
|
||||
(defined(PSNIP_CLOCK_WALL_METHOD) && (PSNIP_CLOCK_WALL_METHOD == PSNIP_CLOCK_METHOD_GETTIMEOFDAY)) || \
|
||||
(defined(PSNIP_CLOCK_MONOTONIC_METHOD) && (PSNIP_CLOCK_MONOTONIC_METHOD == PSNIP_CLOCK_METHOD_GETTIMEOFDAY))
|
||||
# include <sys/time.h>
|
||||
#endif
|
||||
|
||||
#if \
|
||||
(defined(PSNIP_CLOCK_CPU_METHOD) && (PSNIP_CLOCK_CPU_METHOD == PSNIP_CLOCK_METHOD_GETPROCESSTIMES)) || \
|
||||
(defined(PSNIP_CLOCK_WALL_METHOD) && (PSNIP_CLOCK_WALL_METHOD == PSNIP_CLOCK_METHOD_GETPROCESSTIMES)) || \
|
||||
(defined(PSNIP_CLOCK_MONOTONIC_METHOD) && (PSNIP_CLOCK_MONOTONIC_METHOD == PSNIP_CLOCK_METHOD_GETPROCESSTIMES)) || \
|
||||
(defined(PSNIP_CLOCK_CPU_METHOD) && (PSNIP_CLOCK_CPU_METHOD == PSNIP_CLOCK_METHOD_GETTICKCOUNT64)) || \
|
||||
(defined(PSNIP_CLOCK_WALL_METHOD) && (PSNIP_CLOCK_WALL_METHOD == PSNIP_CLOCK_METHOD_GETTICKCOUNT64)) || \
|
||||
(defined(PSNIP_CLOCK_MONOTONIC_METHOD) && (PSNIP_CLOCK_MONOTONIC_METHOD == PSNIP_CLOCK_METHOD_GETTICKCOUNT64))
|
||||
# include <windows.h>
|
||||
#endif
|
||||
|
||||
#if \
|
||||
(defined(PSNIP_CLOCK_CPU_METHOD) && (PSNIP_CLOCK_CPU_METHOD == PSNIP_CLOCK_METHOD_GETRUSAGE)) || \
|
||||
(defined(PSNIP_CLOCK_WALL_METHOD) && (PSNIP_CLOCK_WALL_METHOD == PSNIP_CLOCK_METHOD_GETRUSAGE)) || \
|
||||
(defined(PSNIP_CLOCK_MONOTONIC_METHOD) && (PSNIP_CLOCK_MONOTONIC_METHOD == PSNIP_CLOCK_METHOD_GETRUSAGE))
|
||||
# include <sys/time.h>
|
||||
# include <sys/resource.h>
|
||||
#endif
|
||||
|
||||
#if \
|
||||
(defined(PSNIP_CLOCK_CPU_METHOD) && (PSNIP_CLOCK_CPU_METHOD == PSNIP_CLOCK_METHOD_MACH_ABSOLUTE_TIME)) || \
|
||||
(defined(PSNIP_CLOCK_WALL_METHOD) && (PSNIP_CLOCK_WALL_METHOD == PSNIP_CLOCK_METHOD_MACH_ABSOLUTE_TIME)) || \
|
||||
(defined(PSNIP_CLOCK_MONOTONIC_METHOD) && (PSNIP_CLOCK_MONOTONIC_METHOD == PSNIP_CLOCK_METHOD_MACH_ABSOLUTE_TIME))
|
||||
# include <CoreServices/CoreServices.h>
|
||||
# include <mach/mach.h>
|
||||
# include <mach/mach_time.h>
|
||||
#endif
|
||||
|
||||
/*** Implementations ***/
|
||||
|
||||
#define PSNIP_CLOCK_NSEC_PER_SEC ((psnip_uint32_t) (1000000000ULL))
|
||||
|
||||
#if \
|
||||
(defined(PSNIP_CLOCK_CPU_METHOD) && (PSNIP_CLOCK_CPU_METHOD == PSNIP_CLOCK_METHOD_CLOCK_GETTIME)) || \
|
||||
(defined(PSNIP_CLOCK_WALL_METHOD) && (PSNIP_CLOCK_WALL_METHOD == PSNIP_CLOCK_METHOD_CLOCK_GETTIME)) || \
|
||||
(defined(PSNIP_CLOCK_MONOTONIC_METHOD) && (PSNIP_CLOCK_MONOTONIC_METHOD == PSNIP_CLOCK_METHOD_CLOCK_GETTIME))
|
||||
PSNIP_CLOCK__FUNCTION psnip_uint32_t
|
||||
psnip_clock__clock_getres (clockid_t clk_id) {
|
||||
struct timespec res;
|
||||
int r;
|
||||
|
||||
r = clock_getres(clk_id, &res);
|
||||
if (r != 0)
|
||||
return 0;
|
||||
|
||||
return (psnip_uint32_t) (PSNIP_CLOCK_NSEC_PER_SEC / res.tv_nsec);
|
||||
}
|
||||
|
||||
PSNIP_CLOCK__FUNCTION int
|
||||
psnip_clock__clock_gettime (clockid_t clk_id, struct PsnipClockTimespec* res) {
|
||||
struct timespec ts;
|
||||
|
||||
if (clock_gettime(clk_id, &ts) != 0)
|
||||
return -10;
|
||||
|
||||
res->seconds = (psnip_uint64_t) (ts.tv_sec);
|
||||
res->nanoseconds = (psnip_uint64_t) (ts.tv_nsec);
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
PSNIP_CLOCK__FUNCTION psnip_uint32_t
|
||||
psnip_clock_wall_get_precision (void) {
|
||||
#if !defined(PSNIP_CLOCK_WALL_METHOD)
|
||||
return 0;
|
||||
#elif defined(PSNIP_CLOCK_WALL_METHOD) && PSNIP_CLOCK_WALL_METHOD == PSNIP_CLOCK_METHOD_CLOCK_GETTIME
|
||||
return psnip_clock__clock_getres(PSNIP_CLOCK_CLOCK_GETTIME_WALL);
|
||||
#elif defined(PSNIP_CLOCK_WALL_METHOD) && PSNIP_CLOCK_WALL_METHOD == PSNIP_CLOCK_METHOD_GETTIMEOFDAY
|
||||
return 1000000;
|
||||
#elif defined(PSNIP_CLOCK_WALL_METHOD) && PSNIP_CLOCK_WALL_METHOD == PSNIP_CLOCK_METHOD_TIME
|
||||
return 1;
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
PSNIP_CLOCK__FUNCTION int
|
||||
psnip_clock_wall_get_time (struct PsnipClockTimespec* res) {
|
||||
(void) res;
|
||||
|
||||
#if !defined(PSNIP_CLOCK_WALL_METHOD)
|
||||
return -2;
|
||||
#elif defined(PSNIP_CLOCK_WALL_METHOD) && PSNIP_CLOCK_WALL_METHOD == PSNIP_CLOCK_METHOD_CLOCK_GETTIME
|
||||
return psnip_clock__clock_gettime(PSNIP_CLOCK_CLOCK_GETTIME_WALL, res);
|
||||
#elif defined(PSNIP_CLOCK_WALL_METHOD) && PSNIP_CLOCK_WALL_METHOD == PSNIP_CLOCK_METHOD_TIME
|
||||
res->seconds = time(NULL);
|
||||
res->nanoseconds = 0;
|
||||
#elif defined(PSNIP_CLOCK_WALL_METHOD) && PSNIP_CLOCK_WALL_METHOD == PSNIP_CLOCK_METHOD_GETTIMEOFDAY
|
||||
struct timeval tv;
|
||||
|
||||
if (gettimeofday(&tv, NULL) != 0)
|
||||
return -6;
|
||||
|
||||
res->seconds = tv.tv_sec;
|
||||
res->nanoseconds = tv.tv_usec * 1000;
|
||||
#else
|
||||
return -2;
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
PSNIP_CLOCK__FUNCTION psnip_uint32_t
|
||||
psnip_clock_cpu_get_precision (void) {
|
||||
#if !defined(PSNIP_CLOCK_CPU_METHOD)
|
||||
return 0;
|
||||
#elif defined(PSNIP_CLOCK_CPU_METHOD) && PSNIP_CLOCK_CPU_METHOD == PSNIP_CLOCK_METHOD_CLOCK_GETTIME
|
||||
return psnip_clock__clock_getres(PSNIP_CLOCK_CLOCK_GETTIME_CPU);
|
||||
#elif defined(PSNIP_CLOCK_CPU_METHOD) && PSNIP_CLOCK_CPU_METHOD == PSNIP_CLOCK_METHOD_CLOCK
|
||||
return CLOCKS_PER_SEC;
|
||||
#elif defined(PSNIP_CLOCK_CPU_METHOD) && PSNIP_CLOCK_CPU_METHOD == PSNIP_CLOCK_METHOD_GETPROCESSTIMES
|
||||
return PSNIP_CLOCK_NSEC_PER_SEC / 100;
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
PSNIP_CLOCK__FUNCTION int
|
||||
psnip_clock_cpu_get_time (struct PsnipClockTimespec* res) {
|
||||
#if !defined(PSNIP_CLOCK_CPU_METHOD)
|
||||
(void) res;
|
||||
return -2;
|
||||
#elif defined(PSNIP_CLOCK_CPU_METHOD) && PSNIP_CLOCK_CPU_METHOD == PSNIP_CLOCK_METHOD_CLOCK_GETTIME
|
||||
return psnip_clock__clock_gettime(PSNIP_CLOCK_CLOCK_GETTIME_CPU, res);
|
||||
#elif defined(PSNIP_CLOCK_CPU_METHOD) && PSNIP_CLOCK_CPU_METHOD == PSNIP_CLOCK_METHOD_CLOCK
|
||||
clock_t t = clock();
|
||||
if (t == ((clock_t) -1))
|
||||
return -5;
|
||||
res->seconds = t / CLOCKS_PER_SEC;
|
||||
res->nanoseconds = (t % CLOCKS_PER_SEC) * (PSNIP_CLOCK_NSEC_PER_SEC / CLOCKS_PER_SEC);
|
||||
#elif defined(PSNIP_CLOCK_CPU_METHOD) && PSNIP_CLOCK_CPU_METHOD == PSNIP_CLOCK_METHOD_GETPROCESSTIMES
|
||||
FILETIME CreationTime, ExitTime, KernelTime, UserTime;
|
||||
LARGE_INTEGER date, adjust;
|
||||
|
||||
if (!GetProcessTimes(GetCurrentProcess(), &CreationTime, &ExitTime, &KernelTime, &UserTime))
|
||||
return -7;
|
||||
|
||||
/* http://www.frenk.com/2009/12/convert-filetime-to-unix-timestamp/ */
|
||||
date.HighPart = UserTime.dwHighDateTime;
|
||||
date.LowPart = UserTime.dwLowDateTime;
|
||||
adjust.QuadPart = 11644473600000 * 10000;
|
||||
date.QuadPart -= adjust.QuadPart;
|
||||
|
||||
res->seconds = date.QuadPart / 10000000;
|
||||
res->nanoseconds = (date.QuadPart % 10000000) * (PSNIP_CLOCK_NSEC_PER_SEC / 100);
|
||||
#elif PSNIP_CLOCK_CPU_METHOD == PSNIP_CLOCK_METHOD_GETRUSAGE
|
||||
struct rusage usage;
|
||||
if (getrusage(RUSAGE_SELF, &usage) != 0)
|
||||
return -8;
|
||||
|
||||
res->seconds = usage.ru_utime.tv_sec;
|
||||
res->nanoseconds = tv.tv_usec * 1000;
|
||||
#else
|
||||
(void) res;
|
||||
return -2;
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
PSNIP_CLOCK__FUNCTION psnip_uint32_t
|
||||
psnip_clock_monotonic_get_precision (void) {
|
||||
#if !defined(PSNIP_CLOCK_MONOTONIC_METHOD)
|
||||
return 0;
|
||||
#elif defined(PSNIP_CLOCK_MONOTONIC_METHOD) && PSNIP_CLOCK_MONOTONIC_METHOD == PSNIP_CLOCK_METHOD_CLOCK_GETTIME
|
||||
return psnip_clock__clock_getres(PSNIP_CLOCK_CLOCK_GETTIME_MONOTONIC);
|
||||
#elif defined(PSNIP_CLOCK_MONOTONIC_METHOD) && PSNIP_CLOCK_MONOTONIC_METHOD == PSNIP_CLOCK_METHOD_MACH_ABSOLUTE_TIME
|
||||
static mach_timebase_info_data_t tbi = { 0, };
|
||||
if (tbi.denom == 0)
|
||||
mach_timebase_info(&tbi);
|
||||
return (psnip_uint32_t) (tbi.numer / tbi.denom);
|
||||
#elif defined(PSNIP_CLOCK_MONOTONIC_METHOD) && PSNIP_CLOCK_MONOTONIC_METHOD == PSNIP_CLOCK_METHOD_GETTICKCOUNT64
|
||||
return 1000;
|
||||
#elif defined(PSNIP_CLOCK_MONOTONIC_METHOD) && PSNIP_CLOCK_MONOTONIC_METHOD == PSNIP_CLOCK_METHOD_QUERYPERFORMANCECOUNTER
|
||||
LARGE_INTEGER Frequency;
|
||||
QueryPerformanceFrequency(&Frequency);
|
||||
return (psnip_uint32_t) ((Frequency.QuadPart > PSNIP_CLOCK_NSEC_PER_SEC) ? PSNIP_CLOCK_NSEC_PER_SEC : Frequency.QuadPart);
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
PSNIP_CLOCK__FUNCTION int
|
||||
psnip_clock_monotonic_get_time (struct PsnipClockTimespec* res) {
|
||||
#if !defined(PSNIP_CLOCK_MONOTONIC_METHOD)
|
||||
(void) res;
|
||||
return -2;
|
||||
#elif defined(PSNIP_CLOCK_MONOTONIC_METHOD) && PSNIP_CLOCK_MONOTONIC_METHOD == PSNIP_CLOCK_METHOD_CLOCK_GETTIME
|
||||
return psnip_clock__clock_gettime(PSNIP_CLOCK_CLOCK_GETTIME_MONOTONIC, res);
|
||||
#elif defined(PSNIP_CLOCK_MONOTONIC_METHOD) && PSNIP_CLOCK_MONOTONIC_METHOD == PSNIP_CLOCK_METHOD_MACH_ABSOLUTE_TIME
|
||||
psnip_uint64_t nsec = mach_absolute_time();
|
||||
static mach_timebase_info_data_t tbi = { 0, };
|
||||
if (tbi.denom == 0)
|
||||
mach_timebase_info(&tbi);
|
||||
nsec *= ((psnip_uint64_t) tbi.numer) / ((psnip_uint64_t) tbi.denom);
|
||||
res->seconds = nsec / PSNIP_CLOCK_NSEC_PER_SEC;
|
||||
res->nanoseconds = nsec % PSNIP_CLOCK_NSEC_PER_SEC;
|
||||
#elif defined(PSNIP_CLOCK_MONOTONIC_METHOD) && PSNIP_CLOCK_MONOTONIC_METHOD == PSNIP_CLOCK_METHOD_QUERYPERFORMANCECOUNTER
|
||||
LARGE_INTEGER t, f;
|
||||
if (QueryPerformanceCounter(&t) == 0)
|
||||
return -12;
|
||||
|
||||
QueryPerformanceFrequency(&f);
|
||||
res->seconds = t.QuadPart / f.QuadPart;
|
||||
res->nanoseconds = t.QuadPart % f.QuadPart;
|
||||
if (f.QuadPart > PSNIP_CLOCK_NSEC_PER_SEC)
|
||||
res->nanoseconds /= f.QuadPart / PSNIP_CLOCK_NSEC_PER_SEC;
|
||||
else
|
||||
res->nanoseconds *= PSNIP_CLOCK_NSEC_PER_SEC / f.QuadPart;
|
||||
#elif defined(PSNIP_CLOCK_MONOTONIC_METHOD) && PSNIP_CLOCK_MONOTONIC_METHOD == PSNIP_CLOCK_METHOD_GETTICKCOUNT64
|
||||
const ULONGLONG msec = GetTickCount64();
|
||||
res->seconds = msec / 1000;
|
||||
res->nanoseconds = sec % 1000;
|
||||
#else
|
||||
return -2;
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Returns the number of ticks per second for the specified clock.
|
||||
* For example, a clock with millisecond precision would return 1000,
|
||||
* and a clock with 1 second (such as the time() function) would
|
||||
* return 1.
|
||||
*
|
||||
* If the requested clock isn't available, it will return 0.
|
||||
* Hopefully this will be rare, but if it happens to you please let us
|
||||
* know so we can work on finding a way to support your system.
|
||||
*
|
||||
* Note that different clocks on the same system often have a
|
||||
* different precisions.
|
||||
*/
|
||||
PSNIP_CLOCK__FUNCTION psnip_uint32_t
|
||||
psnip_clock_get_precision (enum PsnipClockType clock_type) {
|
||||
switch (clock_type) {
|
||||
case PSNIP_CLOCK_TYPE_MONOTONIC:
|
||||
return psnip_clock_monotonic_get_precision ();
|
||||
case PSNIP_CLOCK_TYPE_CPU:
|
||||
return psnip_clock_cpu_get_precision ();
|
||||
case PSNIP_CLOCK_TYPE_WALL:
|
||||
return psnip_clock_wall_get_precision ();
|
||||
}
|
||||
|
||||
PSNIP_CLOCK_UNREACHABLE();
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Set the provided timespec to the requested time. Returns 0 on
|
||||
* success, or a negative value on failure. */
|
||||
PSNIP_CLOCK__FUNCTION int
|
||||
psnip_clock_get_time (enum PsnipClockType clock_type, struct PsnipClockTimespec* res) {
|
||||
assert(res != NULL);
|
||||
|
||||
switch (clock_type) {
|
||||
case PSNIP_CLOCK_TYPE_MONOTONIC:
|
||||
return psnip_clock_monotonic_get_time (res);
|
||||
case PSNIP_CLOCK_TYPE_CPU:
|
||||
return psnip_clock_cpu_get_time (res);
|
||||
case PSNIP_CLOCK_TYPE_WALL:
|
||||
return psnip_clock_wall_get_time (res);
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
#endif /* !defined(PSNIP_CLOCK_H) */
|
||||
16
thirdparty/portable-snippets/cpu/README.md
vendored
Normal file
16
thirdparty/portable-snippets/cpu/README.md
vendored
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
# CPU Information
|
||||
|
||||
This module provides an API for querying some CPU features, such as
|
||||
ISA extension support, that works across multiple architectures and
|
||||
platforms.
|
||||
|
||||
## Dependencies
|
||||
|
||||
This module requires the once portable-snippet module. If you do not
|
||||
include once.h before cpu.h, cpu.h will automatically include
|
||||
"../once/once.h". If you include once.h manually you are free to use
|
||||
whatever directory structure you like.
|
||||
|
||||
## Limitations
|
||||
|
||||
This code currently only supports x86/x86-64 and ARM.
|
||||
167
thirdparty/portable-snippets/cpu/cpu.c
vendored
Normal file
167
thirdparty/portable-snippets/cpu/cpu.c
vendored
Normal file
|
|
@ -0,0 +1,167 @@
|
|||
/* CPU Information (v1)
|
||||
* Portable Snippets - https://github.com/nemequ/portable-snippets
|
||||
* Created by Evan Nemerson <evan@nemerson.com>
|
||||
*
|
||||
* To the extent possible under law, the authors have waived all
|
||||
* copyright and related or neighboring rights to this code. For
|
||||
* details, see the Creative Commons Zero 1.0 Universal license at
|
||||
* https://creativecommons.org/publicdomain/zero/1.0/
|
||||
*/
|
||||
|
||||
#include "cpu.h"
|
||||
|
||||
#if !defined(PSNIP_ONCE__H)
|
||||
# include "../once/once.h"
|
||||
#endif
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
#if defined(_WIN32)
|
||||
# include <Windows.h>
|
||||
# define PSNIP_CPU__IMPL_WIN32
|
||||
#elif defined(unix) || defined(__unix__) || defined(__unix)
|
||||
# include <unistd.h>
|
||||
# if defined(_SC_NPROCESSORS_ONLN) || defined(_SC_NPROC_ONLN)
|
||||
# define PSNIP_CPU__IMPL_SYSCONF
|
||||
# else
|
||||
# include <sys/sysctl.h>
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#if defined(PSNIP_CPU_ARCH_X86) || defined(PSNIP_CPU_ARCH_X86_64)
|
||||
# if defined(_MSC_VER)
|
||||
static void psnip_cpu_getid(int func, int* data) {
|
||||
__cpuid(data, func);
|
||||
}
|
||||
# else
|
||||
static void psnip_cpu_getid(int func, int* data) {
|
||||
__asm__ ("cpuid"
|
||||
: "=a" (data[0]), "=b" (data[1]), "=c" (data[2]), "=d" (data[3])
|
||||
: "0" (func), "2" (0));
|
||||
}
|
||||
# endif
|
||||
#elif defined(PSNIP_CPU_ARCH_ARM) || defined(PSNIP_CPU_ARCH_ARM64)
|
||||
# if (defined(__GNUC__) && ((__GNUC__ > 2) || (__GNUC__ == 2 && __GNUC_MINOR__ >= 16)))
|
||||
# define PSNIP_CPU__IMPL_GETAUXVAL
|
||||
# include <sys/auxv.h>
|
||||
# endif
|
||||
#endif
|
||||
|
||||
static psnip_once psnip_cpu_once = PSNIP_ONCE_INIT;
|
||||
|
||||
#if defined(PSNIP_CPU_ARCH_X86) || defined(PSNIP_CPU_ARCH_X86_64)
|
||||
static unsigned int psnip_cpuinfo[8 * 4] = { 0, };
|
||||
#elif defined(PSNIP_CPU_ARCH_ARM) || defined(PSNIP_CPU_ARCH_ARM_64)
|
||||
static unsigned long psnip_cpuinfo[2] = { 0, };
|
||||
#endif
|
||||
|
||||
static void psnip_cpu_init(void) {
|
||||
#if defined(PSNIP_CPU_ARCH_X86) || defined(PSNIP_CPU_ARCH_X86_64)
|
||||
int i;
|
||||
for (i = 0 ; i < 8 ; i++) {
|
||||
psnip_cpu_getid(i, (int*) &(psnip_cpuinfo[i * 4]));
|
||||
}
|
||||
#elif defined(PSNIP_CPU_ARCH_ARM) || defined(PSNIP_CPU_ARCH_ARM_64)
|
||||
psnip_cpuinfo[0] = getauxval (AT_HWCAP);
|
||||
psnip_cpuinfo[1] = getauxval (AT_HWCAP2);
|
||||
#endif
|
||||
}
|
||||
|
||||
int
|
||||
psnip_cpu_feature_check (enum PSnipCPUFeature feature) {
|
||||
#if defined(PSNIP_CPU_ARCH_X86) || defined(PSNIP_CPU_ARCH_X86_64)
|
||||
unsigned int i, r, b;
|
||||
#elif defined(PSNIP_CPU_ARCH_ARM) || defined(PSNIP_CPU_ARCH_ARM_64)
|
||||
unsigned long b, i;
|
||||
#endif
|
||||
|
||||
#if defined(PSNIP_CPU_ARCH_X86) || defined(PSNIP_CPU_ARCH_X86_64)
|
||||
if ((feature & PSNIP_CPU_FEATURE_CPU_MASK) != PSNIP_CPU_FEATURE_X86)
|
||||
return 0;
|
||||
#elif defined(PSNIP_CPU_ARCH_ARM) || defined(PSNIP_CPU_ARCH_ARM_64)
|
||||
if ((feature & PSNIP_CPU_FEATURE_CPU_MASK) != PSNIP_CPU_FEATURE_ARM)
|
||||
return 0;
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
|
||||
feature &= (enum PSnipCPUFeature) ~PSNIP_CPU_FEATURE_CPU_MASK;
|
||||
#if defined(_MSC_VER)
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable:4152)
|
||||
#endif
|
||||
psnip_once_call (&psnip_cpu_once, psnip_cpu_init);
|
||||
#if defined(_MSC_VER)
|
||||
#pragma warning(pop)
|
||||
#endif
|
||||
|
||||
#if defined(PSNIP_CPU_ARCH_X86) || defined(PSNIP_CPU_ARCH_X86_64)
|
||||
i = (feature >> 16) & 0xff;
|
||||
r = (feature >> 8) & 0xff;
|
||||
b = (feature ) & 0xff;
|
||||
|
||||
if (i > 7 || r > 3 || b > 31)
|
||||
return 0;
|
||||
|
||||
return (psnip_cpuinfo[(i * 4) + r] >> b) & 1;
|
||||
#elif defined(PSNIP_CPU_ARCH_ARM) || defined(PSNIP_CPU_ARCH_ARM_64)
|
||||
b = 1 << ((feature & 0xff) - 1);
|
||||
i = psnip_cpuinfo[(feature >> 0x08) & 0xff];
|
||||
return (psnip_cpuinfo[(feature >> 0x08) & 0xff] & b) == b;
|
||||
#endif
|
||||
}
|
||||
|
||||
int
|
||||
psnip_cpu_feature_check_many (enum PSnipCPUFeature* feature) {
|
||||
int n;
|
||||
|
||||
for (n = 0 ; feature[n] != PSNIP_CPU_FEATURE_NONE ; n++)
|
||||
if (!psnip_cpu_feature_check(feature[n]))
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int
|
||||
psnip_cpu_count (void) {
|
||||
static int count = 0;
|
||||
int c;
|
||||
|
||||
#if defined(_WIN32)
|
||||
DWORD_PTR lpProcessAffinityMask;
|
||||
DWORD_PTR lpSystemAffinityMask;
|
||||
int i;
|
||||
#elif defined(PSNIP_CPU__IMPL_SYSCONF) && defined(HW_NCPU)
|
||||
int mib[2];
|
||||
size_t len;
|
||||
#endif
|
||||
|
||||
if (count != 0)
|
||||
return count;
|
||||
|
||||
#if defined(_WIN32)
|
||||
if (!GetProcessAffinityMask(GetCurrentProcess(), &lpProcessAffinityMask, &lpSystemAffinityMask)) {
|
||||
c = -1;
|
||||
} else {
|
||||
c = 0;
|
||||
for (i = 0 ; lpProcessAffinityMask != 0 ; lpProcessAffinityMask >>= 1)
|
||||
c += lpProcessAffinityMask & 1;
|
||||
}
|
||||
#elif defined(_SC_NPROCESSORS_ONLN)
|
||||
c = sysconf (_SC_NPROCESSORS_ONLN);
|
||||
#elif defined(_SC_NPROC_ONLN)
|
||||
c = sysconf (_SC_NPROC_ONLN);
|
||||
#elif defined(_hpux)
|
||||
c = mpctl(MPC_GETNUMSPUS, NULL, NULL);
|
||||
#elif defined(HW_NCPU)
|
||||
c = 0;
|
||||
mib[0] = CTL_HW;
|
||||
mib[1] = HW_NCPU;
|
||||
len = sizeof(c);
|
||||
sysctl (mib, 2, &c, &len, NULL, 0);
|
||||
#endif
|
||||
|
||||
count = (c > 0) ? c : -1;
|
||||
|
||||
return count;
|
||||
}
|
||||
190
thirdparty/portable-snippets/cpu/cpu.h
vendored
Normal file
190
thirdparty/portable-snippets/cpu/cpu.h
vendored
Normal file
|
|
@ -0,0 +1,190 @@
|
|||
/* CPU Information (v1)
|
||||
* Portable Snippets - https://github.com/nemequ/portable-snippets
|
||||
* Created by Evan Nemerson <evan@nemerson.com>
|
||||
*
|
||||
* To the extent possible under law, the authors have waived all
|
||||
* copyright and related or neighboring rights to this code. For
|
||||
* details, see the Creative Commons Zero 1.0 Universal license at
|
||||
* https://creativecommons.org/publicdomain/zero/1.0/
|
||||
*/
|
||||
|
||||
#if !defined(PSNIP_CPU__H)
|
||||
#define PSNIP_CPU__H
|
||||
|
||||
#if defined(__x86_64__) || defined(_M_AMD64) || defined(_M_X64)
|
||||
# define PSNIP_CPU_ARCH_X86_64
|
||||
#elif defined(__i686__) || defined(__i586__) || defined(__i486__) || defined(__i386__) || defined(__i386) || defined(_M_IX86) || defined(_X86_) || defined(__THW_INTEL__)
|
||||
# define PSNIP_CPU_ARCH_X86
|
||||
#elif defined(__arm__) || defined(_M_ARM)
|
||||
# define PSNIP_CPU_ARCH_ARM
|
||||
#elif defined(__aarch64__)
|
||||
# define PSNIP_CPU_ARCH_ARM64
|
||||
#endif
|
||||
|
||||
#if defined(__cplusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
enum PSnipCPUFeature {
|
||||
PSNIP_CPU_FEATURE_NONE = 0,
|
||||
|
||||
PSNIP_CPU_FEATURE_CPU_MASK = 0x1f000000,
|
||||
PSNIP_CPU_FEATURE_X86 = 0x01000000,
|
||||
PSNIP_CPU_FEATURE_ARM = 0x04000000,
|
||||
|
||||
/* x86 CPU features are constructed as:
|
||||
*
|
||||
* (PSNIP_CPU_FEATURE_X86 | (eax << 16) | (ret_reg << 8) | (bit_position)
|
||||
*
|
||||
* For example, SSE3 is determined by the fist bit in the ECX
|
||||
* register for a CPUID call with EAX=1, so we get:
|
||||
*
|
||||
* PSNIP_CPU_FEATURE_X86 | (1 << 16) | (2 << 8) | (0) = 0x01010200
|
||||
*
|
||||
* We should have information for inputs of EAX=0-7 w/ ECX=0.
|
||||
*/
|
||||
PSNIP_CPU_FEATURE_X86_FPU = 0x01010300,
|
||||
PSNIP_CPU_FEATURE_X86_VME = 0x01010301,
|
||||
PSNIP_CPU_FEATURE_X86_DE = 0x01010302,
|
||||
PSNIP_CPU_FEATURE_X86_PSE = 0x01010303,
|
||||
PSNIP_CPU_FEATURE_X86_TSC = 0x01010304,
|
||||
PSNIP_CPU_FEATURE_X86_MSR = 0x01010305,
|
||||
PSNIP_CPU_FEATURE_X86_PAE = 0x01010306,
|
||||
PSNIP_CPU_FEATURE_X86_MCE = 0x01010307,
|
||||
PSNIP_CPU_FEATURE_X86_CX8 = 0x01010308,
|
||||
PSNIP_CPU_FEATURE_X86_APIC = 0x01010309,
|
||||
PSNIP_CPU_FEATURE_X86_SEP = 0x0101030b,
|
||||
PSNIP_CPU_FEATURE_X86_MTRR = 0x0101030c,
|
||||
PSNIP_CPU_FEATURE_X86_PGE = 0x0101030d,
|
||||
PSNIP_CPU_FEATURE_X86_MCA = 0x0101030e,
|
||||
PSNIP_CPU_FEATURE_X86_CMOV = 0x0101030f,
|
||||
PSNIP_CPU_FEATURE_X86_PAT = 0x01010310,
|
||||
PSNIP_CPU_FEATURE_X86_PSE_36 = 0x01010311,
|
||||
PSNIP_CPU_FEATURE_X86_PSN = 0x01010312,
|
||||
PSNIP_CPU_FEATURE_X86_CLFSH = 0x01010313,
|
||||
PSNIP_CPU_FEATURE_X86_DS = 0x01010314,
|
||||
PSNIP_CPU_FEATURE_X86_ACPI = 0x01010316,
|
||||
PSNIP_CPU_FEATURE_X86_MMX = 0x01010317,
|
||||
PSNIP_CPU_FEATURE_X86_FXSR = 0x01010318,
|
||||
PSNIP_CPU_FEATURE_X86_SSE = 0x01010319,
|
||||
PSNIP_CPU_FEATURE_X86_SSE2 = 0x0101031a,
|
||||
PSNIP_CPU_FEATURE_X86_SS = 0x0101031b,
|
||||
PSNIP_CPU_FEATURE_X86_HTT = 0x0101031c,
|
||||
PSNIP_CPU_FEATURE_X86_TM = 0x0101031d,
|
||||
PSNIP_CPU_FEATURE_X86_IA64 = 0x0101031e,
|
||||
PSNIP_CPU_FEATURE_X86_PBE = 0x0101031f,
|
||||
|
||||
PSNIP_CPU_FEATURE_X86_SSE3 = 0x01010200,
|
||||
PSNIP_CPU_FEATURE_X86_PCLMULQDQ = 0x01010201,
|
||||
PSNIP_CPU_FEATURE_X86_DTES64 = 0x01010202,
|
||||
PSNIP_CPU_FEATURE_X86_MONITOR = 0x01010203,
|
||||
PSNIP_CPU_FEATURE_X86_DS_CPL = 0x01010204,
|
||||
PSNIP_CPU_FEATURE_X86_VMX = 0x01010205,
|
||||
PSNIP_CPU_FEATURE_X86_SMX = 0x01010206,
|
||||
PSNIP_CPU_FEATURE_X86_EST = 0x01010207,
|
||||
PSNIP_CPU_FEATURE_X86_TM2 = 0x01010208,
|
||||
PSNIP_CPU_FEATURE_X86_SSSE3 = 0x01010209,
|
||||
PSNIP_CPU_FEATURE_X86_CNXT_ID = 0x0101020a,
|
||||
PSNIP_CPU_FEATURE_X86_SDBG = 0x0101020b,
|
||||
PSNIP_CPU_FEATURE_X86_FMA = 0x0101020c,
|
||||
PSNIP_CPU_FEATURE_X86_CX16 = 0x0101020d,
|
||||
PSNIP_CPU_FEATURE_X86_XTPR = 0x0101020e,
|
||||
PSNIP_CPU_FEATURE_X86_PDCM = 0x0101020f,
|
||||
PSNIP_CPU_FEATURE_X86_PCID = 0x01010211,
|
||||
PSNIP_CPU_FEATURE_X86_DCA = 0x01010212,
|
||||
PSNIP_CPU_FEATURE_X86_SSE4_1 = 0x01010213,
|
||||
PSNIP_CPU_FEATURE_X86_SSE4_2 = 0x01010214,
|
||||
PSNIP_CPU_FEATURE_X86_X2APIC = 0x01010215,
|
||||
PSNIP_CPU_FEATURE_X86_MOVBE = 0x01010216,
|
||||
PSNIP_CPU_FEATURE_X86_POPCNT = 0x01010217,
|
||||
PSNIP_CPU_FEATURE_X86_TSC_DEADLINE = 0x01010218,
|
||||
PSNIP_CPU_FEATURE_X86_AES = 0x01010219,
|
||||
PSNIP_CPU_FEATURE_X86_XSAVE = 0x0101021a,
|
||||
PSNIP_CPU_FEATURE_X86_OSXSAVE = 0x0101021b,
|
||||
PSNIP_CPU_FEATURE_X86_AVX = 0x0101021c,
|
||||
PSNIP_CPU_FEATURE_X86_F16C = 0x0101021d,
|
||||
PSNIP_CPU_FEATURE_X86_RDRND = 0x0101021e,
|
||||
PSNIP_CPU_FEATURE_X86_HYPERVISOR = 0x0101021f,
|
||||
|
||||
PSNIP_CPU_FEATURE_X86_FSGSBASE = 0x01070100,
|
||||
PSNIP_CPU_FEATURE_X86_TSC_ADJ = 0x01070101,
|
||||
PSNIP_CPU_FEATURE_X86_SGX = 0x01070102,
|
||||
PSNIP_CPU_FEATURE_X86_BMI1 = 0x01070103,
|
||||
PSNIP_CPU_FEATURE_X86_HLE = 0x01070104,
|
||||
PSNIP_CPU_FEATURE_X86_AVX2 = 0x01070105,
|
||||
PSNIP_CPU_FEATURE_X86_SMEP = 0x01070107,
|
||||
PSNIP_CPU_FEATURE_X86_BMI2 = 0x01070108,
|
||||
PSNIP_CPU_FEATURE_X86_ERMS = 0x01070109,
|
||||
PSNIP_CPU_FEATURE_X86_INVPCID = 0x0107010a,
|
||||
PSNIP_CPU_FEATURE_X86_RTM = 0x0107010b,
|
||||
PSNIP_CPU_FEATURE_X86_PQM = 0x0107010c,
|
||||
PSNIP_CPU_FEATURE_X86_MPX = 0x0107010e,
|
||||
PSNIP_CPU_FEATURE_X86_PQE = 0x0107010f,
|
||||
PSNIP_CPU_FEATURE_X86_AVX512F = 0x01070110,
|
||||
PSNIP_CPU_FEATURE_X86_AVX512DQ = 0x01070111,
|
||||
PSNIP_CPU_FEATURE_X86_RDSEED = 0x01070112,
|
||||
PSNIP_CPU_FEATURE_X86_ADX = 0x01070113,
|
||||
PSNIP_CPU_FEATURE_X86_SMAP = 0x01070114,
|
||||
PSNIP_CPU_FEATURE_X86_AVX512IFMA = 0x01070115,
|
||||
PSNIP_CPU_FEATURE_X86_PCOMMIT = 0x01070116,
|
||||
PSNIP_CPU_FEATURE_X86_CLFLUSHOPT = 0x01070117,
|
||||
PSNIP_CPU_FEATURE_X86_CLWB = 0x01070118,
|
||||
PSNIP_CPU_FEATURE_X86_INTEL_PT = 0x01070119,
|
||||
PSNIP_CPU_FEATURE_X86_AVX512PF = 0x0107011a,
|
||||
PSNIP_CPU_FEATURE_X86_AVX512ER = 0x0107011b,
|
||||
PSNIP_CPU_FEATURE_X86_AVX512CD = 0x0107011c,
|
||||
PSNIP_CPU_FEATURE_X86_SHA = 0x0107011d,
|
||||
PSNIP_CPU_FEATURE_X86_AVX512BW = 0x0107011e,
|
||||
PSNIP_CPU_FEATURE_X86_AVX512VL = 0x0107011f,
|
||||
|
||||
PSNIP_CPU_FEATURE_X86_PREFETCHWT1 = 0x01070200,
|
||||
PSNIP_CPU_FEATURE_X86_AVX512VBMI = 0x01070201,
|
||||
PSNIP_CPU_FEATURE_X86_UMIP = 0x01070202,
|
||||
PSNIP_CPU_FEATURE_X86_PKU = 0x01070203,
|
||||
PSNIP_CPU_FEATURE_X86_OSPKE = 0x01070204,
|
||||
PSNIP_CPU_FEATURE_X86_AVX512VPOPCNTDQ = 0x0107020e,
|
||||
PSNIP_CPU_FEATURE_X86_RDPID = 0x01070215,
|
||||
PSNIP_CPU_FEATURE_X86_SGX_LC = 0x0107021e,
|
||||
|
||||
PSNIP_CPU_FEATURE_X86_AVX512_4VNNIW = 0x01070302,
|
||||
PSNIP_CPU_FEATURE_X86_AVX512_4FMAPS = 0x01070303,
|
||||
|
||||
PSNIP_CPU_FEATURE_ARM_SWP = PSNIP_CPU_FEATURE_ARM | 1,
|
||||
PSNIP_CPU_FEATURE_ARM_HALF = PSNIP_CPU_FEATURE_ARM | 2,
|
||||
PSNIP_CPU_FEATURE_ARM_THUMB = PSNIP_CPU_FEATURE_ARM | 3,
|
||||
PSNIP_CPU_FEATURE_ARM_26BIT = PSNIP_CPU_FEATURE_ARM | 4,
|
||||
PSNIP_CPU_FEATURE_ARM_FAST_MULT = PSNIP_CPU_FEATURE_ARM | 5,
|
||||
PSNIP_CPU_FEATURE_ARM_FPA = PSNIP_CPU_FEATURE_ARM | 6,
|
||||
PSNIP_CPU_FEATURE_ARM_VFP = PSNIP_CPU_FEATURE_ARM | 7,
|
||||
PSNIP_CPU_FEATURE_ARM_EDSP = PSNIP_CPU_FEATURE_ARM | 8,
|
||||
PSNIP_CPU_FEATURE_ARM_JAVA = PSNIP_CPU_FEATURE_ARM | 9,
|
||||
PSNIP_CPU_FEATURE_ARM_IWMMXT = PSNIP_CPU_FEATURE_ARM | 10,
|
||||
PSNIP_CPU_FEATURE_ARM_CRUNCH = PSNIP_CPU_FEATURE_ARM | 11,
|
||||
PSNIP_CPU_FEATURE_ARM_THUMBEE = PSNIP_CPU_FEATURE_ARM | 12,
|
||||
PSNIP_CPU_FEATURE_ARM_NEON = PSNIP_CPU_FEATURE_ARM | 13,
|
||||
PSNIP_CPU_FEATURE_ARM_VFPV3 = PSNIP_CPU_FEATURE_ARM | 14,
|
||||
PSNIP_CPU_FEATURE_ARM_VFPV3D16 = PSNIP_CPU_FEATURE_ARM | 15,
|
||||
PSNIP_CPU_FEATURE_ARM_TLS = PSNIP_CPU_FEATURE_ARM | 16,
|
||||
PSNIP_CPU_FEATURE_ARM_VFPV4 = PSNIP_CPU_FEATURE_ARM | 17,
|
||||
PSNIP_CPU_FEATURE_ARM_IDIVA = PSNIP_CPU_FEATURE_ARM | 18,
|
||||
PSNIP_CPU_FEATURE_ARM_IDIVT = PSNIP_CPU_FEATURE_ARM | 19,
|
||||
PSNIP_CPU_FEATURE_ARM_VFPD32 = PSNIP_CPU_FEATURE_ARM | 20,
|
||||
PSNIP_CPU_FEATURE_ARM_LPAE = PSNIP_CPU_FEATURE_ARM | 21,
|
||||
PSNIP_CPU_FEATURE_ARM_EVTSTRM = PSNIP_CPU_FEATURE_ARM | 22,
|
||||
|
||||
PSNIP_CPU_FEATURE_ARM_AES = PSNIP_CPU_FEATURE_ARM | 0x0100 | 1,
|
||||
PSNIP_CPU_FEATURE_ARM_PMULL = PSNIP_CPU_FEATURE_ARM | 0x0100 | 2,
|
||||
PSNIP_CPU_FEATURE_ARM_SHA1 = PSNIP_CPU_FEATURE_ARM | 0x0100 | 3,
|
||||
PSNIP_CPU_FEATURE_ARM_SHA2 = PSNIP_CPU_FEATURE_ARM | 0x0100 | 4,
|
||||
PSNIP_CPU_FEATURE_ARM_CRC32 = PSNIP_CPU_FEATURE_ARM | 0x0100 | 5
|
||||
};
|
||||
|
||||
int psnip_cpu_count (void);
|
||||
int psnip_cpu_feature_check (enum PSnipCPUFeature feature);
|
||||
int psnip_cpu_feature_check_many (enum PSnipCPUFeature* feature);
|
||||
|
||||
#if defined(__cplusplus)
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* PSNIP_CPU__H */
|
||||
24
thirdparty/portable-snippets/debug-trap/README.md
vendored
Normal file
24
thirdparty/portable-snippets/debug-trap/README.md
vendored
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
# Debugging assertions and traps
|
||||
|
||||
This is an attempt to provide a fairly portable way to generate traps
|
||||
in code. `__builtin_trap` is `_Noreturn`, so the compiler may optimize
|
||||
away code found after it, which means you can't really drop into a
|
||||
debugger and step through the code after the trap has been hit.
|
||||
|
||||
If `PSNIP_NDEBUG` is defined, or `NDEBUG` is defined and `PSNIP_DEBUG`
|
||||
is not, `psnip_dbg_assert(expr)` will be preprocessed to nothing
|
||||
(i.e., `expr` will not be evaluated). Otherwise it will call
|
||||
`psnip_trap` if `expr` evaluates to false.
|
||||
|
||||
Knowledge about how to do this portably basically comes from:
|
||||
|
||||
* [scottt/debugbreak](https://github.com/scottt/debugbreak/).
|
||||
* GLib's [G_BREAKPOINT](https://developer.gnome.org/glib/stable/glib-Warnings-and-Assertions.html#G-BREAKPOINT:CAPS) macro.
|
||||
* [TI's Wiki](http://processors.wiki.ti.com/index.php/Software_Breakpoints_in_the_IDE)
|
||||
* Assorted compiler documentation.
|
||||
|
||||
On non-hosted platforms we *may* have to fall back on
|
||||
`__builtin_trap`. On non-hosted non-GNU-compatible compilers on
|
||||
relatively exotic architectures you may end up with an error about
|
||||
stdlib.h being missing... if you have a good way to resolve that on
|
||||
your platform please contact us.
|
||||
83
thirdparty/portable-snippets/debug-trap/debug-trap.h
vendored
Normal file
83
thirdparty/portable-snippets/debug-trap/debug-trap.h
vendored
Normal file
|
|
@ -0,0 +1,83 @@
|
|||
/* Debugging assertions and traps
|
||||
* Portable Snippets - https://github.com/nemequ/portable-snippets
|
||||
* Created by Evan Nemerson <evan@nemerson.com>
|
||||
*
|
||||
* To the extent possible under law, the authors have waived all
|
||||
* copyright and related or neighboring rights to this code. For
|
||||
* details, see the Creative Commons Zero 1.0 Universal license at
|
||||
* https://creativecommons.org/publicdomain/zero/1.0/
|
||||
*/
|
||||
|
||||
#if !defined(PSNIP_DEBUG_TRAP_H)
|
||||
#define PSNIP_DEBUG_TRAP_H
|
||||
|
||||
#if !defined(PSNIP_NDEBUG) && defined(NDEBUG) && !defined(PSNIP_DEBUG)
|
||||
# define PSNIP_NDEBUG 1
|
||||
#endif
|
||||
|
||||
#if defined(__has_builtin) && !defined(__ibmxl__)
|
||||
# if __has_builtin(__builtin_debugtrap)
|
||||
# define psnip_trap() __builtin_debugtrap()
|
||||
# elif __has_builtin(__debugbreak)
|
||||
# define psnip_trap() __debugbreak()
|
||||
# endif
|
||||
#endif
|
||||
#if !defined(psnip_trap)
|
||||
# if defined(_MSC_VER) || defined(__INTEL_COMPILER)
|
||||
# define psnip_trap() __debugbreak()
|
||||
# elif defined(__ARMCC_VERSION)
|
||||
# define psnip_trap() __breakpoint(42)
|
||||
# elif defined(__ibmxl__) || defined(__xlC__)
|
||||
# include <builtins.h>
|
||||
# define psnip_trap() __trap(42)
|
||||
# elif defined(__DMC__) && defined(_M_IX86)
|
||||
static inline void psnip_trap(void) { __asm int 3h; }
|
||||
# elif defined(__i386__) || defined(__x86_64__)
|
||||
static inline void psnip_trap(void) { __asm__ __volatile__("int3"); }
|
||||
# elif defined(__thumb__)
|
||||
static inline void psnip_trap(void) { __asm__ __volatile__(".inst 0xde01"); }
|
||||
# elif defined(__aarch64__)
|
||||
static inline void psnip_trap(void) { __asm__ __volatile__(".inst 0xd4200000"); }
|
||||
# elif defined(__arm__)
|
||||
static inline void psnip_trap(void) { __asm__ __volatile__(".inst 0xe7f001f0"); }
|
||||
# elif defined (__alpha__) && !defined(__osf__)
|
||||
static inline void psnip_trap(void) { __asm__ __volatile__("bpt"); }
|
||||
# elif defined(_54_)
|
||||
static inline void psnip_trap(void) { __asm__ __volatile__("ESTOP"); }
|
||||
# elif defined(_55_)
|
||||
static inline void psnip_trap(void) { __asm__ __volatile__(";\n .if (.MNEMONIC)\n ESTOP_1\n .else\n ESTOP_1()\n .endif\n NOP"); }
|
||||
# elif defined(_64P_)
|
||||
static inline void psnip_trap(void) { __asm__ __volatile__("SWBP 0"); }
|
||||
# elif defined(_6x_)
|
||||
static inline void psnip_trap(void) { __asm__ __volatile__("NOP\n .word 0x10000000"); }
|
||||
# elif defined(__STDC_HOSTED__) && (__STDC_HOSTED__ == 0) && defined(__GNUC__)
|
||||
# define psnip_trap() __builtin_trap()
|
||||
# else
|
||||
# include <signal.h>
|
||||
# if defined(SIGTRAP)
|
||||
# define psnip_trap() raise(SIGTRAP)
|
||||
# else
|
||||
# define psnip_trap() raise(SIGABRT)
|
||||
# endif
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#if defined(HEDLEY_LIKELY)
|
||||
# define PSNIP_DBG_LIKELY(expr) HEDLEY_LIKELY(expr)
|
||||
#elif defined(__GNUC__) && (__GNUC__ >= 3)
|
||||
# define PSNIP_DBG_LIKELY(expr) __builtin_expect(!!(expr), 1)
|
||||
#else
|
||||
# define PSNIP_DBG_LIKELY(expr) (!!(expr))
|
||||
#endif
|
||||
|
||||
#if !defined(PSNIP_NDEBUG) || (PSNIP_NDEBUG == 0)
|
||||
# define psnip_dbg_assert(expr) do { \
|
||||
if (!PSNIP_DBG_LIKELY(expr)) { \
|
||||
psnip_trap(); \
|
||||
} \
|
||||
} while (0)
|
||||
#else
|
||||
# define psnip_dbg_assert(expr)
|
||||
#endif
|
||||
|
||||
#endif /* !defined(PSNIP_DEBUG_TRAP_H) */
|
||||
53
thirdparty/portable-snippets/endian/README.md
vendored
Normal file
53
thirdparty/portable-snippets/endian/README.md
vendored
Normal file
|
|
@ -0,0 +1,53 @@
|
|||
# Endianness Detection and Swapping
|
||||
|
||||
This header provides a convenient way to detect endianness, and
|
||||
perform swapping. It provides 6 important functions:
|
||||
|
||||
```c
|
||||
psnip_uint16_t psnip_endian_le16(psnip_uint16_t v);
|
||||
psnip_uint32_t psnip_endian_le32(psnip_uint32_t v);
|
||||
psnip_uint64_t psnip_endian_le64(psnip_uint64_t v);
|
||||
psnip_uint16_t psnip_endian_be16(psnip_uint16_t v);
|
||||
psnip_uint32_t psnip_endian_be32(psnip_uint32_t v);
|
||||
psnip_uint64_t psnip_endian_be64(psnip_uint64_t v);
|
||||
```
|
||||
|
||||
These are usually implemented as macros, the prototypes above are
|
||||
purely for documentation.
|
||||
|
||||
These functions will swap byte ordering to or from the provided type
|
||||
**if necessary**. For example, `psnip_endian_le32` is used to convert
|
||||
a 32-bit unsigned integer to/from little-endian. If the machine is
|
||||
little-endian nothing will be done, but if it is big-endian then a
|
||||
swap will be performed. It's a bit like `hton`/`ntoh`, except instead
|
||||
of host to/from network order, it's host to/from whatever order you
|
||||
want.
|
||||
|
||||
If you wish to ignore the result of compile-time detection attempts,
|
||||
you may define `PSNIP_ENDIAN_FORCE_RT` prior to including this header
|
||||
to force run-time detection.
|
||||
|
||||
If you're only interested in detection you can just ignore the
|
||||
swapping functions mentioned above. If endianness could be determined
|
||||
at compile-time (i.e., through preprocessor macros),
|
||||
`PSNIP_ENDIAN_ORDER` will be defined to either `PSNIP_ENDIAN_LITTLE`
|
||||
or `PSNIP_ENDIAN_BIG`.
|
||||
|
||||
If you need (or prefer) to fall back on run-time detection,
|
||||
`PSNIP_ENDIAN_ORDER_RT` will evaluate to the same values
|
||||
(`PSNIP_ENDIAN_LITTLE` or `PSNIP_ENDIAN_BIG`). Note that the
|
||||
"run-time" detection will likely be optimized away by the compiler.
|
||||
|
||||
## Dependencies
|
||||
|
||||
To maximize portability you should #include the exact-int module
|
||||
before including endian.h, but if you don't want to add the extra
|
||||
file to your project you can omit it and this module will simply rely
|
||||
on <stdint.h>. As an alternative you may define `psnip_uint16_t`,
|
||||
`psnip_uint32_t`, and `psnip_uint64_t` to appropriate values yourself
|
||||
before including endian.h.
|
||||
|
||||
This module requires the builtin portable-snippet module. If you do
|
||||
not include builtin.h before endian.h, endian.h will automatically
|
||||
include "../builtin/builtin.h". If you include builtin.h manually you
|
||||
are free to use whatever directory structure you like.
|
||||
200
thirdparty/portable-snippets/endian/endian.h
vendored
Normal file
200
thirdparty/portable-snippets/endian/endian.h
vendored
Normal file
|
|
@ -0,0 +1,200 @@
|
|||
/* Endianness detection and swapping (v3)
|
||||
* Portable Snippets - https://github.com/nemequ/portable-snippets
|
||||
* Created by Evan Nemerson <evan@nemerson.com>
|
||||
*
|
||||
* To the extent possible under law, the authors have waived all
|
||||
* copyright and related or neighboring rights to this code. For
|
||||
* details, see the Creative Commons Zero 1.0 Universal license at
|
||||
* https://creativecommons.org/publicdomain/zero/1.0/
|
||||
*/
|
||||
|
||||
#if !defined(PSNIP_ENDIAN_H)
|
||||
#define PSNIP_ENDIAN_H
|
||||
|
||||
/* For maximum portability include the exact-int module from
|
||||
portable snippets. */
|
||||
#if \
|
||||
!defined(psnip_uint64_t) || \
|
||||
!defined(psnip_uint32_t) || \
|
||||
!defined(psnip_uint16_t)
|
||||
# include <stdint.h>
|
||||
# if !defined(psnip_uint64_t)
|
||||
# define psnip_uint64_t uint64_t
|
||||
# endif
|
||||
# if !defined(psnip_uint32_t)
|
||||
# define psnip_uint32_t uint32_t
|
||||
# endif
|
||||
# if !defined(psnip_uint16_t)
|
||||
# define psnip_uint16_t uint16_t
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#if !defined(PSNIP_BUILTIN_H)
|
||||
# include "../builtin/builtin.h"
|
||||
#endif
|
||||
|
||||
#if !defined(PSNIP_ENDIAN_STATIC_INLINE)
|
||||
# if defined(__GNUC__)
|
||||
# define PSNIP_ENDIAN__COMPILER_ATTRIBUTES __attribute__((__unused__))
|
||||
# else
|
||||
# define PSNIP_ENDIAN__COMPILER_ATTRIBUTES
|
||||
# endif
|
||||
|
||||
# if defined(HEDLEY_INLINE)
|
||||
# define PSNIP_ENDIAN__INLINE HEDLEY_INLINE
|
||||
# elif defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L
|
||||
# define PSNIP_ENDIAN__INLINE inline
|
||||
# elif defined(__GNUC_STDC_INLINE__)
|
||||
# define PSNIP_ENDIAN__INLINE __inline__
|
||||
# elif defined(_MSC_VER) && _MSC_VER >= 1200
|
||||
# define PSNIP_ENDIAN__INLINE __inline
|
||||
# else
|
||||
# define PSNIP_ENDIAN__INLINE
|
||||
# endif
|
||||
|
||||
# define PSNIP_ENDIAN__FUNCTION PSNIP_ENDIAN__COMPILER_ATTRIBUTES static PSNIP_ENDIAN__INLINE
|
||||
#endif
|
||||
|
||||
#if !defined(PSNIP_ENDIAN_LITTLE)
|
||||
# define PSNIP_ENDIAN_LITTLE 1234
|
||||
#endif
|
||||
#if !defined(PSNIP_ENDIAN_BIG)
|
||||
# define PSNIP_ENDIAN_BIG 4321
|
||||
#endif
|
||||
#if !defined(PSNIP_ENDIAN_PDP)
|
||||
# define PSNIP_ENDIAN_PDP 3412
|
||||
#endif
|
||||
|
||||
/* Detection
|
||||
*
|
||||
* Detecting endianness can be a bit tricky. There isn't really a
|
||||
* good standard way of determining endianness, and it's actually
|
||||
* possible to mix endianness within a single program. This is
|
||||
* currently pretty rare, though.
|
||||
*
|
||||
* We try to define PSNIP_ENDIAN_ORDER to PSNIP_ENDIAN_LITTLE,
|
||||
* PSNIP_ENDIAN_BIG, or PSNIP_ENDIAN_PDP. Additionally, you can use
|
||||
* the PSNIP_RT_BYTE_ORDER to check the runtime byte order, which is a
|
||||
* bit more reliable (though it may introduce some runtime overhead).
|
||||
*
|
||||
* In the event we are unable to determine endianness at compile-time,
|
||||
* PSNIP_ENDIAN_ORDER is left undefined and you will be forced to rely
|
||||
* on PSNIP_RT_BYTE_ORDER. */
|
||||
|
||||
#if !defined(PSNIP_ENDIAN_FORCE_RT)
|
||||
|
||||
#if !defined(PSNIP_ENDIAN_ORDER)
|
||||
/* GCC (and compilers masquerading as GCC) define __BYTE_ORDER__. */
|
||||
# if defined(__BYTE_ORDER__) && defined(__ORDER_LITTLE_ENDIAN__) && (__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__)
|
||||
# define PSNIP_ENDIAN_ORDER PSNIP_ENDIAN_LITTLE
|
||||
# elif defined(__BYTE_ORDER__) && defined(__ORDER_BIG_ENDIAN__) && (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__)
|
||||
# define PSNIP_ENDIAN_ORDER PSNIP_ENDIAN_BIG
|
||||
# elif defined(__BYTE_ORDER__) && defined(__ORDER_PDP_ENDIAN__) && (__BYTE_ORDER__ == __ORDER_PDP_ENDIAN__)
|
||||
# define PSNIP_ENDIAN_ORDER PSNIP_ENDIAN_PDP
|
||||
/* TI defines _BIG_ENDIAN or _LITTLE_ENDIAN */
|
||||
# elif defined(_BIG_ENDIAN)
|
||||
# define PSNIP_ENDIAN_ORDER PSNIP_ENDIAN_BIG
|
||||
# elif defined(_LITTLE_ENDIAN)
|
||||
# define PSNIP_ENDIAN_ORDER PSNIP_ENDIAN_LITTLE
|
||||
/* We know the endianness of some common architectures. Common
|
||||
* architectures not listed (ARM, POWER, MIPS, etc.) here are
|
||||
* bi-endian. */
|
||||
# elif defined(__amd64) || defined(_M_X64) || defined(__i386) || defined(_M_IX86)
|
||||
# define PSNIP_ENDIAN_ORDER PSNIP_ENDIAN_LITTLE
|
||||
# elif defined(__s390x__) || defined(__zarch__)
|
||||
# define PSNIP_ENDIAN_ORDER PSNIP_ENDIAN_BIG
|
||||
/* Looks like we'll have to rely on the platform. If we're missing a
|
||||
* platform, please let us know. */
|
||||
# elif defined(_WIN32)
|
||||
# define PSNIP_ENDIAN_ORDER PSNIP_ENDIAN_LITTLE
|
||||
# elif defined(sun) || defined(__sun) /* Solaris */
|
||||
# include <sys/byteorder.h>
|
||||
# if defined(_LITTLE_ENDIAN)
|
||||
# define PSNIP_ENDIAN_ORDER PSNIP_ENDIAN_LITTLE
|
||||
# elif defined(_BIG_ENDIAN)
|
||||
# define PSNIP_ENDIAN_ORDER PSNIP_ENDIAN_BIG
|
||||
# endif
|
||||
# elif defined(__APPLE__)
|
||||
# include <libkern/OSByteOrder.h>
|
||||
# if defined(__LITTLE_ENDIAN__)
|
||||
# define PSNIP_ENDIAN_ORDER PSNIP_ENDIAN_LITTLE
|
||||
# elif defined(__BIG_ENDIAN__)
|
||||
# define PSNIP_ENDIAN_ORDER PSNIP_ENDIAN_BIG
|
||||
# endif
|
||||
# elif defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__bsdi__) || defined(__DragonFly__) || defined(BSD)
|
||||
# include <machine/endian.h>
|
||||
# if defined(__BYTE_ORDER) && (__BYTE_ORDER == __LITTLE_ENDIAN)
|
||||
# define PSNIP_ENDIAN_ORDER PSNIP_ENDIAN_LITTLE
|
||||
# elif defined(__BYTE_ORDER) && (__BYTE_ORDER == __BIG_ENDIAN)
|
||||
# define PSNIP_ENDIAN_ORDER PSNIP_ENDIAN_BIG
|
||||
# elif defined(__BYTE_ORDER) && (__BYTE_ORDER == __PDP_ENDIAN)
|
||||
# define PSNIP_ENDIAN_ORDER PSNIP_ENDIAN_PDP
|
||||
# endif
|
||||
# elif defined(__linux__) || defined(__linux) || defined(__gnu_linux__)
|
||||
# include <endian.h>
|
||||
# if defined(__BYTE_ORDER) && defined(__LITTLE_ENDIAN) && (__BYTE_ORDER == __LITTLE_ENDIAN)
|
||||
# define PSNIP_ENDIAN_ORDER PSNIP_ENDIAN_LITTLE
|
||||
# elif defined(__BYTE_ORDER) && defined(__BIG_ENDIAN) && (__BYTE_ORDER == __BIG_ENDIAN)
|
||||
# define PSNIP_ENDIAN_ORDER PSNIP_ENDIAN_BIG
|
||||
# elif defined(__BYTE_ORDER) && defined(__PDP_ENDIAN) && (__BYTE_ORDER == __PDP_ENDIAN)
|
||||
# define PSNIP_ENDIAN_ORDER PSNIP_ENDIAN_PDP
|
||||
# endif
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/* PDP endian not yet supported. Patches welcome. */
|
||||
#if defined(PSNIP_ENDIAN_ORDER) && (PSNIP_ENDIAN_ORDER == PSNIP_ENDIAN_PDP)
|
||||
# error PDP endian is not supported.
|
||||
#endif
|
||||
|
||||
#endif /* !defined(PSNIP_ENDIAN_FORCE_RT) */
|
||||
|
||||
static const union {
|
||||
unsigned long long value;
|
||||
unsigned char bytes[4];
|
||||
} psnip_endian_rt_data = {
|
||||
1
|
||||
};
|
||||
|
||||
#define PSNIP_ENDIAN_ORDER_RT_IS_LE (psnip_endian_rt_data.bytes[0] == 1)
|
||||
#define PSNIP_ENDIAN_ORDER_RT_IS_BE (psnip_endian_rt_data.bytes[sizeof(unsigned long long) - 1] == 1)
|
||||
#define PSNIP_ENDIAN_ORDER_RT (PSNIP_ENDIAN_ORDER_RT_IS_LE ? PSNIP_ENDIAN_LITTLE : PSNIP_ENDIAN_BIG)
|
||||
|
||||
#if defined(PSNIP_ENDIAN_FORCE_RT) || !defined(PSNIP_ENDIAN_ORDER)
|
||||
#define PSNIP_ENDIAN__DEFINE_LE_FUNC(siz) \
|
||||
PSNIP_ENDIAN__FUNCTION \
|
||||
psnip_uint##siz##_t psnip_endian_le##siz(psnip_uint##siz##_t v) { \
|
||||
return PSNIP_ENDIAN_ORDER_RT_IS_LE ? v : psnip_builtin_bswap##siz(v); \
|
||||
}
|
||||
|
||||
#define PSNIP_ENDIAN__DEFINE_BE_FUNC(siz) \
|
||||
PSNIP_ENDIAN__FUNCTION \
|
||||
psnip_uint##siz##_t psnip_endian_be##siz(psnip_uint##siz##_t v) { \
|
||||
return PSNIP_ENDIAN_ORDER_RT_IS_BE ? v : psnip_builtin_bswap##siz(v); \
|
||||
}
|
||||
|
||||
PSNIP_ENDIAN__DEFINE_LE_FUNC(16)
|
||||
PSNIP_ENDIAN__DEFINE_LE_FUNC(32)
|
||||
PSNIP_ENDIAN__DEFINE_LE_FUNC(64)
|
||||
PSNIP_ENDIAN__DEFINE_BE_FUNC(16)
|
||||
PSNIP_ENDIAN__DEFINE_BE_FUNC(32)
|
||||
PSNIP_ENDIAN__DEFINE_BE_FUNC(64)
|
||||
#elif PSNIP_ENDIAN_ORDER == PSNIP_ENDIAN_LITTLE
|
||||
# define psnip_endian_le16(v) ((psnip_uint16_t) (v))
|
||||
# define psnip_endian_le32(v) ((psnip_uint32_t) (v))
|
||||
# define psnip_endian_le64(v) ((psnip_uint64_t) (v))
|
||||
# define psnip_endian_be16(v) psnip_builtin_bswap16((psnip_uint16_t) (v))
|
||||
# define psnip_endian_be32(v) psnip_builtin_bswap32((psnip_uint32_t) (v))
|
||||
# define psnip_endian_be64(v) psnip_builtin_bswap64((psnip_uint64_t) (v))
|
||||
#elif PSNIP_ENDIAN_ORDER == PSNIP_ENDIAN_BIG
|
||||
# define psnip_endian_le16(v) psnip_builtin_bswap16((psnip_uint16_t) (v))
|
||||
# define psnip_endian_le32(v) psnip_builtin_bswap32((psnip_uint32_t) (v))
|
||||
# define psnip_endian_le64(v) psnip_builtin_bswap64((psnip_uint64_t) (v))
|
||||
# define psnip_endian_be16(v) ((psnip_uint16_t) (v))
|
||||
# define psnip_endian_be32(v) ((psnip_uint32_t) (v))
|
||||
# define psnip_endian_be64(v) ((psnip_uint64_t) (v))
|
||||
#else
|
||||
# error Unknown endianness.
|
||||
#endif
|
||||
|
||||
#endif /* !defined(PSNIP_ENDIAN_H) */
|
||||
30
thirdparty/portable-snippets/exact-int/README.md
vendored
Normal file
30
thirdparty/portable-snippets/exact-int/README.md
vendored
Normal file
|
|
@ -0,0 +1,30 @@
|
|||
# Exact-Width Integer Types
|
||||
|
||||
Lots of stuff in psnip (as well as outside of psnip) requires
|
||||
exact-width integer types. C99 provides them in `<stdint.h>`, but
|
||||
sometimes you can't rely on C99 being available.
|
||||
|
||||
This header will define macros for `psnip_(u)int(8,16,32,64)_t`, using
|
||||
methods a bit more portable than just blindly including `<stdint.h>`:
|
||||
|
||||
* If `__(U)INTN_TYPE__` is defined, use those types.
|
||||
* On platforms where we know `<stdint.h>` is available (such as if
|
||||
we're compiling in C99 mode), we include `<stdint.h>`.
|
||||
* Otherwise, if we're using Visual Studio, use types we know exist.
|
||||
* If not, use `<limits.h>` to try to find some correctly-size types.
|
||||
|
||||
Headers in portable-snippets which use these types will only try to
|
||||
include `exact-int.h` if they are missing a type they actually use,
|
||||
which means you're free to create your own definitions for these
|
||||
types. This should help ensure that, if you already have exact-size
|
||||
types, portable-snippets will be compatible with them.
|
||||
|
||||
If are looking for a more complete portable implementation of
|
||||
`<stdint.h>` (for example, if you need the `UINT*_C` macros), there
|
||||
are several projects which aim to provide a more complete
|
||||
implementation, including:
|
||||
|
||||
* [pstdint.h](http://www.azillionmonkeys.com/qed/pstdint.h) (BSD-3)
|
||||
* [msinttypes](https://code.google.com/archive/p/msinttypes/) (BSD-3)
|
||||
|
||||
Feel free to file a PR if I'm missing anything.
|
||||
251
thirdparty/portable-snippets/exact-int/exact-int.h
vendored
Normal file
251
thirdparty/portable-snippets/exact-int/exact-int.h
vendored
Normal file
|
|
@ -0,0 +1,251 @@
|
|||
/* Exact-width integer types
|
||||
* Portable Snippets - https://github.com/nemequ/portable-snippets
|
||||
* Created by Evan Nemerson <evan@nemerson.com>
|
||||
*
|
||||
* To the extent possible under law, the authors have waived all
|
||||
* copyright and related or neighboring rights to this code. For
|
||||
* details, see the Creative Commons Zero 1.0 Universal license at
|
||||
* https://creativecommons.org/publicdomain/zero/1.0/
|
||||
*
|
||||
* This header tries to define psnip_(u)int(8|16|32|64)_t to
|
||||
* appropriate types given your system. For most systems this means
|
||||
* including <stdint.h> and adding a few preprocessor definitions, but
|
||||
* when that isn't an option things get a bit more complicated.
|
||||
*/
|
||||
|
||||
#if !defined(PSNIP_EXACT_INT_H)
|
||||
# define PSNIP_EXACT_INT_H
|
||||
|
||||
# if defined(psnip_int8_t)
|
||||
# undef psnip_int8_t
|
||||
# endif
|
||||
# if defined(psnip_uint8_t)
|
||||
# undef psnip_uint8_t
|
||||
# endif
|
||||
# if defined(psnip_int16_t)
|
||||
# undef psnip_int16_t
|
||||
# endif
|
||||
# if defined(psnip_uint16_t)
|
||||
# undef psnip_uint16_t
|
||||
# endif
|
||||
# if defined(psnip_int32_t)
|
||||
# undef psnip_int32_t
|
||||
# endif
|
||||
# if defined(psnip_uint32_t)
|
||||
# undef psnip_uint32_t
|
||||
# endif
|
||||
# if defined(psnip_int64_t)
|
||||
# undef psnip_int64_t
|
||||
# endif
|
||||
# if defined(psnip_uint64_t)
|
||||
# undef psnip_uint64_t
|
||||
# endif
|
||||
|
||||
# if !defined(PSNIP_EXACT_INT_HAVE_STDINT)
|
||||
# if defined(_STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)
|
||||
# define PSNIP_EXACT_INT_HAVE_STDINT
|
||||
# elif defined(__has_include)
|
||||
# if __has_include(<stdint.h>)
|
||||
# define PSNIP_EXACT_INT_HAVE_STDINT
|
||||
# endif
|
||||
# elif \
|
||||
defined(HAVE_STDINT_H) || \
|
||||
defined(_STDINT_H_INCLUDED) || \
|
||||
defined(_STDINT_H) || \
|
||||
defined(_STDINT_H_)
|
||||
# define PSNIP_EXACT_INT_HAVE_STDINT
|
||||
# elif \
|
||||
(defined(__GNUC__) && ((__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 5))) || \
|
||||
(defined(_MSC_VER) && (_MSC_VER >= 1600)) || \
|
||||
(defined(__SUNPRO_C) && (__SUNPRO_C >= 0x570)) || \
|
||||
(defined(__WATCOMC__) && (__WATCOMC__ >= 1250))
|
||||
# define PSNIP_EXACT_INT_HAVE_STDINT
|
||||
# endif
|
||||
# endif
|
||||
|
||||
# if \
|
||||
defined(__INT8_TYPE__) && defined(__INT16_TYPE__) && defined(__INT32_TYPE__) && defined(__INT64_TYPE__) && \
|
||||
defined(__UINT8_TYPE__) && defined(__UINT16_TYPE__) && defined(__UINT32_TYPE__) && defined(__UINT64_TYPE__)
|
||||
# define psnip_int8_t __INT8_TYPE__
|
||||
# define psnip_int16_t __INT16_TYPE__
|
||||
# define psnip_int32_t __INT32_TYPE__
|
||||
# define psnip_int64_t __INT64_TYPE__
|
||||
# define psnip_uint8_t __UINT8_TYPE__
|
||||
# define psnip_uint16_t __UINT16_TYPE__
|
||||
# define psnip_uint32_t __UINT32_TYPE__
|
||||
# define psnip_uint64_t __UINT64_TYPE__
|
||||
# elif defined(PSNIP_EXACT_INT_HAVE_STDINT)
|
||||
# include <stdint.h>
|
||||
# if !defined(psnip_int8_t)
|
||||
# define psnip_int8_t int8_t
|
||||
# endif
|
||||
# if !defined(psnip_uint8_t)
|
||||
# define psnip_uint8_t uint8_t
|
||||
# endif
|
||||
# if !defined(psnip_int16_t)
|
||||
# define psnip_int16_t int16_t
|
||||
# endif
|
||||
# if !defined(psnip_uint16_t)
|
||||
# define psnip_uint16_t uint16_t
|
||||
# endif
|
||||
# if !defined(psnip_int32_t)
|
||||
# define psnip_int32_t int32_t
|
||||
# endif
|
||||
# if !defined(psnip_uint32_t)
|
||||
# define psnip_uint32_t uint32_t
|
||||
# endif
|
||||
# if !defined(psnip_int64_t)
|
||||
# define psnip_int64_t int64_t
|
||||
# endif
|
||||
# if !defined(psnip_uint64_t)
|
||||
# define psnip_uint64_t uint64_t
|
||||
# endif
|
||||
# elif defined(_MSC_VER)
|
||||
# if !defined(psnip_int8_t)
|
||||
# define psnip_int8_t __int8
|
||||
# endif
|
||||
# if !defined(psnip_uint8_t)
|
||||
# define psnip_uint8_t unsigned __int8
|
||||
# endif
|
||||
# if !defined(psnip_int16_t)
|
||||
# define psnip_int16_t __int16
|
||||
# endif
|
||||
# if !defined(psnip_uint16_t)
|
||||
# define psnip_uint16_t unsigned __int16
|
||||
# endif
|
||||
# if !defined(psnip_int32_t)
|
||||
# define psnip_int32_t __int32
|
||||
# endif
|
||||
# if !defined(psnip_uint32_t)
|
||||
# define psnip_uint32_t unsigned __int32
|
||||
# endif
|
||||
# if !defined(psnip_int64_t)
|
||||
# define psnip_int64_t __int64
|
||||
# endif
|
||||
# if !defined(psnip_uint64_t)
|
||||
# define psnip_uint64_t unsigned __int64
|
||||
# endif
|
||||
# else
|
||||
# include <limits.h>
|
||||
# if !defined(psnip_int8_t)
|
||||
# if defined(CHAR_MIN) && defined(CHAR_MAX) && (CHAR_MIN == (-127-1)) && (CHAR_MAX == 127)
|
||||
# define psnip_int8_t char
|
||||
# elif defined(SHRT_MIN) && defined(SHRT_MAX) && (SHRT_MIN == (-127-1)) && (SHRT_MAX == 127)
|
||||
# define psnip_int8_t short
|
||||
# elif defined(INT_MIN) && defined(INT_MAX) && (INT_MIN == (-127-1)) && (INT_MAX == 127)
|
||||
# define psnip_int8_t int
|
||||
# elif defined(LONG_MIN) && defined(LONG_MAX) && (LONG_MIN == (-127-1)) && (LONG_MAX == 127)
|
||||
# define psnip_int8_t long
|
||||
# elif defined(LLONG_MIN) && defined(LLONG_MAX) && (LLONG_MIN == (-127-1)) && (LLONG_MAX == 127)
|
||||
# define psnip_int8_t long long
|
||||
# else
|
||||
# error Unable to locate 8-bit signed integer type.
|
||||
# endif
|
||||
# endif
|
||||
# if !defined(psnip_uint8_t)
|
||||
# if defined(UCHAR_MAX) && (UCHAR_MAX == 255)
|
||||
# define psnip_uint8_t unsigned char
|
||||
# elif defined(USHRT_MAX) && (USHRT_MAX == 255)
|
||||
# define psnip_uint8_t unsigned short
|
||||
# elif defined(UINT_MAX) && (UINT_MAX == 255)
|
||||
# define psnip_uint8_t unsigned int
|
||||
# elif defined(ULONG_MAX) && (ULONG_MAX == 255)
|
||||
# define psnip_uint8_t unsigned long
|
||||
# elif defined(ULLONG_MAX) && (ULLONG_MAX == 255)
|
||||
# define psnip_uint8_t unsigned long long
|
||||
# else
|
||||
# error Unable to locate 8-bit unsigned integer type.
|
||||
# endif
|
||||
# endif
|
||||
# if !defined(psnip_int16_t)
|
||||
# if defined(CHAR_MIN) && defined(CHAR_MAX) && (CHAR_MIN == (-32767-1)) && (CHAR_MAX == 32767)
|
||||
# define psnip_int16_t char
|
||||
# elif defined(SHRT_MIN) && defined(SHRT_MAX) && (SHRT_MIN == (-32767-1)) && (SHRT_MAX == 32767)
|
||||
# define psnip_int16_t short
|
||||
# elif defined(INT_MIN) && defined(INT_MAX) && (INT_MIN == (-32767-1)) && (INT_MAX == 32767)
|
||||
# define psnip_int16_t int
|
||||
# elif defined(LONG_MIN) && defined(LONG_MAX) && (LONG_MIN == (-32767-1)) && (LONG_MAX == 32767)
|
||||
# define psnip_int16_t long
|
||||
# elif defined(LLONG_MIN) && defined(LLONG_MAX) && (LLONG_MIN == (-32767-1)) && (LLONG_MAX == 32767)
|
||||
# define psnip_int16_t long long
|
||||
# else
|
||||
# error Unable to locate 16-bit signed integer type.
|
||||
# endif
|
||||
# endif
|
||||
# if !defined(psnip_uint16_t)
|
||||
# if defined(UCHAR_MAX) && (UCHAR_MAX == 65535)
|
||||
# define psnip_uint16_t unsigned char
|
||||
# elif defined(USHRT_MAX) && (USHRT_MAX == 65535)
|
||||
# define psnip_uint16_t unsigned short
|
||||
# elif defined(UINT_MAX) && (UINT_MAX == 65535)
|
||||
# define psnip_uint16_t unsigned int
|
||||
# elif defined(ULONG_MAX) && (ULONG_MAX == 65535)
|
||||
# define psnip_uint16_t unsigned long
|
||||
# elif defined(ULLONG_MAX) && (ULLONG_MAX == 65535)
|
||||
# define psnip_uint16_t unsigned long long
|
||||
# else
|
||||
# error Unable to locate 16-bit unsigned integer type.
|
||||
# endif
|
||||
# endif
|
||||
# if !defined(psnip_int32_t)
|
||||
# if defined(CHAR_MIN) && defined(CHAR_MAX) && (CHAR_MIN == (-2147483647-1)) && (CHAR_MAX == 2147483647)
|
||||
# define psnip_int32_t char
|
||||
# elif defined(SHRT_MIN) && defined(SHRT_MAX) && (SHRT_MIN == (-2147483647-1)) && (SHRT_MAX == 2147483647)
|
||||
# define psnip_int32_t short
|
||||
# elif defined(INT_MIN) && defined(INT_MAX) && (INT_MIN == (-2147483647-1)) && (INT_MAX == 2147483647)
|
||||
# define psnip_int32_t int
|
||||
# elif defined(LONG_MIN) && defined(LONG_MAX) && (LONG_MIN == (-2147483647-1)) && (LONG_MAX == 2147483647)
|
||||
# define psnip_int32_t long
|
||||
# elif defined(LLONG_MIN) && defined(LLONG_MAX) && (LLONG_MIN == (-2147483647-1)) && (LLONG_MAX == 2147483647)
|
||||
# define psnip_int32_t long long
|
||||
# else
|
||||
# error Unable to locate 32-bit signed integer type.
|
||||
# endif
|
||||
# endif
|
||||
# if !defined(psnip_uint32_t)
|
||||
# if defined(UCHAR_MAX) && (UCHAR_MAX == 4294967295)
|
||||
# define psnip_uint32_t unsigned char
|
||||
# elif defined(USHRT_MAX) && (USHRT_MAX == 4294967295)
|
||||
# define psnip_uint32_t unsigned short
|
||||
# elif defined(UINT_MAX) && (UINT_MAX == 4294967295)
|
||||
# define psnip_uint32_t unsigned int
|
||||
# elif defined(ULONG_MAX) && (ULONG_MAX == 4294967295)
|
||||
# define psnip_uint32_t unsigned long
|
||||
# elif defined(ULLONG_MAX) && (ULLONG_MAX == 4294967295)
|
||||
# define psnip_uint32_t unsigned long long
|
||||
# else
|
||||
# error Unable to locate 32-bit unsigned integer type.
|
||||
# endif
|
||||
# endif
|
||||
# if !defined(psnip_int64_t)
|
||||
# if defined(CHAR_MIN) && defined(CHAR_MAX) && (CHAR_MIN == (-9223372036854775807LL-1)) && (CHAR_MAX == 9223372036854775807LL)
|
||||
# define psnip_int64_t char
|
||||
# elif defined(SHRT_MIN) && defined(SHRT_MAX) && (SHRT_MIN == (-9223372036854775807LL-1)) && (SHRT_MAX == 9223372036854775807LL)
|
||||
# define psnip_int64_t short
|
||||
# elif defined(INT_MIN) && defined(INT_MAX) && (INT_MIN == (-9223372036854775807LL-1)) && (INT_MAX == 9223372036854775807LL)
|
||||
# define psnip_int64_t int
|
||||
# elif defined(LONG_MIN) && defined(LONG_MAX) && (LONG_MIN == (-9223372036854775807LL-1)) && (LONG_MAX == 9223372036854775807LL)
|
||||
# define psnip_int64_t long
|
||||
# elif defined(LLONG_MIN) && defined(LLONG_MAX) && (LLONG_MIN == (-9223372036854775807LL-1)) && (LLONG_MAX == 9223372036854775807LL)
|
||||
# define psnip_int64_t long long
|
||||
# else
|
||||
# error Unable to locate 64-bit signed integer type.
|
||||
# endif
|
||||
# endif
|
||||
# if !defined(psnip_uint64_t)
|
||||
# if defined(UCHAR_MAX) && (UCHAR_MAX == 18446744073709551615ULL)
|
||||
# define psnip_uint64_t unsigned char
|
||||
# elif defined(USHRT_MAX) && (USHRT_MAX == 18446744073709551615ULL)
|
||||
# define psnip_uint64_t unsigned short
|
||||
# elif defined(UINT_MAX) && (UINT_MAX == 18446744073709551615ULL)
|
||||
# define psnip_uint64_t unsigned int
|
||||
# elif defined(ULONG_MAX) && (ULONG_MAX == 18446744073709551615ULL)
|
||||
# define psnip_uint64_t unsigned long
|
||||
# elif defined(ULLONG_MAX) && (ULLONG_MAX == 18446744073709551615ULL)
|
||||
# define psnip_uint64_t unsigned long long
|
||||
# else
|
||||
# error Unable to locate 64-bit unsigned integer type.
|
||||
# endif
|
||||
# endif
|
||||
# endif
|
||||
#endif
|
||||
11
thirdparty/portable-snippets/once/README.md
vendored
Normal file
11
thirdparty/portable-snippets/once/README.md
vendored
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
# Once
|
||||
|
||||
This is a simple abstraction for a once which will choose from a few
|
||||
different back-ends:
|
||||
|
||||
* If C11 threads are available, use `call_once()`.
|
||||
* On Windows, use
|
||||
[InitOnceExecuteOnce()](https://msdn.microsoft.com/en-us/library/windows/desktop/ms683493(v=vs.85).aspx)
|
||||
* If `PTHREAD_ONCE_INIT` is defined (*i.e.*, if `<pthread.h>` has
|
||||
been included prior to including `once.h`), use `pthread_once()`.
|
||||
* Use `[atomic.h](../atomic)`.
|
||||
129
thirdparty/portable-snippets/once/once.h
vendored
Normal file
129
thirdparty/portable-snippets/once/once.h
vendored
Normal file
|
|
@ -0,0 +1,129 @@
|
|||
/* Once (v1)
|
||||
* Portable Snippets - https://github.com/nemequ/portable-snippets
|
||||
* Created by Evan Nemerson <evan@nemerson.com>
|
||||
*
|
||||
* To the extent possible under law, the authors have waived all
|
||||
* copyright and related or neighboring rights to this code. For
|
||||
* details, see the Creative Commons Zero 1.0 Universal license at
|
||||
* https://creativecommons.org/publicdomain/zero/1.0/
|
||||
*/
|
||||
|
||||
#if !defined(PSNIP_ONCE__H)
|
||||
#define PSNIP_ONCE__H
|
||||
|
||||
#define PSNIP_ONCE__BACKEND_ATOMIC 1
|
||||
#define PSNIP_ONCE__BACKEND_PTHREAD 2
|
||||
#define PSNIP_ONCE__BACKEND_NONE 3
|
||||
#define PSNIP_ONCE__BACKEND_C11 11
|
||||
#define PSNIP_ONCE__BACKEND_WIN32 32
|
||||
|
||||
#include <limits.h>
|
||||
|
||||
#if !defined(PSNIP_ONCE_BACKEND)
|
||||
# if defined(__STDC_NO_THREADS__) && __STDC_NO_THREADS__
|
||||
# elif defined(__EMSCRIPTEN__)
|
||||
# elif defined(__has_include)
|
||||
# if __has_include(<threads.h>)
|
||||
# if !defined(__GLIBC__) || (defined(__GLIBC__) && defined(PSNIP_ENABLE_PTHREADS))
|
||||
# include <threads.h>
|
||||
# define PSNIP_ONCE_BACKEND PSNIP_ONCE__BACKEND_C11
|
||||
# endif
|
||||
# endif
|
||||
# elif defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201102L) && !defined(__STDC_NO_THREADS__)
|
||||
# if (defined(__GLIBC__) && (__GLIBC__ < 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ < 16)))
|
||||
/* stdc-predef.h didn't include __STDC_NO_THREADS__ until 2.16. */
|
||||
# else
|
||||
# include <threads.h>
|
||||
# define PSNIP_ONCE_BACKEND PSNIP_ONCE__BACKEND_C11
|
||||
# endif
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#if !defined(PSNIP_ONCE_BACKEND) && defined(_WIN32) && (!defined(WINVER) || (defined(WINVER) && (WINVER >= 0x0600)))
|
||||
# include <Windows.h>
|
||||
# define PSNIP_ONCE_BACKEND PSNIP_ONCE__BACKEND_WIN32
|
||||
#endif
|
||||
|
||||
#if !defined(PSNIP_ONCE_BACKEND) && defined(PTHREAD_ONCE_INIT)
|
||||
# define PSNIP_ONCE_BACKEND PSNIP_ONCE__BACKEND_PTHREAD
|
||||
#endif
|
||||
|
||||
#if !defined(PSNIP_ONCE_BACKEND)
|
||||
# include "../atomic/atomic.h"
|
||||
# if !defined(PSNIP_ATOMIC_NOT_FOUND)
|
||||
# define PSNIP_ONCE_BACKEND PSNIP_ONCE__BACKEND_ATOMIC
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#if !defined(PSNIP_ONCE_BACKEND)
|
||||
# error No once backend found.
|
||||
#endif
|
||||
|
||||
#if defined(__GNUC__) && (__GNUC__ >= 3)
|
||||
# define PSNIP_ONCE__UNLIKELY(expr) __builtin_expect(!!(expr), !!0)
|
||||
#else
|
||||
# define PSNIP_ONCE__UNLIKELY(expr) (!!(expr))
|
||||
#endif
|
||||
|
||||
#if PSNIP_ONCE_BACKEND == PSNIP_ONCE__BACKEND_C11
|
||||
# define PSNIP_ONCE_INIT ONCE_FLAG_INIT
|
||||
typedef once_flag psnip_once;
|
||||
# define psnip_once_call(flag, func) call_once(flag, func)
|
||||
#elif PSNIP_ONCE_BACKEND == PSNIP_ONCE__BACKEND_PTHREAD
|
||||
# define PSNIP_ONCE_INIT PTHREAD_ONCE_INIT
|
||||
typedef pthread_once_t psnip_once;
|
||||
# define psnip_once_call(flag, func) pthread_once(flag, func)
|
||||
#elif PSNIP_ONCE_BACKEND == PSNIP_ONCE__BACKEND_WIN32
|
||||
# define PSNIP_ONCE_INIT INIT_ONCE_STATIC_INIT
|
||||
typedef INIT_ONCE psnip_once;
|
||||
static BOOL CALLBACK psnip_once__callback_wrap(INIT_ONCE* InitOnce, void* Parameter, void** Context) {
|
||||
(void) Context;
|
||||
(void) InitOnce;
|
||||
#if defined(_MSC_VER)
|
||||
# pragma warning(push)
|
||||
# pragma warning(disable:4055)
|
||||
#endif
|
||||
((void (*)(void)) Parameter)();
|
||||
#if defined(_MSC_VER)
|
||||
# pragma warning(pop)
|
||||
#endif
|
||||
return !0;
|
||||
}
|
||||
# if defined(_MSC_VER) && (_MSC_VER >= 1500)
|
||||
# define psnip_once_call(flag, func) \
|
||||
__pragma(warning(push)) \
|
||||
__pragma(warning(disable:4152)) \
|
||||
InitOnceExecuteOnce(flag, &psnip_once__callback_wrap, func, NULL) \
|
||||
__pragma(warning(pop))
|
||||
# else
|
||||
# define psnip_once_call(flag, func) InitOnceExecuteOnce(flag, &psnip_once__callback_wrap, func, NULL)
|
||||
# endif
|
||||
#elif PSNIP_ONCE_BACKEND == PSNIP_ONCE__BACKEND_ATOMIC
|
||||
# define PSNIP_ONCE_INIT PSNIP_ATOMIC_VAR_INIT(0)
|
||||
typedef psnip_atomic_int32 psnip_once;
|
||||
static void psnip_once_call(psnip_once* flag, void (*func)(void)) {
|
||||
psnip_int32_t state = psnip_atomic_int32_load(flag);
|
||||
if (PSNIP_ONCE__UNLIKELY(state == 0)) {
|
||||
if (psnip_atomic_int32_compare_exchange(flag, &state, 1)) {
|
||||
func();
|
||||
psnip_atomic_int32_store(flag, 2);
|
||||
} else {
|
||||
do {
|
||||
/* Spin; another thread is calling the initialization
|
||||
function. */
|
||||
} while (psnip_atomic_int32_load(flag) == 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
#elif PSNIP_ONCE_BACKEND == PSNIP_ONCE__BACKEND_NONE
|
||||
# define PSNIP_ONCE_INIT 0
|
||||
typedef int psnip_once;
|
||||
static void psnip_once_call(psnip_once* flag, void (*func)(void)) {
|
||||
if (*flag == 0) {
|
||||
func();
|
||||
*flag = 1;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* !defined(PSNIP_ONCE__H) */
|
||||
84
thirdparty/portable-snippets/random/README.md
vendored
Normal file
84
thirdparty/portable-snippets/random/README.md
vendored
Normal file
|
|
@ -0,0 +1,84 @@
|
|||
# Random Numbers
|
||||
|
||||
This provides methods for obtaining random, or pseudo-random, numbers.
|
||||
|
||||
There is generally only on function to worry about:
|
||||
|
||||
```c
|
||||
int
|
||||
psnip_random_bytes(enum PSnipRandomSource source,
|
||||
size_t length,
|
||||
psnip_uint8_t data[length]);
|
||||
```
|
||||
|
||||
This will fill `data` with `length` bytes of randomness from `source`.
|
||||
It returns 0 on success or, -1 if the source is not available (only
|
||||
possible with the secure source), -2 if you supplied an invalid source
|
||||
argument, or another negative number for other unexpected errors.
|
||||
|
||||
## Secure
|
||||
|
||||
`PSNIP_RANDOM_SOURCE_SECURE` tries to obtain cryptographically secure
|
||||
random numbers. This may or may not be available, depending on the
|
||||
platform; if no source can be found `psnip_random_get_bytes` will
|
||||
return -1 (you can pass 0 for the length if you just want to query for
|
||||
support without actually generating anything).
|
||||
|
||||
This will try various methods. Currently, this means:
|
||||
|
||||
* [`RtlGenRandom()`](http://msdn.microsoft.com/en-us/library/windows/desktop/aa387694%28v=vs.85%29.aspx) on Windows
|
||||
* `getrandom()` on Solaris >= 11.3 (**TODO**), Linux >= 3.17
|
||||
* `arc4random()` on some BSDs (**TODO**)
|
||||
* [AES-NI](https://software.intel.com/en-us/articles/intel-advanced-encryption-standard-aes-instructions-set/) on CPUs which support it
|
||||
* Reading from `/dev/urandom` or `/dev/random` (if they exist)
|
||||
|
||||
If your platform isn't supported, please get in touch to discuss
|
||||
adding a back-end.
|
||||
|
||||
## Reproducible
|
||||
|
||||
`PSNIP_RANDOM_SOURCE_REPRODUCIBLE` generates a *reproducible* stream
|
||||
of pseudo-random numbers. Currently we use a 32-bit variant of PCG;
|
||||
this was chosen because it provides pretty good quality random
|
||||
numbers, and the state is small enough that we can use atomic
|
||||
operations instead of a mutex.
|
||||
|
||||
To deal with seeding, there are two additional functions:
|
||||
|
||||
```c
|
||||
psnip_uint32_t psnip_random_get_seed (void);
|
||||
void psnip_random_set_seed (const psnip_uint32_t seed);
|
||||
```
|
||||
|
||||
You can use the `psnip_random_set_seed` function to seed this
|
||||
generator. If you do not provide a seed we'll try to generate a
|
||||
decent seed for you, but we make no promises about the quality.
|
||||
Potential sources for the seed include libc's `rand()`, system time,
|
||||
`lrand48()`, etc.
|
||||
|
||||
Even with a high quality seed, **this is not cryptographically secure**.
|
||||
|
||||
## Fast
|
||||
|
||||
`PSNIP_RANDOM_SOURCE_FAST` just tries to provide a random number
|
||||
quickly. It probably isn't cryptographically secure, but may be; for
|
||||
example, if you have a hardware-based RNG which we believe would be
|
||||
faster than the reproducible PRNG, we'll use it.
|
||||
|
||||
Note that, even if the fast source is implemented using the same
|
||||
algorithm as the reproducible source (i.e., PGC with a 32-bit state),
|
||||
the fast source will *not* alter the state of the reproducible PRNG.
|
||||
|
||||
## Dependencies
|
||||
|
||||
This module requires the following portable-snippet modules:
|
||||
|
||||
* exact-int
|
||||
* atomic — for thread-safety
|
||||
* clock — for seeding
|
||||
* once — for thread-safety
|
||||
* cpu — to detect CPU-based PRNGs (*i.e.*, RdRand on Intel)
|
||||
|
||||
The code currently assumes the same directory structure as is used in
|
||||
the portable-snippets repository. Patches to allow other structures
|
||||
will be seriously considered.
|
||||
400
thirdparty/portable-snippets/random/random.c
vendored
Normal file
400
thirdparty/portable-snippets/random/random.c
vendored
Normal file
|
|
@ -0,0 +1,400 @@
|
|||
#define _GNU_SOURCE
|
||||
|
||||
#include "random.h"
|
||||
|
||||
#if !defined(psnip_uint64_t)
|
||||
# include "../exact-int/exact-int.h"
|
||||
#endif
|
||||
|
||||
#include "../atomic/atomic.h"
|
||||
#include "../clock/clock.h"
|
||||
#include "../once/once.h"
|
||||
#include "../cpu/cpu.h"
|
||||
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#if !defined(_WIN32)
|
||||
# include <sys/types.h>
|
||||
# include <unistd.h>
|
||||
#endif
|
||||
|
||||
#if defined(PSNIP_CPU_ARCH_X86_64) || defined(PSNIP_CPU_ARCH_X86)
|
||||
# if defined(__has_builtin)
|
||||
# if defined(__clang__) && (__clang_major__ == 3 && __clang_minor__ == 5)
|
||||
# elif __has_builtin(__builtin_ia32_rdrand64_step) || __has_builtin(__builtin_ia32_rdrand32_step)
|
||||
# define PSNIP_RANDOM__SECURE_ALLOW_RDRAND
|
||||
# endif
|
||||
# elif (defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)))
|
||||
# define PSNIP_RANDOM__SECURE_ALLOW_RDRAND
|
||||
# endif
|
||||
#endif
|
||||
|
||||
static int (* psnip_random_secure_generate)(size_t length, psnip_uint8_t data[PSNIP_RANDOM_ARRAY_PARAM(length)]) = NULL;
|
||||
static psnip_once psnip_random_secure_once = PSNIP_ONCE_INIT;
|
||||
|
||||
#if defined(__linux)
|
||||
# include <unistd.h>
|
||||
# include <sys/syscall.h>
|
||||
|
||||
# if defined(SYS_getrandom)
|
||||
# include <linux/version.h>
|
||||
# include <sys/utsname.h>
|
||||
|
||||
static int
|
||||
psnip_random__have_getrandom(void) {
|
||||
struct utsname buf;
|
||||
int major, minor, revision, r;
|
||||
|
||||
uname(&buf);
|
||||
r = sscanf(buf.release, "%d.%d.%d", &major, &minor, &revision);
|
||||
if (r != 3)
|
||||
return 0;
|
||||
|
||||
return KERNEL_VERSION(major, minor, revision) >= KERNEL_VERSION(3, 17, 0);
|
||||
}
|
||||
|
||||
# if defined(__GLIBC__) && (__GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 26))
|
||||
# include <sys/random.h>
|
||||
# define psnip_random__getrandom(buf, buflen, flags) getrandom(buf, buflen, flags)
|
||||
# else
|
||||
static int
|
||||
psnip_random__getrandom(void* buf, size_t buflen, unsigned int flags) {
|
||||
return (int) syscall(SYS_getrandom, buf, buflen, flags);
|
||||
}
|
||||
# endif
|
||||
|
||||
static int
|
||||
psnip_random_secure_generate_getrandom(size_t length, psnip_uint8_t data[PSNIP_RANDOM_ARRAY_PARAM(length)]) {
|
||||
size_t bytes_read = 0;
|
||||
int r;
|
||||
|
||||
while (bytes_read < length) {
|
||||
r = psnip_random__getrandom(&(data[bytes_read]), length - bytes_read, 0);
|
||||
if (r == -1)
|
||||
return -4;
|
||||
bytes_read += r;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#if defined(PSNIP_RANDOM__SECURE_ALLOW_RDRAND)
|
||||
# if defined(__GNUC__)
|
||||
# include <x86intrin.h>
|
||||
# else
|
||||
# include <immintrin.h>
|
||||
# endif
|
||||
|
||||
#if defined(__GNUC__) && !defined(__INTEL_COMPILER)
|
||||
__attribute__((__target__("rdrnd")))
|
||||
#endif
|
||||
static int
|
||||
psnip_random__rdrand (size_t length, psnip_uint8_t data[PSNIP_RANDOM_ARRAY_PARAM(length)]) {
|
||||
size_t remaining = length;
|
||||
unsigned int r;
|
||||
#if defined(PSNIP_CPU_ARCH_X86_64)
|
||||
unsigned long long int v;
|
||||
#else
|
||||
unsigned int v;
|
||||
#endif
|
||||
|
||||
while (remaining > 0) {
|
||||
do {
|
||||
#if defined(PSNIP_CPU_ARCH_X86_64)
|
||||
# if defined(__GNUC__)
|
||||
r = __builtin_ia32_rdrand64_step(&v);
|
||||
# else
|
||||
r = _rdrand64_step(&v);
|
||||
# endif
|
||||
#else
|
||||
# if defined(__GNUC__)
|
||||
r = __builtin_ia32_rdrand32_step(&v);
|
||||
# else
|
||||
r = _rdrand32_step(&v);
|
||||
# endif
|
||||
#endif
|
||||
} while (r == 0);
|
||||
|
||||
if (remaining >= sizeof(v)) {
|
||||
memcpy(&(data[length - remaining]), &v, sizeof(v));
|
||||
remaining -= sizeof(v);
|
||||
} else {
|
||||
memcpy(&(data[length - remaining]), &v, remaining);
|
||||
remaining = 0;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(_WIN32)
|
||||
static HMODULE psnip_rand_secure__advapi32_dll = NULL;
|
||||
static BOOLEAN (APIENTRY *psnip_rand_secure__RtlGenRandom)(void*, ULONG);
|
||||
|
||||
static int psnip_random_secure_generate_RtlGenRandom(size_t length, psnip_uint8_t data[PSNIP_RANDOM_ARRAY_PARAM(length)]) {
|
||||
assert(psnip_rand_secure__RtlGenRandom != NULL);
|
||||
|
||||
return psnip_rand_secure__RtlGenRandom(data, (ULONG) length) ? 0 : -3;
|
||||
}
|
||||
|
||||
static void
|
||||
psnip_random_secure_init(void) {
|
||||
psnip_rand_secure__advapi32_dll = LoadLibrary("ADVAPI32.DLL");
|
||||
if (psnip_rand_secure__advapi32_dll == NULL)
|
||||
return;
|
||||
|
||||
psnip_rand_secure__RtlGenRandom = (BOOLEAN (APIENTRY *)(void*,ULONG))
|
||||
GetProcAddress(psnip_rand_secure__advapi32_dll, "SystemFunction036");
|
||||
|
||||
if (psnip_rand_secure__RtlGenRandom == NULL)
|
||||
return;
|
||||
|
||||
psnip_random_secure_generate = &psnip_random_secure_generate_RtlGenRandom;
|
||||
}
|
||||
|
||||
# define PSNIP_RANDOM_SECURE_FOUND
|
||||
#endif /* defined(_WIN32) */
|
||||
|
||||
#if !defined(PSNIP_RANDOM_SECURE_FOUND)
|
||||
static int
|
||||
psnip_random_secure_generate_dev_random(size_t length, psnip_uint8_t data[PSNIP_RANDOM_ARRAY_PARAM(length)]) {
|
||||
static FILE* dev_random = NULL;
|
||||
size_t bytes_read = 0;
|
||||
|
||||
if (dev_random == NULL) {
|
||||
dev_random = fopen("/dev/random", "rb");
|
||||
if (dev_random == NULL)
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (length > 0) {
|
||||
bytes_read = fread(data, 1, length, dev_random);
|
||||
if (bytes_read != length)
|
||||
return -5;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
psnip_random_secure_generate_dev_urandom(size_t length, psnip_uint8_t data[PSNIP_RANDOM_ARRAY_PARAM(length)]) {
|
||||
static FILE* dev_urandom = NULL;
|
||||
size_t bytes_read = 0;
|
||||
|
||||
if (dev_urandom == NULL) {
|
||||
dev_urandom = fopen("/dev/random", "rb");
|
||||
if (dev_urandom == NULL)
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (length > 0) {
|
||||
bytes_read = fread(data, 1, length, dev_urandom);
|
||||
if (bytes_read != length)
|
||||
return -5;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
psnip_random_secure_init(void) {
|
||||
#if defined(__linux) && defined(SYS_getrandom)
|
||||
if (psnip_random__have_getrandom()) {
|
||||
psnip_random_secure_generate = &psnip_random_secure_generate_getrandom;
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (psnip_random_secure_generate_dev_urandom(0, NULL) == 0) {
|
||||
psnip_random_secure_generate = &psnip_random_secure_generate_dev_urandom;
|
||||
return;
|
||||
}
|
||||
|
||||
if (psnip_random_secure_generate_dev_random(0, NULL) == 0) {
|
||||
psnip_random_secure_generate = &psnip_random_secure_generate_dev_random;
|
||||
return;
|
||||
}
|
||||
|
||||
#if defined(PSNIP_RANDOM__SECURE_ALLOW_RDRAND)
|
||||
if (psnip_cpu_feature_check(PSNIP_CPU_FEATURE_X86_RDRND)) {
|
||||
psnip_random_secure_generate = &psnip_random__rdrand;
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
/* http://burtleburtle.net/bob/hash/integer.html */
|
||||
static psnip_uint32_t psnip_random__seed_hash(psnip_uint32_t a) {
|
||||
a = (a ^ 61) ^ (a >> 16);
|
||||
a += (a << 3);
|
||||
a ^= (a >> 4);
|
||||
a *= 0x27d4eb2dU;
|
||||
a ^= (a >> 15);
|
||||
|
||||
return a;
|
||||
}
|
||||
|
||||
static psnip_uint32_t
|
||||
psnip_random__pcg_gen_seed(void) {
|
||||
psnip_uint32_t res = 0;
|
||||
struct PsnipClockTimespec cur_time = { 0, };
|
||||
int precision;
|
||||
|
||||
precision = psnip_clock_get_precision(PSNIP_CLOCK_TYPE_WALL);
|
||||
if (precision != 0) {
|
||||
if (psnip_clock_get_time(PSNIP_CLOCK_TYPE_WALL, &cur_time) == 0) {
|
||||
goto complete;
|
||||
}
|
||||
}
|
||||
|
||||
precision = psnip_clock_get_precision(PSNIP_CLOCK_TYPE_MONOTONIC);
|
||||
if (precision != 0) {
|
||||
if (psnip_clock_get_time(PSNIP_CLOCK_TYPE_MONOTONIC, &cur_time) == 0) {
|
||||
goto complete;
|
||||
}
|
||||
}
|
||||
|
||||
precision = psnip_clock_get_precision(PSNIP_CLOCK_TYPE_CPU);
|
||||
if (precision != 0) {
|
||||
if (psnip_clock_get_time(PSNIP_CLOCK_TYPE_CPU, &cur_time) == 0) {
|
||||
goto complete;
|
||||
}
|
||||
}
|
||||
|
||||
complete:
|
||||
res ^= psnip_random__seed_hash((psnip_uint32_t) cur_time.nanoseconds);
|
||||
res ^= psnip_random__seed_hash((psnip_uint32_t) cur_time.seconds);
|
||||
res ^= psnip_random__seed_hash((psnip_uint32_t) rand());
|
||||
#if !defined(_WIN32)
|
||||
res ^= psnip_random__seed_hash((psnip_uint32_t) getpid());
|
||||
res ^= psnip_random__seed_hash((psnip_uint32_t) getppid());
|
||||
#endif
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
/* PCG */
|
||||
|
||||
#define PSNIP_RANDOM__PCG_MULTIPLIER (747796405U)
|
||||
#define PSNIP_RANDOM__PCG_INCREMENT (1729U)
|
||||
|
||||
static psnip_uint32_t
|
||||
psnip_random__pcg_next_state(psnip_uint32_t state) {
|
||||
return state * PSNIP_RANDOM__PCG_MULTIPLIER + PSNIP_RANDOM__PCG_INCREMENT;
|
||||
}
|
||||
|
||||
static psnip_uint32_t
|
||||
psnip_random__pcg_from_state(psnip_uint32_t state) {
|
||||
psnip_uint32_t res = ((state >> ((state >> 28) + 4)) ^ state) * (277803737U);
|
||||
res ^= res >> 22;
|
||||
return res;
|
||||
}
|
||||
|
||||
static int
|
||||
psnip_random__pgc_generate(psnip_atomic_int32* state, size_t length, psnip_uint8_t data[PSNIP_RANDOM_ARRAY_PARAM(length)]) {
|
||||
psnip_int32_t old_state;
|
||||
psnip_uint32_t new_state, v;
|
||||
size_t remaining;
|
||||
|
||||
do {
|
||||
old_state = psnip_atomic_int32_load(state);
|
||||
new_state = (psnip_uint32_t) old_state;
|
||||
|
||||
remaining = length;
|
||||
while (remaining > 0) {
|
||||
v = psnip_random__pcg_from_state(new_state);
|
||||
new_state = psnip_random__pcg_next_state(new_state);
|
||||
|
||||
if (remaining >= sizeof(psnip_uint32_t)) {
|
||||
memcpy(&(data[length - remaining]), &v, sizeof(psnip_uint32_t));
|
||||
remaining -= sizeof(psnip_uint32_t);
|
||||
} else {
|
||||
memcpy(&(data[length - remaining]), &v, remaining);
|
||||
remaining = 0;
|
||||
}
|
||||
}
|
||||
} while (!psnip_atomic_int32_compare_exchange(state, &old_state, (psnip_int32_t) new_state));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Reproducible */
|
||||
|
||||
static psnip_atomic_int32 psnip_random__reproducible_seed = 0;
|
||||
static psnip_atomic_int32 psnip_random__reproducible_state = 0;
|
||||
static psnip_once psnip_random_reproducible_once = PSNIP_ONCE_INIT;
|
||||
|
||||
static void
|
||||
psnip_random_reproducible_init(void) {
|
||||
psnip_int32_t seed = (psnip_uint32_t) psnip_random__pcg_gen_seed();
|
||||
|
||||
psnip_atomic_int32_store(&psnip_random__reproducible_seed, seed);
|
||||
psnip_atomic_int32_store(&psnip_random__reproducible_state, seed);
|
||||
}
|
||||
|
||||
void
|
||||
psnip_random_set_seed (psnip_uint32_t seed) {
|
||||
const psnip_int32_t sseed = (psnip_int32_t) seed;
|
||||
psnip_once_call(&psnip_random_reproducible_once, &psnip_random_reproducible_init);
|
||||
|
||||
psnip_atomic_int32_store(&psnip_random__reproducible_seed, sseed);
|
||||
psnip_atomic_int32_store(&psnip_random__reproducible_state, sseed);
|
||||
}
|
||||
|
||||
psnip_uint32_t
|
||||
psnip_random_get_seed (void) {
|
||||
psnip_once_call(&psnip_random_reproducible_once, &psnip_random_reproducible_init);
|
||||
|
||||
return (psnip_uint32_t) psnip_atomic_int32_load(&psnip_random__reproducible_seed);
|
||||
}
|
||||
|
||||
/* Fast */
|
||||
|
||||
static psnip_atomic_int32 psnip_random__fast_state = 0;
|
||||
static psnip_once psnip_random_fast_once = PSNIP_ONCE_INIT;
|
||||
|
||||
static void
|
||||
psnip_random_fast_init(void) {
|
||||
psnip_int32_t seed = (psnip_int32_t) psnip_random__pcg_gen_seed();
|
||||
|
||||
psnip_atomic_int32_store((psnip_atomic_int32*) &psnip_random__fast_state, seed);
|
||||
}
|
||||
|
||||
int
|
||||
psnip_random_bytes(enum PSnipRandomSource source,
|
||||
size_t length,
|
||||
psnip_uint8_t data[PSNIP_RANDOM_ARRAY_PARAM(length)]) {
|
||||
switch (source) {
|
||||
case PSNIP_RANDOM_SOURCE_SECURE:
|
||||
#if !defined(PSNIP_RANDOM_SECURE_NO_INIT)
|
||||
psnip_once_call(&psnip_random_secure_once, &psnip_random_secure_init);
|
||||
|
||||
if (psnip_random_secure_generate == NULL)
|
||||
return -1;
|
||||
#endif
|
||||
|
||||
return psnip_random_secure_generate(length, data);
|
||||
|
||||
case PSNIP_RANDOM_SOURCE_REPRODUCIBLE:
|
||||
#if !defined(PSNIP_RANDOM_REPRODUCIBLE_NO_INIT)
|
||||
psnip_once_call(&psnip_random_reproducible_once, &psnip_random_reproducible_init);
|
||||
#endif
|
||||
|
||||
return psnip_random__pgc_generate(&psnip_random__reproducible_state, length, data);
|
||||
|
||||
case PSNIP_RANDOM_SOURCE_FAST:
|
||||
#if !defined(PSNIP_RANDOM_FAST_NO_INIT)
|
||||
psnip_once_call(&psnip_random_fast_once, &psnip_random_fast_init);
|
||||
#endif
|
||||
|
||||
return psnip_random__pgc_generate(&psnip_random__fast_state, length, data);
|
||||
}
|
||||
|
||||
return -2;
|
||||
}
|
||||
38
thirdparty/portable-snippets/random/random.h
vendored
Normal file
38
thirdparty/portable-snippets/random/random.h
vendored
Normal file
|
|
@ -0,0 +1,38 @@
|
|||
#if !defined(PSNIP_RANDOM__H)
|
||||
#define PSNIP_RANDOM__H
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#if !defined(psnip_uint8_t)
|
||||
# include "../exact-int/exact-int.h"
|
||||
#endif
|
||||
|
||||
#if defined(HEDLEY_ARRAY_PARAM)
|
||||
# define PSNIP_RANDOM_ARRAY_PARAM(expr) HEDLEY_ARRAY_PARAM(expr)
|
||||
#elif defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) && !defined(__cplusplus) && !defined(__PGI)
|
||||
# define PSNIP_RANDOM_ARRAY_PARAM(expr) (expr)
|
||||
#else
|
||||
# define PSNIP_RANDOM_ARRAY_PARAM(expr)
|
||||
#endif
|
||||
|
||||
#if defined(__cplusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
enum PSnipRandomSource {
|
||||
PSNIP_RANDOM_SOURCE_SECURE,
|
||||
PSNIP_RANDOM_SOURCE_REPRODUCIBLE,
|
||||
PSNIP_RANDOM_SOURCE_FAST,
|
||||
};
|
||||
|
||||
int psnip_random_bytes (enum PSnipRandomSource source,
|
||||
size_t length,
|
||||
psnip_uint8_t data[PSNIP_RANDOM_ARRAY_PARAM(length)]);
|
||||
psnip_uint32_t psnip_random_get_seed (void);
|
||||
void psnip_random_set_seed (psnip_uint32_t seed);
|
||||
|
||||
#if defined(__cplusplus)
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* defined(PSNIP_RANDOM__H) */
|
||||
184
thirdparty/portable-snippets/safe-math/README.md
vendored
Normal file
184
thirdparty/portable-snippets/safe-math/README.md
vendored
Normal file
|
|
@ -0,0 +1,184 @@
|
|||
# Overflow-safe math functions
|
||||
|
||||
The safe-math.h header defines numerous functions for verifying that
|
||||
integer operations do not overflow. Available implementations, in
|
||||
order of priority:
|
||||
|
||||
* Compiler builtins (i.e., `__builtin_*_overflow`).
|
||||
* On Windows, use `<intsafe.h>` for the types it supports.
|
||||
* If a larger type is available, promote the inputs and verify the
|
||||
result falls within the range of the result type before casting to
|
||||
it.
|
||||
* Check that the operation would not result in an overflow before
|
||||
performing it. See [INT32-C in CERT's C Coding
|
||||
Standard](https://www.securecoding.cert.org/confluence/display/c/INT32-C.+Ensure+that+operations+on+signed+integers+do+not+result+in+overflow)
|
||||
for details.
|
||||
|
||||
# APIs
|
||||
|
||||
## Preferred API
|
||||
|
||||
Regardless of which implementation is chosen, the preferred API is the
|
||||
same. For each type and operation, we define:
|
||||
|
||||
```c
|
||||
psnip_safe_bool psnip_safe_{type_identifier}_{operation} ({T}* result, {T} a, {T} b);
|
||||
```
|
||||
|
||||
which returns true if the operation succeeded, or false if it resulted
|
||||
in an overflow (which is the opposite of how e.g.
|
||||
`__builtin_*_overflow` builtins work).
|
||||
|
||||
For example, for addition on signed integers, there is
|
||||
|
||||
```c
|
||||
psnip_safe_bool psnip_safe_int_add (int* res, int a, int b);
|
||||
```
|
||||
|
||||
Values for type_identifier and T are:
|
||||
|
||||
| Identifier | Type |
|
||||
| ---------- | -------------------- |
|
||||
| `char` | `char` |
|
||||
| `uchar` | `unsigned char` |
|
||||
| `short` | `short` |
|
||||
| `ushort` | `unsigned short` |
|
||||
| `int` | `int` |
|
||||
| `uint` | `unsigned int` |
|
||||
| `long` | `long` |
|
||||
| `ulong` | `unsigned long` |
|
||||
| `llong` | `long long` |
|
||||
| `ullong` | `unsigned long long` |
|
||||
| `size` | `size_t` |
|
||||
| `int8` | `int8_t` |
|
||||
| `uint8` | `uint8_t` |
|
||||
| `int16` | `int16_t` |
|
||||
| `uint16` | `uint16_t` |
|
||||
| `int32` | `int32_t` |
|
||||
| `uint32` | `uint32_t` |
|
||||
| `int64` | `int64_t` |
|
||||
| `uint64` | `uint64_t` |
|
||||
|
||||
Operations are:
|
||||
|
||||
* add (addition)
|
||||
* sub (subtraction)
|
||||
* mul (multiplication)
|
||||
* div (division)
|
||||
* mod (modulus)
|
||||
* neg (negation, for signed types only)
|
||||
|
||||
Negation only has one input argument, all the others have two.
|
||||
|
||||
`psnip_safe_bool` is defined to _Bool (for C99) or int.
|
||||
|
||||
## Emulation of native APIs
|
||||
|
||||
If you prefer, you can `#define` either `PSNIP_SAFE_EMULATE_NATIVE` or
|
||||
`PSNIP_BUILTIN_EMULATE_NATIVE` and we will also provide an API
|
||||
compatible with [GCC's overflow
|
||||
builtins](https://gcc.gnu.org/onlinedocs/gcc/Integer-Overflow-Builtins.html)
|
||||
unless the compiler we're using already provides it. There are two
|
||||
things to watch out for if you choose this:
|
||||
|
||||
* The type-generic functions (`__builtin_add_overflow`,
|
||||
`__builtin_sub_overflow`, and `__builtin_mul_overflow`) will only
|
||||
be available in C11 mode.
|
||||
* The argument order in GCC's API is slightly different, with the
|
||||
result coming last instead of first. We prefer the result to come
|
||||
first so the call looks a bit more like an assignment operation,
|
||||
but GCC made a different choice.
|
||||
|
||||
In other words, `__builtin_*_overflow(a, b, res)` are macros
|
||||
defined to `(!psnip_safe_*(res, a, b))` so existing code needn't
|
||||
be altered.
|
||||
|
||||
## The `safe_larger_*` API
|
||||
|
||||
In order to implement the versions of functions which promote the
|
||||
arguments then check the result before casting back to original type,
|
||||
we had to create an API. It's really intended as an internal API, and
|
||||
is a bit of a pain, but if you'd rather just have a larger result
|
||||
instead of having to check for the overflow case it can be useful.
|
||||
|
||||
For types where we know of a larger type we define the macro
|
||||
`PSNIP_SAFE_HAVE_TYPE_LARGER`, as well as a typedef to the larger type
|
||||
called `psnip_safe_type_larger`. For example, we know that there is a type
|
||||
larger than `int16_t` (`int32_t`), so there is:
|
||||
|
||||
```C
|
||||
#define PSNIP_SAFE_HAVE_INT16_LARGER
|
||||
typedef int32_t psnip_safe_int16_larger;
|
||||
```
|
||||
|
||||
This gets slightly more complicated (but more useful) when dealing
|
||||
with the non-fixed-length types. For example, short may or may not be
|
||||
larger than char (it's not shorter, but they may be equal). So,
|
||||
assuming char is less than 64-bits (or the compiler supports 128-bit
|
||||
numbers), we will define `PSNIP_SAFE_HAVE_CHAR_LARGER` and
|
||||
`psnip_safe_char_larger` will be a typedef to the first type which is larger
|
||||
than char (the order we try is `char`, `short`, `int`, `long`, `long
|
||||
long`, `int8_t`, `int16_t`, `int32_t`, `int64_t`, then the 128-bit
|
||||
integer type if available). So, `psnip_safe_char_larger` is a typedef to
|
||||
`short` if `short` is larger than `char`, otherwise `int` if `int` is
|
||||
larger than `char`, otherwise `long`, etc.
|
||||
|
||||
In addition to the typedefs, if there is a larger known type we
|
||||
also generate a set of functions in the form of
|
||||
|
||||
```C
|
||||
psnip_safe_type_larger psnip_safe_larger_type_operation(type, type)
|
||||
```
|
||||
|
||||
This is done for every type and every operation; for example, if
|
||||
`PSNIP_SAFE_HAVE_CHAR_LARGER` is defined, then so too will be
|
||||
|
||||
* `psnip_safe_char_larger psnip_safe_larger_char_add(char, char)`
|
||||
* `psnip_safe_char_larger psnip_safe_larger_char_sub(char, char)`
|
||||
* `psnip_safe_char_larger psnip_safe_larger_char_mul(char, char)`
|
||||
* `psnip_safe_char_larger psnip_safe_larger_char_div(char, char)`
|
||||
* `psnip_safe_char_larger psnip_safe_larger_char_mod(char, char)`
|
||||
* `psnip_safe_char_larger psnip_safe_larger_char_neg(char)`
|
||||
|
||||
# Caveats
|
||||
|
||||
The type-generic functions are only guaranteed to be available in C11
|
||||
mode since there was no standard way to implement them until C11.
|
||||
|
||||
Even if you request emulation of the GCC builtins, we cannot provide
|
||||
the `__builtin_*_overflow_p` functions.
|
||||
|
||||
## Dependencies
|
||||
|
||||
To maximize portability you should #include the exact-int module
|
||||
before including safe-math.h, but if you don't want to add the extra
|
||||
file to your project you can omit it and this module will simply rely
|
||||
on <stdint.h>. As an alternative you may define the following macros
|
||||
to appropriate values yourself:
|
||||
|
||||
* `psnip_int8_t`
|
||||
* `psnip_uint8_t`
|
||||
* `psnip_int16_t`
|
||||
* `psnip_uint16_t`
|
||||
* `psnip_int32_t`
|
||||
* `psnip_uint32_t`
|
||||
* `psnip_int64_t`
|
||||
* `psnip_uint64_t`
|
||||
|
||||
# Alternatives
|
||||
|
||||
## C
|
||||
|
||||
* [GCC Integer Overflow
|
||||
Builtins](https://gcc.gnu.org/onlinedocs/gcc/Integer-Overflow-Builtins.html)
|
||||
(GCC 5+)
|
||||
* [Windows'
|
||||
<intsafe.h>](https://msdn.microsoft.com/en-us/library/windows/desktop/ff521693(v=vs.85).aspx)
|
||||
(Windows only, unsigned only)
|
||||
|
||||
This module will use the above APIs if available.
|
||||
|
||||
## C++
|
||||
|
||||
* [SafeInt](https://safeint.codeplex.com/)
|
||||
* [Boost Safe Numerics](http://blincubator.com/bi_library/safe-numerics/?gform_post_id=426)
|
||||
1071
thirdparty/portable-snippets/safe-math/safe-math.h
vendored
Normal file
1071
thirdparty/portable-snippets/safe-math/safe-math.h
vendored
Normal file
File diff suppressed because it is too large
Load diff
198
thirdparty/portable-snippets/tests/CMakeLists.txt
vendored
Normal file
198
thirdparty/portable-snippets/tests/CMakeLists.txt
vendored
Normal file
|
|
@ -0,0 +1,198 @@
|
|||
cmake_minimum_required(VERSION 3.0)
|
||||
|
||||
project(portable-snippet-tests)
|
||||
|
||||
enable_testing()
|
||||
|
||||
set(CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/cmake)
|
||||
|
||||
if(NOT EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/munit/munit.c")
|
||||
find_program(GIT git)
|
||||
if(GIT)
|
||||
execute_process(COMMAND ${GIT} submodule update --init --recursive)
|
||||
else()
|
||||
message (FATAL_ERROR "It looks like you don't have submodules checked out. Please run `git submodule update --init --recursive'")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(ENABLE_OPENMP)
|
||||
find_package(OpenMP REQUIRED)
|
||||
endif()
|
||||
|
||||
include(CheckFunctionExists)
|
||||
check_function_exists(clock_gettime CLOCK_GETTIME_RES)
|
||||
if(CLOCK_GETTIME_RES)
|
||||
set(CLOCK_GETTIME_EXISTS yes)
|
||||
else()
|
||||
set(orig_req_libs "${CMAKE_REQUIRED_LIBRARIES}")
|
||||
set(CMAKE_REQUIRED_LIBRARIES "${CMAKE_REQUIRED_LIBRARIES};rt")
|
||||
|
||||
check_function_exists(clock_gettime CLOCK_GETTIME_LIBRT_RES)
|
||||
if(CLOCK_GETTIME_LIBRT_RES)
|
||||
set(CLOCK_GETTIME_EXISTS yes)
|
||||
set(CLOCK_GETTIME_LIBRARY "rt")
|
||||
endif()
|
||||
|
||||
set(CMAKE_REQUIRED_LIBRARIES "${orig_req_libs}")
|
||||
unset(orig_req_libs)
|
||||
endif()
|
||||
|
||||
include (AddCompilerFlags)
|
||||
|
||||
set(PSNIP_C_FLAGS)
|
||||
|
||||
if(FATAL_WARNINGS)
|
||||
set_compiler_specific_flags(VARIABLE FATAL_WARNING_FLAGS
|
||||
GCCISH -Werror
|
||||
MSVC /WX)
|
||||
list(APPEND PSNIP_C_FLAGS ${FATAL_WARNING_FLAGS})
|
||||
endif()
|
||||
|
||||
if(ENABLE_AGGRESSIVE_WARNINGS)
|
||||
set_compiler_specific_flags(VARIABLE EXTRA_WARNING_FLAGS
|
||||
GCCISH
|
||||
-Wall
|
||||
-Waggregate-return
|
||||
-Wcast-align
|
||||
-Wclobbered
|
||||
-Wempty-body
|
||||
-Werror=format=2
|
||||
-Werror=format-security
|
||||
-Werror=implicit-function-declaration
|
||||
-Werror=init-self
|
||||
-Werror=missing-include-dirs
|
||||
-Werror=missing-prototypes
|
||||
-Werror=pointer-arith
|
||||
-Wextra
|
||||
-Wformat-nonliteral
|
||||
-Wformat-security
|
||||
-Wignored-qualifiers
|
||||
-Winit-self
|
||||
-Winvalid-pch
|
||||
-Wlogical-op
|
||||
-Wmissing-declarations
|
||||
-Wmissing-format-attribute
|
||||
-Wmissing-include-dirs
|
||||
-Wmissing-noreturn
|
||||
-Wmissing-parameter-type
|
||||
-Wmissing-prototypes
|
||||
-Wnested-externs
|
||||
-Wno-missing-field-initializers
|
||||
-Wno-strict-aliasing
|
||||
-Wno-uninitialized
|
||||
-Wno-unused-parameter
|
||||
-Wold-style-definition
|
||||
-Woverride-init
|
||||
-Wpacked
|
||||
-Wpointer-arith
|
||||
-Wredundant-decls
|
||||
-Wreturn-type
|
||||
-Wshadow
|
||||
-Wsign-compare
|
||||
-Wstrict-prototypes
|
||||
-Wswitch-enum
|
||||
-Wsync-nand
|
||||
-Wtype-limits
|
||||
-Wundef
|
||||
-Wuninitialized
|
||||
-WUnsafe-loop-optimizations
|
||||
-Wwrite-strings
|
||||
-Wsuggest-attribute=format
|
||||
PGI
|
||||
-Minform=inform
|
||||
MSVC
|
||||
/W4
|
||||
/analyze)
|
||||
|
||||
list(APPEND PSNIP_C_FLAGS ${EXTRA_WARNING_FLAGS})
|
||||
endif()
|
||||
|
||||
if(NOT ENABLE_SANITIZER STREQUAL "")
|
||||
if(ENABLE_SANITIZER STREQUAL "undefined")
|
||||
set_compiler_specific_flags(VARIABLE UBSAN_FLAGS
|
||||
GCCISH -fsanitize=undefined
|
||||
GCC -fno-sanitize-recover=undefined,float-cast-overflow,float-divide-by-zero
|
||||
CLANG -fno-sanitize-recover=undefined,integer)
|
||||
list(APPEND PSNIP_C_FLAGS ${UBSAN_FLAGS})
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(NOT CMAKE_BUILD_TYPE)
|
||||
set(CMAKE_BUILD_TYPE Release)
|
||||
endif()
|
||||
|
||||
set(CMAKE_C_FLAGS_DEBUG)
|
||||
set(CMAKE_C_FLAGS_RELEASE)
|
||||
|
||||
set_compiler_specific_flags(
|
||||
VARIABLE PSNIP_RELEASE_FLAGS
|
||||
GCCISH -O3 -DNDEBUG)
|
||||
foreach(flag ${PSNIP_RELEASE_FLAGS})
|
||||
set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} ${flag}")
|
||||
endforeach()
|
||||
|
||||
set_compiler_specific_flags(
|
||||
VARIABLE PSNIP_DEBUG_FLAGS
|
||||
GCCISH -O3 -g)
|
||||
foreach(flag ${PSNIP_DEBUG_FLAGS})
|
||||
set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} ${flag}")
|
||||
endforeach()
|
||||
|
||||
add_library(munit munit/munit.c)
|
||||
set_property(TARGET munit PROPERTY C_STANDARD "99")
|
||||
if("${CLOCK_GETTIME_EXISTS}")
|
||||
target_compile_definitions(munit PRIVATE "MUNIT_ALLOW_CLOCK_GETTIME")
|
||||
target_link_libraries(munit "${CLOCK_GETTIME_LIBRARY}")
|
||||
endif()
|
||||
|
||||
function(psnip_add_tests)
|
||||
set(options)
|
||||
set(oneValueArgs TARGET)
|
||||
set(multiValueArgs SOURCES TESTS)
|
||||
cmake_parse_arguments(PSNIP_TEST "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
|
||||
|
||||
add_executable("${PSNIP_TEST_TARGET}" ${PSNIP_TEST_SOURCES})
|
||||
target_link_libraries("${PSNIP_TEST_TARGET}" munit)
|
||||
target_add_compiler_flags("${PSNIP_TEST_TARGET}" ${PSNIP_C_FLAGS})
|
||||
|
||||
if(PSNIP_TEST_TESTS)
|
||||
foreach(TEST ${PSNIP_TEST_TESTS})
|
||||
add_test(NAME "${TEST}"
|
||||
COMMAND ${CMAKE_CROSSCOMPILING_EMULATOR} $<TARGET_FILE:${PSNIP_TEST_TARGET}> "${TEST}")
|
||||
endforeach(TEST)
|
||||
else()
|
||||
add_test(NAME "/${PSNIP_TEST_TARGET}"
|
||||
COMMAND ${CMAKE_CROSSCOMPILING_EMULATOR} $<TARGET_FILE:${PSNIP_TEST_TARGET}>)
|
||||
endif()
|
||||
endfunction(psnip_add_tests)
|
||||
|
||||
psnip_add_tests(TARGET endian SOURCES endian.c)
|
||||
psnip_add_tests(TARGET atomic SOURCES atomic.c)
|
||||
psnip_add_tests(TARGET builtin SOURCES builtin.c
|
||||
TESTS "/builtin" "/intrin" "/wrapper")
|
||||
psnip_add_tests(TARGET safe-math SOURCES safe-math.c)
|
||||
psnip_add_tests(TARGET unaligned SOURCES unaligned.c)
|
||||
psnip_add_tests(TARGET clock SOURCES clock.c)
|
||||
psnip_add_tests(TARGET once SOURCES once.c)
|
||||
psnip_add_tests(TARGET cpu SOURCES cpu.c ../cpu/cpu.c)
|
||||
psnip_add_tests(TARGET random SOURCES random.c ../random/random.c ../cpu/cpu.c)
|
||||
|
||||
if(ENABLE_PTHREADS)
|
||||
find_package (Threads REQUIRED)
|
||||
foreach(tgt once cpu random)
|
||||
target_link_libraries(${tgt} ${CMAKE_THREAD_LIBS_INIT})
|
||||
target_compile_definitions(${tgt} PRIVATE PSNIP_ENABLE_PTHREADS)
|
||||
endforeach()
|
||||
endif()
|
||||
|
||||
if(ENABLE_OPENMP)
|
||||
foreach(tgt atomic once cpu random)
|
||||
target_compile_options(${tgt} PRIVATE ${OpenMP_C_FLAGS})
|
||||
endforeach()
|
||||
endif()
|
||||
|
||||
if("${CLOCK_GETTIME_EXISTS}")
|
||||
target_link_libraries(clock "${CLOCK_GETTIME_LIBRARY}")
|
||||
else()
|
||||
target_compile_definitions(clock PRIVATE "PSNIP_CLOCK_NO_LIBRT")
|
||||
endif()
|
||||
101
thirdparty/portable-snippets/tests/atomic.c
vendored
Normal file
101
thirdparty/portable-snippets/tests/atomic.c
vendored
Normal file
|
|
@ -0,0 +1,101 @@
|
|||
#include <stdlib.h>
|
||||
#include "../exact-int/exact-int.h"
|
||||
#include "../atomic/atomic.h"
|
||||
#include "munit/munit.h"
|
||||
|
||||
#if !defined(PSNIP_ATOMIC_NOT_FOUND)
|
||||
static psnip_atomic_int64 value64 = PSNIP_ATOMIC_VAR_INIT(9);
|
||||
static psnip_atomic_int32 value32 = PSNIP_ATOMIC_VAR_INIT(9);
|
||||
#endif
|
||||
|
||||
static MunitResult
|
||||
test_atomic_int64(const MunitParameter params[], void* data) {
|
||||
#if !defined(PSNIP_ATOMIC_NOT_FOUND)
|
||||
psnip_int64_t v, expected;
|
||||
#endif
|
||||
|
||||
(void) params;
|
||||
(void) data;
|
||||
|
||||
#if !defined(PSNIP_ATOMIC_NOT_FOUND)
|
||||
v = psnip_atomic_int64_load(&value64);
|
||||
munit_assert_int64(v, ==, 9);
|
||||
|
||||
v = v * v * v;
|
||||
psnip_atomic_int64_store(&value64, v);
|
||||
v = psnip_atomic_int64_load(&value64);
|
||||
munit_assert_int64(v, ==, 729);
|
||||
|
||||
psnip_atomic_int64_add(&value64, 1000);
|
||||
v = psnip_atomic_int64_load(&value64);
|
||||
munit_assert_int64(v, ==, 1729);
|
||||
|
||||
psnip_atomic_int64_sub(&value64, 729);
|
||||
v = psnip_atomic_int64_load(&value64);
|
||||
munit_assert_int64(v, ==, 1000);
|
||||
|
||||
do {
|
||||
expected = psnip_atomic_int64_load(&value64);
|
||||
v = expected * expected;
|
||||
} while (!psnip_atomic_int64_compare_exchange(&value64, &expected, v));
|
||||
v = psnip_atomic_int64_load(&value64);
|
||||
munit_assert_int64(v, ==, 1000 * 1000);
|
||||
|
||||
return MUNIT_OK;
|
||||
#else
|
||||
return MUNIT_SKIP;
|
||||
#endif
|
||||
}
|
||||
|
||||
static MunitResult
|
||||
test_atomic_int32(const MunitParameter params[], void* data) {
|
||||
#if !defined(PSNIP_ATOMIC_NOT_FOUND)
|
||||
psnip_int32_t v, expected;
|
||||
#endif
|
||||
|
||||
(void) params;
|
||||
(void) data;
|
||||
|
||||
#if !defined(PSNIP_ATOMIC_NOT_FOUND)
|
||||
v = psnip_atomic_int32_load(&value32);
|
||||
munit_assert_int32(v, ==, 9);
|
||||
|
||||
v = v * v * v;
|
||||
psnip_atomic_int32_store(&value32, v);
|
||||
v = psnip_atomic_int32_load(&value32);
|
||||
munit_assert_int32(v, ==, 729);
|
||||
|
||||
psnip_atomic_int32_add(&value32, 1000);
|
||||
v = psnip_atomic_int32_load(&value32);
|
||||
munit_assert_int32(v, ==, 1729);
|
||||
|
||||
psnip_atomic_int32_sub(&value32, 729);
|
||||
v = psnip_atomic_int32_load(&value32);
|
||||
munit_assert_int32(v, ==, 1000);
|
||||
|
||||
do {
|
||||
expected = psnip_atomic_int32_load(&value32);
|
||||
v = expected * expected;
|
||||
} while (!psnip_atomic_int32_compare_exchange(&value32, &expected, v));
|
||||
v = psnip_atomic_int32_load(&value32);
|
||||
munit_assert_int32(v, ==, 1000 * 1000);
|
||||
|
||||
return MUNIT_OK;
|
||||
#else
|
||||
return MUNIT_SKIP;
|
||||
#endif
|
||||
}
|
||||
|
||||
static MunitTest test_suite_tests[] = {
|
||||
{ (char*) "/atomic/int64", test_atomic_int64, NULL, NULL, MUNIT_TEST_OPTION_NONE, NULL },
|
||||
{ (char*) "/atomic/int32", test_atomic_int32, NULL, NULL, MUNIT_TEST_OPTION_NONE, NULL },
|
||||
{ NULL, NULL, NULL, NULL, MUNIT_TEST_OPTION_NONE, NULL }
|
||||
};
|
||||
|
||||
static const MunitSuite test_suite = {
|
||||
(char*) "", test_suite_tests, NULL, 1, MUNIT_SUITE_OPTION_NONE
|
||||
};
|
||||
|
||||
int main(int argc, char* argv[MUNIT_ARRAY_PARAM(argc + 1)]) {
|
||||
return munit_suite_main(&test_suite, NULL, argc, argv);
|
||||
}
|
||||
1640
thirdparty/portable-snippets/tests/builtin.c
vendored
Normal file
1640
thirdparty/portable-snippets/tests/builtin.c
vendored
Normal file
File diff suppressed because it is too large
Load diff
175
thirdparty/portable-snippets/tests/clock.c
vendored
Normal file
175
thirdparty/portable-snippets/tests/clock.c
vendored
Normal file
|
|
@ -0,0 +1,175 @@
|
|||
#define _POSIX_C_SOURCE 199309L
|
||||
|
||||
#include "../exact-int/exact-int.h"
|
||||
#include "../clock/clock.h"
|
||||
#include "munit/munit.h"
|
||||
|
||||
/* These tests can yield false positives in some situations, but I'm
|
||||
* having trouble thinking of better ways to test. Ideas welcome. */
|
||||
|
||||
#if !defined(_WIN32)
|
||||
# include <unistd.h>
|
||||
# define sleep_seconds(n) sleep(n)
|
||||
#else
|
||||
# include <Windows.h>
|
||||
# define sleep_seconds(n) Sleep((n) * 1000)
|
||||
#endif
|
||||
|
||||
static MunitResult
|
||||
test_clock_wall_time(const MunitParameter params[], void* data) {
|
||||
#if defined(PSNIP_CLOCK_WALL_METHOD)
|
||||
struct PsnipClockTimespec res;
|
||||
psnip_uint32_t precision = psnip_clock_get_precision(PSNIP_CLOCK_TYPE_WALL);
|
||||
time_t t;
|
||||
int r;
|
||||
|
||||
(void) params;
|
||||
(void) data;
|
||||
|
||||
munit_logf(MUNIT_LOG_DEBUG, "Wall clock method: %d", PSNIP_CLOCK_WALL_METHOD);
|
||||
|
||||
munit_assert_uint32(precision, !=, 0);
|
||||
|
||||
t = time(NULL);
|
||||
/* This test may fail if more than 1 second passes here, but this
|
||||
* thread could conceivably be preempted for longer. */
|
||||
r = psnip_clock_get_time(PSNIP_CLOCK_TYPE_WALL, &res);
|
||||
munit_assert_int(r, ==, 0);
|
||||
|
||||
munit_assert_uint64(t, <=, res.seconds);
|
||||
munit_assert_uint64(t, >=, res.seconds - 1);
|
||||
|
||||
return MUNIT_OK;
|
||||
#else
|
||||
(void) params;
|
||||
(void) data;
|
||||
|
||||
return MUNIT_SKIP;
|
||||
#endif
|
||||
}
|
||||
|
||||
static int ts_difference(struct PsnipClockTimespec* earlier, struct PsnipClockTimespec* later) {
|
||||
return
|
||||
(int) ((later->seconds - earlier->seconds) * 1000) +
|
||||
(int) ((((psnip_int64_t) later->nanoseconds) - ((psnip_int64_t) earlier->nanoseconds)) / 1000000);
|
||||
}
|
||||
|
||||
static MunitResult
|
||||
test_clock_wall_veracity(const MunitParameter params[], void* data) {
|
||||
#if defined(PSNIP_CLOCK_WALL_METHOD)
|
||||
struct PsnipClockTimespec res1, res2;
|
||||
int elapsed_ms;
|
||||
int r;
|
||||
|
||||
r = psnip_clock_get_time(PSNIP_CLOCK_TYPE_WALL, &res1);
|
||||
munit_assert_int(r, ==, 0);
|
||||
|
||||
/* Assuming we aren't interrupted by a signal, aren't suspended for
|
||||
* much more than 1 seconds, etc. */
|
||||
sleep_seconds(1);
|
||||
|
||||
r = psnip_clock_get_time(PSNIP_CLOCK_TYPE_WALL, &res2);
|
||||
munit_assert_int(r, ==, 0);
|
||||
|
||||
elapsed_ms = ts_difference(&res1, &res2);
|
||||
|
||||
munit_assert_int(elapsed_ms, >, 900);
|
||||
munit_assert_int(elapsed_ms, <, 1100);
|
||||
|
||||
(void) params;
|
||||
(void) data;
|
||||
|
||||
return MUNIT_OK;
|
||||
#else
|
||||
(void) params;
|
||||
(void) data;
|
||||
|
||||
return MUNIT_SKIP;
|
||||
#endif
|
||||
}
|
||||
|
||||
static MunitResult
|
||||
test_clock_cpu(const MunitParameter params[], void* data) {
|
||||
#if defined(PSNIP_CLOCK_CPU_METHOD)
|
||||
struct PsnipClockTimespec res1, res2;
|
||||
psnip_uint32_t precision = psnip_clock_get_precision(PSNIP_CLOCK_TYPE_WALL);
|
||||
int r;
|
||||
int elapsed_ms;
|
||||
|
||||
munit_logf(MUNIT_LOG_DEBUG, "CPU clock method: %d", PSNIP_CLOCK_CPU_METHOD);
|
||||
|
||||
munit_assert_uint32(precision, !=, 0);
|
||||
|
||||
r = psnip_clock_get_time(PSNIP_CLOCK_TYPE_WALL, &res1);
|
||||
munit_assert_int(r, ==, 0);
|
||||
|
||||
sleep_seconds(1);
|
||||
|
||||
r = psnip_clock_get_time(PSNIP_CLOCK_TYPE_WALL, &res2);
|
||||
munit_assert_int(r, ==, 0);
|
||||
|
||||
elapsed_ms = ts_difference(&res1, &res2);
|
||||
|
||||
munit_assert_int(elapsed_ms, >=, 1000);
|
||||
if (precision >= 1000)
|
||||
munit_assert_int(elapsed_ms, <=, 1100);
|
||||
|
||||
(void) params;
|
||||
(void) data;
|
||||
|
||||
return MUNIT_OK;
|
||||
#else
|
||||
(void) params;
|
||||
(void) data;
|
||||
|
||||
return MUNIT_SKIP;
|
||||
#endif
|
||||
}
|
||||
|
||||
static MunitResult
|
||||
test_clock_monotonic(const MunitParameter params[], void* data) {
|
||||
|
||||
#if defined(PSNIP_CLOCK_MONOTONIC_METHOD)
|
||||
struct PsnipClockTimespec res1, res2;
|
||||
int r;
|
||||
int elapsed_ms;
|
||||
|
||||
r = psnip_clock_get_time(PSNIP_CLOCK_TYPE_MONOTONIC, &res1);
|
||||
munit_assert_int(r, ==, 0);
|
||||
|
||||
/* Assuming we aren't interrupted by a signal, aren't suspended for
|
||||
* much more than 2 seconds, etc. */
|
||||
sleep_seconds(1);
|
||||
|
||||
r = psnip_clock_get_time(PSNIP_CLOCK_TYPE_MONOTONIC, &res2);
|
||||
munit_assert_int(r, ==, 0);
|
||||
|
||||
elapsed_ms = ts_difference(&res1, &res2);
|
||||
|
||||
munit_assert_int(elapsed_ms, >, 900);
|
||||
munit_assert_int(elapsed_ms, <, 1100);
|
||||
|
||||
(void) params;
|
||||
(void) data;
|
||||
|
||||
return MUNIT_OK;
|
||||
#else
|
||||
return MUNIT_SKIP;
|
||||
#endif
|
||||
}
|
||||
|
||||
static MunitTest test_suite_tests[] = {
|
||||
{ (char*) "/clock/wall/time", test_clock_wall_time, NULL, NULL, MUNIT_TEST_OPTION_SINGLE_ITERATION, NULL },
|
||||
{ (char*) "/clock/wall/veracity", test_clock_wall_veracity, NULL, NULL, MUNIT_TEST_OPTION_SINGLE_ITERATION, NULL },
|
||||
{ (char*) "/clock/cpu", test_clock_cpu, NULL, NULL, MUNIT_TEST_OPTION_SINGLE_ITERATION, NULL },
|
||||
{ (char*) "/clock/monotonic", test_clock_monotonic, NULL, NULL, MUNIT_TEST_OPTION_SINGLE_ITERATION, NULL },
|
||||
{ NULL, NULL, NULL, NULL, MUNIT_TEST_OPTION_NONE, NULL }
|
||||
};
|
||||
|
||||
static const MunitSuite test_suite = {
|
||||
(char*) "", test_suite_tests, NULL, 16384, MUNIT_SUITE_OPTION_NONE
|
||||
};
|
||||
|
||||
int main(int argc, char* argv[MUNIT_ARRAY_PARAM(argc + 1)]) {
|
||||
return munit_suite_main(&test_suite, NULL, argc, argv);
|
||||
}
|
||||
171
thirdparty/portable-snippets/tests/cmake/AddCompilerFlags.cmake
vendored
Normal file
171
thirdparty/portable-snippets/tests/cmake/AddCompilerFlags.cmake
vendored
Normal file
|
|
@ -0,0 +1,171 @@
|
|||
# This module provides a convenient way to add C/C++ compiler flags if
|
||||
# the compiler supports them.
|
||||
|
||||
include (CheckCCompilerFlag)
|
||||
include (CheckCXXCompilerFlag)
|
||||
|
||||
cmake_policy(SET CMP0054 NEW)
|
||||
|
||||
# Depending on the settings, some compilers will accept unknown flags.
|
||||
# We try to disable this behavior by also passing these flags when we
|
||||
# check if a flag is supported.
|
||||
set (ADD_COMPILER_FLAGS_PREPEND "")
|
||||
|
||||
if (CMAKE_C_COMPILER_ID STREQUAL "GNU")
|
||||
set (ADD_COMPILER_FLAGS_PREPEND "-Wall -Wextra -Werror")
|
||||
elseif (CMAKE_C_COMPILER_ID STREQUAL "Clang")
|
||||
set (ADD_COMPILER_FLAGS_PREPEND "-Werror=unknown-warning-option")
|
||||
endif ()
|
||||
|
||||
##
|
||||
# Set a variable to different flags, depending on which compiler is in
|
||||
# use.
|
||||
#
|
||||
# Example:
|
||||
# set_compiler_flags(VARIABLE varname MSVC /wd666 INTEL /wd1729)
|
||||
#
|
||||
# This will set varname to /wd666 if the compiler is MSVC, and /wd1729
|
||||
# if it is Intel.
|
||||
#
|
||||
# Possible compilers:
|
||||
# - GCC: GNU C Compiler
|
||||
# - GCCISH: A compiler that (tries to) be GCC-compatible on the CLI
|
||||
# (i.e., anything but MSVC).
|
||||
# - CLANG: clang
|
||||
# - MSVC: Microsoft Visual C++ compiler
|
||||
# - INTEL: Intel C Compiler
|
||||
# - PGI: PGI C Compiler
|
||||
#
|
||||
# Note: the compiler is determined based on the value of the
|
||||
# CMAKE_C_COMPILER_ID variable, not CMAKE_CXX_COMPILER_ID.
|
||||
##
|
||||
function (set_compiler_specific_flags)
|
||||
set (oneValueArgs VARIABLE)
|
||||
set (multiValueArgs GCC GCCISH INTEL CLANG MSVC PGI)
|
||||
cmake_parse_arguments(COMPILER_SPECIFIC_FLAGS "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
|
||||
unset (options)
|
||||
unset (oneValueArgs)
|
||||
unset (multiValueArgs)
|
||||
|
||||
set (compiler_flags)
|
||||
|
||||
if (CMAKE_C_COMPILER_ID STREQUAL "GNU")
|
||||
list (APPEND compiler_flags ${COMPILER_SPECIFIC_FLAGS_GCC})
|
||||
elseif(CMAKE_C_COMPILER_ID STREQUAL "Clang")
|
||||
list (APPEND compiler_flags ${COMPILER_SPECIFIC_FLAGS_CLANG})
|
||||
elseif(CMAKE_C_COMPILER_ID STREQUAL "Intel")
|
||||
list (APPEND compiler_flags ${COMPILER_SPECIFIC_FLAGS_INTEL})
|
||||
elseif(CMAKE_C_COMPILER_ID STREQUAL "MSVC")
|
||||
list (APPEND compiler_flags ${COMPILER_SPECIFIC_FLAGS_MSVC})
|
||||
elseif(CMAKE_C_COMPILER_ID STREQUAL "PGI")
|
||||
list (APPEND compiler_flags ${COMPILER_SPECIFIC_FLAGS_PGI})
|
||||
endif()
|
||||
|
||||
set(GCCISH_COMPILERS GNU Clang Intel)
|
||||
list(FIND GCCISH_COMPILERS "${CMAKE_C_COMPILER_ID}" IS_GCCISH)
|
||||
if (IS_GCCISH GREATER -1)
|
||||
list (APPEND compiler_flags ${COMPILER_SPECIFIC_FLAGS_GCCISH})
|
||||
endif ()
|
||||
|
||||
set (${COMPILER_SPECIFIC_FLAGS_VARIABLE} "${compiler_flags}" PARENT_SCOPE)
|
||||
endfunction ()
|
||||
|
||||
function (source_file_add_compiler_flags_unchecked file)
|
||||
set (flags ${ARGV})
|
||||
list (REMOVE_AT flags 0)
|
||||
get_source_file_property (sources ${file} SOURCES)
|
||||
|
||||
foreach (flag ${flags})
|
||||
get_source_file_property (existing ${file} COMPILE_FLAGS)
|
||||
if ("${existing}" STREQUAL "NOTFOUND")
|
||||
set_source_files_properties (${file}
|
||||
PROPERTIES COMPILE_FLAGS "${flag}")
|
||||
else ()
|
||||
set_source_files_properties (${file}
|
||||
PROPERTIES COMPILE_FLAGS "${existing} ${flag}")
|
||||
endif ()
|
||||
endforeach (flag)
|
||||
endfunction ()
|
||||
|
||||
function (source_file_add_compiler_flags file)
|
||||
set (flags ${ARGV})
|
||||
list (REMOVE_AT flags 0)
|
||||
get_source_file_property (sources ${file} SOURCES)
|
||||
|
||||
foreach (flag ${flags})
|
||||
if (CMAKE_C_COMPILER_ID STREQUAL "GNU")
|
||||
# Because https://gcc.gnu.org/wiki/FAQ#wnowarning
|
||||
string (REGEX REPLACE "\\-Wno\\-(.+)" "-W\\1" flag_to_test "${flag}")
|
||||
else ()
|
||||
set (flag_to_test ${flag})
|
||||
endif ()
|
||||
|
||||
if (file MATCHES "\\.c$")
|
||||
string (REGEX REPLACE "[^a-zA-Z0-9]+" "_" test_name "CFLAG_${flag_to_test}")
|
||||
CHECK_C_COMPILER_FLAG ("${ADD_COMPILER_FLAGS_PREPEND} ${flag_to_test}" ${test_name})
|
||||
elseif (file MATCHES "\\.(cpp|cc|cxx)$")
|
||||
string (REGEX REPLACE "[^a-zA-Z0-9]+" "_" test_name "CXXFLAG_${flag_to_test}")
|
||||
CHECK_CXX_COMPILER_FLAG ("${ADD_COMPILER_FLAGS_PREPEND} ${flag_to_test}" ${test_name})
|
||||
endif ()
|
||||
|
||||
if (${test_name})
|
||||
source_file_add_compiler_flags_unchecked (${file} ${flag})
|
||||
endif ()
|
||||
|
||||
unset (test_name)
|
||||
unset (flag_to_test)
|
||||
endforeach (flag)
|
||||
|
||||
unset (flags)
|
||||
endfunction ()
|
||||
|
||||
function (target_add_compiler_flags target)
|
||||
set (flags ${ARGV})
|
||||
list (REMOVE_AT flags 0)
|
||||
get_target_property (sources ${target} SOURCES)
|
||||
|
||||
foreach (source ${sources})
|
||||
source_file_add_compiler_flags (${source} ${flags})
|
||||
endforeach (source)
|
||||
|
||||
unset (flags)
|
||||
unset (sources)
|
||||
endfunction (target_add_compiler_flags)
|
||||
|
||||
# global_add_compiler_flags (flag1 [flag2 [flag3 ...]]):
|
||||
#
|
||||
# This just adds the requested compiler flags to
|
||||
# CMAKE_C/CXX_FLAGS variable if they work with the compiler.
|
||||
function (global_add_compiler_flags)
|
||||
set (flags ${ARGV})
|
||||
|
||||
foreach (flag ${flags})
|
||||
if ("GNU" STREQUAL "${CMAKE_C_COMPILER_ID}")
|
||||
# Because https://gcc.gnu.org/wiki/FAQ#wnowarning
|
||||
string (REGEX REPLACE "\\-Wno\\-(.+)" "-W\\1" flag_to_test "${flag}")
|
||||
else ()
|
||||
set (flag_to_test "${flag}")
|
||||
endif ()
|
||||
|
||||
string (REGEX REPLACE "[^a-zA-Z0-9]+" "_" c_test_name "CFLAG_${flag_to_test}")
|
||||
CHECK_C_COMPILER_FLAG ("${ADD_COMPILER_FLAGS_PREPEND} ${flag_to_test}" ${c_test_name})
|
||||
if (${c_test_name})
|
||||
set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${flag}")
|
||||
endif ()
|
||||
unset (c_test_name)
|
||||
|
||||
string (REGEX REPLACE "[^a-zA-Z0-9]+" "_" cxx_test_name "CFLAG_${flag_to_test}")
|
||||
CHECK_CXX_COMPILER_FLAG ("${ADD_COMPILER_FLAGS_PREPEND} ${flag_to_test}" ${cxx_test_name})
|
||||
if (${cxx_test_name})
|
||||
set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${flag}")
|
||||
endif ()
|
||||
unset (cxx_test_name)
|
||||
|
||||
unset (flag_to_test)
|
||||
endforeach (flag)
|
||||
|
||||
unset (flags)
|
||||
|
||||
set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS}" PARENT_SCOPE)
|
||||
set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}" PARENT_SCOPE)
|
||||
endfunction (global_add_compiler_flags)
|
||||
40
thirdparty/portable-snippets/tests/cmake/FindClockGettime.cmake
vendored
Normal file
40
thirdparty/portable-snippets/tests/cmake/FindClockGettime.cmake
vendored
Normal file
|
|
@ -0,0 +1,40 @@
|
|||
include (CheckFunctionExists)
|
||||
|
||||
set(ClockGettime_LIBRARIES "")
|
||||
set(ClockGettime_FOUND 0)
|
||||
mark_as_advanced(ClockGettime_LIBRARIES CLOCK_GETTIME_FOUND)
|
||||
|
||||
set(CMAKE_REQUIRED_LIBRARIES_orig "${CMAKE_REQUIRED_LIBRARIES}")
|
||||
set(CMAKE_REQUIRED_LIBRARIES "")
|
||||
|
||||
check_function_exists(clock_gettime ClockGettime_LIBC)
|
||||
if(ClockGettime_LIBC)
|
||||
set(ClockGettime_LIBRARIES "")
|
||||
set(ClockGettime_FOUND 1)
|
||||
else()
|
||||
set(CMAKE_REQUIRED_LIBRARIES rt)
|
||||
check_function_exists(clock_gettime ClockGettime_LIBRT)
|
||||
|
||||
if(ClockGettime_LIBRT)
|
||||
set(ClockGettime_LIBRARIES rt)
|
||||
set(ClockGettime_FOUND 1)
|
||||
else()
|
||||
# mingw puts clock_gettime in pthreads
|
||||
set(CMAKE_REQUIRED_LIBRARIES pthread)
|
||||
check_function_exists(clock_gettime ClockGettime_LIBPTHREAD)
|
||||
|
||||
if(ClockGettime_LIBPTHREAD)
|
||||
set(ClockGettime_LIBRARIES pthread)
|
||||
set(ClockGettime_FOUND 1)
|
||||
endif()
|
||||
|
||||
unset(ClockGettime_LIBPTHREAD)
|
||||
endif()
|
||||
|
||||
unset(ClockGettime_LIBRT)
|
||||
endif()
|
||||
|
||||
unset(ClockGettime_LIBC)
|
||||
|
||||
set(CMAKE_REQUIRED_LIBRARIES "${CMAKE_REQUIRED_LIBRARIES_orig}")
|
||||
unset(CMAKE_REQUIRED_LIBRARIES_orig)
|
||||
57
thirdparty/portable-snippets/tests/cpu.c
vendored
Normal file
57
thirdparty/portable-snippets/tests/cpu.c
vendored
Normal file
|
|
@ -0,0 +1,57 @@
|
|||
#include "../exact-int/exact-int.h"
|
||||
#include "../cpu/cpu.h"
|
||||
#include "munit/munit.h"
|
||||
|
||||
static MunitResult
|
||||
test_cpu_info(const MunitParameter params[], void* data) {
|
||||
(void) params;
|
||||
(void) data;
|
||||
|
||||
#if defined(__GNUC__) && ((__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ > 7))
|
||||
# if defined(PSNIP_CPU_ARCH_X86_64) || defined(PSNIP_CPU_ARCH_X86)
|
||||
__builtin_cpu_init();
|
||||
|
||||
munit_assert_int(__builtin_cpu_supports("cmov") != 0, ==, psnip_cpu_feature_check(PSNIP_CPU_FEATURE_X86_CMOV));
|
||||
munit_assert_int(__builtin_cpu_supports("mmx") != 0, ==, psnip_cpu_feature_check(PSNIP_CPU_FEATURE_X86_MMX));
|
||||
munit_assert_int(__builtin_cpu_supports("popcnt") != 0, ==, psnip_cpu_feature_check(PSNIP_CPU_FEATURE_X86_POPCNT));
|
||||
munit_assert_int(__builtin_cpu_supports("sse") != 0, ==, psnip_cpu_feature_check(PSNIP_CPU_FEATURE_X86_SSE));
|
||||
munit_assert_int(__builtin_cpu_supports("sse2") != 0, ==, psnip_cpu_feature_check(PSNIP_CPU_FEATURE_X86_SSE2));
|
||||
munit_assert_int(__builtin_cpu_supports("sse3") != 0, ==, psnip_cpu_feature_check(PSNIP_CPU_FEATURE_X86_SSE3));
|
||||
munit_assert_int(__builtin_cpu_supports("sse4.1") != 0, ==, psnip_cpu_feature_check(PSNIP_CPU_FEATURE_X86_SSE4_1));
|
||||
munit_assert_int(__builtin_cpu_supports("sse4.2") != 0, ==, psnip_cpu_feature_check(PSNIP_CPU_FEATURE_X86_SSE4_2));
|
||||
munit_assert_int(__builtin_cpu_supports("avx") != 0, ==, psnip_cpu_feature_check(PSNIP_CPU_FEATURE_X86_AVX));
|
||||
munit_assert_int(__builtin_cpu_supports("avx2") != 0, ==, psnip_cpu_feature_check(PSNIP_CPU_FEATURE_X86_AVX2));
|
||||
#if __GNUC__ >= 5
|
||||
munit_assert_int(__builtin_cpu_supports("avx512f") != 0, ==, psnip_cpu_feature_check(PSNIP_CPU_FEATURE_X86_AVX512F));
|
||||
#endif
|
||||
|
||||
return MUNIT_OK;
|
||||
# endif
|
||||
#endif
|
||||
|
||||
return MUNIT_SKIP;
|
||||
}
|
||||
|
||||
static MunitResult
|
||||
test_cpu_count(const MunitParameter params[], void* data) {
|
||||
(void) params;
|
||||
(void) data;
|
||||
|
||||
munit_assert_int(psnip_cpu_count(), >, 0);
|
||||
|
||||
return MUNIT_OK;
|
||||
}
|
||||
|
||||
static MunitTest test_suite_tests[] = {
|
||||
{ (char*) "/cpu/info", test_cpu_info, NULL, NULL, MUNIT_TEST_OPTION_NONE, NULL },
|
||||
{ (char*) "/cpu/count", test_cpu_count, NULL, NULL, MUNIT_TEST_OPTION_NONE, NULL },
|
||||
{ NULL, NULL, NULL, NULL, MUNIT_TEST_OPTION_NONE, NULL }
|
||||
};
|
||||
|
||||
static const MunitSuite test_suite = {
|
||||
(char*) "", test_suite_tests, NULL, 1, MUNIT_SUITE_OPTION_NONE
|
||||
};
|
||||
|
||||
int main(int argc, char* argv[MUNIT_ARRAY_PARAM(argc + 1)]) {
|
||||
return munit_suite_main(&test_suite, NULL, argc, argv);
|
||||
}
|
||||
139
thirdparty/portable-snippets/tests/endian.c
vendored
Normal file
139
thirdparty/portable-snippets/tests/endian.c
vendored
Normal file
|
|
@ -0,0 +1,139 @@
|
|||
#include <stdlib.h>
|
||||
|
||||
#include "../exact-int/exact-int.h"
|
||||
#include "../endian/endian.h"
|
||||
#include "munit/munit.h"
|
||||
|
||||
const union {
|
||||
unsigned char bytes[2];
|
||||
psnip_uint16_t value;
|
||||
} test_data_16 = {
|
||||
{ 1, 2 }
|
||||
};
|
||||
|
||||
const union {
|
||||
unsigned char bytes[4];
|
||||
psnip_uint32_t value;
|
||||
} test_data_32 = {
|
||||
{ 1, 2, 3, 4 }
|
||||
};
|
||||
|
||||
const union {
|
||||
unsigned char bytes[8];
|
||||
psnip_uint64_t value;
|
||||
} test_data_64 = {
|
||||
{ 1, 2, 3, 4, 5, 6, 7, 8 }
|
||||
};
|
||||
|
||||
#if !defined(UINT8_C)
|
||||
# define UINT8_C(c) ((psnip_uint8_t) (c ## U))
|
||||
#endif
|
||||
#if !defined(UINT16_C)
|
||||
# define UINT16_C(c) ((psnip_uint16_t) (c ## U))
|
||||
#endif
|
||||
#if !defined(UINT32_C)
|
||||
# define UINT32_C(c) c ## U
|
||||
#endif
|
||||
#if !defined(UINT64_C)
|
||||
# define UINT64_C(c) c ## ULL
|
||||
#endif
|
||||
|
||||
static MunitResult
|
||||
test_endian_swap_known(const MunitParameter params[], void* data) {
|
||||
(void) params;
|
||||
(void) data;
|
||||
|
||||
munit_assert_uint16(psnip_builtin_bswap16(UINT16_C(0xefbe)), ==, UINT16_C(0xbeef));
|
||||
munit_assert_uint32(psnip_builtin_bswap32(UINT32_C(0xefbeadde)), ==, UINT32_C(0xdeadbeef));
|
||||
munit_assert_uint64(psnip_builtin_bswap64(UINT64_C(0x0df0dde0fe0fdcba)), ==, UINT64_C(0xbadc0ffee0ddf00d));
|
||||
|
||||
return MUNIT_OK;
|
||||
}
|
||||
|
||||
static MunitResult
|
||||
test_endian_swap_random(const MunitParameter params[], void* data) {
|
||||
(void) params;
|
||||
(void) data;
|
||||
|
||||
munit_assert_uint16(psnip_builtin_bswap16(UINT16_C(0xefbe)), ==, UINT16_C(0xbeef));
|
||||
{
|
||||
const psnip_uint16_t input = (psnip_uint16_t) munit_rand_uint32();
|
||||
const psnip_uint16_t swapped = psnip_builtin_bswap16(input);
|
||||
const psnip_uint16_t double_swapped = psnip_builtin_bswap16(swapped);
|
||||
|
||||
munit_assert_uint16(input, ==, double_swapped);
|
||||
}
|
||||
|
||||
munit_assert_uint32(psnip_builtin_bswap32(UINT32_C(0xefbeadde)), ==, UINT32_C(0xdeadbeef));
|
||||
{
|
||||
const psnip_uint32_t input = munit_rand_uint32();
|
||||
const psnip_uint32_t swapped = psnip_builtin_bswap32(input);
|
||||
const psnip_uint32_t double_swapped = psnip_builtin_bswap32(swapped);
|
||||
|
||||
munit_assert_uint32(input, ==, double_swapped);
|
||||
}
|
||||
|
||||
munit_assert_uint64(psnip_builtin_bswap64(UINT64_C(0xdf0dde0fe0fdcba)), ==, UINT64_C(0xbadc0ffee0ddf00d));
|
||||
{
|
||||
const psnip_uint64_t input = (((psnip_uint64_t) munit_rand_uint32()) << 32) | munit_rand_uint32();
|
||||
const psnip_uint64_t swapped = psnip_builtin_bswap64(input);
|
||||
const psnip_uint64_t double_swapped = psnip_builtin_bswap64(swapped);
|
||||
|
||||
munit_assert_uint64(input, ==, double_swapped);
|
||||
}
|
||||
|
||||
return MUNIT_OK;
|
||||
}
|
||||
|
||||
static MunitResult
|
||||
test_endian_from_be(const MunitParameter params[], void* data) {
|
||||
(void) params;
|
||||
(void) data;
|
||||
|
||||
munit_assert_uint16(psnip_endian_be16(test_data_16.value), ==, UINT16_C(0x0102));
|
||||
munit_assert_uint32(psnip_endian_be32(test_data_32.value), ==, UINT32_C(0x01020304));
|
||||
munit_assert_uint64(psnip_endian_be64(test_data_64.value), ==, UINT64_C(0x0102030405060708));
|
||||
|
||||
return MUNIT_OK;
|
||||
}
|
||||
|
||||
static MunitResult
|
||||
test_endian_from_le(const MunitParameter params[], void* data) {
|
||||
(void) params;
|
||||
(void) data;
|
||||
|
||||
munit_assert_uint16(psnip_endian_le16(test_data_16.value), ==, UINT16_C(0x0201));
|
||||
munit_assert_uint32(psnip_endian_le32(test_data_32.value), ==, UINT32_C(0x04030201));
|
||||
munit_assert_uint64(psnip_endian_le64(test_data_64.value), ==, UINT64_C(0x0807060504030201));
|
||||
|
||||
return MUNIT_OK;
|
||||
}
|
||||
|
||||
static MunitResult
|
||||
test_endian_match_rt(const MunitParameter params[], void* data) {
|
||||
(void) params;
|
||||
(void) data;
|
||||
|
||||
#if defined(PSNIP_ENDIAN_ORDER)
|
||||
munit_assert_uint32(PSNIP_ENDIAN_ORDER, ==, PSNIP_ENDIAN_ORDER_RT);
|
||||
#endif
|
||||
|
||||
return MUNIT_OK;
|
||||
}
|
||||
|
||||
static MunitTest test_suite_tests[] = {
|
||||
{ (char*) "/endian/swap/known", test_endian_swap_known, NULL, NULL, MUNIT_TEST_OPTION_SINGLE_ITERATION, NULL },
|
||||
{ (char*) "/endian/swap/random", test_endian_swap_random, NULL, NULL, MUNIT_TEST_OPTION_NONE, NULL },
|
||||
{ (char*) "/endian/from-be", test_endian_from_be, NULL, NULL, MUNIT_TEST_OPTION_SINGLE_ITERATION, NULL },
|
||||
{ (char*) "/endian/from-le", test_endian_from_le, NULL, NULL, MUNIT_TEST_OPTION_SINGLE_ITERATION, NULL },
|
||||
{ (char*) "/endian/match-rt", test_endian_match_rt, NULL, NULL, MUNIT_TEST_OPTION_SINGLE_ITERATION, NULL },
|
||||
{ NULL, NULL, NULL, NULL, MUNIT_TEST_OPTION_NONE, NULL }
|
||||
};
|
||||
|
||||
static const MunitSuite test_suite = {
|
||||
(char*) "", test_suite_tests, NULL, 16384, MUNIT_SUITE_OPTION_NONE
|
||||
};
|
||||
|
||||
int main(int argc, char* argv[MUNIT_ARRAY_PARAM(argc + 1)]) {
|
||||
return munit_suite_main(&test_suite, NULL, argc, argv);
|
||||
}
|
||||
34
thirdparty/portable-snippets/tests/munit/.appveyor.yml
vendored
Normal file
34
thirdparty/portable-snippets/tests/munit/.appveyor.yml
vendored
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
version: "{build}"
|
||||
|
||||
environment:
|
||||
matrix:
|
||||
- ARCHITECTURE: x64
|
||||
MSVC_VER: 14
|
||||
- ARCHITECTURE: x86
|
||||
MSVC_VER: 14
|
||||
- ARCHITECTURE: x64
|
||||
MSVC_VER: 12
|
||||
- ARCHITECTURE: x86
|
||||
MSVC_VER: 12
|
||||
- ARCHITECTURE: x86
|
||||
MSVC_VER: 11
|
||||
- ARCHITECTURE: x86
|
||||
MSVC_VER: 10
|
||||
- ARCHITECTURE: x86
|
||||
MSVC_VER: 9
|
||||
|
||||
branches:
|
||||
except:
|
||||
- master
|
||||
- /^(wip\/)?(travis|osx|mingw|ipp)(\-.+)?$/
|
||||
|
||||
configuration: Debug
|
||||
|
||||
install:
|
||||
|
||||
before_build:
|
||||
- call "C:\Program Files (x86)\Microsoft Visual Studio %MSVC_VER%.0\VC\vcvarsall.bat" %ARCHITECTURE%
|
||||
|
||||
build_script: cl.exe /W4 /WX /Feexample munit.c example.c
|
||||
|
||||
test_script: example.exe --color always
|
||||
2
thirdparty/portable-snippets/tests/munit/.dir-locals.el
vendored
Normal file
2
thirdparty/portable-snippets/tests/munit/.dir-locals.el
vendored
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
((nil . ((indent-tabs-mode . nil)
|
||||
(c-basic-offset . 2))))
|
||||
6
thirdparty/portable-snippets/tests/munit/.gitignore
vendored
Normal file
6
thirdparty/portable-snippets/tests/munit/.gitignore
vendored
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
*~
|
||||
.#*
|
||||
/*.o
|
||||
/example
|
||||
/*.exe
|
||||
/*.dll
|
||||
142
thirdparty/portable-snippets/tests/munit/.travis.yml
vendored
Normal file
142
thirdparty/portable-snippets/tests/munit/.travis.yml
vendored
Normal file
|
|
@ -0,0 +1,142 @@
|
|||
language: c
|
||||
sudo: false
|
||||
dist: trusty
|
||||
branches:
|
||||
except:
|
||||
- /^(wip\/)?(appveyor|msvc|mingw|windows)(\-.+)?$/
|
||||
- /^master$/
|
||||
matrix:
|
||||
include:
|
||||
###
|
||||
## Linux builds using various versions of GCC.
|
||||
###
|
||||
- env: C_COMPILER=gcc-6
|
||||
addons:
|
||||
apt:
|
||||
sources:
|
||||
- ubuntu-toolchain-r-test
|
||||
packages:
|
||||
- gcc-6
|
||||
- g++-6
|
||||
- env: C_COMPILER=gcc-5
|
||||
addons:
|
||||
apt:
|
||||
sources:
|
||||
- ubuntu-toolchain-r-test
|
||||
packages:
|
||||
- gcc-5
|
||||
- g++-5
|
||||
# - env: C_COMPILER=gcc-4.9
|
||||
# addons:
|
||||
# apt:
|
||||
# sources:
|
||||
# - ubuntu-toolchain-r-test
|
||||
# packages:
|
||||
# - gcc-4.9
|
||||
# - g++-4.9
|
||||
- env: C_COMPILER=gcc-4.8
|
||||
addons:
|
||||
apt:
|
||||
sources:
|
||||
- ubuntu-toolchain-r-test
|
||||
packages:
|
||||
- gcc-4.8
|
||||
- g++-4.8
|
||||
# - env: C_COMPILER=gcc-4.7
|
||||
# addons:
|
||||
# apt:
|
||||
# sources:
|
||||
# - ubuntu-toolchain-r-test
|
||||
# packages:
|
||||
# - gcc-4.7
|
||||
# - g++-4.7
|
||||
- env: C_COMPILER=gcc-4.6
|
||||
addons:
|
||||
apt:
|
||||
sources:
|
||||
- ubuntu-toolchain-r-test
|
||||
packages:
|
||||
- gcc-4.6
|
||||
- g++-4.6
|
||||
# - os: linux
|
||||
# env: C_COMPILER=gcc-4.5
|
||||
# addons:
|
||||
# apt:
|
||||
# sources:
|
||||
# - ubuntu-toolchain-r-test
|
||||
# packages:
|
||||
# - gcc-4.5
|
||||
# - g++-4.5
|
||||
- env: C_COMPILER=gcc-4.4
|
||||
addons:
|
||||
apt:
|
||||
sources:
|
||||
- ubuntu-toolchain-r-test
|
||||
packages:
|
||||
- gcc-4.4
|
||||
- g++-4.4
|
||||
|
||||
###
|
||||
## clang on Linux
|
||||
###
|
||||
- env: C_COMPILER=clang-3.9
|
||||
addons:
|
||||
apt:
|
||||
sources:
|
||||
- llvm-toolchain-precise-3.9
|
||||
- ubuntu-toolchain-r-test
|
||||
packages:
|
||||
- clang-3.9
|
||||
# - env: C_COMPILER=clang-3.8
|
||||
# addons:
|
||||
# apt:
|
||||
# sources:
|
||||
# - llvm-toolchain-precise-3.8
|
||||
# - ubuntu-toolchain-r-test
|
||||
# packages:
|
||||
# - clang-3.8
|
||||
- env: C_COMPILER=clang-3.7
|
||||
addons:
|
||||
apt:
|
||||
sources:
|
||||
- llvm-toolchain-precise-3.7
|
||||
- ubuntu-toolchain-r-test
|
||||
packages:
|
||||
- clang-3.7
|
||||
# - env: C_COMPILER=clang-3.6
|
||||
# addons:
|
||||
# apt:
|
||||
# sources:
|
||||
# - llvm-toolchain-precise-3.6
|
||||
# - ubuntu-toolchain-r-test
|
||||
# packages:
|
||||
# - clang-3.6
|
||||
- env: C_COMPILER=clang-3.5
|
||||
addons:
|
||||
apt:
|
||||
sources:
|
||||
- llvm-toolchain-precise-3.5
|
||||
- ubuntu-toolchain-r-test
|
||||
packages:
|
||||
- clang-3.5
|
||||
|
||||
###
|
||||
## PGI
|
||||
###
|
||||
- env: C_COMPILER=pgcc OPENMP=y
|
||||
|
||||
###
|
||||
## OS X
|
||||
###
|
||||
- os: osx
|
||||
|
||||
before_install:
|
||||
- if [ -n "${C_COMPILER}" ]; then export CC="${C_COMPILER}"; fi
|
||||
- if [ "${C_COMPILER}" = "pgcc" ]; then wget -q -O /dev/stdout 'https://raw.githubusercontent.com/nemequ/pgi-travis/master/install-pgi.sh' | /bin/sh; fi
|
||||
|
||||
script:
|
||||
- make CC="${CC}" AGGRESSIVE_WARNINGS=y EXTENSION="${EXTENSION}" OPENMP="${OPENMP}" ASAN="${ASAN}" UBSAN="${UBSAN}"
|
||||
- make test
|
||||
|
||||
notifications:
|
||||
email: false
|
||||
21
thirdparty/portable-snippets/tests/munit/COPYING
vendored
Normal file
21
thirdparty/portable-snippets/tests/munit/COPYING
vendored
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
µnit Testing Framework
|
||||
Copyright (c) 2013-2016 Evan Nemerson <evan@nemerson.com>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of this software and associated documentation files (the
|
||||
"Software"), to deal in the Software without restriction, including
|
||||
without limitation the rights to use, copy, modify, merge, publish,
|
||||
distribute, sublicense, and/or sell copies of the Software, and to
|
||||
permit persons to whom the Software is furnished to do so, subject to
|
||||
the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be
|
||||
included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
55
thirdparty/portable-snippets/tests/munit/Makefile
vendored
Normal file
55
thirdparty/portable-snippets/tests/munit/Makefile
vendored
Normal file
|
|
@ -0,0 +1,55 @@
|
|||
# Using µnit is very simple; just include the header and add the C
|
||||
# file to your sources. That said, here is a simple Makefile to build
|
||||
# the example.
|
||||
|
||||
CSTD:=99
|
||||
OPENMP:=n
|
||||
ASAN:=n
|
||||
UBSAN:=n
|
||||
EXTENSION:=
|
||||
TEST_ENV:=
|
||||
CFLAGS:=
|
||||
AGGRESSIVE_WARNINGS=n
|
||||
|
||||
ifeq ($(CC),pgcc)
|
||||
CFLAGS+=-c$(CSTD)
|
||||
else
|
||||
CFLAGS+=-std=c$(CSTD)
|
||||
endif
|
||||
|
||||
ifeq ($(OPENMP),y)
|
||||
ifeq ($(CC),pgcc)
|
||||
CFLAGS+=-mp
|
||||
else
|
||||
CFLAGS+=-fopenmp
|
||||
endif
|
||||
endif
|
||||
|
||||
ifneq ($(SANITIZER),)
|
||||
CFLAGS+=-fsanitize=$(SANITIZER)
|
||||
endif
|
||||
|
||||
ifneq ($(CC),pgcc)
|
||||
ifeq ($(EXTRA_WARNINGS),y)
|
||||
CFLAGS+=-Wall -Wextra -Werror
|
||||
endif
|
||||
|
||||
ifeq ($(ASAN),y)
|
||||
CFLAGS+=-fsanitize=address
|
||||
endif
|
||||
|
||||
ifeq ($(UBSAN),y)
|
||||
CFLAGS+=-fsanitize=undefined
|
||||
endif
|
||||
endif
|
||||
|
||||
example$(EXTENSION): munit.h munit.c example.c
|
||||
$(CC) $(CFLAGS) -o $@ munit.c example.c
|
||||
|
||||
test:
|
||||
$(TEST_ENV) ./example$(EXTENSION)
|
||||
|
||||
clean:
|
||||
rm -f example$(EXTENSION)
|
||||
|
||||
all: example$(EXTENSION)
|
||||
40
thirdparty/portable-snippets/tests/munit/README.md
vendored
Normal file
40
thirdparty/portable-snippets/tests/munit/README.md
vendored
Normal file
|
|
@ -0,0 +1,40 @@
|
|||
# µnit
|
||||
|
||||
µnit is a small but full-featured unit testing framework for C. It has
|
||||
no dependencies (beyond libc), is permissively licensed (MIT), and is
|
||||
easy to include into any project.
|
||||
|
||||
For more information, see
|
||||
[the µnit web site](https://nemequ.github.io/munit).
|
||||
|
||||
[](https://travis-ci.org/nemequ/munit)
|
||||
[](https://ci.appveyor.com/project/quixdb/munit/branch/master)
|
||||
|
||||
## Features
|
||||
|
||||
Features µnit currently includes include:
|
||||
|
||||
* Handy assertion macros which make for nice error messages.
|
||||
* Reproducible cross-platform random number generation, including
|
||||
support for supplying a seed via CLI.
|
||||
* Timing of both wall-clock and CPU time.
|
||||
* Parameterized tests.
|
||||
* Nested test suites.
|
||||
* Flexible CLI.
|
||||
* Forking
|
||||
([except on Windows](https://github.com/nemequ/munit/issues/2)).
|
||||
* Hiding output of successful tests.
|
||||
|
||||
Features µnit does not currently include, but some day may include
|
||||
(a.k.a., if you file a PR…), include:
|
||||
|
||||
* [TAP](http://testanything.org/) support; feel free to discuss in
|
||||
[issue #1](https://github.com/nemequ/munit/issues/1)
|
||||
|
||||
## Documentation
|
||||
|
||||
See [the µnit web site](https://nemequ.github.io/munit).
|
||||
|
||||
Additionally, there is a heavily-commented
|
||||
[example.c](https://github.com/nemequ/munit/blob/master/example.c) in
|
||||
the repository.
|
||||
351
thirdparty/portable-snippets/tests/munit/example.c
vendored
Normal file
351
thirdparty/portable-snippets/tests/munit/example.c
vendored
Normal file
|
|
@ -0,0 +1,351 @@
|
|||
/* Example file for using µnit.
|
||||
*
|
||||
* µnit is MIT-licensed, but for this file and this file alone:
|
||||
*
|
||||
* To the extent possible under law, the author(s) of this file have
|
||||
* waived all copyright and related or neighboring rights to this
|
||||
* work. See <https://creativecommons.org/publicdomain/zero/1.0/> for
|
||||
* details.
|
||||
*********************************************************************/
|
||||
|
||||
#include "munit.h"
|
||||
|
||||
/* This is just to disable an MSVC warning about conditional
|
||||
* expressions being constant, which you shouldn't have to do for your
|
||||
* code. It's only here because we want to be able to do silly things
|
||||
* like assert that 0 != 1 for our demo. */
|
||||
#if defined(_MSC_VER)
|
||||
#pragma warning(disable: 4127)
|
||||
#endif
|
||||
|
||||
/* Tests are functions that return void, and take a single void*
|
||||
* parameter. We'll get to what that parameter is later. */
|
||||
static MunitResult
|
||||
test_compare(const MunitParameter params[], void* data) {
|
||||
/* We'll use these later */
|
||||
const unsigned char val_uchar = 'b';
|
||||
const short val_short = 1729;
|
||||
double pi = 3.141592654;
|
||||
char* stewardesses = "stewardesses";
|
||||
char* most_fun_word_to_type;
|
||||
|
||||
/* These are just to silence compiler warnings about the parameters
|
||||
* being unused. */
|
||||
(void) params;
|
||||
(void) data;
|
||||
|
||||
/* Let's start with the basics. */
|
||||
munit_assert(0 != 1);
|
||||
|
||||
/* There is also the more verbose, though slightly more descriptive
|
||||
munit_assert_true/false: */
|
||||
munit_assert_false(0);
|
||||
|
||||
/* You can also call munit_error and munit_errorf yourself. We
|
||||
* won't do it is used to indicate a failure, but here is what it
|
||||
* would look like: */
|
||||
/* munit_error("FAIL"); */
|
||||
/* munit_errorf("Goodbye, cruel %s", "world"); */
|
||||
|
||||
/* There are macros for comparing lots of types. */
|
||||
munit_assert_char('a', ==, 'a');
|
||||
|
||||
/* Sure, you could just assert('a' == 'a'), but if you did that, a
|
||||
* failed assertion would just say something like "assertion failed:
|
||||
* val_uchar == 'b'". µnit will tell you the actual values, so a
|
||||
* failure here would result in something like "assertion failed:
|
||||
* val_uchar == 'b' ('X' == 'b')." */
|
||||
munit_assert_uchar(val_uchar, ==, 'b');
|
||||
|
||||
/* Obviously we can handle values larger than 'char' and 'uchar'.
|
||||
* There are versions for char, short, int, long, long long,
|
||||
* int8/16/32/64_t, as well as the unsigned versions of them all. */
|
||||
munit_assert_short(42, <, val_short);
|
||||
|
||||
/* There is also support for size_t.
|
||||
*
|
||||
* The longest word in English without repeating any letters is
|
||||
* "uncopyrightables", which has uncopyrightable (and
|
||||
* dermatoglyphics, which is the study of fingerprints) beat by a
|
||||
* character */
|
||||
munit_assert_size(strlen("uncopyrightables"), >, strlen("dermatoglyphics"));
|
||||
|
||||
/* Of course there is also support for doubles and floats. */
|
||||
munit_assert_double(pi, ==, 3.141592654);
|
||||
|
||||
/* If you want to compare two doubles for equality, you might want
|
||||
* to consider using munit_assert_double_equal. It compares two
|
||||
* doubles for equality within a precison of 1.0 x 10^-(precision).
|
||||
* Note that precision (the third argument to the macro) needs to be
|
||||
* fully evaluated to an integer by the preprocessor so µnit doesn't
|
||||
* have to depend pow, which is often in libm not libc. */
|
||||
munit_assert_double_equal(3.141592654, 3.141592653589793, 9);
|
||||
|
||||
/* And if you want to check strings for equality (or inequality),
|
||||
* there is munit_assert_string_equal/not_equal.
|
||||
*
|
||||
* "stewardesses" is the longest word you can type on a QWERTY
|
||||
* keyboard with only one hand, which makes it loads of fun to type.
|
||||
* If I'm going to have to type a string repeatedly, let's make it a
|
||||
* good one! */
|
||||
munit_assert_string_equal(stewardesses, "stewardesses");
|
||||
|
||||
/* A personal favorite macro which is fantastic if you're working
|
||||
* with binary data, is the one which naïvely checks two blobs of
|
||||
* memory for equality. If this fails it will tell you the offset
|
||||
* of the first differing byte. */
|
||||
munit_assert_memory_equal(7, stewardesses, "steward");
|
||||
|
||||
/* You can also make sure that two blobs differ *somewhere*: */
|
||||
munit_assert_memory_not_equal(8, stewardesses, "steward");
|
||||
|
||||
/* There are equal/not_equal macros for pointers, too: */
|
||||
most_fun_word_to_type = stewardesses;
|
||||
munit_assert_ptr_equal(most_fun_word_to_type, stewardesses);
|
||||
|
||||
/* And null/not_null */
|
||||
munit_assert_null(NULL);
|
||||
munit_assert_not_null(most_fun_word_to_type);
|
||||
|
||||
/* Lets verify that the data parameter is what we expected. We'll
|
||||
* see where this comes from in a bit.
|
||||
*
|
||||
* Note that the casting isn't usually required; if you give this
|
||||
* function a real pointer (instead of a number like 0xdeadbeef) it
|
||||
* would work as expected. */
|
||||
munit_assert_ptr_equal(data, (void*)(uintptr_t)0xdeadbeef);
|
||||
|
||||
return MUNIT_OK;
|
||||
}
|
||||
|
||||
static MunitResult
|
||||
test_rand(const MunitParameter params[], void* user_data) {
|
||||
int random_int;
|
||||
double random_dbl;
|
||||
munit_uint8_t data[5];
|
||||
|
||||
(void) params;
|
||||
(void) user_data;
|
||||
|
||||
/* One thing missing from a lot of unit testing frameworks is a
|
||||
* random number generator. You can't just use srand/rand because
|
||||
* the implementation varies across different platforms, and it's
|
||||
* important to be able to look at the seed used in a failing test
|
||||
* to see if you can reproduce it. Some randomness is a fantastic
|
||||
* thing to have in your tests, I don't know why more people don't
|
||||
* do it...
|
||||
*
|
||||
* µnit's PRNG is re-seeded with the same value for each iteration
|
||||
* of each test. The seed is retrieved from the MUNIT_SEED
|
||||
* envirnment variable or, if none is provided, one will be
|
||||
* (pseudo-)randomly generated. */
|
||||
|
||||
/* If you need an integer in a given range */
|
||||
random_int = munit_rand_int_range(128, 4096);
|
||||
munit_assert_int(random_int, >=, 128);
|
||||
munit_assert_int(random_int, <=, 4096);
|
||||
|
||||
/* Or maybe you want a double, between 0 and 1: */
|
||||
random_dbl = munit_rand_double();
|
||||
munit_assert_double(random_dbl, >=, 0.0);
|
||||
munit_assert_double(random_dbl, <=, 1.0);
|
||||
|
||||
/* Of course, you want to be able to reproduce bugs discovered
|
||||
* during testing, so every time the tests are run they print the
|
||||
* random seed used. When you want to reproduce a result, just put
|
||||
* that random seed in the MUNIT_SEED environment variable; it even
|
||||
* works on different platforms.
|
||||
*
|
||||
* If you want this to pass, use 0xdeadbeef as the random seed and
|
||||
* uncomment the next line of code. Note that the PRNG is not
|
||||
* re-seeded between iterations of the same test, so this will only
|
||||
* work on the first iteration. */
|
||||
/* munit_assert_uint32(munit_rand_uint32(), ==, 1306447409); */
|
||||
|
||||
/* You can also get blobs of random memory: */
|
||||
munit_rand_memory(sizeof(data), data);
|
||||
|
||||
return MUNIT_OK;
|
||||
}
|
||||
|
||||
/* This test case shows how to accept parameters. We'll see how to
|
||||
* specify them soon.
|
||||
*
|
||||
* By default, every possible variation of a parameterized test is
|
||||
* run, but you can specify parameters manually if you want to only
|
||||
* run specific test(s), or you can pass the --single argument to the
|
||||
* CLI to have the harness simply choose one variation at random
|
||||
* instead of running them all. */
|
||||
static MunitResult
|
||||
test_parameters(const MunitParameter params[], void* user_data) {
|
||||
const char* foo;
|
||||
const char* bar;
|
||||
|
||||
(void) user_data;
|
||||
|
||||
/* The "foo" parameter is specified as one of the following values:
|
||||
* "one", "two", or "three". */
|
||||
foo = munit_parameters_get(params, "foo");
|
||||
/* Similarly, "bar" is one of "four", "five", or "six". */
|
||||
bar = munit_parameters_get(params, "bar");
|
||||
/* "baz" is a bit more complicated. We don't actually specify a
|
||||
* list of valid values, so by default NULL is passed. However, the
|
||||
* CLI will accept any value. This is a good way to have a value
|
||||
* that is usually selected randomly by the test, but can be
|
||||
* overridden on the command line if desired. */
|
||||
/* const char* baz = munit_parameters_get(params, "baz"); */
|
||||
|
||||
/* Notice that we're returning MUNIT_FAIL instead of writing an
|
||||
* error message. Error messages are generally preferable, since
|
||||
* they make it easier to diagnose the issue, but this is an
|
||||
* option.
|
||||
*
|
||||
* Possible values are:
|
||||
* - MUNIT_OK: Sucess
|
||||
* - MUNIT_FAIL: Failure
|
||||
* - MUNIT_SKIP: The test was skipped; usually this happens when a
|
||||
* particular feature isn't in use. For example, if you're
|
||||
* writing a test which uses a Wayland-only feature, but your
|
||||
* application is running on X11.
|
||||
* - MUNIT_ERROR: The test failed, but not because of anything you
|
||||
* wanted to test. For example, maybe your test downloads a
|
||||
* remote resource and tries to parse it, but the network was
|
||||
* down.
|
||||
*/
|
||||
|
||||
if (strcmp(foo, "one") != 0 &&
|
||||
strcmp(foo, "two") != 0 &&
|
||||
strcmp(foo, "three") != 0)
|
||||
return MUNIT_FAIL;
|
||||
|
||||
if (strcmp(bar, "red") != 0 &&
|
||||
strcmp(bar, "green") != 0 &&
|
||||
strcmp(bar, "blue") != 0)
|
||||
return MUNIT_FAIL;
|
||||
|
||||
return MUNIT_OK;
|
||||
}
|
||||
|
||||
/* The setup function, if you provide one, for a test will be run
|
||||
* before the test, and the return value will be passed as the sole
|
||||
* parameter to the test function. */
|
||||
static void*
|
||||
test_compare_setup(const MunitParameter params[], void* user_data) {
|
||||
(void) params;
|
||||
|
||||
munit_assert_string_equal(user_data, "µnit");
|
||||
return (void*) (uintptr_t) 0xdeadbeef;
|
||||
}
|
||||
|
||||
/* To clean up after a test, you can use a tear down function. The
|
||||
* fixture argument is the value returned by the setup function
|
||||
* above. */
|
||||
static void
|
||||
test_compare_tear_down(void* fixture) {
|
||||
munit_assert_ptr_equal(fixture, (void*)(uintptr_t)0xdeadbeef);
|
||||
}
|
||||
|
||||
static char* foo_params[] = {
|
||||
(char*) "one", (char*) "two", (char*) "three", NULL
|
||||
};
|
||||
|
||||
static char* bar_params[] = {
|
||||
(char*) "red", (char*) "green", (char*) "blue", NULL
|
||||
};
|
||||
|
||||
static MunitParameterEnum test_params[] = {
|
||||
{ (char*) "foo", foo_params },
|
||||
{ (char*) "bar", bar_params },
|
||||
{ (char*) "baz", NULL },
|
||||
{ NULL, NULL },
|
||||
};
|
||||
|
||||
/* Creating a test suite is pretty simple. First, you'll need an
|
||||
* array of tests: */
|
||||
static MunitTest test_suite_tests[] = {
|
||||
{
|
||||
/* The name is just a unique human-readable way to identify the
|
||||
* test. You can use it to run a specific test if you want, but
|
||||
* usually it's mostly decorative. */
|
||||
(char*) "/example/compare",
|
||||
/* You probably won't be surprised to learn that the tests are
|
||||
* functions. */
|
||||
test_compare,
|
||||
/* If you want, you can supply a function to set up a fixture. If
|
||||
* you supply NULL, the user_data parameter from munit_suite_main
|
||||
* will be used directly. If, however, you provide a callback
|
||||
* here the user_data parameter will be passed to this callback,
|
||||
* and the return value from this callback will be passed to the
|
||||
* test function.
|
||||
*
|
||||
* For our example we don't really need a fixture, but lets
|
||||
* provide one anyways. */
|
||||
test_compare_setup,
|
||||
/* If you passed a callback for the fixture setup function, you
|
||||
* may want to pass a corresponding callback here to reverse the
|
||||
* operation. */
|
||||
test_compare_tear_down,
|
||||
/* Finally, there is a bitmask for options you can pass here. You
|
||||
* can provide either MUNIT_TEST_OPTION_NONE or 0 here to use the
|
||||
* defaults. */
|
||||
MUNIT_TEST_OPTION_NONE,
|
||||
NULL
|
||||
},
|
||||
/* Usually this is written in a much more compact format; all these
|
||||
* comments kind of ruin that, though. Here is how you'll usually
|
||||
* see entries written: */
|
||||
{ (char*) "/example/rand", test_rand, NULL, NULL, MUNIT_TEST_OPTION_NONE, NULL },
|
||||
/* To tell the test runner when the array is over, just add a NULL
|
||||
* entry at the end. */
|
||||
{ (char*) "/example/parameters", test_parameters, NULL, NULL, MUNIT_TEST_OPTION_NONE, test_params },
|
||||
{ NULL, NULL, NULL, NULL, MUNIT_TEST_OPTION_NONE, NULL }
|
||||
};
|
||||
|
||||
/* If you wanted to have your test suite run other test suites you
|
||||
* could declare an array of them. Of course each sub-suite can
|
||||
* contain more suites, etc. */
|
||||
/* static const MunitSuite other_suites[] = { */
|
||||
/* { "/second", test_suite_tests, NULL, 1, MUNIT_SUITE_OPTION_NONE }, */
|
||||
/* { NULL, NULL, NULL, 0, MUNIT_SUITE_OPTION_NONE } */
|
||||
/* }; */
|
||||
|
||||
/* Now we'll actually declare the test suite. You could do this in
|
||||
* the main function, or on the heap, or whatever you want. */
|
||||
static const MunitSuite test_suite = {
|
||||
/* This string will be prepended to all test names in this suite;
|
||||
* for example, "/example/rand" will become "/µnit/example/rand".
|
||||
* Note that, while it doesn't really matter for the top-level
|
||||
* suite, NULL signal the end of an array of tests; you should use
|
||||
* an empty string ("") instead. */
|
||||
(char*) "",
|
||||
/* The first parameter is the array of test suites. */
|
||||
test_suite_tests,
|
||||
/* In addition to containing test cases, suites can contain other
|
||||
* test suites. This isn't necessary in this example, but it can be
|
||||
* a great help to projects with lots of tests by making it easier
|
||||
* to spread the tests across many files. This is where you would
|
||||
* put "other_suites" (which is commented out above). */
|
||||
NULL,
|
||||
/* An interesting feature of µnit is that it supports automatically
|
||||
* running multiple iterations of the tests. This is usually only
|
||||
* interesting if you make use of the PRNG to randomize your tests
|
||||
* cases a bit, or if you are doing performance testing and want to
|
||||
* average multiple runs. 0 is an alias for 1. */
|
||||
1,
|
||||
/* Just like MUNIT_TEST_OPTION_NONE, you can provide
|
||||
* MUNIT_SUITE_OPTION_NONE or 0 to use the default settings. */
|
||||
MUNIT_SUITE_OPTION_NONE
|
||||
};
|
||||
|
||||
/* This is only necessary for EXIT_SUCCESS and EXIT_FAILURE, which you
|
||||
* *should* be using but probably aren't (no, zero and non-zero don't
|
||||
* always mean success and failure). I guess my point is that nothing
|
||||
* about µnit requires it. */
|
||||
#include <stdlib.h>
|
||||
|
||||
int main(int argc, char* argv[MUNIT_ARRAY_PARAM(argc + 1)]) {
|
||||
/* Finally, we'll actually run our test suite! That second argument
|
||||
* is the user_data parameter which will be passed either to the
|
||||
* test or (if provided) the fixture setup function. */
|
||||
return munit_suite_main(&test_suite, (void*) "µnit", argc, argv);
|
||||
}
|
||||
2047
thirdparty/portable-snippets/tests/munit/munit.c
vendored
Normal file
2047
thirdparty/portable-snippets/tests/munit/munit.c
vendored
Normal file
File diff suppressed because it is too large
Load diff
533
thirdparty/portable-snippets/tests/munit/munit.h
vendored
Normal file
533
thirdparty/portable-snippets/tests/munit/munit.h
vendored
Normal file
|
|
@ -0,0 +1,533 @@
|
|||
/* µnit Testing Framework
|
||||
* Copyright (c) 2013-2017 Evan Nemerson <evan@nemerson.com>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person
|
||||
* obtaining a copy of this software and associated documentation
|
||||
* files (the "Software"), to deal in the Software without
|
||||
* restriction, including without limitation the rights to use, copy,
|
||||
* modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
* of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#if !defined(MUNIT_H)
|
||||
#define MUNIT_H
|
||||
|
||||
#include <stdarg.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#define MUNIT_VERSION(major, minor, revision) \
|
||||
(((major) << 16) | ((minor) << 8) | (revision))
|
||||
|
||||
#define MUNIT_CURRENT_VERSION MUNIT_VERSION(0, 4, 1)
|
||||
|
||||
#if defined(_MSC_VER) && (_MSC_VER < 1600)
|
||||
# define munit_int8_t __int8
|
||||
# define munit_uint8_t unsigned __int8
|
||||
# define munit_int16_t __int16
|
||||
# define munit_uint16_t unsigned __int16
|
||||
# define munit_int32_t __int32
|
||||
# define munit_uint32_t unsigned __int32
|
||||
# define munit_int64_t __int64
|
||||
# define munit_uint64_t unsigned __int64
|
||||
#else
|
||||
# include <stdint.h>
|
||||
# define munit_int8_t int8_t
|
||||
# define munit_uint8_t uint8_t
|
||||
# define munit_int16_t int16_t
|
||||
# define munit_uint16_t uint16_t
|
||||
# define munit_int32_t int32_t
|
||||
# define munit_uint32_t uint32_t
|
||||
# define munit_int64_t int64_t
|
||||
# define munit_uint64_t uint64_t
|
||||
#endif
|
||||
|
||||
#if defined(_MSC_VER) && (_MSC_VER < 1800)
|
||||
# if !defined(PRIi8)
|
||||
# define PRIi8 "i"
|
||||
# endif
|
||||
# if !defined(PRIi16)
|
||||
# define PRIi16 "i"
|
||||
# endif
|
||||
# if !defined(PRIi32)
|
||||
# define PRIi32 "i"
|
||||
# endif
|
||||
# if !defined(PRIi64)
|
||||
# define PRIi64 "I64i"
|
||||
# endif
|
||||
# if !defined(PRId8)
|
||||
# define PRId8 "d"
|
||||
# endif
|
||||
# if !defined(PRId16)
|
||||
# define PRId16 "d"
|
||||
# endif
|
||||
# if !defined(PRId32)
|
||||
# define PRId32 "d"
|
||||
# endif
|
||||
# if !defined(PRId64)
|
||||
# define PRId64 "I64d"
|
||||
# endif
|
||||
# if !defined(PRIx8)
|
||||
# define PRIx8 "x"
|
||||
# endif
|
||||
# if !defined(PRIx16)
|
||||
# define PRIx16 "x"
|
||||
# endif
|
||||
# if !defined(PRIx32)
|
||||
# define PRIx32 "x"
|
||||
# endif
|
||||
# if !defined(PRIx64)
|
||||
# define PRIx64 "I64x"
|
||||
# endif
|
||||
# if !defined(PRIu8)
|
||||
# define PRIu8 "u"
|
||||
# endif
|
||||
# if !defined(PRIu16)
|
||||
# define PRIu16 "u"
|
||||
# endif
|
||||
# if !defined(PRIu32)
|
||||
# define PRIu32 "u"
|
||||
# endif
|
||||
# if !defined(PRIu64)
|
||||
# define PRIu64 "I64u"
|
||||
# endif
|
||||
# if !defined(bool)
|
||||
# define bool int
|
||||
# endif
|
||||
# if !defined(true)
|
||||
# define true (!0)
|
||||
# endif
|
||||
# if !defined(false)
|
||||
# define false (!!0)
|
||||
# endif
|
||||
#else
|
||||
# include <inttypes.h>
|
||||
# include <stdbool.h>
|
||||
#endif
|
||||
|
||||
#if defined(__cplusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#if defined(__GNUC__)
|
||||
# define MUNIT_LIKELY(expr) (__builtin_expect ((expr), 1))
|
||||
# define MUNIT_UNLIKELY(expr) (__builtin_expect ((expr), 0))
|
||||
# define MUNIT_UNUSED __attribute__((__unused__))
|
||||
#else
|
||||
# define MUNIT_LIKELY(expr) (expr)
|
||||
# define MUNIT_UNLIKELY(expr) (expr)
|
||||
# define MUNIT_UNUSED
|
||||
#endif
|
||||
|
||||
#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) && !defined(__PGI)
|
||||
# define MUNIT_ARRAY_PARAM(name) name
|
||||
#else
|
||||
# define MUNIT_ARRAY_PARAM(name)
|
||||
#endif
|
||||
|
||||
#if !defined(_WIN32)
|
||||
# define MUNIT_SIZE_MODIFIER "z"
|
||||
# define MUNIT_CHAR_MODIFIER "hh"
|
||||
# define MUNIT_SHORT_MODIFIER "h"
|
||||
#else
|
||||
# if defined(_M_X64) || defined(__amd64__)
|
||||
# define MUNIT_SIZE_MODIFIER "I64"
|
||||
# else
|
||||
# define MUNIT_SIZE_MODIFIER ""
|
||||
# endif
|
||||
# define MUNIT_CHAR_MODIFIER ""
|
||||
# define MUNIT_SHORT_MODIFIER ""
|
||||
#endif
|
||||
|
||||
#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L
|
||||
# define MUNIT_NO_RETURN _Noreturn
|
||||
#elif defined(__GNUC__)
|
||||
# define MUNIT_NO_RETURN __attribute__((__noreturn__))
|
||||
#elif defined(_MSC_VER)
|
||||
# define MUNIT_NO_RETURN __declspec(noreturn)
|
||||
#else
|
||||
# define MUNIT_NO_RETURN
|
||||
#endif
|
||||
|
||||
#if defined(_MSC_VER) && (_MSC_VER >= 1500)
|
||||
# define MUNIT__PUSH_DISABLE_MSVC_C4127 __pragma(warning(push)) __pragma(warning(disable:4127))
|
||||
# define MUNIT__POP_DISABLE_MSVC_C4127 __pragma(warning(pop))
|
||||
#else
|
||||
# define MUNIT__PUSH_DISABLE_MSVC_C4127
|
||||
# define MUNIT__POP_DISABLE_MSVC_C4127
|
||||
#endif
|
||||
|
||||
typedef enum {
|
||||
MUNIT_LOG_DEBUG,
|
||||
MUNIT_LOG_INFO,
|
||||
MUNIT_LOG_WARNING,
|
||||
MUNIT_LOG_ERROR
|
||||
} MunitLogLevel;
|
||||
|
||||
#if defined(__GNUC__) && !defined(__MINGW32__)
|
||||
# define MUNIT_PRINTF(string_index, first_to_check) __attribute__((format (printf, string_index, first_to_check)))
|
||||
#else
|
||||
# define MUNIT_PRINTF(string_index, first_to_check)
|
||||
#endif
|
||||
|
||||
MUNIT_PRINTF(4, 5)
|
||||
void munit_logf_ex(MunitLogLevel level, const char* filename, int line, const char* format, ...);
|
||||
|
||||
#define munit_logf(level, format, ...) \
|
||||
munit_logf_ex(level, __FILE__, __LINE__, format, __VA_ARGS__)
|
||||
|
||||
#define munit_log(level, msg) \
|
||||
munit_logf(level, "%s", msg)
|
||||
|
||||
MUNIT_NO_RETURN
|
||||
MUNIT_PRINTF(3, 4)
|
||||
void munit_errorf_ex(const char* filename, int line, const char* format, ...);
|
||||
|
||||
#define munit_errorf(format, ...) \
|
||||
munit_errorf_ex(__FILE__, __LINE__, format, __VA_ARGS__)
|
||||
|
||||
#define munit_error(msg) \
|
||||
munit_errorf("%s", msg)
|
||||
|
||||
#define munit_assert(expr) \
|
||||
do { \
|
||||
if (!MUNIT_LIKELY(expr)) { \
|
||||
munit_error("assertion failed: " #expr); \
|
||||
} \
|
||||
MUNIT__PUSH_DISABLE_MSVC_C4127 \
|
||||
} while (0) \
|
||||
MUNIT__POP_DISABLE_MSVC_C4127
|
||||
|
||||
#define munit_assert_true(expr) \
|
||||
do { \
|
||||
if (!MUNIT_LIKELY(expr)) { \
|
||||
munit_error("assertion failed: " #expr " is not true"); \
|
||||
} \
|
||||
MUNIT__PUSH_DISABLE_MSVC_C4127 \
|
||||
} while (0) \
|
||||
MUNIT__POP_DISABLE_MSVC_C4127
|
||||
|
||||
#define munit_assert_false(expr) \
|
||||
do { \
|
||||
if (!MUNIT_LIKELY(!(expr))) { \
|
||||
munit_error("assertion failed: " #expr " is not false"); \
|
||||
} \
|
||||
MUNIT__PUSH_DISABLE_MSVC_C4127 \
|
||||
} while (0) \
|
||||
MUNIT__POP_DISABLE_MSVC_C4127
|
||||
|
||||
#define munit_assert_type_full(prefix, suffix, T, fmt, a, op, b) \
|
||||
do { \
|
||||
T munit_tmp_a_ = (a); \
|
||||
T munit_tmp_b_ = (b); \
|
||||
if (!(munit_tmp_a_ op munit_tmp_b_)) { \
|
||||
munit_errorf("assertion failed: " #a " " #op " " #b " (" prefix "%" fmt suffix " " #op " " prefix "%" fmt suffix ")", \
|
||||
munit_tmp_a_, munit_tmp_b_); \
|
||||
} \
|
||||
MUNIT__PUSH_DISABLE_MSVC_C4127 \
|
||||
} while (0) \
|
||||
MUNIT__POP_DISABLE_MSVC_C4127
|
||||
|
||||
#define munit_assert_type(T, fmt, a, op, b) \
|
||||
munit_assert_type_full("", "", T, fmt, a, op, b)
|
||||
|
||||
#define munit_assert_char(a, op, b) \
|
||||
munit_assert_type_full("'\\x", "'", char, "02" MUNIT_CHAR_MODIFIER "x", a, op, b)
|
||||
#define munit_assert_uchar(a, op, b) \
|
||||
munit_assert_type_full("'\\x", "'", unsigned char, "02" MUNIT_CHAR_MODIFIER "x", a, op, b)
|
||||
#define munit_assert_short(a, op, b) \
|
||||
munit_assert_type(short, MUNIT_SHORT_MODIFIER "d", a, op, b)
|
||||
#define munit_assert_ushort(a, op, b) \
|
||||
munit_assert_type(unsigned short, MUNIT_SHORT_MODIFIER "u", a, op, b)
|
||||
#define munit_assert_int(a, op, b) \
|
||||
munit_assert_type(int, "d", a, op, b)
|
||||
#define munit_assert_uint(a, op, b) \
|
||||
munit_assert_type(unsigned int, "u", a, op, b)
|
||||
#define munit_assert_long(a, op, b) \
|
||||
munit_assert_type(long int, "ld", a, op, b)
|
||||
#define munit_assert_ulong(a, op, b) \
|
||||
munit_assert_type(unsigned long int, "lu", a, op, b)
|
||||
#define munit_assert_llong(a, op, b) \
|
||||
munit_assert_type(long long int, "lld", a, op, b)
|
||||
#define munit_assert_ullong(a, op, b) \
|
||||
munit_assert_type(unsigned long long int, "llu", a, op, b)
|
||||
|
||||
#define munit_assert_size(a, op, b) \
|
||||
munit_assert_type(size_t, MUNIT_SIZE_MODIFIER "u", a, op, b)
|
||||
|
||||
#define munit_assert_float(a, op, b) \
|
||||
munit_assert_type(float, "f", a, op, b)
|
||||
#define munit_assert_double(a, op, b) \
|
||||
munit_assert_type(double, "g", a, op, b)
|
||||
#define munit_assert_ptr(a, op, b) \
|
||||
munit_assert_type(const void*, "p", a, op, b)
|
||||
|
||||
#define munit_assert_int8(a, op, b) \
|
||||
munit_assert_type(munit_int8_t, PRIi8, a, op, b)
|
||||
#define munit_assert_uint8(a, op, b) \
|
||||
munit_assert_type(munit_uint8_t, PRIu8, a, op, b)
|
||||
#define munit_assert_int16(a, op, b) \
|
||||
munit_assert_type(munit_int16_t, PRIi16, a, op, b)
|
||||
#define munit_assert_uint16(a, op, b) \
|
||||
munit_assert_type(munit_uint16_t, PRIu16, a, op, b)
|
||||
#define munit_assert_int32(a, op, b) \
|
||||
munit_assert_type(munit_int32_t, PRIi32, a, op, b)
|
||||
#define munit_assert_uint32(a, op, b) \
|
||||
munit_assert_type(munit_uint32_t, PRIu32, a, op, b)
|
||||
#define munit_assert_int64(a, op, b) \
|
||||
munit_assert_type(munit_int64_t, PRIi64, a, op, b)
|
||||
#define munit_assert_uint64(a, op, b) \
|
||||
munit_assert_type(munit_uint64_t, PRIu64, a, op, b)
|
||||
|
||||
#define munit_assert_double_equal(a, b, precision) \
|
||||
do { \
|
||||
const double munit_tmp_a_ = (a); \
|
||||
const double munit_tmp_b_ = (b); \
|
||||
const double munit_tmp_diff_ = ((munit_tmp_a_ - munit_tmp_b_) < 0) ? \
|
||||
-(munit_tmp_a_ - munit_tmp_b_) : \
|
||||
(munit_tmp_a_ - munit_tmp_b_); \
|
||||
if (MUNIT_UNLIKELY(munit_tmp_diff_ > 1e-##precision)) { \
|
||||
munit_errorf("assertion failed: " #a " == " #b " (%0." #precision "g == %0." #precision "g)", \
|
||||
munit_tmp_a_, munit_tmp_b_); \
|
||||
} \
|
||||
MUNIT__PUSH_DISABLE_MSVC_C4127 \
|
||||
} while (0) \
|
||||
MUNIT__POP_DISABLE_MSVC_C4127
|
||||
|
||||
#include <string.h>
|
||||
#define munit_assert_string_equal(a, b) \
|
||||
do { \
|
||||
const char* munit_tmp_a_ = a; \
|
||||
const char* munit_tmp_b_ = b; \
|
||||
if (MUNIT_UNLIKELY(strcmp(munit_tmp_a_, munit_tmp_b_) != 0)) { \
|
||||
munit_errorf("assertion failed: string " #a " == " #b " (\"%s\" == \"%s\")", \
|
||||
munit_tmp_a_, munit_tmp_b_); \
|
||||
} \
|
||||
MUNIT__PUSH_DISABLE_MSVC_C4127 \
|
||||
} while (0) \
|
||||
MUNIT__POP_DISABLE_MSVC_C4127
|
||||
|
||||
#define munit_assert_string_not_equal(a, b) \
|
||||
do { \
|
||||
const char* munit_tmp_a_ = a; \
|
||||
const char* munit_tmp_b_ = b; \
|
||||
if (MUNIT_UNLIKELY(strcmp(munit_tmp_a_, munit_tmp_b_) == 0)) { \
|
||||
munit_errorf("assertion failed: string " #a " != " #b " (\"%s\" == \"%s\")", \
|
||||
munit_tmp_a_, munit_tmp_b_); \
|
||||
} \
|
||||
MUNIT__PUSH_DISABLE_MSVC_C4127 \
|
||||
} while (0) \
|
||||
MUNIT__POP_DISABLE_MSVC_C4127
|
||||
|
||||
#define munit_assert_memory_equal(size, a, b) \
|
||||
do { \
|
||||
const unsigned char* munit_tmp_a_ = (const unsigned char*) (a); \
|
||||
const unsigned char* munit_tmp_b_ = (const unsigned char*) (b); \
|
||||
const size_t munit_tmp_size_ = (size); \
|
||||
if (MUNIT_UNLIKELY(memcmp(munit_tmp_a_, munit_tmp_b_, munit_tmp_size_)) != 0) { \
|
||||
size_t munit_tmp_pos_; \
|
||||
for (munit_tmp_pos_ = 0 ; munit_tmp_pos_ < munit_tmp_size_ ; munit_tmp_pos_++) { \
|
||||
if (munit_tmp_a_[munit_tmp_pos_] != munit_tmp_b_[munit_tmp_pos_]) { \
|
||||
munit_errorf("assertion failed: memory " #a " == " #b ", at offset %" MUNIT_SIZE_MODIFIER "u", munit_tmp_pos_); \
|
||||
break; \
|
||||
} \
|
||||
} \
|
||||
} \
|
||||
MUNIT__PUSH_DISABLE_MSVC_C4127 \
|
||||
} while (0) \
|
||||
MUNIT__POP_DISABLE_MSVC_C4127
|
||||
|
||||
#define munit_assert_memory_not_equal(size, a, b) \
|
||||
do { \
|
||||
const unsigned char* munit_tmp_a_ = (const unsigned char*) (a); \
|
||||
const unsigned char* munit_tmp_b_ = (const unsigned char*) (b); \
|
||||
const size_t munit_tmp_size_ = (size); \
|
||||
if (MUNIT_UNLIKELY(memcmp(munit_tmp_a_, munit_tmp_b_, munit_tmp_size_)) == 0) { \
|
||||
munit_errorf("assertion failed: memory" #a " != " #b " (%zu bytes)", munit_tmp_size_); \
|
||||
} \
|
||||
MUNIT__PUSH_DISABLE_MSVC_C4127 \
|
||||
} while (0) \
|
||||
MUNIT__POP_DISABLE_MSVC_C4127
|
||||
|
||||
#define munit_assert_ptr_equal(a, b) \
|
||||
munit_assert_ptr(a, ==, b)
|
||||
#define munit_assert_ptr_not_equal(a, b) \
|
||||
munit_assert_ptr(a, !=, b)
|
||||
#define munit_assert_null(ptr) \
|
||||
munit_assert_ptr(ptr, ==, NULL)
|
||||
#define munit_assert_not_null(ptr) \
|
||||
munit_assert_ptr(ptr, !=, NULL)
|
||||
#define munit_assert_ptr_null(ptr) \
|
||||
munit_assert_ptr(ptr, ==, NULL)
|
||||
#define munit_assert_ptr_not_null(ptr) \
|
||||
munit_assert_ptr(ptr, !=, NULL)
|
||||
|
||||
/*** Memory allocation ***/
|
||||
|
||||
void* munit_malloc_ex(const char* filename, int line, size_t size);
|
||||
|
||||
#define munit_malloc(size) \
|
||||
munit_malloc_ex(__FILE__, __LINE__, (size))
|
||||
|
||||
#define munit_new(type) \
|
||||
((type*) munit_malloc(sizeof(type)))
|
||||
|
||||
#define munit_calloc(nmemb, size) \
|
||||
munit_malloc((nmemb) * (size))
|
||||
|
||||
#define munit_newa(type, nmemb) \
|
||||
((type*) munit_calloc((nmemb), sizeof(type)))
|
||||
|
||||
/*** Random number generation ***/
|
||||
|
||||
void munit_rand_seed(munit_uint32_t seed);
|
||||
munit_uint32_t munit_rand_uint32(void);
|
||||
int munit_rand_int_range(int min, int max);
|
||||
double munit_rand_double(void);
|
||||
void munit_rand_memory(size_t size, munit_uint8_t buffer[MUNIT_ARRAY_PARAM(size)]);
|
||||
|
||||
/*** Tests and Suites ***/
|
||||
|
||||
typedef enum {
|
||||
/* Test successful */
|
||||
MUNIT_OK,
|
||||
/* Test failed */
|
||||
MUNIT_FAIL,
|
||||
/* Test was skipped */
|
||||
MUNIT_SKIP,
|
||||
/* Test failed due to circumstances not intended to be tested
|
||||
* (things like network errors, invalid parameter value, failure to
|
||||
* allocate memory in the test harness, etc.). */
|
||||
MUNIT_ERROR
|
||||
} MunitResult;
|
||||
|
||||
typedef struct {
|
||||
char* name;
|
||||
char** values;
|
||||
} MunitParameterEnum;
|
||||
|
||||
typedef struct {
|
||||
char* name;
|
||||
char* value;
|
||||
} MunitParameter;
|
||||
|
||||
const char* munit_parameters_get(const MunitParameter params[], const char* key);
|
||||
|
||||
typedef enum {
|
||||
MUNIT_TEST_OPTION_NONE = 0,
|
||||
MUNIT_TEST_OPTION_SINGLE_ITERATION = 1 << 0,
|
||||
MUNIT_TEST_OPTION_TODO = 1 << 1
|
||||
} MunitTestOptions;
|
||||
|
||||
typedef MunitResult (* MunitTestFunc)(const MunitParameter params[], void* user_data_or_fixture);
|
||||
typedef void* (* MunitTestSetup)(const MunitParameter params[], void* user_data);
|
||||
typedef void (* MunitTestTearDown)(void* fixture);
|
||||
|
||||
typedef struct {
|
||||
char* name;
|
||||
MunitTestFunc test;
|
||||
MunitTestSetup setup;
|
||||
MunitTestTearDown tear_down;
|
||||
MunitTestOptions options;
|
||||
MunitParameterEnum* parameters;
|
||||
} MunitTest;
|
||||
|
||||
typedef enum {
|
||||
MUNIT_SUITE_OPTION_NONE = 0
|
||||
} MunitSuiteOptions;
|
||||
|
||||
typedef struct MunitSuite_ MunitSuite;
|
||||
|
||||
struct MunitSuite_ {
|
||||
char* prefix;
|
||||
MunitTest* tests;
|
||||
MunitSuite* suites;
|
||||
unsigned int iterations;
|
||||
MunitSuiteOptions options;
|
||||
};
|
||||
|
||||
int munit_suite_main(const MunitSuite* suite, void* user_data, int argc, char* const argv[MUNIT_ARRAY_PARAM(argc + 1)]);
|
||||
|
||||
/* Note: I'm not very happy with this API; it's likely to change if I
|
||||
* figure out something better. Suggestions welcome. */
|
||||
|
||||
typedef struct MunitArgument_ MunitArgument;
|
||||
|
||||
struct MunitArgument_ {
|
||||
char* name;
|
||||
bool (* parse_argument)(const MunitSuite* suite, void* user_data, int* arg, int argc, char* const argv[MUNIT_ARRAY_PARAM(argc + 1)]);
|
||||
void (* write_help)(const MunitArgument* argument, void* user_data);
|
||||
};
|
||||
|
||||
int munit_suite_main_custom(const MunitSuite* suite,
|
||||
void* user_data,
|
||||
int argc, char* const argv[MUNIT_ARRAY_PARAM(argc + 1)],
|
||||
const MunitArgument arguments[]);
|
||||
|
||||
#if defined(MUNIT_ENABLE_ASSERT_ALIASES)
|
||||
|
||||
#define assert_true(expr) munit_assert_true(expr)
|
||||
#define assert_false(expr) munit_assert_false(expr)
|
||||
#define assert_char(a, op, b) munit_assert_char(a, op, b)
|
||||
#define assert_uchar(a, op, b) munit_assert_uchar(a, op, b)
|
||||
#define assert_short(a, op, b) munit_assert_short(a, op, b)
|
||||
#define assert_ushort(a, op, b) munit_assert_ushort(a, op, b)
|
||||
#define assert_int(a, op, b) munit_assert_int(a, op, b)
|
||||
#define assert_uint(a, op, b) munit_assert_uint(a, op, b)
|
||||
#define assert_long(a, op, b) munit_assert_long(a, op, b)
|
||||
#define assert_ulong(a, op, b) munit_assert_ulong(a, op, b)
|
||||
#define assert_llong(a, op, b) munit_assert_llong(a, op, b)
|
||||
#define assert_ullong(a, op, b) munit_assert_ullong(a, op, b)
|
||||
#define assert_size(a, op, b) munit_assert_size(a, op, b)
|
||||
#define assert_float(a, op, b) munit_assert_float(a, op, b)
|
||||
#define assert_double(a, op, b) munit_assert_double(a, op, b)
|
||||
#define assert_ptr(a, op, b) munit_assert_ptr(a, op, b)
|
||||
|
||||
#define assert_int8(a, op, b) munit_assert_int8(a, op, b)
|
||||
#define assert_uint8(a, op, b) munit_assert_uint8(a, op, b)
|
||||
#define assert_int16(a, op, b) munit_assert_int16(a, op, b)
|
||||
#define assert_uint16(a, op, b) munit_assert_uint16(a, op, b)
|
||||
#define assert_int32(a, op, b) munit_assert_int32(a, op, b)
|
||||
#define assert_uint32(a, op, b) munit_assert_uint32(a, op, b)
|
||||
#define assert_int64(a, op, b) munit_assert_int64(a, op, b)
|
||||
#define assert_uint64(a, op, b) munit_assert_uint64(a, op, b)
|
||||
|
||||
#define assert_double_equal(a, b, precision) munit_assert_double_equal(a, b, precision)
|
||||
#define assert_string_equal(a, b) munit_assert_string_equal(a, b)
|
||||
#define assert_string_not_equal(a, b) munit_assert_string_not_equal(a, b)
|
||||
#define assert_memory_equal(size, a, b) munit_assert_memory_equal(size, a, b)
|
||||
#define assert_memory_not_equal(size, a, b) munit_assert_memory_not_equal(size, a, b)
|
||||
#define assert_ptr_equal(a, b) munit_assert_ptr_equal(a, b)
|
||||
#define assert_ptr_not_equal(a, b) munit_assert_ptr_not_equal(a, b)
|
||||
#define assert_ptr_null(ptr) munit_assert_null_equal(ptr)
|
||||
#define assert_ptr_not_null(ptr) munit_assert_not_null(ptr)
|
||||
|
||||
#define assert_null(ptr) munit_assert_null(ptr)
|
||||
#define assert_not_null(ptr) munit_assert_not_null(ptr)
|
||||
|
||||
#endif /* defined(MUNIT_ENABLE_ASSERT_ALIASES) */
|
||||
|
||||
#if defined(__cplusplus)
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* !defined(MUNIT_H) */
|
||||
|
||||
#if defined(MUNIT_ENABLE_ASSERT_ALIASES)
|
||||
# if defined(assert)
|
||||
# undef assert
|
||||
# endif
|
||||
# define assert(expr) munit_assert(expr)
|
||||
#endif
|
||||
45
thirdparty/portable-snippets/tests/once.c
vendored
Normal file
45
thirdparty/portable-snippets/tests/once.c
vendored
Normal file
|
|
@ -0,0 +1,45 @@
|
|||
#if defined(PSNIP_ENABLE_PTHREADS)
|
||||
# include <pthread.h>
|
||||
#endif
|
||||
#include "../exact-int/exact-int.h"
|
||||
#include "../once/once.h"
|
||||
#include "munit/munit.h"
|
||||
|
||||
static psnip_once test_once_basic_once = PSNIP_ONCE_INIT;
|
||||
static int test_once_basic_times_called = 0;
|
||||
|
||||
static void test_once_basic_init(void) {
|
||||
munit_assert_int(test_once_basic_times_called, ==, 0);
|
||||
test_once_basic_times_called++;
|
||||
}
|
||||
|
||||
static MunitResult
|
||||
test_once_basic(const MunitParameter params[], void* data) {
|
||||
(void) params;
|
||||
(void) data;
|
||||
|
||||
munit_assert_int(test_once_basic_times_called, ==, 0);
|
||||
psnip_once_call(&test_once_basic_once, &test_once_basic_init);
|
||||
munit_assert_int(test_once_basic_times_called, ==, 1);
|
||||
psnip_once_call(&test_once_basic_once, &test_once_basic_init);
|
||||
munit_assert_int(test_once_basic_times_called, ==, 1);
|
||||
psnip_once_call(&test_once_basic_once, &test_once_basic_init);
|
||||
munit_assert_int(test_once_basic_times_called, ==, 1);
|
||||
|
||||
return MUNIT_OK;
|
||||
}
|
||||
|
||||
/* TODO: thread safety test. */
|
||||
|
||||
static MunitTest test_suite_tests[] = {
|
||||
{ (char*) "/once/basic", test_once_basic, NULL, NULL, MUNIT_TEST_OPTION_NONE, NULL },
|
||||
{ NULL, NULL, NULL, NULL, MUNIT_TEST_OPTION_NONE, NULL }
|
||||
};
|
||||
|
||||
static const MunitSuite test_suite = {
|
||||
(char*) "", test_suite_tests, NULL, 1, MUNIT_SUITE_OPTION_NONE
|
||||
};
|
||||
|
||||
int main(int argc, char* argv[MUNIT_ARRAY_PARAM(argc + 1)]) {
|
||||
return munit_suite_main(&test_suite, NULL, argc, argv);
|
||||
}
|
||||
93
thirdparty/portable-snippets/tests/random.c
vendored
Normal file
93
thirdparty/portable-snippets/tests/random.c
vendored
Normal file
|
|
@ -0,0 +1,93 @@
|
|||
#include "../exact-int/exact-int.h"
|
||||
#include "../random/random.h"
|
||||
#include "munit/munit.h"
|
||||
|
||||
static MunitResult
|
||||
test_random_secure(const MunitParameter params[], void* data) {
|
||||
psnip_uint8_t buf[4096] = { 0, };
|
||||
int r;
|
||||
size_t p;
|
||||
|
||||
(void) params;
|
||||
(void) data;
|
||||
|
||||
r = psnip_random_bytes(PSNIP_RANDOM_SOURCE_SECURE, sizeof(buf), buf);
|
||||
munit_assert_int(r, ==, 0);
|
||||
|
||||
/* Make sure we actually read some data. */
|
||||
for (p = 0 ; p < sizeof(buf) ; p++)
|
||||
if (buf[p] != 0)
|
||||
break;
|
||||
|
||||
munit_assert_size(p, <, sizeof(buf));
|
||||
|
||||
return MUNIT_OK;
|
||||
}
|
||||
|
||||
static MunitResult
|
||||
test_random_reproducible(const MunitParameter params[], void* data) {
|
||||
const psnip_uint32_t test_data[] = {
|
||||
0x8a4b308cU, 0x15534978U, 0xfec18d9aU, 0x7f345f7dU,
|
||||
0x297766eeU, 0x771fb9f4U, 0x31e5a255U, 0xd0c9819dU,
|
||||
0xef73a350U, 0xd9d26480U, 0xb5367e1aU, 0xc1a02725U,
|
||||
0x8b2a1228U, 0x735c43f6U, 0x63ca3280U, 0x9bcd8362U,
|
||||
0xac305d31U, 0x45f16be6U, 0x53247d92U, 0x363d54fbU,
|
||||
0xaccbf201U, 0xc5963be4U, 0x646402c1U, 0xcbbf2841U,
|
||||
0x16c42c02U, 0xf1b19a74U, 0xe2c78da3U, 0x352ac7a4U,
|
||||
0x0e208ef3U, 0x94fec876U, 0x9fd96b4bU, 0x3ed00c53U
|
||||
};
|
||||
psnip_uint32_t buf[sizeof(test_data) / sizeof(test_data[0])] = { 0, };
|
||||
size_t i;
|
||||
int r;
|
||||
|
||||
(void) params;
|
||||
(void) data;
|
||||
|
||||
psnip_random_set_seed(1729);
|
||||
|
||||
r = psnip_random_bytes(PSNIP_RANDOM_SOURCE_REPRODUCIBLE, sizeof(buf), (psnip_uint8_t*) buf);
|
||||
munit_assert_int(r, ==, 0);
|
||||
|
||||
for (i = 0 ; i < sizeof(buf) / sizeof(buf[0]) ; i++) {
|
||||
munit_assert_uint32(buf[i], ==, test_data[i]);
|
||||
}
|
||||
|
||||
return MUNIT_OK;
|
||||
}
|
||||
|
||||
static MunitResult
|
||||
test_random_fast(const MunitParameter params[], void* data) {
|
||||
psnip_uint8_t buf[4096] = { 0, };
|
||||
int r;
|
||||
size_t p;
|
||||
|
||||
(void) params;
|
||||
(void) data;
|
||||
|
||||
r = psnip_random_bytes(PSNIP_RANDOM_SOURCE_FAST, sizeof(buf), buf);
|
||||
munit_assert_int(r, ==, 0);
|
||||
|
||||
/* Make sure we actually read some data. */
|
||||
for (p = 0 ; p < sizeof(buf) ; p++)
|
||||
if (buf[p] != 0)
|
||||
break;
|
||||
|
||||
munit_assert_size(p, <, sizeof(buf));
|
||||
|
||||
return MUNIT_OK;
|
||||
}
|
||||
|
||||
static MunitTest test_suite_tests[] = {
|
||||
{ (char*) "/random/secure", test_random_secure, NULL, NULL, MUNIT_TEST_OPTION_NONE, NULL },
|
||||
{ (char*) "/random/reproducible", test_random_reproducible, NULL, NULL, MUNIT_TEST_OPTION_NONE, NULL },
|
||||
{ (char*) "/random/fast", test_random_fast, NULL, NULL, MUNIT_TEST_OPTION_NONE, NULL },
|
||||
{ NULL, NULL, NULL, NULL, MUNIT_TEST_OPTION_NONE, NULL }
|
||||
};
|
||||
|
||||
static const MunitSuite test_suite = {
|
||||
(char*) "", test_suite_tests, NULL, 1, MUNIT_SUITE_OPTION_NONE
|
||||
};
|
||||
|
||||
int main(int argc, char* argv[MUNIT_ARRAY_PARAM(argc + 1)]) {
|
||||
return munit_suite_main(&test_suite, NULL, argc, argv);
|
||||
}
|
||||
211
thirdparty/portable-snippets/tests/safe-math.c
vendored
Normal file
211
thirdparty/portable-snippets/tests/safe-math.c
vendored
Normal file
|
|
@ -0,0 +1,211 @@
|
|||
#include "../exact-int/exact-int.h"
|
||||
#define PSNIP_BUILTIN_EMULATE_NATIVE
|
||||
#include "../safe-math/safe-math.h"
|
||||
|
||||
#include "munit/munit.h"
|
||||
|
||||
#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L)
|
||||
static MunitResult
|
||||
test_safe_generic(const MunitParameter params[], void* user_data) {
|
||||
unsigned long long a = 1, b = 1, res;
|
||||
|
||||
(void) params;
|
||||
(void) user_data;
|
||||
|
||||
do {
|
||||
if (!psnip_safe_add(&res, a, b)) {
|
||||
munit_logf(MUNIT_LOG_DEBUG, "%llu + %llu overflows", a, b);
|
||||
break;
|
||||
}
|
||||
|
||||
munit_logf(MUNIT_LOG_DEBUG, "%llu + %llu = %llu", a, b, res);
|
||||
a = b;
|
||||
b = res;
|
||||
} while (1);
|
||||
|
||||
return MUNIT_OK;
|
||||
}
|
||||
#endif
|
||||
|
||||
#define DEFINE_PSNIP_SAFE_TESTS(T, name, min, max) \
|
||||
static MunitResult \
|
||||
test_safe_##name##_add(const MunitParameter params[], void* user_data) { \
|
||||
T result; \
|
||||
(void) params; \
|
||||
(void) user_data; \
|
||||
munit_assert_true(psnip_safe_##name##_add(&result, 0, 1)); \
|
||||
munit_assert_##name(result, ==, 1); \
|
||||
munit_assert_true(psnip_safe_##name##_add(&result, 1, 1)); \
|
||||
munit_assert_##name(result, ==, 2); \
|
||||
munit_assert_true(psnip_safe_##name##_add(&result, 1, max - 1)); \
|
||||
munit_assert_##name(result, ==, max); \
|
||||
munit_assert_false(psnip_safe_##name##_add(&result, max, 1)); \
|
||||
return MUNIT_OK; \
|
||||
} \
|
||||
\
|
||||
static MunitResult \
|
||||
test_safe_##name##_sub(const MunitParameter params[], void* user_data) { \
|
||||
T result; \
|
||||
(void) params; \
|
||||
(void) user_data; \
|
||||
munit_assert_true(psnip_safe_##name##_sub(&result, 1, 1)); \
|
||||
munit_assert_##name(result, ==, 0); \
|
||||
munit_assert_false(psnip_safe_##name##_sub(&result, min, 1)); \
|
||||
munit_assert_true(psnip_safe_##name##_sub(&result, max, 1)); \
|
||||
munit_assert_##name(result, ==, max - 1); \
|
||||
return MUNIT_OK; \
|
||||
} \
|
||||
\
|
||||
static MunitResult \
|
||||
test_safe_##name##_mul(const MunitParameter params[], void* user_data) { \
|
||||
T result; \
|
||||
(void) params; \
|
||||
(void) user_data; \
|
||||
munit_assert_true(psnip_safe_##name##_mul(&result, 2, 2)); \
|
||||
munit_assert_##name(result, ==, 4); \
|
||||
munit_assert_true(psnip_safe_##name##_mul(&result, 0, max)); \
|
||||
munit_assert_##name(result, ==, 0); \
|
||||
munit_assert_true(psnip_safe_##name##_mul(&result, max, 0)); \
|
||||
munit_assert_##name(result, ==, 0); \
|
||||
munit_assert_true(psnip_safe_##name##_mul(&result, min, 0)); \
|
||||
munit_assert_##name(result, ==, 0); \
|
||||
return MUNIT_OK; \
|
||||
} \
|
||||
\
|
||||
static MunitResult \
|
||||
test_safe_##name##_div(const MunitParameter params[], void* user_data) { \
|
||||
T result; \
|
||||
(void) params; \
|
||||
(void) user_data; \
|
||||
munit_assert_true(psnip_safe_##name##_div(&result, 2, 2)); \
|
||||
munit_assert_##name(result, ==, 1); \
|
||||
munit_assert_false(psnip_safe_##name##_div(&result, 1, 0)); \
|
||||
munit_assert_##name(result, ==, 0); \
|
||||
return MUNIT_OK; \
|
||||
} \
|
||||
\
|
||||
static MunitResult \
|
||||
test_safe_##name##_mod(const MunitParameter params[], void* user_data) { \
|
||||
T result; \
|
||||
(void) params; \
|
||||
(void) user_data; \
|
||||
munit_assert_true(psnip_safe_##name##_mod(&result, 10, 4)); \
|
||||
munit_assert_##name(result, ==, 2); \
|
||||
munit_assert_false(psnip_safe_##name##_mod(&result, 1, 0)); \
|
||||
munit_assert_##name(result, ==, 0); \
|
||||
return MUNIT_OK; \
|
||||
}
|
||||
|
||||
#define DEFINE_PSNIP_SAFE_TESTS_S(T, name, min, max) \
|
||||
DEFINE_PSNIP_SAFE_TESTS(T, name, min, max) \
|
||||
static MunitResult \
|
||||
test_safe_##name##_div_signed(const MunitParameter params[], void* user_data) { \
|
||||
T result; \
|
||||
(void) params; \
|
||||
(void) user_data; \
|
||||
munit_assert_false(psnip_safe_##name##_div(&result, min, -1)); \
|
||||
munit_assert_##name(result, ==, min); \
|
||||
return MUNIT_OK; \
|
||||
} \
|
||||
\
|
||||
static MunitResult \
|
||||
test_safe_##name##_neg_signed(const MunitParameter params[], void* user_data) { \
|
||||
T result; \
|
||||
(void) params; \
|
||||
(void) user_data; \
|
||||
munit_assert_true(psnip_safe_##name##_neg(&result, max)); \
|
||||
munit_assert_##name(result, ==, -max); \
|
||||
munit_assert_false(psnip_safe_##name##_neg(&result, min)); \
|
||||
munit_assert_##name(result, ==, max); \
|
||||
return MUNIT_OK; \
|
||||
}
|
||||
|
||||
#define DEFINE_PSNIP_SAFE_TEST_ENTRY(name, op) \
|
||||
{ (char*) "/" #name "/" #op, test_safe_##name##_##op, NULL, NULL, MUNIT_TEST_OPTION_NONE, NULL }
|
||||
|
||||
#define DEFINE_PSNIP_SAFE_TEST_ENTRY_S(name, op) \
|
||||
{ (char*) "/" #name "/" #op "/signed", test_safe_##name##_##op##_signed, NULL, NULL, MUNIT_TEST_OPTION_NONE, NULL }
|
||||
|
||||
#define DEFINE_PSNIP_SAFE_TEST_ENTRIES(name) \
|
||||
DEFINE_PSNIP_SAFE_TEST_ENTRY(name, add), \
|
||||
DEFINE_PSNIP_SAFE_TEST_ENTRY(name, sub), \
|
||||
DEFINE_PSNIP_SAFE_TEST_ENTRY(name, mul), \
|
||||
DEFINE_PSNIP_SAFE_TEST_ENTRY(name, div), \
|
||||
DEFINE_PSNIP_SAFE_TEST_ENTRY(name, mod)
|
||||
|
||||
#define DEFINE_PSNIP_SAFE_TEST_ENTRIES_S(name) \
|
||||
DEFINE_PSNIP_SAFE_TEST_ENTRIES(name), \
|
||||
DEFINE_PSNIP_SAFE_TEST_ENTRY_S(name, div), \
|
||||
DEFINE_PSNIP_SAFE_TEST_ENTRY_S(name, neg)
|
||||
|
||||
#if CHAR_MIN < 0
|
||||
DEFINE_PSNIP_SAFE_TESTS_S(char, char, CHAR_MIN, CHAR_MAX)
|
||||
#else
|
||||
DEFINE_PSNIP_SAFE_TESTS (char, char, CHAR_MIN, CHAR_MAX)
|
||||
#endif
|
||||
DEFINE_PSNIP_SAFE_TESTS (unsigned char, uchar, 0, UCHAR_MAX)
|
||||
DEFINE_PSNIP_SAFE_TESTS_S(short, short, SHRT_MIN, SHRT_MAX)
|
||||
DEFINE_PSNIP_SAFE_TESTS (unsigned short, ushort, 0, USHRT_MAX)
|
||||
DEFINE_PSNIP_SAFE_TESTS_S(int, int, INT_MIN, INT_MAX)
|
||||
DEFINE_PSNIP_SAFE_TESTS (unsigned int, uint, 0, UINT_MAX)
|
||||
DEFINE_PSNIP_SAFE_TESTS_S(long, long, LONG_MIN, LONG_MAX)
|
||||
DEFINE_PSNIP_SAFE_TESTS (unsigned long, ulong, 0, ULONG_MAX)
|
||||
DEFINE_PSNIP_SAFE_TESTS_S(long long, llong, LLONG_MIN, LLONG_MAX)
|
||||
DEFINE_PSNIP_SAFE_TESTS (unsigned long long, ullong, 0, ULLONG_MAX)
|
||||
#if defined(SIZE_MAX)
|
||||
DEFINE_PSNIP_SAFE_TESTS (size_t, size, 0, SIZE_MAX)
|
||||
#endif
|
||||
#if !defined(PSNIP_SAFE_NO_FIXED)
|
||||
DEFINE_PSNIP_SAFE_TESTS_S(psnip_int8_t, int8, (-0x7fLL-1), 0x7f)
|
||||
DEFINE_PSNIP_SAFE_TESTS (psnip_uint8_t, uint8, 0, 0xffU)
|
||||
DEFINE_PSNIP_SAFE_TESTS_S(psnip_int16_t, int16, (-0x7fffLL-1), 0x7fff)
|
||||
DEFINE_PSNIP_SAFE_TESTS (psnip_uint16_t, uint16, 0, 0xffffU)
|
||||
DEFINE_PSNIP_SAFE_TESTS_S(psnip_int32_t, int32, (-0x7fffffffLL-1), 0x7fffffffL)
|
||||
DEFINE_PSNIP_SAFE_TESTS (psnip_uint32_t, uint32, 0, 0xffffffffUL)
|
||||
DEFINE_PSNIP_SAFE_TESTS_S(psnip_int64_t, int64, (-0x7fffffffffffffffLL-1), 0x7fffffffffffffffLL)
|
||||
DEFINE_PSNIP_SAFE_TESTS (psnip_uint64_t, uint64, 0, 0xffffffffffffffffULL)
|
||||
#endif /* !defined(PSNIP_SAFE_NO_FIXED) */
|
||||
|
||||
static MunitTest psnip_safe_test_suite_tests[] = {
|
||||
#if CHAR_MIN < 0
|
||||
DEFINE_PSNIP_SAFE_TEST_ENTRIES_S(char),
|
||||
#else
|
||||
DEFINE_PSNIP_SAFE_TEST_ENTRIES(char),
|
||||
#endif
|
||||
DEFINE_PSNIP_SAFE_TEST_ENTRIES(uchar),
|
||||
DEFINE_PSNIP_SAFE_TEST_ENTRIES_S(short),
|
||||
DEFINE_PSNIP_SAFE_TEST_ENTRIES(ushort),
|
||||
DEFINE_PSNIP_SAFE_TEST_ENTRIES_S(int),
|
||||
DEFINE_PSNIP_SAFE_TEST_ENTRIES(uint),
|
||||
DEFINE_PSNIP_SAFE_TEST_ENTRIES_S(long),
|
||||
DEFINE_PSNIP_SAFE_TEST_ENTRIES(ulong),
|
||||
DEFINE_PSNIP_SAFE_TEST_ENTRIES_S(llong),
|
||||
DEFINE_PSNIP_SAFE_TEST_ENTRIES(ullong),
|
||||
DEFINE_PSNIP_SAFE_TEST_ENTRIES(size),
|
||||
#if !defined(PSNIP_SAFE_NO_FIXED)
|
||||
DEFINE_PSNIP_SAFE_TEST_ENTRIES_S(int8),
|
||||
DEFINE_PSNIP_SAFE_TEST_ENTRIES(uint8),
|
||||
DEFINE_PSNIP_SAFE_TEST_ENTRIES_S(int16),
|
||||
DEFINE_PSNIP_SAFE_TEST_ENTRIES(uint16),
|
||||
DEFINE_PSNIP_SAFE_TEST_ENTRIES_S(int32),
|
||||
DEFINE_PSNIP_SAFE_TEST_ENTRIES(uint32),
|
||||
DEFINE_PSNIP_SAFE_TEST_ENTRIES_S(int64),
|
||||
DEFINE_PSNIP_SAFE_TEST_ENTRIES(uint64),
|
||||
#endif /* !defined(PSNIP_SAFE_NO_FIXED) */
|
||||
#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L)
|
||||
{ (char*) "/generic", test_safe_generic, NULL, NULL, MUNIT_TEST_OPTION_NONE, NULL },
|
||||
#endif
|
||||
{ NULL, NULL, NULL, NULL, MUNIT_TEST_OPTION_NONE, NULL }
|
||||
};
|
||||
|
||||
static const MunitSuite test_suite = {
|
||||
(char*) "/safe-math",
|
||||
psnip_safe_test_suite_tests,
|
||||
NULL,
|
||||
1,
|
||||
MUNIT_SUITE_OPTION_NONE
|
||||
};
|
||||
|
||||
int main(int argc, char* argv[MUNIT_ARRAY_PARAM(argc + 1)]) {
|
||||
return munit_suite_main(&test_suite, NULL, argc, argv);
|
||||
}
|
||||
146
thirdparty/portable-snippets/tests/unaligned.c
vendored
Normal file
146
thirdparty/portable-snippets/tests/unaligned.c
vendored
Normal file
|
|
@ -0,0 +1,146 @@
|
|||
#define PSNIP_UNALIGNED_ALLOW_UNDEFINED
|
||||
/* #define PSNIP_UNALIGNED_ALLOW_UBSAN */
|
||||
/* #define PSNIP_UNALIGNED_IMPL 2 */
|
||||
/* #define PSNIP_UNALIGNED_IMPL 3 */
|
||||
|
||||
#include "../exact-int/exact-int.h"
|
||||
#include "../unaligned/unaligned.h"
|
||||
#include "munit/munit.h"
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
static psnip_uint8_t buffer[1024 * 1024];
|
||||
|
||||
static MunitResult
|
||||
test_unaligned_uint64(const MunitParameter params[], void* data) {
|
||||
psnip_uint64_t v;
|
||||
psnip_uint8_t* c = buffer;
|
||||
psnip_uint8_t* e = &(buffer[sizeof(buffer)]) - sizeof(v);
|
||||
|
||||
(void) params;
|
||||
(void) data;
|
||||
|
||||
while (c <= e) {
|
||||
munit_rand_memory(sizeof(v), (psnip_uint8_t*) &v);
|
||||
v ^= psnip_unaligned_load_uint64(c);
|
||||
psnip_unaligned_store_uint64(c, v);
|
||||
|
||||
c++;
|
||||
}
|
||||
|
||||
return MUNIT_OK;
|
||||
}
|
||||
|
||||
static MunitResult
|
||||
test_unaligned_uint32(const MunitParameter params[], void* data) {
|
||||
psnip_uint32_t v;
|
||||
psnip_uint8_t* c = buffer;
|
||||
psnip_uint8_t* e = &(buffer[sizeof(buffer)]) - sizeof(v);
|
||||
|
||||
(void) params;
|
||||
(void) data;
|
||||
|
||||
while (c <= e) {
|
||||
munit_rand_memory(sizeof(v), (psnip_uint8_t*) &v);
|
||||
v ^= psnip_unaligned_load_uint32(c);
|
||||
psnip_unaligned_store_uint32(c, v);
|
||||
|
||||
c++;
|
||||
}
|
||||
|
||||
return MUNIT_OK;
|
||||
}
|
||||
|
||||
static MunitResult
|
||||
test_unaligned_uint16(const MunitParameter params[], void* data) {
|
||||
psnip_uint16_t v;
|
||||
psnip_uint8_t* c = buffer;
|
||||
psnip_uint8_t* e = &(buffer[sizeof(buffer)]) - sizeof(v);
|
||||
|
||||
(void) params;
|
||||
(void) data;
|
||||
|
||||
while (c <= e) {
|
||||
munit_rand_memory(sizeof(v), (psnip_uint8_t*) &v);
|
||||
v ^= psnip_unaligned_load_uint16(c);
|
||||
psnip_unaligned_store_uint16(c, v);
|
||||
|
||||
c++;
|
||||
}
|
||||
|
||||
return MUNIT_OK;
|
||||
}
|
||||
|
||||
/* Try to get the compiler to vectorize this; SIMD instructions are
|
||||
more likely to have problems with unaligned accesses. */
|
||||
#if defined(__GNUC__)
|
||||
# if !defined(__clang__)
|
||||
__attribute__((__optimize__(3),__noinline__))
|
||||
# else
|
||||
__attribute__((__noinline__))
|
||||
# endif
|
||||
#endif
|
||||
static void
|
||||
dangerous_copy(size_t count, psnip_uint64_t* dest, const psnip_uint64_t* src) {
|
||||
size_t i;
|
||||
for (i = 0 ; i < count ; i++) {
|
||||
psnip_unaligned_store_uint64(&(dest[i]), psnip_unaligned_load_uint64(&(src[i])));
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(__GNUC__)
|
||||
# if defined(__has_attribute) && !defined(__ibmxl__)
|
||||
# if __has_attribute(optnone)
|
||||
__attribute__((__optnone__))
|
||||
# endif
|
||||
# elif !defined(__clang__)
|
||||
__attribute__((__optimize__(0)))
|
||||
# endif
|
||||
__attribute__((__noinline__))
|
||||
#endif
|
||||
static MunitResult
|
||||
test_unaligned_uint64_tempt(const MunitParameter params[], void* data) {
|
||||
static psnip_uint8_t buffer2[sizeof(buffer)];
|
||||
psnip_uint8_t buffer_x = 0;
|
||||
psnip_uint8_t buffer_y = 0;
|
||||
size_t i;
|
||||
|
||||
(void) params;
|
||||
(void) data;
|
||||
|
||||
munit_rand_memory(sizeof(buffer), buffer);
|
||||
|
||||
|
||||
dangerous_copy((sizeof(buffer) / sizeof(psnip_uint64_t)) - 1,
|
||||
(void*) (buffer2 + 1), (void*) (buffer + 1));
|
||||
|
||||
/* XOR all the data together, just to try to convince the compiler
|
||||
* not to optimize anything away. */
|
||||
|
||||
for (i = 1 ; i < (sizeof(buffer) - (sizeof(psnip_uint64_t) - 1)) ; i++) {
|
||||
buffer_x ^= buffer[i];
|
||||
buffer_y ^= buffer[i];
|
||||
}
|
||||
|
||||
munit_assert_uint8(buffer_x, ==, buffer_y);
|
||||
|
||||
return MUNIT_OK;
|
||||
}
|
||||
|
||||
static MunitTest test_suite_tests[] = {
|
||||
{ (char*) "/unaligned/uint64", test_unaligned_uint64, NULL, NULL, MUNIT_TEST_OPTION_NONE, NULL },
|
||||
{ (char*) "/unaligned/uint32", test_unaligned_uint32, NULL, NULL, MUNIT_TEST_OPTION_NONE, NULL },
|
||||
{ (char*) "/unaligned/uint16", test_unaligned_uint16, NULL, NULL, MUNIT_TEST_OPTION_NONE, NULL },
|
||||
{ (char*) "/unaligned/uint64/tempt", test_unaligned_uint64_tempt, NULL, NULL, MUNIT_TEST_OPTION_NONE, NULL },
|
||||
{ NULL, NULL, NULL, NULL, MUNIT_TEST_OPTION_NONE, NULL }
|
||||
};
|
||||
|
||||
static const MunitSuite test_suite = {
|
||||
(char*) "", test_suite_tests, NULL, 1, MUNIT_SUITE_OPTION_NONE
|
||||
};
|
||||
|
||||
int main(int argc, char* argv[MUNIT_ARRAY_PARAM(argc + 1)]) {
|
||||
munit_rand_memory(sizeof(buffer), buffer);
|
||||
|
||||
return munit_suite_main(&test_suite, NULL, argc, argv);
|
||||
}
|
||||
107
thirdparty/portable-snippets/unaligned/README.md
vendored
Normal file
107
thirdparty/portable-snippets/unaligned/README.md
vendored
Normal file
|
|
@ -0,0 +1,107 @@
|
|||
# Unaligned Loads and Stores
|
||||
|
||||
**WARNING**: This module is work-in-progress, and not yet ready for
|
||||
widespread adoption. Testing, however, would be greatly appreciated.
|
||||
|
||||
This header provides fast load/store operations.
|
||||
|
||||
## Rationale
|
||||
|
||||
Yann Collet wrote a [great blog
|
||||
post](https://fastcompression.blogspot.fr/2015/08/accessing-unaligned-memory.html)
|
||||
about accessing unaligned memory a while back which is well worth a
|
||||
read. Basically, there are a few different methods to access
|
||||
unaligned memory, with different performance implications. `memcpy`
|
||||
is safe, but slow on some compilers. Other methods rely on undefined
|
||||
behavior which may or may not be safe depending on the compiler and
|
||||
platform, and/or compiler-specific constructs.
|
||||
|
||||
It's important to note that, if you rely on undefined behavior,
|
||||
compilers which currently work may stop working in the future when
|
||||
optimizations are added. For example, unaligned accesses are usually
|
||||
allowed on x86, but not for some SIMD instructions. GCC 4.9 added an
|
||||
optimization which automatically vectorized some code in LZ4, and
|
||||
since LZ4 (at the time) relied on unaligned accesses that change broke
|
||||
LZ4.
|
||||
|
||||
The biggest value of this module is the logic to determine which
|
||||
method to use on different combinations of compilers, compiler
|
||||
versions, and architectures.
|
||||
|
||||
## Usage
|
||||
|
||||
`unaligned.h` defines macros which can be used to generate inline
|
||||
functions for whatever types you want. For example, to generate
|
||||
functions for `int`:
|
||||
|
||||
```c
|
||||
PSNIP_UNALIGNED_LOAD_DEFINE(foo_load, int)
|
||||
PSNIP_UNALIGNED_STORE_DEFINE(foo_store, int)
|
||||
```
|
||||
|
||||
Would yield functions which look something like:
|
||||
|
||||
```c
|
||||
int foo_load(const void* src);
|
||||
void foo_store(void* dest, int src);
|
||||
```
|
||||
|
||||
By default, we will use `memcpy` as it's the only completely safe
|
||||
option. However, if you define `PSNIP_UNALIGNED_ALLOW_UNDEFINED`
|
||||
prior to including `unaligned.h` it will check for platforms where
|
||||
unaligned accesses are safe and faster than `memcpy()`. On such
|
||||
platforms, access may be done through either a cast & dereference or
|
||||
through a packed union.
|
||||
|
||||
If you include `exact-int.h` before including `unaligned.h` (or define
|
||||
the exact-width types yourself), we will also define functions to
|
||||
load/store to/from those types:
|
||||
|
||||
```c
|
||||
psnip_int16_t psnip_unaligned_load_int16 (const void* src);
|
||||
psnip_int32_t psnip_unaligned_load_int32 (const void* src);
|
||||
psnip_int64_t psnip_unaligned_load_int64 (const void* src);
|
||||
psnip_uint16_t psnip_unaligned_load_uint16 (const void* src);
|
||||
psnip_uint32_t psnip_unaligned_load_uint32 (const void* src);
|
||||
psnip_uint64_t psnip_unaligned_load_uint64 (const void* src);
|
||||
void psnip_unaligned_store_int16 (void* dest, int16_t src);
|
||||
void psnip_unaligned_store_int32 (void* dest, int32_t src);
|
||||
void psnip_unaligned_store_int64 (void* dest, int64_t src);
|
||||
void psnip_unaligned_store_uint16(void* dest, uint16_t src);
|
||||
void psnip_unaligned_store_uint32(void* dest, uint32_t src);
|
||||
void psnip_unaligned_store_uint64(void* dest, uint64_t src);
|
||||
```
|
||||
|
||||
If you also include `endian.h` before including `unaligned.h`, we will
|
||||
also define macros to load/store different-endian values to/from
|
||||
the exact-width types:
|
||||
|
||||
```c
|
||||
psnip_int16_t psnip_unaligned_load_int16le (const void* src);
|
||||
psnip_int32_t psnip_unaligned_load_int32le (const void* src);
|
||||
psnip_int64_t psnip_unaligned_load_int64le (const void* src);
|
||||
psnip_int16_t psnip_unaligned_load_int16be (const void* src);
|
||||
psnip_int32_t psnip_unaligned_load_int32be (const void* src);
|
||||
psnip_int64_t psnip_unaligned_load_int64be (const void* src);
|
||||
psnip_uint16_t psnip_unaligned_load_uint16le (const void* src);
|
||||
psnip_uint32_t psnip_unaligned_load_uint32le (const void* src);
|
||||
psnip_uint64_t psnip_unaligned_load_uint64le (const void* src);
|
||||
psnip_uint16_t psnip_unaligned_load_uint16be (const void* src);
|
||||
psnip_uint32_t psnip_unaligned_load_uint32be (const void* src);
|
||||
psnip_uint64_t psnip_unaligned_load_uint64be (const void* src);
|
||||
void psnip_unaligned_store_int16le (void* dest, psnip_int16_t src);
|
||||
void psnip_unaligned_store_int32le (void* dest, psnip_int32_t src);
|
||||
void psnip_unaligned_store_int64le (void* dest, psnip_int64_t src);
|
||||
void psnip_unaligned_store_int16be (void* dest, psnip_int16_t src);
|
||||
void psnip_unaligned_store_int32be (void* dest, psnip_int32_t src);
|
||||
void psnip_unaligned_store_int64be (void* dest, psnip_int64_t src);
|
||||
void psnip_unaligned_store_uint16le(void* dest, psnip_int16_t src);
|
||||
void psnip_unaligned_store_uint32le(void* dest, psnip_int32_t src);
|
||||
void psnip_unaligned_store_uint64le(void* dest, psnip_int64_t src);
|
||||
void psnip_unaligned_store_uint16be(void* dest, psnip_int16_t src);
|
||||
void psnip_unaligned_store_uint32be(void* dest, psnip_int32_t src);
|
||||
void psnip_unaligned_store_uint64be(void* dest, psnip_int64_t src);
|
||||
```
|
||||
|
||||
These are implemented as macros, the prototypes above are purely for
|
||||
documentation.
|
||||
230
thirdparty/portable-snippets/unaligned/unaligned.h
vendored
Normal file
230
thirdparty/portable-snippets/unaligned/unaligned.h
vendored
Normal file
|
|
@ -0,0 +1,230 @@
|
|||
/* Unaligned operations (v1)
|
||||
* Portable Snippets - https://github.com/nemequ/portable-snippets
|
||||
* Created by Evan Nemerson <evan@nemerson.com>
|
||||
*
|
||||
* To the extent possible under law, the authors have waived all
|
||||
* copyright and related or neighboring rights to this code. For
|
||||
* details, see the Creative Commons Zero 1.0 Universal license at
|
||||
* https://creativecommons.org/publicdomain/zero/1.0/
|
||||
*
|
||||
* Most architectures allow unaligned access to some degree, but
|
||||
* according to the C specification unaligned accesses are undefined
|
||||
* behavior. The portable thing to do is use memcpy(), but depending
|
||||
* on the architecture and compiler that may be slower than either
|
||||
* dereferencing a pointer or using a union.
|
||||
*
|
||||
* If you define PSNIP_UNALIGNED_ALLOW_UNDEFINED prior to including
|
||||
* this header, it will try to implement the fastest method which is
|
||||
* known to work given the architecture and compiler.
|
||||
*
|
||||
* Some of the tests are taken from zstd; Yann Collet has done some
|
||||
* great work benchmarking different methods on different
|
||||
* architectures.
|
||||
*/
|
||||
|
||||
#if !defined(PSNIP_UNALIGNED_H)
|
||||
#define PSNIP_UNALIGNED_H
|
||||
|
||||
#define PSNIP_UNALIGNED_IMPL_MEMCPY 1
|
||||
#define PSNIP_UNALIGNED_IMPL_DEREF 2
|
||||
#define PSNIP_UNALIGNED_IMPL_UNION 3
|
||||
|
||||
#if defined(PSNIP_UNALIGNED_IMPL)
|
||||
# if (PSNIP_UNALIGNED_IMPL < 1) || (PSNIP_UNALIGNED_IMPL > 3)
|
||||
# error Unsupported unaligned access method requested.
|
||||
# endif
|
||||
#elif !defined(PSNIP_UNALIGNED_ALLOW_UNDEFINED)
|
||||
# define PSNIP_UNALIGNED_IMPL PSNIP_UNALIGNED_IMPL_MEMCPY
|
||||
#elif defined(__INTEL_COMPILER)
|
||||
# define PSNIP_UNALIGNED_IMPL PSNIP_UNALIGNED_IMPL_UNION
|
||||
#elif defined(__GNUC__)
|
||||
# if (__GNUC__ >= 6)
|
||||
# define PSNIP_UNALIGNED_IMPL PSNIP_UNALIGNED_IMPL_MEMCPY
|
||||
# elif defined(__ARM_ARCH_6__) || defined(__ARM_ARCH_6J__) || defined(__ARM_ARCH_6K__) || defined(__ARM_ARCH_6Z__) || defined(__ARM_ARCH_6ZK__) || defined(__ARM_ARCH_6T2__)
|
||||
# define PSNIP_UNALIGNED_IMPL PSNIP_UNALIGNED_IMPL_UNION
|
||||
# elif (defined(__amd64) || defined(__i386))
|
||||
# if ((__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8))
|
||||
# define PSNIP_UNALIGNED_IMPL PSNIP_UNALIGNED_IMPL_MEMCPY
|
||||
# else
|
||||
# define PSNIP_UNALIGNED_IMPL PSNIP_UNALIGNED_IMPL_DEREF
|
||||
# endif
|
||||
# elif defined(__ARM_ARCH_7__) || defined(__ARM_ARCH_7A__) || defined(__ARM_ARCH_7R__) || defined(__ARM_ARCH_7M__) || defined(__ARM_ARCH_7S__)
|
||||
# define PSNIP_UNALIGNED_IMPL PSNIP_UNALIGNED_IMPL_DEREF
|
||||
# else
|
||||
# define PSNIP_UNALIGNED_IMPL PSNIP_UNALIGNED_IMPL_MEMCPY
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#if !defined(PSNIP_UNALIGNED_IMPL)
|
||||
# define PSNIP_UNALIGNED_IMPL PSNIP_UNALIGNED_IMPL_MEMCPY
|
||||
#endif
|
||||
|
||||
#if !defined(PSNIP_UNALIGNED_STATIC_INLINE)
|
||||
# if defined(__GNUC__)
|
||||
# define PSNIP_UNALIGNED__COMPILER_ATTRIBUTES __attribute__((__unused__))
|
||||
# else
|
||||
# define PSNIP_UNALIGNED__COMPILER_ATTRIBUTES
|
||||
# endif
|
||||
|
||||
# if defined(HEDLEY_ALWAYS_INLINE)
|
||||
# define PSNIP_UNALIGNED__INLINE HEDLEY_ALWAYS_INLINE
|
||||
# elif defined(__GNUC__) && (__GNUC__ >= 4)
|
||||
# define PSNIP_UNALIGNED__INLINE __attribute__((__always_inline__,__gnu_inline__)) inline
|
||||
# elif defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L
|
||||
# define PSNIP_UNALIGNED__INLINE inline
|
||||
# elif defined(__GNUC_STDC_INLINE__)
|
||||
# define PSNIP_UNALIGNED__INLINE __inline__
|
||||
# elif defined(_MSC_VER) && _MSC_VER >= 1200
|
||||
# define PSNIP_UNALIGNED__INLINE __inline
|
||||
# else
|
||||
# define PSNIP_UNALIGNED__INLINE
|
||||
# endif
|
||||
|
||||
# define PSNIP_UNALIGNED__FUNCTION PSNIP_UNALIGNED__COMPILER_ATTRIBUTES static PSNIP_UNALIGNED__INLINE
|
||||
#endif
|
||||
|
||||
|
||||
#if !defined(PSNIP_UNALIGNED_ALLOW_UBSAN)
|
||||
# if defined(__GNUC__) && ((__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 9))
|
||||
# define PSNIP_UNALIGNED__NO_UBSAN __attribute__((__no_sanitize_undefined__))
|
||||
# elif defined(__clang__) && defined(__has_attribute)
|
||||
# if __has_attribute(no_sanitize)
|
||||
# define PSNIP_UNALIGNED__NO_UBSAN __attribute__((no_sanitize("undefined")))
|
||||
# endif
|
||||
# endif
|
||||
#endif
|
||||
#if !defined(PSNIP_UNALIGNED__NO_UBSAN)
|
||||
# define PSNIP_UNALIGNED__NO_UBSAN
|
||||
#endif
|
||||
|
||||
/* http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.faqs/4972.html */
|
||||
#if defined(__CC_ARM)
|
||||
# define PSNIP_UNALIGNED__PACKED __packed
|
||||
#else
|
||||
# define PSNIP_UNALIGNED__PACKED
|
||||
#endif
|
||||
|
||||
#if PSNIP_UNALIGNED_IMPL == PSNIP_UNALIGNED_IMPL_MEMCPY
|
||||
# include <string.h>
|
||||
# define PSNIP_UNALIGNED_LOAD_DEFINE(name, T) \
|
||||
PSNIP_UNALIGNED__FUNCTION \
|
||||
T name(const void* src) { \
|
||||
T r; \
|
||||
memcpy(&r, (PSNIP_UNALIGNED__PACKED const void*) src, sizeof(T)); \
|
||||
return r; \
|
||||
}
|
||||
# define PSNIP_UNALIGNED_STORE_DEFINE(name, T) \
|
||||
PSNIP_UNALIGNED__FUNCTION \
|
||||
void name(void* dest, T src) { \
|
||||
memcpy((PSNIP_UNALIGNED__PACKED void*) &dest, &src, sizeof(T)); \
|
||||
}
|
||||
#elif PSNIP_UNALIGNED_IMPL == PSNIP_UNALIGNED_IMPL_DEREF
|
||||
# if defined(__cplusplus)
|
||||
# define PSNIP_UNALIGNED_LOAD_DEFINE(name, T) \
|
||||
PSNIP_UNALIGNED__FUNCTION \
|
||||
PSNIP_UNALIGNED__NO_UBSAN \
|
||||
T name(const void* src) { \
|
||||
return *static_cast<PSNIP_UNALIGNED__PACKED const T*>(src); \
|
||||
}
|
||||
# define PSNIP_UNALIGNED_STORE_DEFINE(name, T) \
|
||||
PSNIP_UNALIGNED__FUNCTION \
|
||||
PSNIP_UNALIGNED__NO_UBSAN \
|
||||
void name(void* dest, T src) { \
|
||||
*(static_cast<PSNIP_UNALIGNED__PACKED T*>(dest)) = src; \
|
||||
}
|
||||
# else
|
||||
# define PSNIP_UNALIGNED_LOAD_DEFINE(name, T) \
|
||||
PSNIP_UNALIGNED__FUNCTION \
|
||||
PSNIP_UNALIGNED__NO_UBSAN \
|
||||
T name(const void* src) { \
|
||||
return *((PSNIP_UNALIGNED__PACKED T*) src); \
|
||||
}
|
||||
# define PSNIP_UNALIGNED_STORE_DEFINE(name, T) \
|
||||
PSNIP_UNALIGNED__FUNCTION \
|
||||
PSNIP_UNALIGNED__NO_UBSAN \
|
||||
void name(void* dest, T src) { \
|
||||
*((PSNIP_UNALIGNED__PACKED T*) dest) = src; \
|
||||
}
|
||||
# endif
|
||||
#elif PSNIP_UNALIGNED_IMPL == PSNIP_UNALIGNED_IMPL_UNION
|
||||
# if defined(_MSC_VER) || (defined(__INTEL_COMPILER) && defined(WIN32))
|
||||
# define PSNIP_UNALIGNED__UNION_T(T) \
|
||||
__pragma(pack(push, 1)) \
|
||||
union { psnip_int64_t v; char a[sizeof(psnip_int64_t)]; } \
|
||||
__pragma(pack(pop))
|
||||
# else
|
||||
# define PSNIP_UNALIGNED__UNION_T(T) \
|
||||
union { psnip_int64_t v; char a[sizeof(psnip_int64_t)]; } \
|
||||
__attribute__((packed))
|
||||
# endif
|
||||
# define PSNIP_UNALIGNED_LOAD_DEFINE(name, T) \
|
||||
PSNIP_UNALIGNED__FUNCTION \
|
||||
T name(const void* src) { \
|
||||
return ((PSNIP_UNALIGNED__UNION_T(T) *) src)->v; \
|
||||
}
|
||||
# define PSNIP_UNALIGNED_STORE_DEFINE(name, T) \
|
||||
PSNIP_UNALIGNED__FUNCTION \
|
||||
void name(void* dest, T src) { \
|
||||
((PSNIP_UNALIGNED__UNION_T(T) *) dest)->v = src; \
|
||||
}
|
||||
#endif
|
||||
|
||||
/* If we've already included exact-int.h (or defined the relevant
|
||||
types), we'll set up functions for those types */
|
||||
|
||||
#if defined(psnip_int16_t)
|
||||
PSNIP_UNALIGNED_LOAD_DEFINE(psnip_unaligned_load_int16, psnip_int16_t)
|
||||
PSNIP_UNALIGNED_STORE_DEFINE(psnip_unaligned_store_int16, psnip_int16_t)
|
||||
#endif
|
||||
#if defined(psnip_uint16_t)
|
||||
PSNIP_UNALIGNED_LOAD_DEFINE(psnip_unaligned_load_uint16, psnip_uint16_t)
|
||||
PSNIP_UNALIGNED_STORE_DEFINE(psnip_unaligned_store_uint16, psnip_uint16_t)
|
||||
#endif
|
||||
#if defined(psnip_int32_t)
|
||||
PSNIP_UNALIGNED_LOAD_DEFINE(psnip_unaligned_load_int32, psnip_int32_t)
|
||||
PSNIP_UNALIGNED_STORE_DEFINE(psnip_unaligned_store_int32, psnip_int32_t)
|
||||
#endif
|
||||
#if defined(psnip_uint32_t)
|
||||
PSNIP_UNALIGNED_LOAD_DEFINE(psnip_unaligned_load_uint32, psnip_uint32_t)
|
||||
PSNIP_UNALIGNED_STORE_DEFINE(psnip_unaligned_store_uint32, psnip_uint32_t)
|
||||
#endif
|
||||
#if defined(psnip_int64_t)
|
||||
PSNIP_UNALIGNED_LOAD_DEFINE(psnip_unaligned_load_int64, psnip_int64_t)
|
||||
PSNIP_UNALIGNED_STORE_DEFINE(psnip_unaligned_store_int64, psnip_int64_t)
|
||||
#endif
|
||||
#if defined(psnip_uint64_t)
|
||||
PSNIP_UNALIGNED_LOAD_DEFINE(psnip_unaligned_load_uint64, psnip_uint64_t)
|
||||
PSNIP_UNALIGNED_STORE_DEFINE(psnip_unaligned_store_uint64, psnip_uint64_t)
|
||||
#endif
|
||||
|
||||
/* And, if endian.h has been included, we can also define functions to
|
||||
load different-endian data from unaligned addresses… */
|
||||
|
||||
#if defined(PSNIP_ENDIAN_H)
|
||||
# psnip_unaligned_load_int16le(src) psnip_endian_le16(psnip_unaligned_load_int16(src))
|
||||
# psnip_unaligned_load_int32le(src) psnip_endian_le32(psnip_unaligned_load_int32(src))
|
||||
# psnip_unaligned_load_int64le(src) psnip_endian_le64(psnip_unaligned_load_int64(src))
|
||||
# psnip_unaligned_load_int16be(src) psnip_endian_be16(psnip_unaligned_load_int16(src))
|
||||
# psnip_unaligned_load_int32be(src) psnip_endian_be32(psnip_unaligned_load_int32(src))
|
||||
# psnip_unaligned_load_int64be(src) psnip_endian_be64(psnip_unaligned_load_int64(src))
|
||||
# psnip_unaligned_load_uint16le(src) psnip_endian_le16(psnip_unaligned_load_uint16(src))
|
||||
# psnip_unaligned_load_uint32le(src) psnip_endian_le32(psnip_unaligned_load_uint32(src))
|
||||
# psnip_unaligned_load_uint64le(src) psnip_endian_le64(psnip_unaligned_load_uint64(src))
|
||||
# psnip_unaligned_load_uint16be(src) psnip_endian_be16(psnip_unaligned_load_uint16(src))
|
||||
# psnip_unaligned_load_uint32be(src) psnip_endian_be32(psnip_unaligned_load_uint32(src))
|
||||
# psnip_unaligned_load_uint64be(src) psnip_endian_be64(psnip_unaligned_load_uint64(src))
|
||||
# psnip_unaligned_store_int16le(dest, src) psnip_unaligned_store_int16(dest, (psnip_int16_t) psnip_endian_le16(src))
|
||||
# psnip_unaligned_store_int32le(dest, src) psnip_unaligned_store_int32(dest, (psnip_int32_t) psnip_endian_le32(src))
|
||||
# psnip_unaligned_store_int64le(dest, src) psnip_unaligned_store_int64(dest, (psnip_int64_t) psnip_endian_le64(src))
|
||||
# psnip_unaligned_store_int16be(dest, src) psnip_unaligned_store_int16(dest, (psnip_int16_t) psnip_endian_be16(src))
|
||||
# psnip_unaligned_store_int32be(dest, src) psnip_unaligned_store_int32(dest, (psnip_int32_t) psnip_endian_be32(src))
|
||||
# psnip_unaligned_store_int64be(dest, src) psnip_unaligned_store_int64(dest, (psnip_int64_t) psnip_endian_be64(src))
|
||||
# psnip_unaligned_store_uint16le(dest, src) psnip_unaligned_store_uint16(dest, (psnip_uint16_t) psnip_endian_le16(src))
|
||||
# psnip_unaligned_store_uint32le(dest, src) psnip_unaligned_store_uint32(dest, (psnip_uint32_t) psnip_endian_le32(src))
|
||||
# psnip_unaligned_store_uint64le(dest, src) psnip_unaligned_store_uint64(dest, (psnip_uint64_t) psnip_endian_le64(src))
|
||||
# psnip_unaligned_store_uint16be(dest, src) psnip_unaligned_store_uint16(dest, (psnip_uint16_t) psnip_endian_be16(src))
|
||||
# psnip_unaligned_store_uint32be(dest, src) psnip_unaligned_store_uint32(dest, (psnip_uint32_t) psnip_endian_be32(src))
|
||||
# psnip_unaligned_store_uint64be(dest, src) psnip_unaligned_store_uint64(dest, (psnip_uint64_t) psnip_endian_be64(src))
|
||||
#endif
|
||||
|
||||
#endif /* PSNIP_UNALIGNED_H */
|
||||
Loading…
Add table
Add a link
Reference in a new issue