mirror of
https://github.com/xmrig/xmrig.git
synced 2025-12-07 07:55:04 -05:00
Compare commits
238 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a3297b9ea4 | ||
|
|
b46f376f32 | ||
|
|
f02b98efe7 | ||
|
|
7d4bdfc913 | ||
|
|
1964e4f370 | ||
|
|
14cd81a7a1 | ||
|
|
1123c20da0 | ||
|
|
fc810dc87b | ||
|
|
8729616698 | ||
|
|
b43d986537 | ||
|
|
04d3dd6df1 | ||
|
|
603a9c4c6e | ||
|
|
914fdd5f0a | ||
|
|
08f6c222ca | ||
|
|
3ead4eba89 | ||
|
|
af51513614 | ||
|
|
4cf3bb9930 | ||
|
|
3a7bb24b40 | ||
|
|
729ee08631 | ||
|
|
80b0ac2492 | ||
|
|
e9a16912c3 | ||
|
|
4928b6d3e3 | ||
|
|
d0db4770ed | ||
|
|
38e93ed6e3 | ||
|
|
d52aa5a72b | ||
|
|
3d10636a8f | ||
|
|
5591666069 | ||
|
|
fd98dc236a | ||
|
|
325e116624 | ||
|
|
7798f09dc7 | ||
|
|
8e08df2fd2 | ||
|
|
9e9cddedc5 | ||
|
|
1651b041de | ||
|
|
30dd7d6fe4 | ||
|
|
71f06530df | ||
|
|
5601c7a672 | ||
|
|
35c2a729ec | ||
|
|
850e355049 | ||
|
|
6f89c51db5 | ||
|
|
6bf1ef0170 | ||
|
|
4e039a9bce | ||
|
|
7b44fa3737 | ||
|
|
f96e9d5ab7 | ||
|
|
f041571674 | ||
|
|
bb4aeed874 | ||
|
|
076a69907c | ||
|
|
fa5e326d5e | ||
|
|
55bfab95f9 | ||
|
|
fbaae0f080 | ||
|
|
d53a47b12f | ||
|
|
e3e52f6d06 | ||
|
|
b5897b336a | ||
|
|
60224ccd23 | ||
|
|
168b1aac2f | ||
|
|
fc1d6c7e84 | ||
|
|
e3dd4a6581 | ||
|
|
9cb7d727c2 | ||
|
|
e049b80f1a | ||
|
|
beb9af4313 | ||
|
|
8bba0df054 | ||
|
|
27f02d5f9f | ||
|
|
79ffb95f05 | ||
|
|
1b0ddae4eb | ||
|
|
ad0d876b18 | ||
|
|
2f371e884e | ||
|
|
f05a328474 | ||
|
|
c40f212e23 | ||
|
|
61859dfe14 | ||
|
|
eb140fd30f | ||
|
|
a07b0e5953 | ||
|
|
9975b4e4cd | ||
|
|
5ad1a48489 | ||
|
|
62681adcfb | ||
|
|
1720d3e096 | ||
|
|
92d787c817 | ||
|
|
816fc3ee43 | ||
|
|
7004a51ce6 | ||
|
|
3cc18d30de | ||
|
|
bd3665e111 | ||
|
|
a680220d28 | ||
|
|
2d1fdec618 | ||
|
|
b1a2215829 | ||
|
|
eb5f7c6a7b | ||
|
|
1bc23354d3 | ||
|
|
e6a72b2f78 | ||
|
|
5bed17a8af | ||
|
|
7b21749a19 | ||
|
|
0b5587fd6a | ||
|
|
776f77a8d4 | ||
|
|
583f45e2da | ||
|
|
9b474f239f | ||
|
|
9665ff15ae | ||
|
|
b6bf6d9bc9 | ||
|
|
3d9be9484d | ||
|
|
35fd43a6b4 | ||
|
|
294453fdc1 | ||
|
|
30a7f9f7f5 | ||
|
|
8f38462bbe | ||
|
|
ebf54c6d04 | ||
|
|
d7659b5093 | ||
|
|
e00c568ae9 | ||
|
|
a3988374f0 | ||
|
|
9732636155 | ||
|
|
986aee4297 | ||
|
|
66d3e96a1a | ||
|
|
9f4e1ee373 | ||
|
|
ff0c6b6365 | ||
|
|
7397efaf6d | ||
|
|
aadc15ce66 | ||
|
|
ad7c925a1a | ||
|
|
57be6f94bb | ||
|
|
35b188762c | ||
|
|
7c6e429854 | ||
|
|
c15aefd968 | ||
|
|
4a712354f1 | ||
|
|
4545c84a11 | ||
|
|
a66297bed8 | ||
|
|
f4dadfd90b | ||
|
|
955134b162 | ||
|
|
68795137da | ||
|
|
6ed2d61586 | ||
|
|
a96782218f | ||
|
|
32e7041def | ||
|
|
c16388ade3 | ||
|
|
72569a7fc7 | ||
|
|
751be470b8 | ||
|
|
7937c814ff | ||
|
|
8e42fb9138 | ||
|
|
dbc6f26c91 | ||
|
|
074db6bb72 | ||
|
|
71522214ae | ||
|
|
8ec58a8394 | ||
|
|
263634f585 | ||
|
|
a383eba8df | ||
|
|
152b65b67c | ||
|
|
970b5d1964 | ||
|
|
7536663caf | ||
|
|
7e17f77c11 | ||
|
|
25faeabd61 | ||
|
|
bd8776b7ee | ||
|
|
b2d26eb019 | ||
|
|
14c6f8699e | ||
|
|
c0dcfc2a97 | ||
|
|
f36b5eeaad | ||
|
|
952017ae7a | ||
|
|
faf793b0aa | ||
|
|
e97cd98f90 | ||
|
|
95002ead7d | ||
|
|
c1b3802590 | ||
|
|
1bfbc97c7d | ||
|
|
052290d0e9 | ||
|
|
4f512c41d4 | ||
|
|
91ed7e36cd | ||
|
|
77d9beaf89 | ||
|
|
a791bc113e | ||
|
|
9bfa49b7d0 | ||
|
|
ed0972da85 | ||
|
|
815f8cbb96 | ||
|
|
ccc7fba2c4 | ||
|
|
bf56ee00bc | ||
|
|
0d4b908bfe | ||
|
|
8bd2582416 | ||
|
|
09e859d41e | ||
|
|
6fd4d99fa1 | ||
|
|
b8089e637a | ||
|
|
fed163568e | ||
|
|
4e4c54314b | ||
|
|
e759ddca49 | ||
|
|
fcb7b0fb3e | ||
|
|
d1bf9ddc3f | ||
|
|
ccc2d77592 | ||
|
|
70b0a39dc8 | ||
|
|
b34084b961 | ||
|
|
1587fb27d2 | ||
|
|
faf14f5e5a | ||
|
|
555eee8236 | ||
|
|
1bf428f8da | ||
|
|
c86f9816d3 | ||
|
|
599117abde | ||
|
|
e3689ccb1a | ||
|
|
babc48f767 | ||
|
|
33d752bcaa | ||
|
|
5af169fd7b | ||
|
|
8ebb659cd6 | ||
|
|
7c8a9677a1 | ||
|
|
981e043ada | ||
|
|
8c2951db2d | ||
|
|
2d08f59184 | ||
|
|
827e611911 | ||
|
|
de2c351a66 | ||
|
|
42bf85d10b | ||
|
|
9580c30d8a | ||
|
|
3df545cfc5 | ||
|
|
a370b8fd30 | ||
|
|
6774f86fcd | ||
|
|
a0a8711dab | ||
|
|
3ad11685cc | ||
|
|
bcef4b12ec | ||
|
|
f9c244f0aa | ||
|
|
29aa466023 | ||
|
|
b772349f69 | ||
|
|
c5fbc1a182 | ||
|
|
30642881bf | ||
|
|
ef3af1c4fd | ||
|
|
04c5d6d00a | ||
|
|
8b83a5fe2e | ||
|
|
878e021ff6 | ||
|
|
5a606be8be | ||
|
|
da02e9a3a2 | ||
|
|
b11f95d248 | ||
|
|
9797f49456 | ||
|
|
0556fd664c | ||
|
|
1cf5ad5212 | ||
|
|
c31ea00399 | ||
|
|
387524e1c5 | ||
|
|
5f1f901649 | ||
|
|
c29dc8bcf4 | ||
|
|
b8cc1136a4 | ||
|
|
4c06d8b080 | ||
|
|
1ecee56eb6 | ||
|
|
26b8206332 | ||
|
|
7deee3240b | ||
|
|
9dc02fc7f3 | ||
|
|
6551818610 | ||
|
|
668b23c5b0 | ||
|
|
7741c341c7 | ||
|
|
8a70202a98 | ||
|
|
bc2b7d1895 | ||
|
|
ebb0f81f2f | ||
|
|
eb3e2b8868 | ||
|
|
583d892eb5 | ||
|
|
b145f14ad8 | ||
|
|
ce19edf36c | ||
|
|
108fd5690e | ||
|
|
c19fe3cea7 | ||
|
|
187c7680cc | ||
|
|
20061e1b8b | ||
|
|
2baccab0f9 |
1
.gitignore
vendored
1
.gitignore
vendored
@@ -1 +1,2 @@
|
||||
/build
|
||||
/CMakeLists.txt.user
|
||||
|
||||
79
CHANGELOG.md
79
CHANGELOG.md
@@ -1,3 +1,82 @@
|
||||
# v2.4.0
|
||||
- Added [HTTP API](https://github.com/xmrig/xmrig/wiki/API).
|
||||
- Added comments support in config file.
|
||||
- libjansson replaced to rapidjson.
|
||||
- [#98](https://github.com/xmrig/xmrig/issues/98) Ignore `keepalive` option with minergate.com and nicehash.com.
|
||||
- [#101](https://github.com/xmrig/xmrig/issues/101) Fixed MSVC 2017 (15.3) compile time version detection.
|
||||
- [#108](https://github.com/xmrig/xmrig/issues/108) Silently ignore invalid values for `donate-level` option.
|
||||
- [#111](https://github.com/xmrig/xmrig/issues/111) Fixed build without AEON support.
|
||||
|
||||
# v2.3.1
|
||||
- [#68](https://github.com/xmrig/xmrig/issues/68) Fixed compatibility with Docker containers, was nothing print on console.
|
||||
|
||||
# v2.3.0
|
||||
- Added `--cpu-priority` option (0 idle, 2 normal to 5 highest).
|
||||
- Added `--user-agent` option, to set custom user-agent string for pool. For example `cpuminer-multi/0.1`.
|
||||
- Added `--no-huge-pages` option, to disable huge pages support.
|
||||
- [#62](https://github.com/xmrig/xmrig/issues/62) Don't send the login to the dev pool.
|
||||
- Force reconnect if pool block miner IP address. helps switch to backup pool.
|
||||
- Fixed: failed open default config file if path contains non English characters.
|
||||
- Fixed: error occurred if try use unavailable stdin or stdout, regression since version 2.2.0.
|
||||
- Fixed: message about huge pages support successfully enabled on Windows was not shown in release builds.
|
||||
|
||||
# v2.2.1
|
||||
- Fixed [terminal issues](https://github.com/xmrig/xmrig-proxy/issues/2#issuecomment-319914085) after exit on Linux and OS X.
|
||||
|
||||
# v2.2.0
|
||||
- [#46](https://github.com/xmrig/xmrig/issues/46) Restored config file support. Now possible use multiple config files and combine with command line options also added support for default config.
|
||||
- Improved colors support on Windows, now used uv_tty, legacy code removed.
|
||||
- QuickEdit Mode now disabled on Windows.
|
||||
- Added interactive commands in console window:: **h**ashrate, **p**ause, **r**esume.
|
||||
- Fixed autoconf mode for AMD FX CPUs.
|
||||
|
||||
# v2.1.0
|
||||
- [#40](https://github.com/xmrig/xmrig/issues/40)
|
||||
Improved miner shutdown, fixed crash on exit for Linux and OS X.
|
||||
- Fixed, login request was contain malformed JSON if username or password has some special characters for example `\`.
|
||||
- [#220](https://github.com/fireice-uk/xmr-stak-cpu/pull/220) Better support for Round Robin DNS, IP address now always chosen randomly instead of stuck on first one.
|
||||
- Changed donation address, new [xmrig-proxy](https://github.com/xmrig/xmrig-proxy) is coming soon.
|
||||
|
||||
# v2.0.2
|
||||
- Better deal with possible duplicate jobs from pool, show warning and ignore duplicates.
|
||||
- For Windows builds libuv updated to version 1.13.1 and gcc to 7.1.0.
|
||||
|
||||
# v2.0.1
|
||||
- [#27](https://github.com/xmrig/xmrig/issues/27) Fixed possibility crash on 32bit systems.
|
||||
|
||||
# v2.0.0
|
||||
- Option `--backup-url` removed, instead now possibility specify multiple pools for example: `-o example1.com:3333 -u user1 -p password1 -k -o example2.com:5555 -u user2 -o example3.com:4444 -u user3`
|
||||
- [#15](https://github.com/xmrig/xmrig/issues/15) Added option `-l, --log-file=FILE` to write log to file.
|
||||
- [#15](https://github.com/xmrig/xmrig/issues/15) Added option `-S, --syslog` to use syslog for logging, Linux only.
|
||||
- [#18](https://github.com/xmrig/xmrig/issues/18) Added nice messages for accepted/rejected shares with diff and network latency.
|
||||
- [#20](https://github.com/xmrig/xmrig/issues/20) Fixed `--cpu-affinity` for more than 32 threads.
|
||||
- Fixed Windows XP support.
|
||||
- Fixed regression, option `--no-color` was not fully disable colored output.
|
||||
- Show resolved pool IP address in miner output.
|
||||
|
||||
# v1.0.1
|
||||
- Fix broken software AES implementation, app has crashed if CPU not support AES-NI, only version 1.0.0 affected.
|
||||
|
||||
# v1.0.0
|
||||
- Miner complete rewritten in C++ with libuv.
|
||||
- This version should be fully compatible (except config file) with previos versions, many new nice features will come in next versions.
|
||||
- This is still beta. If you found regression, stability or perfomance issues or have an idea for new feature please fell free to open new [issue](https://github.com/xmrig/xmrig/issues/new).
|
||||
- Added new option `--print-time=N`, print hashrate report every N seconds.
|
||||
- New hashrate reports, by default every 60 secons.
|
||||
- Added Microsoft Visual C++ 2015 and 2017 support.
|
||||
- Removed dependency on libcurl.
|
||||
- To compile this version from source please switch to [dev](https://github.com/xmrig/xmrig/tree/dev) branch.
|
||||
|
||||
# v0.8.2
|
||||
- Fixed L2 cache size detection for AMD CPUs (Bulldozer/Piledriver/Steamroller/Excavator architecture).
|
||||
|
||||
# v0.8.2
|
||||
- Fixed L2 cache size detection for AMD CPUs (Bulldozer/Piledriver/Steamroller/Excavator architecture).
|
||||
- Fixed gcc 7.1 support.
|
||||
|
||||
# v0.8.1
|
||||
- Added nicehash support, detects automaticaly by pool URL, for example `cryptonight.eu.nicehash.com:3355` or manually via option `--nicehash`.
|
||||
|
||||
# v0.8.0
|
||||
- Added double hash mode, also known as lower power mode. `--av=2` and `--av=4`.
|
||||
- Added smart automatic CPU configuration. Default threads count now depends on size of the L3 cache of CPU.
|
||||
|
||||
287
CMakeLists.txt
287
CMakeLists.txt
@@ -1,139 +1,236 @@
|
||||
cmake_minimum_required(VERSION 3.0)
|
||||
project(xmrig C)
|
||||
project(xmrig)
|
||||
|
||||
option(WITH_LIBCPUID "Use Libcpuid" ON)
|
||||
option(WITH_AEON "CryptoNight-Lite support" ON)
|
||||
option(WITH_HTTPD "HTTP REST API" ON)
|
||||
|
||||
include (CheckIncludeFile)
|
||||
|
||||
|
||||
set(HEADERS
|
||||
compat.h
|
||||
algo/cryptonight/cryptonight.h
|
||||
algo/cryptonight/cryptonight_aesni.h
|
||||
algo/cryptonight/cryptonight_softaes.h
|
||||
elist.h
|
||||
xmrig.h
|
||||
version.h
|
||||
options.h
|
||||
cpu.h
|
||||
persistent_memory.h
|
||||
stratum.h
|
||||
stats.h
|
||||
util.h
|
||||
donate.h
|
||||
src/3rdparty/align.h
|
||||
src/api/Api.h
|
||||
src/api/ApiState.h
|
||||
src/api/NetworkState.h
|
||||
src/App.h
|
||||
src/Console.h
|
||||
src/Cpu.h
|
||||
src/interfaces/IClientListener.h
|
||||
src/interfaces/IConsoleListener.h
|
||||
src/interfaces/IJobResultListener.h
|
||||
src/interfaces/ILogBackend.h
|
||||
src/interfaces/IStrategy.h
|
||||
src/interfaces/IStrategyListener.h
|
||||
src/interfaces/IWorker.h
|
||||
src/log/ConsoleLog.h
|
||||
src/log/FileLog.h
|
||||
src/log/Log.h
|
||||
src/Mem.h
|
||||
src/net/Client.h
|
||||
src/net/Job.h
|
||||
src/net/JobId.h
|
||||
src/net/JobResult.h
|
||||
src/net/Network.h
|
||||
src/net/strategies/DonateStrategy.h
|
||||
src/net/strategies/FailoverStrategy.h
|
||||
src/net/strategies/SinglePoolStrategy.h
|
||||
src/net/SubmitResult.h
|
||||
src/net/Url.h
|
||||
src/Options.h
|
||||
src/Platform.h
|
||||
src/Summary.h
|
||||
src/version.h
|
||||
src/workers/DoubleWorker.h
|
||||
src/workers/Handle.h
|
||||
src/workers/Hashrate.h
|
||||
src/workers/SingleWorker.h
|
||||
src/workers/Worker.h
|
||||
src/workers/Workers.h
|
||||
)
|
||||
|
||||
set(HEADERS_CRYPTO
|
||||
crypto/c_groestl.h
|
||||
crypto/c_blake256.h
|
||||
crypto/c_jh.h
|
||||
crypto/c_skein.h
|
||||
)
|
||||
|
||||
set(HEADERS_COMPAT
|
||||
compat/winansi.h
|
||||
)
|
||||
|
||||
set(HEADERS_UTILS
|
||||
utils/applog.h
|
||||
utils/threads.h
|
||||
utils/summary.h
|
||||
src/crypto/c_blake256.h
|
||||
src/crypto/c_groestl.h
|
||||
src/crypto/c_jh.h
|
||||
src/crypto/c_keccak.h
|
||||
src/crypto/c_skein.h
|
||||
src/crypto/CryptoNight.h
|
||||
src/crypto/CryptoNight_p.h
|
||||
src/crypto/CryptoNight_test.h
|
||||
src/crypto/groestl_tables.h
|
||||
src/crypto/hash.h
|
||||
src/crypto/skein_port.h
|
||||
)
|
||||
|
||||
set(SOURCES
|
||||
xmrig.c
|
||||
algo/cryptonight/cryptonight.c
|
||||
algo/cryptonight/cryptonight_av1_aesni.c
|
||||
algo/cryptonight/cryptonight_av2_aesni_double.c
|
||||
algo/cryptonight/cryptonight_av3_softaes.c
|
||||
algo/cryptonight/cryptonight_av4_softaes_double.c
|
||||
util.c
|
||||
options.c
|
||||
stratum.c
|
||||
stats.c
|
||||
memory.c
|
||||
src/api/Api.cpp
|
||||
src/api/ApiState.cpp
|
||||
src/api/NetworkState.cpp
|
||||
src/App.cpp
|
||||
src/Console.cpp
|
||||
src/log/ConsoleLog.cpp
|
||||
src/log/FileLog.cpp
|
||||
src/log/Log.cpp
|
||||
src/Mem.cpp
|
||||
src/net/Client.cpp
|
||||
src/net/Job.cpp
|
||||
src/net/Network.cpp
|
||||
src/net/strategies/DonateStrategy.cpp
|
||||
src/net/strategies/FailoverStrategy.cpp
|
||||
src/net/strategies/SinglePoolStrategy.cpp
|
||||
src/net/SubmitResult.cpp
|
||||
src/net/Url.cpp
|
||||
src/Options.cpp
|
||||
src/Platform.cpp
|
||||
src/Summary.cpp
|
||||
src/workers/DoubleWorker.cpp
|
||||
src/workers/Handle.cpp
|
||||
src/workers/Hashrate.cpp
|
||||
src/workers/SingleWorker.cpp
|
||||
src/workers/Worker.cpp
|
||||
src/workers/Workers.cpp
|
||||
src/xmrig.cpp
|
||||
)
|
||||
|
||||
set(SOURCES_CRYPTO
|
||||
crypto/c_keccak.c
|
||||
crypto/c_groestl.c
|
||||
crypto/c_blake256.c
|
||||
crypto/c_jh.c
|
||||
crypto/c_skein.c
|
||||
crypto/soft_aes.c
|
||||
)
|
||||
|
||||
set(SOURCES_UTILS
|
||||
utils/applog.c
|
||||
utils/summary.c
|
||||
src/crypto/c_keccak.c
|
||||
src/crypto/c_groestl.c
|
||||
src/crypto/c_blake256.c
|
||||
src/crypto/c_jh.c
|
||||
src/crypto/c_skein.c
|
||||
src/crypto/soft_aes.c
|
||||
src/crypto/soft_aes.c
|
||||
src/crypto/CryptoNight.cpp
|
||||
)
|
||||
|
||||
if (WIN32)
|
||||
set(SOURCES_OS win/cpu_win.c win/memory_win.c win/xmrig_win.c win/app.rc compat/winansi.c)
|
||||
set(EXTRA_LIBS ws2_32)
|
||||
add_definitions(/D_WIN32_WINNT=0x600)
|
||||
set(SOURCES_OS
|
||||
res/app.rc
|
||||
src/App_win.cpp
|
||||
src/Cpu_win.cpp
|
||||
src/Mem_win.cpp
|
||||
src/Platform_win.cpp
|
||||
)
|
||||
|
||||
add_definitions(/DWIN32)
|
||||
set(EXTRA_LIBS ws2_32 psapi iphlpapi userenv)
|
||||
elseif (APPLE)
|
||||
set(SOURCES_OS
|
||||
src/App_unix.cpp
|
||||
src/Cpu_mac.cpp
|
||||
src/Mem_unix.cpp
|
||||
src/Platform_mac.cpp
|
||||
)
|
||||
else()
|
||||
set(SOURCES_OS unix/cpu_unix.c unix/memory_unix.c unix/xmrig_unix.c)
|
||||
set(SOURCES_OS
|
||||
src/App_unix.cpp
|
||||
src/Cpu_unix.cpp
|
||||
src/Mem_unix.cpp
|
||||
src/Platform_unix.cpp
|
||||
)
|
||||
|
||||
set(EXTRA_LIBS pthread)
|
||||
endif()
|
||||
|
||||
include_directories(.)
|
||||
add_definitions(/DUSE_NATIVE_THREADS)
|
||||
add_definitions(/D_GNU_SOURCE)
|
||||
add_definitions(/D__STDC_FORMAT_MACROS)
|
||||
add_definitions(/DUNICODE)
|
||||
add_definitions(/DRAPIDJSON_SSE2)
|
||||
#add_definitions(/DAPP_DEBUG)
|
||||
|
||||
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/cmake")
|
||||
|
||||
find_package(UV REQUIRED)
|
||||
|
||||
if ("${CMAKE_BUILD_TYPE}" STREQUAL "")
|
||||
set(CMAKE_BUILD_TYPE Release)
|
||||
endif()
|
||||
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -maes -Wno-pointer-to-int-cast")
|
||||
set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -Ofast -funroll-loops -fvariable-expansion-in-unroller -ftree-loop-if-convert-stores -fmerge-all-constants -fbranch-target-load-optimize2")
|
||||
#set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -gdwarf-2")
|
||||
#set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -fprofile-generate")
|
||||
#set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -fprofile-use -fprofile-correction")
|
||||
|
||||
if (WIN32)
|
||||
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -static")
|
||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||
set(CMAKE_CXX_EXTENSIONS OFF)
|
||||
set(CMAKE_CXX_STANDARD 11)
|
||||
|
||||
|
||||
# https://cmake.org/cmake/help/latest/variable/CMAKE_LANG_COMPILER_ID.html
|
||||
if (CMAKE_CXX_COMPILER_ID MATCHES GNU)
|
||||
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -maes -Wall -Wno-strict-aliasing")
|
||||
set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -Ofast -funroll-loops -fvariable-expansion-in-unroller -ftree-loop-if-convert-stores -fmerge-all-constants -fbranch-target-load-optimize2")
|
||||
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -maes -Wall -fno-exceptions -fno-rtti")
|
||||
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -Ofast -s -funroll-loops -fvariable-expansion-in-unroller -ftree-loop-if-convert-stores -fmerge-all-constants -fbranch-target-load-optimize2")
|
||||
|
||||
if (WIN32)
|
||||
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -static")
|
||||
else()
|
||||
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -static-libgcc -static-libstdc++")
|
||||
endif()
|
||||
|
||||
add_definitions(/D_GNU_SOURCE)
|
||||
|
||||
if (${CMAKE_VERSION} VERSION_LESS "3.1.0")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
|
||||
endif()
|
||||
|
||||
#set(CMAKE_C_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -gdwarf-2")
|
||||
|
||||
elseif (CMAKE_CXX_COMPILER_ID MATCHES MSVC)
|
||||
|
||||
set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} /Ox /Ot /Oi /MT /GL")
|
||||
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} /Ox /Ot /Oi /MT /GL")
|
||||
add_definitions(/D_CRT_SECURE_NO_WARNINGS)
|
||||
add_definitions(/D_CRT_NONSTDC_NO_WARNINGS)
|
||||
add_definitions(/DNOMINMAX)
|
||||
|
||||
elseif (CMAKE_CXX_COMPILER_ID MATCHES Clang)
|
||||
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -maes -Wall")
|
||||
set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -Ofast -funroll-loops -fmerge-all-constants")
|
||||
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -maes -Wall -fno-exceptions -fno-rtti -Wno-missing-braces")
|
||||
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -Ofast -funroll-loops -fmerge-all-constants")
|
||||
|
||||
endif()
|
||||
|
||||
include_directories(compat/jansson)
|
||||
add_subdirectory(compat/jansson)
|
||||
|
||||
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/cmake/")
|
||||
|
||||
find_package(CURL REQUIRED)
|
||||
include_directories(${CURL_INCLUDE_DIRS})
|
||||
add_definitions(/DCURL_STATICLIB)
|
||||
link_directories(${CURL_LIBRARIES})
|
||||
|
||||
if (WITH_LIBCPUID)
|
||||
add_subdirectory(compat/libcpuid)
|
||||
add_subdirectory(src/3rdparty/libcpuid)
|
||||
|
||||
include_directories(compat/libcpuid)
|
||||
include_directories(src/3rdparty/libcpuid)
|
||||
set(CPUID_LIB cpuid)
|
||||
set(SOURCES_CPUID cpu.c)
|
||||
set(SOURCES_CPUID src/Cpu.cpp)
|
||||
else()
|
||||
add_definitions(/DXMRIG_NO_LIBCPUID)
|
||||
set(SOURCES_CPUID cpu_stub.c)
|
||||
set(SOURCES_CPUID src/Cpu_stub.cpp)
|
||||
endif()
|
||||
|
||||
if (WITH_AEON)
|
||||
set(SOURCES_AEON
|
||||
algo/cryptonight-lite/cryptonight_lite_av1_aesni.c
|
||||
algo/cryptonight-lite/cryptonight_lite_av2_aesni_double.c
|
||||
algo/cryptonight-lite/cryptonight_lite_av3_softaes.c
|
||||
algo/cryptonight-lite/cryptonight_lite_av4_softaes_double.c
|
||||
algo/cryptonight-lite/cryptonight_lite_aesni.h
|
||||
algo/cryptonight-lite/cryptonight_lite_softaes.h
|
||||
)
|
||||
else()
|
||||
CHECK_INCLUDE_FILE (syslog.h HAVE_SYSLOG_H)
|
||||
if (HAVE_SYSLOG_H)
|
||||
add_definitions(/DHAVE_SYSLOG_H)
|
||||
set(SOURCES_SYSLOG src/log/SysLog.h src/log/SysLog.cpp)
|
||||
endif()
|
||||
|
||||
if (NOT WITH_AEON)
|
||||
add_definitions(/DXMRIG_NO_AEON)
|
||||
endif()
|
||||
|
||||
if (CMAKE_SIZEOF_VOID_P EQUAL 8)
|
||||
add_executable(xmrig ${HEADERS} ${HEADERS_CRYPTO} ${SOURCES} ${SOURCES_CRYPTO} ${HEADERS_UTILS} ${SOURCES_UTILS} ${HEADERS_COMPAT} ${SOURCES_COMPAT} ${SOURCES_OS} ${SOURCES_CPUID} ${SOURCES_AEON})
|
||||
target_link_libraries(xmrig jansson curl ${CPUID_LIB} ${EXTRA_LIBS})
|
||||
if (WITH_HTTPD)
|
||||
find_package(MHD)
|
||||
|
||||
if (MHD_FOUND)
|
||||
include_directories(${MHD_INCLUDE_DIRS})
|
||||
set(HTTPD_SOURCES src/api/Httpd.h src/api/Httpd.cpp)
|
||||
else()
|
||||
message(FATAL_ERROR "microhttpd NOT found: use `-DWITH_HTTPD=OFF` to build without http deamon support")
|
||||
endif()
|
||||
else()
|
||||
add_executable(xmrig32 ${HEADERS} ${HEADERS_CRYPTO} ${SOURCES} ${SOURCES_CRYPTO} ${HEADERS_UTILS} ${SOURCES_UTILS} ${HEADERS_COMPAT} ${SOURCES_COMPAT} ${SOURCES_OS} ${SOURCES_CPUID} ${SOURCES_AEON})
|
||||
target_link_libraries(xmrig32 jansson curl ${CPUID_LIB} ${EXTRA_LIBS})
|
||||
add_definitions(/DXMRIG_NO_HTTPD)
|
||||
add_definitions(/DXMRIG_NO_API)
|
||||
endif()
|
||||
|
||||
source_group("HEADERS" FILES ${HEADERS})
|
||||
include_directories(src)
|
||||
include_directories(src/3rdparty)
|
||||
include_directories(${UV_INCLUDE_DIR})
|
||||
|
||||
add_executable(xmrig ${HEADERS} ${SOURCES} ${SOURCES_OS} ${SOURCES_CPUID} ${HEADERS_CRYPTO} ${SOURCES_CRYPTO} ${SOURCES_SYSLOG} ${HTTPD_SOURCES})
|
||||
target_link_libraries(xmrig ${UV_LIBRARIES} ${MHD_LIBRARY} ${EXTRA_LIBS} ${CPUID_LIB})
|
||||
|
||||
79
README.md
79
README.md
@@ -1,47 +1,56 @@
|
||||
# XMRig
|
||||
XMRig is high performance Monero (XMR) CPU miner, with the official full Windows support.
|
||||
Based on cpuminer-multi with heavy optimizations/rewrites and removing a lot of legacy code.
|
||||
Originally based on cpuminer-multi with heavy optimizations/rewrites and removing a lot of legacy code, since version 1.0.0 complete rewritten from scratch on C++.
|
||||
|
||||
<img src="http://i.imgur.com/GdRDnAu.png" width="596" >
|
||||
* This is the CPU-mining version, there is also a [NVIDIA GPU version](https://github.com/xmrig/xmrig-nvidia).
|
||||
|
||||
<img src="http://i.imgur.com/OKZRVDh.png" width="619" >
|
||||
|
||||
#### Table of contents
|
||||
* [Features](#features)
|
||||
* [Download](#download)
|
||||
* [Usage](#usage)
|
||||
* [Algorithm variations](#algorithm-variations)
|
||||
* [Build](#build)
|
||||
* [Build](https://github.com/xmrig/xmrig/wiki/Build)
|
||||
* [Common Issues](#common-issues)
|
||||
* [Other information](#other-information)
|
||||
* [Donations](#donations)
|
||||
* [Contacts](#contacts)
|
||||
|
||||
## Features
|
||||
* High performance (290+ H/s on i7 6700).
|
||||
* High performance.
|
||||
* Official Windows support.
|
||||
* Small Windows executable, only 535 KB without dependencies.
|
||||
* Small Windows executable, without dependencies.
|
||||
* x86/x64 support.
|
||||
* Support for backup (failover) mining server.
|
||||
* keepalived support.
|
||||
* Command line options compatible with cpuminer.
|
||||
* CryptoNight-Lite support for AEON.
|
||||
* Smart automatic [CPU configuration](https://github.com/xmrig/xmrig/wiki/Threads).
|
||||
* Nicehash support
|
||||
* It's open source software.
|
||||
|
||||
## Download
|
||||
* Binary releases: https://github.com/xmrig/xmrig/releases
|
||||
* Git tree: https://github.com/xmrig/xmrig.git
|
||||
* Clone with `git clone https://github.com/xmrig/xmrig.git`
|
||||
* Clone with `git clone https://github.com/xmrig/xmrig.git` :hammer: [Build instructions](https://github.com/xmrig/xmrig/wiki/Build).
|
||||
|
||||
## Usage
|
||||
### Basic example
|
||||
```
|
||||
xmrig.exe -o xmr-eu.dwarfpool.com:8005 -u YOUR_WALLET -p x -k
|
||||
xmrig.exe -o pool.minemonero.pro:5555 -u YOUR_WALLET -p x -k
|
||||
```
|
||||
|
||||
### Failover
|
||||
```
|
||||
xmrig.exe -o pool.minemonero.pro:5555 -u YOUR_WALLET1 -p x -k -o pool.supportxmr.com:5555 -u YOUR_WALLET2 -p x -k
|
||||
```
|
||||
For failover you can add multiple pools, maximum count not limited.
|
||||
|
||||
### Options
|
||||
```
|
||||
-a, --algo=ALGO cryptonight (default) or cryptonight-lite
|
||||
-o, --url=URL URL of mining server
|
||||
-b, --backup-url=URL URL of backup mining server
|
||||
-O, --userpass=U:P username:password pair for mining server
|
||||
-u, --user=USERNAME username for mining server
|
||||
-p, --pass=PASSWORD password for mining server
|
||||
@@ -50,17 +59,25 @@ xmrig.exe -o xmr-eu.dwarfpool.com:8005 -u YOUR_WALLET -p x -k
|
||||
-k, --keepalive send keepalived for prevent timeout (need pool support)
|
||||
-r, --retries=N number of times to retry before switch to backup server (default: 5)
|
||||
-R, --retry-pause=N time to pause between retries (default: 5)
|
||||
--cpu-affinity set process affinity to cpu core(s), mask 0x3 for cores 0 and 1
|
||||
--cpu-affinity set process affinity to CPU core(s), mask 0x3 for cores 0 and 1
|
||||
--cpu-priority set process priority (0 idle, 2 normal to 5 highest)
|
||||
--no-huge-pages disable huge pages support
|
||||
--no-color disable colored output
|
||||
--donate-level=N donate level, default 5% (5 minutes in 100 minutes)
|
||||
--user-agent set custom user-agent string for pool
|
||||
-B, --background run the miner in the background
|
||||
-c, --config=FILE load a JSON-format configuration file
|
||||
--max-cpu-usage=N maximum cpu usage for automatic threads mode (default 75)
|
||||
--safe safe adjust threads and av settings for current cpu
|
||||
-l, --log-file=FILE log all output to a file
|
||||
--max-cpu-usage=N maximum CPU usage for automatic threads mode (default 75)
|
||||
--safe safe adjust threads and av settings for current CPU
|
||||
--nicehash enable nicehash support
|
||||
--print-time=N print hashrate report every N seconds
|
||||
-h, --help display this help and exit
|
||||
-V, --version output version information and exit
|
||||
```
|
||||
|
||||
Also you can use configuration via config file, default **config.json**. You can load multiple config files and combine it with command line options.
|
||||
|
||||
## Algorithm variations
|
||||
Since version 0.8.0.
|
||||
* `--av=1` For CPUs with hardware AES.
|
||||
@@ -68,42 +85,6 @@ Since version 0.8.0.
|
||||
* `--av=3` Software AES implementation.
|
||||
* `--av=4` Lower power mode (double hash) of `3`.
|
||||
|
||||
## Build
|
||||
### Ubuntu (Debian-based distros)
|
||||
```
|
||||
sudo apt-get install git build-essential cmake libcurl4-openssl-dev
|
||||
git clone https://github.com/xmrig/xmrig.git
|
||||
cd xmrig
|
||||
mkdir build
|
||||
cd build
|
||||
cmake .. -DCMAKE_BUILD_TYPE=Release
|
||||
make
|
||||
```
|
||||
|
||||
### Windows
|
||||
It's complicated, you need [MSYS2](http://www.msys2.org/), custom libcurl build, and of course CMake too.
|
||||
|
||||
Necessary MSYS2 packages:
|
||||
```
|
||||
pacman -Sy
|
||||
pacman -S mingw-w64-x86_64-gcc
|
||||
pacman -S make
|
||||
pacman -S mingw-w64-x86_64-cmake
|
||||
pacman -S mingw-w64-x86_64-pkg-config
|
||||
```
|
||||
Configure options for libcurl:
|
||||
```
|
||||
./configure --disable-shared --enable-optimize --enable-threaded-resolver --disable-libcurl-option --disable-ares --disable-rt --disable-ftp --disable-file --disable-ldap --disable-ldaps --disable-rtsp --disable-dict --disable-telnet --disable-tftp --disable-pop3 --disable-imap --disable-smb --disable-smtp --disable-gopher --disable-manual --disable-ipv6 --disable-sspi --disable-crypto-auth --disable-ntlm-wb --disable-tls-srp --disable-unix-sockets --without-zlib --without-winssl --without-ssl --without-libssh2 --without-nghttp2 --disable-cookies --without-ca-bundle --without-librtmp
|
||||
```
|
||||
CMake options:
|
||||
```
|
||||
cmake .. -G "Unix Makefiles" -DCMAKE_BUILD_TYPE=Release -DCURL_INCLUDE_DIR="c:\<path>\curl-7.53.1\include" -DCURL_LIBRARY="c:\<path>\curl-7.53.1\lib\.libs"
|
||||
```
|
||||
|
||||
### Optional features
|
||||
`-DWITH_LIBCPUID=OFF` Disable libcpuid. Auto configuration of CPU after this will be very limited.
|
||||
`-DWITH_AEON=OFF` Disable CryptoNight-Lite support.
|
||||
|
||||
## Common Issues
|
||||
### HUGE PAGES unavailable
|
||||
* Run XMRig as Administrator.
|
||||
@@ -116,8 +97,8 @@ cmake .. -G "Unix Makefiles" -DCMAKE_BUILD_TYPE=Release -DCURL_INCLUDE_DIR="c:\<
|
||||
|
||||
|
||||
### CPU mining performance
|
||||
* **i7-6700** - 290+ H/s (4 threads, cpu affinity 0xAA)
|
||||
* **Dual E5620** - 377 H/s (12 threads, cpu affinity 0xEEEE)
|
||||
* **Intel i7-7700** - 307 H/s (4 threads)
|
||||
* **AMD Ryzen 7 1700X** - 560 H/s (8 threads)
|
||||
|
||||
Please note performance is highly dependent on system load. The numbers above are obtained on an idle system. Tasks heavily using a processor cache, such as video playback, can greatly degrade hashrate. Optimal number of threads depends on the size of the L3 cache of a processor, 1 thread requires 2 MB of cache.
|
||||
|
||||
|
||||
@@ -1,256 +0,0 @@
|
||||
/* XMRig
|
||||
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com>
|
||||
* Copyright 2012-2014 pooler <pooler@litecoinpool.org>
|
||||
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
|
||||
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
|
||||
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
|
||||
* Copyright 2017 fireice-uk <https://github.com/fireice-uk>
|
||||
* Copyright 2016-2017 XMRig <support@xmrig.com>
|
||||
*
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef __CRYPTONIGHT_LITE_AESNI_H__
|
||||
#define __CRYPTONIGHT_LITE_AESNI_H__
|
||||
|
||||
#include <x86intrin.h>
|
||||
|
||||
|
||||
#define aes_genkey_sub(imm8) \
|
||||
__m128i xout1 = _mm_aeskeygenassist_si128(*xout2, (imm8)); \
|
||||
xout1 = _mm_shuffle_epi32(xout1, 0xFF); \
|
||||
*xout0 = sl_xor(*xout0); \
|
||||
*xout0 = _mm_xor_si128(*xout0, xout1); \
|
||||
xout1 = _mm_aeskeygenassist_si128(*xout0, 0x00);\
|
||||
xout1 = _mm_shuffle_epi32(xout1, 0xAA); \
|
||||
*xout2 = sl_xor(*xout2); \
|
||||
*xout2 = _mm_xor_si128(*xout2, xout1); \
|
||||
|
||||
|
||||
// This will shift and xor tmp1 into itself as 4 32-bit vals such as
|
||||
// sl_xor(a1 a2 a3 a4) = a1 (a2^a1) (a3^a2^a1) (a4^a3^a2^a1)
|
||||
inline __m128i sl_xor(__m128i tmp1)
|
||||
{
|
||||
__m128i tmp4;
|
||||
tmp4 = _mm_slli_si128(tmp1, 0x04);
|
||||
tmp1 = _mm_xor_si128(tmp1, tmp4);
|
||||
tmp4 = _mm_slli_si128(tmp4, 0x04);
|
||||
tmp1 = _mm_xor_si128(tmp1, tmp4);
|
||||
tmp4 = _mm_slli_si128(tmp4, 0x04);
|
||||
tmp1 = _mm_xor_si128(tmp1, tmp4);
|
||||
return tmp1;
|
||||
}
|
||||
|
||||
|
||||
inline void aes_genkey_sub1(__m128i* xout0, __m128i* xout2)
|
||||
{
|
||||
aes_genkey_sub(0x1)
|
||||
}
|
||||
|
||||
|
||||
inline void aes_genkey_sub2(__m128i* xout0, __m128i* xout2)
|
||||
{
|
||||
aes_genkey_sub(0x2)
|
||||
}
|
||||
|
||||
|
||||
inline void aes_genkey_sub4(__m128i* xout0, __m128i* xout2)
|
||||
{
|
||||
aes_genkey_sub(0x4)
|
||||
}
|
||||
|
||||
|
||||
inline void aes_genkey_sub8(__m128i* xout0, __m128i* xout2)
|
||||
{
|
||||
aes_genkey_sub(0x8)
|
||||
}
|
||||
|
||||
|
||||
inline void aes_round(__m128i key, __m128i* x0, __m128i* x1, __m128i* x2, __m128i* x3, __m128i* x4, __m128i* x5, __m128i* x6, __m128i* x7)
|
||||
{
|
||||
*x0 = _mm_aesenc_si128(*x0, key);
|
||||
*x1 = _mm_aesenc_si128(*x1, key);
|
||||
*x2 = _mm_aesenc_si128(*x2, key);
|
||||
*x3 = _mm_aesenc_si128(*x3, key);
|
||||
*x4 = _mm_aesenc_si128(*x4, key);
|
||||
*x5 = _mm_aesenc_si128(*x5, key);
|
||||
*x6 = _mm_aesenc_si128(*x6, key);
|
||||
*x7 = _mm_aesenc_si128(*x7, key);
|
||||
}
|
||||
|
||||
|
||||
inline void aes_genkey(const __m128i* memory, __m128i* k0, __m128i* k1, __m128i* k2, __m128i* k3, __m128i* k4, __m128i* k5, __m128i* k6, __m128i* k7, __m128i* k8, __m128i* k9)
|
||||
{
|
||||
__m128i xout0 = _mm_load_si128(memory);
|
||||
__m128i xout2 = _mm_load_si128(memory + 1);
|
||||
*k0 = xout0;
|
||||
*k1 = xout2;
|
||||
|
||||
aes_genkey_sub1(&xout0, &xout2);
|
||||
*k2 = xout0;
|
||||
*k3 = xout2;
|
||||
|
||||
aes_genkey_sub2(&xout0, &xout2);
|
||||
*k4 = xout0;
|
||||
*k5 = xout2;
|
||||
|
||||
aes_genkey_sub4(&xout0, &xout2);
|
||||
*k6 = xout0;
|
||||
*k7 = xout2;
|
||||
|
||||
aes_genkey_sub8(&xout0, &xout2);
|
||||
*k8 = xout0;
|
||||
*k9 = xout2;
|
||||
}
|
||||
|
||||
|
||||
inline void cn_explode_scratchpad(const __m128i* input, __m128i* output)
|
||||
{
|
||||
// This is more than we have registers, compiler will assign 2 keys on the stack
|
||||
__m128i xin0, xin1, xin2, xin3, xin4, xin5, xin6, xin7;
|
||||
__m128i k0, k1, k2, k3, k4, k5, k6, k7, k8, k9;
|
||||
|
||||
aes_genkey(input, &k0, &k1, &k2, &k3, &k4, &k5, &k6, &k7, &k8, &k9);
|
||||
|
||||
xin0 = _mm_load_si128(input + 4);
|
||||
xin1 = _mm_load_si128(input + 5);
|
||||
xin2 = _mm_load_si128(input + 6);
|
||||
xin3 = _mm_load_si128(input + 7);
|
||||
xin4 = _mm_load_si128(input + 8);
|
||||
xin5 = _mm_load_si128(input + 9);
|
||||
xin6 = _mm_load_si128(input + 10);
|
||||
xin7 = _mm_load_si128(input + 11);
|
||||
|
||||
for (size_t i = 0; __builtin_expect(i < MEMORY_LITE / sizeof(__m128i), 1); i += 8) {
|
||||
aes_round(k0, &xin0, &xin1, &xin2, &xin3, &xin4, &xin5, &xin6, &xin7);
|
||||
aes_round(k1, &xin0, &xin1, &xin2, &xin3, &xin4, &xin5, &xin6, &xin7);
|
||||
aes_round(k2, &xin0, &xin1, &xin2, &xin3, &xin4, &xin5, &xin6, &xin7);
|
||||
aes_round(k3, &xin0, &xin1, &xin2, &xin3, &xin4, &xin5, &xin6, &xin7);
|
||||
aes_round(k4, &xin0, &xin1, &xin2, &xin3, &xin4, &xin5, &xin6, &xin7);
|
||||
aes_round(k5, &xin0, &xin1, &xin2, &xin3, &xin4, &xin5, &xin6, &xin7);
|
||||
aes_round(k6, &xin0, &xin1, &xin2, &xin3, &xin4, &xin5, &xin6, &xin7);
|
||||
aes_round(k7, &xin0, &xin1, &xin2, &xin3, &xin4, &xin5, &xin6, &xin7);
|
||||
aes_round(k8, &xin0, &xin1, &xin2, &xin3, &xin4, &xin5, &xin6, &xin7);
|
||||
aes_round(k9, &xin0, &xin1, &xin2, &xin3, &xin4, &xin5, &xin6, &xin7);
|
||||
|
||||
_mm_store_si128(output + i + 0, xin0);
|
||||
_mm_store_si128(output + i + 1, xin1);
|
||||
_mm_store_si128(output + i + 2, xin2);
|
||||
_mm_store_si128(output + i + 3, xin3);
|
||||
_mm_store_si128(output + i + 4, xin4);
|
||||
_mm_store_si128(output + i + 5, xin5);
|
||||
_mm_store_si128(output + i + 6, xin6);
|
||||
_mm_store_si128(output + i + 7, xin7);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
inline void cn_implode_scratchpad(const __m128i* input, __m128i* output)
|
||||
{
|
||||
// This is more than we have registers, compiler will assign 2 keys on the stack
|
||||
__m128i xout0, xout1, xout2, xout3, xout4, xout5, xout6, xout7;
|
||||
__m128i k0, k1, k2, k3, k4, k5, k6, k7, k8, k9;
|
||||
|
||||
aes_genkey(output + 2, &k0, &k1, &k2, &k3, &k4, &k5, &k6, &k7, &k8, &k9);
|
||||
|
||||
xout0 = _mm_load_si128(output + 4);
|
||||
xout1 = _mm_load_si128(output + 5);
|
||||
xout2 = _mm_load_si128(output + 6);
|
||||
xout3 = _mm_load_si128(output + 7);
|
||||
xout4 = _mm_load_si128(output + 8);
|
||||
xout5 = _mm_load_si128(output + 9);
|
||||
xout6 = _mm_load_si128(output + 10);
|
||||
xout7 = _mm_load_si128(output + 11);
|
||||
|
||||
for (size_t i = 0; __builtin_expect(i < MEMORY_LITE / sizeof(__m128i), 1); i += 8)
|
||||
{
|
||||
xout0 = _mm_xor_si128(_mm_load_si128(input + i + 0), xout0);
|
||||
xout1 = _mm_xor_si128(_mm_load_si128(input + i + 1), xout1);
|
||||
xout2 = _mm_xor_si128(_mm_load_si128(input + i + 2), xout2);
|
||||
xout3 = _mm_xor_si128(_mm_load_si128(input + i + 3), xout3);
|
||||
xout4 = _mm_xor_si128(_mm_load_si128(input + i + 4), xout4);
|
||||
xout5 = _mm_xor_si128(_mm_load_si128(input + i + 5), xout5);
|
||||
xout6 = _mm_xor_si128(_mm_load_si128(input + i + 6), xout6);
|
||||
xout7 = _mm_xor_si128(_mm_load_si128(input + i + 7), xout7);
|
||||
|
||||
aes_round(k0, &xout0, &xout1, &xout2, &xout3, &xout4, &xout5, &xout6, &xout7);
|
||||
aes_round(k1, &xout0, &xout1, &xout2, &xout3, &xout4, &xout5, &xout6, &xout7);
|
||||
aes_round(k2, &xout0, &xout1, &xout2, &xout3, &xout4, &xout5, &xout6, &xout7);
|
||||
aes_round(k3, &xout0, &xout1, &xout2, &xout3, &xout4, &xout5, &xout6, &xout7);
|
||||
aes_round(k4, &xout0, &xout1, &xout2, &xout3, &xout4, &xout5, &xout6, &xout7);
|
||||
aes_round(k5, &xout0, &xout1, &xout2, &xout3, &xout4, &xout5, &xout6, &xout7);
|
||||
aes_round(k6, &xout0, &xout1, &xout2, &xout3, &xout4, &xout5, &xout6, &xout7);
|
||||
aes_round(k7, &xout0, &xout1, &xout2, &xout3, &xout4, &xout5, &xout6, &xout7);
|
||||
aes_round(k8, &xout0, &xout1, &xout2, &xout3, &xout4, &xout5, &xout6, &xout7);
|
||||
aes_round(k9, &xout0, &xout1, &xout2, &xout3, &xout4, &xout5, &xout6, &xout7);
|
||||
}
|
||||
|
||||
_mm_store_si128(output + 4, xout0);
|
||||
_mm_store_si128(output + 5, xout1);
|
||||
_mm_store_si128(output + 6, xout2);
|
||||
_mm_store_si128(output + 7, xout3);
|
||||
_mm_store_si128(output + 8, xout4);
|
||||
_mm_store_si128(output + 9, xout5);
|
||||
_mm_store_si128(output + 10, xout6);
|
||||
_mm_store_si128(output + 11, xout7);
|
||||
}
|
||||
|
||||
|
||||
#if defined(__x86_64__)
|
||||
# define EXTRACT64(X) _mm_cvtsi128_si64(X)
|
||||
|
||||
inline uint64_t _umul128(uint64_t a, uint64_t b, uint64_t* hi)
|
||||
{
|
||||
unsigned __int128 r = (unsigned __int128) a * (unsigned __int128) b;
|
||||
*hi = r >> 64;
|
||||
return (uint64_t) r;
|
||||
}
|
||||
#elif defined(__i386__)
|
||||
# define HI32(X) \
|
||||
_mm_srli_si128((X), 4)
|
||||
|
||||
|
||||
# define EXTRACT64(X) \
|
||||
((uint64_t)(uint32_t)_mm_cvtsi128_si32(X) | \
|
||||
((uint64_t)(uint32_t)_mm_cvtsi128_si32(HI32(X)) << 32))
|
||||
|
||||
inline uint64_t _umul128(uint64_t multiplier, uint64_t multiplicand, uint64_t *product_hi) {
|
||||
// multiplier = ab = a * 2^32 + b
|
||||
// multiplicand = cd = c * 2^32 + d
|
||||
// ab * cd = a * c * 2^64 + (a * d + b * c) * 2^32 + b * d
|
||||
uint64_t a = multiplier >> 32;
|
||||
uint64_t b = multiplier & 0xFFFFFFFF;
|
||||
uint64_t c = multiplicand >> 32;
|
||||
uint64_t d = multiplicand & 0xFFFFFFFF;
|
||||
|
||||
//uint64_t ac = a * c;
|
||||
uint64_t ad = a * d;
|
||||
//uint64_t bc = b * c;
|
||||
uint64_t bd = b * d;
|
||||
|
||||
uint64_t adbc = ad + (b * c);
|
||||
uint64_t adbc_carry = adbc < ad ? 1 : 0;
|
||||
|
||||
// multiplier * multiplicand = product_hi * 2^64 + product_lo
|
||||
uint64_t product_lo = bd + (adbc << 32);
|
||||
uint64_t product_lo_carry = product_lo < bd ? 1 : 0;
|
||||
*product_hi = (a * c) + (adbc >> 32) + (adbc_carry << 32) + product_lo_carry;
|
||||
|
||||
return product_lo;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#endif /* __CRYPTONIGHT_LITE_AESNI_H__ */
|
||||
@@ -1,77 +0,0 @@
|
||||
/* XMRig
|
||||
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com>
|
||||
* Copyright 2012-2014 pooler <pooler@litecoinpool.org>
|
||||
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
|
||||
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
|
||||
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
|
||||
* Copyright 2017 fireice-uk <https://github.com/fireice-uk>
|
||||
* Copyright 2016-2017 XMRig <support@xmrig.com>
|
||||
*
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <x86intrin.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "algo/cryptonight/cryptonight.h"
|
||||
#include "cryptonight_lite_aesni.h"
|
||||
#include "crypto/c_keccak.h"
|
||||
|
||||
|
||||
void cryptonight_lite_av1_aesni(const void *restrict input, size_t size, void *restrict output, struct cryptonight_ctx *restrict ctx)
|
||||
{
|
||||
keccak((const uint8_t *) input, size, ctx->state0, 200);
|
||||
|
||||
cn_explode_scratchpad((__m128i*) ctx->state0, (__m128i*) ctx->memory);
|
||||
|
||||
const uint8_t* l0 = ctx->memory;
|
||||
uint64_t* h0 = (uint64_t*) ctx->state0;
|
||||
|
||||
uint64_t al0 = h0[0] ^ h0[4];
|
||||
uint64_t ah0 = h0[1] ^ h0[5];
|
||||
__m128i bx0 = _mm_set_epi64x(h0[3] ^ h0[7], h0[2] ^ h0[6]);
|
||||
|
||||
uint64_t idx0 = h0[0] ^ h0[4];
|
||||
|
||||
for (size_t i = 0; __builtin_expect(i < 0x40000, 1); i++) {
|
||||
__m128i cx;
|
||||
cx = _mm_load_si128((__m128i *) &l0[idx0 & 0xFFFF0]);
|
||||
cx = _mm_aesenc_si128(cx, _mm_set_epi64x(ah0, al0));
|
||||
|
||||
_mm_store_si128((__m128i *) &l0[idx0 & 0xFFFF0], _mm_xor_si128(bx0, cx));
|
||||
idx0 = EXTRACT64(cx);
|
||||
bx0 = cx;
|
||||
|
||||
uint64_t hi, lo, cl, ch;
|
||||
cl = ((uint64_t*) &l0[idx0 & 0xFFFF0])[0];
|
||||
ch = ((uint64_t*) &l0[idx0 & 0xFFFF0])[1];
|
||||
lo = _umul128(idx0, cl, &hi);
|
||||
|
||||
al0 += hi;
|
||||
ah0 += lo;
|
||||
|
||||
((uint64_t*)&l0[idx0 & 0xFFFF0])[0] = al0;
|
||||
((uint64_t*)&l0[idx0 & 0xFFFF0])[1] = ah0;
|
||||
|
||||
ah0 ^= ch;
|
||||
al0 ^= cl;
|
||||
idx0 = al0;
|
||||
}
|
||||
|
||||
cn_implode_scratchpad((__m128i*) ctx->memory, (__m128i*) ctx->state0);
|
||||
|
||||
keccakf(h0, 24);
|
||||
extra_hashes[ctx->state0[0] & 3](ctx->state0, 200, output);
|
||||
}
|
||||
@@ -1,111 +0,0 @@
|
||||
/* XMRig
|
||||
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com>
|
||||
* Copyright 2012-2014 pooler <pooler@litecoinpool.org>
|
||||
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
|
||||
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
|
||||
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
|
||||
* Copyright 2017 fireice-uk <https://github.com/fireice-uk>
|
||||
* Copyright 2016-2017 XMRig <support@xmrig.com>
|
||||
*
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <x86intrin.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "algo/cryptonight/cryptonight.h"
|
||||
#include "cryptonight_lite_aesni.h"
|
||||
#include "crypto/c_keccak.h"
|
||||
|
||||
|
||||
void cryptonight_lite_av2_aesni_double(const void *restrict input, size_t size, void *restrict output, struct cryptonight_ctx *restrict ctx)
|
||||
{
|
||||
keccak((const uint8_t *) input, size, ctx->state0, 200);
|
||||
keccak((const uint8_t *) input + size, size, ctx->state1, 200);
|
||||
|
||||
const uint8_t* l0 = ctx->memory;
|
||||
const uint8_t* l1 = ctx->memory + MEMORY_LITE;
|
||||
uint64_t* h0 = (uint64_t*) ctx->state0;
|
||||
uint64_t* h1 = (uint64_t*) ctx->state1;
|
||||
|
||||
cn_explode_scratchpad((__m128i*) h0, (__m128i*) l0);
|
||||
cn_explode_scratchpad((__m128i*) h1, (__m128i*) l1);
|
||||
|
||||
uint64_t al0 = h0[0] ^ h0[4];
|
||||
uint64_t al1 = h1[0] ^ h1[4];
|
||||
uint64_t ah0 = h0[1] ^ h0[5];
|
||||
uint64_t ah1 = h1[1] ^ h1[5];
|
||||
|
||||
__m128i bx0 = _mm_set_epi64x(h0[3] ^ h0[7], h0[2] ^ h0[6]);
|
||||
__m128i bx1 = _mm_set_epi64x(h1[3] ^ h1[7], h1[2] ^ h1[6]);
|
||||
|
||||
uint64_t idx0 = h0[0] ^ h0[4];
|
||||
uint64_t idx1 = h1[0] ^ h1[4];
|
||||
|
||||
for (size_t i = 0; __builtin_expect(i < 0x40000, 1); i++) {
|
||||
__m128i cx0 = _mm_load_si128((__m128i *) &l0[idx0 & 0xFFFF0]);
|
||||
__m128i cx1 = _mm_load_si128((__m128i *) &l1[idx1 & 0xFFFF0]);
|
||||
|
||||
cx0 = _mm_aesenc_si128(cx0, _mm_set_epi64x(ah0, al0));
|
||||
cx1 = _mm_aesenc_si128(cx1, _mm_set_epi64x(ah1, al1));
|
||||
|
||||
_mm_store_si128((__m128i *) &l0[idx0 & 0xFFFF0], _mm_xor_si128(bx0, cx0));
|
||||
_mm_store_si128((__m128i *) &l1[idx1 & 0xFFFF0], _mm_xor_si128(bx1, cx1));
|
||||
|
||||
idx0 = EXTRACT64(cx0);
|
||||
idx1 = EXTRACT64(cx1);
|
||||
|
||||
bx0 = cx0;
|
||||
bx1 = cx1;
|
||||
|
||||
uint64_t hi, lo, cl, ch;
|
||||
cl = ((uint64_t*) &l0[idx0 & 0xFFFF0])[0];
|
||||
ch = ((uint64_t*) &l0[idx0 & 0xFFFF0])[1];
|
||||
lo = _umul128(idx0, cl, &hi);
|
||||
|
||||
al0 += hi;
|
||||
ah0 += lo;
|
||||
|
||||
((uint64_t*) &l0[idx0 & 0xFFFF0])[0] = al0;
|
||||
((uint64_t*) &l0[idx0 & 0xFFFF0])[1] = ah0;
|
||||
|
||||
ah0 ^= ch;
|
||||
al0 ^= cl;
|
||||
idx0 = al0;
|
||||
|
||||
cl = ((uint64_t*) &l1[idx1 & 0xFFFF0])[0];
|
||||
ch = ((uint64_t*) &l1[idx1 & 0xFFFF0])[1];
|
||||
lo = _umul128(idx1, cl, &hi);
|
||||
|
||||
al1 += hi;
|
||||
ah1 += lo;
|
||||
|
||||
((uint64_t*) &l1[idx1 & 0xFFFF0])[0] = al1;
|
||||
((uint64_t*) &l1[idx1 & 0xFFFF0])[1] = ah1;
|
||||
|
||||
ah1 ^= ch;
|
||||
al1 ^= cl;
|
||||
idx1 = al1;
|
||||
}
|
||||
|
||||
cn_implode_scratchpad((__m128i*) l0, (__m128i*) h0);
|
||||
cn_implode_scratchpad((__m128i*) l1, (__m128i*) h1);
|
||||
|
||||
keccakf(h0, 24);
|
||||
keccakf(h1, 24);
|
||||
|
||||
extra_hashes[ctx->state0[0] & 3](ctx->state0, 200, output);
|
||||
extra_hashes[ctx->state1[0] & 3](ctx->state1, 200, (char*) output + 32);
|
||||
}
|
||||
@@ -1,77 +0,0 @@
|
||||
/* XMRig
|
||||
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com>
|
||||
* Copyright 2012-2014 pooler <pooler@litecoinpool.org>
|
||||
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
|
||||
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
|
||||
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
|
||||
* Copyright 2017 fireice-uk <https://github.com/fireice-uk>
|
||||
* Copyright 2016-2017 XMRig <support@xmrig.com>
|
||||
*
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <x86intrin.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "algo/cryptonight/cryptonight.h"
|
||||
#include "cryptonight_lite_softaes.h"
|
||||
#include "crypto/c_keccak.h"
|
||||
|
||||
|
||||
void cryptonight_lite_av3_softaes(const void *restrict input, size_t size, void *restrict output, struct cryptonight_ctx *restrict ctx)
|
||||
{
|
||||
keccak((const uint8_t *) input, size, ctx->state0, 200);
|
||||
|
||||
cn_explode_scratchpad((__m128i*) ctx->state0, (__m128i*) ctx->memory);
|
||||
|
||||
const uint8_t* l0 = ctx->memory;
|
||||
uint64_t* h0 = (uint64_t*) ctx->state0;
|
||||
|
||||
uint64_t al0 = h0[0] ^ h0[4];
|
||||
uint64_t ah0 = h0[1] ^ h0[5];
|
||||
__m128i bx0 = _mm_set_epi64x(h0[3] ^ h0[7], h0[2] ^ h0[6]);
|
||||
|
||||
uint64_t idx0 = h0[0] ^ h0[4];
|
||||
|
||||
for (size_t i = 0; __builtin_expect(i < 0x40000, 1); i++) {
|
||||
__m128i cx;
|
||||
cx = _mm_load_si128((__m128i *)&l0[idx0 & 0xFFFF0]);
|
||||
cx = soft_aesenc(cx, _mm_set_epi64x(ah0, al0));
|
||||
|
||||
_mm_store_si128((__m128i *)&l0[idx0 & 0xFFFF0], _mm_xor_si128(bx0, cx));
|
||||
idx0 = EXTRACT64(cx);
|
||||
bx0 = cx;
|
||||
|
||||
uint64_t hi, lo, cl, ch;
|
||||
cl = ((uint64_t*)&l0[idx0 & 0xFFFF0])[0];
|
||||
ch = ((uint64_t*)&l0[idx0 & 0xFFFF0])[1];
|
||||
lo = _umul128(idx0, cl, &hi);
|
||||
|
||||
al0 += hi;
|
||||
ah0 += lo;
|
||||
|
||||
((uint64_t*)&l0[idx0 & 0xFFFF0])[0] = al0;
|
||||
((uint64_t*)&l0[idx0 & 0xFFFF0])[1] = ah0;
|
||||
|
||||
ah0 ^= ch;
|
||||
al0 ^= cl;
|
||||
idx0 = al0;
|
||||
}
|
||||
|
||||
cn_implode_scratchpad((__m128i*) ctx->memory, (__m128i*) ctx->state0);
|
||||
|
||||
keccakf(h0, 24);
|
||||
extra_hashes[ctx->state0[0] & 3](ctx->state0, 200, output);
|
||||
}
|
||||
@@ -1,111 +0,0 @@
|
||||
/* XMRig
|
||||
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com>
|
||||
* Copyright 2012-2014 pooler <pooler@litecoinpool.org>
|
||||
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
|
||||
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
|
||||
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
|
||||
* Copyright 2017 fireice-uk <https://github.com/fireice-uk>
|
||||
* Copyright 2016-2017 XMRig <support@xmrig.com>
|
||||
*
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <x86intrin.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "algo/cryptonight/cryptonight.h"
|
||||
#include "cryptonight_lite_softaes.h"
|
||||
#include "crypto/c_keccak.h"
|
||||
|
||||
|
||||
void cryptonight_lite_av4_softaes_double(const void *restrict input, size_t size, void *restrict output, struct cryptonight_ctx *restrict ctx)
|
||||
{
|
||||
keccak((const uint8_t *) input, size, ctx->state0, 200);
|
||||
keccak((const uint8_t *) input + size, size, ctx->state1, 200);
|
||||
|
||||
const uint8_t* l0 = ctx->memory;
|
||||
const uint8_t* l1 = ctx->memory + MEMORY_LITE;
|
||||
uint64_t* h0 = (uint64_t*) ctx->state0;
|
||||
uint64_t* h1 = (uint64_t*) ctx->state1;
|
||||
|
||||
cn_explode_scratchpad((__m128i*) h0, (__m128i*) l0);
|
||||
cn_explode_scratchpad((__m128i*) h1, (__m128i*) l1);
|
||||
|
||||
uint64_t al0 = h0[0] ^ h0[4];
|
||||
uint64_t al1 = h1[0] ^ h1[4];
|
||||
uint64_t ah0 = h0[1] ^ h0[5];
|
||||
uint64_t ah1 = h1[1] ^ h1[5];
|
||||
|
||||
__m128i bx0 = _mm_set_epi64x(h0[3] ^ h0[7], h0[2] ^ h0[6]);
|
||||
__m128i bx1 = _mm_set_epi64x(h1[3] ^ h1[7], h1[2] ^ h1[6]);
|
||||
|
||||
uint64_t idx0 = h0[0] ^ h0[4];
|
||||
uint64_t idx1 = h1[0] ^ h1[4];
|
||||
|
||||
for (size_t i = 0; __builtin_expect(i < 0x40000, 1); i++) {
|
||||
__m128i cx0 = _mm_load_si128((__m128i *) &l0[idx0 & 0xFFFF0]);
|
||||
__m128i cx1 = _mm_load_si128((__m128i *) &l1[idx1 & 0xFFFF0]);
|
||||
|
||||
cx0 = soft_aesenc(cx0, _mm_set_epi64x(ah0, al0));
|
||||
cx1 = soft_aesenc(cx1, _mm_set_epi64x(ah1, al1));
|
||||
|
||||
_mm_store_si128((__m128i *) &l0[idx0 & 0xFFFF0], _mm_xor_si128(bx0, cx0));
|
||||
_mm_store_si128((__m128i *) &l1[idx1 & 0xFFFF0], _mm_xor_si128(bx1, cx1));
|
||||
|
||||
idx0 = EXTRACT64(cx0);
|
||||
idx1 = EXTRACT64(cx1);
|
||||
|
||||
bx0 = cx0;
|
||||
bx1 = cx1;
|
||||
|
||||
uint64_t hi, lo, cl, ch;
|
||||
cl = ((uint64_t*) &l0[idx0 & 0xFFFF0])[0];
|
||||
ch = ((uint64_t*) &l0[idx0 & 0xFFFF0])[1];
|
||||
lo = _umul128(idx0, cl, &hi);
|
||||
|
||||
al0 += hi;
|
||||
ah0 += lo;
|
||||
|
||||
((uint64_t*) &l0[idx0 & 0xFFFF0])[0] = al0;
|
||||
((uint64_t*) &l0[idx0 & 0xFFFF0])[1] = ah0;
|
||||
|
||||
ah0 ^= ch;
|
||||
al0 ^= cl;
|
||||
idx0 = al0;
|
||||
|
||||
cl = ((uint64_t*) &l1[idx1 & 0xFFFF0])[0];
|
||||
ch = ((uint64_t*) &l1[idx1 & 0xFFFF0])[1];
|
||||
lo = _umul128(idx1, cl, &hi);
|
||||
|
||||
al1 += hi;
|
||||
ah1 += lo;
|
||||
|
||||
((uint64_t*) &l1[idx1 & 0xFFFF0])[0] = al1;
|
||||
((uint64_t*) &l1[idx1 & 0xFFFF0])[1] = ah1;
|
||||
|
||||
ah1 ^= ch;
|
||||
al1 ^= cl;
|
||||
idx1 = al1;
|
||||
}
|
||||
|
||||
cn_implode_scratchpad((__m128i*) l0, (__m128i*) h0);
|
||||
cn_implode_scratchpad((__m128i*) l1, (__m128i*) h1);
|
||||
|
||||
keccakf(h0, 24);
|
||||
keccakf(h1, 24);
|
||||
|
||||
extra_hashes[ctx->state0[0] & 3](ctx->state0, 200, output);
|
||||
extra_hashes[ctx->state1[0] & 3](ctx->state1, 200, (char*) output + 32);
|
||||
}
|
||||
@@ -1,237 +0,0 @@
|
||||
/* XMRig
|
||||
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com>
|
||||
* Copyright 2012-2014 pooler <pooler@litecoinpool.org>
|
||||
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
|
||||
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
|
||||
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
|
||||
* Copyright 2017 fireice-uk <https://github.com/fireice-uk>
|
||||
* Copyright 2016-2017 XMRig <support@xmrig.com>
|
||||
*
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef __CRYPTONIGHT_LITE_SOFTAES_H__
|
||||
#define __CRYPTONIGHT_LITE_SOFTAES_H__
|
||||
|
||||
#include <x86intrin.h>
|
||||
|
||||
extern __m128i soft_aesenc(__m128i in, __m128i key);
|
||||
extern __m128i soft_aeskeygenassist(__m128i key, uint8_t rcon);
|
||||
|
||||
|
||||
// This will shift and xor tmp1 into itself as 4 32-bit vals such as
|
||||
// sl_xor(a1 a2 a3 a4) = a1 (a2^a1) (a3^a2^a1) (a4^a3^a2^a1)
|
||||
inline __m128i sl_xor(__m128i tmp1)
|
||||
{
|
||||
__m128i tmp4;
|
||||
tmp4 = _mm_slli_si128(tmp1, 0x04);
|
||||
tmp1 = _mm_xor_si128(tmp1, tmp4);
|
||||
tmp4 = _mm_slli_si128(tmp4, 0x04);
|
||||
tmp1 = _mm_xor_si128(tmp1, tmp4);
|
||||
tmp4 = _mm_slli_si128(tmp4, 0x04);
|
||||
tmp1 = _mm_xor_si128(tmp1, tmp4);
|
||||
return tmp1;
|
||||
}
|
||||
|
||||
|
||||
inline void aes_genkey_sub(__m128i* xout0, __m128i* xout2, uint8_t rcon)
|
||||
{
|
||||
__m128i xout1 = soft_aeskeygenassist(*xout2, rcon);
|
||||
xout1 = _mm_shuffle_epi32(xout1, 0xFF); // see PSHUFD, set all elems to 4th elem
|
||||
*xout0 = sl_xor(*xout0);
|
||||
*xout0 = _mm_xor_si128(*xout0, xout1);
|
||||
xout1 = soft_aeskeygenassist(*xout0, 0x00);
|
||||
xout1 = _mm_shuffle_epi32(xout1, 0xAA); // see PSHUFD, set all elems to 3rd elem
|
||||
*xout2 = sl_xor(*xout2);
|
||||
*xout2 = _mm_xor_si128(*xout2, xout1);
|
||||
}
|
||||
|
||||
|
||||
inline void aes_round(__m128i key, __m128i* x0, __m128i* x1, __m128i* x2, __m128i* x3, __m128i* x4, __m128i* x5, __m128i* x6, __m128i* x7)
|
||||
{
|
||||
*x0 = soft_aesenc(*x0, key);
|
||||
*x1 = soft_aesenc(*x1, key);
|
||||
*x2 = soft_aesenc(*x2, key);
|
||||
*x3 = soft_aesenc(*x3, key);
|
||||
*x4 = soft_aesenc(*x4, key);
|
||||
*x5 = soft_aesenc(*x5, key);
|
||||
*x6 = soft_aesenc(*x6, key);
|
||||
*x7 = soft_aesenc(*x7, key);
|
||||
}
|
||||
|
||||
|
||||
inline void aes_genkey(const __m128i* memory, __m128i* k0, __m128i* k1, __m128i* k2, __m128i* k3, __m128i* k4, __m128i* k5, __m128i* k6, __m128i* k7, __m128i* k8, __m128i* k9)
|
||||
{
|
||||
__m128i xout0 = _mm_load_si128(memory);
|
||||
__m128i xout2 = _mm_load_si128(memory + 1);
|
||||
*k0 = xout0;
|
||||
*k1 = xout2;
|
||||
|
||||
aes_genkey_sub(&xout0, &xout2, 0x1);
|
||||
*k2 = xout0;
|
||||
*k3 = xout2;
|
||||
|
||||
aes_genkey_sub(&xout0, &xout2, 0x2);
|
||||
*k4 = xout0;
|
||||
*k5 = xout2;
|
||||
|
||||
aes_genkey_sub(&xout0, &xout2, 0x4);
|
||||
*k6 = xout0;
|
||||
*k7 = xout2;
|
||||
|
||||
aes_genkey_sub(&xout0, &xout2, 0x8);
|
||||
*k8 = xout0;
|
||||
*k9 = xout2;
|
||||
}
|
||||
|
||||
|
||||
inline void cn_explode_scratchpad(const __m128i* input, __m128i* output)
|
||||
{
|
||||
// This is more than we have registers, compiler will assign 2 keys on the stack
|
||||
__m128i xin0, xin1, xin2, xin3, xin4, xin5, xin6, xin7;
|
||||
__m128i k0, k1, k2, k3, k4, k5, k6, k7, k8, k9;
|
||||
|
||||
aes_genkey(input, &k0, &k1, &k2, &k3, &k4, &k5, &k6, &k7, &k8, &k9);
|
||||
|
||||
xin0 = _mm_load_si128(input + 4);
|
||||
xin1 = _mm_load_si128(input + 5);
|
||||
xin2 = _mm_load_si128(input + 6);
|
||||
xin3 = _mm_load_si128(input + 7);
|
||||
xin4 = _mm_load_si128(input + 8);
|
||||
xin5 = _mm_load_si128(input + 9);
|
||||
xin6 = _mm_load_si128(input + 10);
|
||||
xin7 = _mm_load_si128(input + 11);
|
||||
|
||||
for (size_t i = 0; i < MEMORY_LITE / sizeof(__m128i); i += 8) {
|
||||
aes_round(k0, &xin0, &xin1, &xin2, &xin3, &xin4, &xin5, &xin6, &xin7);
|
||||
aes_round(k1, &xin0, &xin1, &xin2, &xin3, &xin4, &xin5, &xin6, &xin7);
|
||||
aes_round(k2, &xin0, &xin1, &xin2, &xin3, &xin4, &xin5, &xin6, &xin7);
|
||||
aes_round(k3, &xin0, &xin1, &xin2, &xin3, &xin4, &xin5, &xin6, &xin7);
|
||||
aes_round(k4, &xin0, &xin1, &xin2, &xin3, &xin4, &xin5, &xin6, &xin7);
|
||||
aes_round(k5, &xin0, &xin1, &xin2, &xin3, &xin4, &xin5, &xin6, &xin7);
|
||||
aes_round(k6, &xin0, &xin1, &xin2, &xin3, &xin4, &xin5, &xin6, &xin7);
|
||||
aes_round(k7, &xin0, &xin1, &xin2, &xin3, &xin4, &xin5, &xin6, &xin7);
|
||||
aes_round(k8, &xin0, &xin1, &xin2, &xin3, &xin4, &xin5, &xin6, &xin7);
|
||||
aes_round(k9, &xin0, &xin1, &xin2, &xin3, &xin4, &xin5, &xin6, &xin7);
|
||||
|
||||
_mm_store_si128(output + i + 0, xin0);
|
||||
_mm_store_si128(output + i + 1, xin1);
|
||||
_mm_store_si128(output + i + 2, xin2);
|
||||
_mm_store_si128(output + i + 3, xin3);
|
||||
_mm_store_si128(output + i + 4, xin4);
|
||||
_mm_store_si128(output + i + 5, xin5);
|
||||
_mm_store_si128(output + i + 6, xin6);
|
||||
_mm_store_si128(output + i + 7, xin7);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
inline void cn_implode_scratchpad(const __m128i* input, __m128i* output)
|
||||
{
|
||||
// This is more than we have registers, compiler will assign 2 keys on the stack
|
||||
__m128i xout0, xout1, xout2, xout3, xout4, xout5, xout6, xout7;
|
||||
__m128i k0, k1, k2, k3, k4, k5, k6, k7, k8, k9;
|
||||
|
||||
aes_genkey(output + 2, &k0, &k1, &k2, &k3, &k4, &k5, &k6, &k7, &k8, &k9);
|
||||
|
||||
xout0 = _mm_load_si128(output + 4);
|
||||
xout1 = _mm_load_si128(output + 5);
|
||||
xout2 = _mm_load_si128(output + 6);
|
||||
xout3 = _mm_load_si128(output + 7);
|
||||
xout4 = _mm_load_si128(output + 8);
|
||||
xout5 = _mm_load_si128(output + 9);
|
||||
xout6 = _mm_load_si128(output + 10);
|
||||
xout7 = _mm_load_si128(output + 11);
|
||||
|
||||
for (size_t i = 0; __builtin_expect(i < MEMORY_LITE / sizeof(__m128i), 1); i += 8)
|
||||
{
|
||||
xout0 = _mm_xor_si128(_mm_load_si128(input + i + 0), xout0);
|
||||
xout1 = _mm_xor_si128(_mm_load_si128(input + i + 1), xout1);
|
||||
xout2 = _mm_xor_si128(_mm_load_si128(input + i + 2), xout2);
|
||||
xout3 = _mm_xor_si128(_mm_load_si128(input + i + 3), xout3);
|
||||
xout4 = _mm_xor_si128(_mm_load_si128(input + i + 4), xout4);
|
||||
xout5 = _mm_xor_si128(_mm_load_si128(input + i + 5), xout5);
|
||||
xout6 = _mm_xor_si128(_mm_load_si128(input + i + 6), xout6);
|
||||
xout7 = _mm_xor_si128(_mm_load_si128(input + i + 7), xout7);
|
||||
|
||||
aes_round(k0, &xout0, &xout1, &xout2, &xout3, &xout4, &xout5, &xout6, &xout7);
|
||||
aes_round(k1, &xout0, &xout1, &xout2, &xout3, &xout4, &xout5, &xout6, &xout7);
|
||||
aes_round(k2, &xout0, &xout1, &xout2, &xout3, &xout4, &xout5, &xout6, &xout7);
|
||||
aes_round(k3, &xout0, &xout1, &xout2, &xout3, &xout4, &xout5, &xout6, &xout7);
|
||||
aes_round(k4, &xout0, &xout1, &xout2, &xout3, &xout4, &xout5, &xout6, &xout7);
|
||||
aes_round(k5, &xout0, &xout1, &xout2, &xout3, &xout4, &xout5, &xout6, &xout7);
|
||||
aes_round(k6, &xout0, &xout1, &xout2, &xout3, &xout4, &xout5, &xout6, &xout7);
|
||||
aes_round(k7, &xout0, &xout1, &xout2, &xout3, &xout4, &xout5, &xout6, &xout7);
|
||||
aes_round(k8, &xout0, &xout1, &xout2, &xout3, &xout4, &xout5, &xout6, &xout7);
|
||||
aes_round(k9, &xout0, &xout1, &xout2, &xout3, &xout4, &xout5, &xout6, &xout7);
|
||||
}
|
||||
|
||||
_mm_store_si128(output + 4, xout0);
|
||||
_mm_store_si128(output + 5, xout1);
|
||||
_mm_store_si128(output + 6, xout2);
|
||||
_mm_store_si128(output + 7, xout3);
|
||||
_mm_store_si128(output + 8, xout4);
|
||||
_mm_store_si128(output + 9, xout5);
|
||||
_mm_store_si128(output + 10, xout6);
|
||||
_mm_store_si128(output + 11, xout7);
|
||||
}
|
||||
|
||||
|
||||
#if defined(__x86_64__)
|
||||
# define EXTRACT64(X) _mm_cvtsi128_si64(X)
|
||||
|
||||
inline uint64_t _umul128(uint64_t a, uint64_t b, uint64_t* hi)
|
||||
{
|
||||
unsigned __int128 r = (unsigned __int128) a * (unsigned __int128) b;
|
||||
*hi = r >> 64;
|
||||
return (uint64_t) r;
|
||||
}
|
||||
#elif defined(__i386__)
|
||||
# define HI32(X) \
|
||||
_mm_srli_si128((X), 4)
|
||||
|
||||
|
||||
# define EXTRACT64(X) \
|
||||
((uint64_t)(uint32_t)_mm_cvtsi128_si32(X) | \
|
||||
((uint64_t)(uint32_t)_mm_cvtsi128_si32(HI32(X)) << 32))
|
||||
|
||||
inline uint64_t _umul128(uint64_t multiplier, uint64_t multiplicand, uint64_t *product_hi) {
|
||||
// multiplier = ab = a * 2^32 + b
|
||||
// multiplicand = cd = c * 2^32 + d
|
||||
// ab * cd = a * c * 2^64 + (a * d + b * c) * 2^32 + b * d
|
||||
uint64_t a = multiplier >> 32;
|
||||
uint64_t b = multiplier & 0xFFFFFFFF;
|
||||
uint64_t c = multiplicand >> 32;
|
||||
uint64_t d = multiplicand & 0xFFFFFFFF;
|
||||
|
||||
//uint64_t ac = a * c;
|
||||
uint64_t ad = a * d;
|
||||
//uint64_t bc = b * c;
|
||||
uint64_t bd = b * d;
|
||||
|
||||
uint64_t adbc = ad + (b * c);
|
||||
uint64_t adbc_carry = adbc < ad ? 1 : 0;
|
||||
|
||||
// multiplier * multiplicand = product_hi * 2^64 + product_lo
|
||||
uint64_t product_lo = bd + (adbc << 32);
|
||||
uint64_t product_lo_carry = product_lo < bd ? 1 : 0;
|
||||
*product_hi = (a * c) + (adbc >> 32) + (adbc_carry << 32) + product_lo_carry;
|
||||
|
||||
return product_lo;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#endif /* __CRYPTONIGHT_LITE_SOFTAES_H__ */
|
||||
@@ -1,244 +0,0 @@
|
||||
/* XMRig
|
||||
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com>
|
||||
* Copyright 2012-2014 pooler <pooler@litecoinpool.org>
|
||||
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
|
||||
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
|
||||
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
|
||||
* Copyright 2016-2017 XMRig <support@xmrig.com>
|
||||
*
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <mm_malloc.h>
|
||||
|
||||
#ifndef BUILD_TEST
|
||||
# include "xmrig.h"
|
||||
#endif
|
||||
|
||||
#include "crypto/c_groestl.h"
|
||||
#include "crypto/c_blake256.h"
|
||||
#include "crypto/c_jh.h"
|
||||
#include "crypto/c_skein.h"
|
||||
#include "cryptonight.h"
|
||||
#include "options.h"
|
||||
|
||||
|
||||
const static char test_input[152] = {
|
||||
0x01, 0x00, 0xFB, 0x8E, 0x8A, 0xC8, 0x05, 0x89, 0x93, 0x23, 0x37, 0x1B, 0xB7, 0x90, 0xDB, 0x19,
|
||||
0x21, 0x8A, 0xFD, 0x8D, 0xB8, 0xE3, 0x75, 0x5D, 0x8B, 0x90, 0xF3, 0x9B, 0x3D, 0x55, 0x06, 0xA9,
|
||||
0xAB, 0xCE, 0x4F, 0xA9, 0x12, 0x24, 0x45, 0x00, 0x00, 0x00, 0x00, 0xEE, 0x81, 0x46, 0xD4, 0x9F,
|
||||
0xA9, 0x3E, 0xE7, 0x24, 0xDE, 0xB5, 0x7D, 0x12, 0xCB, 0xC6, 0xC6, 0xF3, 0xB9, 0x24, 0xD9, 0x46,
|
||||
0x12, 0x7C, 0x7A, 0x97, 0x41, 0x8F, 0x93, 0x48, 0x82, 0x8F, 0x0F, 0x02,
|
||||
0x03, 0x05, 0xA0, 0xDB, 0xD6, 0xBF, 0x05, 0xCF, 0x16, 0xE5, 0x03, 0xF3, 0xA6, 0x6F, 0x78, 0x00,
|
||||
0x7C, 0xBF, 0x34, 0x14, 0x43, 0x32, 0xEC, 0xBF, 0xC2, 0x2E, 0xD9, 0x5C, 0x87, 0x00, 0x38, 0x3B,
|
||||
0x30, 0x9A, 0xCE, 0x19, 0x23, 0xA0, 0x96, 0x4B, 0x00, 0x00, 0x00, 0x08, 0xBA, 0x93, 0x9A, 0x62,
|
||||
0x72, 0x4C, 0x0D, 0x75, 0x81, 0xFC, 0xE5, 0x76, 0x1E, 0x9D, 0x8A, 0x0E, 0x6A, 0x1C, 0x3F, 0x92,
|
||||
0x4F, 0xDD, 0x84, 0x93, 0xD1, 0x11, 0x56, 0x49, 0xC0, 0x5E, 0xB6, 0x01
|
||||
};
|
||||
|
||||
|
||||
const static char test_output0[64] = {
|
||||
0x1B, 0x60, 0x6A, 0x3F, 0x4A, 0x07, 0xD6, 0x48, 0x9A, 0x1B, 0xCD, 0x07, 0x69, 0x7B, 0xD1, 0x66,
|
||||
0x96, 0xB6, 0x1C, 0x8A, 0xE9, 0x82, 0xF6, 0x1A, 0x90, 0x16, 0x0F, 0x4E, 0x52, 0x82, 0x8A, 0x7F,
|
||||
0x1A, 0x3F, 0xFB, 0xEE, 0x90, 0x9B, 0x42, 0x0D, 0x91, 0xF7, 0xBE, 0x6E, 0x5F, 0xB5, 0x6D, 0xB7,
|
||||
0x1B, 0x31, 0x10, 0xD8, 0x86, 0x01, 0x1E, 0x87, 0x7E, 0xE5, 0x78, 0x6A, 0xFD, 0x08, 0x01, 0x00
|
||||
};
|
||||
|
||||
|
||||
void cryptonight_av1_aesni(const void* input, size_t size, void* output, struct cryptonight_ctx* ctx);
|
||||
void cryptonight_av2_aesni_double(const void* input, size_t size, void* output, struct cryptonight_ctx* ctx);
|
||||
void cryptonight_av3_softaes(const void* input, size_t size, void* output, struct cryptonight_ctx* ctx);
|
||||
void cryptonight_av4_softaes_double(const void* input, size_t size, void* output, struct cryptonight_ctx* ctx);
|
||||
|
||||
#ifndef XMRIG_NO_AEON
|
||||
const static char test_output1[64] = {
|
||||
0x28, 0xA2, 0x2B, 0xAD, 0x3F, 0x93, 0xD1, 0x40, 0x8F, 0xCA, 0x47, 0x2E, 0xB5, 0xAD, 0x1C, 0xBE,
|
||||
0x75, 0xF2, 0x1D, 0x05, 0x3C, 0x8C, 0xE5, 0xB3, 0xAF, 0x10, 0x5A, 0x57, 0x71, 0x3E, 0x21, 0xDD,
|
||||
0x36, 0x95, 0xB4, 0xB5, 0x3B, 0xB0, 0x03, 0x58, 0xB0, 0xAD, 0x38, 0xDC, 0x16, 0x0F, 0xEB, 0x9E,
|
||||
0x00, 0x4E, 0xEC, 0xE0, 0x9B, 0x83, 0xA7, 0x2E, 0xF6, 0xBA, 0x98, 0x64, 0xD3, 0x51, 0x0C, 0x88,
|
||||
};
|
||||
|
||||
void cryptonight_lite_av1_aesni(const void* input, size_t size, void* output, struct cryptonight_ctx* ctx);
|
||||
void cryptonight_lite_av2_aesni_double(const void* input, size_t size, void* output, struct cryptonight_ctx* ctx);
|
||||
void cryptonight_lite_av3_softaes(const void* input, size_t size, void* output, struct cryptonight_ctx* ctx);
|
||||
void cryptonight_lite_av4_softaes_double(const void* input, size_t size, void* output, struct cryptonight_ctx* ctx);
|
||||
#endif
|
||||
|
||||
void (*cryptonight_hash_ctx)(const void* input, size_t size, void* output, struct cryptonight_ctx* ctx) = NULL;
|
||||
|
||||
|
||||
static bool self_test() {
|
||||
if (cryptonight_hash_ctx == NULL) {
|
||||
return false;
|
||||
}
|
||||
|
||||
char output[64];
|
||||
|
||||
struct cryptonight_ctx *ctx = (struct cryptonight_ctx*) _mm_malloc(sizeof(struct cryptonight_ctx), 16);
|
||||
ctx->memory = (uint8_t *) _mm_malloc(MEMORY * 2, 16);
|
||||
|
||||
cryptonight_hash_ctx(test_input, 76, output, ctx);
|
||||
|
||||
_mm_free(ctx->memory);
|
||||
_mm_free(ctx);
|
||||
|
||||
# ifndef XMRIG_NO_AEON
|
||||
if (opt_algo == ALGO_CRYPTONIGHT_LITE) {
|
||||
return memcmp(output, test_output1, (opt_double_hash ? 64 : 32)) == 0;
|
||||
}
|
||||
# endif
|
||||
|
||||
return memcmp(output, test_output0, (opt_double_hash ? 64 : 32)) == 0;
|
||||
}
|
||||
|
||||
|
||||
#ifndef XMRIG_NO_AEON
|
||||
bool cryptonight_lite_init(int variant) {
|
||||
switch (variant) {
|
||||
case AEON_AV1_AESNI:
|
||||
cryptonight_hash_ctx = cryptonight_lite_av1_aesni;
|
||||
break;
|
||||
|
||||
case AEON_AV2_AESNI_DOUBLE:
|
||||
opt_double_hash = true;
|
||||
cryptonight_hash_ctx = cryptonight_lite_av2_aesni_double;
|
||||
break;
|
||||
|
||||
case AEON_AV3_SOFT_AES:
|
||||
cryptonight_hash_ctx = cryptonight_lite_av3_softaes;
|
||||
break;
|
||||
|
||||
case AEON_AV4_SOFT_AES_DOUBLE:
|
||||
opt_double_hash = true;
|
||||
cryptonight_hash_ctx = cryptonight_lite_av4_softaes_double;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return self_test();
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
bool cryptonight_init(int variant)
|
||||
{
|
||||
# ifndef XMRIG_NO_AEON
|
||||
if (opt_algo == ALGO_CRYPTONIGHT_LITE) {
|
||||
return cryptonight_lite_init(variant);
|
||||
}
|
||||
# endif
|
||||
|
||||
switch (variant) {
|
||||
case XMR_AV1_AESNI:
|
||||
cryptonight_hash_ctx = cryptonight_av1_aesni;
|
||||
break;
|
||||
|
||||
case XMR_AV2_AESNI_DOUBLE:
|
||||
opt_double_hash = true;
|
||||
cryptonight_hash_ctx = cryptonight_av2_aesni_double;
|
||||
break;
|
||||
|
||||
case XMR_AV3_SOFT_AES:
|
||||
cryptonight_hash_ctx = cryptonight_av3_softaes;
|
||||
break;
|
||||
|
||||
case XMR_AV4_SOFT_AES_DOUBLE:
|
||||
opt_double_hash = true;
|
||||
cryptonight_hash_ctx = cryptonight_av4_softaes_double;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return self_test();
|
||||
}
|
||||
|
||||
|
||||
static inline void do_blake_hash(const void* input, size_t len, char* output) {
|
||||
blake256_hash((uint8_t*)output, input, len);
|
||||
}
|
||||
|
||||
|
||||
static inline void do_groestl_hash(const void* input, size_t len, char* output) {
|
||||
groestl(input, len * 8, (uint8_t*)output);
|
||||
}
|
||||
|
||||
|
||||
static inline void do_jh_hash(const void* input, size_t len, char* output) {
|
||||
jh_hash(32 * 8, input, 8 * len, (uint8_t*)output);
|
||||
}
|
||||
|
||||
|
||||
static inline void do_skein_hash(const void* input, size_t len, char* output) {
|
||||
skein_hash(8 * 32, input, 8 * len, (uint8_t*)output);
|
||||
}
|
||||
|
||||
|
||||
void (* const extra_hashes[4])(const void *, size_t, char *) = {do_blake_hash, do_groestl_hash, do_jh_hash, do_skein_hash};
|
||||
|
||||
|
||||
#ifndef BUILD_TEST
|
||||
int scanhash_cryptonight(int thr_id, uint32_t *hash, uint32_t *restrict blob, size_t blob_size, uint32_t target, uint32_t max_nonce, unsigned long *restrict hashes_done, struct cryptonight_ctx *restrict ctx) {
|
||||
uint32_t *nonceptr = (uint32_t*) (((char*) blob) + 39);
|
||||
|
||||
do {
|
||||
cryptonight_hash_ctx(blob, blob_size, hash, ctx);
|
||||
(*hashes_done)++;
|
||||
|
||||
if (unlikely(hash[7] < target)) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
(*nonceptr)++;
|
||||
} while (likely(((*nonceptr) < max_nonce && !work_restart[thr_id].restart)));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int scanhash_cryptonight_double(int thr_id, uint32_t *hash, uint8_t *restrict blob, size_t blob_size, uint32_t target, uint32_t max_nonce, unsigned long *restrict hashes_done, struct cryptonight_ctx *restrict ctx) {
|
||||
int rc = 0;
|
||||
uint32_t *nonceptr0 = (uint32_t*) (((char*) blob) + 39);
|
||||
uint32_t *nonceptr1 = (uint32_t*) (((char*) blob) + 39 + blob_size);
|
||||
|
||||
do {
|
||||
cryptonight_hash_ctx(blob, blob_size, hash, ctx);
|
||||
(*hashes_done) += 2;
|
||||
|
||||
if (unlikely(hash[7] < target)) {
|
||||
return rc |= 1;
|
||||
}
|
||||
|
||||
if (unlikely(hash[15] < target)) {
|
||||
return rc |= 2;
|
||||
}
|
||||
|
||||
if (rc) {
|
||||
break;
|
||||
}
|
||||
|
||||
(*nonceptr0)++;
|
||||
(*nonceptr1)++;
|
||||
} while (likely(((*nonceptr0) < max_nonce && !work_restart[thr_id].restart)));
|
||||
|
||||
return rc;
|
||||
}
|
||||
#endif
|
||||
@@ -1,256 +0,0 @@
|
||||
/* XMRig
|
||||
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com>
|
||||
* Copyright 2012-2014 pooler <pooler@litecoinpool.org>
|
||||
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
|
||||
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
|
||||
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
|
||||
* Copyright 2017 fireice-uk <https://github.com/fireice-uk>
|
||||
* Copyright 2016-2017 XMRig <support@xmrig.com>
|
||||
*
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef __CRYPTONIGHT_AESNI_H__
|
||||
#define __CRYPTONIGHT_AESNI_H__
|
||||
|
||||
#include <x86intrin.h>
|
||||
|
||||
|
||||
#define aes_genkey_sub(imm8) \
|
||||
__m128i xout1 = _mm_aeskeygenassist_si128(*xout2, (imm8)); \
|
||||
xout1 = _mm_shuffle_epi32(xout1, 0xFF); \
|
||||
*xout0 = sl_xor(*xout0); \
|
||||
*xout0 = _mm_xor_si128(*xout0, xout1); \
|
||||
xout1 = _mm_aeskeygenassist_si128(*xout0, 0x00);\
|
||||
xout1 = _mm_shuffle_epi32(xout1, 0xAA); \
|
||||
*xout2 = sl_xor(*xout2); \
|
||||
*xout2 = _mm_xor_si128(*xout2, xout1); \
|
||||
|
||||
|
||||
// This will shift and xor tmp1 into itself as 4 32-bit vals such as
|
||||
// sl_xor(a1 a2 a3 a4) = a1 (a2^a1) (a3^a2^a1) (a4^a3^a2^a1)
|
||||
inline __m128i sl_xor(__m128i tmp1)
|
||||
{
|
||||
__m128i tmp4;
|
||||
tmp4 = _mm_slli_si128(tmp1, 0x04);
|
||||
tmp1 = _mm_xor_si128(tmp1, tmp4);
|
||||
tmp4 = _mm_slli_si128(tmp4, 0x04);
|
||||
tmp1 = _mm_xor_si128(tmp1, tmp4);
|
||||
tmp4 = _mm_slli_si128(tmp4, 0x04);
|
||||
tmp1 = _mm_xor_si128(tmp1, tmp4);
|
||||
return tmp1;
|
||||
}
|
||||
|
||||
|
||||
inline void aes_genkey_sub1(__m128i* xout0, __m128i* xout2)
|
||||
{
|
||||
aes_genkey_sub(0x1)
|
||||
}
|
||||
|
||||
|
||||
inline void aes_genkey_sub2(__m128i* xout0, __m128i* xout2)
|
||||
{
|
||||
aes_genkey_sub(0x2)
|
||||
}
|
||||
|
||||
|
||||
inline void aes_genkey_sub4(__m128i* xout0, __m128i* xout2)
|
||||
{
|
||||
aes_genkey_sub(0x4)
|
||||
}
|
||||
|
||||
|
||||
inline void aes_genkey_sub8(__m128i* xout0, __m128i* xout2)
|
||||
{
|
||||
aes_genkey_sub(0x8)
|
||||
}
|
||||
|
||||
|
||||
inline void aes_round(__m128i key, __m128i* x0, __m128i* x1, __m128i* x2, __m128i* x3, __m128i* x4, __m128i* x5, __m128i* x6, __m128i* x7)
|
||||
{
|
||||
*x0 = _mm_aesenc_si128(*x0, key);
|
||||
*x1 = _mm_aesenc_si128(*x1, key);
|
||||
*x2 = _mm_aesenc_si128(*x2, key);
|
||||
*x3 = _mm_aesenc_si128(*x3, key);
|
||||
*x4 = _mm_aesenc_si128(*x4, key);
|
||||
*x5 = _mm_aesenc_si128(*x5, key);
|
||||
*x6 = _mm_aesenc_si128(*x6, key);
|
||||
*x7 = _mm_aesenc_si128(*x7, key);
|
||||
}
|
||||
|
||||
|
||||
inline void aes_genkey(const __m128i* memory, __m128i* k0, __m128i* k1, __m128i* k2, __m128i* k3, __m128i* k4, __m128i* k5, __m128i* k6, __m128i* k7, __m128i* k8, __m128i* k9)
|
||||
{
|
||||
__m128i xout0 = _mm_load_si128(memory);
|
||||
__m128i xout2 = _mm_load_si128(memory + 1);
|
||||
*k0 = xout0;
|
||||
*k1 = xout2;
|
||||
|
||||
aes_genkey_sub1(&xout0, &xout2);
|
||||
*k2 = xout0;
|
||||
*k3 = xout2;
|
||||
|
||||
aes_genkey_sub2(&xout0, &xout2);
|
||||
*k4 = xout0;
|
||||
*k5 = xout2;
|
||||
|
||||
aes_genkey_sub4(&xout0, &xout2);
|
||||
*k6 = xout0;
|
||||
*k7 = xout2;
|
||||
|
||||
aes_genkey_sub8(&xout0, &xout2);
|
||||
*k8 = xout0;
|
||||
*k9 = xout2;
|
||||
}
|
||||
|
||||
|
||||
inline void cn_explode_scratchpad(const __m128i* input, __m128i* output)
|
||||
{
|
||||
// This is more than we have registers, compiler will assign 2 keys on the stack
|
||||
__m128i xin0, xin1, xin2, xin3, xin4, xin5, xin6, xin7;
|
||||
__m128i k0, k1, k2, k3, k4, k5, k6, k7, k8, k9;
|
||||
|
||||
aes_genkey(input, &k0, &k1, &k2, &k3, &k4, &k5, &k6, &k7, &k8, &k9);
|
||||
|
||||
xin0 = _mm_load_si128(input + 4);
|
||||
xin1 = _mm_load_si128(input + 5);
|
||||
xin2 = _mm_load_si128(input + 6);
|
||||
xin3 = _mm_load_si128(input + 7);
|
||||
xin4 = _mm_load_si128(input + 8);
|
||||
xin5 = _mm_load_si128(input + 9);
|
||||
xin6 = _mm_load_si128(input + 10);
|
||||
xin7 = _mm_load_si128(input + 11);
|
||||
|
||||
for (size_t i = 0; __builtin_expect(i < MEMORY / sizeof(__m128i), 1); i += 8) {
|
||||
aes_round(k0, &xin0, &xin1, &xin2, &xin3, &xin4, &xin5, &xin6, &xin7);
|
||||
aes_round(k1, &xin0, &xin1, &xin2, &xin3, &xin4, &xin5, &xin6, &xin7);
|
||||
aes_round(k2, &xin0, &xin1, &xin2, &xin3, &xin4, &xin5, &xin6, &xin7);
|
||||
aes_round(k3, &xin0, &xin1, &xin2, &xin3, &xin4, &xin5, &xin6, &xin7);
|
||||
aes_round(k4, &xin0, &xin1, &xin2, &xin3, &xin4, &xin5, &xin6, &xin7);
|
||||
aes_round(k5, &xin0, &xin1, &xin2, &xin3, &xin4, &xin5, &xin6, &xin7);
|
||||
aes_round(k6, &xin0, &xin1, &xin2, &xin3, &xin4, &xin5, &xin6, &xin7);
|
||||
aes_round(k7, &xin0, &xin1, &xin2, &xin3, &xin4, &xin5, &xin6, &xin7);
|
||||
aes_round(k8, &xin0, &xin1, &xin2, &xin3, &xin4, &xin5, &xin6, &xin7);
|
||||
aes_round(k9, &xin0, &xin1, &xin2, &xin3, &xin4, &xin5, &xin6, &xin7);
|
||||
|
||||
_mm_store_si128(output + i + 0, xin0);
|
||||
_mm_store_si128(output + i + 1, xin1);
|
||||
_mm_store_si128(output + i + 2, xin2);
|
||||
_mm_store_si128(output + i + 3, xin3);
|
||||
_mm_store_si128(output + i + 4, xin4);
|
||||
_mm_store_si128(output + i + 5, xin5);
|
||||
_mm_store_si128(output + i + 6, xin6);
|
||||
_mm_store_si128(output + i + 7, xin7);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
inline void cn_implode_scratchpad(const __m128i* input, __m128i* output)
|
||||
{
|
||||
// This is more than we have registers, compiler will assign 2 keys on the stack
|
||||
__m128i xout0, xout1, xout2, xout3, xout4, xout5, xout6, xout7;
|
||||
__m128i k0, k1, k2, k3, k4, k5, k6, k7, k8, k9;
|
||||
|
||||
aes_genkey(output + 2, &k0, &k1, &k2, &k3, &k4, &k5, &k6, &k7, &k8, &k9);
|
||||
|
||||
xout0 = _mm_load_si128(output + 4);
|
||||
xout1 = _mm_load_si128(output + 5);
|
||||
xout2 = _mm_load_si128(output + 6);
|
||||
xout3 = _mm_load_si128(output + 7);
|
||||
xout4 = _mm_load_si128(output + 8);
|
||||
xout5 = _mm_load_si128(output + 9);
|
||||
xout6 = _mm_load_si128(output + 10);
|
||||
xout7 = _mm_load_si128(output + 11);
|
||||
|
||||
for (size_t i = 0; __builtin_expect(i < MEMORY / sizeof(__m128i), 1); i += 8)
|
||||
{
|
||||
xout0 = _mm_xor_si128(_mm_load_si128(input + i + 0), xout0);
|
||||
xout1 = _mm_xor_si128(_mm_load_si128(input + i + 1), xout1);
|
||||
xout2 = _mm_xor_si128(_mm_load_si128(input + i + 2), xout2);
|
||||
xout3 = _mm_xor_si128(_mm_load_si128(input + i + 3), xout3);
|
||||
xout4 = _mm_xor_si128(_mm_load_si128(input + i + 4), xout4);
|
||||
xout5 = _mm_xor_si128(_mm_load_si128(input + i + 5), xout5);
|
||||
xout6 = _mm_xor_si128(_mm_load_si128(input + i + 6), xout6);
|
||||
xout7 = _mm_xor_si128(_mm_load_si128(input + i + 7), xout7);
|
||||
|
||||
aes_round(k0, &xout0, &xout1, &xout2, &xout3, &xout4, &xout5, &xout6, &xout7);
|
||||
aes_round(k1, &xout0, &xout1, &xout2, &xout3, &xout4, &xout5, &xout6, &xout7);
|
||||
aes_round(k2, &xout0, &xout1, &xout2, &xout3, &xout4, &xout5, &xout6, &xout7);
|
||||
aes_round(k3, &xout0, &xout1, &xout2, &xout3, &xout4, &xout5, &xout6, &xout7);
|
||||
aes_round(k4, &xout0, &xout1, &xout2, &xout3, &xout4, &xout5, &xout6, &xout7);
|
||||
aes_round(k5, &xout0, &xout1, &xout2, &xout3, &xout4, &xout5, &xout6, &xout7);
|
||||
aes_round(k6, &xout0, &xout1, &xout2, &xout3, &xout4, &xout5, &xout6, &xout7);
|
||||
aes_round(k7, &xout0, &xout1, &xout2, &xout3, &xout4, &xout5, &xout6, &xout7);
|
||||
aes_round(k8, &xout0, &xout1, &xout2, &xout3, &xout4, &xout5, &xout6, &xout7);
|
||||
aes_round(k9, &xout0, &xout1, &xout2, &xout3, &xout4, &xout5, &xout6, &xout7);
|
||||
}
|
||||
|
||||
_mm_store_si128(output + 4, xout0);
|
||||
_mm_store_si128(output + 5, xout1);
|
||||
_mm_store_si128(output + 6, xout2);
|
||||
_mm_store_si128(output + 7, xout3);
|
||||
_mm_store_si128(output + 8, xout4);
|
||||
_mm_store_si128(output + 9, xout5);
|
||||
_mm_store_si128(output + 10, xout6);
|
||||
_mm_store_si128(output + 11, xout7);
|
||||
}
|
||||
|
||||
|
||||
#if defined(__x86_64__)
|
||||
# define EXTRACT64(X) _mm_cvtsi128_si64(X)
|
||||
|
||||
inline uint64_t _umul128(uint64_t a, uint64_t b, uint64_t* hi)
|
||||
{
|
||||
unsigned __int128 r = (unsigned __int128) a * (unsigned __int128) b;
|
||||
*hi = r >> 64;
|
||||
return (uint64_t) r;
|
||||
}
|
||||
#elif defined(__i386__)
|
||||
# define HI32(X) \
|
||||
_mm_srli_si128((X), 4)
|
||||
|
||||
|
||||
# define EXTRACT64(X) \
|
||||
((uint64_t)(uint32_t)_mm_cvtsi128_si32(X) | \
|
||||
((uint64_t)(uint32_t)_mm_cvtsi128_si32(HI32(X)) << 32))
|
||||
|
||||
inline uint64_t _umul128(uint64_t multiplier, uint64_t multiplicand, uint64_t *product_hi) {
|
||||
// multiplier = ab = a * 2^32 + b
|
||||
// multiplicand = cd = c * 2^32 + d
|
||||
// ab * cd = a * c * 2^64 + (a * d + b * c) * 2^32 + b * d
|
||||
uint64_t a = multiplier >> 32;
|
||||
uint64_t b = multiplier & 0xFFFFFFFF;
|
||||
uint64_t c = multiplicand >> 32;
|
||||
uint64_t d = multiplicand & 0xFFFFFFFF;
|
||||
|
||||
//uint64_t ac = a * c;
|
||||
uint64_t ad = a * d;
|
||||
//uint64_t bc = b * c;
|
||||
uint64_t bd = b * d;
|
||||
|
||||
uint64_t adbc = ad + (b * c);
|
||||
uint64_t adbc_carry = adbc < ad ? 1 : 0;
|
||||
|
||||
// multiplier * multiplicand = product_hi * 2^64 + product_lo
|
||||
uint64_t product_lo = bd + (adbc << 32);
|
||||
uint64_t product_lo_carry = product_lo < bd ? 1 : 0;
|
||||
*product_hi = (a * c) + (adbc >> 32) + (adbc_carry << 32) + product_lo_carry;
|
||||
|
||||
return product_lo;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#endif /* __CRYPTONIGHT_AESNI_H__ */
|
||||
@@ -1,77 +0,0 @@
|
||||
/* XMRig
|
||||
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com>
|
||||
* Copyright 2012-2014 pooler <pooler@litecoinpool.org>
|
||||
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
|
||||
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
|
||||
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
|
||||
* Copyright 2017 fireice-uk <https://github.com/fireice-uk>
|
||||
* Copyright 2016-2017 XMRig <support@xmrig.com>
|
||||
*
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <x86intrin.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "cryptonight.h"
|
||||
#include "cryptonight_aesni.h"
|
||||
#include "crypto/c_keccak.h"
|
||||
|
||||
|
||||
void cryptonight_av1_aesni(const void *restrict input, size_t size, void *restrict output, struct cryptonight_ctx *restrict ctx)
|
||||
{
|
||||
keccak((const uint8_t *) input, size, ctx->state0, 200);
|
||||
|
||||
cn_explode_scratchpad((__m128i*) ctx->state0, (__m128i*) ctx->memory);
|
||||
|
||||
const uint8_t* l0 = ctx->memory;
|
||||
uint64_t* h0 = (uint64_t*) ctx->state0;
|
||||
|
||||
uint64_t al0 = h0[0] ^ h0[4];
|
||||
uint64_t ah0 = h0[1] ^ h0[5];
|
||||
__m128i bx0 = _mm_set_epi64x(h0[3] ^ h0[7], h0[2] ^ h0[6]);
|
||||
|
||||
uint64_t idx0 = h0[0] ^ h0[4];
|
||||
|
||||
for (size_t i = 0; __builtin_expect(i < 0x80000, 1); i++) {
|
||||
__m128i cx;
|
||||
cx = _mm_load_si128((__m128i *) &l0[idx0 & 0x1FFFF0]);
|
||||
cx = _mm_aesenc_si128(cx, _mm_set_epi64x(ah0, al0));
|
||||
|
||||
_mm_store_si128((__m128i *) &l0[idx0 & 0x1FFFF0], _mm_xor_si128(bx0, cx));
|
||||
idx0 = EXTRACT64(cx);
|
||||
bx0 = cx;
|
||||
|
||||
uint64_t hi, lo, cl, ch;
|
||||
cl = ((uint64_t*) &l0[idx0 & 0x1FFFF0])[0];
|
||||
ch = ((uint64_t*) &l0[idx0 & 0x1FFFF0])[1];
|
||||
lo = _umul128(idx0, cl, &hi);
|
||||
|
||||
al0 += hi;
|
||||
ah0 += lo;
|
||||
|
||||
((uint64_t*)&l0[idx0 & 0x1FFFF0])[0] = al0;
|
||||
((uint64_t*)&l0[idx0 & 0x1FFFF0])[1] = ah0;
|
||||
|
||||
ah0 ^= ch;
|
||||
al0 ^= cl;
|
||||
idx0 = al0;
|
||||
}
|
||||
|
||||
cn_implode_scratchpad((__m128i*) ctx->memory, (__m128i*) ctx->state0);
|
||||
|
||||
keccakf(h0, 24);
|
||||
extra_hashes[ctx->state0[0] & 3](ctx->state0, 200, output);
|
||||
}
|
||||
@@ -1,111 +0,0 @@
|
||||
/* XMRig
|
||||
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com>
|
||||
* Copyright 2012-2014 pooler <pooler@litecoinpool.org>
|
||||
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
|
||||
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
|
||||
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
|
||||
* Copyright 2017 fireice-uk <https://github.com/fireice-uk>
|
||||
* Copyright 2016-2017 XMRig <support@xmrig.com>
|
||||
*
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <x86intrin.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "cryptonight.h"
|
||||
#include "cryptonight_aesni.h"
|
||||
#include "crypto/c_keccak.h"
|
||||
|
||||
|
||||
void cryptonight_av2_aesni_double(const void *restrict input, size_t size, void *restrict output, struct cryptonight_ctx *restrict ctx)
|
||||
{
|
||||
keccak((const uint8_t *) input, size, ctx->state0, 200);
|
||||
keccak((const uint8_t *) input + size, size, ctx->state1, 200);
|
||||
|
||||
const uint8_t* l0 = ctx->memory;
|
||||
const uint8_t* l1 = ctx->memory + MEMORY;
|
||||
uint64_t* h0 = (uint64_t*) ctx->state0;
|
||||
uint64_t* h1 = (uint64_t*) ctx->state1;
|
||||
|
||||
cn_explode_scratchpad((__m128i*) h0, (__m128i*) l0);
|
||||
cn_explode_scratchpad((__m128i*) h1, (__m128i*) l1);
|
||||
|
||||
uint64_t al0 = h0[0] ^ h0[4];
|
||||
uint64_t al1 = h1[0] ^ h1[4];
|
||||
uint64_t ah0 = h0[1] ^ h0[5];
|
||||
uint64_t ah1 = h1[1] ^ h1[5];
|
||||
|
||||
__m128i bx0 = _mm_set_epi64x(h0[3] ^ h0[7], h0[2] ^ h0[6]);
|
||||
__m128i bx1 = _mm_set_epi64x(h1[3] ^ h1[7], h1[2] ^ h1[6]);
|
||||
|
||||
uint64_t idx0 = h0[0] ^ h0[4];
|
||||
uint64_t idx1 = h1[0] ^ h1[4];
|
||||
|
||||
for (size_t i = 0; __builtin_expect(i < 0x80000, 1); i++) {
|
||||
__m128i cx0 = _mm_load_si128((__m128i *) &l0[idx0 & 0x1FFFF0]);
|
||||
__m128i cx1 = _mm_load_si128((__m128i *) &l1[idx1 & 0x1FFFF0]);
|
||||
|
||||
cx0 = _mm_aesenc_si128(cx0, _mm_set_epi64x(ah0, al0));
|
||||
cx1 = _mm_aesenc_si128(cx1, _mm_set_epi64x(ah1, al1));
|
||||
|
||||
_mm_store_si128((__m128i *) &l0[idx0 & 0x1FFFF0], _mm_xor_si128(bx0, cx0));
|
||||
_mm_store_si128((__m128i *) &l1[idx1 & 0x1FFFF0], _mm_xor_si128(bx1, cx1));
|
||||
|
||||
idx0 = EXTRACT64(cx0);
|
||||
idx1 = EXTRACT64(cx1);
|
||||
|
||||
bx0 = cx0;
|
||||
bx1 = cx1;
|
||||
|
||||
uint64_t hi, lo, cl, ch;
|
||||
cl = ((uint64_t*) &l0[idx0 & 0x1FFFF0])[0];
|
||||
ch = ((uint64_t*) &l0[idx0 & 0x1FFFF0])[1];
|
||||
lo = _umul128(idx0, cl, &hi);
|
||||
|
||||
al0 += hi;
|
||||
ah0 += lo;
|
||||
|
||||
((uint64_t*) &l0[idx0 & 0x1FFFF0])[0] = al0;
|
||||
((uint64_t*) &l0[idx0 & 0x1FFFF0])[1] = ah0;
|
||||
|
||||
ah0 ^= ch;
|
||||
al0 ^= cl;
|
||||
idx0 = al0;
|
||||
|
||||
cl = ((uint64_t*) &l1[idx1 & 0x1FFFF0])[0];
|
||||
ch = ((uint64_t*) &l1[idx1 & 0x1FFFF0])[1];
|
||||
lo = _umul128(idx1, cl, &hi);
|
||||
|
||||
al1 += hi;
|
||||
ah1 += lo;
|
||||
|
||||
((uint64_t*) &l1[idx1 & 0x1FFFF0])[0] = al1;
|
||||
((uint64_t*) &l1[idx1 & 0x1FFFF0])[1] = ah1;
|
||||
|
||||
ah1 ^= ch;
|
||||
al1 ^= cl;
|
||||
idx1 = al1;
|
||||
}
|
||||
|
||||
cn_implode_scratchpad((__m128i*) l0, (__m128i*) h0);
|
||||
cn_implode_scratchpad((__m128i*) l1, (__m128i*) h1);
|
||||
|
||||
keccakf(h0, 24);
|
||||
keccakf(h1, 24);
|
||||
|
||||
extra_hashes[ctx->state0[0] & 3](ctx->state0, 200, output);
|
||||
extra_hashes[ctx->state1[0] & 3](ctx->state1, 200, (char*) output + 32);
|
||||
}
|
||||
@@ -1,77 +0,0 @@
|
||||
/* XMRig
|
||||
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com>
|
||||
* Copyright 2012-2014 pooler <pooler@litecoinpool.org>
|
||||
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
|
||||
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
|
||||
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
|
||||
* Copyright 2017 fireice-uk <https://github.com/fireice-uk>
|
||||
* Copyright 2016-2017 XMRig <support@xmrig.com>
|
||||
*
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <x86intrin.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "cryptonight.h"
|
||||
#include "cryptonight_softaes.h"
|
||||
#include "crypto/c_keccak.h"
|
||||
|
||||
|
||||
void cryptonight_av3_softaes(const void *restrict input, size_t size, void *restrict output, struct cryptonight_ctx *restrict ctx)
|
||||
{
|
||||
keccak((const uint8_t *) input, size, ctx->state0, 200);
|
||||
|
||||
cn_explode_scratchpad((__m128i*) ctx->state0, (__m128i*) ctx->memory);
|
||||
|
||||
const uint8_t* l0 = ctx->memory;
|
||||
uint64_t* h0 = (uint64_t*) ctx->state0;
|
||||
|
||||
uint64_t al0 = h0[0] ^ h0[4];
|
||||
uint64_t ah0 = h0[1] ^ h0[5];
|
||||
__m128i bx0 = _mm_set_epi64x(h0[3] ^ h0[7], h0[2] ^ h0[6]);
|
||||
|
||||
uint64_t idx0 = h0[0] ^ h0[4];
|
||||
|
||||
for (size_t i = 0; __builtin_expect(i < 0x80000, 1); i++) {
|
||||
__m128i cx;
|
||||
cx = _mm_load_si128((__m128i *)&l0[idx0 & 0x1FFFF0]);
|
||||
cx = soft_aesenc(cx, _mm_set_epi64x(ah0, al0));
|
||||
|
||||
_mm_store_si128((__m128i *)&l0[idx0 & 0x1FFFF0], _mm_xor_si128(bx0, cx));
|
||||
idx0 = EXTRACT64(cx);
|
||||
bx0 = cx;
|
||||
|
||||
uint64_t hi, lo, cl, ch;
|
||||
cl = ((uint64_t*)&l0[idx0 & 0x1FFFF0])[0];
|
||||
ch = ((uint64_t*)&l0[idx0 & 0x1FFFF0])[1];
|
||||
lo = _umul128(idx0, cl, &hi);
|
||||
|
||||
al0 += hi;
|
||||
ah0 += lo;
|
||||
|
||||
((uint64_t*)&l0[idx0 & 0x1FFFF0])[0] = al0;
|
||||
((uint64_t*)&l0[idx0 & 0x1FFFF0])[1] = ah0;
|
||||
|
||||
ah0 ^= ch;
|
||||
al0 ^= cl;
|
||||
idx0 = al0;
|
||||
}
|
||||
|
||||
cn_implode_scratchpad((__m128i*) ctx->memory, (__m128i*) ctx->state0);
|
||||
|
||||
keccakf(h0, 24);
|
||||
extra_hashes[ctx->state0[0] & 3](ctx->state0, 200, output);
|
||||
}
|
||||
@@ -1,111 +0,0 @@
|
||||
/* XMRig
|
||||
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com>
|
||||
* Copyright 2012-2014 pooler <pooler@litecoinpool.org>
|
||||
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
|
||||
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
|
||||
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
|
||||
* Copyright 2017 fireice-uk <https://github.com/fireice-uk>
|
||||
* Copyright 2016-2017 XMRig <support@xmrig.com>
|
||||
*
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <x86intrin.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "cryptonight.h"
|
||||
#include "cryptonight_softaes.h"
|
||||
#include "crypto/c_keccak.h"
|
||||
|
||||
|
||||
void cryptonight_av4_softaes_double(const void *restrict input, size_t size, void *restrict output, struct cryptonight_ctx *restrict ctx)
|
||||
{
|
||||
keccak((const uint8_t *) input, size, ctx->state0, 200);
|
||||
keccak((const uint8_t *) input + size, size, ctx->state1, 200);
|
||||
|
||||
const uint8_t* l0 = ctx->memory;
|
||||
const uint8_t* l1 = ctx->memory + MEMORY;
|
||||
uint64_t* h0 = (uint64_t*) ctx->state0;
|
||||
uint64_t* h1 = (uint64_t*) ctx->state1;
|
||||
|
||||
cn_explode_scratchpad((__m128i*) h0, (__m128i*) l0);
|
||||
cn_explode_scratchpad((__m128i*) h1, (__m128i*) l1);
|
||||
|
||||
uint64_t al0 = h0[0] ^ h0[4];
|
||||
uint64_t al1 = h1[0] ^ h1[4];
|
||||
uint64_t ah0 = h0[1] ^ h0[5];
|
||||
uint64_t ah1 = h1[1] ^ h1[5];
|
||||
|
||||
__m128i bx0 = _mm_set_epi64x(h0[3] ^ h0[7], h0[2] ^ h0[6]);
|
||||
__m128i bx1 = _mm_set_epi64x(h1[3] ^ h1[7], h1[2] ^ h1[6]);
|
||||
|
||||
uint64_t idx0 = h0[0] ^ h0[4];
|
||||
uint64_t idx1 = h1[0] ^ h1[4];
|
||||
|
||||
for (size_t i = 0; __builtin_expect(i < 0x80000, 1); i++) {
|
||||
__m128i cx0 = _mm_load_si128((__m128i *) &l0[idx0 & 0x1FFFF0]);
|
||||
__m128i cx1 = _mm_load_si128((__m128i *) &l1[idx1 & 0x1FFFF0]);
|
||||
|
||||
cx0 = soft_aesenc(cx0, _mm_set_epi64x(ah0, al0));
|
||||
cx1 = soft_aesenc(cx1, _mm_set_epi64x(ah1, al1));
|
||||
|
||||
_mm_store_si128((__m128i *) &l0[idx0 & 0x1FFFF0], _mm_xor_si128(bx0, cx0));
|
||||
_mm_store_si128((__m128i *) &l1[idx1 & 0x1FFFF0], _mm_xor_si128(bx1, cx1));
|
||||
|
||||
idx0 = EXTRACT64(cx0);
|
||||
idx1 = EXTRACT64(cx1);
|
||||
|
||||
bx0 = cx0;
|
||||
bx1 = cx1;
|
||||
|
||||
uint64_t hi, lo, cl, ch;
|
||||
cl = ((uint64_t*) &l0[idx0 & 0x1FFFF0])[0];
|
||||
ch = ((uint64_t*) &l0[idx0 & 0x1FFFF0])[1];
|
||||
lo = _umul128(idx0, cl, &hi);
|
||||
|
||||
al0 += hi;
|
||||
ah0 += lo;
|
||||
|
||||
((uint64_t*) &l0[idx0 & 0x1FFFF0])[0] = al0;
|
||||
((uint64_t*) &l0[idx0 & 0x1FFFF0])[1] = ah0;
|
||||
|
||||
ah0 ^= ch;
|
||||
al0 ^= cl;
|
||||
idx0 = al0;
|
||||
|
||||
cl = ((uint64_t*) &l1[idx1 & 0x1FFFF0])[0];
|
||||
ch = ((uint64_t*) &l1[idx1 & 0x1FFFF0])[1];
|
||||
lo = _umul128(idx1, cl, &hi);
|
||||
|
||||
al1 += hi;
|
||||
ah1 += lo;
|
||||
|
||||
((uint64_t*) &l1[idx1 & 0x1FFFF0])[0] = al1;
|
||||
((uint64_t*) &l1[idx1 & 0x1FFFF0])[1] = ah1;
|
||||
|
||||
ah1 ^= ch;
|
||||
al1 ^= cl;
|
||||
idx1 = al1;
|
||||
}
|
||||
|
||||
cn_implode_scratchpad((__m128i*) l0, (__m128i*) h0);
|
||||
cn_implode_scratchpad((__m128i*) l1, (__m128i*) h1);
|
||||
|
||||
keccakf(h0, 24);
|
||||
keccakf(h1, 24);
|
||||
|
||||
extra_hashes[ctx->state0[0] & 3](ctx->state0, 200, output);
|
||||
extra_hashes[ctx->state1[0] & 3](ctx->state1, 200, (char*) output + 32);
|
||||
}
|
||||
@@ -1,237 +0,0 @@
|
||||
/* XMRig
|
||||
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com>
|
||||
* Copyright 2012-2014 pooler <pooler@litecoinpool.org>
|
||||
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
|
||||
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
|
||||
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
|
||||
* Copyright 2017 fireice-uk <https://github.com/fireice-uk>
|
||||
* Copyright 2016-2017 XMRig <support@xmrig.com>
|
||||
*
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef __CRYPTONIGHT_SOFTAES_H__
|
||||
#define __CRYPTONIGHT_SOFTAES_H__
|
||||
|
||||
#include <x86intrin.h>
|
||||
|
||||
extern __m128i soft_aesenc(__m128i in, __m128i key);
|
||||
extern __m128i soft_aeskeygenassist(__m128i key, uint8_t rcon);
|
||||
|
||||
|
||||
// This will shift and xor tmp1 into itself as 4 32-bit vals such as
|
||||
// sl_xor(a1 a2 a3 a4) = a1 (a2^a1) (a3^a2^a1) (a4^a3^a2^a1)
|
||||
inline __m128i sl_xor(__m128i tmp1)
|
||||
{
|
||||
__m128i tmp4;
|
||||
tmp4 = _mm_slli_si128(tmp1, 0x04);
|
||||
tmp1 = _mm_xor_si128(tmp1, tmp4);
|
||||
tmp4 = _mm_slli_si128(tmp4, 0x04);
|
||||
tmp1 = _mm_xor_si128(tmp1, tmp4);
|
||||
tmp4 = _mm_slli_si128(tmp4, 0x04);
|
||||
tmp1 = _mm_xor_si128(tmp1, tmp4);
|
||||
return tmp1;
|
||||
}
|
||||
|
||||
|
||||
inline void aes_genkey_sub(__m128i* xout0, __m128i* xout2, uint8_t rcon)
|
||||
{
|
||||
__m128i xout1 = soft_aeskeygenassist(*xout2, rcon);
|
||||
xout1 = _mm_shuffle_epi32(xout1, 0xFF); // see PSHUFD, set all elems to 4th elem
|
||||
*xout0 = sl_xor(*xout0);
|
||||
*xout0 = _mm_xor_si128(*xout0, xout1);
|
||||
xout1 = soft_aeskeygenassist(*xout0, 0x00);
|
||||
xout1 = _mm_shuffle_epi32(xout1, 0xAA); // see PSHUFD, set all elems to 3rd elem
|
||||
*xout2 = sl_xor(*xout2);
|
||||
*xout2 = _mm_xor_si128(*xout2, xout1);
|
||||
}
|
||||
|
||||
|
||||
inline void aes_round(__m128i key, __m128i* x0, __m128i* x1, __m128i* x2, __m128i* x3, __m128i* x4, __m128i* x5, __m128i* x6, __m128i* x7)
|
||||
{
|
||||
*x0 = soft_aesenc(*x0, key);
|
||||
*x1 = soft_aesenc(*x1, key);
|
||||
*x2 = soft_aesenc(*x2, key);
|
||||
*x3 = soft_aesenc(*x3, key);
|
||||
*x4 = soft_aesenc(*x4, key);
|
||||
*x5 = soft_aesenc(*x5, key);
|
||||
*x6 = soft_aesenc(*x6, key);
|
||||
*x7 = soft_aesenc(*x7, key);
|
||||
}
|
||||
|
||||
|
||||
inline void aes_genkey(const __m128i* memory, __m128i* k0, __m128i* k1, __m128i* k2, __m128i* k3, __m128i* k4, __m128i* k5, __m128i* k6, __m128i* k7, __m128i* k8, __m128i* k9)
|
||||
{
|
||||
__m128i xout0 = _mm_load_si128(memory);
|
||||
__m128i xout2 = _mm_load_si128(memory + 1);
|
||||
*k0 = xout0;
|
||||
*k1 = xout2;
|
||||
|
||||
aes_genkey_sub(&xout0, &xout2, 0x1);
|
||||
*k2 = xout0;
|
||||
*k3 = xout2;
|
||||
|
||||
aes_genkey_sub(&xout0, &xout2, 0x2);
|
||||
*k4 = xout0;
|
||||
*k5 = xout2;
|
||||
|
||||
aes_genkey_sub(&xout0, &xout2, 0x4);
|
||||
*k6 = xout0;
|
||||
*k7 = xout2;
|
||||
|
||||
aes_genkey_sub(&xout0, &xout2, 0x8);
|
||||
*k8 = xout0;
|
||||
*k9 = xout2;
|
||||
}
|
||||
|
||||
|
||||
inline void cn_explode_scratchpad(const __m128i* input, __m128i* output)
|
||||
{
|
||||
// This is more than we have registers, compiler will assign 2 keys on the stack
|
||||
__m128i xin0, xin1, xin2, xin3, xin4, xin5, xin6, xin7;
|
||||
__m128i k0, k1, k2, k3, k4, k5, k6, k7, k8, k9;
|
||||
|
||||
aes_genkey(input, &k0, &k1, &k2, &k3, &k4, &k5, &k6, &k7, &k8, &k9);
|
||||
|
||||
xin0 = _mm_load_si128(input + 4);
|
||||
xin1 = _mm_load_si128(input + 5);
|
||||
xin2 = _mm_load_si128(input + 6);
|
||||
xin3 = _mm_load_si128(input + 7);
|
||||
xin4 = _mm_load_si128(input + 8);
|
||||
xin5 = _mm_load_si128(input + 9);
|
||||
xin6 = _mm_load_si128(input + 10);
|
||||
xin7 = _mm_load_si128(input + 11);
|
||||
|
||||
for (size_t i = 0; i < MEMORY / sizeof(__m128i); i += 8) {
|
||||
aes_round(k0, &xin0, &xin1, &xin2, &xin3, &xin4, &xin5, &xin6, &xin7);
|
||||
aes_round(k1, &xin0, &xin1, &xin2, &xin3, &xin4, &xin5, &xin6, &xin7);
|
||||
aes_round(k2, &xin0, &xin1, &xin2, &xin3, &xin4, &xin5, &xin6, &xin7);
|
||||
aes_round(k3, &xin0, &xin1, &xin2, &xin3, &xin4, &xin5, &xin6, &xin7);
|
||||
aes_round(k4, &xin0, &xin1, &xin2, &xin3, &xin4, &xin5, &xin6, &xin7);
|
||||
aes_round(k5, &xin0, &xin1, &xin2, &xin3, &xin4, &xin5, &xin6, &xin7);
|
||||
aes_round(k6, &xin0, &xin1, &xin2, &xin3, &xin4, &xin5, &xin6, &xin7);
|
||||
aes_round(k7, &xin0, &xin1, &xin2, &xin3, &xin4, &xin5, &xin6, &xin7);
|
||||
aes_round(k8, &xin0, &xin1, &xin2, &xin3, &xin4, &xin5, &xin6, &xin7);
|
||||
aes_round(k9, &xin0, &xin1, &xin2, &xin3, &xin4, &xin5, &xin6, &xin7);
|
||||
|
||||
_mm_store_si128(output + i + 0, xin0);
|
||||
_mm_store_si128(output + i + 1, xin1);
|
||||
_mm_store_si128(output + i + 2, xin2);
|
||||
_mm_store_si128(output + i + 3, xin3);
|
||||
_mm_store_si128(output + i + 4, xin4);
|
||||
_mm_store_si128(output + i + 5, xin5);
|
||||
_mm_store_si128(output + i + 6, xin6);
|
||||
_mm_store_si128(output + i + 7, xin7);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
inline void cn_implode_scratchpad(const __m128i* input, __m128i* output)
|
||||
{
|
||||
// This is more than we have registers, compiler will assign 2 keys on the stack
|
||||
__m128i xout0, xout1, xout2, xout3, xout4, xout5, xout6, xout7;
|
||||
__m128i k0, k1, k2, k3, k4, k5, k6, k7, k8, k9;
|
||||
|
||||
aes_genkey(output + 2, &k0, &k1, &k2, &k3, &k4, &k5, &k6, &k7, &k8, &k9);
|
||||
|
||||
xout0 = _mm_load_si128(output + 4);
|
||||
xout1 = _mm_load_si128(output + 5);
|
||||
xout2 = _mm_load_si128(output + 6);
|
||||
xout3 = _mm_load_si128(output + 7);
|
||||
xout4 = _mm_load_si128(output + 8);
|
||||
xout5 = _mm_load_si128(output + 9);
|
||||
xout6 = _mm_load_si128(output + 10);
|
||||
xout7 = _mm_load_si128(output + 11);
|
||||
|
||||
for (size_t i = 0; __builtin_expect(i < MEMORY / sizeof(__m128i), 1); i += 8)
|
||||
{
|
||||
xout0 = _mm_xor_si128(_mm_load_si128(input + i + 0), xout0);
|
||||
xout1 = _mm_xor_si128(_mm_load_si128(input + i + 1), xout1);
|
||||
xout2 = _mm_xor_si128(_mm_load_si128(input + i + 2), xout2);
|
||||
xout3 = _mm_xor_si128(_mm_load_si128(input + i + 3), xout3);
|
||||
xout4 = _mm_xor_si128(_mm_load_si128(input + i + 4), xout4);
|
||||
xout5 = _mm_xor_si128(_mm_load_si128(input + i + 5), xout5);
|
||||
xout6 = _mm_xor_si128(_mm_load_si128(input + i + 6), xout6);
|
||||
xout7 = _mm_xor_si128(_mm_load_si128(input + i + 7), xout7);
|
||||
|
||||
aes_round(k0, &xout0, &xout1, &xout2, &xout3, &xout4, &xout5, &xout6, &xout7);
|
||||
aes_round(k1, &xout0, &xout1, &xout2, &xout3, &xout4, &xout5, &xout6, &xout7);
|
||||
aes_round(k2, &xout0, &xout1, &xout2, &xout3, &xout4, &xout5, &xout6, &xout7);
|
||||
aes_round(k3, &xout0, &xout1, &xout2, &xout3, &xout4, &xout5, &xout6, &xout7);
|
||||
aes_round(k4, &xout0, &xout1, &xout2, &xout3, &xout4, &xout5, &xout6, &xout7);
|
||||
aes_round(k5, &xout0, &xout1, &xout2, &xout3, &xout4, &xout5, &xout6, &xout7);
|
||||
aes_round(k6, &xout0, &xout1, &xout2, &xout3, &xout4, &xout5, &xout6, &xout7);
|
||||
aes_round(k7, &xout0, &xout1, &xout2, &xout3, &xout4, &xout5, &xout6, &xout7);
|
||||
aes_round(k8, &xout0, &xout1, &xout2, &xout3, &xout4, &xout5, &xout6, &xout7);
|
||||
aes_round(k9, &xout0, &xout1, &xout2, &xout3, &xout4, &xout5, &xout6, &xout7);
|
||||
}
|
||||
|
||||
_mm_store_si128(output + 4, xout0);
|
||||
_mm_store_si128(output + 5, xout1);
|
||||
_mm_store_si128(output + 6, xout2);
|
||||
_mm_store_si128(output + 7, xout3);
|
||||
_mm_store_si128(output + 8, xout4);
|
||||
_mm_store_si128(output + 9, xout5);
|
||||
_mm_store_si128(output + 10, xout6);
|
||||
_mm_store_si128(output + 11, xout7);
|
||||
}
|
||||
|
||||
|
||||
#if defined(__x86_64__)
|
||||
# define EXTRACT64(X) _mm_cvtsi128_si64(X)
|
||||
|
||||
inline uint64_t _umul128(uint64_t a, uint64_t b, uint64_t* hi)
|
||||
{
|
||||
unsigned __int128 r = (unsigned __int128) a * (unsigned __int128) b;
|
||||
*hi = r >> 64;
|
||||
return (uint64_t) r;
|
||||
}
|
||||
#elif defined(__i386__)
|
||||
# define HI32(X) \
|
||||
_mm_srli_si128((X), 4)
|
||||
|
||||
|
||||
# define EXTRACT64(X) \
|
||||
((uint64_t)(uint32_t)_mm_cvtsi128_si32(X) | \
|
||||
((uint64_t)(uint32_t)_mm_cvtsi128_si32(HI32(X)) << 32))
|
||||
|
||||
inline uint64_t _umul128(uint64_t multiplier, uint64_t multiplicand, uint64_t *product_hi) {
|
||||
// multiplier = ab = a * 2^32 + b
|
||||
// multiplicand = cd = c * 2^32 + d
|
||||
// ab * cd = a * c * 2^64 + (a * d + b * c) * 2^32 + b * d
|
||||
uint64_t a = multiplier >> 32;
|
||||
uint64_t b = multiplier & 0xFFFFFFFF;
|
||||
uint64_t c = multiplicand >> 32;
|
||||
uint64_t d = multiplicand & 0xFFFFFFFF;
|
||||
|
||||
//uint64_t ac = a * c;
|
||||
uint64_t ad = a * d;
|
||||
//uint64_t bc = b * c;
|
||||
uint64_t bd = b * d;
|
||||
|
||||
uint64_t adbc = ad + (b * c);
|
||||
uint64_t adbc_carry = adbc < ad ? 1 : 0;
|
||||
|
||||
// multiplier * multiplicand = product_hi * 2^64 + product_lo
|
||||
uint64_t product_lo = bd + (adbc << 32);
|
||||
uint64_t product_lo_carry = product_lo < bd ? 1 : 0;
|
||||
*product_hi = (a * c) + (adbc >> 32) + (adbc_carry << 32) + product_lo_carry;
|
||||
|
||||
return product_lo;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#endif /* __CRYPTONIGHT_SOFTAES_H__ */
|
||||
39
cmake/FindMHD.cmake
Normal file
39
cmake/FindMHD.cmake
Normal file
@@ -0,0 +1,39 @@
|
||||
# - Try to find MHD
|
||||
# Once done this will define
|
||||
#
|
||||
# MHD_FOUND - system has MHD
|
||||
# MHD_INCLUDE_DIRS - the MHD include directory
|
||||
# MHD_LIBRARY - Link these to use MHD
|
||||
|
||||
find_path(
|
||||
MHD_INCLUDE_DIR
|
||||
NAMES microhttpd.h
|
||||
DOC "microhttpd include dir"
|
||||
)
|
||||
|
||||
find_library(
|
||||
MHD_LIBRARY
|
||||
NAMES microhttpd microhttpd-10 libmicrohttpd libmicrohttpd-dll
|
||||
DOC "microhttpd library"
|
||||
)
|
||||
|
||||
set(MHD_INCLUDE_DIRS ${MHD_INCLUDE_DIR})
|
||||
set(MHD_LIBRARIES ${MHD_LIBRARY})
|
||||
|
||||
# debug library on windows
|
||||
# same naming convention as in qt (appending debug library with d)
|
||||
# boost is using the same "hack" as us with "optimized" and "debug"
|
||||
# official MHD project actually uses _d suffix
|
||||
if (${CMAKE_CXX_COMPILER_ID} STREQUAL MSVC)
|
||||
find_library(
|
||||
MHD_LIBRARY_DEBUG
|
||||
NAMES microhttpd_d microhttpd-10_d libmicrohttpd_d libmicrohttpd-dll_d
|
||||
DOC "mhd debug library"
|
||||
)
|
||||
set(MHD_LIBRARIES optimized ${MHD_LIBRARIES} debug ${MHD_LIBRARY_DEBUG})
|
||||
endif()
|
||||
|
||||
include(FindPackageHandleStandardArgs)
|
||||
find_package_handle_standard_args(mhd DEFAULT_MSG MHD_INCLUDE_DIR MHD_LIBRARY)
|
||||
mark_as_advanced(MHD_INCLUDE_DIR MHD_LIBRARY)
|
||||
|
||||
8
cmake/FindUV.cmake
Normal file
8
cmake/FindUV.cmake
Normal file
@@ -0,0 +1,8 @@
|
||||
find_path(UV_INCLUDE_DIR NAMES uv.h)
|
||||
find_library(UV_LIBRARY NAMES uv libuv)
|
||||
|
||||
set(UV_LIBRARIES ${UV_LIBRARY})
|
||||
set(UV_INCLUDE_DIRS ${UV_INCLUDE_DIR})
|
||||
|
||||
include(FindPackageHandleStandardArgs)
|
||||
find_package_handle_standard_args(UV DEFAULT_MSG UV_LIBRARY UV_INCLUDE_DIR)
|
||||
@@ -1,23 +0,0 @@
|
||||
cmake_minimum_required (VERSION 2.8)
|
||||
project (jansson C)
|
||||
|
||||
add_definitions(-DHAVE_CONFIG_H)
|
||||
|
||||
# Add the lib sources.
|
||||
file(GLOB JANSSON_SRC *.c)
|
||||
|
||||
set(JANSSON_HDR_PRIVATE
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/hashtable.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/jansson_private.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/strbuffer.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/utf.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/jansson_private_config.h)
|
||||
|
||||
set(JANSSON_HDR_PUBLIC
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/jansson_config.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/jansson.h)
|
||||
|
||||
add_library(jansson STATIC
|
||||
${JANSSON_SRC}
|
||||
${JANSSON_HDR_PRIVATE}
|
||||
${JANSSON_HDR_PUBLIC})
|
||||
@@ -1,19 +0,0 @@
|
||||
Copyright (c) 2009-2014 Petri Lehtinen <petri@digip.org>
|
||||
|
||||
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.
|
||||
@@ -1,446 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2009-2016 Petri Lehtinen <petri@digip.org>
|
||||
*
|
||||
* Jansson is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the MIT license. See LICENSE for details.
|
||||
*/
|
||||
|
||||
#ifndef _GNU_SOURCE
|
||||
#define _GNU_SOURCE
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include "jansson.h"
|
||||
#include "jansson_private.h"
|
||||
#include "strbuffer.h"
|
||||
#include "utf.h"
|
||||
|
||||
#define MAX_INTEGER_STR_LENGTH 100
|
||||
#define MAX_REAL_STR_LENGTH 100
|
||||
|
||||
#define FLAGS_TO_INDENT(f) ((f) & 0x1F)
|
||||
#define FLAGS_TO_PRECISION(f) (((f) >> 11) & 0x1F)
|
||||
|
||||
static int dump_to_strbuffer(const char *buffer, size_t size, void *data)
|
||||
{
|
||||
return strbuffer_append_bytes((strbuffer_t *)data, buffer, size);
|
||||
}
|
||||
|
||||
static int dump_to_file(const char *buffer, size_t size, void *data)
|
||||
{
|
||||
FILE *dest = (FILE *)data;
|
||||
if(fwrite(buffer, size, 1, dest) != 1)
|
||||
return -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* 32 spaces (the maximum indentation size) */
|
||||
static const char whitespace[] = " ";
|
||||
|
||||
static int dump_indent(size_t flags, int depth, int space, json_dump_callback_t dump, void *data)
|
||||
{
|
||||
if(FLAGS_TO_INDENT(flags) > 0)
|
||||
{
|
||||
unsigned int ws_count = FLAGS_TO_INDENT(flags), n_spaces = depth * ws_count;
|
||||
|
||||
if(dump("\n", 1, data))
|
||||
return -1;
|
||||
|
||||
while(n_spaces > 0)
|
||||
{
|
||||
int cur_n = n_spaces < sizeof whitespace - 1 ? n_spaces : sizeof whitespace - 1;
|
||||
|
||||
if(dump(whitespace, cur_n, data))
|
||||
return -1;
|
||||
|
||||
n_spaces -= cur_n;
|
||||
}
|
||||
}
|
||||
else if(space && !(flags & JSON_COMPACT))
|
||||
{
|
||||
return dump(" ", 1, data);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int dump_string(const char *str, size_t len, json_dump_callback_t dump, void *data, size_t flags)
|
||||
{
|
||||
const char *pos, *end, *lim;
|
||||
int32_t codepoint;
|
||||
|
||||
if(dump("\"", 1, data))
|
||||
return -1;
|
||||
|
||||
end = pos = str;
|
||||
lim = str + len;
|
||||
while(1)
|
||||
{
|
||||
const char *text;
|
||||
char seq[13];
|
||||
int length;
|
||||
|
||||
while(end < lim)
|
||||
{
|
||||
end = utf8_iterate(pos, lim - pos, &codepoint);
|
||||
if(!end)
|
||||
return -1;
|
||||
|
||||
/* mandatory escape or control char */
|
||||
if(codepoint == '\\' || codepoint == '"' || codepoint < 0x20)
|
||||
break;
|
||||
|
||||
/* slash */
|
||||
if((flags & JSON_ESCAPE_SLASH) && codepoint == '/')
|
||||
break;
|
||||
|
||||
/* non-ASCII */
|
||||
if((flags & JSON_ENSURE_ASCII) && codepoint > 0x7F)
|
||||
break;
|
||||
|
||||
pos = end;
|
||||
}
|
||||
|
||||
if(pos != str) {
|
||||
if(dump(str, pos - str, data))
|
||||
return -1;
|
||||
}
|
||||
|
||||
if(end == pos)
|
||||
break;
|
||||
|
||||
/* handle \, /, ", and control codes */
|
||||
length = 2;
|
||||
switch(codepoint)
|
||||
{
|
||||
case '\\': text = "\\\\"; break;
|
||||
case '\"': text = "\\\""; break;
|
||||
case '\b': text = "\\b"; break;
|
||||
case '\f': text = "\\f"; break;
|
||||
case '\n': text = "\\n"; break;
|
||||
case '\r': text = "\\r"; break;
|
||||
case '\t': text = "\\t"; break;
|
||||
case '/': text = "\\/"; break;
|
||||
default:
|
||||
{
|
||||
/* codepoint is in BMP */
|
||||
if(codepoint < 0x10000)
|
||||
{
|
||||
snprintf(seq, sizeof(seq), "\\u%04X", (unsigned int)codepoint);
|
||||
length = 6;
|
||||
}
|
||||
|
||||
/* not in BMP -> construct a UTF-16 surrogate pair */
|
||||
else
|
||||
{
|
||||
int32_t first, last;
|
||||
|
||||
codepoint -= 0x10000;
|
||||
first = 0xD800 | ((codepoint & 0xffc00) >> 10);
|
||||
last = 0xDC00 | (codepoint & 0x003ff);
|
||||
|
||||
snprintf(seq, sizeof(seq), "\\u%04X\\u%04X", (unsigned int)first, (unsigned int)last);
|
||||
length = 12;
|
||||
}
|
||||
|
||||
text = seq;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(dump(text, length, data))
|
||||
return -1;
|
||||
|
||||
str = pos = end;
|
||||
}
|
||||
|
||||
return dump("\"", 1, data);
|
||||
}
|
||||
|
||||
static int compare_keys(const void *key1, const void *key2)
|
||||
{
|
||||
return strcmp(*(const char **)key1, *(const char **)key2);
|
||||
}
|
||||
|
||||
static int do_dump(const json_t *json, size_t flags, int depth,
|
||||
json_dump_callback_t dump, void *data)
|
||||
{
|
||||
if(!json)
|
||||
return -1;
|
||||
|
||||
switch(json_typeof(json)) {
|
||||
case JSON_NULL:
|
||||
return dump("null", 4, data);
|
||||
|
||||
case JSON_TRUE:
|
||||
return dump("true", 4, data);
|
||||
|
||||
case JSON_FALSE:
|
||||
return dump("false", 5, data);
|
||||
|
||||
case JSON_INTEGER:
|
||||
{
|
||||
char buffer[MAX_INTEGER_STR_LENGTH];
|
||||
int size;
|
||||
|
||||
size = snprintf(buffer, MAX_INTEGER_STR_LENGTH,
|
||||
"%" JSON_INTEGER_FORMAT,
|
||||
json_integer_value(json));
|
||||
if(size < 0 || size >= MAX_INTEGER_STR_LENGTH)
|
||||
return -1;
|
||||
|
||||
return dump(buffer, size, data);
|
||||
}
|
||||
|
||||
case JSON_REAL:
|
||||
{
|
||||
char buffer[MAX_REAL_STR_LENGTH];
|
||||
int size;
|
||||
double value = json_real_value(json);
|
||||
|
||||
size = jsonp_dtostr(buffer, MAX_REAL_STR_LENGTH, value,
|
||||
FLAGS_TO_PRECISION(flags));
|
||||
if(size < 0)
|
||||
return -1;
|
||||
|
||||
return dump(buffer, size, data);
|
||||
}
|
||||
|
||||
case JSON_STRING:
|
||||
return dump_string(json_string_value(json), json_string_length(json), dump, data, flags);
|
||||
|
||||
case JSON_ARRAY:
|
||||
{
|
||||
size_t n;
|
||||
size_t i;
|
||||
|
||||
json_array_t *array;
|
||||
|
||||
/* detect circular references */
|
||||
array = json_to_array(json);
|
||||
if(array->visited)
|
||||
goto array_error;
|
||||
array->visited = 1;
|
||||
|
||||
n = json_array_size(json);
|
||||
|
||||
if(dump("[", 1, data))
|
||||
goto array_error;
|
||||
if(n == 0) {
|
||||
array->visited = 0;
|
||||
return dump("]", 1, data);
|
||||
}
|
||||
if(dump_indent(flags, depth + 1, 0, dump, data))
|
||||
goto array_error;
|
||||
|
||||
for(i = 0; i < n; ++i) {
|
||||
if(do_dump(json_array_get(json, i), flags, depth + 1,
|
||||
dump, data))
|
||||
goto array_error;
|
||||
|
||||
if(i < n - 1)
|
||||
{
|
||||
if(dump(",", 1, data) ||
|
||||
dump_indent(flags, depth + 1, 1, dump, data))
|
||||
goto array_error;
|
||||
}
|
||||
else
|
||||
{
|
||||
if(dump_indent(flags, depth, 0, dump, data))
|
||||
goto array_error;
|
||||
}
|
||||
}
|
||||
|
||||
array->visited = 0;
|
||||
return dump("]", 1, data);
|
||||
|
||||
array_error:
|
||||
array->visited = 0;
|
||||
return -1;
|
||||
}
|
||||
|
||||
case JSON_OBJECT:
|
||||
{
|
||||
json_object_t *object;
|
||||
void *iter;
|
||||
const char *separator;
|
||||
int separator_length;
|
||||
|
||||
if(flags & JSON_COMPACT) {
|
||||
separator = ":";
|
||||
separator_length = 1;
|
||||
}
|
||||
else {
|
||||
separator = ": ";
|
||||
separator_length = 2;
|
||||
}
|
||||
|
||||
/* detect circular references */
|
||||
object = json_to_object(json);
|
||||
if(object->visited)
|
||||
goto object_error;
|
||||
object->visited = 1;
|
||||
|
||||
iter = json_object_iter((json_t *)json);
|
||||
|
||||
if(dump("{", 1, data))
|
||||
goto object_error;
|
||||
if(!iter) {
|
||||
object->visited = 0;
|
||||
return dump("}", 1, data);
|
||||
}
|
||||
if(dump_indent(flags, depth + 1, 0, dump, data))
|
||||
goto object_error;
|
||||
|
||||
if(flags & JSON_SORT_KEYS)
|
||||
{
|
||||
const char **keys;
|
||||
size_t size, i;
|
||||
|
||||
size = json_object_size(json);
|
||||
keys = jsonp_malloc(size * sizeof(const char *));
|
||||
if(!keys)
|
||||
goto object_error;
|
||||
|
||||
i = 0;
|
||||
while(iter)
|
||||
{
|
||||
keys[i] = json_object_iter_key(iter);
|
||||
iter = json_object_iter_next((json_t *)json, iter);
|
||||
i++;
|
||||
}
|
||||
assert(i == size);
|
||||
|
||||
qsort(keys, size, sizeof(const char *), compare_keys);
|
||||
|
||||
for(i = 0; i < size; i++)
|
||||
{
|
||||
const char *key;
|
||||
json_t *value;
|
||||
|
||||
key = keys[i];
|
||||
value = json_object_get(json, key);
|
||||
assert(value);
|
||||
|
||||
dump_string(key, strlen(key), dump, data, flags);
|
||||
if(dump(separator, separator_length, data) ||
|
||||
do_dump(value, flags, depth + 1, dump, data))
|
||||
{
|
||||
jsonp_free(keys);
|
||||
goto object_error;
|
||||
}
|
||||
|
||||
if(i < size - 1)
|
||||
{
|
||||
if(dump(",", 1, data) ||
|
||||
dump_indent(flags, depth + 1, 1, dump, data))
|
||||
{
|
||||
jsonp_free(keys);
|
||||
goto object_error;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if(dump_indent(flags, depth, 0, dump, data))
|
||||
{
|
||||
jsonp_free(keys);
|
||||
goto object_error;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
jsonp_free(keys);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Don't sort keys */
|
||||
|
||||
while(iter)
|
||||
{
|
||||
void *next = json_object_iter_next((json_t *)json, iter);
|
||||
const char *key = json_object_iter_key(iter);
|
||||
|
||||
dump_string(key, strlen(key), dump, data, flags);
|
||||
if(dump(separator, separator_length, data) ||
|
||||
do_dump(json_object_iter_value(iter), flags, depth + 1,
|
||||
dump, data))
|
||||
goto object_error;
|
||||
|
||||
if(next)
|
||||
{
|
||||
if(dump(",", 1, data) ||
|
||||
dump_indent(flags, depth + 1, 1, dump, data))
|
||||
goto object_error;
|
||||
}
|
||||
else
|
||||
{
|
||||
if(dump_indent(flags, depth, 0, dump, data))
|
||||
goto object_error;
|
||||
}
|
||||
|
||||
iter = next;
|
||||
}
|
||||
}
|
||||
|
||||
object->visited = 0;
|
||||
return dump("}", 1, data);
|
||||
|
||||
object_error:
|
||||
object->visited = 0;
|
||||
return -1;
|
||||
}
|
||||
|
||||
default:
|
||||
/* not reached */
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
char *json_dumps(const json_t *json, size_t flags)
|
||||
{
|
||||
strbuffer_t strbuff;
|
||||
char *result;
|
||||
|
||||
if(strbuffer_init(&strbuff))
|
||||
return NULL;
|
||||
|
||||
if(json_dump_callback(json, dump_to_strbuffer, (void *)&strbuff, flags))
|
||||
result = NULL;
|
||||
else
|
||||
result = jsonp_strdup(strbuffer_value(&strbuff));
|
||||
|
||||
strbuffer_close(&strbuff);
|
||||
return result;
|
||||
}
|
||||
|
||||
int json_dumpf(const json_t *json, FILE *output, size_t flags)
|
||||
{
|
||||
return json_dump_callback(json, dump_to_file, (void *)output, flags);
|
||||
}
|
||||
|
||||
int json_dump_file(const json_t *json, const char *path, size_t flags)
|
||||
{
|
||||
int result;
|
||||
|
||||
FILE *output = fopen(path, "w");
|
||||
if(!output)
|
||||
return -1;
|
||||
|
||||
result = json_dumpf(json, output, flags);
|
||||
|
||||
fclose(output);
|
||||
return result;
|
||||
}
|
||||
|
||||
int json_dump_callback(const json_t *json, json_dump_callback_t callback, void *data, size_t flags)
|
||||
{
|
||||
if(!(flags & JSON_ENCODE_ANY)) {
|
||||
if(!json_is_array(json) && !json_is_object(json))
|
||||
return -1;
|
||||
}
|
||||
|
||||
return do_dump(json, flags, 0, callback, data);
|
||||
}
|
||||
@@ -1,63 +0,0 @@
|
||||
#include <string.h>
|
||||
#include "jansson_private.h"
|
||||
|
||||
void jsonp_error_init(json_error_t *error, const char *source)
|
||||
{
|
||||
if(error)
|
||||
{
|
||||
error->text[0] = '\0';
|
||||
error->line = -1;
|
||||
error->column = -1;
|
||||
error->position = 0;
|
||||
if(source)
|
||||
jsonp_error_set_source(error, source);
|
||||
else
|
||||
error->source[0] = '\0';
|
||||
}
|
||||
}
|
||||
|
||||
void jsonp_error_set_source(json_error_t *error, const char *source)
|
||||
{
|
||||
size_t length;
|
||||
|
||||
if(!error || !source)
|
||||
return;
|
||||
|
||||
length = strlen(source);
|
||||
if(length < JSON_ERROR_SOURCE_LENGTH)
|
||||
strncpy(error->source, source, length + 1);
|
||||
else {
|
||||
size_t extra = length - JSON_ERROR_SOURCE_LENGTH + 4;
|
||||
strncpy(error->source, "...", 3);
|
||||
strncpy(error->source + 3, source + extra, length - extra + 1);
|
||||
}
|
||||
}
|
||||
|
||||
void jsonp_error_set(json_error_t *error, int line, int column,
|
||||
size_t position, const char *msg, ...)
|
||||
{
|
||||
va_list ap;
|
||||
|
||||
va_start(ap, msg);
|
||||
jsonp_error_vset(error, line, column, position, msg, ap);
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
void jsonp_error_vset(json_error_t *error, int line, int column,
|
||||
size_t position, const char *msg, va_list ap)
|
||||
{
|
||||
if(!error)
|
||||
return;
|
||||
|
||||
if(error->text[0] != '\0') {
|
||||
/* error already set */
|
||||
return;
|
||||
}
|
||||
|
||||
error->line = line;
|
||||
error->column = column;
|
||||
error->position = (int)position;
|
||||
|
||||
vsnprintf(error->text, JSON_ERROR_TEXT_LENGTH, msg, ap);
|
||||
error->text[JSON_ERROR_TEXT_LENGTH - 1] = '\0';
|
||||
}
|
||||
@@ -1,356 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2009-2016 Petri Lehtinen <petri@digip.org>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the MIT license. See LICENSE for details.
|
||||
*/
|
||||
|
||||
#if HAVE_CONFIG_H
|
||||
#include <jansson_private_config.h>
|
||||
#endif
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#if HAVE_STDINT_H
|
||||
#include <stdint.h>
|
||||
#endif
|
||||
|
||||
#include <jansson_config.h> /* for JSON_INLINE */
|
||||
#include "jansson_private.h" /* for container_of() */
|
||||
#include "hashtable.h"
|
||||
|
||||
#ifndef INITIAL_HASHTABLE_ORDER
|
||||
#define INITIAL_HASHTABLE_ORDER 3
|
||||
#endif
|
||||
|
||||
typedef struct hashtable_list list_t;
|
||||
typedef struct hashtable_pair pair_t;
|
||||
typedef struct hashtable_bucket bucket_t;
|
||||
|
||||
extern volatile uint32_t hashtable_seed;
|
||||
|
||||
/* Implementation of the hash function */
|
||||
#include "lookup3.h"
|
||||
|
||||
#define list_to_pair(list_) container_of(list_, pair_t, list)
|
||||
#define ordered_list_to_pair(list_) container_of(list_, pair_t, ordered_list)
|
||||
#define hash_str(key) ((size_t)hashlittle((key), strlen(key), hashtable_seed))
|
||||
|
||||
static JSON_INLINE void list_init(list_t *list)
|
||||
{
|
||||
list->next = list;
|
||||
list->prev = list;
|
||||
}
|
||||
|
||||
static JSON_INLINE void list_insert(list_t *list, list_t *node)
|
||||
{
|
||||
node->next = list;
|
||||
node->prev = list->prev;
|
||||
list->prev->next = node;
|
||||
list->prev = node;
|
||||
}
|
||||
|
||||
static JSON_INLINE void list_remove(list_t *list)
|
||||
{
|
||||
list->prev->next = list->next;
|
||||
list->next->prev = list->prev;
|
||||
}
|
||||
|
||||
static JSON_INLINE int bucket_is_empty(hashtable_t *hashtable, bucket_t *bucket)
|
||||
{
|
||||
return bucket->first == &hashtable->list && bucket->first == bucket->last;
|
||||
}
|
||||
|
||||
static void insert_to_bucket(hashtable_t *hashtable, bucket_t *bucket,
|
||||
list_t *list)
|
||||
{
|
||||
if(bucket_is_empty(hashtable, bucket))
|
||||
{
|
||||
list_insert(&hashtable->list, list);
|
||||
bucket->first = bucket->last = list;
|
||||
}
|
||||
else
|
||||
{
|
||||
list_insert(bucket->first, list);
|
||||
bucket->first = list;
|
||||
}
|
||||
}
|
||||
|
||||
static pair_t *hashtable_find_pair(hashtable_t *hashtable, bucket_t *bucket,
|
||||
const char *key, size_t hash)
|
||||
{
|
||||
list_t *list;
|
||||
pair_t *pair;
|
||||
|
||||
if(bucket_is_empty(hashtable, bucket))
|
||||
return NULL;
|
||||
|
||||
list = bucket->first;
|
||||
while(1)
|
||||
{
|
||||
pair = list_to_pair(list);
|
||||
if(pair->hash == hash && strcmp(pair->key, key) == 0)
|
||||
return pair;
|
||||
|
||||
if(list == bucket->last)
|
||||
break;
|
||||
|
||||
list = list->next;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* returns 0 on success, -1 if key was not found */
|
||||
static int hashtable_do_del(hashtable_t *hashtable,
|
||||
const char *key, size_t hash)
|
||||
{
|
||||
pair_t *pair;
|
||||
bucket_t *bucket;
|
||||
size_t index;
|
||||
|
||||
index = hash & hashmask(hashtable->order);
|
||||
bucket = &hashtable->buckets[index];
|
||||
|
||||
pair = hashtable_find_pair(hashtable, bucket, key, hash);
|
||||
if(!pair)
|
||||
return -1;
|
||||
|
||||
if(&pair->list == bucket->first && &pair->list == bucket->last)
|
||||
bucket->first = bucket->last = &hashtable->list;
|
||||
|
||||
else if(&pair->list == bucket->first)
|
||||
bucket->first = pair->list.next;
|
||||
|
||||
else if(&pair->list == bucket->last)
|
||||
bucket->last = pair->list.prev;
|
||||
|
||||
list_remove(&pair->list);
|
||||
list_remove(&pair->ordered_list);
|
||||
json_decref(pair->value);
|
||||
|
||||
jsonp_free(pair);
|
||||
hashtable->size--;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void hashtable_do_clear(hashtable_t *hashtable)
|
||||
{
|
||||
list_t *list, *next;
|
||||
pair_t *pair;
|
||||
|
||||
for(list = hashtable->list.next; list != &hashtable->list; list = next)
|
||||
{
|
||||
next = list->next;
|
||||
pair = list_to_pair(list);
|
||||
json_decref(pair->value);
|
||||
jsonp_free(pair);
|
||||
}
|
||||
}
|
||||
|
||||
static int hashtable_do_rehash(hashtable_t *hashtable)
|
||||
{
|
||||
list_t *list, *next;
|
||||
pair_t *pair;
|
||||
size_t i, index, new_size, new_order;
|
||||
struct hashtable_bucket *new_buckets;
|
||||
|
||||
new_order = hashtable->order + 1;
|
||||
new_size = hashsize(new_order);
|
||||
|
||||
new_buckets = jsonp_malloc(new_size * sizeof(bucket_t));
|
||||
if(!new_buckets)
|
||||
return -1;
|
||||
|
||||
jsonp_free(hashtable->buckets);
|
||||
hashtable->buckets = new_buckets;
|
||||
hashtable->order = new_order;
|
||||
|
||||
for(i = 0; i < hashsize(hashtable->order); i++)
|
||||
{
|
||||
hashtable->buckets[i].first = hashtable->buckets[i].last =
|
||||
&hashtable->list;
|
||||
}
|
||||
|
||||
list = hashtable->list.next;
|
||||
list_init(&hashtable->list);
|
||||
|
||||
for(; list != &hashtable->list; list = next) {
|
||||
next = list->next;
|
||||
pair = list_to_pair(list);
|
||||
index = pair->hash % new_size;
|
||||
insert_to_bucket(hashtable, &hashtable->buckets[index], &pair->list);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int hashtable_init(hashtable_t *hashtable)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
hashtable->size = 0;
|
||||
hashtable->order = INITIAL_HASHTABLE_ORDER;
|
||||
hashtable->buckets = jsonp_malloc(hashsize(hashtable->order) * sizeof(bucket_t));
|
||||
if(!hashtable->buckets)
|
||||
return -1;
|
||||
|
||||
list_init(&hashtable->list);
|
||||
list_init(&hashtable->ordered_list);
|
||||
|
||||
for(i = 0; i < hashsize(hashtable->order); i++)
|
||||
{
|
||||
hashtable->buckets[i].first = hashtable->buckets[i].last =
|
||||
&hashtable->list;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void hashtable_close(hashtable_t *hashtable)
|
||||
{
|
||||
hashtable_do_clear(hashtable);
|
||||
jsonp_free(hashtable->buckets);
|
||||
}
|
||||
|
||||
int hashtable_set(hashtable_t *hashtable, const char *key, json_t *value)
|
||||
{
|
||||
pair_t *pair;
|
||||
bucket_t *bucket;
|
||||
size_t hash, index;
|
||||
|
||||
/* rehash if the load ratio exceeds 1 */
|
||||
if(hashtable->size >= hashsize(hashtable->order))
|
||||
if(hashtable_do_rehash(hashtable))
|
||||
return -1;
|
||||
|
||||
hash = hash_str(key);
|
||||
index = hash & hashmask(hashtable->order);
|
||||
bucket = &hashtable->buckets[index];
|
||||
pair = hashtable_find_pair(hashtable, bucket, key, hash);
|
||||
|
||||
if(pair)
|
||||
{
|
||||
json_decref(pair->value);
|
||||
pair->value = value;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* offsetof(...) returns the size of pair_t without the last,
|
||||
flexible member. This way, the correct amount is
|
||||
allocated. */
|
||||
|
||||
size_t len = strlen(key);
|
||||
if(len >= (size_t)-1 - offsetof(pair_t, key)) {
|
||||
/* Avoid an overflow if the key is very long */
|
||||
return -1;
|
||||
}
|
||||
|
||||
pair = jsonp_malloc(offsetof(pair_t, key) + len + 1);
|
||||
if(!pair)
|
||||
return -1;
|
||||
|
||||
pair->hash = hash;
|
||||
strncpy(pair->key, key, len + 1);
|
||||
pair->value = value;
|
||||
list_init(&pair->list);
|
||||
list_init(&pair->ordered_list);
|
||||
|
||||
insert_to_bucket(hashtable, bucket, &pair->list);
|
||||
list_insert(&hashtable->ordered_list, &pair->ordered_list);
|
||||
|
||||
hashtable->size++;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void *hashtable_get(hashtable_t *hashtable, const char *key)
|
||||
{
|
||||
pair_t *pair;
|
||||
size_t hash;
|
||||
bucket_t *bucket;
|
||||
|
||||
hash = hash_str(key);
|
||||
bucket = &hashtable->buckets[hash & hashmask(hashtable->order)];
|
||||
|
||||
pair = hashtable_find_pair(hashtable, bucket, key, hash);
|
||||
if(!pair)
|
||||
return NULL;
|
||||
|
||||
return pair->value;
|
||||
}
|
||||
|
||||
int hashtable_del(hashtable_t *hashtable, const char *key)
|
||||
{
|
||||
size_t hash = hash_str(key);
|
||||
return hashtable_do_del(hashtable, key, hash);
|
||||
}
|
||||
|
||||
void hashtable_clear(hashtable_t *hashtable)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
hashtable_do_clear(hashtable);
|
||||
|
||||
for(i = 0; i < hashsize(hashtable->order); i++)
|
||||
{
|
||||
hashtable->buckets[i].first = hashtable->buckets[i].last =
|
||||
&hashtable->list;
|
||||
}
|
||||
|
||||
list_init(&hashtable->list);
|
||||
list_init(&hashtable->ordered_list);
|
||||
hashtable->size = 0;
|
||||
}
|
||||
|
||||
void *hashtable_iter(hashtable_t *hashtable)
|
||||
{
|
||||
return hashtable_iter_next(hashtable, &hashtable->ordered_list);
|
||||
}
|
||||
|
||||
void *hashtable_iter_at(hashtable_t *hashtable, const char *key)
|
||||
{
|
||||
pair_t *pair;
|
||||
size_t hash;
|
||||
bucket_t *bucket;
|
||||
|
||||
hash = hash_str(key);
|
||||
bucket = &hashtable->buckets[hash & hashmask(hashtable->order)];
|
||||
|
||||
pair = hashtable_find_pair(hashtable, bucket, key, hash);
|
||||
if(!pair)
|
||||
return NULL;
|
||||
|
||||
return &pair->ordered_list;
|
||||
}
|
||||
|
||||
void *hashtable_iter_next(hashtable_t *hashtable, void *iter)
|
||||
{
|
||||
list_t *list = (list_t *)iter;
|
||||
if(list->next == &hashtable->ordered_list)
|
||||
return NULL;
|
||||
return list->next;
|
||||
}
|
||||
|
||||
void *hashtable_iter_key(void *iter)
|
||||
{
|
||||
pair_t *pair = ordered_list_to_pair((list_t *)iter);
|
||||
return pair->key;
|
||||
}
|
||||
|
||||
void *hashtable_iter_value(void *iter)
|
||||
{
|
||||
pair_t *pair = ordered_list_to_pair((list_t *)iter);
|
||||
return pair->value;
|
||||
}
|
||||
|
||||
void hashtable_iter_set(void *iter, json_t *value)
|
||||
{
|
||||
pair_t *pair = ordered_list_to_pair((list_t *)iter);
|
||||
|
||||
json_decref(pair->value);
|
||||
pair->value = value;
|
||||
}
|
||||
@@ -1,176 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2009-2016 Petri Lehtinen <petri@digip.org>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the MIT license. See LICENSE for details.
|
||||
*/
|
||||
|
||||
#ifndef HASHTABLE_H
|
||||
#define HASHTABLE_H
|
||||
|
||||
#include <stdlib.h>
|
||||
#include "jansson.h"
|
||||
|
||||
struct hashtable_list {
|
||||
struct hashtable_list *prev;
|
||||
struct hashtable_list *next;
|
||||
};
|
||||
|
||||
/* "pair" may be a bit confusing a name, but think of it as a
|
||||
key-value pair. In this case, it just encodes some extra data,
|
||||
too */
|
||||
struct hashtable_pair {
|
||||
struct hashtable_list list;
|
||||
struct hashtable_list ordered_list;
|
||||
size_t hash;
|
||||
json_t *value;
|
||||
char key[1];
|
||||
};
|
||||
|
||||
struct hashtable_bucket {
|
||||
struct hashtable_list *first;
|
||||
struct hashtable_list *last;
|
||||
};
|
||||
|
||||
typedef struct hashtable {
|
||||
size_t size;
|
||||
struct hashtable_bucket *buckets;
|
||||
size_t order; /* hashtable has pow(2, order) buckets */
|
||||
struct hashtable_list list;
|
||||
struct hashtable_list ordered_list;
|
||||
} hashtable_t;
|
||||
|
||||
|
||||
#define hashtable_key_to_iter(key_) \
|
||||
(&(container_of(key_, struct hashtable_pair, key)->ordered_list))
|
||||
|
||||
|
||||
/**
|
||||
* hashtable_init - Initialize a hashtable object
|
||||
*
|
||||
* @hashtable: The (statically allocated) hashtable object
|
||||
*
|
||||
* Initializes a statically allocated hashtable object. The object
|
||||
* should be cleared with hashtable_close when it's no longer used.
|
||||
*
|
||||
* Returns 0 on success, -1 on error (out of memory).
|
||||
*/
|
||||
int hashtable_init(hashtable_t *hashtable);
|
||||
|
||||
/**
|
||||
* hashtable_close - Release all resources used by a hashtable object
|
||||
*
|
||||
* @hashtable: The hashtable
|
||||
*
|
||||
* Destroys a statically allocated hashtable object.
|
||||
*/
|
||||
void hashtable_close(hashtable_t *hashtable);
|
||||
|
||||
/**
|
||||
* hashtable_set - Add/modify value in hashtable
|
||||
*
|
||||
* @hashtable: The hashtable object
|
||||
* @key: The key
|
||||
* @serial: For addition order of keys
|
||||
* @value: The value
|
||||
*
|
||||
* If a value with the given key already exists, its value is replaced
|
||||
* with the new value. Value is "stealed" in the sense that hashtable
|
||||
* doesn't increment its refcount but decreases the refcount when the
|
||||
* value is no longer needed.
|
||||
*
|
||||
* Returns 0 on success, -1 on failure (out of memory).
|
||||
*/
|
||||
int hashtable_set(hashtable_t *hashtable, const char *key, json_t *value);
|
||||
|
||||
/**
|
||||
* hashtable_get - Get a value associated with a key
|
||||
*
|
||||
* @hashtable: The hashtable object
|
||||
* @key: The key
|
||||
*
|
||||
* Returns value if it is found, or NULL otherwise.
|
||||
*/
|
||||
void *hashtable_get(hashtable_t *hashtable, const char *key);
|
||||
|
||||
/**
|
||||
* hashtable_del - Remove a value from the hashtable
|
||||
*
|
||||
* @hashtable: The hashtable object
|
||||
* @key: The key
|
||||
*
|
||||
* Returns 0 on success, or -1 if the key was not found.
|
||||
*/
|
||||
int hashtable_del(hashtable_t *hashtable, const char *key);
|
||||
|
||||
/**
|
||||
* hashtable_clear - Clear hashtable
|
||||
*
|
||||
* @hashtable: The hashtable object
|
||||
*
|
||||
* Removes all items from the hashtable.
|
||||
*/
|
||||
void hashtable_clear(hashtable_t *hashtable);
|
||||
|
||||
/**
|
||||
* hashtable_iter - Iterate over hashtable
|
||||
*
|
||||
* @hashtable: The hashtable object
|
||||
*
|
||||
* Returns an opaque iterator to the first element in the hashtable.
|
||||
* The iterator should be passed to hashtable_iter_* functions.
|
||||
* The hashtable items are not iterated over in any particular order.
|
||||
*
|
||||
* There's no need to free the iterator in any way. The iterator is
|
||||
* valid as long as the item that is referenced by the iterator is not
|
||||
* deleted. Other values may be added or deleted. In particular,
|
||||
* hashtable_iter_next() may be called on an iterator, and after that
|
||||
* the key/value pair pointed by the old iterator may be deleted.
|
||||
*/
|
||||
void *hashtable_iter(hashtable_t *hashtable);
|
||||
|
||||
/**
|
||||
* hashtable_iter_at - Return an iterator at a specific key
|
||||
*
|
||||
* @hashtable: The hashtable object
|
||||
* @key: The key that the iterator should point to
|
||||
*
|
||||
* Like hashtable_iter() but returns an iterator pointing to a
|
||||
* specific key.
|
||||
*/
|
||||
void *hashtable_iter_at(hashtable_t *hashtable, const char *key);
|
||||
|
||||
/**
|
||||
* hashtable_iter_next - Advance an iterator
|
||||
*
|
||||
* @hashtable: The hashtable object
|
||||
* @iter: The iterator
|
||||
*
|
||||
* Returns a new iterator pointing to the next element in the
|
||||
* hashtable or NULL if the whole hastable has been iterated over.
|
||||
*/
|
||||
void *hashtable_iter_next(hashtable_t *hashtable, void *iter);
|
||||
|
||||
/**
|
||||
* hashtable_iter_key - Retrieve the key pointed by an iterator
|
||||
*
|
||||
* @iter: The iterator
|
||||
*/
|
||||
void *hashtable_iter_key(void *iter);
|
||||
|
||||
/**
|
||||
* hashtable_iter_value - Retrieve the value pointed by an iterator
|
||||
*
|
||||
* @iter: The iterator
|
||||
*/
|
||||
void *hashtable_iter_value(void *iter);
|
||||
|
||||
/**
|
||||
* hashtable_iter_set - Set the value pointed by an iterator
|
||||
*
|
||||
* @iter: The iterator
|
||||
* @value: The value to set
|
||||
*/
|
||||
void hashtable_iter_set(void *iter, json_t *value);
|
||||
|
||||
#endif
|
||||
@@ -1,277 +0,0 @@
|
||||
/* Generate sizeof(uint32_t) bytes of as random data as possible to seed
|
||||
the hash function.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include <jansson_private_config.h>
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <time.h>
|
||||
|
||||
#ifdef HAVE_STDINT_H
|
||||
#include <stdint.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_FCNTL_H
|
||||
#include <fcntl.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_SCHED_H
|
||||
#include <sched.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_UNISTD_H
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_SYS_STAT_H
|
||||
#include <sys/stat.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_SYS_TIME_H
|
||||
#include <sys/time.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_SYS_TYPES_H
|
||||
#include <sys/types.h>
|
||||
#endif
|
||||
|
||||
#if defined(_WIN32)
|
||||
/* For GetModuleHandle(), GetProcAddress() and GetCurrentProcessId() */
|
||||
#include <windows.h>
|
||||
#endif
|
||||
|
||||
#include "jansson.h"
|
||||
|
||||
|
||||
static uint32_t buf_to_uint32(char *data) {
|
||||
size_t i;
|
||||
uint32_t result = 0;
|
||||
|
||||
for (i = 0; i < sizeof(uint32_t); i++)
|
||||
result = (result << 8) | (unsigned char)data[i];
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* /dev/urandom */
|
||||
#if !defined(_WIN32) && defined(USE_URANDOM)
|
||||
static int seed_from_urandom(uint32_t *seed) {
|
||||
/* Use unbuffered I/O if we have open(), close() and read(). Otherwise
|
||||
fall back to fopen() */
|
||||
|
||||
char data[sizeof(uint32_t)];
|
||||
int ok;
|
||||
|
||||
#if defined(HAVE_OPEN) && defined(HAVE_CLOSE) && defined(HAVE_READ)
|
||||
int urandom;
|
||||
urandom = open("/dev/urandom", O_RDONLY);
|
||||
if (urandom == -1)
|
||||
return 1;
|
||||
|
||||
ok = read(urandom, data, sizeof(uint32_t)) == sizeof(uint32_t);
|
||||
close(urandom);
|
||||
#else
|
||||
FILE *urandom;
|
||||
|
||||
urandom = fopen("/dev/urandom", "rb");
|
||||
if (!urandom)
|
||||
return 1;
|
||||
|
||||
ok = fread(data, 1, sizeof(uint32_t), urandom) == sizeof(uint32_t);
|
||||
fclose(urandom);
|
||||
#endif
|
||||
|
||||
if (!ok)
|
||||
return 1;
|
||||
|
||||
*seed = buf_to_uint32(data);
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Windows Crypto API */
|
||||
#if defined(_WIN32) && defined(USE_WINDOWS_CRYPTOAPI)
|
||||
#include <wincrypt.h>
|
||||
|
||||
typedef BOOL (WINAPI *CRYPTACQUIRECONTEXTA)(HCRYPTPROV *phProv, LPCSTR pszContainer, LPCSTR pszProvider, DWORD dwProvType, DWORD dwFlags);
|
||||
typedef BOOL (WINAPI *CRYPTGENRANDOM)(HCRYPTPROV hProv, DWORD dwLen, BYTE *pbBuffer);
|
||||
typedef BOOL (WINAPI *CRYPTRELEASECONTEXT)(HCRYPTPROV hProv, DWORD dwFlags);
|
||||
|
||||
static int seed_from_windows_cryptoapi(uint32_t *seed)
|
||||
{
|
||||
HINSTANCE hAdvAPI32 = NULL;
|
||||
CRYPTACQUIRECONTEXTA pCryptAcquireContext = NULL;
|
||||
CRYPTGENRANDOM pCryptGenRandom = NULL;
|
||||
CRYPTRELEASECONTEXT pCryptReleaseContext = NULL;
|
||||
HCRYPTPROV hCryptProv = 0;
|
||||
BYTE data[sizeof(uint32_t)];
|
||||
int ok;
|
||||
|
||||
hAdvAPI32 = GetModuleHandle(TEXT("advapi32.dll"));
|
||||
if(hAdvAPI32 == NULL)
|
||||
return 1;
|
||||
|
||||
pCryptAcquireContext = (CRYPTACQUIRECONTEXTA)GetProcAddress(hAdvAPI32, "CryptAcquireContextA");
|
||||
if (!pCryptAcquireContext)
|
||||
return 1;
|
||||
|
||||
pCryptGenRandom = (CRYPTGENRANDOM)GetProcAddress(hAdvAPI32, "CryptGenRandom");
|
||||
if (!pCryptGenRandom)
|
||||
return 1;
|
||||
|
||||
pCryptReleaseContext = (CRYPTRELEASECONTEXT)GetProcAddress(hAdvAPI32, "CryptReleaseContext");
|
||||
if (!pCryptReleaseContext)
|
||||
return 1;
|
||||
|
||||
if (!pCryptAcquireContext(&hCryptProv, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT))
|
||||
return 1;
|
||||
|
||||
ok = pCryptGenRandom(hCryptProv, sizeof(uint32_t), data);
|
||||
pCryptReleaseContext(hCryptProv, 0);
|
||||
|
||||
if (!ok)
|
||||
return 1;
|
||||
|
||||
*seed = buf_to_uint32((char *)data);
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* gettimeofday() and getpid() */
|
||||
static int seed_from_timestamp_and_pid(uint32_t *seed) {
|
||||
#ifdef HAVE_GETTIMEOFDAY
|
||||
/* XOR of seconds and microseconds */
|
||||
struct timeval tv;
|
||||
gettimeofday(&tv, NULL);
|
||||
*seed = (uint32_t)tv.tv_sec ^ (uint32_t)tv.tv_usec;
|
||||
#else
|
||||
/* Seconds only */
|
||||
*seed = (uint32_t)time(NULL);
|
||||
#endif
|
||||
|
||||
/* XOR with PID for more randomness */
|
||||
#if defined(_WIN32)
|
||||
*seed ^= (uint32_t)GetCurrentProcessId();
|
||||
#elif defined(HAVE_GETPID)
|
||||
*seed ^= (uint32_t)getpid();
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static uint32_t generate_seed() {
|
||||
uint32_t seed;
|
||||
int done = 0;
|
||||
|
||||
#if !defined(_WIN32) && defined(USE_URANDOM)
|
||||
if (!done && seed_from_urandom(&seed) == 0)
|
||||
done = 1;
|
||||
#endif
|
||||
|
||||
#if defined(_WIN32) && defined(USE_WINDOWS_CRYPTOAPI)
|
||||
if (!done && seed_from_windows_cryptoapi(&seed) == 0)
|
||||
done = 1;
|
||||
#endif
|
||||
|
||||
if (!done) {
|
||||
/* Fall back to timestamp and PID if no better randomness is
|
||||
available */
|
||||
seed_from_timestamp_and_pid(&seed);
|
||||
}
|
||||
|
||||
/* Make sure the seed is never zero */
|
||||
if (seed == 0)
|
||||
seed = 1;
|
||||
|
||||
return seed;
|
||||
}
|
||||
|
||||
|
||||
volatile uint32_t hashtable_seed = 0;
|
||||
|
||||
#if defined(HAVE_ATOMIC_BUILTINS) && (defined(HAVE_SCHED_YIELD) || !defined(_WIN32))
|
||||
static volatile char seed_initialized = 0;
|
||||
|
||||
void json_object_seed(size_t seed) {
|
||||
uint32_t new_seed = (uint32_t)seed;
|
||||
|
||||
if (hashtable_seed == 0) {
|
||||
if (__atomic_test_and_set(&seed_initialized, __ATOMIC_RELAXED) == 0) {
|
||||
/* Do the seeding ourselves */
|
||||
if (new_seed == 0)
|
||||
new_seed = generate_seed();
|
||||
|
||||
__atomic_store_n(&hashtable_seed, new_seed, __ATOMIC_RELEASE);
|
||||
} else {
|
||||
/* Wait for another thread to do the seeding */
|
||||
do {
|
||||
#ifdef HAVE_SCHED_YIELD
|
||||
sched_yield();
|
||||
#endif
|
||||
} while(__atomic_load_n(&hashtable_seed, __ATOMIC_ACQUIRE) == 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
#elif defined(HAVE_SYNC_BUILTINS) && (defined(HAVE_SCHED_YIELD) || !defined(_WIN32))
|
||||
void json_object_seed(size_t seed) {
|
||||
uint32_t new_seed = (uint32_t)seed;
|
||||
|
||||
if (hashtable_seed == 0) {
|
||||
if (new_seed == 0) {
|
||||
/* Explicit synchronization fences are not supported by the
|
||||
__sync builtins, so every thread getting here has to
|
||||
generate the seed value.
|
||||
*/
|
||||
new_seed = generate_seed();
|
||||
}
|
||||
|
||||
do {
|
||||
if (__sync_bool_compare_and_swap(&hashtable_seed, 0, new_seed)) {
|
||||
/* We were the first to seed */
|
||||
break;
|
||||
} else {
|
||||
/* Wait for another thread to do the seeding */
|
||||
#ifdef HAVE_SCHED_YIELD
|
||||
sched_yield();
|
||||
#endif
|
||||
}
|
||||
} while(hashtable_seed == 0);
|
||||
}
|
||||
}
|
||||
#elif defined(_WIN32)
|
||||
static long seed_initialized = 0;
|
||||
void json_object_seed(size_t seed) {
|
||||
uint32_t new_seed = (uint32_t)seed;
|
||||
|
||||
if (hashtable_seed == 0) {
|
||||
if (InterlockedIncrement(&seed_initialized) == 1) {
|
||||
/* Do the seeding ourselves */
|
||||
if (new_seed == 0)
|
||||
new_seed = generate_seed();
|
||||
|
||||
hashtable_seed = new_seed;
|
||||
} else {
|
||||
/* Wait for another thread to do the seeding */
|
||||
do {
|
||||
SwitchToThread();
|
||||
} while (hashtable_seed == 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
#else
|
||||
/* Fall back to a thread-unsafe version */
|
||||
void json_object_seed(size_t seed) {
|
||||
uint32_t new_seed = (uint32_t)seed;
|
||||
|
||||
if (hashtable_seed == 0) {
|
||||
if (new_seed == 0)
|
||||
new_seed = generate_seed();
|
||||
|
||||
hashtable_seed = new_seed;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -1,311 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2009-2016 Petri Lehtinen <petri@digip.org>
|
||||
*
|
||||
* Jansson is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the MIT license. See LICENSE for details.
|
||||
*/
|
||||
|
||||
#ifndef JANSSON_H
|
||||
#define JANSSON_H
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h> /* for size_t */
|
||||
#include <stdarg.h>
|
||||
|
||||
#include "jansson_config.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* version */
|
||||
|
||||
#define JANSSON_MAJOR_VERSION 2
|
||||
#define JANSSON_MINOR_VERSION 9
|
||||
#define JANSSON_MICRO_VERSION 0
|
||||
|
||||
/* Micro version is omitted if it's 0 */
|
||||
#define JANSSON_VERSION "2.9"
|
||||
|
||||
/* Version as a 3-byte hex number, e.g. 0x010201 == 1.2.1. Use this
|
||||
for numeric comparisons, e.g. #if JANSSON_VERSION_HEX >= ... */
|
||||
#define JANSSON_VERSION_HEX ((JANSSON_MAJOR_VERSION << 16) | \
|
||||
(JANSSON_MINOR_VERSION << 8) | \
|
||||
(JANSSON_MICRO_VERSION << 0))
|
||||
|
||||
|
||||
/* types */
|
||||
|
||||
typedef enum {
|
||||
JSON_OBJECT,
|
||||
JSON_ARRAY,
|
||||
JSON_STRING,
|
||||
JSON_INTEGER,
|
||||
JSON_REAL,
|
||||
JSON_TRUE,
|
||||
JSON_FALSE,
|
||||
JSON_NULL
|
||||
} json_type;
|
||||
|
||||
typedef struct json_t {
|
||||
json_type type;
|
||||
size_t refcount;
|
||||
} json_t;
|
||||
|
||||
#ifndef JANSSON_USING_CMAKE /* disabled if using cmake */
|
||||
#if JSON_INTEGER_IS_LONG_LONG
|
||||
#ifdef _WIN32
|
||||
#define JSON_INTEGER_FORMAT "I64d"
|
||||
#else
|
||||
#define JSON_INTEGER_FORMAT "lld"
|
||||
#endif
|
||||
typedef long long json_int_t;
|
||||
#else
|
||||
#define JSON_INTEGER_FORMAT "ld"
|
||||
typedef long json_int_t;
|
||||
#endif /* JSON_INTEGER_IS_LONG_LONG */
|
||||
#endif
|
||||
|
||||
#define json_typeof(json) ((json)->type)
|
||||
#define json_is_object(json) ((json) && json_typeof(json) == JSON_OBJECT)
|
||||
#define json_is_array(json) ((json) && json_typeof(json) == JSON_ARRAY)
|
||||
#define json_is_string(json) ((json) && json_typeof(json) == JSON_STRING)
|
||||
#define json_is_integer(json) ((json) && json_typeof(json) == JSON_INTEGER)
|
||||
#define json_is_real(json) ((json) && json_typeof(json) == JSON_REAL)
|
||||
#define json_is_number(json) (json_is_integer(json) || json_is_real(json))
|
||||
#define json_is_true(json) ((json) && json_typeof(json) == JSON_TRUE)
|
||||
#define json_is_false(json) ((json) && json_typeof(json) == JSON_FALSE)
|
||||
#define json_boolean_value json_is_true
|
||||
#define json_is_boolean(json) (json_is_true(json) || json_is_false(json))
|
||||
#define json_is_null(json) ((json) && json_typeof(json) == JSON_NULL)
|
||||
|
||||
/* construction, destruction, reference counting */
|
||||
|
||||
json_t *json_object(void);
|
||||
json_t *json_array(void);
|
||||
json_t *json_string(const char *value);
|
||||
json_t *json_stringn(const char *value, size_t len);
|
||||
json_t *json_string_nocheck(const char *value);
|
||||
json_t *json_stringn_nocheck(const char *value, size_t len);
|
||||
json_t *json_integer(json_int_t value);
|
||||
json_t *json_real(double value);
|
||||
json_t *json_true(void);
|
||||
json_t *json_false(void);
|
||||
#define json_boolean(val) ((val) ? json_true() : json_false())
|
||||
json_t *json_null(void);
|
||||
|
||||
static JSON_INLINE
|
||||
json_t *json_incref(json_t *json)
|
||||
{
|
||||
if(json && json->refcount != (size_t)-1)
|
||||
++json->refcount;
|
||||
return json;
|
||||
}
|
||||
|
||||
/* do not call json_delete directly */
|
||||
void json_delete(json_t *json);
|
||||
|
||||
static JSON_INLINE
|
||||
void json_decref(json_t *json)
|
||||
{
|
||||
if(json && json->refcount != (size_t)-1 && --json->refcount == 0)
|
||||
json_delete(json);
|
||||
}
|
||||
|
||||
#if defined(__GNUC__) || defined(__clang__)
|
||||
static JSON_INLINE
|
||||
void json_decrefp(json_t **json)
|
||||
{
|
||||
if(json) {
|
||||
json_decref(*json);
|
||||
*json = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
#define json_auto_t json_t __attribute__((cleanup(json_decrefp)))
|
||||
#endif
|
||||
|
||||
|
||||
/* error reporting */
|
||||
|
||||
#define JSON_ERROR_TEXT_LENGTH 160
|
||||
#define JSON_ERROR_SOURCE_LENGTH 80
|
||||
|
||||
typedef struct {
|
||||
int line;
|
||||
int column;
|
||||
int position;
|
||||
char source[JSON_ERROR_SOURCE_LENGTH];
|
||||
char text[JSON_ERROR_TEXT_LENGTH];
|
||||
} json_error_t;
|
||||
|
||||
|
||||
/* getters, setters, manipulation */
|
||||
|
||||
void json_object_seed(size_t seed);
|
||||
size_t json_object_size(const json_t *object);
|
||||
json_t *json_object_get(const json_t *object, const char *key);
|
||||
int json_object_set_new(json_t *object, const char *key, json_t *value);
|
||||
int json_object_set_new_nocheck(json_t *object, const char *key, json_t *value);
|
||||
int json_object_del(json_t *object, const char *key);
|
||||
int json_object_clear(json_t *object);
|
||||
int json_object_update(json_t *object, json_t *other);
|
||||
int json_object_update_existing(json_t *object, json_t *other);
|
||||
int json_object_update_missing(json_t *object, json_t *other);
|
||||
void *json_object_iter(json_t *object);
|
||||
void *json_object_iter_at(json_t *object, const char *key);
|
||||
void *json_object_key_to_iter(const char *key);
|
||||
void *json_object_iter_next(json_t *object, void *iter);
|
||||
const char *json_object_iter_key(void *iter);
|
||||
json_t *json_object_iter_value(void *iter);
|
||||
int json_object_iter_set_new(json_t *object, void *iter, json_t *value);
|
||||
|
||||
#define json_object_foreach(object, key, value) \
|
||||
for(key = json_object_iter_key(json_object_iter(object)); \
|
||||
key && (value = json_object_iter_value(json_object_key_to_iter(key))); \
|
||||
key = json_object_iter_key(json_object_iter_next(object, json_object_key_to_iter(key))))
|
||||
|
||||
#define json_object_foreach_safe(object, n, key, value) \
|
||||
for(key = json_object_iter_key(json_object_iter(object)), \
|
||||
n = json_object_iter_next(object, json_object_key_to_iter(key)); \
|
||||
key && (value = json_object_iter_value(json_object_key_to_iter(key))); \
|
||||
key = json_object_iter_key(n), \
|
||||
n = json_object_iter_next(object, json_object_key_to_iter(key)))
|
||||
|
||||
#define json_array_foreach(array, index, value) \
|
||||
for(index = 0; \
|
||||
index < json_array_size(array) && (value = json_array_get(array, index)); \
|
||||
index++)
|
||||
|
||||
static JSON_INLINE
|
||||
int json_object_set(json_t *object, const char *key, json_t *value)
|
||||
{
|
||||
return json_object_set_new(object, key, json_incref(value));
|
||||
}
|
||||
|
||||
static JSON_INLINE
|
||||
int json_object_set_nocheck(json_t *object, const char *key, json_t *value)
|
||||
{
|
||||
return json_object_set_new_nocheck(object, key, json_incref(value));
|
||||
}
|
||||
|
||||
static JSON_INLINE
|
||||
int json_object_iter_set(json_t *object, void *iter, json_t *value)
|
||||
{
|
||||
return json_object_iter_set_new(object, iter, json_incref(value));
|
||||
}
|
||||
|
||||
size_t json_array_size(const json_t *array);
|
||||
json_t *json_array_get(const json_t *array, size_t index);
|
||||
int json_array_set_new(json_t *array, size_t index, json_t *value);
|
||||
int json_array_append_new(json_t *array, json_t *value);
|
||||
int json_array_insert_new(json_t *array, size_t index, json_t *value);
|
||||
int json_array_remove(json_t *array, size_t index);
|
||||
int json_array_clear(json_t *array);
|
||||
int json_array_extend(json_t *array, json_t *other);
|
||||
|
||||
static JSON_INLINE
|
||||
int json_array_set(json_t *array, size_t ind, json_t *value)
|
||||
{
|
||||
return json_array_set_new(array, ind, json_incref(value));
|
||||
}
|
||||
|
||||
static JSON_INLINE
|
||||
int json_array_append(json_t *array, json_t *value)
|
||||
{
|
||||
return json_array_append_new(array, json_incref(value));
|
||||
}
|
||||
|
||||
static JSON_INLINE
|
||||
int json_array_insert(json_t *array, size_t ind, json_t *value)
|
||||
{
|
||||
return json_array_insert_new(array, ind, json_incref(value));
|
||||
}
|
||||
|
||||
const char *json_string_value(const json_t *string);
|
||||
size_t json_string_length(const json_t *string);
|
||||
json_int_t json_integer_value(const json_t *integer);
|
||||
double json_real_value(const json_t *real);
|
||||
double json_number_value(const json_t *json);
|
||||
|
||||
int json_string_set(json_t *string, const char *value);
|
||||
int json_string_setn(json_t *string, const char *value, size_t len);
|
||||
int json_string_set_nocheck(json_t *string, const char *value);
|
||||
int json_string_setn_nocheck(json_t *string, const char *value, size_t len);
|
||||
int json_integer_set(json_t *integer, json_int_t value);
|
||||
int json_real_set(json_t *real, double value);
|
||||
|
||||
/* pack, unpack */
|
||||
|
||||
json_t *json_pack(const char *fmt, ...);
|
||||
json_t *json_pack_ex(json_error_t *error, size_t flags, const char *fmt, ...);
|
||||
json_t *json_vpack_ex(json_error_t *error, size_t flags, const char *fmt, va_list ap);
|
||||
|
||||
#define JSON_VALIDATE_ONLY 0x1
|
||||
#define JSON_STRICT 0x2
|
||||
|
||||
int json_unpack(json_t *root, const char *fmt, ...);
|
||||
int json_unpack_ex(json_t *root, json_error_t *error, size_t flags, const char *fmt, ...);
|
||||
int json_vunpack_ex(json_t *root, json_error_t *error, size_t flags, const char *fmt, va_list ap);
|
||||
|
||||
|
||||
/* equality */
|
||||
|
||||
int json_equal(json_t *value1, json_t *value2);
|
||||
|
||||
|
||||
/* copying */
|
||||
|
||||
json_t *json_copy(json_t *value);
|
||||
json_t *json_deep_copy(const json_t *value);
|
||||
|
||||
|
||||
/* decoding */
|
||||
|
||||
#define JSON_REJECT_DUPLICATES 0x1
|
||||
#define JSON_DISABLE_EOF_CHECK 0x2
|
||||
#define JSON_DECODE_ANY 0x4
|
||||
#define JSON_DECODE_INT_AS_REAL 0x8
|
||||
#define JSON_ALLOW_NUL 0x10
|
||||
|
||||
typedef size_t (*json_load_callback_t)(void *buffer, size_t buflen, void *data);
|
||||
|
||||
json_t *json_loads(const char *input, size_t flags, json_error_t *error);
|
||||
json_t *json_loadb(const char *buffer, size_t buflen, size_t flags, json_error_t *error);
|
||||
json_t *json_loadf(FILE *input, size_t flags, json_error_t *error);
|
||||
json_t *json_load_file(const char *path, size_t flags, json_error_t *error);
|
||||
json_t *json_load_callback(json_load_callback_t callback, void *data, size_t flags, json_error_t *error);
|
||||
|
||||
|
||||
/* encoding */
|
||||
|
||||
#define JSON_MAX_INDENT 0x1F
|
||||
#define JSON_INDENT(n) ((n) & JSON_MAX_INDENT)
|
||||
#define JSON_COMPACT 0x20
|
||||
#define JSON_ENSURE_ASCII 0x40
|
||||
#define JSON_SORT_KEYS 0x80
|
||||
#define JSON_PRESERVE_ORDER 0x100
|
||||
#define JSON_ENCODE_ANY 0x200
|
||||
#define JSON_ESCAPE_SLASH 0x400
|
||||
#define JSON_REAL_PRECISION(n) (((n) & 0x1F) << 11)
|
||||
|
||||
typedef int (*json_dump_callback_t)(const char *buffer, size_t size, void *data);
|
||||
|
||||
char *json_dumps(const json_t *json, size_t flags);
|
||||
int json_dumpf(const json_t *json, FILE *output, size_t flags);
|
||||
int json_dump_file(const json_t *json, const char *path, size_t flags);
|
||||
int json_dump_callback(const json_t *json, json_dump_callback_t callback, void *data, size_t flags);
|
||||
|
||||
/* custom memory allocation */
|
||||
|
||||
typedef void *(*json_malloc_t)(size_t);
|
||||
typedef void (*json_free_t)(void *);
|
||||
|
||||
void json_set_alloc_funcs(json_malloc_t malloc_fn, json_free_t free_fn);
|
||||
void json_get_alloc_funcs(json_malloc_t *malloc_fn, json_free_t *free_fn);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -1,43 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2010-2016 Petri Lehtinen <petri@digip.org>
|
||||
*
|
||||
* Jansson is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the MIT license. See LICENSE for details.
|
||||
*
|
||||
*
|
||||
* This file specifies a part of the site-specific configuration for
|
||||
* Jansson, namely those things that affect the public API in
|
||||
* jansson.h.
|
||||
*
|
||||
* The configure script copies this file to jansson_config.h and
|
||||
* replaces @var@ substitutions by values that fit your system. If you
|
||||
* cannot run the configure script, you can do the value substitution
|
||||
* by hand.
|
||||
*/
|
||||
|
||||
#ifndef JANSSON_CONFIG_H
|
||||
#define JANSSON_CONFIG_H
|
||||
|
||||
/* If your compiler supports the inline keyword in C, JSON_INLINE is
|
||||
defined to `inline', otherwise empty. In C++, the inline is always
|
||||
supported. */
|
||||
#ifdef __cplusplus
|
||||
#define JSON_INLINE inline
|
||||
#else
|
||||
#define JSON_INLINE inline
|
||||
#endif
|
||||
|
||||
/* If your compiler supports the `long long` type and the strtoll()
|
||||
library function, JSON_INTEGER_IS_LONG_LONG is defined to 1,
|
||||
otherwise to 0. */
|
||||
#define JSON_INTEGER_IS_LONG_LONG 1
|
||||
|
||||
/* If locale.h and localeconv() are available, define to 1,
|
||||
otherwise to 0. */
|
||||
#define JSON_HAVE_LOCALECONV 1
|
||||
|
||||
/* Maximum recursion depth for parsing JSON input.
|
||||
This limits the depth of e.g. array-within-array constructions. */
|
||||
#define JSON_PARSER_MAX_DEPTH 2048
|
||||
|
||||
#endif
|
||||
@@ -1,108 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2009-2016 Petri Lehtinen <petri@digip.org>
|
||||
*
|
||||
* Jansson is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the MIT license. See LICENSE for details.
|
||||
*/
|
||||
|
||||
#ifndef JANSSON_PRIVATE_H
|
||||
#define JANSSON_PRIVATE_H
|
||||
|
||||
#include <stddef.h>
|
||||
#include "jansson.h"
|
||||
#include "hashtable.h"
|
||||
#include "strbuffer.h"
|
||||
|
||||
#define container_of(ptr_, type_, member_) \
|
||||
((type_ *)((char *)ptr_ - offsetof(type_, member_)))
|
||||
|
||||
/* On some platforms, max() may already be defined */
|
||||
#ifndef max
|
||||
#define max(a, b) ((a) > (b) ? (a) : (b))
|
||||
#endif
|
||||
|
||||
/* va_copy is a C99 feature. In C89 implementations, it's sometimes
|
||||
available as __va_copy. If not, memcpy() should do the trick. */
|
||||
#ifndef va_copy
|
||||
#ifdef __va_copy
|
||||
#define va_copy __va_copy
|
||||
#else
|
||||
#define va_copy(a, b) memcpy(&(a), &(b), sizeof(va_list))
|
||||
#endif
|
||||
#endif
|
||||
|
||||
typedef struct {
|
||||
json_t json;
|
||||
hashtable_t hashtable;
|
||||
int visited;
|
||||
} json_object_t;
|
||||
|
||||
typedef struct {
|
||||
json_t json;
|
||||
size_t size;
|
||||
size_t entries;
|
||||
json_t **table;
|
||||
int visited;
|
||||
} json_array_t;
|
||||
|
||||
typedef struct {
|
||||
json_t json;
|
||||
char *value;
|
||||
size_t length;
|
||||
} json_string_t;
|
||||
|
||||
typedef struct {
|
||||
json_t json;
|
||||
double value;
|
||||
} json_real_t;
|
||||
|
||||
typedef struct {
|
||||
json_t json;
|
||||
json_int_t value;
|
||||
} json_integer_t;
|
||||
|
||||
#define json_to_object(json_) container_of(json_, json_object_t, json)
|
||||
#define json_to_array(json_) container_of(json_, json_array_t, json)
|
||||
#define json_to_string(json_) container_of(json_, json_string_t, json)
|
||||
#define json_to_real(json_) container_of(json_, json_real_t, json)
|
||||
#define json_to_integer(json_) container_of(json_, json_integer_t, json)
|
||||
|
||||
/* Create a string by taking ownership of an existing buffer */
|
||||
json_t *jsonp_stringn_nocheck_own(const char *value, size_t len);
|
||||
|
||||
/* Error message formatting */
|
||||
void jsonp_error_init(json_error_t *error, const char *source);
|
||||
void jsonp_error_set_source(json_error_t *error, const char *source);
|
||||
void jsonp_error_set(json_error_t *error, int line, int column,
|
||||
size_t position, const char *msg, ...);
|
||||
void jsonp_error_vset(json_error_t *error, int line, int column,
|
||||
size_t position, const char *msg, va_list ap);
|
||||
|
||||
/* Locale independent string<->double conversions */
|
||||
int jsonp_strtod(strbuffer_t *strbuffer, double *out);
|
||||
int jsonp_dtostr(char *buffer, size_t size, double value, int prec);
|
||||
|
||||
/* Wrappers for custom memory functions */
|
||||
void* jsonp_malloc(size_t size);
|
||||
void jsonp_free(void *ptr);
|
||||
char *jsonp_strndup(const char *str, size_t length);
|
||||
char *jsonp_strdup(const char *str);
|
||||
char *jsonp_strndup(const char *str, size_t len);
|
||||
|
||||
|
||||
/* Windows compatibility */
|
||||
#if defined(_WIN32) || defined(WIN32)
|
||||
# if defined(_MSC_VER) /* MS compiller */
|
||||
# if (_MSC_VER < 1900) && !defined(snprintf) /* snprintf not defined yet & not introduced */
|
||||
# define snprintf _snprintf
|
||||
# endif
|
||||
# if (_MSC_VER < 1500) && !defined(vsnprintf) /* vsnprintf not defined yet & not introduced */
|
||||
# define vsnprintf(b,c,f,a) _vsnprintf(b,c,f,a)
|
||||
# endif
|
||||
# else /* Other Windows compiller, old definition */
|
||||
# define snprintf _snprintf
|
||||
# define vsnprintf _vsnprintf
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -1,159 +0,0 @@
|
||||
/* jansson_private_config.h. Generated from jansson_private_config.h.in by configure. */
|
||||
/* jansson_private_config.h.in. Generated from configure.ac by autoheader. */
|
||||
|
||||
/* Define to 1 if gcc's __atomic builtins are available */
|
||||
#define HAVE_ATOMIC_BUILTINS 1
|
||||
|
||||
/* Define to 1 if you have the `close' function. */
|
||||
#define HAVE_CLOSE 1
|
||||
|
||||
/* Define to 1 if you have the <dlfcn.h> header file. */
|
||||
/* #undef HAVE_DLFCN_H */
|
||||
|
||||
/* Define to 1 if you have the <endian.h> header file. */
|
||||
/* #undef HAVE_ENDIAN_H */
|
||||
|
||||
/* Define to 1 if you have the <fcntl.h> header file. */
|
||||
#define HAVE_FCNTL_H 1
|
||||
|
||||
/* Define to 1 if you have the `getpid' function. */
|
||||
#define HAVE_GETPID 1
|
||||
|
||||
/* Define to 1 if you have the `gettimeofday' function. */
|
||||
#define HAVE_GETTIMEOFDAY 1
|
||||
|
||||
/* Define to 1 if you have the <inttypes.h> header file. */
|
||||
#define HAVE_INTTYPES_H 1
|
||||
|
||||
/* Define to 1 if you have the `localeconv' function. */
|
||||
#define HAVE_LOCALECONV 1
|
||||
|
||||
/* Define to 1 if you have the <locale.h> header file. */
|
||||
#define HAVE_LOCALE_H 1
|
||||
|
||||
/* Define to 1 if the system has the type 'long long int'. */
|
||||
#define HAVE_LONG_LONG_INT 1
|
||||
|
||||
/* Define to 1 if you have the <memory.h> header file. */
|
||||
#define HAVE_MEMORY_H 1
|
||||
|
||||
/* Define to 1 if you have the `open' function. */
|
||||
#define HAVE_OPEN 1
|
||||
|
||||
/* Define to 1 if you have the `read' function. */
|
||||
#define HAVE_READ 1
|
||||
|
||||
/* Define to 1 if you have the <sched.h> header file. */
|
||||
#define HAVE_SCHED_H 1
|
||||
|
||||
/* Define to 1 if you have the `sched_yield' function. */
|
||||
#define HAVE_SCHED_YIELD 1
|
||||
|
||||
/* Define to 1 if you have the <stdint.h> header file. */
|
||||
#define HAVE_STDINT_H 1
|
||||
|
||||
/* Define to 1 if you have the <stdlib.h> header file. */
|
||||
#define HAVE_STDLIB_H 1
|
||||
|
||||
/* Define to 1 if you have the <strings.h> header file. */
|
||||
#define HAVE_STRINGS_H 1
|
||||
|
||||
/* Define to 1 if you have the <string.h> header file. */
|
||||
#define HAVE_STRING_H 1
|
||||
|
||||
/* Define to 1 if you have the `strtoll' function. */
|
||||
#define HAVE_STRTOLL 1
|
||||
|
||||
/* Define to 1 if gcc's __sync builtins are available */
|
||||
#define HAVE_SYNC_BUILTINS 1
|
||||
|
||||
/* Define to 1 if you have the <sys/param.h> header file. */
|
||||
#define HAVE_SYS_PARAM_H 1
|
||||
|
||||
/* Define to 1 if you have the <sys/stat.h> header file. */
|
||||
#define HAVE_SYS_STAT_H 1
|
||||
|
||||
/* Define to 1 if you have the <sys/time.h> header file. */
|
||||
#define HAVE_SYS_TIME_H 1
|
||||
|
||||
/* Define to 1 if you have the <sys/types.h> header file. */
|
||||
#define HAVE_SYS_TYPES_H 1
|
||||
|
||||
/* Define to 1 if you have the <unistd.h> header file. */
|
||||
#define HAVE_UNISTD_H 1
|
||||
|
||||
/* Define to 1 if the system has the type 'unsigned long long int'. */
|
||||
#define HAVE_UNSIGNED_LONG_LONG_INT 1
|
||||
|
||||
/* Number of buckets new object hashtables contain is 2 raised to this power.
|
||||
E.g. 3 -> 2^3 = 8. */
|
||||
#define INITIAL_HASHTABLE_ORDER 3
|
||||
|
||||
/* Define to the sub-directory where libtool stores uninstalled libraries. */
|
||||
#define LT_OBJDIR ".libs/"
|
||||
|
||||
/* Name of package */
|
||||
#define PACKAGE "jansson"
|
||||
|
||||
/* Define to the address where bug reports for this package should be sent. */
|
||||
#define PACKAGE_BUGREPORT "petri@digip.org"
|
||||
|
||||
/* Define to the full name of this package. */
|
||||
#define PACKAGE_NAME "jansson"
|
||||
|
||||
/* Define to the full name and version of this package. */
|
||||
#define PACKAGE_STRING "jansson 2.9"
|
||||
|
||||
/* Define to the one symbol short name of this package. */
|
||||
#define PACKAGE_TARNAME "jansson"
|
||||
|
||||
/* Define to the home page for this package. */
|
||||
#define PACKAGE_URL ""
|
||||
|
||||
/* Define to the version of this package. */
|
||||
#define PACKAGE_VERSION "2.9"
|
||||
|
||||
/* Define to 1 if you have the ANSI C header files. */
|
||||
#define STDC_HEADERS 1
|
||||
|
||||
/* Define to 1 if /dev/urandom should be used for seeding the hash function */
|
||||
#define USE_URANDOM 1
|
||||
|
||||
/* Define to 1 if CryptGenRandom should be used for seeding the hash function
|
||||
*/
|
||||
#define USE_WINDOWS_CRYPTOAPI 1
|
||||
|
||||
/* Version number of package */
|
||||
#define VERSION "2.9"
|
||||
|
||||
/* Define for Solaris 2.5.1 so the uint32_t typedef from <sys/synch.h>,
|
||||
<pthread.h>, or <semaphore.h> is not used. If the typedef were allowed, the
|
||||
#define below would cause a syntax error. */
|
||||
/* #undef _UINT32_T */
|
||||
|
||||
/* Define for Solaris 2.5.1 so the uint8_t typedef from <sys/synch.h>,
|
||||
<pthread.h>, or <semaphore.h> is not used. If the typedef were allowed, the
|
||||
#define below would cause a syntax error. */
|
||||
/* #undef _UINT8_T */
|
||||
|
||||
/* Define to `__inline__' or `__inline' if that's what the C compiler
|
||||
calls it, or to nothing if 'inline' is not supported under any name. */
|
||||
#ifndef __cplusplus
|
||||
/* #undef inline */
|
||||
#endif
|
||||
|
||||
/* Define to the type of a signed integer type of width exactly 32 bits if
|
||||
such a type exists and the standard includes do not define it. */
|
||||
/* #undef int32_t */
|
||||
|
||||
/* Define to the type of an unsigned integer type of width exactly 16 bits if
|
||||
such a type exists and the standard includes do not define it. */
|
||||
/* #undef uint16_t */
|
||||
|
||||
/* Define to the type of an unsigned integer type of width exactly 32 bits if
|
||||
such a type exists and the standard includes do not define it. */
|
||||
/* #undef uint32_t */
|
||||
|
||||
/* Define to the type of an unsigned integer type of width exactly 8 bits if
|
||||
such a type exists and the standard includes do not define it. */
|
||||
/* #undef uint8_t */
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,381 +0,0 @@
|
||||
/*
|
||||
-------------------------------------------------------------------------------
|
||||
lookup3.c, by Bob Jenkins, May 2006, Public Domain.
|
||||
|
||||
These are functions for producing 32-bit hashes for hash table lookup.
|
||||
hashword(), hashlittle(), hashlittle2(), hashbig(), mix(), and final()
|
||||
are externally useful functions. Routines to test the hash are included
|
||||
if SELF_TEST is defined. You can use this free for any purpose. It's in
|
||||
the public domain. It has no warranty.
|
||||
|
||||
You probably want to use hashlittle(). hashlittle() and hashbig()
|
||||
hash byte arrays. hashlittle() is is faster than hashbig() on
|
||||
little-endian machines. Intel and AMD are little-endian machines.
|
||||
On second thought, you probably want hashlittle2(), which is identical to
|
||||
hashlittle() except it returns two 32-bit hashes for the price of one.
|
||||
You could implement hashbig2() if you wanted but I haven't bothered here.
|
||||
|
||||
If you want to find a hash of, say, exactly 7 integers, do
|
||||
a = i1; b = i2; c = i3;
|
||||
mix(a,b,c);
|
||||
a += i4; b += i5; c += i6;
|
||||
mix(a,b,c);
|
||||
a += i7;
|
||||
final(a,b,c);
|
||||
then use c as the hash value. If you have a variable length array of
|
||||
4-byte integers to hash, use hashword(). If you have a byte array (like
|
||||
a character string), use hashlittle(). If you have several byte arrays, or
|
||||
a mix of things, see the comments above hashlittle().
|
||||
|
||||
Why is this so big? I read 12 bytes at a time into 3 4-byte integers,
|
||||
then mix those integers. This is fast (you can do a lot more thorough
|
||||
mixing with 12*3 instructions on 3 integers than you can with 3 instructions
|
||||
on 1 byte), but shoehorning those bytes into integers efficiently is messy.
|
||||
-------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include <jansson_private_config.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_STDINT_H
|
||||
#include <stdint.h> /* defines uint32_t etc */
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_SYS_PARAM_H
|
||||
#include <sys/param.h> /* attempt to define endianness */
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_ENDIAN_H
|
||||
# include <endian.h> /* attempt to define endianness */
|
||||
#endif
|
||||
|
||||
/*
|
||||
* My best guess at if you are big-endian or little-endian. This may
|
||||
* need adjustment.
|
||||
*/
|
||||
#if (defined(__BYTE_ORDER) && defined(__LITTLE_ENDIAN) && \
|
||||
__BYTE_ORDER == __LITTLE_ENDIAN) || \
|
||||
(defined(i386) || defined(__i386__) || defined(__i486__) || \
|
||||
defined(__i586__) || defined(__i686__) || defined(vax) || defined(MIPSEL))
|
||||
# define HASH_LITTLE_ENDIAN 1
|
||||
# define HASH_BIG_ENDIAN 0
|
||||
#elif (defined(__BYTE_ORDER) && defined(__BIG_ENDIAN) && \
|
||||
__BYTE_ORDER == __BIG_ENDIAN) || \
|
||||
(defined(sparc) || defined(POWERPC) || defined(mc68000) || defined(sel))
|
||||
# define HASH_LITTLE_ENDIAN 0
|
||||
# define HASH_BIG_ENDIAN 1
|
||||
#else
|
||||
# define HASH_LITTLE_ENDIAN 0
|
||||
# define HASH_BIG_ENDIAN 0
|
||||
#endif
|
||||
|
||||
#define hashsize(n) ((uint32_t)1<<(n))
|
||||
#define hashmask(n) (hashsize(n)-1)
|
||||
#define rot(x,k) (((x)<<(k)) | ((x)>>(32-(k))))
|
||||
|
||||
/*
|
||||
-------------------------------------------------------------------------------
|
||||
mix -- mix 3 32-bit values reversibly.
|
||||
|
||||
This is reversible, so any information in (a,b,c) before mix() is
|
||||
still in (a,b,c) after mix().
|
||||
|
||||
If four pairs of (a,b,c) inputs are run through mix(), or through
|
||||
mix() in reverse, there are at least 32 bits of the output that
|
||||
are sometimes the same for one pair and different for another pair.
|
||||
This was tested for:
|
||||
* pairs that differed by one bit, by two bits, in any combination
|
||||
of top bits of (a,b,c), or in any combination of bottom bits of
|
||||
(a,b,c).
|
||||
* "differ" is defined as +, -, ^, or ~^. For + and -, I transformed
|
||||
the output delta to a Gray code (a^(a>>1)) so a string of 1's (as
|
||||
is commonly produced by subtraction) look like a single 1-bit
|
||||
difference.
|
||||
* the base values were pseudorandom, all zero but one bit set, or
|
||||
all zero plus a counter that starts at zero.
|
||||
|
||||
Some k values for my "a-=c; a^=rot(c,k); c+=b;" arrangement that
|
||||
satisfy this are
|
||||
4 6 8 16 19 4
|
||||
9 15 3 18 27 15
|
||||
14 9 3 7 17 3
|
||||
Well, "9 15 3 18 27 15" didn't quite get 32 bits diffing
|
||||
for "differ" defined as + with a one-bit base and a two-bit delta. I
|
||||
used http://burtleburtle.net/bob/hash/avalanche.html to choose
|
||||
the operations, constants, and arrangements of the variables.
|
||||
|
||||
This does not achieve avalanche. There are input bits of (a,b,c)
|
||||
that fail to affect some output bits of (a,b,c), especially of a. The
|
||||
most thoroughly mixed value is c, but it doesn't really even achieve
|
||||
avalanche in c.
|
||||
|
||||
This allows some parallelism. Read-after-writes are good at doubling
|
||||
the number of bits affected, so the goal of mixing pulls in the opposite
|
||||
direction as the goal of parallelism. I did what I could. Rotates
|
||||
seem to cost as much as shifts on every machine I could lay my hands
|
||||
on, and rotates are much kinder to the top and bottom bits, so I used
|
||||
rotates.
|
||||
-------------------------------------------------------------------------------
|
||||
*/
|
||||
#define mix(a,b,c) \
|
||||
{ \
|
||||
a -= c; a ^= rot(c, 4); c += b; \
|
||||
b -= a; b ^= rot(a, 6); a += c; \
|
||||
c -= b; c ^= rot(b, 8); b += a; \
|
||||
a -= c; a ^= rot(c,16); c += b; \
|
||||
b -= a; b ^= rot(a,19); a += c; \
|
||||
c -= b; c ^= rot(b, 4); b += a; \
|
||||
}
|
||||
|
||||
/*
|
||||
-------------------------------------------------------------------------------
|
||||
final -- final mixing of 3 32-bit values (a,b,c) into c
|
||||
|
||||
Pairs of (a,b,c) values differing in only a few bits will usually
|
||||
produce values of c that look totally different. This was tested for
|
||||
* pairs that differed by one bit, by two bits, in any combination
|
||||
of top bits of (a,b,c), or in any combination of bottom bits of
|
||||
(a,b,c).
|
||||
* "differ" is defined as +, -, ^, or ~^. For + and -, I transformed
|
||||
the output delta to a Gray code (a^(a>>1)) so a string of 1's (as
|
||||
is commonly produced by subtraction) look like a single 1-bit
|
||||
difference.
|
||||
* the base values were pseudorandom, all zero but one bit set, or
|
||||
all zero plus a counter that starts at zero.
|
||||
|
||||
These constants passed:
|
||||
14 11 25 16 4 14 24
|
||||
12 14 25 16 4 14 24
|
||||
and these came close:
|
||||
4 8 15 26 3 22 24
|
||||
10 8 15 26 3 22 24
|
||||
11 8 15 26 3 22 24
|
||||
-------------------------------------------------------------------------------
|
||||
*/
|
||||
#define final(a,b,c) \
|
||||
{ \
|
||||
c ^= b; c -= rot(b,14); \
|
||||
a ^= c; a -= rot(c,11); \
|
||||
b ^= a; b -= rot(a,25); \
|
||||
c ^= b; c -= rot(b,16); \
|
||||
a ^= c; a -= rot(c,4); \
|
||||
b ^= a; b -= rot(a,14); \
|
||||
c ^= b; c -= rot(b,24); \
|
||||
}
|
||||
|
||||
/*
|
||||
-------------------------------------------------------------------------------
|
||||
hashlittle() -- hash a variable-length key into a 32-bit value
|
||||
k : the key (the unaligned variable-length array of bytes)
|
||||
length : the length of the key, counting by bytes
|
||||
initval : can be any 4-byte value
|
||||
Returns a 32-bit value. Every bit of the key affects every bit of
|
||||
the return value. Two keys differing by one or two bits will have
|
||||
totally different hash values.
|
||||
|
||||
The best hash table sizes are powers of 2. There is no need to do
|
||||
mod a prime (mod is sooo slow!). If you need less than 32 bits,
|
||||
use a bitmask. For example, if you need only 10 bits, do
|
||||
h = (h & hashmask(10));
|
||||
In which case, the hash table should have hashsize(10) elements.
|
||||
|
||||
If you are hashing n strings (uint8_t **)k, do it like this:
|
||||
for (i=0, h=0; i<n; ++i) h = hashlittle( k[i], len[i], h);
|
||||
|
||||
By Bob Jenkins, 2006. bob_jenkins@burtleburtle.net. You may use this
|
||||
code any way you wish, private, educational, or commercial. It's free.
|
||||
|
||||
Use for hash table lookup, or anything where one collision in 2^^32 is
|
||||
acceptable. Do NOT use for cryptographic purposes.
|
||||
-------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
static uint32_t hashlittle(const void *key, size_t length, uint32_t initval)
|
||||
{
|
||||
uint32_t a,b,c; /* internal state */
|
||||
union { const void *ptr; size_t i; } u; /* needed for Mac Powerbook G4 */
|
||||
|
||||
/* Set up the internal state */
|
||||
a = b = c = 0xdeadbeef + ((uint32_t)length) + initval;
|
||||
|
||||
u.ptr = key;
|
||||
if (HASH_LITTLE_ENDIAN && ((u.i & 0x3) == 0)) {
|
||||
const uint32_t *k = (const uint32_t *)key; /* read 32-bit chunks */
|
||||
|
||||
/* Detect Valgrind or AddressSanitizer */
|
||||
#ifdef VALGRIND
|
||||
# define NO_MASKING_TRICK 1
|
||||
#else
|
||||
# if defined(__has_feature) /* Clang */
|
||||
# if __has_feature(address_sanitizer) /* is ASAN enabled? */
|
||||
# define NO_MASKING_TRICK 1
|
||||
# endif
|
||||
# else
|
||||
# if defined(__SANITIZE_ADDRESS__) /* GCC 4.8.x, is ASAN enabled? */
|
||||
# define NO_MASKING_TRICK 1
|
||||
# endif
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifdef NO_MASKING_TRICK
|
||||
const uint8_t *k8;
|
||||
#endif
|
||||
|
||||
/*------ all but last block: aligned reads and affect 32 bits of (a,b,c) */
|
||||
while (length > 12)
|
||||
{
|
||||
a += k[0];
|
||||
b += k[1];
|
||||
c += k[2];
|
||||
mix(a,b,c);
|
||||
length -= 12;
|
||||
k += 3;
|
||||
}
|
||||
|
||||
/*----------------------------- handle the last (probably partial) block */
|
||||
/*
|
||||
* "k[2]&0xffffff" actually reads beyond the end of the string, but
|
||||
* then masks off the part it's not allowed to read. Because the
|
||||
* string is aligned, the masked-off tail is in the same word as the
|
||||
* rest of the string. Every machine with memory protection I've seen
|
||||
* does it on word boundaries, so is OK with this. But VALGRIND will
|
||||
* still catch it and complain. The masking trick does make the hash
|
||||
* noticably faster for short strings (like English words).
|
||||
*/
|
||||
#ifndef NO_MASKING_TRICK
|
||||
|
||||
switch(length)
|
||||
{
|
||||
case 12: c+=k[2]; b+=k[1]; a+=k[0]; break;
|
||||
case 11: c+=k[2]&0xffffff; b+=k[1]; a+=k[0]; break;
|
||||
case 10: c+=k[2]&0xffff; b+=k[1]; a+=k[0]; break;
|
||||
case 9 : c+=k[2]&0xff; b+=k[1]; a+=k[0]; break;
|
||||
case 8 : b+=k[1]; a+=k[0]; break;
|
||||
case 7 : b+=k[1]&0xffffff; a+=k[0]; break;
|
||||
case 6 : b+=k[1]&0xffff; a+=k[0]; break;
|
||||
case 5 : b+=k[1]&0xff; a+=k[0]; break;
|
||||
case 4 : a+=k[0]; break;
|
||||
case 3 : a+=k[0]&0xffffff; break;
|
||||
case 2 : a+=k[0]&0xffff; break;
|
||||
case 1 : a+=k[0]&0xff; break;
|
||||
case 0 : return c; /* zero length strings require no mixing */
|
||||
}
|
||||
|
||||
#else /* make valgrind happy */
|
||||
|
||||
k8 = (const uint8_t *)k;
|
||||
switch(length)
|
||||
{
|
||||
case 12: c+=k[2]; b+=k[1]; a+=k[0]; break;
|
||||
case 11: c+=((uint32_t)k8[10])<<16; /* fall through */
|
||||
case 10: c+=((uint32_t)k8[9])<<8; /* fall through */
|
||||
case 9 : c+=k8[8]; /* fall through */
|
||||
case 8 : b+=k[1]; a+=k[0]; break;
|
||||
case 7 : b+=((uint32_t)k8[6])<<16; /* fall through */
|
||||
case 6 : b+=((uint32_t)k8[5])<<8; /* fall through */
|
||||
case 5 : b+=k8[4]; /* fall through */
|
||||
case 4 : a+=k[0]; break;
|
||||
case 3 : a+=((uint32_t)k8[2])<<16; /* fall through */
|
||||
case 2 : a+=((uint32_t)k8[1])<<8; /* fall through */
|
||||
case 1 : a+=k8[0]; break;
|
||||
case 0 : return c;
|
||||
}
|
||||
|
||||
#endif /* !valgrind */
|
||||
|
||||
} else if (HASH_LITTLE_ENDIAN && ((u.i & 0x1) == 0)) {
|
||||
const uint16_t *k = (const uint16_t *)key; /* read 16-bit chunks */
|
||||
const uint8_t *k8;
|
||||
|
||||
/*--------------- all but last block: aligned reads and different mixing */
|
||||
while (length > 12)
|
||||
{
|
||||
a += k[0] + (((uint32_t)k[1])<<16);
|
||||
b += k[2] + (((uint32_t)k[3])<<16);
|
||||
c += k[4] + (((uint32_t)k[5])<<16);
|
||||
mix(a,b,c);
|
||||
length -= 12;
|
||||
k += 6;
|
||||
}
|
||||
|
||||
/*----------------------------- handle the last (probably partial) block */
|
||||
k8 = (const uint8_t *)k;
|
||||
switch(length)
|
||||
{
|
||||
case 12: c+=k[4]+(((uint32_t)k[5])<<16);
|
||||
b+=k[2]+(((uint32_t)k[3])<<16);
|
||||
a+=k[0]+(((uint32_t)k[1])<<16);
|
||||
break;
|
||||
case 11: c+=((uint32_t)k8[10])<<16; /* fall through */
|
||||
case 10: c+=k[4];
|
||||
b+=k[2]+(((uint32_t)k[3])<<16);
|
||||
a+=k[0]+(((uint32_t)k[1])<<16);
|
||||
break;
|
||||
case 9 : c+=k8[8]; /* fall through */
|
||||
case 8 : b+=k[2]+(((uint32_t)k[3])<<16);
|
||||
a+=k[0]+(((uint32_t)k[1])<<16);
|
||||
break;
|
||||
case 7 : b+=((uint32_t)k8[6])<<16; /* fall through */
|
||||
case 6 : b+=k[2];
|
||||
a+=k[0]+(((uint32_t)k[1])<<16);
|
||||
break;
|
||||
case 5 : b+=k8[4]; /* fall through */
|
||||
case 4 : a+=k[0]+(((uint32_t)k[1])<<16);
|
||||
break;
|
||||
case 3 : a+=((uint32_t)k8[2])<<16; /* fall through */
|
||||
case 2 : a+=k[0];
|
||||
break;
|
||||
case 1 : a+=k8[0];
|
||||
break;
|
||||
case 0 : return c; /* zero length requires no mixing */
|
||||
}
|
||||
|
||||
} else { /* need to read the key one byte at a time */
|
||||
const uint8_t *k = (const uint8_t *)key;
|
||||
|
||||
/*--------------- all but the last block: affect some 32 bits of (a,b,c) */
|
||||
while (length > 12)
|
||||
{
|
||||
a += k[0];
|
||||
a += ((uint32_t)k[1])<<8;
|
||||
a += ((uint32_t)k[2])<<16;
|
||||
a += ((uint32_t)k[3])<<24;
|
||||
b += k[4];
|
||||
b += ((uint32_t)k[5])<<8;
|
||||
b += ((uint32_t)k[6])<<16;
|
||||
b += ((uint32_t)k[7])<<24;
|
||||
c += k[8];
|
||||
c += ((uint32_t)k[9])<<8;
|
||||
c += ((uint32_t)k[10])<<16;
|
||||
c += ((uint32_t)k[11])<<24;
|
||||
mix(a,b,c);
|
||||
length -= 12;
|
||||
k += 12;
|
||||
}
|
||||
|
||||
/*-------------------------------- last block: affect all 32 bits of (c) */
|
||||
switch(length) /* all the case statements fall through */
|
||||
{
|
||||
case 12: c+=((uint32_t)k[11])<<24;
|
||||
case 11: c+=((uint32_t)k[10])<<16;
|
||||
case 10: c+=((uint32_t)k[9])<<8;
|
||||
case 9 : c+=k[8];
|
||||
case 8 : b+=((uint32_t)k[7])<<24;
|
||||
case 7 : b+=((uint32_t)k[6])<<16;
|
||||
case 6 : b+=((uint32_t)k[5])<<8;
|
||||
case 5 : b+=k[4];
|
||||
case 4 : a+=((uint32_t)k[3])<<24;
|
||||
case 3 : a+=((uint32_t)k[2])<<16;
|
||||
case 2 : a+=((uint32_t)k[1])<<8;
|
||||
case 1 : a+=k[0];
|
||||
break;
|
||||
case 0 : return c;
|
||||
}
|
||||
}
|
||||
|
||||
final(a,b,c);
|
||||
return c;
|
||||
}
|
||||
@@ -1,69 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2009-2016 Petri Lehtinen <petri@digip.org>
|
||||
* Copyright (c) 2011-2012 Basile Starynkevitch <basile@starynkevitch.net>
|
||||
*
|
||||
* Jansson is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the MIT license. See LICENSE for details.
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "jansson.h"
|
||||
#include "jansson_private.h"
|
||||
|
||||
/* C89 allows these to be macros */
|
||||
#undef malloc
|
||||
#undef free
|
||||
|
||||
/* memory function pointers */
|
||||
static json_malloc_t do_malloc = malloc;
|
||||
static json_free_t do_free = free;
|
||||
|
||||
void *jsonp_malloc(size_t size)
|
||||
{
|
||||
if(!size)
|
||||
return NULL;
|
||||
|
||||
return (*do_malloc)(size);
|
||||
}
|
||||
|
||||
void jsonp_free(void *ptr)
|
||||
{
|
||||
if(!ptr)
|
||||
return;
|
||||
|
||||
(*do_free)(ptr);
|
||||
}
|
||||
|
||||
char *jsonp_strdup(const char *str)
|
||||
{
|
||||
return jsonp_strndup(str, strlen(str));
|
||||
}
|
||||
|
||||
char *jsonp_strndup(const char *str, size_t len)
|
||||
{
|
||||
char *new_str;
|
||||
|
||||
new_str = jsonp_malloc(len + 1);
|
||||
if(!new_str)
|
||||
return NULL;
|
||||
|
||||
memcpy(new_str, str, len);
|
||||
new_str[len] = '\0';
|
||||
return new_str;
|
||||
}
|
||||
|
||||
void json_set_alloc_funcs(json_malloc_t malloc_fn, json_free_t free_fn)
|
||||
{
|
||||
do_malloc = malloc_fn;
|
||||
do_free = free_fn;
|
||||
}
|
||||
|
||||
void json_get_alloc_funcs(json_malloc_t *malloc_fn, json_free_t *free_fn)
|
||||
{
|
||||
if (malloc_fn)
|
||||
*malloc_fn = do_malloc;
|
||||
if (free_fn)
|
||||
*free_fn = do_free;
|
||||
}
|
||||
@@ -1,871 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2009-2016 Petri Lehtinen <petri@digip.org>
|
||||
* Copyright (c) 2011-2012 Graeme Smecher <graeme.smecher@mail.mcgill.ca>
|
||||
*
|
||||
* Jansson is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the MIT license. See LICENSE for details.
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include "jansson.h"
|
||||
#include "jansson_private.h"
|
||||
#include "utf.h"
|
||||
|
||||
typedef struct {
|
||||
int line;
|
||||
int column;
|
||||
size_t pos;
|
||||
char token;
|
||||
} token_t;
|
||||
|
||||
typedef struct {
|
||||
const char *start;
|
||||
const char *fmt;
|
||||
token_t prev_token;
|
||||
token_t token;
|
||||
token_t next_token;
|
||||
json_error_t *error;
|
||||
size_t flags;
|
||||
int line;
|
||||
int column;
|
||||
size_t pos;
|
||||
} scanner_t;
|
||||
|
||||
#define token(scanner) ((scanner)->token.token)
|
||||
|
||||
static const char * const type_names[] = {
|
||||
"object",
|
||||
"array",
|
||||
"string",
|
||||
"integer",
|
||||
"real",
|
||||
"true",
|
||||
"false",
|
||||
"null"
|
||||
};
|
||||
|
||||
#define type_name(x) type_names[json_typeof(x)]
|
||||
|
||||
static const char unpack_value_starters[] = "{[siIbfFOon";
|
||||
|
||||
static void scanner_init(scanner_t *s, json_error_t *error,
|
||||
size_t flags, const char *fmt)
|
||||
{
|
||||
s->error = error;
|
||||
s->flags = flags;
|
||||
s->fmt = s->start = fmt;
|
||||
memset(&s->prev_token, 0, sizeof(token_t));
|
||||
memset(&s->token, 0, sizeof(token_t));
|
||||
memset(&s->next_token, 0, sizeof(token_t));
|
||||
s->line = 1;
|
||||
s->column = 0;
|
||||
s->pos = 0;
|
||||
}
|
||||
|
||||
static void next_token(scanner_t *s)
|
||||
{
|
||||
const char *t;
|
||||
s->prev_token = s->token;
|
||||
|
||||
if(s->next_token.line) {
|
||||
s->token = s->next_token;
|
||||
s->next_token.line = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
t = s->fmt;
|
||||
s->column++;
|
||||
s->pos++;
|
||||
|
||||
/* skip space and ignored chars */
|
||||
while(*t == ' ' || *t == '\t' || *t == '\n' || *t == ',' || *t == ':') {
|
||||
if(*t == '\n') {
|
||||
s->line++;
|
||||
s->column = 1;
|
||||
}
|
||||
else
|
||||
s->column++;
|
||||
|
||||
s->pos++;
|
||||
t++;
|
||||
}
|
||||
|
||||
s->token.token = *t;
|
||||
s->token.line = s->line;
|
||||
s->token.column = s->column;
|
||||
s->token.pos = s->pos;
|
||||
|
||||
t++;
|
||||
s->fmt = t;
|
||||
}
|
||||
|
||||
static void prev_token(scanner_t *s)
|
||||
{
|
||||
s->next_token = s->token;
|
||||
s->token = s->prev_token;
|
||||
}
|
||||
|
||||
static void set_error(scanner_t *s, const char *source, const char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
va_start(ap, fmt);
|
||||
|
||||
jsonp_error_vset(s->error, s->token.line, s->token.column, s->token.pos,
|
||||
fmt, ap);
|
||||
|
||||
jsonp_error_set_source(s->error, source);
|
||||
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
static json_t *pack(scanner_t *s, va_list *ap);
|
||||
|
||||
|
||||
/* ours will be set to 1 if jsonp_free() must be called for the result
|
||||
afterwards */
|
||||
static char *read_string(scanner_t *s, va_list *ap,
|
||||
const char *purpose, size_t *out_len, int *ours)
|
||||
{
|
||||
char t;
|
||||
strbuffer_t strbuff;
|
||||
const char *str;
|
||||
size_t length;
|
||||
|
||||
next_token(s);
|
||||
t = token(s);
|
||||
prev_token(s);
|
||||
|
||||
if(t != '#' && t != '%' && t != '+') {
|
||||
/* Optimize the simple case */
|
||||
str = va_arg(*ap, const char *);
|
||||
|
||||
if(!str) {
|
||||
set_error(s, "<args>", "NULL string argument");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
length = strlen(str);
|
||||
|
||||
if(!utf8_check_string(str, length)) {
|
||||
set_error(s, "<args>", "Invalid UTF-8 %s", purpose);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
*out_len = length;
|
||||
*ours = 0;
|
||||
return (char *)str;
|
||||
}
|
||||
|
||||
strbuffer_init(&strbuff);
|
||||
|
||||
while(1) {
|
||||
str = va_arg(*ap, const char *);
|
||||
if(!str) {
|
||||
set_error(s, "<args>", "NULL string argument");
|
||||
strbuffer_close(&strbuff);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
next_token(s);
|
||||
|
||||
if(token(s) == '#') {
|
||||
length = va_arg(*ap, int);
|
||||
}
|
||||
else if(token(s) == '%') {
|
||||
length = va_arg(*ap, size_t);
|
||||
}
|
||||
else {
|
||||
prev_token(s);
|
||||
length = strlen(str);
|
||||
}
|
||||
|
||||
if(strbuffer_append_bytes(&strbuff, str, length) == -1) {
|
||||
set_error(s, "<internal>", "Out of memory");
|
||||
strbuffer_close(&strbuff);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
next_token(s);
|
||||
if(token(s) != '+') {
|
||||
prev_token(s);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(!utf8_check_string(strbuff.value, strbuff.length)) {
|
||||
set_error(s, "<args>", "Invalid UTF-8 %s", purpose);
|
||||
strbuffer_close(&strbuff);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
*out_len = strbuff.length;
|
||||
*ours = 1;
|
||||
return strbuffer_steal_value(&strbuff);
|
||||
}
|
||||
|
||||
static json_t *pack_object(scanner_t *s, va_list *ap)
|
||||
{
|
||||
json_t *object = json_object();
|
||||
next_token(s);
|
||||
|
||||
while(token(s) != '}') {
|
||||
char *key;
|
||||
size_t len;
|
||||
int ours;
|
||||
json_t *value;
|
||||
|
||||
if(!token(s)) {
|
||||
set_error(s, "<format>", "Unexpected end of format string");
|
||||
goto error;
|
||||
}
|
||||
|
||||
if(token(s) != 's') {
|
||||
set_error(s, "<format>", "Expected format 's', got '%c'", token(s));
|
||||
goto error;
|
||||
}
|
||||
|
||||
key = read_string(s, ap, "object key", &len, &ours);
|
||||
if(!key)
|
||||
goto error;
|
||||
|
||||
next_token(s);
|
||||
|
||||
value = pack(s, ap);
|
||||
if(!value) {
|
||||
if(ours)
|
||||
jsonp_free(key);
|
||||
|
||||
goto error;
|
||||
}
|
||||
|
||||
if(json_object_set_new_nocheck(object, key, value)) {
|
||||
set_error(s, "<internal>", "Unable to add key \"%s\"", key);
|
||||
if(ours)
|
||||
jsonp_free(key);
|
||||
|
||||
goto error;
|
||||
}
|
||||
|
||||
if(ours)
|
||||
jsonp_free(key);
|
||||
|
||||
next_token(s);
|
||||
}
|
||||
|
||||
return object;
|
||||
|
||||
error:
|
||||
json_decref(object);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static json_t *pack_array(scanner_t *s, va_list *ap)
|
||||
{
|
||||
json_t *array = json_array();
|
||||
next_token(s);
|
||||
|
||||
while(token(s) != ']') {
|
||||
json_t *value;
|
||||
|
||||
if(!token(s)) {
|
||||
set_error(s, "<format>", "Unexpected end of format string");
|
||||
goto error;
|
||||
}
|
||||
|
||||
value = pack(s, ap);
|
||||
if(!value)
|
||||
goto error;
|
||||
|
||||
if(json_array_append_new(array, value)) {
|
||||
set_error(s, "<internal>", "Unable to append to array");
|
||||
goto error;
|
||||
}
|
||||
|
||||
next_token(s);
|
||||
}
|
||||
return array;
|
||||
|
||||
error:
|
||||
json_decref(array);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static json_t *pack_string(scanner_t *s, va_list *ap)
|
||||
{
|
||||
char *str;
|
||||
size_t len;
|
||||
int ours;
|
||||
int nullable;
|
||||
|
||||
next_token(s);
|
||||
nullable = token(s) == '?';
|
||||
if (!nullable)
|
||||
prev_token(s);
|
||||
|
||||
str = read_string(s, ap, "string", &len, &ours);
|
||||
if (!str) {
|
||||
return nullable ? json_null() : NULL;
|
||||
} else if (ours) {
|
||||
return jsonp_stringn_nocheck_own(str, len);
|
||||
} else {
|
||||
return json_stringn_nocheck(str, len);
|
||||
}
|
||||
}
|
||||
|
||||
static json_t *pack(scanner_t *s, va_list *ap)
|
||||
{
|
||||
switch(token(s)) {
|
||||
case '{':
|
||||
return pack_object(s, ap);
|
||||
|
||||
case '[':
|
||||
return pack_array(s, ap);
|
||||
|
||||
case 's': /* string */
|
||||
return pack_string(s, ap);
|
||||
|
||||
case 'n': /* null */
|
||||
return json_null();
|
||||
|
||||
case 'b': /* boolean */
|
||||
return va_arg(*ap, int) ? json_true() : json_false();
|
||||
|
||||
case 'i': /* integer from int */
|
||||
return json_integer(va_arg(*ap, int));
|
||||
|
||||
case 'I': /* integer from json_int_t */
|
||||
return json_integer(va_arg(*ap, json_int_t));
|
||||
|
||||
case 'f': /* real */
|
||||
return json_real(va_arg(*ap, double));
|
||||
|
||||
case 'O': /* a json_t object; increments refcount */
|
||||
{
|
||||
int nullable;
|
||||
json_t *json;
|
||||
|
||||
next_token(s);
|
||||
nullable = token(s) == '?';
|
||||
if (!nullable)
|
||||
prev_token(s);
|
||||
|
||||
json = va_arg(*ap, json_t *);
|
||||
if (!json && nullable) {
|
||||
return json_null();
|
||||
} else {
|
||||
return json_incref(json);
|
||||
}
|
||||
}
|
||||
|
||||
case 'o': /* a json_t object; doesn't increment refcount */
|
||||
{
|
||||
int nullable;
|
||||
json_t *json;
|
||||
|
||||
next_token(s);
|
||||
nullable = token(s) == '?';
|
||||
if (!nullable)
|
||||
prev_token(s);
|
||||
|
||||
json = va_arg(*ap, json_t *);
|
||||
if (!json && nullable) {
|
||||
return json_null();
|
||||
} else {
|
||||
return json;
|
||||
}
|
||||
}
|
||||
|
||||
default:
|
||||
set_error(s, "<format>", "Unexpected format character '%c'",
|
||||
token(s));
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static int unpack(scanner_t *s, json_t *root, va_list *ap);
|
||||
|
||||
static int unpack_object(scanner_t *s, json_t *root, va_list *ap)
|
||||
{
|
||||
int ret = -1;
|
||||
int strict = 0;
|
||||
int gotopt = 0;
|
||||
|
||||
/* Use a set (emulated by a hashtable) to check that all object
|
||||
keys are accessed. Checking that the correct number of keys
|
||||
were accessed is not enough, as the same key can be unpacked
|
||||
multiple times.
|
||||
*/
|
||||
hashtable_t key_set;
|
||||
|
||||
if(hashtable_init(&key_set)) {
|
||||
set_error(s, "<internal>", "Out of memory");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if(root && !json_is_object(root)) {
|
||||
set_error(s, "<validation>", "Expected object, got %s",
|
||||
type_name(root));
|
||||
goto out;
|
||||
}
|
||||
next_token(s);
|
||||
|
||||
while(token(s) != '}') {
|
||||
const char *key;
|
||||
json_t *value;
|
||||
int opt = 0;
|
||||
|
||||
if(strict != 0) {
|
||||
set_error(s, "<format>", "Expected '}' after '%c', got '%c'",
|
||||
(strict == 1 ? '!' : '*'), token(s));
|
||||
goto out;
|
||||
}
|
||||
|
||||
if(!token(s)) {
|
||||
set_error(s, "<format>", "Unexpected end of format string");
|
||||
goto out;
|
||||
}
|
||||
|
||||
if(token(s) == '!' || token(s) == '*') {
|
||||
strict = (token(s) == '!' ? 1 : -1);
|
||||
next_token(s);
|
||||
continue;
|
||||
}
|
||||
|
||||
if(token(s) != 's') {
|
||||
set_error(s, "<format>", "Expected format 's', got '%c'", token(s));
|
||||
goto out;
|
||||
}
|
||||
|
||||
key = va_arg(*ap, const char *);
|
||||
if(!key) {
|
||||
set_error(s, "<args>", "NULL object key");
|
||||
goto out;
|
||||
}
|
||||
|
||||
next_token(s);
|
||||
|
||||
if(token(s) == '?') {
|
||||
opt = gotopt = 1;
|
||||
next_token(s);
|
||||
}
|
||||
|
||||
if(!root) {
|
||||
/* skipping */
|
||||
value = NULL;
|
||||
}
|
||||
else {
|
||||
value = json_object_get(root, key);
|
||||
if(!value && !opt) {
|
||||
set_error(s, "<validation>", "Object item not found: %s", key);
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
if(unpack(s, value, ap))
|
||||
goto out;
|
||||
|
||||
hashtable_set(&key_set, key, json_null());
|
||||
next_token(s);
|
||||
}
|
||||
|
||||
if(strict == 0 && (s->flags & JSON_STRICT))
|
||||
strict = 1;
|
||||
|
||||
if(root && strict == 1) {
|
||||
/* We need to check that all non optional items have been parsed */
|
||||
const char *key;
|
||||
int have_unrecognized_keys = 0;
|
||||
strbuffer_t unrecognized_keys;
|
||||
json_t *value;
|
||||
long unpacked = 0;
|
||||
if (gotopt) {
|
||||
/* We have optional keys, we need to iter on each key */
|
||||
json_object_foreach(root, key, value) {
|
||||
if(!hashtable_get(&key_set, key)) {
|
||||
unpacked++;
|
||||
|
||||
/* Save unrecognized keys for the error message */
|
||||
if (!have_unrecognized_keys) {
|
||||
strbuffer_init(&unrecognized_keys);
|
||||
have_unrecognized_keys = 1;
|
||||
} else {
|
||||
strbuffer_append_bytes(&unrecognized_keys, ", ", 2);
|
||||
}
|
||||
strbuffer_append_bytes(&unrecognized_keys, key, strlen(key));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
/* No optional keys, we can just compare the number of items */
|
||||
unpacked = (long)json_object_size(root) - (long)key_set.size;
|
||||
}
|
||||
if (unpacked) {
|
||||
if (!gotopt) {
|
||||
/* Save unrecognized keys for the error message */
|
||||
json_object_foreach(root, key, value) {
|
||||
if(!hashtable_get(&key_set, key)) {
|
||||
if (!have_unrecognized_keys) {
|
||||
strbuffer_init(&unrecognized_keys);
|
||||
have_unrecognized_keys = 1;
|
||||
} else {
|
||||
strbuffer_append_bytes(&unrecognized_keys, ", ", 2);
|
||||
}
|
||||
strbuffer_append_bytes(&unrecognized_keys, key, strlen(key));
|
||||
}
|
||||
}
|
||||
}
|
||||
set_error(s, "<validation>",
|
||||
"%li object item(s) left unpacked: %s",
|
||||
unpacked, strbuffer_value(&unrecognized_keys));
|
||||
strbuffer_close(&unrecognized_keys);
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
ret = 0;
|
||||
|
||||
out:
|
||||
hashtable_close(&key_set);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int unpack_array(scanner_t *s, json_t *root, va_list *ap)
|
||||
{
|
||||
size_t i = 0;
|
||||
int strict = 0;
|
||||
|
||||
if(root && !json_is_array(root)) {
|
||||
set_error(s, "<validation>", "Expected array, got %s", type_name(root));
|
||||
return -1;
|
||||
}
|
||||
next_token(s);
|
||||
|
||||
while(token(s) != ']') {
|
||||
json_t *value;
|
||||
|
||||
if(strict != 0) {
|
||||
set_error(s, "<format>", "Expected ']' after '%c', got '%c'",
|
||||
(strict == 1 ? '!' : '*'),
|
||||
token(s));
|
||||
return -1;
|
||||
}
|
||||
|
||||
if(!token(s)) {
|
||||
set_error(s, "<format>", "Unexpected end of format string");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if(token(s) == '!' || token(s) == '*') {
|
||||
strict = (token(s) == '!' ? 1 : -1);
|
||||
next_token(s);
|
||||
continue;
|
||||
}
|
||||
|
||||
if(!strchr(unpack_value_starters, token(s))) {
|
||||
set_error(s, "<format>", "Unexpected format character '%c'",
|
||||
token(s));
|
||||
return -1;
|
||||
}
|
||||
|
||||
if(!root) {
|
||||
/* skipping */
|
||||
value = NULL;
|
||||
}
|
||||
else {
|
||||
value = json_array_get(root, i);
|
||||
if(!value) {
|
||||
set_error(s, "<validation>", "Array index %lu out of range",
|
||||
(unsigned long)i);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
if(unpack(s, value, ap))
|
||||
return -1;
|
||||
|
||||
next_token(s);
|
||||
i++;
|
||||
}
|
||||
|
||||
if(strict == 0 && (s->flags & JSON_STRICT))
|
||||
strict = 1;
|
||||
|
||||
if(root && strict == 1 && i != json_array_size(root)) {
|
||||
long diff = (long)json_array_size(root) - (long)i;
|
||||
set_error(s, "<validation>", "%li array item(s) left unpacked", diff);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int unpack(scanner_t *s, json_t *root, va_list *ap)
|
||||
{
|
||||
switch(token(s))
|
||||
{
|
||||
case '{':
|
||||
return unpack_object(s, root, ap);
|
||||
|
||||
case '[':
|
||||
return unpack_array(s, root, ap);
|
||||
|
||||
case 's':
|
||||
if(root && !json_is_string(root)) {
|
||||
set_error(s, "<validation>", "Expected string, got %s",
|
||||
type_name(root));
|
||||
return -1;
|
||||
}
|
||||
|
||||
if(!(s->flags & JSON_VALIDATE_ONLY)) {
|
||||
const char **str_target;
|
||||
size_t *len_target = NULL;
|
||||
|
||||
str_target = va_arg(*ap, const char **);
|
||||
if(!str_target) {
|
||||
set_error(s, "<args>", "NULL string argument");
|
||||
return -1;
|
||||
}
|
||||
|
||||
next_token(s);
|
||||
|
||||
if(token(s) == '%') {
|
||||
len_target = va_arg(*ap, size_t *);
|
||||
if(!len_target) {
|
||||
set_error(s, "<args>", "NULL string length argument");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
else
|
||||
prev_token(s);
|
||||
|
||||
if(root) {
|
||||
*str_target = json_string_value(root);
|
||||
if(len_target)
|
||||
*len_target = json_string_length(root);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
|
||||
case 'i':
|
||||
if(root && !json_is_integer(root)) {
|
||||
set_error(s, "<validation>", "Expected integer, got %s",
|
||||
type_name(root));
|
||||
return -1;
|
||||
}
|
||||
|
||||
if(!(s->flags & JSON_VALIDATE_ONLY)) {
|
||||
int *target = va_arg(*ap, int*);
|
||||
if(root)
|
||||
*target = (int)json_integer_value(root);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
case 'I':
|
||||
if(root && !json_is_integer(root)) {
|
||||
set_error(s, "<validation>", "Expected integer, got %s",
|
||||
type_name(root));
|
||||
return -1;
|
||||
}
|
||||
|
||||
if(!(s->flags & JSON_VALIDATE_ONLY)) {
|
||||
json_int_t *target = va_arg(*ap, json_int_t*);
|
||||
if(root)
|
||||
*target = json_integer_value(root);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
case 'b':
|
||||
if(root && !json_is_boolean(root)) {
|
||||
set_error(s, "<validation>", "Expected true or false, got %s",
|
||||
type_name(root));
|
||||
return -1;
|
||||
}
|
||||
|
||||
if(!(s->flags & JSON_VALIDATE_ONLY)) {
|
||||
int *target = va_arg(*ap, int*);
|
||||
if(root)
|
||||
*target = json_is_true(root);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
case 'f':
|
||||
if(root && !json_is_real(root)) {
|
||||
set_error(s, "<validation>", "Expected real, got %s",
|
||||
type_name(root));
|
||||
return -1;
|
||||
}
|
||||
|
||||
if(!(s->flags & JSON_VALIDATE_ONLY)) {
|
||||
double *target = va_arg(*ap, double*);
|
||||
if(root)
|
||||
*target = json_real_value(root);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
case 'F':
|
||||
if(root && !json_is_number(root)) {
|
||||
set_error(s, "<validation>", "Expected real or integer, got %s",
|
||||
type_name(root));
|
||||
return -1;
|
||||
}
|
||||
|
||||
if(!(s->flags & JSON_VALIDATE_ONLY)) {
|
||||
double *target = va_arg(*ap, double*);
|
||||
if(root)
|
||||
*target = json_number_value(root);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
case 'O':
|
||||
if(root && !(s->flags & JSON_VALIDATE_ONLY))
|
||||
json_incref(root);
|
||||
/* Fall through */
|
||||
|
||||
case 'o':
|
||||
if(!(s->flags & JSON_VALIDATE_ONLY)) {
|
||||
json_t **target = va_arg(*ap, json_t**);
|
||||
if(root)
|
||||
*target = root;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
case 'n':
|
||||
/* Never assign, just validate */
|
||||
if(root && !json_is_null(root)) {
|
||||
set_error(s, "<validation>", "Expected null, got %s",
|
||||
type_name(root));
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
|
||||
default:
|
||||
set_error(s, "<format>", "Unexpected format character '%c'",
|
||||
token(s));
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
json_t *json_vpack_ex(json_error_t *error, size_t flags,
|
||||
const char *fmt, va_list ap)
|
||||
{
|
||||
scanner_t s;
|
||||
va_list ap_copy;
|
||||
json_t *value;
|
||||
|
||||
if(!fmt || !*fmt) {
|
||||
jsonp_error_init(error, "<format>");
|
||||
jsonp_error_set(error, -1, -1, 0, "NULL or empty format string");
|
||||
return NULL;
|
||||
}
|
||||
jsonp_error_init(error, NULL);
|
||||
|
||||
scanner_init(&s, error, flags, fmt);
|
||||
next_token(&s);
|
||||
|
||||
va_copy(ap_copy, ap);
|
||||
value = pack(&s, &ap_copy);
|
||||
va_end(ap_copy);
|
||||
|
||||
if(!value)
|
||||
return NULL;
|
||||
|
||||
next_token(&s);
|
||||
if(token(&s)) {
|
||||
json_decref(value);
|
||||
set_error(&s, "<format>", "Garbage after format string");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
json_t *json_pack_ex(json_error_t *error, size_t flags, const char *fmt, ...)
|
||||
{
|
||||
json_t *value;
|
||||
va_list ap;
|
||||
|
||||
va_start(ap, fmt);
|
||||
value = json_vpack_ex(error, flags, fmt, ap);
|
||||
va_end(ap);
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
json_t *json_pack(const char *fmt, ...)
|
||||
{
|
||||
json_t *value;
|
||||
va_list ap;
|
||||
|
||||
va_start(ap, fmt);
|
||||
value = json_vpack_ex(NULL, 0, fmt, ap);
|
||||
va_end(ap);
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
int json_vunpack_ex(json_t *root, json_error_t *error, size_t flags,
|
||||
const char *fmt, va_list ap)
|
||||
{
|
||||
scanner_t s;
|
||||
va_list ap_copy;
|
||||
|
||||
if(!root) {
|
||||
jsonp_error_init(error, "<root>");
|
||||
jsonp_error_set(error, -1, -1, 0, "NULL root value");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if(!fmt || !*fmt) {
|
||||
jsonp_error_init(error, "<format>");
|
||||
jsonp_error_set(error, -1, -1, 0, "NULL or empty format string");
|
||||
return -1;
|
||||
}
|
||||
jsonp_error_init(error, NULL);
|
||||
|
||||
scanner_init(&s, error, flags, fmt);
|
||||
next_token(&s);
|
||||
|
||||
va_copy(ap_copy, ap);
|
||||
if(unpack(&s, root, &ap_copy)) {
|
||||
va_end(ap_copy);
|
||||
return -1;
|
||||
}
|
||||
va_end(ap_copy);
|
||||
|
||||
next_token(&s);
|
||||
if(token(&s)) {
|
||||
set_error(&s, "<format>", "Garbage after format string");
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int json_unpack_ex(json_t *root, json_error_t *error, size_t flags, const char *fmt, ...)
|
||||
{
|
||||
int ret;
|
||||
va_list ap;
|
||||
|
||||
va_start(ap, fmt);
|
||||
ret = json_vunpack_ex(root, error, flags, fmt, ap);
|
||||
va_end(ap);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int json_unpack(json_t *root, const char *fmt, ...)
|
||||
{
|
||||
int ret;
|
||||
va_list ap;
|
||||
|
||||
va_start(ap, fmt);
|
||||
ret = json_vunpack_ex(root, NULL, 0, fmt, ap);
|
||||
va_end(ap);
|
||||
|
||||
return ret;
|
||||
}
|
||||
@@ -1,111 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2009-2016 Petri Lehtinen <petri@digip.org>
|
||||
*
|
||||
* Jansson is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the MIT license. See LICENSE for details.
|
||||
*/
|
||||
|
||||
#ifndef _GNU_SOURCE
|
||||
#define _GNU_SOURCE
|
||||
#endif
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "jansson_private.h"
|
||||
#include "strbuffer.h"
|
||||
|
||||
#define STRBUFFER_MIN_SIZE 16
|
||||
#define STRBUFFER_FACTOR 2
|
||||
#define STRBUFFER_SIZE_MAX ((size_t)-1)
|
||||
|
||||
int strbuffer_init(strbuffer_t *strbuff)
|
||||
{
|
||||
strbuff->size = STRBUFFER_MIN_SIZE;
|
||||
strbuff->length = 0;
|
||||
|
||||
strbuff->value = jsonp_malloc(strbuff->size);
|
||||
if(!strbuff->value)
|
||||
return -1;
|
||||
|
||||
/* initialize to empty */
|
||||
strbuff->value[0] = '\0';
|
||||
return 0;
|
||||
}
|
||||
|
||||
void strbuffer_close(strbuffer_t *strbuff)
|
||||
{
|
||||
if(strbuff->value)
|
||||
jsonp_free(strbuff->value);
|
||||
|
||||
strbuff->size = 0;
|
||||
strbuff->length = 0;
|
||||
strbuff->value = NULL;
|
||||
}
|
||||
|
||||
void strbuffer_clear(strbuffer_t *strbuff)
|
||||
{
|
||||
strbuff->length = 0;
|
||||
strbuff->value[0] = '\0';
|
||||
}
|
||||
|
||||
const char *strbuffer_value(const strbuffer_t *strbuff)
|
||||
{
|
||||
return strbuff->value;
|
||||
}
|
||||
|
||||
char *strbuffer_steal_value(strbuffer_t *strbuff)
|
||||
{
|
||||
char *result = strbuff->value;
|
||||
strbuff->value = NULL;
|
||||
return result;
|
||||
}
|
||||
|
||||
int strbuffer_append_byte(strbuffer_t *strbuff, char byte)
|
||||
{
|
||||
return strbuffer_append_bytes(strbuff, &byte, 1);
|
||||
}
|
||||
|
||||
int strbuffer_append_bytes(strbuffer_t *strbuff, const char *data, size_t size)
|
||||
{
|
||||
if(size >= strbuff->size - strbuff->length)
|
||||
{
|
||||
size_t new_size;
|
||||
char *new_value;
|
||||
|
||||
/* avoid integer overflow */
|
||||
if (strbuff->size > STRBUFFER_SIZE_MAX / STRBUFFER_FACTOR
|
||||
|| size > STRBUFFER_SIZE_MAX - 1
|
||||
|| strbuff->length > STRBUFFER_SIZE_MAX - 1 - size)
|
||||
return -1;
|
||||
|
||||
new_size = max(strbuff->size * STRBUFFER_FACTOR,
|
||||
strbuff->length + size + 1);
|
||||
|
||||
new_value = jsonp_malloc(new_size);
|
||||
if(!new_value)
|
||||
return -1;
|
||||
|
||||
memcpy(new_value, strbuff->value, strbuff->length);
|
||||
|
||||
jsonp_free(strbuff->value);
|
||||
strbuff->value = new_value;
|
||||
strbuff->size = new_size;
|
||||
}
|
||||
|
||||
memcpy(strbuff->value + strbuff->length, data, size);
|
||||
strbuff->length += size;
|
||||
strbuff->value[strbuff->length] = '\0';
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
char strbuffer_pop(strbuffer_t *strbuff)
|
||||
{
|
||||
if(strbuff->length > 0) {
|
||||
char c = strbuff->value[--strbuff->length];
|
||||
strbuff->value[strbuff->length] = '\0';
|
||||
return c;
|
||||
}
|
||||
else
|
||||
return '\0';
|
||||
}
|
||||
@@ -1,34 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2009-2016 Petri Lehtinen <petri@digip.org>
|
||||
*
|
||||
* Jansson is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the MIT license. See LICENSE for details.
|
||||
*/
|
||||
|
||||
#ifndef STRBUFFER_H
|
||||
#define STRBUFFER_H
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
typedef struct {
|
||||
char *value;
|
||||
size_t length; /* bytes used */
|
||||
size_t size; /* bytes allocated */
|
||||
} strbuffer_t;
|
||||
|
||||
int strbuffer_init(strbuffer_t *strbuff);
|
||||
void strbuffer_close(strbuffer_t *strbuff);
|
||||
|
||||
void strbuffer_clear(strbuffer_t *strbuff);
|
||||
|
||||
const char *strbuffer_value(const strbuffer_t *strbuff);
|
||||
|
||||
/* Steal the value and close the strbuffer */
|
||||
char *strbuffer_steal_value(strbuffer_t *strbuff);
|
||||
|
||||
int strbuffer_append_byte(strbuffer_t *strbuff, char byte);
|
||||
int strbuffer_append_bytes(strbuffer_t *strbuff, const char *data, size_t size);
|
||||
|
||||
char strbuffer_pop(strbuffer_t *strbuff);
|
||||
|
||||
#endif
|
||||
@@ -1,145 +0,0 @@
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <math.h>
|
||||
#ifdef __MINGW32__
|
||||
#undef __NO_ISOCEXT /* ensure stdlib.h will declare prototypes for mingw own 'strtod' replacement, called '__strtod' */
|
||||
#endif
|
||||
#include "jansson_private.h"
|
||||
#include "strbuffer.h"
|
||||
|
||||
/* need jansson_private_config.h to get the correct snprintf */
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include <jansson_private_config.h>
|
||||
#endif
|
||||
|
||||
#ifdef __MINGW32__
|
||||
#define strtod __strtod
|
||||
#endif
|
||||
|
||||
#if JSON_HAVE_LOCALECONV
|
||||
#include <locale.h>
|
||||
|
||||
/*
|
||||
- This code assumes that the decimal separator is exactly one
|
||||
character.
|
||||
|
||||
- If setlocale() is called by another thread between the call to
|
||||
localeconv() and the call to sprintf() or strtod(), the result may
|
||||
be wrong. setlocale() is not thread-safe and should not be used
|
||||
this way. Multi-threaded programs should use uselocale() instead.
|
||||
*/
|
||||
|
||||
static void to_locale(strbuffer_t *strbuffer)
|
||||
{
|
||||
const char *point;
|
||||
char *pos;
|
||||
|
||||
point = localeconv()->decimal_point;
|
||||
if(*point == '.') {
|
||||
/* No conversion needed */
|
||||
return;
|
||||
}
|
||||
|
||||
pos = strchr(strbuffer->value, '.');
|
||||
if(pos)
|
||||
*pos = *point;
|
||||
}
|
||||
|
||||
static void from_locale(char *buffer)
|
||||
{
|
||||
const char *point;
|
||||
char *pos;
|
||||
|
||||
point = localeconv()->decimal_point;
|
||||
if(*point == '.') {
|
||||
/* No conversion needed */
|
||||
return;
|
||||
}
|
||||
|
||||
pos = strchr(buffer, *point);
|
||||
if(pos)
|
||||
*pos = '.';
|
||||
}
|
||||
#endif
|
||||
|
||||
int jsonp_strtod(strbuffer_t *strbuffer, double *out)
|
||||
{
|
||||
double value;
|
||||
char *end;
|
||||
|
||||
#if JSON_HAVE_LOCALECONV
|
||||
to_locale(strbuffer);
|
||||
#endif
|
||||
|
||||
errno = 0;
|
||||
value = strtod(strbuffer->value, &end);
|
||||
assert(end == strbuffer->value + strbuffer->length);
|
||||
|
||||
if((value == HUGE_VAL || value == -HUGE_VAL) && errno == ERANGE) {
|
||||
/* Overflow */
|
||||
return -1;
|
||||
}
|
||||
|
||||
*out = value;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int jsonp_dtostr(char *buffer, size_t size, double value, int precision)
|
||||
{
|
||||
int ret;
|
||||
char *start, *end;
|
||||
size_t length;
|
||||
|
||||
if (precision == 0)
|
||||
precision = 17;
|
||||
|
||||
ret = snprintf(buffer, size, "%.*g", precision, value);
|
||||
if(ret < 0)
|
||||
return -1;
|
||||
|
||||
length = (size_t)ret;
|
||||
if(length >= size)
|
||||
return -1;
|
||||
|
||||
#if JSON_HAVE_LOCALECONV
|
||||
from_locale(buffer);
|
||||
#endif
|
||||
|
||||
/* Make sure there's a dot or 'e' in the output. Otherwise
|
||||
a real is converted to an integer when decoding */
|
||||
if(strchr(buffer, '.') == NULL &&
|
||||
strchr(buffer, 'e') == NULL)
|
||||
{
|
||||
if(length + 3 >= size) {
|
||||
/* No space to append ".0" */
|
||||
return -1;
|
||||
}
|
||||
buffer[length] = '.';
|
||||
buffer[length + 1] = '0';
|
||||
buffer[length + 2] = '\0';
|
||||
length += 2;
|
||||
}
|
||||
|
||||
/* Remove leading '+' from positive exponent. Also remove leading
|
||||
zeros from exponents (added by some printf() implementations) */
|
||||
start = strchr(buffer, 'e');
|
||||
if(start) {
|
||||
start++;
|
||||
end = start + 1;
|
||||
|
||||
if(*start == '-')
|
||||
start++;
|
||||
|
||||
while(*end == '0')
|
||||
end++;
|
||||
|
||||
if(end != start) {
|
||||
memmove(start, end, length - (size_t)(end - buffer));
|
||||
length -= (size_t)(end - start);
|
||||
}
|
||||
}
|
||||
|
||||
return (int)length;
|
||||
}
|
||||
@@ -1,187 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2009-2016 Petri Lehtinen <petri@digip.org>
|
||||
*
|
||||
* Jansson is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the MIT license. See LICENSE for details.
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include "utf.h"
|
||||
|
||||
int utf8_encode(int32_t codepoint, char *buffer, size_t *size)
|
||||
{
|
||||
if(codepoint < 0)
|
||||
return -1;
|
||||
else if(codepoint < 0x80)
|
||||
{
|
||||
buffer[0] = (char)codepoint;
|
||||
*size = 1;
|
||||
}
|
||||
else if(codepoint < 0x800)
|
||||
{
|
||||
buffer[0] = 0xC0 + ((codepoint & 0x7C0) >> 6);
|
||||
buffer[1] = 0x80 + ((codepoint & 0x03F));
|
||||
*size = 2;
|
||||
}
|
||||
else if(codepoint < 0x10000)
|
||||
{
|
||||
buffer[0] = 0xE0 + ((codepoint & 0xF000) >> 12);
|
||||
buffer[1] = 0x80 + ((codepoint & 0x0FC0) >> 6);
|
||||
buffer[2] = 0x80 + ((codepoint & 0x003F));
|
||||
*size = 3;
|
||||
}
|
||||
else if(codepoint <= 0x10FFFF)
|
||||
{
|
||||
buffer[0] = 0xF0 + ((codepoint & 0x1C0000) >> 18);
|
||||
buffer[1] = 0x80 + ((codepoint & 0x03F000) >> 12);
|
||||
buffer[2] = 0x80 + ((codepoint & 0x000FC0) >> 6);
|
||||
buffer[3] = 0x80 + ((codepoint & 0x00003F));
|
||||
*size = 4;
|
||||
}
|
||||
else
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
size_t utf8_check_first(char byte)
|
||||
{
|
||||
unsigned char u = (unsigned char)byte;
|
||||
|
||||
if(u < 0x80)
|
||||
return 1;
|
||||
|
||||
if(0x80 <= u && u <= 0xBF) {
|
||||
/* second, third or fourth byte of a multi-byte
|
||||
sequence, i.e. a "continuation byte" */
|
||||
return 0;
|
||||
}
|
||||
else if(u == 0xC0 || u == 0xC1) {
|
||||
/* overlong encoding of an ASCII byte */
|
||||
return 0;
|
||||
}
|
||||
else if(0xC2 <= u && u <= 0xDF) {
|
||||
/* 2-byte sequence */
|
||||
return 2;
|
||||
}
|
||||
|
||||
else if(0xE0 <= u && u <= 0xEF) {
|
||||
/* 3-byte sequence */
|
||||
return 3;
|
||||
}
|
||||
else if(0xF0 <= u && u <= 0xF4) {
|
||||
/* 4-byte sequence */
|
||||
return 4;
|
||||
}
|
||||
else { /* u >= 0xF5 */
|
||||
/* Restricted (start of 4-, 5- or 6-byte sequence) or invalid
|
||||
UTF-8 */
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
size_t utf8_check_full(const char *buffer, size_t size, int32_t *codepoint)
|
||||
{
|
||||
size_t i;
|
||||
int32_t value = 0;
|
||||
unsigned char u = (unsigned char)buffer[0];
|
||||
|
||||
if(size == 2)
|
||||
{
|
||||
value = u & 0x1F;
|
||||
}
|
||||
else if(size == 3)
|
||||
{
|
||||
value = u & 0xF;
|
||||
}
|
||||
else if(size == 4)
|
||||
{
|
||||
value = u & 0x7;
|
||||
}
|
||||
else
|
||||
return 0;
|
||||
|
||||
for(i = 1; i < size; i++)
|
||||
{
|
||||
u = (unsigned char)buffer[i];
|
||||
|
||||
if(u < 0x80 || u > 0xBF) {
|
||||
/* not a continuation byte */
|
||||
return 0;
|
||||
}
|
||||
|
||||
value = (value << 6) + (u & 0x3F);
|
||||
}
|
||||
|
||||
if(value > 0x10FFFF) {
|
||||
/* not in Unicode range */
|
||||
return 0;
|
||||
}
|
||||
|
||||
else if(0xD800 <= value && value <= 0xDFFF) {
|
||||
/* invalid code point (UTF-16 surrogate halves) */
|
||||
return 0;
|
||||
}
|
||||
|
||||
else if((size == 2 && value < 0x80) ||
|
||||
(size == 3 && value < 0x800) ||
|
||||
(size == 4 && value < 0x10000)) {
|
||||
/* overlong encoding */
|
||||
return 0;
|
||||
}
|
||||
|
||||
if(codepoint)
|
||||
*codepoint = value;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
const char *utf8_iterate(const char *buffer, size_t bufsize, int32_t *codepoint)
|
||||
{
|
||||
size_t count;
|
||||
int32_t value;
|
||||
|
||||
if(!bufsize)
|
||||
return buffer;
|
||||
|
||||
count = utf8_check_first(buffer[0]);
|
||||
if(count <= 0)
|
||||
return NULL;
|
||||
|
||||
if(count == 1)
|
||||
value = (unsigned char)buffer[0];
|
||||
else
|
||||
{
|
||||
if(count > bufsize || !utf8_check_full(buffer, count, &value))
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if(codepoint)
|
||||
*codepoint = value;
|
||||
|
||||
return buffer + count;
|
||||
}
|
||||
|
||||
int utf8_check_string(const char *string, size_t length)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
for(i = 0; i < length; i++)
|
||||
{
|
||||
size_t count = utf8_check_first(string[i]);
|
||||
if(count == 0)
|
||||
return 0;
|
||||
else if(count > 1)
|
||||
{
|
||||
if(count > length - i)
|
||||
return 0;
|
||||
|
||||
if(!utf8_check_full(&string[i], count, NULL))
|
||||
return 0;
|
||||
|
||||
i += count - 1;
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
@@ -1,27 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2009-2016 Petri Lehtinen <petri@digip.org>
|
||||
*
|
||||
* Jansson is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the MIT license. See LICENSE for details.
|
||||
*/
|
||||
|
||||
#ifndef UTF_H
|
||||
#define UTF_H
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include <jansson_private_config.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_STDINT_H
|
||||
#include <stdint.h>
|
||||
#endif
|
||||
|
||||
int utf8_encode(int32_t codepoint, char *buffer, size_t *size);
|
||||
|
||||
size_t utf8_check_first(char byte);
|
||||
size_t utf8_check_full(const char *buffer, size_t size, int32_t *codepoint);
|
||||
const char *utf8_iterate(const char *buffer, size_t size, int32_t *codepoint);
|
||||
|
||||
int utf8_check_string(const char *string, size_t length);
|
||||
|
||||
#endif
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,218 +0,0 @@
|
||||
/*
|
||||
* Copyright 2008 Veselin Georgiev,
|
||||
* anrieffNOSPAM @ mgail_DOT.com (convert to gmail)
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdarg.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
#include "libcpuid.h"
|
||||
#include "libcpuid_util.h"
|
||||
|
||||
int _current_verboselevel;
|
||||
|
||||
void match_features(const struct feature_map_t* matchtable, int count, uint32_t reg, struct cpu_id_t* data)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < count; i++)
|
||||
if (reg & (1u << matchtable[i].bit))
|
||||
data->flags[matchtable[i].feature] = 1;
|
||||
}
|
||||
|
||||
static void default_warn(const char *msg)
|
||||
{
|
||||
fprintf(stderr, "%s", msg);
|
||||
}
|
||||
|
||||
libcpuid_warn_fn_t _warn_fun = default_warn;
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
# define vsnprintf _vsnprintf
|
||||
#endif
|
||||
void warnf(const char* format, ...)
|
||||
{
|
||||
char buff[1024];
|
||||
va_list va;
|
||||
if (!_warn_fun) return;
|
||||
va_start(va, format);
|
||||
vsnprintf(buff, sizeof(buff), format, va);
|
||||
va_end(va);
|
||||
_warn_fun(buff);
|
||||
}
|
||||
|
||||
void debugf(int verboselevel, const char* format, ...)
|
||||
{
|
||||
char buff[1024];
|
||||
va_list va;
|
||||
if (verboselevel > _current_verboselevel) return;
|
||||
va_start(va, format);
|
||||
vsnprintf(buff, sizeof(buff), format, va);
|
||||
va_end(va);
|
||||
_warn_fun(buff);
|
||||
}
|
||||
|
||||
static int popcount64(uint64_t mask)
|
||||
{
|
||||
int num_set_bits = 0;
|
||||
|
||||
while (mask) {
|
||||
mask &= mask - 1;
|
||||
num_set_bits++;
|
||||
}
|
||||
|
||||
return num_set_bits;
|
||||
}
|
||||
|
||||
static int score(const struct match_entry_t* entry, const struct cpu_id_t* data,
|
||||
int brand_code, uint64_t bits, int model_code)
|
||||
{
|
||||
int res = 0;
|
||||
if (entry->family == data->family ) res += 2;
|
||||
if (entry->model == data->model ) res += 2;
|
||||
if (entry->stepping == data->stepping ) res += 2;
|
||||
if (entry->ext_family == data->ext_family) res += 2;
|
||||
if (entry->ext_model == data->ext_model ) res += 2;
|
||||
if (entry->ncores == data->num_cores ) res += 2;
|
||||
if (entry->l2cache == data->l2_cache ) res += 1;
|
||||
if (entry->l3cache == data->l3_cache ) res += 1;
|
||||
if (entry->brand_code == brand_code ) res += 2;
|
||||
if (entry->model_code == model_code ) res += 2;
|
||||
|
||||
res += popcount64(entry->model_bits & bits) * 2;
|
||||
return res;
|
||||
}
|
||||
|
||||
int match_cpu_codename(const struct match_entry_t* matchtable, int count,
|
||||
struct cpu_id_t* data, int brand_code, uint64_t bits,
|
||||
int model_code)
|
||||
{
|
||||
int bestscore = -1;
|
||||
int bestindex = 0;
|
||||
int i, t;
|
||||
|
||||
debugf(3, "Matching cpu f:%d, m:%d, s:%d, xf:%d, xm:%d, ncore:%d, l2:%d, bcode:%d, bits:%llu, code:%d\n",
|
||||
data->family, data->model, data->stepping, data->ext_family,
|
||||
data->ext_model, data->num_cores, data->l2_cache, brand_code, (unsigned long long) bits, model_code);
|
||||
|
||||
for (i = 0; i < count; i++) {
|
||||
t = score(&matchtable[i], data, brand_code, bits, model_code);
|
||||
debugf(3, "Entry %d, `%s', score %d\n", i, matchtable[i].name, t);
|
||||
if (t > bestscore) {
|
||||
debugf(2, "Entry `%s' selected - best score so far (%d)\n", matchtable[i].name, t);
|
||||
bestscore = t;
|
||||
bestindex = i;
|
||||
}
|
||||
}
|
||||
strcpy(data->cpu_codename, matchtable[bestindex].name);
|
||||
return bestscore;
|
||||
}
|
||||
|
||||
void generic_get_cpu_list(const struct match_entry_t* matchtable, int count,
|
||||
struct cpu_list_t* list)
|
||||
{
|
||||
int i, j, n, good;
|
||||
n = 0;
|
||||
list->names = (char**) malloc(sizeof(char*) * count);
|
||||
for (i = 0; i < count; i++) {
|
||||
if (strstr(matchtable[i].name, "Unknown")) continue;
|
||||
good = 1;
|
||||
for (j = n - 1; j >= 0; j--)
|
||||
if (!strcmp(list->names[j], matchtable[i].name)) {
|
||||
good = 0;
|
||||
break;
|
||||
}
|
||||
if (!good) continue;
|
||||
#if defined(_MSC_VER)
|
||||
list->names[n++] = _strdup(matchtable[i].name);
|
||||
#else
|
||||
list->names[n++] = strdup(matchtable[i].name);
|
||||
#endif
|
||||
}
|
||||
list->num_entries = n;
|
||||
}
|
||||
|
||||
static int xmatch_entry(char c, const char* p)
|
||||
{
|
||||
int i, j;
|
||||
if (c == 0) return -1;
|
||||
if (c == p[0]) return 1;
|
||||
if (p[0] == '.') return 1;
|
||||
if (p[0] == '#' && isdigit(c)) return 1;
|
||||
if (p[0] == '[') {
|
||||
j = 1;
|
||||
while (p[j] && p[j] != ']') j++;
|
||||
if (!p[j]) return -1;
|
||||
for (i = 1; i < j; i++)
|
||||
if (p[i] == c) return j + 1;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
int match_pattern(const char* s, const char* p)
|
||||
{
|
||||
int i, j, dj, k, n, m;
|
||||
n = (int) strlen(s);
|
||||
m = (int) strlen(p);
|
||||
for (i = 0; i < n; i++) {
|
||||
if (xmatch_entry(s[i], p) != -1) {
|
||||
j = 0;
|
||||
k = 0;
|
||||
while (j < m && ((dj = xmatch_entry(s[i + k], p + j)) != -1)) {
|
||||
k++;
|
||||
j += dj;
|
||||
}
|
||||
if (j == m) return i + 1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct cpu_id_t* get_cached_cpuid(void)
|
||||
{
|
||||
static int initialized = 0;
|
||||
static struct cpu_id_t id;
|
||||
if (initialized) return &id;
|
||||
if (cpu_identify(NULL, &id))
|
||||
memset(&id, 0, sizeof(id));
|
||||
initialized = 1;
|
||||
return &id;
|
||||
}
|
||||
|
||||
int match_all(uint64_t bits, uint64_t mask)
|
||||
{
|
||||
return (bits & mask) == mask;
|
||||
}
|
||||
|
||||
void debug_print_lbits(int debuglevel, uint64_t mask)
|
||||
{
|
||||
int i, first = 0;
|
||||
for (i = 0; i < 64; i++) if (mask & (((uint64_t) 1) << i)) {
|
||||
if (first) first = 0;
|
||||
else debugf(2, " + ");
|
||||
debugf(2, "LBIT(%d)", i);
|
||||
}
|
||||
debugf(2, "\n");
|
||||
}
|
||||
@@ -1,549 +0,0 @@
|
||||
/*
|
||||
* Copyright 2008 Veselin Georgiev,
|
||||
* anrieffNOSPAM @ mgail_DOT.com (convert to gmail)
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
#include "libcpuid.h"
|
||||
#include "libcpuid_util.h"
|
||||
#include "libcpuid_internal.h"
|
||||
#include "recog_amd.h"
|
||||
|
||||
const struct amd_code_str { amd_code_t code; char *str; } amd_code_str[] = {
|
||||
#define CODE(x) { x, #x }
|
||||
#define CODE2(x, y) CODE(x)
|
||||
#include "amd_code_t.h"
|
||||
#undef CODE
|
||||
};
|
||||
|
||||
struct amd_code_and_bits_t {
|
||||
int code;
|
||||
uint64_t bits;
|
||||
};
|
||||
|
||||
enum _amd_bits_t {
|
||||
ATHLON_ = LBIT( 0 ),
|
||||
_XP_ = LBIT( 1 ),
|
||||
_M_ = LBIT( 2 ),
|
||||
_MP_ = LBIT( 3 ),
|
||||
MOBILE_ = LBIT( 4 ),
|
||||
DURON_ = LBIT( 5 ),
|
||||
SEMPRON_ = LBIT( 6 ),
|
||||
OPTERON_ = LBIT( 7 ),
|
||||
TURION_ = LBIT( 8 ),
|
||||
_LV_ = LBIT( 9 ),
|
||||
_64_ = LBIT( 10 ),
|
||||
_X2 = LBIT( 11 ),
|
||||
_X3 = LBIT( 12 ),
|
||||
_X4 = LBIT( 13 ),
|
||||
_X6 = LBIT( 14 ),
|
||||
_FX = LBIT( 15 ),
|
||||
};
|
||||
typedef enum _amd_bits_t amd_bits_t;
|
||||
|
||||
enum _amd_model_codes_t {
|
||||
// Only for Ryzen CPUs:
|
||||
_1400,
|
||||
_1500,
|
||||
_1600,
|
||||
};
|
||||
|
||||
|
||||
const struct match_entry_t cpudb_amd[] = {
|
||||
{ -1, -1, -1, -1, -1, 1, -1, -1, NC, 0 , 0, "Unknown AMD CPU" },
|
||||
|
||||
/* 486 and the likes */
|
||||
{ 4, -1, -1, -1, -1, 1, -1, -1, NC, 0 , 0, "Unknown AMD 486" },
|
||||
{ 4, 3, -1, -1, -1, 1, -1, -1, NC, 0 , 0, "AMD 486DX2" },
|
||||
{ 4, 7, -1, -1, -1, 1, -1, -1, NC, 0 , 0, "AMD 486DX2WB" },
|
||||
{ 4, 8, -1, -1, -1, 1, -1, -1, NC, 0 , 0, "AMD 486DX4" },
|
||||
{ 4, 9, -1, -1, -1, 1, -1, -1, NC, 0 , 0, "AMD 486DX4WB" },
|
||||
|
||||
/* Pentia clones */
|
||||
{ 5, -1, -1, -1, -1, 1, -1, -1, NC, 0 , 0, "Unknown AMD 586" },
|
||||
{ 5, 0, -1, -1, -1, 1, -1, -1, NC, 0 , 0, "K5" },
|
||||
{ 5, 1, -1, -1, -1, 1, -1, -1, NC, 0 , 0, "K5" },
|
||||
{ 5, 2, -1, -1, -1, 1, -1, -1, NC, 0 , 0, "K5" },
|
||||
{ 5, 3, -1, -1, -1, 1, -1, -1, NC, 0 , 0, "K5" },
|
||||
|
||||
/* The K6 */
|
||||
{ 5, 6, -1, -1, -1, 1, -1, -1, NC, 0 , 0, "K6" },
|
||||
{ 5, 7, -1, -1, -1, 1, -1, -1, NC, 0 , 0, "K6" },
|
||||
|
||||
{ 5, 8, -1, -1, -1, 1, -1, -1, NC, 0 , 0, "K6-2" },
|
||||
{ 5, 9, -1, -1, -1, 1, -1, -1, NC, 0 , 0, "K6-III" },
|
||||
{ 5, 10, -1, -1, -1, 1, -1, -1, NC, 0 , 0, "Unknown K6" },
|
||||
{ 5, 11, -1, -1, -1, 1, -1, -1, NC, 0 , 0, "Unknown K6" },
|
||||
{ 5, 12, -1, -1, -1, 1, -1, -1, NC, 0 , 0, "Unknown K6" },
|
||||
{ 5, 13, -1, -1, -1, 1, -1, -1, NC, 0 , 0, "K6-2+" },
|
||||
|
||||
/* Athlon et al. */
|
||||
{ 6, 1, -1, -1, -1, 1, -1, -1, NC, 0 , 0, "Athlon (Slot-A)" },
|
||||
{ 6, 2, -1, -1, -1, 1, -1, -1, NC, 0 , 0, "Athlon (Slot-A)" },
|
||||
{ 6, 3, -1, -1, -1, 1, -1, -1, NC, 0 , 0, "Duron (Spitfire)" },
|
||||
{ 6, 4, -1, -1, -1, 1, -1, -1, NC, 0 , 0, "Athlon (ThunderBird)" },
|
||||
|
||||
{ 6, 6, -1, -1, -1, 1, -1, -1, NC, 0 , 0, "Unknown Athlon" },
|
||||
{ 6, 6, -1, -1, -1, 1, -1, -1, NC, ATHLON_ , 0, "Athlon (Palomino)" },
|
||||
{ 6, 6, -1, -1, -1, 1, -1, -1, NC, ATHLON_|_MP_ , 0, "Athlon MP (Palomino)" },
|
||||
{ 6, 6, -1, -1, -1, 1, -1, -1, NC, DURON_ , 0, "Duron (Palomino)" },
|
||||
{ 6, 6, -1, -1, -1, 1, -1, -1, NC, ATHLON_|_XP_ , 0, "Athlon XP" },
|
||||
|
||||
{ 6, 7, -1, -1, -1, 1, -1, -1, NC, 0 , 0, "Unknown Athlon XP" },
|
||||
{ 6, 7, -1, -1, -1, 1, -1, -1, NC, DURON_ , 0, "Duron (Morgan)" },
|
||||
|
||||
{ 6, 8, -1, -1, -1, 1, -1, -1, NC, 0 , 0, "Athlon XP" },
|
||||
{ 6, 8, -1, -1, -1, 1, -1, -1, NC, ATHLON_ , 0, "Athlon XP (Thoroughbred)" },
|
||||
{ 6, 8, -1, -1, -1, 1, -1, -1, NC, ATHLON_|_XP_ , 0, "Athlon XP (Thoroughbred)" },
|
||||
{ 6, 8, -1, -1, -1, 1, -1, -1, NC, DURON_ , 0, "Duron (Applebred)" },
|
||||
{ 6, 8, -1, -1, -1, 1, -1, -1, NC, SEMPRON_ , 0, "Sempron (Thoroughbred)" },
|
||||
{ 6, 8, -1, -1, -1, 1, 128, -1, NC, SEMPRON_ , 0, "Sempron (Thoroughbred)" },
|
||||
{ 6, 8, -1, -1, -1, 1, 256, -1, NC, SEMPRON_ , 0, "Sempron (Thoroughbred)" },
|
||||
{ 6, 8, -1, -1, -1, 1, -1, -1, NC, ATHLON_|_MP_ , 0, "Athlon MP (Thoroughbred)" },
|
||||
{ 6, 8, -1, -1, -1, 1, -1, -1, NC, ATHLON_|_XP_|_M_ , 0, "Mobile Athlon (T-Bred)" },
|
||||
{ 6, 8, -1, -1, -1, 1, -1, -1, NC, ATHLON_|_XP_|_M_|_LV_, 0, "Mobile Athlon (T-Bred)" },
|
||||
|
||||
{ 6, 10, -1, -1, -1, 1, -1, -1, NC, 0 , 0, "Athlon XP (Barton)" },
|
||||
{ 6, 10, -1, -1, -1, 1, 512, -1, NC, ATHLON_|_XP_ , 0, "Athlon XP (Barton)" },
|
||||
{ 6, 10, -1, -1, -1, 1, 512, -1, NC, SEMPRON_ , 0, "Sempron (Barton)" },
|
||||
{ 6, 10, -1, -1, -1, 1, 256, -1, NC, SEMPRON_ , 0, "Sempron (Thorton)" },
|
||||
{ 6, 10, -1, -1, -1, 1, 256, -1, NC, ATHLON_|_XP_ , 0, "Athlon XP (Thorton)" },
|
||||
{ 6, 10, -1, -1, -1, 1, -1, -1, NC, ATHLON_|_MP_ , 0, "Athlon MP (Barton)" },
|
||||
{ 6, 10, -1, -1, -1, 1, -1, -1, NC, ATHLON_|_XP_|_M_ , 0, "Mobile Athlon (Barton)" },
|
||||
{ 6, 10, -1, -1, -1, 1, -1, -1, NC, ATHLON_|_XP_|_M_|_LV_, 0, "Mobile Athlon (Barton)" },
|
||||
|
||||
/* K8 Architecture */
|
||||
{ 15, -1, -1, 15, -1, 1, -1, -1, NC, 0 , 0, "Unknown K8" },
|
||||
{ 15, -1, -1, 16, -1, 1, -1, -1, NC, 0 , 0, "Unknown K9" },
|
||||
|
||||
{ 15, -1, -1, 15, -1, 1, -1, -1, NC, 0 , 0, "Unknown A64" },
|
||||
{ 15, -1, -1, 15, -1, 1, -1, -1, NC, OPTERON_ , 0, "Opteron" },
|
||||
{ 15, -1, -1, 15, -1, 2, -1, -1, NC, OPTERON_|_X2 , 0, "Opteron (Dual Core)" },
|
||||
{ 15, 3, -1, 15, -1, 1, -1, -1, NC, OPTERON_ , 0, "Opteron" },
|
||||
{ 15, 3, -1, 15, -1, 2, -1, -1, NC, OPTERON_|_X2 , 0, "Opteron (Dual Core)" },
|
||||
{ 15, -1, -1, 15, -1, 1, 512, -1, NC, ATHLON_|_64_ , 0, "Athlon 64 (512K)" },
|
||||
{ 15, -1, -1, 15, -1, 1, 1024, -1, NC, ATHLON_|_64_ , 0, "Athlon 64 (1024K)" },
|
||||
{ 15, -1, -1, 15, -1, 1, -1, -1, NC, ATHLON_|_FX , 0, "Athlon FX" },
|
||||
{ 15, -1, -1, 15, -1, 1, -1, -1, NC, ATHLON_|_64_|_FX , 0, "Athlon 64 FX" },
|
||||
{ 15, 3, -1, 15, 35, 2, -1, -1, NC, ATHLON_|_64_|_FX , 0, "Athlon 64 FX X2 (Toledo)" },
|
||||
{ 15, -1, -1, 15, -1, 2, 512, -1, NC, ATHLON_|_64_|_X2 , 0, "Athlon 64 X2 (512K)" },
|
||||
{ 15, -1, -1, 15, -1, 2, 1024, -1, NC, ATHLON_|_64_|_X2 , 0, "Athlon 64 X2 (1024K)" },
|
||||
{ 15, -1, -1, 15, -1, 1, 512, -1, NC, TURION_|_64_ , 0, "Turion 64 (512K)" },
|
||||
{ 15, -1, -1, 15, -1, 1, 1024, -1, NC, TURION_|_64_ , 0, "Turion 64 (1024K)" },
|
||||
{ 15, -1, -1, 15, -1, 2, 512, -1, NC, TURION_|_X2 , 0, "Turion 64 X2 (512K)" },
|
||||
{ 15, -1, -1, 15, -1, 2, 1024, -1, NC, TURION_|_X2 , 0, "Turion 64 X2 (1024K)" },
|
||||
{ 15, -1, -1, 15, -1, 1, 128, -1, NC, SEMPRON_ , 0, "A64 Sempron (128K)" },
|
||||
{ 15, -1, -1, 15, -1, 1, 256, -1, NC, SEMPRON_ , 0, "A64 Sempron (256K)" },
|
||||
{ 15, -1, -1, 15, -1, 1, 512, -1, NC, SEMPRON_ , 0, "A64 Sempron (512K)" },
|
||||
{ 15, -1, -1, 15, 0x4f, 1, 512, -1, NC, ATHLON_|_64_ , 0, "Athlon 64 (Orleans/512K)" },
|
||||
{ 15, -1, -1, 15, 0x5f, 1, 512, -1, NC, ATHLON_|_64_ , 0, "Athlon 64 (Orleans/512K)" },
|
||||
{ 15, -1, -1, 15, 0x2f, 1, 512, -1, NC, ATHLON_|_64_ , 0, "Athlon 64 (Venice/512K)" },
|
||||
{ 15, -1, -1, 15, 0x2c, 1, 512, -1, NC, ATHLON_|_64_ , 0, "Athlon 64 (Venice/512K)" },
|
||||
{ 15, -1, -1, 15, 0x1f, 1, 512, -1, NC, ATHLON_|_64_ , 0, "Athlon 64 (Winchester/512K)" },
|
||||
{ 15, -1, -1, 15, 0x0c, 1, 512, -1, NC, ATHLON_|_64_ , 0, "Athlon 64 (Newcastle/512K)" },
|
||||
{ 15, -1, -1, 15, 0x27, 1, 512, -1, NC, ATHLON_|_64_ , 0, "Athlon 64 (San Diego/512K)" },
|
||||
{ 15, -1, -1, 15, 0x37, 1, 512, -1, NC, ATHLON_|_64_ , 0, "Athlon 64 (San Diego/512K)" },
|
||||
{ 15, -1, -1, 15, 0x04, 1, 512, -1, NC, ATHLON_|_64_ , 0, "Athlon 64 (ClawHammer/512K)" },
|
||||
|
||||
{ 15, -1, -1, 15, 0x5f, 1, 1024, -1, NC, ATHLON_|_64_ , 0, "Athlon 64 (Orleans/1024K)" },
|
||||
{ 15, -1, -1, 15, 0x27, 1, 1024, -1, NC, ATHLON_|_64_ , 0, "Athlon 64 (San Diego/1024K)" },
|
||||
{ 15, -1, -1, 15, 0x04, 1, 1024, -1, NC, ATHLON_|_64_ , 0, "Athlon 64 (ClawHammer/1024K)" },
|
||||
|
||||
{ 15, -1, -1, 15, 0x4b, 2, 256, -1, NC, SEMPRON_ , 0, "Athlon 64 X2 (Windsor/256K)" },
|
||||
|
||||
{ 15, -1, -1, 15, 0x23, 2, 512, -1, NC, ATHLON_|_64_|_X2 , 0, "Athlon 64 X2 (Toledo/512K)" },
|
||||
{ 15, -1, -1, 15, 0x4b, 2, 512, -1, NC, ATHLON_|_64_|_X2 , 0, "Athlon 64 X2 (Windsor/512K)" },
|
||||
{ 15, -1, -1, 15, 0x43, 2, 512, -1, NC, ATHLON_|_64_|_X2 , 0, "Athlon 64 X2 (Windsor/512K)" },
|
||||
{ 15, -1, -1, 15, 0x6b, 2, 512, -1, NC, ATHLON_|_64_|_X2 , 0, "Athlon 64 X2 (Brisbane/512K)" },
|
||||
{ 15, -1, -1, 15, 0x2b, 2, 512, -1, NC, ATHLON_|_64_|_X2 , 0, "Athlon 64 X2 (Manchester/512K)"},
|
||||
|
||||
{ 15, -1, -1, 15, 0x23, 2, 1024, -1, NC, ATHLON_|_64_|_X2 , 0, "Athlon 64 X2 (Toledo/1024K)" },
|
||||
{ 15, -1, -1, 15, 0x43, 2, 1024, -1, NC, ATHLON_|_64_|_X2 , 0, "Athlon 64 X2 (Windsor/1024K)" },
|
||||
|
||||
{ 15, -1, -1, 15, 0x08, 1, 128, -1, NC, MOBILE_|SEMPRON_ , 0, "Mobile Sempron 64 (Dublin/128K)"},
|
||||
{ 15, -1, -1, 15, 0x08, 1, 256, -1, NC, MOBILE_|SEMPRON_ , 0, "Mobile Sempron 64 (Dublin/256K)"},
|
||||
{ 15, -1, -1, 15, 0x0c, 1, 256, -1, NC, SEMPRON_ , 0, "Sempron 64 (Paris)" },
|
||||
{ 15, -1, -1, 15, 0x1c, 1, 128, -1, NC, SEMPRON_ , 0, "Sempron 64 (Palermo/128K)" },
|
||||
{ 15, -1, -1, 15, 0x1c, 1, 256, -1, NC, SEMPRON_ , 0, "Sempron 64 (Palermo/256K)" },
|
||||
{ 15, -1, -1, 15, 0x1c, 1, 128, -1, NC, MOBILE_| SEMPRON_ , 0, "Mobile Sempron 64 (Sonora/128K)"},
|
||||
{ 15, -1, -1, 15, 0x1c, 1, 256, -1, NC, MOBILE_| SEMPRON_ , 0, "Mobile Sempron 64 (Sonora/256K)"},
|
||||
{ 15, -1, -1, 15, 0x2c, 1, 128, -1, NC, SEMPRON_ , 0, "Sempron 64 (Palermo/128K)" },
|
||||
{ 15, -1, -1, 15, 0x2c, 1, 256, -1, NC, SEMPRON_ , 0, "Sempron 64 (Palermo/256K)" },
|
||||
{ 15, -1, -1, 15, 0x2c, 1, 128, -1, NC, MOBILE_| SEMPRON_ , 0, "Mobile Sempron 64 (Albany/128K)"},
|
||||
{ 15, -1, -1, 15, 0x2c, 1, 256, -1, NC, MOBILE_| SEMPRON_ , 0, "Mobile Sempron 64 (Albany/256K)"},
|
||||
{ 15, -1, -1, 15, 0x2f, 1, 128, -1, NC, SEMPRON_ , 0, "Sempron 64 (Palermo/128K)" },
|
||||
{ 15, -1, -1, 15, 0x2f, 1, 256, -1, NC, SEMPRON_ , 0, "Sempron 64 (Palermo/256K)" },
|
||||
{ 15, -1, -1, 15, 0x4f, 1, 128, -1, NC, SEMPRON_ , 0, "Sempron 64 (Manila/128K)" },
|
||||
{ 15, -1, -1, 15, 0x4f, 1, 256, -1, NC, SEMPRON_ , 0, "Sempron 64 (Manila/256K)" },
|
||||
{ 15, -1, -1, 15, 0x5f, 1, 128, -1, NC, SEMPRON_ , 0, "Sempron 64 (Manila/128K)" },
|
||||
{ 15, -1, -1, 15, 0x5f, 1, 256, -1, NC, SEMPRON_ , 0, "Sempron 64 (Manila/256K)" },
|
||||
{ 15, -1, -1, 15, 0x6b, 2, 256, -1, NC, SEMPRON_ , 0, "Sempron 64 Dual (Sherman/256K)"},
|
||||
{ 15, -1, -1, 15, 0x6b, 2, 512, -1, NC, SEMPRON_ , 0, "Sempron 64 Dual (Sherman/512K)"},
|
||||
{ 15, -1, -1, 15, 0x7f, 1, 256, -1, NC, SEMPRON_ , 0, "Sempron 64 (Sparta/256K)" },
|
||||
{ 15, -1, -1, 15, 0x7f, 1, 512, -1, NC, SEMPRON_ , 0, "Sempron 64 (Sparta/512K)" },
|
||||
{ 15, -1, -1, 15, 0x4c, 1, 256, -1, NC, MOBILE_| SEMPRON_ , 0, "Mobile Sempron 64 (Keene/256K)"},
|
||||
{ 15, -1, -1, 15, 0x4c, 1, 512, -1, NC, MOBILE_| SEMPRON_ , 0, "Mobile Sempron 64 (Keene/512K)"},
|
||||
{ 15, -1, -1, 15, -1, 2, -1, -1, NC, SEMPRON_ , 0, "Sempron Dual Core" },
|
||||
|
||||
{ 15, -1, -1, 15, 0x24, 1, 512, -1, NC, TURION_|_64_ , 0, "Turion 64 (Lancaster/512K)" },
|
||||
{ 15, -1, -1, 15, 0x24, 1, 1024, -1, NC, TURION_|_64_ , 0, "Turion 64 (Lancaster/1024K)" },
|
||||
{ 15, -1, -1, 15, 0x48, 2, 256, -1, NC, TURION_|_X2 , 0, "Turion X2 (Taylor)" },
|
||||
{ 15, -1, -1, 15, 0x48, 2, 512, -1, NC, TURION_|_X2 , 0, "Turion X2 (Trinidad)" },
|
||||
{ 15, -1, -1, 15, 0x4c, 1, 512, -1, NC, TURION_|_64_ , 0, "Turion 64 (Richmond)" },
|
||||
{ 15, -1, -1, 15, 0x68, 2, 256, -1, NC, TURION_|_X2 , 0, "Turion X2 (Tyler/256K)" },
|
||||
{ 15, -1, -1, 15, 0x68, 2, 512, -1, NC, TURION_|_X2 , 0, "Turion X2 (Tyler/512K)" },
|
||||
{ 15, -1, -1, 17, 3, 2, 512, -1, NC, TURION_|_X2 , 0, "Turion X2 (Griffin/512K)" },
|
||||
{ 15, -1, -1, 17, 3, 2, 1024, -1, NC, TURION_|_X2 , 0, "Turion X2 (Griffin/1024K)" },
|
||||
|
||||
/* K10 Architecture (2007) */
|
||||
{ 15, -1, -1, 16, -1, 1, -1, -1, PHENOM, 0 , 0, "Unknown AMD Phenom" },
|
||||
{ 15, 2, -1, 16, -1, 1, -1, -1, PHENOM, 0 , 0, "Phenom" },
|
||||
{ 15, 2, -1, 16, -1, 3, -1, -1, PHENOM, 0 , 0, "Phenom X3 (Toliman)" },
|
||||
{ 15, 2, -1, 16, -1, 4, -1, -1, PHENOM, 0 , 0, "Phenom X4 (Agena)" },
|
||||
{ 15, 2, -1, 16, -1, 3, 512, -1, PHENOM, 0 , 0, "Phenom X3 (Toliman/256K)" },
|
||||
{ 15, 2, -1, 16, -1, 3, 512, -1, PHENOM, 0 , 0, "Phenom X3 (Toliman/512K)" },
|
||||
{ 15, 2, -1, 16, -1, 4, 128, -1, PHENOM, 0 , 0, "Phenom X4 (Agena/128K)" },
|
||||
{ 15, 2, -1, 16, -1, 4, 256, -1, PHENOM, 0 , 0, "Phenom X4 (Agena/256K)" },
|
||||
{ 15, 2, -1, 16, -1, 4, 512, -1, PHENOM, 0 , 0, "Phenom X4 (Agena/512K)" },
|
||||
{ 15, 2, -1, 16, -1, 2, 512, -1, NC, ATHLON_|_64_|_X2 , 0, "Athlon X2 (Kuma)" },
|
||||
/* Phenom II derivates: */
|
||||
{ 15, 4, -1, 16, -1, 4, -1, -1, NC, 0 , 0, "Phenom (Deneb-based)" },
|
||||
{ 15, 4, -1, 16, -1, 1, 1024, -1, NC, SEMPRON_ , 0, "Sempron (Sargas)" },
|
||||
{ 15, 4, -1, 16, -1, 2, 512, -1, PHENOM2, 0 , 0, "Phenom II X2 (Callisto)" },
|
||||
{ 15, 4, -1, 16, -1, 3, 512, -1, PHENOM2, 0 , 0, "Phenom II X3 (Heka)" },
|
||||
{ 15, 4, -1, 16, -1, 4, 512, -1, PHENOM2, 0 , 0, "Phenom II X4" },
|
||||
{ 15, 4, -1, 16, 4, 4, 512, -1, PHENOM2, 0 , 0, "Phenom II X4 (Deneb)" },
|
||||
{ 15, 5, -1, 16, 5, 4, 512, -1, PHENOM2, 0 , 0, "Phenom II X4 (Deneb)" },
|
||||
{ 15, 4, -1, 16, 10, 4, 512, -1, PHENOM2, 0 , 0, "Phenom II X4 (Zosma)" },
|
||||
{ 15, 4, -1, 16, 10, 6, 512, -1, PHENOM2, 0 , 0, "Phenom II X6 (Thuban)" },
|
||||
/* Athlon II derivates: */
|
||||
{ 15, 6, -1, 16, 6, 2, 512, -1, NC, ATHLON_|_X2 , 0, "Athlon II (Champlain)" },
|
||||
{ 15, 6, -1, 16, 6, 2, 512, -1, NC, ATHLON_|_64_|_X2 , 0, "Athlon II X2 (Regor)" },
|
||||
{ 15, 6, -1, 16, 6, 2, 1024, -1, NC, ATHLON_|_64_|_X2 , 0, "Athlon II X2 (Regor)" },
|
||||
{ 15, 5, -1, 16, 5, 3, 512, -1, NC, ATHLON_|_64_|_X3 , 0, "Athlon II X3 (Rana)" },
|
||||
{ 15, 5, -1, 16, 5, 4, 512, -1, NC, ATHLON_|_64_|_X4 , 0, "Athlon II X4 (Propus)" },
|
||||
/* Llano APUs (2011): */
|
||||
{ 15, 1, -1, 18, 1, 2, -1, -1, FUSION_EA, 0 , 0, "Llano X2" },
|
||||
{ 15, 1, -1, 18, 1, 3, -1, -1, FUSION_EA, 0 , 0, "Llano X3" },
|
||||
{ 15, 1, -1, 18, 1, 4, -1, -1, FUSION_EA, 0 , 0, "Llano X4" },
|
||||
|
||||
/* Family 14h: Bobcat Architecture (2011) */
|
||||
{ 15, 2, -1, 20, -1, 1, -1, -1, FUSION_C, 0 , 0, "Brazos Ontario" },
|
||||
{ 15, 2, -1, 20, -1, 2, -1, -1, FUSION_C, 0 , 0, "Brazos Ontario (Dual-core)" },
|
||||
{ 15, 1, -1, 20, -1, 1, -1, -1, FUSION_E, 0 , 0, "Brazos Zacate" },
|
||||
{ 15, 1, -1, 20, -1, 2, -1, -1, FUSION_E, 0 , 0, "Brazos Zacate (Dual-core)" },
|
||||
{ 15, 2, -1, 20, -1, 2, -1, -1, FUSION_Z, 0 , 0, "Brazos Desna (Dual-core)" },
|
||||
|
||||
/* Family 15h: Bulldozer Architecture (2011) */
|
||||
{ 15, -1, -1, 21, 0, 4, -1, -1, NC, 0 , 0, "Bulldozer X2" },
|
||||
{ 15, -1, -1, 21, 1, 4, -1, -1, NC, 0 , 0, "Bulldozer X2" },
|
||||
{ 15, -1, -1, 21, 1, 6, -1, -1, NC, 0 , 0, "Bulldozer X3" },
|
||||
{ 15, -1, -1, 21, 1, 8, -1, -1, NC, 0 , 0, "Bulldozer X4" },
|
||||
/* 2nd-gen, Piledriver core (2012): */
|
||||
{ 15, -1, -1, 21, 2, 4, -1, -1, NC, 0 , 0, "Vishera X2" },
|
||||
{ 15, -1, -1, 21, 2, 6, -1, -1, NC, 0 , 0, "Vishera X3" },
|
||||
{ 15, -1, -1, 21, 2, 8, -1, -1, NC, 0 , 0, "Vishera X4" },
|
||||
{ 15, 0, -1, 21, 16, 2, -1, -1, FUSION_A, 0 , 0, "Trinity X2" },
|
||||
{ 15, 0, -1, 21, 16, 4, -1, -1, FUSION_A, 0 , 0, "Trinity X4" },
|
||||
{ 15, 3, -1, 21, 19, 2, -1, -1, FUSION_A, 0 , 0, "Richland X2" },
|
||||
{ 15, 3, -1, 21, 19, 4, -1, -1, FUSION_A, 0 , 0, "Richland X4" },
|
||||
/* 3rd-gen, Steamroller core (2014): */
|
||||
{ 15, 0, -1, 21, 48, 2, -1, -1, FUSION_A, 0 , 0, "Kaveri X2" },
|
||||
{ 15, 0, -1, 21, 48, 4, -1, -1, FUSION_A, 0 , 0, "Kaveri X4" },
|
||||
{ 15, 8, -1, 21, 56, 4, -1, -1, FUSION_A, 0 , 0, "Godavari X4" },
|
||||
/* 4th-gen, Excavator core (2015): */
|
||||
{ 15, 1, -1, 21, 96, 2, -1, -1, FUSION_A, 0 , 0, "Carrizo X2" },
|
||||
{ 15, 1, -1, 21, 96, 4, -1, -1, FUSION_A, 0 , 0, "Carrizo X4" },
|
||||
{ 15, 5, -1, 21, 101, 2, -1, -1, FUSION_A, 0 , 0, "Bristol Ridge X2" },
|
||||
{ 15, 5, -1, 21, 101, 4, -1, -1, FUSION_A, 0 , 0, "Bristol Ridge X4" },
|
||||
{ 15, 0, -1, 21, 112, 2, -1, -1, FUSION_A, 0 , 0, "Stoney Ridge X2" },
|
||||
{ 15, 0, -1, 21, 112, 2, -1, -1, FUSION_E, 0 , 0, "Stoney Ridge X2" },
|
||||
|
||||
/* Family 16h: Jaguar Architecture (2013) */
|
||||
{ 15, 0, -1, 22, 0, 2, -1, -1, FUSION_A, 0 , 0, "Kabini X2" },
|
||||
{ 15, 0, -1, 22, 0, 4, -1, -1, FUSION_A, 0 , 0, "Kabini X4" },
|
||||
/* 2nd-gen, Puma core (2013): */
|
||||
{ 15, 0, -1, 22, 48, 2, -1, -1, FUSION_E, 0 , 0, "Mullins X2" },
|
||||
{ 15, 0, -1, 22, 48, 4, -1, -1, FUSION_A, 0 , 0, "Mullins X4" },
|
||||
|
||||
/* Family 17h: Zen Architecture (2017) */
|
||||
{ 15, -1, -1, 23, 1, 8, -1, -1, NC, 0 , 0, "Ryzen 7" },
|
||||
{ 15, -1, -1, 23, 1, 6, -1, -1, NC, 0 , _1600, "Ryzen 5" },
|
||||
{ 15, -1, -1, 23, 1, 4, -1, -1, NC, 0 , _1500, "Ryzen 5" },
|
||||
{ 15, -1, -1, 23, 1, 4, -1, -1, NC, 0 , _1400, "Ryzen 5" },
|
||||
{ 15, -1, -1, 23, 1, 4, -1, -1, NC, 0 , 0, "Ryzen 3" },
|
||||
//{ 15, -1, -1, 23, 1, 4, -1, -1, NC, 0 , 0, "Raven Ridge" }, //TBA
|
||||
|
||||
/* Newer Opterons: */
|
||||
{ 15, 9, -1, 22, 9, 8, -1, -1, NC, OPTERON_ , 0, "Magny-Cours Opteron" },
|
||||
};
|
||||
|
||||
|
||||
static void load_amd_features(struct cpu_raw_data_t* raw, struct cpu_id_t* data)
|
||||
{
|
||||
const struct feature_map_t matchtable_edx81[] = {
|
||||
{ 20, CPU_FEATURE_NX },
|
||||
{ 22, CPU_FEATURE_MMXEXT },
|
||||
{ 25, CPU_FEATURE_FXSR_OPT },
|
||||
{ 30, CPU_FEATURE_3DNOWEXT },
|
||||
{ 31, CPU_FEATURE_3DNOW },
|
||||
};
|
||||
const struct feature_map_t matchtable_ecx81[] = {
|
||||
{ 1, CPU_FEATURE_CMP_LEGACY },
|
||||
{ 2, CPU_FEATURE_SVM },
|
||||
{ 5, CPU_FEATURE_ABM },
|
||||
{ 6, CPU_FEATURE_SSE4A },
|
||||
{ 7, CPU_FEATURE_MISALIGNSSE },
|
||||
{ 8, CPU_FEATURE_3DNOWPREFETCH },
|
||||
{ 9, CPU_FEATURE_OSVW },
|
||||
{ 10, CPU_FEATURE_IBS },
|
||||
{ 11, CPU_FEATURE_XOP },
|
||||
{ 12, CPU_FEATURE_SKINIT },
|
||||
{ 13, CPU_FEATURE_WDT },
|
||||
{ 16, CPU_FEATURE_FMA4 },
|
||||
{ 21, CPU_FEATURE_TBM },
|
||||
};
|
||||
const struct feature_map_t matchtable_edx87[] = {
|
||||
{ 0, CPU_FEATURE_TS },
|
||||
{ 1, CPU_FEATURE_FID },
|
||||
{ 2, CPU_FEATURE_VID },
|
||||
{ 3, CPU_FEATURE_TTP },
|
||||
{ 4, CPU_FEATURE_TM_AMD },
|
||||
{ 5, CPU_FEATURE_STC },
|
||||
{ 6, CPU_FEATURE_100MHZSTEPS },
|
||||
{ 7, CPU_FEATURE_HWPSTATE },
|
||||
/* id 8 is handled in common */
|
||||
{ 9, CPU_FEATURE_CPB },
|
||||
{ 10, CPU_FEATURE_APERFMPERF },
|
||||
{ 11, CPU_FEATURE_PFI },
|
||||
{ 12, CPU_FEATURE_PA },
|
||||
};
|
||||
if (raw->ext_cpuid[0][0] >= 0x80000001) {
|
||||
match_features(matchtable_edx81, COUNT_OF(matchtable_edx81), raw->ext_cpuid[1][3], data);
|
||||
match_features(matchtable_ecx81, COUNT_OF(matchtable_ecx81), raw->ext_cpuid[1][2], data);
|
||||
}
|
||||
if (raw->ext_cpuid[0][0] >= 0x80000007)
|
||||
match_features(matchtable_edx87, COUNT_OF(matchtable_edx87), raw->ext_cpuid[7][3], data);
|
||||
if (raw->ext_cpuid[0][0] >= 0x8000001a) {
|
||||
/* We have the extended info about SSE unit size */
|
||||
data->detection_hints[CPU_HINT_SSE_SIZE_AUTH] = 1;
|
||||
data->sse_size = (raw->ext_cpuid[0x1a][0] & 1) ? 128 : 64;
|
||||
}
|
||||
}
|
||||
|
||||
static void decode_amd_cache_info(struct cpu_raw_data_t* raw, struct cpu_id_t* data)
|
||||
{
|
||||
int l3_result;
|
||||
const int assoc_table[16] = {
|
||||
0, 1, 2, 0, 4, 0, 8, 0, 16, 0, 32, 48, 64, 96, 128, 255
|
||||
};
|
||||
unsigned n = raw->ext_cpuid[0][0];
|
||||
|
||||
if (n >= 0x80000005) {
|
||||
data->l1_data_cache = (raw->ext_cpuid[5][2] >> 24) & 0xff;
|
||||
data->l1_assoc = (raw->ext_cpuid[5][2] >> 16) & 0xff;
|
||||
data->l1_cacheline = (raw->ext_cpuid[5][2]) & 0xff;
|
||||
data->l1_instruction_cache = (raw->ext_cpuid[5][3] >> 24) & 0xff;
|
||||
}
|
||||
if (n >= 0x80000006) {
|
||||
data->l2_cache = (raw->ext_cpuid[6][2] >> 16) & 0xffff;
|
||||
data->l2_assoc = assoc_table[(raw->ext_cpuid[6][2] >> 12) & 0xf];
|
||||
data->l2_cacheline = (raw->ext_cpuid[6][2]) & 0xff;
|
||||
|
||||
l3_result = (raw->ext_cpuid[6][3] >> 18);
|
||||
if (l3_result > 0) {
|
||||
l3_result = 512 * l3_result; /* AMD spec says it's a range,
|
||||
but we take the lower bound */
|
||||
data->l3_cache = l3_result;
|
||||
data->l3_assoc = assoc_table[(raw->ext_cpuid[6][3] >> 12) & 0xf];
|
||||
data->l3_cacheline = (raw->ext_cpuid[6][3]) & 0xff;
|
||||
} else {
|
||||
data->l3_cache = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void decode_amd_number_of_cores(struct cpu_raw_data_t* raw, struct cpu_id_t* data)
|
||||
{
|
||||
int logical_cpus = -1, num_cores = -1;
|
||||
|
||||
if (raw->basic_cpuid[0][0] >= 1) {
|
||||
logical_cpus = (raw->basic_cpuid[1][1] >> 16) & 0xff;
|
||||
if (raw->ext_cpuid[0][0] >= 8) {
|
||||
num_cores = 1 + (raw->ext_cpuid[8][2] & 0xff);
|
||||
}
|
||||
}
|
||||
if (data->flags[CPU_FEATURE_HT]) {
|
||||
if (num_cores > 1) {
|
||||
if (data->ext_family >= 23)
|
||||
num_cores /= 2; // e.g., Ryzen 7 reports 16 "real" cores, but they are really just 8.
|
||||
data->num_cores = num_cores;
|
||||
data->num_logical_cpus = logical_cpus;
|
||||
} else {
|
||||
data->num_cores = 1;
|
||||
data->num_logical_cpus = (logical_cpus >= 2 ? logical_cpus : 2);
|
||||
}
|
||||
} else {
|
||||
data->num_cores = data->num_logical_cpus = 1;
|
||||
}
|
||||
}
|
||||
|
||||
static int amd_has_turion_modelname(const char *bs)
|
||||
{
|
||||
/* We search for something like TL-60. Ahh, I miss regexes...*/
|
||||
int i, l, k;
|
||||
char code[3] = {0};
|
||||
const char* codes[] = { "ML", "MT", "MK", "TK", "TL", "RM", "ZM", "" };
|
||||
l = (int) strlen(bs);
|
||||
for (i = 3; i < l - 2; i++) {
|
||||
if (bs[i] == '-' &&
|
||||
isupper(bs[i-1]) && isupper(bs[i-2]) && !isupper(bs[i-3]) &&
|
||||
isdigit(bs[i+1]) && isdigit(bs[i+2]) && !isdigit(bs[i+3]))
|
||||
{
|
||||
code[0] = bs[i-2];
|
||||
code[1] = bs[i-1];
|
||||
for (k = 0; codes[k][0]; k++)
|
||||
if (!strcmp(codes[k], code)) return 1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct amd_code_and_bits_t decode_amd_codename_part1(const char *bs)
|
||||
{
|
||||
amd_code_t code = NC;
|
||||
uint64_t bits = 0;
|
||||
struct amd_code_and_bits_t result;
|
||||
|
||||
if (strstr(bs, "Dual Core") ||
|
||||
strstr(bs, "Dual-Core") ||
|
||||
strstr(bs, " X2 "))
|
||||
bits |= _X2;
|
||||
if (strstr(bs, " X4 ")) bits |= _X4;
|
||||
if (strstr(bs, " X3 ")) bits |= _X3;
|
||||
if (strstr(bs, "Opteron")) bits |= OPTERON_;
|
||||
if (strstr(bs, "Phenom")) {
|
||||
code = (strstr(bs, "II")) ? PHENOM2 : PHENOM;
|
||||
}
|
||||
if (amd_has_turion_modelname(bs)) {
|
||||
bits |= TURION_;
|
||||
}
|
||||
if (strstr(bs, "Athlon(tm)")) bits |= ATHLON_;
|
||||
if (strstr(bs, "Sempron(tm)")) bits |= SEMPRON_;
|
||||
if (strstr(bs, "Duron")) bits |= DURON_;
|
||||
if (strstr(bs, " 64 ")) bits |= _64_;
|
||||
if (strstr(bs, " FX")) bits |= _FX;
|
||||
if (strstr(bs, " MP")) bits |= _MP_;
|
||||
if (strstr(bs, "Athlon(tm) 64") || strstr(bs, "Athlon(tm) II X") || match_pattern(bs, "Athlon(tm) X#")) {
|
||||
bits |= ATHLON_ | _64_;
|
||||
}
|
||||
if (strstr(bs, "Turion")) bits |= TURION_;
|
||||
|
||||
if (strstr(bs, "mobile") || strstr(bs, "Mobile")) {
|
||||
bits |= MOBILE_;
|
||||
}
|
||||
|
||||
if (strstr(bs, "XP")) bits |= _XP_;
|
||||
if (strstr(bs, "XP-M")) bits |= _M_;
|
||||
if (strstr(bs, "(LV)")) bits |= _LV_;
|
||||
|
||||
if (match_pattern(bs, "C-##")) code = FUSION_C;
|
||||
if (match_pattern(bs, "E-###")) code = FUSION_E;
|
||||
if (match_pattern(bs, "Z-##")) code = FUSION_Z;
|
||||
if (match_pattern(bs, "E#-####") || match_pattern(bs, "A#-####")) code = FUSION_EA;
|
||||
|
||||
result.code = code;
|
||||
result.bits = bits;
|
||||
return result;
|
||||
}
|
||||
|
||||
static int decode_amd_ryzen_model_code(const char* bs)
|
||||
{
|
||||
const struct {
|
||||
int model_code;
|
||||
const char* match_str;
|
||||
} patterns[] = {
|
||||
{ _1600, "1600" },
|
||||
{ _1500, "1500" },
|
||||
{ _1400, "1400" },
|
||||
};
|
||||
int i;
|
||||
|
||||
for (i = 0; i < COUNT_OF(patterns); i++)
|
||||
if (strstr(bs, patterns[i].match_str))
|
||||
return patterns[i].model_code;
|
||||
//
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void decode_amd_codename(struct cpu_raw_data_t* raw, struct cpu_id_t* data, struct internal_id_info_t* internal)
|
||||
{
|
||||
struct amd_code_and_bits_t code_and_bits = decode_amd_codename_part1(data->brand_str);
|
||||
int i = 0;
|
||||
char* code_str = NULL;
|
||||
int model_code;
|
||||
|
||||
for (i = 0; i < COUNT_OF(amd_code_str); i++) {
|
||||
if (code_and_bits.code == amd_code_str[i].code) {
|
||||
code_str = amd_code_str[i].str;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (/*code == ATHLON_64_X2*/ match_all(code_and_bits.bits, ATHLON_|_64_|_X2) && data->l2_cache < 512) {
|
||||
code_and_bits.bits &= ~(ATHLON_ | _64_);
|
||||
code_and_bits.bits |= SEMPRON_;
|
||||
}
|
||||
if (code_str)
|
||||
debugf(2, "Detected AMD brand code: %d (%s)\n", code_and_bits.code, code_str);
|
||||
else
|
||||
debugf(2, "Detected AMD brand code: %d\n", code_and_bits.code);
|
||||
|
||||
if (code_and_bits.bits) {
|
||||
debugf(2, "Detected AMD bits: ");
|
||||
debug_print_lbits(2, code_and_bits.bits);
|
||||
}
|
||||
// is it Ryzen? if so, we need to detect discern between the four-core 1400/1500 (Ryzen 5) and the four-core Ryzen 3:
|
||||
model_code = (data->ext_family == 23) ? decode_amd_ryzen_model_code(data->brand_str) : 0;
|
||||
|
||||
internal->code.amd = code_and_bits.code;
|
||||
internal->bits = code_and_bits.bits;
|
||||
internal->score = match_cpu_codename(cpudb_amd, COUNT_OF(cpudb_amd), data, code_and_bits.code,
|
||||
code_and_bits.bits, model_code);
|
||||
}
|
||||
|
||||
int cpuid_identify_amd(struct cpu_raw_data_t* raw, struct cpu_id_t* data, struct internal_id_info_t* internal)
|
||||
{
|
||||
load_amd_features(raw, data);
|
||||
decode_amd_cache_info(raw, data);
|
||||
decode_amd_number_of_cores(raw, data);
|
||||
decode_amd_codename(raw, data, internal);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void cpuid_get_list_amd(struct cpu_list_t* list)
|
||||
{
|
||||
generic_get_cpu_list(cpudb_amd, COUNT_OF(cpudb_amd), list);
|
||||
}
|
||||
@@ -1,935 +0,0 @@
|
||||
/*
|
||||
* Copyright 2008 Veselin Georgiev,
|
||||
* anrieffNOSPAM @ mgail_DOT.com (convert to gmail)
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
#include "libcpuid.h"
|
||||
#include "libcpuid_util.h"
|
||||
#include "libcpuid_internal.h"
|
||||
#include "recog_intel.h"
|
||||
|
||||
const struct intel_bcode_str { intel_code_t code; char *str; } intel_bcode_str[] = {
|
||||
#define CODE(x) { x, #x }
|
||||
#define CODE2(x, y) CODE(x)
|
||||
#include "intel_code_t.h"
|
||||
#undef CODE
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
int code;
|
||||
uint64_t bits;
|
||||
} intel_code_and_bits_t;
|
||||
|
||||
enum _intel_model_t {
|
||||
UNKNOWN = -1,
|
||||
_3000 = 100,
|
||||
_3100,
|
||||
_3200,
|
||||
X3200,
|
||||
_3300,
|
||||
X3300,
|
||||
_5100,
|
||||
_5200,
|
||||
_5300,
|
||||
_5400,
|
||||
_2xxx, /* Core i[357] 2xxx */
|
||||
_3xxx, /* Core i[357] 3xxx */
|
||||
};
|
||||
typedef enum _intel_model_t intel_model_t;
|
||||
|
||||
enum _intel_bits_t {
|
||||
PENTIUM_ = LBIT( 0 ),
|
||||
CELERON_ = LBIT( 1 ),
|
||||
MOBILE_ = LBIT( 2 ),
|
||||
CORE_ = LBIT( 3 ),
|
||||
_I_ = LBIT( 4 ),
|
||||
_M_ = LBIT( 5 ),
|
||||
_3 = LBIT( 6 ),
|
||||
_5 = LBIT( 7 ),
|
||||
_7 = LBIT( 8 ),
|
||||
XEON_ = LBIT( 9 ),
|
||||
_MP = LBIT( 10 ),
|
||||
ATOM_ = LBIT( 11 ),
|
||||
|
||||
};
|
||||
typedef enum _intel_bits_t intel_bits_t;
|
||||
|
||||
const struct match_entry_t cpudb_intel[] = {
|
||||
{ -1, -1, -1, -1, -1, 1, -1, -1, NC, 0 , 0, "Unknown Intel CPU" },
|
||||
|
||||
/* i486 */
|
||||
{ 4, -1, -1, -1, -1, 1, -1, -1, NC, 0 , 0, "Unknown i486" },
|
||||
{ 4, 0, -1, -1, -1, 1, -1, -1, NC, 0 , 0, "i486 DX-25/33" },
|
||||
{ 4, 1, -1, -1, -1, 1, -1, -1, NC, 0 , 0, "i486 DX-50" },
|
||||
{ 4, 2, -1, -1, -1, 1, -1, -1, NC, 0 , 0, "i486 SX" },
|
||||
{ 4, 3, -1, -1, -1, 1, -1, -1, NC, 0 , 0, "i486 DX2" },
|
||||
{ 4, 4, -1, -1, -1, 1, -1, -1, NC, 0 , 0, "i486 SL" },
|
||||
{ 4, 5, -1, -1, -1, 1, -1, -1, NC, 0 , 0, "i486 SX2" },
|
||||
{ 4, 7, -1, -1, -1, 1, -1, -1, NC, 0 , 0, "i486 DX2 WriteBack" },
|
||||
{ 4, 8, -1, -1, -1, 1, -1, -1, NC, 0 , 0, "i486 DX4" },
|
||||
{ 4, 9, -1, -1, -1, 1, -1, -1, NC, 0 , 0, "i486 DX4 WriteBack" },
|
||||
|
||||
/* All Pentia:
|
||||
Pentium 1 */
|
||||
{ 5, -1, -1, -1, -1, 1, -1, -1, NC, 0 , 0, "Unknown Pentium" },
|
||||
{ 5, 0, -1, -1, -1, 1, -1, -1, NC, 0 , 0, "Pentium A-Step" },
|
||||
{ 5, 1, -1, -1, -1, 1, -1, -1, NC, 0 , 0, "Pentium 1 (0.8u)" },
|
||||
{ 5, 2, -1, -1, -1, 1, -1, -1, NC, 0 , 0, "Pentium 1 (0.35u)" },
|
||||
{ 5, 3, -1, -1, -1, 1, -1, -1, NC, 0 , 0, "Pentium OverDrive" },
|
||||
{ 5, 4, -1, -1, -1, 1, -1, -1, NC, 0 , 0, "Pentium 1 (0.35u)" },
|
||||
{ 5, 7, -1, -1, -1, 1, -1, -1, NC, 0 , 0, "Pentium 1 (0.35u)" },
|
||||
{ 5, 8, -1, -1, -1, 1, -1, -1, NC, 0 , 0, "Pentium MMX (0.25u)" },
|
||||
|
||||
/* Pentium 2 / 3 / M / Conroe / whatsnext - all P6 based. */
|
||||
{ 6, -1, -1, -1, -1, 1, -1, -1, NC, 0 , 0, "Unknown P6" },
|
||||
{ 6, 0, -1, -1, -1, 1, -1, -1, NC, 0 , 0, "Pentium Pro" },
|
||||
{ 6, 1, -1, -1, -1, 1, -1, -1, NC, 0 , 0, "Pentium Pro" },
|
||||
{ 6, 3, -1, -1, -1, 1, -1, -1, NC, 0 , 0, "Pentium II (Klamath)" },
|
||||
{ 6, 5, -1, -1, -1, 1, -1, -1, NC, 0 , 0, "Pentium II (Deschutes)" },
|
||||
{ 6, 5, -1, -1, -1, 1, -1, -1, NC, MOBILE_|PENTIUM_, 0, "Mobile Pentium II (Tonga)"},
|
||||
{ 6, 6, -1, -1, -1, 1, -1, -1, NC,0 , 0, "Pentium II (Dixon)" },
|
||||
|
||||
{ 6, 3, -1, -1, -1, 1, -1, -1, NC, XEON_ , 0, "P-II Xeon (Klamath)" },
|
||||
{ 6, 5, -1, -1, -1, 1, -1, -1, NC, XEON_ , 0, "P-II Xeon (Drake)" },
|
||||
{ 6, 6, -1, -1, -1, 1, -1, -1, NC, XEON_ , 0, "P-II Xeon (Dixon)" },
|
||||
|
||||
{ 6, 5, -1, -1, -1, 1, -1, -1, NC, CELERON_ , 0, "P-II Celeron (Covington)" },
|
||||
{ 6, 6, -1, -1, -1, 1, -1, -1, NC, CELERON_ , 0, "P-II Celeron (Mendocino)" },
|
||||
|
||||
/* -------------------------------------------------- */
|
||||
|
||||
{ 6, 7, -1, -1, -1, 1, -1, -1, NC, 0 , 0, "Pentium III (Katmai)" },
|
||||
{ 6, 8, -1, -1, -1, 1, -1, -1, NC, 0 , 0, "Pentium III (Coppermine)"},
|
||||
{ 6, 10, -1, -1, -1, 1, -1, -1, NC, 0 , 0, "Pentium III (Coppermine)"},
|
||||
{ 6, 11, -1, -1, -1, 1, -1, -1, NC, 0 , 0, "Pentium III (Tualatin)" },
|
||||
|
||||
{ 6, 7, -1, -1, -1, 1, -1, -1, NC, XEON_ , 0, "P-III Xeon (Tanner)" },
|
||||
{ 6, 8, -1, -1, -1, 1, -1, -1, NC, XEON_ , 0, "P-III Xeon (Cascades)" },
|
||||
{ 6, 10, -1, -1, -1, 1, -1, -1, NC, XEON_ , 0, "P-III Xeon (Cascades)" },
|
||||
{ 6, 11, -1, -1, -1, 1, -1, -1, NC, XEON_ , 0, "P-III Xeon (Tualatin)" },
|
||||
|
||||
{ 6, 7, -1, -1, -1, 1, -1, -1, NC, CELERON_ , 0, "P-III Celeron (Katmai)" },
|
||||
{ 6, 8, -1, -1, -1, 1, -1, -1, NC, CELERON_ , 0, "P-III Celeron (Coppermine)" },
|
||||
{ 6, 10, -1, -1, -1, 1, -1, -1, NC, CELERON_ , 0, "P-III Celeron (Coppermine)" },
|
||||
{ 6, 11, -1, -1, -1, 1, -1, -1, NC, CELERON_ , 0, "P-III Celeron (Tualatin)" },
|
||||
|
||||
/* Netburst based (Pentium 4 and later)
|
||||
classic P4s */
|
||||
{ 15, -1, -1, -1, -1, 1, -1, -1, NC, 0 , 0, "Unknown Pentium 4" },
|
||||
{ 15, -1, -1, 15, -1, 1, -1, -1, NC, CELERON_ , 0, "Unknown P-4 Celeron" },
|
||||
{ 15, -1, -1, 15, -1, 1, -1, -1, NC, XEON_ , 0, "Unknown Xeon" },
|
||||
|
||||
{ 15, 0, -1, 15, -1, 1, -1, -1, NC, PENTIUM_ , 0, "Pentium 4 (Willamette)" },
|
||||
{ 15, 1, -1, 15, -1, 1, -1, -1, NC, PENTIUM_ , 0, "Pentium 4 (Willamette)" },
|
||||
{ 15, 2, -1, 15, -1, 1, -1, -1, NC, PENTIUM_ , 0, "Pentium 4 (Northwood)" },
|
||||
{ 15, 3, -1, 15, -1, 1, -1, -1, NC, PENTIUM_ , 0, "Pentium 4 (Prescott)" },
|
||||
{ 15, 4, -1, 15, -1, 1, -1, -1, NC, PENTIUM_ , 0, "Pentium 4 (Prescott)" },
|
||||
{ 15, 6, -1, 15, -1, 1, -1, -1, NC, PENTIUM_ , 0, "Pentium 4 (Cedar Mill)" },
|
||||
{ 15, 0, -1, 15, -1, 1, -1, -1, NC, MOBILE_|PENTIUM_, 0, "Mobile P-4 (Willamette)" },
|
||||
{ 15, 1, -1, 15, -1, 1, -1, -1, NC, MOBILE_|PENTIUM_, 0, "Mobile P-4 (Willamette)" },
|
||||
{ 15, 2, -1, 15, -1, 1, -1, -1, NC, MOBILE_|PENTIUM_, 0, "Mobile P-4 (Northwood)" },
|
||||
{ 15, 3, -1, 15, -1, 1, -1, -1, NC, MOBILE_|PENTIUM_, 0, "Mobile P-4 (Prescott)" },
|
||||
{ 15, 4, -1, 15, -1, 1, -1, -1, NC, MOBILE_|PENTIUM_, 0, "Mobile P-4 (Prescott)" },
|
||||
{ 15, 6, -1, 15, -1, 1, -1, -1, NC, MOBILE_|PENTIUM_, 0, "Mobile P-4 (Cedar Mill)" },
|
||||
|
||||
/* server CPUs */
|
||||
{ 15, 0, -1, 15, -1, 1, -1, -1, NC, XEON_ , 0, "Xeon (Foster)" },
|
||||
{ 15, 1, -1, 15, -1, 1, -1, -1, NC, XEON_ , 0, "Xeon (Foster)" },
|
||||
{ 15, 2, -1, 15, -1, 1, -1, -1, NC, XEON_ , 0, "Xeon (Prestonia)" },
|
||||
{ 15, 2, -1, 15, -1, 1, -1, -1, NC, XEON_|_MP , 0, "Xeon (Gallatin)" },
|
||||
{ 15, 3, -1, 15, -1, 1, -1, -1, NC, XEON_ , 0, "Xeon (Nocona)" },
|
||||
{ 15, 4, -1, 15, -1, 1, -1, -1, NC, XEON_ , 0, "Xeon (Nocona)" },
|
||||
{ 15, 4, -1, 15, -1, 1, -1, -1, IRWIN, XEON_ , 0, "Xeon (Irwindale)" },
|
||||
{ 15, 4, -1, 15, -1, 1, -1, -1, NC, XEON_|_MP , 0, "Xeon (Cranford)" },
|
||||
{ 15, 4, -1, 15, -1, 1, -1, -1, POTOMAC, XEON_ , 0, "Xeon (Potomac)" },
|
||||
{ 15, 6, -1, 15, -1, 1, -1, -1, NC, XEON_ , 0, "Xeon (Dempsey)" },
|
||||
|
||||
/* Pentium Ds */
|
||||
{ 15, 4, 4, 15, -1, 1, -1, -1, NC, 0 , 0, "Pentium D (SmithField)" },
|
||||
{ 15, 4, -1, 15, -1, 1, -1, -1, PENTIUM_D, 0 , 0, "Pentium D (SmithField)" },
|
||||
{ 15, 4, 7, 15, -1, 1, -1, -1, NC, 0 , 0, "Pentium D (SmithField)" },
|
||||
{ 15, 6, -1, 15, -1, 1, -1, -1, PENTIUM_D, 0 , 0, "Pentium D (Presler)" },
|
||||
|
||||
/* Celeron and Celeron Ds */
|
||||
{ 15, 1, -1, 15, -1, 1, -1, -1, NC, CELERON_ , 0, "P-4 Celeron (Willamette)" },
|
||||
{ 15, 2, -1, 15, -1, 1, -1, -1, NC, CELERON_ , 0, "P-4 Celeron (Northwood)" },
|
||||
{ 15, 3, -1, 15, -1, 1, -1, -1, NC, CELERON_ , 0, "P-4 Celeron D (Prescott)" },
|
||||
{ 15, 4, -1, 15, -1, 1, -1, -1, NC, CELERON_ , 0, "P-4 Celeron D (Prescott)" },
|
||||
{ 15, 6, -1, 15, -1, 1, -1, -1, NC, CELERON_ , 0, "P-4 Celeron D (Cedar Mill)" },
|
||||
|
||||
/* -------------------------------------------------- */
|
||||
/* Intel Core microarchitecture - P6-based */
|
||||
|
||||
{ 6, 9, -1, -1, -1, 1, -1, -1, NC, 0 , 0, "Unknown Pentium M" },
|
||||
{ 6, 9, -1, -1, -1, 1, -1, -1, PENTIUM_M, 0 , 0, "Unknown Pentium M" },
|
||||
{ 6, 9, -1, -1, -1, 1, -1, -1, NC, PENTIUM_ , 0, "Pentium M (Banias)" },
|
||||
{ 6, 9, -1, -1, -1, 1, -1, -1, PENTIUM_M, 0 , 0, "Pentium M (Banias)" },
|
||||
{ 6, 9, -1, -1, -1, 1, -1, -1, NC, CELERON_ , 0, "Celeron M" },
|
||||
{ 6, 13, -1, -1, -1, 1, -1, -1, NC, PENTIUM_ , 0, "Pentium M (Dothan)" },
|
||||
{ 6, 13, -1, -1, -1, 1, -1, -1, PENTIUM_M, 0 , 0, "Pentium M (Dothan)" },
|
||||
{ 6, 13, -1, -1, -1, 1, -1, -1, NC, CELERON_ , 0, "Celeron M" },
|
||||
|
||||
{ 6, 12, -1, -1, -1, -1, -1, -1, NC, ATOM_ , 0, "Unknown Atom" },
|
||||
{ 6, 12, -1, -1, -1, -1, -1, -1, DIAMONDVILLE,ATOM_, 0, "Atom (Diamondville)" },
|
||||
{ 6, 12, -1, -1, -1, -1, -1, -1, SILVERTHORNE,ATOM_, 0, "Atom (Silverthorne)" },
|
||||
{ 6, 12, -1, -1, -1, -1, -1, -1, CEDARVIEW, ATOM_ , 0, "Atom (Cedarview)" },
|
||||
{ 6, 6, -1, -1, -1, -1, -1, -1, CEDARVIEW, ATOM_ , 0, "Atom (Cedarview)" },
|
||||
{ 6, 12, -1, -1, -1, -1, -1, -1, PINEVIEW, ATOM_ , 0, "Atom (Pineview)" },
|
||||
|
||||
/* -------------------------------------------------- */
|
||||
|
||||
{ 6, 14, -1, -1, -1, 1, -1, -1, NC, 0 , 0, "Unknown Yonah" },
|
||||
{ 6, 14, -1, -1, -1, 1, -1, -1, CORE_SOLO, 0 , 0, "Yonah (Core Solo)" },
|
||||
{ 6, 14, -1, -1, -1, 2, -1, -1, CORE_DUO, 0 , 0, "Yonah (Core Duo)" },
|
||||
{ 6, 14, -1, -1, -1, 1, -1, -1, CORE_SOLO, MOBILE_, 0, "Yonah (Core Solo)" },
|
||||
{ 6, 14, -1, -1, -1, 2, -1, -1, CORE_DUO , MOBILE_, 0, "Yonah (Core Duo)" },
|
||||
{ 6, 14, -1, -1, -1, 1, -1, -1, CORE_SOLO, 0 , 0, "Yonah (Core Solo)" },
|
||||
|
||||
{ 6, 15, -1, -1, -1, 1, -1, -1, NC, 0 , 0, "Unknown Core 2" },
|
||||
{ 6, 15, -1, -1, -1, 2, 4096, -1, CORE_DUO, 0 , 0, "Conroe (Core 2 Duo)" },
|
||||
{ 6, 15, -1, -1, -1, 2, 1024, -1, CORE_DUO, 0 , 0, "Conroe (Core 2 Duo) 1024K" },
|
||||
{ 6, 15, -1, -1, -1, 2, 512, -1, CORE_DUO, 0 , 0, "Conroe (Core 2 Duo) 512K" },
|
||||
{ 6, 15, -1, -1, -1, 4, -1, -1, QUAD_CORE, 0 , 0, "Kentsfield (Core 2 Quad)" },
|
||||
{ 6, 15, -1, -1, -1, 4, 4096, -1, QUAD_CORE, 0 , 0, "Kentsfield (Core 2 Quad)" },
|
||||
{ 6, 15, -1, -1, -1, 400, -1, -1, MORE_THAN_QUADCORE, 0, 0, "More than quad-core" },
|
||||
{ 6, 15, -1, -1, -1, 2, 2048, -1, CORE_DUO, 0 , 0, "Allendale (Core 2 Duo)" },
|
||||
{ 6, 15, -1, -1, -1, 2, -1, -1, MOBILE_CORE_DUO, 0, 0, "Merom (Core 2 Duo)" },
|
||||
{ 6, 15, -1, -1, -1, 2, 2048, -1, MEROM, 0 , 0, "Merom (Core 2 Duo) 2048K" },
|
||||
{ 6, 15, -1, -1, -1, 2, 4096, -1, MEROM, 0 , 0, "Merom (Core 2 Duo) 4096K" },
|
||||
|
||||
{ 6, 15, -1, -1, 15, 1, -1, -1, NC, CELERON_ , 0, "Conroe-L (Celeron)" },
|
||||
{ 6, 6, -1, -1, 22, 1, -1, -1, NC, CELERON_ , 0, "Conroe-L (Celeron)" },
|
||||
{ 6, 15, -1, -1, 15, 2, -1, -1, NC, CELERON_ , 0, "Conroe-L (Allendale)" },
|
||||
{ 6, 6, -1, -1, 22, 2, -1, -1, NC, CELERON_ , 0, "Conroe-L (Allendale)" },
|
||||
|
||||
|
||||
{ 6, 6, -1, -1, 22, 1, -1, -1, NC, 0 , 0, "Unknown Core ?" },
|
||||
{ 6, 7, -1, -1, 23, 1, -1, -1, NC, 0 , 0, "Unknown Core ?" },
|
||||
{ 6, 6, -1, -1, 22, 400, -1, -1, MORE_THAN_QUADCORE, 0, 0, "More than quad-core" },
|
||||
{ 6, 7, -1, -1, 23, 400, -1, -1, MORE_THAN_QUADCORE, 0, 0, "More than quad-core" },
|
||||
|
||||
{ 6, 7, -1, -1, 23, 1, -1, -1, CORE_SOLO , 0, 0, "Unknown Core 45nm" },
|
||||
{ 6, 7, -1, -1, 23, 1, -1, -1, CORE_DUO , 0, 0, "Unknown Core 45nm" },
|
||||
{ 6, 7, -1, -1, 23, 2, 1024, -1, WOLFDALE , 0, 0, "Celeron Wolfdale 1M" },
|
||||
{ 6, 7, -1, -1, 23, 2, 2048, -1, WOLFDALE , 0, 0, "Wolfdale (Core 2 Duo) 2M" },
|
||||
{ 6, 7, -1, -1, 23, 2, 3072, -1, WOLFDALE , 0, 0, "Wolfdale (Core 2 Duo) 3M" },
|
||||
{ 6, 7, -1, -1, 23, 2, 6144, -1, WOLFDALE , 0, 0, "Wolfdale (Core 2 Duo) 6M" },
|
||||
{ 6, 7, -1, -1, 23, 1, -1, -1, MOBILE_CORE_DUO , 0, 0, "Penryn (Core 2 Duo)" },
|
||||
{ 6, 7, -1, -1, 23, 2, 1024, -1, PENRYN , 0, 0, "Penryn (Core 2 Duo)" },
|
||||
{ 6, 7, -1, -1, 23, 2, 3072, -1, PENRYN , 0, 0, "Penryn (Core 2 Duo) 3M" },
|
||||
{ 6, 7, -1, -1, 23, 2, 6144, -1, PENRYN , 0, 0, "Penryn (Core 2 Duo) 6M" },
|
||||
{ 6, 7, -1, -1, 23, 4, 2048, -1, NC , 0, 0, "Yorkfield (Core 2 Quad) 2M"},
|
||||
{ 6, 7, -1, -1, 23, 4, 3072, -1, NC , 0, 0, "Yorkfield (Core 2 Quad) 3M"},
|
||||
{ 6, 7, -1, -1, 23, 4, 6144, -1, NC , 0, 0, "Yorkfield (Core 2 Quad) 6M"},
|
||||
|
||||
/* Core microarchitecture-based Xeons: */
|
||||
{ 6, 14, -1, -1, 14, 1, -1, -1, NC, XEON_ , 0, "Xeon LV" },
|
||||
{ 6, 15, -1, -1, 15, 2, 4096, -1, NC, XEON_ , _5100, "Xeon (Woodcrest)" },
|
||||
{ 6, 15, -1, -1, 15, 2, 2048, -1, NC, XEON_ , _3000, "Xeon (Conroe/2M)" },
|
||||
{ 6, 15, -1, -1, 15, 2, 4096, -1, NC, XEON_ , _3000, "Xeon (Conroe/4M)" },
|
||||
{ 6, 15, -1, -1, 15, 4, 4096, -1, NC, XEON_ , X3200, "Xeon (Kentsfield)" },
|
||||
{ 6, 15, -1, -1, 15, 4, 4096, -1, NC, XEON_ , _5300, "Xeon (Clovertown)" },
|
||||
{ 6, 7, -1, -1, 23, 2, 6144, -1, NC, XEON_ , _3100, "Xeon (Wolfdale)" },
|
||||
{ 6, 7, -1, -1, 23, 2, 6144, -1, NC, XEON_ , _5200, "Xeon (Wolfdale DP)" },
|
||||
{ 6, 7, -1, -1, 23, 4, 6144, -1, NC, XEON_ , _5400, "Xeon (Harpertown)" },
|
||||
{ 6, 7, -1, -1, 23, 4, 3072, -1, NC, XEON_ , X3300, "Xeon (Yorkfield/3M)" },
|
||||
{ 6, 7, -1, -1, 23, 4, 6144, -1, NC, XEON_ , X3300, "Xeon (Yorkfield/6M)" },
|
||||
|
||||
/* Nehalem CPUs (45nm): */
|
||||
{ 6, 10, -1, -1, 26, 4, -1, -1, GAINESTOWN, XEON_ , 0, "Gainestown (Xeon)" },
|
||||
{ 6, 10, -1, -1, 26, 4, -1, 4096, GAINESTOWN, XEON_ , 0, "Gainestown 4M (Xeon)" },
|
||||
{ 6, 10, -1, -1, 26, 4, -1, 8192, GAINESTOWN, XEON_ , 0, "Gainestown 8M (Xeon)" },
|
||||
{ 6, 10, -1, -1, 26, 4, -1, -1, NC, XEON_|_7 , 0, "Bloomfield (Xeon)" },
|
||||
{ 6, 10, -1, -1, 26, 4, -1, -1, NC, CORE_|_I_|_7 , 0, "Bloomfield (Core i7)" },
|
||||
{ 6, 10, -1, -1, 30, 4, -1, -1, NC, CORE_|_I_|_7 , 0, "Lynnfield (Core i7)" },
|
||||
{ 6, 5, -1, -1, 37, 4, -1, 8192, NC, CORE_|_I_|_5 , 0, "Lynnfield (Core i5)" },
|
||||
|
||||
/* Westmere CPUs (32nm): */
|
||||
{ 6, 5, -1, -1, 37, 2, -1, -1, NC, 0 , 0, "Unknown Core i3/i5" },
|
||||
{ 6, 12, -1, -1, 44, -1, -1, -1, WESTMERE, XEON_ , 0, "Westmere (Xeon)" },
|
||||
{ 6, 12, -1, -1, 44, -1, -1, 12288, WESTMERE, XEON_ , 0, "Gulftown (Xeon)" },
|
||||
{ 6, 12, -1, -1, 44, 4, -1, 12288, NC, CORE_|_I_|_7 , 0, "Gulftown (Core i7)" },
|
||||
{ 6, 5, -1, -1, 37, 2, -1, 4096, NC, CORE_|_I_|_5 , 0, "Clarkdale (Core i5)" },
|
||||
{ 6, 5, -1, -1, 37, 2, -1, 4096, NC, CORE_|_I_|_3 , 0, "Clarkdale (Core i3)" },
|
||||
{ 6, 5, -1, -1, 37, 2, -1, -1, NC, PENTIUM_ , 0, "Arrandale" },
|
||||
{ 6, 5, -1, -1, 37, 2, -1, 4096, NC, CORE_|_I_|_7 , 0, "Arrandale (Core i7)" },
|
||||
{ 6, 5, -1, -1, 37, 2, -1, 3072, NC, CORE_|_I_|_5 , 0, "Arrandale (Core i5)" },
|
||||
{ 6, 5, -1, -1, 37, 2, -1, 3072, NC, CORE_|_I_|_3 , 0, "Arrandale (Core i3)" },
|
||||
|
||||
/* Sandy Bridge CPUs (32nm): */
|
||||
{ 6, 10, -1, -1, 42, -1, -1, -1, NC, 0 , 0, "Unknown Sandy Bridge" },
|
||||
{ 6, 10, -1, -1, 42, -1, -1, -1, NC, XEON_ , 0, "Sandy Bridge (Xeon)" },
|
||||
{ 6, 10, -1, -1, 42, -1, -1, -1, NC, CORE_|_I_|_7 , 0, "Sandy Bridge (Core i7)" },
|
||||
{ 6, 10, -1, -1, 42, 4, -1, -1, NC, CORE_|_I_|_7 , 0, "Sandy Bridge (Core i7)" },
|
||||
{ 6, 10, -1, -1, 42, 4, -1, -1, NC, CORE_|_I_|_5 , 0, "Sandy Bridge (Core i5)" },
|
||||
{ 6, 10, -1, -1, 42, 2, -1, -1, NC, CORE_|_I_|_3 , 0, "Sandy Bridge (Core i3)" },
|
||||
{ 6, 10, -1, -1, 42, 2, -1, -1, NC, PENTIUM_ , 0, "Sandy Bridge (Pentium)" },
|
||||
{ 6, 10, -1, -1, 42, 1, -1, -1, NC, CELERON_ , 0, "Sandy Bridge (Celeron)" },
|
||||
{ 6, 10, -1, -1, 42, 2, -1, -1, NC, CELERON_ , 0, "Sandy Bridge (Celeron)" },
|
||||
{ 6, 13, -1, -1, 45, -1, -1, -1, NC, CORE_|_I_|_3 , 0, "Sandy Bridge-E" },
|
||||
{ 6, 13, -1, -1, 45, -1, -1, -1, NC, XEON_ , 0, "Sandy Bridge-E (Xeon)" },
|
||||
|
||||
/* Ivy Bridge CPUs (22nm): */
|
||||
{ 6, 10, -1, -1, 58, -1, -1, -1, NC, XEON_ , 0, "Ivy Bridge (Xeon)" },
|
||||
{ 6, 10, -1, -1, 58, 4, -1, -1, NC, CORE_|_I_|_7 , 0, "Ivy Bridge (Core i7)" },
|
||||
{ 6, 10, -1, -1, 58, 4, -1, -1, NC, CORE_|_I_|_5 , 0, "Ivy Bridge (Core i5)" },
|
||||
{ 6, 10, -1, -1, 58, 2, -1, -1, NC, CORE_|_I_|_3 , 0, "Ivy Bridge (Core i3)" },
|
||||
{ 6, 10, -1, -1, 58, 2, -1, -1, NC, PENTIUM_ , 0, "Ivy Bridge (Pentium)" },
|
||||
{ 6, 10, -1, -1, 58, 1, -1, -1, NC, CELERON_ , 0, "Ivy Bridge (Celeron)" },
|
||||
{ 6, 10, -1, -1, 58, 2, -1, -1, NC, CELERON_ , 0, "Ivy Bridge (Celeron)" },
|
||||
{ 6, 14, -1, -1, 62, -1, -1, -1, NC, 0 , 0, "Ivy Bridge-E" },
|
||||
|
||||
/* Haswell CPUs (22nm): */
|
||||
{ 6, 12, -1, -1, 60, -1, -1, -1, NC, XEON_ , 0, "Haswell (Xeon)" },
|
||||
{ 6, 12, -1, -1, 60, 4, -1, -1, NC, CORE_|_I_|_7 , 0, "Haswell (Core i7)" },
|
||||
{ 6, 5, -1, -1, 69, 4, -1, -1, NC, CORE_|_I_|_7 , 0, "Haswell (Core i7)" },
|
||||
{ 6, 6, -1, -1, 70, 4, -1, -1, NC, CORE_|_I_|_7 , 0, "Haswell (Core i7)" },
|
||||
{ 6, 12, -1, -1, 60, 4, -1, -1, NC, CORE_|_I_|_5 , 0, "Haswell (Core i5)" },
|
||||
{ 6, 5, -1, -1, 69, 4, -1, -1, NC, CORE_|_I_|_5 , 0, "Haswell (Core i5)" },
|
||||
{ 6, 12, -1, -1, 60, 2, -1, -1, NC, CORE_|_I_|_5 , 0, "Haswell (Core i5)" },
|
||||
{ 6, 5, -1, -1, 69, 2, -1, -1, NC, CORE_|_I_|_5 , 0, "Haswell (Core i5)" },
|
||||
{ 6, 12, -1, -1, 60, 2, -1, -1, NC, CORE_|_I_|_3 , 0, "Haswell (Core i3)" },
|
||||
{ 6, 5, -1, -1, 69, 2, -1, -1, NC, CORE_|_I_|_3 , 0, "Haswell (Core i3)" },
|
||||
{ 6, 12, -1, -1, 60, 2, -1, -1, NC, PENTIUM_ , 0, "Haswell (Pentium)" },
|
||||
{ 6, 12, -1, -1, 60, 2, -1, -1, NC, CELERON_ , 0, "Haswell (Celeron)" },
|
||||
{ 6, 12, -1, -1, 60, 1, -1, -1, NC, CELERON_ , 0, "Haswell (Celeron)" },
|
||||
{ 6, 15, -1, -1, 63, -1, -1, -1, NC, 0 , 0, "Haswell-E" },
|
||||
|
||||
/* Broadwell CPUs (14nm): */
|
||||
{ 6, 7, -1, -1, 71, 4, -1, -1, NC, CORE_|_I_|_7 , 0, "Broadwell (Core i7)" },
|
||||
{ 6, 7, -1, -1, 71, 4, -1, -1, NC, CORE_|_I_|_5 , 0, "Broadwell (Core i5)" },
|
||||
{ 6, 13, -1, -1, 61, 4, -1, -1, NC, CORE_|_I_|_7 , 0, "Broadwell-U (Core i7)" },
|
||||
{ 6, 13, -1, -1, 61, 2, -1, -1, NC, CORE_|_I_|_7 , 0, "Broadwell-U (Core i7)" },
|
||||
{ 6, 13, -1, -1, 61, 2, -1, -1, NC, CORE_|_I_|_5 , 0, "Broadwell-U (Core i5)" },
|
||||
{ 6, 13, -1, -1, 61, 2, -1, -1, NC, CORE_|_I_|_3 , 0, "Broadwell-U (Core i3)" },
|
||||
{ 6, 13, -1, -1, 61, 2, -1, -1, NC, PENTIUM_ , 0, "Broadwell-U (Pentium)" },
|
||||
{ 6, 13, -1, -1, 61, 2, -1, -1, NC, CELERON_ , 0, "Broadwell-U (Celeron)" },
|
||||
{ 6, 13, -1, -1, 61, 2, -1, -1, NA, 0 , 0, "Broadwell-U (Core M)" },
|
||||
{ 6, 15, -1, -1, 79, -1, -1, -1, NC, XEON_ , 0, "Broadwell-E (Xeon)" },
|
||||
{ 6, 15, -1, -1, 79, 2, -1, -1, NC, CORE_|_I_|_3 , 0, "Broadwell-E (Core i3)" },
|
||||
{ 6, 15, -1, -1, 79, 2, -1, -1, NC, CORE_|_I_|_5 , 0, "Broadwell-E (Core i5)" },
|
||||
{ 6, 15, -1, -1, 79, 4, -1, -1, NC, CORE_|_I_|_5 , 0, "Broadwell-E (Core i5)" },
|
||||
{ 6, 15, -1, -1, 79, 2, -1, -1, NC, CORE_|_I_|_7 , 0, "Broadwell-E (Core i7)" },
|
||||
{ 6, 15, -1, -1, 79, 4, -1, -1, NC, CORE_|_I_|_7 , 0, "Broadwell-E (Core i7)" },
|
||||
|
||||
/* Skylake CPUs (14nm): */
|
||||
{ 6, 14, -1, -1, 94, -1, -1, -1, NC, XEON_ , 0, "Skylake (Xeon)" },
|
||||
{ 6, 14, -1, -1, 94, 4, -1, -1, NC, CORE_|_I_|_7 , 0, "Skylake (Core i7)" },
|
||||
{ 6, 14, -1, -1, 94, 4, -1, -1, NC, CORE_|_I_|_5 , 0, "Skylake (Core i5)" },
|
||||
{ 6, 14, -1, -1, 94, 2, -1, -1, NC, CORE_|_I_|_3 , 0, "Skylake (Core i3)" },
|
||||
{ 6, 14, -1, -1, 94, 2, -1, -1, NC, PENTIUM_ , 0, "Skylake (Pentium)" },
|
||||
{ 6, 14, -1, -1, 78, 2, -1, -1, NC, PENTIUM_ , 0, "Skylake (Pentium)" },
|
||||
{ 6, 14, -1, -1, 94, 2, -1, -1, NC, CELERON_ , 0, "Skylake (Celeron)" },
|
||||
{ 6, 14, -1, -1, 78, 2, -1, -1, NC, CELERON_ , 0, "Skylake (Celeron)" },
|
||||
{ 6, 14, -1, -1, 78, 2, -1, -1, NC, CORE_|_M_|_7 , 0, "Skylake (Core m7)" },
|
||||
{ 6, 14, -1, -1, 78, 2, -1, -1, NC, CORE_|_M_|_5 , 0, "Skylake (Core m5)" },
|
||||
{ 6, 14, -1, -1, 78, 2, -1, -1, NC, CORE_|_M_|_3 , 0, "Skylake (Core m3)" },
|
||||
|
||||
/* Kaby Lake CPUs (14nm): */
|
||||
{ 6, 14, -1, -1, 158, 4, -1, -1, NC, CORE_|_I_|_7 , 0, "Kaby Lake (Core i7)" },
|
||||
{ 6, 14, -1, -1, 158, 4, -1, -1, NC, CORE_|_I_|_5 , 0, "Kaby Lake (Core i5)" },
|
||||
{ 6, 14, -1, -1, 158, 2, -1, -1, NC, CORE_|_I_|_3 , 0, "Kaby Lake (Core i3)" },
|
||||
{ 6, 14, -1, -1, 158, 2, -1, -1, NC, PENTIUM_ , 0, "Kaby Lake (Pentium)" },
|
||||
{ 6, 14, -1, -1, 158, 2, -1, -1, NC, CELERON_ , 0, "Kaby Lake (Celeron)" },
|
||||
{ 6, 14, -1, -1, 158, 2, -1, -1, NC, CORE_|_M_|_3 , 0, "Kaby Lake (Core m3)" },
|
||||
|
||||
/* Itaniums */
|
||||
{ 7, -1, -1, -1, -1, 1, -1, -1, NC, 0 , 0, "Itanium" },
|
||||
{ 15, -1, -1, 16, -1, 1, -1, -1, NC, 0 , 0, "Itanium 2" },
|
||||
};
|
||||
|
||||
|
||||
static void load_intel_features(struct cpu_raw_data_t* raw, struct cpu_id_t* data)
|
||||
{
|
||||
const struct feature_map_t matchtable_edx1[] = {
|
||||
{ 18, CPU_FEATURE_PN },
|
||||
{ 21, CPU_FEATURE_DTS },
|
||||
{ 22, CPU_FEATURE_ACPI },
|
||||
{ 27, CPU_FEATURE_SS },
|
||||
{ 29, CPU_FEATURE_TM },
|
||||
{ 30, CPU_FEATURE_IA64 },
|
||||
{ 31, CPU_FEATURE_PBE },
|
||||
};
|
||||
const struct feature_map_t matchtable_ecx1[] = {
|
||||
{ 2, CPU_FEATURE_DTS64 },
|
||||
{ 4, CPU_FEATURE_DS_CPL },
|
||||
{ 5, CPU_FEATURE_VMX },
|
||||
{ 6, CPU_FEATURE_SMX },
|
||||
{ 7, CPU_FEATURE_EST },
|
||||
{ 8, CPU_FEATURE_TM2 },
|
||||
{ 10, CPU_FEATURE_CID },
|
||||
{ 14, CPU_FEATURE_XTPR },
|
||||
{ 15, CPU_FEATURE_PDCM },
|
||||
{ 18, CPU_FEATURE_DCA },
|
||||
{ 21, CPU_FEATURE_X2APIC },
|
||||
};
|
||||
const struct feature_map_t matchtable_edx81[] = {
|
||||
{ 20, CPU_FEATURE_XD },
|
||||
};
|
||||
const struct feature_map_t matchtable_ebx7[] = {
|
||||
{ 2, CPU_FEATURE_SGX },
|
||||
{ 4, CPU_FEATURE_HLE },
|
||||
{ 11, CPU_FEATURE_RTM },
|
||||
{ 16, CPU_FEATURE_AVX512F },
|
||||
{ 17, CPU_FEATURE_AVX512DQ },
|
||||
{ 18, CPU_FEATURE_RDSEED },
|
||||
{ 19, CPU_FEATURE_ADX },
|
||||
{ 26, CPU_FEATURE_AVX512PF },
|
||||
{ 27, CPU_FEATURE_AVX512ER },
|
||||
{ 28, CPU_FEATURE_AVX512CD },
|
||||
{ 29, CPU_FEATURE_SHA_NI },
|
||||
{ 30, CPU_FEATURE_AVX512BW },
|
||||
{ 31, CPU_FEATURE_AVX512VL },
|
||||
};
|
||||
if (raw->basic_cpuid[0][0] >= 1) {
|
||||
match_features(matchtable_edx1, COUNT_OF(matchtable_edx1), raw->basic_cpuid[1][3], data);
|
||||
match_features(matchtable_ecx1, COUNT_OF(matchtable_ecx1), raw->basic_cpuid[1][2], data);
|
||||
}
|
||||
if (raw->ext_cpuid[0][0] >= 1) {
|
||||
match_features(matchtable_edx81, COUNT_OF(matchtable_edx81), raw->ext_cpuid[1][3], data);
|
||||
}
|
||||
// detect TSX/AVX512:
|
||||
if (raw->basic_cpuid[0][0] >= 7) {
|
||||
match_features(matchtable_ebx7, COUNT_OF(matchtable_ebx7), raw->basic_cpuid[7][1], data);
|
||||
}
|
||||
}
|
||||
|
||||
enum _cache_type_t {
|
||||
L1I,
|
||||
L1D,
|
||||
L2,
|
||||
L3,
|
||||
L4
|
||||
};
|
||||
typedef enum _cache_type_t cache_type_t;
|
||||
|
||||
static void check_case(uint8_t on, cache_type_t cache, int size, int assoc, int linesize, struct cpu_id_t* data)
|
||||
{
|
||||
if (!on) return;
|
||||
switch (cache) {
|
||||
case L1I:
|
||||
data->l1_instruction_cache = size;
|
||||
break;
|
||||
case L1D:
|
||||
data->l1_data_cache = size;
|
||||
data->l1_assoc = assoc;
|
||||
data->l1_cacheline = linesize;
|
||||
break;
|
||||
case L2:
|
||||
data->l2_cache = size;
|
||||
data->l2_assoc = assoc;
|
||||
data->l2_cacheline = linesize;
|
||||
break;
|
||||
case L3:
|
||||
data->l3_cache = size;
|
||||
data->l3_assoc = assoc;
|
||||
data->l3_cacheline = linesize;
|
||||
break;
|
||||
case L4:
|
||||
data->l4_cache = size;
|
||||
data->l4_assoc = assoc;
|
||||
data->l4_cacheline = linesize;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void decode_intel_oldstyle_cache_info(struct cpu_raw_data_t* raw, struct cpu_id_t* data)
|
||||
{
|
||||
uint8_t f[256] = {0};
|
||||
int reg, off;
|
||||
uint32_t x;
|
||||
for (reg = 0; reg < 4; reg++) {
|
||||
x = raw->basic_cpuid[2][reg];
|
||||
if (x & 0x80000000) continue;
|
||||
for (off = 0; off < 4; off++) {
|
||||
f[x & 0xff] = 1;
|
||||
x >>= 8;
|
||||
}
|
||||
}
|
||||
|
||||
check_case(f[0x06], L1I, 8, 4, 32, data);
|
||||
check_case(f[0x08], L1I, 16, 4, 32, data);
|
||||
check_case(f[0x0A], L1D, 8, 2, 32, data);
|
||||
check_case(f[0x0C], L1D, 16, 4, 32, data);
|
||||
check_case(f[0x22], L3, 512, 4, 64, data);
|
||||
check_case(f[0x23], L3, 1024, 8, 64, data);
|
||||
check_case(f[0x25], L3, 2048, 8, 64, data);
|
||||
check_case(f[0x29], L3, 4096, 8, 64, data);
|
||||
check_case(f[0x2C], L1D, 32, 8, 64, data);
|
||||
check_case(f[0x30], L1I, 32, 8, 64, data);
|
||||
check_case(f[0x39], L2, 128, 4, 64, data);
|
||||
check_case(f[0x3A], L2, 192, 6, 64, data);
|
||||
check_case(f[0x3B], L2, 128, 2, 64, data);
|
||||
check_case(f[0x3C], L2, 256, 4, 64, data);
|
||||
check_case(f[0x3D], L2, 384, 6, 64, data);
|
||||
check_case(f[0x3E], L2, 512, 4, 64, data);
|
||||
check_case(f[0x41], L2, 128, 4, 32, data);
|
||||
check_case(f[0x42], L2, 256, 4, 32, data);
|
||||
check_case(f[0x43], L2, 512, 4, 32, data);
|
||||
check_case(f[0x44], L2, 1024, 4, 32, data);
|
||||
check_case(f[0x45], L2, 2048, 4, 32, data);
|
||||
check_case(f[0x46], L3, 4096, 4, 64, data);
|
||||
check_case(f[0x47], L3, 8192, 8, 64, data);
|
||||
check_case(f[0x4A], L3, 6144, 12, 64, data);
|
||||
check_case(f[0x4B], L3, 8192, 16, 64, data);
|
||||
check_case(f[0x4C], L3, 12288, 12, 64, data);
|
||||
check_case(f[0x4D], L3, 16384, 16, 64, data);
|
||||
check_case(f[0x4E], L2, 6144, 24, 64, data);
|
||||
check_case(f[0x60], L1D, 16, 8, 64, data);
|
||||
check_case(f[0x66], L1D, 8, 4, 64, data);
|
||||
check_case(f[0x67], L1D, 16, 4, 64, data);
|
||||
check_case(f[0x68], L1D, 32, 4, 64, data);
|
||||
/* The following four entries are trace cache. Intel does not
|
||||
* specify a cache-line size, so we use -1 instead
|
||||
*/
|
||||
check_case(f[0x70], L1I, 12, 8, -1, data);
|
||||
check_case(f[0x71], L1I, 16, 8, -1, data);
|
||||
check_case(f[0x72], L1I, 32, 8, -1, data);
|
||||
check_case(f[0x73], L1I, 64, 8, -1, data);
|
||||
|
||||
check_case(f[0x78], L2, 1024, 4, 64, data);
|
||||
check_case(f[0x79], L2, 128, 8, 64, data);
|
||||
check_case(f[0x7A], L2, 256, 8, 64, data);
|
||||
check_case(f[0x7B], L2, 512, 8, 64, data);
|
||||
check_case(f[0x7C], L2, 1024, 8, 64, data);
|
||||
check_case(f[0x7D], L2, 2048, 8, 64, data);
|
||||
check_case(f[0x7F], L2, 512, 2, 64, data);
|
||||
check_case(f[0x82], L2, 256, 8, 32, data);
|
||||
check_case(f[0x83], L2, 512, 8, 32, data);
|
||||
check_case(f[0x84], L2, 1024, 8, 32, data);
|
||||
check_case(f[0x85], L2, 2048, 8, 32, data);
|
||||
check_case(f[0x86], L2, 512, 4, 64, data);
|
||||
check_case(f[0x87], L2, 1024, 8, 64, data);
|
||||
|
||||
if (f[0x49]) {
|
||||
/* This flag is overloaded with two meanings. On Xeon MP
|
||||
* (family 0xf, model 0x6) this means L3 cache. On all other
|
||||
* CPUs (notably Conroe et al), this is L2 cache. In both cases
|
||||
* it means 4MB, 16-way associative, 64-byte line size.
|
||||
*/
|
||||
if (data->family == 0xf && data->model == 0x6) {
|
||||
data->l3_cache = 4096;
|
||||
data->l3_assoc = 16;
|
||||
data->l3_cacheline = 64;
|
||||
} else {
|
||||
data->l2_cache = 4096;
|
||||
data->l2_assoc = 16;
|
||||
data->l2_cacheline = 64;
|
||||
}
|
||||
}
|
||||
if (f[0x40]) {
|
||||
/* Again, a special flag. It means:
|
||||
* 1) If no L2 is specified, then CPU is w/o L2 (0 KB)
|
||||
* 2) If L2 is specified by other flags, then, CPU is w/o L3.
|
||||
*/
|
||||
if (data->l2_cache == -1) {
|
||||
data->l2_cache = 0;
|
||||
} else {
|
||||
data->l3_cache = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void decode_intel_deterministic_cache_info(struct cpu_raw_data_t* raw,
|
||||
struct cpu_id_t* data)
|
||||
{
|
||||
int ecx;
|
||||
int ways, partitions, linesize, sets, size, level, typenumber;
|
||||
cache_type_t type;
|
||||
for (ecx = 0; ecx < MAX_INTELFN4_LEVEL; ecx++) {
|
||||
typenumber = raw->intel_fn4[ecx][0] & 0x1f;
|
||||
if (typenumber == 0) break;
|
||||
level = (raw->intel_fn4[ecx][0] >> 5) & 0x7;
|
||||
if (level == 1 && typenumber == 1)
|
||||
type = L1D;
|
||||
else if (level == 1 && typenumber == 2)
|
||||
type = L1I;
|
||||
else if (level == 2 && typenumber == 3)
|
||||
type = L2;
|
||||
else if (level == 3 && typenumber == 3)
|
||||
type = L3;
|
||||
else if (level == 4 && typenumber == 3)
|
||||
type = L4;
|
||||
else {
|
||||
warnf("deterministic_cache: unknown level/typenumber combo (%d/%d), cannot\n", level, typenumber);
|
||||
warnf("deterministic_cache: recognize cache type\n");
|
||||
continue;
|
||||
}
|
||||
ways = ((raw->intel_fn4[ecx][1] >> 22) & 0x3ff) + 1;
|
||||
partitions = ((raw->intel_fn4[ecx][1] >> 12) & 0x3ff) + 1;
|
||||
linesize = (raw->intel_fn4[ecx][1] & 0xfff) + 1;
|
||||
sets = raw->intel_fn4[ecx][2] + 1;
|
||||
size = ways * partitions * linesize * sets / 1024;
|
||||
check_case(1, type, size, ways, linesize, data);
|
||||
}
|
||||
}
|
||||
|
||||
static int decode_intel_extended_topology(struct cpu_raw_data_t* raw,
|
||||
struct cpu_id_t* data)
|
||||
{
|
||||
int i, level_type, num_smt = -1, num_core = -1;
|
||||
for (i = 0; i < MAX_INTELFN11_LEVEL; i++) {
|
||||
level_type = (raw->intel_fn11[i][2] & 0xff00) >> 8;
|
||||
switch (level_type) {
|
||||
case 0x01:
|
||||
num_smt = raw->intel_fn11[i][1] & 0xffff;
|
||||
break;
|
||||
case 0x02:
|
||||
num_core = raw->intel_fn11[i][1] & 0xffff;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (num_smt == -1 || num_core == -1) return 0;
|
||||
data->num_logical_cpus = num_core;
|
||||
data->num_cores = num_core / num_smt;
|
||||
// make sure num_cores is at least 1. In VMs, the CPUID instruction
|
||||
// is rigged and may give nonsensical results, but we should at least
|
||||
// avoid outputs like data->num_cores == 0.
|
||||
if (data->num_cores <= 0) data->num_cores = 1;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void decode_intel_number_of_cores(struct cpu_raw_data_t* raw,
|
||||
struct cpu_id_t* data)
|
||||
{
|
||||
int logical_cpus = -1, num_cores = -1;
|
||||
|
||||
if (raw->basic_cpuid[0][0] >= 11) {
|
||||
if (decode_intel_extended_topology(raw, data)) return;
|
||||
}
|
||||
|
||||
if (raw->basic_cpuid[0][0] >= 1) {
|
||||
logical_cpus = (raw->basic_cpuid[1][1] >> 16) & 0xff;
|
||||
if (raw->basic_cpuid[0][0] >= 4) {
|
||||
num_cores = 1 + ((raw->basic_cpuid[4][0] >> 26) & 0x3f);
|
||||
}
|
||||
}
|
||||
if (data->flags[CPU_FEATURE_HT]) {
|
||||
if (num_cores > 1) {
|
||||
data->num_cores = num_cores;
|
||||
data->num_logical_cpus = logical_cpus;
|
||||
} else {
|
||||
data->num_cores = 1;
|
||||
data->num_logical_cpus = (logical_cpus >= 1 ? logical_cpus : 1);
|
||||
if (data->num_logical_cpus == 1)
|
||||
data->flags[CPU_FEATURE_HT] = 0;
|
||||
}
|
||||
} else {
|
||||
data->num_cores = data->num_logical_cpus = 1;
|
||||
}
|
||||
}
|
||||
|
||||
static intel_code_and_bits_t get_brand_code_and_bits(struct cpu_id_t* data)
|
||||
{
|
||||
intel_code_t code = (intel_code_t) NC;
|
||||
intel_code_and_bits_t result;
|
||||
uint64_t bits = 0;
|
||||
int i = 0;
|
||||
const char* bs = data->brand_str;
|
||||
const char* s;
|
||||
const struct { intel_code_t c; const char *search; } matchtable[] = {
|
||||
{ PENTIUM_M, "Pentium(R) M" },
|
||||
{ CORE_SOLO, "Pentium(R) Dual CPU" },
|
||||
{ CORE_SOLO, "Pentium(R) Dual-Core" },
|
||||
{ PENTIUM_D, "Pentium(R) D" },
|
||||
{ CORE_SOLO, "Genuine Intel(R) CPU" },
|
||||
{ CORE_SOLO, "Intel(R) Core(TM)" },
|
||||
{ DIAMONDVILLE, "CPU [N ][23]## " },
|
||||
{ SILVERTHORNE, "CPU Z" },
|
||||
{ PINEVIEW, "CPU [ND][45]## " },
|
||||
{ CEDARVIEW, "CPU [ND]#### " },
|
||||
};
|
||||
|
||||
const struct { uint64_t bit; const char* search; } bit_matchtable[] = {
|
||||
{ XEON_, "Xeon" },
|
||||
{ _MP, " MP" },
|
||||
{ ATOM_, "Atom(TM) CPU" },
|
||||
{ MOBILE_, "Mobile" },
|
||||
{ CELERON_, "Celeron" },
|
||||
{ PENTIUM_, "Pentium" },
|
||||
};
|
||||
|
||||
for (i = 0; i < COUNT_OF(bit_matchtable); i++) {
|
||||
if (match_pattern(bs, bit_matchtable[i].search))
|
||||
bits |= bit_matchtable[i].bit;
|
||||
}
|
||||
|
||||
if ((i = match_pattern(bs, "Core(TM) [im][357]")) != 0) {
|
||||
bits |= CORE_;
|
||||
i--;
|
||||
switch (bs[i + 9]) {
|
||||
case 'i': bits |= _I_; break;
|
||||
case 'm': bits |= _M_; break;
|
||||
}
|
||||
switch (bs[i + 10]) {
|
||||
case '3': bits |= _3; break;
|
||||
case '5': bits |= _5; break;
|
||||
case '7': bits |= _7; break;
|
||||
}
|
||||
}
|
||||
for (i = 0; i < COUNT_OF(matchtable); i++)
|
||||
if (match_pattern(bs, matchtable[i].search)) {
|
||||
code = matchtable[i].c;
|
||||
break;
|
||||
}
|
||||
debugf(2, "intel matchtable result is %d\n", code);
|
||||
if (bits & XEON_) {
|
||||
if (match_pattern(bs, "W35##") || match_pattern(bs, "[ELXW]75##"))
|
||||
bits |= _7;
|
||||
else if (match_pattern(bs, "[ELXW]55##"))
|
||||
code = GAINESTOWN;
|
||||
else if (match_pattern(bs, "[ELXW]56##"))
|
||||
code = WESTMERE;
|
||||
else if (data->l3_cache > 0 && data->family == 16)
|
||||
/* restrict by family, since later Xeons also have L3 ... */
|
||||
code = IRWIN;
|
||||
}
|
||||
if (match_all(bits, XEON_ + _MP) && data->l3_cache > 0)
|
||||
code = POTOMAC;
|
||||
if (code == CORE_SOLO) {
|
||||
s = strstr(bs, "CPU");
|
||||
if (s) {
|
||||
s += 3;
|
||||
while (*s == ' ') s++;
|
||||
if (*s == 'T')
|
||||
bits |= MOBILE_;
|
||||
}
|
||||
}
|
||||
if (code == CORE_SOLO) {
|
||||
switch (data->num_cores) {
|
||||
case 1: break;
|
||||
case 2:
|
||||
{
|
||||
code = CORE_DUO;
|
||||
if (data->num_logical_cpus > 2)
|
||||
code = DUAL_CORE_HT;
|
||||
break;
|
||||
}
|
||||
case 4:
|
||||
{
|
||||
code = QUAD_CORE;
|
||||
if (data->num_logical_cpus > 4)
|
||||
code = QUAD_CORE_HT;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
code = MORE_THAN_QUADCORE; break;
|
||||
}
|
||||
}
|
||||
|
||||
if (code == CORE_DUO && (bits & MOBILE_) && data->model != 14) {
|
||||
if (data->ext_model < 23) {
|
||||
code = MEROM;
|
||||
} else {
|
||||
code = PENRYN;
|
||||
}
|
||||
}
|
||||
if (data->ext_model == 23 &&
|
||||
(code == CORE_DUO || code == PENTIUM_D || (bits & CELERON_))) {
|
||||
code = WOLFDALE;
|
||||
}
|
||||
|
||||
result.code = code;
|
||||
result.bits = bits;
|
||||
return result;
|
||||
}
|
||||
|
||||
static intel_model_t get_model_code(struct cpu_id_t* data)
|
||||
{
|
||||
int i = 0;
|
||||
int l = (int) strlen(data->brand_str);
|
||||
const char *bs = data->brand_str;
|
||||
int mod_flags = 0, model_no = 0, ndigs = 0;
|
||||
/* If the CPU is a Core ix, then just return the model number generation: */
|
||||
if ((i = match_pattern(bs, "Core(TM) i[357]")) != 0) {
|
||||
i += 11;
|
||||
if (i + 4 >= l) return UNKNOWN;
|
||||
if (bs[i] == '2') return _2xxx;
|
||||
if (bs[i] == '3') return _3xxx;
|
||||
return UNKNOWN;
|
||||
}
|
||||
|
||||
/* For Core2-based Xeons: */
|
||||
while (i < l - 3) {
|
||||
if (bs[i] == 'C' && bs[i+1] == 'P' && bs[i+2] == 'U')
|
||||
break;
|
||||
i++;
|
||||
}
|
||||
if (i >= l - 3) return UNKNOWN;
|
||||
i += 3;
|
||||
while (i < l - 4 && bs[i] == ' ') i++;
|
||||
if (i >= l - 4) return UNKNOWN;
|
||||
while (i < l - 4 && !isdigit(bs[i])) {
|
||||
if (bs[i] >= 'A' && bs[i] <= 'Z')
|
||||
mod_flags |= (1 << (bs[i] - 'A'));
|
||||
i++;
|
||||
}
|
||||
if (i >= l - 4) return UNKNOWN;
|
||||
while (isdigit(bs[i])) {
|
||||
ndigs++;
|
||||
model_no = model_no * 10 + (int) (bs[i] - '0');
|
||||
i++;
|
||||
}
|
||||
if (ndigs != 4) return UNKNOWN;
|
||||
#define HAVE(ch, flags) ((flags & (1 << ((int)(ch-'A')))) != 0)
|
||||
switch (model_no / 100) {
|
||||
case 30: return _3000;
|
||||
case 31: return _3100;
|
||||
case 32:
|
||||
{
|
||||
return (HAVE('X', mod_flags)) ? X3200 : _3200;
|
||||
}
|
||||
case 33:
|
||||
{
|
||||
return (HAVE('X', mod_flags)) ? X3300 : _3300;
|
||||
}
|
||||
case 51: return _5100;
|
||||
case 52: return _5200;
|
||||
case 53: return _5300;
|
||||
case 54: return _5400;
|
||||
default:
|
||||
return UNKNOWN;
|
||||
}
|
||||
#undef HAVE
|
||||
}
|
||||
|
||||
static void decode_intel_sgx_features(const struct cpu_raw_data_t* raw, struct cpu_id_t* data)
|
||||
{
|
||||
struct cpu_epc_t epc;
|
||||
int i;
|
||||
|
||||
if (raw->basic_cpuid[0][0] < 0x12) return; // no 12h leaf
|
||||
if (raw->basic_cpuid[0x12][0] == 0) return; // no sub-leafs available, probably it's disabled by BIOS
|
||||
|
||||
// decode sub-leaf 0:
|
||||
if (raw->basic_cpuid[0x12][0] & 1) data->sgx.flags[INTEL_SGX1] = 1;
|
||||
if (raw->basic_cpuid[0x12][0] & 2) data->sgx.flags[INTEL_SGX2] = 1;
|
||||
if (data->sgx.flags[INTEL_SGX1] || data->sgx.flags[INTEL_SGX2])
|
||||
data->sgx.present = 1;
|
||||
data->sgx.misc_select = raw->basic_cpuid[0x12][1];
|
||||
data->sgx.max_enclave_32bit = (raw->basic_cpuid[0x12][3] ) & 0xff;
|
||||
data->sgx.max_enclave_64bit = (raw->basic_cpuid[0x12][3] >> 8) & 0xff;
|
||||
|
||||
// decode sub-leaf 1:
|
||||
data->sgx.secs_attributes = raw->intel_fn12h[1][0] | (((uint64_t) raw->intel_fn12h[1][1]) << 32);
|
||||
data->sgx.secs_xfrm = raw->intel_fn12h[1][2] | (((uint64_t) raw->intel_fn12h[1][3]) << 32);
|
||||
|
||||
// decode higher-order subleafs, whenever present:
|
||||
data->sgx.num_epc_sections = -1;
|
||||
for (i = 0; i < 1000000; i++) {
|
||||
epc = cpuid_get_epc(i, raw);
|
||||
if (epc.length == 0) {
|
||||
debugf(2, "SGX: epc section request for %d returned null, no more EPC sections.\n", i);
|
||||
data->sgx.num_epc_sections = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (data->sgx.num_epc_sections == -1) {
|
||||
debugf(1, "SGX: warning: seems to be infinitude of EPC sections.\n");
|
||||
data->sgx.num_epc_sections = 1000000;
|
||||
}
|
||||
}
|
||||
|
||||
struct cpu_epc_t cpuid_get_epc(int index, const struct cpu_raw_data_t* raw)
|
||||
{
|
||||
uint32_t regs[4];
|
||||
struct cpu_epc_t retval = {0, 0};
|
||||
if (raw && index < MAX_INTELFN12H_LEVEL - 2) {
|
||||
// this was queried already, use the data:
|
||||
memcpy(regs, raw->intel_fn12h[2 + index], sizeof(regs));
|
||||
} else {
|
||||
// query this ourselves:
|
||||
regs[0] = 0x12;
|
||||
regs[2] = 2 + index;
|
||||
regs[1] = regs[3] = 0;
|
||||
cpu_exec_cpuid_ext(regs);
|
||||
}
|
||||
|
||||
// decode values:
|
||||
if ((regs[0] & 0xf) == 0x1) {
|
||||
retval.start_addr |= (regs[0] & 0xfffff000); // bits [12, 32) -> bits [12, 32)
|
||||
retval.start_addr |= ((uint64_t) (regs[1] & 0x000fffff)) << 32; // bits [0, 20) -> bits [32, 52)
|
||||
retval.length |= (regs[2] & 0xfffff000); // bits [12, 32) -> bits [12, 32)
|
||||
retval.length |= ((uint64_t) (regs[3] & 0x000fffff)) << 32; // bits [0, 20) -> bits [32, 52)
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
|
||||
int cpuid_identify_intel(struct cpu_raw_data_t* raw, struct cpu_id_t* data, struct internal_id_info_t* internal)
|
||||
{
|
||||
intel_code_and_bits_t brand;
|
||||
intel_model_t model_code;
|
||||
int i;
|
||||
char* brand_code_str = NULL;
|
||||
|
||||
load_intel_features(raw, data);
|
||||
if (raw->basic_cpuid[0][0] >= 4) {
|
||||
/* Deterministic way is preferred, being more generic */
|
||||
decode_intel_deterministic_cache_info(raw, data);
|
||||
} else if (raw->basic_cpuid[0][0] >= 2) {
|
||||
decode_intel_oldstyle_cache_info(raw, data);
|
||||
}
|
||||
decode_intel_number_of_cores(raw, data);
|
||||
|
||||
brand = get_brand_code_and_bits(data);
|
||||
model_code = get_model_code(data);
|
||||
for (i = 0; i < COUNT_OF(intel_bcode_str); i++) {
|
||||
if (brand.code == intel_bcode_str[i].code) {
|
||||
brand_code_str = intel_bcode_str[i].str;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (brand_code_str)
|
||||
debugf(2, "Detected Intel brand code: %d (%s)\n", brand.code, brand_code_str);
|
||||
else
|
||||
debugf(2, "Detected Intel brand code: %d\n", brand.code);
|
||||
if (brand.bits) {
|
||||
debugf(2, "Detected Intel bits: ");
|
||||
debug_print_lbits(2, brand.bits);
|
||||
}
|
||||
debugf(2, "Detected Intel model code: %d\n", model_code);
|
||||
|
||||
internal->code.intel = brand.code;
|
||||
internal->bits = brand.bits;
|
||||
|
||||
if (data->flags[CPU_FEATURE_SGX]) {
|
||||
debugf(2, "SGX seems to be present, decoding...\n");
|
||||
// if SGX is indicated by the CPU, verify its presence:
|
||||
decode_intel_sgx_features(raw, data);
|
||||
}
|
||||
|
||||
internal->score = match_cpu_codename(cpudb_intel, COUNT_OF(cpudb_intel), data,
|
||||
brand.code, brand.bits, model_code);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void cpuid_get_list_intel(struct cpu_list_t* list)
|
||||
{
|
||||
generic_get_cpu_list(cpudb_intel, COUNT_OF(cpudb_intel), list);
|
||||
}
|
||||
392
compat/winansi.c
392
compat/winansi.c
@@ -1,392 +0,0 @@
|
||||
/**
|
||||
* Old Git implementation of windows terminal colors (2009)
|
||||
* before use of a threaded wrapper.
|
||||
*/
|
||||
|
||||
#undef NOGDI
|
||||
#include <windows.h>
|
||||
#include <wingdi.h>
|
||||
#include <winreg.h>
|
||||
#include <malloc.h>
|
||||
#include <stdio.h>
|
||||
#include <io.h>
|
||||
|
||||
#include "compat/winansi.h"
|
||||
/*
|
||||
* Copyright 2008 Peter Harris <git@peter.is-a-geek.org>
|
||||
*/
|
||||
|
||||
/*
|
||||
Functions to be wrapped:
|
||||
*/
|
||||
#undef printf
|
||||
#undef fprintf
|
||||
#undef fputs
|
||||
#undef vfprintf
|
||||
/* TODO: write */
|
||||
|
||||
/*
|
||||
ANSI codes used by git: m, K
|
||||
|
||||
This file is git-specific. Therefore, this file does not attempt
|
||||
to implement any codes that are not used by git.
|
||||
*/
|
||||
|
||||
static HANDLE console;
|
||||
static WORD plain_attr;
|
||||
static WORD attr;
|
||||
static int negative;
|
||||
|
||||
static void init(void)
|
||||
{
|
||||
CONSOLE_SCREEN_BUFFER_INFO sbi;
|
||||
|
||||
static int initialized = 0;
|
||||
if (initialized)
|
||||
return;
|
||||
|
||||
console = GetStdHandle(STD_OUTPUT_HANDLE);
|
||||
if (console == INVALID_HANDLE_VALUE)
|
||||
console = NULL;
|
||||
|
||||
if (!console)
|
||||
return;
|
||||
|
||||
GetConsoleScreenBufferInfo(console, &sbi);
|
||||
attr = plain_attr = sbi.wAttributes;
|
||||
negative = 0;
|
||||
|
||||
initialized = 1;
|
||||
}
|
||||
|
||||
static int write_console(const char *str, int len)
|
||||
{
|
||||
/* convert utf-8 to utf-16, write directly to console */
|
||||
int wlen = MultiByteToWideChar(CP_UTF8, 0, str, len, NULL, 0);
|
||||
wchar_t *wbuf = (wchar_t *)alloca(wlen * sizeof(wchar_t));
|
||||
MultiByteToWideChar(CP_UTF8, 0, str, len, wbuf, wlen);
|
||||
|
||||
WriteConsoleW(console, wbuf, wlen, NULL, NULL);
|
||||
|
||||
/* return original (utf-8 encoded) length */
|
||||
return len;
|
||||
}
|
||||
|
||||
#define FOREGROUND_ALL (FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE)
|
||||
#define BACKGROUND_ALL (BACKGROUND_RED | BACKGROUND_GREEN | BACKGROUND_BLUE)
|
||||
|
||||
static void set_console_attr(void)
|
||||
{
|
||||
WORD attributes = attr;
|
||||
if (negative) {
|
||||
attributes &= ~FOREGROUND_ALL;
|
||||
attributes &= ~BACKGROUND_ALL;
|
||||
|
||||
/* This could probably use a bitmask
|
||||
instead of a series of ifs */
|
||||
if (attr & FOREGROUND_RED)
|
||||
attributes |= BACKGROUND_RED;
|
||||
if (attr & FOREGROUND_GREEN)
|
||||
attributes |= BACKGROUND_GREEN;
|
||||
if (attr & FOREGROUND_BLUE)
|
||||
attributes |= BACKGROUND_BLUE;
|
||||
|
||||
if (attr & BACKGROUND_RED)
|
||||
attributes |= FOREGROUND_RED;
|
||||
if (attr & BACKGROUND_GREEN)
|
||||
attributes |= FOREGROUND_GREEN;
|
||||
if (attr & BACKGROUND_BLUE)
|
||||
attributes |= FOREGROUND_BLUE;
|
||||
}
|
||||
SetConsoleTextAttribute(console, attributes);
|
||||
}
|
||||
|
||||
static void erase_in_line(void)
|
||||
{
|
||||
CONSOLE_SCREEN_BUFFER_INFO sbi;
|
||||
DWORD dummy; /* Needed for Windows 7 (or Vista) regression */
|
||||
|
||||
if (!console)
|
||||
return;
|
||||
|
||||
GetConsoleScreenBufferInfo(console, &sbi);
|
||||
FillConsoleOutputCharacterA(console, ' ',
|
||||
sbi.dwSize.X - sbi.dwCursorPosition.X, sbi.dwCursorPosition,
|
||||
&dummy);
|
||||
}
|
||||
|
||||
|
||||
static const char *set_attr(const char *str)
|
||||
{
|
||||
const char *func;
|
||||
size_t len = strspn(str, "0123456789;");
|
||||
func = str + len;
|
||||
|
||||
switch (*func) {
|
||||
case 'm':
|
||||
do {
|
||||
long val = strtol(str, (char **)&str, 10);
|
||||
switch (val) {
|
||||
case 0: /* reset */
|
||||
attr = plain_attr;
|
||||
negative = 0;
|
||||
break;
|
||||
case 1: /* bold */
|
||||
attr |= FOREGROUND_INTENSITY;
|
||||
break;
|
||||
case 2: /* faint */
|
||||
case 22: /* normal */
|
||||
attr &= ~FOREGROUND_INTENSITY;
|
||||
break;
|
||||
case 3: /* italic */
|
||||
/* Unsupported */
|
||||
break;
|
||||
case 4: /* underline */
|
||||
case 21: /* double underline */
|
||||
/* Wikipedia says this flag does nothing */
|
||||
/* Furthermore, mingw doesn't define this flag
|
||||
attr |= COMMON_LVB_UNDERSCORE; */
|
||||
break;
|
||||
case 24: /* no underline */
|
||||
/* attr &= ~COMMON_LVB_UNDERSCORE; */
|
||||
break;
|
||||
case 5: /* slow blink */
|
||||
case 6: /* fast blink */
|
||||
/* We don't have blink, but we do have
|
||||
background intensity */
|
||||
attr |= BACKGROUND_INTENSITY;
|
||||
break;
|
||||
case 25: /* no blink */
|
||||
attr &= ~BACKGROUND_INTENSITY;
|
||||
break;
|
||||
case 7: /* negative */
|
||||
negative = 1;
|
||||
break;
|
||||
case 27: /* positive */
|
||||
negative = 0;
|
||||
break;
|
||||
case 8: /* conceal */
|
||||
case 28: /* reveal */
|
||||
/* Unsupported */
|
||||
break;
|
||||
case 30: /* Black */
|
||||
attr &= ~FOREGROUND_ALL;
|
||||
break;
|
||||
case 31: /* Red */
|
||||
attr &= ~FOREGROUND_ALL;
|
||||
attr |= FOREGROUND_RED;
|
||||
break;
|
||||
case 32: /* Green */
|
||||
attr &= ~FOREGROUND_ALL;
|
||||
attr |= FOREGROUND_GREEN;
|
||||
break;
|
||||
case 33: /* Yellow */
|
||||
attr &= ~FOREGROUND_ALL;
|
||||
attr |= FOREGROUND_RED | FOREGROUND_GREEN;
|
||||
break;
|
||||
case 34: /* Blue */
|
||||
attr &= ~FOREGROUND_ALL;
|
||||
attr |= FOREGROUND_BLUE;
|
||||
break;
|
||||
case 35: /* Magenta */
|
||||
attr &= ~FOREGROUND_ALL;
|
||||
attr |= FOREGROUND_RED | FOREGROUND_BLUE;
|
||||
break;
|
||||
case 36: /* Cyan */
|
||||
attr &= ~FOREGROUND_ALL;
|
||||
attr |= FOREGROUND_GREEN | FOREGROUND_BLUE;
|
||||
break;
|
||||
case 37: /* White */
|
||||
attr |= FOREGROUND_RED |
|
||||
FOREGROUND_GREEN |
|
||||
FOREGROUND_BLUE;
|
||||
break;
|
||||
case 38: /* Unknown */
|
||||
break;
|
||||
case 39: /* reset */
|
||||
attr &= ~FOREGROUND_ALL;
|
||||
attr |= (plain_attr & FOREGROUND_ALL);
|
||||
break;
|
||||
case 40: /* Black */
|
||||
attr &= ~BACKGROUND_ALL;
|
||||
break;
|
||||
case 41: /* Red */
|
||||
attr &= ~BACKGROUND_ALL;
|
||||
attr |= BACKGROUND_RED;
|
||||
break;
|
||||
case 42: /* Green */
|
||||
attr &= ~BACKGROUND_ALL;
|
||||
attr |= BACKGROUND_GREEN;
|
||||
break;
|
||||
case 43: /* Yellow */
|
||||
attr &= ~BACKGROUND_ALL;
|
||||
attr |= BACKGROUND_RED | BACKGROUND_GREEN;
|
||||
break;
|
||||
case 44: /* Blue */
|
||||
attr &= ~BACKGROUND_ALL;
|
||||
attr |= BACKGROUND_BLUE;
|
||||
break;
|
||||
case 45: /* Magenta */
|
||||
attr &= ~BACKGROUND_ALL;
|
||||
attr |= BACKGROUND_RED | BACKGROUND_BLUE;
|
||||
break;
|
||||
case 46: /* Cyan */
|
||||
attr &= ~BACKGROUND_ALL;
|
||||
attr |= BACKGROUND_GREEN | BACKGROUND_BLUE;
|
||||
break;
|
||||
case 47: /* White */
|
||||
attr |= BACKGROUND_RED |
|
||||
BACKGROUND_GREEN |
|
||||
BACKGROUND_BLUE;
|
||||
break;
|
||||
case 48: /* Unknown */
|
||||
break;
|
||||
case 49: /* reset */
|
||||
attr &= ~BACKGROUND_ALL;
|
||||
attr |= (plain_attr & BACKGROUND_ALL);
|
||||
break;
|
||||
default:
|
||||
/* Unsupported code */
|
||||
break;
|
||||
}
|
||||
str++;
|
||||
} while (*(str - 1) == ';');
|
||||
|
||||
set_console_attr();
|
||||
break;
|
||||
case 'K':
|
||||
erase_in_line();
|
||||
break;
|
||||
default:
|
||||
/* Unsupported code */
|
||||
break;
|
||||
}
|
||||
|
||||
return func + 1;
|
||||
}
|
||||
|
||||
static int ansi_emulate(const char *str, FILE *stream)
|
||||
{
|
||||
int rv = 0;
|
||||
const char *pos = str;
|
||||
|
||||
fflush(stream);
|
||||
|
||||
while (*pos) {
|
||||
pos = strstr(str, "\033[");
|
||||
if (pos) {
|
||||
int len = (int) (pos - str);
|
||||
|
||||
if (len) {
|
||||
int out_len = write_console(str, len);
|
||||
rv += out_len;
|
||||
if (out_len < len)
|
||||
return rv;
|
||||
}
|
||||
|
||||
str = pos + 2;
|
||||
rv += 2;
|
||||
|
||||
pos = set_attr(str);
|
||||
rv += (int) (pos - str);
|
||||
str = pos;
|
||||
}
|
||||
else {
|
||||
int len = (int) strlen(str);
|
||||
rv += write_console(str, len);
|
||||
return rv;
|
||||
}
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
int winansi_fputs(const char *str, FILE *stream)
|
||||
{
|
||||
int rv;
|
||||
|
||||
if (!isatty(fileno(stream)))
|
||||
return fputs(str, stream);
|
||||
|
||||
init();
|
||||
|
||||
if (!console)
|
||||
return fputs(str, stream);
|
||||
|
||||
rv = ansi_emulate(str, stream);
|
||||
|
||||
if (rv >= 0)
|
||||
return 0;
|
||||
else
|
||||
return EOF;
|
||||
}
|
||||
|
||||
int winansi_vfprintf(FILE *stream, const char *format, va_list list)
|
||||
{
|
||||
int len, rv;
|
||||
char small_buf[256] = { 0 };
|
||||
char *buf = small_buf;
|
||||
va_list cp;
|
||||
|
||||
if (!isatty(fileno(stream)))
|
||||
goto abort;
|
||||
|
||||
init();
|
||||
|
||||
if (!console)
|
||||
goto abort;
|
||||
|
||||
va_copy(cp, list);
|
||||
len = vsnprintf(small_buf, sizeof(small_buf), format, cp);
|
||||
#ifdef WIN32
|
||||
/* bug on long strings without that */
|
||||
if (len == -1)
|
||||
len = _vscprintf(format, cp);
|
||||
#endif
|
||||
va_end(cp);
|
||||
|
||||
if (len > sizeof(small_buf) - 1) {
|
||||
buf = malloc(len + 1);
|
||||
if (!buf)
|
||||
goto abort;
|
||||
|
||||
len = vsnprintf(buf, len + 1, format, list);
|
||||
#ifdef WIN32
|
||||
if (len == -1)
|
||||
len = _vscprintf(format, list);
|
||||
#endif
|
||||
}
|
||||
|
||||
rv = ansi_emulate(buf, stream);
|
||||
|
||||
if (buf != small_buf)
|
||||
free(buf);
|
||||
return rv;
|
||||
|
||||
abort:
|
||||
rv = vfprintf(stream, format, list);
|
||||
return rv;
|
||||
}
|
||||
|
||||
int winansi_fprintf(FILE *stream, const char *format, ...)
|
||||
{
|
||||
va_list list;
|
||||
int rv;
|
||||
|
||||
va_start(list, format);
|
||||
rv = winansi_vfprintf(stream, format, list);
|
||||
va_end(list);
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
int winansi_printf(const char *format, ...)
|
||||
{
|
||||
va_list list;
|
||||
int rv;
|
||||
|
||||
va_start(list, format);
|
||||
rv = winansi_vfprintf(stdout, format, list);
|
||||
va_end(list);
|
||||
|
||||
return rv;
|
||||
}
|
||||
@@ -1,32 +0,0 @@
|
||||
/*
|
||||
* ANSI emulation wrappers
|
||||
*/
|
||||
#ifdef WIN32
|
||||
#include <windows.h>
|
||||
#include <stddef.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#define isatty(fd) _isatty(fd)
|
||||
#define fileno(fd) _fileno(fd)
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
int winansi_fputs(const char *str, FILE *stream);
|
||||
int winansi_printf(const char *format, ...);
|
||||
int winansi_fprintf(FILE *stream, const char *format, ...);
|
||||
int winansi_vfprintf(FILE *stream, const char *format, va_list list);
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#undef fputs
|
||||
#undef fprintf
|
||||
#undef vfprintf
|
||||
|
||||
#define fputs winansi_fputs
|
||||
#define printf winansi_printf
|
||||
#define fprintf winansi_fprintf
|
||||
#define vfprintf winansi_vfprintf
|
||||
|
||||
#endif
|
||||
93
cpu.c
93
cpu.c
@@ -1,93 +0,0 @@
|
||||
/* XMRig
|
||||
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com>
|
||||
* Copyright 2012-2014 pooler <pooler@litecoinpool.org>
|
||||
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
|
||||
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
|
||||
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
|
||||
* Copyright 2016-2017 XMRig <support@xmrig.com>
|
||||
*
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <cpuid.h>
|
||||
#include <string.h>
|
||||
#include <stdbool.h>
|
||||
#include <math.h>
|
||||
|
||||
#ifndef BUILD_TEST
|
||||
# include <libcpuid.h>
|
||||
#endif
|
||||
|
||||
#include "cpu.h"
|
||||
#include "utils/applog.h"
|
||||
|
||||
|
||||
#ifndef BUILD_TEST
|
||||
void cpu_init_common() {
|
||||
struct cpu_raw_data_t raw = { 0 };
|
||||
struct cpu_id_t data = { 0 };
|
||||
|
||||
cpuid_get_raw_data(&raw);
|
||||
cpu_identify(&raw, &data);
|
||||
|
||||
strncpy(cpu_info.brand, data.brand_str, sizeof(cpu_info.brand) - 1);
|
||||
|
||||
cpu_info.total_logical_cpus = data.total_logical_cpus;
|
||||
cpu_info.sockets = data.total_logical_cpus / data.num_logical_cpus;
|
||||
cpu_info.total_cores = data.num_cores * cpu_info.sockets;
|
||||
cpu_info.l2_cache = data.l2_cache > 0 ? data.l2_cache * cpu_info.total_cores * cpu_info.sockets : 0;
|
||||
cpu_info.l3_cache = data.l3_cache > 0 ? data.l3_cache * cpu_info.sockets : 0;
|
||||
|
||||
# ifdef __x86_64__
|
||||
cpu_info.flags |= CPU_FLAG_X86_64;
|
||||
# endif
|
||||
|
||||
if (data.flags[CPU_FEATURE_AES]) {
|
||||
cpu_info.flags |= CPU_FLAG_AES;
|
||||
}
|
||||
|
||||
if (data.flags[CPU_FEATURE_BMI2]) {
|
||||
cpu_info.flags |= CPU_FLAG_BMI2;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
int get_optimal_threads_count(int algo, bool double_hash, int max_cpu_usage) {
|
||||
if (cpu_info.total_logical_cpus == 1) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
int cache = cpu_info.l3_cache ? cpu_info.l3_cache : cpu_info.l2_cache;
|
||||
int count = 0;
|
||||
const int size = (algo ? 1024 : 2048) * (double_hash ? 2 : 1);
|
||||
|
||||
if (cache) {
|
||||
count = cache / size;
|
||||
}
|
||||
else {
|
||||
count = cpu_info.total_logical_cpus / 2;
|
||||
}
|
||||
|
||||
if (count > cpu_info.total_logical_cpus) {
|
||||
count = cpu_info.total_logical_cpus;
|
||||
}
|
||||
|
||||
if (((float) count / cpu_info.total_logical_cpus * 100) > max_cpu_usage) {
|
||||
count = ceil((float) cpu_info.total_logical_cpus * (max_cpu_usage / 100.0));
|
||||
}
|
||||
|
||||
return count < 1 ? 1 : count;
|
||||
}
|
||||
@@ -1,123 +0,0 @@
|
||||
// keccak.c
|
||||
// 19-Nov-11 Markku-Juhani O. Saarinen <mjos@iki.fi>
|
||||
// A baseline Keccak (3rd round) implementation.
|
||||
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
#define HASH_DATA_AREA 136
|
||||
#define KECCAK_ROUNDS 24
|
||||
|
||||
#ifndef ROTL64
|
||||
#define ROTL64(x, y) (((x) << (y)) | ((x) >> (64 - (y))))
|
||||
#endif
|
||||
|
||||
const uint64_t keccakf_rndc[24] =
|
||||
{
|
||||
0x0000000000000001, 0x0000000000008082, 0x800000000000808a,
|
||||
0x8000000080008000, 0x000000000000808b, 0x0000000080000001,
|
||||
0x8000000080008081, 0x8000000000008009, 0x000000000000008a,
|
||||
0x0000000000000088, 0x0000000080008009, 0x000000008000000a,
|
||||
0x000000008000808b, 0x800000000000008b, 0x8000000000008089,
|
||||
0x8000000000008003, 0x8000000000008002, 0x8000000000000080,
|
||||
0x000000000000800a, 0x800000008000000a, 0x8000000080008081,
|
||||
0x8000000000008080, 0x0000000080000001, 0x8000000080008008
|
||||
};
|
||||
|
||||
const int keccakf_rotc[24] =
|
||||
{
|
||||
1, 3, 6, 10, 15, 21, 28, 36, 45, 55, 2, 14,
|
||||
27, 41, 56, 8, 25, 43, 62, 18, 39, 61, 20, 44
|
||||
};
|
||||
|
||||
const int keccakf_piln[24] =
|
||||
{
|
||||
10, 7, 11, 17, 18, 3, 5, 16, 8, 21, 24, 4,
|
||||
15, 23, 19, 13, 12, 2, 20, 14, 22, 9, 6, 1
|
||||
};
|
||||
|
||||
// update the state with given number of rounds
|
||||
|
||||
void keccakf(uint64_t st[25], int rounds)
|
||||
{
|
||||
int i, j, round;
|
||||
uint64_t t, bc[5];
|
||||
|
||||
for (round = 0; round < rounds; ++round) {
|
||||
|
||||
// Theta
|
||||
bc[0] = st[0] ^ st[5] ^ st[10] ^ st[15] ^ st[20];
|
||||
bc[1] = st[1] ^ st[6] ^ st[11] ^ st[16] ^ st[21];
|
||||
bc[2] = st[2] ^ st[7] ^ st[12] ^ st[17] ^ st[22];
|
||||
bc[3] = st[3] ^ st[8] ^ st[13] ^ st[18] ^ st[23];
|
||||
bc[4] = st[4] ^ st[9] ^ st[14] ^ st[19] ^ st[24];
|
||||
|
||||
for (i = 0; i < 5; ++i) {
|
||||
t = bc[(i + 4) % 5] ^ ROTL64(bc[(i + 1) % 5], 1);
|
||||
st[i ] ^= t;
|
||||
st[i + 5] ^= t;
|
||||
st[i + 10] ^= t;
|
||||
st[i + 15] ^= t;
|
||||
st[i + 20] ^= t;
|
||||
}
|
||||
|
||||
// Rho Pi
|
||||
t = st[1];
|
||||
for (i = 0; i < 24; ++i) {
|
||||
bc[0] = st[keccakf_piln[i]];
|
||||
st[keccakf_piln[i]] = ROTL64(t, keccakf_rotc[i]);
|
||||
t = bc[0];
|
||||
}
|
||||
|
||||
// Chi
|
||||
for (j = 0; j < 25; j += 5) {
|
||||
bc[0] = st[j ];
|
||||
bc[1] = st[j + 1];
|
||||
bc[2] = st[j + 2];
|
||||
bc[3] = st[j + 3];
|
||||
bc[4] = st[j + 4];
|
||||
st[j ] ^= (~bc[1]) & bc[2];
|
||||
st[j + 1] ^= (~bc[2]) & bc[3];
|
||||
st[j + 2] ^= (~bc[3]) & bc[4];
|
||||
st[j + 3] ^= (~bc[4]) & bc[0];
|
||||
st[j + 4] ^= (~bc[0]) & bc[1];
|
||||
}
|
||||
|
||||
// Iota
|
||||
st[0] ^= keccakf_rndc[round];
|
||||
}
|
||||
}
|
||||
|
||||
// compute a keccak hash (md) of given byte length from "in"
|
||||
typedef uint64_t state_t[25];
|
||||
|
||||
void keccak(const uint8_t *in, int inlen, uint8_t *md, int mdlen)
|
||||
{
|
||||
state_t st;
|
||||
uint8_t temp[144];
|
||||
int i, rsiz, rsizw;
|
||||
|
||||
rsiz = sizeof(state_t) == mdlen ? HASH_DATA_AREA : 200 - 2 * mdlen;
|
||||
rsizw = rsiz / 8;
|
||||
|
||||
memset(st, 0, sizeof(st));
|
||||
|
||||
for ( ; inlen >= rsiz; inlen -= rsiz, in += rsiz) {
|
||||
for (i = 0; i < rsizw; i++)
|
||||
st[i] ^= ((uint64_t *) in)[i];
|
||||
keccakf(st, KECCAK_ROUNDS);
|
||||
}
|
||||
|
||||
// last block and padding
|
||||
memcpy(temp, in, inlen);
|
||||
temp[inlen++] = 1;
|
||||
memset(temp + inlen, 0, rsiz - inlen);
|
||||
temp[rsiz - 1] |= 0x80;
|
||||
|
||||
for (i = 0; i < rsizw; i++)
|
||||
st[i] ^= ((uint64_t *) temp)[i];
|
||||
|
||||
keccakf(st, KECCAK_ROUNDS);
|
||||
|
||||
memcpy(md, st, mdlen);
|
||||
}
|
||||
2036
crypto/c_skein.c
2036
crypto/c_skein.c
File diff suppressed because it is too large
Load Diff
@@ -1,24 +0,0 @@
|
||||
// Copyright (c) 2012-2013 The Cryptonote developers
|
||||
// Distributed under the MIT/X11 software license, see the accompanying
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "hash-ops.h"
|
||||
#include "c_keccak.h"
|
||||
|
||||
void hash_permutation(union hash_state *state) {
|
||||
keccakf((uint64_t*)state, 24);
|
||||
}
|
||||
|
||||
void hash_process(union hash_state *state, const uint8_t *buf, size_t count) {
|
||||
keccak1600(buf, count, (uint8_t*)state);
|
||||
}
|
||||
|
||||
void cn_fast_hash(const void *data, size_t length, char *hash) {
|
||||
union hash_state state;
|
||||
hash_process(&state, data, length);
|
||||
memcpy(hash, &state, HASH_SIZE);
|
||||
}
|
||||
274
elist.h
274
elist.h
@@ -1,274 +0,0 @@
|
||||
/* XMRig
|
||||
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com>
|
||||
* Copyright 2012-2014 pooler <pooler@litecoinpool.org>
|
||||
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
|
||||
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
|
||||
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
|
||||
* Copyright 2016-2017 XMRig <support@xmrig.com>
|
||||
*
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef _LINUX_LIST_H
|
||||
#define _LINUX_LIST_H
|
||||
|
||||
/*
|
||||
* Simple doubly linked list implementation.
|
||||
*
|
||||
* Some of the internal functions ("__xxx") are useful when
|
||||
* manipulating whole lists rather than single entries, as
|
||||
* sometimes we already know the next/prev entries and we can
|
||||
* generate better code by using them directly rather than
|
||||
* using the generic single-entry routines.
|
||||
*/
|
||||
|
||||
struct list_head {
|
||||
struct list_head *next, *prev;
|
||||
};
|
||||
|
||||
#define LIST_HEAD_INIT(name) { &(name), &(name) }
|
||||
|
||||
#define LIST_HEAD(name) \
|
||||
struct list_head name = LIST_HEAD_INIT(name)
|
||||
|
||||
#define INIT_LIST_HEAD(ptr) do { \
|
||||
(ptr)->next = (ptr); (ptr)->prev = (ptr); \
|
||||
} while (0)
|
||||
|
||||
/*
|
||||
* Insert a new entry between two known consecutive entries.
|
||||
*
|
||||
* This is only for internal list manipulation where we know
|
||||
* the prev/next entries already!
|
||||
*/
|
||||
static inline void __list_add(struct list_head *new,
|
||||
struct list_head *prev,
|
||||
struct list_head *next)
|
||||
{
|
||||
next->prev = new;
|
||||
new->next = next;
|
||||
new->prev = prev;
|
||||
prev->next = new;
|
||||
}
|
||||
|
||||
/**
|
||||
* list_add - add a new entry
|
||||
* @new: new entry to be added
|
||||
* @head: list head to add it after
|
||||
*
|
||||
* Insert a new entry after the specified head.
|
||||
* This is good for implementing stacks.
|
||||
*/
|
||||
static inline void list_add(struct list_head *new, struct list_head *head)
|
||||
{
|
||||
__list_add(new, head, head->next);
|
||||
}
|
||||
|
||||
/**
|
||||
* list_add_tail - add a new entry
|
||||
* @new: new entry to be added
|
||||
* @head: list head to add it before
|
||||
*
|
||||
* Insert a new entry before the specified head.
|
||||
* This is useful for implementing queues.
|
||||
*/
|
||||
static inline void list_add_tail(struct list_head *new, struct list_head *head)
|
||||
{
|
||||
__list_add(new, head->prev, head);
|
||||
}
|
||||
|
||||
/*
|
||||
* Delete a list entry by making the prev/next entries
|
||||
* point to each other.
|
||||
*
|
||||
* This is only for internal list manipulation where we know
|
||||
* the prev/next entries already!
|
||||
*/
|
||||
static inline void __list_del(struct list_head *prev, struct list_head *next)
|
||||
{
|
||||
next->prev = prev;
|
||||
prev->next = next;
|
||||
}
|
||||
|
||||
/**
|
||||
* list_del - deletes entry from list.
|
||||
* @entry: the element to delete from the list.
|
||||
* Note: list_empty on entry does not return true after this, the entry is in an undefined state.
|
||||
*/
|
||||
static inline void list_del(struct list_head *entry)
|
||||
{
|
||||
__list_del(entry->prev, entry->next);
|
||||
entry->next = (void *) 0;
|
||||
entry->prev = (void *) 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* list_del_init - deletes entry from list and reinitialize it.
|
||||
* @entry: the element to delete from the list.
|
||||
*/
|
||||
static inline void list_del_init(struct list_head *entry)
|
||||
{
|
||||
__list_del(entry->prev, entry->next);
|
||||
INIT_LIST_HEAD(entry);
|
||||
}
|
||||
|
||||
/**
|
||||
* list_move - delete from one list and add as another's head
|
||||
* @list: the entry to move
|
||||
* @head: the head that will precede our entry
|
||||
*/
|
||||
static inline void list_move(struct list_head *list, struct list_head *head)
|
||||
{
|
||||
__list_del(list->prev, list->next);
|
||||
list_add(list, head);
|
||||
}
|
||||
|
||||
/**
|
||||
* list_move_tail - delete from one list and add as another's tail
|
||||
* @list: the entry to move
|
||||
* @head: the head that will follow our entry
|
||||
*/
|
||||
static inline void list_move_tail(struct list_head *list,
|
||||
struct list_head *head)
|
||||
{
|
||||
__list_del(list->prev, list->next);
|
||||
list_add_tail(list, head);
|
||||
}
|
||||
|
||||
/**
|
||||
* list_empty - tests whether a list is empty
|
||||
* @head: the list to test.
|
||||
*/
|
||||
static inline int list_empty(struct list_head *head)
|
||||
{
|
||||
return head->next == head;
|
||||
}
|
||||
|
||||
static inline void __list_splice(struct list_head *list,
|
||||
struct list_head *head)
|
||||
{
|
||||
struct list_head *first = list->next;
|
||||
struct list_head *last = list->prev;
|
||||
struct list_head *at = head->next;
|
||||
|
||||
first->prev = head;
|
||||
head->next = first;
|
||||
|
||||
last->next = at;
|
||||
at->prev = last;
|
||||
}
|
||||
|
||||
/**
|
||||
* list_splice - join two lists
|
||||
* @list: the new list to add.
|
||||
* @head: the place to add it in the first list.
|
||||
*/
|
||||
static inline void list_splice(struct list_head *list, struct list_head *head)
|
||||
{
|
||||
if (!list_empty(list))
|
||||
__list_splice(list, head);
|
||||
}
|
||||
|
||||
/**
|
||||
* list_splice_init - join two lists and reinitialise the emptied list.
|
||||
* @list: the new list to add.
|
||||
* @head: the place to add it in the first list.
|
||||
*
|
||||
* The list at @list is reinitialised
|
||||
*/
|
||||
static inline void list_splice_init(struct list_head *list,
|
||||
struct list_head *head)
|
||||
{
|
||||
if (!list_empty(list)) {
|
||||
__list_splice(list, head);
|
||||
INIT_LIST_HEAD(list);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* list_entry - get the struct for this entry
|
||||
* @ptr: the &struct list_head pointer.
|
||||
* @type: the type of the struct this is embedded in.
|
||||
* @member: the name of the list_struct within the struct.
|
||||
*/
|
||||
#define list_entry(ptr, type, member) \
|
||||
((type *)((char *)(ptr)-(unsigned long)(&((type *)0)->member)))
|
||||
|
||||
/**
|
||||
* list_for_each - iterate over a list
|
||||
* @pos: the &struct list_head to use as a loop counter.
|
||||
* @head: the head for your list.
|
||||
*/
|
||||
#define list_for_each(pos, head) \
|
||||
for (pos = (head)->next; pos != (head); \
|
||||
pos = pos->next)
|
||||
/**
|
||||
* list_for_each_prev - iterate over a list backwards
|
||||
* @pos: the &struct list_head to use as a loop counter.
|
||||
* @head: the head for your list.
|
||||
*/
|
||||
#define list_for_each_prev(pos, head) \
|
||||
for (pos = (head)->prev; pos != (head); \
|
||||
pos = pos->prev)
|
||||
|
||||
/**
|
||||
* list_for_each_safe - iterate over a list safe against removal of list entry
|
||||
* @pos: the &struct list_head to use as a loop counter.
|
||||
* @n: another &struct list_head to use as temporary storage
|
||||
* @head: the head for your list.
|
||||
*/
|
||||
#define list_for_each_safe(pos, n, head) \
|
||||
for (pos = (head)->next, n = pos->next; pos != (head); \
|
||||
pos = n, n = pos->next)
|
||||
|
||||
/**
|
||||
* list_for_each_entry - iterate over list of given type
|
||||
* @pos: the type * to use as a loop counter.
|
||||
* @head: the head for your list.
|
||||
* @member: the name of the list_struct within the struct.
|
||||
*/
|
||||
#define list_for_each_entry(pos, head, member) \
|
||||
for (pos = list_entry((head)->next, typeof(*pos), member); \
|
||||
&pos->member != (head); \
|
||||
pos = list_entry(pos->member.next, typeof(*pos), member))
|
||||
|
||||
/**
|
||||
* list_for_each_entry_safe - iterate over list of given type safe against removal of list entry
|
||||
* @pos: the type * to use as a loop counter.
|
||||
* @n: another type * to use as temporary storage
|
||||
* @head: the head for your list.
|
||||
* @member: the name of the list_struct within the struct.
|
||||
*/
|
||||
#define list_for_each_entry_safe(pos, n, head, member) \
|
||||
for (pos = list_entry((head)->next, typeof(*pos), member), \
|
||||
n = list_entry(pos->member.next, typeof(*pos), member); \
|
||||
&pos->member != (head); \
|
||||
pos = n, n = list_entry(n->member.next, typeof(*n), member))
|
||||
|
||||
/**
|
||||
* list_for_each_entry_continue - iterate over list of given type
|
||||
* continuing after existing point
|
||||
* @pos: the type * to use as a loop counter.
|
||||
* @head: the head for your list.
|
||||
* @member: the name of the list_struct within the struct.
|
||||
*/
|
||||
#define list_for_each_entry_continue(pos, head, member) \
|
||||
for (pos = list_entry(pos->member.next, typeof(*pos), member), \
|
||||
prefetch(pos->member.next); \
|
||||
&pos->member != (head); \
|
||||
pos = list_entry(pos->member.next, typeof(*pos), member), \
|
||||
prefetch(pos->member.next))
|
||||
|
||||
#endif
|
||||
509
options.c
509
options.c
@@ -1,509 +0,0 @@
|
||||
/* XMRig
|
||||
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com>
|
||||
* Copyright 2012-2014 pooler <pooler@litecoinpool.org>
|
||||
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
|
||||
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
|
||||
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
|
||||
* Copyright 2016-2017 XMRig <support@xmrig.com>
|
||||
*
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <jansson.h>
|
||||
#include <curl/curl.h>
|
||||
#include <getopt.h>
|
||||
|
||||
#include "version.h"
|
||||
#include "utils/applog.h"
|
||||
#include "options.h"
|
||||
#include "cpu.h"
|
||||
#include "donate.h"
|
||||
#include "algo/cryptonight/cryptonight.h"
|
||||
|
||||
|
||||
int64_t opt_affinity = -1L;
|
||||
int opt_n_threads = 0;
|
||||
int opt_algo_variant = 0;
|
||||
int opt_retries = 5;
|
||||
int opt_retry_pause = 5;
|
||||
int opt_donate_level = DONATE_LEVEL;
|
||||
int opt_max_cpu_usage = 75;
|
||||
bool opt_colors = true;
|
||||
bool opt_keepalive = false;
|
||||
bool opt_background = false;
|
||||
bool opt_double_hash = false;
|
||||
bool opt_safe = false;
|
||||
char *opt_url = NULL;
|
||||
char *opt_backup_url = NULL;
|
||||
char *opt_userpass = NULL;
|
||||
char *opt_user = NULL;
|
||||
char *opt_pass = NULL;
|
||||
|
||||
enum mining_algo opt_algo = ALGO_CRYPTONIGHT;
|
||||
|
||||
|
||||
static char const usage[] = "\
|
||||
Usage: " APP_ID " [OPTIONS]\n\
|
||||
Options:\n\
|
||||
-a, --algo=ALGO cryptonight (default) or cryptonight-lite\n\
|
||||
-o, --url=URL URL of mining server\n\
|
||||
-b, --backup-url=URL URL of backup mining server\n\
|
||||
-O, --userpass=U:P username:password pair for mining server\n\
|
||||
-u, --user=USERNAME username for mining server\n\
|
||||
-p, --pass=PASSWORD password for mining server\n\
|
||||
-t, --threads=N number of miner threads\n\
|
||||
-v, --av=N algorithm variation, 0 auto select\n\
|
||||
-k, --keepalive send keepalived for prevent timeout (need pool support)\n\
|
||||
-r, --retries=N number of times to retry before switch to backup server (default: 5)\n\
|
||||
-R, --retry-pause=N time to pause between retries (default: 5)\n\
|
||||
--cpu-affinity set process affinity to CPU core(s), mask 0x3 for cores 0 and 1\n\
|
||||
--no-color disable colored output\n\
|
||||
--donate-level=N donate level, default 5%% (5 minutes in 100 minutes)\n\
|
||||
-B, --background run the miner in the background\n\
|
||||
-c, --config=FILE load a JSON-format configuration file\n\
|
||||
--max-cpu-usage=N maximum CPU usage for automatic threads mode (default 75)\n\
|
||||
--safe safe adjust threads and av settings for current CPU\n\
|
||||
-h, --help display this help and exit\n\
|
||||
-V, --version output version information and exit\n\
|
||||
";
|
||||
|
||||
|
||||
static char const short_options[] = "a:c:khBp:Px:r:R:s:t:T:o:u:O:v:Vb:";
|
||||
|
||||
|
||||
static struct option const options[] = {
|
||||
{ "algo", 1, NULL, 'a' },
|
||||
{ "av", 1, NULL, 'v' },
|
||||
{ "background", 0, NULL, 'B' },
|
||||
{ "backup-url", 1, NULL, 'b' },
|
||||
{ "config", 1, NULL, 'c' },
|
||||
{ "cpu-affinity", 1, NULL, 1020 },
|
||||
{ "donate-level", 1, NULL, 1003 },
|
||||
{ "help", 0, NULL, 'h' },
|
||||
{ "keepalive", 0, NULL ,'k' },
|
||||
{ "max-cpu-usage", 1, NULL, 1004 },
|
||||
{ "no-color", 0, NULL, 1002 },
|
||||
{ "pass", 1, NULL, 'p' },
|
||||
{ "retries", 1, NULL, 'r' },
|
||||
{ "retry-pause", 1, NULL, 'R' },
|
||||
{ "safe", 0, NULL, 1005 },
|
||||
{ "threads", 1, NULL, 't' },
|
||||
{ "url", 1, NULL, 'o' },
|
||||
{ "user", 1, NULL, 'u' },
|
||||
{ "userpass", 1, NULL, 'O' },
|
||||
{ "version", 0, NULL, 'V' },
|
||||
{ 0, 0, 0, 0 }
|
||||
};
|
||||
|
||||
|
||||
static const char *algo_names[] = {
|
||||
[ALGO_CRYPTONIGHT] = "cryptonight",
|
||||
# ifndef XMRIG_NO_AEON
|
||||
[ALGO_CRYPTONIGHT_LITE] = "cryptonight-lite"
|
||||
# endif
|
||||
};
|
||||
|
||||
|
||||
#ifndef XMRIG_NO_AEON
|
||||
static int get_cryptonight_lite_variant(int variant) {
|
||||
if (variant <= AEON_AV0_AUTO || variant >= AEON_AV_MAX) {
|
||||
return (cpu_info.flags & CPU_FLAG_AES) ? AEON_AV2_AESNI_DOUBLE : AEON_AV4_SOFT_AES_DOUBLE;
|
||||
}
|
||||
|
||||
if (opt_safe && !(cpu_info.flags & CPU_FLAG_AES) && variant <= AEON_AV2_AESNI_DOUBLE) {
|
||||
return variant + 2;
|
||||
}
|
||||
|
||||
return variant;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
static int get_algo_variant(int algo, int variant) {
|
||||
# ifndef XMRIG_NO_AEON
|
||||
if (algo == ALGO_CRYPTONIGHT_LITE) {
|
||||
return get_cryptonight_lite_variant(variant);
|
||||
}
|
||||
# endif
|
||||
|
||||
if (variant <= XMR_AV0_AUTO || variant >= XMR_AV_MAX) {
|
||||
return (cpu_info.flags & CPU_FLAG_AES) ? XMR_AV1_AESNI : XMR_AV3_SOFT_AES;
|
||||
}
|
||||
|
||||
if (opt_safe && !(cpu_info.flags & CPU_FLAG_AES) && variant <= XMR_AV2_AESNI_DOUBLE) {
|
||||
return variant + 2;
|
||||
}
|
||||
|
||||
return variant;
|
||||
}
|
||||
|
||||
|
||||
static void parse_config(json_t *config, char *ref);
|
||||
static char *parse_url(const char *arg);
|
||||
|
||||
|
||||
static void parse_arg(int key, char *arg) {
|
||||
char *p;
|
||||
int v;
|
||||
uint64_t ul;
|
||||
|
||||
switch (key)
|
||||
{
|
||||
case 'a':
|
||||
for (int i = 0; i < ARRAY_SIZE(algo_names); i++) {
|
||||
if (algo_names[i] && !strcmp(arg, algo_names[i])) {
|
||||
opt_algo = i;
|
||||
break;
|
||||
}
|
||||
|
||||
# ifndef XMRIG_NO_AEON
|
||||
if (i == ARRAY_SIZE(algo_names) && !strcmp(arg, "cryptonight-light")) {
|
||||
opt_algo = i = ALGO_CRYPTONIGHT_LITE;
|
||||
}
|
||||
# endif
|
||||
|
||||
if (i == ARRAY_SIZE(algo_names)) {
|
||||
show_usage_and_exit(1);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case 'O': /* --userpass */
|
||||
p = strchr(arg, ':');
|
||||
if (!p) {
|
||||
show_usage_and_exit(1);
|
||||
}
|
||||
|
||||
free(opt_userpass);
|
||||
opt_userpass = strdup(arg);
|
||||
free(opt_user);
|
||||
opt_user = calloc(p - arg + 1, 1);
|
||||
strncpy(opt_user, arg, p - arg);
|
||||
free(opt_pass);
|
||||
opt_pass = strdup(p + 1);
|
||||
break;
|
||||
|
||||
case 'o': /* --url */
|
||||
p = parse_url(arg);
|
||||
if (p) {
|
||||
free(opt_url);
|
||||
opt_url = p;
|
||||
}
|
||||
break;
|
||||
|
||||
case 'b': /* --backup-url */
|
||||
p = parse_url(arg);
|
||||
if (p) {
|
||||
free(opt_backup_url);
|
||||
opt_backup_url = p;
|
||||
}
|
||||
break;
|
||||
|
||||
case 'u': /* --user */
|
||||
free(opt_user);
|
||||
opt_user = strdup(arg);
|
||||
break;
|
||||
|
||||
case 'p': /* --pass */
|
||||
free(opt_pass);
|
||||
opt_pass = strdup(arg);
|
||||
break;
|
||||
|
||||
case 'r': /* --retries */
|
||||
v = atoi(arg);
|
||||
if (v < 1 || v > 1000) {
|
||||
show_usage_and_exit(1);
|
||||
}
|
||||
|
||||
opt_retries = v;
|
||||
break;
|
||||
|
||||
case 'R': /* --retry-pause */
|
||||
v = atoi(arg);
|
||||
if (v < 1 || v > 3600) {
|
||||
show_usage_and_exit(1);
|
||||
}
|
||||
|
||||
opt_retry_pause = v;
|
||||
break;
|
||||
|
||||
case 't': /* --threads */
|
||||
v = atoi(arg);
|
||||
if (v < 1 || v > 1024) {
|
||||
show_usage_and_exit(1);
|
||||
}
|
||||
|
||||
opt_n_threads = v;
|
||||
break;
|
||||
|
||||
case 1004: /* --max-cpu-usage */
|
||||
v = atoi(arg);
|
||||
if (v < 1 || v > 100) {
|
||||
show_usage_and_exit(1);
|
||||
}
|
||||
|
||||
opt_max_cpu_usage = v;
|
||||
break;
|
||||
|
||||
case 1005: /* --safe */
|
||||
opt_safe = true;
|
||||
break;
|
||||
|
||||
case 'k': /* --keepalive */
|
||||
opt_keepalive = true;
|
||||
break;
|
||||
|
||||
case 'V': /* --version */
|
||||
show_version_and_exit();
|
||||
break;
|
||||
|
||||
case 'h': /* --help */
|
||||
show_usage_and_exit(0);
|
||||
break;
|
||||
|
||||
case 'c': { /* --config */
|
||||
json_error_t err;
|
||||
json_t *config = json_load_file(arg, 0, &err);
|
||||
|
||||
if (!json_is_object(config)) {
|
||||
if (err.line < 0) {
|
||||
applog(LOG_ERR, "%s\n", err.text);
|
||||
}
|
||||
else {
|
||||
applog(LOG_ERR, "%s:%d: %s\n", arg, err.line, err.text);
|
||||
}
|
||||
} else {
|
||||
parse_config(config, arg);
|
||||
json_decref(config);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case 'B': /* --background */
|
||||
opt_background = true;
|
||||
opt_colors = false;
|
||||
break;
|
||||
|
||||
case 'v': /* --av */
|
||||
v = atoi(arg);
|
||||
if (v < 0 || v > 1000) {
|
||||
show_usage_and_exit(1);
|
||||
}
|
||||
|
||||
opt_algo_variant = v;
|
||||
break;
|
||||
|
||||
case 1020: /* --cpu-affinity */
|
||||
p = strstr(arg, "0x");
|
||||
ul = p ? strtoul(p, NULL, 16) : atol(arg);
|
||||
if (ul > (1UL << cpu_info.total_logical_cpus) -1) {
|
||||
ul = -1;
|
||||
}
|
||||
|
||||
opt_affinity = ul;
|
||||
break;
|
||||
|
||||
case 1002: /* --no-color */
|
||||
opt_colors = false;
|
||||
break;
|
||||
|
||||
case 1003: /* --donate-level */
|
||||
v = atoi(arg);
|
||||
if (v < 1 || v > 99) {
|
||||
show_usage_and_exit(1);
|
||||
}
|
||||
|
||||
opt_donate_level = v;
|
||||
break;
|
||||
|
||||
default:
|
||||
show_usage_and_exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void parse_config(json_t *config, char *ref)
|
||||
{
|
||||
int i;
|
||||
char buf[16];
|
||||
json_t *val;
|
||||
|
||||
applog(LOG_ERR, ref);
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(options); i++) {
|
||||
if (!options[i].name) {
|
||||
break;
|
||||
}
|
||||
|
||||
val = json_object_get(config, options[i].name);
|
||||
if (!val) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (options[i].has_arg && json_is_string(val)) {
|
||||
char *s = strdup(json_string_value(val));
|
||||
if (!s) {
|
||||
break;
|
||||
}
|
||||
|
||||
parse_arg(options[i].val, s);
|
||||
free(s);
|
||||
}
|
||||
else if (options[i].has_arg && json_is_integer(val)) {
|
||||
sprintf(buf, "%d", (int) json_integer_value(val));
|
||||
parse_arg(options[i].val, buf);
|
||||
}
|
||||
else if (options[i].has_arg && json_is_real(val)) {
|
||||
sprintf(buf, "%f", json_real_value(val));
|
||||
parse_arg(options[i].val, buf);
|
||||
}
|
||||
else if (!options[i].has_arg) {
|
||||
if (json_is_true(val)) {
|
||||
parse_arg(options[i].val, "");
|
||||
}
|
||||
}
|
||||
else {
|
||||
applog(LOG_ERR, "JSON option %s invalid", options[i].name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static char *parse_url(const char *arg)
|
||||
{
|
||||
char *p = strstr(arg, "://");
|
||||
if (p) {
|
||||
if (strncasecmp(arg, "stratum+tcp://", 14)) {
|
||||
show_usage_and_exit(1);
|
||||
}
|
||||
|
||||
return strdup(arg);
|
||||
}
|
||||
|
||||
|
||||
if (!strlen(arg) || *arg == '/') {
|
||||
show_usage_and_exit(1);
|
||||
}
|
||||
|
||||
char *dest = malloc(strlen(arg) + 16);
|
||||
sprintf(dest, "stratum+tcp://%s", arg);
|
||||
|
||||
return dest;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Parse application command line via getopt.
|
||||
*/
|
||||
void parse_cmdline(int argc, char *argv[]) {
|
||||
opt_user = strdup("x");
|
||||
opt_pass = strdup("x");
|
||||
|
||||
int key;
|
||||
|
||||
while (1) {
|
||||
key = getopt_long(argc, argv, short_options, options, NULL);
|
||||
if (key < 0) {
|
||||
break;
|
||||
}
|
||||
|
||||
parse_arg(key, optarg);
|
||||
}
|
||||
|
||||
if (optind < argc) {
|
||||
fprintf(stderr, "%s: unsupported non-option argument '%s'\n", argv[0], argv[optind]);
|
||||
show_usage_and_exit(1);
|
||||
}
|
||||
|
||||
if (!opt_url) {
|
||||
applog_notime(LOG_ERR, "No pool URL supplied. Exiting.\n", argv[0]);
|
||||
proper_exit(1);
|
||||
}
|
||||
|
||||
if (!opt_userpass) {
|
||||
opt_userpass = malloc(strlen(opt_user) + strlen(opt_pass) + 2);
|
||||
if (!opt_userpass) {
|
||||
proper_exit(1);
|
||||
}
|
||||
|
||||
sprintf(opt_userpass, "%s:%s", opt_user, opt_pass);
|
||||
}
|
||||
|
||||
opt_algo_variant = get_algo_variant(opt_algo, opt_algo_variant);
|
||||
|
||||
if (!cryptonight_init(opt_algo_variant)) {
|
||||
applog(LOG_ERR, "Cryptonight hash self-test failed. This might be caused by bad compiler optimizations.");
|
||||
proper_exit(1);
|
||||
}
|
||||
|
||||
if (!opt_n_threads) {
|
||||
opt_n_threads = get_optimal_threads_count(opt_algo, opt_double_hash, opt_max_cpu_usage);
|
||||
}
|
||||
|
||||
if (opt_safe) {
|
||||
const int count = get_optimal_threads_count(opt_algo, opt_double_hash, opt_max_cpu_usage);
|
||||
if (opt_n_threads > count) {
|
||||
opt_n_threads = count;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void show_usage_and_exit(int status) {
|
||||
if (status) {
|
||||
fprintf(stderr, "Try \"" APP_ID "\" --help' for more information.\n");
|
||||
}
|
||||
else {
|
||||
printf(usage);
|
||||
}
|
||||
|
||||
proper_exit(status);
|
||||
}
|
||||
|
||||
|
||||
void show_version_and_exit(void) {
|
||||
printf(APP_NAME " " APP_VERSION "\n built on " __DATE__
|
||||
|
||||
#ifdef __GNUC__
|
||||
" with GCC");
|
||||
printf(" %d.%d.%d", __GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__);
|
||||
#endif
|
||||
|
||||
printf("\n features:"
|
||||
#ifdef __i386__
|
||||
" i386"
|
||||
#endif
|
||||
#ifdef __x86_64__
|
||||
" x86_64"
|
||||
#endif
|
||||
#ifdef __AES__
|
||||
" AES-NI"
|
||||
#endif
|
||||
"\n");
|
||||
|
||||
printf("\n%s\n", curl_version());
|
||||
#ifdef JANSSON_VERSION
|
||||
printf("libjansson/%s\n", JANSSON_VERSION);
|
||||
#endif
|
||||
proper_exit(0);
|
||||
}
|
||||
|
||||
|
||||
const char* get_current_algo_name(void) {
|
||||
return algo_names[opt_algo];
|
||||
}
|
||||
90
options.h
90
options.h
@@ -1,90 +0,0 @@
|
||||
/* XMRig
|
||||
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com>
|
||||
* Copyright 2012-2014 pooler <pooler@litecoinpool.org>
|
||||
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
|
||||
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
|
||||
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
|
||||
* Copyright 2016-2017 XMRig <support@xmrig.com>
|
||||
*
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef __OPTIONS_H__
|
||||
#define __OPTIONS_H__
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#ifndef ARRAY_SIZE
|
||||
# define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))
|
||||
#endif
|
||||
|
||||
|
||||
enum mining_algo {
|
||||
ALGO_CRYPTONIGHT, /* CryptoNight (Monero) */
|
||||
ALGO_CRYPTONIGHT_LITE, /* CryptoNight-Lite (AEON) */
|
||||
};
|
||||
|
||||
|
||||
enum xmr_algo_variant {
|
||||
XMR_AV0_AUTO,
|
||||
XMR_AV1_AESNI,
|
||||
XMR_AV2_AESNI_DOUBLE,
|
||||
XMR_AV3_SOFT_AES,
|
||||
XMR_AV4_SOFT_AES_DOUBLE,
|
||||
XMR_AV_MAX
|
||||
};
|
||||
|
||||
|
||||
#ifndef XMRIG_NO_AEON
|
||||
enum aeon_algo_variant {
|
||||
AEON_AV0_AUTO,
|
||||
AEON_AV1_AESNI,
|
||||
AEON_AV2_AESNI_DOUBLE,
|
||||
AEON_AV3_SOFT_AES,
|
||||
AEON_AV4_SOFT_AES_DOUBLE,
|
||||
AEON_AV_MAX
|
||||
};
|
||||
#endif
|
||||
|
||||
|
||||
extern bool opt_colors;
|
||||
extern bool opt_keepalive;
|
||||
extern bool opt_background;
|
||||
extern bool opt_double_hash;
|
||||
extern bool opt_safe;
|
||||
extern char *opt_url;
|
||||
extern char *opt_backup_url;
|
||||
extern char *opt_userpass;
|
||||
extern char *opt_user;
|
||||
extern char *opt_pass;
|
||||
extern int opt_n_threads;
|
||||
extern int opt_algo_variant;
|
||||
extern int opt_retry_pause;
|
||||
extern int opt_retries;
|
||||
extern int opt_donate_level;
|
||||
extern int opt_max_cpu_usage;
|
||||
extern int64_t opt_affinity;
|
||||
extern enum mining_algo opt_algo;
|
||||
|
||||
void parse_cmdline(int argc, char *argv[]);
|
||||
void show_usage_and_exit(int status);
|
||||
void show_version_and_exit(void);
|
||||
const char* get_current_algo_name(void);
|
||||
|
||||
extern void proper_exit(int reason);
|
||||
|
||||
|
||||
#endif /* __OPTIONS_H__ */
|
||||
|
Before Width: | Height: | Size: 15 KiB After Width: | Height: | Size: 15 KiB |
@@ -1,5 +1,5 @@
|
||||
#include <windows.h>
|
||||
#include "../version.h"
|
||||
#include "../src/version.h"
|
||||
|
||||
IDI_ICON1 ICON DISCARDABLE "app.ico"
|
||||
|
||||
33
src/3rdparty/align.h
vendored
Normal file
33
src/3rdparty/align.h
vendored
Normal file
@@ -0,0 +1,33 @@
|
||||
/* XMRig
|
||||
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com>
|
||||
* Copyright 2012-2014 pooler <pooler@litecoinpool.org>
|
||||
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
|
||||
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
|
||||
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
|
||||
* Copyright 2016-2017 XMRig <support@xmrig.com>
|
||||
*
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef __ALIGN_H__
|
||||
#define __ALIGN_H__
|
||||
|
||||
#ifdef _MSC_VER
|
||||
# define VAR_ALIGN(x, decl) __declspec(align(x)) decl
|
||||
#else
|
||||
# define VAR_ALIGN(x, decl) decl __attribute__ ((aligned(x)))
|
||||
#endif
|
||||
|
||||
#endif /* __ALIGN_H__ */
|
||||
653
src/3rdparty/getopt/getopt.h
vendored
Normal file
653
src/3rdparty/getopt/getopt.h
vendored
Normal file
@@ -0,0 +1,653 @@
|
||||
#ifndef __GETOPT_H__
|
||||
/**
|
||||
* DISCLAIMER
|
||||
* This file is part of the mingw-w64 runtime package.
|
||||
*
|
||||
* The mingw-w64 runtime package and its code is distributed in the hope that it
|
||||
* will be useful but WITHOUT ANY WARRANTY. ALL WARRANTIES, EXPRESSED OR
|
||||
* IMPLIED ARE HEREBY DISCLAIMED. This includes but is not limited to
|
||||
* warranties of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
*/
|
||||
/*
|
||||
* Copyright (c) 2002 Todd C. Miller <Todd.Miller@courtesan.com>
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*
|
||||
* Sponsored in part by the Defense Advanced Research Projects
|
||||
* Agency (DARPA) and Air Force Research Laboratory, Air Force
|
||||
* Materiel Command, USAF, under agreement number F39502-99-1-0512.
|
||||
*/
|
||||
/*-
|
||||
* Copyright (c) 2000 The NetBSD Foundation, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to The NetBSD Foundation
|
||||
* by Dieter Baron and Thomas Klausner.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
|
||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
|
||||
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#pragma warning(disable:4996)
|
||||
|
||||
#define __GETOPT_H__
|
||||
|
||||
/* All the headers include this file. */
|
||||
#include <crtdefs.h>
|
||||
#include <errno.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
#include <windows.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define REPLACE_GETOPT /* use this getopt as the system getopt(3) */
|
||||
|
||||
#ifdef REPLACE_GETOPT
|
||||
int opterr = 1; /* if error message should be printed */
|
||||
int optind = 1; /* index into parent argv vector */
|
||||
int optopt = '?'; /* character checked for validity */
|
||||
#undef optreset /* see getopt.h */
|
||||
#define optreset __mingw_optreset
|
||||
int optreset; /* reset getopt */
|
||||
char *optarg; /* argument associated with option */
|
||||
#endif
|
||||
|
||||
//extern int optind; /* index of first non-option in argv */
|
||||
//extern int optopt; /* single option character, as parsed */
|
||||
//extern int opterr; /* flag to enable built-in diagnostics... */
|
||||
// /* (user may set to zero, to suppress) */
|
||||
//
|
||||
//extern char *optarg; /* pointer to argument of current option */
|
||||
|
||||
#define PRINT_ERROR ((opterr) && (*options != ':'))
|
||||
|
||||
#define FLAG_PERMUTE 0x01 /* permute non-options to the end of argv */
|
||||
#define FLAG_ALLARGS 0x02 /* treat non-options as args to option "-1" */
|
||||
#define FLAG_LONGONLY 0x04 /* operate as getopt_long_only */
|
||||
|
||||
/* return values */
|
||||
#define BADCH (int)'?'
|
||||
#define BADARG ((*options == ':') ? (int)':' : (int)'?')
|
||||
#define INORDER (int)1
|
||||
|
||||
#ifndef __CYGWIN__
|
||||
#define __progname __argv[0]
|
||||
#else
|
||||
extern char __declspec(dllimport) *__progname;
|
||||
#endif
|
||||
|
||||
#ifdef __CYGWIN__
|
||||
static char EMSG[] = "";
|
||||
#else
|
||||
#define EMSG ""
|
||||
#endif
|
||||
|
||||
static int getopt_internal(int, char * const *, const char *,
|
||||
const struct option *, int *, int);
|
||||
static int parse_long_options(char * const *, const char *,
|
||||
const struct option *, int *, int);
|
||||
static int gcd(int, int);
|
||||
static void permute_args(int, int, int, char * const *);
|
||||
|
||||
static char *place = EMSG; /* option letter processing */
|
||||
|
||||
/* XXX: set optreset to 1 rather than these two */
|
||||
static int nonopt_start = -1; /* first non option argument (for permute) */
|
||||
static int nonopt_end = -1; /* first option after non options (for permute) */
|
||||
|
||||
/* Error messages */
|
||||
static const char recargchar[] = "option requires an argument -- %c";
|
||||
static const char recargstring[] = "option requires an argument -- %s";
|
||||
static const char ambig[] = "ambiguous option -- %.*s";
|
||||
static const char noarg[] = "option doesn't take an argument -- %.*s";
|
||||
static const char illoptchar[] = "unknown option -- %c";
|
||||
static const char illoptstring[] = "unknown option -- %s";
|
||||
|
||||
static void
|
||||
_vwarnx(const char *fmt,va_list ap)
|
||||
{
|
||||
(void)fprintf(stderr,"%s: ",__progname);
|
||||
if (fmt != NULL)
|
||||
(void)vfprintf(stderr,fmt,ap);
|
||||
(void)fprintf(stderr,"\n");
|
||||
}
|
||||
|
||||
static void
|
||||
warnx(const char *fmt,...)
|
||||
{
|
||||
va_list ap;
|
||||
va_start(ap,fmt);
|
||||
_vwarnx(fmt,ap);
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
/*
|
||||
* Compute the greatest common divisor of a and b.
|
||||
*/
|
||||
static int
|
||||
gcd(int a, int b)
|
||||
{
|
||||
int c;
|
||||
|
||||
c = a % b;
|
||||
while (c != 0) {
|
||||
a = b;
|
||||
b = c;
|
||||
c = a % b;
|
||||
}
|
||||
|
||||
return (b);
|
||||
}
|
||||
|
||||
/*
|
||||
* Exchange the block from nonopt_start to nonopt_end with the block
|
||||
* from nonopt_end to opt_end (keeping the same order of arguments
|
||||
* in each block).
|
||||
*/
|
||||
static void
|
||||
permute_args(int panonopt_start, int panonopt_end, int opt_end,
|
||||
char * const *nargv)
|
||||
{
|
||||
int cstart, cyclelen, i, j, ncycle, nnonopts, nopts, pos;
|
||||
char *swap;
|
||||
|
||||
/*
|
||||
* compute lengths of blocks and number and size of cycles
|
||||
*/
|
||||
nnonopts = panonopt_end - panonopt_start;
|
||||
nopts = opt_end - panonopt_end;
|
||||
ncycle = gcd(nnonopts, nopts);
|
||||
cyclelen = (opt_end - panonopt_start) / ncycle;
|
||||
|
||||
for (i = 0; i < ncycle; i++) {
|
||||
cstart = panonopt_end+i;
|
||||
pos = cstart;
|
||||
for (j = 0; j < cyclelen; j++) {
|
||||
if (pos >= panonopt_end)
|
||||
pos -= nnonopts;
|
||||
else
|
||||
pos += nopts;
|
||||
swap = nargv[pos];
|
||||
/* LINTED const cast */
|
||||
((char **) nargv)[pos] = nargv[cstart];
|
||||
/* LINTED const cast */
|
||||
((char **)nargv)[cstart] = swap;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef REPLACE_GETOPT
|
||||
/*
|
||||
* getopt --
|
||||
* Parse argc/argv argument vector.
|
||||
*
|
||||
* [eventually this will replace the BSD getopt]
|
||||
*/
|
||||
int
|
||||
getopt(int nargc, char * const *nargv, const char *options)
|
||||
{
|
||||
|
||||
/*
|
||||
* We don't pass FLAG_PERMUTE to getopt_internal() since
|
||||
* the BSD getopt(3) (unlike GNU) has never done this.
|
||||
*
|
||||
* Furthermore, since many privileged programs call getopt()
|
||||
* before dropping privileges it makes sense to keep things
|
||||
* as simple (and bug-free) as possible.
|
||||
*/
|
||||
return (getopt_internal(nargc, nargv, options, NULL, NULL, 0));
|
||||
}
|
||||
#endif /* REPLACE_GETOPT */
|
||||
|
||||
//extern int getopt(int nargc, char * const *nargv, const char *options);
|
||||
|
||||
#ifdef _BSD_SOURCE
|
||||
/*
|
||||
* BSD adds the non-standard `optreset' feature, for reinitialisation
|
||||
* of `getopt' parsing. We support this feature, for applications which
|
||||
* proclaim their BSD heritage, before including this header; however,
|
||||
* to maintain portability, developers are advised to avoid it.
|
||||
*/
|
||||
# define optreset __mingw_optreset
|
||||
extern int optreset;
|
||||
#endif
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
/*
|
||||
* POSIX requires the `getopt' API to be specified in `unistd.h';
|
||||
* thus, `unistd.h' includes this header. However, we do not want
|
||||
* to expose the `getopt_long' or `getopt_long_only' APIs, when
|
||||
* included in this manner. Thus, close the standard __GETOPT_H__
|
||||
* declarations block, and open an additional __GETOPT_LONG_H__
|
||||
* specific block, only when *not* __UNISTD_H_SOURCED__, in which
|
||||
* to declare the extended API.
|
||||
*/
|
||||
#endif /* !defined(__GETOPT_H__) */
|
||||
|
||||
#if !defined(__UNISTD_H_SOURCED__) && !defined(__GETOPT_LONG_H__)
|
||||
#define __GETOPT_LONG_H__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
struct option /* specification for a long form option... */
|
||||
{
|
||||
const char *name; /* option name, without leading hyphens */
|
||||
int has_arg; /* does it take an argument? */
|
||||
int *flag; /* where to save its status, or NULL */
|
||||
int val; /* its associated status value */
|
||||
};
|
||||
|
||||
enum /* permitted values for its `has_arg' field... */
|
||||
{
|
||||
no_argument = 0, /* option never takes an argument */
|
||||
required_argument, /* option always requires an argument */
|
||||
optional_argument /* option may take an argument */
|
||||
};
|
||||
|
||||
/*
|
||||
* parse_long_options --
|
||||
* Parse long options in argc/argv argument vector.
|
||||
* Returns -1 if short_too is set and the option does not match long_options.
|
||||
*/
|
||||
static int
|
||||
parse_long_options(char * const *nargv, const char *options,
|
||||
const struct option *long_options, int *idx, int short_too)
|
||||
{
|
||||
char *current_argv, *has_equal;
|
||||
size_t current_argv_len;
|
||||
int i, ambiguous, match;
|
||||
|
||||
#define IDENTICAL_INTERPRETATION(_x, _y) \
|
||||
(long_options[(_x)].has_arg == long_options[(_y)].has_arg && \
|
||||
long_options[(_x)].flag == long_options[(_y)].flag && \
|
||||
long_options[(_x)].val == long_options[(_y)].val)
|
||||
|
||||
current_argv = place;
|
||||
match = -1;
|
||||
ambiguous = 0;
|
||||
|
||||
optind++;
|
||||
|
||||
if ((has_equal = strchr(current_argv, '=')) != NULL) {
|
||||
/* argument found (--option=arg) */
|
||||
current_argv_len = has_equal - current_argv;
|
||||
has_equal++;
|
||||
} else
|
||||
current_argv_len = strlen(current_argv);
|
||||
|
||||
for (i = 0; long_options[i].name; i++) {
|
||||
/* find matching long option */
|
||||
if (strncmp(current_argv, long_options[i].name,
|
||||
current_argv_len))
|
||||
continue;
|
||||
|
||||
if (strlen(long_options[i].name) == current_argv_len) {
|
||||
/* exact match */
|
||||
match = i;
|
||||
ambiguous = 0;
|
||||
break;
|
||||
}
|
||||
/*
|
||||
* If this is a known short option, don't allow
|
||||
* a partial match of a single character.
|
||||
*/
|
||||
if (short_too && current_argv_len == 1)
|
||||
continue;
|
||||
|
||||
if (match == -1) /* partial match */
|
||||
match = i;
|
||||
else if (!IDENTICAL_INTERPRETATION(i, match))
|
||||
ambiguous = 1;
|
||||
}
|
||||
if (ambiguous) {
|
||||
/* ambiguous abbreviation */
|
||||
if (PRINT_ERROR)
|
||||
warnx(ambig, (int)current_argv_len,
|
||||
current_argv);
|
||||
optopt = 0;
|
||||
return (BADCH);
|
||||
}
|
||||
if (match != -1) { /* option found */
|
||||
if (long_options[match].has_arg == no_argument
|
||||
&& has_equal) {
|
||||
if (PRINT_ERROR)
|
||||
warnx(noarg, (int)current_argv_len,
|
||||
current_argv);
|
||||
/*
|
||||
* XXX: GNU sets optopt to val regardless of flag
|
||||
*/
|
||||
if (long_options[match].flag == NULL)
|
||||
optopt = long_options[match].val;
|
||||
else
|
||||
optopt = 0;
|
||||
return (BADARG);
|
||||
}
|
||||
if (long_options[match].has_arg == required_argument ||
|
||||
long_options[match].has_arg == optional_argument) {
|
||||
if (has_equal)
|
||||
optarg = has_equal;
|
||||
else if (long_options[match].has_arg ==
|
||||
required_argument) {
|
||||
/*
|
||||
* optional argument doesn't use next nargv
|
||||
*/
|
||||
optarg = nargv[optind++];
|
||||
}
|
||||
}
|
||||
if ((long_options[match].has_arg == required_argument)
|
||||
&& (optarg == NULL)) {
|
||||
/*
|
||||
* Missing argument; leading ':' indicates no error
|
||||
* should be generated.
|
||||
*/
|
||||
if (PRINT_ERROR)
|
||||
warnx(recargstring,
|
||||
current_argv);
|
||||
/*
|
||||
* XXX: GNU sets optopt to val regardless of flag
|
||||
*/
|
||||
if (long_options[match].flag == NULL)
|
||||
optopt = long_options[match].val;
|
||||
else
|
||||
optopt = 0;
|
||||
--optind;
|
||||
return (BADARG);
|
||||
}
|
||||
} else { /* unknown option */
|
||||
if (short_too) {
|
||||
--optind;
|
||||
return (-1);
|
||||
}
|
||||
if (PRINT_ERROR)
|
||||
warnx(illoptstring, current_argv);
|
||||
optopt = 0;
|
||||
return (BADCH);
|
||||
}
|
||||
if (idx)
|
||||
*idx = match;
|
||||
if (long_options[match].flag) {
|
||||
*long_options[match].flag = long_options[match].val;
|
||||
return (0);
|
||||
} else
|
||||
return (long_options[match].val);
|
||||
#undef IDENTICAL_INTERPRETATION
|
||||
}
|
||||
|
||||
/*
|
||||
* getopt_internal --
|
||||
* Parse argc/argv argument vector. Called by user level routines.
|
||||
*/
|
||||
static int
|
||||
getopt_internal(int nargc, char * const *nargv, const char *options,
|
||||
const struct option *long_options, int *idx, int flags)
|
||||
{
|
||||
char *oli; /* option letter list index */
|
||||
int optchar, short_too;
|
||||
static int posixly_correct = -1;
|
||||
|
||||
if (options == NULL)
|
||||
return (-1);
|
||||
|
||||
/*
|
||||
* XXX Some GNU programs (like cvs) set optind to 0 instead of
|
||||
* XXX using optreset. Work around this braindamage.
|
||||
*/
|
||||
if (optind == 0)
|
||||
optind = optreset = 1;
|
||||
|
||||
/*
|
||||
* Disable GNU extensions if POSIXLY_CORRECT is set or options
|
||||
* string begins with a '+'.
|
||||
*
|
||||
* CV, 2009-12-14: Check POSIXLY_CORRECT anew if optind == 0 or
|
||||
* optreset != 0 for GNU compatibility.
|
||||
*/
|
||||
if (posixly_correct == -1 || optreset != 0)
|
||||
posixly_correct = (getenv("POSIXLY_CORRECT") != NULL);
|
||||
if (*options == '-')
|
||||
flags |= FLAG_ALLARGS;
|
||||
else if (posixly_correct || *options == '+')
|
||||
flags &= ~FLAG_PERMUTE;
|
||||
if (*options == '+' || *options == '-')
|
||||
options++;
|
||||
|
||||
optarg = NULL;
|
||||
if (optreset)
|
||||
nonopt_start = nonopt_end = -1;
|
||||
start:
|
||||
if (optreset || !*place) { /* update scanning pointer */
|
||||
optreset = 0;
|
||||
if (optind >= nargc) { /* end of argument vector */
|
||||
place = EMSG;
|
||||
if (nonopt_end != -1) {
|
||||
/* do permutation, if we have to */
|
||||
permute_args(nonopt_start, nonopt_end,
|
||||
optind, nargv);
|
||||
optind -= nonopt_end - nonopt_start;
|
||||
}
|
||||
else if (nonopt_start != -1) {
|
||||
/*
|
||||
* If we skipped non-options, set optind
|
||||
* to the first of them.
|
||||
*/
|
||||
optind = nonopt_start;
|
||||
}
|
||||
nonopt_start = nonopt_end = -1;
|
||||
return (-1);
|
||||
}
|
||||
if (*(place = nargv[optind]) != '-' ||
|
||||
(place[1] == '\0' && strchr(options, '-') == NULL)) {
|
||||
place = EMSG; /* found non-option */
|
||||
if (flags & FLAG_ALLARGS) {
|
||||
/*
|
||||
* GNU extension:
|
||||
* return non-option as argument to option 1
|
||||
*/
|
||||
optarg = nargv[optind++];
|
||||
return (INORDER);
|
||||
}
|
||||
if (!(flags & FLAG_PERMUTE)) {
|
||||
/*
|
||||
* If no permutation wanted, stop parsing
|
||||
* at first non-option.
|
||||
*/
|
||||
return (-1);
|
||||
}
|
||||
/* do permutation */
|
||||
if (nonopt_start == -1)
|
||||
nonopt_start = optind;
|
||||
else if (nonopt_end != -1) {
|
||||
permute_args(nonopt_start, nonopt_end,
|
||||
optind, nargv);
|
||||
nonopt_start = optind -
|
||||
(nonopt_end - nonopt_start);
|
||||
nonopt_end = -1;
|
||||
}
|
||||
optind++;
|
||||
/* process next argument */
|
||||
goto start;
|
||||
}
|
||||
if (nonopt_start != -1 && nonopt_end == -1)
|
||||
nonopt_end = optind;
|
||||
|
||||
/*
|
||||
* If we have "-" do nothing, if "--" we are done.
|
||||
*/
|
||||
if (place[1] != '\0' && *++place == '-' && place[1] == '\0') {
|
||||
optind++;
|
||||
place = EMSG;
|
||||
/*
|
||||
* We found an option (--), so if we skipped
|
||||
* non-options, we have to permute.
|
||||
*/
|
||||
if (nonopt_end != -1) {
|
||||
permute_args(nonopt_start, nonopt_end,
|
||||
optind, nargv);
|
||||
optind -= nonopt_end - nonopt_start;
|
||||
}
|
||||
nonopt_start = nonopt_end = -1;
|
||||
return (-1);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Check long options if:
|
||||
* 1) we were passed some
|
||||
* 2) the arg is not just "-"
|
||||
* 3) either the arg starts with -- we are getopt_long_only()
|
||||
*/
|
||||
if (long_options != NULL && place != nargv[optind] &&
|
||||
(*place == '-' || (flags & FLAG_LONGONLY))) {
|
||||
short_too = 0;
|
||||
if (*place == '-')
|
||||
place++; /* --foo long option */
|
||||
else if (*place != ':' && strchr(options, *place) != NULL)
|
||||
short_too = 1; /* could be short option too */
|
||||
|
||||
optchar = parse_long_options(nargv, options, long_options,
|
||||
idx, short_too);
|
||||
if (optchar != -1) {
|
||||
place = EMSG;
|
||||
return (optchar);
|
||||
}
|
||||
}
|
||||
|
||||
if ((optchar = (int)*place++) == (int)':' ||
|
||||
(optchar == (int)'-' && *place != '\0') ||
|
||||
(oli = (char*)strchr(options, optchar)) == NULL) {
|
||||
/*
|
||||
* If the user specified "-" and '-' isn't listed in
|
||||
* options, return -1 (non-option) as per POSIX.
|
||||
* Otherwise, it is an unknown option character (or ':').
|
||||
*/
|
||||
if (optchar == (int)'-' && *place == '\0')
|
||||
return (-1);
|
||||
if (!*place)
|
||||
++optind;
|
||||
if (PRINT_ERROR)
|
||||
warnx(illoptchar, optchar);
|
||||
optopt = optchar;
|
||||
return (BADCH);
|
||||
}
|
||||
if (long_options != NULL && optchar == 'W' && oli[1] == ';') {
|
||||
/* -W long-option */
|
||||
if (*place) /* no space */
|
||||
/* NOTHING */;
|
||||
else if (++optind >= nargc) { /* no arg */
|
||||
place = EMSG;
|
||||
if (PRINT_ERROR)
|
||||
warnx(recargchar, optchar);
|
||||
optopt = optchar;
|
||||
return (BADARG);
|
||||
} else /* white space */
|
||||
place = nargv[optind];
|
||||
optchar = parse_long_options(nargv, options, long_options,
|
||||
idx, 0);
|
||||
place = EMSG;
|
||||
return (optchar);
|
||||
}
|
||||
if (*++oli != ':') { /* doesn't take argument */
|
||||
if (!*place)
|
||||
++optind;
|
||||
} else { /* takes (optional) argument */
|
||||
optarg = NULL;
|
||||
if (*place) /* no white space */
|
||||
optarg = place;
|
||||
else if (oli[1] != ':') { /* arg not optional */
|
||||
if (++optind >= nargc) { /* no arg */
|
||||
place = EMSG;
|
||||
if (PRINT_ERROR)
|
||||
warnx(recargchar, optchar);
|
||||
optopt = optchar;
|
||||
return (BADARG);
|
||||
} else
|
||||
optarg = nargv[optind];
|
||||
}
|
||||
place = EMSG;
|
||||
++optind;
|
||||
}
|
||||
/* dump back option letter */
|
||||
return (optchar);
|
||||
}
|
||||
|
||||
/*
|
||||
* getopt_long --
|
||||
* Parse argc/argv argument vector.
|
||||
*/
|
||||
int
|
||||
getopt_long(int nargc, char * const *nargv, const char *options,
|
||||
const struct option *long_options, int *idx)
|
||||
{
|
||||
|
||||
return (getopt_internal(nargc, nargv, options, long_options, idx,
|
||||
FLAG_PERMUTE));
|
||||
}
|
||||
|
||||
/*
|
||||
* getopt_long_only --
|
||||
* Parse argc/argv argument vector.
|
||||
*/
|
||||
int
|
||||
getopt_long_only(int nargc, char * const *nargv, const char *options,
|
||||
const struct option *long_options, int *idx)
|
||||
{
|
||||
|
||||
return (getopt_internal(nargc, nargv, options, long_options, idx,
|
||||
FLAG_PERMUTE|FLAG_LONGONLY));
|
||||
}
|
||||
|
||||
//extern int getopt_long(int nargc, char * const *nargv, const char *options,
|
||||
// const struct option *long_options, int *idx);
|
||||
//extern int getopt_long_only(int nargc, char * const *nargv, const char *options,
|
||||
// const struct option *long_options, int *idx);
|
||||
/*
|
||||
* Previous MinGW implementation had...
|
||||
*/
|
||||
#ifndef HAVE_DECL_GETOPT
|
||||
/*
|
||||
* ...for the long form API only; keep this for compatibility.
|
||||
*/
|
||||
# define HAVE_DECL_GETOPT 1
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* !defined(__UNISTD_H_SOURCED__) && !defined(__GETOPT_LONG_H__) */
|
||||
@@ -3,17 +3,19 @@ project (cpuid C)
|
||||
|
||||
add_definitions(/DVERSION="0.4.0")
|
||||
|
||||
set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -Os")
|
||||
|
||||
set(HEADERS
|
||||
libcpuid.h
|
||||
libcpuid_types.h
|
||||
libcpuid_constants.h
|
||||
libcpuid_internal.h
|
||||
amd_code_t.h
|
||||
intel_code_t.h
|
||||
recog_amd.h
|
||||
recog_intel.h
|
||||
asm-bits.h
|
||||
libcpuid_util.h
|
||||
amd_code_t.h
|
||||
intel_code_t.h
|
||||
recog_amd.h
|
||||
recog_intel.h
|
||||
asm-bits.h
|
||||
libcpuid_util.h
|
||||
)
|
||||
|
||||
set(SOURCES
|
||||
@@ -24,7 +26,13 @@ set(SOURCES
|
||||
libcpuid_util.c
|
||||
)
|
||||
|
||||
if (CMAKE_CL_64)
|
||||
enable_language(ASM_MASM)
|
||||
set(SOURCES_ASM masm-x64.asm)
|
||||
endif()
|
||||
|
||||
add_library(cpuid STATIC
|
||||
${HEADERS}
|
||||
${SOURCES}
|
||||
${SOURCES_ASM}
|
||||
)
|
||||
@@ -46,11 +46,6 @@ int set_error(cpu_error_t err)
|
||||
return (int) err;
|
||||
}
|
||||
|
||||
static void raw_data_t_constructor(struct cpu_raw_data_t* raw)
|
||||
{
|
||||
memset(raw, 0, sizeof(struct cpu_raw_data_t));
|
||||
}
|
||||
|
||||
static void cpu_id_t_constructor(struct cpu_id_t* id)
|
||||
{
|
||||
memset(id, 0, sizeof(struct cpu_id_t));
|
||||
@@ -60,29 +55,6 @@ static void cpu_id_t_constructor(struct cpu_id_t* id)
|
||||
id->sse_size = -1;
|
||||
}
|
||||
|
||||
static int parse_token(const char* expected_token, const char *token,
|
||||
const char *value, uint32_t array[][4], int limit, int *recognized)
|
||||
{
|
||||
char format[32];
|
||||
int veax, vebx, vecx, vedx;
|
||||
int index;
|
||||
|
||||
if (*recognized) return 1; /* already recognized */
|
||||
if (strncmp(token, expected_token, strlen(expected_token))) return 1; /* not what we search for */
|
||||
sprintf(format, "%s[%%d]", expected_token);
|
||||
*recognized = 1;
|
||||
if (1 == sscanf(token, format, &index) && index >=0 && index < limit) {
|
||||
if (4 == sscanf(value, "%x%x%x%x", &veax, &vebx, &vecx, &vedx)) {
|
||||
array[index][0] = veax;
|
||||
array[index][1] = vebx;
|
||||
array[index][2] = vecx;
|
||||
array[index][3] = vedx;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* get_total_cpus() system specific code: uses OS routines to determine total number of CPUs */
|
||||
#ifdef __APPLE__
|
||||
#include <unistd.h>
|
||||
@@ -117,7 +89,7 @@ static int get_total_cpus(void)
|
||||
#if defined linux || defined __linux__ || defined __sun
|
||||
#include <sys/sysinfo.h>
|
||||
#include <unistd.h>
|
||||
|
||||
|
||||
static int get_total_cpus(void)
|
||||
{
|
||||
return sysconf(_SC_NPROCESSORS_ONLN);
|
||||
@@ -249,42 +221,42 @@ static void load_features_common(struct cpu_raw_data_t* raw, struct cpu_id_t* da
|
||||
|
||||
static cpu_vendor_t cpuid_vendor_identify(const uint32_t *raw_vendor, char *vendor_str)
|
||||
{
|
||||
int i;
|
||||
cpu_vendor_t vendor = VENDOR_UNKNOWN;
|
||||
const struct { cpu_vendor_t vendor; char match[16]; }
|
||||
matchtable[NUM_CPU_VENDORS] = {
|
||||
/* source: http://www.sandpile.org/ia32/cpuid.htm */
|
||||
{ VENDOR_INTEL , "GenuineIntel" },
|
||||
{ VENDOR_AMD , "AuthenticAMD" },
|
||||
{ VENDOR_CYRIX , "CyrixInstead" },
|
||||
{ VENDOR_NEXGEN , "NexGenDriven" },
|
||||
{ VENDOR_TRANSMETA , "GenuineTMx86" },
|
||||
{ VENDOR_UMC , "UMC UMC UMC " },
|
||||
{ VENDOR_CENTAUR , "CentaurHauls" },
|
||||
{ VENDOR_RISE , "RiseRiseRise" },
|
||||
{ VENDOR_SIS , "SiS SiS SiS " },
|
||||
{ VENDOR_NSC , "Geode by NSC" },
|
||||
};
|
||||
int i;
|
||||
cpu_vendor_t vendor = VENDOR_UNKNOWN;
|
||||
const struct { cpu_vendor_t vendor; char match[16]; }
|
||||
matchtable[NUM_CPU_VENDORS] = {
|
||||
/* source: http://www.sandpile.org/ia32/cpuid.htm */
|
||||
{ VENDOR_INTEL , "GenuineIntel" },
|
||||
{ VENDOR_AMD , "AuthenticAMD" },
|
||||
{ VENDOR_CYRIX , "CyrixInstead" },
|
||||
{ VENDOR_NEXGEN , "NexGenDriven" },
|
||||
{ VENDOR_TRANSMETA , "GenuineTMx86" },
|
||||
{ VENDOR_UMC , "UMC UMC UMC " },
|
||||
{ VENDOR_CENTAUR , "CentaurHauls" },
|
||||
{ VENDOR_RISE , "RiseRiseRise" },
|
||||
{ VENDOR_SIS , "SiS SiS SiS " },
|
||||
{ VENDOR_NSC , "Geode by NSC" },
|
||||
};
|
||||
|
||||
memcpy(vendor_str + 0, &raw_vendor[1], 4);
|
||||
memcpy(vendor_str + 4, &raw_vendor[3], 4);
|
||||
memcpy(vendor_str + 8, &raw_vendor[2], 4);
|
||||
vendor_str[12] = 0;
|
||||
memcpy(vendor_str + 0, &raw_vendor[1], 4);
|
||||
memcpy(vendor_str + 4, &raw_vendor[3], 4);
|
||||
memcpy(vendor_str + 8, &raw_vendor[2], 4);
|
||||
vendor_str[12] = 0;
|
||||
|
||||
/* Determine vendor: */
|
||||
for (i = 0; i < NUM_CPU_VENDORS; i++)
|
||||
if (!strcmp(vendor_str, matchtable[i].match)) {
|
||||
vendor = matchtable[i].vendor;
|
||||
break;
|
||||
}
|
||||
return vendor;
|
||||
/* Determine vendor: */
|
||||
for (i = 0; i < NUM_CPU_VENDORS; i++)
|
||||
if (!strcmp(vendor_str, matchtable[i].match)) {
|
||||
vendor = matchtable[i].vendor;
|
||||
break;
|
||||
}
|
||||
return vendor;
|
||||
}
|
||||
|
||||
static int cpuid_basic_identify(struct cpu_raw_data_t* raw, struct cpu_id_t* data)
|
||||
{
|
||||
int i, j, basic, xmodel, xfamily, ext;
|
||||
char brandstr[64] = {0};
|
||||
data->vendor = cpuid_vendor_identify(raw->basic_cpuid[0], data->vendor_str);
|
||||
data->vendor = cpuid_vendor_identify(raw->basic_cpuid[0], data->vendor_str);
|
||||
|
||||
if (data->vendor == VENDOR_UNKNOWN)
|
||||
return set_error(ERR_CPU_UNKN);
|
||||
@@ -302,7 +274,7 @@ static int cpuid_basic_identify(struct cpu_raw_data_t* raw, struct cpu_id_t* dat
|
||||
data->ext_model = data->model + (xmodel << 4);
|
||||
}
|
||||
ext = raw->ext_cpuid[0][0] - 0x8000000;
|
||||
|
||||
|
||||
/* obtain the brand string, if present: */
|
||||
if (ext >= 4) {
|
||||
for (i = 0; i < 3; i++)
|
||||
@@ -320,27 +292,6 @@ static int cpuid_basic_identify(struct cpu_raw_data_t* raw, struct cpu_id_t* dat
|
||||
return set_error(ERR_OK);
|
||||
}
|
||||
|
||||
static void make_list_from_string(const char* csv, struct cpu_list_t* list)
|
||||
{
|
||||
int i, n, l, last;
|
||||
l = (int) strlen(csv);
|
||||
n = 0;
|
||||
for (i = 0; i < l; i++) if (csv[i] == ',') n++;
|
||||
n++;
|
||||
list->num_entries = n;
|
||||
list->names = (char**) malloc(sizeof(char*) * n);
|
||||
last = -1;
|
||||
n = 0;
|
||||
for (i = 0; i <= l; i++) if (i == l || csv[i] == ',') {
|
||||
list->names[n] = (char*) malloc(i - last);
|
||||
memcpy(list->names[n], &csv[last + 1], i - last - 1);
|
||||
list->names[n][i - last - 1] = '\0';
|
||||
n++;
|
||||
last = i;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Interface: */
|
||||
|
||||
int cpuid_get_total_cpus(void)
|
||||
@@ -610,39 +610,6 @@ void cpu_exec_cpuid_ext(uint32_t* regs);
|
||||
*/
|
||||
int cpuid_get_raw_data(struct cpu_raw_data_t* data);
|
||||
|
||||
/**
|
||||
* @brief Writes the raw CPUID data to a text file
|
||||
* @param data - a pointer to cpu_raw_data_t structure
|
||||
* @param filename - the path of the file, where the serialized data should be
|
||||
* written. If empty, stdout will be used.
|
||||
* @note This is intended primarily for debugging. On some processor, which is
|
||||
* not currently supported or not completely recognized by cpu_identify,
|
||||
* one can still successfully get the raw data and write it to a file.
|
||||
* libcpuid developers can later import this file and debug the detection
|
||||
* code as if running on the actual hardware.
|
||||
* The file is simple text format of "something=value" pairs. Version info
|
||||
* is also written, but the format is not intended to be neither backward-
|
||||
* nor forward compatible.
|
||||
* @returns zero if successful, and some negative number on error.
|
||||
* The error message can be obtained by calling \ref cpuid_error.
|
||||
* @see cpu_error_t
|
||||
*/
|
||||
int cpuid_serialize_raw_data(struct cpu_raw_data_t* data, const char* filename);
|
||||
|
||||
/**
|
||||
* @brief Reads raw CPUID data from file
|
||||
* @param data - a pointer to cpu_raw_data_t structure. The deserialized data will
|
||||
* be written here.
|
||||
* @param filename - the path of the file, containing the serialized raw data.
|
||||
* If empty, stdin will be used.
|
||||
* @note This function may fail, if the file is created by different version of
|
||||
* the library. Also, see the notes on cpuid_serialize_raw_data.
|
||||
* @returns zero if successful, and some negative number on error.
|
||||
* The error message can be obtained by calling \ref cpuid_error.
|
||||
* @see cpu_error_t
|
||||
*/
|
||||
int cpuid_deserialize_raw_data(struct cpu_raw_data_t* data, const char* filename);
|
||||
|
||||
/**
|
||||
* @brief Identifies the CPU
|
||||
* @param raw - Input - a pointer to the raw CPUID data, which is obtained
|
||||
@@ -668,222 +635,6 @@ int cpuid_deserialize_raw_data(struct cpu_raw_data_t* data, const char* filename
|
||||
*/
|
||||
int cpu_identify(struct cpu_raw_data_t* raw, struct cpu_id_t* data);
|
||||
|
||||
/**
|
||||
* @brief Returns the short textual representation of a CPU flag
|
||||
* @param feature - the feature, whose textual representation is wanted.
|
||||
* @returns a constant string like "fpu", "tsc", "sse2", etc.
|
||||
* @note the names of the returned flags are compatible with those from
|
||||
* /proc/cpuinfo in Linux, with the exception of `tm_amd'
|
||||
*/
|
||||
const char* cpu_feature_str(cpu_feature_t feature);
|
||||
|
||||
/**
|
||||
* @brief Returns textual description of the last error
|
||||
*
|
||||
* libcpuid stores an `errno'-style error status, whose description
|
||||
* can be obtained with this function.
|
||||
* @note This function is not thread-safe
|
||||
* @see cpu_error_t
|
||||
*/
|
||||
const char* cpuid_error(void);
|
||||
|
||||
/**
|
||||
* @brief Executes RDTSC
|
||||
*
|
||||
* The RDTSC (ReaD Time Stamp Counter) instruction gives access to an
|
||||
* internal 64-bit counter, which usually increments at each clock cycle.
|
||||
* This can be used for various timing routines, and as a very precise
|
||||
* clock source. It is set to zero on system startup. Beware that may not
|
||||
* increment at the same frequency as the CPU. Consecutive calls of RDTSC
|
||||
* are, however, guaranteed to return monotonically-increasing values.
|
||||
*
|
||||
* @param result - a pointer to a 64-bit unsigned integer, where the TSC value
|
||||
* will be stored
|
||||
*
|
||||
* @note If 100% compatibility is a concern, you must first check if the
|
||||
* RDTSC instruction is present (if it is not, your program will crash
|
||||
* with "invalid opcode" exception). Only some very old processors (i486,
|
||||
* early AMD K5 and some Cyrix CPUs) lack that instruction - they should
|
||||
* have become exceedingly rare these days. To verify RDTSC presence,
|
||||
* run cpu_identify() and check flags[CPU_FEATURE_TSC].
|
||||
*
|
||||
* @note The monotonically increasing nature of the TSC may be violated
|
||||
* on SMP systems, if their TSC clocks run at different rate. If the OS
|
||||
* doesn't account for that, the TSC drift may become arbitrary large.
|
||||
*/
|
||||
void cpu_rdtsc(uint64_t* result);
|
||||
|
||||
/**
|
||||
* @brief Store TSC and timing info
|
||||
*
|
||||
* This function stores the current TSC value and current
|
||||
* time info from a precise OS-specific clock source in the cpu_mark_t
|
||||
* structure. The sys_clock field contains time with microsecond resolution.
|
||||
* The values can later be used to measure time intervals, number of clocks,
|
||||
* FPU frequency, etc.
|
||||
* @see cpu_rdtsc
|
||||
*
|
||||
* @param mark [out] - a pointer to a cpu_mark_t structure
|
||||
*/
|
||||
void cpu_tsc_mark(struct cpu_mark_t* mark);
|
||||
|
||||
/**
|
||||
* @brief Calculate TSC and timing difference
|
||||
*
|
||||
* @param mark - input/output: a pointer to a cpu_mark_t sturcture, which has
|
||||
* already been initialized by cpu_tsc_mark. The difference in
|
||||
* TSC and time will be written here.
|
||||
*
|
||||
* This function calculates the TSC and time difference, by obtaining the
|
||||
* current TSC and timing values and subtracting the contents of the `mark'
|
||||
* structure from them. Results are written in the same structure.
|
||||
*
|
||||
* Example:
|
||||
* @code
|
||||
* ...
|
||||
* struct cpu_mark_t mark;
|
||||
* cpu_tsc_mark(&mark);
|
||||
* foo();
|
||||
* cpu_tsc_unmark(&mark);
|
||||
* printf("Foo finished. Executed in %llu cycles and %llu usecs\n",
|
||||
* mark.tsc, mark.sys_clock);
|
||||
* ...
|
||||
* @endcode
|
||||
*/
|
||||
void cpu_tsc_unmark(struct cpu_mark_t* mark);
|
||||
|
||||
/**
|
||||
* @brief Calculates the CPU clock
|
||||
*
|
||||
* @param mark - pointer to a cpu_mark_t structure, which has been initialized
|
||||
* with cpu_tsc_mark and later `stopped' with cpu_tsc_unmark.
|
||||
*
|
||||
* @note For reliable results, the marked time interval should be at least about
|
||||
* 10 ms.
|
||||
*
|
||||
* @returns the CPU clock frequency, in MHz. Due to measurement error, it will
|
||||
* differ from the true value in a few least-significant bits. Accuracy depends
|
||||
* on the timing interval - the more, the better. If the timing interval is
|
||||
* insufficient, the result is -1. Also, see the comment on cpu_clock_measure
|
||||
* for additional issues and pitfalls in using RDTSC for CPU frequency
|
||||
* measurements.
|
||||
*/
|
||||
int cpu_clock_by_mark(struct cpu_mark_t* mark);
|
||||
|
||||
/**
|
||||
* @brief Returns the CPU clock, as reported by the OS
|
||||
*
|
||||
* This function uses OS-specific functions to obtain the CPU clock. It may
|
||||
* differ from the true clock for several reasons:<br><br>
|
||||
*
|
||||
* i) The CPU might be in some power saving state, while the OS reports its
|
||||
* full-power frequency, or vice-versa.<br>
|
||||
* ii) In some cases you can raise or lower the CPU frequency with overclocking
|
||||
* utilities and the OS will not notice.
|
||||
*
|
||||
* @returns the CPU clock frequency in MHz. If the OS is not (yet) supported
|
||||
* or lacks the necessary reporting machinery, the return value is -1
|
||||
*/
|
||||
int cpu_clock_by_os(void);
|
||||
|
||||
/**
|
||||
* @brief Measure the CPU clock frequency
|
||||
*
|
||||
* @param millis - How much time to waste in the busy-wait cycle. In millisecs.
|
||||
* Useful values 10 - 1000
|
||||
* @param quad_check - Do a more thorough measurement if nonzero
|
||||
* (see the explanation).
|
||||
*
|
||||
* The function performs a busy-wait cycle for the given time and calculates
|
||||
* the CPU frequency by the difference of the TSC values. The accuracy of the
|
||||
* calculation depends on the length of the busy-wait cycle: more is better,
|
||||
* but 100ms should be enough for most purposes.
|
||||
*
|
||||
* While this will calculate the CPU frequency correctly in most cases, there are
|
||||
* several reasons why it might be incorrect:<br>
|
||||
*
|
||||
* i) RDTSC doesn't guarantee it will run at the same clock as the CPU.
|
||||
* Apparently there aren't CPUs at the moment, but still, there's no
|
||||
* guarantee.<br>
|
||||
* ii) The CPU might be in a low-frequency power saving mode, and the CPU
|
||||
* might be switched to higher frequency at any time. If this happens
|
||||
* during the measurement, the result can be anywhere between the
|
||||
* low and high frequencies. Also, if you're interested in the
|
||||
* high frequency value only, this function might return the low one
|
||||
* instead.<br>
|
||||
* iii) On SMP systems exhibiting TSC drift (see \ref cpu_rdtsc)
|
||||
*
|
||||
* the quad_check option will run four consecutive measurements and
|
||||
* then return the average of the two most-consistent results. The total
|
||||
* runtime of the function will still be `millis' - consider using
|
||||
* a bit more time for the timing interval.
|
||||
*
|
||||
* Finally, for benchmarking / CPU intensive applications, the best strategy is
|
||||
* to use the cpu_tsc_mark() / cpu_tsc_unmark() / cpu_clock_by_mark() method.
|
||||
* Begin by mark()-ing about one second after application startup (allowing the
|
||||
* power-saving manager to kick in and rise the frequency during that time),
|
||||
* then unmark() just before application finishing. The result will most
|
||||
* acurately represent at what frequency your app was running.
|
||||
*
|
||||
* @returns the CPU clock frequency in MHz (within some measurement error
|
||||
* margin). If RDTSC is not supported, the result is -1.
|
||||
*/
|
||||
int cpu_clock_measure(int millis, int quad_check);
|
||||
|
||||
/**
|
||||
* @brief Measure the CPU clock frequency using instruction-counting
|
||||
*
|
||||
* @param millis - how much time to allocate for each run, in milliseconds
|
||||
* @param runs - how many runs to perform
|
||||
*
|
||||
* The function performs a busy-wait cycle using a known number of "heavy" (SSE)
|
||||
* instructions. These instructions run at (more or less guaranteed) 1 IPC rate,
|
||||
* so by running a busy loop for a fixed amount of time, and measuring the
|
||||
* amount of instructions done, the CPU clock is accurately measured.
|
||||
*
|
||||
* Of course, this function is still affected by the power-saving schemes, so
|
||||
* the warnings as of cpu_clock_measure() still apply. However, this function is
|
||||
* immune to problems with detection, related to the Intel Nehalem's "Turbo"
|
||||
* mode, where the internal clock is raised, but the RDTSC rate is unaffected.
|
||||
*
|
||||
* The function will run for about (millis * runs) milliseconds.
|
||||
* You can make only a single busy-wait run (runs == 1); however, this can
|
||||
* be affected by task scheduling (which will break the counting), so allowing
|
||||
* more than one run is recommended. As run length is not imperative for
|
||||
* accurate readings (e.g., 50ms is sufficient), you can afford a lot of short
|
||||
* runs, e.g. 10 runs of 50ms or 20 runs of 25ms.
|
||||
*
|
||||
* Recommended values - millis = 50, runs = 4. For more robustness,
|
||||
* increase the number of runs.
|
||||
*
|
||||
* NOTE: on Bulldozer and later CPUs, the busy-wait cycle runs at 1.4 IPC, thus
|
||||
* the results are skewed. This is corrected internally by dividing the resulting
|
||||
* value by 1.4.
|
||||
* However, this only occurs if the thread is executed on a single CMT
|
||||
* module - if there are other threads competing for resources, the results are
|
||||
* unpredictable. Make sure you run cpu_clock_by_ic() on a CPU that is free from
|
||||
* competing threads, or if there are such threads, they shouldn't exceed the
|
||||
* number of modules. On a Bulldozer X8, that means 4 threads.
|
||||
*
|
||||
* @returns the CPU clock frequency in MHz (within some measurement error
|
||||
* margin). If SSE is not supported, the result is -1. If the input parameters
|
||||
* are incorrect, or some other internal fault is detected, the result is -2.
|
||||
*/
|
||||
int cpu_clock_by_ic(int millis, int runs);
|
||||
|
||||
/**
|
||||
* @brief Get the CPU clock frequency (all-in-one method)
|
||||
*
|
||||
* This is an all-in-one method for getting the CPU clock frequency.
|
||||
* It tries to use the OS for that. If the OS doesn't have this info, it
|
||||
* uses cpu_clock_measure with 200ms time interval and quadruple checking.
|
||||
*
|
||||
* @returns the CPU clock frequency in MHz. If every possible method fails,
|
||||
* the result is -1.
|
||||
*/
|
||||
int cpu_clock(void);
|
||||
|
||||
|
||||
/**
|
||||
* @brief The return value of cpuid_get_epc().
|
||||
* @details
|
||||
@@ -916,230 +667,6 @@ struct cpu_epc_t cpuid_get_epc(int index, const struct cpu_raw_data_t* raw);
|
||||
*/
|
||||
const char* cpuid_lib_version(void);
|
||||
|
||||
typedef void (*libcpuid_warn_fn_t) (const char *msg);
|
||||
/**
|
||||
* @brief Sets the warning print function
|
||||
*
|
||||
* In some cases, the internal libcpuid machinery would like to emit useful
|
||||
* debug warnings. By default, these warnings are written to stderr. However,
|
||||
* you can set a custom function that will receive those warnings.
|
||||
*
|
||||
* @param warn_fun - the warning function you want to set. If NULL, warnings
|
||||
* are disabled. The function takes const char* argument.
|
||||
*
|
||||
* @returns the current warning function. You can use the return value to
|
||||
* keep the previous warning function and restore it at your discretion.
|
||||
*/
|
||||
libcpuid_warn_fn_t cpuid_set_warn_function(libcpuid_warn_fn_t warn_fun);
|
||||
|
||||
/**
|
||||
* @brief Sets the verbosiness level
|
||||
*
|
||||
* When the verbosiness level is above zero, some functions might print
|
||||
* diagnostic information about what are they doing. The higher the level is,
|
||||
* the more detail is printed. Level zero is guaranteed to omit all such
|
||||
* output. The output is written using the same machinery as the warnings,
|
||||
* @see cpuid_set_warn_function()
|
||||
*
|
||||
* @param level the desired verbosiness level. Useful values 0..2 inclusive
|
||||
*/
|
||||
void cpuid_set_verbosiness_level(int level);
|
||||
|
||||
|
||||
/**
|
||||
* @brief Obtains the CPU vendor from CPUID from the current CPU
|
||||
* @note The result is cached.
|
||||
* @returns VENDOR_UNKNOWN if failed, otherwise the CPU vendor type.
|
||||
* @see cpu_vendor_t
|
||||
*/
|
||||
cpu_vendor_t cpuid_get_vendor(void);
|
||||
|
||||
/**
|
||||
* @brief a structure that holds a list of processor names
|
||||
*/
|
||||
struct cpu_list_t {
|
||||
/** Number of entries in the list */
|
||||
int num_entries;
|
||||
/** Pointers to names. There will be num_entries of them */
|
||||
char **names;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Gets a list of all known CPU names from a specific vendor.
|
||||
*
|
||||
* This function compiles a list of all known CPU (code)names
|
||||
* (i.e. the possible values of cpu_id_t::cpu_codename) for the given vendor.
|
||||
*
|
||||
* There are about 100 entries for Intel and AMD, and a few for the other
|
||||
* vendors. The list is written out in approximate chronological introduction
|
||||
* order of the parts.
|
||||
*
|
||||
* @param vendor the vendor to be queried
|
||||
* @param list [out] the resulting list will be written here.
|
||||
* NOTE: As the memory is dynamically allocated, be sure to call
|
||||
* cpuid_free_cpu_list() after you're done with the data
|
||||
* @see cpu_list_t
|
||||
*/
|
||||
void cpuid_get_cpu_list(cpu_vendor_t vendor, struct cpu_list_t* list);
|
||||
|
||||
/**
|
||||
* @brief Frees a CPU list
|
||||
*
|
||||
* This function deletes all the memory associated with a CPU list, as obtained
|
||||
* by cpuid_get_cpu_list()
|
||||
*
|
||||
* @param list - the list to be free()'d.
|
||||
*/
|
||||
void cpuid_free_cpu_list(struct cpu_list_t* list);
|
||||
|
||||
struct msr_driver_t;
|
||||
/**
|
||||
* @brief Starts/opens a driver, needed to read MSRs (Model Specific Registers)
|
||||
*
|
||||
* On systems that support it, this function will create a temporary
|
||||
* system driver, that has privileges to execute the RDMSR instruction.
|
||||
* After the driver is created, you can read MSRs by calling \ref cpu_rdmsr
|
||||
*
|
||||
* @returns a handle to the driver on success, and NULL on error.
|
||||
* The error message can be obtained by calling \ref cpuid_error.
|
||||
* @see cpu_error_t
|
||||
*/
|
||||
struct msr_driver_t* cpu_msr_driver_open(void);
|
||||
|
||||
/**
|
||||
* @brief Similar to \ref cpu_msr_driver_open, but accept one parameter
|
||||
*
|
||||
* This function works on certain operating systems (GNU/Linux, FreeBSD)
|
||||
*
|
||||
* @param core_num specify the core number for MSR.
|
||||
* The first core number is 0.
|
||||
* The last core number is \ref cpuid_get_total_cpus - 1.
|
||||
*
|
||||
* @returns a handle to the driver on success, and NULL on error.
|
||||
* The error message can be obtained by calling \ref cpuid_error.
|
||||
* @see cpu_error_t
|
||||
*/
|
||||
struct msr_driver_t* cpu_msr_driver_open_core(unsigned core_num);
|
||||
|
||||
/**
|
||||
* @brief Reads a Model-Specific Register (MSR)
|
||||
*
|
||||
* If the CPU has MSRs (as indicated by the CPU_FEATURE_MSR flag), you can
|
||||
* read a MSR with the given index by calling this function.
|
||||
*
|
||||
* There are several prerequisites you must do before reading MSRs:
|
||||
* 1) You must ensure the CPU has RDMSR. Check the CPU_FEATURE_MSR flag
|
||||
* in cpu_id_t::flags
|
||||
* 2) You must ensure that the CPU implements the specific MSR you intend to
|
||||
* read.
|
||||
* 3) You must open a MSR-reader driver. RDMSR is a privileged instruction and
|
||||
* needs ring-0 access in order to work. This temporary driver is created
|
||||
* by calling \ref cpu_msr_driver_open
|
||||
*
|
||||
* @param handle - a handle to the MSR reader driver, as created by
|
||||
* cpu_msr_driver_open
|
||||
* @param msr_index - the numeric ID of the MSR you want to read
|
||||
* @param result - a pointer to a 64-bit integer, where the MSR value is stored
|
||||
*
|
||||
* @returns zero if successful, and some negative number on error.
|
||||
* The error message can be obtained by calling \ref cpuid_error.
|
||||
* @see cpu_error_t
|
||||
*/
|
||||
int cpu_rdmsr(struct msr_driver_t* handle, uint32_t msr_index, uint64_t* result);
|
||||
|
||||
|
||||
typedef enum {
|
||||
INFO_MPERF, /*!< Maximum performance frequency clock. This
|
||||
is a counter, which increments as a
|
||||
proportion of the actual processor speed. */
|
||||
INFO_APERF, /*!< Actual performance frequency clock. This
|
||||
accumulates the core clock counts when the
|
||||
core is active. */
|
||||
INFO_MIN_MULTIPLIER, /*!< Minimum CPU:FSB ratio for this CPU,
|
||||
multiplied by 100. */
|
||||
INFO_CUR_MULTIPLIER, /*!< Current CPU:FSB ratio, multiplied by 100.
|
||||
e.g., a CPU:FSB value of 18.5 reads as
|
||||
"1850". */
|
||||
INFO_MAX_MULTIPLIER, /*!< Maximum CPU:FSB ratio for this CPU,
|
||||
multiplied by 100. */
|
||||
INFO_TEMPERATURE, /*!< The current core temperature in Celsius. */
|
||||
INFO_THROTTLING, /*!< 1 if the current logical processor is
|
||||
throttling. 0 if it is running normally. */
|
||||
INFO_VOLTAGE, /*!< The current core voltage in Volt,
|
||||
multiplied by 100. */
|
||||
INFO_BCLK, /*!< See \ref INFO_BUS_CLOCK. */
|
||||
INFO_BUS_CLOCK, /*!< The main bus clock in MHz,
|
||||
e.g., FSB/QPI/DMI/HT base clock,
|
||||
multiplied by 100. */
|
||||
} cpu_msrinfo_request_t;
|
||||
|
||||
/**
|
||||
* @brief Similar to \ref cpu_rdmsr, but extract a range of bits
|
||||
*
|
||||
* @param handle - a handle to the MSR reader driver, as created by
|
||||
* cpu_msr_driver_open
|
||||
* @param msr_index - the numeric ID of the MSR you want to read
|
||||
* @param highbit - the high bit in range, must be inferior to 64
|
||||
* @param lowbit - the low bit in range, must be equal or superior to 0
|
||||
* @param result - a pointer to a 64-bit integer, where the MSR value is stored
|
||||
*
|
||||
* @returns zero if successful, and some negative number on error.
|
||||
* The error message can be obtained by calling \ref cpuid_error.
|
||||
* @see cpu_error_t
|
||||
*/
|
||||
int cpu_rdmsr_range(struct msr_driver_t* handle, uint32_t msr_index, uint8_t highbit,
|
||||
uint8_t lowbit, uint64_t* result);
|
||||
|
||||
/**
|
||||
* @brief Reads extended CPU information from Model-Specific Registers.
|
||||
* @param handle - a handle to an open MSR driver, @see cpu_msr_driver_open
|
||||
* @param which - which info field should be returned. A list of
|
||||
* available information entities is listed in the
|
||||
* cpu_msrinfo_request_t enum.
|
||||
* @retval - if the requested information is available for the current
|
||||
* processor model, the respective value is returned.
|
||||
* if no information is available, or the CPU doesn't support
|
||||
* the query, the special value CPU_INVALID_VALUE is returned
|
||||
* @note This function is not MT-safe. If you intend to call it from multiple
|
||||
* threads, guard it through a mutex or a similar primitive.
|
||||
*/
|
||||
int cpu_msrinfo(struct msr_driver_t* handle, cpu_msrinfo_request_t which);
|
||||
#define CPU_INVALID_VALUE 0x3fffffff
|
||||
|
||||
/**
|
||||
* @brief Writes the raw MSR data to a text file
|
||||
* @param data - a pointer to msr_driver_t structure
|
||||
* @param filename - the path of the file, where the serialized data should be
|
||||
* written. If empty, stdout will be used.
|
||||
* @note This is intended primarily for debugging. On some processor, which is
|
||||
* not currently supported or not completely recognized by cpu_identify,
|
||||
* one can still successfully get the raw data and write it to a file.
|
||||
* libcpuid developers can later import this file and debug the detection
|
||||
* code as if running on the actual hardware.
|
||||
* The file is simple text format of "something=value" pairs. Version info
|
||||
* is also written, but the format is not intended to be neither backward-
|
||||
* nor forward compatible.
|
||||
* @returns zero if successful, and some negative number on error.
|
||||
* The error message can be obtained by calling \ref cpuid_error.
|
||||
* @see cpu_error_t
|
||||
*/
|
||||
int msr_serialize_raw_data(struct msr_driver_t* handle, const char* filename);
|
||||
|
||||
/**
|
||||
* @brief Closes an open MSR driver
|
||||
*
|
||||
* This function unloads the MSR driver opened by cpu_msr_driver_open and
|
||||
* frees any resources associated with it.
|
||||
*
|
||||
* @param handle - a handle to the MSR reader driver, as created by
|
||||
* cpu_msr_driver_open
|
||||
*
|
||||
* @returns zero if successful, and some negative number on error.
|
||||
* The error message can be obtained by calling \ref cpuid_error.
|
||||
* @see cpu_error_t
|
||||
*/
|
||||
int cpu_msr_driver_close(struct msr_driver_t* handle);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}; /* extern "C" */
|
||||
#endif
|
||||
@@ -58,6 +58,48 @@ struct internal_id_info_t {
|
||||
int score; // detection (matchtable) score
|
||||
};
|
||||
|
||||
#define LBIT(x) (((long long) 1) << x)
|
||||
|
||||
enum _common_bits_t {
|
||||
_M_ = LBIT( 0 ),
|
||||
MOBILE_ = LBIT( 1 ),
|
||||
_MP_ = LBIT( 2 ),
|
||||
};
|
||||
|
||||
// additional detection bits for Intel CPUs:
|
||||
enum _intel_bits_t {
|
||||
PENTIUM_ = LBIT( 10 ),
|
||||
CELERON_ = LBIT( 11 ),
|
||||
CORE_ = LBIT( 12 ),
|
||||
_I_ = LBIT( 13 ),
|
||||
_3 = LBIT( 14 ),
|
||||
_5 = LBIT( 15 ),
|
||||
_7 = LBIT( 16 ),
|
||||
XEON_ = LBIT( 17 ),
|
||||
ATOM_ = LBIT( 18 ),
|
||||
};
|
||||
typedef enum _intel_bits_t intel_bits_t;
|
||||
|
||||
enum _amd_bits_t {
|
||||
ATHLON_ = LBIT( 10 ),
|
||||
_XP_ = LBIT( 11 ),
|
||||
DURON_ = LBIT( 12 ),
|
||||
SEMPRON_ = LBIT( 13 ),
|
||||
OPTERON_ = LBIT( 14 ),
|
||||
TURION_ = LBIT( 15 ),
|
||||
_LV_ = LBIT( 16 ),
|
||||
_64_ = LBIT( 17 ),
|
||||
_X2 = LBIT( 18 ),
|
||||
_X3 = LBIT( 19 ),
|
||||
_X4 = LBIT( 20 ),
|
||||
_X6 = LBIT( 21 ),
|
||||
_FX = LBIT( 22 ),
|
||||
_APU_ = LBIT( 23 ),
|
||||
};
|
||||
typedef enum _amd_bits_t amd_bits_t;
|
||||
|
||||
|
||||
|
||||
int cpu_ident_internal(struct cpu_raw_data_t* raw, struct cpu_id_t* data,
|
||||
struct internal_id_info_t* internal);
|
||||
|
||||
93
src/3rdparty/libcpuid/libcpuid_util.c
vendored
Normal file
93
src/3rdparty/libcpuid/libcpuid_util.c
vendored
Normal file
@@ -0,0 +1,93 @@
|
||||
/*
|
||||
* Copyright 2008 Veselin Georgiev,
|
||||
* anrieffNOSPAM @ mgail_DOT.com (convert to gmail)
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdarg.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
#include "libcpuid.h"
|
||||
#include "libcpuid_util.h"
|
||||
|
||||
void match_features(const struct feature_map_t* matchtable, int count, uint32_t reg, struct cpu_id_t* data)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < count; i++)
|
||||
if (reg & (1u << matchtable[i].bit))
|
||||
data->flags[matchtable[i].feature] = 1;
|
||||
}
|
||||
|
||||
static int xmatch_entry(char c, const char* p)
|
||||
{
|
||||
int i, j;
|
||||
if (c == 0) return -1;
|
||||
if (c == p[0]) return 1;
|
||||
if (p[0] == '.') return 1;
|
||||
if (p[0] == '#' && isdigit(c)) return 1;
|
||||
if (p[0] == '[') {
|
||||
j = 1;
|
||||
while (p[j] && p[j] != ']') j++;
|
||||
if (!p[j]) return -1;
|
||||
for (i = 1; i < j; i++)
|
||||
if (p[i] == c) return j + 1;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
int match_pattern(const char* s, const char* p)
|
||||
{
|
||||
int i, j, dj, k, n, m;
|
||||
n = (int) strlen(s);
|
||||
m = (int) strlen(p);
|
||||
for (i = 0; i < n; i++) {
|
||||
if (xmatch_entry(s[i], p) != -1) {
|
||||
j = 0;
|
||||
k = 0;
|
||||
while (j < m && ((dj = xmatch_entry(s[i + k], p + j)) != -1)) {
|
||||
k++;
|
||||
j += dj;
|
||||
}
|
||||
if (j == m) return i + 1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct cpu_id_t* get_cached_cpuid(void)
|
||||
{
|
||||
static int initialized = 0;
|
||||
static struct cpu_id_t id;
|
||||
if (initialized) return &id;
|
||||
if (cpu_identify(NULL, &id))
|
||||
memset(&id, 0, sizeof(id));
|
||||
initialized = 1;
|
||||
return &id;
|
||||
}
|
||||
|
||||
int match_all(uint64_t bits, uint64_t mask)
|
||||
{
|
||||
return (bits & mask) == mask;
|
||||
}
|
||||
@@ -28,8 +28,6 @@
|
||||
|
||||
#define COUNT_OF(array) (sizeof(array) / sizeof(array[0]))
|
||||
|
||||
#define LBIT(x) (((long long) 1) << x)
|
||||
|
||||
struct feature_map_t {
|
||||
unsigned bit;
|
||||
cpu_feature_t feature;
|
||||
@@ -50,20 +48,6 @@ struct match_entry_t {
|
||||
int match_cpu_codename(const struct match_entry_t* matchtable, int count,
|
||||
struct cpu_id_t* data, int brand_code, uint64_t bits,
|
||||
int model_code);
|
||||
|
||||
void warnf(const char* format, ...)
|
||||
#ifdef __GNUC__
|
||||
__attribute__((format(printf, 1, 2)))
|
||||
#endif
|
||||
;
|
||||
void debugf(int verboselevel, const char* format, ...)
|
||||
#ifdef __GNUC__
|
||||
__attribute__((format(printf, 2, 3)))
|
||||
#endif
|
||||
;
|
||||
void generic_get_cpu_list(const struct match_entry_t* matchtable, int count,
|
||||
struct cpu_list_t* list);
|
||||
|
||||
/*
|
||||
* Seek for a pattern in `haystack'.
|
||||
* Pattern may be an fixed string, or contain the special metacharacters
|
||||
@@ -86,15 +70,9 @@ struct cpu_id_t* get_cached_cpuid(void);
|
||||
/* returns true if all bits of mask are present in `bits'. */
|
||||
int match_all(uint64_t bits, uint64_t mask);
|
||||
|
||||
/* print what bits a mask consists of */
|
||||
void debug_print_lbits(int debuglevel, uint64_t mask);
|
||||
|
||||
/*
|
||||
* Sets the current errno
|
||||
*/
|
||||
int set_error(cpu_error_t err);
|
||||
|
||||
extern libcpuid_warn_fn_t _warn_fun;
|
||||
extern int _current_verboselevel;
|
||||
|
||||
#endif /* __LIBCPUID_UTIL_H__ */
|
||||
359
src/3rdparty/libcpuid/masm-x64.asm
vendored
Normal file
359
src/3rdparty/libcpuid/masm-x64.asm
vendored
Normal file
@@ -0,0 +1,359 @@
|
||||
|
||||
.code
|
||||
; procedure exec_cpuid
|
||||
; Signature: void exec_cpiud(uint32_t *regs)
|
||||
exec_cpuid Proc
|
||||
push rbx
|
||||
push rcx
|
||||
push rdx
|
||||
push rdi
|
||||
|
||||
mov rdi, rcx
|
||||
|
||||
mov eax, [rdi]
|
||||
mov ebx, [rdi+4]
|
||||
mov ecx, [rdi+8]
|
||||
mov edx, [rdi+12]
|
||||
|
||||
cpuid
|
||||
|
||||
mov [rdi], eax
|
||||
mov [rdi+4], ebx
|
||||
mov [rdi+8], ecx
|
||||
mov [rdi+12], edx
|
||||
pop rdi
|
||||
pop rdx
|
||||
pop rcx
|
||||
pop rbx
|
||||
ret
|
||||
exec_cpuid endp
|
||||
|
||||
; procedure cpu_rdtsc
|
||||
; Signature: void cpu_rdtsc(uint64_t *result)
|
||||
cpu_rdtsc Proc
|
||||
push rdx
|
||||
rdtsc
|
||||
mov [rcx], eax
|
||||
mov [rcx+4], edx
|
||||
pop rdx
|
||||
ret
|
||||
cpu_rdtsc endp
|
||||
|
||||
; procedure busy_sse_loop
|
||||
; Signature: void busy_sse_loop(int cycles)
|
||||
busy_sse_loop Proc
|
||||
; save xmm6 & xmm7 into the shadow area, as Visual C++ 2008
|
||||
; expects that we don't touch them:
|
||||
movups [rsp + 8], xmm6
|
||||
movups [rsp + 24], xmm7
|
||||
|
||||
xorps xmm0, xmm0
|
||||
xorps xmm1, xmm1
|
||||
xorps xmm2, xmm2
|
||||
xorps xmm3, xmm3
|
||||
xorps xmm4, xmm4
|
||||
xorps xmm5, xmm5
|
||||
xorps xmm6, xmm6
|
||||
xorps xmm7, xmm7
|
||||
; --
|
||||
align 16
|
||||
bsLoop:
|
||||
; 0:
|
||||
addps xmm0, xmm1
|
||||
addps xmm1, xmm2
|
||||
addps xmm2, xmm3
|
||||
addps xmm3, xmm4
|
||||
addps xmm4, xmm5
|
||||
addps xmm5, xmm6
|
||||
addps xmm6, xmm7
|
||||
addps xmm7, xmm0
|
||||
; 1:
|
||||
addps xmm0, xmm1
|
||||
addps xmm1, xmm2
|
||||
addps xmm2, xmm3
|
||||
addps xmm3, xmm4
|
||||
addps xmm4, xmm5
|
||||
addps xmm5, xmm6
|
||||
addps xmm6, xmm7
|
||||
addps xmm7, xmm0
|
||||
; 2:
|
||||
addps xmm0, xmm1
|
||||
addps xmm1, xmm2
|
||||
addps xmm2, xmm3
|
||||
addps xmm3, xmm4
|
||||
addps xmm4, xmm5
|
||||
addps xmm5, xmm6
|
||||
addps xmm6, xmm7
|
||||
addps xmm7, xmm0
|
||||
; 3:
|
||||
addps xmm0, xmm1
|
||||
addps xmm1, xmm2
|
||||
addps xmm2, xmm3
|
||||
addps xmm3, xmm4
|
||||
addps xmm4, xmm5
|
||||
addps xmm5, xmm6
|
||||
addps xmm6, xmm7
|
||||
addps xmm7, xmm0
|
||||
; 4:
|
||||
addps xmm0, xmm1
|
||||
addps xmm1, xmm2
|
||||
addps xmm2, xmm3
|
||||
addps xmm3, xmm4
|
||||
addps xmm4, xmm5
|
||||
addps xmm5, xmm6
|
||||
addps xmm6, xmm7
|
||||
addps xmm7, xmm0
|
||||
; 5:
|
||||
addps xmm0, xmm1
|
||||
addps xmm1, xmm2
|
||||
addps xmm2, xmm3
|
||||
addps xmm3, xmm4
|
||||
addps xmm4, xmm5
|
||||
addps xmm5, xmm6
|
||||
addps xmm6, xmm7
|
||||
addps xmm7, xmm0
|
||||
; 6:
|
||||
addps xmm0, xmm1
|
||||
addps xmm1, xmm2
|
||||
addps xmm2, xmm3
|
||||
addps xmm3, xmm4
|
||||
addps xmm4, xmm5
|
||||
addps xmm5, xmm6
|
||||
addps xmm6, xmm7
|
||||
addps xmm7, xmm0
|
||||
; 7:
|
||||
addps xmm0, xmm1
|
||||
addps xmm1, xmm2
|
||||
addps xmm2, xmm3
|
||||
addps xmm3, xmm4
|
||||
addps xmm4, xmm5
|
||||
addps xmm5, xmm6
|
||||
addps xmm6, xmm7
|
||||
addps xmm7, xmm0
|
||||
; 8:
|
||||
addps xmm0, xmm1
|
||||
addps xmm1, xmm2
|
||||
addps xmm2, xmm3
|
||||
addps xmm3, xmm4
|
||||
addps xmm4, xmm5
|
||||
addps xmm5, xmm6
|
||||
addps xmm6, xmm7
|
||||
addps xmm7, xmm0
|
||||
; 9:
|
||||
addps xmm0, xmm1
|
||||
addps xmm1, xmm2
|
||||
addps xmm2, xmm3
|
||||
addps xmm3, xmm4
|
||||
addps xmm4, xmm5
|
||||
addps xmm5, xmm6
|
||||
addps xmm6, xmm7
|
||||
addps xmm7, xmm0
|
||||
; 10:
|
||||
addps xmm0, xmm1
|
||||
addps xmm1, xmm2
|
||||
addps xmm2, xmm3
|
||||
addps xmm3, xmm4
|
||||
addps xmm4, xmm5
|
||||
addps xmm5, xmm6
|
||||
addps xmm6, xmm7
|
||||
addps xmm7, xmm0
|
||||
; 11:
|
||||
addps xmm0, xmm1
|
||||
addps xmm1, xmm2
|
||||
addps xmm2, xmm3
|
||||
addps xmm3, xmm4
|
||||
addps xmm4, xmm5
|
||||
addps xmm5, xmm6
|
||||
addps xmm6, xmm7
|
||||
addps xmm7, xmm0
|
||||
; 12:
|
||||
addps xmm0, xmm1
|
||||
addps xmm1, xmm2
|
||||
addps xmm2, xmm3
|
||||
addps xmm3, xmm4
|
||||
addps xmm4, xmm5
|
||||
addps xmm5, xmm6
|
||||
addps xmm6, xmm7
|
||||
addps xmm7, xmm0
|
||||
; 13:
|
||||
addps xmm0, xmm1
|
||||
addps xmm1, xmm2
|
||||
addps xmm2, xmm3
|
||||
addps xmm3, xmm4
|
||||
addps xmm4, xmm5
|
||||
addps xmm5, xmm6
|
||||
addps xmm6, xmm7
|
||||
addps xmm7, xmm0
|
||||
; 14:
|
||||
addps xmm0, xmm1
|
||||
addps xmm1, xmm2
|
||||
addps xmm2, xmm3
|
||||
addps xmm3, xmm4
|
||||
addps xmm4, xmm5
|
||||
addps xmm5, xmm6
|
||||
addps xmm6, xmm7
|
||||
addps xmm7, xmm0
|
||||
; 15:
|
||||
addps xmm0, xmm1
|
||||
addps xmm1, xmm2
|
||||
addps xmm2, xmm3
|
||||
addps xmm3, xmm4
|
||||
addps xmm4, xmm5
|
||||
addps xmm5, xmm6
|
||||
addps xmm6, xmm7
|
||||
addps xmm7, xmm0
|
||||
; 16:
|
||||
addps xmm0, xmm1
|
||||
addps xmm1, xmm2
|
||||
addps xmm2, xmm3
|
||||
addps xmm3, xmm4
|
||||
addps xmm4, xmm5
|
||||
addps xmm5, xmm6
|
||||
addps xmm6, xmm7
|
||||
addps xmm7, xmm0
|
||||
; 17:
|
||||
addps xmm0, xmm1
|
||||
addps xmm1, xmm2
|
||||
addps xmm2, xmm3
|
||||
addps xmm3, xmm4
|
||||
addps xmm4, xmm5
|
||||
addps xmm5, xmm6
|
||||
addps xmm6, xmm7
|
||||
addps xmm7, xmm0
|
||||
; 18:
|
||||
addps xmm0, xmm1
|
||||
addps xmm1, xmm2
|
||||
addps xmm2, xmm3
|
||||
addps xmm3, xmm4
|
||||
addps xmm4, xmm5
|
||||
addps xmm5, xmm6
|
||||
addps xmm6, xmm7
|
||||
addps xmm7, xmm0
|
||||
; 19:
|
||||
addps xmm0, xmm1
|
||||
addps xmm1, xmm2
|
||||
addps xmm2, xmm3
|
||||
addps xmm3, xmm4
|
||||
addps xmm4, xmm5
|
||||
addps xmm5, xmm6
|
||||
addps xmm6, xmm7
|
||||
addps xmm7, xmm0
|
||||
; 20:
|
||||
addps xmm0, xmm1
|
||||
addps xmm1, xmm2
|
||||
addps xmm2, xmm3
|
||||
addps xmm3, xmm4
|
||||
addps xmm4, xmm5
|
||||
addps xmm5, xmm6
|
||||
addps xmm6, xmm7
|
||||
addps xmm7, xmm0
|
||||
; 21:
|
||||
addps xmm0, xmm1
|
||||
addps xmm1, xmm2
|
||||
addps xmm2, xmm3
|
||||
addps xmm3, xmm4
|
||||
addps xmm4, xmm5
|
||||
addps xmm5, xmm6
|
||||
addps xmm6, xmm7
|
||||
addps xmm7, xmm0
|
||||
; 22:
|
||||
addps xmm0, xmm1
|
||||
addps xmm1, xmm2
|
||||
addps xmm2, xmm3
|
||||
addps xmm3, xmm4
|
||||
addps xmm4, xmm5
|
||||
addps xmm5, xmm6
|
||||
addps xmm6, xmm7
|
||||
addps xmm7, xmm0
|
||||
; 23:
|
||||
addps xmm0, xmm1
|
||||
addps xmm1, xmm2
|
||||
addps xmm2, xmm3
|
||||
addps xmm3, xmm4
|
||||
addps xmm4, xmm5
|
||||
addps xmm5, xmm6
|
||||
addps xmm6, xmm7
|
||||
addps xmm7, xmm0
|
||||
; 24:
|
||||
addps xmm0, xmm1
|
||||
addps xmm1, xmm2
|
||||
addps xmm2, xmm3
|
||||
addps xmm3, xmm4
|
||||
addps xmm4, xmm5
|
||||
addps xmm5, xmm6
|
||||
addps xmm6, xmm7
|
||||
addps xmm7, xmm0
|
||||
; 25:
|
||||
addps xmm0, xmm1
|
||||
addps xmm1, xmm2
|
||||
addps xmm2, xmm3
|
||||
addps xmm3, xmm4
|
||||
addps xmm4, xmm5
|
||||
addps xmm5, xmm6
|
||||
addps xmm6, xmm7
|
||||
addps xmm7, xmm0
|
||||
; 26:
|
||||
addps xmm0, xmm1
|
||||
addps xmm1, xmm2
|
||||
addps xmm2, xmm3
|
||||
addps xmm3, xmm4
|
||||
addps xmm4, xmm5
|
||||
addps xmm5, xmm6
|
||||
addps xmm6, xmm7
|
||||
addps xmm7, xmm0
|
||||
; 27:
|
||||
addps xmm0, xmm1
|
||||
addps xmm1, xmm2
|
||||
addps xmm2, xmm3
|
||||
addps xmm3, xmm4
|
||||
addps xmm4, xmm5
|
||||
addps xmm5, xmm6
|
||||
addps xmm6, xmm7
|
||||
addps xmm7, xmm0
|
||||
; 28:
|
||||
addps xmm0, xmm1
|
||||
addps xmm1, xmm2
|
||||
addps xmm2, xmm3
|
||||
addps xmm3, xmm4
|
||||
addps xmm4, xmm5
|
||||
addps xmm5, xmm6
|
||||
addps xmm6, xmm7
|
||||
addps xmm7, xmm0
|
||||
; 29:
|
||||
addps xmm0, xmm1
|
||||
addps xmm1, xmm2
|
||||
addps xmm2, xmm3
|
||||
addps xmm3, xmm4
|
||||
addps xmm4, xmm5
|
||||
addps xmm5, xmm6
|
||||
addps xmm6, xmm7
|
||||
addps xmm7, xmm0
|
||||
; 30:
|
||||
addps xmm0, xmm1
|
||||
addps xmm1, xmm2
|
||||
addps xmm2, xmm3
|
||||
addps xmm3, xmm4
|
||||
addps xmm4, xmm5
|
||||
addps xmm5, xmm6
|
||||
addps xmm6, xmm7
|
||||
addps xmm7, xmm0
|
||||
; 31:
|
||||
addps xmm0, xmm1
|
||||
addps xmm1, xmm2
|
||||
addps xmm2, xmm3
|
||||
addps xmm3, xmm4
|
||||
addps xmm4, xmm5
|
||||
addps xmm5, xmm6
|
||||
addps xmm6, xmm7
|
||||
addps xmm7, xmm0
|
||||
; ----------------------
|
||||
dec ecx
|
||||
jnz bsLoop
|
||||
|
||||
; restore xmm6 & xmm7:
|
||||
movups xmm6, [rsp + 8]
|
||||
movups xmm7, [rsp + 24]
|
||||
ret
|
||||
busy_sse_loop endp
|
||||
|
||||
END
|
||||
169
src/3rdparty/libcpuid/recog_amd.c
vendored
Normal file
169
src/3rdparty/libcpuid/recog_amd.c
vendored
Normal file
@@ -0,0 +1,169 @@
|
||||
/*
|
||||
* Copyright 2008 Veselin Georgiev,
|
||||
* anrieffNOSPAM @ mgail_DOT.com (convert to gmail)
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
#include "libcpuid.h"
|
||||
#include "libcpuid_util.h"
|
||||
#include "libcpuid_internal.h"
|
||||
#include "recog_amd.h"
|
||||
|
||||
const struct amd_code_str { amd_code_t code; char *str; } amd_code_str[] = {
|
||||
#define CODE(x) { x, #x }
|
||||
#define CODE2(x, y) CODE(x)
|
||||
#include "amd_code_t.h"
|
||||
#undef CODE
|
||||
};
|
||||
|
||||
struct amd_code_and_bits_t {
|
||||
int code;
|
||||
uint64_t bits;
|
||||
};
|
||||
|
||||
enum _amd_model_codes_t {
|
||||
// Only for Ryzen CPUs:
|
||||
_1400,
|
||||
_1500,
|
||||
_1600,
|
||||
};
|
||||
|
||||
static void load_amd_features(struct cpu_raw_data_t* raw, struct cpu_id_t* data)
|
||||
{
|
||||
const struct feature_map_t matchtable_edx81[] = {
|
||||
{ 20, CPU_FEATURE_NX },
|
||||
{ 22, CPU_FEATURE_MMXEXT },
|
||||
{ 25, CPU_FEATURE_FXSR_OPT },
|
||||
{ 30, CPU_FEATURE_3DNOWEXT },
|
||||
{ 31, CPU_FEATURE_3DNOW },
|
||||
};
|
||||
const struct feature_map_t matchtable_ecx81[] = {
|
||||
{ 1, CPU_FEATURE_CMP_LEGACY },
|
||||
{ 2, CPU_FEATURE_SVM },
|
||||
{ 5, CPU_FEATURE_ABM },
|
||||
{ 6, CPU_FEATURE_SSE4A },
|
||||
{ 7, CPU_FEATURE_MISALIGNSSE },
|
||||
{ 8, CPU_FEATURE_3DNOWPREFETCH },
|
||||
{ 9, CPU_FEATURE_OSVW },
|
||||
{ 10, CPU_FEATURE_IBS },
|
||||
{ 11, CPU_FEATURE_XOP },
|
||||
{ 12, CPU_FEATURE_SKINIT },
|
||||
{ 13, CPU_FEATURE_WDT },
|
||||
{ 16, CPU_FEATURE_FMA4 },
|
||||
{ 21, CPU_FEATURE_TBM },
|
||||
};
|
||||
const struct feature_map_t matchtable_edx87[] = {
|
||||
{ 0, CPU_FEATURE_TS },
|
||||
{ 1, CPU_FEATURE_FID },
|
||||
{ 2, CPU_FEATURE_VID },
|
||||
{ 3, CPU_FEATURE_TTP },
|
||||
{ 4, CPU_FEATURE_TM_AMD },
|
||||
{ 5, CPU_FEATURE_STC },
|
||||
{ 6, CPU_FEATURE_100MHZSTEPS },
|
||||
{ 7, CPU_FEATURE_HWPSTATE },
|
||||
/* id 8 is handled in common */
|
||||
{ 9, CPU_FEATURE_CPB },
|
||||
{ 10, CPU_FEATURE_APERFMPERF },
|
||||
{ 11, CPU_FEATURE_PFI },
|
||||
{ 12, CPU_FEATURE_PA },
|
||||
};
|
||||
if (raw->ext_cpuid[0][0] >= 0x80000001) {
|
||||
match_features(matchtable_edx81, COUNT_OF(matchtable_edx81), raw->ext_cpuid[1][3], data);
|
||||
match_features(matchtable_ecx81, COUNT_OF(matchtable_ecx81), raw->ext_cpuid[1][2], data);
|
||||
}
|
||||
if (raw->ext_cpuid[0][0] >= 0x80000007)
|
||||
match_features(matchtable_edx87, COUNT_OF(matchtable_edx87), raw->ext_cpuid[7][3], data);
|
||||
if (raw->ext_cpuid[0][0] >= 0x8000001a) {
|
||||
/* We have the extended info about SSE unit size */
|
||||
data->detection_hints[CPU_HINT_SSE_SIZE_AUTH] = 1;
|
||||
data->sse_size = (raw->ext_cpuid[0x1a][0] & 1) ? 128 : 64;
|
||||
}
|
||||
}
|
||||
|
||||
static void decode_amd_cache_info(struct cpu_raw_data_t* raw, struct cpu_id_t* data)
|
||||
{
|
||||
int l3_result;
|
||||
const int assoc_table[16] = {
|
||||
0, 1, 2, 0, 4, 0, 8, 0, 16, 0, 32, 48, 64, 96, 128, 255
|
||||
};
|
||||
unsigned n = raw->ext_cpuid[0][0];
|
||||
|
||||
if (n >= 0x80000005) {
|
||||
data->l1_data_cache = (raw->ext_cpuid[5][2] >> 24) & 0xff;
|
||||
data->l1_assoc = (raw->ext_cpuid[5][2] >> 16) & 0xff;
|
||||
data->l1_cacheline = (raw->ext_cpuid[5][2]) & 0xff;
|
||||
data->l1_instruction_cache = (raw->ext_cpuid[5][3] >> 24) & 0xff;
|
||||
}
|
||||
if (n >= 0x80000006) {
|
||||
data->l2_cache = (raw->ext_cpuid[6][2] >> 16) & 0xffff;
|
||||
data->l2_assoc = assoc_table[(raw->ext_cpuid[6][2] >> 12) & 0xf];
|
||||
data->l2_cacheline = (raw->ext_cpuid[6][2]) & 0xff;
|
||||
|
||||
l3_result = (raw->ext_cpuid[6][3] >> 18);
|
||||
if (l3_result > 0) {
|
||||
l3_result = 512 * l3_result; /* AMD spec says it's a range,
|
||||
but we take the lower bound */
|
||||
data->l3_cache = l3_result;
|
||||
data->l3_assoc = assoc_table[(raw->ext_cpuid[6][3] >> 12) & 0xf];
|
||||
data->l3_cacheline = (raw->ext_cpuid[6][3]) & 0xff;
|
||||
} else {
|
||||
data->l3_cache = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void decode_amd_number_of_cores(struct cpu_raw_data_t* raw, struct cpu_id_t* data)
|
||||
{
|
||||
int logical_cpus = -1, num_cores = -1;
|
||||
|
||||
if (raw->basic_cpuid[0][0] >= 1) {
|
||||
logical_cpus = (raw->basic_cpuid[1][1] >> 16) & 0xff;
|
||||
if (raw->ext_cpuid[0][0] >= 8) {
|
||||
num_cores = 1 + (raw->ext_cpuid[8][2] & 0xff);
|
||||
}
|
||||
}
|
||||
if (data->flags[CPU_FEATURE_HT]) {
|
||||
if (num_cores > 1) {
|
||||
if (data->ext_family >= 23)
|
||||
num_cores /= 2; // e.g., Ryzen 7 reports 16 "real" cores, but they are really just 8.
|
||||
data->num_cores = num_cores;
|
||||
data->num_logical_cpus = logical_cpus;
|
||||
} else {
|
||||
data->num_cores = 1;
|
||||
data->num_logical_cpus = (logical_cpus >= 2 ? logical_cpus : 2);
|
||||
}
|
||||
} else {
|
||||
data->num_cores = data->num_logical_cpus = 1;
|
||||
}
|
||||
}
|
||||
|
||||
int cpuid_identify_amd(struct cpu_raw_data_t* raw, struct cpu_id_t* data, struct internal_id_info_t* internal)
|
||||
{
|
||||
load_amd_features(raw, data);
|
||||
decode_amd_cache_info(raw, data);
|
||||
decode_amd_number_of_cores(raw, data);
|
||||
return 0;
|
||||
}
|
||||
@@ -27,6 +27,5 @@
|
||||
#define __RECOG_AMD_H__
|
||||
|
||||
int cpuid_identify_amd(struct cpu_raw_data_t* raw, struct cpu_id_t* data, struct internal_id_info_t* internal);
|
||||
void cpuid_get_list_amd(struct cpu_list_t* list);
|
||||
|
||||
#endif /* __RECOG_AMD_H__ */
|
||||
542
src/3rdparty/libcpuid/recog_intel.c
vendored
Normal file
542
src/3rdparty/libcpuid/recog_intel.c
vendored
Normal file
@@ -0,0 +1,542 @@
|
||||
/*
|
||||
* Copyright 2008 Veselin Georgiev,
|
||||
* anrieffNOSPAM @ mgail_DOT.com (convert to gmail)
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
#include "libcpuid.h"
|
||||
#include "libcpuid_util.h"
|
||||
#include "libcpuid_internal.h"
|
||||
#include "recog_intel.h"
|
||||
|
||||
const struct intel_bcode_str { intel_code_t code; char *str; } intel_bcode_str[] = {
|
||||
#define CODE(x) { x, #x }
|
||||
#define CODE2(x, y) CODE(x)
|
||||
#include "intel_code_t.h"
|
||||
#undef CODE
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
int code;
|
||||
uint64_t bits;
|
||||
} intel_code_and_bits_t;
|
||||
|
||||
enum _intel_model_t {
|
||||
UNKNOWN = -1,
|
||||
_3000 = 100,
|
||||
_3100,
|
||||
_3200,
|
||||
X3200,
|
||||
_3300,
|
||||
X3300,
|
||||
_5100,
|
||||
_5200,
|
||||
_5300,
|
||||
_5400,
|
||||
_2xxx, /* Core i[357] 2xxx */
|
||||
_3xxx, /* Core i[357] 3xxx */
|
||||
};
|
||||
typedef enum _intel_model_t intel_model_t;
|
||||
|
||||
static void load_intel_features(struct cpu_raw_data_t* raw, struct cpu_id_t* data)
|
||||
{
|
||||
const struct feature_map_t matchtable_edx1[] = {
|
||||
{ 18, CPU_FEATURE_PN },
|
||||
{ 21, CPU_FEATURE_DTS },
|
||||
{ 22, CPU_FEATURE_ACPI },
|
||||
{ 27, CPU_FEATURE_SS },
|
||||
{ 29, CPU_FEATURE_TM },
|
||||
{ 30, CPU_FEATURE_IA64 },
|
||||
{ 31, CPU_FEATURE_PBE },
|
||||
};
|
||||
const struct feature_map_t matchtable_ecx1[] = {
|
||||
{ 2, CPU_FEATURE_DTS64 },
|
||||
{ 4, CPU_FEATURE_DS_CPL },
|
||||
{ 5, CPU_FEATURE_VMX },
|
||||
{ 6, CPU_FEATURE_SMX },
|
||||
{ 7, CPU_FEATURE_EST },
|
||||
{ 8, CPU_FEATURE_TM2 },
|
||||
{ 10, CPU_FEATURE_CID },
|
||||
{ 14, CPU_FEATURE_XTPR },
|
||||
{ 15, CPU_FEATURE_PDCM },
|
||||
{ 18, CPU_FEATURE_DCA },
|
||||
{ 21, CPU_FEATURE_X2APIC },
|
||||
};
|
||||
const struct feature_map_t matchtable_edx81[] = {
|
||||
{ 20, CPU_FEATURE_XD },
|
||||
};
|
||||
const struct feature_map_t matchtable_ebx7[] = {
|
||||
{ 2, CPU_FEATURE_SGX },
|
||||
{ 4, CPU_FEATURE_HLE },
|
||||
{ 11, CPU_FEATURE_RTM },
|
||||
{ 16, CPU_FEATURE_AVX512F },
|
||||
{ 17, CPU_FEATURE_AVX512DQ },
|
||||
{ 18, CPU_FEATURE_RDSEED },
|
||||
{ 19, CPU_FEATURE_ADX },
|
||||
{ 26, CPU_FEATURE_AVX512PF },
|
||||
{ 27, CPU_FEATURE_AVX512ER },
|
||||
{ 28, CPU_FEATURE_AVX512CD },
|
||||
{ 29, CPU_FEATURE_SHA_NI },
|
||||
{ 30, CPU_FEATURE_AVX512BW },
|
||||
{ 31, CPU_FEATURE_AVX512VL },
|
||||
};
|
||||
if (raw->basic_cpuid[0][0] >= 1) {
|
||||
match_features(matchtable_edx1, COUNT_OF(matchtable_edx1), raw->basic_cpuid[1][3], data);
|
||||
match_features(matchtable_ecx1, COUNT_OF(matchtable_ecx1), raw->basic_cpuid[1][2], data);
|
||||
}
|
||||
if (raw->ext_cpuid[0][0] >= 1) {
|
||||
match_features(matchtable_edx81, COUNT_OF(matchtable_edx81), raw->ext_cpuid[1][3], data);
|
||||
}
|
||||
// detect TSX/AVX512:
|
||||
if (raw->basic_cpuid[0][0] >= 7) {
|
||||
match_features(matchtable_ebx7, COUNT_OF(matchtable_ebx7), raw->basic_cpuid[7][1], data);
|
||||
}
|
||||
}
|
||||
|
||||
enum _cache_type_t {
|
||||
L1I,
|
||||
L1D,
|
||||
L2,
|
||||
L3,
|
||||
L4
|
||||
};
|
||||
typedef enum _cache_type_t cache_type_t;
|
||||
|
||||
static void check_case(uint8_t on, cache_type_t cache, int size, int assoc, int linesize, struct cpu_id_t* data)
|
||||
{
|
||||
if (!on) return;
|
||||
switch (cache) {
|
||||
case L1I:
|
||||
data->l1_instruction_cache = size;
|
||||
break;
|
||||
case L1D:
|
||||
data->l1_data_cache = size;
|
||||
data->l1_assoc = assoc;
|
||||
data->l1_cacheline = linesize;
|
||||
break;
|
||||
case L2:
|
||||
data->l2_cache = size;
|
||||
data->l2_assoc = assoc;
|
||||
data->l2_cacheline = linesize;
|
||||
break;
|
||||
case L3:
|
||||
data->l3_cache = size;
|
||||
data->l3_assoc = assoc;
|
||||
data->l3_cacheline = linesize;
|
||||
break;
|
||||
case L4:
|
||||
data->l4_cache = size;
|
||||
data->l4_assoc = assoc;
|
||||
data->l4_cacheline = linesize;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void decode_intel_oldstyle_cache_info(struct cpu_raw_data_t* raw, struct cpu_id_t* data)
|
||||
{
|
||||
uint8_t f[256] = {0};
|
||||
int reg, off;
|
||||
uint32_t x;
|
||||
for (reg = 0; reg < 4; reg++) {
|
||||
x = raw->basic_cpuid[2][reg];
|
||||
if (x & 0x80000000) continue;
|
||||
for (off = 0; off < 4; off++) {
|
||||
f[x & 0xff] = 1;
|
||||
x >>= 8;
|
||||
}
|
||||
}
|
||||
|
||||
check_case(f[0x06], L1I, 8, 4, 32, data);
|
||||
check_case(f[0x08], L1I, 16, 4, 32, data);
|
||||
check_case(f[0x0A], L1D, 8, 2, 32, data);
|
||||
check_case(f[0x0C], L1D, 16, 4, 32, data);
|
||||
check_case(f[0x22], L3, 512, 4, 64, data);
|
||||
check_case(f[0x23], L3, 1024, 8, 64, data);
|
||||
check_case(f[0x25], L3, 2048, 8, 64, data);
|
||||
check_case(f[0x29], L3, 4096, 8, 64, data);
|
||||
check_case(f[0x2C], L1D, 32, 8, 64, data);
|
||||
check_case(f[0x30], L1I, 32, 8, 64, data);
|
||||
check_case(f[0x39], L2, 128, 4, 64, data);
|
||||
check_case(f[0x3A], L2, 192, 6, 64, data);
|
||||
check_case(f[0x3B], L2, 128, 2, 64, data);
|
||||
check_case(f[0x3C], L2, 256, 4, 64, data);
|
||||
check_case(f[0x3D], L2, 384, 6, 64, data);
|
||||
check_case(f[0x3E], L2, 512, 4, 64, data);
|
||||
check_case(f[0x41], L2, 128, 4, 32, data);
|
||||
check_case(f[0x42], L2, 256, 4, 32, data);
|
||||
check_case(f[0x43], L2, 512, 4, 32, data);
|
||||
check_case(f[0x44], L2, 1024, 4, 32, data);
|
||||
check_case(f[0x45], L2, 2048, 4, 32, data);
|
||||
check_case(f[0x46], L3, 4096, 4, 64, data);
|
||||
check_case(f[0x47], L3, 8192, 8, 64, data);
|
||||
check_case(f[0x4A], L3, 6144, 12, 64, data);
|
||||
check_case(f[0x4B], L3, 8192, 16, 64, data);
|
||||
check_case(f[0x4C], L3, 12288, 12, 64, data);
|
||||
check_case(f[0x4D], L3, 16384, 16, 64, data);
|
||||
check_case(f[0x4E], L2, 6144, 24, 64, data);
|
||||
check_case(f[0x60], L1D, 16, 8, 64, data);
|
||||
check_case(f[0x66], L1D, 8, 4, 64, data);
|
||||
check_case(f[0x67], L1D, 16, 4, 64, data);
|
||||
check_case(f[0x68], L1D, 32, 4, 64, data);
|
||||
/* The following four entries are trace cache. Intel does not
|
||||
* specify a cache-line size, so we use -1 instead
|
||||
*/
|
||||
check_case(f[0x70], L1I, 12, 8, -1, data);
|
||||
check_case(f[0x71], L1I, 16, 8, -1, data);
|
||||
check_case(f[0x72], L1I, 32, 8, -1, data);
|
||||
check_case(f[0x73], L1I, 64, 8, -1, data);
|
||||
|
||||
check_case(f[0x78], L2, 1024, 4, 64, data);
|
||||
check_case(f[0x79], L2, 128, 8, 64, data);
|
||||
check_case(f[0x7A], L2, 256, 8, 64, data);
|
||||
check_case(f[0x7B], L2, 512, 8, 64, data);
|
||||
check_case(f[0x7C], L2, 1024, 8, 64, data);
|
||||
check_case(f[0x7D], L2, 2048, 8, 64, data);
|
||||
check_case(f[0x7F], L2, 512, 2, 64, data);
|
||||
check_case(f[0x82], L2, 256, 8, 32, data);
|
||||
check_case(f[0x83], L2, 512, 8, 32, data);
|
||||
check_case(f[0x84], L2, 1024, 8, 32, data);
|
||||
check_case(f[0x85], L2, 2048, 8, 32, data);
|
||||
check_case(f[0x86], L2, 512, 4, 64, data);
|
||||
check_case(f[0x87], L2, 1024, 8, 64, data);
|
||||
|
||||
if (f[0x49]) {
|
||||
/* This flag is overloaded with two meanings. On Xeon MP
|
||||
* (family 0xf, model 0x6) this means L3 cache. On all other
|
||||
* CPUs (notably Conroe et al), this is L2 cache. In both cases
|
||||
* it means 4MB, 16-way associative, 64-byte line size.
|
||||
*/
|
||||
if (data->family == 0xf && data->model == 0x6) {
|
||||
data->l3_cache = 4096;
|
||||
data->l3_assoc = 16;
|
||||
data->l3_cacheline = 64;
|
||||
} else {
|
||||
data->l2_cache = 4096;
|
||||
data->l2_assoc = 16;
|
||||
data->l2_cacheline = 64;
|
||||
}
|
||||
}
|
||||
if (f[0x40]) {
|
||||
/* Again, a special flag. It means:
|
||||
* 1) If no L2 is specified, then CPU is w/o L2 (0 KB)
|
||||
* 2) If L2 is specified by other flags, then, CPU is w/o L3.
|
||||
*/
|
||||
if (data->l2_cache == -1) {
|
||||
data->l2_cache = 0;
|
||||
} else {
|
||||
data->l3_cache = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void decode_intel_deterministic_cache_info(struct cpu_raw_data_t* raw,
|
||||
struct cpu_id_t* data)
|
||||
{
|
||||
int ecx;
|
||||
int ways, partitions, linesize, sets, size, level, typenumber;
|
||||
cache_type_t type;
|
||||
for (ecx = 0; ecx < MAX_INTELFN4_LEVEL; ecx++) {
|
||||
typenumber = raw->intel_fn4[ecx][0] & 0x1f;
|
||||
if (typenumber == 0) break;
|
||||
level = (raw->intel_fn4[ecx][0] >> 5) & 0x7;
|
||||
if (level == 1 && typenumber == 1)
|
||||
type = L1D;
|
||||
else if (level == 1 && typenumber == 2)
|
||||
type = L1I;
|
||||
else if (level == 2 && typenumber == 3)
|
||||
type = L2;
|
||||
else if (level == 3 && typenumber == 3)
|
||||
type = L3;
|
||||
else if (level == 4 && typenumber == 3)
|
||||
type = L4;
|
||||
else {
|
||||
continue;
|
||||
}
|
||||
ways = ((raw->intel_fn4[ecx][1] >> 22) & 0x3ff) + 1;
|
||||
partitions = ((raw->intel_fn4[ecx][1] >> 12) & 0x3ff) + 1;
|
||||
linesize = (raw->intel_fn4[ecx][1] & 0xfff) + 1;
|
||||
sets = raw->intel_fn4[ecx][2] + 1;
|
||||
size = ways * partitions * linesize * sets / 1024;
|
||||
check_case(1, type, size, ways, linesize, data);
|
||||
}
|
||||
}
|
||||
|
||||
static int decode_intel_extended_topology(struct cpu_raw_data_t* raw,
|
||||
struct cpu_id_t* data)
|
||||
{
|
||||
int i, level_type, num_smt = -1, num_core = -1;
|
||||
for (i = 0; i < MAX_INTELFN11_LEVEL; i++) {
|
||||
level_type = (raw->intel_fn11[i][2] & 0xff00) >> 8;
|
||||
switch (level_type) {
|
||||
case 0x01:
|
||||
num_smt = raw->intel_fn11[i][1] & 0xffff;
|
||||
break;
|
||||
case 0x02:
|
||||
num_core = raw->intel_fn11[i][1] & 0xffff;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (num_smt == -1 || num_core == -1) return 0;
|
||||
data->num_logical_cpus = num_core;
|
||||
data->num_cores = num_core / num_smt;
|
||||
// make sure num_cores is at least 1. In VMs, the CPUID instruction
|
||||
// is rigged and may give nonsensical results, but we should at least
|
||||
// avoid outputs like data->num_cores == 0.
|
||||
if (data->num_cores <= 0) data->num_cores = 1;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void decode_intel_number_of_cores(struct cpu_raw_data_t* raw,
|
||||
struct cpu_id_t* data)
|
||||
{
|
||||
int logical_cpus = -1, num_cores = -1;
|
||||
|
||||
if (raw->basic_cpuid[0][0] >= 11) {
|
||||
if (decode_intel_extended_topology(raw, data)) return;
|
||||
}
|
||||
|
||||
if (raw->basic_cpuid[0][0] >= 1) {
|
||||
logical_cpus = (raw->basic_cpuid[1][1] >> 16) & 0xff;
|
||||
if (raw->basic_cpuid[0][0] >= 4) {
|
||||
num_cores = 1 + ((raw->basic_cpuid[4][0] >> 26) & 0x3f);
|
||||
}
|
||||
}
|
||||
if (data->flags[CPU_FEATURE_HT]) {
|
||||
if (num_cores > 1) {
|
||||
data->num_cores = num_cores;
|
||||
data->num_logical_cpus = logical_cpus;
|
||||
} else {
|
||||
data->num_cores = 1;
|
||||
data->num_logical_cpus = (logical_cpus >= 1 ? logical_cpus : 1);
|
||||
if (data->num_logical_cpus == 1)
|
||||
data->flags[CPU_FEATURE_HT] = 0;
|
||||
}
|
||||
} else {
|
||||
data->num_cores = data->num_logical_cpus = 1;
|
||||
}
|
||||
}
|
||||
|
||||
static intel_code_and_bits_t get_brand_code_and_bits(struct cpu_id_t* data)
|
||||
{
|
||||
intel_code_t code = (intel_code_t) NC;
|
||||
intel_code_and_bits_t result;
|
||||
uint64_t bits = 0;
|
||||
int i = 0;
|
||||
const char* bs = data->brand_str;
|
||||
const char* s;
|
||||
const struct { intel_code_t c; const char *search; } matchtable[] = {
|
||||
{ PENTIUM_M, "Pentium(R) M" },
|
||||
{ CORE_SOLO, "Pentium(R) Dual CPU" },
|
||||
{ CORE_SOLO, "Pentium(R) Dual-Core" },
|
||||
{ PENTIUM_D, "Pentium(R) D" },
|
||||
{ CORE_SOLO, "Genuine Intel(R) CPU" },
|
||||
{ CORE_SOLO, "Intel(R) Core(TM)" },
|
||||
{ DIAMONDVILLE, "CPU [N ][23]## " },
|
||||
{ SILVERTHORNE, "CPU Z" },
|
||||
{ PINEVIEW, "CPU [ND][45]## " },
|
||||
{ CEDARVIEW, "CPU [ND]#### " },
|
||||
};
|
||||
|
||||
const struct { uint64_t bit; const char* search; } bit_matchtable[] = {
|
||||
{ XEON_, "Xeon" },
|
||||
{ _MP_, " MP" },
|
||||
{ ATOM_, "Atom(TM) CPU" },
|
||||
{ MOBILE_, "Mobile" },
|
||||
{ CELERON_, "Celeron" },
|
||||
{ PENTIUM_, "Pentium" },
|
||||
};
|
||||
|
||||
for (i = 0; i < COUNT_OF(bit_matchtable); i++) {
|
||||
if (match_pattern(bs, bit_matchtable[i].search))
|
||||
bits |= bit_matchtable[i].bit;
|
||||
}
|
||||
|
||||
if ((i = match_pattern(bs, "Core(TM) [im][357]")) != 0) {
|
||||
bits |= CORE_;
|
||||
i--;
|
||||
switch (bs[i + 9]) {
|
||||
case 'i': bits |= _I_; break;
|
||||
case 'm': bits |= _M_; break;
|
||||
}
|
||||
switch (bs[i + 10]) {
|
||||
case '3': bits |= _3; break;
|
||||
case '5': bits |= _5; break;
|
||||
case '7': bits |= _7; break;
|
||||
}
|
||||
}
|
||||
for (i = 0; i < COUNT_OF(matchtable); i++)
|
||||
if (match_pattern(bs, matchtable[i].search)) {
|
||||
code = matchtable[i].c;
|
||||
break;
|
||||
}
|
||||
if (bits & XEON_) {
|
||||
if (match_pattern(bs, "W35##") || match_pattern(bs, "[ELXW]75##"))
|
||||
bits |= _7;
|
||||
else if (match_pattern(bs, "[ELXW]55##"))
|
||||
code = GAINESTOWN;
|
||||
else if (match_pattern(bs, "[ELXW]56##"))
|
||||
code = WESTMERE;
|
||||
else if (data->l3_cache > 0 && data->family == 16)
|
||||
/* restrict by family, since later Xeons also have L3 ... */
|
||||
code = IRWIN;
|
||||
}
|
||||
if (match_all(bits, XEON_ + _MP_) && data->l3_cache > 0)
|
||||
code = POTOMAC;
|
||||
if (code == CORE_SOLO) {
|
||||
s = strstr(bs, "CPU");
|
||||
if (s) {
|
||||
s += 3;
|
||||
while (*s == ' ') s++;
|
||||
if (*s == 'T')
|
||||
bits |= MOBILE_;
|
||||
}
|
||||
}
|
||||
if (code == CORE_SOLO) {
|
||||
switch (data->num_cores) {
|
||||
case 1: break;
|
||||
case 2:
|
||||
{
|
||||
code = CORE_DUO;
|
||||
if (data->num_logical_cpus > 2)
|
||||
code = DUAL_CORE_HT;
|
||||
break;
|
||||
}
|
||||
case 4:
|
||||
{
|
||||
code = QUAD_CORE;
|
||||
if (data->num_logical_cpus > 4)
|
||||
code = QUAD_CORE_HT;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
code = MORE_THAN_QUADCORE; break;
|
||||
}
|
||||
}
|
||||
|
||||
if (code == CORE_DUO && (bits & MOBILE_) && data->model != 14) {
|
||||
if (data->ext_model < 23) {
|
||||
code = MEROM;
|
||||
} else {
|
||||
code = PENRYN;
|
||||
}
|
||||
}
|
||||
if (data->ext_model == 23 &&
|
||||
(code == CORE_DUO || code == PENTIUM_D || (bits & CELERON_))) {
|
||||
code = WOLFDALE;
|
||||
}
|
||||
|
||||
result.code = code;
|
||||
result.bits = bits;
|
||||
return result;
|
||||
}
|
||||
|
||||
static void decode_intel_sgx_features(const struct cpu_raw_data_t* raw, struct cpu_id_t* data)
|
||||
{
|
||||
struct cpu_epc_t epc;
|
||||
int i;
|
||||
|
||||
if (raw->basic_cpuid[0][0] < 0x12) return; // no 12h leaf
|
||||
if (raw->basic_cpuid[0x12][0] == 0) return; // no sub-leafs available, probably it's disabled by BIOS
|
||||
|
||||
// decode sub-leaf 0:
|
||||
if (raw->basic_cpuid[0x12][0] & 1) data->sgx.flags[INTEL_SGX1] = 1;
|
||||
if (raw->basic_cpuid[0x12][0] & 2) data->sgx.flags[INTEL_SGX2] = 1;
|
||||
if (data->sgx.flags[INTEL_SGX1] || data->sgx.flags[INTEL_SGX2])
|
||||
data->sgx.present = 1;
|
||||
data->sgx.misc_select = raw->basic_cpuid[0x12][1];
|
||||
data->sgx.max_enclave_32bit = (raw->basic_cpuid[0x12][3] ) & 0xff;
|
||||
data->sgx.max_enclave_64bit = (raw->basic_cpuid[0x12][3] >> 8) & 0xff;
|
||||
|
||||
// decode sub-leaf 1:
|
||||
data->sgx.secs_attributes = raw->intel_fn12h[1][0] | (((uint64_t) raw->intel_fn12h[1][1]) << 32);
|
||||
data->sgx.secs_xfrm = raw->intel_fn12h[1][2] | (((uint64_t) raw->intel_fn12h[1][3]) << 32);
|
||||
|
||||
// decode higher-order subleafs, whenever present:
|
||||
data->sgx.num_epc_sections = -1;
|
||||
for (i = 0; i < 1000000; i++) {
|
||||
epc = cpuid_get_epc(i, raw);
|
||||
if (epc.length == 0) {
|
||||
data->sgx.num_epc_sections = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (data->sgx.num_epc_sections == -1) {
|
||||
data->sgx.num_epc_sections = 1000000;
|
||||
}
|
||||
}
|
||||
|
||||
struct cpu_epc_t cpuid_get_epc(int index, const struct cpu_raw_data_t* raw)
|
||||
{
|
||||
uint32_t regs[4];
|
||||
struct cpu_epc_t retval = {0, 0};
|
||||
if (raw && index < MAX_INTELFN12H_LEVEL - 2) {
|
||||
// this was queried already, use the data:
|
||||
memcpy(regs, raw->intel_fn12h[2 + index], sizeof(regs));
|
||||
} else {
|
||||
// query this ourselves:
|
||||
regs[0] = 0x12;
|
||||
regs[2] = 2 + index;
|
||||
regs[1] = regs[3] = 0;
|
||||
cpu_exec_cpuid_ext(regs);
|
||||
}
|
||||
|
||||
// decode values:
|
||||
if ((regs[0] & 0xf) == 0x1) {
|
||||
retval.start_addr |= (regs[0] & 0xfffff000); // bits [12, 32) -> bits [12, 32)
|
||||
retval.start_addr |= ((uint64_t) (regs[1] & 0x000fffff)) << 32; // bits [0, 20) -> bits [32, 52)
|
||||
retval.length |= (regs[2] & 0xfffff000); // bits [12, 32) -> bits [12, 32)
|
||||
retval.length |= ((uint64_t) (regs[3] & 0x000fffff)) << 32; // bits [0, 20) -> bits [32, 52)
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
|
||||
int cpuid_identify_intel(struct cpu_raw_data_t* raw, struct cpu_id_t* data, struct internal_id_info_t* internal)
|
||||
{
|
||||
intel_code_and_bits_t brand;
|
||||
|
||||
load_intel_features(raw, data);
|
||||
if (raw->basic_cpuid[0][0] >= 4) {
|
||||
/* Deterministic way is preferred, being more generic */
|
||||
decode_intel_deterministic_cache_info(raw, data);
|
||||
} else if (raw->basic_cpuid[0][0] >= 2) {
|
||||
decode_intel_oldstyle_cache_info(raw, data);
|
||||
}
|
||||
decode_intel_number_of_cores(raw, data);
|
||||
|
||||
brand = get_brand_code_and_bits(data);
|
||||
|
||||
internal->code.intel = brand.code;
|
||||
internal->bits = brand.bits;
|
||||
|
||||
if (data->flags[CPU_FEATURE_SGX]) {
|
||||
// if SGX is indicated by the CPU, verify its presence:
|
||||
decode_intel_sgx_features(raw, data);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -27,6 +27,5 @@
|
||||
#define __RECOG_INTEL_H__
|
||||
|
||||
int cpuid_identify_intel(struct cpu_raw_data_t* raw, struct cpu_id_t* data, struct internal_id_info_t* internal);
|
||||
void cpuid_get_list_intel(struct cpu_list_t* list);
|
||||
|
||||
#endif /*__RECOG_INTEL_H__*/
|
||||
271
src/3rdparty/rapidjson/allocators.h
vendored
Normal file
271
src/3rdparty/rapidjson/allocators.h
vendored
Normal file
@@ -0,0 +1,271 @@
|
||||
// Tencent is pleased to support the open source community by making RapidJSON available.
|
||||
//
|
||||
// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
|
||||
//
|
||||
// Licensed under the MIT License (the "License"); you may not use this file except
|
||||
// in compliance with the License. You may obtain a copy of the License at
|
||||
//
|
||||
// http://opensource.org/licenses/MIT
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software distributed
|
||||
// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
|
||||
// CONDITIONS OF ANY KIND, either express or implied. See the License for the
|
||||
// specific language governing permissions and limitations under the License.
|
||||
|
||||
#ifndef RAPIDJSON_ALLOCATORS_H_
|
||||
#define RAPIDJSON_ALLOCATORS_H_
|
||||
|
||||
#include "rapidjson.h"
|
||||
|
||||
RAPIDJSON_NAMESPACE_BEGIN
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Allocator
|
||||
|
||||
/*! \class rapidjson::Allocator
|
||||
\brief Concept for allocating, resizing and freeing memory block.
|
||||
|
||||
Note that Malloc() and Realloc() are non-static but Free() is static.
|
||||
|
||||
So if an allocator need to support Free(), it needs to put its pointer in
|
||||
the header of memory block.
|
||||
|
||||
\code
|
||||
concept Allocator {
|
||||
static const bool kNeedFree; //!< Whether this allocator needs to call Free().
|
||||
|
||||
// Allocate a memory block.
|
||||
// \param size of the memory block in bytes.
|
||||
// \returns pointer to the memory block.
|
||||
void* Malloc(size_t size);
|
||||
|
||||
// Resize a memory block.
|
||||
// \param originalPtr The pointer to current memory block. Null pointer is permitted.
|
||||
// \param originalSize The current size in bytes. (Design issue: since some allocator may not book-keep this, explicitly pass to it can save memory.)
|
||||
// \param newSize the new size in bytes.
|
||||
void* Realloc(void* originalPtr, size_t originalSize, size_t newSize);
|
||||
|
||||
// Free a memory block.
|
||||
// \param pointer to the memory block. Null pointer is permitted.
|
||||
static void Free(void *ptr);
|
||||
};
|
||||
\endcode
|
||||
*/
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// CrtAllocator
|
||||
|
||||
//! C-runtime library allocator.
|
||||
/*! This class is just wrapper for standard C library memory routines.
|
||||
\note implements Allocator concept
|
||||
*/
|
||||
class CrtAllocator {
|
||||
public:
|
||||
static const bool kNeedFree = true;
|
||||
void* Malloc(size_t size) {
|
||||
if (size) // behavior of malloc(0) is implementation defined.
|
||||
return std::malloc(size);
|
||||
else
|
||||
return NULL; // standardize to returning NULL.
|
||||
}
|
||||
void* Realloc(void* originalPtr, size_t originalSize, size_t newSize) {
|
||||
(void)originalSize;
|
||||
if (newSize == 0) {
|
||||
std::free(originalPtr);
|
||||
return NULL;
|
||||
}
|
||||
return std::realloc(originalPtr, newSize);
|
||||
}
|
||||
static void Free(void *ptr) { std::free(ptr); }
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// MemoryPoolAllocator
|
||||
|
||||
//! Default memory allocator used by the parser and DOM.
|
||||
/*! This allocator allocate memory blocks from pre-allocated memory chunks.
|
||||
|
||||
It does not free memory blocks. And Realloc() only allocate new memory.
|
||||
|
||||
The memory chunks are allocated by BaseAllocator, which is CrtAllocator by default.
|
||||
|
||||
User may also supply a buffer as the first chunk.
|
||||
|
||||
If the user-buffer is full then additional chunks are allocated by BaseAllocator.
|
||||
|
||||
The user-buffer is not deallocated by this allocator.
|
||||
|
||||
\tparam BaseAllocator the allocator type for allocating memory chunks. Default is CrtAllocator.
|
||||
\note implements Allocator concept
|
||||
*/
|
||||
template <typename BaseAllocator = CrtAllocator>
|
||||
class MemoryPoolAllocator {
|
||||
public:
|
||||
static const bool kNeedFree = false; //!< Tell users that no need to call Free() with this allocator. (concept Allocator)
|
||||
|
||||
//! Constructor with chunkSize.
|
||||
/*! \param chunkSize The size of memory chunk. The default is kDefaultChunkSize.
|
||||
\param baseAllocator The allocator for allocating memory chunks.
|
||||
*/
|
||||
MemoryPoolAllocator(size_t chunkSize = kDefaultChunkCapacity, BaseAllocator* baseAllocator = 0) :
|
||||
chunkHead_(0), chunk_capacity_(chunkSize), userBuffer_(0), baseAllocator_(baseAllocator), ownBaseAllocator_(0)
|
||||
{
|
||||
}
|
||||
|
||||
//! Constructor with user-supplied buffer.
|
||||
/*! The user buffer will be used firstly. When it is full, memory pool allocates new chunk with chunk size.
|
||||
|
||||
The user buffer will not be deallocated when this allocator is destructed.
|
||||
|
||||
\param buffer User supplied buffer.
|
||||
\param size Size of the buffer in bytes. It must at least larger than sizeof(ChunkHeader).
|
||||
\param chunkSize The size of memory chunk. The default is kDefaultChunkSize.
|
||||
\param baseAllocator The allocator for allocating memory chunks.
|
||||
*/
|
||||
MemoryPoolAllocator(void *buffer, size_t size, size_t chunkSize = kDefaultChunkCapacity, BaseAllocator* baseAllocator = 0) :
|
||||
chunkHead_(0), chunk_capacity_(chunkSize), userBuffer_(buffer), baseAllocator_(baseAllocator), ownBaseAllocator_(0)
|
||||
{
|
||||
RAPIDJSON_ASSERT(buffer != 0);
|
||||
RAPIDJSON_ASSERT(size > sizeof(ChunkHeader));
|
||||
chunkHead_ = reinterpret_cast<ChunkHeader*>(buffer);
|
||||
chunkHead_->capacity = size - sizeof(ChunkHeader);
|
||||
chunkHead_->size = 0;
|
||||
chunkHead_->next = 0;
|
||||
}
|
||||
|
||||
//! Destructor.
|
||||
/*! This deallocates all memory chunks, excluding the user-supplied buffer.
|
||||
*/
|
||||
~MemoryPoolAllocator() {
|
||||
Clear();
|
||||
RAPIDJSON_DELETE(ownBaseAllocator_);
|
||||
}
|
||||
|
||||
//! Deallocates all memory chunks, excluding the user-supplied buffer.
|
||||
void Clear() {
|
||||
while (chunkHead_ && chunkHead_ != userBuffer_) {
|
||||
ChunkHeader* next = chunkHead_->next;
|
||||
baseAllocator_->Free(chunkHead_);
|
||||
chunkHead_ = next;
|
||||
}
|
||||
if (chunkHead_ && chunkHead_ == userBuffer_)
|
||||
chunkHead_->size = 0; // Clear user buffer
|
||||
}
|
||||
|
||||
//! Computes the total capacity of allocated memory chunks.
|
||||
/*! \return total capacity in bytes.
|
||||
*/
|
||||
size_t Capacity() const {
|
||||
size_t capacity = 0;
|
||||
for (ChunkHeader* c = chunkHead_; c != 0; c = c->next)
|
||||
capacity += c->capacity;
|
||||
return capacity;
|
||||
}
|
||||
|
||||
//! Computes the memory blocks allocated.
|
||||
/*! \return total used bytes.
|
||||
*/
|
||||
size_t Size() const {
|
||||
size_t size = 0;
|
||||
for (ChunkHeader* c = chunkHead_; c != 0; c = c->next)
|
||||
size += c->size;
|
||||
return size;
|
||||
}
|
||||
|
||||
//! Allocates a memory block. (concept Allocator)
|
||||
void* Malloc(size_t size) {
|
||||
if (!size)
|
||||
return NULL;
|
||||
|
||||
size = RAPIDJSON_ALIGN(size);
|
||||
if (chunkHead_ == 0 || chunkHead_->size + size > chunkHead_->capacity)
|
||||
if (!AddChunk(chunk_capacity_ > size ? chunk_capacity_ : size))
|
||||
return NULL;
|
||||
|
||||
void *buffer = reinterpret_cast<char *>(chunkHead_) + RAPIDJSON_ALIGN(sizeof(ChunkHeader)) + chunkHead_->size;
|
||||
chunkHead_->size += size;
|
||||
return buffer;
|
||||
}
|
||||
|
||||
//! Resizes a memory block (concept Allocator)
|
||||
void* Realloc(void* originalPtr, size_t originalSize, size_t newSize) {
|
||||
if (originalPtr == 0)
|
||||
return Malloc(newSize);
|
||||
|
||||
if (newSize == 0)
|
||||
return NULL;
|
||||
|
||||
originalSize = RAPIDJSON_ALIGN(originalSize);
|
||||
newSize = RAPIDJSON_ALIGN(newSize);
|
||||
|
||||
// Do not shrink if new size is smaller than original
|
||||
if (originalSize >= newSize)
|
||||
return originalPtr;
|
||||
|
||||
// Simply expand it if it is the last allocation and there is sufficient space
|
||||
if (originalPtr == reinterpret_cast<char *>(chunkHead_) + RAPIDJSON_ALIGN(sizeof(ChunkHeader)) + chunkHead_->size - originalSize) {
|
||||
size_t increment = static_cast<size_t>(newSize - originalSize);
|
||||
if (chunkHead_->size + increment <= chunkHead_->capacity) {
|
||||
chunkHead_->size += increment;
|
||||
return originalPtr;
|
||||
}
|
||||
}
|
||||
|
||||
// Realloc process: allocate and copy memory, do not free original buffer.
|
||||
if (void* newBuffer = Malloc(newSize)) {
|
||||
if (originalSize)
|
||||
std::memcpy(newBuffer, originalPtr, originalSize);
|
||||
return newBuffer;
|
||||
}
|
||||
else
|
||||
return NULL;
|
||||
}
|
||||
|
||||
//! Frees a memory block (concept Allocator)
|
||||
static void Free(void *ptr) { (void)ptr; } // Do nothing
|
||||
|
||||
private:
|
||||
//! Copy constructor is not permitted.
|
||||
MemoryPoolAllocator(const MemoryPoolAllocator& rhs) /* = delete */;
|
||||
//! Copy assignment operator is not permitted.
|
||||
MemoryPoolAllocator& operator=(const MemoryPoolAllocator& rhs) /* = delete */;
|
||||
|
||||
//! Creates a new chunk.
|
||||
/*! \param capacity Capacity of the chunk in bytes.
|
||||
\return true if success.
|
||||
*/
|
||||
bool AddChunk(size_t capacity) {
|
||||
if (!baseAllocator_)
|
||||
ownBaseAllocator_ = baseAllocator_ = RAPIDJSON_NEW(BaseAllocator());
|
||||
if (ChunkHeader* chunk = reinterpret_cast<ChunkHeader*>(baseAllocator_->Malloc(RAPIDJSON_ALIGN(sizeof(ChunkHeader)) + capacity))) {
|
||||
chunk->capacity = capacity;
|
||||
chunk->size = 0;
|
||||
chunk->next = chunkHead_;
|
||||
chunkHead_ = chunk;
|
||||
return true;
|
||||
}
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
static const int kDefaultChunkCapacity = 64 * 1024; //!< Default chunk capacity.
|
||||
|
||||
//! Chunk header for perpending to each chunk.
|
||||
/*! Chunks are stored as a singly linked list.
|
||||
*/
|
||||
struct ChunkHeader {
|
||||
size_t capacity; //!< Capacity of the chunk in bytes (excluding the header itself).
|
||||
size_t size; //!< Current size of allocated memory in bytes.
|
||||
ChunkHeader *next; //!< Next chunk in the linked list.
|
||||
};
|
||||
|
||||
ChunkHeader *chunkHead_; //!< Head of the chunk linked-list. Only the head chunk serves allocation.
|
||||
size_t chunk_capacity_; //!< The minimum capacity of chunk when they are allocated.
|
||||
void *userBuffer_; //!< User supplied buffer.
|
||||
BaseAllocator* baseAllocator_; //!< base allocator for allocating memory chunks.
|
||||
BaseAllocator* ownBaseAllocator_; //!< base allocator created by this object.
|
||||
};
|
||||
|
||||
RAPIDJSON_NAMESPACE_END
|
||||
|
||||
#endif // RAPIDJSON_ENCODINGS_H_
|
||||
2575
src/3rdparty/rapidjson/document.h
vendored
Normal file
2575
src/3rdparty/rapidjson/document.h
vendored
Normal file
File diff suppressed because it is too large
Load Diff
299
src/3rdparty/rapidjson/encodedstream.h
vendored
Normal file
299
src/3rdparty/rapidjson/encodedstream.h
vendored
Normal file
@@ -0,0 +1,299 @@
|
||||
// Tencent is pleased to support the open source community by making RapidJSON available.
|
||||
//
|
||||
// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
|
||||
//
|
||||
// Licensed under the MIT License (the "License"); you may not use this file except
|
||||
// in compliance with the License. You may obtain a copy of the License at
|
||||
//
|
||||
// http://opensource.org/licenses/MIT
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software distributed
|
||||
// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
|
||||
// CONDITIONS OF ANY KIND, either express or implied. See the License for the
|
||||
// specific language governing permissions and limitations under the License.
|
||||
|
||||
#ifndef RAPIDJSON_ENCODEDSTREAM_H_
|
||||
#define RAPIDJSON_ENCODEDSTREAM_H_
|
||||
|
||||
#include "stream.h"
|
||||
#include "memorystream.h"
|
||||
|
||||
#ifdef __GNUC__
|
||||
RAPIDJSON_DIAG_PUSH
|
||||
RAPIDJSON_DIAG_OFF(effc++)
|
||||
#endif
|
||||
|
||||
#ifdef __clang__
|
||||
RAPIDJSON_DIAG_PUSH
|
||||
RAPIDJSON_DIAG_OFF(padded)
|
||||
#endif
|
||||
|
||||
RAPIDJSON_NAMESPACE_BEGIN
|
||||
|
||||
//! Input byte stream wrapper with a statically bound encoding.
|
||||
/*!
|
||||
\tparam Encoding The interpretation of encoding of the stream. Either UTF8, UTF16LE, UTF16BE, UTF32LE, UTF32BE.
|
||||
\tparam InputByteStream Type of input byte stream. For example, FileReadStream.
|
||||
*/
|
||||
template <typename Encoding, typename InputByteStream>
|
||||
class EncodedInputStream {
|
||||
RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1);
|
||||
public:
|
||||
typedef typename Encoding::Ch Ch;
|
||||
|
||||
EncodedInputStream(InputByteStream& is) : is_(is) {
|
||||
current_ = Encoding::TakeBOM(is_);
|
||||
}
|
||||
|
||||
Ch Peek() const { return current_; }
|
||||
Ch Take() { Ch c = current_; current_ = Encoding::Take(is_); return c; }
|
||||
size_t Tell() const { return is_.Tell(); }
|
||||
|
||||
// Not implemented
|
||||
void Put(Ch) { RAPIDJSON_ASSERT(false); }
|
||||
void Flush() { RAPIDJSON_ASSERT(false); }
|
||||
Ch* PutBegin() { RAPIDJSON_ASSERT(false); return 0; }
|
||||
size_t PutEnd(Ch*) { RAPIDJSON_ASSERT(false); return 0; }
|
||||
|
||||
private:
|
||||
EncodedInputStream(const EncodedInputStream&);
|
||||
EncodedInputStream& operator=(const EncodedInputStream&);
|
||||
|
||||
InputByteStream& is_;
|
||||
Ch current_;
|
||||
};
|
||||
|
||||
//! Specialized for UTF8 MemoryStream.
|
||||
template <>
|
||||
class EncodedInputStream<UTF8<>, MemoryStream> {
|
||||
public:
|
||||
typedef UTF8<>::Ch Ch;
|
||||
|
||||
EncodedInputStream(MemoryStream& is) : is_(is) {
|
||||
if (static_cast<unsigned char>(is_.Peek()) == 0xEFu) is_.Take();
|
||||
if (static_cast<unsigned char>(is_.Peek()) == 0xBBu) is_.Take();
|
||||
if (static_cast<unsigned char>(is_.Peek()) == 0xBFu) is_.Take();
|
||||
}
|
||||
Ch Peek() const { return is_.Peek(); }
|
||||
Ch Take() { return is_.Take(); }
|
||||
size_t Tell() const { return is_.Tell(); }
|
||||
|
||||
// Not implemented
|
||||
void Put(Ch) {}
|
||||
void Flush() {}
|
||||
Ch* PutBegin() { return 0; }
|
||||
size_t PutEnd(Ch*) { return 0; }
|
||||
|
||||
MemoryStream& is_;
|
||||
|
||||
private:
|
||||
EncodedInputStream(const EncodedInputStream&);
|
||||
EncodedInputStream& operator=(const EncodedInputStream&);
|
||||
};
|
||||
|
||||
//! Output byte stream wrapper with statically bound encoding.
|
||||
/*!
|
||||
\tparam Encoding The interpretation of encoding of the stream. Either UTF8, UTF16LE, UTF16BE, UTF32LE, UTF32BE.
|
||||
\tparam OutputByteStream Type of input byte stream. For example, FileWriteStream.
|
||||
*/
|
||||
template <typename Encoding, typename OutputByteStream>
|
||||
class EncodedOutputStream {
|
||||
RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1);
|
||||
public:
|
||||
typedef typename Encoding::Ch Ch;
|
||||
|
||||
EncodedOutputStream(OutputByteStream& os, bool putBOM = true) : os_(os) {
|
||||
if (putBOM)
|
||||
Encoding::PutBOM(os_);
|
||||
}
|
||||
|
||||
void Put(Ch c) { Encoding::Put(os_, c); }
|
||||
void Flush() { os_.Flush(); }
|
||||
|
||||
// Not implemented
|
||||
Ch Peek() const { RAPIDJSON_ASSERT(false); return 0;}
|
||||
Ch Take() { RAPIDJSON_ASSERT(false); return 0;}
|
||||
size_t Tell() const { RAPIDJSON_ASSERT(false); return 0; }
|
||||
Ch* PutBegin() { RAPIDJSON_ASSERT(false); return 0; }
|
||||
size_t PutEnd(Ch*) { RAPIDJSON_ASSERT(false); return 0; }
|
||||
|
||||
private:
|
||||
EncodedOutputStream(const EncodedOutputStream&);
|
||||
EncodedOutputStream& operator=(const EncodedOutputStream&);
|
||||
|
||||
OutputByteStream& os_;
|
||||
};
|
||||
|
||||
#define RAPIDJSON_ENCODINGS_FUNC(x) UTF8<Ch>::x, UTF16LE<Ch>::x, UTF16BE<Ch>::x, UTF32LE<Ch>::x, UTF32BE<Ch>::x
|
||||
|
||||
//! Input stream wrapper with dynamically bound encoding and automatic encoding detection.
|
||||
/*!
|
||||
\tparam CharType Type of character for reading.
|
||||
\tparam InputByteStream type of input byte stream to be wrapped.
|
||||
*/
|
||||
template <typename CharType, typename InputByteStream>
|
||||
class AutoUTFInputStream {
|
||||
RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1);
|
||||
public:
|
||||
typedef CharType Ch;
|
||||
|
||||
//! Constructor.
|
||||
/*!
|
||||
\param is input stream to be wrapped.
|
||||
\param type UTF encoding type if it is not detected from the stream.
|
||||
*/
|
||||
AutoUTFInputStream(InputByteStream& is, UTFType type = kUTF8) : is_(&is), type_(type), hasBOM_(false) {
|
||||
RAPIDJSON_ASSERT(type >= kUTF8 && type <= kUTF32BE);
|
||||
DetectType();
|
||||
static const TakeFunc f[] = { RAPIDJSON_ENCODINGS_FUNC(Take) };
|
||||
takeFunc_ = f[type_];
|
||||
current_ = takeFunc_(*is_);
|
||||
}
|
||||
|
||||
UTFType GetType() const { return type_; }
|
||||
bool HasBOM() const { return hasBOM_; }
|
||||
|
||||
Ch Peek() const { return current_; }
|
||||
Ch Take() { Ch c = current_; current_ = takeFunc_(*is_); return c; }
|
||||
size_t Tell() const { return is_->Tell(); }
|
||||
|
||||
// Not implemented
|
||||
void Put(Ch) { RAPIDJSON_ASSERT(false); }
|
||||
void Flush() { RAPIDJSON_ASSERT(false); }
|
||||
Ch* PutBegin() { RAPIDJSON_ASSERT(false); return 0; }
|
||||
size_t PutEnd(Ch*) { RAPIDJSON_ASSERT(false); return 0; }
|
||||
|
||||
private:
|
||||
AutoUTFInputStream(const AutoUTFInputStream&);
|
||||
AutoUTFInputStream& operator=(const AutoUTFInputStream&);
|
||||
|
||||
// Detect encoding type with BOM or RFC 4627
|
||||
void DetectType() {
|
||||
// BOM (Byte Order Mark):
|
||||
// 00 00 FE FF UTF-32BE
|
||||
// FF FE 00 00 UTF-32LE
|
||||
// FE FF UTF-16BE
|
||||
// FF FE UTF-16LE
|
||||
// EF BB BF UTF-8
|
||||
|
||||
const unsigned char* c = reinterpret_cast<const unsigned char *>(is_->Peek4());
|
||||
if (!c)
|
||||
return;
|
||||
|
||||
unsigned bom = static_cast<unsigned>(c[0] | (c[1] << 8) | (c[2] << 16) | (c[3] << 24));
|
||||
hasBOM_ = false;
|
||||
if (bom == 0xFFFE0000) { type_ = kUTF32BE; hasBOM_ = true; is_->Take(); is_->Take(); is_->Take(); is_->Take(); }
|
||||
else if (bom == 0x0000FEFF) { type_ = kUTF32LE; hasBOM_ = true; is_->Take(); is_->Take(); is_->Take(); is_->Take(); }
|
||||
else if ((bom & 0xFFFF) == 0xFFFE) { type_ = kUTF16BE; hasBOM_ = true; is_->Take(); is_->Take(); }
|
||||
else if ((bom & 0xFFFF) == 0xFEFF) { type_ = kUTF16LE; hasBOM_ = true; is_->Take(); is_->Take(); }
|
||||
else if ((bom & 0xFFFFFF) == 0xBFBBEF) { type_ = kUTF8; hasBOM_ = true; is_->Take(); is_->Take(); is_->Take(); }
|
||||
|
||||
// RFC 4627: Section 3
|
||||
// "Since the first two characters of a JSON text will always be ASCII
|
||||
// characters [RFC0020], it is possible to determine whether an octet
|
||||
// stream is UTF-8, UTF-16 (BE or LE), or UTF-32 (BE or LE) by looking
|
||||
// at the pattern of nulls in the first four octets."
|
||||
// 00 00 00 xx UTF-32BE
|
||||
// 00 xx 00 xx UTF-16BE
|
||||
// xx 00 00 00 UTF-32LE
|
||||
// xx 00 xx 00 UTF-16LE
|
||||
// xx xx xx xx UTF-8
|
||||
|
||||
if (!hasBOM_) {
|
||||
unsigned pattern = (c[0] ? 1 : 0) | (c[1] ? 2 : 0) | (c[2] ? 4 : 0) | (c[3] ? 8 : 0);
|
||||
switch (pattern) {
|
||||
case 0x08: type_ = kUTF32BE; break;
|
||||
case 0x0A: type_ = kUTF16BE; break;
|
||||
case 0x01: type_ = kUTF32LE; break;
|
||||
case 0x05: type_ = kUTF16LE; break;
|
||||
case 0x0F: type_ = kUTF8; break;
|
||||
default: break; // Use type defined by user.
|
||||
}
|
||||
}
|
||||
|
||||
// Runtime check whether the size of character type is sufficient. It only perform checks with assertion.
|
||||
if (type_ == kUTF16LE || type_ == kUTF16BE) RAPIDJSON_ASSERT(sizeof(Ch) >= 2);
|
||||
if (type_ == kUTF32LE || type_ == kUTF32BE) RAPIDJSON_ASSERT(sizeof(Ch) >= 4);
|
||||
}
|
||||
|
||||
typedef Ch (*TakeFunc)(InputByteStream& is);
|
||||
InputByteStream* is_;
|
||||
UTFType type_;
|
||||
Ch current_;
|
||||
TakeFunc takeFunc_;
|
||||
bool hasBOM_;
|
||||
};
|
||||
|
||||
//! Output stream wrapper with dynamically bound encoding and automatic encoding detection.
|
||||
/*!
|
||||
\tparam CharType Type of character for writing.
|
||||
\tparam OutputByteStream type of output byte stream to be wrapped.
|
||||
*/
|
||||
template <typename CharType, typename OutputByteStream>
|
||||
class AutoUTFOutputStream {
|
||||
RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1);
|
||||
public:
|
||||
typedef CharType Ch;
|
||||
|
||||
//! Constructor.
|
||||
/*!
|
||||
\param os output stream to be wrapped.
|
||||
\param type UTF encoding type.
|
||||
\param putBOM Whether to write BOM at the beginning of the stream.
|
||||
*/
|
||||
AutoUTFOutputStream(OutputByteStream& os, UTFType type, bool putBOM) : os_(&os), type_(type) {
|
||||
RAPIDJSON_ASSERT(type >= kUTF8 && type <= kUTF32BE);
|
||||
|
||||
// Runtime check whether the size of character type is sufficient. It only perform checks with assertion.
|
||||
if (type_ == kUTF16LE || type_ == kUTF16BE) RAPIDJSON_ASSERT(sizeof(Ch) >= 2);
|
||||
if (type_ == kUTF32LE || type_ == kUTF32BE) RAPIDJSON_ASSERT(sizeof(Ch) >= 4);
|
||||
|
||||
static const PutFunc f[] = { RAPIDJSON_ENCODINGS_FUNC(Put) };
|
||||
putFunc_ = f[type_];
|
||||
|
||||
if (putBOM)
|
||||
PutBOM();
|
||||
}
|
||||
|
||||
UTFType GetType() const { return type_; }
|
||||
|
||||
void Put(Ch c) { putFunc_(*os_, c); }
|
||||
void Flush() { os_->Flush(); }
|
||||
|
||||
// Not implemented
|
||||
Ch Peek() const { RAPIDJSON_ASSERT(false); return 0;}
|
||||
Ch Take() { RAPIDJSON_ASSERT(false); return 0;}
|
||||
size_t Tell() const { RAPIDJSON_ASSERT(false); return 0; }
|
||||
Ch* PutBegin() { RAPIDJSON_ASSERT(false); return 0; }
|
||||
size_t PutEnd(Ch*) { RAPIDJSON_ASSERT(false); return 0; }
|
||||
|
||||
private:
|
||||
AutoUTFOutputStream(const AutoUTFOutputStream&);
|
||||
AutoUTFOutputStream& operator=(const AutoUTFOutputStream&);
|
||||
|
||||
void PutBOM() {
|
||||
typedef void (*PutBOMFunc)(OutputByteStream&);
|
||||
static const PutBOMFunc f[] = { RAPIDJSON_ENCODINGS_FUNC(PutBOM) };
|
||||
f[type_](*os_);
|
||||
}
|
||||
|
||||
typedef void (*PutFunc)(OutputByteStream&, Ch);
|
||||
|
||||
OutputByteStream* os_;
|
||||
UTFType type_;
|
||||
PutFunc putFunc_;
|
||||
};
|
||||
|
||||
#undef RAPIDJSON_ENCODINGS_FUNC
|
||||
|
||||
RAPIDJSON_NAMESPACE_END
|
||||
|
||||
#ifdef __clang__
|
||||
RAPIDJSON_DIAG_POP
|
||||
#endif
|
||||
|
||||
#ifdef __GNUC__
|
||||
RAPIDJSON_DIAG_POP
|
||||
#endif
|
||||
|
||||
#endif // RAPIDJSON_FILESTREAM_H_
|
||||
716
src/3rdparty/rapidjson/encodings.h
vendored
Normal file
716
src/3rdparty/rapidjson/encodings.h
vendored
Normal file
@@ -0,0 +1,716 @@
|
||||
// Tencent is pleased to support the open source community by making RapidJSON available.
|
||||
//
|
||||
// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
|
||||
//
|
||||
// Licensed under the MIT License (the "License"); you may not use this file except
|
||||
// in compliance with the License. You may obtain a copy of the License at
|
||||
//
|
||||
// http://opensource.org/licenses/MIT
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software distributed
|
||||
// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
|
||||
// CONDITIONS OF ANY KIND, either express or implied. See the License for the
|
||||
// specific language governing permissions and limitations under the License.
|
||||
|
||||
#ifndef RAPIDJSON_ENCODINGS_H_
|
||||
#define RAPIDJSON_ENCODINGS_H_
|
||||
|
||||
#include "rapidjson.h"
|
||||
|
||||
#ifdef _MSC_VER
|
||||
RAPIDJSON_DIAG_PUSH
|
||||
RAPIDJSON_DIAG_OFF(4244) // conversion from 'type1' to 'type2', possible loss of data
|
||||
RAPIDJSON_DIAG_OFF(4702) // unreachable code
|
||||
#elif defined(__GNUC__)
|
||||
RAPIDJSON_DIAG_PUSH
|
||||
RAPIDJSON_DIAG_OFF(effc++)
|
||||
RAPIDJSON_DIAG_OFF(overflow)
|
||||
#endif
|
||||
|
||||
RAPIDJSON_NAMESPACE_BEGIN
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Encoding
|
||||
|
||||
/*! \class rapidjson::Encoding
|
||||
\brief Concept for encoding of Unicode characters.
|
||||
|
||||
\code
|
||||
concept Encoding {
|
||||
typename Ch; //! Type of character. A "character" is actually a code unit in unicode's definition.
|
||||
|
||||
enum { supportUnicode = 1 }; // or 0 if not supporting unicode
|
||||
|
||||
//! \brief Encode a Unicode codepoint to an output stream.
|
||||
//! \param os Output stream.
|
||||
//! \param codepoint An unicode codepoint, ranging from 0x0 to 0x10FFFF inclusively.
|
||||
template<typename OutputStream>
|
||||
static void Encode(OutputStream& os, unsigned codepoint);
|
||||
|
||||
//! \brief Decode a Unicode codepoint from an input stream.
|
||||
//! \param is Input stream.
|
||||
//! \param codepoint Output of the unicode codepoint.
|
||||
//! \return true if a valid codepoint can be decoded from the stream.
|
||||
template <typename InputStream>
|
||||
static bool Decode(InputStream& is, unsigned* codepoint);
|
||||
|
||||
//! \brief Validate one Unicode codepoint from an encoded stream.
|
||||
//! \param is Input stream to obtain codepoint.
|
||||
//! \param os Output for copying one codepoint.
|
||||
//! \return true if it is valid.
|
||||
//! \note This function just validating and copying the codepoint without actually decode it.
|
||||
template <typename InputStream, typename OutputStream>
|
||||
static bool Validate(InputStream& is, OutputStream& os);
|
||||
|
||||
// The following functions are deal with byte streams.
|
||||
|
||||
//! Take a character from input byte stream, skip BOM if exist.
|
||||
template <typename InputByteStream>
|
||||
static CharType TakeBOM(InputByteStream& is);
|
||||
|
||||
//! Take a character from input byte stream.
|
||||
template <typename InputByteStream>
|
||||
static Ch Take(InputByteStream& is);
|
||||
|
||||
//! Put BOM to output byte stream.
|
||||
template <typename OutputByteStream>
|
||||
static void PutBOM(OutputByteStream& os);
|
||||
|
||||
//! Put a character to output byte stream.
|
||||
template <typename OutputByteStream>
|
||||
static void Put(OutputByteStream& os, Ch c);
|
||||
};
|
||||
\endcode
|
||||
*/
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// UTF8
|
||||
|
||||
//! UTF-8 encoding.
|
||||
/*! http://en.wikipedia.org/wiki/UTF-8
|
||||
http://tools.ietf.org/html/rfc3629
|
||||
\tparam CharType Code unit for storing 8-bit UTF-8 data. Default is char.
|
||||
\note implements Encoding concept
|
||||
*/
|
||||
template<typename CharType = char>
|
||||
struct UTF8 {
|
||||
typedef CharType Ch;
|
||||
|
||||
enum { supportUnicode = 1 };
|
||||
|
||||
template<typename OutputStream>
|
||||
static void Encode(OutputStream& os, unsigned codepoint) {
|
||||
if (codepoint <= 0x7F)
|
||||
os.Put(static_cast<Ch>(codepoint & 0xFF));
|
||||
else if (codepoint <= 0x7FF) {
|
||||
os.Put(static_cast<Ch>(0xC0 | ((codepoint >> 6) & 0xFF)));
|
||||
os.Put(static_cast<Ch>(0x80 | ((codepoint & 0x3F))));
|
||||
}
|
||||
else if (codepoint <= 0xFFFF) {
|
||||
os.Put(static_cast<Ch>(0xE0 | ((codepoint >> 12) & 0xFF)));
|
||||
os.Put(static_cast<Ch>(0x80 | ((codepoint >> 6) & 0x3F)));
|
||||
os.Put(static_cast<Ch>(0x80 | (codepoint & 0x3F)));
|
||||
}
|
||||
else {
|
||||
RAPIDJSON_ASSERT(codepoint <= 0x10FFFF);
|
||||
os.Put(static_cast<Ch>(0xF0 | ((codepoint >> 18) & 0xFF)));
|
||||
os.Put(static_cast<Ch>(0x80 | ((codepoint >> 12) & 0x3F)));
|
||||
os.Put(static_cast<Ch>(0x80 | ((codepoint >> 6) & 0x3F)));
|
||||
os.Put(static_cast<Ch>(0x80 | (codepoint & 0x3F)));
|
||||
}
|
||||
}
|
||||
|
||||
template<typename OutputStream>
|
||||
static void EncodeUnsafe(OutputStream& os, unsigned codepoint) {
|
||||
if (codepoint <= 0x7F)
|
||||
PutUnsafe(os, static_cast<Ch>(codepoint & 0xFF));
|
||||
else if (codepoint <= 0x7FF) {
|
||||
PutUnsafe(os, static_cast<Ch>(0xC0 | ((codepoint >> 6) & 0xFF)));
|
||||
PutUnsafe(os, static_cast<Ch>(0x80 | ((codepoint & 0x3F))));
|
||||
}
|
||||
else if (codepoint <= 0xFFFF) {
|
||||
PutUnsafe(os, static_cast<Ch>(0xE0 | ((codepoint >> 12) & 0xFF)));
|
||||
PutUnsafe(os, static_cast<Ch>(0x80 | ((codepoint >> 6) & 0x3F)));
|
||||
PutUnsafe(os, static_cast<Ch>(0x80 | (codepoint & 0x3F)));
|
||||
}
|
||||
else {
|
||||
RAPIDJSON_ASSERT(codepoint <= 0x10FFFF);
|
||||
PutUnsafe(os, static_cast<Ch>(0xF0 | ((codepoint >> 18) & 0xFF)));
|
||||
PutUnsafe(os, static_cast<Ch>(0x80 | ((codepoint >> 12) & 0x3F)));
|
||||
PutUnsafe(os, static_cast<Ch>(0x80 | ((codepoint >> 6) & 0x3F)));
|
||||
PutUnsafe(os, static_cast<Ch>(0x80 | (codepoint & 0x3F)));
|
||||
}
|
||||
}
|
||||
|
||||
template <typename InputStream>
|
||||
static bool Decode(InputStream& is, unsigned* codepoint) {
|
||||
#define COPY() c = is.Take(); *codepoint = (*codepoint << 6) | (static_cast<unsigned char>(c) & 0x3Fu)
|
||||
#define TRANS(mask) result &= ((GetRange(static_cast<unsigned char>(c)) & mask) != 0)
|
||||
#define TAIL() COPY(); TRANS(0x70)
|
||||
typename InputStream::Ch c = is.Take();
|
||||
if (!(c & 0x80)) {
|
||||
*codepoint = static_cast<unsigned char>(c);
|
||||
return true;
|
||||
}
|
||||
|
||||
unsigned char type = GetRange(static_cast<unsigned char>(c));
|
||||
if (type >= 32) {
|
||||
*codepoint = 0;
|
||||
} else {
|
||||
*codepoint = (0xFF >> type) & static_cast<unsigned char>(c);
|
||||
}
|
||||
bool result = true;
|
||||
switch (type) {
|
||||
case 2: TAIL(); return result;
|
||||
case 3: TAIL(); TAIL(); return result;
|
||||
case 4: COPY(); TRANS(0x50); TAIL(); return result;
|
||||
case 5: COPY(); TRANS(0x10); TAIL(); TAIL(); return result;
|
||||
case 6: TAIL(); TAIL(); TAIL(); return result;
|
||||
case 10: COPY(); TRANS(0x20); TAIL(); return result;
|
||||
case 11: COPY(); TRANS(0x60); TAIL(); TAIL(); return result;
|
||||
default: return false;
|
||||
}
|
||||
#undef COPY
|
||||
#undef TRANS
|
||||
#undef TAIL
|
||||
}
|
||||
|
||||
template <typename InputStream, typename OutputStream>
|
||||
static bool Validate(InputStream& is, OutputStream& os) {
|
||||
#define COPY() os.Put(c = is.Take())
|
||||
#define TRANS(mask) result &= ((GetRange(static_cast<unsigned char>(c)) & mask) != 0)
|
||||
#define TAIL() COPY(); TRANS(0x70)
|
||||
Ch c;
|
||||
COPY();
|
||||
if (!(c & 0x80))
|
||||
return true;
|
||||
|
||||
bool result = true;
|
||||
switch (GetRange(static_cast<unsigned char>(c))) {
|
||||
case 2: TAIL(); return result;
|
||||
case 3: TAIL(); TAIL(); return result;
|
||||
case 4: COPY(); TRANS(0x50); TAIL(); return result;
|
||||
case 5: COPY(); TRANS(0x10); TAIL(); TAIL(); return result;
|
||||
case 6: TAIL(); TAIL(); TAIL(); return result;
|
||||
case 10: COPY(); TRANS(0x20); TAIL(); return result;
|
||||
case 11: COPY(); TRANS(0x60); TAIL(); TAIL(); return result;
|
||||
default: return false;
|
||||
}
|
||||
#undef COPY
|
||||
#undef TRANS
|
||||
#undef TAIL
|
||||
}
|
||||
|
||||
static unsigned char GetRange(unsigned char c) {
|
||||
// Referring to DFA of http://bjoern.hoehrmann.de/utf-8/decoder/dfa/
|
||||
// With new mapping 1 -> 0x10, 7 -> 0x20, 9 -> 0x40, such that AND operation can test multiple types.
|
||||
static const unsigned char type[] = {
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,
|
||||
0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,
|
||||
0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
|
||||
0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
|
||||
8,8,2,2,2,2,2,2,2,2,2,2,2,2,2,2, 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
|
||||
10,3,3,3,3,3,3,3,3,3,3,3,3,4,3,3, 11,6,6,6,5,8,8,8,8,8,8,8,8,8,8,8,
|
||||
};
|
||||
return type[c];
|
||||
}
|
||||
|
||||
template <typename InputByteStream>
|
||||
static CharType TakeBOM(InputByteStream& is) {
|
||||
RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1);
|
||||
typename InputByteStream::Ch c = Take(is);
|
||||
if (static_cast<unsigned char>(c) != 0xEFu) return c;
|
||||
c = is.Take();
|
||||
if (static_cast<unsigned char>(c) != 0xBBu) return c;
|
||||
c = is.Take();
|
||||
if (static_cast<unsigned char>(c) != 0xBFu) return c;
|
||||
c = is.Take();
|
||||
return c;
|
||||
}
|
||||
|
||||
template <typename InputByteStream>
|
||||
static Ch Take(InputByteStream& is) {
|
||||
RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1);
|
||||
return static_cast<Ch>(is.Take());
|
||||
}
|
||||
|
||||
template <typename OutputByteStream>
|
||||
static void PutBOM(OutputByteStream& os) {
|
||||
RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1);
|
||||
os.Put(static_cast<typename OutputByteStream::Ch>(0xEFu));
|
||||
os.Put(static_cast<typename OutputByteStream::Ch>(0xBBu));
|
||||
os.Put(static_cast<typename OutputByteStream::Ch>(0xBFu));
|
||||
}
|
||||
|
||||
template <typename OutputByteStream>
|
||||
static void Put(OutputByteStream& os, Ch c) {
|
||||
RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1);
|
||||
os.Put(static_cast<typename OutputByteStream::Ch>(c));
|
||||
}
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// UTF16
|
||||
|
||||
//! UTF-16 encoding.
|
||||
/*! http://en.wikipedia.org/wiki/UTF-16
|
||||
http://tools.ietf.org/html/rfc2781
|
||||
\tparam CharType Type for storing 16-bit UTF-16 data. Default is wchar_t. C++11 may use char16_t instead.
|
||||
\note implements Encoding concept
|
||||
|
||||
\note For in-memory access, no need to concern endianness. The code units and code points are represented by CPU's endianness.
|
||||
For streaming, use UTF16LE and UTF16BE, which handle endianness.
|
||||
*/
|
||||
template<typename CharType = wchar_t>
|
||||
struct UTF16 {
|
||||
typedef CharType Ch;
|
||||
RAPIDJSON_STATIC_ASSERT(sizeof(Ch) >= 2);
|
||||
|
||||
enum { supportUnicode = 1 };
|
||||
|
||||
template<typename OutputStream>
|
||||
static void Encode(OutputStream& os, unsigned codepoint) {
|
||||
RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputStream::Ch) >= 2);
|
||||
if (codepoint <= 0xFFFF) {
|
||||
RAPIDJSON_ASSERT(codepoint < 0xD800 || codepoint > 0xDFFF); // Code point itself cannot be surrogate pair
|
||||
os.Put(static_cast<typename OutputStream::Ch>(codepoint));
|
||||
}
|
||||
else {
|
||||
RAPIDJSON_ASSERT(codepoint <= 0x10FFFF);
|
||||
unsigned v = codepoint - 0x10000;
|
||||
os.Put(static_cast<typename OutputStream::Ch>((v >> 10) | 0xD800));
|
||||
os.Put((v & 0x3FF) | 0xDC00);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
template<typename OutputStream>
|
||||
static void EncodeUnsafe(OutputStream& os, unsigned codepoint) {
|
||||
RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputStream::Ch) >= 2);
|
||||
if (codepoint <= 0xFFFF) {
|
||||
RAPIDJSON_ASSERT(codepoint < 0xD800 || codepoint > 0xDFFF); // Code point itself cannot be surrogate pair
|
||||
PutUnsafe(os, static_cast<typename OutputStream::Ch>(codepoint));
|
||||
}
|
||||
else {
|
||||
RAPIDJSON_ASSERT(codepoint <= 0x10FFFF);
|
||||
unsigned v = codepoint - 0x10000;
|
||||
PutUnsafe(os, static_cast<typename OutputStream::Ch>((v >> 10) | 0xD800));
|
||||
PutUnsafe(os, (v & 0x3FF) | 0xDC00);
|
||||
}
|
||||
}
|
||||
|
||||
template <typename InputStream>
|
||||
static bool Decode(InputStream& is, unsigned* codepoint) {
|
||||
RAPIDJSON_STATIC_ASSERT(sizeof(typename InputStream::Ch) >= 2);
|
||||
typename InputStream::Ch c = is.Take();
|
||||
if (c < 0xD800 || c > 0xDFFF) {
|
||||
*codepoint = static_cast<unsigned>(c);
|
||||
return true;
|
||||
}
|
||||
else if (c <= 0xDBFF) {
|
||||
*codepoint = (static_cast<unsigned>(c) & 0x3FF) << 10;
|
||||
c = is.Take();
|
||||
*codepoint |= (static_cast<unsigned>(c) & 0x3FF);
|
||||
*codepoint += 0x10000;
|
||||
return c >= 0xDC00 && c <= 0xDFFF;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
template <typename InputStream, typename OutputStream>
|
||||
static bool Validate(InputStream& is, OutputStream& os) {
|
||||
RAPIDJSON_STATIC_ASSERT(sizeof(typename InputStream::Ch) >= 2);
|
||||
RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputStream::Ch) >= 2);
|
||||
typename InputStream::Ch c;
|
||||
os.Put(static_cast<typename OutputStream::Ch>(c = is.Take()));
|
||||
if (c < 0xD800 || c > 0xDFFF)
|
||||
return true;
|
||||
else if (c <= 0xDBFF) {
|
||||
os.Put(c = is.Take());
|
||||
return c >= 0xDC00 && c <= 0xDFFF;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
//! UTF-16 little endian encoding.
|
||||
template<typename CharType = wchar_t>
|
||||
struct UTF16LE : UTF16<CharType> {
|
||||
template <typename InputByteStream>
|
||||
static CharType TakeBOM(InputByteStream& is) {
|
||||
RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1);
|
||||
CharType c = Take(is);
|
||||
return static_cast<uint16_t>(c) == 0xFEFFu ? Take(is) : c;
|
||||
}
|
||||
|
||||
template <typename InputByteStream>
|
||||
static CharType Take(InputByteStream& is) {
|
||||
RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1);
|
||||
unsigned c = static_cast<uint8_t>(is.Take());
|
||||
c |= static_cast<unsigned>(static_cast<uint8_t>(is.Take())) << 8;
|
||||
return static_cast<CharType>(c);
|
||||
}
|
||||
|
||||
template <typename OutputByteStream>
|
||||
static void PutBOM(OutputByteStream& os) {
|
||||
RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1);
|
||||
os.Put(static_cast<typename OutputByteStream::Ch>(0xFFu));
|
||||
os.Put(static_cast<typename OutputByteStream::Ch>(0xFEu));
|
||||
}
|
||||
|
||||
template <typename OutputByteStream>
|
||||
static void Put(OutputByteStream& os, CharType c) {
|
||||
RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1);
|
||||
os.Put(static_cast<typename OutputByteStream::Ch>(static_cast<unsigned>(c) & 0xFFu));
|
||||
os.Put(static_cast<typename OutputByteStream::Ch>((static_cast<unsigned>(c) >> 8) & 0xFFu));
|
||||
}
|
||||
};
|
||||
|
||||
//! UTF-16 big endian encoding.
|
||||
template<typename CharType = wchar_t>
|
||||
struct UTF16BE : UTF16<CharType> {
|
||||
template <typename InputByteStream>
|
||||
static CharType TakeBOM(InputByteStream& is) {
|
||||
RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1);
|
||||
CharType c = Take(is);
|
||||
return static_cast<uint16_t>(c) == 0xFEFFu ? Take(is) : c;
|
||||
}
|
||||
|
||||
template <typename InputByteStream>
|
||||
static CharType Take(InputByteStream& is) {
|
||||
RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1);
|
||||
unsigned c = static_cast<unsigned>(static_cast<uint8_t>(is.Take())) << 8;
|
||||
c |= static_cast<uint8_t>(is.Take());
|
||||
return static_cast<CharType>(c);
|
||||
}
|
||||
|
||||
template <typename OutputByteStream>
|
||||
static void PutBOM(OutputByteStream& os) {
|
||||
RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1);
|
||||
os.Put(static_cast<typename OutputByteStream::Ch>(0xFEu));
|
||||
os.Put(static_cast<typename OutputByteStream::Ch>(0xFFu));
|
||||
}
|
||||
|
||||
template <typename OutputByteStream>
|
||||
static void Put(OutputByteStream& os, CharType c) {
|
||||
RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1);
|
||||
os.Put(static_cast<typename OutputByteStream::Ch>((static_cast<unsigned>(c) >> 8) & 0xFFu));
|
||||
os.Put(static_cast<typename OutputByteStream::Ch>(static_cast<unsigned>(c) & 0xFFu));
|
||||
}
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// UTF32
|
||||
|
||||
//! UTF-32 encoding.
|
||||
/*! http://en.wikipedia.org/wiki/UTF-32
|
||||
\tparam CharType Type for storing 32-bit UTF-32 data. Default is unsigned. C++11 may use char32_t instead.
|
||||
\note implements Encoding concept
|
||||
|
||||
\note For in-memory access, no need to concern endianness. The code units and code points are represented by CPU's endianness.
|
||||
For streaming, use UTF32LE and UTF32BE, which handle endianness.
|
||||
*/
|
||||
template<typename CharType = unsigned>
|
||||
struct UTF32 {
|
||||
typedef CharType Ch;
|
||||
RAPIDJSON_STATIC_ASSERT(sizeof(Ch) >= 4);
|
||||
|
||||
enum { supportUnicode = 1 };
|
||||
|
||||
template<typename OutputStream>
|
||||
static void Encode(OutputStream& os, unsigned codepoint) {
|
||||
RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputStream::Ch) >= 4);
|
||||
RAPIDJSON_ASSERT(codepoint <= 0x10FFFF);
|
||||
os.Put(codepoint);
|
||||
}
|
||||
|
||||
template<typename OutputStream>
|
||||
static void EncodeUnsafe(OutputStream& os, unsigned codepoint) {
|
||||
RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputStream::Ch) >= 4);
|
||||
RAPIDJSON_ASSERT(codepoint <= 0x10FFFF);
|
||||
PutUnsafe(os, codepoint);
|
||||
}
|
||||
|
||||
template <typename InputStream>
|
||||
static bool Decode(InputStream& is, unsigned* codepoint) {
|
||||
RAPIDJSON_STATIC_ASSERT(sizeof(typename InputStream::Ch) >= 4);
|
||||
Ch c = is.Take();
|
||||
*codepoint = c;
|
||||
return c <= 0x10FFFF;
|
||||
}
|
||||
|
||||
template <typename InputStream, typename OutputStream>
|
||||
static bool Validate(InputStream& is, OutputStream& os) {
|
||||
RAPIDJSON_STATIC_ASSERT(sizeof(typename InputStream::Ch) >= 4);
|
||||
Ch c;
|
||||
os.Put(c = is.Take());
|
||||
return c <= 0x10FFFF;
|
||||
}
|
||||
};
|
||||
|
||||
//! UTF-32 little endian enocoding.
|
||||
template<typename CharType = unsigned>
|
||||
struct UTF32LE : UTF32<CharType> {
|
||||
template <typename InputByteStream>
|
||||
static CharType TakeBOM(InputByteStream& is) {
|
||||
RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1);
|
||||
CharType c = Take(is);
|
||||
return static_cast<uint32_t>(c) == 0x0000FEFFu ? Take(is) : c;
|
||||
}
|
||||
|
||||
template <typename InputByteStream>
|
||||
static CharType Take(InputByteStream& is) {
|
||||
RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1);
|
||||
unsigned c = static_cast<uint8_t>(is.Take());
|
||||
c |= static_cast<unsigned>(static_cast<uint8_t>(is.Take())) << 8;
|
||||
c |= static_cast<unsigned>(static_cast<uint8_t>(is.Take())) << 16;
|
||||
c |= static_cast<unsigned>(static_cast<uint8_t>(is.Take())) << 24;
|
||||
return static_cast<CharType>(c);
|
||||
}
|
||||
|
||||
template <typename OutputByteStream>
|
||||
static void PutBOM(OutputByteStream& os) {
|
||||
RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1);
|
||||
os.Put(static_cast<typename OutputByteStream::Ch>(0xFFu));
|
||||
os.Put(static_cast<typename OutputByteStream::Ch>(0xFEu));
|
||||
os.Put(static_cast<typename OutputByteStream::Ch>(0x00u));
|
||||
os.Put(static_cast<typename OutputByteStream::Ch>(0x00u));
|
||||
}
|
||||
|
||||
template <typename OutputByteStream>
|
||||
static void Put(OutputByteStream& os, CharType c) {
|
||||
RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1);
|
||||
os.Put(static_cast<typename OutputByteStream::Ch>(c & 0xFFu));
|
||||
os.Put(static_cast<typename OutputByteStream::Ch>((c >> 8) & 0xFFu));
|
||||
os.Put(static_cast<typename OutputByteStream::Ch>((c >> 16) & 0xFFu));
|
||||
os.Put(static_cast<typename OutputByteStream::Ch>((c >> 24) & 0xFFu));
|
||||
}
|
||||
};
|
||||
|
||||
//! UTF-32 big endian encoding.
|
||||
template<typename CharType = unsigned>
|
||||
struct UTF32BE : UTF32<CharType> {
|
||||
template <typename InputByteStream>
|
||||
static CharType TakeBOM(InputByteStream& is) {
|
||||
RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1);
|
||||
CharType c = Take(is);
|
||||
return static_cast<uint32_t>(c) == 0x0000FEFFu ? Take(is) : c;
|
||||
}
|
||||
|
||||
template <typename InputByteStream>
|
||||
static CharType Take(InputByteStream& is) {
|
||||
RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1);
|
||||
unsigned c = static_cast<unsigned>(static_cast<uint8_t>(is.Take())) << 24;
|
||||
c |= static_cast<unsigned>(static_cast<uint8_t>(is.Take())) << 16;
|
||||
c |= static_cast<unsigned>(static_cast<uint8_t>(is.Take())) << 8;
|
||||
c |= static_cast<unsigned>(static_cast<uint8_t>(is.Take()));
|
||||
return static_cast<CharType>(c);
|
||||
}
|
||||
|
||||
template <typename OutputByteStream>
|
||||
static void PutBOM(OutputByteStream& os) {
|
||||
RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1);
|
||||
os.Put(static_cast<typename OutputByteStream::Ch>(0x00u));
|
||||
os.Put(static_cast<typename OutputByteStream::Ch>(0x00u));
|
||||
os.Put(static_cast<typename OutputByteStream::Ch>(0xFEu));
|
||||
os.Put(static_cast<typename OutputByteStream::Ch>(0xFFu));
|
||||
}
|
||||
|
||||
template <typename OutputByteStream>
|
||||
static void Put(OutputByteStream& os, CharType c) {
|
||||
RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1);
|
||||
os.Put(static_cast<typename OutputByteStream::Ch>((c >> 24) & 0xFFu));
|
||||
os.Put(static_cast<typename OutputByteStream::Ch>((c >> 16) & 0xFFu));
|
||||
os.Put(static_cast<typename OutputByteStream::Ch>((c >> 8) & 0xFFu));
|
||||
os.Put(static_cast<typename OutputByteStream::Ch>(c & 0xFFu));
|
||||
}
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// ASCII
|
||||
|
||||
//! ASCII encoding.
|
||||
/*! http://en.wikipedia.org/wiki/ASCII
|
||||
\tparam CharType Code unit for storing 7-bit ASCII data. Default is char.
|
||||
\note implements Encoding concept
|
||||
*/
|
||||
template<typename CharType = char>
|
||||
struct ASCII {
|
||||
typedef CharType Ch;
|
||||
|
||||
enum { supportUnicode = 0 };
|
||||
|
||||
template<typename OutputStream>
|
||||
static void Encode(OutputStream& os, unsigned codepoint) {
|
||||
RAPIDJSON_ASSERT(codepoint <= 0x7F);
|
||||
os.Put(static_cast<Ch>(codepoint & 0xFF));
|
||||
}
|
||||
|
||||
template<typename OutputStream>
|
||||
static void EncodeUnsafe(OutputStream& os, unsigned codepoint) {
|
||||
RAPIDJSON_ASSERT(codepoint <= 0x7F);
|
||||
PutUnsafe(os, static_cast<Ch>(codepoint & 0xFF));
|
||||
}
|
||||
|
||||
template <typename InputStream>
|
||||
static bool Decode(InputStream& is, unsigned* codepoint) {
|
||||
uint8_t c = static_cast<uint8_t>(is.Take());
|
||||
*codepoint = c;
|
||||
return c <= 0X7F;
|
||||
}
|
||||
|
||||
template <typename InputStream, typename OutputStream>
|
||||
static bool Validate(InputStream& is, OutputStream& os) {
|
||||
uint8_t c = static_cast<uint8_t>(is.Take());
|
||||
os.Put(static_cast<typename OutputStream::Ch>(c));
|
||||
return c <= 0x7F;
|
||||
}
|
||||
|
||||
template <typename InputByteStream>
|
||||
static CharType TakeBOM(InputByteStream& is) {
|
||||
RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1);
|
||||
uint8_t c = static_cast<uint8_t>(Take(is));
|
||||
return static_cast<Ch>(c);
|
||||
}
|
||||
|
||||
template <typename InputByteStream>
|
||||
static Ch Take(InputByteStream& is) {
|
||||
RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1);
|
||||
return static_cast<Ch>(is.Take());
|
||||
}
|
||||
|
||||
template <typename OutputByteStream>
|
||||
static void PutBOM(OutputByteStream& os) {
|
||||
RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1);
|
||||
(void)os;
|
||||
}
|
||||
|
||||
template <typename OutputByteStream>
|
||||
static void Put(OutputByteStream& os, Ch c) {
|
||||
RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1);
|
||||
os.Put(static_cast<typename OutputByteStream::Ch>(c));
|
||||
}
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// AutoUTF
|
||||
|
||||
//! Runtime-specified UTF encoding type of a stream.
|
||||
enum UTFType {
|
||||
kUTF8 = 0, //!< UTF-8.
|
||||
kUTF16LE = 1, //!< UTF-16 little endian.
|
||||
kUTF16BE = 2, //!< UTF-16 big endian.
|
||||
kUTF32LE = 3, //!< UTF-32 little endian.
|
||||
kUTF32BE = 4 //!< UTF-32 big endian.
|
||||
};
|
||||
|
||||
//! Dynamically select encoding according to stream's runtime-specified UTF encoding type.
|
||||
/*! \note This class can be used with AutoUTFInputtStream and AutoUTFOutputStream, which provides GetType().
|
||||
*/
|
||||
template<typename CharType>
|
||||
struct AutoUTF {
|
||||
typedef CharType Ch;
|
||||
|
||||
enum { supportUnicode = 1 };
|
||||
|
||||
#define RAPIDJSON_ENCODINGS_FUNC(x) UTF8<Ch>::x, UTF16LE<Ch>::x, UTF16BE<Ch>::x, UTF32LE<Ch>::x, UTF32BE<Ch>::x
|
||||
|
||||
template<typename OutputStream>
|
||||
RAPIDJSON_FORCEINLINE static void Encode(OutputStream& os, unsigned codepoint) {
|
||||
typedef void (*EncodeFunc)(OutputStream&, unsigned);
|
||||
static const EncodeFunc f[] = { RAPIDJSON_ENCODINGS_FUNC(Encode) };
|
||||
(*f[os.GetType()])(os, codepoint);
|
||||
}
|
||||
|
||||
template<typename OutputStream>
|
||||
RAPIDJSON_FORCEINLINE static void EncodeUnsafe(OutputStream& os, unsigned codepoint) {
|
||||
typedef void (*EncodeFunc)(OutputStream&, unsigned);
|
||||
static const EncodeFunc f[] = { RAPIDJSON_ENCODINGS_FUNC(EncodeUnsafe) };
|
||||
(*f[os.GetType()])(os, codepoint);
|
||||
}
|
||||
|
||||
template <typename InputStream>
|
||||
RAPIDJSON_FORCEINLINE static bool Decode(InputStream& is, unsigned* codepoint) {
|
||||
typedef bool (*DecodeFunc)(InputStream&, unsigned*);
|
||||
static const DecodeFunc f[] = { RAPIDJSON_ENCODINGS_FUNC(Decode) };
|
||||
return (*f[is.GetType()])(is, codepoint);
|
||||
}
|
||||
|
||||
template <typename InputStream, typename OutputStream>
|
||||
RAPIDJSON_FORCEINLINE static bool Validate(InputStream& is, OutputStream& os) {
|
||||
typedef bool (*ValidateFunc)(InputStream&, OutputStream&);
|
||||
static const ValidateFunc f[] = { RAPIDJSON_ENCODINGS_FUNC(Validate) };
|
||||
return (*f[is.GetType()])(is, os);
|
||||
}
|
||||
|
||||
#undef RAPIDJSON_ENCODINGS_FUNC
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Transcoder
|
||||
|
||||
//! Encoding conversion.
|
||||
template<typename SourceEncoding, typename TargetEncoding>
|
||||
struct Transcoder {
|
||||
//! Take one Unicode codepoint from source encoding, convert it to target encoding and put it to the output stream.
|
||||
template<typename InputStream, typename OutputStream>
|
||||
RAPIDJSON_FORCEINLINE static bool Transcode(InputStream& is, OutputStream& os) {
|
||||
unsigned codepoint;
|
||||
if (!SourceEncoding::Decode(is, &codepoint))
|
||||
return false;
|
||||
TargetEncoding::Encode(os, codepoint);
|
||||
return true;
|
||||
}
|
||||
|
||||
template<typename InputStream, typename OutputStream>
|
||||
RAPIDJSON_FORCEINLINE static bool TranscodeUnsafe(InputStream& is, OutputStream& os) {
|
||||
unsigned codepoint;
|
||||
if (!SourceEncoding::Decode(is, &codepoint))
|
||||
return false;
|
||||
TargetEncoding::EncodeUnsafe(os, codepoint);
|
||||
return true;
|
||||
}
|
||||
|
||||
//! Validate one Unicode codepoint from an encoded stream.
|
||||
template<typename InputStream, typename OutputStream>
|
||||
RAPIDJSON_FORCEINLINE static bool Validate(InputStream& is, OutputStream& os) {
|
||||
return Transcode(is, os); // Since source/target encoding is different, must transcode.
|
||||
}
|
||||
};
|
||||
|
||||
// Forward declaration.
|
||||
template<typename Stream>
|
||||
inline void PutUnsafe(Stream& stream, typename Stream::Ch c);
|
||||
|
||||
//! Specialization of Transcoder with same source and target encoding.
|
||||
template<typename Encoding>
|
||||
struct Transcoder<Encoding, Encoding> {
|
||||
template<typename InputStream, typename OutputStream>
|
||||
RAPIDJSON_FORCEINLINE static bool Transcode(InputStream& is, OutputStream& os) {
|
||||
os.Put(is.Take()); // Just copy one code unit. This semantic is different from primary template class.
|
||||
return true;
|
||||
}
|
||||
|
||||
template<typename InputStream, typename OutputStream>
|
||||
RAPIDJSON_FORCEINLINE static bool TranscodeUnsafe(InputStream& is, OutputStream& os) {
|
||||
PutUnsafe(os, is.Take()); // Just copy one code unit. This semantic is different from primary template class.
|
||||
return true;
|
||||
}
|
||||
|
||||
template<typename InputStream, typename OutputStream>
|
||||
RAPIDJSON_FORCEINLINE static bool Validate(InputStream& is, OutputStream& os) {
|
||||
return Encoding::Validate(is, os); // source/target encoding are the same
|
||||
}
|
||||
};
|
||||
|
||||
RAPIDJSON_NAMESPACE_END
|
||||
|
||||
#if defined(__GNUC__) || defined(_MSC_VER)
|
||||
RAPIDJSON_DIAG_POP
|
||||
#endif
|
||||
|
||||
#endif // RAPIDJSON_ENCODINGS_H_
|
||||
74
src/3rdparty/rapidjson/error/en.h
vendored
Normal file
74
src/3rdparty/rapidjson/error/en.h
vendored
Normal file
@@ -0,0 +1,74 @@
|
||||
// Tencent is pleased to support the open source community by making RapidJSON available.
|
||||
//
|
||||
// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
|
||||
//
|
||||
// Licensed under the MIT License (the "License"); you may not use this file except
|
||||
// in compliance with the License. You may obtain a copy of the License at
|
||||
//
|
||||
// http://opensource.org/licenses/MIT
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software distributed
|
||||
// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
|
||||
// CONDITIONS OF ANY KIND, either express or implied. See the License for the
|
||||
// specific language governing permissions and limitations under the License.
|
||||
|
||||
#ifndef RAPIDJSON_ERROR_EN_H_
|
||||
#define RAPIDJSON_ERROR_EN_H_
|
||||
|
||||
#include "error.h"
|
||||
|
||||
#ifdef __clang__
|
||||
RAPIDJSON_DIAG_PUSH
|
||||
RAPIDJSON_DIAG_OFF(switch-enum)
|
||||
RAPIDJSON_DIAG_OFF(covered-switch-default)
|
||||
#endif
|
||||
|
||||
RAPIDJSON_NAMESPACE_BEGIN
|
||||
|
||||
//! Maps error code of parsing into error message.
|
||||
/*!
|
||||
\ingroup RAPIDJSON_ERRORS
|
||||
\param parseErrorCode Error code obtained in parsing.
|
||||
\return the error message.
|
||||
\note User can make a copy of this function for localization.
|
||||
Using switch-case is safer for future modification of error codes.
|
||||
*/
|
||||
inline const RAPIDJSON_ERROR_CHARTYPE* GetParseError_En(ParseErrorCode parseErrorCode) {
|
||||
switch (parseErrorCode) {
|
||||
case kParseErrorNone: return RAPIDJSON_ERROR_STRING("No error.");
|
||||
|
||||
case kParseErrorDocumentEmpty: return RAPIDJSON_ERROR_STRING("The document is empty.");
|
||||
case kParseErrorDocumentRootNotSingular: return RAPIDJSON_ERROR_STRING("The document root must not be followed by other values.");
|
||||
|
||||
case kParseErrorValueInvalid: return RAPIDJSON_ERROR_STRING("Invalid value.");
|
||||
|
||||
case kParseErrorObjectMissName: return RAPIDJSON_ERROR_STRING("Missing a name for object member.");
|
||||
case kParseErrorObjectMissColon: return RAPIDJSON_ERROR_STRING("Missing a colon after a name of object member.");
|
||||
case kParseErrorObjectMissCommaOrCurlyBracket: return RAPIDJSON_ERROR_STRING("Missing a comma or '}' after an object member.");
|
||||
|
||||
case kParseErrorArrayMissCommaOrSquareBracket: return RAPIDJSON_ERROR_STRING("Missing a comma or ']' after an array element.");
|
||||
|
||||
case kParseErrorStringUnicodeEscapeInvalidHex: return RAPIDJSON_ERROR_STRING("Incorrect hex digit after \\u escape in string.");
|
||||
case kParseErrorStringUnicodeSurrogateInvalid: return RAPIDJSON_ERROR_STRING("The surrogate pair in string is invalid.");
|
||||
case kParseErrorStringEscapeInvalid: return RAPIDJSON_ERROR_STRING("Invalid escape character in string.");
|
||||
case kParseErrorStringMissQuotationMark: return RAPIDJSON_ERROR_STRING("Missing a closing quotation mark in string.");
|
||||
case kParseErrorStringInvalidEncoding: return RAPIDJSON_ERROR_STRING("Invalid encoding in string.");
|
||||
|
||||
case kParseErrorNumberTooBig: return RAPIDJSON_ERROR_STRING("Number too big to be stored in double.");
|
||||
case kParseErrorNumberMissFraction: return RAPIDJSON_ERROR_STRING("Miss fraction part in number.");
|
||||
case kParseErrorNumberMissExponent: return RAPIDJSON_ERROR_STRING("Miss exponent in number.");
|
||||
|
||||
case kParseErrorTermination: return RAPIDJSON_ERROR_STRING("Terminate parsing due to Handler error.");
|
||||
case kParseErrorUnspecificSyntaxError: return RAPIDJSON_ERROR_STRING("Unspecific syntax error.");
|
||||
|
||||
default: return RAPIDJSON_ERROR_STRING("Unknown error.");
|
||||
}
|
||||
}
|
||||
|
||||
RAPIDJSON_NAMESPACE_END
|
||||
|
||||
#ifdef __clang__
|
||||
RAPIDJSON_DIAG_POP
|
||||
#endif
|
||||
|
||||
#endif // RAPIDJSON_ERROR_EN_H_
|
||||
155
src/3rdparty/rapidjson/error/error.h
vendored
Normal file
155
src/3rdparty/rapidjson/error/error.h
vendored
Normal file
@@ -0,0 +1,155 @@
|
||||
// Tencent is pleased to support the open source community by making RapidJSON available.
|
||||
//
|
||||
// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
|
||||
//
|
||||
// Licensed under the MIT License (the "License"); you may not use this file except
|
||||
// in compliance with the License. You may obtain a copy of the License at
|
||||
//
|
||||
// http://opensource.org/licenses/MIT
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software distributed
|
||||
// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
|
||||
// CONDITIONS OF ANY KIND, either express or implied. See the License for the
|
||||
// specific language governing permissions and limitations under the License.
|
||||
|
||||
#ifndef RAPIDJSON_ERROR_ERROR_H_
|
||||
#define RAPIDJSON_ERROR_ERROR_H_
|
||||
|
||||
#include "../rapidjson.h"
|
||||
|
||||
#ifdef __clang__
|
||||
RAPIDJSON_DIAG_PUSH
|
||||
RAPIDJSON_DIAG_OFF(padded)
|
||||
#endif
|
||||
|
||||
/*! \file error.h */
|
||||
|
||||
/*! \defgroup RAPIDJSON_ERRORS RapidJSON error handling */
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// RAPIDJSON_ERROR_CHARTYPE
|
||||
|
||||
//! Character type of error messages.
|
||||
/*! \ingroup RAPIDJSON_ERRORS
|
||||
The default character type is \c char.
|
||||
On Windows, user can define this macro as \c TCHAR for supporting both
|
||||
unicode/non-unicode settings.
|
||||
*/
|
||||
#ifndef RAPIDJSON_ERROR_CHARTYPE
|
||||
#define RAPIDJSON_ERROR_CHARTYPE char
|
||||
#endif
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// RAPIDJSON_ERROR_STRING
|
||||
|
||||
//! Macro for converting string literial to \ref RAPIDJSON_ERROR_CHARTYPE[].
|
||||
/*! \ingroup RAPIDJSON_ERRORS
|
||||
By default this conversion macro does nothing.
|
||||
On Windows, user can define this macro as \c _T(x) for supporting both
|
||||
unicode/non-unicode settings.
|
||||
*/
|
||||
#ifndef RAPIDJSON_ERROR_STRING
|
||||
#define RAPIDJSON_ERROR_STRING(x) x
|
||||
#endif
|
||||
|
||||
RAPIDJSON_NAMESPACE_BEGIN
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// ParseErrorCode
|
||||
|
||||
//! Error code of parsing.
|
||||
/*! \ingroup RAPIDJSON_ERRORS
|
||||
\see GenericReader::Parse, GenericReader::GetParseErrorCode
|
||||
*/
|
||||
enum ParseErrorCode {
|
||||
kParseErrorNone = 0, //!< No error.
|
||||
|
||||
kParseErrorDocumentEmpty, //!< The document is empty.
|
||||
kParseErrorDocumentRootNotSingular, //!< The document root must not follow by other values.
|
||||
|
||||
kParseErrorValueInvalid, //!< Invalid value.
|
||||
|
||||
kParseErrorObjectMissName, //!< Missing a name for object member.
|
||||
kParseErrorObjectMissColon, //!< Missing a colon after a name of object member.
|
||||
kParseErrorObjectMissCommaOrCurlyBracket, //!< Missing a comma or '}' after an object member.
|
||||
|
||||
kParseErrorArrayMissCommaOrSquareBracket, //!< Missing a comma or ']' after an array element.
|
||||
|
||||
kParseErrorStringUnicodeEscapeInvalidHex, //!< Incorrect hex digit after \\u escape in string.
|
||||
kParseErrorStringUnicodeSurrogateInvalid, //!< The surrogate pair in string is invalid.
|
||||
kParseErrorStringEscapeInvalid, //!< Invalid escape character in string.
|
||||
kParseErrorStringMissQuotationMark, //!< Missing a closing quotation mark in string.
|
||||
kParseErrorStringInvalidEncoding, //!< Invalid encoding in string.
|
||||
|
||||
kParseErrorNumberTooBig, //!< Number too big to be stored in double.
|
||||
kParseErrorNumberMissFraction, //!< Miss fraction part in number.
|
||||
kParseErrorNumberMissExponent, //!< Miss exponent in number.
|
||||
|
||||
kParseErrorTermination, //!< Parsing was terminated.
|
||||
kParseErrorUnspecificSyntaxError //!< Unspecific syntax error.
|
||||
};
|
||||
|
||||
//! Result of parsing (wraps ParseErrorCode)
|
||||
/*!
|
||||
\ingroup RAPIDJSON_ERRORS
|
||||
\code
|
||||
Document doc;
|
||||
ParseResult ok = doc.Parse("[42]");
|
||||
if (!ok) {
|
||||
fprintf(stderr, "JSON parse error: %s (%u)",
|
||||
GetParseError_En(ok.Code()), ok.Offset());
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
\endcode
|
||||
\see GenericReader::Parse, GenericDocument::Parse
|
||||
*/
|
||||
struct ParseResult {
|
||||
public:
|
||||
//! Default constructor, no error.
|
||||
ParseResult() : code_(kParseErrorNone), offset_(0) {}
|
||||
//! Constructor to set an error.
|
||||
ParseResult(ParseErrorCode code, size_t offset) : code_(code), offset_(offset) {}
|
||||
|
||||
//! Get the error code.
|
||||
ParseErrorCode Code() const { return code_; }
|
||||
//! Get the error offset, if \ref IsError(), 0 otherwise.
|
||||
size_t Offset() const { return offset_; }
|
||||
|
||||
//! Conversion to \c bool, returns \c true, iff !\ref IsError().
|
||||
operator bool() const { return !IsError(); }
|
||||
//! Whether the result is an error.
|
||||
bool IsError() const { return code_ != kParseErrorNone; }
|
||||
|
||||
bool operator==(const ParseResult& that) const { return code_ == that.code_; }
|
||||
bool operator==(ParseErrorCode code) const { return code_ == code; }
|
||||
friend bool operator==(ParseErrorCode code, const ParseResult & err) { return code == err.code_; }
|
||||
|
||||
//! Reset error code.
|
||||
void Clear() { Set(kParseErrorNone); }
|
||||
//! Update error code and offset.
|
||||
void Set(ParseErrorCode code, size_t offset = 0) { code_ = code; offset_ = offset; }
|
||||
|
||||
private:
|
||||
ParseErrorCode code_;
|
||||
size_t offset_;
|
||||
};
|
||||
|
||||
//! Function pointer type of GetParseError().
|
||||
/*! \ingroup RAPIDJSON_ERRORS
|
||||
|
||||
This is the prototype for \c GetParseError_X(), where \c X is a locale.
|
||||
User can dynamically change locale in runtime, e.g.:
|
||||
\code
|
||||
GetParseErrorFunc GetParseError = GetParseError_En; // or whatever
|
||||
const RAPIDJSON_ERROR_CHARTYPE* s = GetParseError(document.GetParseErrorCode());
|
||||
\endcode
|
||||
*/
|
||||
typedef const RAPIDJSON_ERROR_CHARTYPE* (*GetParseErrorFunc)(ParseErrorCode);
|
||||
|
||||
RAPIDJSON_NAMESPACE_END
|
||||
|
||||
#ifdef __clang__
|
||||
RAPIDJSON_DIAG_POP
|
||||
#endif
|
||||
|
||||
#endif // RAPIDJSON_ERROR_ERROR_H_
|
||||
99
src/3rdparty/rapidjson/filereadstream.h
vendored
Normal file
99
src/3rdparty/rapidjson/filereadstream.h
vendored
Normal file
@@ -0,0 +1,99 @@
|
||||
// Tencent is pleased to support the open source community by making RapidJSON available.
|
||||
//
|
||||
// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
|
||||
//
|
||||
// Licensed under the MIT License (the "License"); you may not use this file except
|
||||
// in compliance with the License. You may obtain a copy of the License at
|
||||
//
|
||||
// http://opensource.org/licenses/MIT
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software distributed
|
||||
// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
|
||||
// CONDITIONS OF ANY KIND, either express or implied. See the License for the
|
||||
// specific language governing permissions and limitations under the License.
|
||||
|
||||
#ifndef RAPIDJSON_FILEREADSTREAM_H_
|
||||
#define RAPIDJSON_FILEREADSTREAM_H_
|
||||
|
||||
#include "stream.h"
|
||||
#include <cstdio>
|
||||
|
||||
#ifdef __clang__
|
||||
RAPIDJSON_DIAG_PUSH
|
||||
RAPIDJSON_DIAG_OFF(padded)
|
||||
RAPIDJSON_DIAG_OFF(unreachable-code)
|
||||
RAPIDJSON_DIAG_OFF(missing-noreturn)
|
||||
#endif
|
||||
|
||||
RAPIDJSON_NAMESPACE_BEGIN
|
||||
|
||||
//! File byte stream for input using fread().
|
||||
/*!
|
||||
\note implements Stream concept
|
||||
*/
|
||||
class FileReadStream {
|
||||
public:
|
||||
typedef char Ch; //!< Character type (byte).
|
||||
|
||||
//! Constructor.
|
||||
/*!
|
||||
\param fp File pointer opened for read.
|
||||
\param buffer user-supplied buffer.
|
||||
\param bufferSize size of buffer in bytes. Must >=4 bytes.
|
||||
*/
|
||||
FileReadStream(std::FILE* fp, char* buffer, size_t bufferSize) : fp_(fp), buffer_(buffer), bufferSize_(bufferSize), bufferLast_(0), current_(buffer_), readCount_(0), count_(0), eof_(false) {
|
||||
RAPIDJSON_ASSERT(fp_ != 0);
|
||||
RAPIDJSON_ASSERT(bufferSize >= 4);
|
||||
Read();
|
||||
}
|
||||
|
||||
Ch Peek() const { return *current_; }
|
||||
Ch Take() { Ch c = *current_; Read(); return c; }
|
||||
size_t Tell() const { return count_ + static_cast<size_t>(current_ - buffer_); }
|
||||
|
||||
// Not implemented
|
||||
void Put(Ch) { RAPIDJSON_ASSERT(false); }
|
||||
void Flush() { RAPIDJSON_ASSERT(false); }
|
||||
Ch* PutBegin() { RAPIDJSON_ASSERT(false); return 0; }
|
||||
size_t PutEnd(Ch*) { RAPIDJSON_ASSERT(false); return 0; }
|
||||
|
||||
// For encoding detection only.
|
||||
const Ch* Peek4() const {
|
||||
return (current_ + 4 <= bufferLast_) ? current_ : 0;
|
||||
}
|
||||
|
||||
private:
|
||||
void Read() {
|
||||
if (current_ < bufferLast_)
|
||||
++current_;
|
||||
else if (!eof_) {
|
||||
count_ += readCount_;
|
||||
readCount_ = fread(buffer_, 1, bufferSize_, fp_);
|
||||
bufferLast_ = buffer_ + readCount_ - 1;
|
||||
current_ = buffer_;
|
||||
|
||||
if (readCount_ < bufferSize_) {
|
||||
buffer_[readCount_] = '\0';
|
||||
++bufferLast_;
|
||||
eof_ = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::FILE* fp_;
|
||||
Ch *buffer_;
|
||||
size_t bufferSize_;
|
||||
Ch *bufferLast_;
|
||||
Ch *current_;
|
||||
size_t readCount_;
|
||||
size_t count_; //!< Number of characters read
|
||||
bool eof_;
|
||||
};
|
||||
|
||||
RAPIDJSON_NAMESPACE_END
|
||||
|
||||
#ifdef __clang__
|
||||
RAPIDJSON_DIAG_POP
|
||||
#endif
|
||||
|
||||
#endif // RAPIDJSON_FILESTREAM_H_
|
||||
104
src/3rdparty/rapidjson/filewritestream.h
vendored
Normal file
104
src/3rdparty/rapidjson/filewritestream.h
vendored
Normal file
@@ -0,0 +1,104 @@
|
||||
// Tencent is pleased to support the open source community by making RapidJSON available.
|
||||
//
|
||||
// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
|
||||
//
|
||||
// Licensed under the MIT License (the "License"); you may not use this file except
|
||||
// in compliance with the License. You may obtain a copy of the License at
|
||||
//
|
||||
// http://opensource.org/licenses/MIT
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software distributed
|
||||
// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
|
||||
// CONDITIONS OF ANY KIND, either express or implied. See the License for the
|
||||
// specific language governing permissions and limitations under the License.
|
||||
|
||||
#ifndef RAPIDJSON_FILEWRITESTREAM_H_
|
||||
#define RAPIDJSON_FILEWRITESTREAM_H_
|
||||
|
||||
#include "stream.h"
|
||||
#include <cstdio>
|
||||
|
||||
#ifdef __clang__
|
||||
RAPIDJSON_DIAG_PUSH
|
||||
RAPIDJSON_DIAG_OFF(unreachable-code)
|
||||
#endif
|
||||
|
||||
RAPIDJSON_NAMESPACE_BEGIN
|
||||
|
||||
//! Wrapper of C file stream for input using fread().
|
||||
/*!
|
||||
\note implements Stream concept
|
||||
*/
|
||||
class FileWriteStream {
|
||||
public:
|
||||
typedef char Ch; //!< Character type. Only support char.
|
||||
|
||||
FileWriteStream(std::FILE* fp, char* buffer, size_t bufferSize) : fp_(fp), buffer_(buffer), bufferEnd_(buffer + bufferSize), current_(buffer_) {
|
||||
RAPIDJSON_ASSERT(fp_ != 0);
|
||||
}
|
||||
|
||||
void Put(char c) {
|
||||
if (current_ >= bufferEnd_)
|
||||
Flush();
|
||||
|
||||
*current_++ = c;
|
||||
}
|
||||
|
||||
void PutN(char c, size_t n) {
|
||||
size_t avail = static_cast<size_t>(bufferEnd_ - current_);
|
||||
while (n > avail) {
|
||||
std::memset(current_, c, avail);
|
||||
current_ += avail;
|
||||
Flush();
|
||||
n -= avail;
|
||||
avail = static_cast<size_t>(bufferEnd_ - current_);
|
||||
}
|
||||
|
||||
if (n > 0) {
|
||||
std::memset(current_, c, n);
|
||||
current_ += n;
|
||||
}
|
||||
}
|
||||
|
||||
void Flush() {
|
||||
if (current_ != buffer_) {
|
||||
size_t result = fwrite(buffer_, 1, static_cast<size_t>(current_ - buffer_), fp_);
|
||||
if (result < static_cast<size_t>(current_ - buffer_)) {
|
||||
// failure deliberately ignored at this time
|
||||
// added to avoid warn_unused_result build errors
|
||||
}
|
||||
current_ = buffer_;
|
||||
}
|
||||
}
|
||||
|
||||
// Not implemented
|
||||
char Peek() const { RAPIDJSON_ASSERT(false); return 0; }
|
||||
char Take() { RAPIDJSON_ASSERT(false); return 0; }
|
||||
size_t Tell() const { RAPIDJSON_ASSERT(false); return 0; }
|
||||
char* PutBegin() { RAPIDJSON_ASSERT(false); return 0; }
|
||||
size_t PutEnd(char*) { RAPIDJSON_ASSERT(false); return 0; }
|
||||
|
||||
private:
|
||||
// Prohibit copy constructor & assignment operator.
|
||||
FileWriteStream(const FileWriteStream&);
|
||||
FileWriteStream& operator=(const FileWriteStream&);
|
||||
|
||||
std::FILE* fp_;
|
||||
char *buffer_;
|
||||
char *bufferEnd_;
|
||||
char *current_;
|
||||
};
|
||||
|
||||
//! Implement specialized version of PutN() with memset() for better performance.
|
||||
template<>
|
||||
inline void PutN(FileWriteStream& stream, char c, size_t n) {
|
||||
stream.PutN(c, n);
|
||||
}
|
||||
|
||||
RAPIDJSON_NAMESPACE_END
|
||||
|
||||
#ifdef __clang__
|
||||
RAPIDJSON_DIAG_POP
|
||||
#endif
|
||||
|
||||
#endif // RAPIDJSON_FILESTREAM_H_
|
||||
151
src/3rdparty/rapidjson/fwd.h
vendored
Normal file
151
src/3rdparty/rapidjson/fwd.h
vendored
Normal file
@@ -0,0 +1,151 @@
|
||||
// Tencent is pleased to support the open source community by making RapidJSON available.
|
||||
//
|
||||
// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
|
||||
//
|
||||
// Licensed under the MIT License (the "License"); you may not use this file except
|
||||
// in compliance with the License. You may obtain a copy of the License at
|
||||
//
|
||||
// http://opensource.org/licenses/MIT
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software distributed
|
||||
// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
|
||||
// CONDITIONS OF ANY KIND, either express or implied. See the License for the
|
||||
// specific language governing permissions and limitations under the License.
|
||||
|
||||
#ifndef RAPIDJSON_FWD_H_
|
||||
#define RAPIDJSON_FWD_H_
|
||||
|
||||
#include "rapidjson.h"
|
||||
|
||||
RAPIDJSON_NAMESPACE_BEGIN
|
||||
|
||||
// encodings.h
|
||||
|
||||
template<typename CharType> struct UTF8;
|
||||
template<typename CharType> struct UTF16;
|
||||
template<typename CharType> struct UTF16BE;
|
||||
template<typename CharType> struct UTF16LE;
|
||||
template<typename CharType> struct UTF32;
|
||||
template<typename CharType> struct UTF32BE;
|
||||
template<typename CharType> struct UTF32LE;
|
||||
template<typename CharType> struct ASCII;
|
||||
template<typename CharType> struct AutoUTF;
|
||||
|
||||
template<typename SourceEncoding, typename TargetEncoding>
|
||||
struct Transcoder;
|
||||
|
||||
// allocators.h
|
||||
|
||||
class CrtAllocator;
|
||||
|
||||
template <typename BaseAllocator>
|
||||
class MemoryPoolAllocator;
|
||||
|
||||
// stream.h
|
||||
|
||||
template <typename Encoding>
|
||||
struct GenericStringStream;
|
||||
|
||||
typedef GenericStringStream<UTF8<char> > StringStream;
|
||||
|
||||
template <typename Encoding>
|
||||
struct GenericInsituStringStream;
|
||||
|
||||
typedef GenericInsituStringStream<UTF8<char> > InsituStringStream;
|
||||
|
||||
// stringbuffer.h
|
||||
|
||||
template <typename Encoding, typename Allocator>
|
||||
class GenericStringBuffer;
|
||||
|
||||
typedef GenericStringBuffer<UTF8<char>, CrtAllocator> StringBuffer;
|
||||
|
||||
// filereadstream.h
|
||||
|
||||
class FileReadStream;
|
||||
|
||||
// filewritestream.h
|
||||
|
||||
class FileWriteStream;
|
||||
|
||||
// memorybuffer.h
|
||||
|
||||
template <typename Allocator>
|
||||
struct GenericMemoryBuffer;
|
||||
|
||||
typedef GenericMemoryBuffer<CrtAllocator> MemoryBuffer;
|
||||
|
||||
// memorystream.h
|
||||
|
||||
struct MemoryStream;
|
||||
|
||||
// reader.h
|
||||
|
||||
template<typename Encoding, typename Derived>
|
||||
struct BaseReaderHandler;
|
||||
|
||||
template <typename SourceEncoding, typename TargetEncoding, typename StackAllocator>
|
||||
class GenericReader;
|
||||
|
||||
typedef GenericReader<UTF8<char>, UTF8<char>, CrtAllocator> Reader;
|
||||
|
||||
// writer.h
|
||||
|
||||
template<typename OutputStream, typename SourceEncoding, typename TargetEncoding, typename StackAllocator, unsigned writeFlags>
|
||||
class Writer;
|
||||
|
||||
// prettywriter.h
|
||||
|
||||
template<typename OutputStream, typename SourceEncoding, typename TargetEncoding, typename StackAllocator, unsigned writeFlags>
|
||||
class PrettyWriter;
|
||||
|
||||
// document.h
|
||||
|
||||
template <typename Encoding, typename Allocator>
|
||||
struct GenericMember;
|
||||
|
||||
template <bool Const, typename Encoding, typename Allocator>
|
||||
class GenericMemberIterator;
|
||||
|
||||
template<typename CharType>
|
||||
struct GenericStringRef;
|
||||
|
||||
template <typename Encoding, typename Allocator>
|
||||
class GenericValue;
|
||||
|
||||
typedef GenericValue<UTF8<char>, MemoryPoolAllocator<CrtAllocator> > Value;
|
||||
|
||||
template <typename Encoding, typename Allocator, typename StackAllocator>
|
||||
class GenericDocument;
|
||||
|
||||
typedef GenericDocument<UTF8<char>, MemoryPoolAllocator<CrtAllocator>, CrtAllocator> Document;
|
||||
|
||||
// pointer.h
|
||||
|
||||
template <typename ValueType, typename Allocator>
|
||||
class GenericPointer;
|
||||
|
||||
typedef GenericPointer<Value, CrtAllocator> Pointer;
|
||||
|
||||
// schema.h
|
||||
|
||||
template <typename SchemaDocumentType>
|
||||
class IGenericRemoteSchemaDocumentProvider;
|
||||
|
||||
template <typename ValueT, typename Allocator>
|
||||
class GenericSchemaDocument;
|
||||
|
||||
typedef GenericSchemaDocument<Value, CrtAllocator> SchemaDocument;
|
||||
typedef IGenericRemoteSchemaDocumentProvider<SchemaDocument> IRemoteSchemaDocumentProvider;
|
||||
|
||||
template <
|
||||
typename SchemaDocumentType,
|
||||
typename OutputHandler,
|
||||
typename StateAllocator>
|
||||
class GenericSchemaValidator;
|
||||
|
||||
typedef GenericSchemaValidator<SchemaDocument, BaseReaderHandler<UTF8<char>, void>, CrtAllocator> SchemaValidator;
|
||||
|
||||
RAPIDJSON_NAMESPACE_END
|
||||
|
||||
#endif // RAPIDJSON_RAPIDJSONFWD_H_
|
||||
290
src/3rdparty/rapidjson/internal/biginteger.h
vendored
Normal file
290
src/3rdparty/rapidjson/internal/biginteger.h
vendored
Normal file
@@ -0,0 +1,290 @@
|
||||
// Tencent is pleased to support the open source community by making RapidJSON available.
|
||||
//
|
||||
// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
|
||||
//
|
||||
// Licensed under the MIT License (the "License"); you may not use this file except
|
||||
// in compliance with the License. You may obtain a copy of the License at
|
||||
//
|
||||
// http://opensource.org/licenses/MIT
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software distributed
|
||||
// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
|
||||
// CONDITIONS OF ANY KIND, either express or implied. See the License for the
|
||||
// specific language governing permissions and limitations under the License.
|
||||
|
||||
#ifndef RAPIDJSON_BIGINTEGER_H_
|
||||
#define RAPIDJSON_BIGINTEGER_H_
|
||||
|
||||
#include "../rapidjson.h"
|
||||
|
||||
#if defined(_MSC_VER) && defined(_M_AMD64)
|
||||
#include <intrin.h> // for _umul128
|
||||
#pragma intrinsic(_umul128)
|
||||
#endif
|
||||
|
||||
RAPIDJSON_NAMESPACE_BEGIN
|
||||
namespace internal {
|
||||
|
||||
class BigInteger {
|
||||
public:
|
||||
typedef uint64_t Type;
|
||||
|
||||
BigInteger(const BigInteger& rhs) : count_(rhs.count_) {
|
||||
std::memcpy(digits_, rhs.digits_, count_ * sizeof(Type));
|
||||
}
|
||||
|
||||
explicit BigInteger(uint64_t u) : count_(1) {
|
||||
digits_[0] = u;
|
||||
}
|
||||
|
||||
BigInteger(const char* decimals, size_t length) : count_(1) {
|
||||
RAPIDJSON_ASSERT(length > 0);
|
||||
digits_[0] = 0;
|
||||
size_t i = 0;
|
||||
const size_t kMaxDigitPerIteration = 19; // 2^64 = 18446744073709551616 > 10^19
|
||||
while (length >= kMaxDigitPerIteration) {
|
||||
AppendDecimal64(decimals + i, decimals + i + kMaxDigitPerIteration);
|
||||
length -= kMaxDigitPerIteration;
|
||||
i += kMaxDigitPerIteration;
|
||||
}
|
||||
|
||||
if (length > 0)
|
||||
AppendDecimal64(decimals + i, decimals + i + length);
|
||||
}
|
||||
|
||||
BigInteger& operator=(const BigInteger &rhs)
|
||||
{
|
||||
if (this != &rhs) {
|
||||
count_ = rhs.count_;
|
||||
std::memcpy(digits_, rhs.digits_, count_ * sizeof(Type));
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
BigInteger& operator=(uint64_t u) {
|
||||
digits_[0] = u;
|
||||
count_ = 1;
|
||||
return *this;
|
||||
}
|
||||
|
||||
BigInteger& operator+=(uint64_t u) {
|
||||
Type backup = digits_[0];
|
||||
digits_[0] += u;
|
||||
for (size_t i = 0; i < count_ - 1; i++) {
|
||||
if (digits_[i] >= backup)
|
||||
return *this; // no carry
|
||||
backup = digits_[i + 1];
|
||||
digits_[i + 1] += 1;
|
||||
}
|
||||
|
||||
// Last carry
|
||||
if (digits_[count_ - 1] < backup)
|
||||
PushBack(1);
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
BigInteger& operator*=(uint64_t u) {
|
||||
if (u == 0) return *this = 0;
|
||||
if (u == 1) return *this;
|
||||
if (*this == 1) return *this = u;
|
||||
|
||||
uint64_t k = 0;
|
||||
for (size_t i = 0; i < count_; i++) {
|
||||
uint64_t hi;
|
||||
digits_[i] = MulAdd64(digits_[i], u, k, &hi);
|
||||
k = hi;
|
||||
}
|
||||
|
||||
if (k > 0)
|
||||
PushBack(k);
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
BigInteger& operator*=(uint32_t u) {
|
||||
if (u == 0) return *this = 0;
|
||||
if (u == 1) return *this;
|
||||
if (*this == 1) return *this = u;
|
||||
|
||||
uint64_t k = 0;
|
||||
for (size_t i = 0; i < count_; i++) {
|
||||
const uint64_t c = digits_[i] >> 32;
|
||||
const uint64_t d = digits_[i] & 0xFFFFFFFF;
|
||||
const uint64_t uc = u * c;
|
||||
const uint64_t ud = u * d;
|
||||
const uint64_t p0 = ud + k;
|
||||
const uint64_t p1 = uc + (p0 >> 32);
|
||||
digits_[i] = (p0 & 0xFFFFFFFF) | (p1 << 32);
|
||||
k = p1 >> 32;
|
||||
}
|
||||
|
||||
if (k > 0)
|
||||
PushBack(k);
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
BigInteger& operator<<=(size_t shift) {
|
||||
if (IsZero() || shift == 0) return *this;
|
||||
|
||||
size_t offset = shift / kTypeBit;
|
||||
size_t interShift = shift % kTypeBit;
|
||||
RAPIDJSON_ASSERT(count_ + offset <= kCapacity);
|
||||
|
||||
if (interShift == 0) {
|
||||
std::memmove(&digits_[count_ - 1 + offset], &digits_[count_ - 1], count_ * sizeof(Type));
|
||||
count_ += offset;
|
||||
}
|
||||
else {
|
||||
digits_[count_] = 0;
|
||||
for (size_t i = count_; i > 0; i--)
|
||||
digits_[i + offset] = (digits_[i] << interShift) | (digits_[i - 1] >> (kTypeBit - interShift));
|
||||
digits_[offset] = digits_[0] << interShift;
|
||||
count_ += offset;
|
||||
if (digits_[count_])
|
||||
count_++;
|
||||
}
|
||||
|
||||
std::memset(digits_, 0, offset * sizeof(Type));
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool operator==(const BigInteger& rhs) const {
|
||||
return count_ == rhs.count_ && std::memcmp(digits_, rhs.digits_, count_ * sizeof(Type)) == 0;
|
||||
}
|
||||
|
||||
bool operator==(const Type rhs) const {
|
||||
return count_ == 1 && digits_[0] == rhs;
|
||||
}
|
||||
|
||||
BigInteger& MultiplyPow5(unsigned exp) {
|
||||
static const uint32_t kPow5[12] = {
|
||||
5,
|
||||
5 * 5,
|
||||
5 * 5 * 5,
|
||||
5 * 5 * 5 * 5,
|
||||
5 * 5 * 5 * 5 * 5,
|
||||
5 * 5 * 5 * 5 * 5 * 5,
|
||||
5 * 5 * 5 * 5 * 5 * 5 * 5,
|
||||
5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,
|
||||
5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,
|
||||
5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,
|
||||
5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,
|
||||
5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5
|
||||
};
|
||||
if (exp == 0) return *this;
|
||||
for (; exp >= 27; exp -= 27) *this *= RAPIDJSON_UINT64_C2(0X6765C793, 0XFA10079D); // 5^27
|
||||
for (; exp >= 13; exp -= 13) *this *= static_cast<uint32_t>(1220703125u); // 5^13
|
||||
if (exp > 0) *this *= kPow5[exp - 1];
|
||||
return *this;
|
||||
}
|
||||
|
||||
// Compute absolute difference of this and rhs.
|
||||
// Assume this != rhs
|
||||
bool Difference(const BigInteger& rhs, BigInteger* out) const {
|
||||
int cmp = Compare(rhs);
|
||||
RAPIDJSON_ASSERT(cmp != 0);
|
||||
const BigInteger *a, *b; // Makes a > b
|
||||
bool ret;
|
||||
if (cmp < 0) { a = &rhs; b = this; ret = true; }
|
||||
else { a = this; b = &rhs; ret = false; }
|
||||
|
||||
Type borrow = 0;
|
||||
for (size_t i = 0; i < a->count_; i++) {
|
||||
Type d = a->digits_[i] - borrow;
|
||||
if (i < b->count_)
|
||||
d -= b->digits_[i];
|
||||
borrow = (d > a->digits_[i]) ? 1 : 0;
|
||||
out->digits_[i] = d;
|
||||
if (d != 0)
|
||||
out->count_ = i + 1;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int Compare(const BigInteger& rhs) const {
|
||||
if (count_ != rhs.count_)
|
||||
return count_ < rhs.count_ ? -1 : 1;
|
||||
|
||||
for (size_t i = count_; i-- > 0;)
|
||||
if (digits_[i] != rhs.digits_[i])
|
||||
return digits_[i] < rhs.digits_[i] ? -1 : 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
size_t GetCount() const { return count_; }
|
||||
Type GetDigit(size_t index) const { RAPIDJSON_ASSERT(index < count_); return digits_[index]; }
|
||||
bool IsZero() const { return count_ == 1 && digits_[0] == 0; }
|
||||
|
||||
private:
|
||||
void AppendDecimal64(const char* begin, const char* end) {
|
||||
uint64_t u = ParseUint64(begin, end);
|
||||
if (IsZero())
|
||||
*this = u;
|
||||
else {
|
||||
unsigned exp = static_cast<unsigned>(end - begin);
|
||||
(MultiplyPow5(exp) <<= exp) += u; // *this = *this * 10^exp + u
|
||||
}
|
||||
}
|
||||
|
||||
void PushBack(Type digit) {
|
||||
RAPIDJSON_ASSERT(count_ < kCapacity);
|
||||
digits_[count_++] = digit;
|
||||
}
|
||||
|
||||
static uint64_t ParseUint64(const char* begin, const char* end) {
|
||||
uint64_t r = 0;
|
||||
for (const char* p = begin; p != end; ++p) {
|
||||
RAPIDJSON_ASSERT(*p >= '0' && *p <= '9');
|
||||
r = r * 10u + static_cast<unsigned>(*p - '0');
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
// Assume a * b + k < 2^128
|
||||
static uint64_t MulAdd64(uint64_t a, uint64_t b, uint64_t k, uint64_t* outHigh) {
|
||||
#if defined(_MSC_VER) && defined(_M_AMD64)
|
||||
uint64_t low = _umul128(a, b, outHigh) + k;
|
||||
if (low < k)
|
||||
(*outHigh)++;
|
||||
return low;
|
||||
#elif (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)) && defined(__x86_64__)
|
||||
__extension__ typedef unsigned __int128 uint128;
|
||||
uint128 p = static_cast<uint128>(a) * static_cast<uint128>(b);
|
||||
p += k;
|
||||
*outHigh = static_cast<uint64_t>(p >> 64);
|
||||
return static_cast<uint64_t>(p);
|
||||
#else
|
||||
const uint64_t a0 = a & 0xFFFFFFFF, a1 = a >> 32, b0 = b & 0xFFFFFFFF, b1 = b >> 32;
|
||||
uint64_t x0 = a0 * b0, x1 = a0 * b1, x2 = a1 * b0, x3 = a1 * b1;
|
||||
x1 += (x0 >> 32); // can't give carry
|
||||
x1 += x2;
|
||||
if (x1 < x2)
|
||||
x3 += (static_cast<uint64_t>(1) << 32);
|
||||
uint64_t lo = (x1 << 32) + (x0 & 0xFFFFFFFF);
|
||||
uint64_t hi = x3 + (x1 >> 32);
|
||||
|
||||
lo += k;
|
||||
if (lo < k)
|
||||
hi++;
|
||||
*outHigh = hi;
|
||||
return lo;
|
||||
#endif
|
||||
}
|
||||
|
||||
static const size_t kBitCount = 3328; // 64bit * 54 > 10^1000
|
||||
static const size_t kCapacity = kBitCount / sizeof(Type);
|
||||
static const size_t kTypeBit = sizeof(Type) * 8;
|
||||
|
||||
Type digits_[kCapacity];
|
||||
size_t count_;
|
||||
};
|
||||
|
||||
} // namespace internal
|
||||
RAPIDJSON_NAMESPACE_END
|
||||
|
||||
#endif // RAPIDJSON_BIGINTEGER_H_
|
||||
258
src/3rdparty/rapidjson/internal/diyfp.h
vendored
Normal file
258
src/3rdparty/rapidjson/internal/diyfp.h
vendored
Normal file
@@ -0,0 +1,258 @@
|
||||
// Tencent is pleased to support the open source community by making RapidJSON available.
|
||||
//
|
||||
// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
|
||||
//
|
||||
// Licensed under the MIT License (the "License"); you may not use this file except
|
||||
// in compliance with the License. You may obtain a copy of the License at
|
||||
//
|
||||
// http://opensource.org/licenses/MIT
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software distributed
|
||||
// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
|
||||
// CONDITIONS OF ANY KIND, either express or implied. See the License for the
|
||||
// specific language governing permissions and limitations under the License.
|
||||
|
||||
// This is a C++ header-only implementation of Grisu2 algorithm from the publication:
|
||||
// Loitsch, Florian. "Printing floating-point numbers quickly and accurately with
|
||||
// integers." ACM Sigplan Notices 45.6 (2010): 233-243.
|
||||
|
||||
#ifndef RAPIDJSON_DIYFP_H_
|
||||
#define RAPIDJSON_DIYFP_H_
|
||||
|
||||
#include "../rapidjson.h"
|
||||
|
||||
#if defined(_MSC_VER) && defined(_M_AMD64)
|
||||
#include <intrin.h>
|
||||
#pragma intrinsic(_BitScanReverse64)
|
||||
#pragma intrinsic(_umul128)
|
||||
#endif
|
||||
|
||||
RAPIDJSON_NAMESPACE_BEGIN
|
||||
namespace internal {
|
||||
|
||||
#ifdef __GNUC__
|
||||
RAPIDJSON_DIAG_PUSH
|
||||
RAPIDJSON_DIAG_OFF(effc++)
|
||||
#endif
|
||||
|
||||
#ifdef __clang__
|
||||
RAPIDJSON_DIAG_PUSH
|
||||
RAPIDJSON_DIAG_OFF(padded)
|
||||
#endif
|
||||
|
||||
struct DiyFp {
|
||||
DiyFp() : f(), e() {}
|
||||
|
||||
DiyFp(uint64_t fp, int exp) : f(fp), e(exp) {}
|
||||
|
||||
explicit DiyFp(double d) {
|
||||
union {
|
||||
double d;
|
||||
uint64_t u64;
|
||||
} u = { d };
|
||||
|
||||
int biased_e = static_cast<int>((u.u64 & kDpExponentMask) >> kDpSignificandSize);
|
||||
uint64_t significand = (u.u64 & kDpSignificandMask);
|
||||
if (biased_e != 0) {
|
||||
f = significand + kDpHiddenBit;
|
||||
e = biased_e - kDpExponentBias;
|
||||
}
|
||||
else {
|
||||
f = significand;
|
||||
e = kDpMinExponent + 1;
|
||||
}
|
||||
}
|
||||
|
||||
DiyFp operator-(const DiyFp& rhs) const {
|
||||
return DiyFp(f - rhs.f, e);
|
||||
}
|
||||
|
||||
DiyFp operator*(const DiyFp& rhs) const {
|
||||
#if defined(_MSC_VER) && defined(_M_AMD64)
|
||||
uint64_t h;
|
||||
uint64_t l = _umul128(f, rhs.f, &h);
|
||||
if (l & (uint64_t(1) << 63)) // rounding
|
||||
h++;
|
||||
return DiyFp(h, e + rhs.e + 64);
|
||||
#elif (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)) && defined(__x86_64__)
|
||||
__extension__ typedef unsigned __int128 uint128;
|
||||
uint128 p = static_cast<uint128>(f) * static_cast<uint128>(rhs.f);
|
||||
uint64_t h = static_cast<uint64_t>(p >> 64);
|
||||
uint64_t l = static_cast<uint64_t>(p);
|
||||
if (l & (uint64_t(1) << 63)) // rounding
|
||||
h++;
|
||||
return DiyFp(h, e + rhs.e + 64);
|
||||
#else
|
||||
const uint64_t M32 = 0xFFFFFFFF;
|
||||
const uint64_t a = f >> 32;
|
||||
const uint64_t b = f & M32;
|
||||
const uint64_t c = rhs.f >> 32;
|
||||
const uint64_t d = rhs.f & M32;
|
||||
const uint64_t ac = a * c;
|
||||
const uint64_t bc = b * c;
|
||||
const uint64_t ad = a * d;
|
||||
const uint64_t bd = b * d;
|
||||
uint64_t tmp = (bd >> 32) + (ad & M32) + (bc & M32);
|
||||
tmp += 1U << 31; /// mult_round
|
||||
return DiyFp(ac + (ad >> 32) + (bc >> 32) + (tmp >> 32), e + rhs.e + 64);
|
||||
#endif
|
||||
}
|
||||
|
||||
DiyFp Normalize() const {
|
||||
#if defined(_MSC_VER) && defined(_M_AMD64)
|
||||
unsigned long index;
|
||||
_BitScanReverse64(&index, f);
|
||||
return DiyFp(f << (63 - index), e - (63 - index));
|
||||
#elif defined(__GNUC__) && __GNUC__ >= 4
|
||||
int s = __builtin_clzll(f);
|
||||
return DiyFp(f << s, e - s);
|
||||
#else
|
||||
DiyFp res = *this;
|
||||
while (!(res.f & (static_cast<uint64_t>(1) << 63))) {
|
||||
res.f <<= 1;
|
||||
res.e--;
|
||||
}
|
||||
return res;
|
||||
#endif
|
||||
}
|
||||
|
||||
DiyFp NormalizeBoundary() const {
|
||||
DiyFp res = *this;
|
||||
while (!(res.f & (kDpHiddenBit << 1))) {
|
||||
res.f <<= 1;
|
||||
res.e--;
|
||||
}
|
||||
res.f <<= (kDiySignificandSize - kDpSignificandSize - 2);
|
||||
res.e = res.e - (kDiySignificandSize - kDpSignificandSize - 2);
|
||||
return res;
|
||||
}
|
||||
|
||||
void NormalizedBoundaries(DiyFp* minus, DiyFp* plus) const {
|
||||
DiyFp pl = DiyFp((f << 1) + 1, e - 1).NormalizeBoundary();
|
||||
DiyFp mi = (f == kDpHiddenBit) ? DiyFp((f << 2) - 1, e - 2) : DiyFp((f << 1) - 1, e - 1);
|
||||
mi.f <<= mi.e - pl.e;
|
||||
mi.e = pl.e;
|
||||
*plus = pl;
|
||||
*minus = mi;
|
||||
}
|
||||
|
||||
double ToDouble() const {
|
||||
union {
|
||||
double d;
|
||||
uint64_t u64;
|
||||
}u;
|
||||
const uint64_t be = (e == kDpDenormalExponent && (f & kDpHiddenBit) == 0) ? 0 :
|
||||
static_cast<uint64_t>(e + kDpExponentBias);
|
||||
u.u64 = (f & kDpSignificandMask) | (be << kDpSignificandSize);
|
||||
return u.d;
|
||||
}
|
||||
|
||||
static const int kDiySignificandSize = 64;
|
||||
static const int kDpSignificandSize = 52;
|
||||
static const int kDpExponentBias = 0x3FF + kDpSignificandSize;
|
||||
static const int kDpMaxExponent = 0x7FF - kDpExponentBias;
|
||||
static const int kDpMinExponent = -kDpExponentBias;
|
||||
static const int kDpDenormalExponent = -kDpExponentBias + 1;
|
||||
static const uint64_t kDpExponentMask = RAPIDJSON_UINT64_C2(0x7FF00000, 0x00000000);
|
||||
static const uint64_t kDpSignificandMask = RAPIDJSON_UINT64_C2(0x000FFFFF, 0xFFFFFFFF);
|
||||
static const uint64_t kDpHiddenBit = RAPIDJSON_UINT64_C2(0x00100000, 0x00000000);
|
||||
|
||||
uint64_t f;
|
||||
int e;
|
||||
};
|
||||
|
||||
inline DiyFp GetCachedPowerByIndex(size_t index) {
|
||||
// 10^-348, 10^-340, ..., 10^340
|
||||
static const uint64_t kCachedPowers_F[] = {
|
||||
RAPIDJSON_UINT64_C2(0xfa8fd5a0, 0x081c0288), RAPIDJSON_UINT64_C2(0xbaaee17f, 0xa23ebf76),
|
||||
RAPIDJSON_UINT64_C2(0x8b16fb20, 0x3055ac76), RAPIDJSON_UINT64_C2(0xcf42894a, 0x5dce35ea),
|
||||
RAPIDJSON_UINT64_C2(0x9a6bb0aa, 0x55653b2d), RAPIDJSON_UINT64_C2(0xe61acf03, 0x3d1a45df),
|
||||
RAPIDJSON_UINT64_C2(0xab70fe17, 0xc79ac6ca), RAPIDJSON_UINT64_C2(0xff77b1fc, 0xbebcdc4f),
|
||||
RAPIDJSON_UINT64_C2(0xbe5691ef, 0x416bd60c), RAPIDJSON_UINT64_C2(0x8dd01fad, 0x907ffc3c),
|
||||
RAPIDJSON_UINT64_C2(0xd3515c28, 0x31559a83), RAPIDJSON_UINT64_C2(0x9d71ac8f, 0xada6c9b5),
|
||||
RAPIDJSON_UINT64_C2(0xea9c2277, 0x23ee8bcb), RAPIDJSON_UINT64_C2(0xaecc4991, 0x4078536d),
|
||||
RAPIDJSON_UINT64_C2(0x823c1279, 0x5db6ce57), RAPIDJSON_UINT64_C2(0xc2109436, 0x4dfb5637),
|
||||
RAPIDJSON_UINT64_C2(0x9096ea6f, 0x3848984f), RAPIDJSON_UINT64_C2(0xd77485cb, 0x25823ac7),
|
||||
RAPIDJSON_UINT64_C2(0xa086cfcd, 0x97bf97f4), RAPIDJSON_UINT64_C2(0xef340a98, 0x172aace5),
|
||||
RAPIDJSON_UINT64_C2(0xb23867fb, 0x2a35b28e), RAPIDJSON_UINT64_C2(0x84c8d4df, 0xd2c63f3b),
|
||||
RAPIDJSON_UINT64_C2(0xc5dd4427, 0x1ad3cdba), RAPIDJSON_UINT64_C2(0x936b9fce, 0xbb25c996),
|
||||
RAPIDJSON_UINT64_C2(0xdbac6c24, 0x7d62a584), RAPIDJSON_UINT64_C2(0xa3ab6658, 0x0d5fdaf6),
|
||||
RAPIDJSON_UINT64_C2(0xf3e2f893, 0xdec3f126), RAPIDJSON_UINT64_C2(0xb5b5ada8, 0xaaff80b8),
|
||||
RAPIDJSON_UINT64_C2(0x87625f05, 0x6c7c4a8b), RAPIDJSON_UINT64_C2(0xc9bcff60, 0x34c13053),
|
||||
RAPIDJSON_UINT64_C2(0x964e858c, 0x91ba2655), RAPIDJSON_UINT64_C2(0xdff97724, 0x70297ebd),
|
||||
RAPIDJSON_UINT64_C2(0xa6dfbd9f, 0xb8e5b88f), RAPIDJSON_UINT64_C2(0xf8a95fcf, 0x88747d94),
|
||||
RAPIDJSON_UINT64_C2(0xb9447093, 0x8fa89bcf), RAPIDJSON_UINT64_C2(0x8a08f0f8, 0xbf0f156b),
|
||||
RAPIDJSON_UINT64_C2(0xcdb02555, 0x653131b6), RAPIDJSON_UINT64_C2(0x993fe2c6, 0xd07b7fac),
|
||||
RAPIDJSON_UINT64_C2(0xe45c10c4, 0x2a2b3b06), RAPIDJSON_UINT64_C2(0xaa242499, 0x697392d3),
|
||||
RAPIDJSON_UINT64_C2(0xfd87b5f2, 0x8300ca0e), RAPIDJSON_UINT64_C2(0xbce50864, 0x92111aeb),
|
||||
RAPIDJSON_UINT64_C2(0x8cbccc09, 0x6f5088cc), RAPIDJSON_UINT64_C2(0xd1b71758, 0xe219652c),
|
||||
RAPIDJSON_UINT64_C2(0x9c400000, 0x00000000), RAPIDJSON_UINT64_C2(0xe8d4a510, 0x00000000),
|
||||
RAPIDJSON_UINT64_C2(0xad78ebc5, 0xac620000), RAPIDJSON_UINT64_C2(0x813f3978, 0xf8940984),
|
||||
RAPIDJSON_UINT64_C2(0xc097ce7b, 0xc90715b3), RAPIDJSON_UINT64_C2(0x8f7e32ce, 0x7bea5c70),
|
||||
RAPIDJSON_UINT64_C2(0xd5d238a4, 0xabe98068), RAPIDJSON_UINT64_C2(0x9f4f2726, 0x179a2245),
|
||||
RAPIDJSON_UINT64_C2(0xed63a231, 0xd4c4fb27), RAPIDJSON_UINT64_C2(0xb0de6538, 0x8cc8ada8),
|
||||
RAPIDJSON_UINT64_C2(0x83c7088e, 0x1aab65db), RAPIDJSON_UINT64_C2(0xc45d1df9, 0x42711d9a),
|
||||
RAPIDJSON_UINT64_C2(0x924d692c, 0xa61be758), RAPIDJSON_UINT64_C2(0xda01ee64, 0x1a708dea),
|
||||
RAPIDJSON_UINT64_C2(0xa26da399, 0x9aef774a), RAPIDJSON_UINT64_C2(0xf209787b, 0xb47d6b85),
|
||||
RAPIDJSON_UINT64_C2(0xb454e4a1, 0x79dd1877), RAPIDJSON_UINT64_C2(0x865b8692, 0x5b9bc5c2),
|
||||
RAPIDJSON_UINT64_C2(0xc83553c5, 0xc8965d3d), RAPIDJSON_UINT64_C2(0x952ab45c, 0xfa97a0b3),
|
||||
RAPIDJSON_UINT64_C2(0xde469fbd, 0x99a05fe3), RAPIDJSON_UINT64_C2(0xa59bc234, 0xdb398c25),
|
||||
RAPIDJSON_UINT64_C2(0xf6c69a72, 0xa3989f5c), RAPIDJSON_UINT64_C2(0xb7dcbf53, 0x54e9bece),
|
||||
RAPIDJSON_UINT64_C2(0x88fcf317, 0xf22241e2), RAPIDJSON_UINT64_C2(0xcc20ce9b, 0xd35c78a5),
|
||||
RAPIDJSON_UINT64_C2(0x98165af3, 0x7b2153df), RAPIDJSON_UINT64_C2(0xe2a0b5dc, 0x971f303a),
|
||||
RAPIDJSON_UINT64_C2(0xa8d9d153, 0x5ce3b396), RAPIDJSON_UINT64_C2(0xfb9b7cd9, 0xa4a7443c),
|
||||
RAPIDJSON_UINT64_C2(0xbb764c4c, 0xa7a44410), RAPIDJSON_UINT64_C2(0x8bab8eef, 0xb6409c1a),
|
||||
RAPIDJSON_UINT64_C2(0xd01fef10, 0xa657842c), RAPIDJSON_UINT64_C2(0x9b10a4e5, 0xe9913129),
|
||||
RAPIDJSON_UINT64_C2(0xe7109bfb, 0xa19c0c9d), RAPIDJSON_UINT64_C2(0xac2820d9, 0x623bf429),
|
||||
RAPIDJSON_UINT64_C2(0x80444b5e, 0x7aa7cf85), RAPIDJSON_UINT64_C2(0xbf21e440, 0x03acdd2d),
|
||||
RAPIDJSON_UINT64_C2(0x8e679c2f, 0x5e44ff8f), RAPIDJSON_UINT64_C2(0xd433179d, 0x9c8cb841),
|
||||
RAPIDJSON_UINT64_C2(0x9e19db92, 0xb4e31ba9), RAPIDJSON_UINT64_C2(0xeb96bf6e, 0xbadf77d9),
|
||||
RAPIDJSON_UINT64_C2(0xaf87023b, 0x9bf0ee6b)
|
||||
};
|
||||
static const int16_t kCachedPowers_E[] = {
|
||||
-1220, -1193, -1166, -1140, -1113, -1087, -1060, -1034, -1007, -980,
|
||||
-954, -927, -901, -874, -847, -821, -794, -768, -741, -715,
|
||||
-688, -661, -635, -608, -582, -555, -529, -502, -475, -449,
|
||||
-422, -396, -369, -343, -316, -289, -263, -236, -210, -183,
|
||||
-157, -130, -103, -77, -50, -24, 3, 30, 56, 83,
|
||||
109, 136, 162, 189, 216, 242, 269, 295, 322, 348,
|
||||
375, 402, 428, 455, 481, 508, 534, 561, 588, 614,
|
||||
641, 667, 694, 720, 747, 774, 800, 827, 853, 880,
|
||||
907, 933, 960, 986, 1013, 1039, 1066
|
||||
};
|
||||
return DiyFp(kCachedPowers_F[index], kCachedPowers_E[index]);
|
||||
}
|
||||
|
||||
inline DiyFp GetCachedPower(int e, int* K) {
|
||||
|
||||
//int k = static_cast<int>(ceil((-61 - e) * 0.30102999566398114)) + 374;
|
||||
double dk = (-61 - e) * 0.30102999566398114 + 347; // dk must be positive, so can do ceiling in positive
|
||||
int k = static_cast<int>(dk);
|
||||
if (dk - k > 0.0)
|
||||
k++;
|
||||
|
||||
unsigned index = static_cast<unsigned>((k >> 3) + 1);
|
||||
*K = -(-348 + static_cast<int>(index << 3)); // decimal exponent no need lookup table
|
||||
|
||||
return GetCachedPowerByIndex(index);
|
||||
}
|
||||
|
||||
inline DiyFp GetCachedPower10(int exp, int *outExp) {
|
||||
unsigned index = (static_cast<unsigned>(exp) + 348u) / 8u;
|
||||
*outExp = -348 + static_cast<int>(index) * 8;
|
||||
return GetCachedPowerByIndex(index);
|
||||
}
|
||||
|
||||
#ifdef __GNUC__
|
||||
RAPIDJSON_DIAG_POP
|
||||
#endif
|
||||
|
||||
#ifdef __clang__
|
||||
RAPIDJSON_DIAG_POP
|
||||
RAPIDJSON_DIAG_OFF(padded)
|
||||
#endif
|
||||
|
||||
} // namespace internal
|
||||
RAPIDJSON_NAMESPACE_END
|
||||
|
||||
#endif // RAPIDJSON_DIYFP_H_
|
||||
245
src/3rdparty/rapidjson/internal/dtoa.h
vendored
Normal file
245
src/3rdparty/rapidjson/internal/dtoa.h
vendored
Normal file
@@ -0,0 +1,245 @@
|
||||
// Tencent is pleased to support the open source community by making RapidJSON available.
|
||||
//
|
||||
// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
|
||||
//
|
||||
// Licensed under the MIT License (the "License"); you may not use this file except
|
||||
// in compliance with the License. You may obtain a copy of the License at
|
||||
//
|
||||
// http://opensource.org/licenses/MIT
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software distributed
|
||||
// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
|
||||
// CONDITIONS OF ANY KIND, either express or implied. See the License for the
|
||||
// specific language governing permissions and limitations under the License.
|
||||
|
||||
// This is a C++ header-only implementation of Grisu2 algorithm from the publication:
|
||||
// Loitsch, Florian. "Printing floating-point numbers quickly and accurately with
|
||||
// integers." ACM Sigplan Notices 45.6 (2010): 233-243.
|
||||
|
||||
#ifndef RAPIDJSON_DTOA_
|
||||
#define RAPIDJSON_DTOA_
|
||||
|
||||
#include "itoa.h" // GetDigitsLut()
|
||||
#include "diyfp.h"
|
||||
#include "ieee754.h"
|
||||
|
||||
RAPIDJSON_NAMESPACE_BEGIN
|
||||
namespace internal {
|
||||
|
||||
#ifdef __GNUC__
|
||||
RAPIDJSON_DIAG_PUSH
|
||||
RAPIDJSON_DIAG_OFF(effc++)
|
||||
RAPIDJSON_DIAG_OFF(array-bounds) // some gcc versions generate wrong warnings https://gcc.gnu.org/bugzilla/show_bug.cgi?id=59124
|
||||
#endif
|
||||
|
||||
inline void GrisuRound(char* buffer, int len, uint64_t delta, uint64_t rest, uint64_t ten_kappa, uint64_t wp_w) {
|
||||
while (rest < wp_w && delta - rest >= ten_kappa &&
|
||||
(rest + ten_kappa < wp_w || /// closer
|
||||
wp_w - rest > rest + ten_kappa - wp_w)) {
|
||||
buffer[len - 1]--;
|
||||
rest += ten_kappa;
|
||||
}
|
||||
}
|
||||
|
||||
inline unsigned CountDecimalDigit32(uint32_t n) {
|
||||
// Simple pure C++ implementation was faster than __builtin_clz version in this situation.
|
||||
if (n < 10) return 1;
|
||||
if (n < 100) return 2;
|
||||
if (n < 1000) return 3;
|
||||
if (n < 10000) return 4;
|
||||
if (n < 100000) return 5;
|
||||
if (n < 1000000) return 6;
|
||||
if (n < 10000000) return 7;
|
||||
if (n < 100000000) return 8;
|
||||
// Will not reach 10 digits in DigitGen()
|
||||
//if (n < 1000000000) return 9;
|
||||
//return 10;
|
||||
return 9;
|
||||
}
|
||||
|
||||
inline void DigitGen(const DiyFp& W, const DiyFp& Mp, uint64_t delta, char* buffer, int* len, int* K) {
|
||||
static const uint32_t kPow10[] = { 1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000 };
|
||||
const DiyFp one(uint64_t(1) << -Mp.e, Mp.e);
|
||||
const DiyFp wp_w = Mp - W;
|
||||
uint32_t p1 = static_cast<uint32_t>(Mp.f >> -one.e);
|
||||
uint64_t p2 = Mp.f & (one.f - 1);
|
||||
unsigned kappa = CountDecimalDigit32(p1); // kappa in [0, 9]
|
||||
*len = 0;
|
||||
|
||||
while (kappa > 0) {
|
||||
uint32_t d = 0;
|
||||
switch (kappa) {
|
||||
case 9: d = p1 / 100000000; p1 %= 100000000; break;
|
||||
case 8: d = p1 / 10000000; p1 %= 10000000; break;
|
||||
case 7: d = p1 / 1000000; p1 %= 1000000; break;
|
||||
case 6: d = p1 / 100000; p1 %= 100000; break;
|
||||
case 5: d = p1 / 10000; p1 %= 10000; break;
|
||||
case 4: d = p1 / 1000; p1 %= 1000; break;
|
||||
case 3: d = p1 / 100; p1 %= 100; break;
|
||||
case 2: d = p1 / 10; p1 %= 10; break;
|
||||
case 1: d = p1; p1 = 0; break;
|
||||
default:;
|
||||
}
|
||||
if (d || *len)
|
||||
buffer[(*len)++] = static_cast<char>('0' + static_cast<char>(d));
|
||||
kappa--;
|
||||
uint64_t tmp = (static_cast<uint64_t>(p1) << -one.e) + p2;
|
||||
if (tmp <= delta) {
|
||||
*K += kappa;
|
||||
GrisuRound(buffer, *len, delta, tmp, static_cast<uint64_t>(kPow10[kappa]) << -one.e, wp_w.f);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// kappa = 0
|
||||
for (;;) {
|
||||
p2 *= 10;
|
||||
delta *= 10;
|
||||
char d = static_cast<char>(p2 >> -one.e);
|
||||
if (d || *len)
|
||||
buffer[(*len)++] = static_cast<char>('0' + d);
|
||||
p2 &= one.f - 1;
|
||||
kappa--;
|
||||
if (p2 < delta) {
|
||||
*K += kappa;
|
||||
int index = -static_cast<int>(kappa);
|
||||
GrisuRound(buffer, *len, delta, p2, one.f, wp_w.f * (index < 9 ? kPow10[-static_cast<int>(kappa)] : 0));
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
inline void Grisu2(double value, char* buffer, int* length, int* K) {
|
||||
const DiyFp v(value);
|
||||
DiyFp w_m, w_p;
|
||||
v.NormalizedBoundaries(&w_m, &w_p);
|
||||
|
||||
const DiyFp c_mk = GetCachedPower(w_p.e, K);
|
||||
const DiyFp W = v.Normalize() * c_mk;
|
||||
DiyFp Wp = w_p * c_mk;
|
||||
DiyFp Wm = w_m * c_mk;
|
||||
Wm.f++;
|
||||
Wp.f--;
|
||||
DigitGen(W, Wp, Wp.f - Wm.f, buffer, length, K);
|
||||
}
|
||||
|
||||
inline char* WriteExponent(int K, char* buffer) {
|
||||
if (K < 0) {
|
||||
*buffer++ = '-';
|
||||
K = -K;
|
||||
}
|
||||
|
||||
if (K >= 100) {
|
||||
*buffer++ = static_cast<char>('0' + static_cast<char>(K / 100));
|
||||
K %= 100;
|
||||
const char* d = GetDigitsLut() + K * 2;
|
||||
*buffer++ = d[0];
|
||||
*buffer++ = d[1];
|
||||
}
|
||||
else if (K >= 10) {
|
||||
const char* d = GetDigitsLut() + K * 2;
|
||||
*buffer++ = d[0];
|
||||
*buffer++ = d[1];
|
||||
}
|
||||
else
|
||||
*buffer++ = static_cast<char>('0' + static_cast<char>(K));
|
||||
|
||||
return buffer;
|
||||
}
|
||||
|
||||
inline char* Prettify(char* buffer, int length, int k, int maxDecimalPlaces) {
|
||||
const int kk = length + k; // 10^(kk-1) <= v < 10^kk
|
||||
|
||||
if (0 <= k && kk <= 21) {
|
||||
// 1234e7 -> 12340000000
|
||||
for (int i = length; i < kk; i++)
|
||||
buffer[i] = '0';
|
||||
buffer[kk] = '.';
|
||||
buffer[kk + 1] = '0';
|
||||
return &buffer[kk + 2];
|
||||
}
|
||||
else if (0 < kk && kk <= 21) {
|
||||
// 1234e-2 -> 12.34
|
||||
std::memmove(&buffer[kk + 1], &buffer[kk], static_cast<size_t>(length - kk));
|
||||
buffer[kk] = '.';
|
||||
if (0 > k + maxDecimalPlaces) {
|
||||
// When maxDecimalPlaces = 2, 1.2345 -> 1.23, 1.102 -> 1.1
|
||||
// Remove extra trailing zeros (at least one) after truncation.
|
||||
for (int i = kk + maxDecimalPlaces; i > kk + 1; i--)
|
||||
if (buffer[i] != '0')
|
||||
return &buffer[i + 1];
|
||||
return &buffer[kk + 2]; // Reserve one zero
|
||||
}
|
||||
else
|
||||
return &buffer[length + 1];
|
||||
}
|
||||
else if (-6 < kk && kk <= 0) {
|
||||
// 1234e-6 -> 0.001234
|
||||
const int offset = 2 - kk;
|
||||
std::memmove(&buffer[offset], &buffer[0], static_cast<size_t>(length));
|
||||
buffer[0] = '0';
|
||||
buffer[1] = '.';
|
||||
for (int i = 2; i < offset; i++)
|
||||
buffer[i] = '0';
|
||||
if (length - kk > maxDecimalPlaces) {
|
||||
// When maxDecimalPlaces = 2, 0.123 -> 0.12, 0.102 -> 0.1
|
||||
// Remove extra trailing zeros (at least one) after truncation.
|
||||
for (int i = maxDecimalPlaces + 1; i > 2; i--)
|
||||
if (buffer[i] != '0')
|
||||
return &buffer[i + 1];
|
||||
return &buffer[3]; // Reserve one zero
|
||||
}
|
||||
else
|
||||
return &buffer[length + offset];
|
||||
}
|
||||
else if (kk < -maxDecimalPlaces) {
|
||||
// Truncate to zero
|
||||
buffer[0] = '0';
|
||||
buffer[1] = '.';
|
||||
buffer[2] = '0';
|
||||
return &buffer[3];
|
||||
}
|
||||
else if (length == 1) {
|
||||
// 1e30
|
||||
buffer[1] = 'e';
|
||||
return WriteExponent(kk - 1, &buffer[2]);
|
||||
}
|
||||
else {
|
||||
// 1234e30 -> 1.234e33
|
||||
std::memmove(&buffer[2], &buffer[1], static_cast<size_t>(length - 1));
|
||||
buffer[1] = '.';
|
||||
buffer[length + 1] = 'e';
|
||||
return WriteExponent(kk - 1, &buffer[0 + length + 2]);
|
||||
}
|
||||
}
|
||||
|
||||
inline char* dtoa(double value, char* buffer, int maxDecimalPlaces = 324) {
|
||||
RAPIDJSON_ASSERT(maxDecimalPlaces >= 1);
|
||||
Double d(value);
|
||||
if (d.IsZero()) {
|
||||
if (d.Sign())
|
||||
*buffer++ = '-'; // -0.0, Issue #289
|
||||
buffer[0] = '0';
|
||||
buffer[1] = '.';
|
||||
buffer[2] = '0';
|
||||
return &buffer[3];
|
||||
}
|
||||
else {
|
||||
if (value < 0) {
|
||||
*buffer++ = '-';
|
||||
value = -value;
|
||||
}
|
||||
int length, K;
|
||||
Grisu2(value, buffer, &length, &K);
|
||||
return Prettify(buffer, length, K, maxDecimalPlaces);
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef __GNUC__
|
||||
RAPIDJSON_DIAG_POP
|
||||
#endif
|
||||
|
||||
} // namespace internal
|
||||
RAPIDJSON_NAMESPACE_END
|
||||
|
||||
#endif // RAPIDJSON_DTOA_
|
||||
78
src/3rdparty/rapidjson/internal/ieee754.h
vendored
Normal file
78
src/3rdparty/rapidjson/internal/ieee754.h
vendored
Normal file
@@ -0,0 +1,78 @@
|
||||
// Tencent is pleased to support the open source community by making RapidJSON available.
|
||||
//
|
||||
// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
|
||||
//
|
||||
// Licensed under the MIT License (the "License"); you may not use this file except
|
||||
// in compliance with the License. You may obtain a copy of the License at
|
||||
//
|
||||
// http://opensource.org/licenses/MIT
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software distributed
|
||||
// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
|
||||
// CONDITIONS OF ANY KIND, either express or implied. See the License for the
|
||||
// specific language governing permissions and limitations under the License.
|
||||
|
||||
#ifndef RAPIDJSON_IEEE754_
|
||||
#define RAPIDJSON_IEEE754_
|
||||
|
||||
#include "../rapidjson.h"
|
||||
|
||||
RAPIDJSON_NAMESPACE_BEGIN
|
||||
namespace internal {
|
||||
|
||||
class Double {
|
||||
public:
|
||||
Double() {}
|
||||
Double(double d) : d_(d) {}
|
||||
Double(uint64_t u) : u_(u) {}
|
||||
|
||||
double Value() const { return d_; }
|
||||
uint64_t Uint64Value() const { return u_; }
|
||||
|
||||
double NextPositiveDouble() const {
|
||||
RAPIDJSON_ASSERT(!Sign());
|
||||
return Double(u_ + 1).Value();
|
||||
}
|
||||
|
||||
bool Sign() const { return (u_ & kSignMask) != 0; }
|
||||
uint64_t Significand() const { return u_ & kSignificandMask; }
|
||||
int Exponent() const { return static_cast<int>(((u_ & kExponentMask) >> kSignificandSize) - kExponentBias); }
|
||||
|
||||
bool IsNan() const { return (u_ & kExponentMask) == kExponentMask && Significand() != 0; }
|
||||
bool IsInf() const { return (u_ & kExponentMask) == kExponentMask && Significand() == 0; }
|
||||
bool IsNanOrInf() const { return (u_ & kExponentMask) == kExponentMask; }
|
||||
bool IsNormal() const { return (u_ & kExponentMask) != 0 || Significand() == 0; }
|
||||
bool IsZero() const { return (u_ & (kExponentMask | kSignificandMask)) == 0; }
|
||||
|
||||
uint64_t IntegerSignificand() const { return IsNormal() ? Significand() | kHiddenBit : Significand(); }
|
||||
int IntegerExponent() const { return (IsNormal() ? Exponent() : kDenormalExponent) - kSignificandSize; }
|
||||
uint64_t ToBias() const { return (u_ & kSignMask) ? ~u_ + 1 : u_ | kSignMask; }
|
||||
|
||||
static unsigned EffectiveSignificandSize(int order) {
|
||||
if (order >= -1021)
|
||||
return 53;
|
||||
else if (order <= -1074)
|
||||
return 0;
|
||||
else
|
||||
return static_cast<unsigned>(order) + 1074;
|
||||
}
|
||||
|
||||
private:
|
||||
static const int kSignificandSize = 52;
|
||||
static const int kExponentBias = 0x3FF;
|
||||
static const int kDenormalExponent = 1 - kExponentBias;
|
||||
static const uint64_t kSignMask = RAPIDJSON_UINT64_C2(0x80000000, 0x00000000);
|
||||
static const uint64_t kExponentMask = RAPIDJSON_UINT64_C2(0x7FF00000, 0x00000000);
|
||||
static const uint64_t kSignificandMask = RAPIDJSON_UINT64_C2(0x000FFFFF, 0xFFFFFFFF);
|
||||
static const uint64_t kHiddenBit = RAPIDJSON_UINT64_C2(0x00100000, 0x00000000);
|
||||
|
||||
union {
|
||||
double d_;
|
||||
uint64_t u_;
|
||||
};
|
||||
};
|
||||
|
||||
} // namespace internal
|
||||
RAPIDJSON_NAMESPACE_END
|
||||
|
||||
#endif // RAPIDJSON_IEEE754_
|
||||
304
src/3rdparty/rapidjson/internal/itoa.h
vendored
Normal file
304
src/3rdparty/rapidjson/internal/itoa.h
vendored
Normal file
@@ -0,0 +1,304 @@
|
||||
// Tencent is pleased to support the open source community by making RapidJSON available.
|
||||
//
|
||||
// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
|
||||
//
|
||||
// Licensed under the MIT License (the "License"); you may not use this file except
|
||||
// in compliance with the License. You may obtain a copy of the License at
|
||||
//
|
||||
// http://opensource.org/licenses/MIT
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software distributed
|
||||
// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
|
||||
// CONDITIONS OF ANY KIND, either express or implied. See the License for the
|
||||
// specific language governing permissions and limitations under the License.
|
||||
|
||||
#ifndef RAPIDJSON_ITOA_
|
||||
#define RAPIDJSON_ITOA_
|
||||
|
||||
#include "../rapidjson.h"
|
||||
|
||||
RAPIDJSON_NAMESPACE_BEGIN
|
||||
namespace internal {
|
||||
|
||||
inline const char* GetDigitsLut() {
|
||||
static const char cDigitsLut[200] = {
|
||||
'0','0','0','1','0','2','0','3','0','4','0','5','0','6','0','7','0','8','0','9',
|
||||
'1','0','1','1','1','2','1','3','1','4','1','5','1','6','1','7','1','8','1','9',
|
||||
'2','0','2','1','2','2','2','3','2','4','2','5','2','6','2','7','2','8','2','9',
|
||||
'3','0','3','1','3','2','3','3','3','4','3','5','3','6','3','7','3','8','3','9',
|
||||
'4','0','4','1','4','2','4','3','4','4','4','5','4','6','4','7','4','8','4','9',
|
||||
'5','0','5','1','5','2','5','3','5','4','5','5','5','6','5','7','5','8','5','9',
|
||||
'6','0','6','1','6','2','6','3','6','4','6','5','6','6','6','7','6','8','6','9',
|
||||
'7','0','7','1','7','2','7','3','7','4','7','5','7','6','7','7','7','8','7','9',
|
||||
'8','0','8','1','8','2','8','3','8','4','8','5','8','6','8','7','8','8','8','9',
|
||||
'9','0','9','1','9','2','9','3','9','4','9','5','9','6','9','7','9','8','9','9'
|
||||
};
|
||||
return cDigitsLut;
|
||||
}
|
||||
|
||||
inline char* u32toa(uint32_t value, char* buffer) {
|
||||
const char* cDigitsLut = GetDigitsLut();
|
||||
|
||||
if (value < 10000) {
|
||||
const uint32_t d1 = (value / 100) << 1;
|
||||
const uint32_t d2 = (value % 100) << 1;
|
||||
|
||||
if (value >= 1000)
|
||||
*buffer++ = cDigitsLut[d1];
|
||||
if (value >= 100)
|
||||
*buffer++ = cDigitsLut[d1 + 1];
|
||||
if (value >= 10)
|
||||
*buffer++ = cDigitsLut[d2];
|
||||
*buffer++ = cDigitsLut[d2 + 1];
|
||||
}
|
||||
else if (value < 100000000) {
|
||||
// value = bbbbcccc
|
||||
const uint32_t b = value / 10000;
|
||||
const uint32_t c = value % 10000;
|
||||
|
||||
const uint32_t d1 = (b / 100) << 1;
|
||||
const uint32_t d2 = (b % 100) << 1;
|
||||
|
||||
const uint32_t d3 = (c / 100) << 1;
|
||||
const uint32_t d4 = (c % 100) << 1;
|
||||
|
||||
if (value >= 10000000)
|
||||
*buffer++ = cDigitsLut[d1];
|
||||
if (value >= 1000000)
|
||||
*buffer++ = cDigitsLut[d1 + 1];
|
||||
if (value >= 100000)
|
||||
*buffer++ = cDigitsLut[d2];
|
||||
*buffer++ = cDigitsLut[d2 + 1];
|
||||
|
||||
*buffer++ = cDigitsLut[d3];
|
||||
*buffer++ = cDigitsLut[d3 + 1];
|
||||
*buffer++ = cDigitsLut[d4];
|
||||
*buffer++ = cDigitsLut[d4 + 1];
|
||||
}
|
||||
else {
|
||||
// value = aabbbbcccc in decimal
|
||||
|
||||
const uint32_t a = value / 100000000; // 1 to 42
|
||||
value %= 100000000;
|
||||
|
||||
if (a >= 10) {
|
||||
const unsigned i = a << 1;
|
||||
*buffer++ = cDigitsLut[i];
|
||||
*buffer++ = cDigitsLut[i + 1];
|
||||
}
|
||||
else
|
||||
*buffer++ = static_cast<char>('0' + static_cast<char>(a));
|
||||
|
||||
const uint32_t b = value / 10000; // 0 to 9999
|
||||
const uint32_t c = value % 10000; // 0 to 9999
|
||||
|
||||
const uint32_t d1 = (b / 100) << 1;
|
||||
const uint32_t d2 = (b % 100) << 1;
|
||||
|
||||
const uint32_t d3 = (c / 100) << 1;
|
||||
const uint32_t d4 = (c % 100) << 1;
|
||||
|
||||
*buffer++ = cDigitsLut[d1];
|
||||
*buffer++ = cDigitsLut[d1 + 1];
|
||||
*buffer++ = cDigitsLut[d2];
|
||||
*buffer++ = cDigitsLut[d2 + 1];
|
||||
*buffer++ = cDigitsLut[d3];
|
||||
*buffer++ = cDigitsLut[d3 + 1];
|
||||
*buffer++ = cDigitsLut[d4];
|
||||
*buffer++ = cDigitsLut[d4 + 1];
|
||||
}
|
||||
return buffer;
|
||||
}
|
||||
|
||||
inline char* i32toa(int32_t value, char* buffer) {
|
||||
uint32_t u = static_cast<uint32_t>(value);
|
||||
if (value < 0) {
|
||||
*buffer++ = '-';
|
||||
u = ~u + 1;
|
||||
}
|
||||
|
||||
return u32toa(u, buffer);
|
||||
}
|
||||
|
||||
inline char* u64toa(uint64_t value, char* buffer) {
|
||||
const char* cDigitsLut = GetDigitsLut();
|
||||
const uint64_t kTen8 = 100000000;
|
||||
const uint64_t kTen9 = kTen8 * 10;
|
||||
const uint64_t kTen10 = kTen8 * 100;
|
||||
const uint64_t kTen11 = kTen8 * 1000;
|
||||
const uint64_t kTen12 = kTen8 * 10000;
|
||||
const uint64_t kTen13 = kTen8 * 100000;
|
||||
const uint64_t kTen14 = kTen8 * 1000000;
|
||||
const uint64_t kTen15 = kTen8 * 10000000;
|
||||
const uint64_t kTen16 = kTen8 * kTen8;
|
||||
|
||||
if (value < kTen8) {
|
||||
uint32_t v = static_cast<uint32_t>(value);
|
||||
if (v < 10000) {
|
||||
const uint32_t d1 = (v / 100) << 1;
|
||||
const uint32_t d2 = (v % 100) << 1;
|
||||
|
||||
if (v >= 1000)
|
||||
*buffer++ = cDigitsLut[d1];
|
||||
if (v >= 100)
|
||||
*buffer++ = cDigitsLut[d1 + 1];
|
||||
if (v >= 10)
|
||||
*buffer++ = cDigitsLut[d2];
|
||||
*buffer++ = cDigitsLut[d2 + 1];
|
||||
}
|
||||
else {
|
||||
// value = bbbbcccc
|
||||
const uint32_t b = v / 10000;
|
||||
const uint32_t c = v % 10000;
|
||||
|
||||
const uint32_t d1 = (b / 100) << 1;
|
||||
const uint32_t d2 = (b % 100) << 1;
|
||||
|
||||
const uint32_t d3 = (c / 100) << 1;
|
||||
const uint32_t d4 = (c % 100) << 1;
|
||||
|
||||
if (value >= 10000000)
|
||||
*buffer++ = cDigitsLut[d1];
|
||||
if (value >= 1000000)
|
||||
*buffer++ = cDigitsLut[d1 + 1];
|
||||
if (value >= 100000)
|
||||
*buffer++ = cDigitsLut[d2];
|
||||
*buffer++ = cDigitsLut[d2 + 1];
|
||||
|
||||
*buffer++ = cDigitsLut[d3];
|
||||
*buffer++ = cDigitsLut[d3 + 1];
|
||||
*buffer++ = cDigitsLut[d4];
|
||||
*buffer++ = cDigitsLut[d4 + 1];
|
||||
}
|
||||
}
|
||||
else if (value < kTen16) {
|
||||
const uint32_t v0 = static_cast<uint32_t>(value / kTen8);
|
||||
const uint32_t v1 = static_cast<uint32_t>(value % kTen8);
|
||||
|
||||
const uint32_t b0 = v0 / 10000;
|
||||
const uint32_t c0 = v0 % 10000;
|
||||
|
||||
const uint32_t d1 = (b0 / 100) << 1;
|
||||
const uint32_t d2 = (b0 % 100) << 1;
|
||||
|
||||
const uint32_t d3 = (c0 / 100) << 1;
|
||||
const uint32_t d4 = (c0 % 100) << 1;
|
||||
|
||||
const uint32_t b1 = v1 / 10000;
|
||||
const uint32_t c1 = v1 % 10000;
|
||||
|
||||
const uint32_t d5 = (b1 / 100) << 1;
|
||||
const uint32_t d6 = (b1 % 100) << 1;
|
||||
|
||||
const uint32_t d7 = (c1 / 100) << 1;
|
||||
const uint32_t d8 = (c1 % 100) << 1;
|
||||
|
||||
if (value >= kTen15)
|
||||
*buffer++ = cDigitsLut[d1];
|
||||
if (value >= kTen14)
|
||||
*buffer++ = cDigitsLut[d1 + 1];
|
||||
if (value >= kTen13)
|
||||
*buffer++ = cDigitsLut[d2];
|
||||
if (value >= kTen12)
|
||||
*buffer++ = cDigitsLut[d2 + 1];
|
||||
if (value >= kTen11)
|
||||
*buffer++ = cDigitsLut[d3];
|
||||
if (value >= kTen10)
|
||||
*buffer++ = cDigitsLut[d3 + 1];
|
||||
if (value >= kTen9)
|
||||
*buffer++ = cDigitsLut[d4];
|
||||
if (value >= kTen8)
|
||||
*buffer++ = cDigitsLut[d4 + 1];
|
||||
|
||||
*buffer++ = cDigitsLut[d5];
|
||||
*buffer++ = cDigitsLut[d5 + 1];
|
||||
*buffer++ = cDigitsLut[d6];
|
||||
*buffer++ = cDigitsLut[d6 + 1];
|
||||
*buffer++ = cDigitsLut[d7];
|
||||
*buffer++ = cDigitsLut[d7 + 1];
|
||||
*buffer++ = cDigitsLut[d8];
|
||||
*buffer++ = cDigitsLut[d8 + 1];
|
||||
}
|
||||
else {
|
||||
const uint32_t a = static_cast<uint32_t>(value / kTen16); // 1 to 1844
|
||||
value %= kTen16;
|
||||
|
||||
if (a < 10)
|
||||
*buffer++ = static_cast<char>('0' + static_cast<char>(a));
|
||||
else if (a < 100) {
|
||||
const uint32_t i = a << 1;
|
||||
*buffer++ = cDigitsLut[i];
|
||||
*buffer++ = cDigitsLut[i + 1];
|
||||
}
|
||||
else if (a < 1000) {
|
||||
*buffer++ = static_cast<char>('0' + static_cast<char>(a / 100));
|
||||
|
||||
const uint32_t i = (a % 100) << 1;
|
||||
*buffer++ = cDigitsLut[i];
|
||||
*buffer++ = cDigitsLut[i + 1];
|
||||
}
|
||||
else {
|
||||
const uint32_t i = (a / 100) << 1;
|
||||
const uint32_t j = (a % 100) << 1;
|
||||
*buffer++ = cDigitsLut[i];
|
||||
*buffer++ = cDigitsLut[i + 1];
|
||||
*buffer++ = cDigitsLut[j];
|
||||
*buffer++ = cDigitsLut[j + 1];
|
||||
}
|
||||
|
||||
const uint32_t v0 = static_cast<uint32_t>(value / kTen8);
|
||||
const uint32_t v1 = static_cast<uint32_t>(value % kTen8);
|
||||
|
||||
const uint32_t b0 = v0 / 10000;
|
||||
const uint32_t c0 = v0 % 10000;
|
||||
|
||||
const uint32_t d1 = (b0 / 100) << 1;
|
||||
const uint32_t d2 = (b0 % 100) << 1;
|
||||
|
||||
const uint32_t d3 = (c0 / 100) << 1;
|
||||
const uint32_t d4 = (c0 % 100) << 1;
|
||||
|
||||
const uint32_t b1 = v1 / 10000;
|
||||
const uint32_t c1 = v1 % 10000;
|
||||
|
||||
const uint32_t d5 = (b1 / 100) << 1;
|
||||
const uint32_t d6 = (b1 % 100) << 1;
|
||||
|
||||
const uint32_t d7 = (c1 / 100) << 1;
|
||||
const uint32_t d8 = (c1 % 100) << 1;
|
||||
|
||||
*buffer++ = cDigitsLut[d1];
|
||||
*buffer++ = cDigitsLut[d1 + 1];
|
||||
*buffer++ = cDigitsLut[d2];
|
||||
*buffer++ = cDigitsLut[d2 + 1];
|
||||
*buffer++ = cDigitsLut[d3];
|
||||
*buffer++ = cDigitsLut[d3 + 1];
|
||||
*buffer++ = cDigitsLut[d4];
|
||||
*buffer++ = cDigitsLut[d4 + 1];
|
||||
*buffer++ = cDigitsLut[d5];
|
||||
*buffer++ = cDigitsLut[d5 + 1];
|
||||
*buffer++ = cDigitsLut[d6];
|
||||
*buffer++ = cDigitsLut[d6 + 1];
|
||||
*buffer++ = cDigitsLut[d7];
|
||||
*buffer++ = cDigitsLut[d7 + 1];
|
||||
*buffer++ = cDigitsLut[d8];
|
||||
*buffer++ = cDigitsLut[d8 + 1];
|
||||
}
|
||||
|
||||
return buffer;
|
||||
}
|
||||
|
||||
inline char* i64toa(int64_t value, char* buffer) {
|
||||
uint64_t u = static_cast<uint64_t>(value);
|
||||
if (value < 0) {
|
||||
*buffer++ = '-';
|
||||
u = ~u + 1;
|
||||
}
|
||||
|
||||
return u64toa(u, buffer);
|
||||
}
|
||||
|
||||
} // namespace internal
|
||||
RAPIDJSON_NAMESPACE_END
|
||||
|
||||
#endif // RAPIDJSON_ITOA_
|
||||
181
src/3rdparty/rapidjson/internal/meta.h
vendored
Normal file
181
src/3rdparty/rapidjson/internal/meta.h
vendored
Normal file
@@ -0,0 +1,181 @@
|
||||
// Tencent is pleased to support the open source community by making RapidJSON available.
|
||||
//
|
||||
// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
|
||||
//
|
||||
// Licensed under the MIT License (the "License"); you may not use this file except
|
||||
// in compliance with the License. You may obtain a copy of the License at
|
||||
//
|
||||
// http://opensource.org/licenses/MIT
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software distributed
|
||||
// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
|
||||
// CONDITIONS OF ANY KIND, either express or implied. See the License for the
|
||||
// specific language governing permissions and limitations under the License.
|
||||
|
||||
#ifndef RAPIDJSON_INTERNAL_META_H_
|
||||
#define RAPIDJSON_INTERNAL_META_H_
|
||||
|
||||
#include "../rapidjson.h"
|
||||
|
||||
#ifdef __GNUC__
|
||||
RAPIDJSON_DIAG_PUSH
|
||||
RAPIDJSON_DIAG_OFF(effc++)
|
||||
#endif
|
||||
#if defined(_MSC_VER)
|
||||
RAPIDJSON_DIAG_PUSH
|
||||
RAPIDJSON_DIAG_OFF(6334)
|
||||
#endif
|
||||
|
||||
#if RAPIDJSON_HAS_CXX11_TYPETRAITS
|
||||
#include <type_traits>
|
||||
#endif
|
||||
|
||||
//@cond RAPIDJSON_INTERNAL
|
||||
RAPIDJSON_NAMESPACE_BEGIN
|
||||
namespace internal {
|
||||
|
||||
// Helper to wrap/convert arbitrary types to void, useful for arbitrary type matching
|
||||
template <typename T> struct Void { typedef void Type; };
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// BoolType, TrueType, FalseType
|
||||
//
|
||||
template <bool Cond> struct BoolType {
|
||||
static const bool Value = Cond;
|
||||
typedef BoolType Type;
|
||||
};
|
||||
typedef BoolType<true> TrueType;
|
||||
typedef BoolType<false> FalseType;
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// SelectIf, BoolExpr, NotExpr, AndExpr, OrExpr
|
||||
//
|
||||
|
||||
template <bool C> struct SelectIfImpl { template <typename T1, typename T2> struct Apply { typedef T1 Type; }; };
|
||||
template <> struct SelectIfImpl<false> { template <typename T1, typename T2> struct Apply { typedef T2 Type; }; };
|
||||
template <bool C, typename T1, typename T2> struct SelectIfCond : SelectIfImpl<C>::template Apply<T1,T2> {};
|
||||
template <typename C, typename T1, typename T2> struct SelectIf : SelectIfCond<C::Value, T1, T2> {};
|
||||
|
||||
template <bool Cond1, bool Cond2> struct AndExprCond : FalseType {};
|
||||
template <> struct AndExprCond<true, true> : TrueType {};
|
||||
template <bool Cond1, bool Cond2> struct OrExprCond : TrueType {};
|
||||
template <> struct OrExprCond<false, false> : FalseType {};
|
||||
|
||||
template <typename C> struct BoolExpr : SelectIf<C,TrueType,FalseType>::Type {};
|
||||
template <typename C> struct NotExpr : SelectIf<C,FalseType,TrueType>::Type {};
|
||||
template <typename C1, typename C2> struct AndExpr : AndExprCond<C1::Value, C2::Value>::Type {};
|
||||
template <typename C1, typename C2> struct OrExpr : OrExprCond<C1::Value, C2::Value>::Type {};
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// AddConst, MaybeAddConst, RemoveConst
|
||||
template <typename T> struct AddConst { typedef const T Type; };
|
||||
template <bool Constify, typename T> struct MaybeAddConst : SelectIfCond<Constify, const T, T> {};
|
||||
template <typename T> struct RemoveConst { typedef T Type; };
|
||||
template <typename T> struct RemoveConst<const T> { typedef T Type; };
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// IsSame, IsConst, IsMoreConst, IsPointer
|
||||
//
|
||||
template <typename T, typename U> struct IsSame : FalseType {};
|
||||
template <typename T> struct IsSame<T, T> : TrueType {};
|
||||
|
||||
template <typename T> struct IsConst : FalseType {};
|
||||
template <typename T> struct IsConst<const T> : TrueType {};
|
||||
|
||||
template <typename CT, typename T>
|
||||
struct IsMoreConst
|
||||
: AndExpr<IsSame<typename RemoveConst<CT>::Type, typename RemoveConst<T>::Type>,
|
||||
BoolType<IsConst<CT>::Value >= IsConst<T>::Value> >::Type {};
|
||||
|
||||
template <typename T> struct IsPointer : FalseType {};
|
||||
template <typename T> struct IsPointer<T*> : TrueType {};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// IsBaseOf
|
||||
//
|
||||
#if RAPIDJSON_HAS_CXX11_TYPETRAITS
|
||||
|
||||
template <typename B, typename D> struct IsBaseOf
|
||||
: BoolType< ::std::is_base_of<B,D>::value> {};
|
||||
|
||||
#else // simplified version adopted from Boost
|
||||
|
||||
template<typename B, typename D> struct IsBaseOfImpl {
|
||||
RAPIDJSON_STATIC_ASSERT(sizeof(B) != 0);
|
||||
RAPIDJSON_STATIC_ASSERT(sizeof(D) != 0);
|
||||
|
||||
typedef char (&Yes)[1];
|
||||
typedef char (&No) [2];
|
||||
|
||||
template <typename T>
|
||||
static Yes Check(const D*, T);
|
||||
static No Check(const B*, int);
|
||||
|
||||
struct Host {
|
||||
operator const B*() const;
|
||||
operator const D*();
|
||||
};
|
||||
|
||||
enum { Value = (sizeof(Check(Host(), 0)) == sizeof(Yes)) };
|
||||
};
|
||||
|
||||
template <typename B, typename D> struct IsBaseOf
|
||||
: OrExpr<IsSame<B, D>, BoolExpr<IsBaseOfImpl<B, D> > >::Type {};
|
||||
|
||||
#endif // RAPIDJSON_HAS_CXX11_TYPETRAITS
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// EnableIf / DisableIf
|
||||
//
|
||||
template <bool Condition, typename T = void> struct EnableIfCond { typedef T Type; };
|
||||
template <typename T> struct EnableIfCond<false, T> { /* empty */ };
|
||||
|
||||
template <bool Condition, typename T = void> struct DisableIfCond { typedef T Type; };
|
||||
template <typename T> struct DisableIfCond<true, T> { /* empty */ };
|
||||
|
||||
template <typename Condition, typename T = void>
|
||||
struct EnableIf : EnableIfCond<Condition::Value, T> {};
|
||||
|
||||
template <typename Condition, typename T = void>
|
||||
struct DisableIf : DisableIfCond<Condition::Value, T> {};
|
||||
|
||||
// SFINAE helpers
|
||||
struct SfinaeTag {};
|
||||
template <typename T> struct RemoveSfinaeTag;
|
||||
template <typename T> struct RemoveSfinaeTag<SfinaeTag&(*)(T)> { typedef T Type; };
|
||||
|
||||
#define RAPIDJSON_REMOVEFPTR_(type) \
|
||||
typename ::RAPIDJSON_NAMESPACE::internal::RemoveSfinaeTag \
|
||||
< ::RAPIDJSON_NAMESPACE::internal::SfinaeTag&(*) type>::Type
|
||||
|
||||
#define RAPIDJSON_ENABLEIF(cond) \
|
||||
typename ::RAPIDJSON_NAMESPACE::internal::EnableIf \
|
||||
<RAPIDJSON_REMOVEFPTR_(cond)>::Type * = NULL
|
||||
|
||||
#define RAPIDJSON_DISABLEIF(cond) \
|
||||
typename ::RAPIDJSON_NAMESPACE::internal::DisableIf \
|
||||
<RAPIDJSON_REMOVEFPTR_(cond)>::Type * = NULL
|
||||
|
||||
#define RAPIDJSON_ENABLEIF_RETURN(cond,returntype) \
|
||||
typename ::RAPIDJSON_NAMESPACE::internal::EnableIf \
|
||||
<RAPIDJSON_REMOVEFPTR_(cond), \
|
||||
RAPIDJSON_REMOVEFPTR_(returntype)>::Type
|
||||
|
||||
#define RAPIDJSON_DISABLEIF_RETURN(cond,returntype) \
|
||||
typename ::RAPIDJSON_NAMESPACE::internal::DisableIf \
|
||||
<RAPIDJSON_REMOVEFPTR_(cond), \
|
||||
RAPIDJSON_REMOVEFPTR_(returntype)>::Type
|
||||
|
||||
} // namespace internal
|
||||
RAPIDJSON_NAMESPACE_END
|
||||
//@endcond
|
||||
|
||||
#if defined(__GNUC__) || defined(_MSC_VER)
|
||||
RAPIDJSON_DIAG_POP
|
||||
#endif
|
||||
|
||||
#endif // RAPIDJSON_INTERNAL_META_H_
|
||||
55
src/3rdparty/rapidjson/internal/pow10.h
vendored
Normal file
55
src/3rdparty/rapidjson/internal/pow10.h
vendored
Normal file
@@ -0,0 +1,55 @@
|
||||
// Tencent is pleased to support the open source community by making RapidJSON available.
|
||||
//
|
||||
// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
|
||||
//
|
||||
// Licensed under the MIT License (the "License"); you may not use this file except
|
||||
// in compliance with the License. You may obtain a copy of the License at
|
||||
//
|
||||
// http://opensource.org/licenses/MIT
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software distributed
|
||||
// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
|
||||
// CONDITIONS OF ANY KIND, either express or implied. See the License for the
|
||||
// specific language governing permissions and limitations under the License.
|
||||
|
||||
#ifndef RAPIDJSON_POW10_
|
||||
#define RAPIDJSON_POW10_
|
||||
|
||||
#include "../rapidjson.h"
|
||||
|
||||
RAPIDJSON_NAMESPACE_BEGIN
|
||||
namespace internal {
|
||||
|
||||
//! Computes integer powers of 10 in double (10.0^n).
|
||||
/*! This function uses lookup table for fast and accurate results.
|
||||
\param n non-negative exponent. Must <= 308.
|
||||
\return 10.0^n
|
||||
*/
|
||||
inline double Pow10(int n) {
|
||||
static const double e[] = { // 1e-0...1e308: 309 * 8 bytes = 2472 bytes
|
||||
1e+0,
|
||||
1e+1, 1e+2, 1e+3, 1e+4, 1e+5, 1e+6, 1e+7, 1e+8, 1e+9, 1e+10, 1e+11, 1e+12, 1e+13, 1e+14, 1e+15, 1e+16, 1e+17, 1e+18, 1e+19, 1e+20,
|
||||
1e+21, 1e+22, 1e+23, 1e+24, 1e+25, 1e+26, 1e+27, 1e+28, 1e+29, 1e+30, 1e+31, 1e+32, 1e+33, 1e+34, 1e+35, 1e+36, 1e+37, 1e+38, 1e+39, 1e+40,
|
||||
1e+41, 1e+42, 1e+43, 1e+44, 1e+45, 1e+46, 1e+47, 1e+48, 1e+49, 1e+50, 1e+51, 1e+52, 1e+53, 1e+54, 1e+55, 1e+56, 1e+57, 1e+58, 1e+59, 1e+60,
|
||||
1e+61, 1e+62, 1e+63, 1e+64, 1e+65, 1e+66, 1e+67, 1e+68, 1e+69, 1e+70, 1e+71, 1e+72, 1e+73, 1e+74, 1e+75, 1e+76, 1e+77, 1e+78, 1e+79, 1e+80,
|
||||
1e+81, 1e+82, 1e+83, 1e+84, 1e+85, 1e+86, 1e+87, 1e+88, 1e+89, 1e+90, 1e+91, 1e+92, 1e+93, 1e+94, 1e+95, 1e+96, 1e+97, 1e+98, 1e+99, 1e+100,
|
||||
1e+101,1e+102,1e+103,1e+104,1e+105,1e+106,1e+107,1e+108,1e+109,1e+110,1e+111,1e+112,1e+113,1e+114,1e+115,1e+116,1e+117,1e+118,1e+119,1e+120,
|
||||
1e+121,1e+122,1e+123,1e+124,1e+125,1e+126,1e+127,1e+128,1e+129,1e+130,1e+131,1e+132,1e+133,1e+134,1e+135,1e+136,1e+137,1e+138,1e+139,1e+140,
|
||||
1e+141,1e+142,1e+143,1e+144,1e+145,1e+146,1e+147,1e+148,1e+149,1e+150,1e+151,1e+152,1e+153,1e+154,1e+155,1e+156,1e+157,1e+158,1e+159,1e+160,
|
||||
1e+161,1e+162,1e+163,1e+164,1e+165,1e+166,1e+167,1e+168,1e+169,1e+170,1e+171,1e+172,1e+173,1e+174,1e+175,1e+176,1e+177,1e+178,1e+179,1e+180,
|
||||
1e+181,1e+182,1e+183,1e+184,1e+185,1e+186,1e+187,1e+188,1e+189,1e+190,1e+191,1e+192,1e+193,1e+194,1e+195,1e+196,1e+197,1e+198,1e+199,1e+200,
|
||||
1e+201,1e+202,1e+203,1e+204,1e+205,1e+206,1e+207,1e+208,1e+209,1e+210,1e+211,1e+212,1e+213,1e+214,1e+215,1e+216,1e+217,1e+218,1e+219,1e+220,
|
||||
1e+221,1e+222,1e+223,1e+224,1e+225,1e+226,1e+227,1e+228,1e+229,1e+230,1e+231,1e+232,1e+233,1e+234,1e+235,1e+236,1e+237,1e+238,1e+239,1e+240,
|
||||
1e+241,1e+242,1e+243,1e+244,1e+245,1e+246,1e+247,1e+248,1e+249,1e+250,1e+251,1e+252,1e+253,1e+254,1e+255,1e+256,1e+257,1e+258,1e+259,1e+260,
|
||||
1e+261,1e+262,1e+263,1e+264,1e+265,1e+266,1e+267,1e+268,1e+269,1e+270,1e+271,1e+272,1e+273,1e+274,1e+275,1e+276,1e+277,1e+278,1e+279,1e+280,
|
||||
1e+281,1e+282,1e+283,1e+284,1e+285,1e+286,1e+287,1e+288,1e+289,1e+290,1e+291,1e+292,1e+293,1e+294,1e+295,1e+296,1e+297,1e+298,1e+299,1e+300,
|
||||
1e+301,1e+302,1e+303,1e+304,1e+305,1e+306,1e+307,1e+308
|
||||
};
|
||||
RAPIDJSON_ASSERT(n >= 0 && n <= 308);
|
||||
return e[n];
|
||||
}
|
||||
|
||||
} // namespace internal
|
||||
RAPIDJSON_NAMESPACE_END
|
||||
|
||||
#endif // RAPIDJSON_POW10_
|
||||
701
src/3rdparty/rapidjson/internal/regex.h
vendored
Normal file
701
src/3rdparty/rapidjson/internal/regex.h
vendored
Normal file
@@ -0,0 +1,701 @@
|
||||
// Tencent is pleased to support the open source community by making RapidJSON available.
|
||||
//
|
||||
// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
|
||||
//
|
||||
// Licensed under the MIT License (the "License"); you may not use this file except
|
||||
// in compliance with the License. You may obtain a copy of the License at
|
||||
//
|
||||
// http://opensource.org/licenses/MIT
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software distributed
|
||||
// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
|
||||
// CONDITIONS OF ANY KIND, either express or implied. See the License for the
|
||||
// specific language governing permissions and limitations under the License.
|
||||
|
||||
#ifndef RAPIDJSON_INTERNAL_REGEX_H_
|
||||
#define RAPIDJSON_INTERNAL_REGEX_H_
|
||||
|
||||
#include "../allocators.h"
|
||||
#include "../stream.h"
|
||||
#include "stack.h"
|
||||
|
||||
#ifdef __clang__
|
||||
RAPIDJSON_DIAG_PUSH
|
||||
RAPIDJSON_DIAG_OFF(padded)
|
||||
RAPIDJSON_DIAG_OFF(switch-enum)
|
||||
RAPIDJSON_DIAG_OFF(implicit-fallthrough)
|
||||
#endif
|
||||
|
||||
#ifdef __GNUC__
|
||||
RAPIDJSON_DIAG_PUSH
|
||||
RAPIDJSON_DIAG_OFF(effc++)
|
||||
#endif
|
||||
|
||||
#ifdef _MSC_VER
|
||||
RAPIDJSON_DIAG_PUSH
|
||||
RAPIDJSON_DIAG_OFF(4512) // assignment operator could not be generated
|
||||
#endif
|
||||
|
||||
#ifndef RAPIDJSON_REGEX_VERBOSE
|
||||
#define RAPIDJSON_REGEX_VERBOSE 0
|
||||
#endif
|
||||
|
||||
RAPIDJSON_NAMESPACE_BEGIN
|
||||
namespace internal {
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// GenericRegex
|
||||
|
||||
static const SizeType kRegexInvalidState = ~SizeType(0); //!< Represents an invalid index in GenericRegex::State::out, out1
|
||||
static const SizeType kRegexInvalidRange = ~SizeType(0);
|
||||
|
||||
//! Regular expression engine with subset of ECMAscript grammar.
|
||||
/*!
|
||||
Supported regular expression syntax:
|
||||
- \c ab Concatenation
|
||||
- \c a|b Alternation
|
||||
- \c a? Zero or one
|
||||
- \c a* Zero or more
|
||||
- \c a+ One or more
|
||||
- \c a{3} Exactly 3 times
|
||||
- \c a{3,} At least 3 times
|
||||
- \c a{3,5} 3 to 5 times
|
||||
- \c (ab) Grouping
|
||||
- \c ^a At the beginning
|
||||
- \c a$ At the end
|
||||
- \c . Any character
|
||||
- \c [abc] Character classes
|
||||
- \c [a-c] Character class range
|
||||
- \c [a-z0-9_] Character class combination
|
||||
- \c [^abc] Negated character classes
|
||||
- \c [^a-c] Negated character class range
|
||||
- \c [\b] Backspace (U+0008)
|
||||
- \c \\| \\\\ ... Escape characters
|
||||
- \c \\f Form feed (U+000C)
|
||||
- \c \\n Line feed (U+000A)
|
||||
- \c \\r Carriage return (U+000D)
|
||||
- \c \\t Tab (U+0009)
|
||||
- \c \\v Vertical tab (U+000B)
|
||||
|
||||
\note This is a Thompson NFA engine, implemented with reference to
|
||||
Cox, Russ. "Regular Expression Matching Can Be Simple And Fast (but is slow in Java, Perl, PHP, Python, Ruby,...).",
|
||||
https://swtch.com/~rsc/regexp/regexp1.html
|
||||
*/
|
||||
template <typename Encoding, typename Allocator = CrtAllocator>
|
||||
class GenericRegex {
|
||||
public:
|
||||
typedef typename Encoding::Ch Ch;
|
||||
|
||||
GenericRegex(const Ch* source, Allocator* allocator = 0) :
|
||||
states_(allocator, 256), ranges_(allocator, 256), root_(kRegexInvalidState), stateCount_(), rangeCount_(),
|
||||
stateSet_(), state0_(allocator, 0), state1_(allocator, 0), anchorBegin_(), anchorEnd_()
|
||||
{
|
||||
GenericStringStream<Encoding> ss(source);
|
||||
DecodedStream<GenericStringStream<Encoding> > ds(ss);
|
||||
Parse(ds);
|
||||
}
|
||||
|
||||
~GenericRegex() {
|
||||
Allocator::Free(stateSet_);
|
||||
}
|
||||
|
||||
bool IsValid() const {
|
||||
return root_ != kRegexInvalidState;
|
||||
}
|
||||
|
||||
template <typename InputStream>
|
||||
bool Match(InputStream& is) const {
|
||||
return SearchWithAnchoring(is, true, true);
|
||||
}
|
||||
|
||||
bool Match(const Ch* s) const {
|
||||
GenericStringStream<Encoding> is(s);
|
||||
return Match(is);
|
||||
}
|
||||
|
||||
template <typename InputStream>
|
||||
bool Search(InputStream& is) const {
|
||||
return SearchWithAnchoring(is, anchorBegin_, anchorEnd_);
|
||||
}
|
||||
|
||||
bool Search(const Ch* s) const {
|
||||
GenericStringStream<Encoding> is(s);
|
||||
return Search(is);
|
||||
}
|
||||
|
||||
private:
|
||||
enum Operator {
|
||||
kZeroOrOne,
|
||||
kZeroOrMore,
|
||||
kOneOrMore,
|
||||
kConcatenation,
|
||||
kAlternation,
|
||||
kLeftParenthesis
|
||||
};
|
||||
|
||||
static const unsigned kAnyCharacterClass = 0xFFFFFFFF; //!< For '.'
|
||||
static const unsigned kRangeCharacterClass = 0xFFFFFFFE;
|
||||
static const unsigned kRangeNegationFlag = 0x80000000;
|
||||
|
||||
struct Range {
|
||||
unsigned start; //
|
||||
unsigned end;
|
||||
SizeType next;
|
||||
};
|
||||
|
||||
struct State {
|
||||
SizeType out; //!< Equals to kInvalid for matching state
|
||||
SizeType out1; //!< Equals to non-kInvalid for split
|
||||
SizeType rangeStart;
|
||||
unsigned codepoint;
|
||||
};
|
||||
|
||||
struct Frag {
|
||||
Frag(SizeType s, SizeType o, SizeType m) : start(s), out(o), minIndex(m) {}
|
||||
SizeType start;
|
||||
SizeType out; //!< link-list of all output states
|
||||
SizeType minIndex;
|
||||
};
|
||||
|
||||
template <typename SourceStream>
|
||||
class DecodedStream {
|
||||
public:
|
||||
DecodedStream(SourceStream& ss) : ss_(ss), codepoint_() { Decode(); }
|
||||
unsigned Peek() { return codepoint_; }
|
||||
unsigned Take() {
|
||||
unsigned c = codepoint_;
|
||||
if (c) // No further decoding when '\0'
|
||||
Decode();
|
||||
return c;
|
||||
}
|
||||
|
||||
private:
|
||||
void Decode() {
|
||||
if (!Encoding::Decode(ss_, &codepoint_))
|
||||
codepoint_ = 0;
|
||||
}
|
||||
|
||||
SourceStream& ss_;
|
||||
unsigned codepoint_;
|
||||
};
|
||||
|
||||
State& GetState(SizeType index) {
|
||||
RAPIDJSON_ASSERT(index < stateCount_);
|
||||
return states_.template Bottom<State>()[index];
|
||||
}
|
||||
|
||||
const State& GetState(SizeType index) const {
|
||||
RAPIDJSON_ASSERT(index < stateCount_);
|
||||
return states_.template Bottom<State>()[index];
|
||||
}
|
||||
|
||||
Range& GetRange(SizeType index) {
|
||||
RAPIDJSON_ASSERT(index < rangeCount_);
|
||||
return ranges_.template Bottom<Range>()[index];
|
||||
}
|
||||
|
||||
const Range& GetRange(SizeType index) const {
|
||||
RAPIDJSON_ASSERT(index < rangeCount_);
|
||||
return ranges_.template Bottom<Range>()[index];
|
||||
}
|
||||
|
||||
template <typename InputStream>
|
||||
void Parse(DecodedStream<InputStream>& ds) {
|
||||
Allocator allocator;
|
||||
Stack<Allocator> operandStack(&allocator, 256); // Frag
|
||||
Stack<Allocator> operatorStack(&allocator, 256); // Operator
|
||||
Stack<Allocator> atomCountStack(&allocator, 256); // unsigned (Atom per parenthesis)
|
||||
|
||||
*atomCountStack.template Push<unsigned>() = 0;
|
||||
|
||||
unsigned codepoint;
|
||||
while (ds.Peek() != 0) {
|
||||
switch (codepoint = ds.Take()) {
|
||||
case '^':
|
||||
anchorBegin_ = true;
|
||||
break;
|
||||
|
||||
case '$':
|
||||
anchorEnd_ = true;
|
||||
break;
|
||||
|
||||
case '|':
|
||||
while (!operatorStack.Empty() && *operatorStack.template Top<Operator>() < kAlternation)
|
||||
if (!Eval(operandStack, *operatorStack.template Pop<Operator>(1)))
|
||||
return;
|
||||
*operatorStack.template Push<Operator>() = kAlternation;
|
||||
*atomCountStack.template Top<unsigned>() = 0;
|
||||
break;
|
||||
|
||||
case '(':
|
||||
*operatorStack.template Push<Operator>() = kLeftParenthesis;
|
||||
*atomCountStack.template Push<unsigned>() = 0;
|
||||
break;
|
||||
|
||||
case ')':
|
||||
while (!operatorStack.Empty() && *operatorStack.template Top<Operator>() != kLeftParenthesis)
|
||||
if (!Eval(operandStack, *operatorStack.template Pop<Operator>(1)))
|
||||
return;
|
||||
if (operatorStack.Empty())
|
||||
return;
|
||||
operatorStack.template Pop<Operator>(1);
|
||||
atomCountStack.template Pop<unsigned>(1);
|
||||
ImplicitConcatenation(atomCountStack, operatorStack);
|
||||
break;
|
||||
|
||||
case '?':
|
||||
if (!Eval(operandStack, kZeroOrOne))
|
||||
return;
|
||||
break;
|
||||
|
||||
case '*':
|
||||
if (!Eval(operandStack, kZeroOrMore))
|
||||
return;
|
||||
break;
|
||||
|
||||
case '+':
|
||||
if (!Eval(operandStack, kOneOrMore))
|
||||
return;
|
||||
break;
|
||||
|
||||
case '{':
|
||||
{
|
||||
unsigned n, m;
|
||||
if (!ParseUnsigned(ds, &n))
|
||||
return;
|
||||
|
||||
if (ds.Peek() == ',') {
|
||||
ds.Take();
|
||||
if (ds.Peek() == '}')
|
||||
m = kInfinityQuantifier;
|
||||
else if (!ParseUnsigned(ds, &m) || m < n)
|
||||
return;
|
||||
}
|
||||
else
|
||||
m = n;
|
||||
|
||||
if (!EvalQuantifier(operandStack, n, m) || ds.Peek() != '}')
|
||||
return;
|
||||
ds.Take();
|
||||
}
|
||||
break;
|
||||
|
||||
case '.':
|
||||
PushOperand(operandStack, kAnyCharacterClass);
|
||||
ImplicitConcatenation(atomCountStack, operatorStack);
|
||||
break;
|
||||
|
||||
case '[':
|
||||
{
|
||||
SizeType range;
|
||||
if (!ParseRange(ds, &range))
|
||||
return;
|
||||
SizeType s = NewState(kRegexInvalidState, kRegexInvalidState, kRangeCharacterClass);
|
||||
GetState(s).rangeStart = range;
|
||||
*operandStack.template Push<Frag>() = Frag(s, s, s);
|
||||
}
|
||||
ImplicitConcatenation(atomCountStack, operatorStack);
|
||||
break;
|
||||
|
||||
case '\\': // Escape character
|
||||
if (!CharacterEscape(ds, &codepoint))
|
||||
return; // Unsupported escape character
|
||||
// fall through to default
|
||||
|
||||
default: // Pattern character
|
||||
PushOperand(operandStack, codepoint);
|
||||
ImplicitConcatenation(atomCountStack, operatorStack);
|
||||
}
|
||||
}
|
||||
|
||||
while (!operatorStack.Empty())
|
||||
if (!Eval(operandStack, *operatorStack.template Pop<Operator>(1)))
|
||||
return;
|
||||
|
||||
// Link the operand to matching state.
|
||||
if (operandStack.GetSize() == sizeof(Frag)) {
|
||||
Frag* e = operandStack.template Pop<Frag>(1);
|
||||
Patch(e->out, NewState(kRegexInvalidState, kRegexInvalidState, 0));
|
||||
root_ = e->start;
|
||||
|
||||
#if RAPIDJSON_REGEX_VERBOSE
|
||||
printf("root: %d\n", root_);
|
||||
for (SizeType i = 0; i < stateCount_ ; i++) {
|
||||
State& s = GetState(i);
|
||||
printf("[%2d] out: %2d out1: %2d c: '%c'\n", i, s.out, s.out1, (char)s.codepoint);
|
||||
}
|
||||
printf("\n");
|
||||
#endif
|
||||
}
|
||||
|
||||
// Preallocate buffer for SearchWithAnchoring()
|
||||
RAPIDJSON_ASSERT(stateSet_ == 0);
|
||||
if (stateCount_ > 0) {
|
||||
stateSet_ = static_cast<unsigned*>(states_.GetAllocator().Malloc(GetStateSetSize()));
|
||||
state0_.template Reserve<SizeType>(stateCount_);
|
||||
state1_.template Reserve<SizeType>(stateCount_);
|
||||
}
|
||||
}
|
||||
|
||||
SizeType NewState(SizeType out, SizeType out1, unsigned codepoint) {
|
||||
State* s = states_.template Push<State>();
|
||||
s->out = out;
|
||||
s->out1 = out1;
|
||||
s->codepoint = codepoint;
|
||||
s->rangeStart = kRegexInvalidRange;
|
||||
return stateCount_++;
|
||||
}
|
||||
|
||||
void PushOperand(Stack<Allocator>& operandStack, unsigned codepoint) {
|
||||
SizeType s = NewState(kRegexInvalidState, kRegexInvalidState, codepoint);
|
||||
*operandStack.template Push<Frag>() = Frag(s, s, s);
|
||||
}
|
||||
|
||||
void ImplicitConcatenation(Stack<Allocator>& atomCountStack, Stack<Allocator>& operatorStack) {
|
||||
if (*atomCountStack.template Top<unsigned>())
|
||||
*operatorStack.template Push<Operator>() = kConcatenation;
|
||||
(*atomCountStack.template Top<unsigned>())++;
|
||||
}
|
||||
|
||||
SizeType Append(SizeType l1, SizeType l2) {
|
||||
SizeType old = l1;
|
||||
while (GetState(l1).out != kRegexInvalidState)
|
||||
l1 = GetState(l1).out;
|
||||
GetState(l1).out = l2;
|
||||
return old;
|
||||
}
|
||||
|
||||
void Patch(SizeType l, SizeType s) {
|
||||
for (SizeType next; l != kRegexInvalidState; l = next) {
|
||||
next = GetState(l).out;
|
||||
GetState(l).out = s;
|
||||
}
|
||||
}
|
||||
|
||||
bool Eval(Stack<Allocator>& operandStack, Operator op) {
|
||||
switch (op) {
|
||||
case kConcatenation:
|
||||
RAPIDJSON_ASSERT(operandStack.GetSize() >= sizeof(Frag) * 2);
|
||||
{
|
||||
Frag e2 = *operandStack.template Pop<Frag>(1);
|
||||
Frag e1 = *operandStack.template Pop<Frag>(1);
|
||||
Patch(e1.out, e2.start);
|
||||
*operandStack.template Push<Frag>() = Frag(e1.start, e2.out, Min(e1.minIndex, e2.minIndex));
|
||||
}
|
||||
return true;
|
||||
|
||||
case kAlternation:
|
||||
if (operandStack.GetSize() >= sizeof(Frag) * 2) {
|
||||
Frag e2 = *operandStack.template Pop<Frag>(1);
|
||||
Frag e1 = *operandStack.template Pop<Frag>(1);
|
||||
SizeType s = NewState(e1.start, e2.start, 0);
|
||||
*operandStack.template Push<Frag>() = Frag(s, Append(e1.out, e2.out), Min(e1.minIndex, e2.minIndex));
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
||||
case kZeroOrOne:
|
||||
if (operandStack.GetSize() >= sizeof(Frag)) {
|
||||
Frag e = *operandStack.template Pop<Frag>(1);
|
||||
SizeType s = NewState(kRegexInvalidState, e.start, 0);
|
||||
*operandStack.template Push<Frag>() = Frag(s, Append(e.out, s), e.minIndex);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
||||
case kZeroOrMore:
|
||||
if (operandStack.GetSize() >= sizeof(Frag)) {
|
||||
Frag e = *operandStack.template Pop<Frag>(1);
|
||||
SizeType s = NewState(kRegexInvalidState, e.start, 0);
|
||||
Patch(e.out, s);
|
||||
*operandStack.template Push<Frag>() = Frag(s, s, e.minIndex);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
||||
default:
|
||||
RAPIDJSON_ASSERT(op == kOneOrMore);
|
||||
if (operandStack.GetSize() >= sizeof(Frag)) {
|
||||
Frag e = *operandStack.template Pop<Frag>(1);
|
||||
SizeType s = NewState(kRegexInvalidState, e.start, 0);
|
||||
Patch(e.out, s);
|
||||
*operandStack.template Push<Frag>() = Frag(e.start, s, e.minIndex);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool EvalQuantifier(Stack<Allocator>& operandStack, unsigned n, unsigned m) {
|
||||
RAPIDJSON_ASSERT(n <= m);
|
||||
RAPIDJSON_ASSERT(operandStack.GetSize() >= sizeof(Frag));
|
||||
|
||||
if (n == 0) {
|
||||
if (m == 0) // a{0} not support
|
||||
return false;
|
||||
else if (m == kInfinityQuantifier)
|
||||
Eval(operandStack, kZeroOrMore); // a{0,} -> a*
|
||||
else {
|
||||
Eval(operandStack, kZeroOrOne); // a{0,5} -> a?
|
||||
for (unsigned i = 0; i < m - 1; i++)
|
||||
CloneTopOperand(operandStack); // a{0,5} -> a? a? a? a? a?
|
||||
for (unsigned i = 0; i < m - 1; i++)
|
||||
Eval(operandStack, kConcatenation); // a{0,5} -> a?a?a?a?a?
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
for (unsigned i = 0; i < n - 1; i++) // a{3} -> a a a
|
||||
CloneTopOperand(operandStack);
|
||||
|
||||
if (m == kInfinityQuantifier)
|
||||
Eval(operandStack, kOneOrMore); // a{3,} -> a a a+
|
||||
else if (m > n) {
|
||||
CloneTopOperand(operandStack); // a{3,5} -> a a a a
|
||||
Eval(operandStack, kZeroOrOne); // a{3,5} -> a a a a?
|
||||
for (unsigned i = n; i < m - 1; i++)
|
||||
CloneTopOperand(operandStack); // a{3,5} -> a a a a? a?
|
||||
for (unsigned i = n; i < m; i++)
|
||||
Eval(operandStack, kConcatenation); // a{3,5} -> a a aa?a?
|
||||
}
|
||||
|
||||
for (unsigned i = 0; i < n - 1; i++)
|
||||
Eval(operandStack, kConcatenation); // a{3} -> aaa, a{3,} -> aaa+, a{3.5} -> aaaa?a?
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static SizeType Min(SizeType a, SizeType b) { return a < b ? a : b; }
|
||||
|
||||
void CloneTopOperand(Stack<Allocator>& operandStack) {
|
||||
const Frag src = *operandStack.template Top<Frag>(); // Copy constructor to prevent invalidation
|
||||
SizeType count = stateCount_ - src.minIndex; // Assumes top operand contains states in [src->minIndex, stateCount_)
|
||||
State* s = states_.template Push<State>(count);
|
||||
memcpy(s, &GetState(src.minIndex), count * sizeof(State));
|
||||
for (SizeType j = 0; j < count; j++) {
|
||||
if (s[j].out != kRegexInvalidState)
|
||||
s[j].out += count;
|
||||
if (s[j].out1 != kRegexInvalidState)
|
||||
s[j].out1 += count;
|
||||
}
|
||||
*operandStack.template Push<Frag>() = Frag(src.start + count, src.out + count, src.minIndex + count);
|
||||
stateCount_ += count;
|
||||
}
|
||||
|
||||
template <typename InputStream>
|
||||
bool ParseUnsigned(DecodedStream<InputStream>& ds, unsigned* u) {
|
||||
unsigned r = 0;
|
||||
if (ds.Peek() < '0' || ds.Peek() > '9')
|
||||
return false;
|
||||
while (ds.Peek() >= '0' && ds.Peek() <= '9') {
|
||||
if (r >= 429496729 && ds.Peek() > '5') // 2^32 - 1 = 4294967295
|
||||
return false; // overflow
|
||||
r = r * 10 + (ds.Take() - '0');
|
||||
}
|
||||
*u = r;
|
||||
return true;
|
||||
}
|
||||
|
||||
template <typename InputStream>
|
||||
bool ParseRange(DecodedStream<InputStream>& ds, SizeType* range) {
|
||||
bool isBegin = true;
|
||||
bool negate = false;
|
||||
int step = 0;
|
||||
SizeType start = kRegexInvalidRange;
|
||||
SizeType current = kRegexInvalidRange;
|
||||
unsigned codepoint;
|
||||
while ((codepoint = ds.Take()) != 0) {
|
||||
if (isBegin) {
|
||||
isBegin = false;
|
||||
if (codepoint == '^') {
|
||||
negate = true;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
switch (codepoint) {
|
||||
case ']':
|
||||
if (start == kRegexInvalidRange)
|
||||
return false; // Error: nothing inside []
|
||||
if (step == 2) { // Add trailing '-'
|
||||
SizeType r = NewRange('-');
|
||||
RAPIDJSON_ASSERT(current != kRegexInvalidRange);
|
||||
GetRange(current).next = r;
|
||||
}
|
||||
if (negate)
|
||||
GetRange(start).start |= kRangeNegationFlag;
|
||||
*range = start;
|
||||
return true;
|
||||
|
||||
case '\\':
|
||||
if (ds.Peek() == 'b') {
|
||||
ds.Take();
|
||||
codepoint = 0x0008; // Escape backspace character
|
||||
}
|
||||
else if (!CharacterEscape(ds, &codepoint))
|
||||
return false;
|
||||
// fall through to default
|
||||
|
||||
default:
|
||||
switch (step) {
|
||||
case 1:
|
||||
if (codepoint == '-') {
|
||||
step++;
|
||||
break;
|
||||
}
|
||||
// fall through to step 0 for other characters
|
||||
|
||||
case 0:
|
||||
{
|
||||
SizeType r = NewRange(codepoint);
|
||||
if (current != kRegexInvalidRange)
|
||||
GetRange(current).next = r;
|
||||
if (start == kRegexInvalidRange)
|
||||
start = r;
|
||||
current = r;
|
||||
}
|
||||
step = 1;
|
||||
break;
|
||||
|
||||
default:
|
||||
RAPIDJSON_ASSERT(step == 2);
|
||||
GetRange(current).end = codepoint;
|
||||
step = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
SizeType NewRange(unsigned codepoint) {
|
||||
Range* r = ranges_.template Push<Range>();
|
||||
r->start = r->end = codepoint;
|
||||
r->next = kRegexInvalidRange;
|
||||
return rangeCount_++;
|
||||
}
|
||||
|
||||
template <typename InputStream>
|
||||
bool CharacterEscape(DecodedStream<InputStream>& ds, unsigned* escapedCodepoint) {
|
||||
unsigned codepoint;
|
||||
switch (codepoint = ds.Take()) {
|
||||
case '^':
|
||||
case '$':
|
||||
case '|':
|
||||
case '(':
|
||||
case ')':
|
||||
case '?':
|
||||
case '*':
|
||||
case '+':
|
||||
case '.':
|
||||
case '[':
|
||||
case ']':
|
||||
case '{':
|
||||
case '}':
|
||||
case '\\':
|
||||
*escapedCodepoint = codepoint; return true;
|
||||
case 'f': *escapedCodepoint = 0x000C; return true;
|
||||
case 'n': *escapedCodepoint = 0x000A; return true;
|
||||
case 'r': *escapedCodepoint = 0x000D; return true;
|
||||
case 't': *escapedCodepoint = 0x0009; return true;
|
||||
case 'v': *escapedCodepoint = 0x000B; return true;
|
||||
default:
|
||||
return false; // Unsupported escape character
|
||||
}
|
||||
}
|
||||
|
||||
template <typename InputStream>
|
||||
bool SearchWithAnchoring(InputStream& is, bool anchorBegin, bool anchorEnd) const {
|
||||
RAPIDJSON_ASSERT(IsValid());
|
||||
DecodedStream<InputStream> ds(is);
|
||||
|
||||
state0_.Clear();
|
||||
Stack<Allocator> *current = &state0_, *next = &state1_;
|
||||
const size_t stateSetSize = GetStateSetSize();
|
||||
std::memset(stateSet_, 0, stateSetSize);
|
||||
|
||||
bool matched = AddState(*current, root_);
|
||||
unsigned codepoint;
|
||||
while (!current->Empty() && (codepoint = ds.Take()) != 0) {
|
||||
std::memset(stateSet_, 0, stateSetSize);
|
||||
next->Clear();
|
||||
matched = false;
|
||||
for (const SizeType* s = current->template Bottom<SizeType>(); s != current->template End<SizeType>(); ++s) {
|
||||
const State& sr = GetState(*s);
|
||||
if (sr.codepoint == codepoint ||
|
||||
sr.codepoint == kAnyCharacterClass ||
|
||||
(sr.codepoint == kRangeCharacterClass && MatchRange(sr.rangeStart, codepoint)))
|
||||
{
|
||||
matched = AddState(*next, sr.out) || matched;
|
||||
if (!anchorEnd && matched)
|
||||
return true;
|
||||
}
|
||||
if (!anchorBegin)
|
||||
AddState(*next, root_);
|
||||
}
|
||||
internal::Swap(current, next);
|
||||
}
|
||||
|
||||
return matched;
|
||||
}
|
||||
|
||||
size_t GetStateSetSize() const {
|
||||
return (stateCount_ + 31) / 32 * 4;
|
||||
}
|
||||
|
||||
// Return whether the added states is a match state
|
||||
bool AddState(Stack<Allocator>& l, SizeType index) const {
|
||||
RAPIDJSON_ASSERT(index != kRegexInvalidState);
|
||||
|
||||
const State& s = GetState(index);
|
||||
if (s.out1 != kRegexInvalidState) { // Split
|
||||
bool matched = AddState(l, s.out);
|
||||
return AddState(l, s.out1) || matched;
|
||||
}
|
||||
else if (!(stateSet_[index >> 5] & (1 << (index & 31)))) {
|
||||
stateSet_[index >> 5] |= (1 << (index & 31));
|
||||
*l.template PushUnsafe<SizeType>() = index;
|
||||
}
|
||||
return s.out == kRegexInvalidState; // by using PushUnsafe() above, we can ensure s is not validated due to reallocation.
|
||||
}
|
||||
|
||||
bool MatchRange(SizeType rangeIndex, unsigned codepoint) const {
|
||||
bool yes = (GetRange(rangeIndex).start & kRangeNegationFlag) == 0;
|
||||
while (rangeIndex != kRegexInvalidRange) {
|
||||
const Range& r = GetRange(rangeIndex);
|
||||
if (codepoint >= (r.start & ~kRangeNegationFlag) && codepoint <= r.end)
|
||||
return yes;
|
||||
rangeIndex = r.next;
|
||||
}
|
||||
return !yes;
|
||||
}
|
||||
|
||||
Stack<Allocator> states_;
|
||||
Stack<Allocator> ranges_;
|
||||
SizeType root_;
|
||||
SizeType stateCount_;
|
||||
SizeType rangeCount_;
|
||||
|
||||
static const unsigned kInfinityQuantifier = ~0u;
|
||||
|
||||
// For SearchWithAnchoring()
|
||||
uint32_t* stateSet_; // allocated by states_.GetAllocator()
|
||||
mutable Stack<Allocator> state0_;
|
||||
mutable Stack<Allocator> state1_;
|
||||
bool anchorBegin_;
|
||||
bool anchorEnd_;
|
||||
};
|
||||
|
||||
typedef GenericRegex<UTF8<> > Regex;
|
||||
|
||||
} // namespace internal
|
||||
RAPIDJSON_NAMESPACE_END
|
||||
|
||||
#ifdef __clang__
|
||||
RAPIDJSON_DIAG_POP
|
||||
#endif
|
||||
|
||||
#ifdef _MSC_VER
|
||||
RAPIDJSON_DIAG_POP
|
||||
#endif
|
||||
|
||||
#endif // RAPIDJSON_INTERNAL_REGEX_H_
|
||||
230
src/3rdparty/rapidjson/internal/stack.h
vendored
Normal file
230
src/3rdparty/rapidjson/internal/stack.h
vendored
Normal file
@@ -0,0 +1,230 @@
|
||||
// Tencent is pleased to support the open source community by making RapidJSON available.
|
||||
//
|
||||
// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
|
||||
//
|
||||
// Licensed under the MIT License (the "License"); you may not use this file except
|
||||
// in compliance with the License. You may obtain a copy of the License at
|
||||
//
|
||||
// http://opensource.org/licenses/MIT
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software distributed
|
||||
// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
|
||||
// CONDITIONS OF ANY KIND, either express or implied. See the License for the
|
||||
// specific language governing permissions and limitations under the License.
|
||||
|
||||
#ifndef RAPIDJSON_INTERNAL_STACK_H_
|
||||
#define RAPIDJSON_INTERNAL_STACK_H_
|
||||
|
||||
#include "../allocators.h"
|
||||
#include "swap.h"
|
||||
|
||||
#if defined(__clang__)
|
||||
RAPIDJSON_DIAG_PUSH
|
||||
RAPIDJSON_DIAG_OFF(c++98-compat)
|
||||
#endif
|
||||
|
||||
RAPIDJSON_NAMESPACE_BEGIN
|
||||
namespace internal {
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Stack
|
||||
|
||||
//! A type-unsafe stack for storing different types of data.
|
||||
/*! \tparam Allocator Allocator for allocating stack memory.
|
||||
*/
|
||||
template <typename Allocator>
|
||||
class Stack {
|
||||
public:
|
||||
// Optimization note: Do not allocate memory for stack_ in constructor.
|
||||
// Do it lazily when first Push() -> Expand() -> Resize().
|
||||
Stack(Allocator* allocator, size_t stackCapacity) : allocator_(allocator), ownAllocator_(0), stack_(0), stackTop_(0), stackEnd_(0), initialCapacity_(stackCapacity) {
|
||||
}
|
||||
|
||||
#if RAPIDJSON_HAS_CXX11_RVALUE_REFS
|
||||
Stack(Stack&& rhs)
|
||||
: allocator_(rhs.allocator_),
|
||||
ownAllocator_(rhs.ownAllocator_),
|
||||
stack_(rhs.stack_),
|
||||
stackTop_(rhs.stackTop_),
|
||||
stackEnd_(rhs.stackEnd_),
|
||||
initialCapacity_(rhs.initialCapacity_)
|
||||
{
|
||||
rhs.allocator_ = 0;
|
||||
rhs.ownAllocator_ = 0;
|
||||
rhs.stack_ = 0;
|
||||
rhs.stackTop_ = 0;
|
||||
rhs.stackEnd_ = 0;
|
||||
rhs.initialCapacity_ = 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
~Stack() {
|
||||
Destroy();
|
||||
}
|
||||
|
||||
#if RAPIDJSON_HAS_CXX11_RVALUE_REFS
|
||||
Stack& operator=(Stack&& rhs) {
|
||||
if (&rhs != this)
|
||||
{
|
||||
Destroy();
|
||||
|
||||
allocator_ = rhs.allocator_;
|
||||
ownAllocator_ = rhs.ownAllocator_;
|
||||
stack_ = rhs.stack_;
|
||||
stackTop_ = rhs.stackTop_;
|
||||
stackEnd_ = rhs.stackEnd_;
|
||||
initialCapacity_ = rhs.initialCapacity_;
|
||||
|
||||
rhs.allocator_ = 0;
|
||||
rhs.ownAllocator_ = 0;
|
||||
rhs.stack_ = 0;
|
||||
rhs.stackTop_ = 0;
|
||||
rhs.stackEnd_ = 0;
|
||||
rhs.initialCapacity_ = 0;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
#endif
|
||||
|
||||
void Swap(Stack& rhs) RAPIDJSON_NOEXCEPT {
|
||||
internal::Swap(allocator_, rhs.allocator_);
|
||||
internal::Swap(ownAllocator_, rhs.ownAllocator_);
|
||||
internal::Swap(stack_, rhs.stack_);
|
||||
internal::Swap(stackTop_, rhs.stackTop_);
|
||||
internal::Swap(stackEnd_, rhs.stackEnd_);
|
||||
internal::Swap(initialCapacity_, rhs.initialCapacity_);
|
||||
}
|
||||
|
||||
void Clear() { stackTop_ = stack_; }
|
||||
|
||||
void ShrinkToFit() {
|
||||
if (Empty()) {
|
||||
// If the stack is empty, completely deallocate the memory.
|
||||
Allocator::Free(stack_);
|
||||
stack_ = 0;
|
||||
stackTop_ = 0;
|
||||
stackEnd_ = 0;
|
||||
}
|
||||
else
|
||||
Resize(GetSize());
|
||||
}
|
||||
|
||||
// Optimization note: try to minimize the size of this function for force inline.
|
||||
// Expansion is run very infrequently, so it is moved to another (probably non-inline) function.
|
||||
template<typename T>
|
||||
RAPIDJSON_FORCEINLINE void Reserve(size_t count = 1) {
|
||||
// Expand the stack if needed
|
||||
if (RAPIDJSON_UNLIKELY(stackTop_ + sizeof(T) * count > stackEnd_))
|
||||
Expand<T>(count);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
RAPIDJSON_FORCEINLINE T* Push(size_t count = 1) {
|
||||
Reserve<T>(count);
|
||||
return PushUnsafe<T>(count);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
RAPIDJSON_FORCEINLINE T* PushUnsafe(size_t count = 1) {
|
||||
RAPIDJSON_ASSERT(stackTop_ + sizeof(T) * count <= stackEnd_);
|
||||
T* ret = reinterpret_cast<T*>(stackTop_);
|
||||
stackTop_ += sizeof(T) * count;
|
||||
return ret;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
T* Pop(size_t count) {
|
||||
RAPIDJSON_ASSERT(GetSize() >= count * sizeof(T));
|
||||
stackTop_ -= count * sizeof(T);
|
||||
return reinterpret_cast<T*>(stackTop_);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
T* Top() {
|
||||
RAPIDJSON_ASSERT(GetSize() >= sizeof(T));
|
||||
return reinterpret_cast<T*>(stackTop_ - sizeof(T));
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
const T* Top() const {
|
||||
RAPIDJSON_ASSERT(GetSize() >= sizeof(T));
|
||||
return reinterpret_cast<T*>(stackTop_ - sizeof(T));
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
T* End() { return reinterpret_cast<T*>(stackTop_); }
|
||||
|
||||
template<typename T>
|
||||
const T* End() const { return reinterpret_cast<T*>(stackTop_); }
|
||||
|
||||
template<typename T>
|
||||
T* Bottom() { return reinterpret_cast<T*>(stack_); }
|
||||
|
||||
template<typename T>
|
||||
const T* Bottom() const { return reinterpret_cast<T*>(stack_); }
|
||||
|
||||
bool HasAllocator() const {
|
||||
return allocator_ != 0;
|
||||
}
|
||||
|
||||
Allocator& GetAllocator() {
|
||||
RAPIDJSON_ASSERT(allocator_);
|
||||
return *allocator_;
|
||||
}
|
||||
|
||||
bool Empty() const { return stackTop_ == stack_; }
|
||||
size_t GetSize() const { return static_cast<size_t>(stackTop_ - stack_); }
|
||||
size_t GetCapacity() const { return static_cast<size_t>(stackEnd_ - stack_); }
|
||||
|
||||
private:
|
||||
template<typename T>
|
||||
void Expand(size_t count) {
|
||||
// Only expand the capacity if the current stack exists. Otherwise just create a stack with initial capacity.
|
||||
size_t newCapacity;
|
||||
if (stack_ == 0) {
|
||||
if (!allocator_)
|
||||
ownAllocator_ = allocator_ = RAPIDJSON_NEW(Allocator());
|
||||
newCapacity = initialCapacity_;
|
||||
} else {
|
||||
newCapacity = GetCapacity();
|
||||
newCapacity += (newCapacity + 1) / 2;
|
||||
}
|
||||
size_t newSize = GetSize() + sizeof(T) * count;
|
||||
if (newCapacity < newSize)
|
||||
newCapacity = newSize;
|
||||
|
||||
Resize(newCapacity);
|
||||
}
|
||||
|
||||
void Resize(size_t newCapacity) {
|
||||
const size_t size = GetSize(); // Backup the current size
|
||||
stack_ = static_cast<char*>(allocator_->Realloc(stack_, GetCapacity(), newCapacity));
|
||||
stackTop_ = stack_ + size;
|
||||
stackEnd_ = stack_ + newCapacity;
|
||||
}
|
||||
|
||||
void Destroy() {
|
||||
Allocator::Free(stack_);
|
||||
RAPIDJSON_DELETE(ownAllocator_); // Only delete if it is owned by the stack
|
||||
}
|
||||
|
||||
// Prohibit copy constructor & assignment operator.
|
||||
Stack(const Stack&);
|
||||
Stack& operator=(const Stack&);
|
||||
|
||||
Allocator* allocator_;
|
||||
Allocator* ownAllocator_;
|
||||
char *stack_;
|
||||
char *stackTop_;
|
||||
char *stackEnd_;
|
||||
size_t initialCapacity_;
|
||||
};
|
||||
|
||||
} // namespace internal
|
||||
RAPIDJSON_NAMESPACE_END
|
||||
|
||||
#if defined(__clang__)
|
||||
RAPIDJSON_DIAG_POP
|
||||
#endif
|
||||
|
||||
#endif // RAPIDJSON_STACK_H_
|
||||
55
src/3rdparty/rapidjson/internal/strfunc.h
vendored
Normal file
55
src/3rdparty/rapidjson/internal/strfunc.h
vendored
Normal file
@@ -0,0 +1,55 @@
|
||||
// Tencent is pleased to support the open source community by making RapidJSON available.
|
||||
//
|
||||
// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
|
||||
//
|
||||
// Licensed under the MIT License (the "License"); you may not use this file except
|
||||
// in compliance with the License. You may obtain a copy of the License at
|
||||
//
|
||||
// http://opensource.org/licenses/MIT
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software distributed
|
||||
// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
|
||||
// CONDITIONS OF ANY KIND, either express or implied. See the License for the
|
||||
// specific language governing permissions and limitations under the License.
|
||||
|
||||
#ifndef RAPIDJSON_INTERNAL_STRFUNC_H_
|
||||
#define RAPIDJSON_INTERNAL_STRFUNC_H_
|
||||
|
||||
#include "../stream.h"
|
||||
|
||||
RAPIDJSON_NAMESPACE_BEGIN
|
||||
namespace internal {
|
||||
|
||||
//! Custom strlen() which works on different character types.
|
||||
/*! \tparam Ch Character type (e.g. char, wchar_t, short)
|
||||
\param s Null-terminated input string.
|
||||
\return Number of characters in the string.
|
||||
\note This has the same semantics as strlen(), the return value is not number of Unicode codepoints.
|
||||
*/
|
||||
template <typename Ch>
|
||||
inline SizeType StrLen(const Ch* s) {
|
||||
const Ch* p = s;
|
||||
while (*p) ++p;
|
||||
return SizeType(p - s);
|
||||
}
|
||||
|
||||
//! Returns number of code points in a encoded string.
|
||||
template<typename Encoding>
|
||||
bool CountStringCodePoint(const typename Encoding::Ch* s, SizeType length, SizeType* outCount) {
|
||||
GenericStringStream<Encoding> is(s);
|
||||
const typename Encoding::Ch* end = s + length;
|
||||
SizeType count = 0;
|
||||
while (is.src_ < end) {
|
||||
unsigned codepoint;
|
||||
if (!Encoding::Decode(is, &codepoint))
|
||||
return false;
|
||||
count++;
|
||||
}
|
||||
*outCount = count;
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace internal
|
||||
RAPIDJSON_NAMESPACE_END
|
||||
|
||||
#endif // RAPIDJSON_INTERNAL_STRFUNC_H_
|
||||
269
src/3rdparty/rapidjson/internal/strtod.h
vendored
Normal file
269
src/3rdparty/rapidjson/internal/strtod.h
vendored
Normal file
@@ -0,0 +1,269 @@
|
||||
// Tencent is pleased to support the open source community by making RapidJSON available.
|
||||
//
|
||||
// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
|
||||
//
|
||||
// Licensed under the MIT License (the "License"); you may not use this file except
|
||||
// in compliance with the License. You may obtain a copy of the License at
|
||||
//
|
||||
// http://opensource.org/licenses/MIT
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software distributed
|
||||
// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
|
||||
// CONDITIONS OF ANY KIND, either express or implied. See the License for the
|
||||
// specific language governing permissions and limitations under the License.
|
||||
|
||||
#ifndef RAPIDJSON_STRTOD_
|
||||
#define RAPIDJSON_STRTOD_
|
||||
|
||||
#include "ieee754.h"
|
||||
#include "biginteger.h"
|
||||
#include "diyfp.h"
|
||||
#include "pow10.h"
|
||||
|
||||
RAPIDJSON_NAMESPACE_BEGIN
|
||||
namespace internal {
|
||||
|
||||
inline double FastPath(double significand, int exp) {
|
||||
if (exp < -308)
|
||||
return 0.0;
|
||||
else if (exp >= 0)
|
||||
return significand * internal::Pow10(exp);
|
||||
else
|
||||
return significand / internal::Pow10(-exp);
|
||||
}
|
||||
|
||||
inline double StrtodNormalPrecision(double d, int p) {
|
||||
if (p < -308) {
|
||||
// Prevent expSum < -308, making Pow10(p) = 0
|
||||
d = FastPath(d, -308);
|
||||
d = FastPath(d, p + 308);
|
||||
}
|
||||
else
|
||||
d = FastPath(d, p);
|
||||
return d;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline T Min3(T a, T b, T c) {
|
||||
T m = a;
|
||||
if (m > b) m = b;
|
||||
if (m > c) m = c;
|
||||
return m;
|
||||
}
|
||||
|
||||
inline int CheckWithinHalfULP(double b, const BigInteger& d, int dExp) {
|
||||
const Double db(b);
|
||||
const uint64_t bInt = db.IntegerSignificand();
|
||||
const int bExp = db.IntegerExponent();
|
||||
const int hExp = bExp - 1;
|
||||
|
||||
int dS_Exp2 = 0, dS_Exp5 = 0, bS_Exp2 = 0, bS_Exp5 = 0, hS_Exp2 = 0, hS_Exp5 = 0;
|
||||
|
||||
// Adjust for decimal exponent
|
||||
if (dExp >= 0) {
|
||||
dS_Exp2 += dExp;
|
||||
dS_Exp5 += dExp;
|
||||
}
|
||||
else {
|
||||
bS_Exp2 -= dExp;
|
||||
bS_Exp5 -= dExp;
|
||||
hS_Exp2 -= dExp;
|
||||
hS_Exp5 -= dExp;
|
||||
}
|
||||
|
||||
// Adjust for binary exponent
|
||||
if (bExp >= 0)
|
||||
bS_Exp2 += bExp;
|
||||
else {
|
||||
dS_Exp2 -= bExp;
|
||||
hS_Exp2 -= bExp;
|
||||
}
|
||||
|
||||
// Adjust for half ulp exponent
|
||||
if (hExp >= 0)
|
||||
hS_Exp2 += hExp;
|
||||
else {
|
||||
dS_Exp2 -= hExp;
|
||||
bS_Exp2 -= hExp;
|
||||
}
|
||||
|
||||
// Remove common power of two factor from all three scaled values
|
||||
int common_Exp2 = Min3(dS_Exp2, bS_Exp2, hS_Exp2);
|
||||
dS_Exp2 -= common_Exp2;
|
||||
bS_Exp2 -= common_Exp2;
|
||||
hS_Exp2 -= common_Exp2;
|
||||
|
||||
BigInteger dS = d;
|
||||
dS.MultiplyPow5(static_cast<unsigned>(dS_Exp5)) <<= static_cast<unsigned>(dS_Exp2);
|
||||
|
||||
BigInteger bS(bInt);
|
||||
bS.MultiplyPow5(static_cast<unsigned>(bS_Exp5)) <<= static_cast<unsigned>(bS_Exp2);
|
||||
|
||||
BigInteger hS(1);
|
||||
hS.MultiplyPow5(static_cast<unsigned>(hS_Exp5)) <<= static_cast<unsigned>(hS_Exp2);
|
||||
|
||||
BigInteger delta(0);
|
||||
dS.Difference(bS, &delta);
|
||||
|
||||
return delta.Compare(hS);
|
||||
}
|
||||
|
||||
inline bool StrtodFast(double d, int p, double* result) {
|
||||
// Use fast path for string-to-double conversion if possible
|
||||
// see http://www.exploringbinary.com/fast-path-decimal-to-floating-point-conversion/
|
||||
if (p > 22 && p < 22 + 16) {
|
||||
// Fast Path Cases In Disguise
|
||||
d *= internal::Pow10(p - 22);
|
||||
p = 22;
|
||||
}
|
||||
|
||||
if (p >= -22 && p <= 22 && d <= 9007199254740991.0) { // 2^53 - 1
|
||||
*result = FastPath(d, p);
|
||||
return true;
|
||||
}
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
// Compute an approximation and see if it is within 1/2 ULP
|
||||
inline bool StrtodDiyFp(const char* decimals, size_t length, size_t decimalPosition, int exp, double* result) {
|
||||
uint64_t significand = 0;
|
||||
size_t i = 0; // 2^64 - 1 = 18446744073709551615, 1844674407370955161 = 0x1999999999999999
|
||||
for (; i < length; i++) {
|
||||
if (significand > RAPIDJSON_UINT64_C2(0x19999999, 0x99999999) ||
|
||||
(significand == RAPIDJSON_UINT64_C2(0x19999999, 0x99999999) && decimals[i] > '5'))
|
||||
break;
|
||||
significand = significand * 10u + static_cast<unsigned>(decimals[i] - '0');
|
||||
}
|
||||
|
||||
if (i < length && decimals[i] >= '5') // Rounding
|
||||
significand++;
|
||||
|
||||
size_t remaining = length - i;
|
||||
const unsigned kUlpShift = 3;
|
||||
const unsigned kUlp = 1 << kUlpShift;
|
||||
int64_t error = (remaining == 0) ? 0 : kUlp / 2;
|
||||
|
||||
DiyFp v(significand, 0);
|
||||
v = v.Normalize();
|
||||
error <<= -v.e;
|
||||
|
||||
const int dExp = static_cast<int>(decimalPosition) - static_cast<int>(i) + exp;
|
||||
|
||||
int actualExp;
|
||||
DiyFp cachedPower = GetCachedPower10(dExp, &actualExp);
|
||||
if (actualExp != dExp) {
|
||||
static const DiyFp kPow10[] = {
|
||||
DiyFp(RAPIDJSON_UINT64_C2(0xa0000000, 00000000), -60), // 10^1
|
||||
DiyFp(RAPIDJSON_UINT64_C2(0xc8000000, 00000000), -57), // 10^2
|
||||
DiyFp(RAPIDJSON_UINT64_C2(0xfa000000, 00000000), -54), // 10^3
|
||||
DiyFp(RAPIDJSON_UINT64_C2(0x9c400000, 00000000), -50), // 10^4
|
||||
DiyFp(RAPIDJSON_UINT64_C2(0xc3500000, 00000000), -47), // 10^5
|
||||
DiyFp(RAPIDJSON_UINT64_C2(0xf4240000, 00000000), -44), // 10^6
|
||||
DiyFp(RAPIDJSON_UINT64_C2(0x98968000, 00000000), -40) // 10^7
|
||||
};
|
||||
int adjustment = dExp - actualExp - 1;
|
||||
RAPIDJSON_ASSERT(adjustment >= 0 && adjustment < 7);
|
||||
v = v * kPow10[adjustment];
|
||||
if (length + static_cast<unsigned>(adjustment)> 19u) // has more digits than decimal digits in 64-bit
|
||||
error += kUlp / 2;
|
||||
}
|
||||
|
||||
v = v * cachedPower;
|
||||
|
||||
error += kUlp + (error == 0 ? 0 : 1);
|
||||
|
||||
const int oldExp = v.e;
|
||||
v = v.Normalize();
|
||||
error <<= oldExp - v.e;
|
||||
|
||||
const unsigned effectiveSignificandSize = Double::EffectiveSignificandSize(64 + v.e);
|
||||
unsigned precisionSize = 64 - effectiveSignificandSize;
|
||||
if (precisionSize + kUlpShift >= 64) {
|
||||
unsigned scaleExp = (precisionSize + kUlpShift) - 63;
|
||||
v.f >>= scaleExp;
|
||||
v.e += scaleExp;
|
||||
error = (error >> scaleExp) + 1 + static_cast<int>(kUlp);
|
||||
precisionSize -= scaleExp;
|
||||
}
|
||||
|
||||
DiyFp rounded(v.f >> precisionSize, v.e + static_cast<int>(precisionSize));
|
||||
const uint64_t precisionBits = (v.f & ((uint64_t(1) << precisionSize) - 1)) * kUlp;
|
||||
const uint64_t halfWay = (uint64_t(1) << (precisionSize - 1)) * kUlp;
|
||||
if (precisionBits >= halfWay + static_cast<unsigned>(error)) {
|
||||
rounded.f++;
|
||||
if (rounded.f & (DiyFp::kDpHiddenBit << 1)) { // rounding overflows mantissa (issue #340)
|
||||
rounded.f >>= 1;
|
||||
rounded.e++;
|
||||
}
|
||||
}
|
||||
|
||||
*result = rounded.ToDouble();
|
||||
|
||||
return halfWay - static_cast<unsigned>(error) >= precisionBits || precisionBits >= halfWay + static_cast<unsigned>(error);
|
||||
}
|
||||
|
||||
inline double StrtodBigInteger(double approx, const char* decimals, size_t length, size_t decimalPosition, int exp) {
|
||||
const BigInteger dInt(decimals, length);
|
||||
const int dExp = static_cast<int>(decimalPosition) - static_cast<int>(length) + exp;
|
||||
Double a(approx);
|
||||
int cmp = CheckWithinHalfULP(a.Value(), dInt, dExp);
|
||||
if (cmp < 0)
|
||||
return a.Value(); // within half ULP
|
||||
else if (cmp == 0) {
|
||||
// Round towards even
|
||||
if (a.Significand() & 1)
|
||||
return a.NextPositiveDouble();
|
||||
else
|
||||
return a.Value();
|
||||
}
|
||||
else // adjustment
|
||||
return a.NextPositiveDouble();
|
||||
}
|
||||
|
||||
inline double StrtodFullPrecision(double d, int p, const char* decimals, size_t length, size_t decimalPosition, int exp) {
|
||||
RAPIDJSON_ASSERT(d >= 0.0);
|
||||
RAPIDJSON_ASSERT(length >= 1);
|
||||
|
||||
double result;
|
||||
if (StrtodFast(d, p, &result))
|
||||
return result;
|
||||
|
||||
// Trim leading zeros
|
||||
while (*decimals == '0' && length > 1) {
|
||||
length--;
|
||||
decimals++;
|
||||
decimalPosition--;
|
||||
}
|
||||
|
||||
// Trim trailing zeros
|
||||
while (decimals[length - 1] == '0' && length > 1) {
|
||||
length--;
|
||||
decimalPosition--;
|
||||
exp++;
|
||||
}
|
||||
|
||||
// Trim right-most digits
|
||||
const int kMaxDecimalDigit = 780;
|
||||
if (static_cast<int>(length) > kMaxDecimalDigit) {
|
||||
int delta = (static_cast<int>(length) - kMaxDecimalDigit);
|
||||
exp += delta;
|
||||
decimalPosition -= static_cast<unsigned>(delta);
|
||||
length = kMaxDecimalDigit;
|
||||
}
|
||||
|
||||
// If too small, underflow to zero
|
||||
if (int(length) + exp < -324)
|
||||
return 0.0;
|
||||
|
||||
if (StrtodDiyFp(decimals, length, decimalPosition, exp, &result))
|
||||
return result;
|
||||
|
||||
// Use approximation from StrtodDiyFp and make adjustment with BigInteger comparison
|
||||
return StrtodBigInteger(result, decimals, length, decimalPosition, exp);
|
||||
}
|
||||
|
||||
} // namespace internal
|
||||
RAPIDJSON_NAMESPACE_END
|
||||
|
||||
#endif // RAPIDJSON_STRTOD_
|
||||
46
src/3rdparty/rapidjson/internal/swap.h
vendored
Normal file
46
src/3rdparty/rapidjson/internal/swap.h
vendored
Normal file
@@ -0,0 +1,46 @@
|
||||
// Tencent is pleased to support the open source community by making RapidJSON available.
|
||||
//
|
||||
// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
|
||||
//
|
||||
// Licensed under the MIT License (the "License"); you may not use this file except
|
||||
// in compliance with the License. You may obtain a copy of the License at
|
||||
//
|
||||
// http://opensource.org/licenses/MIT
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software distributed
|
||||
// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
|
||||
// CONDITIONS OF ANY KIND, either express or implied. See the License for the
|
||||
// specific language governing permissions and limitations under the License.
|
||||
|
||||
#ifndef RAPIDJSON_INTERNAL_SWAP_H_
|
||||
#define RAPIDJSON_INTERNAL_SWAP_H_
|
||||
|
||||
#include "../rapidjson.h"
|
||||
|
||||
#if defined(__clang__)
|
||||
RAPIDJSON_DIAG_PUSH
|
||||
RAPIDJSON_DIAG_OFF(c++98-compat)
|
||||
#endif
|
||||
|
||||
RAPIDJSON_NAMESPACE_BEGIN
|
||||
namespace internal {
|
||||
|
||||
//! Custom swap() to avoid dependency on C++ <algorithm> header
|
||||
/*! \tparam T Type of the arguments to swap, should be instantiated with primitive C++ types only.
|
||||
\note This has the same semantics as std::swap().
|
||||
*/
|
||||
template <typename T>
|
||||
inline void Swap(T& a, T& b) RAPIDJSON_NOEXCEPT {
|
||||
T tmp = a;
|
||||
a = b;
|
||||
b = tmp;
|
||||
}
|
||||
|
||||
} // namespace internal
|
||||
RAPIDJSON_NAMESPACE_END
|
||||
|
||||
#if defined(__clang__)
|
||||
RAPIDJSON_DIAG_POP
|
||||
#endif
|
||||
|
||||
#endif // RAPIDJSON_INTERNAL_SWAP_H_
|
||||
115
src/3rdparty/rapidjson/istreamwrapper.h
vendored
Normal file
115
src/3rdparty/rapidjson/istreamwrapper.h
vendored
Normal file
@@ -0,0 +1,115 @@
|
||||
// Tencent is pleased to support the open source community by making RapidJSON available.
|
||||
//
|
||||
// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
|
||||
//
|
||||
// Licensed under the MIT License (the "License"); you may not use this file except
|
||||
// in compliance with the License. You may obtain a copy of the License at
|
||||
//
|
||||
// http://opensource.org/licenses/MIT
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software distributed
|
||||
// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
|
||||
// CONDITIONS OF ANY KIND, either express or implied. See the License for the
|
||||
// specific language governing permissions and limitations under the License.
|
||||
|
||||
#ifndef RAPIDJSON_ISTREAMWRAPPER_H_
|
||||
#define RAPIDJSON_ISTREAMWRAPPER_H_
|
||||
|
||||
#include "stream.h"
|
||||
#include <iosfwd>
|
||||
|
||||
#ifdef __clang__
|
||||
RAPIDJSON_DIAG_PUSH
|
||||
RAPIDJSON_DIAG_OFF(padded)
|
||||
#endif
|
||||
|
||||
#ifdef _MSC_VER
|
||||
RAPIDJSON_DIAG_PUSH
|
||||
RAPIDJSON_DIAG_OFF(4351) // new behavior: elements of array 'array' will be default initialized
|
||||
#endif
|
||||
|
||||
RAPIDJSON_NAMESPACE_BEGIN
|
||||
|
||||
//! Wrapper of \c std::basic_istream into RapidJSON's Stream concept.
|
||||
/*!
|
||||
The classes can be wrapped including but not limited to:
|
||||
|
||||
- \c std::istringstream
|
||||
- \c std::stringstream
|
||||
- \c std::wistringstream
|
||||
- \c std::wstringstream
|
||||
- \c std::ifstream
|
||||
- \c std::fstream
|
||||
- \c std::wifstream
|
||||
- \c std::wfstream
|
||||
|
||||
\tparam StreamType Class derived from \c std::basic_istream.
|
||||
*/
|
||||
|
||||
template <typename StreamType>
|
||||
class BasicIStreamWrapper {
|
||||
public:
|
||||
typedef typename StreamType::char_type Ch;
|
||||
BasicIStreamWrapper(StreamType& stream) : stream_(stream), count_(), peekBuffer_() {}
|
||||
|
||||
Ch Peek() const {
|
||||
typename StreamType::int_type c = stream_.peek();
|
||||
return RAPIDJSON_LIKELY(c != StreamType::traits_type::eof()) ? static_cast<Ch>(c) : '\0';
|
||||
}
|
||||
|
||||
Ch Take() {
|
||||
typename StreamType::int_type c = stream_.get();
|
||||
if (RAPIDJSON_LIKELY(c != StreamType::traits_type::eof())) {
|
||||
count_++;
|
||||
return static_cast<Ch>(c);
|
||||
}
|
||||
else
|
||||
return '\0';
|
||||
}
|
||||
|
||||
// tellg() may return -1 when failed. So we count by ourself.
|
||||
size_t Tell() const { return count_; }
|
||||
|
||||
Ch* PutBegin() { RAPIDJSON_ASSERT(false); return 0; }
|
||||
void Put(Ch) { RAPIDJSON_ASSERT(false); }
|
||||
void Flush() { RAPIDJSON_ASSERT(false); }
|
||||
size_t PutEnd(Ch*) { RAPIDJSON_ASSERT(false); return 0; }
|
||||
|
||||
// For encoding detection only.
|
||||
const Ch* Peek4() const {
|
||||
RAPIDJSON_ASSERT(sizeof(Ch) == 1); // Only usable for byte stream.
|
||||
int i;
|
||||
bool hasError = false;
|
||||
for (i = 0; i < 4; ++i) {
|
||||
typename StreamType::int_type c = stream_.get();
|
||||
if (c == StreamType::traits_type::eof()) {
|
||||
hasError = true;
|
||||
stream_.clear();
|
||||
break;
|
||||
}
|
||||
peekBuffer_[i] = static_cast<Ch>(c);
|
||||
}
|
||||
for (--i; i >= 0; --i)
|
||||
stream_.putback(peekBuffer_[i]);
|
||||
return !hasError ? peekBuffer_ : 0;
|
||||
}
|
||||
|
||||
private:
|
||||
BasicIStreamWrapper(const BasicIStreamWrapper&);
|
||||
BasicIStreamWrapper& operator=(const BasicIStreamWrapper&);
|
||||
|
||||
StreamType& stream_;
|
||||
size_t count_; //!< Number of characters read. Note:
|
||||
mutable Ch peekBuffer_[4];
|
||||
};
|
||||
|
||||
typedef BasicIStreamWrapper<std::istream> IStreamWrapper;
|
||||
typedef BasicIStreamWrapper<std::wistream> WIStreamWrapper;
|
||||
|
||||
#if defined(__clang__) || defined(_MSC_VER)
|
||||
RAPIDJSON_DIAG_POP
|
||||
#endif
|
||||
|
||||
RAPIDJSON_NAMESPACE_END
|
||||
|
||||
#endif // RAPIDJSON_ISTREAMWRAPPER_H_
|
||||
70
src/3rdparty/rapidjson/memorybuffer.h
vendored
Normal file
70
src/3rdparty/rapidjson/memorybuffer.h
vendored
Normal file
@@ -0,0 +1,70 @@
|
||||
// Tencent is pleased to support the open source community by making RapidJSON available.
|
||||
//
|
||||
// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
|
||||
//
|
||||
// Licensed under the MIT License (the "License"); you may not use this file except
|
||||
// in compliance with the License. You may obtain a copy of the License at
|
||||
//
|
||||
// http://opensource.org/licenses/MIT
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software distributed
|
||||
// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
|
||||
// CONDITIONS OF ANY KIND, either express or implied. See the License for the
|
||||
// specific language governing permissions and limitations under the License.
|
||||
|
||||
#ifndef RAPIDJSON_MEMORYBUFFER_H_
|
||||
#define RAPIDJSON_MEMORYBUFFER_H_
|
||||
|
||||
#include "stream.h"
|
||||
#include "internal/stack.h"
|
||||
|
||||
RAPIDJSON_NAMESPACE_BEGIN
|
||||
|
||||
//! Represents an in-memory output byte stream.
|
||||
/*!
|
||||
This class is mainly for being wrapped by EncodedOutputStream or AutoUTFOutputStream.
|
||||
|
||||
It is similar to FileWriteBuffer but the destination is an in-memory buffer instead of a file.
|
||||
|
||||
Differences between MemoryBuffer and StringBuffer:
|
||||
1. StringBuffer has Encoding but MemoryBuffer is only a byte buffer.
|
||||
2. StringBuffer::GetString() returns a null-terminated string. MemoryBuffer::GetBuffer() returns a buffer without terminator.
|
||||
|
||||
\tparam Allocator type for allocating memory buffer.
|
||||
\note implements Stream concept
|
||||
*/
|
||||
template <typename Allocator = CrtAllocator>
|
||||
struct GenericMemoryBuffer {
|
||||
typedef char Ch; // byte
|
||||
|
||||
GenericMemoryBuffer(Allocator* allocator = 0, size_t capacity = kDefaultCapacity) : stack_(allocator, capacity) {}
|
||||
|
||||
void Put(Ch c) { *stack_.template Push<Ch>() = c; }
|
||||
void Flush() {}
|
||||
|
||||
void Clear() { stack_.Clear(); }
|
||||
void ShrinkToFit() { stack_.ShrinkToFit(); }
|
||||
Ch* Push(size_t count) { return stack_.template Push<Ch>(count); }
|
||||
void Pop(size_t count) { stack_.template Pop<Ch>(count); }
|
||||
|
||||
const Ch* GetBuffer() const {
|
||||
return stack_.template Bottom<Ch>();
|
||||
}
|
||||
|
||||
size_t GetSize() const { return stack_.GetSize(); }
|
||||
|
||||
static const size_t kDefaultCapacity = 256;
|
||||
mutable internal::Stack<Allocator> stack_;
|
||||
};
|
||||
|
||||
typedef GenericMemoryBuffer<> MemoryBuffer;
|
||||
|
||||
//! Implement specialized version of PutN() with memset() for better performance.
|
||||
template<>
|
||||
inline void PutN(MemoryBuffer& memoryBuffer, char c, size_t n) {
|
||||
std::memset(memoryBuffer.stack_.Push<char>(n), c, n * sizeof(c));
|
||||
}
|
||||
|
||||
RAPIDJSON_NAMESPACE_END
|
||||
|
||||
#endif // RAPIDJSON_MEMORYBUFFER_H_
|
||||
71
src/3rdparty/rapidjson/memorystream.h
vendored
Normal file
71
src/3rdparty/rapidjson/memorystream.h
vendored
Normal file
@@ -0,0 +1,71 @@
|
||||
// Tencent is pleased to support the open source community by making RapidJSON available.
|
||||
//
|
||||
// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
|
||||
//
|
||||
// Licensed under the MIT License (the "License"); you may not use this file except
|
||||
// in compliance with the License. You may obtain a copy of the License at
|
||||
//
|
||||
// http://opensource.org/licenses/MIT
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software distributed
|
||||
// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
|
||||
// CONDITIONS OF ANY KIND, either express or implied. See the License for the
|
||||
// specific language governing permissions and limitations under the License.
|
||||
|
||||
#ifndef RAPIDJSON_MEMORYSTREAM_H_
|
||||
#define RAPIDJSON_MEMORYSTREAM_H_
|
||||
|
||||
#include "stream.h"
|
||||
|
||||
#ifdef __clang__
|
||||
RAPIDJSON_DIAG_PUSH
|
||||
RAPIDJSON_DIAG_OFF(unreachable-code)
|
||||
RAPIDJSON_DIAG_OFF(missing-noreturn)
|
||||
#endif
|
||||
|
||||
RAPIDJSON_NAMESPACE_BEGIN
|
||||
|
||||
//! Represents an in-memory input byte stream.
|
||||
/*!
|
||||
This class is mainly for being wrapped by EncodedInputStream or AutoUTFInputStream.
|
||||
|
||||
It is similar to FileReadBuffer but the source is an in-memory buffer instead of a file.
|
||||
|
||||
Differences between MemoryStream and StringStream:
|
||||
1. StringStream has encoding but MemoryStream is a byte stream.
|
||||
2. MemoryStream needs size of the source buffer and the buffer don't need to be null terminated. StringStream assume null-terminated string as source.
|
||||
3. MemoryStream supports Peek4() for encoding detection. StringStream is specified with an encoding so it should not have Peek4().
|
||||
\note implements Stream concept
|
||||
*/
|
||||
struct MemoryStream {
|
||||
typedef char Ch; // byte
|
||||
|
||||
MemoryStream(const Ch *src, size_t size) : src_(src), begin_(src), end_(src + size), size_(size) {}
|
||||
|
||||
Ch Peek() const { return RAPIDJSON_UNLIKELY(src_ == end_) ? '\0' : *src_; }
|
||||
Ch Take() { return RAPIDJSON_UNLIKELY(src_ == end_) ? '\0' : *src_++; }
|
||||
size_t Tell() const { return static_cast<size_t>(src_ - begin_); }
|
||||
|
||||
Ch* PutBegin() { RAPIDJSON_ASSERT(false); return 0; }
|
||||
void Put(Ch) { RAPIDJSON_ASSERT(false); }
|
||||
void Flush() { RAPIDJSON_ASSERT(false); }
|
||||
size_t PutEnd(Ch*) { RAPIDJSON_ASSERT(false); return 0; }
|
||||
|
||||
// For encoding detection only.
|
||||
const Ch* Peek4() const {
|
||||
return Tell() + 4 <= size_ ? src_ : 0;
|
||||
}
|
||||
|
||||
const Ch* src_; //!< Current read position.
|
||||
const Ch* begin_; //!< Original head of the string.
|
||||
const Ch* end_; //!< End of stream.
|
||||
size_t size_; //!< Size of the stream.
|
||||
};
|
||||
|
||||
RAPIDJSON_NAMESPACE_END
|
||||
|
||||
#ifdef __clang__
|
||||
RAPIDJSON_DIAG_POP
|
||||
#endif
|
||||
|
||||
#endif // RAPIDJSON_MEMORYBUFFER_H_
|
||||
316
src/3rdparty/rapidjson/msinttypes/inttypes.h
vendored
Normal file
316
src/3rdparty/rapidjson/msinttypes/inttypes.h
vendored
Normal file
@@ -0,0 +1,316 @@
|
||||
// ISO C9x compliant inttypes.h for Microsoft Visual Studio
|
||||
// Based on ISO/IEC 9899:TC2 Committee draft (May 6, 2005) WG14/N1124
|
||||
//
|
||||
// Copyright (c) 2006-2013 Alexander Chemeris
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// 3. Neither the name of the product nor the names of its contributors may
|
||||
// be used to endorse or promote products derived from this software
|
||||
// without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
|
||||
// EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
|
||||
// OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
||||
// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// The above software in this distribution may have been modified by
|
||||
// THL A29 Limited ("Tencent Modifications").
|
||||
// All Tencent Modifications are Copyright (C) 2015 THL A29 Limited.
|
||||
|
||||
#ifndef _MSC_VER // [
|
||||
#error "Use this header only with Microsoft Visual C++ compilers!"
|
||||
#endif // _MSC_VER ]
|
||||
|
||||
#ifndef _MSC_INTTYPES_H_ // [
|
||||
#define _MSC_INTTYPES_H_
|
||||
|
||||
#if _MSC_VER > 1000
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#include "stdint.h"
|
||||
|
||||
// miloyip: VC supports inttypes.h since VC2013
|
||||
#if _MSC_VER >= 1800
|
||||
#include <inttypes.h>
|
||||
#else
|
||||
|
||||
// 7.8 Format conversion of integer types
|
||||
|
||||
typedef struct {
|
||||
intmax_t quot;
|
||||
intmax_t rem;
|
||||
} imaxdiv_t;
|
||||
|
||||
// 7.8.1 Macros for format specifiers
|
||||
|
||||
#if !defined(__cplusplus) || defined(__STDC_FORMAT_MACROS) // [ See footnote 185 at page 198
|
||||
|
||||
// The fprintf macros for signed integers are:
|
||||
#define PRId8 "d"
|
||||
#define PRIi8 "i"
|
||||
#define PRIdLEAST8 "d"
|
||||
#define PRIiLEAST8 "i"
|
||||
#define PRIdFAST8 "d"
|
||||
#define PRIiFAST8 "i"
|
||||
|
||||
#define PRId16 "hd"
|
||||
#define PRIi16 "hi"
|
||||
#define PRIdLEAST16 "hd"
|
||||
#define PRIiLEAST16 "hi"
|
||||
#define PRIdFAST16 "hd"
|
||||
#define PRIiFAST16 "hi"
|
||||
|
||||
#define PRId32 "I32d"
|
||||
#define PRIi32 "I32i"
|
||||
#define PRIdLEAST32 "I32d"
|
||||
#define PRIiLEAST32 "I32i"
|
||||
#define PRIdFAST32 "I32d"
|
||||
#define PRIiFAST32 "I32i"
|
||||
|
||||
#define PRId64 "I64d"
|
||||
#define PRIi64 "I64i"
|
||||
#define PRIdLEAST64 "I64d"
|
||||
#define PRIiLEAST64 "I64i"
|
||||
#define PRIdFAST64 "I64d"
|
||||
#define PRIiFAST64 "I64i"
|
||||
|
||||
#define PRIdMAX "I64d"
|
||||
#define PRIiMAX "I64i"
|
||||
|
||||
#define PRIdPTR "Id"
|
||||
#define PRIiPTR "Ii"
|
||||
|
||||
// The fprintf macros for unsigned integers are:
|
||||
#define PRIo8 "o"
|
||||
#define PRIu8 "u"
|
||||
#define PRIx8 "x"
|
||||
#define PRIX8 "X"
|
||||
#define PRIoLEAST8 "o"
|
||||
#define PRIuLEAST8 "u"
|
||||
#define PRIxLEAST8 "x"
|
||||
#define PRIXLEAST8 "X"
|
||||
#define PRIoFAST8 "o"
|
||||
#define PRIuFAST8 "u"
|
||||
#define PRIxFAST8 "x"
|
||||
#define PRIXFAST8 "X"
|
||||
|
||||
#define PRIo16 "ho"
|
||||
#define PRIu16 "hu"
|
||||
#define PRIx16 "hx"
|
||||
#define PRIX16 "hX"
|
||||
#define PRIoLEAST16 "ho"
|
||||
#define PRIuLEAST16 "hu"
|
||||
#define PRIxLEAST16 "hx"
|
||||
#define PRIXLEAST16 "hX"
|
||||
#define PRIoFAST16 "ho"
|
||||
#define PRIuFAST16 "hu"
|
||||
#define PRIxFAST16 "hx"
|
||||
#define PRIXFAST16 "hX"
|
||||
|
||||
#define PRIo32 "I32o"
|
||||
#define PRIu32 "I32u"
|
||||
#define PRIx32 "I32x"
|
||||
#define PRIX32 "I32X"
|
||||
#define PRIoLEAST32 "I32o"
|
||||
#define PRIuLEAST32 "I32u"
|
||||
#define PRIxLEAST32 "I32x"
|
||||
#define PRIXLEAST32 "I32X"
|
||||
#define PRIoFAST32 "I32o"
|
||||
#define PRIuFAST32 "I32u"
|
||||
#define PRIxFAST32 "I32x"
|
||||
#define PRIXFAST32 "I32X"
|
||||
|
||||
#define PRIo64 "I64o"
|
||||
#define PRIu64 "I64u"
|
||||
#define PRIx64 "I64x"
|
||||
#define PRIX64 "I64X"
|
||||
#define PRIoLEAST64 "I64o"
|
||||
#define PRIuLEAST64 "I64u"
|
||||
#define PRIxLEAST64 "I64x"
|
||||
#define PRIXLEAST64 "I64X"
|
||||
#define PRIoFAST64 "I64o"
|
||||
#define PRIuFAST64 "I64u"
|
||||
#define PRIxFAST64 "I64x"
|
||||
#define PRIXFAST64 "I64X"
|
||||
|
||||
#define PRIoMAX "I64o"
|
||||
#define PRIuMAX "I64u"
|
||||
#define PRIxMAX "I64x"
|
||||
#define PRIXMAX "I64X"
|
||||
|
||||
#define PRIoPTR "Io"
|
||||
#define PRIuPTR "Iu"
|
||||
#define PRIxPTR "Ix"
|
||||
#define PRIXPTR "IX"
|
||||
|
||||
// The fscanf macros for signed integers are:
|
||||
#define SCNd8 "d"
|
||||
#define SCNi8 "i"
|
||||
#define SCNdLEAST8 "d"
|
||||
#define SCNiLEAST8 "i"
|
||||
#define SCNdFAST8 "d"
|
||||
#define SCNiFAST8 "i"
|
||||
|
||||
#define SCNd16 "hd"
|
||||
#define SCNi16 "hi"
|
||||
#define SCNdLEAST16 "hd"
|
||||
#define SCNiLEAST16 "hi"
|
||||
#define SCNdFAST16 "hd"
|
||||
#define SCNiFAST16 "hi"
|
||||
|
||||
#define SCNd32 "ld"
|
||||
#define SCNi32 "li"
|
||||
#define SCNdLEAST32 "ld"
|
||||
#define SCNiLEAST32 "li"
|
||||
#define SCNdFAST32 "ld"
|
||||
#define SCNiFAST32 "li"
|
||||
|
||||
#define SCNd64 "I64d"
|
||||
#define SCNi64 "I64i"
|
||||
#define SCNdLEAST64 "I64d"
|
||||
#define SCNiLEAST64 "I64i"
|
||||
#define SCNdFAST64 "I64d"
|
||||
#define SCNiFAST64 "I64i"
|
||||
|
||||
#define SCNdMAX "I64d"
|
||||
#define SCNiMAX "I64i"
|
||||
|
||||
#ifdef _WIN64 // [
|
||||
# define SCNdPTR "I64d"
|
||||
# define SCNiPTR "I64i"
|
||||
#else // _WIN64 ][
|
||||
# define SCNdPTR "ld"
|
||||
# define SCNiPTR "li"
|
||||
#endif // _WIN64 ]
|
||||
|
||||
// The fscanf macros for unsigned integers are:
|
||||
#define SCNo8 "o"
|
||||
#define SCNu8 "u"
|
||||
#define SCNx8 "x"
|
||||
#define SCNX8 "X"
|
||||
#define SCNoLEAST8 "o"
|
||||
#define SCNuLEAST8 "u"
|
||||
#define SCNxLEAST8 "x"
|
||||
#define SCNXLEAST8 "X"
|
||||
#define SCNoFAST8 "o"
|
||||
#define SCNuFAST8 "u"
|
||||
#define SCNxFAST8 "x"
|
||||
#define SCNXFAST8 "X"
|
||||
|
||||
#define SCNo16 "ho"
|
||||
#define SCNu16 "hu"
|
||||
#define SCNx16 "hx"
|
||||
#define SCNX16 "hX"
|
||||
#define SCNoLEAST16 "ho"
|
||||
#define SCNuLEAST16 "hu"
|
||||
#define SCNxLEAST16 "hx"
|
||||
#define SCNXLEAST16 "hX"
|
||||
#define SCNoFAST16 "ho"
|
||||
#define SCNuFAST16 "hu"
|
||||
#define SCNxFAST16 "hx"
|
||||
#define SCNXFAST16 "hX"
|
||||
|
||||
#define SCNo32 "lo"
|
||||
#define SCNu32 "lu"
|
||||
#define SCNx32 "lx"
|
||||
#define SCNX32 "lX"
|
||||
#define SCNoLEAST32 "lo"
|
||||
#define SCNuLEAST32 "lu"
|
||||
#define SCNxLEAST32 "lx"
|
||||
#define SCNXLEAST32 "lX"
|
||||
#define SCNoFAST32 "lo"
|
||||
#define SCNuFAST32 "lu"
|
||||
#define SCNxFAST32 "lx"
|
||||
#define SCNXFAST32 "lX"
|
||||
|
||||
#define SCNo64 "I64o"
|
||||
#define SCNu64 "I64u"
|
||||
#define SCNx64 "I64x"
|
||||
#define SCNX64 "I64X"
|
||||
#define SCNoLEAST64 "I64o"
|
||||
#define SCNuLEAST64 "I64u"
|
||||
#define SCNxLEAST64 "I64x"
|
||||
#define SCNXLEAST64 "I64X"
|
||||
#define SCNoFAST64 "I64o"
|
||||
#define SCNuFAST64 "I64u"
|
||||
#define SCNxFAST64 "I64x"
|
||||
#define SCNXFAST64 "I64X"
|
||||
|
||||
#define SCNoMAX "I64o"
|
||||
#define SCNuMAX "I64u"
|
||||
#define SCNxMAX "I64x"
|
||||
#define SCNXMAX "I64X"
|
||||
|
||||
#ifdef _WIN64 // [
|
||||
# define SCNoPTR "I64o"
|
||||
# define SCNuPTR "I64u"
|
||||
# define SCNxPTR "I64x"
|
||||
# define SCNXPTR "I64X"
|
||||
#else // _WIN64 ][
|
||||
# define SCNoPTR "lo"
|
||||
# define SCNuPTR "lu"
|
||||
# define SCNxPTR "lx"
|
||||
# define SCNXPTR "lX"
|
||||
#endif // _WIN64 ]
|
||||
|
||||
#endif // __STDC_FORMAT_MACROS ]
|
||||
|
||||
// 7.8.2 Functions for greatest-width integer types
|
||||
|
||||
// 7.8.2.1 The imaxabs function
|
||||
#define imaxabs _abs64
|
||||
|
||||
// 7.8.2.2 The imaxdiv function
|
||||
|
||||
// This is modified version of div() function from Microsoft's div.c found
|
||||
// in %MSVC.NET%\crt\src\div.c
|
||||
#ifdef STATIC_IMAXDIV // [
|
||||
static
|
||||
#else // STATIC_IMAXDIV ][
|
||||
_inline
|
||||
#endif // STATIC_IMAXDIV ]
|
||||
imaxdiv_t __cdecl imaxdiv(intmax_t numer, intmax_t denom)
|
||||
{
|
||||
imaxdiv_t result;
|
||||
|
||||
result.quot = numer / denom;
|
||||
result.rem = numer % denom;
|
||||
|
||||
if (numer < 0 && result.rem > 0) {
|
||||
// did division wrong; must fix up
|
||||
++result.quot;
|
||||
result.rem -= denom;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
// 7.8.2.3 The strtoimax and strtoumax functions
|
||||
#define strtoimax _strtoi64
|
||||
#define strtoumax _strtoui64
|
||||
|
||||
// 7.8.2.4 The wcstoimax and wcstoumax functions
|
||||
#define wcstoimax _wcstoi64
|
||||
#define wcstoumax _wcstoui64
|
||||
|
||||
#endif // _MSC_VER >= 1800
|
||||
|
||||
#endif // _MSC_INTTYPES_H_ ]
|
||||
300
src/3rdparty/rapidjson/msinttypes/stdint.h
vendored
Normal file
300
src/3rdparty/rapidjson/msinttypes/stdint.h
vendored
Normal file
@@ -0,0 +1,300 @@
|
||||
// ISO C9x compliant stdint.h for Microsoft Visual Studio
|
||||
// Based on ISO/IEC 9899:TC2 Committee draft (May 6, 2005) WG14/N1124
|
||||
//
|
||||
// Copyright (c) 2006-2013 Alexander Chemeris
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// 3. Neither the name of the product nor the names of its contributors may
|
||||
// be used to endorse or promote products derived from this software
|
||||
// without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
|
||||
// EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
|
||||
// OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
||||
// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// The above software in this distribution may have been modified by
|
||||
// THL A29 Limited ("Tencent Modifications").
|
||||
// All Tencent Modifications are Copyright (C) 2015 THL A29 Limited.
|
||||
|
||||
#ifndef _MSC_VER // [
|
||||
#error "Use this header only with Microsoft Visual C++ compilers!"
|
||||
#endif // _MSC_VER ]
|
||||
|
||||
#ifndef _MSC_STDINT_H_ // [
|
||||
#define _MSC_STDINT_H_
|
||||
|
||||
#if _MSC_VER > 1000
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
// miloyip: Originally Visual Studio 2010 uses its own stdint.h. However it generates warning with INT64_C(), so change to use this file for vs2010.
|
||||
#if _MSC_VER >= 1600 // [
|
||||
#include <stdint.h>
|
||||
|
||||
#if !defined(__cplusplus) || defined(__STDC_CONSTANT_MACROS) // [ See footnote 224 at page 260
|
||||
|
||||
#undef INT8_C
|
||||
#undef INT16_C
|
||||
#undef INT32_C
|
||||
#undef INT64_C
|
||||
#undef UINT8_C
|
||||
#undef UINT16_C
|
||||
#undef UINT32_C
|
||||
#undef UINT64_C
|
||||
|
||||
// 7.18.4.1 Macros for minimum-width integer constants
|
||||
|
||||
#define INT8_C(val) val##i8
|
||||
#define INT16_C(val) val##i16
|
||||
#define INT32_C(val) val##i32
|
||||
#define INT64_C(val) val##i64
|
||||
|
||||
#define UINT8_C(val) val##ui8
|
||||
#define UINT16_C(val) val##ui16
|
||||
#define UINT32_C(val) val##ui32
|
||||
#define UINT64_C(val) val##ui64
|
||||
|
||||
// 7.18.4.2 Macros for greatest-width integer constants
|
||||
// These #ifndef's are needed to prevent collisions with <boost/cstdint.hpp>.
|
||||
// Check out Issue 9 for the details.
|
||||
#ifndef INTMAX_C // [
|
||||
# define INTMAX_C INT64_C
|
||||
#endif // INTMAX_C ]
|
||||
#ifndef UINTMAX_C // [
|
||||
# define UINTMAX_C UINT64_C
|
||||
#endif // UINTMAX_C ]
|
||||
|
||||
#endif // __STDC_CONSTANT_MACROS ]
|
||||
|
||||
#else // ] _MSC_VER >= 1700 [
|
||||
|
||||
#include <limits.h>
|
||||
|
||||
// For Visual Studio 6 in C++ mode and for many Visual Studio versions when
|
||||
// compiling for ARM we have to wrap <wchar.h> include with 'extern "C++" {}'
|
||||
// or compiler would give many errors like this:
|
||||
// error C2733: second C linkage of overloaded function 'wmemchr' not allowed
|
||||
#if defined(__cplusplus) && !defined(_M_ARM)
|
||||
extern "C" {
|
||||
#endif
|
||||
# include <wchar.h>
|
||||
#if defined(__cplusplus) && !defined(_M_ARM)
|
||||
}
|
||||
#endif
|
||||
|
||||
// Define _W64 macros to mark types changing their size, like intptr_t.
|
||||
#ifndef _W64
|
||||
# if !defined(__midl) && (defined(_X86_) || defined(_M_IX86)) && _MSC_VER >= 1300
|
||||
# define _W64 __w64
|
||||
# else
|
||||
# define _W64
|
||||
# endif
|
||||
#endif
|
||||
|
||||
|
||||
// 7.18.1 Integer types
|
||||
|
||||
// 7.18.1.1 Exact-width integer types
|
||||
|
||||
// Visual Studio 6 and Embedded Visual C++ 4 doesn't
|
||||
// realize that, e.g. char has the same size as __int8
|
||||
// so we give up on __intX for them.
|
||||
#if (_MSC_VER < 1300)
|
||||
typedef signed char int8_t;
|
||||
typedef signed short int16_t;
|
||||
typedef signed int int32_t;
|
||||
typedef unsigned char uint8_t;
|
||||
typedef unsigned short uint16_t;
|
||||
typedef unsigned int uint32_t;
|
||||
#else
|
||||
typedef signed __int8 int8_t;
|
||||
typedef signed __int16 int16_t;
|
||||
typedef signed __int32 int32_t;
|
||||
typedef unsigned __int8 uint8_t;
|
||||
typedef unsigned __int16 uint16_t;
|
||||
typedef unsigned __int32 uint32_t;
|
||||
#endif
|
||||
typedef signed __int64 int64_t;
|
||||
typedef unsigned __int64 uint64_t;
|
||||
|
||||
|
||||
// 7.18.1.2 Minimum-width integer types
|
||||
typedef int8_t int_least8_t;
|
||||
typedef int16_t int_least16_t;
|
||||
typedef int32_t int_least32_t;
|
||||
typedef int64_t int_least64_t;
|
||||
typedef uint8_t uint_least8_t;
|
||||
typedef uint16_t uint_least16_t;
|
||||
typedef uint32_t uint_least32_t;
|
||||
typedef uint64_t uint_least64_t;
|
||||
|
||||
// 7.18.1.3 Fastest minimum-width integer types
|
||||
typedef int8_t int_fast8_t;
|
||||
typedef int16_t int_fast16_t;
|
||||
typedef int32_t int_fast32_t;
|
||||
typedef int64_t int_fast64_t;
|
||||
typedef uint8_t uint_fast8_t;
|
||||
typedef uint16_t uint_fast16_t;
|
||||
typedef uint32_t uint_fast32_t;
|
||||
typedef uint64_t uint_fast64_t;
|
||||
|
||||
// 7.18.1.4 Integer types capable of holding object pointers
|
||||
#ifdef _WIN64 // [
|
||||
typedef signed __int64 intptr_t;
|
||||
typedef unsigned __int64 uintptr_t;
|
||||
#else // _WIN64 ][
|
||||
typedef _W64 signed int intptr_t;
|
||||
typedef _W64 unsigned int uintptr_t;
|
||||
#endif // _WIN64 ]
|
||||
|
||||
// 7.18.1.5 Greatest-width integer types
|
||||
typedef int64_t intmax_t;
|
||||
typedef uint64_t uintmax_t;
|
||||
|
||||
|
||||
// 7.18.2 Limits of specified-width integer types
|
||||
|
||||
#if !defined(__cplusplus) || defined(__STDC_LIMIT_MACROS) // [ See footnote 220 at page 257 and footnote 221 at page 259
|
||||
|
||||
// 7.18.2.1 Limits of exact-width integer types
|
||||
#define INT8_MIN ((int8_t)_I8_MIN)
|
||||
#define INT8_MAX _I8_MAX
|
||||
#define INT16_MIN ((int16_t)_I16_MIN)
|
||||
#define INT16_MAX _I16_MAX
|
||||
#define INT32_MIN ((int32_t)_I32_MIN)
|
||||
#define INT32_MAX _I32_MAX
|
||||
#define INT64_MIN ((int64_t)_I64_MIN)
|
||||
#define INT64_MAX _I64_MAX
|
||||
#define UINT8_MAX _UI8_MAX
|
||||
#define UINT16_MAX _UI16_MAX
|
||||
#define UINT32_MAX _UI32_MAX
|
||||
#define UINT64_MAX _UI64_MAX
|
||||
|
||||
// 7.18.2.2 Limits of minimum-width integer types
|
||||
#define INT_LEAST8_MIN INT8_MIN
|
||||
#define INT_LEAST8_MAX INT8_MAX
|
||||
#define INT_LEAST16_MIN INT16_MIN
|
||||
#define INT_LEAST16_MAX INT16_MAX
|
||||
#define INT_LEAST32_MIN INT32_MIN
|
||||
#define INT_LEAST32_MAX INT32_MAX
|
||||
#define INT_LEAST64_MIN INT64_MIN
|
||||
#define INT_LEAST64_MAX INT64_MAX
|
||||
#define UINT_LEAST8_MAX UINT8_MAX
|
||||
#define UINT_LEAST16_MAX UINT16_MAX
|
||||
#define UINT_LEAST32_MAX UINT32_MAX
|
||||
#define UINT_LEAST64_MAX UINT64_MAX
|
||||
|
||||
// 7.18.2.3 Limits of fastest minimum-width integer types
|
||||
#define INT_FAST8_MIN INT8_MIN
|
||||
#define INT_FAST8_MAX INT8_MAX
|
||||
#define INT_FAST16_MIN INT16_MIN
|
||||
#define INT_FAST16_MAX INT16_MAX
|
||||
#define INT_FAST32_MIN INT32_MIN
|
||||
#define INT_FAST32_MAX INT32_MAX
|
||||
#define INT_FAST64_MIN INT64_MIN
|
||||
#define INT_FAST64_MAX INT64_MAX
|
||||
#define UINT_FAST8_MAX UINT8_MAX
|
||||
#define UINT_FAST16_MAX UINT16_MAX
|
||||
#define UINT_FAST32_MAX UINT32_MAX
|
||||
#define UINT_FAST64_MAX UINT64_MAX
|
||||
|
||||
// 7.18.2.4 Limits of integer types capable of holding object pointers
|
||||
#ifdef _WIN64 // [
|
||||
# define INTPTR_MIN INT64_MIN
|
||||
# define INTPTR_MAX INT64_MAX
|
||||
# define UINTPTR_MAX UINT64_MAX
|
||||
#else // _WIN64 ][
|
||||
# define INTPTR_MIN INT32_MIN
|
||||
# define INTPTR_MAX INT32_MAX
|
||||
# define UINTPTR_MAX UINT32_MAX
|
||||
#endif // _WIN64 ]
|
||||
|
||||
// 7.18.2.5 Limits of greatest-width integer types
|
||||
#define INTMAX_MIN INT64_MIN
|
||||
#define INTMAX_MAX INT64_MAX
|
||||
#define UINTMAX_MAX UINT64_MAX
|
||||
|
||||
// 7.18.3 Limits of other integer types
|
||||
|
||||
#ifdef _WIN64 // [
|
||||
# define PTRDIFF_MIN _I64_MIN
|
||||
# define PTRDIFF_MAX _I64_MAX
|
||||
#else // _WIN64 ][
|
||||
# define PTRDIFF_MIN _I32_MIN
|
||||
# define PTRDIFF_MAX _I32_MAX
|
||||
#endif // _WIN64 ]
|
||||
|
||||
#define SIG_ATOMIC_MIN INT_MIN
|
||||
#define SIG_ATOMIC_MAX INT_MAX
|
||||
|
||||
#ifndef SIZE_MAX // [
|
||||
# ifdef _WIN64 // [
|
||||
# define SIZE_MAX _UI64_MAX
|
||||
# else // _WIN64 ][
|
||||
# define SIZE_MAX _UI32_MAX
|
||||
# endif // _WIN64 ]
|
||||
#endif // SIZE_MAX ]
|
||||
|
||||
// WCHAR_MIN and WCHAR_MAX are also defined in <wchar.h>
|
||||
#ifndef WCHAR_MIN // [
|
||||
# define WCHAR_MIN 0
|
||||
#endif // WCHAR_MIN ]
|
||||
#ifndef WCHAR_MAX // [
|
||||
# define WCHAR_MAX _UI16_MAX
|
||||
#endif // WCHAR_MAX ]
|
||||
|
||||
#define WINT_MIN 0
|
||||
#define WINT_MAX _UI16_MAX
|
||||
|
||||
#endif // __STDC_LIMIT_MACROS ]
|
||||
|
||||
|
||||
// 7.18.4 Limits of other integer types
|
||||
|
||||
#if !defined(__cplusplus) || defined(__STDC_CONSTANT_MACROS) // [ See footnote 224 at page 260
|
||||
|
||||
// 7.18.4.1 Macros for minimum-width integer constants
|
||||
|
||||
#define INT8_C(val) val##i8
|
||||
#define INT16_C(val) val##i16
|
||||
#define INT32_C(val) val##i32
|
||||
#define INT64_C(val) val##i64
|
||||
|
||||
#define UINT8_C(val) val##ui8
|
||||
#define UINT16_C(val) val##ui16
|
||||
#define UINT32_C(val) val##ui32
|
||||
#define UINT64_C(val) val##ui64
|
||||
|
||||
// 7.18.4.2 Macros for greatest-width integer constants
|
||||
// These #ifndef's are needed to prevent collisions with <boost/cstdint.hpp>.
|
||||
// Check out Issue 9 for the details.
|
||||
#ifndef INTMAX_C // [
|
||||
# define INTMAX_C INT64_C
|
||||
#endif // INTMAX_C ]
|
||||
#ifndef UINTMAX_C // [
|
||||
# define UINTMAX_C UINT64_C
|
||||
#endif // UINTMAX_C ]
|
||||
|
||||
#endif // __STDC_CONSTANT_MACROS ]
|
||||
|
||||
#endif // _MSC_VER >= 1600 ]
|
||||
|
||||
#endif // _MSC_STDINT_H_ ]
|
||||
81
src/3rdparty/rapidjson/ostreamwrapper.h
vendored
Normal file
81
src/3rdparty/rapidjson/ostreamwrapper.h
vendored
Normal file
@@ -0,0 +1,81 @@
|
||||
// Tencent is pleased to support the open source community by making RapidJSON available.
|
||||
//
|
||||
// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
|
||||
//
|
||||
// Licensed under the MIT License (the "License"); you may not use this file except
|
||||
// in compliance with the License. You may obtain a copy of the License at
|
||||
//
|
||||
// http://opensource.org/licenses/MIT
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software distributed
|
||||
// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
|
||||
// CONDITIONS OF ANY KIND, either express or implied. See the License for the
|
||||
// specific language governing permissions and limitations under the License.
|
||||
|
||||
#ifndef RAPIDJSON_OSTREAMWRAPPER_H_
|
||||
#define RAPIDJSON_OSTREAMWRAPPER_H_
|
||||
|
||||
#include "stream.h"
|
||||
#include <iosfwd>
|
||||
|
||||
#ifdef __clang__
|
||||
RAPIDJSON_DIAG_PUSH
|
||||
RAPIDJSON_DIAG_OFF(padded)
|
||||
#endif
|
||||
|
||||
RAPIDJSON_NAMESPACE_BEGIN
|
||||
|
||||
//! Wrapper of \c std::basic_ostream into RapidJSON's Stream concept.
|
||||
/*!
|
||||
The classes can be wrapped including but not limited to:
|
||||
|
||||
- \c std::ostringstream
|
||||
- \c std::stringstream
|
||||
- \c std::wpstringstream
|
||||
- \c std::wstringstream
|
||||
- \c std::ifstream
|
||||
- \c std::fstream
|
||||
- \c std::wofstream
|
||||
- \c std::wfstream
|
||||
|
||||
\tparam StreamType Class derived from \c std::basic_ostream.
|
||||
*/
|
||||
|
||||
template <typename StreamType>
|
||||
class BasicOStreamWrapper {
|
||||
public:
|
||||
typedef typename StreamType::char_type Ch;
|
||||
BasicOStreamWrapper(StreamType& stream) : stream_(stream) {}
|
||||
|
||||
void Put(Ch c) {
|
||||
stream_.put(c);
|
||||
}
|
||||
|
||||
void Flush() {
|
||||
stream_.flush();
|
||||
}
|
||||
|
||||
// Not implemented
|
||||
char Peek() const { RAPIDJSON_ASSERT(false); return 0; }
|
||||
char Take() { RAPIDJSON_ASSERT(false); return 0; }
|
||||
size_t Tell() const { RAPIDJSON_ASSERT(false); return 0; }
|
||||
char* PutBegin() { RAPIDJSON_ASSERT(false); return 0; }
|
||||
size_t PutEnd(char*) { RAPIDJSON_ASSERT(false); return 0; }
|
||||
|
||||
private:
|
||||
BasicOStreamWrapper(const BasicOStreamWrapper&);
|
||||
BasicOStreamWrapper& operator=(const BasicOStreamWrapper&);
|
||||
|
||||
StreamType& stream_;
|
||||
};
|
||||
|
||||
typedef BasicOStreamWrapper<std::ostream> OStreamWrapper;
|
||||
typedef BasicOStreamWrapper<std::wostream> WOStreamWrapper;
|
||||
|
||||
#ifdef __clang__
|
||||
RAPIDJSON_DIAG_POP
|
||||
#endif
|
||||
|
||||
RAPIDJSON_NAMESPACE_END
|
||||
|
||||
#endif // RAPIDJSON_OSTREAMWRAPPER_H_
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user