From f93187b024610ed83f41e18a5b6145ff7b91f61d Mon Sep 17 00:00:00 2001 From: stanz2g Date: Sat, 6 Jan 2018 17:07:07 +0800 Subject: [PATCH 01/14] can build without microhttpd when WITH_HTTPD=OFF --- CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index 377bdb94..1e1673ea 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -195,6 +195,7 @@ if (WITH_HTTPD) message(FATAL_ERROR "microhttpd NOT found: use `-DWITH_HTTPD=OFF` to build without http deamon support") endif() else() + set(MHD_LIBRARY "") add_definitions(/DXMRIG_NO_HTTPD) add_definitions(/DXMRIG_NO_API) endif() From 56ffa7af794c0eebaad557d1218b6ee8f766d4e5 Mon Sep 17 00:00:00 2001 From: XMRig Date: Sat, 20 Jan 2018 12:58:43 +0700 Subject: [PATCH 02/14] #341 Fix wrong exit code. --- src/App.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/App.cpp b/src/App.cpp index 1c00e4fb..2eb81f56 100644 --- a/src/App.cpp +++ b/src/App.cpp @@ -113,7 +113,7 @@ App::~App() int App::exec() { if (!m_options) { - return 0; + return 2; } uv_signal_start(&m_sigHUP, App::onSignal, SIGHUP); From 9bceb65ad87e64e6e88599e0d6988cbea51c5555 Mon Sep 17 00:00:00 2001 From: Foudge Date: Sat, 20 Jan 2018 10:43:56 +0100 Subject: [PATCH 03/14] +15% boost with non-AES CPU Performance boost validated on Core 2 Quad processor under Windows 10. But it's Windows/MS Visual C++ specific. --- src/crypto/soft_aes.h | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/src/crypto/soft_aes.h b/src/crypto/soft_aes.h index 99321c4e..148f39c1 100644 --- a/src/crypto/soft_aes.h +++ b/src/crypto/soft_aes.h @@ -91,10 +91,17 @@ alignas(16) const uint8_t saes_sbox[256] = saes_data(saes_h0); static inline __m128i soft_aesenc(__m128i in, __m128i key) { - const uint32_t x0 = _mm_cvtsi128_si32(in); - const uint32_t x1 = _mm_cvtsi128_si32(_mm_shuffle_epi32(in, 0x55)); - const uint32_t x2 = _mm_cvtsi128_si32(_mm_shuffle_epi32(in, 0xAA)); - const uint32_t x3 = _mm_cvtsi128_si32(_mm_shuffle_epi32(in, 0xFF)); +#if defined(_MSC_VER) + const uint32_t x0 = in.m128i_u32[0]; + const uint32_t x1 = in.m128i_u32[1]; + const uint32_t x2 = in.m128i_u32[2]; + const uint32_t x3 = in.m128i_u32[3]; +#else + const uint32_t x0 = _mm_cvtsi128_si32(in); + const uint32_t x1 = _mm_cvtsi128_si32(_mm_shuffle_epi32(in, 0x55)); + const uint32_t x2 = _mm_cvtsi128_si32(_mm_shuffle_epi32(in, 0xAA)); + const uint32_t x3 = _mm_cvtsi128_si32(_mm_shuffle_epi32(in, 0xFF)); +#endif __m128i out = _mm_set_epi32( (saes_table[0][x3 & 0xff] ^ saes_table[1][(x0 >> 8) & 0xff] ^ saes_table[2][(x1 >> 16) & 0xff] ^ saes_table[3][x2 >> 24]), From 631fd755c814b772dc2bf95fe3c54a3273c4607b Mon Sep 17 00:00:00 2001 From: XMRig Date: Sat, 20 Jan 2018 20:43:31 +0700 Subject: [PATCH 04/14] #341 Added option --dry-run. --- src/App.cpp | 26 ++++++++++++++++++++------ src/App.h | 1 + src/Options.cpp | 14 +++++++++++--- src/Options.h | 2 ++ 4 files changed, 34 insertions(+), 9 deletions(-) diff --git a/src/App.cpp b/src/App.cpp index 2eb81f56..d656acc8 100644 --- a/src/App.cpp +++ b/src/App.cpp @@ -130,6 +130,13 @@ int App::exec() Mem::allocate(m_options->algo(), m_options->threads(), m_options->doubleHash(), m_options->hugePages()); Summary::print(); + if (m_options->dryRun()) { + LOG_NOTICE("OK"); + release(); + + return 0; + } + # ifndef XMRIG_NO_API Api::start(); # endif @@ -146,12 +153,7 @@ int App::exec() const int r = uv_run(uv_default_loop(), UV_RUN_DEFAULT); uv_loop_close(uv_default_loop()); - delete m_network; - - Options::release(); - Mem::release(); - Platform::release(); - + release(); return r; } @@ -200,6 +202,18 @@ void App::close() } +void App::release() +{ + if (m_network) { + delete m_network; + } + + Options::release(); + Mem::release(); + Platform::release(); +} + + void App::onSignal(uv_signal_t *handle, int signum) { switch (signum) diff --git a/src/App.h b/src/App.h index fcb3b71b..1b96040d 100644 --- a/src/App.h +++ b/src/App.h @@ -51,6 +51,7 @@ protected: private: void background(); void close(); + void release(); static void onSignal(uv_signal_t *handle, int signum); diff --git a/src/Options.cpp b/src/Options.cpp index 3eaf07ce..4e7c75ca 100644 --- a/src/Options.cpp +++ b/src/Options.cpp @@ -101,12 +101,16 @@ static char const short_options[] = "a:c:khBp:Px:r:R:s:t:T:o:u:O:v:Vl:S"; static struct option const options[] = { { "algo", 1, nullptr, 'a' }, + { "api-access-token", 1, nullptr, 4001 }, + { "api-port", 1, nullptr, 4000 }, + { "api-worker-id", 1, nullptr, 4002 }, { "av", 1, nullptr, 'v' }, { "background", 0, nullptr, 'B' }, { "config", 1, nullptr, 'c' }, { "cpu-affinity", 1, nullptr, 1020 }, { "cpu-priority", 1, nullptr, 1021 }, { "donate-level", 1, nullptr, 1003 }, + { "dry-run", 0, nullptr, 5000 }, { "help", 0, nullptr, 'h' }, { "keepalive", 0, nullptr ,'k' }, { "log-file", 1, nullptr, 'l' }, @@ -126,9 +130,6 @@ static struct option const options[] = { { "user-agent", 1, nullptr, 1008 }, { "userpass", 1, nullptr, 'O' }, { "version", 0, nullptr, 'V' }, - { "api-port", 1, nullptr, 4000 }, - { "api-access-token", 1, nullptr, 4001 }, - { "api-worker-id", 1, nullptr, 4002 }, { 0, 0, 0, 0 } }; @@ -141,6 +142,7 @@ static struct option const config_options[] = { { "cpu-affinity", 1, nullptr, 1020 }, { "cpu-priority", 1, nullptr, 1021 }, { "donate-level", 1, nullptr, 1003 }, + { "dry-run", 0, nullptr, 5000 }, { "huge-pages", 0, nullptr, 1009 }, { "log-file", 1, nullptr, 'l' }, { "max-cpu-usage", 1, nullptr, 1004 }, @@ -205,6 +207,7 @@ Options::Options(int argc, char **argv) : m_background(false), m_colors(true), m_doubleHash(false), + m_dryRun(false), m_hugePages(true), m_ready(false), m_safe(false), @@ -384,6 +387,7 @@ bool Options::parseArg(int key, const char *arg) case 'S': /* --syslog */ case 1005: /* --safe */ case 1006: /* --nicehash */ + case 5000: /* --dry-run */ return parseBoolean(key, true); case 1002: /* --no-color */ @@ -557,6 +561,10 @@ bool Options::parseBoolean(int key, bool enable) m_colors = enable; break; + case 5000: /* --dry-run */ + m_dryRun = enable; + break; + default: break; } diff --git a/src/Options.h b/src/Options.h index 9070888f..6f074917 100644 --- a/src/Options.h +++ b/src/Options.h @@ -59,6 +59,7 @@ public: inline bool background() const { return m_background; } inline bool colors() const { return m_colors; } inline bool doubleHash() const { return m_doubleHash; } + inline bool dryRun() const { return m_dryRun; } inline bool hugePages() const { return m_hugePages; } inline bool syslog() const { return m_syslog; } inline const char *apiToken() const { return m_apiToken; } @@ -110,6 +111,7 @@ private: bool m_background; bool m_colors; bool m_doubleHash; + bool m_dryRun; bool m_hugePages; bool m_ready; bool m_safe; From 15fe6ce23f4aa2654bb8b458463e6213ee867486 Mon Sep 17 00:00:00 2001 From: Foudge Date: Sat, 27 Jan 2018 11:42:22 +0100 Subject: [PATCH 05/14] Remove compilation warnings under MSVC --- src/api/NetworkState.cpp | 4 ++-- src/net/Client.cpp | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/api/NetworkState.cpp b/src/api/NetworkState.cpp index bae290d0..d3ffddd3 100644 --- a/src/api/NetworkState.cpp +++ b/src/api/NetworkState.cpp @@ -46,7 +46,7 @@ NetworkState::NetworkState() : int NetworkState::connectionTime() const { - return m_active ? ((uv_now(uv_default_loop()) - m_connectionTime) / 1000) : 0; + return m_active ? (int)((uv_now(uv_default_loop()) - m_connectionTime) / 1000) : 0; } @@ -56,7 +56,7 @@ uint32_t NetworkState::avgTime() const return 0; } - return (uint32_t) connectionTime() / m_latency.size(); + return connectionTime() / (uint32_t)m_latency.size(); } diff --git a/src/net/Client.cpp b/src/net/Client.cpp index 8e8ebcfd..fcaec8eb 100644 --- a/src/net/Client.cpp +++ b/src/net/Client.cpp @@ -532,7 +532,7 @@ void Client::onAllocBuffer(uv_handle_t *handle, size_t suggested_size, uv_buf_t auto client = getClient(handle->data); buf->base = &client->m_recvBuf.base[client->m_recvBufPos]; - buf->len = client->m_recvBuf.len - client->m_recvBufPos; + buf->len = client->m_recvBuf.len - (ULONG)client->m_recvBufPos; } From 9a28ad590ca6137bf5e19ba477e3f379527bbd73 Mon Sep 17 00:00:00 2001 From: Foudge Date: Sun, 28 Jan 2018 12:58:19 +0100 Subject: [PATCH 06/14] up to 20% perf increase with Cryptonight with non-AES CPU This time, the performance increase is got with MSVC and GCC. On non-AES CPU, there were an useless load/store SSE2 register. The last MSVC "hack" is replaced by a portable code and he's more complete (a load is saved). On my C2Q6600, with 3 thread, I have +16% with MSVC2015 and +20% with GCC 7.3, compared to official 2.4.4 version. --- src/crypto/CryptoNight_arm.h | 30 +++++++++-------- src/crypto/CryptoNight_x86.h | 62 ++++++++++++++++++------------------ src/crypto/soft_aes.h | 17 +++------- 3 files changed, 52 insertions(+), 57 deletions(-) diff --git a/src/crypto/CryptoNight_arm.h b/src/crypto/CryptoNight_arm.h index 15be6c3d..17bba7af 100644 --- a/src/crypto/CryptoNight_arm.h +++ b/src/crypto/CryptoNight_arm.h @@ -194,14 +194,14 @@ template static inline void aes_round(__m128i key, __m128i* x0, __m128i* x1, __m128i* x2, __m128i* x3, __m128i* x4, __m128i* x5, __m128i* x6, __m128i* x7) { if (SOFT_AES) { - *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); + *x0 = soft_aesenc((uint32_t*)x0, key); + *x1 = soft_aesenc((uint32_t*)x1, key); + *x2 = soft_aesenc((uint32_t*)x2, key); + *x3 = soft_aesenc((uint32_t*)x3, key); + *x4 = soft_aesenc((uint32_t*)x4, key); + *x5 = soft_aesenc((uint32_t*)x5, key); + *x6 = soft_aesenc((uint32_t*)x6, key); + *x7 = soft_aesenc((uint32_t*)x7, key); } # ifndef XMRIG_ARMv7 else { @@ -361,12 +361,13 @@ inline void cryptonight_hash(const void *__restrict__ input, size_t size, void * uint64_t idx0 = h0[0] ^ h0[4]; for (size_t i = 0; i < ITERATIONS; i++) { - __m128i cx = _mm_load_si128((__m128i *) &l0[idx0 & MASK]); + __m128i cx; if (SOFT_AES) { - cx = soft_aesenc(cx, _mm_set_epi64x(ah0, al0)); + cx = soft_aesenc((uint32_t*)&l0[idx0 & MASK], _mm_set_epi64x(ah0, al0)); } else { + cx = _mm_load_si128((__m128i *) &l0[idx0 & MASK]); # ifndef XMRIG_ARMv7 cx = vreinterpretq_m128i_u8(vaesmcq_u8(vaeseq_u8(cx, vdupq_n_u8(0)))) ^ _mm_set_epi64x(ah0, al0); # endif @@ -425,14 +426,15 @@ inline void cryptonight_double_hash(const void *__restrict__ input, size_t size, uint64_t idx1 = h1[0] ^ h1[4]; for (size_t i = 0; i < ITERATIONS; i++) { - __m128i cx0 = _mm_load_si128((__m128i *) &l0[idx0 & MASK]); - __m128i cx1 = _mm_load_si128((__m128i *) &l1[idx1 & MASK]); + __m128i cx0, cx1; if (SOFT_AES) { - cx0 = soft_aesenc(cx0, _mm_set_epi64x(ah0, al0)); - cx1 = soft_aesenc(cx1, _mm_set_epi64x(ah1, al1)); + cx0 = soft_aesenc((uint32_t*)&l0[idx0 & MASK], _mm_set_epi64x(ah0, al0)); + cx1 = soft_aesenc((uint32_t*)&l1[idx1 & MASK], _mm_set_epi64x(ah1, al1)); } else { + cx0 = _mm_load_si128((__m128i *) &l0[idx0 & MASK]); + cx1 = _mm_load_si128((__m128i *) &l1[idx1 & MASK]); # ifndef XMRIG_ARMv7 cx0 = vreinterpretq_m128i_u8(vaesmcq_u8(vaeseq_u8(cx0, vdupq_n_u8(0)))) ^ _mm_set_epi64x(ah0, al0); cx1 = vreinterpretq_m128i_u8(vaesmcq_u8(vaeseq_u8(cx1, vdupq_n_u8(0)))) ^ _mm_set_epi64x(ah1, al1); diff --git a/src/crypto/CryptoNight_x86.h b/src/crypto/CryptoNight_x86.h index 362a1a9f..786d28f1 100644 --- a/src/crypto/CryptoNight_x86.h +++ b/src/crypto/CryptoNight_x86.h @@ -193,14 +193,14 @@ template static inline void aes_round(__m128i key, __m128i* x0, __m128i* x1, __m128i* x2, __m128i* x3, __m128i* x4, __m128i* x5, __m128i* x6, __m128i* x7) { if (SOFT_AES) { - *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); + *x0 = soft_aesenc((uint32_t*)x0, key); + *x1 = soft_aesenc((uint32_t*)x1, key); + *x2 = soft_aesenc((uint32_t*)x2, key); + *x3 = soft_aesenc((uint32_t*)x3, key); + *x4 = soft_aesenc((uint32_t*)x4, key); + *x5 = soft_aesenc((uint32_t*)x5, key); + *x6 = soft_aesenc((uint32_t*)x6, key); + *x7 = soft_aesenc((uint32_t*)x7, key); } else { *x0 = _mm_aesenc_si128(*x0, key); @@ -324,19 +324,18 @@ inline void cryptonight_hash(const void *__restrict__ input, size_t size, void * uint64_t idx0 = h0[0] ^ h0[4]; for (size_t i = 0; i < ITERATIONS; i++) { - __m128i cx; - cx = _mm_load_si128((__m128i *) &l0[idx0 & MASK]); + __m128i cx; - if (SOFT_AES) { - cx = soft_aesenc(cx, _mm_set_epi64x(ah0, al0)); - } - else { - cx = _mm_aesenc_si128(cx, _mm_set_epi64x(ah0, al0)); - } - - _mm_store_si128((__m128i *) &l0[idx0 & MASK], _mm_xor_si128(bx0, cx)); - idx0 = EXTRACT64(cx); - bx0 = cx; + if (SOFT_AES) { + cx = soft_aesenc((uint32_t*)&l0[idx0 & MASK], _mm_set_epi64x(ah0, al0)); + } + else { + cx = _mm_load_si128((__m128i *) &l0[idx0 & MASK]); + cx = _mm_aesenc_si128(cx, _mm_set_epi64x(ah0, al0)); + } + _mm_store_si128((__m128i *) &l0[idx0 & MASK], _mm_xor_si128(bx0, cx)); + idx0 = EXTRACT64(cx); + bx0 = cx; uint64_t hi, lo, cl, ch; cl = ((uint64_t*) &l0[idx0 & MASK])[0]; @@ -386,18 +385,19 @@ inline void cryptonight_double_hash(const void *__restrict__ input, size_t size, uint64_t idx0 = h0[0] ^ h0[4]; uint64_t idx1 = h1[0] ^ h1[4]; - for (size_t i = 0; i < ITERATIONS; i++) { - __m128i cx0 = _mm_load_si128((__m128i *) &l0[idx0 & MASK]); - __m128i cx1 = _mm_load_si128((__m128i *) &l1[idx1 & MASK]); + for (size_t i = 0; i < ITERATIONS; i++) { + __m128i cx0, cx1; - if (SOFT_AES) { - cx0 = soft_aesenc(cx0, _mm_set_epi64x(ah0, al0)); - cx1 = soft_aesenc(cx1, _mm_set_epi64x(ah1, al1)); - } - else { - cx0 = _mm_aesenc_si128(cx0, _mm_set_epi64x(ah0, al0)); - cx1 = _mm_aesenc_si128(cx1, _mm_set_epi64x(ah1, al1)); - } + if (SOFT_AES) { + cx0 = soft_aesenc((uint32_t*)&l0[idx0 & MASK], _mm_set_epi64x(ah0, al0)); + cx1 = soft_aesenc((uint32_t*)&l1[idx1 & MASK], _mm_set_epi64x(ah1, al1)); + } + else { + cx0 = _mm_load_si128((__m128i *) &l0[idx0 & MASK]); + cx1 = _mm_load_si128((__m128i *) &l1[idx1 & MASK]); + 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 & MASK], _mm_xor_si128(bx0, cx0)); _mm_store_si128((__m128i *) &l1[idx1 & MASK], _mm_xor_si128(bx1, cx1)); diff --git a/src/crypto/soft_aes.h b/src/crypto/soft_aes.h index 148f39c1..b7698ac4 100644 --- a/src/crypto/soft_aes.h +++ b/src/crypto/soft_aes.h @@ -89,19 +89,12 @@ alignas(16) const uint32_t saes_table[4][256] = { saes_data(saes_u0), saes_data(saes_u1), saes_data(saes_u2), saes_data(saes_u3) }; alignas(16) const uint8_t saes_sbox[256] = saes_data(saes_h0); -static inline __m128i soft_aesenc(__m128i in, __m128i key) +static inline __m128i soft_aesenc(const uint32_t* in, __m128i key) { -#if defined(_MSC_VER) - const uint32_t x0 = in.m128i_u32[0]; - const uint32_t x1 = in.m128i_u32[1]; - const uint32_t x2 = in.m128i_u32[2]; - const uint32_t x3 = in.m128i_u32[3]; -#else - const uint32_t x0 = _mm_cvtsi128_si32(in); - const uint32_t x1 = _mm_cvtsi128_si32(_mm_shuffle_epi32(in, 0x55)); - const uint32_t x2 = _mm_cvtsi128_si32(_mm_shuffle_epi32(in, 0xAA)); - const uint32_t x3 = _mm_cvtsi128_si32(_mm_shuffle_epi32(in, 0xFF)); -#endif + const uint32_t x0 = in[0]; + const uint32_t x1 = in[1]; + const uint32_t x2 = in[2]; + const uint32_t x3 = in[3]; __m128i out = _mm_set_epi32( (saes_table[0][x3 & 0xff] ^ saes_table[1][(x0 >> 8) & 0xff] ^ saes_table[2][(x1 >> 16) & 0xff] ^ saes_table[3][x2 >> 24]), From d2964576c7da7784d060116a4970f60f6b895f10 Mon Sep 17 00:00:00 2001 From: Foudge Date: Sun, 28 Jan 2018 18:13:00 +0100 Subject: [PATCH 07/14] Compilation error under FreeBSD ULONG is not recognized under this OS, so replaced it with more portable definition. --- src/net/Client.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/net/Client.cpp b/src/net/Client.cpp index fcaec8eb..fb83acd2 100644 --- a/src/net/Client.cpp +++ b/src/net/Client.cpp @@ -532,7 +532,7 @@ void Client::onAllocBuffer(uv_handle_t *handle, size_t suggested_size, uv_buf_t auto client = getClient(handle->data); buf->base = &client->m_recvBuf.base[client->m_recvBufPos]; - buf->len = client->m_recvBuf.len - (ULONG)client->m_recvBufPos; + buf->len = client->m_recvBuf.len - (unsigned long)client->m_recvBufPos; } From 037abd703720cc52f228c99d1e0e205ce48abd85 Mon Sep 17 00:00:00 2001 From: Foudge Date: Sat, 3 Feb 2018 16:03:14 +0100 Subject: [PATCH 08/14] Correct L2 cache size calculation for Intel Core 2 family This is a workaround for total L2 cache size calculation of Intel Core Solo, Core Duo, Core 2 Duo, Core 2 Quad and their Xeon homologue. These processors have L2 cache shared by 2 cores. There is maybe more CPU with L2 shared cache, but I am sure that these models are concerned and they are not so numerous. A better way would be to modify libcpuid to implement L2 cache counting. --- src/Cpu.cpp | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/Cpu.cpp b/src/Cpu.cpp index ff6f49e9..b122e156 100644 --- a/src/Cpu.cpp +++ b/src/Cpu.cpp @@ -100,7 +100,13 @@ void Cpu::initCommon() m_l2_cache = data.l2_cache * (m_totalCores / 2) * m_sockets; m_l2_exclusive = true; } - else { + // Workaround for Intel Core Solo, Core Duo, Core 2 Duo, Core 2 Quad and their Xeon homologue + // These processors have L2 cache shared by 2 cores. + else if (data.vendor == VENDOR_INTEL && data.family == 0x06 && (data.model == 0x0E || data.model == 0x0F || data.model == 0x07)) { + int l2_count_per_socket = m_totalCores > 1 ? m_totalCores / 2 : 1; + m_l2_cache = data.l2_cache > 0 ? data.l2_cache * l2_count_per_socket * m_sockets : 0; + } + else{ m_l2_cache = data.l2_cache > 0 ? data.l2_cache * m_totalCores * m_sockets : 0; } From e78e810cfea6bb5594a6be3720378d83e29a3675 Mon Sep 17 00:00:00 2001 From: XMRig Date: Thu, 8 Feb 2018 17:02:32 +0700 Subject: [PATCH 09/14] Fix code style, replace tabs to space. --- src/Cpu.cpp | 14 +++++------ src/crypto/CryptoNight_x86.h | 46 ++++++++++++++++++------------------ src/crypto/soft_aes.h | 30 +++++++++++------------ 3 files changed, 45 insertions(+), 45 deletions(-) diff --git a/src/Cpu.cpp b/src/Cpu.cpp index b122e156..a619781e 100644 --- a/src/Cpu.cpp +++ b/src/Cpu.cpp @@ -100,13 +100,13 @@ void Cpu::initCommon() m_l2_cache = data.l2_cache * (m_totalCores / 2) * m_sockets; m_l2_exclusive = true; } - // Workaround for Intel Core Solo, Core Duo, Core 2 Duo, Core 2 Quad and their Xeon homologue - // These processors have L2 cache shared by 2 cores. - else if (data.vendor == VENDOR_INTEL && data.family == 0x06 && (data.model == 0x0E || data.model == 0x0F || data.model == 0x07)) { - int l2_count_per_socket = m_totalCores > 1 ? m_totalCores / 2 : 1; - m_l2_cache = data.l2_cache > 0 ? data.l2_cache * l2_count_per_socket * m_sockets : 0; - } - else{ + // Workaround for Intel Core Solo, Core Duo, Core 2 Duo, Core 2 Quad and their Xeon homologue + // These processors have L2 cache shared by 2 cores. + else if (data.vendor == VENDOR_INTEL && data.family == 0x06 && (data.model == 0x0E || data.model == 0x0F || data.model == 0x07)) { + int l2_count_per_socket = m_totalCores > 1 ? m_totalCores / 2 : 1; + m_l2_cache = data.l2_cache > 0 ? data.l2_cache * l2_count_per_socket * m_sockets : 0; + } + else{ m_l2_cache = data.l2_cache > 0 ? data.l2_cache * m_totalCores * m_sockets : 0; } diff --git a/src/crypto/CryptoNight_x86.h b/src/crypto/CryptoNight_x86.h index 786d28f1..927aab72 100644 --- a/src/crypto/CryptoNight_x86.h +++ b/src/crypto/CryptoNight_x86.h @@ -324,18 +324,18 @@ inline void cryptonight_hash(const void *__restrict__ input, size_t size, void * uint64_t idx0 = h0[0] ^ h0[4]; for (size_t i = 0; i < ITERATIONS; i++) { - __m128i cx; + __m128i cx; - if (SOFT_AES) { - cx = soft_aesenc((uint32_t*)&l0[idx0 & MASK], _mm_set_epi64x(ah0, al0)); - } - else { - cx = _mm_load_si128((__m128i *) &l0[idx0 & MASK]); - cx = _mm_aesenc_si128(cx, _mm_set_epi64x(ah0, al0)); - } - _mm_store_si128((__m128i *) &l0[idx0 & MASK], _mm_xor_si128(bx0, cx)); - idx0 = EXTRACT64(cx); - bx0 = cx; + if (SOFT_AES) { + cx = soft_aesenc((uint32_t*)&l0[idx0 & MASK], _mm_set_epi64x(ah0, al0)); + } + else { + cx = _mm_load_si128((__m128i *) &l0[idx0 & MASK]); + cx = _mm_aesenc_si128(cx, _mm_set_epi64x(ah0, al0)); + } + _mm_store_si128((__m128i *) &l0[idx0 & MASK], _mm_xor_si128(bx0, cx)); + idx0 = EXTRACT64(cx); + bx0 = cx; uint64_t hi, lo, cl, ch; cl = ((uint64_t*) &l0[idx0 & MASK])[0]; @@ -385,19 +385,19 @@ inline void cryptonight_double_hash(const void *__restrict__ input, size_t size, uint64_t idx0 = h0[0] ^ h0[4]; uint64_t idx1 = h1[0] ^ h1[4]; - for (size_t i = 0; i < ITERATIONS; i++) { - __m128i cx0, cx1; + for (size_t i = 0; i < ITERATIONS; i++) { + __m128i cx0, cx1; - if (SOFT_AES) { - cx0 = soft_aesenc((uint32_t*)&l0[idx0 & MASK], _mm_set_epi64x(ah0, al0)); - cx1 = soft_aesenc((uint32_t*)&l1[idx1 & MASK], _mm_set_epi64x(ah1, al1)); - } - else { - cx0 = _mm_load_si128((__m128i *) &l0[idx0 & MASK]); - cx1 = _mm_load_si128((__m128i *) &l1[idx1 & MASK]); - cx0 = _mm_aesenc_si128(cx0, _mm_set_epi64x(ah0, al0)); - cx1 = _mm_aesenc_si128(cx1, _mm_set_epi64x(ah1, al1)); - } + if (SOFT_AES) { + cx0 = soft_aesenc((uint32_t*)&l0[idx0 & MASK], _mm_set_epi64x(ah0, al0)); + cx1 = soft_aesenc((uint32_t*)&l1[idx1 & MASK], _mm_set_epi64x(ah1, al1)); + } + else { + cx0 = _mm_load_si128((__m128i *) &l0[idx0 & MASK]); + cx1 = _mm_load_si128((__m128i *) &l1[idx1 & MASK]); + 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 & MASK], _mm_xor_si128(bx0, cx0)); _mm_store_si128((__m128i *) &l1[idx1 & MASK], _mm_xor_si128(bx1, cx1)); diff --git a/src/crypto/soft_aes.h b/src/crypto/soft_aes.h index b7698ac4..0703f98d 100644 --- a/src/crypto/soft_aes.h +++ b/src/crypto/soft_aes.h @@ -91,32 +91,32 @@ alignas(16) const uint8_t saes_sbox[256] = saes_data(saes_h0); static inline __m128i soft_aesenc(const uint32_t* in, __m128i key) { - const uint32_t x0 = in[0]; - const uint32_t x1 = in[1]; - const uint32_t x2 = in[2]; - const uint32_t x3 = in[3]; + const uint32_t x0 = in[0]; + const uint32_t x1 = in[1]; + const uint32_t x2 = in[2]; + const uint32_t x3 = in[3]; - __m128i out = _mm_set_epi32( - (saes_table[0][x3 & 0xff] ^ saes_table[1][(x0 >> 8) & 0xff] ^ saes_table[2][(x1 >> 16) & 0xff] ^ saes_table[3][x2 >> 24]), - (saes_table[0][x2 & 0xff] ^ saes_table[1][(x3 >> 8) & 0xff] ^ saes_table[2][(x0 >> 16) & 0xff] ^ saes_table[3][x1 >> 24]), - (saes_table[0][x1 & 0xff] ^ saes_table[1][(x2 >> 8) & 0xff] ^ saes_table[2][(x3 >> 16) & 0xff] ^ saes_table[3][x0 >> 24]), - (saes_table[0][x0 & 0xff] ^ saes_table[1][(x1 >> 8) & 0xff] ^ saes_table[2][(x2 >> 16) & 0xff] ^ saes_table[3][x3 >> 24])); + __m128i out = _mm_set_epi32( + (saes_table[0][x3 & 0xff] ^ saes_table[1][(x0 >> 8) & 0xff] ^ saes_table[2][(x1 >> 16) & 0xff] ^ saes_table[3][x2 >> 24]), + (saes_table[0][x2 & 0xff] ^ saes_table[1][(x3 >> 8) & 0xff] ^ saes_table[2][(x0 >> 16) & 0xff] ^ saes_table[3][x1 >> 24]), + (saes_table[0][x1 & 0xff] ^ saes_table[1][(x2 >> 8) & 0xff] ^ saes_table[2][(x3 >> 16) & 0xff] ^ saes_table[3][x0 >> 24]), + (saes_table[0][x0 & 0xff] ^ saes_table[1][(x1 >> 8) & 0xff] ^ saes_table[2][(x2 >> 16) & 0xff] ^ saes_table[3][x3 >> 24])); - return _mm_xor_si128(out, key); + return _mm_xor_si128(out, key); } static inline uint32_t sub_word(uint32_t key) { - return (saes_sbox[key >> 24 ] << 24) | - (saes_sbox[(key >> 16) & 0xff] << 16 ) | - (saes_sbox[(key >> 8) & 0xff] << 8 ) | - saes_sbox[key & 0xff]; + return (saes_sbox[key >> 24 ] << 24) | + (saes_sbox[(key >> 16) & 0xff] << 16 ) | + (saes_sbox[(key >> 8) & 0xff] << 8 ) | + saes_sbox[key & 0xff]; } #if defined(__clang__) || defined(XMRIG_ARM) static inline uint32_t _rotr(uint32_t value, uint32_t amount) { - return (value >> amount) | (value << ((32 - amount) & 31)); + return (value >> amount) | (value << ((32 - amount) & 31)); } #endif From 184f79ad3f51db2e49aebd06565b05a4d358ab2f Mon Sep 17 00:00:00 2001 From: XMRig Date: Thu, 8 Feb 2018 17:21:12 +0700 Subject: [PATCH 10/14] Fix code style, replace tabs to space #2. --- src/crypto/CryptoNight_arm.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/crypto/CryptoNight_arm.h b/src/crypto/CryptoNight_arm.h index 17bba7af..4ac14f34 100644 --- a/src/crypto/CryptoNight_arm.h +++ b/src/crypto/CryptoNight_arm.h @@ -361,13 +361,13 @@ inline void cryptonight_hash(const void *__restrict__ input, size_t size, void * uint64_t idx0 = h0[0] ^ h0[4]; for (size_t i = 0; i < ITERATIONS; i++) { - __m128i cx; + __m128i cx; if (SOFT_AES) { cx = soft_aesenc((uint32_t*)&l0[idx0 & MASK], _mm_set_epi64x(ah0, al0)); } else { - cx = _mm_load_si128((__m128i *) &l0[idx0 & MASK]); + cx = _mm_load_si128((__m128i *) &l0[idx0 & MASK]); # ifndef XMRIG_ARMv7 cx = vreinterpretq_m128i_u8(vaesmcq_u8(vaeseq_u8(cx, vdupq_n_u8(0)))) ^ _mm_set_epi64x(ah0, al0); # endif @@ -433,8 +433,8 @@ inline void cryptonight_double_hash(const void *__restrict__ input, size_t size, cx1 = soft_aesenc((uint32_t*)&l1[idx1 & MASK], _mm_set_epi64x(ah1, al1)); } else { - cx0 = _mm_load_si128((__m128i *) &l0[idx0 & MASK]); - cx1 = _mm_load_si128((__m128i *) &l1[idx1 & MASK]); + cx0 = _mm_load_si128((__m128i *) &l0[idx0 & MASK]); + cx1 = _mm_load_si128((__m128i *) &l1[idx1 & MASK]); # ifndef XMRIG_ARMv7 cx0 = vreinterpretq_m128i_u8(vaesmcq_u8(vaeseq_u8(cx0, vdupq_n_u8(0)))) ^ _mm_set_epi64x(ah0, al0); cx1 = vreinterpretq_m128i_u8(vaesmcq_u8(vaeseq_u8(cx1, vdupq_n_u8(0)))) ^ _mm_set_epi64x(ah1, al1); From f0604d1e975b26ec1a2e5cba85e5d6daf8ebd074 Mon Sep 17 00:00:00 2001 From: xmrig Date: Sun, 18 Feb 2018 05:06:10 +0700 Subject: [PATCH 11/14] Update README.md --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 6ab4b6a2..c33216d1 100644 --- a/README.md +++ b/README.md @@ -3,6 +3,7 @@ XMRig is a high performance Monero (XMR) CPU miner, with official support for Wi Originally based on cpuminer-multi with heavy optimizations/rewrites and removing a lot of legacy code, since version 1.0.0 completely rewritten from scratch on C++. * This is the **CPU-mining** version, there is also a [NVIDIA GPU version](https://github.com/xmrig/xmrig-nvidia) and [AMD GPU version]( https://github.com/xmrig/xmrig-amd). +* You can use [config.xmrig.com](https://config.xmrig.com/) to generate/edit/share your configurations. :new: * [Roadmap](https://github.com/xmrig/xmrig/issues/106) for next releases. From c9acc2912e9e71d234648bec2595137bec355dfc Mon Sep 17 00:00:00 2001 From: xmrig Date: Sun, 18 Feb 2018 05:32:36 +0700 Subject: [PATCH 12/14] Update CHANGELOG.md --- CHANGELOG.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 878ff984..c23c5d29 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,8 @@ +# v2.4.5 +- [#324](https://github.com/xmrig/xmrig/pull/324) Fixed build without libmicrohttpd (CMake cache issue). +- [#341](https://github.com/xmrig/xmrig/issues/341) Fixed wrong exit code and added command line option `--dry-run`. +- [#385](https://github.com/xmrig/xmrig/pull/385) Up to 20% performance increase with for non-AES CPU and fixed Intel Core 2 cache detection. + # v2.4.4 - Added libmicrohttpd version to --version output. - Fixed bug in singal handler, in some cases miner wasn't shutdown properly. From 0b73632ac5bb439bf8c00635718ff9dd141165d3 Mon Sep 17 00:00:00 2001 From: enWILLYado Date: Sat, 17 Feb 2018 23:48:46 +0100 Subject: [PATCH 13/14] Merge --- .gitignore | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.gitignore b/.gitignore index 189b414f..05aa56e3 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,4 @@ /build /CMakeLists.txt.user +/vs/*/ +*.sdf From 4001fecdf7f948f2dec018ff0619de836ba14e93 Mon Sep 17 00:00:00 2001 From: enWILLYado Date: Sat, 17 Feb 2018 23:50:16 +0100 Subject: [PATCH 14/14] Merge. --- src/3rdparty/aligned_malloc.h | 35 +- src/3rdparty/getopt/getopt.h | 422 +- src/3rdparty/libcpuid/amd_code_t.h | 18 +- src/3rdparty/libcpuid/asm-bits.c | 762 +-- src/3rdparty/libcpuid/asm-bits.h | 2 +- src/3rdparty/libcpuid/cpuid_main.c | 668 ++- src/3rdparty/libcpuid/intel_code_t.h | 56 +- src/3rdparty/libcpuid/libcpuid.h | 601 ++- src/3rdparty/libcpuid/libcpuid_internal.h | 84 +- src/3rdparty/libcpuid/libcpuid_types.h | 32 +- src/3rdparty/libcpuid/libcpuid_util.c | 248 +- src/3rdparty/libcpuid/libcpuid_util.h | 28 +- src/3rdparty/libcpuid/msrdriver.c | 595 +++ src/3rdparty/libcpuid/rdmsr.c | 1291 +++++ src/3rdparty/libcpuid/rdtsc.c | 409 ++ src/3rdparty/libcpuid/rdtsc.h | 33 + src/3rdparty/libcpuid/recog_amd.c | 527 +- src/3rdparty/libcpuid/recog_amd.h | 1 + src/3rdparty/libcpuid/recog_intel.c | 907 +++- src/3rdparty/libcpuid/recog_intel.h | 4 +- src/3rdparty/rapidjson/allocators.h | 387 +- src/3rdparty/rapidjson/document.h | 5017 +++++++++++------- src/3rdparty/rapidjson/encodedstream.h | 559 +- src/3rdparty/rapidjson/encodings.h | 1096 ++-- src/3rdparty/rapidjson/error/en.h | 103 +- src/3rdparty/rapidjson/error/error.h | 120 +- src/3rdparty/rapidjson/filereadstream.h | 142 +- src/3rdparty/rapidjson/filewritestream.h | 141 +- src/3rdparty/rapidjson/fwd.h | 23 +- src/3rdparty/rapidjson/internal/biginteger.h | 561 +- src/3rdparty/rapidjson/internal/diyfp.h | 406 +- src/3rdparty/rapidjson/internal/dtoa.h | 500 +- src/3rdparty/rapidjson/internal/ieee754.h | 146 +- src/3rdparty/rapidjson/internal/itoa.h | 609 ++- src/3rdparty/rapidjson/internal/meta.h | 239 +- src/3rdparty/rapidjson/internal/pow10.h | 69 +- src/3rdparty/rapidjson/internal/regex.h | 1314 +++-- src/3rdparty/rapidjson/internal/stack.h | 389 +- src/3rdparty/rapidjson/internal/strfunc.h | 73 +- src/3rdparty/rapidjson/internal/strtod.h | 485 +- src/3rdparty/rapidjson/internal/swap.h | 26 +- src/3rdparty/rapidjson/istreamwrapper.h | 128 +- src/3rdparty/rapidjson/memorybuffer.h | 66 +- src/3rdparty/rapidjson/memorystream.h | 73 +- src/3rdparty/rapidjson/msinttypes/inttypes.h | 72 +- src/3rdparty/rapidjson/msinttypes/stdint.h | 167 +- src/3rdparty/rapidjson/ostreamwrapper.h | 69 +- src/3rdparty/rapidjson/pointer.h | 2262 ++++---- src/3rdparty/rapidjson/prettywriter.h | 427 +- src/3rdparty/rapidjson/rapidjson.h | 54 +- src/3rdparty/rapidjson/reader.h | 3405 +++++++----- src/3rdparty/rapidjson/schema.h | 3789 +++++++------ src/3rdparty/rapidjson/stream.h | 170 +- src/3rdparty/rapidjson/stringbuffer.h | 128 +- src/3rdparty/rapidjson/writer.h | 1059 ++-- src/App.cpp | 232 +- src/App.h | 32 +- src/App_unix.cpp | 52 +- src/App_win.cpp | 33 +- src/Console.cpp | 43 +- src/Console.h | 12 +- src/Cpu.cpp | 130 +- src/Cpu.h | 75 +- src/Cpu_arm.cpp | 12 +- src/Cpu_mac.cpp | 8 +- src/Cpu_stub.cpp | 84 +- src/Cpu_unix.cpp | 38 +- src/Cpu_win.cpp | 22 +- src/Mem.cpp | 54 +- src/Mem.h | 58 +- src/Mem_unix.cpp | 90 +- src/Mem_win.cpp | 188 +- src/Options.cpp | 979 ++-- src/Options.h | 235 +- src/Platform.cpp | 50 +- src/Platform.h | 20 +- src/Platform_mac.cpp | 77 +- src/Platform_unix.cpp | 96 +- src/Platform_win.cpp | 174 +- src/Summary.cpp | 165 +- src/Summary.h | 2 +- src/api/Api.cpp | 60 +- src/api/Api.h | 15 +- src/api/ApiState.cpp | 265 +- src/api/ApiState.h | 39 +- src/api/Httpd.cpp | 134 +- src/api/Httpd.h | 26 +- src/api/NetworkState.cpp | 86 +- src/api/NetworkState.h | 34 +- src/config.json | 16 +- src/crypto/CryptoNight.cpp | 132 +- src/crypto/CryptoNight.h | 17 +- src/crypto/CryptoNight_arm.h | 618 +-- src/crypto/CryptoNight_test.h | 45 +- src/crypto/CryptoNight_x86.h | 556 +- src/crypto/SSE2NEON.h | 334 +- src/crypto/c_blake256.c | 536 +- src/crypto/c_blake256.h | 48 +- src/crypto/c_groestl.c | 550 +- src/crypto/c_groestl.h | 25 +- src/crypto/c_jh.c | 601 ++- src/crypto/c_jh.h | 2 +- src/crypto/c_keccak.c | 259 +- src/crypto/c_keccak.h | 4 +- src/crypto/c_skein.c | 763 +-- src/crypto/c_skein.h | 18 +- src/crypto/groestl_tables.h | 63 +- src/crypto/skein_port.h | 66 +- src/crypto/soft_aes.h | 110 +- src/donate.h | 5 +- src/interfaces/IClientListener.h | 10 +- src/interfaces/IConsoleListener.h | 4 +- src/interfaces/IJobResultListener.h | 4 +- src/interfaces/ILogBackend.h | 20 +- src/interfaces/IStrategy.h | 17 +- src/interfaces/IStrategyListener.h | 15 +- src/interfaces/IWorker.h | 8 +- src/interfaces/interface.h | 62 + src/log/ConsoleLog.cpp | 156 +- src/log/ConsoleLog.h | 17 +- src/log/FileLog.cpp | 88 +- src/log/FileLog.h | 18 +- src/log/Log.cpp | 48 +- src/log/Log.h | 114 +- src/log/SysLog.cpp | 14 +- src/log/SysLog.h | 6 +- src/net/Client.cpp | 937 ++-- src/net/Client.h | 190 +- src/net/Job.cpp | 201 +- src/net/Job.h | 134 +- src/net/JobId.h | 73 +- src/net/JobResult.h | 63 +- src/net/Network.cpp | 199 +- src/net/Network.h | 39 +- src/net/SubmitResult.cpp | 12 +- src/net/SubmitResult.h | 16 +- src/net/Url.cpp | 309 +- src/net/Url.h | 128 +- src/net/strategies/DonateStrategy.cpp | 180 +- src/net/strategies/DonateStrategy.h | 50 +- src/net/strategies/FailoverStrategy.cpp | 140 +- src/net/strategies/FailoverStrategy.h | 35 +- src/net/strategies/SinglePoolStrategy.cpp | 60 +- src/net/strategies/SinglePoolStrategy.h | 31 +- src/workers/DoubleWorker.cpp | 175 +- src/workers/DoubleWorker.h | 20 +- src/workers/Handle.cpp | 16 +- src/workers/Handle.h | 48 +- src/workers/Hashrate.cpp | 181 +- src/workers/Hashrate.h | 56 +- src/workers/SingleWorker.cpp | 134 +- src/workers/SingleWorker.h | 16 +- src/workers/Worker.cpp | 37 +- src/workers/Worker.h | 32 +- src/workers/Workers.cpp | 188 +- src/workers/Workers.h | 82 +- src/xmrig.cpp | 7 +- 157 files changed, 27089 insertions(+), 16686 deletions(-) create mode 100644 src/3rdparty/libcpuid/msrdriver.c create mode 100644 src/3rdparty/libcpuid/rdmsr.c create mode 100644 src/3rdparty/libcpuid/rdtsc.c create mode 100644 src/3rdparty/libcpuid/rdtsc.h create mode 100644 src/interfaces/interface.h diff --git a/src/3rdparty/aligned_malloc.h b/src/3rdparty/aligned_malloc.h index 0b74b17e..587e62f8 100644 --- a/src/3rdparty/aligned_malloc.h +++ b/src/3rdparty/aligned_malloc.h @@ -29,37 +29,42 @@ #ifndef __cplusplus -extern int posix_memalign(void **__memptr, size_t __alignment, size_t __size); +extern int posix_memalign(void** __memptr, size_t __alignment, size_t __size); #else // Some systems (e.g. those with GNU libc) declare posix_memalign with an // exception specifier. Via an "egregious workaround" in // Sema::CheckEquivalentExceptionSpec, Clang accepts the following as a valid // redeclaration of glibc's declaration. -extern "C" int posix_memalign(void **__memptr, size_t __alignment, size_t __size); +extern "C" int posix_memalign(void** __memptr, size_t __alignment, size_t __size); #endif -static __inline__ void *__attribute__((__always_inline__, __malloc__)) _mm_malloc(size_t __size, size_t __align) +static __inline__ void* __attribute__((__always_inline__, __malloc__)) _mm_malloc(size_t __size, + size_t __align) { - if (__align == 1) { - return malloc(__size); - } + if(__align == 1) + { + return malloc(__size); + } - if (!(__align & (__align - 1)) && __align < sizeof(void *)) - __align = sizeof(void *); + if(!(__align & (__align - 1)) && __align < sizeof(void*)) + { + __align = sizeof(void*); + } - void *__mallocedMemory; - if (posix_memalign(&__mallocedMemory, __align, __size)) { - return 0; - } + void* __mallocedMemory; + if(posix_memalign(&__mallocedMemory, __align, __size)) + { + return 0; + } - return __mallocedMemory; + return __mallocedMemory; } -static __inline__ void __attribute__((__always_inline__)) _mm_free(void *__p) +static __inline__ void __attribute__((__always_inline__)) _mm_free(void* __p) { - free(__p); + free(__p); } #endif /* __ALIGNED_MALLOC_H__ */ diff --git a/src/3rdparty/getopt/getopt.h b/src/3rdparty/getopt/getopt.h index bcbff179..5a918cb5 100644 --- a/src/3rdparty/getopt/getopt.h +++ b/src/3rdparty/getopt/getopt.h @@ -3,30 +3,30 @@ * 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 + * 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 - * - * 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) 2002 Todd C. Miller +* +* 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. @@ -82,7 +82,7 @@ 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 */ +char* optarg; /* argument associated with option */ #endif //extern int optind; /* index of first non-option in argv */ @@ -106,7 +106,7 @@ char *optarg; /* argument associated with option */ #ifndef __CYGWIN__ #define __progname __argv[0] #else -extern char __declspec(dllimport) *__progname; +extern char __declspec(dllimport)* __progname; #endif #ifdef __CYGWIN__ @@ -115,14 +115,14 @@ static char EMSG[] = ""; #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 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 void permute_args(int, int, int, char* const*); -static char *place = EMSG; /* option letter processing */ +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) */ @@ -137,21 +137,23 @@ static const char illoptchar[] = "unknown option -- %c"; static const char illoptstring[] = "unknown option -- %s"; static void -_vwarnx(const char *fmt,va_list ap) +_vwarnx(const char* fmt, va_list ap) { - (void)fprintf(stderr,"%s: ",__progname); - if (fmt != NULL) - (void)vfprintf(stderr,fmt,ap); - (void)fprintf(stderr,"\n"); + (void)fprintf(stderr, "%s: ", __progname); + if(fmt != NULL) + { + (void)vfprintf(stderr, fmt, ap); + } + (void)fprintf(stderr, "\n"); } static void -warnx(const char *fmt,...) +warnx(const char* fmt, ...) { - va_list ap; - va_start(ap,fmt); - _vwarnx(fmt,ap); - va_end(ap); + va_list ap; + va_start(ap, fmt); + _vwarnx(fmt, ap); + va_end(ap); } /* @@ -163,7 +165,8 @@ gcd(int a, int b) int c; c = a % b; - while (c != 0) { + while(c != 0) + { a = b; b = c; c = a % b; @@ -179,10 +182,10 @@ gcd(int a, int b) */ static void permute_args(int panonopt_start, int panonopt_end, int opt_end, - char * const *nargv) + char* const* nargv) { int cstart, cyclelen, i, j, ncycle, nnonopts, nopts, pos; - char *swap; + char* swap; /* * compute lengths of blocks and number and size of cycles @@ -192,19 +195,25 @@ permute_args(int panonopt_start, int panonopt_end, int opt_end, ncycle = gcd(nnonopts, nopts); cyclelen = (opt_end - panonopt_start) / ncycle; - for (i = 0; i < ncycle; i++) { - cstart = panonopt_end+i; + for(i = 0; i < ncycle; i++) + { + cstart = panonopt_end + i; pos = cstart; - for (j = 0; j < cyclelen; j++) { - if (pos >= panonopt_end) + 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]; + ((char**) nargv)[pos] = nargv[cstart]; /* LINTED const cast */ - ((char **)nargv)[cstart] = swap; + ((char**)nargv)[cstart] = swap; } } } @@ -217,7 +226,7 @@ permute_args(int panonopt_start, int panonopt_end, int opt_end, * [eventually this will replace the BSD getopt] */ int -getopt(int nargc, char * const *nargv, const char *options) +getopt(int nargc, char* const* nargv, const char* options) { /* @@ -267,17 +276,17 @@ extern "C" { 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 */ + 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 */ + no_argument = 0, /* option never takes an argument */ + required_argument, /* option always requires an argument */ + optional_argument /* option may take an argument */ }; /* @@ -286,10 +295,10 @@ enum /* permitted values for its `has_arg' field... */ * 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) +parse_long_options(char* const* nargv, const char* options, + const struct option* long_options, int* idx, int short_too) { - char *current_argv, *has_equal; + char* current_argv, *has_equal; size_t current_argv_len; int i, ambiguous, match; @@ -304,20 +313,28 @@ parse_long_options(char * const *nargv, const char *options, optind++; - if ((has_equal = strchr(current_argv, '=')) != NULL) { + if((has_equal = strchr(current_argv, '=')) != NULL) + { /* argument found (--option=arg) */ current_argv_len = has_equal - current_argv; has_equal++; - } else + } + else + { current_argv_len = strlen(current_argv); + } - for (i = 0; long_options[i].name; i++) { + for(i = 0; long_options[i].name; i++) + { /* find matching long option */ - if (strncmp(current_argv, long_options[i].name, - current_argv_len)) + if(strncmp(current_argv, long_options[i].name, + current_argv_len)) + { continue; + } - if (strlen(long_options[i].name) == current_argv_len) { + if(strlen(long_options[i].name) == current_argv_len) + { /* exact match */ match = i; ambiguous = 0; @@ -327,85 +344,118 @@ parse_long_options(char * const *nargv, const char *options, * If this is a known short option, don't allow * a partial match of a single character. */ - if (short_too && current_argv_len == 1) + if(short_too && current_argv_len == 1) + { continue; + } - if (match == -1) /* partial match */ + if(match == -1) /* partial match */ + { match = i; - else if (!IDENTICAL_INTERPRETATION(i, match)) + } + else if(!IDENTICAL_INTERPRETATION(i, match)) + { ambiguous = 1; + } } - if (ambiguous) { + if(ambiguous) + { /* ambiguous abbreviation */ - if (PRINT_ERROR) + if(PRINT_ERROR) warnx(ambig, (int)current_argv_len, - current_argv); + current_argv); optopt = 0; return (BADCH); } - if (match != -1) { /* option found */ - if (long_options[match].has_arg == no_argument - && has_equal) { - if (PRINT_ERROR) + 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); + current_argv); /* * XXX: GNU sets optopt to val regardless of flag */ - if (long_options[match].flag == NULL) + 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) + 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) { + } + 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)) { + if((long_options[match].has_arg == required_argument) + && (optarg == NULL)) + { /* * Missing argument; leading ':' indicates no error * should be generated. */ - if (PRINT_ERROR) + if(PRINT_ERROR) warnx(recargstring, - current_argv); + current_argv); /* * XXX: GNU sets optopt to val regardless of flag */ - if (long_options[match].flag == NULL) + if(long_options[match].flag == NULL) + { optopt = long_options[match].val; + } else + { optopt = 0; + } --optind; return (BADARG); } - } else { /* unknown option */ - if (short_too) { + } + else /* unknown option */ + { + if(short_too) + { --optind; return (-1); } - if (PRINT_ERROR) + if(PRINT_ERROR) + { warnx(illoptstring, current_argv); + } optopt = 0; return (BADCH); } - if (idx) + if(idx) + { *idx = match; - if (long_options[match].flag) { + } + if(long_options[match].flag) + { *long_options[match].flag = long_options[match].val; return (0); - } else + } + else + { return (long_options[match].val); + } #undef IDENTICAL_INTERPRETATION } @@ -414,22 +464,26 @@ parse_long_options(char * const *nargv, const char *options, * 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) +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 */ + char* oli; /* option letter list index */ int optchar, short_too; static int posixly_correct = -1; - if (options == NULL) + 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) + if(optind == 0) + { optind = optreset = 1; + } /* * Disable GNU extensions if POSIXLY_CORRECT is set or options @@ -438,30 +492,44 @@ getopt_internal(int nargc, char * const *nargv, const char *options, * CV, 2009-12-14: Check POSIXLY_CORRECT anew if optind == 0 or * optreset != 0 for GNU compatibility. */ - if (posixly_correct == -1 || optreset != 0) + if(posixly_correct == -1 || optreset != 0) + { posixly_correct = (getenv("POSIXLY_CORRECT") != NULL); - if (*options == '-') + } + if(*options == '-') + { flags |= FLAG_ALLARGS; - else if (posixly_correct || *options == '+') + } + else if(posixly_correct || *options == '+') + { flags &= ~FLAG_PERMUTE; - if (*options == '+' || *options == '-') + } + if(*options == '+' || *options == '-') + { options++; + } optarg = NULL; - if (optreset) + if(optreset) + { nonopt_start = nonopt_end = -1; + } start: - if (optreset || !*place) { /* update scanning pointer */ + if(optreset || !*place) /* update scanning pointer */ + { optreset = 0; - if (optind >= nargc) { /* end of argument vector */ + if(optind >= nargc) /* end of argument vector */ + { place = EMSG; - if (nonopt_end != -1) { + if(nonopt_end != -1) + { /* do permutation, if we have to */ permute_args(nonopt_start, nonopt_end, - optind, nargv); + optind, nargv); optind -= nonopt_end - nonopt_start; } - else if (nonopt_start != -1) { + else if(nonopt_start != -1) + { /* * If we skipped non-options, set optind * to the first of them. @@ -471,10 +539,12 @@ start: nonopt_start = nonopt_end = -1; return (-1); } - if (*(place = nargv[optind]) != '-' || - (place[1] == '\0' && strchr(options, '-') == NULL)) { + if(*(place = nargv[optind]) != '-' || + (place[1] == '\0' && strchr(options, '-') == NULL)) + { place = EMSG; /* found non-option */ - if (flags & FLAG_ALLARGS) { + if(flags & FLAG_ALLARGS) + { /* * GNU extension: * return non-option as argument to option 1 @@ -482,7 +552,8 @@ start: optarg = nargv[optind++]; return (INORDER); } - if (!(flags & FLAG_PERMUTE)) { + if(!(flags & FLAG_PERMUTE)) + { /* * If no permutation wanted, stop parsing * at first non-option. @@ -490,35 +561,42 @@ start: return (-1); } /* do permutation */ - if (nonopt_start == -1) + if(nonopt_start == -1) + { nonopt_start = optind; - else if (nonopt_end != -1) { + } + else if(nonopt_end != -1) + { permute_args(nonopt_start, nonopt_end, - optind, nargv); + optind, nargv); nonopt_start = optind - - (nonopt_end - nonopt_start); + (nonopt_end - nonopt_start); nonopt_end = -1; } optind++; /* process next argument */ goto start; } - if (nonopt_start != -1 && nonopt_end == -1) + 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') { + 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) { + if(nonopt_end != -1) + { permute_args(nonopt_start, nonopt_end, - optind, nargv); + optind, nargv); optind -= nonopt_end - nonopt_start; } nonopt_start = nonopt_end = -1; @@ -532,72 +610,106 @@ start: * 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))) { + 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 */ + 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) { + 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((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') + if(optchar == (int)'-' && *place == '\0') + { return (-1); - if (!*place) + } + if(!*place) + { ++optind; - if (PRINT_ERROR) + } + if(PRINT_ERROR) + { warnx(illoptchar, optchar); + } optopt = optchar; return (BADCH); } - if (long_options != NULL && optchar == 'W' && oli[1] == ';') { + if(long_options != NULL && optchar == 'W' && oli[1] == ';') + { /* -W long-option */ - if (*place) /* no space */ + if(*place) /* no space */ /* NOTHING */; - else if (++optind >= nargc) { /* no arg */ + else if(++optind >= nargc) /* no arg */ + { place = EMSG; - if (PRINT_ERROR) + if(PRINT_ERROR) + { warnx(recargchar, optchar); + } optopt = optchar; return (BADARG); - } else /* white space */ + } + else /* white space */ + { place = nargv[optind]; + } optchar = parse_long_options(nargv, options, long_options, - idx, 0); + idx, 0); place = EMSG; return (optchar); } - if (*++oli != ':') { /* doesn't take argument */ - if (!*place) + if(*++oli != ':') /* doesn't take argument */ + { + if(!*place) + { ++optind; - } else { /* takes (optional) argument */ + } + } + else /* takes (optional) argument */ + { optarg = NULL; - if (*place) /* no white space */ + if(*place) /* no white space */ + { optarg = place; - else if (oli[1] != ':') { /* arg not optional */ - if (++optind >= nargc) { /* no arg */ + } + else if(oli[1] != ':') /* arg not optional */ + { + if(++optind >= nargc) /* no arg */ + { place = EMSG; - if (PRINT_ERROR) + if(PRINT_ERROR) + { warnx(recargchar, optchar); + } optopt = optchar; return (BADARG); - } else + } + else + { optarg = nargv[optind]; + } } place = EMSG; ++optind; @@ -611,12 +723,12 @@ start: * Parse argc/argv argument vector. */ int -getopt_long(int nargc, char * const *nargv, const char *options, - const struct option *long_options, int *idx) +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)); + FLAG_PERMUTE)); } /* @@ -624,12 +736,12 @@ getopt_long(int nargc, char * const *nargv, const char *options, * Parse argc/argv argument vector. */ int -getopt_long_only(int nargc, char * const *nargv, const char *options, - const struct option *long_options, int *idx) +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)); + FLAG_PERMUTE | FLAG_LONGONLY)); } //extern int getopt_long(int nargc, char * const *nargv, const char *options, diff --git a/src/3rdparty/libcpuid/amd_code_t.h b/src/3rdparty/libcpuid/amd_code_t.h index 058e8957..1349bda3 100644 --- a/src/3rdparty/libcpuid/amd_code_t.h +++ b/src/3rdparty/libcpuid/amd_code_t.h @@ -28,12 +28,12 @@ * This file contains a list of internal codes we use in detection. It is * of no external use and isn't a complete list of AMD products. */ - CODE2(OPTERON_800, 1000), - CODE(PHENOM), - CODE(PHENOM2), - CODE(FUSION_C), - CODE(FUSION_E), - CODE(FUSION_EA), - CODE(FUSION_Z), - CODE(FUSION_A), - +CODE2(OPTERON_800, 1000), + CODE(PHENOM), + CODE(PHENOM2), + CODE(FUSION_C), + CODE(FUSION_E), + CODE(FUSION_EA), + CODE(FUSION_Z), + CODE(FUSION_A), + diff --git a/src/3rdparty/libcpuid/asm-bits.c b/src/3rdparty/libcpuid/asm-bits.c index b8e32284..1a00c91f 100644 --- a/src/3rdparty/libcpuid/asm-bits.c +++ b/src/3rdparty/libcpuid/asm-bits.c @@ -35,24 +35,25 @@ int cpuid_exists_by_eflags(void) # if defined(COMPILER_GCC) int result; __asm __volatile( - " pushfl\n" - " pop %%eax\n" - " mov %%eax, %%ecx\n" - " xor $0x200000, %%eax\n" - " push %%eax\n" - " popfl\n" - " pushfl\n" - " pop %%eax\n" - " xor %%ecx, %%eax\n" - " mov %%eax, %0\n" - " push %%ecx\n" - " popfl\n" - : "=m"(result) - : :"eax", "ecx", "memory"); + " pushfl\n" + " pop %%eax\n" + " mov %%eax, %%ecx\n" + " xor $0x200000, %%eax\n" + " push %%eax\n" + " popfl\n" + " pushfl\n" + " pop %%eax\n" + " xor %%ecx, %%eax\n" + " mov %%eax, %0\n" + " push %%ecx\n" + " popfl\n" + : "=m"(result) + : : "eax", "ecx", "memory"); return (result != 0); # elif defined(COMPILER_MICROSOFT) int result; - __asm { + __asm + { pushfd pop eax mov ecx, eax @@ -76,87 +77,88 @@ int cpuid_exists_by_eflags(void) } #ifdef INLINE_ASM_SUPPORTED -/* +/* * with MSVC/AMD64, the exec_cpuid() and cpu_rdtsc() functions * are implemented in separate .asm files. Otherwise, use inline assembly */ -void exec_cpuid(uint32_t *regs) +void exec_cpuid(uint32_t* regs) { #ifdef COMPILER_GCC # ifdef PLATFORM_X64 __asm __volatile( - " mov %0, %%rdi\n" + " mov %0, %%rdi\n" - " push %%rbx\n" - " push %%rcx\n" - " push %%rdx\n" - - " mov (%%rdi), %%eax\n" - " mov 4(%%rdi), %%ebx\n" - " mov 8(%%rdi), %%ecx\n" - " mov 12(%%rdi), %%edx\n" - - " cpuid\n" - - " movl %%eax, (%%rdi)\n" - " movl %%ebx, 4(%%rdi)\n" - " movl %%ecx, 8(%%rdi)\n" - " movl %%edx, 12(%%rdi)\n" - " pop %%rdx\n" - " pop %%rcx\n" - " pop %%rbx\n" - : - :"m"(regs) - :"memory", "eax", "rdi" + " push %%rbx\n" + " push %%rcx\n" + " push %%rdx\n" + + " mov (%%rdi), %%eax\n" + " mov 4(%%rdi), %%ebx\n" + " mov 8(%%rdi), %%ecx\n" + " mov 12(%%rdi), %%edx\n" + + " cpuid\n" + + " movl %%eax, (%%rdi)\n" + " movl %%ebx, 4(%%rdi)\n" + " movl %%ecx, 8(%%rdi)\n" + " movl %%edx, 12(%%rdi)\n" + " pop %%rdx\n" + " pop %%rcx\n" + " pop %%rbx\n" + : + : "m"(regs) + : "memory", "eax", "rdi" ); # else __asm __volatile( - " mov %0, %%edi\n" + " mov %0, %%edi\n" - " push %%ebx\n" - " push %%ecx\n" - " push %%edx\n" - - " mov (%%edi), %%eax\n" - " mov 4(%%edi), %%ebx\n" - " mov 8(%%edi), %%ecx\n" - " mov 12(%%edi), %%edx\n" - - " cpuid\n" - - " mov %%eax, (%%edi)\n" - " mov %%ebx, 4(%%edi)\n" - " mov %%ecx, 8(%%edi)\n" - " mov %%edx, 12(%%edi)\n" - " pop %%edx\n" - " pop %%ecx\n" - " pop %%ebx\n" - : - :"m"(regs) - :"memory", "eax", "edi" + " push %%ebx\n" + " push %%ecx\n" + " push %%edx\n" + + " mov (%%edi), %%eax\n" + " mov 4(%%edi), %%ebx\n" + " mov 8(%%edi), %%ecx\n" + " mov 12(%%edi), %%edx\n" + + " cpuid\n" + + " mov %%eax, (%%edi)\n" + " mov %%ebx, 4(%%edi)\n" + " mov %%ecx, 8(%%edi)\n" + " mov %%edx, 12(%%edi)\n" + " pop %%edx\n" + " pop %%ecx\n" + " pop %%ebx\n" + : + : "m"(regs) + : "memory", "eax", "edi" ); # endif /* COMPILER_GCC */ #else # ifdef COMPILER_MICROSOFT - __asm { + __asm + { push ebx push ecx push edx push edi mov edi, regs - + mov eax, [edi] mov ebx, [edi+4] mov ecx, [edi+8] mov edx, [edi+12] - + cpuid - + mov [edi], eax mov [edi+4], ebx mov [edi+8], ecx mov [edi+12], edx - + pop edi pop edx pop ecx @@ -174,15 +176,16 @@ void cpu_rdtsc(uint64_t* result) { uint32_t low_part, hi_part; #ifdef COMPILER_GCC - __asm __volatile ( - " rdtsc\n" - " mov %%eax, %0\n" - " mov %%edx, %1\n" - :"=m"(low_part), "=m"(hi_part)::"memory", "eax", "edx" + __asm __volatile( + " rdtsc\n" + " mov %%eax, %0\n" + " mov %%edx, %1\n" + : "=m"(low_part), "=m"(hi_part)::"memory", "eax", "edx" ); #else # ifdef COMPILER_MICROSOFT - __asm { + __asm + { rdtsc mov low_part, eax mov hi_part, edx @@ -204,315 +207,316 @@ void busy_sse_loop(int cycles) #else # define XALIGN ".align 4\n" #endif - __asm __volatile ( - " xorps %%xmm0, %%xmm0\n" - " xorps %%xmm1, %%xmm1\n" - " xorps %%xmm2, %%xmm2\n" - " xorps %%xmm3, %%xmm3\n" - " xorps %%xmm4, %%xmm4\n" - " xorps %%xmm5, %%xmm5\n" - " xorps %%xmm6, %%xmm6\n" - " xorps %%xmm7, %%xmm7\n" - XALIGN - /* ".bsLoop:\n" */ - "1:\n" - // 0: - " addps %%xmm1, %%xmm0\n" - " addps %%xmm2, %%xmm1\n" - " addps %%xmm3, %%xmm2\n" - " addps %%xmm4, %%xmm3\n" - " addps %%xmm5, %%xmm4\n" - " addps %%xmm6, %%xmm5\n" - " addps %%xmm7, %%xmm6\n" - " addps %%xmm0, %%xmm7\n" - // 1: - " addps %%xmm1, %%xmm0\n" - " addps %%xmm2, %%xmm1\n" - " addps %%xmm3, %%xmm2\n" - " addps %%xmm4, %%xmm3\n" - " addps %%xmm5, %%xmm4\n" - " addps %%xmm6, %%xmm5\n" - " addps %%xmm7, %%xmm6\n" - " addps %%xmm0, %%xmm7\n" - // 2: - " addps %%xmm1, %%xmm0\n" - " addps %%xmm2, %%xmm1\n" - " addps %%xmm3, %%xmm2\n" - " addps %%xmm4, %%xmm3\n" - " addps %%xmm5, %%xmm4\n" - " addps %%xmm6, %%xmm5\n" - " addps %%xmm7, %%xmm6\n" - " addps %%xmm0, %%xmm7\n" - // 3: - " addps %%xmm1, %%xmm0\n" - " addps %%xmm2, %%xmm1\n" - " addps %%xmm3, %%xmm2\n" - " addps %%xmm4, %%xmm3\n" - " addps %%xmm5, %%xmm4\n" - " addps %%xmm6, %%xmm5\n" - " addps %%xmm7, %%xmm6\n" - " addps %%xmm0, %%xmm7\n" - // 4: - " addps %%xmm1, %%xmm0\n" - " addps %%xmm2, %%xmm1\n" - " addps %%xmm3, %%xmm2\n" - " addps %%xmm4, %%xmm3\n" - " addps %%xmm5, %%xmm4\n" - " addps %%xmm6, %%xmm5\n" - " addps %%xmm7, %%xmm6\n" - " addps %%xmm0, %%xmm7\n" - // 5: - " addps %%xmm1, %%xmm0\n" - " addps %%xmm2, %%xmm1\n" - " addps %%xmm3, %%xmm2\n" - " addps %%xmm4, %%xmm3\n" - " addps %%xmm5, %%xmm4\n" - " addps %%xmm6, %%xmm5\n" - " addps %%xmm7, %%xmm6\n" - " addps %%xmm0, %%xmm7\n" - // 6: - " addps %%xmm1, %%xmm0\n" - " addps %%xmm2, %%xmm1\n" - " addps %%xmm3, %%xmm2\n" - " addps %%xmm4, %%xmm3\n" - " addps %%xmm5, %%xmm4\n" - " addps %%xmm6, %%xmm5\n" - " addps %%xmm7, %%xmm6\n" - " addps %%xmm0, %%xmm7\n" - // 7: - " addps %%xmm1, %%xmm0\n" - " addps %%xmm2, %%xmm1\n" - " addps %%xmm3, %%xmm2\n" - " addps %%xmm4, %%xmm3\n" - " addps %%xmm5, %%xmm4\n" - " addps %%xmm6, %%xmm5\n" - " addps %%xmm7, %%xmm6\n" - " addps %%xmm0, %%xmm7\n" - // 8: - " addps %%xmm1, %%xmm0\n" - " addps %%xmm2, %%xmm1\n" - " addps %%xmm3, %%xmm2\n" - " addps %%xmm4, %%xmm3\n" - " addps %%xmm5, %%xmm4\n" - " addps %%xmm6, %%xmm5\n" - " addps %%xmm7, %%xmm6\n" - " addps %%xmm0, %%xmm7\n" - // 9: - " addps %%xmm1, %%xmm0\n" - " addps %%xmm2, %%xmm1\n" - " addps %%xmm3, %%xmm2\n" - " addps %%xmm4, %%xmm3\n" - " addps %%xmm5, %%xmm4\n" - " addps %%xmm6, %%xmm5\n" - " addps %%xmm7, %%xmm6\n" - " addps %%xmm0, %%xmm7\n" - //10: - " addps %%xmm1, %%xmm0\n" - " addps %%xmm2, %%xmm1\n" - " addps %%xmm3, %%xmm2\n" - " addps %%xmm4, %%xmm3\n" - " addps %%xmm5, %%xmm4\n" - " addps %%xmm6, %%xmm5\n" - " addps %%xmm7, %%xmm6\n" - " addps %%xmm0, %%xmm7\n" - //11: - " addps %%xmm1, %%xmm0\n" - " addps %%xmm2, %%xmm1\n" - " addps %%xmm3, %%xmm2\n" - " addps %%xmm4, %%xmm3\n" - " addps %%xmm5, %%xmm4\n" - " addps %%xmm6, %%xmm5\n" - " addps %%xmm7, %%xmm6\n" - " addps %%xmm0, %%xmm7\n" - //12: - " addps %%xmm1, %%xmm0\n" - " addps %%xmm2, %%xmm1\n" - " addps %%xmm3, %%xmm2\n" - " addps %%xmm4, %%xmm3\n" - " addps %%xmm5, %%xmm4\n" - " addps %%xmm6, %%xmm5\n" - " addps %%xmm7, %%xmm6\n" - " addps %%xmm0, %%xmm7\n" - //13: - " addps %%xmm1, %%xmm0\n" - " addps %%xmm2, %%xmm1\n" - " addps %%xmm3, %%xmm2\n" - " addps %%xmm4, %%xmm3\n" - " addps %%xmm5, %%xmm4\n" - " addps %%xmm6, %%xmm5\n" - " addps %%xmm7, %%xmm6\n" - " addps %%xmm0, %%xmm7\n" - //14: - " addps %%xmm1, %%xmm0\n" - " addps %%xmm2, %%xmm1\n" - " addps %%xmm3, %%xmm2\n" - " addps %%xmm4, %%xmm3\n" - " addps %%xmm5, %%xmm4\n" - " addps %%xmm6, %%xmm5\n" - " addps %%xmm7, %%xmm6\n" - " addps %%xmm0, %%xmm7\n" - //15: - " addps %%xmm1, %%xmm0\n" - " addps %%xmm2, %%xmm1\n" - " addps %%xmm3, %%xmm2\n" - " addps %%xmm4, %%xmm3\n" - " addps %%xmm5, %%xmm4\n" - " addps %%xmm6, %%xmm5\n" - " addps %%xmm7, %%xmm6\n" - " addps %%xmm0, %%xmm7\n" - //16: - " addps %%xmm1, %%xmm0\n" - " addps %%xmm2, %%xmm1\n" - " addps %%xmm3, %%xmm2\n" - " addps %%xmm4, %%xmm3\n" - " addps %%xmm5, %%xmm4\n" - " addps %%xmm6, %%xmm5\n" - " addps %%xmm7, %%xmm6\n" - " addps %%xmm0, %%xmm7\n" - //17: - " addps %%xmm1, %%xmm0\n" - " addps %%xmm2, %%xmm1\n" - " addps %%xmm3, %%xmm2\n" - " addps %%xmm4, %%xmm3\n" - " addps %%xmm5, %%xmm4\n" - " addps %%xmm6, %%xmm5\n" - " addps %%xmm7, %%xmm6\n" - " addps %%xmm0, %%xmm7\n" - //18: - " addps %%xmm1, %%xmm0\n" - " addps %%xmm2, %%xmm1\n" - " addps %%xmm3, %%xmm2\n" - " addps %%xmm4, %%xmm3\n" - " addps %%xmm5, %%xmm4\n" - " addps %%xmm6, %%xmm5\n" - " addps %%xmm7, %%xmm6\n" - " addps %%xmm0, %%xmm7\n" - //19: - " addps %%xmm1, %%xmm0\n" - " addps %%xmm2, %%xmm1\n" - " addps %%xmm3, %%xmm2\n" - " addps %%xmm4, %%xmm3\n" - " addps %%xmm5, %%xmm4\n" - " addps %%xmm6, %%xmm5\n" - " addps %%xmm7, %%xmm6\n" - " addps %%xmm0, %%xmm7\n" - //20: - " addps %%xmm1, %%xmm0\n" - " addps %%xmm2, %%xmm1\n" - " addps %%xmm3, %%xmm2\n" - " addps %%xmm4, %%xmm3\n" - " addps %%xmm5, %%xmm4\n" - " addps %%xmm6, %%xmm5\n" - " addps %%xmm7, %%xmm6\n" - " addps %%xmm0, %%xmm7\n" - //21: - " addps %%xmm1, %%xmm0\n" - " addps %%xmm2, %%xmm1\n" - " addps %%xmm3, %%xmm2\n" - " addps %%xmm4, %%xmm3\n" - " addps %%xmm5, %%xmm4\n" - " addps %%xmm6, %%xmm5\n" - " addps %%xmm7, %%xmm6\n" - " addps %%xmm0, %%xmm7\n" - //22: - " addps %%xmm1, %%xmm0\n" - " addps %%xmm2, %%xmm1\n" - " addps %%xmm3, %%xmm2\n" - " addps %%xmm4, %%xmm3\n" - " addps %%xmm5, %%xmm4\n" - " addps %%xmm6, %%xmm5\n" - " addps %%xmm7, %%xmm6\n" - " addps %%xmm0, %%xmm7\n" - //23: - " addps %%xmm1, %%xmm0\n" - " addps %%xmm2, %%xmm1\n" - " addps %%xmm3, %%xmm2\n" - " addps %%xmm4, %%xmm3\n" - " addps %%xmm5, %%xmm4\n" - " addps %%xmm6, %%xmm5\n" - " addps %%xmm7, %%xmm6\n" - " addps %%xmm0, %%xmm7\n" - //24: - " addps %%xmm1, %%xmm0\n" - " addps %%xmm2, %%xmm1\n" - " addps %%xmm3, %%xmm2\n" - " addps %%xmm4, %%xmm3\n" - " addps %%xmm5, %%xmm4\n" - " addps %%xmm6, %%xmm5\n" - " addps %%xmm7, %%xmm6\n" - " addps %%xmm0, %%xmm7\n" - //25: - " addps %%xmm1, %%xmm0\n" - " addps %%xmm2, %%xmm1\n" - " addps %%xmm3, %%xmm2\n" - " addps %%xmm4, %%xmm3\n" - " addps %%xmm5, %%xmm4\n" - " addps %%xmm6, %%xmm5\n" - " addps %%xmm7, %%xmm6\n" - " addps %%xmm0, %%xmm7\n" - //26: - " addps %%xmm1, %%xmm0\n" - " addps %%xmm2, %%xmm1\n" - " addps %%xmm3, %%xmm2\n" - " addps %%xmm4, %%xmm3\n" - " addps %%xmm5, %%xmm4\n" - " addps %%xmm6, %%xmm5\n" - " addps %%xmm7, %%xmm6\n" - " addps %%xmm0, %%xmm7\n" - //27: - " addps %%xmm1, %%xmm0\n" - " addps %%xmm2, %%xmm1\n" - " addps %%xmm3, %%xmm2\n" - " addps %%xmm4, %%xmm3\n" - " addps %%xmm5, %%xmm4\n" - " addps %%xmm6, %%xmm5\n" - " addps %%xmm7, %%xmm6\n" - " addps %%xmm0, %%xmm7\n" - //28: - " addps %%xmm1, %%xmm0\n" - " addps %%xmm2, %%xmm1\n" - " addps %%xmm3, %%xmm2\n" - " addps %%xmm4, %%xmm3\n" - " addps %%xmm5, %%xmm4\n" - " addps %%xmm6, %%xmm5\n" - " addps %%xmm7, %%xmm6\n" - " addps %%xmm0, %%xmm7\n" - //29: - " addps %%xmm1, %%xmm0\n" - " addps %%xmm2, %%xmm1\n" - " addps %%xmm3, %%xmm2\n" - " addps %%xmm4, %%xmm3\n" - " addps %%xmm5, %%xmm4\n" - " addps %%xmm6, %%xmm5\n" - " addps %%xmm7, %%xmm6\n" - " addps %%xmm0, %%xmm7\n" - //30: - " addps %%xmm1, %%xmm0\n" - " addps %%xmm2, %%xmm1\n" - " addps %%xmm3, %%xmm2\n" - " addps %%xmm4, %%xmm3\n" - " addps %%xmm5, %%xmm4\n" - " addps %%xmm6, %%xmm5\n" - " addps %%xmm7, %%xmm6\n" - " addps %%xmm0, %%xmm7\n" - //31: - " addps %%xmm1, %%xmm0\n" - " addps %%xmm2, %%xmm1\n" - " addps %%xmm3, %%xmm2\n" - " addps %%xmm4, %%xmm3\n" - " addps %%xmm5, %%xmm4\n" - " addps %%xmm6, %%xmm5\n" - " addps %%xmm7, %%xmm6\n" - " addps %%xmm0, %%xmm7\n" - - " dec %%eax\n" - /* "jnz .bsLoop\n" */ - " jnz 1b\n" - ::"a"(cycles) + __asm __volatile( + " xorps %%xmm0, %%xmm0\n" + " xorps %%xmm1, %%xmm1\n" + " xorps %%xmm2, %%xmm2\n" + " xorps %%xmm3, %%xmm3\n" + " xorps %%xmm4, %%xmm4\n" + " xorps %%xmm5, %%xmm5\n" + " xorps %%xmm6, %%xmm6\n" + " xorps %%xmm7, %%xmm7\n" + XALIGN + /* ".bsLoop:\n" */ + "1:\n" + // 0: + " addps %%xmm1, %%xmm0\n" + " addps %%xmm2, %%xmm1\n" + " addps %%xmm3, %%xmm2\n" + " addps %%xmm4, %%xmm3\n" + " addps %%xmm5, %%xmm4\n" + " addps %%xmm6, %%xmm5\n" + " addps %%xmm7, %%xmm6\n" + " addps %%xmm0, %%xmm7\n" + // 1: + " addps %%xmm1, %%xmm0\n" + " addps %%xmm2, %%xmm1\n" + " addps %%xmm3, %%xmm2\n" + " addps %%xmm4, %%xmm3\n" + " addps %%xmm5, %%xmm4\n" + " addps %%xmm6, %%xmm5\n" + " addps %%xmm7, %%xmm6\n" + " addps %%xmm0, %%xmm7\n" + // 2: + " addps %%xmm1, %%xmm0\n" + " addps %%xmm2, %%xmm1\n" + " addps %%xmm3, %%xmm2\n" + " addps %%xmm4, %%xmm3\n" + " addps %%xmm5, %%xmm4\n" + " addps %%xmm6, %%xmm5\n" + " addps %%xmm7, %%xmm6\n" + " addps %%xmm0, %%xmm7\n" + // 3: + " addps %%xmm1, %%xmm0\n" + " addps %%xmm2, %%xmm1\n" + " addps %%xmm3, %%xmm2\n" + " addps %%xmm4, %%xmm3\n" + " addps %%xmm5, %%xmm4\n" + " addps %%xmm6, %%xmm5\n" + " addps %%xmm7, %%xmm6\n" + " addps %%xmm0, %%xmm7\n" + // 4: + " addps %%xmm1, %%xmm0\n" + " addps %%xmm2, %%xmm1\n" + " addps %%xmm3, %%xmm2\n" + " addps %%xmm4, %%xmm3\n" + " addps %%xmm5, %%xmm4\n" + " addps %%xmm6, %%xmm5\n" + " addps %%xmm7, %%xmm6\n" + " addps %%xmm0, %%xmm7\n" + // 5: + " addps %%xmm1, %%xmm0\n" + " addps %%xmm2, %%xmm1\n" + " addps %%xmm3, %%xmm2\n" + " addps %%xmm4, %%xmm3\n" + " addps %%xmm5, %%xmm4\n" + " addps %%xmm6, %%xmm5\n" + " addps %%xmm7, %%xmm6\n" + " addps %%xmm0, %%xmm7\n" + // 6: + " addps %%xmm1, %%xmm0\n" + " addps %%xmm2, %%xmm1\n" + " addps %%xmm3, %%xmm2\n" + " addps %%xmm4, %%xmm3\n" + " addps %%xmm5, %%xmm4\n" + " addps %%xmm6, %%xmm5\n" + " addps %%xmm7, %%xmm6\n" + " addps %%xmm0, %%xmm7\n" + // 7: + " addps %%xmm1, %%xmm0\n" + " addps %%xmm2, %%xmm1\n" + " addps %%xmm3, %%xmm2\n" + " addps %%xmm4, %%xmm3\n" + " addps %%xmm5, %%xmm4\n" + " addps %%xmm6, %%xmm5\n" + " addps %%xmm7, %%xmm6\n" + " addps %%xmm0, %%xmm7\n" + // 8: + " addps %%xmm1, %%xmm0\n" + " addps %%xmm2, %%xmm1\n" + " addps %%xmm3, %%xmm2\n" + " addps %%xmm4, %%xmm3\n" + " addps %%xmm5, %%xmm4\n" + " addps %%xmm6, %%xmm5\n" + " addps %%xmm7, %%xmm6\n" + " addps %%xmm0, %%xmm7\n" + // 9: + " addps %%xmm1, %%xmm0\n" + " addps %%xmm2, %%xmm1\n" + " addps %%xmm3, %%xmm2\n" + " addps %%xmm4, %%xmm3\n" + " addps %%xmm5, %%xmm4\n" + " addps %%xmm6, %%xmm5\n" + " addps %%xmm7, %%xmm6\n" + " addps %%xmm0, %%xmm7\n" + //10: + " addps %%xmm1, %%xmm0\n" + " addps %%xmm2, %%xmm1\n" + " addps %%xmm3, %%xmm2\n" + " addps %%xmm4, %%xmm3\n" + " addps %%xmm5, %%xmm4\n" + " addps %%xmm6, %%xmm5\n" + " addps %%xmm7, %%xmm6\n" + " addps %%xmm0, %%xmm7\n" + //11: + " addps %%xmm1, %%xmm0\n" + " addps %%xmm2, %%xmm1\n" + " addps %%xmm3, %%xmm2\n" + " addps %%xmm4, %%xmm3\n" + " addps %%xmm5, %%xmm4\n" + " addps %%xmm6, %%xmm5\n" + " addps %%xmm7, %%xmm6\n" + " addps %%xmm0, %%xmm7\n" + //12: + " addps %%xmm1, %%xmm0\n" + " addps %%xmm2, %%xmm1\n" + " addps %%xmm3, %%xmm2\n" + " addps %%xmm4, %%xmm3\n" + " addps %%xmm5, %%xmm4\n" + " addps %%xmm6, %%xmm5\n" + " addps %%xmm7, %%xmm6\n" + " addps %%xmm0, %%xmm7\n" + //13: + " addps %%xmm1, %%xmm0\n" + " addps %%xmm2, %%xmm1\n" + " addps %%xmm3, %%xmm2\n" + " addps %%xmm4, %%xmm3\n" + " addps %%xmm5, %%xmm4\n" + " addps %%xmm6, %%xmm5\n" + " addps %%xmm7, %%xmm6\n" + " addps %%xmm0, %%xmm7\n" + //14: + " addps %%xmm1, %%xmm0\n" + " addps %%xmm2, %%xmm1\n" + " addps %%xmm3, %%xmm2\n" + " addps %%xmm4, %%xmm3\n" + " addps %%xmm5, %%xmm4\n" + " addps %%xmm6, %%xmm5\n" + " addps %%xmm7, %%xmm6\n" + " addps %%xmm0, %%xmm7\n" + //15: + " addps %%xmm1, %%xmm0\n" + " addps %%xmm2, %%xmm1\n" + " addps %%xmm3, %%xmm2\n" + " addps %%xmm4, %%xmm3\n" + " addps %%xmm5, %%xmm4\n" + " addps %%xmm6, %%xmm5\n" + " addps %%xmm7, %%xmm6\n" + " addps %%xmm0, %%xmm7\n" + //16: + " addps %%xmm1, %%xmm0\n" + " addps %%xmm2, %%xmm1\n" + " addps %%xmm3, %%xmm2\n" + " addps %%xmm4, %%xmm3\n" + " addps %%xmm5, %%xmm4\n" + " addps %%xmm6, %%xmm5\n" + " addps %%xmm7, %%xmm6\n" + " addps %%xmm0, %%xmm7\n" + //17: + " addps %%xmm1, %%xmm0\n" + " addps %%xmm2, %%xmm1\n" + " addps %%xmm3, %%xmm2\n" + " addps %%xmm4, %%xmm3\n" + " addps %%xmm5, %%xmm4\n" + " addps %%xmm6, %%xmm5\n" + " addps %%xmm7, %%xmm6\n" + " addps %%xmm0, %%xmm7\n" + //18: + " addps %%xmm1, %%xmm0\n" + " addps %%xmm2, %%xmm1\n" + " addps %%xmm3, %%xmm2\n" + " addps %%xmm4, %%xmm3\n" + " addps %%xmm5, %%xmm4\n" + " addps %%xmm6, %%xmm5\n" + " addps %%xmm7, %%xmm6\n" + " addps %%xmm0, %%xmm7\n" + //19: + " addps %%xmm1, %%xmm0\n" + " addps %%xmm2, %%xmm1\n" + " addps %%xmm3, %%xmm2\n" + " addps %%xmm4, %%xmm3\n" + " addps %%xmm5, %%xmm4\n" + " addps %%xmm6, %%xmm5\n" + " addps %%xmm7, %%xmm6\n" + " addps %%xmm0, %%xmm7\n" + //20: + " addps %%xmm1, %%xmm0\n" + " addps %%xmm2, %%xmm1\n" + " addps %%xmm3, %%xmm2\n" + " addps %%xmm4, %%xmm3\n" + " addps %%xmm5, %%xmm4\n" + " addps %%xmm6, %%xmm5\n" + " addps %%xmm7, %%xmm6\n" + " addps %%xmm0, %%xmm7\n" + //21: + " addps %%xmm1, %%xmm0\n" + " addps %%xmm2, %%xmm1\n" + " addps %%xmm3, %%xmm2\n" + " addps %%xmm4, %%xmm3\n" + " addps %%xmm5, %%xmm4\n" + " addps %%xmm6, %%xmm5\n" + " addps %%xmm7, %%xmm6\n" + " addps %%xmm0, %%xmm7\n" + //22: + " addps %%xmm1, %%xmm0\n" + " addps %%xmm2, %%xmm1\n" + " addps %%xmm3, %%xmm2\n" + " addps %%xmm4, %%xmm3\n" + " addps %%xmm5, %%xmm4\n" + " addps %%xmm6, %%xmm5\n" + " addps %%xmm7, %%xmm6\n" + " addps %%xmm0, %%xmm7\n" + //23: + " addps %%xmm1, %%xmm0\n" + " addps %%xmm2, %%xmm1\n" + " addps %%xmm3, %%xmm2\n" + " addps %%xmm4, %%xmm3\n" + " addps %%xmm5, %%xmm4\n" + " addps %%xmm6, %%xmm5\n" + " addps %%xmm7, %%xmm6\n" + " addps %%xmm0, %%xmm7\n" + //24: + " addps %%xmm1, %%xmm0\n" + " addps %%xmm2, %%xmm1\n" + " addps %%xmm3, %%xmm2\n" + " addps %%xmm4, %%xmm3\n" + " addps %%xmm5, %%xmm4\n" + " addps %%xmm6, %%xmm5\n" + " addps %%xmm7, %%xmm6\n" + " addps %%xmm0, %%xmm7\n" + //25: + " addps %%xmm1, %%xmm0\n" + " addps %%xmm2, %%xmm1\n" + " addps %%xmm3, %%xmm2\n" + " addps %%xmm4, %%xmm3\n" + " addps %%xmm5, %%xmm4\n" + " addps %%xmm6, %%xmm5\n" + " addps %%xmm7, %%xmm6\n" + " addps %%xmm0, %%xmm7\n" + //26: + " addps %%xmm1, %%xmm0\n" + " addps %%xmm2, %%xmm1\n" + " addps %%xmm3, %%xmm2\n" + " addps %%xmm4, %%xmm3\n" + " addps %%xmm5, %%xmm4\n" + " addps %%xmm6, %%xmm5\n" + " addps %%xmm7, %%xmm6\n" + " addps %%xmm0, %%xmm7\n" + //27: + " addps %%xmm1, %%xmm0\n" + " addps %%xmm2, %%xmm1\n" + " addps %%xmm3, %%xmm2\n" + " addps %%xmm4, %%xmm3\n" + " addps %%xmm5, %%xmm4\n" + " addps %%xmm6, %%xmm5\n" + " addps %%xmm7, %%xmm6\n" + " addps %%xmm0, %%xmm7\n" + //28: + " addps %%xmm1, %%xmm0\n" + " addps %%xmm2, %%xmm1\n" + " addps %%xmm3, %%xmm2\n" + " addps %%xmm4, %%xmm3\n" + " addps %%xmm5, %%xmm4\n" + " addps %%xmm6, %%xmm5\n" + " addps %%xmm7, %%xmm6\n" + " addps %%xmm0, %%xmm7\n" + //29: + " addps %%xmm1, %%xmm0\n" + " addps %%xmm2, %%xmm1\n" + " addps %%xmm3, %%xmm2\n" + " addps %%xmm4, %%xmm3\n" + " addps %%xmm5, %%xmm4\n" + " addps %%xmm6, %%xmm5\n" + " addps %%xmm7, %%xmm6\n" + " addps %%xmm0, %%xmm7\n" + //30: + " addps %%xmm1, %%xmm0\n" + " addps %%xmm2, %%xmm1\n" + " addps %%xmm3, %%xmm2\n" + " addps %%xmm4, %%xmm3\n" + " addps %%xmm5, %%xmm4\n" + " addps %%xmm6, %%xmm5\n" + " addps %%xmm7, %%xmm6\n" + " addps %%xmm0, %%xmm7\n" + //31: + " addps %%xmm1, %%xmm0\n" + " addps %%xmm2, %%xmm1\n" + " addps %%xmm3, %%xmm2\n" + " addps %%xmm4, %%xmm3\n" + " addps %%xmm5, %%xmm4\n" + " addps %%xmm6, %%xmm5\n" + " addps %%xmm7, %%xmm6\n" + " addps %%xmm0, %%xmm7\n" + + " dec %%eax\n" + /* "jnz .bsLoop\n" */ + " jnz 1b\n" + ::"a"(cycles) ); #else # ifdef COMPILER_MICROSOFT - __asm { + __asm + { mov eax, cycles xorps xmm0, xmm0 xorps xmm1, xmm1 @@ -524,7 +528,7 @@ void busy_sse_loop(int cycles) xorps xmm7, xmm7 //-- align 16 -bsLoop: + bsLoop: // 0: addps xmm0, xmm1 addps xmm1, xmm2 diff --git a/src/3rdparty/libcpuid/asm-bits.h b/src/3rdparty/libcpuid/asm-bits.h index 3a03e11c..c9f9d2e7 100644 --- a/src/3rdparty/libcpuid/asm-bits.h +++ b/src/3rdparty/libcpuid/asm-bits.h @@ -47,7 +47,7 @@ #endif int cpuid_exists_by_eflags(void); -void exec_cpuid(uint32_t *regs); +void exec_cpuid(uint32_t* regs); void busy_sse_loop(int cycles); #endif /* __ASM_BITS_H__ */ diff --git a/src/3rdparty/libcpuid/cpuid_main.c b/src/3rdparty/libcpuid/cpuid_main.c index f22c7dd6..1005cef7 100644 --- a/src/3rdparty/libcpuid/cpuid_main.c +++ b/src/3rdparty/libcpuid/cpuid_main.c @@ -36,6 +36,10 @@ #include #include +#ifndef VERSION +#define VERSION "7.10" +#endif + /* Implementation: */ static int _libcpiud_errno = ERR_OK; @@ -46,6 +50,11 @@ 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)); @@ -55,6 +64,37 @@ 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 @@ -69,7 +109,10 @@ static int get_total_cpus(void) host_flavor_t flavor = HOST_BASIC_INFO; mach_msg_type_number_t count = HOST_BASIC_INFO_COUNT; kr = host_info(mach_host_self(), flavor, info, &count); - if (kr != KERN_SUCCESS) return 1; + if(kr != KERN_SUCCESS) + { + return 1; + } return basic_info.avail_cpus; } #define GET_TOTAL_CPUS_DEFINED @@ -89,7 +132,7 @@ static int get_total_cpus(void) #if defined linux || defined __linux__ || defined __sun #include #include - + static int get_total_cpus(void) { return sysconf(_SC_NPROCESSORS_ONLN); @@ -106,7 +149,10 @@ static int get_total_cpus(void) int mib[2] = { CTL_HW, HW_NCPU }; int ncpus; size_t len = sizeof(ncpus); - if (sysctl(mib, 2, &ncpus, &len, (void *) 0, 0) != 0) return 1; + if(sysctl(mib, 2, &ncpus, &len, (void*) 0, 0) != 0) + { + return 1; + } return ncpus; } #define GET_TOTAL_CPUS_DEFINED @@ -116,7 +162,8 @@ static int get_total_cpus(void) static int get_total_cpus(void) { static int warning_printed = 0; - if (!warning_printed) { + if(!warning_printed) + { warning_printed = 1; warnf("Your system is not supported by libcpuid -- don't know how to detect the\n"); warnf("total number of CPUs on your system. It will be reported as 1.\n"); @@ -129,7 +176,8 @@ static int get_total_cpus(void) static void load_features_common(struct cpu_raw_data_t* raw, struct cpu_id_t* data) { - const struct feature_map_t matchtable_edx1[] = { + const struct feature_map_t matchtable_edx1[] = + { { 0, CPU_FEATURE_FPU }, { 1, CPU_FEATURE_VME }, { 2, CPU_FEATURE_DE }, @@ -154,7 +202,8 @@ static void load_features_common(struct cpu_raw_data_t* raw, struct cpu_id_t* da { 26, CPU_FEATURE_SSE2 }, { 28, CPU_FEATURE_HT }, }; - const struct feature_map_t matchtable_ecx1[] = { + const struct feature_map_t matchtable_ecx1[] = + { { 0, CPU_FEATURE_PNI }, { 1, CPU_FEATURE_PCLMUL }, { 3, CPU_FEATURE_MONITOR }, @@ -172,118 +221,145 @@ static void load_features_common(struct cpu_raw_data_t* raw, struct cpu_id_t* da { 29, CPU_FEATURE_F16C }, { 30, CPU_FEATURE_RDRAND }, }; - const struct feature_map_t matchtable_ebx7[] = { + const struct feature_map_t matchtable_ebx7[] = + { { 3, CPU_FEATURE_BMI1 }, { 5, CPU_FEATURE_AVX2 }, { 8, CPU_FEATURE_BMI2 }, }; - const struct feature_map_t matchtable_edx81[] = { + const struct feature_map_t matchtable_edx81[] = + { { 11, CPU_FEATURE_SYSCALL }, { 27, CPU_FEATURE_RDTSCP }, { 29, CPU_FEATURE_LM }, }; - const struct feature_map_t matchtable_ecx81[] = { + const struct feature_map_t matchtable_ecx81[] = + { { 0, CPU_FEATURE_LAHF_LM }, }; - const struct feature_map_t matchtable_edx87[] = { + const struct feature_map_t matchtable_edx87[] = + { { 8, CPU_FEATURE_CONSTANT_TSC }, }; - if (raw->basic_cpuid[0][0] >= 1) { + 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->basic_cpuid[0][0] >= 7) { + if(raw->basic_cpuid[0][0] >= 7) + { match_features(matchtable_ebx7, COUNT_OF(matchtable_ebx7), raw->basic_cpuid[7][1], data); } - if (raw->ext_cpuid[0][0] >= 0x80000001) { + 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) { + if(raw->ext_cpuid[0][0] >= 0x80000007) + { match_features(matchtable_edx87, COUNT_OF(matchtable_edx87), raw->ext_cpuid[7][3], data); } - if (data->flags[CPU_FEATURE_SSE]) { + if(data->flags[CPU_FEATURE_SSE]) + { /* apply guesswork to check if the SSE unit width is 128 bit */ - switch (data->vendor) { - case VENDOR_AMD: - data->sse_size = (data->ext_family >= 16 && data->ext_family != 17) ? 128 : 64; - break; - case VENDOR_INTEL: - data->sse_size = (data->family == 6 && data->ext_model >= 15) ? 128 : 64; - break; - default: - break; + switch(data->vendor) + { + case VENDOR_AMD: + data->sse_size = (data->ext_family >= 16 && data->ext_family != 17) ? 128 : 64; + break; + case VENDOR_INTEL: + data->sse_size = (data->family == 6 && data->ext_model >= 15) ? 128 : 64; + break; + default: + break; } /* leave the CPU_FEATURE_128BIT_SSE_AUTH 0; the advanced per-vendor detection routines * will set it accordingly if they detect the needed bit */ } } -static cpu_vendor_t cpuid_vendor_identify(const uint32_t *raw_vendor, char *vendor_str) +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) + if(data->vendor == VENDOR_UNKNOWN) + { return set_error(ERR_CPU_UNKN); + } basic = raw->basic_cpuid[0][0]; - if (basic >= 1) { + if(basic >= 1) + { data->family = (raw->basic_cpuid[1][0] >> 8) & 0xf; data->model = (raw->basic_cpuid[1][0] >> 4) & 0xf; data->stepping = raw->basic_cpuid[1][0] & 0xf; xmodel = (raw->basic_cpuid[1][0] >> 16) & 0xf; xfamily = (raw->basic_cpuid[1][0] >> 20) & 0xff; - if (data->vendor == VENDOR_AMD && data->family < 0xf) + if(data->vendor == VENDOR_AMD && data->family < 0xf) + { data->ext_family = data->family; + } else + { data->ext_family = data->family + xfamily; + } 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++) - for (j = 0; j < 4; j++) + if(ext >= 4) + { + for(i = 0; i < 3; i++) + for(j = 0; j < 4; j++) memcpy(brandstr + i * 16 + j * 4, &raw->ext_cpuid[2 + i][j], 4); brandstr[48] = 0; i = 0; - while (brandstr[i] == ' ') i++; + while(brandstr[i] == ' ') + { + i++; + } strncpy(data->brand_str, brandstr + i, sizeof(data->brand_str)); data->brand_str[48] = 0; } @@ -292,6 +368,31 @@ 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) @@ -319,31 +420,41 @@ void cpu_exec_cpuid_ext(uint32_t* regs) int cpuid_get_raw_data(struct cpu_raw_data_t* data) { unsigned i; - if (!cpuid_present()) + if(!cpuid_present()) + { return set_error(ERR_NO_CPUID); - for (i = 0; i < 32; i++) + } + for(i = 0; i < 32; i++) + { cpu_exec_cpuid(i, data->basic_cpuid[i]); - for (i = 0; i < 32; i++) + } + for(i = 0; i < 32; i++) + { cpu_exec_cpuid(0x80000000 + i, data->ext_cpuid[i]); - for (i = 0; i < MAX_INTELFN4_LEVEL; i++) { + } + for(i = 0; i < MAX_INTELFN4_LEVEL; i++) + { memset(data->intel_fn4[i], 0, sizeof(data->intel_fn4[i])); data->intel_fn4[i][0] = 4; data->intel_fn4[i][2] = i; cpu_exec_cpuid_ext(data->intel_fn4[i]); } - for (i = 0; i < MAX_INTELFN11_LEVEL; i++) { + for(i = 0; i < MAX_INTELFN11_LEVEL; i++) + { memset(data->intel_fn11[i], 0, sizeof(data->intel_fn11[i])); data->intel_fn11[i][0] = 11; data->intel_fn11[i][2] = i; cpu_exec_cpuid_ext(data->intel_fn11[i]); } - for (i = 0; i < MAX_INTELFN12H_LEVEL; i++) { + for(i = 0; i < MAX_INTELFN12H_LEVEL; i++) + { memset(data->intel_fn12h[i], 0, sizeof(data->intel_fn12h[i])); data->intel_fn12h[i][0] = 0x12; data->intel_fn12h[i][2] = i; cpu_exec_cpuid_ext(data->intel_fn12h[i]); } - for (i = 0; i < MAX_INTELFN14H_LEVEL; i++) { + for(i = 0; i < MAX_INTELFN14H_LEVEL; i++) + { memset(data->intel_fn14h[i], 0, sizeof(data->intel_fn14h[i])); data->intel_fn14h[i][0] = 0x14; data->intel_fn14h[i][2] = i; @@ -352,27 +463,167 @@ int cpuid_get_raw_data(struct cpu_raw_data_t* data) return set_error(ERR_OK); } +int cpuid_serialize_raw_data(struct cpu_raw_data_t* data, const char* filename) +{ + int i; + FILE* f; + + if(!strcmp(filename, "")) + { + f = stdout; + } + else + { + f = fopen(filename, "wt"); + } + if(!f) + { + return set_error(ERR_OPEN); + } + + fprintf(f, "version=%s\n", VERSION); + for(i = 0; i < MAX_CPUID_LEVEL; i++) + fprintf(f, "basic_cpuid[%d]=%08x %08x %08x %08x\n", i, + data->basic_cpuid[i][0], data->basic_cpuid[i][1], + data->basic_cpuid[i][2], data->basic_cpuid[i][3]); + for(i = 0; i < MAX_EXT_CPUID_LEVEL; i++) + fprintf(f, "ext_cpuid[%d]=%08x %08x %08x %08x\n", i, + data->ext_cpuid[i][0], data->ext_cpuid[i][1], + data->ext_cpuid[i][2], data->ext_cpuid[i][3]); + for(i = 0; i < MAX_INTELFN4_LEVEL; i++) + fprintf(f, "intel_fn4[%d]=%08x %08x %08x %08x\n", i, + data->intel_fn4[i][0], data->intel_fn4[i][1], + data->intel_fn4[i][2], data->intel_fn4[i][3]); + for(i = 0; i < MAX_INTELFN11_LEVEL; i++) + fprintf(f, "intel_fn11[%d]=%08x %08x %08x %08x\n", i, + data->intel_fn11[i][0], data->intel_fn11[i][1], + data->intel_fn11[i][2], data->intel_fn11[i][3]); + for(i = 0; i < MAX_INTELFN12H_LEVEL; i++) + fprintf(f, "intel_fn12h[%d]=%08x %08x %08x %08x\n", i, + data->intel_fn12h[i][0], data->intel_fn12h[i][1], + data->intel_fn12h[i][2], data->intel_fn12h[i][3]); + for(i = 0; i < MAX_INTELFN14H_LEVEL; i++) + fprintf(f, "intel_fn14h[%d]=%08x %08x %08x %08x\n", i, + data->intel_fn14h[i][0], data->intel_fn14h[i][1], + data->intel_fn14h[i][2], data->intel_fn14h[i][3]); + + if(strcmp(filename, "")) + { + fclose(f); + } + return set_error(ERR_OK); +} + +int cpuid_deserialize_raw_data(struct cpu_raw_data_t* data, const char* filename) +{ + int i, len; + char line[100]; + char token[100]; + char* value; + int syntax; + int cur_line = 0; + int recognized; + FILE* f; + + raw_data_t_constructor(data); + + if(!strcmp(filename, "")) + { + f = stdin; + } + else + { + f = fopen(filename, "rt"); + } + if(!f) + { + return set_error(ERR_OPEN); + } + while(fgets(line, sizeof(line), f)) + { + ++cur_line; + len = (int) strlen(line); + if(len < 2) + { + continue; + } + if(line[len - 1] == '\n') + { + line[--len] = '\0'; + } + for(i = 0; i < len && line[i] != '='; i++) + if(i >= len && i < 1 && len - i - 1 <= 0) + { + fclose(f); + return set_error(ERR_BADFMT); + } + strncpy(token, line, i); + token[i] = '\0'; + value = &line[i + 1]; + /* try to recognize the line */ + recognized = 0; + if(!strcmp(token, "version") || !strcmp(token, "build_date")) + { + recognized = 1; + } + syntax = 1; + syntax = syntax && parse_token("basic_cpuid", token, value, data->basic_cpuid, MAX_CPUID_LEVEL, &recognized); + syntax = syntax && + parse_token("ext_cpuid", token, value, data->ext_cpuid, MAX_EXT_CPUID_LEVEL, &recognized); + syntax = syntax && + parse_token("intel_fn4", token, value, data->intel_fn4, MAX_INTELFN4_LEVEL, &recognized); + syntax = syntax && + parse_token("intel_fn11", token, value, data->intel_fn11, MAX_INTELFN11_LEVEL, &recognized); + syntax = syntax && + parse_token("intel_fn12h", token, value, data->intel_fn12h, MAX_INTELFN12H_LEVEL, &recognized); + syntax = syntax && + parse_token("intel_fn14h", token, value, data->intel_fn14h, MAX_INTELFN14H_LEVEL, &recognized); + if(!syntax) + { + warnf("Error: %s:%d: Syntax error\n", filename, cur_line); + fclose(f); + return set_error(ERR_BADFMT); + } + if(!recognized) + { + warnf("Warning: %s:%d not understood!\n", filename, cur_line); + } + } + + if(strcmp(filename, "")) + { + fclose(f); + } + return set_error(ERR_OK); +} + int cpu_ident_internal(struct cpu_raw_data_t* raw, struct cpu_id_t* data, struct internal_id_info_t* internal) { int r; struct cpu_raw_data_t myraw; - if (!raw) { - if ((r = cpuid_get_raw_data(&myraw)) < 0) + if(!raw) + { + if((r = cpuid_get_raw_data(&myraw)) < 0) + { return set_error(r); + } raw = &myraw; } cpu_id_t_constructor(data); - if ((r = cpuid_basic_identify(raw, data)) < 0) + if((r = cpuid_basic_identify(raw, data)) < 0) + { return set_error(r); - switch (data->vendor) { - case VENDOR_INTEL: - r = cpuid_identify_intel(raw, data, internal); - break; - case VENDOR_AMD: - r = cpuid_identify_amd(raw, data, internal); - break; - default: - break; + } + switch(data->vendor) + { + case VENDOR_INTEL: + r = cpuid_identify_intel(raw, data, internal); + break; + case VENDOR_AMD: + r = cpuid_identify_amd(raw, data, internal); + break; + default: + break; } return set_error(r); } @@ -383,7 +634,264 @@ int cpu_identify(struct cpu_raw_data_t* raw, struct cpu_id_t* data) return cpu_ident_internal(raw, data, &throwaway); } +const char* cpu_feature_str(cpu_feature_t feature) +{ + const struct + { + cpu_feature_t feature; + const char* name; + } + matchtable[] = + { + { CPU_FEATURE_FPU, "fpu" }, + { CPU_FEATURE_VME, "vme" }, + { CPU_FEATURE_DE, "de" }, + { CPU_FEATURE_PSE, "pse" }, + { CPU_FEATURE_TSC, "tsc" }, + { CPU_FEATURE_MSR, "msr" }, + { CPU_FEATURE_PAE, "pae" }, + { CPU_FEATURE_MCE, "mce" }, + { CPU_FEATURE_CX8, "cx8" }, + { CPU_FEATURE_APIC, "apic" }, + { CPU_FEATURE_MTRR, "mtrr" }, + { CPU_FEATURE_SEP, "sep" }, + { CPU_FEATURE_PGE, "pge" }, + { CPU_FEATURE_MCA, "mca" }, + { CPU_FEATURE_CMOV, "cmov" }, + { CPU_FEATURE_PAT, "pat" }, + { CPU_FEATURE_PSE36, "pse36" }, + { CPU_FEATURE_PN, "pn" }, + { CPU_FEATURE_CLFLUSH, "clflush" }, + { CPU_FEATURE_DTS, "dts" }, + { CPU_FEATURE_ACPI, "acpi" }, + { CPU_FEATURE_MMX, "mmx" }, + { CPU_FEATURE_FXSR, "fxsr" }, + { CPU_FEATURE_SSE, "sse" }, + { CPU_FEATURE_SSE2, "sse2" }, + { CPU_FEATURE_SS, "ss" }, + { CPU_FEATURE_HT, "ht" }, + { CPU_FEATURE_TM, "tm" }, + { CPU_FEATURE_IA64, "ia64" }, + { CPU_FEATURE_PBE, "pbe" }, + { CPU_FEATURE_PNI, "pni" }, + { CPU_FEATURE_PCLMUL, "pclmul" }, + { CPU_FEATURE_DTS64, "dts64" }, + { CPU_FEATURE_MONITOR, "monitor" }, + { CPU_FEATURE_DS_CPL, "ds_cpl" }, + { CPU_FEATURE_VMX, "vmx" }, + { CPU_FEATURE_SMX, "smx" }, + { CPU_FEATURE_EST, "est" }, + { CPU_FEATURE_TM2, "tm2" }, + { CPU_FEATURE_SSSE3, "ssse3" }, + { CPU_FEATURE_CID, "cid" }, + { CPU_FEATURE_CX16, "cx16" }, + { CPU_FEATURE_XTPR, "xtpr" }, + { CPU_FEATURE_PDCM, "pdcm" }, + { CPU_FEATURE_DCA, "dca" }, + { CPU_FEATURE_SSE4_1, "sse4_1" }, + { CPU_FEATURE_SSE4_2, "sse4_2" }, + { CPU_FEATURE_SYSCALL, "syscall" }, + { CPU_FEATURE_XD, "xd" }, + { CPU_FEATURE_X2APIC, "x2apic"}, + { CPU_FEATURE_MOVBE, "movbe" }, + { CPU_FEATURE_POPCNT, "popcnt" }, + { CPU_FEATURE_AES, "aes" }, + { CPU_FEATURE_XSAVE, "xsave" }, + { CPU_FEATURE_OSXSAVE, "osxsave" }, + { CPU_FEATURE_AVX, "avx" }, + { CPU_FEATURE_MMXEXT, "mmxext" }, + { CPU_FEATURE_3DNOW, "3dnow" }, + { CPU_FEATURE_3DNOWEXT, "3dnowext" }, + { CPU_FEATURE_NX, "nx" }, + { CPU_FEATURE_FXSR_OPT, "fxsr_opt" }, + { CPU_FEATURE_RDTSCP, "rdtscp" }, + { CPU_FEATURE_LM, "lm" }, + { CPU_FEATURE_LAHF_LM, "lahf_lm" }, + { CPU_FEATURE_CMP_LEGACY, "cmp_legacy" }, + { CPU_FEATURE_SVM, "svm" }, + { CPU_FEATURE_SSE4A, "sse4a" }, + { CPU_FEATURE_MISALIGNSSE, "misalignsse" }, + { CPU_FEATURE_ABM, "abm" }, + { CPU_FEATURE_3DNOWPREFETCH, "3dnowprefetch" }, + { CPU_FEATURE_OSVW, "osvw" }, + { CPU_FEATURE_IBS, "ibs" }, + { CPU_FEATURE_SSE5, "sse5" }, + { CPU_FEATURE_SKINIT, "skinit" }, + { CPU_FEATURE_WDT, "wdt" }, + { CPU_FEATURE_TS, "ts" }, + { CPU_FEATURE_FID, "fid" }, + { CPU_FEATURE_VID, "vid" }, + { CPU_FEATURE_TTP, "ttp" }, + { CPU_FEATURE_TM_AMD, "tm_amd" }, + { CPU_FEATURE_STC, "stc" }, + { CPU_FEATURE_100MHZSTEPS, "100mhzsteps" }, + { CPU_FEATURE_HWPSTATE, "hwpstate" }, + { CPU_FEATURE_CONSTANT_TSC, "constant_tsc" }, + { CPU_FEATURE_XOP, "xop" }, + { CPU_FEATURE_FMA3, "fma3" }, + { CPU_FEATURE_FMA4, "fma4" }, + { CPU_FEATURE_TBM, "tbm" }, + { CPU_FEATURE_F16C, "f16c" }, + { CPU_FEATURE_RDRAND, "rdrand" }, + { CPU_FEATURE_CPB, "cpb" }, + { CPU_FEATURE_APERFMPERF, "aperfmperf" }, + { CPU_FEATURE_PFI, "pfi" }, + { CPU_FEATURE_PA, "pa" }, + { CPU_FEATURE_AVX2, "avx2" }, + { CPU_FEATURE_BMI1, "bmi1" }, + { CPU_FEATURE_BMI2, "bmi2" }, + { CPU_FEATURE_HLE, "hle" }, + { CPU_FEATURE_RTM, "rtm" }, + { CPU_FEATURE_AVX512F, "avx512f" }, + { CPU_FEATURE_AVX512DQ, "avx512dq" }, + { CPU_FEATURE_AVX512PF, "avx512pf" }, + { CPU_FEATURE_AVX512ER, "avx512er" }, + { CPU_FEATURE_AVX512CD, "avx512cd" }, + { CPU_FEATURE_SHA_NI, "sha_ni" }, + { CPU_FEATURE_AVX512BW, "avx512bw" }, + { CPU_FEATURE_AVX512VL, "avx512vl" }, + { CPU_FEATURE_SGX, "sgx" }, + { CPU_FEATURE_RDSEED, "rdseed" }, + { CPU_FEATURE_ADX, "adx" }, + }; + unsigned i, n = COUNT_OF(matchtable); + if(n != NUM_CPU_FEATURES) + { + warnf("Warning: incomplete library, feature matchtable size differs from the actual number of features.\n"); + } + for(i = 0; i < n; i++) + if(matchtable[i].feature == feature) + { + return matchtable[i].name; + } + return ""; +} + +const char* cpuid_error(void) +{ + const struct + { + cpu_error_t error; + const char* description; + } + matchtable[] = + { + { ERR_OK , "No error"}, + { ERR_NO_CPUID , "CPUID instruction is not supported"}, + { ERR_NO_RDTSC , "RDTSC instruction is not supported"}, + { ERR_NO_MEM , "Memory allocation failed"}, + { ERR_OPEN , "File open operation failed"}, + { ERR_BADFMT , "Bad file format"}, + { ERR_NOT_IMP , "Not implemented"}, + { ERR_CPU_UNKN , "Unsupported processor"}, + { ERR_NO_RDMSR , "RDMSR instruction is not supported"}, + { ERR_NO_DRIVER, "RDMSR driver error (generic)"}, + { ERR_NO_PERMS , "No permissions to install RDMSR driver"}, + { ERR_EXTRACT , "Cannot extract RDMSR driver (read only media?)"}, + { ERR_HANDLE , "Bad handle"}, + { ERR_INVMSR , "Invalid MSR"}, + { ERR_INVCNB , "Invalid core number"}, + { ERR_HANDLE_R , "Error on handle read"}, + { ERR_INVRANGE , "Invalid given range"}, + }; + unsigned i; + for(i = 0; i < COUNT_OF(matchtable); i++) + if(_libcpiud_errno == matchtable[i].error) + { + return matchtable[i].description; + } + return "Unknown error"; +} + + const char* cpuid_lib_version(void) { return VERSION; } + +libcpuid_warn_fn_t cpuid_set_warn_function(libcpuid_warn_fn_t new_fn) +{ + libcpuid_warn_fn_t ret = _warn_fun; + _warn_fun = new_fn; + return ret; +} + +void cpuid_set_verbosiness_level(int level) +{ + _current_verboselevel = level; +} + +cpu_vendor_t cpuid_get_vendor(void) +{ + static cpu_vendor_t vendor = VENDOR_UNKNOWN; + uint32_t raw_vendor[4]; + char vendor_str[VENDOR_STR_MAX]; + + if(vendor == VENDOR_UNKNOWN) + { + if(!cpuid_present()) + { + set_error(ERR_NO_CPUID); + } + else + { + cpu_exec_cpuid(0, raw_vendor); + vendor = cpuid_vendor_identify(raw_vendor, vendor_str); + } + } + return vendor; +} + +void cpuid_get_cpu_list(cpu_vendor_t vendor, struct cpu_list_t* list) +{ + switch(vendor) + { + case VENDOR_INTEL: + cpuid_get_list_intel(list); + break; + case VENDOR_AMD: + cpuid_get_list_amd(list); + break; + case VENDOR_CYRIX: + make_list_from_string("Cx486,Cx5x86,6x86,6x86MX,M II,MediaGX,MediaGXi,MediaGXm", list); + break; + case VENDOR_NEXGEN: + make_list_from_string("Nx586", list); + break; + case VENDOR_TRANSMETA: + make_list_from_string("Crusoe,Efficeon", list); + break; + case VENDOR_UMC: + make_list_from_string("UMC x86 CPU", list); + break; + case VENDOR_CENTAUR: + make_list_from_string("VIA C3,VIA C7,VIA Nano", list); + break; + case VENDOR_RISE: + make_list_from_string("Rise mP6", list); + break; + case VENDOR_SIS: + make_list_from_string("SiS mP6", list); + break; + case VENDOR_NSC: + make_list_from_string("Geode GXm,Geode GXLV,Geode GX1,Geode GX2", list); + break; + default: + warnf("Unknown vendor passed to cpuid_get_cpu_list()\n"); + break; + } +} + +void cpuid_free_cpu_list(struct cpu_list_t* list) +{ + int i; + if(list->num_entries <= 0) + { + return; + } + for(i = 0; i < list->num_entries; i++) + { + free(list->names[i]); + } + free(list->names); +} diff --git a/src/3rdparty/libcpuid/intel_code_t.h b/src/3rdparty/libcpuid/intel_code_t.h index 718ca337..d5885a5b 100644 --- a/src/3rdparty/libcpuid/intel_code_t.h +++ b/src/3rdparty/libcpuid/intel_code_t.h @@ -28,31 +28,31 @@ * This file contains a list of internal codes we use in detection. It is * of no external use and isn't a complete list of intel products. */ - CODE2(PENTIUM, 2000), - - CODE(IRWIN), - CODE(POTOMAC), - CODE(GAINESTOWN), - CODE(WESTMERE), - - CODE(PENTIUM_M), - CODE(NOT_CELERON), - - CODE(CORE_SOLO), - CODE(MOBILE_CORE_SOLO), - CODE(CORE_DUO), - CODE(MOBILE_CORE_DUO), - - CODE(WOLFDALE), - CODE(MEROM), - CODE(PENRYN), - CODE(QUAD_CORE), - CODE(DUAL_CORE_HT), - CODE(QUAD_CORE_HT), - CODE(MORE_THAN_QUADCORE), - CODE(PENTIUM_D), - - CODE(SILVERTHORNE), - CODE(DIAMONDVILLE), - CODE(PINEVIEW), - CODE(CEDARVIEW), +CODE2(PENTIUM, 2000), + + CODE(IRWIN), + CODE(POTOMAC), + CODE(GAINESTOWN), + CODE(WESTMERE), + + CODE(PENTIUM_M), + CODE(NOT_CELERON), + + CODE(CORE_SOLO), + CODE(MOBILE_CORE_SOLO), + CODE(CORE_DUO), + CODE(MOBILE_CORE_DUO), + + CODE(WOLFDALE), + CODE(MEROM), + CODE(PENRYN), + CODE(QUAD_CORE), + CODE(DUAL_CORE_HT), + CODE(QUAD_CORE_HT), + CODE(MORE_THAN_QUADCORE), + CODE(PENTIUM_D), + + CODE(SILVERTHORNE), + CODE(DIAMONDVILLE), + CODE(PINEVIEW), + CODE(CEDARVIEW), diff --git a/src/3rdparty/libcpuid/libcpuid.h b/src/3rdparty/libcpuid/libcpuid.h index c44990c3..88ec5721 100644 --- a/src/3rdparty/libcpuid/libcpuid.h +++ b/src/3rdparty/libcpuid/libcpuid.h @@ -73,7 +73,7 @@ * \ref cpu_tsc_mark + \ref cpu_tsc_unmark + \ref cpu_clock_by_mark, * \ref cpu_clock_measure or \ref cpu_clock_by_ic. * Read carefully for pros/cons of each method.
- * + * * To read MSRs, use \ref cpu_msr_driver_open to get a handle, and then * \ref cpu_rdmsr for querying abilities. Some MSR decoding is available on recent * CPUs, and can be queried through \ref cpu_msrinfo; the various types of queries @@ -85,7 +85,11 @@ @{ */ /* Include some integer type specifications: */ +#ifdef _WIN32 #include "libcpuid_types.h" +#else +# include +#endif /* Some limits and other constants */ #include "libcpuid_constants.h" @@ -97,7 +101,8 @@ extern "C" { /** * @brief CPU vendor, as guessed from the Vendor String. */ -typedef enum { +typedef enum +{ VENDOR_INTEL = 0, /*!< Intel CPU */ VENDOR_AMD, /*!< AMD CPU */ VENDOR_CYRIX, /*!< Cyrix CPU */ @@ -108,7 +113,7 @@ typedef enum { VENDOR_RISE, /*!< x86 CPU by Rise Technology */ VENDOR_SIS, /*!< x86 CPU by SiS */ VENDOR_NSC, /*!< x86 CPU by National Semiconductor */ - + NUM_CPU_VENDORS, /*!< Valid CPU vendor ids: 0..NUM_CPU_VENDORS - 1 */ VENDOR_UNKNOWN = -1, } cpu_vendor_t; @@ -121,23 +126,24 @@ typedef enum { * and feature recognition. Every processor should be identifiable using this * data only. */ -struct cpu_raw_data_t { +struct cpu_raw_data_t +{ /** contains results of CPUID for eax = 0, 1, ...*/ uint32_t basic_cpuid[MAX_CPUID_LEVEL][4]; /** contains results of CPUID for eax = 0x80000000, 0x80000001, ...*/ uint32_t ext_cpuid[MAX_EXT_CPUID_LEVEL][4]; - + /** when the CPU is intel and it supports deterministic cache information: this contains the results of CPUID for eax = 4 and ecx = 0, 1, ... */ uint32_t intel_fn4[MAX_INTELFN4_LEVEL][4]; - + /** when the CPU is intel and it supports leaf 0Bh (Extended Topology - enumeration leaf), this stores the result of CPUID with + enumeration leaf), this stores the result of CPUID with eax = 11 and ecx = 0, 1, 2... */ uint32_t intel_fn11[MAX_INTELFN11_LEVEL][4]; - + /** when the CPU is intel and supports leaf 12h (SGX enumeration leaf), * this stores the result of CPUID with eax = 0x12 and * ecx = 0, 1, 2... */ @@ -157,7 +163,7 @@ struct cpu_raw_data_t { * ... * struct cpu_raw_data_t raw; * struct cpu_id_t id; - * + * * if (cpuid_get_raw_data(&raw) == 0 && cpu_identify(&raw, &id) == 0 && id.sgx.present) { * printf("SGX is present.\n"); * printf("SGX1 instructions: %s.\n", id.sgx.flags[INTEL_SGX1] ? "present" : "absent"); @@ -172,42 +178,43 @@ struct cpu_raw_data_t { * printf("SGX is not present.\n"); * } * @endcode - */ -struct cpu_sgx_t { + */ +struct cpu_sgx_t +{ /** Whether SGX is present (boolean) */ uint32_t present; - + /** Max enclave size in 32-bit mode. This is a power-of-two value: * if it is "31", then the max enclave size is 2^31 bytes (2 GiB). */ uint8_t max_enclave_32bit; - + /** Max enclave size in 64-bit mode. This is a power-of-two value: * if it is "36", then the max enclave size is 2^36 bytes (64 GiB). */ uint8_t max_enclave_64bit; - + /** * contains SGX feature flags. See the \ref cpu_sgx_feature_t * "INTEL_SGX*" macros below. */ uint8_t flags[SGX_FLAGS_MAX]; - + /** number of Enclave Page Cache (EPC) sections. Info for each * section is available through the \ref cpuid_get_epc() function */ int num_epc_sections; - + /** bit vector of the supported extended features that can be written * to the MISC region of the SSA (Save State Area) - */ + */ uint32_t misc_select; - + /** a bit vector of the attributes that can be set to SECS.ATTRIBUTES * via ECREATE. Corresponds to bits 0-63 (incl.) of SECS.ATTRIBUTES. - */ + */ uint64_t secs_attributes; - + /** a bit vector of the bits that can be set in the XSAVE feature * request mask; Corresponds to bits 64-127 of SECS.ATTRIBUTES. */ @@ -217,48 +224,49 @@ struct cpu_sgx_t { /** * @brief This contains the recognized CPU features/info */ -struct cpu_id_t { +struct cpu_id_t +{ /** contains the CPU vendor string, e.g. "GenuineIntel" */ char vendor_str[VENDOR_STR_MAX]; - + /** contains the brand string, e.g. "Intel(R) Xeon(TM) CPU 2.40GHz" */ char brand_str[BRAND_STR_MAX]; - + /** contains the recognized CPU vendor */ cpu_vendor_t vendor; - + /** * contain CPU flags. Used to test for features. See * the \ref cpu_feature_t "CPU_FEATURE_*" macros below. * @see Features */ uint8_t flags[CPU_FLAGS_MAX]; - + /** CPU family */ int32_t family; - + /** CPU model */ int32_t model; - + /** CPU stepping */ int32_t stepping; - + /** CPU extended family */ int32_t ext_family; - + /** CPU extended model */ int32_t ext_model; - + /** Number of CPU cores on the current processor */ int32_t num_cores; - + /** * Number of logical processors on the current processor. * Could be more than the number of physical cores, * e.g. when the processor has HyperThreading. */ int32_t num_logical_cpus; - + /** * The total number of logical processors. * The same value is availabe through \ref cpuid_get_total_cpus. @@ -274,13 +282,13 @@ struct cpu_id_t { * */ int32_t total_logical_cpus; - + /** * L1 data cache size in KB. Could be zero, if the CPU lacks cache. * If the size cannot be determined, it will be -1. */ int32_t l1_data_cache; - + /** * L1 instruction cache size in KB. Could be zero, if the CPU lacks * cache. If the size cannot be determined, it will be -1. @@ -288,40 +296,40 @@ struct cpu_id_t { * a trace cache, the size will be expressed in K uOps. */ int32_t l1_instruction_cache; - + /** * L2 cache size in KB. Could be zero, if the CPU lacks L2 cache. * If the size of the cache could not be determined, it will be -1 */ int32_t l2_cache; - + /** L3 cache size in KB. Zero on most systems */ int32_t l3_cache; /** L4 cache size in KB. Zero on most systems */ int32_t l4_cache; - + /** Cache associativity for the L1 data cache. -1 if undetermined */ int32_t l1_assoc; - + /** Cache associativity for the L2 cache. -1 if undetermined */ int32_t l2_assoc; - + /** Cache associativity for the L3 cache. -1 if undetermined */ int32_t l3_assoc; /** Cache associativity for the L4 cache. -1 if undetermined */ int32_t l4_assoc; - + /** Cache-line size for L1 data cache. -1 if undetermined */ int32_t l1_cacheline; - + /** Cache-line size for L2 cache. -1 if undetermined */ int32_t l2_cacheline; - + /** Cache-line size for L3 cache. -1 if undetermined */ int32_t l3_cacheline; - + /** Cache-line size for L4 cache. -1 if undetermined */ int32_t l4_cacheline; @@ -340,17 +348,17 @@ struct cpu_id_t { * @endcode */ char cpu_codename[64]; - + /** SSE execution unit size (64 or 128; -1 if N/A) */ int32_t sse_size; - + /** * contain miscellaneous detection information. Used to test about specifics of * certain detected features. See \ref cpu_hint_t "CPU_HINT_*" macros below. * @see Hints */ uint8_t detection_hints[CPU_HINTS_MAX]; - + /** contains information about SGX features if the processor, if present */ struct cpu_sgx_t sgx; }; @@ -375,7 +383,8 @@ struct cpu_id_t { * } * @endcode */ -typedef enum { +typedef enum +{ CPU_FEATURE_FPU = 0, /*!< Floating point unit */ CPU_FEATURE_VME, /*!< Virtual mode extension */ CPU_FEATURE_DE, /*!< Debugging extension */ @@ -495,7 +504,8 @@ typedef enum { * * Usage: similar to the flags usage */ -typedef enum { +typedef enum +{ CPU_HINT_SSE_SIZE_AUTH = 0, /*!< SSE unit size is authoritative (not only a Family/Model guesswork, but based on an actual CPUID bit) */ /* termination */ NUM_CPU_HINTS, @@ -522,11 +532,12 @@ typedef enum { * } * @endcode */ - -typedef enum { + +typedef enum +{ INTEL_SGX1, /*!< SGX1 instructions support */ INTEL_SGX2, /*!< SGX2 instructions support */ - + /* termination: */ NUM_SGX_FEATURES, } cpu_sgx_feature_t; @@ -534,7 +545,8 @@ typedef enum { /** * @brief Describes common library error codes */ -typedef enum { +typedef enum +{ ERR_OK = 0, /*!< "No error" */ ERR_NO_CPUID = -1, /*!< "CPUID instruction is not supported" */ ERR_NO_RDTSC = -2, /*!< "RDTSC instruction is not supported" */ @@ -544,7 +556,7 @@ typedef enum { ERR_NOT_IMP = -6, /*!< "Not implemented" */ ERR_CPU_UNKN = -7, /*!< "Unsupported processor" */ ERR_NO_RDMSR = -8, /*!< "RDMSR instruction is not supported" */ - ERR_NO_DRIVER= -9, /*!< "RDMSR driver error (generic)" */ + ERR_NO_DRIVER = -9, /*!< "RDMSR driver error (generic)" */ ERR_NO_PERMS = -10, /*!< "No permissions to install RDMSR driver" */ ERR_EXTRACT = -11, /*!< "Cannot extract RDMSR driver (read only media?)" */ ERR_HANDLE = -12, /*!< "Bad handle" */ @@ -558,7 +570,8 @@ typedef enum { * @brief Internal structure, used in cpu_tsc_mark, cpu_tsc_unmark and * cpu_clock_by_mark */ -struct cpu_mark_t { +struct cpu_mark_t +{ uint64_t tsc; /*!< Time-stamp from RDTSC */ uint64_t sys_clock; /*!< In microsecond resolution */ }; @@ -610,6 +623,39 @@ 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 @@ -635,14 +681,231 @@ int cpuid_get_raw_data(struct cpu_raw_data_t* data); */ 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:

+ * + * i) The CPU might be in some power saving state, while the OS reports its + * full-power frequency, or vice-versa.
+ * 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:
+ * + * 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.
+ * 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.
+ * 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 * Describes an EPC (Enclave Page Cache) layout (physical address and size). * A CPU may have one or more EPC areas, and information about each is * fetched via \ref cpuid_get_epc. - */ -struct cpu_epc_t { + */ +struct cpu_epc_t +{ uint64_t start_addr; uint64_t length; }; @@ -667,6 +930,232 @@ 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 diff --git a/src/3rdparty/libcpuid/libcpuid_internal.h b/src/3rdparty/libcpuid/libcpuid_internal.h index 038aa209..ea96af1e 100644 --- a/src/3rdparty/libcpuid/libcpuid_internal.h +++ b/src/3rdparty/libcpuid/libcpuid_internal.h @@ -30,27 +30,32 @@ * for the workings of the internal library infrastructure. */ -enum _common_codes_t { +enum _common_codes_t +{ NA = 0, NC, /* No code */ }; #define CODE(x) x #define CODE2(x, y) x = y -enum _amd_code_t { - #include "amd_code_t.h" +enum _amd_code_t +{ +#include "amd_code_t.h" }; typedef enum _amd_code_t amd_code_t; -enum _intel_code_t { - #include "intel_code_t.h" +enum _intel_code_t +{ +#include "intel_code_t.h" }; typedef enum _intel_code_t intel_code_t; #undef CODE #undef CODE2 -struct internal_id_info_t { - union { +struct internal_id_info_t +{ + union + { amd_code_t amd; intel_code_t intel; } code; @@ -60,47 +65,50 @@ struct internal_id_info_t { #define LBIT(x) (((long long) 1) << x) -enum _common_bits_t { - _M_ = LBIT( 0 ), - MOBILE_ = LBIT( 1 ), - _MP_ = LBIT( 2 ), +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 ), +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 ), +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); +int cpu_ident_internal(struct cpu_raw_data_t* raw, struct cpu_id_t* data, + struct internal_id_info_t* internal); #endif /* __LIBCPUID_INTERNAL_H__ */ diff --git a/src/3rdparty/libcpuid/libcpuid_types.h b/src/3rdparty/libcpuid/libcpuid_types.h index 9e897275..b0923cc6 100644 --- a/src/3rdparty/libcpuid/libcpuid_types.h +++ b/src/3rdparty/libcpuid/libcpuid_types.h @@ -32,6 +32,36 @@ #ifndef __LIBCPUID_TYPES_H__ #define __LIBCPUID_TYPES_H__ -#include +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#if defined(HAVE_STDINT_H) +# include +#else +/* we have to provide our own: */ +# if !defined(HAVE_INT32_T) && !defined(__int32_t_defined) +typedef int int32_t; +# endif + +# if !defined(HAVE_UINT32_T) && !defined(__uint32_t_defined) +typedef unsigned uint32_t; +# endif + +typedef signed char int8_t; +typedef unsigned char uint8_t; +typedef signed short int16_t; +typedef unsigned short uint16_t; +#if (defined _MSC_VER) && (_MSC_VER <= 1300) +/* MSVC 6.0: no long longs ... */ +typedef signed __int64 int64_t; +typedef unsigned __int64 uint64_t; +#else +/* all other sane compilers: */ +typedef signed long long int64_t; +typedef unsigned long long uint64_t; +#endif + +#endif #endif /* __LIBCPUID_TYPES_H__ */ diff --git a/src/3rdparty/libcpuid/libcpuid_util.c b/src/3rdparty/libcpuid/libcpuid_util.c index 440b3724..48d2ca67 100644 --- a/src/3rdparty/libcpuid/libcpuid_util.c +++ b/src/3rdparty/libcpuid/libcpuid_util.c @@ -32,27 +32,212 @@ #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)) + 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] == '[') { + 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; + 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; } @@ -62,15 +247,21 @@ 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) { + 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)) { + while(j < m && ((dj = xmatch_entry(s[i + k], p + j)) != -1)) + { k++; j += dj; } - if (j == m) return i + 1; + if(j == m) + { + return i + 1; + } } } return 0; @@ -80,9 +271,14 @@ 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)) + if(initialized) + { + return &id; + } + if(cpu_identify(NULL, &id)) + { memset(&id, 0, sizeof(id)); + } initialized = 1; return &id; } @@ -91,3 +287,21 @@ 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"); +} diff --git a/src/3rdparty/libcpuid/libcpuid_util.h b/src/3rdparty/libcpuid/libcpuid_util.h index 0c8200e8..9c75435e 100644 --- a/src/3rdparty/libcpuid/libcpuid_util.h +++ b/src/3rdparty/libcpuid/libcpuid_util.h @@ -28,15 +28,17 @@ #define COUNT_OF(array) (sizeof(array) / sizeof(array[0])) -struct feature_map_t { +struct feature_map_t +{ unsigned bit; cpu_feature_t feature; }; - + void match_features(const struct feature_map_t* matchtable, int count, uint32_t reg, struct cpu_id_t* data); -struct match_entry_t { +struct match_entry_t +{ int family, model, stepping, ext_family, ext_model; int ncores, l2cache, l3cache, brand_code; uint64_t model_bits; @@ -48,6 +50,20 @@ 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 @@ -70,9 +86,15 @@ 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__ */ diff --git a/src/3rdparty/libcpuid/msrdriver.c b/src/3rdparty/libcpuid/msrdriver.c new file mode 100644 index 00000000..9dc42bdd --- /dev/null +++ b/src/3rdparty/libcpuid/msrdriver.c @@ -0,0 +1,595 @@ +/* + * Copyright 2009 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. + */ + +/** + * @File msrdriver.c + * @Brief Contains the binary images of the x86 and x64 MSR drivers for Windows + * @Date 2009-09-29 + * + * The driver is courtesy of Nick 'Bombera' Gabareff, and its source is actually + * available, see the contrib/ dir. + * + * However, for simplicity, here we just include the images of the compiled .SYS + * files. + * They are extracted to the filesystem on demand and loaded in the kernel + * by the cpu_msr_driver_open() function + */ +#ifdef _WIN32 +#include "asm-bits.h" +//begin { +int cc_x86driver_code_size = 4608; +uint8_t cc_x86driver_code[4608] = +{ + 0x4d, 0x5a, 0x90, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xb8, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc8, 0x00, 0x00, 0x00, 0x0e, 0x1f, 0xba, 0x0e, 0x00, 0xb4, 0x09, 0xcd, + 0x21, 0xb8, 0x01, 0x4c, 0xcd, 0x21, 0x54, 0x68, 0x69, 0x73, 0x20, 0x70, 0x72, 0x6f, 0x67, 0x72, 0x61, 0x6d, + 0x20, 0x63, 0x61, 0x6e, 0x6e, 0x6f, 0x74, 0x20, 0x62, 0x65, 0x20, 0x72, 0x75, 0x6e, 0x20, 0x69, 0x6e, 0x20, + 0x44, 0x4f, 0x53, 0x20, 0x6d, 0x6f, 0x64, 0x65, 0x2e, 0x0d, 0x0d, 0x0a, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x9f, 0x99, 0x48, 0xdf, 0xdb, 0xf8, 0x26, 0x8c, 0xdb, 0xf8, 0x26, 0x8c, 0xdb, 0xf8, 0x26, 0x8c, + 0xdb, 0xf8, 0x27, 0x8c, 0xdd, 0xf8, 0x26, 0x8c, 0x21, 0xdb, 0x3f, 0x8c, 0xd8, 0xf8, 0x26, 0x8c, 0xfc, 0x3e, + 0x57, 0x8c, 0xda, 0xf8, 0x26, 0x8c, 0xfc, 0x3e, 0x5a, 0x8c, 0xda, 0xf8, 0x26, 0x8c, 0xfc, 0x3e, 0x5e, 0x8c, + 0xda, 0xf8, 0x26, 0x8c, 0x52, 0x69, 0x63, 0x68, 0xdb, 0xf8, 0x26, 0x8c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x50, 0x45, 0x00, 0x00, 0x4c, 0x01, 0x07, 0x00, 0x12, 0x9b, 0x9b, 0x4a, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xe0, 0x00, 0x02, 0x21, 0x0b, 0x01, 0x08, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x0a, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, + 0x00, 0x00, 0x01, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, + 0xa9, 0xd1, 0x00, 0x00, 0x01, 0x00, 0x00, 0x04, 0x00, 0x00, 0x10, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, + 0x10, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0xc0, 0x03, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x70, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2e, 0x74, + 0x65, 0x78, 0x74, 0x00, 0x00, 0x00, 0xa3, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, + 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, + 0x00, 0x68, 0x2e, 0x72, 0x64, 0x61, 0x74, 0x61, 0x00, 0x00, 0x62, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, + 0x00, 0x02, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x40, 0x00, 0x00, 0x48, 0x2e, 0x64, 0x61, 0x74, 0x61, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0xc8, 0x50, 0x41, 0x47, 0x45, 0x30, 0x44, 0x45, 0x46, + 0x8c, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x60, 0x49, 0x4e, 0x49, 0x54, + 0x00, 0x00, 0x00, 0x00, 0xd4, 0x00, 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x0a, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0xe2, + 0x2e, 0x72, 0x73, 0x72, 0x63, 0x00, 0x00, 0x00, 0xc0, 0x03, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x04, + 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x40, 0x00, 0x00, 0x42, 0x2e, 0x72, 0x65, 0x6c, 0x6f, 0x63, 0x00, 0x00, 0x68, 0x00, 0x00, 0x00, 0x00, 0x70, + 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x42, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8b, 0x4c, + 0x24, 0x08, 0x83, 0x61, 0x18, 0x00, 0x83, 0x61, 0x1c, 0x00, 0x32, 0xd2, 0xff, 0x15, 0x08, 0x20, 0x01, 0x00, + 0x33, 0xc0, 0xc2, 0x08, 0x00, 0x56, 0x8b, 0x74, 0x24, 0x0c, 0x8b, 0x46, 0x60, 0x81, 0x78, 0x0c, 0x0c, 0xe0, + 0x22, 0x00, 0x57, 0x75, 0x3c, 0x83, 0x78, 0x04, 0x08, 0x72, 0x36, 0x83, 0x78, 0x08, 0x04, 0x75, 0x07, 0x8b, + 0x46, 0x0c, 0x8b, 0x08, 0xeb, 0x05, 0xb9, 0x9c, 0x01, 0x00, 0x00, 0x8b, 0x7e, 0x0c, 0x0f, 0x32, 0x89, 0x07, + 0x89, 0x57, 0x04, 0xc7, 0x46, 0x1c, 0x08, 0x00, 0x00, 0x00, 0x33, 0xff, 0x32, 0xd2, 0x8b, 0xce, 0xff, 0x15, + 0x08, 0x20, 0x01, 0x00, 0x8b, 0xc7, 0x5f, 0x5e, 0xc2, 0x08, 0x00, 0x83, 0x66, 0x1c, 0x00, 0xbf, 0x01, 0x00, + 0x00, 0xc0, 0x89, 0x7e, 0x18, 0xeb, 0xe1, 0x55, 0x8b, 0xec, 0x51, 0x51, 0x8b, 0x45, 0x08, 0xff, 0x70, 0x04, + 0xff, 0x15, 0x04, 0x20, 0x01, 0x00, 0x68, 0x3c, 0x20, 0x01, 0x00, 0x8d, 0x45, 0xf8, 0x50, 0xff, 0x15, 0x00, + 0x20, 0x01, 0x00, 0x8d, 0x45, 0xf8, 0x50, 0xff, 0x15, 0x14, 0x20, 0x01, 0x00, 0xc9, 0xc2, 0x04, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5c, 0x50, 0x00, 0x00, 0x74, 0x50, 0x00, 0x00, 0x86, 0x50, 0x00, 0x00, + 0x9c, 0x50, 0x00, 0x00, 0xb4, 0x50, 0x00, 0x00, 0x44, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5c, 0x00, + 0x44, 0x00, 0x65, 0x00, 0x76, 0x00, 0x69, 0x00, 0x63, 0x00, 0x65, 0x00, 0x5c, 0x00, 0x54, 0x00, 0x6d, 0x00, + 0x70, 0x00, 0x52, 0x00, 0x64, 0x00, 0x72, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5c, 0x00, 0x44, 0x00, 0x6f, 0x00, + 0x73, 0x00, 0x44, 0x00, 0x65, 0x00, 0x76, 0x00, 0x69, 0x00, 0x63, 0x00, 0x65, 0x00, 0x73, 0x00, 0x5c, 0x00, + 0x54, 0x00, 0x6d, 0x00, 0x70, 0x00, 0x52, 0x00, 0x64, 0x00, 0x72, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x55, 0x8b, 0xec, 0x83, + 0xec, 0x14, 0x56, 0x8b, 0x35, 0x00, 0x20, 0x01, 0x00, 0x57, 0x68, 0x1c, 0x20, 0x01, 0x00, 0x8d, 0x45, 0xf4, + 0x50, 0xff, 0xd6, 0x8b, 0x7d, 0x08, 0x8d, 0x45, 0xfc, 0x50, 0x6a, 0x00, 0x6a, 0x00, 0x6a, 0x22, 0x8d, 0x45, + 0xf4, 0x50, 0x6a, 0x04, 0x57, 0xff, 0x15, 0x10, 0x20, 0x01, 0x00, 0x85, 0xc0, 0x75, 0x4f, 0x68, 0x3c, 0x20, + 0x01, 0x00, 0x8d, 0x45, 0xec, 0x50, 0xff, 0xd6, 0x8d, 0x45, 0xf4, 0x50, 0x8d, 0x45, 0xec, 0x50, 0xff, 0x15, + 0x0c, 0x20, 0x01, 0x00, 0x8b, 0xf0, 0x85, 0xf6, 0x74, 0x0d, 0xff, 0x75, 0xfc, 0xff, 0x15, 0x04, 0x20, 0x01, + 0x00, 0x8b, 0xc6, 0xeb, 0x23, 0x8b, 0x45, 0xfc, 0xa3, 0x00, 0x30, 0x01, 0x00, 0xb8, 0x00, 0x10, 0x01, 0x00, + 0x89, 0x47, 0x38, 0x89, 0x47, 0x40, 0xc7, 0x47, 0x34, 0x75, 0x10, 0x01, 0x00, 0xc7, 0x47, 0x70, 0x19, 0x10, + 0x01, 0x00, 0x33, 0xc0, 0x5f, 0x5e, 0xc9, 0xc2, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x28, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0x50, + 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5c, 0x50, 0x00, 0x00, 0x74, 0x50, 0x00, 0x00, 0x86, 0x50, + 0x00, 0x00, 0x9c, 0x50, 0x00, 0x00, 0xb4, 0x50, 0x00, 0x00, 0x44, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x4b, 0x01, 0x49, 0x6f, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x53, 0x79, 0x6d, 0x62, 0x6f, 0x6c, 0x69, 0x63, + 0x4c, 0x69, 0x6e, 0x6b, 0x00, 0x00, 0x0b, 0x04, 0x52, 0x74, 0x6c, 0x49, 0x6e, 0x69, 0x74, 0x55, 0x6e, 0x69, + 0x63, 0x6f, 0x64, 0x65, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x00, 0x00, 0x49, 0x01, 0x49, 0x6f, 0x44, 0x65, + 0x6c, 0x65, 0x74, 0x65, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x00, 0x00, 0xda, 0x01, 0x49, 0x6f, 0x66, 0x43, + 0x6f, 0x6d, 0x70, 0x6c, 0x65, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x00, 0x00, 0x41, 0x01, + 0x49, 0x6f, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x53, 0x79, 0x6d, 0x62, 0x6f, 0x6c, 0x69, 0x63, 0x4c, 0x69, + 0x6e, 0x6b, 0x00, 0x00, 0x38, 0x01, 0x49, 0x6f, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x44, 0x65, 0x76, 0x69, + 0x63, 0x65, 0x00, 0x00, 0x6e, 0x74, 0x6f, 0x73, 0x6b, 0x72, 0x6e, 0x6c, 0x2e, 0x65, 0x78, 0x65, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x10, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x80, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, + 0x00, 0x00, 0x30, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x01, 0x00, 0x09, 0x04, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, 0x60, 0x60, 0x00, 0x00, 0x5c, 0x03, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x5c, 0x03, 0x34, 0x00, 0x00, 0x00, 0x56, 0x00, 0x53, 0x00, 0x5f, 0x00, 0x56, 0x00, 0x45, 0x00, 0x52, 0x00, + 0x53, 0x00, 0x49, 0x00, 0x4f, 0x00, 0x4e, 0x00, 0x5f, 0x00, 0x49, 0x00, 0x4e, 0x00, 0x46, 0x00, 0x4f, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xbd, 0x04, 0xef, 0xfe, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x04, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xba, 0x02, 0x00, 0x00, 0x01, 0x00, 0x53, 0x00, 0x74, 0x00, 0x72, 0x00, 0x69, 0x00, 0x6e, 0x00, + 0x67, 0x00, 0x46, 0x00, 0x69, 0x00, 0x6c, 0x00, 0x65, 0x00, 0x49, 0x00, 0x6e, 0x00, 0x66, 0x00, 0x6f, 0x00, + 0x00, 0x00, 0x96, 0x02, 0x00, 0x00, 0x01, 0x00, 0x30, 0x00, 0x34, 0x00, 0x30, 0x00, 0x39, 0x00, 0x30, 0x00, + 0x34, 0x00, 0x62, 0x00, 0x30, 0x00, 0x00, 0x00, 0x58, 0x00, 0x20, 0x00, 0x01, 0x00, 0x43, 0x00, 0x6f, 0x00, + 0x6d, 0x00, 0x6d, 0x00, 0x65, 0x00, 0x6e, 0x00, 0x74, 0x00, 0x73, 0x00, 0x00, 0x00, 0x4d, 0x00, 0x53, 0x00, + 0x52, 0x00, 0x20, 0x00, 0x72, 0x00, 0x65, 0x00, 0x61, 0x00, 0x64, 0x00, 0x65, 0x00, 0x72, 0x00, 0x20, 0x00, + 0x33, 0x00, 0x32, 0x00, 0x2d, 0x00, 0x62, 0x00, 0x69, 0x00, 0x74, 0x00, 0x20, 0x00, 0x6b, 0x00, 0x65, 0x00, + 0x72, 0x00, 0x6e, 0x00, 0x65, 0x00, 0x6c, 0x00, 0x20, 0x00, 0x64, 0x00, 0x72, 0x00, 0x69, 0x00, 0x76, 0x00, + 0x65, 0x00, 0x72, 0x00, 0x00, 0x00, 0x42, 0x00, 0x11, 0x00, 0x01, 0x00, 0x43, 0x00, 0x6f, 0x00, 0x6d, 0x00, + 0x70, 0x00, 0x61, 0x00, 0x6e, 0x00, 0x79, 0x00, 0x4e, 0x00, 0x61, 0x00, 0x6d, 0x00, 0x65, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x49, 0x00, 0x72, 0x00, 0x6f, 0x00, 0x6e, 0x00, 0x20, 0x00, 0x53, 0x00, 0x74, 0x00, 0x65, 0x00, + 0x65, 0x00, 0x64, 0x00, 0x73, 0x00, 0x20, 0x00, 0x49, 0x00, 0x6e, 0x00, 0x63, 0x00, 0x2e, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x60, 0x00, 0x1c, 0x00, 0x01, 0x00, 0x46, 0x00, 0x69, 0x00, 0x6c, 0x00, 0x65, 0x00, 0x44, 0x00, + 0x65, 0x00, 0x73, 0x00, 0x63, 0x00, 0x72, 0x00, 0x69, 0x00, 0x70, 0x00, 0x74, 0x00, 0x69, 0x00, 0x6f, 0x00, + 0x6e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x54, 0x00, 0x6d, 0x00, 0x70, 0x00, 0x52, 0x00, 0x64, 0x00, 0x72, 0x00, + 0x20, 0x00, 0x33, 0x00, 0x32, 0x00, 0x2d, 0x00, 0x62, 0x00, 0x69, 0x00, 0x74, 0x00, 0x20, 0x00, 0x4b, 0x00, + 0x65, 0x00, 0x72, 0x00, 0x6e, 0x00, 0x65, 0x00, 0x6c, 0x00, 0x20, 0x00, 0x4d, 0x00, 0x6f, 0x00, 0x64, 0x00, + 0x75, 0x00, 0x6c, 0x00, 0x65, 0x00, 0x00, 0x00, 0x36, 0x00, 0x0b, 0x00, 0x01, 0x00, 0x46, 0x00, 0x69, 0x00, + 0x6c, 0x00, 0x65, 0x00, 0x56, 0x00, 0x65, 0x00, 0x72, 0x00, 0x73, 0x00, 0x69, 0x00, 0x6f, 0x00, 0x6e, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x31, 0x00, 0x2c, 0x00, 0x20, 0x00, 0x30, 0x00, 0x2c, 0x00, 0x20, 0x00, 0x30, 0x00, + 0x2c, 0x00, 0x20, 0x00, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2e, 0x00, 0x07, 0x00, 0x01, 0x00, 0x49, 0x00, + 0x6e, 0x00, 0x74, 0x00, 0x65, 0x00, 0x72, 0x00, 0x6e, 0x00, 0x61, 0x00, 0x6c, 0x00, 0x4e, 0x00, 0x61, 0x00, + 0x6d, 0x00, 0x65, 0x00, 0x00, 0x00, 0x54, 0x00, 0x6d, 0x00, 0x70, 0x00, 0x52, 0x00, 0x64, 0x00, 0x72, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x4a, 0x00, 0x13, 0x00, 0x01, 0x00, 0x4c, 0x00, 0x65, 0x00, 0x67, 0x00, 0x61, 0x00, + 0x6c, 0x00, 0x43, 0x00, 0x6f, 0x00, 0x70, 0x00, 0x79, 0x00, 0x72, 0x00, 0x69, 0x00, 0x67, 0x00, 0x68, 0x00, + 0x74, 0x00, 0x00, 0x00, 0x4e, 0x00, 0x69, 0x00, 0x63, 0x00, 0x6b, 0x00, 0x20, 0x00, 0x47, 0x00, 0x61, 0x00, + 0x62, 0x00, 0x61, 0x00, 0x72, 0x00, 0x65, 0x00, 0x76, 0x00, 0x20, 0x00, 0x27, 0x00, 0x32, 0x00, 0x30, 0x00, + 0x30, 0x00, 0x39, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x0b, 0x00, 0x01, 0x00, 0x4f, 0x00, 0x72, 0x00, + 0x69, 0x00, 0x67, 0x00, 0x69, 0x00, 0x6e, 0x00, 0x61, 0x00, 0x6c, 0x00, 0x46, 0x00, 0x69, 0x00, 0x6c, 0x00, + 0x65, 0x00, 0x6e, 0x00, 0x61, 0x00, 0x6d, 0x00, 0x65, 0x00, 0x00, 0x00, 0x54, 0x00, 0x6d, 0x00, 0x70, 0x00, + 0x52, 0x00, 0x64, 0x00, 0x72, 0x00, 0x2e, 0x00, 0x73, 0x00, 0x79, 0x00, 0x73, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x54, 0x00, 0x1a, 0x00, 0x01, 0x00, 0x50, 0x00, 0x72, 0x00, 0x6f, 0x00, 0x64, 0x00, 0x75, 0x00, 0x63, 0x00, + 0x74, 0x00, 0x4e, 0x00, 0x61, 0x00, 0x6d, 0x00, 0x65, 0x00, 0x00, 0x00, 0x00, 0x00, 0x43, 0x00, 0x6f, 0x00, + 0x72, 0x00, 0x65, 0x00, 0x20, 0x00, 0x32, 0x00, 0x20, 0x00, 0x54, 0x00, 0x65, 0x00, 0x6d, 0x00, 0x70, 0x00, + 0x65, 0x00, 0x72, 0x00, 0x61, 0x00, 0x74, 0x00, 0x75, 0x00, 0x72, 0x00, 0x65, 0x00, 0x20, 0x00, 0x52, 0x00, + 0x65, 0x00, 0x61, 0x00, 0x64, 0x00, 0x65, 0x00, 0x72, 0x00, 0x00, 0x00, 0x3a, 0x00, 0x0b, 0x00, 0x01, 0x00, + 0x50, 0x00, 0x72, 0x00, 0x6f, 0x00, 0x64, 0x00, 0x75, 0x00, 0x63, 0x00, 0x74, 0x00, 0x56, 0x00, 0x65, 0x00, + 0x72, 0x00, 0x73, 0x00, 0x69, 0x00, 0x6f, 0x00, 0x6e, 0x00, 0x00, 0x00, 0x31, 0x00, 0x2c, 0x00, 0x20, 0x00, + 0x30, 0x00, 0x2c, 0x00, 0x20, 0x00, 0x30, 0x00, 0x2c, 0x00, 0x20, 0x00, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x44, 0x00, 0x00, 0x00, 0x01, 0x00, 0x56, 0x00, 0x61, 0x00, 0x72, 0x00, 0x46, 0x00, 0x69, 0x00, 0x6c, 0x00, + 0x65, 0x00, 0x49, 0x00, 0x6e, 0x00, 0x66, 0x00, 0x6f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x24, 0x00, 0x04, 0x00, + 0x00, 0x00, 0x54, 0x00, 0x72, 0x00, 0x61, 0x00, 0x6e, 0x00, 0x73, 0x00, 0x6c, 0x00, 0x61, 0x00, 0x74, 0x00, + 0x69, 0x00, 0x6f, 0x00, 0x6e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x04, 0xb0, 0x04, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, + 0x10, 0x30, 0x5c, 0x30, 0x82, 0x30, 0x87, 0x30, 0x91, 0x30, 0x9b, 0x30, 0x00, 0x40, 0x00, 0x00, 0x1c, 0x00, + 0x00, 0x00, 0x09, 0x30, 0x0f, 0x30, 0x2f, 0x30, 0x38, 0x30, 0x4c, 0x30, 0x5b, 0x30, 0x67, 0x30, 0x6c, 0x30, + 0x79, 0x30, 0x80, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +}; +int cc_x64driver_code_size = 5120; +uint8_t cc_x64driver_code[5120] = +{ + 0x4d, 0x5a, 0x90, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xb8, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd0, 0x00, 0x00, 0x00, 0x0e, 0x1f, 0xba, 0x0e, 0x00, 0xb4, 0x09, 0xcd, + 0x21, 0xb8, 0x01, 0x4c, 0xcd, 0x21, 0x54, 0x68, 0x69, 0x73, 0x20, 0x70, 0x72, 0x6f, 0x67, 0x72, 0x61, 0x6d, + 0x20, 0x63, 0x61, 0x6e, 0x6e, 0x6f, 0x74, 0x20, 0x62, 0x65, 0x20, 0x72, 0x75, 0x6e, 0x20, 0x69, 0x6e, 0x20, + 0x44, 0x4f, 0x53, 0x20, 0x6d, 0x6f, 0x64, 0x65, 0x2e, 0x0d, 0x0d, 0x0a, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xb7, 0x04, 0xa8, 0xc2, 0xf3, 0x65, 0xc6, 0x91, 0xf3, 0x65, 0xc6, 0x91, 0xf3, 0x65, 0xc6, 0x91, + 0xf3, 0x65, 0xc7, 0x91, 0xf4, 0x65, 0xc6, 0x91, 0x85, 0xf8, 0xbd, 0x91, 0xf0, 0x65, 0xc6, 0x91, 0x85, 0xf8, + 0xab, 0x91, 0xf0, 0x65, 0xc6, 0x91, 0x30, 0x6a, 0x98, 0x91, 0xf2, 0x65, 0xc6, 0x91, 0x85, 0xf8, 0xbe, 0x91, + 0xf2, 0x65, 0xc6, 0x91, 0x52, 0x69, 0x63, 0x68, 0xf3, 0x65, 0xc6, 0x91, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, 0x45, 0x00, 0x00, 0x64, 0x86, 0x07, 0x00, + 0x41, 0xc8, 0x6d, 0x49, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x22, 0x00, 0x0b, 0x02, + 0x08, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x60, 0x00, 0x00, + 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x02, + 0x00, 0x00, 0x05, 0x00, 0x02, 0x00, 0x05, 0x00, 0x02, 0x00, 0x05, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x80, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x79, 0x44, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6c, 0x60, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, + 0x00, 0x70, 0x00, 0x00, 0xc0, 0x03, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x20, 0x00, 0x00, + 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x2e, 0x74, 0x65, 0x78, 0x74, 0x00, 0x00, 0x00, 0x26, 0x01, 0x00, 0x00, 0x00, 0x10, + 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x68, 0x2e, 0x72, 0x64, 0x61, 0x74, 0x61, 0x00, 0x00, 0xf0, 0x00, + 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x48, 0x2e, 0x64, 0x61, 0x74, 0x61, 0x00, + 0x00, 0x00, 0x18, 0x01, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0xc8, 0x2e, 0x70, + 0x64, 0x61, 0x74, 0x61, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, + 0x00, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, + 0x00, 0x48, 0x50, 0x41, 0x47, 0x45, 0x30, 0x44, 0x45, 0x46, 0x4e, 0x01, 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, + 0x00, 0x02, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x20, 0x00, 0x00, 0x60, 0x49, 0x4e, 0x49, 0x54, 0x00, 0x00, 0x00, 0x00, 0x60, 0x01, 0x00, 0x00, + 0x00, 0x60, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0xe2, 0x2e, 0x72, 0x73, 0x72, 0x63, 0x00, 0x00, 0x00, + 0xc0, 0x03, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x42, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x83, 0xec, 0x28, + 0x33, 0xc9, 0x48, 0x8b, 0xc2, 0x89, 0x4a, 0x30, 0x48, 0x89, 0x4a, 0x38, 0x33, 0xd2, 0x48, 0x8b, 0xc8, 0xff, + 0x15, 0xfd, 0x0f, 0x00, 0x00, 0x33, 0xc0, 0x48, 0x83, 0xc4, 0x28, 0xc3, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, + 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x48, 0x83, 0xec, 0x28, 0x48, 0x8b, 0x82, 0xb8, 0x00, 0x00, + 0x00, 0x4c, 0x8b, 0xca, 0x81, 0x78, 0x18, 0x0c, 0xe0, 0x22, 0x00, 0x75, 0x43, 0x83, 0x78, 0x08, 0x08, 0x72, + 0x3d, 0x83, 0x78, 0x10, 0x04, 0x75, 0x08, 0x48, 0x8b, 0x42, 0x18, 0x8b, 0x08, 0xeb, 0x05, 0xb9, 0x9c, 0x01, + 0x00, 0x00, 0x4c, 0x8b, 0x42, 0x18, 0x0f, 0x32, 0x48, 0xc1, 0xe2, 0x20, 0x49, 0x8b, 0xc9, 0x48, 0x0b, 0xc2, + 0x33, 0xd2, 0x49, 0x89, 0x00, 0x49, 0xc7, 0x41, 0x38, 0x08, 0x00, 0x00, 0x00, 0xff, 0x15, 0x95, 0x0f, 0x00, + 0x00, 0x33, 0xc0, 0x48, 0x83, 0xc4, 0x28, 0xc3, 0xc7, 0x42, 0x30, 0x01, 0x00, 0x00, 0xc0, 0x48, 0xc7, 0x42, + 0x38, 0x00, 0x00, 0x00, 0x00, 0x49, 0x8b, 0xc9, 0x33, 0xd2, 0xff, 0x15, 0x74, 0x0f, 0x00, 0x00, 0xb8, 0x01, + 0x00, 0x00, 0xc0, 0x48, 0x83, 0xc4, 0x28, 0xc3, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, + 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x48, 0x83, 0xec, 0x38, 0x48, 0x8b, 0x49, 0x08, 0xff, 0x15, + 0x32, 0x0f, 0x00, 0x00, 0x48, 0x8d, 0x15, 0x1b, 0x00, 0x00, 0x00, 0x48, 0x8d, 0x4c, 0x24, 0x20, 0xff, 0x15, + 0x18, 0x0f, 0x00, 0x00, 0x48, 0x8d, 0x4c, 0x24, 0x20, 0xff, 0x15, 0x05, 0x0f, 0x00, 0x00, 0x48, 0x83, 0xc4, + 0x38, 0xc3, 0x5c, 0x00, 0x44, 0x00, 0x6f, 0x00, 0x73, 0x00, 0x44, 0x00, 0x65, 0x00, 0x76, 0x00, 0x69, 0x00, + 0x63, 0x00, 0x65, 0x00, 0x73, 0x00, 0x5c, 0x00, 0x54, 0x00, 0x6d, 0x00, 0x70, 0x00, 0x52, 0x00, 0x64, 0x00, + 0x72, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe6, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x60, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x16, 0x61, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, 0x61, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x40, 0x61, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd0, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x41, 0xc8, 0x6d, 0x49, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x49, 0x00, 0x00, 0x00, + 0x5c, 0x20, 0x00, 0x00, 0x5c, 0x06, 0x00, 0x00, 0x52, 0x53, 0x44, 0x53, 0xd9, 0x5e, 0xab, 0x47, 0xc4, 0xf2, + 0x4f, 0x40, 0xaa, 0xe9, 0x90, 0x47, 0x67, 0x30, 0xa5, 0xfa, 0x03, 0x00, 0x00, 0x00, 0x44, 0x3a, 0x5c, 0x74, + 0x6d, 0x70, 0x5c, 0x4b, 0x65, 0x72, 0x6e, 0x65, 0x6c, 0x5c, 0x6f, 0x62, 0x6a, 0x66, 0x72, 0x65, 0x5f, 0x77, + 0x6e, 0x65, 0x74, 0x5f, 0x41, 0x4d, 0x44, 0x36, 0x34, 0x5c, 0x61, 0x6d, 0x64, 0x36, 0x34, 0x5c, 0x54, 0x6d, + 0x70, 0x52, 0x64, 0x72, 0x2e, 0x70, 0x64, 0x62, 0x00, 0x00, 0x00, 0x00, 0x01, 0x04, 0x01, 0x00, 0x04, 0x42, + 0x00, 0x00, 0x01, 0x04, 0x01, 0x00, 0x04, 0x42, 0x00, 0x00, 0x01, 0x04, 0x01, 0x00, 0x04, 0x62, 0x00, 0x00, + 0x21, 0x00, 0x00, 0x00, 0x10, 0x50, 0x00, 0x00, 0x74, 0x50, 0x00, 0x00, 0xe4, 0x20, 0x00, 0x00, 0x21, 0x08, + 0x02, 0x00, 0x08, 0x74, 0x13, 0x00, 0x10, 0x50, 0x00, 0x00, 0x74, 0x50, 0x00, 0x00, 0xe4, 0x20, 0x00, 0x00, + 0x01, 0x0c, 0x03, 0x00, 0x0c, 0x34, 0x12, 0x00, 0x04, 0xe2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xcd, 0x5d, 0x20, 0xd2, 0x66, 0xd4, 0xff, 0xff, 0x32, 0xa2, 0xdf, 0x2d, 0x99, 0x2b, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x10, 0x10, 0x00, 0x00, 0x32, 0x10, 0x00, 0x00, 0xa8, 0x20, 0x00, 0x00, 0x40, 0x10, + 0x00, 0x00, 0xbe, 0x10, 0x00, 0x00, 0xb0, 0x20, 0x00, 0x00, 0xd0, 0x10, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, + 0xb8, 0x20, 0x00, 0x00, 0x10, 0x50, 0x00, 0x00, 0x74, 0x50, 0x00, 0x00, 0xe4, 0x20, 0x00, 0x00, 0x74, 0x50, + 0x00, 0x00, 0xe8, 0x50, 0x00, 0x00, 0xd0, 0x20, 0x00, 0x00, 0xe8, 0x50, 0x00, 0x00, 0xf5, 0x50, 0x00, 0x00, + 0xc0, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x83, 0xec, 0x78, 0x48, 0x89, 0x9c, 0x24, + 0x90, 0x00, 0x00, 0x00, 0x48, 0x8b, 0xd9, 0x48, 0x8d, 0x15, 0x0a, 0x01, 0x00, 0x00, 0x48, 0x8d, 0x4c, 0x24, + 0x48, 0xff, 0x15, 0xd7, 0xcf, 0xff, 0xff, 0x41, 0xb9, 0x22, 0x00, 0x00, 0x00, 0x4c, 0x8d, 0x5c, 0x24, 0x40, + 0x4c, 0x89, 0x5c, 0x24, 0x30, 0x4c, 0x8d, 0x44, 0x24, 0x48, 0x41, 0x8d, 0x51, 0xe6, 0x48, 0x8b, 0xcb, 0xc6, + 0x44, 0x24, 0x28, 0x00, 0xc7, 0x44, 0x24, 0x20, 0x00, 0x00, 0x00, 0x00, 0xff, 0x15, 0xc0, 0xcf, 0xff, 0xff, + 0x85, 0xc0, 0x0f, 0x85, 0x80, 0x00, 0x00, 0x00, 0x48, 0x8d, 0x15, 0x91, 0x00, 0x00, 0x00, 0x48, 0x8d, 0x4c, + 0x24, 0x58, 0x48, 0x89, 0xbc, 0x24, 0x98, 0x00, 0x00, 0x00, 0xff, 0x15, 0x86, 0xcf, 0xff, 0xff, 0x48, 0x8d, + 0x54, 0x24, 0x48, 0x48, 0x8d, 0x4c, 0x24, 0x58, 0xff, 0x15, 0x86, 0xcf, 0xff, 0xff, 0x85, 0xc0, 0x8b, 0xf8, + 0x74, 0x0f, 0x48, 0x8b, 0x4c, 0x24, 0x40, 0xff, 0x15, 0x6d, 0xcf, 0xff, 0xff, 0x8b, 0xc7, 0xeb, 0x39, 0x48, + 0x8b, 0x44, 0x24, 0x40, 0x48, 0x89, 0x05, 0x5d, 0xe0, 0xff, 0xff, 0x48, 0x8d, 0x05, 0x16, 0xc0, 0xff, 0xff, + 0x48, 0x89, 0x43, 0x68, 0x48, 0x8d, 0x05, 0x4b, 0xbf, 0xff, 0xff, 0x48, 0x89, 0x43, 0x70, 0x48, 0x89, 0x83, + 0x80, 0x00, 0x00, 0x00, 0x48, 0x8d, 0x05, 0x69, 0xbf, 0xff, 0xff, 0x48, 0x89, 0x83, 0xe0, 0x00, 0x00, 0x00, + 0x33, 0xc0, 0x48, 0x8b, 0xbc, 0x24, 0x98, 0x00, 0x00, 0x00, 0x48, 0x8b, 0x9c, 0x24, 0x90, 0x00, 0x00, 0x00, + 0x48, 0x83, 0xc4, 0x78, 0xc3, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x5c, 0x00, + 0x44, 0x00, 0x6f, 0x00, 0x73, 0x00, 0x44, 0x00, 0x65, 0x00, 0x76, 0x00, 0x69, 0x00, 0x63, 0x00, 0x65, 0x00, + 0x73, 0x00, 0x5c, 0x00, 0x54, 0x00, 0x6d, 0x00, 0x70, 0x00, 0x52, 0x00, 0x64, 0x00, 0x72, 0x00, 0x00, 0x00, + 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x5c, 0x00, 0x44, 0x00, 0x65, 0x00, 0x76, 0x00, + 0x69, 0x00, 0x63, 0x00, 0x65, 0x00, 0x5c, 0x00, 0x54, 0x00, 0x6d, 0x00, 0x70, 0x00, 0x52, 0x00, 0x64, 0x00, + 0x72, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x48, 0x8b, 0x05, 0xf1, 0xd0, 0xff, 0xff, 0x49, 0xb9, 0x32, 0xa2, 0xdf, 0x2d, 0x99, 0x2b, 0x00, 0x00, 0x48, + 0x85, 0xc0, 0x74, 0x05, 0x49, 0x3b, 0xc1, 0x75, 0x2f, 0x4c, 0x8d, 0x05, 0xd6, 0xd0, 0xff, 0xff, 0x48, 0xb8, + 0x20, 0x03, 0x00, 0x00, 0x80, 0xf7, 0xff, 0xff, 0x48, 0x8b, 0x00, 0x49, 0x33, 0xc0, 0x49, 0xb8, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x49, 0x23, 0xc0, 0x49, 0x0f, 0x44, 0xc1, 0x48, 0x89, 0x05, 0xae, 0xd0, + 0xff, 0xff, 0x48, 0xf7, 0xd0, 0x48, 0x89, 0x05, 0x9c, 0xd0, 0xff, 0xff, 0xe9, 0xa7, 0xef, 0xff, 0xff, 0xcc, + 0xcc, 0xcc, 0x98, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x52, 0x61, 0x00, 0x00, + 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe6, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xfe, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x16, 0x61, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, 0x61, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x61, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd0, 0x60, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf6, 0x01, 0x49, 0x6f, 0x66, 0x43, + 0x6f, 0x6d, 0x70, 0x6c, 0x65, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x00, 0x00, 0x61, 0x01, + 0x49, 0x6f, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x53, 0x79, 0x6d, 0x62, 0x6f, 0x6c, 0x69, 0x63, 0x4c, 0x69, + 0x6e, 0x6b, 0x00, 0x00, 0x3e, 0x04, 0x52, 0x74, 0x6c, 0x49, 0x6e, 0x69, 0x74, 0x55, 0x6e, 0x69, 0x63, 0x6f, + 0x64, 0x65, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x00, 0x00, 0x5f, 0x01, 0x49, 0x6f, 0x44, 0x65, 0x6c, 0x65, + 0x74, 0x65, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x00, 0x00, 0x55, 0x01, 0x49, 0x6f, 0x43, 0x72, 0x65, 0x61, + 0x74, 0x65, 0x53, 0x79, 0x6d, 0x62, 0x6f, 0x6c, 0x69, 0x63, 0x4c, 0x69, 0x6e, 0x6b, 0x00, 0x00, 0x4c, 0x01, + 0x49, 0x6f, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x00, 0x00, 0x6e, 0x74, + 0x6f, 0x73, 0x6b, 0x72, 0x6e, 0x6c, 0x2e, 0x65, 0x78, 0x65, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x10, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x80, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x30, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x09, 0x04, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, 0x60, 0x70, 0x00, 0x00, 0x60, 0x03, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x03, + 0x34, 0x00, 0x00, 0x00, 0x56, 0x00, 0x53, 0x00, 0x5f, 0x00, 0x56, 0x00, 0x45, 0x00, 0x52, 0x00, 0x53, 0x00, + 0x49, 0x00, 0x4f, 0x00, 0x4e, 0x00, 0x5f, 0x00, 0x49, 0x00, 0x4e, 0x00, 0x46, 0x00, 0x4f, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xbd, 0x04, 0xef, 0xfe, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, + 0x04, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xbe, 0x02, 0x00, 0x00, 0x01, 0x00, 0x53, 0x00, 0x74, 0x00, 0x72, 0x00, 0x69, 0x00, 0x6e, 0x00, 0x67, 0x00, + 0x46, 0x00, 0x69, 0x00, 0x6c, 0x00, 0x65, 0x00, 0x49, 0x00, 0x6e, 0x00, 0x66, 0x00, 0x6f, 0x00, 0x00, 0x00, + 0x9a, 0x02, 0x00, 0x00, 0x01, 0x00, 0x30, 0x00, 0x34, 0x00, 0x30, 0x00, 0x39, 0x00, 0x30, 0x00, 0x34, 0x00, + 0x62, 0x00, 0x30, 0x00, 0x00, 0x00, 0x58, 0x00, 0x20, 0x00, 0x01, 0x00, 0x43, 0x00, 0x6f, 0x00, 0x6d, 0x00, + 0x6d, 0x00, 0x65, 0x00, 0x6e, 0x00, 0x74, 0x00, 0x73, 0x00, 0x00, 0x00, 0x4d, 0x00, 0x53, 0x00, 0x52, 0x00, + 0x20, 0x00, 0x72, 0x00, 0x65, 0x00, 0x61, 0x00, 0x64, 0x00, 0x65, 0x00, 0x72, 0x00, 0x20, 0x00, 0x36, 0x00, + 0x34, 0x00, 0x2d, 0x00, 0x62, 0x00, 0x69, 0x00, 0x74, 0x00, 0x20, 0x00, 0x6b, 0x00, 0x65, 0x00, 0x72, 0x00, + 0x6e, 0x00, 0x65, 0x00, 0x6c, 0x00, 0x20, 0x00, 0x64, 0x00, 0x72, 0x00, 0x69, 0x00, 0x76, 0x00, 0x65, 0x00, + 0x72, 0x00, 0x00, 0x00, 0x42, 0x00, 0x11, 0x00, 0x01, 0x00, 0x43, 0x00, 0x6f, 0x00, 0x6d, 0x00, 0x70, 0x00, + 0x61, 0x00, 0x6e, 0x00, 0x79, 0x00, 0x4e, 0x00, 0x61, 0x00, 0x6d, 0x00, 0x65, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x49, 0x00, 0x72, 0x00, 0x6f, 0x00, 0x6e, 0x00, 0x20, 0x00, 0x53, 0x00, 0x74, 0x00, 0x65, 0x00, 0x65, 0x00, + 0x64, 0x00, 0x73, 0x00, 0x20, 0x00, 0x49, 0x00, 0x6e, 0x00, 0x63, 0x00, 0x2e, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x60, 0x00, 0x1c, 0x00, 0x01, 0x00, 0x46, 0x00, 0x69, 0x00, 0x6c, 0x00, 0x65, 0x00, 0x44, 0x00, 0x65, 0x00, + 0x73, 0x00, 0x63, 0x00, 0x72, 0x00, 0x69, 0x00, 0x70, 0x00, 0x74, 0x00, 0x69, 0x00, 0x6f, 0x00, 0x6e, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x54, 0x00, 0x6d, 0x00, 0x70, 0x00, 0x52, 0x00, 0x64, 0x00, 0x72, 0x00, 0x20, 0x00, + 0x36, 0x00, 0x34, 0x00, 0x2d, 0x00, 0x62, 0x00, 0x69, 0x00, 0x74, 0x00, 0x20, 0x00, 0x4b, 0x00, 0x65, 0x00, + 0x72, 0x00, 0x6e, 0x00, 0x65, 0x00, 0x6c, 0x00, 0x20, 0x00, 0x4d, 0x00, 0x6f, 0x00, 0x64, 0x00, 0x75, 0x00, + 0x6c, 0x00, 0x65, 0x00, 0x00, 0x00, 0x36, 0x00, 0x0b, 0x00, 0x01, 0x00, 0x46, 0x00, 0x69, 0x00, 0x6c, 0x00, + 0x65, 0x00, 0x56, 0x00, 0x65, 0x00, 0x72, 0x00, 0x73, 0x00, 0x69, 0x00, 0x6f, 0x00, 0x6e, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x31, 0x00, 0x2c, 0x00, 0x20, 0x00, 0x30, 0x00, 0x2c, 0x00, 0x20, 0x00, 0x30, 0x00, 0x2c, 0x00, + 0x20, 0x00, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2e, 0x00, 0x07, 0x00, 0x01, 0x00, 0x49, 0x00, 0x6e, 0x00, + 0x74, 0x00, 0x65, 0x00, 0x72, 0x00, 0x6e, 0x00, 0x61, 0x00, 0x6c, 0x00, 0x4e, 0x00, 0x61, 0x00, 0x6d, 0x00, + 0x65, 0x00, 0x00, 0x00, 0x54, 0x00, 0x6d, 0x00, 0x70, 0x00, 0x52, 0x00, 0x64, 0x00, 0x72, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x4a, 0x00, 0x13, 0x00, 0x01, 0x00, 0x4c, 0x00, 0x65, 0x00, 0x67, 0x00, 0x61, 0x00, 0x6c, 0x00, + 0x43, 0x00, 0x6f, 0x00, 0x70, 0x00, 0x79, 0x00, 0x72, 0x00, 0x69, 0x00, 0x67, 0x00, 0x68, 0x00, 0x74, 0x00, + 0x00, 0x00, 0x4e, 0x00, 0x69, 0x00, 0x63, 0x00, 0x6b, 0x00, 0x20, 0x00, 0x47, 0x00, 0x61, 0x00, 0x62, 0x00, + 0x61, 0x00, 0x72, 0x00, 0x65, 0x00, 0x76, 0x00, 0x20, 0x00, 0x27, 0x00, 0x32, 0x00, 0x30, 0x00, 0x30, 0x00, + 0x39, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0x00, 0x0d, 0x00, 0x01, 0x00, 0x4f, 0x00, 0x72, 0x00, 0x69, 0x00, + 0x67, 0x00, 0x69, 0x00, 0x6e, 0x00, 0x61, 0x00, 0x6c, 0x00, 0x46, 0x00, 0x69, 0x00, 0x6c, 0x00, 0x65, 0x00, + 0x6e, 0x00, 0x61, 0x00, 0x6d, 0x00, 0x65, 0x00, 0x00, 0x00, 0x54, 0x00, 0x6d, 0x00, 0x70, 0x00, 0x52, 0x00, + 0x64, 0x00, 0x72, 0x00, 0x36, 0x00, 0x34, 0x00, 0x2e, 0x00, 0x73, 0x00, 0x79, 0x00, 0x73, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x54, 0x00, 0x1a, 0x00, 0x01, 0x00, 0x50, 0x00, 0x72, 0x00, 0x6f, 0x00, 0x64, 0x00, 0x75, 0x00, + 0x63, 0x00, 0x74, 0x00, 0x4e, 0x00, 0x61, 0x00, 0x6d, 0x00, 0x65, 0x00, 0x00, 0x00, 0x00, 0x00, 0x43, 0x00, + 0x6f, 0x00, 0x72, 0x00, 0x65, 0x00, 0x20, 0x00, 0x32, 0x00, 0x20, 0x00, 0x54, 0x00, 0x65, 0x00, 0x6d, 0x00, + 0x70, 0x00, 0x65, 0x00, 0x72, 0x00, 0x61, 0x00, 0x74, 0x00, 0x75, 0x00, 0x72, 0x00, 0x65, 0x00, 0x20, 0x00, + 0x52, 0x00, 0x65, 0x00, 0x61, 0x00, 0x64, 0x00, 0x65, 0x00, 0x72, 0x00, 0x00, 0x00, 0x3a, 0x00, 0x0b, 0x00, + 0x01, 0x00, 0x50, 0x00, 0x72, 0x00, 0x6f, 0x00, 0x64, 0x00, 0x75, 0x00, 0x63, 0x00, 0x74, 0x00, 0x56, 0x00, + 0x65, 0x00, 0x72, 0x00, 0x73, 0x00, 0x69, 0x00, 0x6f, 0x00, 0x6e, 0x00, 0x00, 0x00, 0x31, 0x00, 0x2c, 0x00, + 0x20, 0x00, 0x30, 0x00, 0x2c, 0x00, 0x20, 0x00, 0x30, 0x00, 0x2c, 0x00, 0x20, 0x00, 0x31, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x44, 0x00, 0x00, 0x00, 0x01, 0x00, 0x56, 0x00, 0x61, 0x00, 0x72, 0x00, 0x46, 0x00, 0x69, 0x00, + 0x6c, 0x00, 0x65, 0x00, 0x49, 0x00, 0x6e, 0x00, 0x66, 0x00, 0x6f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x24, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x54, 0x00, 0x72, 0x00, 0x61, 0x00, 0x6e, 0x00, 0x73, 0x00, 0x6c, 0x00, 0x61, 0x00, + 0x74, 0x00, 0x69, 0x00, 0x6f, 0x00, 0x6e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x04, 0xb0, 0x04, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +}; +//} end +#endif // _WIN32 + +int msrdriver_dummy; // a dummy to avoid a linker warning on OS X. diff --git a/src/3rdparty/libcpuid/rdmsr.c b/src/3rdparty/libcpuid/rdmsr.c new file mode 100644 index 00000000..60a75600 --- /dev/null +++ b/src/3rdparty/libcpuid/rdmsr.c @@ -0,0 +1,1291 @@ +/* + * Copyright 2009 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. + */ +#define _XOPEN_SOURCE 500 +#include +#include +#include +#include "libcpuid.h" +#include "asm-bits.h" +#include "libcpuid_util.h" +#include "libcpuid_internal.h" +#include "rdtsc.h" + +#if defined (__linux__) || defined (__gnu_linux__) +/* Assuming linux with /dev/cpu/x/msr: */ +#include +#include +#include +#include +#include +#include +struct msr_driver_t +{ + int fd; +}; +static int rdmsr_supported(void); +static int load_driver(char* msr_path) +{ + const int file_exists = !access(msr_path, F_OK); + const int file_readable = !access(msr_path, R_OK); + + if(file_exists && file_readable) + { + return 1; + } + else if(file_exists && !file_readable) + { + return 0; + } + else if(getuid() != 0) + { + return 0; + } + else + { + return !system("modprobe msr 2> /dev/null"); + } +} + +struct msr_driver_t* cpu_msr_driver_open(void) +{ + return cpu_msr_driver_open_core(0); +} + +struct msr_driver_t* cpu_msr_driver_open_core(unsigned core_num) +{ + char msr[32]; + struct msr_driver_t* handle; + if(core_num >= cpuid_get_total_cpus()) + { + set_error(ERR_INVCNB); + return NULL; + } + if(!rdmsr_supported()) + { + set_error(ERR_NO_RDMSR); + return NULL; + } + sprintf(msr, "/dev/cpu/%u/msr", core_num); + if(!load_driver(msr)) + { + set_error(ERR_NO_DRIVER); + return NULL; + } + int fd = open(msr, O_RDONLY); + if(fd < 0) + { + if(errno == EIO) + { + set_error(ERR_NO_RDMSR); + return NULL; + } + set_error(ERR_NO_DRIVER); + return NULL; + } + handle = (struct msr_driver_t*) malloc(sizeof(struct msr_driver_t)); + handle->fd = fd; + return handle; +} + +int cpu_rdmsr(struct msr_driver_t* driver, uint32_t msr_index, uint64_t* result) +{ + ssize_t ret; + + if(!driver || driver->fd < 0) + { + return set_error(ERR_HANDLE); + } + ret = pread(driver->fd, result, 8, msr_index); + if(ret != 8) + { + return set_error(ERR_INVMSR); + } + return 0; +} + +int cpu_msr_driver_close(struct msr_driver_t* drv) +{ + if(drv && drv->fd >= 0) + { + close(drv->fd); + free(drv); + } + return 0; +} + +/* #endif defined (__linux__) || defined (__gnu_linux__) */ + +#elif defined (__FreeBSD__) || defined (__DragonFly__) +/* Assuming FreeBSD with /dev/cpuctlX */ +#include +#include +#include +#include +#include + +struct msr_driver_t +{ + int fd; +}; +static int rdmsr_supported(void); +static int load_driver(char* msr_path) +{ + const int file_exists = !access(msr_path, F_OK); + const int file_readable = !access(msr_path, R_OK); + + if(file_exists && file_readable) + { + return 1; + } + else if(file_exists && !file_readable) + { + return 0; + } + else if(getuid() != 0) + { + return 0; + } + else + { + return !system("kldload -n cpuctl 2> /dev/null"); + } +} + +struct msr_driver_t* cpu_msr_driver_open(void) +{ + return cpu_msr_driver_open_core(0); +} + +struct msr_driver_t* cpu_msr_driver_open_core(unsigned core_num) +{ + char msr[32]; + struct msr_driver_t* handle; + if(core_num >= cpuid_get_total_cpus()) + { + set_error(ERR_INVCNB); + return NULL; + } + if(!rdmsr_supported()) + { + set_error(ERR_NO_RDMSR); + return NULL; + } + sprintf(msr, "/dev/cpuctl%u", core_num); + if(!load_driver(msr)) + { + set_error(ERR_NO_DRIVER); + return NULL; + } + int fd = open(msr, O_RDONLY); + if(fd < 0) + { + if(errno == EIO) + { + set_error(ERR_NO_RDMSR); + return NULL; + } + set_error(ERR_NO_DRIVER); + return NULL; + } + handle = (struct msr_driver_t*) malloc(sizeof(struct msr_driver_t)); + handle->fd = fd; + return handle; +} + +int cpu_rdmsr(struct msr_driver_t* driver, uint32_t msr_index, uint64_t* result) +{ + cpuctl_msr_args_t args; + args.msr = msr_index; + + if(!driver || driver->fd < 0) + { + return set_error(ERR_HANDLE); + } + + if(ioctl(driver->fd, CPUCTL_RDMSR, &args)) + { + return set_error(ERR_INVMSR); + } + + *result = args.data; + return 0; +} + +int cpu_msr_driver_close(struct msr_driver_t* drv) +{ + if(drv && drv->fd >= 0) + { + close(drv->fd); + free(drv); + } + return 0; +} + +/* #endif defined (__FreeBSD__) || defined (__DragonFly__) */ + +#elif defined (_WIN32) +#include +#include +#include + +extern uint8_t cc_x86driver_code[]; +extern int cc_x86driver_code_size; +extern uint8_t cc_x64driver_code[]; +extern int cc_x64driver_code_size; + +struct msr_driver_t +{ + char driver_path[MAX_PATH + 1]; + SC_HANDLE scManager; + volatile SC_HANDLE scDriver; + HANDLE hhDriver; + OVERLAPPED ovl; + int errorcode; +}; + +static int rdmsr_supported(void); +static int extract_driver(struct msr_driver_t* driver); +static int load_driver(struct msr_driver_t* driver); + +struct msr_driver_t* cpu_msr_driver_open(void) +{ + struct msr_driver_t* drv; + int status; + if(!rdmsr_supported()) + { + set_error(ERR_NO_RDMSR); + return NULL; + } + + drv = (struct msr_driver_t*) malloc(sizeof(struct msr_driver_t)); + if(!drv) + { + set_error(ERR_NO_MEM); + return NULL; + } + memset(drv, 0, sizeof(struct msr_driver_t)); + + if(!extract_driver(drv)) + { + free(drv); + set_error(ERR_EXTRACT); + return NULL; + } + + status = load_driver(drv); + if(!DeleteFile(drv->driver_path)) + { + debugf(1, "Deleting temporary driver file failed.\n"); + } + if(!status) + { + set_error(drv->errorcode ? drv->errorcode : ERR_NO_DRIVER); + free(drv); + return NULL; + } + return drv; +} + +struct msr_driver_t* cpu_msr_driver_open_core(unsigned core_num) +{ + warnf("cpu_msr_driver_open_core(): parameter ignored (function is the same as cpu_msr_driver_open)\n"); + return cpu_msr_driver_open(); +} + +typedef BOOL (WINAPI* LPFN_ISWOW64PROCESS)(HANDLE, PBOOL); +static BOOL is_running_x64(void) +{ + BOOL bIsWow64 = FALSE; + + LPFN_ISWOW64PROCESS fnIsWow64Process = (LPFN_ISWOW64PROCESS)GetProcAddress(GetModuleHandle(__TEXT("kernel32")), + "IsWow64Process"); + if(NULL != fnIsWow64Process) + { + fnIsWow64Process(GetCurrentProcess(), &bIsWow64); + } + return bIsWow64; +} + + +static int extract_driver(struct msr_driver_t* driver) +{ + FILE* f; + if(!GetTempPath(sizeof(driver->driver_path), driver->driver_path)) + { + return 0; + } + strcat(driver->driver_path, "TmpRdr.sys"); + + f = fopen(driver->driver_path, "wb"); + if(!f) + { + return 0; + } + if(is_running_x64()) + { + fwrite(cc_x64driver_code, 1, cc_x64driver_code_size, f); + } + else + { + fwrite(cc_x86driver_code, 1, cc_x86driver_code_size, f); + } + fclose(f); + return 1; +} + +static BOOL wait_for_service_state(SC_HANDLE hService, DWORD dwDesiredState, SERVICE_STATUS* lpsrvStatus) +{ + BOOL fOK = FALSE; + DWORD dwWaitHint; + + if(hService != NULL) + { + while(TRUE) + { + fOK = QueryServiceStatus(hService, lpsrvStatus); + if(!fOK) + { + break; + } + if(lpsrvStatus->dwCurrentState == dwDesiredState) + { + break; + } + + dwWaitHint = lpsrvStatus->dwWaitHint / 10; // Poll 1/10 of the wait hint + if(dwWaitHint < 1000) + { + dwWaitHint = 1000; // At most once per second + } + if(dwWaitHint > 10000) + { + dwWaitHint = 10000; // At least every 10 seconds + } + Sleep(dwWaitHint); + } + } + + return fOK; +} + +static int load_driver(struct msr_driver_t* drv) +{ + LPTSTR lpszInfo = __TEXT("RDMSR Executor Driver"); + USHORT uLen = 0; + SERVICE_STATUS srvStatus = {0}; + BOOL fRunning = FALSE; + DWORD dwLastError; + LPTSTR lpszDriverServiceName = __TEXT("TmpRdr"); + TCHAR lpszDriverName[] = __TEXT("\\\\.\\Global\\TmpRdr"); + + if((LPVOID)(drv->scManager = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS)) != NULL) + { + drv->scDriver = CreateService(drv->scManager, lpszDriverServiceName, lpszInfo, SERVICE_ALL_ACCESS, + SERVICE_KERNEL_DRIVER, SERVICE_DEMAND_START, SERVICE_ERROR_NORMAL, + drv->driver_path, NULL, NULL, NULL, NULL, NULL); + if(drv->scDriver == NULL) + { + switch(dwLastError = GetLastError()) + { + case ERROR_SERVICE_EXISTS: + case ERROR_SERVICE_MARKED_FOR_DELETE: + { + LPQUERY_SERVICE_CONFIG lpqsc; + DWORD dwBytesNeeded; + + drv->scDriver = OpenService(drv->scManager, lpszDriverServiceName, SERVICE_ALL_ACCESS); + if(drv->scDriver == NULL) + { + debugf(1, "Error opening service: %d\n", GetLastError()); + break; + } + + QueryServiceConfig(drv->scDriver, NULL, 0, &dwBytesNeeded); + if((dwLastError = GetLastError()) == ERROR_INSUFFICIENT_BUFFER) + { + lpqsc = calloc(1, dwBytesNeeded); + if(!QueryServiceConfig(drv->scDriver, lpqsc, dwBytesNeeded, &dwBytesNeeded)) + { + free(lpqsc); + debugf(1, "Error query service config(adjusted buffer): %d\n", GetLastError()); + goto clean_up; + } + else + { + free(lpqsc); + } + } + else + { + debugf(1, "Error query service config: %d\n", dwLastError); + goto clean_up; + } + + break; + } + case ERROR_ACCESS_DENIED: + drv->errorcode = ERR_NO_PERMS; + break; + default: + debugf(1, "Create driver service failed: %d\n", dwLastError); + break; + } + } + if(drv->scDriver != NULL) + { + if(StartService(drv->scDriver, 0, NULL)) + { + if(!wait_for_service_state(drv->scDriver, SERVICE_RUNNING, &srvStatus)) + { + debugf(1, "Driver load failed.\n"); + DeleteService(drv->scDriver); + CloseServiceHandle(drv->scManager); + drv->scDriver = NULL; + goto clean_up; + } + else + { + fRunning = TRUE; + } + } + else + { + if((dwLastError = GetLastError()) == ERROR_SERVICE_ALREADY_RUNNING) + { + fRunning = TRUE; + } + else + { + debugf(1, "Driver start failed.\n"); + DeleteService(drv->scDriver); + CloseServiceHandle(drv->scManager); + drv->scDriver = NULL; + goto clean_up; + } + + } + if(fRunning) + { + debugf(1, "Driver already running.\n"); + } + else + { + debugf(1, "Driver loaded.\n"); + } + CloseServiceHandle(drv->scManager); + drv->hhDriver = CreateFile(lpszDriverName, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, 0, + OPEN_EXISTING, FILE_FLAG_OVERLAPPED, 0); + drv->ovl.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL); + return 1; + } + } + else + { + debugf(1, "Open SCM failed: %d\n", GetLastError()); + } + +clean_up: + if(drv->scManager != NULL) + { + CloseServiceHandle(drv->scManager); + drv->scManager = 0; // pointless + } + if(drv->scDriver != NULL) + { + if(!DeleteService(drv->scDriver)) + { + debugf(1, "Delete driver service failed: %d\n", GetLastError()); + } + CloseServiceHandle(drv->scDriver); + drv->scDriver = 0; + } + + return 0; +} + +#define FILE_DEVICE_UNKNOWN 0x00000022 +#define IOCTL_UNKNOWN_BASE FILE_DEVICE_UNKNOWN +#define IOCTL_PROCVIEW_RDMSR CTL_CODE(IOCTL_UNKNOWN_BASE, 0x0803, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS) + +int cpu_rdmsr(struct msr_driver_t* driver, uint32_t msr_index, uint64_t* result) +{ + DWORD dwBytesReturned; + __int64 msrdata; + SERVICE_STATUS srvStatus = {0}; + + if(!driver) + { + return set_error(ERR_HANDLE); + } + DeviceIoControl(driver->hhDriver, IOCTL_PROCVIEW_RDMSR, &msr_index, sizeof(int), &msrdata, sizeof(__int64), + &dwBytesReturned, &driver->ovl); + GetOverlappedResult(driver->hhDriver, &driver->ovl, &dwBytesReturned, TRUE); + *result = msrdata; + return 0; +} + +int cpu_msr_driver_close(struct msr_driver_t* drv) +{ + SERVICE_STATUS srvStatus = {0}; + if(drv == NULL) + { + return 0; + } + if(drv->scDriver != NULL) + { + if(drv->hhDriver) + { + CancelIo(drv->hhDriver); + } + if(drv->ovl.hEvent != NULL) + { + CloseHandle(drv->ovl.hEvent); + } + if(drv->hhDriver) + { + CloseHandle(drv->hhDriver); + } + drv->hhDriver = NULL; + drv->ovl.hEvent = NULL; + if(ControlService(drv->scDriver, SERVICE_CONTROL_STOP, &srvStatus)) + { + if(wait_for_service_state(drv->scDriver, SERVICE_STOPPED, &srvStatus)) + { + DeleteService(drv->scDriver); + } + } + } + return 0; +} + +/* endif defined (_WIN32) */ + +#else /* Unsupported OS */ +/* On others OS (i.e., Darwin), we still do not support RDMSR, so supply dummy struct + and functions */ + +#define RDMSR_UNSUPPORTED_OS + +struct msr_driver_t +{ + int dummy; +}; +struct msr_driver_t* cpu_msr_driver_open(void) +{ + set_error(ERR_NOT_IMP); + return NULL; +} + +struct msr_driver_t* cpu_msr_driver_open_core(unsigned core_num) +{ + set_error(ERR_NOT_IMP); + return NULL; +} + +int cpu_rdmsr(struct msr_driver_t* driver, uint32_t msr_index, uint64_t* result) +{ + return set_error(ERR_NOT_IMP); +} + +int cpu_msr_driver_close(struct msr_driver_t* driver) +{ + return set_error(ERR_NOT_IMP); +} + +int cpu_rdmsr_range(struct msr_driver_t* handle, uint32_t msr_index, uint8_t highbit, + uint8_t lowbit, uint64_t* result) +{ + return set_error(ERR_NOT_IMP); +} + +int cpu_msrinfo(struct msr_driver_t* driver, cpu_msrinfo_request_t which) +{ + return set_error(ERR_NOT_IMP); +} + +int msr_serialize_raw_data(struct msr_driver_t* handle, const char* filename) +{ + return set_error(ERR_NOT_IMP); +} + +#endif /* Unsupported OS */ + +#ifndef RDMSR_UNSUPPORTED_OS + +/* Useful links for hackers: +- AMD MSRs: + AMD BIOS and Kernel Developer’s Guide (BKDG) + * AMD Family 10h Processors + http://support.amd.com/TechDocs/31116.pdf + * AMD Family 11h Processors + http://support.amd.com/TechDocs/41256.pdf + * AMD Family 12h Processors + http://support.amd.com/TechDocs/41131.pdf + * AMD Family 14h Processors + http://support.amd.com/TechDocs/43170_14h_Mod_00h-0Fh_BKDG.pdf + * AMD Family 15h Processors + http://support.amd.com/TechDocs/42301_15h_Mod_00h-0Fh_BKDG.pdf + http://support.amd.com/TechDocs/42300_15h_Mod_10h-1Fh_BKDG.pdf + http://support.amd.com/TechDocs/49125_15h_Models_30h-3Fh_BKDG.pdf + http://support.amd.com/TechDocs/50742_15h_Models_60h-6Fh_BKDG.pdf + http://support.amd.com/TechDocs/55072_AMD_Family_15h_Models_70h-7Fh_BKDG.pdf + * AMD Family 16h Processors + http://support.amd.com/TechDocs/48751_16h_bkdg.pdf + http://support.amd.com/TechDocs/52740_16h_Models_30h-3Fh_BKDG.pdf + + AMD Processor Programming Reference (PPR) + * AMD Family 17h Processors + https://support.amd.com/TechDocs/54945_PPR_Family_17h_Models_00h-0Fh.pdf + +- Intel MSRs: + Intel® 64 and IA-32 Architectures Software Developer’s Manual + * Volume 3 (3A, 3B, 3C & 3D): System Programming Guide + http://www.intel.com/content/dam/www/public/us/en/documents/manuals/64-ia-32-architectures-software-developer-system-programming-manual-325384.pdf +*/ + +/* AMD MSRs addresses */ +#define MSR_PSTATE_L 0xC0010061 +#define MSR_PSTATE_S 0xC0010063 +#define MSR_PSTATE_0 0xC0010064 +#define MSR_PSTATE_1 0xC0010065 +#define MSR_PSTATE_2 0xC0010066 +#define MSR_PSTATE_3 0xC0010067 +#define MSR_PSTATE_4 0xC0010068 +#define MSR_PSTATE_5 0xC0010069 +#define MSR_PSTATE_6 0xC001006A +#define MSR_PSTATE_7 0xC001006B +static const uint32_t amd_msr[] = +{ + MSR_PSTATE_L, + MSR_PSTATE_S, + MSR_PSTATE_0, + MSR_PSTATE_1, + MSR_PSTATE_2, + MSR_PSTATE_3, + MSR_PSTATE_4, + MSR_PSTATE_5, + MSR_PSTATE_6, + MSR_PSTATE_7, + CPU_INVALID_VALUE +}; + +/* Intel MSRs addresses */ +#define IA32_MPERF 0xE7 +#define IA32_APERF 0xE8 +#define IA32_PERF_STATUS 0x198 +#define IA32_THERM_STATUS 0x19C +#define MSR_EBL_CR_POWERON 0x2A +#define MSR_TURBO_RATIO_LIMIT 0x1AD +#define MSR_TEMPERATURE_TARGET 0x1A2 +#define MSR_PERF_STATUS 0x198 +#define MSR_PLATFORM_INFO 0xCE +static const uint32_t intel_msr[] = +{ + IA32_MPERF, + IA32_APERF, + IA32_PERF_STATUS, + IA32_THERM_STATUS, + MSR_EBL_CR_POWERON, + MSR_TURBO_RATIO_LIMIT, + MSR_TEMPERATURE_TARGET, + MSR_PERF_STATUS, + MSR_PLATFORM_INFO, + CPU_INVALID_VALUE +}; + +struct msr_info_t +{ + int cpu_clock; + struct msr_driver_t* handle; + struct cpu_id_t* id; + struct internal_id_info_t* internal; +}; + +static int rdmsr_supported(void) +{ + struct cpu_id_t* id = get_cached_cpuid(); + return id->flags[CPU_FEATURE_MSR]; +} + +static int perfmsr_measure(struct msr_driver_t* handle, int msr) +{ + int err; + uint64_t a, b; + uint64_t x, y; + err = cpu_rdmsr(handle, msr, &x); + if(err) + { + return CPU_INVALID_VALUE; + } + sys_precise_clock(&a); + busy_loop_delay(10); + cpu_rdmsr(handle, msr, &y); + sys_precise_clock(&b); + if(a >= b || x > y) + { + return CPU_INVALID_VALUE; + } + return (int)((y - x) / (b - a)); +} + +static int get_amd_multipliers(struct msr_info_t* info, uint32_t pstate, double* multiplier) +{ + int i, err; + uint64_t CpuFid, CpuDid, CpuDidLSD; + + /* Constant values needed for 12h family */ + const struct + { + uint64_t did; + double divisor; + } divisor_t[] = + { + { 0x0, 1 }, + { 0x1, 1.5 }, + { 0x2, 2 }, + { 0x3, 3 }, + { 0x4, 4 }, + { 0x5, 6 }, + { 0x6, 8 }, + { 0x7, 12 }, + { 0x8, 16 }, + }; + const int num_dids = (int) COUNT_OF(divisor_t); + + /* Constant values for common families */ + const int magic_constant = (info->id->ext_family == 0x11) ? 0x8 : 0x10; + const int is_apu = ((FUSION_C <= info->internal->code.amd) && (info->internal->code.amd <= FUSION_A)) || + (info->internal->bits & _APU_); + const double divisor = is_apu ? 1.0 : 2.0; + + /* Check if P-state is valid */ + if(pstate < MSR_PSTATE_0 || MSR_PSTATE_7 < pstate) + { + return 1; + } + + switch(info->id->ext_family) + { + case 0x12: + /* BKDG 12h, page 469 + MSRC001_00[6B:64][8:4] is CpuFid + MSRC001_00[6B:64][3:0] is CpuDid + CPU COF is (100MHz * (CpuFid + 10h) / (divisor specified by CpuDid)) + Note: This family contains only APUs */ + err = cpu_rdmsr_range(info->handle, pstate, 8, 4, &CpuFid); + err += cpu_rdmsr_range(info->handle, pstate, 3, 0, &CpuDid); + i = 0; + while(i < num_dids && divisor_t[i].did != CpuDid) + { + i++; + } + if(i < num_dids) + { + *multiplier = (double)((CpuFid + magic_constant) / divisor_t[i].divisor); + } + else + { + err++; + } + break; + case 0x14: + /* BKDG 14h, page 430 + MSRC001_00[6B:64][8:4] is CpuDidMSD + MSRC001_00[6B:64][3:0] is CpuDidLSD + PLL COF is (100 MHz * (D18F3xD4[MainPllOpFreqId] + 10h)) + Divisor is (CpuDidMSD + (CpuDidLSD * 0.25) + 1) + CPU COF is (main PLL frequency specified by D18F3xD4[MainPllOpFreqId]) / (core clock divisor specified by CpuDidMSD and CpuDidLSD) + Note: This family contains only APUs */ + err = cpu_rdmsr_range(info->handle, pstate, 8, 4, &CpuDid); + err += cpu_rdmsr_range(info->handle, pstate, 3, 0, &CpuDidLSD); + *multiplier = (double)(((info->cpu_clock + 5) / 100 + magic_constant) / (CpuDid + CpuDidLSD * 0.25 + 1)); + break; + case 0x10: + /* BKDG 10h, page 429 + MSRC001_00[6B:64][8:6] is CpuDid + MSRC001_00[6B:64][5:0] is CpuFid + CPU COF is (100 MHz * (CpuFid + 10h) / (2^CpuDid)) + Note: This family contains only CPUs */ + case 0x11: + /* BKDG 11h, page 236 + MSRC001_00[6B:64][8:6] is CpuDid + MSRC001_00[6B:64][5:0] is CpuFid + CPU COF is ((100 MHz * (CpuFid + 08h)) / (2^CpuDid)) + Note: This family contains only CPUs */ + case 0x15: + /* BKDG 15h, page 570/580/635/692 (00h-0Fh/10h-1Fh/30h-3Fh/60h-6Fh) + MSRC001_00[6B:64][8:6] is CpuDid + MSRC001_00[6B:64][5:0] is CpuFid + CoreCOF is (100 * (MSRC001_00[6B:64][CpuFid] + 10h) / (2^MSRC001_00[6B:64][CpuDid])) + Note: This family contains BOTH CPUs and APUs */ + case 0x16: + /* BKDG 16h, page 549/611 (00h-0Fh/30h-3Fh) + MSRC001_00[6B:64][8:6] is CpuDid + MSRC001_00[6B:64][5:0] is CpuFid + CoreCOF is (100 * (MSRC001_00[6B:64][CpuFid] + 10h) / (2^MSRC001_00[6B:64][CpuDid])) + Note: This family contains only APUs */ + err = cpu_rdmsr_range(info->handle, pstate, 8, 6, &CpuDid); + err += cpu_rdmsr_range(info->handle, pstate, 5, 0, &CpuFid); + *multiplier = (double)((CpuFid + magic_constant) / (1ull << CpuDid)) / divisor; + break; + case 0x17: + /* PPR 17h, pages 30 and 138-139 + MSRC001_00[6B:64][13:8] is CpuDfsId + MSRC001_00[6B:64][7:0] is CpuFid + CoreCOF is (Core::X86::Msr::PStateDef[CpuFid[7:0]] / Core::X86::Msr::PStateDef[CpuDfsId]) * 200 */ + err = cpu_rdmsr_range(info->handle, pstate, 13, 8, &CpuDid); + err += cpu_rdmsr_range(info->handle, pstate, 7, 0, &CpuFid); + *multiplier = (double)(CpuFid / CpuDid) * 2; + break; + default: + err = 1; + break; + } + + return err; +} + +static uint32_t get_amd_last_pstate_addr(struct msr_info_t* info) +{ + static uint32_t last_addr = 0x0; + uint64_t reg = 0x0; + + /* The result is cached, need to be computed once */ + if(last_addr != 0x0) + { + return last_addr; + } + + /* Refer links above + MSRC001_00[6B:64][63] is PstateEn + PstateEn indicates if the rest of the P-state information in the register is valid after a reset */ + last_addr = MSR_PSTATE_7 + 1; + while((reg == 0x0) && (last_addr > MSR_PSTATE_0)) + { + last_addr--; + cpu_rdmsr_range(info->handle, last_addr, 63, 63, ®); + } + return last_addr; +} + +static double get_info_min_multiplier(struct msr_info_t* info) +{ + int err; + double mult; + uint32_t addr; + uint64_t reg; + + if(info->id->vendor == VENDOR_INTEL) + { + /* Refer links above + Table 35-12. MSRs in Next Generation Intel Atom Processors Based on the Goldmont Microarchitecture + Table 35-13. MSRs in Processors Based on Intel® Microarchitecture Code Name Nehalem + Table 35-18. MSRs Supported by Intel® Processors based on Intel® microarchitecture code name Sandy Bridge (Contd.) + Table 35-23. Additional MSRs Supported by 3rd Generation Intel® Coreâ„¢ Processors (based on Intel® microarchitecture code name Ivy Bridge) + Table 35-24. MSRs Supported by Intel® Xeon® Processors E5 v2 Product Family (based on Ivy Bridge-E microarchitecture) + Table 35-27. Additional MSRs Supported by Processors based on the Haswell or Haswell-E microarchitectures + Table 35-34. Additional MSRs Common to Intel® Xeon® Processor D and Intel Xeon Processors E5 v4 Family Based on the Broadwell Microarchitecture + Table 35-40. Selected MSRs Supported by Next Generation Intel® Xeon Phiâ„¢ Processors with DisplayFamily_DisplayModel Signature 06_57H + MSR_PLATFORM_INFO[47:40] is Maximum Efficiency Ratio + Maximum Efficiency Ratio is the minimum ratio that the processor can operates */ + err = cpu_rdmsr_range(info->handle, MSR_PLATFORM_INFO, 47, 40, ®); + if(!err) + { + return (double) reg; + } + } + else if(info->id->vendor == VENDOR_AMD) + { + /* N.B.: Find the last P-state + get_amd_last_pstate_addr() returns the last P-state, MSR_PSTATE_0 <= addr <= MSR_PSTATE_7 */ + addr = get_amd_last_pstate_addr(info); + err = get_amd_multipliers(info, addr, &mult); + if(!err) + { + return mult; + } + } + + return (double) CPU_INVALID_VALUE / 100; +} + +static double get_info_cur_multiplier(struct msr_info_t* info) +{ + int err; + double mult; + uint64_t reg; + + if(info->id->vendor == VENDOR_INTEL && info->internal->code.intel == PENTIUM) + { + err = cpu_rdmsr(info->handle, MSR_EBL_CR_POWERON, ®); + if(!err) + { + return (double)((reg >> 22) & 0x1f); + } + } + else if(info->id->vendor == VENDOR_INTEL && info->internal->code.intel != PENTIUM) + { + /* Refer links above + Table 35-2. IA-32 Architectural MSRs (Contd.) + IA32_PERF_STATUS[15:0] is Current performance State Value + [7:0] is 0x0, [15:8] looks like current ratio */ + err = cpu_rdmsr_range(info->handle, IA32_PERF_STATUS, 15, 8, ®); + if(!err) + { + return (double) reg; + } + } + else if(info->id->vendor == VENDOR_AMD) + { + /* Refer links above + MSRC001_0063[2:0] is CurPstate */ + err = cpu_rdmsr_range(info->handle, MSR_PSTATE_S, 2, 0, ®); + err += get_amd_multipliers(info, MSR_PSTATE_0 + (uint32_t) reg, &mult); + if(!err) + { + return mult; + } + } + + return (double) CPU_INVALID_VALUE / 100; +} + +static double get_info_max_multiplier(struct msr_info_t* info) +{ + int err; + double mult; + uint64_t reg; + + if(info->id->vendor == VENDOR_INTEL && info->internal->code.intel == PENTIUM) + { + err = cpu_rdmsr(info->handle, IA32_PERF_STATUS, ®); + if(!err) + { + return (double)((reg >> 40) & 0x1f); + } + } + else if(info->id->vendor == VENDOR_INTEL && info->internal->code.intel != PENTIUM) + { + /* Refer links above + Table 35-10. Specific MSRs Supported by Intel® Atomâ„¢ Processor C2000 Series with CPUID Signature 06_4DH + Table 35-12. MSRs in Next Generation Intel Atom Processors Based on the Goldmont Microarchitecture (Contd.) + Table 35-13. MSRs in Processors Based on Intel® Microarchitecture Code Name Nehalem (Contd.) + Table 35-14. Additional MSRs in Intel® Xeon® Processor 5500 and 3400 Series + Table 35-16. Additional MSRs Supported by Intel Processors (Based on Intel® Microarchitecture Code Name Westmere) + Table 35-19. MSRs Supported by 2nd Generation Intel® Coreâ„¢ Processors (Intel® microarchitecture code name Sandy Bridge) + Table 35-21. Selected MSRs Supported by Intel® Xeon® Processors E5 Family (based on Sandy Bridge microarchitecture) + Table 35-28. MSRs Supported by 4th Generation Intel® Coreâ„¢ Processors (Haswell microarchitecture) (Contd.) + Table 35-30. Additional MSRs Supported by Intel® Xeon® Processor E5 v3 Family + Table 35-33. Additional MSRs Supported by Intel® Coreâ„¢ M Processors and 5th Generation Intel® Coreâ„¢ Processors + Table 35-34. Additional MSRs Common to Intel® Xeon® Processor D and Intel Xeon Processors E5 v4 Family Based on the Broadwell Microarchitecture + Table 35-37. Additional MSRs Supported by 6th Generation Intel® Coreâ„¢ Processors Based on Skylake Microarchitecture + Table 35-40. Selected MSRs Supported by Next Generation Intel® Xeon Phiâ„¢ Processors with DisplayFamily_DisplayModel Signature 06_57H + MSR_TURBO_RATIO_LIMIT[7:0] is Maximum Ratio Limit for 1C */ + err = cpu_rdmsr_range(info->handle, MSR_TURBO_RATIO_LIMIT, 7, 0, ®); + if(!err) + { + return (double) reg; + } + } + else if(info->id->vendor == VENDOR_AMD) + { + /* Refer links above + MSRC001_0064 is Pb0 + Pb0 is the highest-performance boosted P-state */ + err = get_amd_multipliers(info, MSR_PSTATE_0, &mult); + if(!err) + { + return mult; + } + } + + return (double) CPU_INVALID_VALUE / 100; +} + +static int get_info_temperature(struct msr_info_t* info) +{ + int err; + uint64_t DigitalReadout, ReadingValid, TemperatureTarget; + + if(info->id->vendor == VENDOR_INTEL) + { + /* Refer links above + Table 35-2. IA-32 Architectural MSRs + IA32_THERM_STATUS[22:16] is Digital Readout + IA32_THERM_STATUS[31] is Reading Valid + + Table 35-6. MSRs Common to the Silvermont Microarchitecture and Newer Microarchitectures for Intel® Atom + Table 35-13. MSRs in Processors Based on Intel® Microarchitecture Code Name Nehalem (Contd.) + Table 35-18. MSRs Supported by Intel® Processors based on Intel® microarchitecture code name Sandy Bridge (Contd.) + Table 35-24. MSRs Supported by Intel® Xeon® Processors E5 v2 Product Family (based on Ivy Bridge-E microarchitecture) (Contd.) + Table 35-34. Additional MSRs Common to Intel® Xeon® Processor D and Intel Xeon Processors E5 v4 Family Based on the Broadwell Microarchitecture + Table 35-40. Selected MSRs Supported by Next Generation Intel® Xeon Phiâ„¢ Processors with DisplayFamily_DisplayModel Signature 06_57H + MSR_TEMPERATURE_TARGET[23:16] is Temperature Target */ + err = cpu_rdmsr_range(info->handle, IA32_THERM_STATUS, 22, 16, &DigitalReadout); + err += cpu_rdmsr_range(info->handle, IA32_THERM_STATUS, 31, 31, &ReadingValid); + err += cpu_rdmsr_range(info->handle, MSR_TEMPERATURE_TARGET, 23, 16, &TemperatureTarget); + if(!err && ReadingValid) + { + return (int)(TemperatureTarget - DigitalReadout); + } + } + + return CPU_INVALID_VALUE; +} + +static double get_info_voltage(struct msr_info_t* info) +{ + int err; + double VIDStep; + uint64_t reg, CpuVid; + + if(info->id->vendor == VENDOR_INTEL) + { + /* Refer links above + Table 35-18. MSRs Supported by Intel® Processors based on Intel® microarchitecture code name Sandy Bridge (Contd.) + MSR_PERF_STATUS[47:32] is Core Voltage + P-state core voltage can be computed by MSR_PERF_STATUS[37:32] * (float) 1/(2^13). */ + err = cpu_rdmsr_range(info->handle, MSR_PERF_STATUS, 47, 32, ®); + if(!err) + { + return (double) reg / (1 << 13); + } + } + else if(info->id->vendor == VENDOR_AMD) + { + /* Refer links above + MSRC001_00[6B:64][15:9] is CpuVid (Jaguar and before) + MSRC001_00[6B:64][21:14] is CpuVid (Zen) + MSRC001_0063[2:0] is P-state Status + BKDG 10h, page 49: voltage = 1.550V - 0.0125V * SviVid (SVI1) + BKDG 15h, page 50: Voltage = 1.5500 - 0.00625 * Vid[7:0] (SVI2) + SVI2 since Piledriver (Family 15h, 2nd-gen): Models 10h-1Fh Processors */ + VIDStep = ((info->id->ext_family < 0x15) || ((info->id->ext_family == 0x15) && + (info->id->ext_model < 0x10))) ? 0.0125 : 0.00625; + err = cpu_rdmsr_range(info->handle, MSR_PSTATE_S, 2, 0, ®); + if(info->id->ext_family < 0x17) + { + err += cpu_rdmsr_range(info->handle, MSR_PSTATE_0 + (uint32_t) reg, 15, 9, &CpuVid); + } + else + { + err += cpu_rdmsr_range(info->handle, MSR_PSTATE_0 + (uint32_t) reg, 21, 14, &CpuVid); + } + if(!err && MSR_PSTATE_0 + (uint32_t) reg <= MSR_PSTATE_7) + { + return 1.550 - VIDStep * CpuVid; + } + } + + return (double) CPU_INVALID_VALUE / 100; +} + +static double get_info_bus_clock(struct msr_info_t* info) +{ + int err; + double mult; + uint32_t addr; + uint64_t reg; + + if(info->id->vendor == VENDOR_INTEL) + { + /* Refer links above + Table 35-12. MSRs in Next Generation Intel Atom Processors Based on the Goldmont Microarchitecture + Table 35-13. MSRs in Processors Based on Intel® Microarchitecture Code Name Nehalem + Table 35-18. MSRs Supported by Intel® Processors based on Intel® microarchitecture code name Sandy Bridge (Contd.) + Table 35-23. Additional MSRs Supported by 3rd Generation Intel® Coreâ„¢ Processors (based on Intel® microarchitecture code name Ivy Bridge) + Table 35-24. MSRs Supported by Intel® Xeon® Processors E5 v2 Product Family (based on Ivy Bridge-E microarchitecture) + Table 35-27. Additional MSRs Supported by Processors based on the Haswell or Haswell-E microarchitectures + Table 35-40. Selected MSRs Supported by Next Generation Intel® Xeon Phiâ„¢ Processors with DisplayFamily_DisplayModel Signature 06_57H + MSR_PLATFORM_INFO[15:8] is Maximum Non-Turbo Ratio */ + err = cpu_rdmsr_range(info->handle, MSR_PLATFORM_INFO, 15, 8, ®); + if(!err) + { + return (double) info->cpu_clock / reg; + } + } + else if(info->id->vendor == VENDOR_AMD) + { + /* Refer links above + MSRC001_0061[6:4] is PstateMaxVal + PstateMaxVal is the the lowest-performance non-boosted P-state */ + addr = get_amd_last_pstate_addr(info); + err = cpu_rdmsr_range(info->handle, MSR_PSTATE_L, 6, 4, ®); + err += get_amd_multipliers(info, addr - reg, &mult); + if(!err) + { + return (double) info->cpu_clock / mult; + } + } + + return (double) CPU_INVALID_VALUE / 100; +} + +int cpu_rdmsr_range(struct msr_driver_t* handle, uint32_t msr_index, uint8_t highbit, + uint8_t lowbit, uint64_t* result) +{ + int err; + const uint8_t bits = highbit - lowbit + 1; + + if(highbit > 63 || lowbit > highbit) + { + return set_error(ERR_INVRANGE); + } + + err = cpu_rdmsr(handle, msr_index, result); + + if(!err && bits < 64) + { + /* Show only part of register */ + *result >>= lowbit; + *result &= (1ULL << bits) - 1; + } + + return err; +} + +int cpu_msrinfo(struct msr_driver_t* handle, cpu_msrinfo_request_t which) +{ + static int err = 0, init = 0; + struct cpu_raw_data_t raw; + static struct cpu_id_t id; + static struct internal_id_info_t internal; + static struct msr_info_t info; + + if(handle == NULL) + { + set_error(ERR_HANDLE); + return CPU_INVALID_VALUE; + } + + info.handle = handle; + if(!init) + { + err = cpuid_get_raw_data(&raw); + err += cpu_ident_internal(&raw, &id, &internal); + info.cpu_clock = cpu_clock_measure(250, 1); + info.id = &id; + info.internal = &internal; + init = 1; + } + + if(err) + { + return CPU_INVALID_VALUE; + } + + switch(which) + { + case INFO_MPERF: + return perfmsr_measure(handle, IA32_MPERF); + case INFO_APERF: + return perfmsr_measure(handle, IA32_APERF); + case INFO_MIN_MULTIPLIER: + return (int)(get_info_min_multiplier(&info) * 100); + case INFO_CUR_MULTIPLIER: + return (int)(get_info_cur_multiplier(&info) * 100); + case INFO_MAX_MULTIPLIER: + return (int)(get_info_max_multiplier(&info) * 100); + case INFO_TEMPERATURE: + return get_info_temperature(&info); + case INFO_THROTTLING: + return CPU_INVALID_VALUE; + case INFO_VOLTAGE: + return (int)(get_info_voltage(&info) * 100); + case INFO_BCLK: + case INFO_BUS_CLOCK: + return (int)(get_info_bus_clock(&info) * 100); + default: + return CPU_INVALID_VALUE; + } +} + +int msr_serialize_raw_data(struct msr_driver_t* handle, const char* filename) +{ + int i, j; + FILE* f; + uint64_t reg; + const uint32_t* msr; + struct cpu_raw_data_t raw; + struct cpu_id_t id; + struct internal_id_info_t internal; + + if(handle == NULL) + { + return set_error(ERR_HANDLE); + } + + if(!strcmp(filename, "")) + { + f = stdout; + } + else + { + f = fopen(filename, "wt"); + } + if(!f) + { + return set_error(ERR_OPEN); + } + + if(cpuid_get_raw_data(&raw) || cpu_ident_internal(&raw, &id, &internal)) + { + return -1; + } + + fprintf(f, "CPU is %s %s, stock clock is %dMHz.\n", id.vendor_str, id.brand_str, cpu_clock_measure(250, 1)); + if(id.vendor == VENDOR_INTEL) + { + msr = intel_msr; + } + else if(id.vendor == VENDOR_AMD) + { + msr = amd_msr; + } + else + { + return set_error(ERR_CPU_UNKN); + } + + for(i = 0; msr[i] != CPU_INVALID_VALUE; i++) + { + cpu_rdmsr(handle, msr[i], ®); + fprintf(f, "msr[%#08x]=", msr[i]); + for(j = 56; j >= 0; j -= 8) + { + fprintf(f, "%02x ", (int)(reg >> j) & 0xff); + } + printf("\n"); + } + + if(strcmp(filename, "")) + { + fclose(f); + } + return set_error(ERR_OK); +} + +#endif // RDMSR_UNSUPPORTED_OS diff --git a/src/3rdparty/libcpuid/rdtsc.c b/src/3rdparty/libcpuid/rdtsc.c new file mode 100644 index 00000000..4c810132 --- /dev/null +++ b/src/3rdparty/libcpuid/rdtsc.c @@ -0,0 +1,409 @@ +/* + * 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 +#include +#include "libcpuid.h" +#include "libcpuid_util.h" +#include "asm-bits.h" +#include "rdtsc.h" + +#ifdef _WIN32 +#include +void sys_precise_clock(uint64_t* result) +{ + double c, f; + LARGE_INTEGER freq, counter; + QueryPerformanceCounter(&counter); + QueryPerformanceFrequency(&freq); + c = (double) counter.QuadPart; + f = (double) freq.QuadPart; + *result = (uint64_t)(c * 1000000.0 / f); +} +#else +/* assuming Linux, Mac OS or other POSIX */ +#include +void sys_precise_clock(uint64_t* result) +{ + struct timeval tv; + gettimeofday(&tv, NULL); + *result = (uint64_t) tv.tv_sec * (uint64_t) 1000000 + + (uint64_t) tv.tv_usec; +} +#endif /* _WIN32 */ + +/* out = a - b */ +static void mark_t_subtract(struct cpu_mark_t* a, struct cpu_mark_t* b, struct cpu_mark_t* out) +{ + out->tsc = a->tsc - b->tsc; + out->sys_clock = a->sys_clock - b->sys_clock; +} + +void cpu_tsc_mark(struct cpu_mark_t* mark) +{ + cpu_rdtsc(&mark->tsc); + sys_precise_clock(&mark->sys_clock); +} + +void cpu_tsc_unmark(struct cpu_mark_t* mark) +{ + struct cpu_mark_t temp; + cpu_tsc_mark(&temp); + mark_t_subtract(&temp, mark, mark); +} + + +int cpu_clock_by_mark(struct cpu_mark_t* mark) +{ + uint64_t result; + + /* Check if some subtraction resulted in a negative number: */ + if((mark->tsc >> 63) != 0 || (mark->sys_clock >> 63) != 0) + { + return -1; + } + + /* Divide-by-zero check: */ + if(mark->sys_clock == 0) + { + return -1; + } + + /* Check if the result fits in 32bits */ + result = mark->tsc / mark->sys_clock; + if(result > (uint64_t) 0x7fffffff) + { + return -1; + } + return (int) result; +} + +#ifdef _WIN32 +int cpu_clock_by_os(void) +{ + HKEY key; + DWORD result; + DWORD size = 4; + + if(RegOpenKeyEx(HKEY_LOCAL_MACHINE, TEXT("HARDWARE\\DESCRIPTION\\System\\CentralProcessor\\0"), 0, KEY_READ, + &key) != ERROR_SUCCESS) + { + return -1; + } + + if(RegQueryValueEx(key, TEXT("~MHz"), NULL, NULL, (LPBYTE) &result, (LPDWORD) &size) != ERROR_SUCCESS) + { + RegCloseKey(key); + return -1; + } + RegCloseKey(key); + + return (int)result; +} +#else +#ifdef __APPLE__ +#include +#include +/* Assuming Mac OS X with hw.cpufrequency sysctl */ +int cpu_clock_by_os(void) +{ + long long result = -1; + size_t size = sizeof(result); + if(sysctlbyname("hw.cpufrequency", &result, &size, NULL, 0)) + { + return -1; + } + return (int)(result / (long long) 1000000); +} +#else +/* Assuming Linux with /proc/cpuinfo */ +int cpu_clock_by_os(void) +{ + FILE* f; + char line[1024], *s; + int result; + + f = fopen("/proc/cpuinfo", "rt"); + if(!f) + { + return -1; + } + + while(fgets(line, sizeof(line), f)) + { + if(!strncmp(line, "cpu MHz", 7)) + { + s = strchr(line, ':'); + if(s && 1 == sscanf(s, ":%d.", &result)) + { + fclose(f); + return result; + } + } + } + fclose(f); + return -1; +} +#endif /* __APPLE__ */ +#endif /* _WIN32 */ + +/* Emulate doing useful CPU intensive work */ +static int busy_loop(int amount) +{ + int i, j, k, s = 0; + static volatile int data[42] = {32, 12, -1, 5, 23, 0 }; + for(i = 0; i < amount; i++) + for(j = 0; j < 65536; j++) + for(k = 0; k < 42; k++) + { + s += data[k]; + } + return s; +} + +int busy_loop_delay(int milliseconds) +{ + int cycles = 0, r = 0, first = 1; + uint64_t a, b, c; + sys_precise_clock(&a); + while(1) + { + sys_precise_clock(&c); + if((c - a) / 1000 > milliseconds) + { + return r; + } + r += busy_loop(cycles); + if(first) + { + first = 0; + } + else + { + if(c - b < 1000) + { + cycles *= 2; + } + if(c - b > 10000) + { + cycles /= 2; + } + } + b = c; + } +} + +int cpu_clock_measure(int millis, int quad_check) +{ + struct cpu_mark_t begin[4], end[4], temp, temp2; + int results[4], cycles, n, k, i, j, bi, bj, mdiff, diff, _zero = 0; + uint64_t tl; + + if(millis < 1) + { + return -1; + } + tl = millis * (uint64_t) 1000; + if(quad_check) + { + tl /= 4; + } + n = quad_check ? 4 : 1; + cycles = 1; + for(k = 0; k < n; k++) + { + cpu_tsc_mark(&begin[k]); + end[k] = begin[k]; + do + { + /* Run busy loop, and fool the compiler that we USE the garbishy + value it calculates */ + _zero |= (1 & busy_loop(cycles)); + cpu_tsc_mark(&temp); + mark_t_subtract(&temp, &end[k], &temp2); + /* If busy loop is too short, increase it */ + if(temp2.sys_clock < tl / 8) + { + cycles *= 2; + } + end[k] = temp; + } + while(end[k].sys_clock - begin[k].sys_clock < tl); + mark_t_subtract(&end[k], &begin[k], &temp); + results[k] = cpu_clock_by_mark(&temp); + } + if(n == 1) + { + return results[0]; + } + mdiff = 0x7fffffff; + bi = bj = -1; + for(i = 0; i < 4; i++) + { + for(j = i + 1; j < 4; j++) + { + diff = results[i] - results[j]; + if(diff < 0) + { + diff = -diff; + } + if(diff < mdiff) + { + mdiff = diff; + bi = i; + bj = j; + } + } + } + if(results[bi] == -1) + { + return -1; + } + return (results[bi] + results[bj] + _zero) / 2; +} + + +static void adjust_march_ic_multiplier(const struct cpu_id_t* id, int* numerator, int* denom) +{ + /* + * for cpu_clock_by_ic: we need to know how many clocks does a typical ADDPS instruction + * take, when issued in rapid succesion without dependencies. The whole idea of + * cpu_clock_by_ic was that this is easy to determine, at least it was back in 2010. Now + * it's getting progressively more hairy, but here are the current measurements: + * + * 1. For CPUs with 64-bit SSE units, ADDPS issue rate is 0.5 IPC (one insn in 2 clocks) + * 2. For CPUs with 128-bit SSE units, issue rate is exactly 1.0 IPC + * 3. For Bulldozer and later, it is 1.4 IPC (we multiply by 5/7) + * 4. For Skylake and later, it is 1.6 IPC (we multiply by 5/8) + */ + // + if(id->sse_size < 128) + { + debugf(1, "SSE execution path is 64-bit\n"); + // on a CPU with half SSE unit length, SSE instructions execute at 0.5 IPC; + // the resulting value must be multiplied by 2: + *numerator = 2; + } + else + { + debugf(1, "SSE execution path is 128-bit\n"); + } + // + // Bulldozer or later: assume 1.4 IPC + if(id->vendor == VENDOR_AMD && id->ext_family >= 21) + { + debugf(1, "cpu_clock_by_ic: Bulldozer (or later) detected, dividing result by 1.4\n"); + *numerator = 5; + *denom = 7; // multiply by 5/7, to divide by 1.4 + } + // + // Skylake or later: assume 1.6 IPC + if(id->vendor == VENDOR_INTEL && id->ext_model >= 94) + { + debugf(1, "cpu_clock_by_ic: Skylake (or later) detected, dividing result by 1.6\n"); + *numerator = 5; + *denom = 8; // to divide by 1.6, multiply by 5/8 + } +} + +int cpu_clock_by_ic(int millis, int runs) +{ + int max_value = 0, cur_value, i, ri, cycles_inner, cycles_outer, c; + struct cpu_id_t* id; + uint64_t t0, t1, tl, hz; + int multiplier_numerator = 1, multiplier_denom = 1; + if(millis <= 0 || runs <= 0) + { + return -2; + } + id = get_cached_cpuid(); + // if there aren't SSE instructions - we can't run the test at all + if(!id || !id->flags[CPU_FEATURE_SSE]) + { + return -1; + } + // + adjust_march_ic_multiplier(id, &multiplier_numerator, &multiplier_denom); + // + tl = millis * 125; // (*1000 / 8) + cycles_inner = 128; + cycles_outer = 1; + do + { + if(cycles_inner < 1000000000) + { + cycles_inner *= 2; + } + else + { + cycles_outer *= 2; + } + sys_precise_clock(&t0); + for(i = 0; i < cycles_outer; i++) + { + busy_sse_loop(cycles_inner); + } + sys_precise_clock(&t1); + } + while(t1 - t0 < tl); + debugf(2, "inner: %d, outer: %d\n", cycles_inner, cycles_outer); + for(ri = 0; ri < runs; ri++) + { + sys_precise_clock(&t0); + c = 0; + do + { + c++; + for(i = 0; i < cycles_outer; i++) + { + busy_sse_loop(cycles_inner); + } + sys_precise_clock(&t1); + } + while(t1 - t0 < tl * (uint64_t) 8); + // cpu_Hz = cycles_inner * cycles_outer * 256 / (t1 - t0) * 1000000 + debugf(2, "c = %d, td = %d\n", c, (int)(t1 - t0)); + hz = ((uint64_t) cycles_inner * (uint64_t) 256 + 12) * + (uint64_t) cycles_outer * (uint64_t) multiplier_numerator * (uint64_t) c * (uint64_t) 1000000 + / ((t1 - t0) * (uint64_t) multiplier_denom); + cur_value = (int)(hz / 1000000); + if(cur_value > max_value) + { + max_value = cur_value; + } + } + return max_value; +} + +int cpu_clock(void) +{ + int result; + result = cpu_clock_by_os(); + if(result <= 0) + { + result = cpu_clock_measure(200, 1); + } + return result; +} diff --git a/src/3rdparty/libcpuid/rdtsc.h b/src/3rdparty/libcpuid/rdtsc.h new file mode 100644 index 00000000..7a3307d9 --- /dev/null +++ b/src/3rdparty/libcpuid/rdtsc.h @@ -0,0 +1,33 @@ +/* + * Copyright 2010 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. + */ +#ifndef __RDTSC_H__ +#define __RDTSC_H__ + +void sys_precise_clock(uint64_t* result); +int busy_loop_delay(int milliseconds); + + +#endif /* __RDTSC_H__ */ diff --git a/src/3rdparty/libcpuid/recog_amd.c b/src/3rdparty/libcpuid/recog_amd.c index 352d733b..1c851901 100644 --- a/src/3rdparty/libcpuid/recog_amd.c +++ b/src/3rdparty/libcpuid/recog_amd.c @@ -32,35 +32,276 @@ #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 +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 { +struct amd_code_and_bits_t +{ int code; uint64_t bits; }; -enum _amd_model_codes_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[] = { + 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[] = { + const struct feature_map_t matchtable_ecx81[] = + { { 1, CPU_FEATURE_CMP_LEGACY }, { 2, CPU_FEATURE_SVM }, { 5, CPU_FEATURE_ABM }, @@ -75,7 +316,8 @@ static void load_amd_features(struct cpu_raw_data_t* raw, struct cpu_id_t* data) { 16, CPU_FEATURE_FMA4 }, { 21, CPU_FEATURE_TBM }, }; - const struct feature_map_t matchtable_edx87[] = { + const struct feature_map_t matchtable_edx87[] = + { { 0, CPU_FEATURE_TS }, { 1, CPU_FEATURE_FID }, { 2, CPU_FEATURE_VID }, @@ -90,13 +332,17 @@ static void load_amd_features(struct cpu_raw_data_t* raw, struct cpu_id_t* data) { 11, CPU_FEATURE_PFI }, { 12, CPU_FEATURE_PA }, }; - if (raw->ext_cpuid[0][0] >= 0x80000001) { + 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) + 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) { + } + 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; @@ -106,30 +352,36 @@ static void load_amd_features(struct cpu_raw_data_t* raw, struct cpu_id_t* data) 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] = { + 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) { + + 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) { + 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) { + 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 { + } + else + { data->l3_cache = 0; } } @@ -138,32 +390,249 @@ static void decode_amd_cache_info(struct cpu_raw_data_t* raw, struct cpu_id_t* d 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) { + + if(raw->basic_cpuid[0][0] >= 1) + { logical_cpus = (raw->basic_cpuid[1][1] >> 16) & 0xff; - if (raw->ext_cpuid[0][0] >= 8) { + 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. + 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 { + } + else + { data->num_cores = 1; data->num_logical_cpus = (logical_cpus >= 2 ? logical_cpus : 2); } - } else { + } + 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(strstr(bs, " APU ")) + { + bits |= _APU_; + } + + 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, "[EA]#-####")) + { + 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); +} diff --git a/src/3rdparty/libcpuid/recog_amd.h b/src/3rdparty/libcpuid/recog_amd.h index 19f839ba..34e89598 100644 --- a/src/3rdparty/libcpuid/recog_amd.h +++ b/src/3rdparty/libcpuid/recog_amd.h @@ -27,5 +27,6 @@ #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__ */ diff --git a/src/3rdparty/libcpuid/recog_intel.c b/src/3rdparty/libcpuid/recog_intel.c index 5467c19f..3e4707ac 100644 --- a/src/3rdparty/libcpuid/recog_intel.c +++ b/src/3rdparty/libcpuid/recog_intel.c @@ -30,19 +30,26 @@ #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 +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 { +typedef struct +{ int code; uint64_t bits; } intel_code_and_bits_t; -enum _intel_model_t { +enum _intel_model_t +{ UNKNOWN = -1, _3000 = 100, _3100, @@ -59,9 +66,302 @@ enum _intel_model_t { }; typedef enum _intel_model_t intel_model_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)" }, + { 6, 5, -1, -1, 85, 8, -1, -1, NC, XEON_, 0, "Skylake (Xeon Scalable)" }, + + /* 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)" }, + + /* Coffee Lake CPUs (14nm): */ + { 6, 14, -1, -1, 158, 6, -1, -1, NC, CORE_ | _I_ | _7 , 0, "Coffee Lake (Core i7)" }, + { 6, 14, -1, -1, 158, 6, -1, -1, NC, CORE_ | _I_ | _5 , 0, "Coffee Lake (Core i5)" }, + { 6, 14, -1, -1, 158, 4, -1, -1, NC, CORE_ | _I_ | _3 , 0, "Coffee Lake (Core i3)" }, + + /* 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[] = { + const struct feature_map_t matchtable_edx1[] = + { { 18, CPU_FEATURE_PN }, { 21, CPU_FEATURE_DTS }, { 22, CPU_FEATURE_ACPI }, @@ -70,7 +370,8 @@ static void load_intel_features(struct cpu_raw_data_t* raw, struct cpu_id_t* dat { 30, CPU_FEATURE_IA64 }, { 31, CPU_FEATURE_PBE }, }; - const struct feature_map_t matchtable_ecx1[] = { + const struct feature_map_t matchtable_ecx1[] = + { { 2, CPU_FEATURE_DTS64 }, { 4, CPU_FEATURE_DS_CPL }, { 5, CPU_FEATURE_VMX }, @@ -83,10 +384,12 @@ static void load_intel_features(struct cpu_raw_data_t* raw, struct cpu_id_t* dat { 18, CPU_FEATURE_DCA }, { 21, CPU_FEATURE_X2APIC }, }; - const struct feature_map_t matchtable_edx81[] = { + const struct feature_map_t matchtable_edx81[] = + { { 20, CPU_FEATURE_XD }, }; - const struct feature_map_t matchtable_ebx7[] = { + const struct feature_map_t matchtable_ebx7[] = + { { 2, CPU_FEATURE_SGX }, { 4, CPU_FEATURE_HLE }, { 11, CPU_FEATURE_RTM }, @@ -101,20 +404,24 @@ static void load_intel_features(struct cpu_raw_data_t* raw, struct cpu_id_t* dat { 30, CPU_FEATURE_AVX512BW }, { 31, CPU_FEATURE_AVX512VL }, }; - if (raw->basic_cpuid[0][0] >= 1) { + 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) { + 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) { + 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 { +enum _cache_type_t +{ L1I, L1D, L2, @@ -123,35 +430,40 @@ enum _cache_type_t { }; 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) +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; + 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; } } @@ -160,15 +472,20 @@ static void decode_intel_oldstyle_cache_info(struct cpu_raw_data_t* raw, struct uint8_t f[256] = {0}; int reg, off; uint32_t x; - for (reg = 0; reg < 4; reg++) { + for(reg = 0; reg < 4; reg++) + { x = raw->basic_cpuid[2][reg]; - if (x & 0x80000000) continue; - for (off = 0; off < 4; off++) { + 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); @@ -208,7 +525,7 @@ static void decode_intel_oldstyle_cache_info(struct cpu_raw_data_t* raw, struct 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); @@ -222,57 +539,82 @@ static void decode_intel_oldstyle_cache_info(struct cpu_raw_data_t* raw, struct 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]) { + + 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) { + if(data->family == 0xf && data->model == 0x6) + { data->l3_cache = 4096; data->l3_assoc = 16; data->l3_cacheline = 64; - } else { + } + else + { data->l2_cache = 4096; data->l2_assoc = 16; data->l2_cacheline = 64; } } - if (f[0x40]) { + 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) { + if(data->l2_cache == -1) + { data->l2_cache = 0; - } else { + } + else + { data->l3_cache = 0; } } } static void decode_intel_deterministic_cache_info(struct cpu_raw_data_t* raw, - struct cpu_id_t* data) + 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++) { + for(ecx = 0; ecx < MAX_INTELFN4_LEVEL; ecx++) + { typenumber = raw->intel_fn4[ecx][0] & 0x1f; - if (typenumber == 0) break; + if(typenumber == 0) + { + break; + } level = (raw->intel_fn4[ecx][0] >> 5) & 0x7; - if (level == 1 && typenumber == 1) + if(level == 1 && typenumber == 1) + { type = L1D; - else if (level == 1 && typenumber == 2) + } + else if(level == 1 && typenumber == 2) + { type = L1I; - else if (level == 2 && typenumber == 3) + } + else if(level == 2 && typenumber == 3) + { type = L2; - else if (level == 3 && typenumber == 3) + } + else if(level == 3 && typenumber == 3) + { type = L3; - else if (level == 4 && typenumber == 3) + } + else if(level == 4 && typenumber == 3) + { type = L4; - else { + } + 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; @@ -285,58 +627,80 @@ static void decode_intel_deterministic_cache_info(struct cpu_raw_data_t* raw, } static int decode_intel_extended_topology(struct cpu_raw_data_t* raw, - struct cpu_id_t* data) + struct cpu_id_t* data) { int i, level_type, num_smt = -1, num_core = -1; - for (i = 0; i < MAX_INTELFN11_LEVEL; i++) { + 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; + 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; + 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; + 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) + 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] >= 11) + { + if(decode_intel_extended_topology(raw, data)) + { + return; + } } - - if (raw->basic_cpuid[0][0] >= 1) { + + if(raw->basic_cpuid[0][0] >= 1) + { logical_cpus = (raw->basic_cpuid[1][1] >> 16) & 0xff; - if (raw->basic_cpuid[0][0] >= 4) { + 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) { + if(data->flags[CPU_FEATURE_HT]) + { + if(num_cores > 1) + { data->num_cores = num_cores; data->num_logical_cpus = logical_cpus; - } else { + } + else + { data->num_cores = 1; data->num_logical_cpus = (logical_cpus >= 1 ? logical_cpus : 1); - if (data->num_logical_cpus == 1) + if(data->num_logical_cpus == 1) + { data->flags[CPU_FEATURE_HT] = 0; + } } - } else { + } + else + { data->num_cores = data->num_logical_cpus = 1; } } @@ -349,7 +713,12 @@ static intel_code_and_bits_t get_brand_code_and_bits(struct cpu_id_t* data) int i = 0; const char* bs = data->brand_str; const char* s; - const struct { intel_code_t c; const char *search; } matchtable[] = { + 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" }, @@ -361,8 +730,13 @@ static intel_code_and_bits_t get_brand_code_and_bits(struct cpu_id_t* data) { PINEVIEW, "CPU [ND][45]## " }, { CEDARVIEW, "CPU [ND]#### " }, }; - - const struct { uint64_t bit; const char* search; } bit_matchtable[] = { + + const struct + { + uint64_t bit; + const char* search; + } bit_matchtable[] = + { { XEON_, "Xeon" }, { _MP_, " MP" }, { ATOM_, "Atom(TM) CPU" }, @@ -370,83 +744,132 @@ static intel_code_and_bits_t get_brand_code_and_bits(struct cpu_id_t* data) { CELERON_, "Celeron" }, { PENTIUM_, "Pentium" }, }; - - for (i = 0; i < COUNT_OF(bit_matchtable); i++) { - if (match_pattern(bs, bit_matchtable[i].search)) + + 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) { + + 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 + 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; + 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)) { + 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##")) + 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##")) + } + else if(match_pattern(bs, "[ELXW]55##")) + { code = GAINESTOWN; - else if (match_pattern(bs, "[ELXW]56##")) + } + else if(match_pattern(bs, "[ELXW]56##")) + { code = WESTMERE; - else if (data->l3_cache > 0 && data->family == 16) + } + 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) + if(match_all(bits, XEON_ + _MP_) && data->l3_cache > 0) + { code = POTOMAC; - if (code == CORE_SOLO) { + } + if(code == CORE_SOLO) + { s = strstr(bs, "CPU"); - if (s) { + if(s) + { s += 3; - while (*s == ' ') s++; - if (*s == 'T') + while(*s == ' ') + { + s++; + } + if(*s == 'T') + { bits |= MOBILE_; + } } } - if (code == CORE_SOLO) { - switch (data->num_cores) { - case 1: break; - case 2: + if(code == CORE_SOLO) + { + switch(data->num_cores) + { + case 1: + break; + case 2: + { + code = CORE_DUO; + if(data->num_logical_cpus > 2) { - code = CORE_DUO; - if (data->num_logical_cpus > 2) - code = DUAL_CORE_HT; - break; + code = DUAL_CORE_HT; } - case 4: + break; + } + case 4: + { + code = QUAD_CORE; + if(data->num_logical_cpus > 4) { - code = QUAD_CORE; - if (data->num_logical_cpus > 4) - code = QUAD_CORE_HT; - break; + code = QUAD_CORE_HT; } - default: - code = MORE_THAN_QUADCORE; break; + break; + } + default: + code = MORE_THAN_QUADCORE; + break; } } - - if (code == CORE_DUO && (bits & MOBILE_) && data->model != 14) { - if (data->ext_model < 23) { + + if(code == CORE_DUO && (bits & MOBILE_) && data->model != 14) + { + if(data->ext_model < 23) + { code = MEROM; - } else { + } + else + { code = PENRYN; } } - if (data->ext_model == 23 && - (code == CORE_DUO || code == PENTIUM_D || (bits & CELERON_))) { + if(data->ext_model == 23 && + (code == CORE_DUO || code == PENTIUM_D || (bits & CELERON_))) + { code = WOLFDALE; } @@ -455,37 +878,154 @@ static intel_code_and_bits_t get_brand_code_and_bits(struct cpu_id_t* data) 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 - + + 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]) + 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_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++) { + for(i = 0; i < 1000000; i++) + { epc = cpuid_get_epc(i, raw); - if (epc.length == 0) { + 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) { + 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; } } @@ -494,49 +1034,92 @@ 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) { + if(raw && index < MAX_INTELFN12H_LEVEL - 2) + { // this was queried already, use the data: memcpy(regs, raw->intel_fn12h[2 + index], sizeof(regs)); - } else { + } + 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) { + 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.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) + 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) +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) { + 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) { + } + 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]) { + + 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); +} diff --git a/src/3rdparty/libcpuid/recog_intel.h b/src/3rdparty/libcpuid/recog_intel.h index 96676f3b..c411e5ee 100644 --- a/src/3rdparty/libcpuid/recog_intel.h +++ b/src/3rdparty/libcpuid/recog_intel.h @@ -26,6 +26,8 @@ #ifndef __RECOG_INTEL_H__ #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); +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__*/ diff --git a/src/3rdparty/rapidjson/allocators.h b/src/3rdparty/rapidjson/allocators.h index 98affe03..8619cbc2 100644 --- a/src/3rdparty/rapidjson/allocators.h +++ b/src/3rdparty/rapidjson/allocators.h @@ -1,5 +1,5 @@ // 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 @@ -7,9 +7,9 @@ // // 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 +// 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_ @@ -24,10 +24,10 @@ RAPIDJSON_NAMESPACE_BEGIN /*! \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 + + So if an allocator need to support Free(), it needs to put its pointer in the header of memory block. \code @@ -59,31 +59,42 @@ concept Allocator { /*! This class is just wrapper for standard C library memory routines. \note implements Allocator concept */ -class CrtAllocator { +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); } + 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. +/*! This allocator allocate memory blocks from pre-allocated memory chunks. It does not free memory blocks. And Realloc() only allocate new memory. @@ -99,171 +110,217 @@ public: \note implements Allocator concept */ template -class MemoryPoolAllocator { +class MemoryPoolAllocator +{ public: - static const bool kNeedFree = false; //!< Tell users that no need to call Free() with this allocator. (concept Allocator) + 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 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. + //! 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. + 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(buffer); - chunkHead_->capacity = size - sizeof(ChunkHeader); - chunkHead_->size = 0; - chunkHead_->next = 0; - } + \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(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_); - } + //! 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 - } + //! 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 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; - } + //! 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; + //! 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; + 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(chunkHead_) + RAPIDJSON_ALIGN(sizeof(ChunkHeader)) + chunkHead_->size; - chunkHead_->size += size; - return buffer; - } + void* buffer = reinterpret_cast(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); + //! 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; + if(newSize == 0) + { + return NULL; + } - originalSize = RAPIDJSON_ALIGN(originalSize); - newSize = RAPIDJSON_ALIGN(newSize); + originalSize = RAPIDJSON_ALIGN(originalSize); + newSize = RAPIDJSON_ALIGN(newSize); - // Do not shrink if new size is smaller than original - if (originalSize >= newSize) - return originalPtr; + // 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(chunkHead_) + RAPIDJSON_ALIGN(sizeof(ChunkHeader)) + chunkHead_->size - originalSize) { - size_t increment = static_cast(newSize - originalSize); - if (chunkHead_->size + increment <= chunkHead_->capacity) { - chunkHead_->size += increment; - return originalPtr; - } - } + // Simply expand it if it is the last allocation and there is sufficient space + if(originalPtr == reinterpret_cast(chunkHead_) + RAPIDJSON_ALIGN(sizeof( + ChunkHeader)) + chunkHead_->size - originalSize) + { + size_t increment = static_cast(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; - } + // 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 + //! 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 */; + //! 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(baseAllocator_->Malloc(RAPIDJSON_ALIGN(sizeof(ChunkHeader)) + capacity))) { - chunk->capacity = capacity; - chunk->size = 0; - chunk->next = chunkHead_; - chunkHead_ = chunk; - return true; - } - else - return false; - } + //! 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(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. + 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. - }; + //! 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. + 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 diff --git a/src/3rdparty/rapidjson/document.h b/src/3rdparty/rapidjson/document.h index e3e20dfb..d1dcfa5b 100644 --- a/src/3rdparty/rapidjson/document.h +++ b/src/3rdparty/rapidjson/document.h @@ -1,5 +1,5 @@ // 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 @@ -7,9 +7,9 @@ // // 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 +// 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_DOCUMENT_H_ @@ -33,14 +33,14 @@ RAPIDJSON_DIAG_OFF(4244) // conversion from kXxxFlags to 'uint16_t', possible lo #ifdef __clang__ RAPIDJSON_DIAG_OFF(padded) -RAPIDJSON_DIAG_OFF(switch-enum) -RAPIDJSON_DIAG_OFF(c++98-compat) +RAPIDJSON_DIAG_OFF(switch - enum) + RAPIDJSON_DIAG_OFF(c++98 - compat) #endif #ifdef __GNUC__ -RAPIDJSON_DIAG_OFF(effc++) + RAPIDJSON_DIAG_OFF(effc++) #if __GNUC__ >= 6 -RAPIDJSON_DIAG_OFF(terminate) // ignore throwing RAPIDJSON_ASSERT in RAPIDJSON_NOEXCEPT functions + RAPIDJSON_DIAG_OFF(terminate) // ignore throwing RAPIDJSON_ASSERT in RAPIDJSON_NOEXCEPT functions #endif #endif // __GNUC__ @@ -52,10 +52,17 @@ RAPIDJSON_DIAG_OFF(terminate) // ignore throwing RAPIDJSON_ASSERT in RAPIDJSON_N #include // std::move #endif -RAPIDJSON_NAMESPACE_BEGIN +#ifdef max +#undef max +#endif +#ifdef min +#undef min +#endif -// Forward declaration. -template + RAPIDJSON_NAMESPACE_BEGIN + + // Forward declaration. + template class GenericValue; template @@ -67,10 +74,11 @@ class GenericDocument; But a compiler (IBM XL C/C++ for AIX) have reported to have problem with that so it moved as a namespace scope struct. https://code.google.com/p/rapidjson/issues/detail?id=64 */ -template -struct GenericMember { - GenericValue name; //!< name of member (must be a string) - GenericValue value; //!< value of member. +template +struct GenericMember +{ + GenericValue name; //!< name of member (must be a string) + GenericValue value; //!< value of member. }; /////////////////////////////////////////////////////////////////////////////// @@ -99,98 +107,165 @@ struct GenericMember { */ template class GenericMemberIterator - : public std::iterator >::Type> { + : public std::iterator>::Type> +{ - friend class GenericValue; - template friend class GenericMemberIterator; + friend class GenericValue; + template friend class GenericMemberIterator; - typedef GenericMember PlainType; - typedef typename internal::MaybeAddConst::Type ValueType; - typedef std::iterator BaseType; + typedef GenericMember PlainType; + typedef typename internal::MaybeAddConst::Type ValueType; + typedef std::iterator BaseType; public: - //! Iterator type itself - typedef GenericMemberIterator Iterator; - //! Constant iterator type - typedef GenericMemberIterator ConstIterator; - //! Non-constant iterator type - typedef GenericMemberIterator NonConstIterator; + //! Iterator type itself + typedef GenericMemberIterator Iterator; + //! Constant iterator type + typedef GenericMemberIterator ConstIterator; + //! Non-constant iterator type + typedef GenericMemberIterator NonConstIterator; - //! Pointer to (const) GenericMember - typedef typename BaseType::pointer Pointer; - //! Reference to (const) GenericMember - typedef typename BaseType::reference Reference; - //! Signed integer type (e.g. \c ptrdiff_t) - typedef typename BaseType::difference_type DifferenceType; + //! Pointer to (const) GenericMember + typedef typename BaseType::pointer Pointer; + //! Reference to (const) GenericMember + typedef typename BaseType::reference Reference; + //! Signed integer type (e.g. \c ptrdiff_t) + typedef typename BaseType::difference_type DifferenceType; - //! Default constructor (singular value) - /*! Creates an iterator pointing to no element. - \note All operations, except for comparisons, are undefined on such values. - */ - GenericMemberIterator() : ptr_() {} + //! Default constructor (singular value) + /*! Creates an iterator pointing to no element. + \note All operations, except for comparisons, are undefined on such values. + */ + GenericMemberIterator() : ptr_() {} - //! Iterator conversions to more const - /*! - \param it (Non-const) iterator to copy from + //! Iterator conversions to more const + /*! + \param it (Non-const) iterator to copy from - Allows the creation of an iterator from another GenericMemberIterator - that is "less const". Especially, creating a non-constant iterator - from a constant iterator are disabled: - \li const -> non-const (not ok) - \li const -> const (ok) - \li non-const -> const (ok) - \li non-const -> non-const (ok) + Allows the creation of an iterator from another GenericMemberIterator + that is "less const". Especially, creating a non-constant iterator + from a constant iterator are disabled: + \li const -> non-const (not ok) + \li const -> const (ok) + \li non-const -> const (ok) + \li non-const -> non-const (ok) - \note If the \c Const template parameter is already \c false, this - constructor effectively defines a regular copy-constructor. - Otherwise, the copy constructor is implicitly defined. - */ - GenericMemberIterator(const NonConstIterator & it) : ptr_(it.ptr_) {} - Iterator& operator=(const NonConstIterator & it) { ptr_ = it.ptr_; return *this; } + \note If the \c Const template parameter is already \c false, this + constructor effectively defines a regular copy-constructor. + Otherwise, the copy constructor is implicitly defined. + */ + GenericMemberIterator(const NonConstIterator & it) : ptr_(it.ptr_) {} + Iterator & operator=(const NonConstIterator & it) + { + ptr_ = it.ptr_; + return *this; + } - //! @name stepping - //@{ - Iterator& operator++(){ ++ptr_; return *this; } - Iterator& operator--(){ --ptr_; return *this; } - Iterator operator++(int){ Iterator old(*this); ++ptr_; return old; } - Iterator operator--(int){ Iterator old(*this); --ptr_; return old; } - //@} + //! @name stepping + //@{ + Iterator & operator++() + { + ++ptr_; + return *this; + } + Iterator & operator--() + { + --ptr_; + return *this; + } + Iterator operator++(int) + { + Iterator old(*this); + ++ptr_; + return old; + } + Iterator operator--(int) + { + Iterator old(*this); + --ptr_; + return old; + } + //@} - //! @name increment/decrement - //@{ - Iterator operator+(DifferenceType n) const { return Iterator(ptr_+n); } - Iterator operator-(DifferenceType n) const { return Iterator(ptr_-n); } + //! @name increment/decrement + //@{ + Iterator operator+(DifferenceType n) const + { + return Iterator(ptr_ + n); + } + Iterator operator-(DifferenceType n) const + { + return Iterator(ptr_ - n); + } - Iterator& operator+=(DifferenceType n) { ptr_+=n; return *this; } - Iterator& operator-=(DifferenceType n) { ptr_-=n; return *this; } - //@} + Iterator & operator+=(DifferenceType n) + { + ptr_ += n; + return *this; + } + Iterator & operator-=(DifferenceType n) + { + ptr_ -= n; + return *this; + } + //@} - //! @name relations - //@{ - bool operator==(ConstIterator that) const { return ptr_ == that.ptr_; } - bool operator!=(ConstIterator that) const { return ptr_ != that.ptr_; } - bool operator<=(ConstIterator that) const { return ptr_ <= that.ptr_; } - bool operator>=(ConstIterator that) const { return ptr_ >= that.ptr_; } - bool operator< (ConstIterator that) const { return ptr_ < that.ptr_; } - bool operator> (ConstIterator that) const { return ptr_ > that.ptr_; } - //@} + //! @name relations + //@{ + bool operator==(ConstIterator that) const + { + return ptr_ == that.ptr_; + } + bool operator!=(ConstIterator that) const + { + return ptr_ != that.ptr_; + } + bool operator<=(ConstIterator that) const + { + return ptr_ <= that.ptr_; + } + bool operator>=(ConstIterator that) const + { + return ptr_ >= that.ptr_; + } + bool operator< (ConstIterator that) const + { + return ptr_ < that.ptr_; + } + bool operator> (ConstIterator that) const + { + return ptr_ > that.ptr_; + } + //@} - //! @name dereference - //@{ - Reference operator*() const { return *ptr_; } - Pointer operator->() const { return ptr_; } - Reference operator[](DifferenceType n) const { return ptr_[n]; } - //@} + //! @name dereference + //@{ + Reference operator*() const + { + return *ptr_; + } + Pointer operator->() const + { + return ptr_; + } + Reference operator[](DifferenceType n) const + { + return ptr_[n]; + } + //@} - //! Distance - DifferenceType operator-(ConstIterator that) const { return ptr_-that.ptr_; } + //! Distance + DifferenceType operator-(ConstIterator that) const + { + return ptr_ - that.ptr_; + } private: - //! Internal constructor from plain pointer - explicit GenericMemberIterator(Pointer p) : ptr_(p) {} + //! Internal constructor from plain pointer + explicit GenericMemberIterator(Pointer p) : ptr_(p) {} - Pointer ptr_; //!< raw pointer + Pointer ptr_; //!< raw pointer }; #else // RAPIDJSON_NOMEMBERITERATORCLASS @@ -202,15 +277,17 @@ struct GenericMemberIterator; //! non-const GenericMemberIterator template -struct GenericMemberIterator { - //! use plain pointer as iterator type - typedef GenericMember* Iterator; +struct GenericMemberIterator +{ + //! use plain pointer as iterator type + typedef GenericMember* Iterator; }; //! const GenericMemberIterator template -struct GenericMemberIterator { - //! use plain const pointer as iterator type - typedef const GenericMember* Iterator; +struct GenericMemberIterator +{ + //! use plain const pointer as iterator type + typedef const GenericMember* Iterator; }; #endif // RAPIDJSON_NOMEMBERITERATORCLASS @@ -246,88 +323,103 @@ struct GenericMemberIterator { \see StringRef, GenericValue::SetString */ template -struct GenericStringRef { - typedef CharType Ch; //!< character type of the string +struct GenericStringRef +{ + typedef CharType Ch; //!< character type of the string - //! Create string reference from \c const character array + //! Create string reference from \c const character array #ifndef __clang__ // -Wdocumentation - /*! - This constructor implicitly creates a constant string reference from - a \c const character array. It has better performance than - \ref StringRef(const CharType*) by inferring the string \ref length - from the array length, and also supports strings containing null - characters. + /*! + This constructor implicitly creates a constant string reference from + a \c const character array. It has better performance than + \ref StringRef(const CharType*) by inferring the string \ref length + from the array length, and also supports strings containing null + characters. - \tparam N length of the string, automatically inferred + \tparam N length of the string, automatically inferred - \param str Constant character array, lifetime assumed to be longer - than the use of the string in e.g. a GenericValue + \param str Constant character array, lifetime assumed to be longer + than the use of the string in e.g. a GenericValue - \post \ref s == str + \post \ref s == str - \note Constant complexity. - \note There is a hidden, private overload to disallow references to - non-const character arrays to be created via this constructor. - By this, e.g. function-scope arrays used to be filled via - \c snprintf are excluded from consideration. - In such cases, the referenced string should be \b copied to the - GenericValue instead. - */ + \note Constant complexity. + \note There is a hidden, private overload to disallow references to + non-const character arrays to be created via this constructor. + By this, e.g. function-scope arrays used to be filled via + \c snprintf are excluded from consideration. + In such cases, the referenced string should be \b copied to the + GenericValue instead. + */ #endif - template - GenericStringRef(const CharType (&str)[N]) RAPIDJSON_NOEXCEPT - : s(str), length(N-1) {} + template + GenericStringRef(const CharType(&str)[N]) RAPIDJSON_NOEXCEPT +: + s(str), length(N - 1) {} - //! Explicitly create string reference from \c const character pointer + //! Explicitly create string reference from \c const character pointer #ifndef __clang__ // -Wdocumentation - /*! - This constructor can be used to \b explicitly create a reference to - a constant string pointer. + /*! + This constructor can be used to \b explicitly create a reference to + a constant string pointer. - \see StringRef(const CharType*) + \see StringRef(const CharType*) - \param str Constant character pointer, lifetime assumed to be longer - than the use of the string in e.g. a GenericValue + \param str Constant character pointer, lifetime assumed to be longer + than the use of the string in e.g. a GenericValue - \post \ref s == str + \post \ref s == str - \note There is a hidden, private overload to disallow references to - non-const character arrays to be created via this constructor. - By this, e.g. function-scope arrays used to be filled via - \c snprintf are excluded from consideration. - In such cases, the referenced string should be \b copied to the - GenericValue instead. - */ + \note There is a hidden, private overload to disallow references to + non-const character arrays to be created via this constructor. + By this, e.g. function-scope arrays used to be filled via + \c snprintf are excluded from consideration. + In such cases, the referenced string should be \b copied to the + GenericValue instead. + */ #endif - explicit GenericStringRef(const CharType* str) - : s(str), length(internal::StrLen(str)){ RAPIDJSON_ASSERT(s != 0); } + explicit GenericStringRef(const CharType* str) + : s(str), length(internal::StrLen(str)) + { + RAPIDJSON_ASSERT(s != 0); + } - //! Create constant string reference from pointer and length + //! Create constant string reference from pointer and length #ifndef __clang__ // -Wdocumentation - /*! \param str constant string, lifetime assumed to be longer than the use of the string in e.g. a GenericValue - \param len length of the string, excluding the trailing NULL terminator + /*! \param str constant string, lifetime assumed to be longer than the use of the string in e.g. a GenericValue + \param len length of the string, excluding the trailing NULL terminator - \post \ref s == str && \ref length == len - \note Constant complexity. - */ + \post \ref s == str && \ref length == len + \note Constant complexity. + */ #endif - GenericStringRef(const CharType* str, SizeType len) - : s(str), length(len) { RAPIDJSON_ASSERT(s != 0); } + GenericStringRef(const CharType* str, SizeType len) + : s(str), length(len) + { + RAPIDJSON_ASSERT(s != 0); + } - GenericStringRef(const GenericStringRef& rhs) : s(rhs.s), length(rhs.length) {} + GenericStringRef(const GenericStringRef & rhs) : s(rhs.s), length(rhs.length) {} - GenericStringRef& operator=(const GenericStringRef& rhs) { s = rhs.s; length = rhs.length; } + GenericStringRef & operator=(const GenericStringRef & rhs) + { + s = rhs.s; + length = rhs.length; + } - //! implicit conversion to plain CharType pointer - operator const Ch *() const { return s; } + //! implicit conversion to plain CharType pointer + operator const Ch* () const + { + return s; + } - const Ch* const s; //!< plain CharType pointer - const SizeType length; //!< length of the string (excluding the trailing NULL terminator) + const Ch* const s; //!< plain CharType pointer + const SizeType length; //!< length of the string (excluding the trailing NULL terminator) private: - //! Disallow construction from non-const array - template - GenericStringRef(CharType (&str)[N]) /* = delete */; + //! Disallow construction from non-const array + template + GenericStringRef(CharType(&str)[N]) /* = delete */; }; //! Mark a character pointer as constant string @@ -343,8 +435,9 @@ private: \see GenericValue::GenericValue(StringRefType), GenericValue::operator=(StringRefType), GenericValue::SetString(StringRefType), GenericValue::PushBack(StringRefType, Allocator&), GenericValue::AddMember */ template -inline GenericStringRef StringRef(const CharType* str) { - return GenericStringRef(str, internal::StrLen(str)); +inline GenericStringRef StringRef(const CharType* str) +{ + return GenericStringRef(str, internal::StrLen(str)); } //! Mark a character pointer as constant string @@ -363,8 +456,9 @@ inline GenericStringRef StringRef(const CharType* str) { \relatesalso GenericStringRef */ template -inline GenericStringRef StringRef(const CharType* str, size_t length) { - return GenericStringRef(str, SizeType(length)); +inline GenericStringRef StringRef(const CharType* str, size_t length) +{ + return GenericStringRef(str, SizeType(length)); } #if RAPIDJSON_HAS_STDSTRING @@ -381,141 +475,299 @@ inline GenericStringRef StringRef(const CharType* str, size_t length) \note Requires the definition of the preprocessor symbol \ref RAPIDJSON_HAS_STDSTRING. */ template -inline GenericStringRef StringRef(const std::basic_string& str) { - return GenericStringRef(str.data(), SizeType(str.size())); +inline GenericStringRef StringRef(const std::basic_string & str) +{ + return GenericStringRef(str.data(), SizeType(str.size())); } #endif /////////////////////////////////////////////////////////////////////////////// // GenericValue type traits -namespace internal { +namespace internal +{ -template -struct IsGenericValueImpl : FalseType {}; + template + struct IsGenericValueImpl : FalseType {}; -// select candidates according to nested encoding and allocator types -template struct IsGenericValueImpl::Type, typename Void::Type> - : IsBaseOf, T>::Type {}; + // select candidates according to nested encoding and allocator types + template struct + IsGenericValueImpl::Type, typename Void::Type> + : IsBaseOf, T>::Type {}; -// helper to match arbitrary GenericValue instantiations, including derived classes -template struct IsGenericValue : IsGenericValueImpl::Type {}; + // helper to match arbitrary GenericValue instantiations, including derived classes + template struct IsGenericValue : IsGenericValueImpl::Type {}; } // namespace internal /////////////////////////////////////////////////////////////////////////////// // TypeHelper -namespace internal { +namespace internal +{ -template -struct TypeHelper {}; + template + struct TypeHelper {}; -template -struct TypeHelper { - static bool Is(const ValueType& v) { return v.IsBool(); } - static bool Get(const ValueType& v) { return v.GetBool(); } - static ValueType& Set(ValueType& v, bool data) { return v.SetBool(data); } - static ValueType& Set(ValueType& v, bool data, typename ValueType::AllocatorType&) { return v.SetBool(data); } -}; + template + struct TypeHelper + { + static bool Is(const ValueType & v) + { + return v.IsBool(); + } + static bool Get(const ValueType & v) + { + return v.GetBool(); + } + static ValueType & Set(ValueType & v, bool data) + { + return v.SetBool(data); + } + static ValueType & Set(ValueType & v, bool data, typename ValueType::AllocatorType &) + { + return v.SetBool(data); + } + }; -template -struct TypeHelper { - static bool Is(const ValueType& v) { return v.IsInt(); } - static int Get(const ValueType& v) { return v.GetInt(); } - static ValueType& Set(ValueType& v, int data) { return v.SetInt(data); } - static ValueType& Set(ValueType& v, int data, typename ValueType::AllocatorType&) { return v.SetInt(data); } -}; + template + struct TypeHelper + { + static bool Is(const ValueType & v) + { + return v.IsInt(); + } + static int Get(const ValueType & v) + { + return v.GetInt(); + } + static ValueType & Set(ValueType & v, int data) + { + return v.SetInt(data); + } + static ValueType & Set(ValueType & v, int data, typename ValueType::AllocatorType &) + { + return v.SetInt(data); + } + }; -template -struct TypeHelper { - static bool Is(const ValueType& v) { return v.IsUint(); } - static unsigned Get(const ValueType& v) { return v.GetUint(); } - static ValueType& Set(ValueType& v, unsigned data) { return v.SetUint(data); } - static ValueType& Set(ValueType& v, unsigned data, typename ValueType::AllocatorType&) { return v.SetUint(data); } -}; + template + struct TypeHelper + { + static bool Is(const ValueType & v) + { + return v.IsUint(); + } + static unsigned Get(const ValueType & v) + { + return v.GetUint(); + } + static ValueType & Set(ValueType & v, unsigned data) + { + return v.SetUint(data); + } + static ValueType & Set(ValueType & v, unsigned data, typename ValueType::AllocatorType &) + { + return v.SetUint(data); + } + }; -template -struct TypeHelper { - static bool Is(const ValueType& v) { return v.IsInt64(); } - static int64_t Get(const ValueType& v) { return v.GetInt64(); } - static ValueType& Set(ValueType& v, int64_t data) { return v.SetInt64(data); } - static ValueType& Set(ValueType& v, int64_t data, typename ValueType::AllocatorType&) { return v.SetInt64(data); } -}; + template + struct TypeHelper + { + static bool Is(const ValueType & v) + { + return v.IsInt64(); + } + static int64_t Get(const ValueType & v) + { + return v.GetInt64(); + } + static ValueType & Set(ValueType & v, int64_t data) + { + return v.SetInt64(data); + } + static ValueType & Set(ValueType & v, int64_t data, typename ValueType::AllocatorType &) + { + return v.SetInt64(data); + } + }; -template -struct TypeHelper { - static bool Is(const ValueType& v) { return v.IsUint64(); } - static uint64_t Get(const ValueType& v) { return v.GetUint64(); } - static ValueType& Set(ValueType& v, uint64_t data) { return v.SetUint64(data); } - static ValueType& Set(ValueType& v, uint64_t data, typename ValueType::AllocatorType&) { return v.SetUint64(data); } -}; + template + struct TypeHelper + { + static bool Is(const ValueType & v) + { + return v.IsUint64(); + } + static uint64_t Get(const ValueType & v) + { + return v.GetUint64(); + } + static ValueType & Set(ValueType & v, uint64_t data) + { + return v.SetUint64(data); + } + static ValueType & Set(ValueType & v, uint64_t data, typename ValueType::AllocatorType &) + { + return v.SetUint64(data); + } + }; -template -struct TypeHelper { - static bool Is(const ValueType& v) { return v.IsDouble(); } - static double Get(const ValueType& v) { return v.GetDouble(); } - static ValueType& Set(ValueType& v, double data) { return v.SetDouble(data); } - static ValueType& Set(ValueType& v, double data, typename ValueType::AllocatorType&) { return v.SetDouble(data); } -}; + template + struct TypeHelper + { + static bool Is(const ValueType & v) + { + return v.IsDouble(); + } + static double Get(const ValueType & v) + { + return v.GetDouble(); + } + static ValueType & Set(ValueType & v, double data) + { + return v.SetDouble(data); + } + static ValueType & Set(ValueType & v, double data, typename ValueType::AllocatorType &) + { + return v.SetDouble(data); + } + }; -template -struct TypeHelper { - static bool Is(const ValueType& v) { return v.IsFloat(); } - static float Get(const ValueType& v) { return v.GetFloat(); } - static ValueType& Set(ValueType& v, float data) { return v.SetFloat(data); } - static ValueType& Set(ValueType& v, float data, typename ValueType::AllocatorType&) { return v.SetFloat(data); } -}; + template + struct TypeHelper + { + static bool Is(const ValueType & v) + { + return v.IsFloat(); + } + static float Get(const ValueType & v) + { + return v.GetFloat(); + } + static ValueType & Set(ValueType & v, float data) + { + return v.SetFloat(data); + } + static ValueType & Set(ValueType & v, float data, typename ValueType::AllocatorType &) + { + return v.SetFloat(data); + } + }; -template -struct TypeHelper { - typedef const typename ValueType::Ch* StringType; - static bool Is(const ValueType& v) { return v.IsString(); } - static StringType Get(const ValueType& v) { return v.GetString(); } - static ValueType& Set(ValueType& v, const StringType data) { return v.SetString(typename ValueType::StringRefType(data)); } - static ValueType& Set(ValueType& v, const StringType data, typename ValueType::AllocatorType& a) { return v.SetString(data, a); } -}; + template + struct TypeHelper + { + typedef const typename ValueType::Ch* StringType; + static bool Is(const ValueType & v) + { + return v.IsString(); + } + static StringType Get(const ValueType & v) + { + return v.GetString(); + } + static ValueType & Set(ValueType & v, const StringType data) + { + return v.SetString(typename ValueType::StringRefType(data)); + } + static ValueType & Set(ValueType & v, const StringType data, typename ValueType::AllocatorType & a) + { + return v.SetString(data, a); + } + }; #if RAPIDJSON_HAS_STDSTRING -template -struct TypeHelper > { - typedef std::basic_string StringType; - static bool Is(const ValueType& v) { return v.IsString(); } - static StringType Get(const ValueType& v) { return StringType(v.GetString(), v.GetStringLength()); } - static ValueType& Set(ValueType& v, const StringType& data, typename ValueType::AllocatorType& a) { return v.SetString(data, a); } -}; + template + struct TypeHelper> + { + typedef std::basic_string StringType; + static bool Is(const ValueType & v) + { + return v.IsString(); + } + static StringType Get(const ValueType & v) + { + return StringType(v.GetString(), v.GetStringLength()); + } + static ValueType & Set(ValueType & v, const StringType & data, typename ValueType::AllocatorType & a) + { + return v.SetString(data, a); + } + }; #endif -template -struct TypeHelper { - typedef typename ValueType::Array ArrayType; - static bool Is(const ValueType& v) { return v.IsArray(); } - static ArrayType Get(ValueType& v) { return v.GetArray(); } - static ValueType& Set(ValueType& v, ArrayType data) { return v = data; } - static ValueType& Set(ValueType& v, ArrayType data, typename ValueType::AllocatorType&) { return v = data; } -}; + template + struct TypeHelper + { + typedef typename ValueType::Array ArrayType; + static bool Is(const ValueType & v) + { + return v.IsArray(); + } + static ArrayType Get(ValueType & v) + { + return v.GetArray(); + } + static ValueType & Set(ValueType & v, ArrayType data) + { + return v = data; + } + static ValueType & Set(ValueType & v, ArrayType data, typename ValueType::AllocatorType &) + { + return v = data; + } + }; -template -struct TypeHelper { - typedef typename ValueType::ConstArray ArrayType; - static bool Is(const ValueType& v) { return v.IsArray(); } - static ArrayType Get(const ValueType& v) { return v.GetArray(); } -}; + template + struct TypeHelper + { + typedef typename ValueType::ConstArray ArrayType; + static bool Is(const ValueType & v) + { + return v.IsArray(); + } + static ArrayType Get(const ValueType & v) + { + return v.GetArray(); + } + }; -template -struct TypeHelper { - typedef typename ValueType::Object ObjectType; - static bool Is(const ValueType& v) { return v.IsObject(); } - static ObjectType Get(ValueType& v) { return v.GetObject(); } - static ValueType& Set(ValueType& v, ObjectType data) { return v = data; } - static ValueType& Set(ValueType& v, ObjectType data, typename ValueType::AllocatorType&) { v = data; } -}; + template + struct TypeHelper + { + typedef typename ValueType::Object ObjectType; + static bool Is(const ValueType & v) + { + return v.IsObject(); + } + static ObjectType Get(ValueType & v) + { + return v.GetObject(); + } + static ValueType & Set(ValueType & v, ObjectType data) + { + return v = data; + } + static ValueType & Set(ValueType & v, ObjectType data, typename ValueType::AllocatorType &) + { + v = data; + } + }; -template -struct TypeHelper { - typedef typename ValueType::ConstObject ObjectType; - static bool Is(const ValueType& v) { return v.IsObject(); } - static ObjectType Get(const ValueType& v) { return v.GetObject(); } -}; + template + struct TypeHelper + { + typedef typename ValueType::ConstObject ObjectType; + static bool Is(const ValueType & v) + { + return v.IsObject(); + } + static ObjectType Get(const ValueType & v) + { + return v.GetObject(); + } + }; } // namespace internal @@ -536,1481 +788,2057 @@ template class GenericObject; \tparam Encoding Encoding of the value. (Even non-string values need to have the same encoding in a document) \tparam Allocator Allocator type for allocating memory of object, array and string. */ -template > -class GenericValue { +template > +class GenericValue +{ public: - //! Name-value pair in an object. - typedef GenericMember Member; - typedef Encoding EncodingType; //!< Encoding type from template parameter. - typedef Allocator AllocatorType; //!< Allocator type from template parameter. - typedef typename Encoding::Ch Ch; //!< Character type derived from Encoding. - typedef GenericStringRef StringRefType; //!< Reference to a constant string - typedef typename GenericMemberIterator::Iterator MemberIterator; //!< Member iterator for iterating in object. - typedef typename GenericMemberIterator::Iterator ConstMemberIterator; //!< Constant member iterator for iterating in object. - typedef GenericValue* ValueIterator; //!< Value iterator for iterating in array. - typedef const GenericValue* ConstValueIterator; //!< Constant value iterator for iterating in array. - typedef GenericValue ValueType; //!< Value type of itself. - typedef GenericArray Array; - typedef GenericArray ConstArray; - typedef GenericObject Object; - typedef GenericObject ConstObject; + //! Name-value pair in an object. + typedef GenericMember Member; + typedef Encoding EncodingType; //!< Encoding type from template parameter. + typedef Allocator AllocatorType; //!< Allocator type from template parameter. + typedef typename Encoding::Ch Ch; //!< Character type derived from Encoding. + typedef GenericStringRef StringRefType; //!< Reference to a constant string + typedef typename GenericMemberIterator::Iterator + MemberIterator; //!< Member iterator for iterating in object. + typedef typename GenericMemberIterator::Iterator + ConstMemberIterator; //!< Constant member iterator for iterating in object. + typedef GenericValue* ValueIterator; //!< Value iterator for iterating in array. + typedef const GenericValue* ConstValueIterator; //!< Constant value iterator for iterating in array. + typedef GenericValue ValueType; //!< Value type of itself. + typedef GenericArray Array; + typedef GenericArray ConstArray; + typedef GenericObject Object; + typedef GenericObject ConstObject; - //!@name Constructors and destructor. - //@{ + //!@name Constructors and destructor. + //@{ - //! Default constructor creates a null value. - GenericValue() RAPIDJSON_NOEXCEPT : data_() { data_.f.flags = kNullFlag; } + //! Default constructor creates a null value. +GenericValue() RAPIDJSON_NOEXCEPT : + data_() + { + data_.f.flags = kNullFlag; + } #if RAPIDJSON_HAS_CXX11_RVALUE_REFS - //! Move constructor in C++11 - GenericValue(GenericValue&& rhs) RAPIDJSON_NOEXCEPT : data_(rhs.data_) { - rhs.data_.f.flags = kNullFlag; // give up contents - } + //! Move constructor in C++11 +GenericValue(GenericValue && rhs) RAPIDJSON_NOEXCEPT : + data_(rhs.data_) + { + rhs.data_.f.flags = kNullFlag; // give up contents + } #endif private: - //! Copy constructor is not permitted. - GenericValue(const GenericValue& rhs); + //! Copy constructor is not permitted. + GenericValue(const GenericValue & rhs); #if RAPIDJSON_HAS_CXX11_RVALUE_REFS - //! Moving from a GenericDocument is not permitted. - template - GenericValue(GenericDocument&& rhs); + //! Moving from a GenericDocument is not permitted. + template + GenericValue(GenericDocument && rhs); - //! Move assignment from a GenericDocument is not permitted. - template - GenericValue& operator=(GenericDocument&& rhs); + //! Move assignment from a GenericDocument is not permitted. + template + GenericValue & operator=(GenericDocument && rhs); #endif public: - //! Constructor with JSON value type. - /*! This creates a Value of specified type with default content. - \param type Type of the value. - \note Default content for number is zero. - */ - explicit GenericValue(Type type) RAPIDJSON_NOEXCEPT : data_() { - static const uint16_t defaultFlags[7] = { - kNullFlag, kFalseFlag, kTrueFlag, kObjectFlag, kArrayFlag, kShortStringFlag, - kNumberAnyFlag - }; - RAPIDJSON_ASSERT(type <= kNumberType); - data_.f.flags = defaultFlags[type]; + //! Constructor with JSON value type. + /*! This creates a Value of specified type with default content. + \param type Type of the value. + \note Default content for number is zero. + */ +explicit GenericValue(Type type) RAPIDJSON_NOEXCEPT : + data_() + { + static const uint16_t defaultFlags[7] = + { + kNullFlag, kFalseFlag, kTrueFlag, kObjectFlag, kArrayFlag, kShortStringFlag, + kNumberAnyFlag + }; + RAPIDJSON_ASSERT(type <= kNumberType); + data_.f.flags = defaultFlags[type]; - // Use ShortString to store empty string. - if (type == kStringType) - data_.ss.SetLength(0); - } + // Use ShortString to store empty string. + if(type == kStringType) + { + data_.ss.SetLength(0); + } + } - //! Explicit copy constructor (with allocator) - /*! Creates a copy of a Value by using the given Allocator - \tparam SourceAllocator allocator of \c rhs - \param rhs Value to copy from (read-only) - \param allocator Allocator for allocating copied elements and buffers. Commonly use GenericDocument::GetAllocator(). - \see CopyFrom() - */ - template< typename SourceAllocator > - GenericValue(const GenericValue& rhs, Allocator & allocator); + //! Explicit copy constructor (with allocator) + /*! Creates a copy of a Value by using the given Allocator + \tparam SourceAllocator allocator of \c rhs + \param rhs Value to copy from (read-only) + \param allocator Allocator for allocating copied elements and buffers. Commonly use GenericDocument::GetAllocator(). + \see CopyFrom() + */ + template + GenericValue(const GenericValue & rhs, Allocator & allocator); - //! Constructor for boolean value. - /*! \param b Boolean value - \note This constructor is limited to \em real boolean values and rejects - implicitly converted types like arbitrary pointers. Use an explicit cast - to \c bool, if you want to construct a boolean JSON value in such cases. - */ + //! Constructor for boolean value. + /*! \param b Boolean value + \note This constructor is limited to \em real boolean values and rejects + implicitly converted types like arbitrary pointers. Use an explicit cast + to \c bool, if you want to construct a boolean JSON value in such cases. + */ #ifndef RAPIDJSON_DOXYGEN_RUNNING // hide SFINAE from Doxygen - template - explicit GenericValue(T b, RAPIDJSON_ENABLEIF((internal::IsSame))) RAPIDJSON_NOEXCEPT // See #472 + template + explicit GenericValue(T b, RAPIDJSON_ENABLEIF((internal::IsSame))) RAPIDJSON_NOEXCEPT // See #472 #else - explicit GenericValue(bool b) RAPIDJSON_NOEXCEPT + explicit GenericValue(bool b) RAPIDJSON_NOEXCEPT #endif - : data_() { - // safe-guard against failing SFINAE - RAPIDJSON_STATIC_ASSERT((internal::IsSame::Value)); - data_.f.flags = b ? kTrueFlag : kFalseFlag; - } +: + data_() + { + // safe-guard against failing SFINAE + RAPIDJSON_STATIC_ASSERT((internal::IsSame::Value)); + data_.f.flags = b ? kTrueFlag : kFalseFlag; + } - //! Constructor for int value. - explicit GenericValue(int i) RAPIDJSON_NOEXCEPT : data_() { - data_.n.i64 = i; - data_.f.flags = (i >= 0) ? (kNumberIntFlag | kUintFlag | kUint64Flag) : kNumberIntFlag; - } + //! Constructor for int value. +explicit GenericValue(int i) RAPIDJSON_NOEXCEPT : + data_() + { + data_.n.i64 = i; + data_.f.flags = (i >= 0) ? (kNumberIntFlag | kUintFlag | kUint64Flag) : kNumberIntFlag; + } - //! Constructor for unsigned value. - explicit GenericValue(unsigned u) RAPIDJSON_NOEXCEPT : data_() { - data_.n.u64 = u; - data_.f.flags = (u & 0x80000000) ? kNumberUintFlag : (kNumberUintFlag | kIntFlag | kInt64Flag); - } + //! Constructor for unsigned value. +explicit GenericValue(unsigned u) RAPIDJSON_NOEXCEPT : + data_() + { + data_.n.u64 = u; + data_.f.flags = (u & 0x80000000) ? kNumberUintFlag : (kNumberUintFlag | kIntFlag | kInt64Flag); + } - //! Constructor for int64_t value. - explicit GenericValue(int64_t i64) RAPIDJSON_NOEXCEPT : data_() { - data_.n.i64 = i64; - data_.f.flags = kNumberInt64Flag; - if (i64 >= 0) { - data_.f.flags |= kNumberUint64Flag; - if (!(static_cast(i64) & RAPIDJSON_UINT64_C2(0xFFFFFFFF, 0x00000000))) - data_.f.flags |= kUintFlag; - if (!(static_cast(i64) & RAPIDJSON_UINT64_C2(0xFFFFFFFF, 0x80000000))) - data_.f.flags |= kIntFlag; - } - else if (i64 >= static_cast(RAPIDJSON_UINT64_C2(0xFFFFFFFF, 0x80000000))) - data_.f.flags |= kIntFlag; - } + //! Constructor for int64_t value. +explicit GenericValue(int64_t i64) RAPIDJSON_NOEXCEPT : + data_() + { + data_.n.i64 = i64; + data_.f.flags = kNumberInt64Flag; + if(i64 >= 0) + { + data_.f.flags |= kNumberUint64Flag; + if(!(static_cast(i64) & RAPIDJSON_UINT64_C2(0xFFFFFFFF, 0x00000000))) + { + data_.f.flags |= kUintFlag; + } + if(!(static_cast(i64) & RAPIDJSON_UINT64_C2(0xFFFFFFFF, 0x80000000))) + { + data_.f.flags |= kIntFlag; + } + } + else if(i64 >= static_cast(RAPIDJSON_UINT64_C2(0xFFFFFFFF, 0x80000000))) + { + data_.f.flags |= kIntFlag; + } + } - //! Constructor for uint64_t value. - explicit GenericValue(uint64_t u64) RAPIDJSON_NOEXCEPT : data_() { - data_.n.u64 = u64; - data_.f.flags = kNumberUint64Flag; - if (!(u64 & RAPIDJSON_UINT64_C2(0x80000000, 0x00000000))) - data_.f.flags |= kInt64Flag; - if (!(u64 & RAPIDJSON_UINT64_C2(0xFFFFFFFF, 0x00000000))) - data_.f.flags |= kUintFlag; - if (!(u64 & RAPIDJSON_UINT64_C2(0xFFFFFFFF, 0x80000000))) - data_.f.flags |= kIntFlag; - } + //! Constructor for uint64_t value. +explicit GenericValue(uint64_t u64) RAPIDJSON_NOEXCEPT : + data_() + { + data_.n.u64 = u64; + data_.f.flags = kNumberUint64Flag; + if(!(u64 & RAPIDJSON_UINT64_C2(0x80000000, 0x00000000))) + { + data_.f.flags |= kInt64Flag; + } + if(!(u64 & RAPIDJSON_UINT64_C2(0xFFFFFFFF, 0x00000000))) + { + data_.f.flags |= kUintFlag; + } + if(!(u64 & RAPIDJSON_UINT64_C2(0xFFFFFFFF, 0x80000000))) + { + data_.f.flags |= kIntFlag; + } + } - //! Constructor for double value. - explicit GenericValue(double d) RAPIDJSON_NOEXCEPT : data_() { data_.n.d = d; data_.f.flags = kNumberDoubleFlag; } + //! Constructor for double value. +explicit GenericValue(double d) RAPIDJSON_NOEXCEPT : + data_() + { + data_.n.d = d; + data_.f.flags = kNumberDoubleFlag; + } - //! Constructor for constant string (i.e. do not make a copy of string) - GenericValue(const Ch* s, SizeType length) RAPIDJSON_NOEXCEPT : data_() { SetStringRaw(StringRef(s, length)); } + //! Constructor for constant string (i.e. do not make a copy of string) +GenericValue(const Ch* s, SizeType length) RAPIDJSON_NOEXCEPT : + data_() + { + SetStringRaw(StringRef(s, length)); + } - //! Constructor for constant string (i.e. do not make a copy of string) - explicit GenericValue(StringRefType s) RAPIDJSON_NOEXCEPT : data_() { SetStringRaw(s); } + //! Constructor for constant string (i.e. do not make a copy of string) +explicit GenericValue(StringRefType s) RAPIDJSON_NOEXCEPT : + data_() + { + SetStringRaw(s); + } - //! Constructor for copy-string (i.e. do make a copy of string) - GenericValue(const Ch* s, SizeType length, Allocator& allocator) : data_() { SetStringRaw(StringRef(s, length), allocator); } + //! Constructor for copy-string (i.e. do make a copy of string) + GenericValue(const Ch* s, SizeType length, Allocator & allocator) : data_() + { + SetStringRaw(StringRef(s, length), allocator); + } - //! Constructor for copy-string (i.e. do make a copy of string) - GenericValue(const Ch*s, Allocator& allocator) : data_() { SetStringRaw(StringRef(s), allocator); } + //! Constructor for copy-string (i.e. do make a copy of string) + GenericValue(const Ch* s, Allocator & allocator) : data_() + { + SetStringRaw(StringRef(s), allocator); + } #if RAPIDJSON_HAS_STDSTRING - //! Constructor for copy-string from a string object (i.e. do make a copy of string) - /*! \note Requires the definition of the preprocessor symbol \ref RAPIDJSON_HAS_STDSTRING. - */ - GenericValue(const std::basic_string& s, Allocator& allocator) : data_() { SetStringRaw(StringRef(s), allocator); } + //! Constructor for copy-string from a string object (i.e. do make a copy of string) + /*! \note Requires the definition of the preprocessor symbol \ref RAPIDJSON_HAS_STDSTRING. + */ + GenericValue(const std::basic_string & s, Allocator & allocator) : data_() + { + SetStringRaw(StringRef(s), allocator); + } #endif - //! Constructor for Array. - /*! - \param a An array obtained by \c GetArray(). - \note \c Array is always pass-by-value. - \note the source array is moved into this value and the sourec array becomes empty. - */ - GenericValue(Array a) RAPIDJSON_NOEXCEPT : data_(a.value_.data_) { - a.value_.data_ = Data(); - a.value_.data_.f.flags = kArrayFlag; - } + //! Constructor for Array. + /*! + \param a An array obtained by \c GetArray(). + \note \c Array is always pass-by-value. + \note the source array is moved into this value and the sourec array becomes empty. + */ +GenericValue(Array a) RAPIDJSON_NOEXCEPT : + data_(a.value_.data_) + { + a.value_.data_ = Data(); + a.value_.data_.f.flags = kArrayFlag; + } - //! Constructor for Object. - /*! - \param o An object obtained by \c GetObject(). - \note \c Object is always pass-by-value. - \note the source object is moved into this value and the sourec object becomes empty. - */ - GenericValue(Object o) RAPIDJSON_NOEXCEPT : data_(o.value_.data_) { - o.value_.data_ = Data(); - o.value_.data_.f.flags = kObjectFlag; - } + //! Constructor for Object. + /*! + \param o An object obtained by \c GetObject(). + \note \c Object is always pass-by-value. + \note the source object is moved into this value and the sourec object becomes empty. + */ +GenericValue(Object o) RAPIDJSON_NOEXCEPT : + data_(o.value_.data_) + { + o.value_.data_ = Data(); + o.value_.data_.f.flags = kObjectFlag; + } - //! Destructor. - /*! Need to destruct elements of array, members of object, or copy-string. - */ - ~GenericValue() { - if (Allocator::kNeedFree) { // Shortcut by Allocator's trait - switch(data_.f.flags) { - case kArrayFlag: - { - GenericValue* e = GetElementsPointer(); - for (GenericValue* v = e; v != e + data_.a.size; ++v) - v->~GenericValue(); - Allocator::Free(e); - } - break; + //! Destructor. + /*! Need to destruct elements of array, members of object, or copy-string. + */ + ~GenericValue() + { + if(Allocator::kNeedFree) // Shortcut by Allocator's trait + { + switch(data_.f.flags) + { + case kArrayFlag: + { + GenericValue* e = GetElementsPointer(); + for(GenericValue* v = e; v != e + data_.a.size; ++v) + { + v->~GenericValue(); + } + Allocator::Free(e); + } + break; - case kObjectFlag: - for (MemberIterator m = MemberBegin(); m != MemberEnd(); ++m) - m->~Member(); - Allocator::Free(GetMembersPointer()); - break; + case kObjectFlag: + for(MemberIterator m = MemberBegin(); m != MemberEnd(); ++m) + { + m->~Member(); + } + Allocator::Free(GetMembersPointer()); + break; - case kCopyStringFlag: - Allocator::Free(const_cast(GetStringPointer())); - break; + case kCopyStringFlag: + Allocator::Free(const_cast(GetStringPointer())); + break; - default: - break; // Do nothing for other types. - } - } - } + default: + break; // Do nothing for other types. + } + } + } - //@} + //@} - //!@name Assignment operators - //@{ + //!@name Assignment operators + //@{ - //! Assignment with move semantics. - /*! \param rhs Source of the assignment. It will become a null value after assignment. - */ - GenericValue& operator=(GenericValue& rhs) RAPIDJSON_NOEXCEPT { - RAPIDJSON_ASSERT(this != &rhs); - this->~GenericValue(); - RawAssign(rhs); - return *this; - } + //! Assignment with move semantics. + /*! \param rhs Source of the assignment. It will become a null value after assignment. + */ + GenericValue & operator=(GenericValue & rhs) RAPIDJSON_NOEXCEPT + { + RAPIDJSON_ASSERT(this != &rhs); + this->~GenericValue(); + RawAssign(rhs); + return *this; + } #if RAPIDJSON_HAS_CXX11_RVALUE_REFS - //! Move assignment in C++11 - GenericValue& operator=(GenericValue&& rhs) RAPIDJSON_NOEXCEPT { - return *this = rhs.Move(); - } + //! Move assignment in C++11 + GenericValue & operator=(GenericValue && rhs) RAPIDJSON_NOEXCEPT + { + return *this = rhs.Move(); + } #endif - //! Assignment of constant string reference (no copy) - /*! \param str Constant string reference to be assigned - \note This overload is needed to avoid clashes with the generic primitive type assignment overload below. - \see GenericStringRef, operator=(T) - */ - GenericValue& operator=(StringRefType str) RAPIDJSON_NOEXCEPT { - GenericValue s(str); - return *this = s; - } + //! Assignment of constant string reference (no copy) + /*! \param str Constant string reference to be assigned + \note This overload is needed to avoid clashes with the generic primitive type assignment overload below. + \see GenericStringRef, operator=(T) + */ + GenericValue & operator=(StringRefType str) RAPIDJSON_NOEXCEPT + { + GenericValue s(str); + return *this = s; + } - //! Assignment with primitive types. - /*! \tparam T Either \ref Type, \c int, \c unsigned, \c int64_t, \c uint64_t - \param value The value to be assigned. + //! Assignment with primitive types. + /*! \tparam T Either \ref Type, \c int, \c unsigned, \c int64_t, \c uint64_t + \param value The value to be assigned. - \note The source type \c T explicitly disallows all pointer types, - especially (\c const) \ref Ch*. This helps avoiding implicitly - referencing character strings with insufficient lifetime, use - \ref SetString(const Ch*, Allocator&) (for copying) or - \ref StringRef() (to explicitly mark the pointer as constant) instead. - All other pointer types would implicitly convert to \c bool, - use \ref SetBool() instead. - */ - template - RAPIDJSON_DISABLEIF_RETURN((internal::IsPointer), (GenericValue&)) - operator=(T value) { - GenericValue v(value); - return *this = v; - } + \note The source type \c T explicitly disallows all pointer types, + especially (\c const) \ref Ch*. This helps avoiding implicitly + referencing character strings with insufficient lifetime, use + \ref SetString(const Ch*, Allocator&) (for copying) or + \ref StringRef() (to explicitly mark the pointer as constant) instead. + All other pointer types would implicitly convert to \c bool, + use \ref SetBool() instead. + */ + template + RAPIDJSON_DISABLEIF_RETURN((internal::IsPointer), (GenericValue &)) + operator=(T value) + { + GenericValue v(value); + return *this = v; + } - //! Deep-copy assignment from Value - /*! Assigns a \b copy of the Value to the current Value object - \tparam SourceAllocator Allocator type of \c rhs - \param rhs Value to copy from (read-only) - \param allocator Allocator to use for copying - */ - template - GenericValue& CopyFrom(const GenericValue& rhs, Allocator& allocator) { - RAPIDJSON_ASSERT(static_cast(this) != static_cast(&rhs)); - this->~GenericValue(); - new (this) GenericValue(rhs, allocator); - return *this; - } + //! Deep-copy assignment from Value + /*! Assigns a \b copy of the Value to the current Value object + \tparam SourceAllocator Allocator type of \c rhs + \param rhs Value to copy from (read-only) + \param allocator Allocator to use for copying + */ + template + GenericValue & CopyFrom(const GenericValue & rhs, Allocator & allocator) + { + RAPIDJSON_ASSERT(static_cast(this) != static_cast(&rhs)); + this->~GenericValue(); + new(this) GenericValue(rhs, allocator); + return *this; + } - //! Exchange the contents of this value with those of other. - /*! - \param other Another value. - \note Constant complexity. - */ - GenericValue& Swap(GenericValue& other) RAPIDJSON_NOEXCEPT { - GenericValue temp; - temp.RawAssign(*this); - RawAssign(other); - other.RawAssign(temp); - return *this; - } + //! Exchange the contents of this value with those of other. + /*! + \param other Another value. + \note Constant complexity. + */ + GenericValue & Swap(GenericValue & other) RAPIDJSON_NOEXCEPT + { + GenericValue temp; + temp.RawAssign(*this); + RawAssign(other); + other.RawAssign(temp); + return *this; + } - //! free-standing swap function helper - /*! - Helper function to enable support for common swap implementation pattern based on \c std::swap: - \code - void swap(MyClass& a, MyClass& b) { - using std::swap; - swap(a.value, b.value); - // ... - } - \endcode - \see Swap() - */ - friend inline void swap(GenericValue& a, GenericValue& b) RAPIDJSON_NOEXCEPT { a.Swap(b); } + //! free-standing swap function helper + /*! + Helper function to enable support for common swap implementation pattern based on \c std::swap: + \code + void swap(MyClass& a, MyClass& b) { + using std::swap; + swap(a.value, b.value); + // ... + } + \endcode + \see Swap() + */ + friend inline void swap(GenericValue & a, GenericValue & b) RAPIDJSON_NOEXCEPT { a.Swap(b); } - //! Prepare Value for move semantics - /*! \return *this */ - GenericValue& Move() RAPIDJSON_NOEXCEPT { return *this; } - //@} + //! Prepare Value for move semantics + /*! \return *this */ + GenericValue & Move() RAPIDJSON_NOEXCEPT { return *this; } + //@} - //!@name Equal-to and not-equal-to operators - //@{ - //! Equal-to operator - /*! - \note If an object contains duplicated named member, comparing equality with any object is always \c false. - \note Linear time complexity (number of all values in the subtree and total lengths of all strings). - */ - template - bool operator==(const GenericValue& rhs) const { - typedef GenericValue RhsType; - if (GetType() != rhs.GetType()) - return false; + //!@name Equal-to and not-equal-to operators + //@{ + //! Equal-to operator + /*! + \note If an object contains duplicated named member, comparing equality with any object is always \c false. + \note Linear time complexity (number of all values in the subtree and total lengths of all strings). + */ + template + bool operator==(const GenericValue & rhs) const + { + typedef GenericValue RhsType; + if(GetType() != rhs.GetType()) + { + return false; + } - switch (GetType()) { - case kObjectType: // Warning: O(n^2) inner-loop - if (data_.o.size != rhs.data_.o.size) - return false; - for (ConstMemberIterator lhsMemberItr = MemberBegin(); lhsMemberItr != MemberEnd(); ++lhsMemberItr) { - typename RhsType::ConstMemberIterator rhsMemberItr = rhs.FindMember(lhsMemberItr->name); - if (rhsMemberItr == rhs.MemberEnd() || lhsMemberItr->value != rhsMemberItr->value) - return false; - } - return true; - - case kArrayType: - if (data_.a.size != rhs.data_.a.size) - return false; - for (SizeType i = 0; i < data_.a.size; i++) - if ((*this)[i] != rhs[i]) - return false; - return true; + switch(GetType()) + { + case kObjectType: // Warning: O(n^2) inner-loop + if(data_.o.size != rhs.data_.o.size) + { + return false; + } + for(ConstMemberIterator lhsMemberItr = MemberBegin(); lhsMemberItr != MemberEnd(); ++lhsMemberItr) + { + typename RhsType::ConstMemberIterator rhsMemberItr = rhs.FindMember(lhsMemberItr->name); + if(rhsMemberItr == rhs.MemberEnd() || lhsMemberItr->value != rhsMemberItr->value) + { + return false; + } + } + return true; - case kStringType: - return StringEqual(rhs); + case kArrayType: + if(data_.a.size != rhs.data_.a.size) + { + return false; + } + for(SizeType i = 0; i < data_.a.size; i++) + if((*this)[i] != rhs[i]) + { + return false; + } + return true; - case kNumberType: - if (IsDouble() || rhs.IsDouble()) { - double a = GetDouble(); // May convert from integer to double. - double b = rhs.GetDouble(); // Ditto - return a >= b && a <= b; // Prevent -Wfloat-equal - } - else - return data_.n.u64 == rhs.data_.n.u64; + case kStringType: + return StringEqual(rhs); - default: - return true; - } - } + case kNumberType: + if(IsDouble() || rhs.IsDouble()) + { + double a = GetDouble(); // May convert from integer to double. + double b = rhs.GetDouble(); // Ditto + return a >= b && a <= b; // Prevent -Wfloat-equal + } + else + { + return data_.n.u64 == rhs.data_.n.u64; + } - //! Equal-to operator with const C-string pointer - bool operator==(const Ch* rhs) const { return *this == GenericValue(StringRef(rhs)); } + default: + return true; + } + } + + //! Equal-to operator with const C-string pointer + bool operator==(const Ch* rhs) const + { + return *this == GenericValue(StringRef(rhs)); + } #if RAPIDJSON_HAS_STDSTRING - //! Equal-to operator with string object - /*! \note Requires the definition of the preprocessor symbol \ref RAPIDJSON_HAS_STDSTRING. - */ - bool operator==(const std::basic_string& rhs) const { return *this == GenericValue(StringRef(rhs)); } + //! Equal-to operator with string object + /*! \note Requires the definition of the preprocessor symbol \ref RAPIDJSON_HAS_STDSTRING. + */ + bool operator==(const std::basic_string & rhs) const + { + return *this == GenericValue(StringRef(rhs)); + } #endif - //! Equal-to operator with primitive types - /*! \tparam T Either \ref Type, \c int, \c unsigned, \c int64_t, \c uint64_t, \c double, \c true, \c false - */ - template RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr,internal::IsGenericValue >), (bool)) operator==(const T& rhs) const { return *this == GenericValue(rhs); } + //! Equal-to operator with primitive types + /*! \tparam T Either \ref Type, \c int, \c unsigned, \c int64_t, \c uint64_t, \c double, \c true, \c false + */ + template RAPIDJSON_DISABLEIF_RETURN(( + internal::OrExpr, internal::IsGenericValue>), + (bool)) operator==(const T & rhs) const + { + return *this == GenericValue(rhs); + } - //! Not-equal-to operator - /*! \return !(*this == rhs) - */ - template - bool operator!=(const GenericValue& rhs) const { return !(*this == rhs); } + //! Not-equal-to operator + /*! \return !(*this == rhs) + */ + template + bool operator!=(const GenericValue & rhs) const + { + return !(*this == rhs); + } - //! Not-equal-to operator with const C-string pointer - bool operator!=(const Ch* rhs) const { return !(*this == rhs); } + //! Not-equal-to operator with const C-string pointer + bool operator!=(const Ch* rhs) const + { + return !(*this == rhs); + } - //! Not-equal-to operator with arbitrary types - /*! \return !(*this == rhs) - */ - template RAPIDJSON_DISABLEIF_RETURN((internal::IsGenericValue), (bool)) operator!=(const T& rhs) const { return !(*this == rhs); } + //! Not-equal-to operator with arbitrary types + /*! \return !(*this == rhs) + */ + template RAPIDJSON_DISABLEIF_RETURN((internal::IsGenericValue), + (bool)) operator!=(const T & rhs) const + { + return !(*this == rhs); + } - //! Equal-to operator with arbitrary types (symmetric version) - /*! \return (rhs == lhs) - */ - template friend RAPIDJSON_DISABLEIF_RETURN((internal::IsGenericValue), (bool)) operator==(const T& lhs, const GenericValue& rhs) { return rhs == lhs; } + //! Equal-to operator with arbitrary types (symmetric version) + /*! \return (rhs == lhs) + */ + template friend RAPIDJSON_DISABLEIF_RETURN((internal::IsGenericValue), + (bool)) operator==(const T & lhs, const GenericValue & rhs) + { + return rhs == lhs; + } - //! Not-Equal-to operator with arbitrary types (symmetric version) - /*! \return !(rhs == lhs) - */ - template friend RAPIDJSON_DISABLEIF_RETURN((internal::IsGenericValue), (bool)) operator!=(const T& lhs, const GenericValue& rhs) { return !(rhs == lhs); } - //@} + //! Not-Equal-to operator with arbitrary types (symmetric version) + /*! \return !(rhs == lhs) + */ + template friend RAPIDJSON_DISABLEIF_RETURN((internal::IsGenericValue), + (bool)) operator!=(const T & lhs, const GenericValue & rhs) + { + return !(rhs == lhs); + } + //@} - //!@name Type - //@{ + //!@name Type + //@{ - Type GetType() const { return static_cast(data_.f.flags & kTypeMask); } - bool IsNull() const { return data_.f.flags == kNullFlag; } - bool IsFalse() const { return data_.f.flags == kFalseFlag; } - bool IsTrue() const { return data_.f.flags == kTrueFlag; } - bool IsBool() const { return (data_.f.flags & kBoolFlag) != 0; } - bool IsObject() const { return data_.f.flags == kObjectFlag; } - bool IsArray() const { return data_.f.flags == kArrayFlag; } - bool IsNumber() const { return (data_.f.flags & kNumberFlag) != 0; } - bool IsInt() const { return (data_.f.flags & kIntFlag) != 0; } - bool IsUint() const { return (data_.f.flags & kUintFlag) != 0; } - bool IsInt64() const { return (data_.f.flags & kInt64Flag) != 0; } - bool IsUint64() const { return (data_.f.flags & kUint64Flag) != 0; } - bool IsDouble() const { return (data_.f.flags & kDoubleFlag) != 0; } - bool IsString() const { return (data_.f.flags & kStringFlag) != 0; } + Type GetType() const + { + return static_cast(data_.f.flags & kTypeMask); + } + bool IsNull() const + { + return data_.f.flags == kNullFlag; + } + bool IsFalse() const + { + return data_.f.flags == kFalseFlag; + } + bool IsTrue() const + { + return data_.f.flags == kTrueFlag; + } + bool IsBool() const + { + return (data_.f.flags & kBoolFlag) != 0; + } + bool IsObject() const + { + return data_.f.flags == kObjectFlag; + } + bool IsArray() const + { + return data_.f.flags == kArrayFlag; + } + bool IsNumber() const + { + return (data_.f.flags & kNumberFlag) != 0; + } + bool IsInt() const + { + return (data_.f.flags & kIntFlag) != 0; + } + bool IsUint() const + { + return (data_.f.flags & kUintFlag) != 0; + } + bool IsInt64() const + { + return (data_.f.flags & kInt64Flag) != 0; + } + bool IsUint64() const + { + return (data_.f.flags & kUint64Flag) != 0; + } + bool IsDouble() const + { + return (data_.f.flags & kDoubleFlag) != 0; + } + bool IsString() const + { + return (data_.f.flags & kStringFlag) != 0; + } - // Checks whether a number can be losslessly converted to a double. - bool IsLosslessDouble() const { - if (!IsNumber()) return false; - if (IsUint64()) { - uint64_t u = GetUint64(); - volatile double d = static_cast(u); - return (d >= 0.0) - && (d < static_cast(std::numeric_limits::max())) - && (u == static_cast(d)); - } - if (IsInt64()) { - int64_t i = GetInt64(); - volatile double d = static_cast(i); - return (d >= static_cast(std::numeric_limits::min())) - && (d < static_cast(std::numeric_limits::max())) - && (i == static_cast(d)); - } - return true; // double, int, uint are always lossless - } + // Checks whether a number can be losslessly converted to a double. + bool IsLosslessDouble() const + { + if(!IsNumber()) + { + return false; + } + if(IsUint64()) + { + uint64_t u = GetUint64(); + volatile double d = static_cast(u); + return (d >= 0.0) + && (d < static_cast(std::numeric_limits::max())) + && (u == static_cast(d)); + } + if(IsInt64()) + { + int64_t i = GetInt64(); + volatile double d = static_cast(i); + return (d >= static_cast(std::numeric_limits::min())) + && (d < static_cast(std::numeric_limits::max())) + && (i == static_cast(d)); + } + return true; // double, int, uint are always lossless + } - // Checks whether a number is a float (possible lossy). - bool IsFloat() const { - if ((data_.f.flags & kDoubleFlag) == 0) - return false; - double d = GetDouble(); - return d >= -3.4028234e38 && d <= 3.4028234e38; - } - // Checks whether a number can be losslessly converted to a float. - bool IsLosslessFloat() const { - if (!IsNumber()) return false; - double a = GetDouble(); - if (a < static_cast(-std::numeric_limits::max()) - || a > static_cast(std::numeric_limits::max())) - return false; - double b = static_cast(static_cast(a)); - return a >= b && a <= b; // Prevent -Wfloat-equal - } + // Checks whether a number is a float (possible lossy). + bool IsFloat() const + { + if((data_.f.flags & kDoubleFlag) == 0) + { + return false; + } + double d = GetDouble(); + return d >= -3.4028234e38 && d <= 3.4028234e38; + } + // Checks whether a number can be losslessly converted to a float. + bool IsLosslessFloat() const + { + if(!IsNumber()) + { + return false; + } + double a = GetDouble(); + if(a < static_cast(-std::numeric_limits::max()) + || a > static_cast(std::numeric_limits::max())) + { + return false; + } + double b = static_cast(static_cast(a)); + return a >= b && a <= b; // Prevent -Wfloat-equal + } - //@} + //@} - //!@name Null - //@{ + //!@name Null + //@{ - GenericValue& SetNull() { this->~GenericValue(); new (this) GenericValue(); return *this; } + GenericValue & SetNull() + { + this->~GenericValue(); + new(this) GenericValue(); + return *this; + } - //@} + //@} - //!@name Bool - //@{ + //!@name Bool + //@{ - bool GetBool() const { RAPIDJSON_ASSERT(IsBool()); return data_.f.flags == kTrueFlag; } - //!< Set boolean value - /*! \post IsBool() == true */ - GenericValue& SetBool(bool b) { this->~GenericValue(); new (this) GenericValue(b); return *this; } + bool GetBool() const + { + RAPIDJSON_ASSERT(IsBool()); + return data_.f.flags == kTrueFlag; + } + //!< Set boolean value + /*! \post IsBool() == true */ + GenericValue & SetBool(bool b) + { + this->~GenericValue(); + new(this) GenericValue(b); + return *this; + } - //@} + //@} - //!@name Object - //@{ + //!@name Object + //@{ - //! Set this value as an empty object. - /*! \post IsObject() == true */ - GenericValue& SetObject() { this->~GenericValue(); new (this) GenericValue(kObjectType); return *this; } + //! Set this value as an empty object. + /*! \post IsObject() == true */ + GenericValue & SetObject() + { + this->~GenericValue(); + new(this) GenericValue(kObjectType); + return *this; + } - //! Get the number of members in the object. - SizeType MemberCount() const { RAPIDJSON_ASSERT(IsObject()); return data_.o.size; } + //! Get the number of members in the object. + SizeType MemberCount() const + { + RAPIDJSON_ASSERT(IsObject()); + return data_.o.size; + } - //! Check whether the object is empty. - bool ObjectEmpty() const { RAPIDJSON_ASSERT(IsObject()); return data_.o.size == 0; } + //! Check whether the object is empty. + bool ObjectEmpty() const + { + RAPIDJSON_ASSERT(IsObject()); + return data_.o.size == 0; + } - //! Get a value from an object associated with the name. - /*! \pre IsObject() == true - \tparam T Either \c Ch or \c const \c Ch (template used for disambiguation with \ref operator[](SizeType)) - \note In version 0.1x, if the member is not found, this function returns a null value. This makes issue 7. - Since 0.2, if the name is not correct, it will assert. - If user is unsure whether a member exists, user should use HasMember() first. - A better approach is to use FindMember(). - \note Linear time complexity. - */ - template - RAPIDJSON_DISABLEIF_RETURN((internal::NotExpr::Type, Ch> >),(GenericValue&)) operator[](T* name) { - GenericValue n(StringRef(name)); - return (*this)[n]; - } - template - RAPIDJSON_DISABLEIF_RETURN((internal::NotExpr::Type, Ch> >),(const GenericValue&)) operator[](T* name) const { return const_cast(*this)[name]; } + //! Get a value from an object associated with the name. + /*! \pre IsObject() == true + \tparam T Either \c Ch or \c const \c Ch (template used for disambiguation with \ref operator[](SizeType)) + \note In version 0.1x, if the member is not found, this function returns a null value. This makes issue 7. + Since 0.2, if the name is not correct, it will assert. + If user is unsure whether a member exists, user should use HasMember() first. + A better approach is to use FindMember(). + \note Linear time complexity. + */ + template + RAPIDJSON_DISABLEIF_RETURN((internal::NotExpr::Type, Ch>>), + (GenericValue &)) operator[](T* name) + { + GenericValue n(StringRef(name)); + return (*this)[n]; + } + template + RAPIDJSON_DISABLEIF_RETURN((internal::NotExpr::Type, Ch>>), + (const GenericValue &)) operator[](T* name) const + { + return const_cast(*this)[name]; + } - //! Get a value from an object associated with the name. - /*! \pre IsObject() == true - \tparam SourceAllocator Allocator of the \c name value + //! Get a value from an object associated with the name. + /*! \pre IsObject() == true + \tparam SourceAllocator Allocator of the \c name value - \note Compared to \ref operator[](T*), this version is faster because it does not need a StrLen(). - And it can also handle strings with embedded null characters. + \note Compared to \ref operator[](T*), this version is faster because it does not need a StrLen(). + And it can also handle strings with embedded null characters. - \note Linear time complexity. - */ - template - GenericValue& operator[](const GenericValue& name) { - MemberIterator member = FindMember(name); - if (member != MemberEnd()) - return member->value; - else { - RAPIDJSON_ASSERT(false); // see above note + \note Linear time complexity. + */ + template + GenericValue & operator[](const GenericValue & name) + { + MemberIterator member = FindMember(name); + if(member != MemberEnd()) + { + return member->value; + } + else + { + RAPIDJSON_ASSERT(false); // see above note - // This will generate -Wexit-time-destructors in clang - // static GenericValue NullValue; - // return NullValue; + // This will generate -Wexit-time-destructors in clang + // static GenericValue NullValue; + // return NullValue; - // Use static buffer and placement-new to prevent destruction - static char buffer[sizeof(GenericValue)]; - return *new (buffer) GenericValue(); - } - } - template - const GenericValue& operator[](const GenericValue& name) const { return const_cast(*this)[name]; } + // Use static buffer and placement-new to prevent destruction + static char buffer[sizeof(GenericValue)]; + return *new(buffer) GenericValue(); + } + } + template + const GenericValue & operator[](const GenericValue & name) const + { + return const_cast(*this)[name]; + } #if RAPIDJSON_HAS_STDSTRING - //! Get a value from an object associated with name (string object). - GenericValue& operator[](const std::basic_string& name) { return (*this)[GenericValue(StringRef(name))]; } - const GenericValue& operator[](const std::basic_string& name) const { return (*this)[GenericValue(StringRef(name))]; } + //! Get a value from an object associated with name (string object). + GenericValue & operator[](const std::basic_string & name) + { + return (*this)[GenericValue(StringRef(name))]; + } + const GenericValue & operator[](const std::basic_string & name) const + { + return (*this)[GenericValue(StringRef(name))]; + } #endif - //! Const member iterator - /*! \pre IsObject() == true */ - ConstMemberIterator MemberBegin() const { RAPIDJSON_ASSERT(IsObject()); return ConstMemberIterator(GetMembersPointer()); } - //! Const \em past-the-end member iterator - /*! \pre IsObject() == true */ - ConstMemberIterator MemberEnd() const { RAPIDJSON_ASSERT(IsObject()); return ConstMemberIterator(GetMembersPointer() + data_.o.size); } - //! Member iterator - /*! \pre IsObject() == true */ - MemberIterator MemberBegin() { RAPIDJSON_ASSERT(IsObject()); return MemberIterator(GetMembersPointer()); } - //! \em Past-the-end member iterator - /*! \pre IsObject() == true */ - MemberIterator MemberEnd() { RAPIDJSON_ASSERT(IsObject()); return MemberIterator(GetMembersPointer() + data_.o.size); } + //! Const member iterator + /*! \pre IsObject() == true */ + ConstMemberIterator MemberBegin() const + { + RAPIDJSON_ASSERT(IsObject()); + return ConstMemberIterator(GetMembersPointer()); + } + //! Const \em past-the-end member iterator + /*! \pre IsObject() == true */ + ConstMemberIterator MemberEnd() const + { + RAPIDJSON_ASSERT(IsObject()); + return ConstMemberIterator(GetMembersPointer() + data_.o.size); + } + //! Member iterator + /*! \pre IsObject() == true */ + MemberIterator MemberBegin() + { + RAPIDJSON_ASSERT(IsObject()); + return MemberIterator(GetMembersPointer()); + } + //! \em Past-the-end member iterator + /*! \pre IsObject() == true */ + MemberIterator MemberEnd() + { + RAPIDJSON_ASSERT(IsObject()); + return MemberIterator(GetMembersPointer() + data_.o.size); + } - //! Check whether a member exists in the object. - /*! - \param name Member name to be searched. - \pre IsObject() == true - \return Whether a member with that name exists. - \note It is better to use FindMember() directly if you need the obtain the value as well. - \note Linear time complexity. - */ - bool HasMember(const Ch* name) const { return FindMember(name) != MemberEnd(); } + //! Check whether a member exists in the object. + /*! + \param name Member name to be searched. + \pre IsObject() == true + \return Whether a member with that name exists. + \note It is better to use FindMember() directly if you need the obtain the value as well. + \note Linear time complexity. + */ + bool HasMember(const Ch* name) const + { + return FindMember(name) != MemberEnd(); + } #if RAPIDJSON_HAS_STDSTRING - //! Check whether a member exists in the object with string object. - /*! - \param name Member name to be searched. - \pre IsObject() == true - \return Whether a member with that name exists. - \note It is better to use FindMember() directly if you need the obtain the value as well. - \note Linear time complexity. - */ - bool HasMember(const std::basic_string& name) const { return FindMember(name) != MemberEnd(); } + //! Check whether a member exists in the object with string object. + /*! + \param name Member name to be searched. + \pre IsObject() == true + \return Whether a member with that name exists. + \note It is better to use FindMember() directly if you need the obtain the value as well. + \note Linear time complexity. + */ + bool HasMember(const std::basic_string & name) const + { + return FindMember(name) != MemberEnd(); + } #endif - //! Check whether a member exists in the object with GenericValue name. - /*! - This version is faster because it does not need a StrLen(). It can also handle string with null character. - \param name Member name to be searched. - \pre IsObject() == true - \return Whether a member with that name exists. - \note It is better to use FindMember() directly if you need the obtain the value as well. - \note Linear time complexity. - */ - template - bool HasMember(const GenericValue& name) const { return FindMember(name) != MemberEnd(); } + //! Check whether a member exists in the object with GenericValue name. + /*! + This version is faster because it does not need a StrLen(). It can also handle string with null character. + \param name Member name to be searched. + \pre IsObject() == true + \return Whether a member with that name exists. + \note It is better to use FindMember() directly if you need the obtain the value as well. + \note Linear time complexity. + */ + template + bool HasMember(const GenericValue & name) const + { + return FindMember(name) != MemberEnd(); + } - //! Find member by name. - /*! - \param name Member name to be searched. - \pre IsObject() == true - \return Iterator to member, if it exists. - Otherwise returns \ref MemberEnd(). + //! Find member by name. + /*! + \param name Member name to be searched. + \pre IsObject() == true + \return Iterator to member, if it exists. + Otherwise returns \ref MemberEnd(). - \note Earlier versions of Rapidjson returned a \c NULL pointer, in case - the requested member doesn't exist. For consistency with e.g. - \c std::map, this has been changed to MemberEnd() now. - \note Linear time complexity. - */ - MemberIterator FindMember(const Ch* name) { - GenericValue n(StringRef(name)); - return FindMember(n); - } + \note Earlier versions of Rapidjson returned a \c NULL pointer, in case + the requested member doesn't exist. For consistency with e.g. + \c std::map, this has been changed to MemberEnd() now. + \note Linear time complexity. + */ + MemberIterator FindMember(const Ch* name) + { + GenericValue n(StringRef(name)); + return FindMember(n); + } - ConstMemberIterator FindMember(const Ch* name) const { return const_cast(*this).FindMember(name); } + ConstMemberIterator FindMember(const Ch* name) const + { + return const_cast(*this).FindMember(name); + } - //! Find member by name. - /*! - This version is faster because it does not need a StrLen(). It can also handle string with null character. - \param name Member name to be searched. - \pre IsObject() == true - \return Iterator to member, if it exists. - Otherwise returns \ref MemberEnd(). + //! Find member by name. + /*! + This version is faster because it does not need a StrLen(). It can also handle string with null character. + \param name Member name to be searched. + \pre IsObject() == true + \return Iterator to member, if it exists. + Otherwise returns \ref MemberEnd(). - \note Earlier versions of Rapidjson returned a \c NULL pointer, in case - the requested member doesn't exist. For consistency with e.g. - \c std::map, this has been changed to MemberEnd() now. - \note Linear time complexity. - */ - template - MemberIterator FindMember(const GenericValue& name) { - RAPIDJSON_ASSERT(IsObject()); - RAPIDJSON_ASSERT(name.IsString()); - MemberIterator member = MemberBegin(); - for ( ; member != MemberEnd(); ++member) - if (name.StringEqual(member->name)) - break; - return member; - } - template ConstMemberIterator FindMember(const GenericValue& name) const { return const_cast(*this).FindMember(name); } + \note Earlier versions of Rapidjson returned a \c NULL pointer, in case + the requested member doesn't exist. For consistency with e.g. + \c std::map, this has been changed to MemberEnd() now. + \note Linear time complexity. + */ + template + MemberIterator FindMember(const GenericValue & name) + { + RAPIDJSON_ASSERT(IsObject()); + RAPIDJSON_ASSERT(name.IsString()); + MemberIterator member = MemberBegin(); + for(; member != MemberEnd(); ++member) + if(name.StringEqual(member->name)) + { + break; + } + return member; + } + template ConstMemberIterator FindMember(const + GenericValue & name) const + { + return const_cast(*this).FindMember(name); + } #if RAPIDJSON_HAS_STDSTRING - //! Find member by string object name. - /*! - \param name Member name to be searched. - \pre IsObject() == true - \return Iterator to member, if it exists. - Otherwise returns \ref MemberEnd(). - */ - MemberIterator FindMember(const std::basic_string& name) { return FindMember(GenericValue(StringRef(name))); } - ConstMemberIterator FindMember(const std::basic_string& name) const { return FindMember(GenericValue(StringRef(name))); } + //! Find member by string object name. + /*! + \param name Member name to be searched. + \pre IsObject() == true + \return Iterator to member, if it exists. + Otherwise returns \ref MemberEnd(). + */ + MemberIterator FindMember(const std::basic_string & name) + { + return FindMember(GenericValue(StringRef(name))); + } + ConstMemberIterator FindMember(const std::basic_string & name) const + { + return FindMember(GenericValue(StringRef(name))); + } #endif - //! Add a member (name-value pair) to the object. - /*! \param name A string value as name of member. - \param value Value of any type. - \param allocator Allocator for reallocating memory. It must be the same one as used before. Commonly use GenericDocument::GetAllocator(). - \return The value itself for fluent API. - \note The ownership of \c name and \c value will be transferred to this object on success. - \pre IsObject() && name.IsString() - \post name.IsNull() && value.IsNull() - \note Amortized Constant time complexity. - */ - GenericValue& AddMember(GenericValue& name, GenericValue& value, Allocator& allocator) { - RAPIDJSON_ASSERT(IsObject()); - RAPIDJSON_ASSERT(name.IsString()); + //! Add a member (name-value pair) to the object. + /*! \param name A string value as name of member. + \param value Value of any type. + \param allocator Allocator for reallocating memory. It must be the same one as used before. Commonly use GenericDocument::GetAllocator(). + \return The value itself for fluent API. + \note The ownership of \c name and \c value will be transferred to this object on success. + \pre IsObject() && name.IsString() + \post name.IsNull() && value.IsNull() + \note Amortized Constant time complexity. + */ + GenericValue & AddMember(GenericValue & name, GenericValue & value, Allocator & allocator) + { + RAPIDJSON_ASSERT(IsObject()); + RAPIDJSON_ASSERT(name.IsString()); - ObjectData& o = data_.o; - if (o.size >= o.capacity) { - if (o.capacity == 0) { - o.capacity = kDefaultObjectCapacity; - SetMembersPointer(reinterpret_cast(allocator.Malloc(o.capacity * sizeof(Member)))); - } - else { - SizeType oldCapacity = o.capacity; - o.capacity += (oldCapacity + 1) / 2; // grow by factor 1.5 - SetMembersPointer(reinterpret_cast(allocator.Realloc(GetMembersPointer(), oldCapacity * sizeof(Member), o.capacity * sizeof(Member)))); - } - } - Member* members = GetMembersPointer(); - members[o.size].name.RawAssign(name); - members[o.size].value.RawAssign(value); - o.size++; - return *this; - } + ObjectData & o = data_.o; + if(o.size >= o.capacity) + { + if(o.capacity == 0) + { + o.capacity = kDefaultObjectCapacity; + SetMembersPointer(reinterpret_cast(allocator.Malloc(o.capacity * sizeof(Member)))); + } + else + { + SizeType oldCapacity = o.capacity; + o.capacity += (oldCapacity + 1) / 2; // grow by factor 1.5 + SetMembersPointer(reinterpret_cast(allocator.Realloc(GetMembersPointer(), + oldCapacity * sizeof(Member), o.capacity * sizeof(Member)))); + } + } + Member* members = GetMembersPointer(); + members[o.size].name.RawAssign(name); + members[o.size].value.RawAssign(value); + o.size++; + return *this; + } - //! Add a constant string value as member (name-value pair) to the object. - /*! \param name A string value as name of member. - \param value constant string reference as value of member. - \param allocator Allocator for reallocating memory. It must be the same one as used before. Commonly use GenericDocument::GetAllocator(). - \return The value itself for fluent API. - \pre IsObject() - \note This overload is needed to avoid clashes with the generic primitive type AddMember(GenericValue&,T,Allocator&) overload below. - \note Amortized Constant time complexity. - */ - GenericValue& AddMember(GenericValue& name, StringRefType value, Allocator& allocator) { - GenericValue v(value); - return AddMember(name, v, allocator); - } + //! Add a constant string value as member (name-value pair) to the object. + /*! \param name A string value as name of member. + \param value constant string reference as value of member. + \param allocator Allocator for reallocating memory. It must be the same one as used before. Commonly use GenericDocument::GetAllocator(). + \return The value itself for fluent API. + \pre IsObject() + \note This overload is needed to avoid clashes with the generic primitive type AddMember(GenericValue&,T,Allocator&) overload below. + \note Amortized Constant time complexity. + */ + GenericValue & AddMember(GenericValue & name, StringRefType value, Allocator & allocator) + { + GenericValue v(value); + return AddMember(name, v, allocator); + } #if RAPIDJSON_HAS_STDSTRING - //! Add a string object as member (name-value pair) to the object. - /*! \param name A string value as name of member. - \param value constant string reference as value of member. - \param allocator Allocator for reallocating memory. It must be the same one as used before. Commonly use GenericDocument::GetAllocator(). - \return The value itself for fluent API. - \pre IsObject() - \note This overload is needed to avoid clashes with the generic primitive type AddMember(GenericValue&,T,Allocator&) overload below. - \note Amortized Constant time complexity. - */ - GenericValue& AddMember(GenericValue& name, std::basic_string& value, Allocator& allocator) { - GenericValue v(value, allocator); - return AddMember(name, v, allocator); - } + //! Add a string object as member (name-value pair) to the object. + /*! \param name A string value as name of member. + \param value constant string reference as value of member. + \param allocator Allocator for reallocating memory. It must be the same one as used before. Commonly use GenericDocument::GetAllocator(). + \return The value itself for fluent API. + \pre IsObject() + \note This overload is needed to avoid clashes with the generic primitive type AddMember(GenericValue&,T,Allocator&) overload below. + \note Amortized Constant time complexity. + */ + GenericValue & AddMember(GenericValue & name, std::basic_string & value, Allocator & allocator) + { + GenericValue v(value, allocator); + return AddMember(name, v, allocator); + } #endif - //! Add any primitive value as member (name-value pair) to the object. - /*! \tparam T Either \ref Type, \c int, \c unsigned, \c int64_t, \c uint64_t - \param name A string value as name of member. - \param value Value of primitive type \c T as value of member - \param allocator Allocator for reallocating memory. Commonly use GenericDocument::GetAllocator(). - \return The value itself for fluent API. - \pre IsObject() + //! Add any primitive value as member (name-value pair) to the object. + /*! \tparam T Either \ref Type, \c int, \c unsigned, \c int64_t, \c uint64_t + \param name A string value as name of member. + \param value Value of primitive type \c T as value of member + \param allocator Allocator for reallocating memory. Commonly use GenericDocument::GetAllocator(). + \return The value itself for fluent API. + \pre IsObject() - \note The source type \c T explicitly disallows all pointer types, - especially (\c const) \ref Ch*. This helps avoiding implicitly - referencing character strings with insufficient lifetime, use - \ref AddMember(StringRefType, GenericValue&, Allocator&) or \ref - AddMember(StringRefType, StringRefType, Allocator&). - All other pointer types would implicitly convert to \c bool, - use an explicit cast instead, if needed. - \note Amortized Constant time complexity. - */ - template - RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr, internal::IsGenericValue >), (GenericValue&)) - AddMember(GenericValue& name, T value, Allocator& allocator) { - GenericValue v(value); - return AddMember(name, v, allocator); - } + \note The source type \c T explicitly disallows all pointer types, + especially (\c const) \ref Ch*. This helps avoiding implicitly + referencing character strings with insufficient lifetime, use + \ref AddMember(StringRefType, GenericValue&, Allocator&) or \ref + AddMember(StringRefType, StringRefType, Allocator&). + All other pointer types would implicitly convert to \c bool, + use an explicit cast instead, if needed. + \note Amortized Constant time complexity. + */ + template + RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr, internal::IsGenericValue>), + (GenericValue &)) + AddMember(GenericValue & name, T value, Allocator & allocator) + { + GenericValue v(value); + return AddMember(name, v, allocator); + } #if RAPIDJSON_HAS_CXX11_RVALUE_REFS - GenericValue& AddMember(GenericValue&& name, GenericValue&& value, Allocator& allocator) { - return AddMember(name, value, allocator); - } - GenericValue& AddMember(GenericValue&& name, GenericValue& value, Allocator& allocator) { - return AddMember(name, value, allocator); - } - GenericValue& AddMember(GenericValue& name, GenericValue&& value, Allocator& allocator) { - return AddMember(name, value, allocator); - } - GenericValue& AddMember(StringRefType name, GenericValue&& value, Allocator& allocator) { - GenericValue n(name); - return AddMember(n, value, allocator); - } + GenericValue & AddMember(GenericValue && name, GenericValue && value, Allocator & allocator) + { + return AddMember(name, value, allocator); + } + GenericValue & AddMember(GenericValue && name, GenericValue & value, Allocator & allocator) + { + return AddMember(name, value, allocator); + } + GenericValue & AddMember(GenericValue & name, GenericValue && value, Allocator & allocator) + { + return AddMember(name, value, allocator); + } + GenericValue & AddMember(StringRefType name, GenericValue && value, Allocator & allocator) + { + GenericValue n(name); + return AddMember(n, value, allocator); + } #endif // RAPIDJSON_HAS_CXX11_RVALUE_REFS - //! Add a member (name-value pair) to the object. - /*! \param name A constant string reference as name of member. - \param value Value of any type. - \param allocator Allocator for reallocating memory. It must be the same one as used before. Commonly use GenericDocument::GetAllocator(). - \return The value itself for fluent API. - \note The ownership of \c value will be transferred to this object on success. - \pre IsObject() - \post value.IsNull() - \note Amortized Constant time complexity. - */ - GenericValue& AddMember(StringRefType name, GenericValue& value, Allocator& allocator) { - GenericValue n(name); - return AddMember(n, value, allocator); - } + //! Add a member (name-value pair) to the object. + /*! \param name A constant string reference as name of member. + \param value Value of any type. + \param allocator Allocator for reallocating memory. It must be the same one as used before. Commonly use GenericDocument::GetAllocator(). + \return The value itself for fluent API. + \note The ownership of \c value will be transferred to this object on success. + \pre IsObject() + \post value.IsNull() + \note Amortized Constant time complexity. + */ + GenericValue & AddMember(StringRefType name, GenericValue & value, Allocator & allocator) + { + GenericValue n(name); + return AddMember(n, value, allocator); + } - //! Add a constant string value as member (name-value pair) to the object. - /*! \param name A constant string reference as name of member. - \param value constant string reference as value of member. - \param allocator Allocator for reallocating memory. It must be the same one as used before. Commonly use GenericDocument::GetAllocator(). - \return The value itself for fluent API. - \pre IsObject() - \note This overload is needed to avoid clashes with the generic primitive type AddMember(StringRefType,T,Allocator&) overload below. - \note Amortized Constant time complexity. - */ - GenericValue& AddMember(StringRefType name, StringRefType value, Allocator& allocator) { - GenericValue v(value); - return AddMember(name, v, allocator); - } + //! Add a constant string value as member (name-value pair) to the object. + /*! \param name A constant string reference as name of member. + \param value constant string reference as value of member. + \param allocator Allocator for reallocating memory. It must be the same one as used before. Commonly use GenericDocument::GetAllocator(). + \return The value itself for fluent API. + \pre IsObject() + \note This overload is needed to avoid clashes with the generic primitive type AddMember(StringRefType,T,Allocator&) overload below. + \note Amortized Constant time complexity. + */ + GenericValue & AddMember(StringRefType name, StringRefType value, Allocator & allocator) + { + GenericValue v(value); + return AddMember(name, v, allocator); + } - //! Add any primitive value as member (name-value pair) to the object. - /*! \tparam T Either \ref Type, \c int, \c unsigned, \c int64_t, \c uint64_t - \param name A constant string reference as name of member. - \param value Value of primitive type \c T as value of member - \param allocator Allocator for reallocating memory. Commonly use GenericDocument::GetAllocator(). - \return The value itself for fluent API. - \pre IsObject() + //! Add any primitive value as member (name-value pair) to the object. + /*! \tparam T Either \ref Type, \c int, \c unsigned, \c int64_t, \c uint64_t + \param name A constant string reference as name of member. + \param value Value of primitive type \c T as value of member + \param allocator Allocator for reallocating memory. Commonly use GenericDocument::GetAllocator(). + \return The value itself for fluent API. + \pre IsObject() - \note The source type \c T explicitly disallows all pointer types, - especially (\c const) \ref Ch*. This helps avoiding implicitly - referencing character strings with insufficient lifetime, use - \ref AddMember(StringRefType, GenericValue&, Allocator&) or \ref - AddMember(StringRefType, StringRefType, Allocator&). - All other pointer types would implicitly convert to \c bool, - use an explicit cast instead, if needed. - \note Amortized Constant time complexity. - */ - template - RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr, internal::IsGenericValue >), (GenericValue&)) - AddMember(StringRefType name, T value, Allocator& allocator) { - GenericValue n(name); - return AddMember(n, value, allocator); - } + \note The source type \c T explicitly disallows all pointer types, + especially (\c const) \ref Ch*. This helps avoiding implicitly + referencing character strings with insufficient lifetime, use + \ref AddMember(StringRefType, GenericValue&, Allocator&) or \ref + AddMember(StringRefType, StringRefType, Allocator&). + All other pointer types would implicitly convert to \c bool, + use an explicit cast instead, if needed. + \note Amortized Constant time complexity. + */ + template + RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr, internal::IsGenericValue>), + (GenericValue &)) + AddMember(StringRefType name, T value, Allocator & allocator) + { + GenericValue n(name); + return AddMember(n, value, allocator); + } - //! Remove all members in the object. - /*! This function do not deallocate memory in the object, i.e. the capacity is unchanged. - \note Linear time complexity. - */ - void RemoveAllMembers() { - RAPIDJSON_ASSERT(IsObject()); - for (MemberIterator m = MemberBegin(); m != MemberEnd(); ++m) - m->~Member(); - data_.o.size = 0; - } + //! Remove all members in the object. + /*! This function do not deallocate memory in the object, i.e. the capacity is unchanged. + \note Linear time complexity. + */ + void RemoveAllMembers() + { + RAPIDJSON_ASSERT(IsObject()); + for(MemberIterator m = MemberBegin(); m != MemberEnd(); ++m) + { + m->~Member(); + } + data_.o.size = 0; + } - //! Remove a member in object by its name. - /*! \param name Name of member to be removed. - \return Whether the member existed. - \note This function may reorder the object members. Use \ref - EraseMember(ConstMemberIterator) if you need to preserve the - relative order of the remaining members. - \note Linear time complexity. - */ - bool RemoveMember(const Ch* name) { - GenericValue n(StringRef(name)); - return RemoveMember(n); - } + //! Remove a member in object by its name. + /*! \param name Name of member to be removed. + \return Whether the member existed. + \note This function may reorder the object members. Use \ref + EraseMember(ConstMemberIterator) if you need to preserve the + relative order of the remaining members. + \note Linear time complexity. + */ + bool RemoveMember(const Ch* name) + { + GenericValue n(StringRef(name)); + return RemoveMember(n); + } #if RAPIDJSON_HAS_STDSTRING - bool RemoveMember(const std::basic_string& name) { return RemoveMember(GenericValue(StringRef(name))); } + bool RemoveMember(const std::basic_string & name) + { + return RemoveMember(GenericValue(StringRef(name))); + } #endif - template - bool RemoveMember(const GenericValue& name) { - MemberIterator m = FindMember(name); - if (m != MemberEnd()) { - RemoveMember(m); - return true; - } - else - return false; - } + template + bool RemoveMember(const GenericValue & name) + { + MemberIterator m = FindMember(name); + if(m != MemberEnd()) + { + RemoveMember(m); + return true; + } + else + { + return false; + } + } - //! Remove a member in object by iterator. - /*! \param m member iterator (obtained by FindMember() or MemberBegin()). - \return the new iterator after removal. - \note This function may reorder the object members. Use \ref - EraseMember(ConstMemberIterator) if you need to preserve the - relative order of the remaining members. - \note Constant time complexity. - */ - MemberIterator RemoveMember(MemberIterator m) { - RAPIDJSON_ASSERT(IsObject()); - RAPIDJSON_ASSERT(data_.o.size > 0); - RAPIDJSON_ASSERT(GetMembersPointer() != 0); - RAPIDJSON_ASSERT(m >= MemberBegin() && m < MemberEnd()); + //! Remove a member in object by iterator. + /*! \param m member iterator (obtained by FindMember() or MemberBegin()). + \return the new iterator after removal. + \note This function may reorder the object members. Use \ref + EraseMember(ConstMemberIterator) if you need to preserve the + relative order of the remaining members. + \note Constant time complexity. + */ + MemberIterator RemoveMember(MemberIterator m) + { + RAPIDJSON_ASSERT(IsObject()); + RAPIDJSON_ASSERT(data_.o.size > 0); + RAPIDJSON_ASSERT(GetMembersPointer() != 0); + RAPIDJSON_ASSERT(m >= MemberBegin() && m < MemberEnd()); - MemberIterator last(GetMembersPointer() + (data_.o.size - 1)); - if (data_.o.size > 1 && m != last) - *m = *last; // Move the last one to this place - else - m->~Member(); // Only one left, just destroy - --data_.o.size; - return m; - } + MemberIterator last(GetMembersPointer() + (data_.o.size - 1)); + if(data_.o.size > 1 && m != last) + { + *m = *last; // Move the last one to this place + } + else + { + m->~Member(); // Only one left, just destroy + } + --data_.o.size; + return m; + } - //! Remove a member from an object by iterator. - /*! \param pos iterator to the member to remove - \pre IsObject() == true && \ref MemberBegin() <= \c pos < \ref MemberEnd() - \return Iterator following the removed element. - If the iterator \c pos refers to the last element, the \ref MemberEnd() iterator is returned. - \note This function preserves the relative order of the remaining object - members. If you do not need this, use the more efficient \ref RemoveMember(MemberIterator). - \note Linear time complexity. - */ - MemberIterator EraseMember(ConstMemberIterator pos) { - return EraseMember(pos, pos +1); - } + //! Remove a member from an object by iterator. + /*! \param pos iterator to the member to remove + \pre IsObject() == true && \ref MemberBegin() <= \c pos < \ref MemberEnd() + \return Iterator following the removed element. + If the iterator \c pos refers to the last element, the \ref MemberEnd() iterator is returned. + \note This function preserves the relative order of the remaining object + members. If you do not need this, use the more efficient \ref RemoveMember(MemberIterator). + \note Linear time complexity. + */ + MemberIterator EraseMember(ConstMemberIterator pos) + { + return EraseMember(pos, pos + 1); + } - //! Remove members in the range [first, last) from an object. - /*! \param first iterator to the first member to remove - \param last iterator following the last member to remove - \pre IsObject() == true && \ref MemberBegin() <= \c first <= \c last <= \ref MemberEnd() - \return Iterator following the last removed element. - \note This function preserves the relative order of the remaining object - members. - \note Linear time complexity. - */ - MemberIterator EraseMember(ConstMemberIterator first, ConstMemberIterator last) { - RAPIDJSON_ASSERT(IsObject()); - RAPIDJSON_ASSERT(data_.o.size > 0); - RAPIDJSON_ASSERT(GetMembersPointer() != 0); - RAPIDJSON_ASSERT(first >= MemberBegin()); - RAPIDJSON_ASSERT(first <= last); - RAPIDJSON_ASSERT(last <= MemberEnd()); + //! Remove members in the range [first, last) from an object. + /*! \param first iterator to the first member to remove + \param last iterator following the last member to remove + \pre IsObject() == true && \ref MemberBegin() <= \c first <= \c last <= \ref MemberEnd() + \return Iterator following the last removed element. + \note This function preserves the relative order of the remaining object + members. + \note Linear time complexity. + */ + MemberIterator EraseMember(ConstMemberIterator first, ConstMemberIterator last) + { + RAPIDJSON_ASSERT(IsObject()); + RAPIDJSON_ASSERT(data_.o.size > 0); + RAPIDJSON_ASSERT(GetMembersPointer() != 0); + RAPIDJSON_ASSERT(first >= MemberBegin()); + RAPIDJSON_ASSERT(first <= last); + RAPIDJSON_ASSERT(last <= MemberEnd()); - MemberIterator pos = MemberBegin() + (first - MemberBegin()); - for (MemberIterator itr = pos; itr != last; ++itr) - itr->~Member(); - std::memmove(&*pos, &*last, static_cast(MemberEnd() - last) * sizeof(Member)); - data_.o.size -= static_cast(last - first); - return pos; - } + MemberIterator pos = MemberBegin() + (first - MemberBegin()); + for(MemberIterator itr = pos; itr != last; ++itr) + { + itr->~Member(); + } + std::memmove(&*pos, &*last, static_cast(MemberEnd() - last) * sizeof(Member)); + data_.o.size -= static_cast(last - first); + return pos; + } - //! Erase a member in object by its name. - /*! \param name Name of member to be removed. - \return Whether the member existed. - \note Linear time complexity. - */ - bool EraseMember(const Ch* name) { - GenericValue n(StringRef(name)); - return EraseMember(n); - } + //! Erase a member in object by its name. + /*! \param name Name of member to be removed. + \return Whether the member existed. + \note Linear time complexity. + */ + bool EraseMember(const Ch* name) + { + GenericValue n(StringRef(name)); + return EraseMember(n); + } #if RAPIDJSON_HAS_STDSTRING - bool EraseMember(const std::basic_string& name) { return EraseMember(GenericValue(StringRef(name))); } + bool EraseMember(const std::basic_string & name) + { + return EraseMember(GenericValue(StringRef(name))); + } #endif - template - bool EraseMember(const GenericValue& name) { - MemberIterator m = FindMember(name); - if (m != MemberEnd()) { - EraseMember(m); - return true; - } - else - return false; - } + template + bool EraseMember(const GenericValue & name) + { + MemberIterator m = FindMember(name); + if(m != MemberEnd()) + { + EraseMember(m); + return true; + } + else + { + return false; + } + } - Object GetObject() { RAPIDJSON_ASSERT(IsObject()); return Object(*this); } - ConstObject GetObject() const { RAPIDJSON_ASSERT(IsObject()); return ConstObject(*this); } + Object GetObject() + { + RAPIDJSON_ASSERT(IsObject()); + return Object(*this); + } + ConstObject GetObject() const + { + RAPIDJSON_ASSERT(IsObject()); + return ConstObject(*this); + } - //@} + //@} - //!@name Array - //@{ + //!@name Array + //@{ - //! Set this value as an empty array. - /*! \post IsArray == true */ - GenericValue& SetArray() { this->~GenericValue(); new (this) GenericValue(kArrayType); return *this; } + //! Set this value as an empty array. + /*! \post IsArray == true */ + GenericValue & SetArray() + { + this->~GenericValue(); + new(this) GenericValue(kArrayType); + return *this; + } - //! Get the number of elements in array. - SizeType Size() const { RAPIDJSON_ASSERT(IsArray()); return data_.a.size; } + //! Get the number of elements in array. + SizeType Size() const + { + RAPIDJSON_ASSERT(IsArray()); + return data_.a.size; + } - //! Get the capacity of array. - SizeType Capacity() const { RAPIDJSON_ASSERT(IsArray()); return data_.a.capacity; } + //! Get the capacity of array. + SizeType Capacity() const + { + RAPIDJSON_ASSERT(IsArray()); + return data_.a.capacity; + } - //! Check whether the array is empty. - bool Empty() const { RAPIDJSON_ASSERT(IsArray()); return data_.a.size == 0; } + //! Check whether the array is empty. + bool Empty() const + { + RAPIDJSON_ASSERT(IsArray()); + return data_.a.size == 0; + } - //! Remove all elements in the array. - /*! This function do not deallocate memory in the array, i.e. the capacity is unchanged. - \note Linear time complexity. - */ - void Clear() { - RAPIDJSON_ASSERT(IsArray()); - GenericValue* e = GetElementsPointer(); - for (GenericValue* v = e; v != e + data_.a.size; ++v) - v->~GenericValue(); - data_.a.size = 0; - } + //! Remove all elements in the array. + /*! This function do not deallocate memory in the array, i.e. the capacity is unchanged. + \note Linear time complexity. + */ + void Clear() + { + RAPIDJSON_ASSERT(IsArray()); + GenericValue* e = GetElementsPointer(); + for(GenericValue* v = e; v != e + data_.a.size; ++v) + { + v->~GenericValue(); + } + data_.a.size = 0; + } - //! Get an element from array by index. - /*! \pre IsArray() == true - \param index Zero-based index of element. - \see operator[](T*) - */ - GenericValue& operator[](SizeType index) { - RAPIDJSON_ASSERT(IsArray()); - RAPIDJSON_ASSERT(index < data_.a.size); - return GetElementsPointer()[index]; - } - const GenericValue& operator[](SizeType index) const { return const_cast(*this)[index]; } + //! Get an element from array by index. + /*! \pre IsArray() == true + \param index Zero-based index of element. + \see operator[](T*) + */ + GenericValue & operator[](SizeType index) + { + RAPIDJSON_ASSERT(IsArray()); + RAPIDJSON_ASSERT(index < data_.a.size); + return GetElementsPointer()[index]; + } + const GenericValue & operator[](SizeType index) const + { + return const_cast(*this)[index]; + } - //! Element iterator - /*! \pre IsArray() == true */ - ValueIterator Begin() { RAPIDJSON_ASSERT(IsArray()); return GetElementsPointer(); } - //! \em Past-the-end element iterator - /*! \pre IsArray() == true */ - ValueIterator End() { RAPIDJSON_ASSERT(IsArray()); return GetElementsPointer() + data_.a.size; } - //! Constant element iterator - /*! \pre IsArray() == true */ - ConstValueIterator Begin() const { return const_cast(*this).Begin(); } - //! Constant \em past-the-end element iterator - /*! \pre IsArray() == true */ - ConstValueIterator End() const { return const_cast(*this).End(); } + //! Element iterator + /*! \pre IsArray() == true */ + ValueIterator Begin() + { + RAPIDJSON_ASSERT(IsArray()); + return GetElementsPointer(); + } + //! \em Past-the-end element iterator + /*! \pre IsArray() == true */ + ValueIterator End() + { + RAPIDJSON_ASSERT(IsArray()); + return GetElementsPointer() + data_.a.size; + } + //! Constant element iterator + /*! \pre IsArray() == true */ + ConstValueIterator Begin() const + { + return const_cast(*this).Begin(); + } + //! Constant \em past-the-end element iterator + /*! \pre IsArray() == true */ + ConstValueIterator End() const + { + return const_cast(*this).End(); + } - //! Request the array to have enough capacity to store elements. - /*! \param newCapacity The capacity that the array at least need to have. - \param allocator Allocator for reallocating memory. It must be the same one as used before. Commonly use GenericDocument::GetAllocator(). - \return The value itself for fluent API. - \note Linear time complexity. - */ - GenericValue& Reserve(SizeType newCapacity, Allocator &allocator) { - RAPIDJSON_ASSERT(IsArray()); - if (newCapacity > data_.a.capacity) { - SetElementsPointer(reinterpret_cast(allocator.Realloc(GetElementsPointer(), data_.a.capacity * sizeof(GenericValue), newCapacity * sizeof(GenericValue)))); - data_.a.capacity = newCapacity; - } - return *this; - } + //! Request the array to have enough capacity to store elements. + /*! \param newCapacity The capacity that the array at least need to have. + \param allocator Allocator for reallocating memory. It must be the same one as used before. Commonly use GenericDocument::GetAllocator(). + \return The value itself for fluent API. + \note Linear time complexity. + */ + GenericValue & Reserve(SizeType newCapacity, Allocator & allocator) + { + RAPIDJSON_ASSERT(IsArray()); + if(newCapacity > data_.a.capacity) + { + SetElementsPointer(reinterpret_cast(allocator.Realloc(GetElementsPointer(), + data_.a.capacity * sizeof(GenericValue), newCapacity * sizeof(GenericValue)))); + data_.a.capacity = newCapacity; + } + return *this; + } - //! Append a GenericValue at the end of the array. - /*! \param value Value to be appended. - \param allocator Allocator for reallocating memory. It must be the same one as used before. Commonly use GenericDocument::GetAllocator(). - \pre IsArray() == true - \post value.IsNull() == true - \return The value itself for fluent API. - \note The ownership of \c value will be transferred to this array on success. - \note If the number of elements to be appended is known, calls Reserve() once first may be more efficient. - \note Amortized constant time complexity. - */ - GenericValue& PushBack(GenericValue& value, Allocator& allocator) { - RAPIDJSON_ASSERT(IsArray()); - if (data_.a.size >= data_.a.capacity) - Reserve(data_.a.capacity == 0 ? kDefaultArrayCapacity : (data_.a.capacity + (data_.a.capacity + 1) / 2), allocator); - GetElementsPointer()[data_.a.size++].RawAssign(value); - return *this; - } + //! Append a GenericValue at the end of the array. + /*! \param value Value to be appended. + \param allocator Allocator for reallocating memory. It must be the same one as used before. Commonly use GenericDocument::GetAllocator(). + \pre IsArray() == true + \post value.IsNull() == true + \return The value itself for fluent API. + \note The ownership of \c value will be transferred to this array on success. + \note If the number of elements to be appended is known, calls Reserve() once first may be more efficient. + \note Amortized constant time complexity. + */ + GenericValue & PushBack(GenericValue & value, Allocator & allocator) + { + RAPIDJSON_ASSERT(IsArray()); + if(data_.a.size >= data_.a.capacity) + { + Reserve(data_.a.capacity == 0 ? kDefaultArrayCapacity : (data_.a.capacity + (data_.a.capacity + 1) / 2), + allocator); + } + GetElementsPointer()[data_.a.size++].RawAssign(value); + return *this; + } #if RAPIDJSON_HAS_CXX11_RVALUE_REFS - GenericValue& PushBack(GenericValue&& value, Allocator& allocator) { - return PushBack(value, allocator); - } + GenericValue & PushBack(GenericValue && value, Allocator & allocator) + { + return PushBack(value, allocator); + } #endif // RAPIDJSON_HAS_CXX11_RVALUE_REFS - //! Append a constant string reference at the end of the array. - /*! \param value Constant string reference to be appended. - \param allocator Allocator for reallocating memory. It must be the same one used previously. Commonly use GenericDocument::GetAllocator(). - \pre IsArray() == true - \return The value itself for fluent API. - \note If the number of elements to be appended is known, calls Reserve() once first may be more efficient. - \note Amortized constant time complexity. - \see GenericStringRef - */ - GenericValue& PushBack(StringRefType value, Allocator& allocator) { - return (*this).template PushBack(value, allocator); - } + //! Append a constant string reference at the end of the array. + /*! \param value Constant string reference to be appended. + \param allocator Allocator for reallocating memory. It must be the same one used previously. Commonly use GenericDocument::GetAllocator(). + \pre IsArray() == true + \return The value itself for fluent API. + \note If the number of elements to be appended is known, calls Reserve() once first may be more efficient. + \note Amortized constant time complexity. + \see GenericStringRef + */ + GenericValue & PushBack(StringRefType value, Allocator & allocator) + { + return (*this).template PushBack(value, allocator); + } - //! Append a primitive value at the end of the array. - /*! \tparam T Either \ref Type, \c int, \c unsigned, \c int64_t, \c uint64_t - \param value Value of primitive type T to be appended. - \param allocator Allocator for reallocating memory. It must be the same one as used before. Commonly use GenericDocument::GetAllocator(). - \pre IsArray() == true - \return The value itself for fluent API. - \note If the number of elements to be appended is known, calls Reserve() once first may be more efficient. + //! Append a primitive value at the end of the array. + /*! \tparam T Either \ref Type, \c int, \c unsigned, \c int64_t, \c uint64_t + \param value Value of primitive type T to be appended. + \param allocator Allocator for reallocating memory. It must be the same one as used before. Commonly use GenericDocument::GetAllocator(). + \pre IsArray() == true + \return The value itself for fluent API. + \note If the number of elements to be appended is known, calls Reserve() once first may be more efficient. - \note The source type \c T explicitly disallows all pointer types, - especially (\c const) \ref Ch*. This helps avoiding implicitly - referencing character strings with insufficient lifetime, use - \ref PushBack(GenericValue&, Allocator&) or \ref - PushBack(StringRefType, Allocator&). - All other pointer types would implicitly convert to \c bool, - use an explicit cast instead, if needed. - \note Amortized constant time complexity. - */ - template - RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr, internal::IsGenericValue >), (GenericValue&)) - PushBack(T value, Allocator& allocator) { - GenericValue v(value); - return PushBack(v, allocator); - } + \note The source type \c T explicitly disallows all pointer types, + especially (\c const) \ref Ch*. This helps avoiding implicitly + referencing character strings with insufficient lifetime, use + \ref PushBack(GenericValue&, Allocator&) or \ref + PushBack(StringRefType, Allocator&). + All other pointer types would implicitly convert to \c bool, + use an explicit cast instead, if needed. + \note Amortized constant time complexity. + */ + template + RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr, internal::IsGenericValue>), + (GenericValue &)) + PushBack(T value, Allocator & allocator) + { + GenericValue v(value); + return PushBack(v, allocator); + } - //! Remove the last element in the array. - /*! - \note Constant time complexity. - */ - GenericValue& PopBack() { - RAPIDJSON_ASSERT(IsArray()); - RAPIDJSON_ASSERT(!Empty()); - GetElementsPointer()[--data_.a.size].~GenericValue(); - return *this; - } + //! Remove the last element in the array. + /*! + \note Constant time complexity. + */ + GenericValue & PopBack() + { + RAPIDJSON_ASSERT(IsArray()); + RAPIDJSON_ASSERT(!Empty()); + GetElementsPointer()[--data_.a.size].~GenericValue(); + return *this; + } - //! Remove an element of array by iterator. - /*! - \param pos iterator to the element to remove - \pre IsArray() == true && \ref Begin() <= \c pos < \ref End() - \return Iterator following the removed element. If the iterator pos refers to the last element, the End() iterator is returned. - \note Linear time complexity. - */ - ValueIterator Erase(ConstValueIterator pos) { - return Erase(pos, pos + 1); - } + //! Remove an element of array by iterator. + /*! + \param pos iterator to the element to remove + \pre IsArray() == true && \ref Begin() <= \c pos < \ref End() + \return Iterator following the removed element. If the iterator pos refers to the last element, the End() iterator is returned. + \note Linear time complexity. + */ + ValueIterator Erase(ConstValueIterator pos) + { + return Erase(pos, pos + 1); + } - //! Remove elements in the range [first, last) of the array. - /*! - \param first iterator to the first element to remove - \param last iterator following the last element to remove - \pre IsArray() == true && \ref Begin() <= \c first <= \c last <= \ref End() - \return Iterator following the last removed element. - \note Linear time complexity. - */ - ValueIterator Erase(ConstValueIterator first, ConstValueIterator last) { - RAPIDJSON_ASSERT(IsArray()); - RAPIDJSON_ASSERT(data_.a.size > 0); - RAPIDJSON_ASSERT(GetElementsPointer() != 0); - RAPIDJSON_ASSERT(first >= Begin()); - RAPIDJSON_ASSERT(first <= last); - RAPIDJSON_ASSERT(last <= End()); - ValueIterator pos = Begin() + (first - Begin()); - for (ValueIterator itr = pos; itr != last; ++itr) - itr->~GenericValue(); - std::memmove(pos, last, static_cast(End() - last) * sizeof(GenericValue)); - data_.a.size -= static_cast(last - first); - return pos; - } + //! Remove elements in the range [first, last) of the array. + /*! + \param first iterator to the first element to remove + \param last iterator following the last element to remove + \pre IsArray() == true && \ref Begin() <= \c first <= \c last <= \ref End() + \return Iterator following the last removed element. + \note Linear time complexity. + */ + ValueIterator Erase(ConstValueIterator first, ConstValueIterator last) + { + RAPIDJSON_ASSERT(IsArray()); + RAPIDJSON_ASSERT(data_.a.size > 0); + RAPIDJSON_ASSERT(GetElementsPointer() != 0); + RAPIDJSON_ASSERT(first >= Begin()); + RAPIDJSON_ASSERT(first <= last); + RAPIDJSON_ASSERT(last <= End()); + ValueIterator pos = Begin() + (first - Begin()); + for(ValueIterator itr = pos; itr != last; ++itr) + { + itr->~GenericValue(); + } + std::memmove(pos, last, static_cast(End() - last) * sizeof(GenericValue)); + data_.a.size -= static_cast(last - first); + return pos; + } - Array GetArray() { RAPIDJSON_ASSERT(IsArray()); return Array(*this); } - ConstArray GetArray() const { RAPIDJSON_ASSERT(IsArray()); return ConstArray(*this); } + Array GetArray() + { + RAPIDJSON_ASSERT(IsArray()); + return Array(*this); + } + ConstArray GetArray() const + { + RAPIDJSON_ASSERT(IsArray()); + return ConstArray(*this); + } - //@} + //@} - //!@name Number - //@{ + //!@name Number + //@{ - int GetInt() const { RAPIDJSON_ASSERT(data_.f.flags & kIntFlag); return data_.n.i.i; } - unsigned GetUint() const { RAPIDJSON_ASSERT(data_.f.flags & kUintFlag); return data_.n.u.u; } - int64_t GetInt64() const { RAPIDJSON_ASSERT(data_.f.flags & kInt64Flag); return data_.n.i64; } - uint64_t GetUint64() const { RAPIDJSON_ASSERT(data_.f.flags & kUint64Flag); return data_.n.u64; } + int GetInt() const + { + RAPIDJSON_ASSERT(data_.f.flags & kIntFlag); + return data_.n.i.i; + } + unsigned GetUint() const + { + RAPIDJSON_ASSERT(data_.f.flags & kUintFlag); + return data_.n.u.u; + } + int64_t GetInt64() const + { + RAPIDJSON_ASSERT(data_.f.flags & kInt64Flag); + return data_.n.i64; + } + uint64_t GetUint64() const + { + RAPIDJSON_ASSERT(data_.f.flags & kUint64Flag); + return data_.n.u64; + } - //! Get the value as double type. - /*! \note If the value is 64-bit integer type, it may lose precision. Use \c IsLosslessDouble() to check whether the converison is lossless. - */ - double GetDouble() const { - RAPIDJSON_ASSERT(IsNumber()); - if ((data_.f.flags & kDoubleFlag) != 0) return data_.n.d; // exact type, no conversion. - if ((data_.f.flags & kIntFlag) != 0) return data_.n.i.i; // int -> double - if ((data_.f.flags & kUintFlag) != 0) return data_.n.u.u; // unsigned -> double - if ((data_.f.flags & kInt64Flag) != 0) return static_cast(data_.n.i64); // int64_t -> double (may lose precision) - RAPIDJSON_ASSERT((data_.f.flags & kUint64Flag) != 0); return static_cast(data_.n.u64); // uint64_t -> double (may lose precision) - } + //! Get the value as double type. + /*! \note If the value is 64-bit integer type, it may lose precision. Use \c IsLosslessDouble() to check whether the converison is lossless. + */ + double GetDouble() const + { + RAPIDJSON_ASSERT(IsNumber()); + if((data_.f.flags & kDoubleFlag) != 0) + { + return data_.n.d; // exact type, no conversion. + } + if((data_.f.flags & kIntFlag) != 0) + { + return data_.n.i.i; // int -> double + } + if((data_.f.flags & kUintFlag) != 0) + { + return data_.n.u.u; // unsigned -> double + } + if((data_.f.flags & kInt64Flag) != 0) + { + return static_cast(data_.n.i64); // int64_t -> double (may lose precision) + } + RAPIDJSON_ASSERT((data_.f.flags & kUint64Flag) != 0); + return static_cast(data_.n.u64); // uint64_t -> double (may lose precision) + } - //! Get the value as float type. - /*! \note If the value is 64-bit integer type, it may lose precision. Use \c IsLosslessFloat() to check whether the converison is lossless. - */ - float GetFloat() const { - return static_cast(GetDouble()); - } + //! Get the value as float type. + /*! \note If the value is 64-bit integer type, it may lose precision. Use \c IsLosslessFloat() to check whether the converison is lossless. + */ + float GetFloat() const + { + return static_cast(GetDouble()); + } - GenericValue& SetInt(int i) { this->~GenericValue(); new (this) GenericValue(i); return *this; } - GenericValue& SetUint(unsigned u) { this->~GenericValue(); new (this) GenericValue(u); return *this; } - GenericValue& SetInt64(int64_t i64) { this->~GenericValue(); new (this) GenericValue(i64); return *this; } - GenericValue& SetUint64(uint64_t u64) { this->~GenericValue(); new (this) GenericValue(u64); return *this; } - GenericValue& SetDouble(double d) { this->~GenericValue(); new (this) GenericValue(d); return *this; } - GenericValue& SetFloat(float f) { this->~GenericValue(); new (this) GenericValue(f); return *this; } + GenericValue & SetInt(int i) + { + this->~GenericValue(); + new(this) GenericValue(i); + return *this; + } + GenericValue & SetUint(unsigned u) + { + this->~GenericValue(); + new(this) GenericValue(u); + return *this; + } + GenericValue & SetInt64(int64_t i64) + { + this->~GenericValue(); + new(this) GenericValue(i64); + return *this; + } + GenericValue & SetUint64(uint64_t u64) + { + this->~GenericValue(); + new(this) GenericValue(u64); + return *this; + } + GenericValue & SetDouble(double d) + { + this->~GenericValue(); + new(this) GenericValue(d); + return *this; + } + GenericValue & SetFloat(float f) + { + this->~GenericValue(); + new(this) GenericValue(f); + return *this; + } - //@} + //@} - //!@name String - //@{ + //!@name String + //@{ - const Ch* GetString() const { RAPIDJSON_ASSERT(IsString()); return (data_.f.flags & kInlineStrFlag) ? data_.ss.str : GetStringPointer(); } + const Ch* GetString() const + { + RAPIDJSON_ASSERT(IsString()); + return (data_.f.flags & kInlineStrFlag) ? data_.ss.str : GetStringPointer(); + } - //! Get the length of string. - /*! Since rapidjson permits "\\u0000" in the json string, strlen(v.GetString()) may not equal to v.GetStringLength(). - */ - SizeType GetStringLength() const { RAPIDJSON_ASSERT(IsString()); return ((data_.f.flags & kInlineStrFlag) ? (data_.ss.GetLength()) : data_.s.length); } + //! Get the length of string. + /*! Since rapidjson permits "\\u0000" in the json string, strlen(v.GetString()) may not equal to v.GetStringLength(). + */ + SizeType GetStringLength() const + { + RAPIDJSON_ASSERT(IsString()); + return ((data_.f.flags & kInlineStrFlag) ? (data_.ss.GetLength()) : data_.s.length); + } - //! Set this value as a string without copying source string. - /*! This version has better performance with supplied length, and also support string containing null character. - \param s source string pointer. - \param length The length of source string, excluding the trailing null terminator. - \return The value itself for fluent API. - \post IsString() == true && GetString() == s && GetStringLength() == length - \see SetString(StringRefType) - */ - GenericValue& SetString(const Ch* s, SizeType length) { return SetString(StringRef(s, length)); } + //! Set this value as a string without copying source string. + /*! This version has better performance with supplied length, and also support string containing null character. + \param s source string pointer. + \param length The length of source string, excluding the trailing null terminator. + \return The value itself for fluent API. + \post IsString() == true && GetString() == s && GetStringLength() == length + \see SetString(StringRefType) + */ + GenericValue & SetString(const Ch* s, SizeType length) + { + return SetString(StringRef(s, length)); + } - //! Set this value as a string without copying source string. - /*! \param s source string reference - \return The value itself for fluent API. - \post IsString() == true && GetString() == s && GetStringLength() == s.length - */ - GenericValue& SetString(StringRefType s) { this->~GenericValue(); SetStringRaw(s); return *this; } + //! Set this value as a string without copying source string. + /*! \param s source string reference + \return The value itself for fluent API. + \post IsString() == true && GetString() == s && GetStringLength() == s.length + */ + GenericValue & SetString(StringRefType s) + { + this->~GenericValue(); + SetStringRaw(s); + return *this; + } - //! Set this value as a string by copying from source string. - /*! This version has better performance with supplied length, and also support string containing null character. - \param s source string. - \param length The length of source string, excluding the trailing null terminator. - \param allocator Allocator for allocating copied buffer. Commonly use GenericDocument::GetAllocator(). - \return The value itself for fluent API. - \post IsString() == true && GetString() != s && strcmp(GetString(),s) == 0 && GetStringLength() == length - */ - GenericValue& SetString(const Ch* s, SizeType length, Allocator& allocator) { this->~GenericValue(); SetStringRaw(StringRef(s, length), allocator); return *this; } + //! Set this value as a string by copying from source string. + /*! This version has better performance with supplied length, and also support string containing null character. + \param s source string. + \param length The length of source string, excluding the trailing null terminator. + \param allocator Allocator for allocating copied buffer. Commonly use GenericDocument::GetAllocator(). + \return The value itself for fluent API. + \post IsString() == true && GetString() != s && strcmp(GetString(),s) == 0 && GetStringLength() == length + */ + GenericValue & SetString(const Ch* s, SizeType length, Allocator & allocator) + { + this->~GenericValue(); + SetStringRaw(StringRef(s, length), allocator); + return *this; + } - //! Set this value as a string by copying from source string. - /*! \param s source string. - \param allocator Allocator for allocating copied buffer. Commonly use GenericDocument::GetAllocator(). - \return The value itself for fluent API. - \post IsString() == true && GetString() != s && strcmp(GetString(),s) == 0 && GetStringLength() == length - */ - GenericValue& SetString(const Ch* s, Allocator& allocator) { return SetString(s, internal::StrLen(s), allocator); } + //! Set this value as a string by copying from source string. + /*! \param s source string. + \param allocator Allocator for allocating copied buffer. Commonly use GenericDocument::GetAllocator(). + \return The value itself for fluent API. + \post IsString() == true && GetString() != s && strcmp(GetString(),s) == 0 && GetStringLength() == length + */ + GenericValue & SetString(const Ch* s, Allocator & allocator) + { + return SetString(s, internal::StrLen(s), allocator); + } #if RAPIDJSON_HAS_STDSTRING - //! Set this value as a string by copying from source string. - /*! \param s source string. - \param allocator Allocator for allocating copied buffer. Commonly use GenericDocument::GetAllocator(). - \return The value itself for fluent API. - \post IsString() == true && GetString() != s.data() && strcmp(GetString(),s.data() == 0 && GetStringLength() == s.size() - \note Requires the definition of the preprocessor symbol \ref RAPIDJSON_HAS_STDSTRING. - */ - GenericValue& SetString(const std::basic_string& s, Allocator& allocator) { return SetString(s.data(), SizeType(s.size()), allocator); } + //! Set this value as a string by copying from source string. + /*! \param s source string. + \param allocator Allocator for allocating copied buffer. Commonly use GenericDocument::GetAllocator(). + \return The value itself for fluent API. + \post IsString() == true && GetString() != s.data() && strcmp(GetString(),s.data() == 0 && GetStringLength() == s.size() + \note Requires the definition of the preprocessor symbol \ref RAPIDJSON_HAS_STDSTRING. + */ + GenericValue & SetString(const std::basic_string & s, Allocator & allocator) + { + return SetString(s.data(), SizeType(s.size()), allocator); + } #endif - //@} + //@} - //!@name Array - //@{ + //!@name Array + //@{ - //! Templated version for checking whether this value is type T. - /*! - \tparam T Either \c bool, \c int, \c unsigned, \c int64_t, \c uint64_t, \c double, \c float, \c const \c char*, \c std::basic_string - */ - template - bool Is() const { return internal::TypeHelper::Is(*this); } + //! Templated version for checking whether this value is type T. + /*! + \tparam T Either \c bool, \c int, \c unsigned, \c int64_t, \c uint64_t, \c double, \c float, \c const \c char*, \c std::basic_string + */ + template + bool Is() const + { + return internal::TypeHelper::Is(*this); + } - template - T Get() const { return internal::TypeHelper::Get(*this); } + template + T Get() const + { + return internal::TypeHelper::Get(*this); + } - template - T Get() { return internal::TypeHelper::Get(*this); } + template + T Get() + { + return internal::TypeHelper::Get(*this); + } - template - ValueType& Set(const T& data) { return internal::TypeHelper::Set(*this, data); } + template + ValueType & Set(const T & data) + { + return internal::TypeHelper::Set(*this, data); + } - template - ValueType& Set(const T& data, AllocatorType& allocator) { return internal::TypeHelper::Set(*this, data, allocator); } + template + ValueType & Set(const T & data, AllocatorType & allocator) + { + return internal::TypeHelper::Set(*this, data, allocator); + } - //@} + //@} - //! Generate events of this value to a Handler. - /*! This function adopts the GoF visitor pattern. - Typical usage is to output this JSON value as JSON text via Writer, which is a Handler. - It can also be used to deep clone this value via GenericDocument, which is also a Handler. - \tparam Handler type of handler. - \param handler An object implementing concept Handler. - */ - template - bool Accept(Handler& handler) const { - switch(GetType()) { - case kNullType: return handler.Null(); - case kFalseType: return handler.Bool(false); - case kTrueType: return handler.Bool(true); + //! Generate events of this value to a Handler. + /*! This function adopts the GoF visitor pattern. + Typical usage is to output this JSON value as JSON text via Writer, which is a Handler. + It can also be used to deep clone this value via GenericDocument, which is also a Handler. + \tparam Handler type of handler. + \param handler An object implementing concept Handler. + */ + template + bool Accept(Handler & handler) const + { + switch(GetType()) + { + case kNullType: + return handler.Null(); + case kFalseType: + return handler.Bool(false); + case kTrueType: + return handler.Bool(true); - case kObjectType: - if (RAPIDJSON_UNLIKELY(!handler.StartObject())) - return false; - for (ConstMemberIterator m = MemberBegin(); m != MemberEnd(); ++m) { - RAPIDJSON_ASSERT(m->name.IsString()); // User may change the type of name by MemberIterator. - if (RAPIDJSON_UNLIKELY(!handler.Key(m->name.GetString(), m->name.GetStringLength(), (m->name.data_.f.flags & kCopyFlag) != 0))) - return false; - if (RAPIDJSON_UNLIKELY(!m->value.Accept(handler))) - return false; - } - return handler.EndObject(data_.o.size); + case kObjectType: + if(RAPIDJSON_UNLIKELY(!handler.StartObject())) + { + return false; + } + for(ConstMemberIterator m = MemberBegin(); m != MemberEnd(); ++m) + { + RAPIDJSON_ASSERT(m->name.IsString()); // User may change the type of name by MemberIterator. + if(RAPIDJSON_UNLIKELY(!handler.Key(m->name.GetString(), m->name.GetStringLength(), + (m->name.data_.f.flags & kCopyFlag) != 0))) + { + return false; + } + if(RAPIDJSON_UNLIKELY(!m->value.Accept(handler))) + { + return false; + } + } + return handler.EndObject(data_.o.size); - case kArrayType: - if (RAPIDJSON_UNLIKELY(!handler.StartArray())) - return false; - for (const GenericValue* v = Begin(); v != End(); ++v) - if (RAPIDJSON_UNLIKELY(!v->Accept(handler))) - return false; - return handler.EndArray(data_.a.size); - - case kStringType: - return handler.String(GetString(), GetStringLength(), (data_.f.flags & kCopyFlag) != 0); - - default: - RAPIDJSON_ASSERT(GetType() == kNumberType); - if (IsDouble()) return handler.Double(data_.n.d); - else if (IsInt()) return handler.Int(data_.n.i.i); - else if (IsUint()) return handler.Uint(data_.n.u.u); - else if (IsInt64()) return handler.Int64(data_.n.i64); - else return handler.Uint64(data_.n.u64); - } - } + case kArrayType: + if(RAPIDJSON_UNLIKELY(!handler.StartArray())) + { + return false; + } + for(const GenericValue* v = Begin(); v != End(); ++v) + if(RAPIDJSON_UNLIKELY(!v->Accept(handler))) + { + return false; + } + return handler.EndArray(data_.a.size); + + case kStringType: + return handler.String(GetString(), GetStringLength(), (data_.f.flags & kCopyFlag) != 0); + + default: + RAPIDJSON_ASSERT(GetType() == kNumberType); + if(IsDouble()) + { + return handler.Double(data_.n.d); + } + else if(IsInt()) + { + return handler.Int(data_.n.i.i); + } + else if(IsUint()) + { + return handler.Uint(data_.n.u.u); + } + else if(IsInt64()) + { + return handler.Int64(data_.n.i64); + } + else + { + return handler.Uint64(data_.n.u64); + } + } + } private: - template friend class GenericValue; - template friend class GenericDocument; + template friend class GenericValue; + template friend class GenericDocument; - enum { - kBoolFlag = 0x0008, - kNumberFlag = 0x0010, - kIntFlag = 0x0020, - kUintFlag = 0x0040, - kInt64Flag = 0x0080, - kUint64Flag = 0x0100, - kDoubleFlag = 0x0200, - kStringFlag = 0x0400, - kCopyFlag = 0x0800, - kInlineStrFlag = 0x1000, + enum + { + kBoolFlag = 0x0008, + kNumberFlag = 0x0010, + kIntFlag = 0x0020, + kUintFlag = 0x0040, + kInt64Flag = 0x0080, + kUint64Flag = 0x0100, + kDoubleFlag = 0x0200, + kStringFlag = 0x0400, + kCopyFlag = 0x0800, + kInlineStrFlag = 0x1000, - // Initial flags of different types. - kNullFlag = kNullType, - kTrueFlag = kTrueType | kBoolFlag, - kFalseFlag = kFalseType | kBoolFlag, - kNumberIntFlag = kNumberType | kNumberFlag | kIntFlag | kInt64Flag, - kNumberUintFlag = kNumberType | kNumberFlag | kUintFlag | kUint64Flag | kInt64Flag, - kNumberInt64Flag = kNumberType | kNumberFlag | kInt64Flag, - kNumberUint64Flag = kNumberType | kNumberFlag | kUint64Flag, - kNumberDoubleFlag = kNumberType | kNumberFlag | kDoubleFlag, - kNumberAnyFlag = kNumberType | kNumberFlag | kIntFlag | kInt64Flag | kUintFlag | kUint64Flag | kDoubleFlag, - kConstStringFlag = kStringType | kStringFlag, - kCopyStringFlag = kStringType | kStringFlag | kCopyFlag, - kShortStringFlag = kStringType | kStringFlag | kCopyFlag | kInlineStrFlag, - kObjectFlag = kObjectType, - kArrayFlag = kArrayType, + // Initial flags of different types. + kNullFlag = kNullType, + kTrueFlag = kTrueType | kBoolFlag, + kFalseFlag = kFalseType | kBoolFlag, + kNumberIntFlag = kNumberType | kNumberFlag | kIntFlag | kInt64Flag, + kNumberUintFlag = kNumberType | kNumberFlag | kUintFlag | kUint64Flag | kInt64Flag, + kNumberInt64Flag = kNumberType | kNumberFlag | kInt64Flag, + kNumberUint64Flag = kNumberType | kNumberFlag | kUint64Flag, + kNumberDoubleFlag = kNumberType | kNumberFlag | kDoubleFlag, + kNumberAnyFlag = kNumberType | kNumberFlag | kIntFlag | kInt64Flag | kUintFlag | kUint64Flag | kDoubleFlag, + kConstStringFlag = kStringType | kStringFlag, + kCopyStringFlag = kStringType | kStringFlag | kCopyFlag, + kShortStringFlag = kStringType | kStringFlag | kCopyFlag | kInlineStrFlag, + kObjectFlag = kObjectType, + kArrayFlag = kArrayType, - kTypeMask = 0x07 - }; + kTypeMask = 0x07 + }; - static const SizeType kDefaultArrayCapacity = 16; - static const SizeType kDefaultObjectCapacity = 16; + static const SizeType kDefaultArrayCapacity = 16; + static const SizeType kDefaultObjectCapacity = 16; - struct Flag { + struct Flag + { #if RAPIDJSON_48BITPOINTER_OPTIMIZATION - char payload[sizeof(SizeType) * 2 + 6]; // 2 x SizeType + lower 48-bit pointer + char payload[sizeof(SizeType) * 2 + 6]; // 2 x SizeType + lower 48-bit pointer #elif RAPIDJSON_64BIT - char payload[sizeof(SizeType) * 2 + sizeof(void*) + 6]; // 6 padding bytes + char payload[sizeof(SizeType) * 2 + sizeof(void*) + 6]; // 6 padding bytes #else - char payload[sizeof(SizeType) * 2 + sizeof(void*) + 2]; // 2 padding bytes + char payload[sizeof(SizeType) * 2 + sizeof(void*) + 2]; // 2 padding bytes #endif - uint16_t flags; - }; + uint16_t flags; + }; - struct String { - SizeType length; - SizeType hashcode; //!< reserved - const Ch* str; - }; // 12 bytes in 32-bit mode, 16 bytes in 64-bit mode + struct String + { + SizeType length; + SizeType hashcode; //!< reserved + const Ch* str; + }; // 12 bytes in 32-bit mode, 16 bytes in 64-bit mode - // implementation detail: ShortString can represent zero-terminated strings up to MaxSize chars - // (excluding the terminating zero) and store a value to determine the length of the contained - // string in the last character str[LenPos] by storing "MaxSize - length" there. If the string - // to store has the maximal length of MaxSize then str[LenPos] will be 0 and therefore act as - // the string terminator as well. For getting the string length back from that value just use - // "MaxSize - str[LenPos]". - // This allows to store 13-chars strings in 32-bit mode, 21-chars strings in 64-bit mode, - // 13-chars strings for RAPIDJSON_48BITPOINTER_OPTIMIZATION=1 inline (for `UTF8`-encoded strings). - struct ShortString { - enum { MaxChars = sizeof(static_cast(0)->payload) / sizeof(Ch), MaxSize = MaxChars - 1, LenPos = MaxSize }; - Ch str[MaxChars]; + // implementation detail: ShortString can represent zero-terminated strings up to MaxSize chars + // (excluding the terminating zero) and store a value to determine the length of the contained + // string in the last character str[LenPos] by storing "MaxSize - length" there. If the string + // to store has the maximal length of MaxSize then str[LenPos] will be 0 and therefore act as + // the string terminator as well. For getting the string length back from that value just use + // "MaxSize - str[LenPos]". + // This allows to store 13-chars strings in 32-bit mode, 21-chars strings in 64-bit mode, + // 13-chars strings for RAPIDJSON_48BITPOINTER_OPTIMIZATION=1 inline (for `UTF8`-encoded strings). + struct ShortString + { + enum { MaxChars = sizeof(static_cast(0)->payload) / sizeof(Ch), MaxSize = MaxChars - 1, LenPos = MaxSize }; + Ch str[MaxChars]; - inline static bool Usable(SizeType len) { return (MaxSize >= len); } - inline void SetLength(SizeType len) { str[LenPos] = static_cast(MaxSize - len); } - inline SizeType GetLength() const { return static_cast(MaxSize - str[LenPos]); } - }; // at most as many bytes as "String" above => 12 bytes in 32-bit mode, 16 bytes in 64-bit mode + inline static bool Usable(SizeType len) + { + return (MaxSize >= len); + } + inline void SetLength(SizeType len) + { + str[LenPos] = static_cast(MaxSize - len); + } + inline SizeType GetLength() const + { + return static_cast(MaxSize - str[LenPos]); + } + }; // at most as many bytes as "String" above => 12 bytes in 32-bit mode, 16 bytes in 64-bit mode - // By using proper binary layout, retrieval of different integer types do not need conversions. - union Number { + // By using proper binary layout, retrieval of different integer types do not need conversions. + union Number + { #if RAPIDJSON_ENDIAN == RAPIDJSON_LITTLEENDIAN - struct I { - int i; - char padding[4]; - }i; - struct U { - unsigned u; - char padding2[4]; - }u; + struct I + { + int i; + char padding[4]; + } i; + struct U + { + unsigned u; + char padding2[4]; + } u; #else - struct I { - char padding[4]; - int i; - }i; - struct U { - char padding2[4]; - unsigned u; - }u; + struct I + { + char padding[4]; + int i; + } i; + struct U + { + char padding2[4]; + unsigned u; + } u; #endif - int64_t i64; - uint64_t u64; - double d; - }; // 8 bytes + int64_t i64; + uint64_t u64; + double d; + }; // 8 bytes - struct ObjectData { - SizeType size; - SizeType capacity; - Member* members; - }; // 12 bytes in 32-bit mode, 16 bytes in 64-bit mode + struct ObjectData + { + SizeType size; + SizeType capacity; + Member* members; + }; // 12 bytes in 32-bit mode, 16 bytes in 64-bit mode - struct ArrayData { - SizeType size; - SizeType capacity; - GenericValue* elements; - }; // 12 bytes in 32-bit mode, 16 bytes in 64-bit mode + struct ArrayData + { + SizeType size; + SizeType capacity; + GenericValue* elements; + }; // 12 bytes in 32-bit mode, 16 bytes in 64-bit mode - union Data { - String s; - ShortString ss; - Number n; - ObjectData o; - ArrayData a; - Flag f; - }; // 16 bytes in 32-bit mode, 24 bytes in 64-bit mode, 16 bytes in 64-bit with RAPIDJSON_48BITPOINTER_OPTIMIZATION + union Data + { + String s; + ShortString ss; + Number n; + ObjectData o; + ArrayData a; + Flag f; + }; // 16 bytes in 32-bit mode, 24 bytes in 64-bit mode, 16 bytes in 64-bit with RAPIDJSON_48BITPOINTER_OPTIMIZATION - RAPIDJSON_FORCEINLINE const Ch* GetStringPointer() const { return RAPIDJSON_GETPOINTER(Ch, data_.s.str); } - RAPIDJSON_FORCEINLINE const Ch* SetStringPointer(const Ch* str) { return RAPIDJSON_SETPOINTER(Ch, data_.s.str, str); } - RAPIDJSON_FORCEINLINE GenericValue* GetElementsPointer() const { return RAPIDJSON_GETPOINTER(GenericValue, data_.a.elements); } - RAPIDJSON_FORCEINLINE GenericValue* SetElementsPointer(GenericValue* elements) { return RAPIDJSON_SETPOINTER(GenericValue, data_.a.elements, elements); } - RAPIDJSON_FORCEINLINE Member* GetMembersPointer() const { return RAPIDJSON_GETPOINTER(Member, data_.o.members); } - RAPIDJSON_FORCEINLINE Member* SetMembersPointer(Member* members) { return RAPIDJSON_SETPOINTER(Member, data_.o.members, members); } + RAPIDJSON_FORCEINLINE const Ch* GetStringPointer() const + { + return RAPIDJSON_GETPOINTER(Ch, data_.s.str); + } + RAPIDJSON_FORCEINLINE const Ch* SetStringPointer(const Ch* str) + { + return RAPIDJSON_SETPOINTER(Ch, data_.s.str, str); + } + RAPIDJSON_FORCEINLINE GenericValue* GetElementsPointer() const + { + return RAPIDJSON_GETPOINTER(GenericValue, data_.a.elements); + } + RAPIDJSON_FORCEINLINE GenericValue* SetElementsPointer(GenericValue* elements) + { + return RAPIDJSON_SETPOINTER(GenericValue, data_.a.elements, elements); + } + RAPIDJSON_FORCEINLINE Member* GetMembersPointer() const + { + return RAPIDJSON_GETPOINTER(Member, data_.o.members); + } + RAPIDJSON_FORCEINLINE Member* SetMembersPointer(Member* members) + { + return RAPIDJSON_SETPOINTER(Member, data_.o.members, members); + } - // Initialize this value as array with initial data, without calling destructor. - void SetArrayRaw(GenericValue* values, SizeType count, Allocator& allocator) { - data_.f.flags = kArrayFlag; - if (count) { - GenericValue* e = static_cast(allocator.Malloc(count * sizeof(GenericValue))); - SetElementsPointer(e); - std::memcpy(e, values, count * sizeof(GenericValue)); - } - else - SetElementsPointer(0); - data_.a.size = data_.a.capacity = count; - } + // Initialize this value as array with initial data, without calling destructor. + void SetArrayRaw(GenericValue* values, SizeType count, Allocator & allocator) + { + data_.f.flags = kArrayFlag; + if(count) + { + GenericValue* e = static_cast(allocator.Malloc(count * sizeof(GenericValue))); + SetElementsPointer(e); + std::memcpy(e, values, count * sizeof(GenericValue)); + } + else + { + SetElementsPointer(0); + } + data_.a.size = data_.a.capacity = count; + } - //! Initialize this value as object with initial data, without calling destructor. - void SetObjectRaw(Member* members, SizeType count, Allocator& allocator) { - data_.f.flags = kObjectFlag; - if (count) { - Member* m = static_cast(allocator.Malloc(count * sizeof(Member))); - SetMembersPointer(m); - std::memcpy(m, members, count * sizeof(Member)); - } - else - SetMembersPointer(0); - data_.o.size = data_.o.capacity = count; - } + //! Initialize this value as object with initial data, without calling destructor. + void SetObjectRaw(Member* members, SizeType count, Allocator & allocator) + { + data_.f.flags = kObjectFlag; + if(count) + { + Member* m = static_cast(allocator.Malloc(count * sizeof(Member))); + SetMembersPointer(m); + std::memcpy(m, members, count * sizeof(Member)); + } + else + { + SetMembersPointer(0); + } + data_.o.size = data_.o.capacity = count; + } - //! Initialize this value as constant string, without calling destructor. - void SetStringRaw(StringRefType s) RAPIDJSON_NOEXCEPT { - data_.f.flags = kConstStringFlag; - SetStringPointer(s); - data_.s.length = s.length; - } + //! Initialize this value as constant string, without calling destructor. + void SetStringRaw(StringRefType s) RAPIDJSON_NOEXCEPT + { + data_.f.flags = kConstStringFlag; + SetStringPointer(s); + data_.s.length = s.length; + } - //! Initialize this value as copy string with initial data, without calling destructor. - void SetStringRaw(StringRefType s, Allocator& allocator) { - Ch* str = 0; - if (ShortString::Usable(s.length)) { - data_.f.flags = kShortStringFlag; - data_.ss.SetLength(s.length); - str = data_.ss.str; - } else { - data_.f.flags = kCopyStringFlag; - data_.s.length = s.length; - str = static_cast(allocator.Malloc((s.length + 1) * sizeof(Ch))); - SetStringPointer(str); - } - std::memcpy(str, s, s.length * sizeof(Ch)); - str[s.length] = '\0'; - } + //! Initialize this value as copy string with initial data, without calling destructor. + void SetStringRaw(StringRefType s, Allocator & allocator) + { + Ch* str = 0; + if(ShortString::Usable(s.length)) + { + data_.f.flags = kShortStringFlag; + data_.ss.SetLength(s.length); + str = data_.ss.str; + } + else + { + data_.f.flags = kCopyStringFlag; + data_.s.length = s.length; + str = static_cast(allocator.Malloc((s.length + 1) * sizeof(Ch))); + SetStringPointer(str); + } + std::memcpy(str, s, s.length * sizeof(Ch)); + str[s.length] = '\0'; + } - //! Assignment without calling destructor - void RawAssign(GenericValue& rhs) RAPIDJSON_NOEXCEPT { - data_ = rhs.data_; - // data_.f.flags = rhs.data_.f.flags; - rhs.data_.f.flags = kNullFlag; - } + //! Assignment without calling destructor + void RawAssign(GenericValue & rhs) RAPIDJSON_NOEXCEPT + { + data_ = rhs.data_; + // data_.f.flags = rhs.data_.f.flags; + rhs.data_.f.flags = kNullFlag; + } - template - bool StringEqual(const GenericValue& rhs) const { - RAPIDJSON_ASSERT(IsString()); - RAPIDJSON_ASSERT(rhs.IsString()); + template + bool StringEqual(const GenericValue & rhs) const + { + RAPIDJSON_ASSERT(IsString()); + RAPIDJSON_ASSERT(rhs.IsString()); - const SizeType len1 = GetStringLength(); - const SizeType len2 = rhs.GetStringLength(); - if(len1 != len2) { return false; } + const SizeType len1 = GetStringLength(); + const SizeType len2 = rhs.GetStringLength(); + if(len1 != len2) + { + return false; + } - const Ch* const str1 = GetString(); - const Ch* const str2 = rhs.GetString(); - if(str1 == str2) { return true; } // fast path for constant string + const Ch* const str1 = GetString(); + const Ch* const str2 = rhs.GetString(); + if(str1 == str2) + { + return true; // fast path for constant string + } - return (std::memcmp(str1, str2, sizeof(Ch) * len1) == 0); - } + return (std::memcmp(str1, str2, sizeof(Ch) * len1) == 0); + } - Data data_; + Data data_; }; //! GenericValue with UTF8 encoding -typedef GenericValue > Value; +typedef GenericValue> Value; /////////////////////////////////////////////////////////////////////////////// -// GenericDocument +// GenericDocument //! A document for parsing JSON text as DOM. /*! @@ -2021,413 +2849,525 @@ typedef GenericValue > Value; \warning Although GenericDocument inherits from GenericValue, the API does \b not provide any virtual functions, especially no virtual destructor. To avoid memory leaks, do not \c delete a GenericDocument object via a pointer to a GenericValue. */ template , typename StackAllocator = CrtAllocator> -class GenericDocument : public GenericValue { +class GenericDocument : public GenericValue +{ public: - typedef typename Encoding::Ch Ch; //!< Character type derived from Encoding. - typedef GenericValue ValueType; //!< Value type of the document. - typedef Allocator AllocatorType; //!< Allocator type from template parameter. + typedef typename Encoding::Ch Ch; //!< Character type derived from Encoding. + typedef GenericValue ValueType; //!< Value type of the document. + typedef Allocator AllocatorType; //!< Allocator type from template parameter. - //! Constructor - /*! Creates an empty document of specified type. - \param type Mandatory type of object to create. - \param allocator Optional allocator for allocating memory. - \param stackCapacity Optional initial capacity of stack in bytes. - \param stackAllocator Optional allocator for allocating memory for stack. - */ - explicit GenericDocument(Type type, Allocator* allocator = 0, size_t stackCapacity = kDefaultStackCapacity, StackAllocator* stackAllocator = 0) : - GenericValue(type), allocator_(allocator), ownAllocator_(0), stack_(stackAllocator, stackCapacity), parseResult_() - { - if (!allocator_) - ownAllocator_ = allocator_ = RAPIDJSON_NEW(Allocator()); - } + //! Constructor + /*! Creates an empty document of specified type. + \param type Mandatory type of object to create. + \param allocator Optional allocator for allocating memory. + \param stackCapacity Optional initial capacity of stack in bytes. + \param stackAllocator Optional allocator for allocating memory for stack. + */ + explicit GenericDocument(Type type, Allocator* allocator = 0, size_t stackCapacity = kDefaultStackCapacity, + StackAllocator* stackAllocator = 0) : + GenericValue(type), allocator_(allocator), ownAllocator_(0), stack_(stackAllocator, + stackCapacity), parseResult_() + { + if(!allocator_) + { + ownAllocator_ = allocator_ = RAPIDJSON_NEW(Allocator()); + } + } - //! Constructor - /*! Creates an empty document which type is Null. - \param allocator Optional allocator for allocating memory. - \param stackCapacity Optional initial capacity of stack in bytes. - \param stackAllocator Optional allocator for allocating memory for stack. - */ - GenericDocument(Allocator* allocator = 0, size_t stackCapacity = kDefaultStackCapacity, StackAllocator* stackAllocator = 0) : - allocator_(allocator), ownAllocator_(0), stack_(stackAllocator, stackCapacity), parseResult_() - { - if (!allocator_) - ownAllocator_ = allocator_ = RAPIDJSON_NEW(Allocator()); - } + //! Constructor + /*! Creates an empty document which type is Null. + \param allocator Optional allocator for allocating memory. + \param stackCapacity Optional initial capacity of stack in bytes. + \param stackAllocator Optional allocator for allocating memory for stack. + */ + GenericDocument(Allocator* allocator = 0, size_t stackCapacity = kDefaultStackCapacity, + StackAllocator* stackAllocator = 0) : + allocator_(allocator), ownAllocator_(0), stack_(stackAllocator, stackCapacity), parseResult_() + { + if(!allocator_) + { + ownAllocator_ = allocator_ = RAPIDJSON_NEW(Allocator()); + } + } #if RAPIDJSON_HAS_CXX11_RVALUE_REFS - //! Move constructor in C++11 - GenericDocument(GenericDocument&& rhs) RAPIDJSON_NOEXCEPT - : ValueType(std::forward(rhs)), // explicit cast to avoid prohibited move from Document - allocator_(rhs.allocator_), - ownAllocator_(rhs.ownAllocator_), - stack_(std::move(rhs.stack_)), - parseResult_(rhs.parseResult_) - { - rhs.allocator_ = 0; - rhs.ownAllocator_ = 0; - rhs.parseResult_ = ParseResult(); - } + //! Move constructor in C++11 + GenericDocument(GenericDocument && rhs) RAPIDJSON_NOEXCEPT +: + ValueType(std::forward(rhs)), // explicit cast to avoid prohibited move from Document + allocator_(rhs.allocator_), + ownAllocator_(rhs.ownAllocator_), + stack_(std::move(rhs.stack_)), + parseResult_(rhs.parseResult_) + { + rhs.allocator_ = 0; + rhs.ownAllocator_ = 0; + rhs.parseResult_ = ParseResult(); + } #endif - ~GenericDocument() { - Destroy(); - } + ~GenericDocument() + { + Destroy(); + } #if RAPIDJSON_HAS_CXX11_RVALUE_REFS - //! Move assignment in C++11 - GenericDocument& operator=(GenericDocument&& rhs) RAPIDJSON_NOEXCEPT - { - // The cast to ValueType is necessary here, because otherwise it would - // attempt to call GenericValue's templated assignment operator. - ValueType::operator=(std::forward(rhs)); + //! Move assignment in C++11 + GenericDocument & operator=(GenericDocument && rhs) RAPIDJSON_NOEXCEPT + { + // The cast to ValueType is necessary here, because otherwise it would + // attempt to call GenericValue's templated assignment operator. + ValueType::operator=(std::forward(rhs)); - // Calling the destructor here would prematurely call stack_'s destructor - Destroy(); + // Calling the destructor here would prematurely call stack_'s destructor + Destroy(); - allocator_ = rhs.allocator_; - ownAllocator_ = rhs.ownAllocator_; - stack_ = std::move(rhs.stack_); - parseResult_ = rhs.parseResult_; + allocator_ = rhs.allocator_; + ownAllocator_ = rhs.ownAllocator_; + stack_ = std::move(rhs.stack_); + parseResult_ = rhs.parseResult_; - rhs.allocator_ = 0; - rhs.ownAllocator_ = 0; - rhs.parseResult_ = ParseResult(); + rhs.allocator_ = 0; + rhs.ownAllocator_ = 0; + rhs.parseResult_ = ParseResult(); - return *this; - } + return *this; + } #endif - //! Exchange the contents of this document with those of another. - /*! - \param rhs Another document. - \note Constant complexity. - \see GenericValue::Swap - */ - GenericDocument& Swap(GenericDocument& rhs) RAPIDJSON_NOEXCEPT { - ValueType::Swap(rhs); - stack_.Swap(rhs.stack_); - internal::Swap(allocator_, rhs.allocator_); - internal::Swap(ownAllocator_, rhs.ownAllocator_); - internal::Swap(parseResult_, rhs.parseResult_); - return *this; - } + //! Exchange the contents of this document with those of another. + /*! + \param rhs Another document. + \note Constant complexity. + \see GenericValue::Swap + */ + GenericDocument & Swap(GenericDocument & rhs) RAPIDJSON_NOEXCEPT + { + ValueType::Swap(rhs); + stack_.Swap(rhs.stack_); + internal::Swap(allocator_, rhs.allocator_); + internal::Swap(ownAllocator_, rhs.ownAllocator_); + internal::Swap(parseResult_, rhs.parseResult_); + return *this; + } - //! free-standing swap function helper - /*! - Helper function to enable support for common swap implementation pattern based on \c std::swap: - \code - void swap(MyClass& a, MyClass& b) { - using std::swap; - swap(a.doc, b.doc); - // ... - } - \endcode - \see Swap() - */ - friend inline void swap(GenericDocument& a, GenericDocument& b) RAPIDJSON_NOEXCEPT { a.Swap(b); } + //! free-standing swap function helper + /*! + Helper function to enable support for common swap implementation pattern based on \c std::swap: + \code + void swap(MyClass& a, MyClass& b) { + using std::swap; + swap(a.doc, b.doc); + // ... + } + \endcode + \see Swap() + */ + friend inline void swap(GenericDocument & a, GenericDocument & b) RAPIDJSON_NOEXCEPT { a.Swap(b); } - //! Populate this document by a generator which produces SAX events. - /*! \tparam Generator A functor with bool f(Handler) prototype. - \param g Generator functor which sends SAX events to the parameter. - \return The document itself for fluent API. - */ - template - GenericDocument& Populate(Generator& g) { - ClearStackOnExit scope(*this); - if (g(*this)) { - RAPIDJSON_ASSERT(stack_.GetSize() == sizeof(ValueType)); // Got one and only one root object - ValueType::operator=(*stack_.template Pop(1));// Move value from stack to document - } - return *this; - } + //! Populate this document by a generator which produces SAX events. + /*! \tparam Generator A functor with bool f(Handler) prototype. + \param g Generator functor which sends SAX events to the parameter. + \return The document itself for fluent API. + */ + template + GenericDocument & Populate(Generator & g) + { + ClearStackOnExit scope(*this); + if(g(*this)) + { + RAPIDJSON_ASSERT(stack_.GetSize() == sizeof(ValueType)); // Got one and only one root object + ValueType::operator=(*stack_.template Pop(1));// Move value from stack to document + } + return *this; + } - //!@name Parse from stream - //!@{ + //!@name Parse from stream + //!@{ - //! Parse JSON text from an input stream (with Encoding conversion) - /*! \tparam parseFlags Combination of \ref ParseFlag. - \tparam SourceEncoding Encoding of input stream - \tparam InputStream Type of input stream, implementing Stream concept - \param is Input stream to be parsed. - \return The document itself for fluent API. - */ - template - GenericDocument& ParseStream(InputStream& is) { - GenericReader reader( - stack_.HasAllocator() ? &stack_.GetAllocator() : 0); - ClearStackOnExit scope(*this); - parseResult_ = reader.template Parse(is, *this); - if (parseResult_) { - RAPIDJSON_ASSERT(stack_.GetSize() == sizeof(ValueType)); // Got one and only one root object - ValueType::operator=(*stack_.template Pop(1));// Move value from stack to document - } - return *this; - } + //! Parse JSON text from an input stream (with Encoding conversion) + /*! \tparam parseFlags Combination of \ref ParseFlag. + \tparam SourceEncoding Encoding of input stream + \tparam InputStream Type of input stream, implementing Stream concept + \param is Input stream to be parsed. + \return The document itself for fluent API. + */ + template + GenericDocument & ParseStream(InputStream & is) + { + GenericReader reader( + stack_.HasAllocator() ? &stack_.GetAllocator() : 0); + ClearStackOnExit scope(*this); + parseResult_ = reader.template Parse(is, *this); + if(parseResult_) + { + RAPIDJSON_ASSERT(stack_.GetSize() == sizeof(ValueType)); // Got one and only one root object + ValueType::operator=(*stack_.template Pop(1));// Move value from stack to document + } + return *this; + } - //! Parse JSON text from an input stream - /*! \tparam parseFlags Combination of \ref ParseFlag. - \tparam InputStream Type of input stream, implementing Stream concept - \param is Input stream to be parsed. - \return The document itself for fluent API. - */ - template - GenericDocument& ParseStream(InputStream& is) { - return ParseStream(is); - } + //! Parse JSON text from an input stream + /*! \tparam parseFlags Combination of \ref ParseFlag. + \tparam InputStream Type of input stream, implementing Stream concept + \param is Input stream to be parsed. + \return The document itself for fluent API. + */ + template + GenericDocument & ParseStream(InputStream & is) + { + return ParseStream(is); + } - //! Parse JSON text from an input stream (with \ref kParseDefaultFlags) - /*! \tparam InputStream Type of input stream, implementing Stream concept - \param is Input stream to be parsed. - \return The document itself for fluent API. - */ - template - GenericDocument& ParseStream(InputStream& is) { - return ParseStream(is); - } - //!@} + //! Parse JSON text from an input stream (with \ref kParseDefaultFlags) + /*! \tparam InputStream Type of input stream, implementing Stream concept + \param is Input stream to be parsed. + \return The document itself for fluent API. + */ + template + GenericDocument & ParseStream(InputStream & is) + { + return ParseStream(is); + } + //!@} - //!@name Parse in-place from mutable string - //!@{ + //!@name Parse in-place from mutable string + //!@{ - //! Parse JSON text from a mutable string - /*! \tparam parseFlags Combination of \ref ParseFlag. - \param str Mutable zero-terminated string to be parsed. - \return The document itself for fluent API. - */ - template - GenericDocument& ParseInsitu(Ch* str) { - GenericInsituStringStream s(str); - return ParseStream(s); - } + //! Parse JSON text from a mutable string + /*! \tparam parseFlags Combination of \ref ParseFlag. + \param str Mutable zero-terminated string to be parsed. + \return The document itself for fluent API. + */ + template + GenericDocument & ParseInsitu(Ch* str) + { + GenericInsituStringStream s(str); + return ParseStream < parseFlags | kParseInsituFlag > (s); + } - //! Parse JSON text from a mutable string (with \ref kParseDefaultFlags) - /*! \param str Mutable zero-terminated string to be parsed. - \return The document itself for fluent API. - */ - GenericDocument& ParseInsitu(Ch* str) { - return ParseInsitu(str); - } - //!@} + //! Parse JSON text from a mutable string (with \ref kParseDefaultFlags) + /*! \param str Mutable zero-terminated string to be parsed. + \return The document itself for fluent API. + */ + GenericDocument & ParseInsitu(Ch* str) + { + return ParseInsitu(str); + } + //!@} - //!@name Parse from read-only string - //!@{ + //!@name Parse from read-only string + //!@{ - //! Parse JSON text from a read-only string (with Encoding conversion) - /*! \tparam parseFlags Combination of \ref ParseFlag (must not contain \ref kParseInsituFlag). - \tparam SourceEncoding Transcoding from input Encoding - \param str Read-only zero-terminated string to be parsed. - */ - template - GenericDocument& Parse(const typename SourceEncoding::Ch* str) { - RAPIDJSON_ASSERT(!(parseFlags & kParseInsituFlag)); - GenericStringStream s(str); - return ParseStream(s); - } + //! Parse JSON text from a read-only string (with Encoding conversion) + /*! \tparam parseFlags Combination of \ref ParseFlag (must not contain \ref kParseInsituFlag). + \tparam SourceEncoding Transcoding from input Encoding + \param str Read-only zero-terminated string to be parsed. + */ + template + GenericDocument & Parse(const typename SourceEncoding::Ch* str) + { + RAPIDJSON_ASSERT(!(parseFlags & kParseInsituFlag)); + GenericStringStream s(str); + return ParseStream(s); + } - //! Parse JSON text from a read-only string - /*! \tparam parseFlags Combination of \ref ParseFlag (must not contain \ref kParseInsituFlag). - \param str Read-only zero-terminated string to be parsed. - */ - template - GenericDocument& Parse(const Ch* str) { - return Parse(str); - } + //! Parse JSON text from a read-only string + /*! \tparam parseFlags Combination of \ref ParseFlag (must not contain \ref kParseInsituFlag). + \param str Read-only zero-terminated string to be parsed. + */ + template + GenericDocument & Parse(const Ch* str) + { + return Parse(str); + } - //! Parse JSON text from a read-only string (with \ref kParseDefaultFlags) - /*! \param str Read-only zero-terminated string to be parsed. - */ - GenericDocument& Parse(const Ch* str) { - return Parse(str); - } + //! Parse JSON text from a read-only string (with \ref kParseDefaultFlags) + /*! \param str Read-only zero-terminated string to be parsed. + */ + GenericDocument & Parse(const Ch* str) + { + return Parse(str); + } - template - GenericDocument& Parse(const typename SourceEncoding::Ch* str, size_t length) { - RAPIDJSON_ASSERT(!(parseFlags & kParseInsituFlag)); - MemoryStream ms(static_cast(str), length * sizeof(typename SourceEncoding::Ch)); - EncodedInputStream is(ms); - ParseStream(is); - return *this; - } + template + GenericDocument & Parse(const typename SourceEncoding::Ch* str, size_t length) + { + RAPIDJSON_ASSERT(!(parseFlags & kParseInsituFlag)); + MemoryStream ms(static_cast(str), length * sizeof(typename SourceEncoding::Ch)); + EncodedInputStream is(ms); + ParseStream(is); + return *this; + } - template - GenericDocument& Parse(const Ch* str, size_t length) { - return Parse(str, length); - } - - GenericDocument& Parse(const Ch* str, size_t length) { - return Parse(str, length); - } + template + GenericDocument & Parse(const Ch* str, size_t length) + { + return Parse(str, length); + } + + GenericDocument & Parse(const Ch* str, size_t length) + { + return Parse(str, length); + } #if RAPIDJSON_HAS_STDSTRING - template - GenericDocument& Parse(const std::basic_string& str) { - // c_str() is constant complexity according to standard. Should be faster than Parse(const char*, size_t) - return Parse(str.c_str()); - } + template + GenericDocument & Parse(const std::basic_string & str) + { + // c_str() is constant complexity according to standard. Should be faster than Parse(const char*, size_t) + return Parse(str.c_str()); + } - template - GenericDocument& Parse(const std::basic_string& str) { - return Parse(str.c_str()); - } + template + GenericDocument & Parse(const std::basic_string & str) + { + return Parse(str.c_str()); + } - GenericDocument& Parse(const std::basic_string& str) { - return Parse(str); - } + GenericDocument & Parse(const std::basic_string & str) + { + return Parse(str); + } #endif // RAPIDJSON_HAS_STDSTRING - //!@} + //!@} - //!@name Handling parse errors - //!@{ + //!@name Handling parse errors + //!@{ - //! Whether a parse error has occured in the last parsing. - bool HasParseError() const { return parseResult_.IsError(); } + //! Whether a parse error has occured in the last parsing. + bool HasParseError() const + { + return parseResult_.IsError(); + } - //! Get the \ref ParseErrorCode of last parsing. - ParseErrorCode GetParseError() const { return parseResult_.Code(); } + //! Get the \ref ParseErrorCode of last parsing. + ParseErrorCode GetParseError() const + { + return parseResult_.Code(); + } - //! Get the position of last parsing error in input, 0 otherwise. - size_t GetErrorOffset() const { return parseResult_.Offset(); } + //! Get the position of last parsing error in input, 0 otherwise. + size_t GetErrorOffset() const + { + return parseResult_.Offset(); + } - //! Implicit conversion to get the last parse result + //! Implicit conversion to get the last parse result #ifndef __clang // -Wdocumentation - /*! \return \ref ParseResult of the last parse operation + /*! \return \ref ParseResult of the last parse operation - \code - Document doc; - ParseResult ok = doc.Parse(json); - if (!ok) - printf( "JSON parse error: %s (%u)\n", GetParseError_En(ok.Code()), ok.Offset()); - \endcode - */ + \code + Document doc; + ParseResult ok = doc.Parse(json); + if (!ok) + printf( "JSON parse error: %s (%u)\n", GetParseError_En(ok.Code()), ok.Offset()); + \endcode + */ #endif - operator ParseResult() const { return parseResult_; } - //!@} + operator ParseResult() const + { + return parseResult_; + } + //!@} - //! Get the allocator of this document. - Allocator& GetAllocator() { - RAPIDJSON_ASSERT(allocator_); - return *allocator_; - } + //! Get the allocator of this document. + Allocator & GetAllocator() + { + RAPIDJSON_ASSERT(allocator_); + return *allocator_; + } - //! Get the capacity of stack in bytes. - size_t GetStackCapacity() const { return stack_.GetCapacity(); } + //! Get the capacity of stack in bytes. + size_t GetStackCapacity() const + { + return stack_.GetCapacity(); + } private: - // clear stack on any exit from ParseStream, e.g. due to exception - struct ClearStackOnExit { - explicit ClearStackOnExit(GenericDocument& d) : d_(d) {} - ~ClearStackOnExit() { d_.ClearStack(); } - private: - ClearStackOnExit(const ClearStackOnExit&); - ClearStackOnExit& operator=(const ClearStackOnExit&); - GenericDocument& d_; - }; + // clear stack on any exit from ParseStream, e.g. due to exception + struct ClearStackOnExit + { + explicit ClearStackOnExit(GenericDocument & d) : d_(d) {} + ~ClearStackOnExit() + { + d_.ClearStack(); + } + private: + ClearStackOnExit(const ClearStackOnExit &); + ClearStackOnExit & operator=(const ClearStackOnExit &); + GenericDocument & d_; + }; - // callers of the following private Handler functions - // template friend class GenericReader; // for parsing - template friend class GenericValue; // for deep copying + // callers of the following private Handler functions + // template friend class GenericReader; // for parsing + template friend class GenericValue; // for deep copying public: - // Implementation of Handler - bool Null() { new (stack_.template Push()) ValueType(); return true; } - bool Bool(bool b) { new (stack_.template Push()) ValueType(b); return true; } - bool Int(int i) { new (stack_.template Push()) ValueType(i); return true; } - bool Uint(unsigned i) { new (stack_.template Push()) ValueType(i); return true; } - bool Int64(int64_t i) { new (stack_.template Push()) ValueType(i); return true; } - bool Uint64(uint64_t i) { new (stack_.template Push()) ValueType(i); return true; } - bool Double(double d) { new (stack_.template Push()) ValueType(d); return true; } + // Implementation of Handler + bool Null() + { + new(stack_.template Push()) ValueType(); + return true; + } + bool Bool(bool b) + { + new(stack_.template Push()) ValueType(b); + return true; + } + bool Int(int i) + { + new(stack_.template Push()) ValueType(i); + return true; + } + bool Uint(unsigned i) + { + new(stack_.template Push()) ValueType(i); + return true; + } + bool Int64(int64_t i) + { + new(stack_.template Push()) ValueType(i); + return true; + } + bool Uint64(uint64_t i) + { + new(stack_.template Push()) ValueType(i); + return true; + } + bool Double(double d) + { + new(stack_.template Push()) ValueType(d); + return true; + } - bool RawNumber(const Ch* str, SizeType length, bool copy) { - if (copy) - new (stack_.template Push()) ValueType(str, length, GetAllocator()); - else - new (stack_.template Push()) ValueType(str, length); - return true; - } + bool RawNumber(const Ch* str, SizeType length, bool copy) + { + if(copy) + { + new(stack_.template Push()) ValueType(str, length, GetAllocator()); + } + else + { + new(stack_.template Push()) ValueType(str, length); + } + return true; + } - bool String(const Ch* str, SizeType length, bool copy) { - if (copy) - new (stack_.template Push()) ValueType(str, length, GetAllocator()); - else - new (stack_.template Push()) ValueType(str, length); - return true; - } + bool String(const Ch* str, SizeType length, bool copy) + { + if(copy) + { + new(stack_.template Push()) ValueType(str, length, GetAllocator()); + } + else + { + new(stack_.template Push()) ValueType(str, length); + } + return true; + } - bool StartObject() { new (stack_.template Push()) ValueType(kObjectType); return true; } - - bool Key(const Ch* str, SizeType length, bool copy) { return String(str, length, copy); } + bool StartObject() + { + new(stack_.template Push()) ValueType(kObjectType); + return true; + } - bool EndObject(SizeType memberCount) { - typename ValueType::Member* members = stack_.template Pop(memberCount); - stack_.template Top()->SetObjectRaw(members, memberCount, GetAllocator()); - return true; - } + bool Key(const Ch* str, SizeType length, bool copy) + { + return String(str, length, copy); + } - bool StartArray() { new (stack_.template Push()) ValueType(kArrayType); return true; } - - bool EndArray(SizeType elementCount) { - ValueType* elements = stack_.template Pop(elementCount); - stack_.template Top()->SetArrayRaw(elements, elementCount, GetAllocator()); - return true; - } + bool EndObject(SizeType memberCount) + { + typename ValueType::Member* members = stack_.template Pop(memberCount); + stack_.template Top()->SetObjectRaw(members, memberCount, GetAllocator()); + return true; + } + + bool StartArray() + { + new(stack_.template Push()) ValueType(kArrayType); + return true; + } + + bool EndArray(SizeType elementCount) + { + ValueType* elements = stack_.template Pop(elementCount); + stack_.template Top()->SetArrayRaw(elements, elementCount, GetAllocator()); + return true; + } private: - //! Prohibit copying - GenericDocument(const GenericDocument&); - //! Prohibit assignment - GenericDocument& operator=(const GenericDocument&); + //! Prohibit copying + GenericDocument(const GenericDocument &); + //! Prohibit assignment + GenericDocument & operator=(const GenericDocument &); - void ClearStack() { - if (Allocator::kNeedFree) - while (stack_.GetSize() > 0) // Here assumes all elements in stack array are GenericValue (Member is actually 2 GenericValue objects) - (stack_.template Pop(1))->~ValueType(); - else - stack_.Clear(); - stack_.ShrinkToFit(); - } + void ClearStack() + { + if(Allocator::kNeedFree) + while(stack_.GetSize() > + 0) // Here assumes all elements in stack array are GenericValue (Member is actually 2 GenericValue objects) + { + (stack_.template Pop(1))->~ValueType(); + } + else + { + stack_.Clear(); + } + stack_.ShrinkToFit(); + } - void Destroy() { - RAPIDJSON_DELETE(ownAllocator_); - } + void Destroy() + { + RAPIDJSON_DELETE(ownAllocator_); + } - static const size_t kDefaultStackCapacity = 1024; - Allocator* allocator_; - Allocator* ownAllocator_; - internal::Stack stack_; - ParseResult parseResult_; + static const size_t kDefaultStackCapacity = 1024; + Allocator* allocator_; + Allocator* ownAllocator_; + internal::Stack stack_; + ParseResult parseResult_; }; //! GenericDocument with UTF8 encoding -typedef GenericDocument > Document; +typedef GenericDocument> Document; // defined here due to the dependency on GenericDocument template template inline -GenericValue::GenericValue(const GenericValue& rhs, Allocator& allocator) +GenericValue::GenericValue(const GenericValue & rhs, + Allocator & allocator) { - switch (rhs.GetType()) { - case kObjectType: - case kArrayType: { // perform deep copy via SAX Handler - GenericDocument d(&allocator); - rhs.Accept(d); - RawAssign(*d.stack_.template Pop(1)); - } - break; - case kStringType: - if (rhs.data_.f.flags == kConstStringFlag) { - data_.f.flags = rhs.data_.f.flags; - data_ = *reinterpret_cast(&rhs.data_); - } else { - SetStringRaw(StringRef(rhs.GetString(), rhs.GetStringLength()), allocator); - } - break; - default: - data_.f.flags = rhs.data_.f.flags; - data_ = *reinterpret_cast(&rhs.data_); - break; - } + switch(rhs.GetType()) + { + case kObjectType: + case kArrayType: // perform deep copy via SAX Handler + { + GenericDocument d(&allocator); + rhs.Accept(d); + RawAssign(*d.stack_.template Pop(1)); + } + break; + case kStringType: + if(rhs.data_.f.flags == kConstStringFlag) + { + data_.f.flags = rhs.data_.f.flags; + data_ = *reinterpret_cast(&rhs.data_); + } + else + { + SetStringRaw(StringRef(rhs.GetString(), rhs.GetStringLength()), allocator); + } + break; + default: + data_.f.flags = rhs.data_.f.flags; + data_ = *reinterpret_cast(&rhs.data_); + break; + } } //! Helper class for accessing Value of array type. @@ -2436,51 +3376,115 @@ GenericValue::GenericValue(const GenericValue -class GenericArray { +class GenericArray +{ public: - typedef GenericArray ConstArray; - typedef GenericArray Array; - typedef ValueT PlainType; - typedef typename internal::MaybeAddConst::Type ValueType; - typedef ValueType* ValueIterator; // This may be const or non-const iterator - typedef const ValueT* ConstValueIterator; - typedef typename ValueType::AllocatorType AllocatorType; - typedef typename ValueType::StringRefType StringRefType; + typedef GenericArray ConstArray; + typedef GenericArray Array; + typedef ValueT PlainType; + typedef typename internal::MaybeAddConst::Type ValueType; + typedef ValueType* ValueIterator; // This may be const or non-const iterator + typedef const ValueT* ConstValueIterator; + typedef typename ValueType::AllocatorType AllocatorType; + typedef typename ValueType::StringRefType StringRefType; - template - friend class GenericValue; + template + friend class GenericValue; - GenericArray(const GenericArray& rhs) : value_(rhs.value_) {} - GenericArray& operator=(const GenericArray& rhs) { value_ = rhs.value_; return *this; } - ~GenericArray() {} + GenericArray(const GenericArray & rhs) : value_(rhs.value_) {} + GenericArray & operator=(const GenericArray & rhs) + { + value_ = rhs.value_; + return *this; + } + ~GenericArray() {} - SizeType Size() const { return value_.Size(); } - SizeType Capacity() const { return value_.Capacity(); } - bool Empty() const { return value_.Empty(); } - void Clear() const { value_.Clear(); } - ValueType& operator[](SizeType index) const { return value_[index]; } - ValueIterator Begin() const { return value_.Begin(); } - ValueIterator End() const { return value_.End(); } - GenericArray Reserve(SizeType newCapacity, AllocatorType &allocator) const { value_.Reserve(newCapacity, allocator); return *this; } - GenericArray PushBack(ValueType& value, AllocatorType& allocator) const { value_.PushBack(value, allocator); return *this; } + SizeType Size() const + { + return value_.Size(); + } + SizeType Capacity() const + { + return value_.Capacity(); + } + bool Empty() const + { + return value_.Empty(); + } + void Clear() const + { + value_.Clear(); + } + ValueType & operator[](SizeType index) const + { + return value_[index]; + } + ValueIterator Begin() const + { + return value_.Begin(); + } + ValueIterator End() const + { + return value_.End(); + } + GenericArray Reserve(SizeType newCapacity, AllocatorType & allocator) const + { + value_.Reserve(newCapacity, allocator); + return *this; + } + GenericArray PushBack(ValueType & value, AllocatorType & allocator) const + { + value_.PushBack(value, allocator); + return *this; + } #if RAPIDJSON_HAS_CXX11_RVALUE_REFS - GenericArray PushBack(ValueType&& value, AllocatorType& allocator) const { value_.PushBack(value, allocator); return *this; } + GenericArray PushBack(ValueType && value, AllocatorType & allocator) const + { + value_.PushBack(value, allocator); + return *this; + } #endif // RAPIDJSON_HAS_CXX11_RVALUE_REFS - GenericArray PushBack(StringRefType value, AllocatorType& allocator) const { value_.PushBack(value, allocator); return *this; } - template RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr, internal::IsGenericValue >), (const GenericArray&)) PushBack(T value, AllocatorType& allocator) const { value_.PushBack(value, allocator); return *this; } - GenericArray PopBack() const { value_.PopBack(); return *this; } - ValueIterator Erase(ConstValueIterator pos) const { return value_.Erase(pos); } - ValueIterator Erase(ConstValueIterator first, ConstValueIterator last) const { return value_.Erase(first, last); } + GenericArray PushBack(StringRefType value, AllocatorType & allocator) const + { + value_.PushBack(value, allocator); + return *this; + } + template RAPIDJSON_DISABLEIF_RETURN(( + internal::OrExpr, internal::IsGenericValue>), + (const GenericArray &)) PushBack(T value, AllocatorType & allocator) const + { + value_.PushBack(value, allocator); + return *this; + } + GenericArray PopBack() const + { + value_.PopBack(); + return *this; + } + ValueIterator Erase(ConstValueIterator pos) const + { + return value_.Erase(pos); + } + ValueIterator Erase(ConstValueIterator first, ConstValueIterator last) const + { + return value_.Erase(first, last); + } #if RAPIDJSON_HAS_CXX11_RANGE_FOR - ValueIterator begin() const { return value_.Begin(); } - ValueIterator end() const { return value_.End(); } + ValueIterator begin() const + { + return value_.Begin(); + } + ValueIterator end() const + { + return value_.End(); + } #endif private: - GenericArray(); - GenericArray(ValueType& value) : value_(value) {} - ValueType& value_; + GenericArray(); + GenericArray(ValueType & value) : value_(value) {} + ValueType & value_; }; //! Helper class for accessing Value of object type. @@ -2489,84 +3493,219 @@ private: In addition to all APIs for array type, it provides range-based for loop if \c RAPIDJSON_HAS_CXX11_RANGE_FOR=1. */ template -class GenericObject { +class GenericObject +{ public: - typedef GenericObject ConstObject; - typedef GenericObject Object; - typedef ValueT PlainType; - typedef typename internal::MaybeAddConst::Type ValueType; - typedef GenericMemberIterator MemberIterator; // This may be const or non-const iterator - typedef GenericMemberIterator ConstMemberIterator; - typedef typename ValueType::AllocatorType AllocatorType; - typedef typename ValueType::StringRefType StringRefType; - typedef typename ValueType::EncodingType EncodingType; - typedef typename ValueType::Ch Ch; + typedef GenericObject ConstObject; + typedef GenericObject Object; + typedef ValueT PlainType; + typedef typename internal::MaybeAddConst::Type ValueType; + typedef GenericMemberIterator + MemberIterator; // This may be const or non-const iterator + typedef GenericMemberIterator + ConstMemberIterator; + typedef typename ValueType::AllocatorType AllocatorType; + typedef typename ValueType::StringRefType StringRefType; + typedef typename ValueType::EncodingType EncodingType; + typedef typename ValueType::Ch Ch; - template - friend class GenericValue; + template + friend class GenericValue; - GenericObject(const GenericObject& rhs) : value_(rhs.value_) {} - GenericObject& operator=(const GenericObject& rhs) { value_ = rhs.value_; return *this; } - ~GenericObject() {} + GenericObject(const GenericObject & rhs) : value_(rhs.value_) {} + GenericObject & operator=(const GenericObject & rhs) + { + value_ = rhs.value_; + return *this; + } + ~GenericObject() {} - SizeType MemberCount() const { return value_.MemberCount(); } - bool ObjectEmpty() const { return value_.ObjectEmpty(); } - template ValueType& operator[](T* name) const { return value_[name]; } - template ValueType& operator[](const GenericValue& name) const { return value_[name]; } + SizeType MemberCount() const + { + return value_.MemberCount(); + } + bool ObjectEmpty() const + { + return value_.ObjectEmpty(); + } + template ValueType & operator[](T* name) const + { + return value_[name]; + } + template ValueType & operator[](const GenericValue & + name) const + { + return value_[name]; + } #if RAPIDJSON_HAS_STDSTRING - ValueType& operator[](const std::basic_string& name) const { return value_[name]; } + ValueType & operator[](const std::basic_string & name) const + { + return value_[name]; + } #endif - MemberIterator MemberBegin() const { return value_.MemberBegin(); } - MemberIterator MemberEnd() const { return value_.MemberEnd(); } - bool HasMember(const Ch* name) const { return value_.HasMember(name); } + MemberIterator MemberBegin() const + { + return value_.MemberBegin(); + } + MemberIterator MemberEnd() const + { + return value_.MemberEnd(); + } + bool HasMember(const Ch* name) const + { + return value_.HasMember(name); + } #if RAPIDJSON_HAS_STDSTRING - bool HasMember(const std::basic_string& name) const { return value_.HasMember(name); } + bool HasMember(const std::basic_string & name) const + { + return value_.HasMember(name); + } #endif - template bool HasMember(const GenericValue& name) const { return value_.HasMember(name); } - MemberIterator FindMember(const Ch* name) const { return value_.FindMember(name); } - template MemberIterator FindMember(const GenericValue& name) const { return value_.FindMember(name); } + template bool HasMember(const GenericValue & name) + const + { + return value_.HasMember(name); + } + MemberIterator FindMember(const Ch* name) const + { + return value_.FindMember(name); + } + template MemberIterator FindMember(const + GenericValue & name) const + { + return value_.FindMember(name); + } #if RAPIDJSON_HAS_STDSTRING - MemberIterator FindMember(const std::basic_string& name) const { return value_.FindMember(name); } + MemberIterator FindMember(const std::basic_string & name) const + { + return value_.FindMember(name); + } #endif - GenericObject AddMember(ValueType& name, ValueType& value, AllocatorType& allocator) const { value_.AddMember(name, value, allocator); return *this; } - GenericObject AddMember(ValueType& name, StringRefType value, AllocatorType& allocator) const { value_.AddMember(name, value, allocator); return *this; } + GenericObject AddMember(ValueType & name, ValueType & value, AllocatorType & allocator) const + { + value_.AddMember(name, value, allocator); + return *this; + } + GenericObject AddMember(ValueType & name, StringRefType value, AllocatorType & allocator) const + { + value_.AddMember(name, value, allocator); + return *this; + } #if RAPIDJSON_HAS_STDSTRING - GenericObject AddMember(ValueType& name, std::basic_string& value, AllocatorType& allocator) const { value_.AddMember(name, value, allocator); return *this; } + GenericObject AddMember(ValueType & name, std::basic_string & value, AllocatorType & allocator) const + { + value_.AddMember(name, value, allocator); + return *this; + } #endif - template RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr, internal::IsGenericValue >), (ValueType&)) AddMember(ValueType& name, T value, AllocatorType& allocator) const { value_.AddMember(name, value, allocator); return *this; } + template RAPIDJSON_DISABLEIF_RETURN(( + internal::OrExpr, internal::IsGenericValue>), + (ValueType &)) AddMember(ValueType & name, T value, AllocatorType & allocator) const + { + value_.AddMember(name, value, allocator); + return *this; + } #if RAPIDJSON_HAS_CXX11_RVALUE_REFS - GenericObject AddMember(ValueType&& name, ValueType&& value, AllocatorType& allocator) const { value_.AddMember(name, value, allocator); return *this; } - GenericObject AddMember(ValueType&& name, ValueType& value, AllocatorType& allocator) const { value_.AddMember(name, value, allocator); return *this; } - GenericObject AddMember(ValueType& name, ValueType&& value, AllocatorType& allocator) const { value_.AddMember(name, value, allocator); return *this; } - GenericObject AddMember(StringRefType name, ValueType&& value, AllocatorType& allocator) const { value_.AddMember(name, value, allocator); return *this; } + GenericObject AddMember(ValueType && name, ValueType && value, AllocatorType & allocator) const + { + value_.AddMember(name, value, allocator); + return *this; + } + GenericObject AddMember(ValueType && name, ValueType & value, AllocatorType & allocator) const + { + value_.AddMember(name, value, allocator); + return *this; + } + GenericObject AddMember(ValueType & name, ValueType && value, AllocatorType & allocator) const + { + value_.AddMember(name, value, allocator); + return *this; + } + GenericObject AddMember(StringRefType name, ValueType && value, AllocatorType & allocator) const + { + value_.AddMember(name, value, allocator); + return *this; + } #endif // RAPIDJSON_HAS_CXX11_RVALUE_REFS - GenericObject AddMember(StringRefType name, ValueType& value, AllocatorType& allocator) const { value_.AddMember(name, value, allocator); return *this; } - GenericObject AddMember(StringRefType name, StringRefType value, AllocatorType& allocator) const { value_.AddMember(name, value, allocator); return *this; } - template RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr, internal::IsGenericValue >), (GenericObject)) AddMember(StringRefType name, T value, AllocatorType& allocator) const { value_.AddMember(name, value, allocator); return *this; } - void RemoveAllMembers() { return value_.RemoveAllMembers(); } - bool RemoveMember(const Ch* name) const { return value_.RemoveMember(name); } + GenericObject AddMember(StringRefType name, ValueType & value, AllocatorType & allocator) const + { + value_.AddMember(name, value, allocator); + return *this; + } + GenericObject AddMember(StringRefType name, StringRefType value, AllocatorType & allocator) const + { + value_.AddMember(name, value, allocator); + return *this; + } + template RAPIDJSON_DISABLEIF_RETURN(( + internal::OrExpr, internal::IsGenericValue>), + (GenericObject)) AddMember(StringRefType name, T value, AllocatorType & allocator) const + { + value_.AddMember(name, value, allocator); + return *this; + } + void RemoveAllMembers() + { + return value_.RemoveAllMembers(); + } + bool RemoveMember(const Ch* name) const + { + return value_.RemoveMember(name); + } #if RAPIDJSON_HAS_STDSTRING - bool RemoveMember(const std::basic_string& name) const { return value_.RemoveMember(name); } + bool RemoveMember(const std::basic_string & name) const + { + return value_.RemoveMember(name); + } #endif - template bool RemoveMember(const GenericValue& name) const { return value_.RemoveMember(name); } - MemberIterator RemoveMember(MemberIterator m) const { return value_.RemoveMember(m); } - MemberIterator EraseMember(ConstMemberIterator pos) const { return value_.EraseMember(pos); } - MemberIterator EraseMember(ConstMemberIterator first, ConstMemberIterator last) const { return value_.EraseMember(first, last); } - bool EraseMember(const Ch* name) const { return value_.EraseMember(name); } + template bool RemoveMember(const GenericValue & name) + const + { + return value_.RemoveMember(name); + } + MemberIterator RemoveMember(MemberIterator m) const + { + return value_.RemoveMember(m); + } + MemberIterator EraseMember(ConstMemberIterator pos) const + { + return value_.EraseMember(pos); + } + MemberIterator EraseMember(ConstMemberIterator first, ConstMemberIterator last) const + { + return value_.EraseMember(first, last); + } + bool EraseMember(const Ch* name) const + { + return value_.EraseMember(name); + } #if RAPIDJSON_HAS_STDSTRING - bool EraseMember(const std::basic_string& name) const { return EraseMember(ValueType(StringRef(name))); } + bool EraseMember(const std::basic_string & name) const + { + return EraseMember(ValueType(StringRef(name))); + } #endif - template bool EraseMember(const GenericValue& name) const { return value_.EraseMember(name); } + template bool EraseMember(const GenericValue & name) + const + { + return value_.EraseMember(name); + } #if RAPIDJSON_HAS_CXX11_RANGE_FOR - MemberIterator begin() const { return value_.MemberBegin(); } - MemberIterator end() const { return value_.MemberEnd(); } + MemberIterator begin() const + { + return value_.MemberBegin(); + } + MemberIterator end() const + { + return value_.MemberEnd(); + } #endif private: - GenericObject(); - GenericObject(ValueType& value) : value_(value) {} - ValueType& value_; + GenericObject(); + GenericObject(ValueType & value) : value_(value) {} + ValueType & value_; }; RAPIDJSON_NAMESPACE_END diff --git a/src/3rdparty/rapidjson/encodedstream.h b/src/3rdparty/rapidjson/encodedstream.h index 14506838..efdaeb27 100644 --- a/src/3rdparty/rapidjson/encodedstream.h +++ b/src/3rdparty/rapidjson/encodedstream.h @@ -1,5 +1,5 @@ // 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 @@ -7,9 +7,9 @@ // // 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 +// 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_ @@ -36,59 +36,112 @@ RAPIDJSON_NAMESPACE_BEGIN \tparam InputByteStream Type of input byte stream. For example, FileReadStream. */ template -class EncodedInputStream { - RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1); +class EncodedInputStream +{ + RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1); public: - typedef typename Encoding::Ch Ch; + typedef typename Encoding::Ch Ch; - EncodedInputStream(InputByteStream& is) : is_(is) { - current_ = Encoding::TakeBOM(is_); - } + 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(); } + 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; } + // 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&); + EncodedInputStream(const EncodedInputStream &); + EncodedInputStream & operator=(const EncodedInputStream &); - InputByteStream& is_; - Ch current_; + InputByteStream & is_; + Ch current_; }; //! Specialized for UTF8 MemoryStream. template <> -class EncodedInputStream, MemoryStream> { +class EncodedInputStream, MemoryStream> +{ public: - typedef UTF8<>::Ch Ch; + typedef UTF8<>::Ch Ch; - EncodedInputStream(MemoryStream& is) : is_(is) { - if (static_cast(is_.Peek()) == 0xEFu) is_.Take(); - if (static_cast(is_.Peek()) == 0xBBu) is_.Take(); - if (static_cast(is_.Peek()) == 0xBFu) is_.Take(); - } - Ch Peek() const { return is_.Peek(); } - Ch Take() { return is_.Take(); } - size_t Tell() const { return is_.Tell(); } + EncodedInputStream(MemoryStream & is) : is_(is) + { + if(static_cast(is_.Peek()) == 0xEFu) + { + is_.Take(); + } + if(static_cast(is_.Peek()) == 0xBBu) + { + is_.Take(); + } + if(static_cast(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; } + // Not implemented + void Put(Ch) {} + void Flush() {} + Ch* PutBegin() + { + return 0; + } + size_t PutEnd(Ch*) + { + return 0; + } - MemoryStream& is_; + MemoryStream & is_; private: - EncodedInputStream(const EncodedInputStream&); - EncodedInputStream& operator=(const EncodedInputStream&); + EncodedInputStream(const EncodedInputStream &); + EncodedInputStream & operator=(const EncodedInputStream &); }; //! Output byte stream wrapper with statically bound encoding. @@ -97,31 +150,61 @@ private: \tparam OutputByteStream Type of input byte stream. For example, FileWriteStream. */ template -class EncodedOutputStream { - RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1); +class EncodedOutputStream +{ + RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1); public: - typedef typename Encoding::Ch Ch; + typedef typename Encoding::Ch Ch; - EncodedOutputStream(OutputByteStream& os, bool putBOM = true) : os_(os) { - if (putBOM) - Encoding::PutBOM(os_); - } + 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(); } + 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; } + // 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&); + EncodedOutputStream(const EncodedOutputStream &); + EncodedOutputStream & operator=(const EncodedOutputStream &); - OutputByteStream& os_; + OutputByteStream & os_; }; #define RAPIDJSON_ENCODINGS_FUNC(x) UTF8::x, UTF16LE::x, UTF16BE::x, UTF32LE::x, UTF32BE::x @@ -132,96 +215,186 @@ private: \tparam InputByteStream type of input byte stream to be wrapped. */ template -class AutoUTFInputStream { - RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1); +class AutoUTFInputStream +{ + RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1); public: - typedef CharType Ch; + 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_); - } + //! 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_; } + 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(); } + 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; } + // 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&); + 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 + // 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(is_->Peek4()); - if (!c) - return; + const unsigned char* c = reinterpret_cast(is_->Peek4()); + if(!c) + { + return; + } - unsigned bom = static_cast(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(); } + unsigned bom = static_cast(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 + // 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. - } - } + 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); - } + // 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_; + 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. @@ -230,58 +403,98 @@ private: \tparam OutputByteStream type of output byte stream to be wrapped. */ template -class AutoUTFOutputStream { - RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1); +class AutoUTFOutputStream +{ + RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1); public: - typedef CharType Ch; + 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); + //! 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); + // 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_]; + static const PutFunc f[] = { RAPIDJSON_ENCODINGS_FUNC(Put) }; + putFunc_ = f[type_]; - if (putBOM) - PutBOM(); - } + if(putBOM) + { + PutBOM(); + } + } - UTFType GetType() const { return type_; } + UTFType GetType() const + { + return type_; + } - void Put(Ch c) { putFunc_(*os_, c); } - void Flush() { os_->Flush(); } + 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; } + // 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&); + AutoUTFOutputStream(const AutoUTFOutputStream &); + AutoUTFOutputStream & operator=(const AutoUTFOutputStream &); - void PutBOM() { - typedef void (*PutBOMFunc)(OutputByteStream&); - static const PutBOMFunc f[] = { RAPIDJSON_ENCODINGS_FUNC(PutBOM) }; - f[type_](*os_); - } + void PutBOM() + { + typedef void (*PutBOMFunc)(OutputByteStream &); + static const PutBOMFunc f[] = { RAPIDJSON_ENCODINGS_FUNC(PutBOM) }; + f[type_](*os_); + } - typedef void (*PutFunc)(OutputByteStream&, Ch); + typedef void (*PutFunc)(OutputByteStream &, Ch); - OutputByteStream* os_; - UTFType type_; - PutFunc putFunc_; + OutputByteStream* os_; + UTFType type_; + PutFunc putFunc_; }; #undef RAPIDJSON_ENCODINGS_FUNC diff --git a/src/3rdparty/rapidjson/encodings.h b/src/3rdparty/rapidjson/encodings.h index baa7c2b1..d9cebb91 100644 --- a/src/3rdparty/rapidjson/encodings.h +++ b/src/3rdparty/rapidjson/encodings.h @@ -1,5 +1,5 @@ // 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 @@ -7,9 +7,9 @@ // // 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 +// 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_ @@ -93,164 +93,258 @@ concept Encoding { \note implements Encoding concept */ template -struct UTF8 { - typedef CharType Ch; +struct UTF8 +{ + typedef CharType Ch; - enum { supportUnicode = 1 }; + enum { supportUnicode = 1 }; - template - static void Encode(OutputStream& os, unsigned codepoint) { - if (codepoint <= 0x7F) - os.Put(static_cast(codepoint & 0xFF)); - else if (codepoint <= 0x7FF) { - os.Put(static_cast(0xC0 | ((codepoint >> 6) & 0xFF))); - os.Put(static_cast(0x80 | ((codepoint & 0x3F)))); - } - else if (codepoint <= 0xFFFF) { - os.Put(static_cast(0xE0 | ((codepoint >> 12) & 0xFF))); - os.Put(static_cast(0x80 | ((codepoint >> 6) & 0x3F))); - os.Put(static_cast(0x80 | (codepoint & 0x3F))); - } - else { - RAPIDJSON_ASSERT(codepoint <= 0x10FFFF); - os.Put(static_cast(0xF0 | ((codepoint >> 18) & 0xFF))); - os.Put(static_cast(0x80 | ((codepoint >> 12) & 0x3F))); - os.Put(static_cast(0x80 | ((codepoint >> 6) & 0x3F))); - os.Put(static_cast(0x80 | (codepoint & 0x3F))); - } - } + template + static void Encode(OutputStream & os, unsigned codepoint) + { + if(codepoint <= 0x7F) + { + os.Put(static_cast(codepoint & 0xFF)); + } + else if(codepoint <= 0x7FF) + { + os.Put(static_cast(0xC0 | ((codepoint >> 6) & 0xFF))); + os.Put(static_cast(0x80 | ((codepoint & 0x3F)))); + } + else if(codepoint <= 0xFFFF) + { + os.Put(static_cast(0xE0 | ((codepoint >> 12) & 0xFF))); + os.Put(static_cast(0x80 | ((codepoint >> 6) & 0x3F))); + os.Put(static_cast(0x80 | (codepoint & 0x3F))); + } + else + { + RAPIDJSON_ASSERT(codepoint <= 0x10FFFF); + os.Put(static_cast(0xF0 | ((codepoint >> 18) & 0xFF))); + os.Put(static_cast(0x80 | ((codepoint >> 12) & 0x3F))); + os.Put(static_cast(0x80 | ((codepoint >> 6) & 0x3F))); + os.Put(static_cast(0x80 | (codepoint & 0x3F))); + } + } - template - static void EncodeUnsafe(OutputStream& os, unsigned codepoint) { - if (codepoint <= 0x7F) - PutUnsafe(os, static_cast(codepoint & 0xFF)); - else if (codepoint <= 0x7FF) { - PutUnsafe(os, static_cast(0xC0 | ((codepoint >> 6) & 0xFF))); - PutUnsafe(os, static_cast(0x80 | ((codepoint & 0x3F)))); - } - else if (codepoint <= 0xFFFF) { - PutUnsafe(os, static_cast(0xE0 | ((codepoint >> 12) & 0xFF))); - PutUnsafe(os, static_cast(0x80 | ((codepoint >> 6) & 0x3F))); - PutUnsafe(os, static_cast(0x80 | (codepoint & 0x3F))); - } - else { - RAPIDJSON_ASSERT(codepoint <= 0x10FFFF); - PutUnsafe(os, static_cast(0xF0 | ((codepoint >> 18) & 0xFF))); - PutUnsafe(os, static_cast(0x80 | ((codepoint >> 12) & 0x3F))); - PutUnsafe(os, static_cast(0x80 | ((codepoint >> 6) & 0x3F))); - PutUnsafe(os, static_cast(0x80 | (codepoint & 0x3F))); - } - } + template + static void EncodeUnsafe(OutputStream & os, unsigned codepoint) + { + if(codepoint <= 0x7F) + { + PutUnsafe(os, static_cast(codepoint & 0xFF)); + } + else if(codepoint <= 0x7FF) + { + PutUnsafe(os, static_cast(0xC0 | ((codepoint >> 6) & 0xFF))); + PutUnsafe(os, static_cast(0x80 | ((codepoint & 0x3F)))); + } + else if(codepoint <= 0xFFFF) + { + PutUnsafe(os, static_cast(0xE0 | ((codepoint >> 12) & 0xFF))); + PutUnsafe(os, static_cast(0x80 | ((codepoint >> 6) & 0x3F))); + PutUnsafe(os, static_cast(0x80 | (codepoint & 0x3F))); + } + else + { + RAPIDJSON_ASSERT(codepoint <= 0x10FFFF); + PutUnsafe(os, static_cast(0xF0 | ((codepoint >> 18) & 0xFF))); + PutUnsafe(os, static_cast(0x80 | ((codepoint >> 12) & 0x3F))); + PutUnsafe(os, static_cast(0x80 | ((codepoint >> 6) & 0x3F))); + PutUnsafe(os, static_cast(0x80 | (codepoint & 0x3F))); + } + } - template - static bool Decode(InputStream& is, unsigned* codepoint) { + template + static bool Decode(InputStream & is, unsigned* codepoint) + { #define COPY() c = is.Take(); *codepoint = (*codepoint << 6) | (static_cast(c) & 0x3Fu) #define TRANS(mask) result &= ((GetRange(static_cast(c)) & mask) != 0) #define TAIL() COPY(); TRANS(0x70) - typename InputStream::Ch c = is.Take(); - if (!(c & 0x80)) { - *codepoint = static_cast(c); - return true; - } + typename InputStream::Ch c = is.Take(); + if(!(c & 0x80)) + { + *codepoint = static_cast(c); + return true; + } - unsigned char type = GetRange(static_cast(c)); - if (type >= 32) { - *codepoint = 0; - } else { - *codepoint = (0xFF >> type) & static_cast(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; - } + unsigned char type = GetRange(static_cast(c)); + if(type >= 32) + { + *codepoint = 0; + } + else + { + *codepoint = (0xFF >> type) & static_cast(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 - static bool Validate(InputStream& is, OutputStream& os) { + template + static bool Validate(InputStream & is, OutputStream & os) + { #define COPY() os.Put(c = is.Take()) #define TRANS(mask) result &= ((GetRange(static_cast(c)) & mask) != 0) #define TAIL() COPY(); TRANS(0x70) - Ch c; - COPY(); - if (!(c & 0x80)) - return true; + Ch c; + COPY(); + if(!(c & 0x80)) + { + return true; + } - bool result = true; - switch (GetRange(static_cast(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; - } + bool result = true; + switch(GetRange(static_cast(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]; - } + 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 - static CharType TakeBOM(InputByteStream& is) { - RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1); - typename InputByteStream::Ch c = Take(is); - if (static_cast(c) != 0xEFu) return c; - c = is.Take(); - if (static_cast(c) != 0xBBu) return c; - c = is.Take(); - if (static_cast(c) != 0xBFu) return c; - c = is.Take(); - return c; - } + template + static CharType TakeBOM(InputByteStream & is) + { + RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1); + typename InputByteStream::Ch c = Take(is); + if(static_cast(c) != 0xEFu) + { + return c; + } + c = is.Take(); + if(static_cast(c) != 0xBBu) + { + return c; + } + c = is.Take(); + if(static_cast(c) != 0xBFu) + { + return c; + } + c = is.Take(); + return c; + } - template - static Ch Take(InputByteStream& is) { - RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1); - return static_cast(is.Take()); - } + template + static Ch Take(InputByteStream & is) + { + RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1); + return static_cast(is.Take()); + } - template - static void PutBOM(OutputByteStream& os) { - RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1); - os.Put(static_cast(0xEFu)); - os.Put(static_cast(0xBBu)); - os.Put(static_cast(0xBFu)); - } + template + static void PutBOM(OutputByteStream & os) + { + RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1); + os.Put(static_cast(0xEFu)); + os.Put(static_cast(0xBBu)); + os.Put(static_cast(0xBFu)); + } - template - static void Put(OutputByteStream& os, Ch c) { - RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1); - os.Put(static_cast(c)); - } + template + static void Put(OutputByteStream & os, Ch c) + { + RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1); + os.Put(static_cast(c)); + } }; /////////////////////////////////////////////////////////////////////////////// @@ -266,147 +360,171 @@ struct UTF8 { For streaming, use UTF16LE and UTF16BE, which handle endianness. */ template -struct UTF16 { - typedef CharType Ch; - RAPIDJSON_STATIC_ASSERT(sizeof(Ch) >= 2); +struct UTF16 +{ + typedef CharType Ch; + RAPIDJSON_STATIC_ASSERT(sizeof(Ch) >= 2); - enum { supportUnicode = 1 }; + enum { supportUnicode = 1 }; - template - 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(codepoint)); - } - else { - RAPIDJSON_ASSERT(codepoint <= 0x10FFFF); - unsigned v = codepoint - 0x10000; - os.Put(static_cast((v >> 10) | 0xD800)); - os.Put((v & 0x3FF) | 0xDC00); - } - } + template + 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(codepoint)); + } + else + { + RAPIDJSON_ASSERT(codepoint <= 0x10FFFF); + unsigned v = codepoint - 0x10000; + os.Put(static_cast((v >> 10) | 0xD800)); + os.Put((v & 0x3FF) | 0xDC00); + } + } - template - 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(codepoint)); - } - else { - RAPIDJSON_ASSERT(codepoint <= 0x10FFFF); - unsigned v = codepoint - 0x10000; - PutUnsafe(os, static_cast((v >> 10) | 0xD800)); - PutUnsafe(os, (v & 0x3FF) | 0xDC00); - } - } + template + 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(codepoint)); + } + else + { + RAPIDJSON_ASSERT(codepoint <= 0x10FFFF); + unsigned v = codepoint - 0x10000; + PutUnsafe(os, static_cast((v >> 10) | 0xD800)); + PutUnsafe(os, (v & 0x3FF) | 0xDC00); + } + } - template - 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(c); - return true; - } - else if (c <= 0xDBFF) { - *codepoint = (static_cast(c) & 0x3FF) << 10; - c = is.Take(); - *codepoint |= (static_cast(c) & 0x3FF); - *codepoint += 0x10000; - return c >= 0xDC00 && c <= 0xDFFF; - } - return false; - } + template + 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(c); + return true; + } + else if(c <= 0xDBFF) + { + *codepoint = (static_cast(c) & 0x3FF) << 10; + c = is.Take(); + *codepoint |= (static_cast(c) & 0x3FF); + *codepoint += 0x10000; + return c >= 0xDC00 && c <= 0xDFFF; + } + return false; + } - template - 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(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; - } + template + 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(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 -struct UTF16LE : UTF16 { - template - static CharType TakeBOM(InputByteStream& is) { - RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1); - CharType c = Take(is); - return static_cast(c) == 0xFEFFu ? Take(is) : c; - } +struct UTF16LE : UTF16 +{ + template + static CharType TakeBOM(InputByteStream & is) + { + RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1); + CharType c = Take(is); + return static_cast(c) == 0xFEFFu ? Take(is) : c; + } - template - static CharType Take(InputByteStream& is) { - RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1); - unsigned c = static_cast(is.Take()); - c |= static_cast(static_cast(is.Take())) << 8; - return static_cast(c); - } + template + static CharType Take(InputByteStream & is) + { + RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1); + unsigned c = static_cast(is.Take()); + c |= static_cast(static_cast(is.Take())) << 8; + return static_cast(c); + } - template - static void PutBOM(OutputByteStream& os) { - RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1); - os.Put(static_cast(0xFFu)); - os.Put(static_cast(0xFEu)); - } + template + static void PutBOM(OutputByteStream & os) + { + RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1); + os.Put(static_cast(0xFFu)); + os.Put(static_cast(0xFEu)); + } - template - static void Put(OutputByteStream& os, CharType c) { - RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1); - os.Put(static_cast(static_cast(c) & 0xFFu)); - os.Put(static_cast((static_cast(c) >> 8) & 0xFFu)); - } + template + static void Put(OutputByteStream & os, CharType c) + { + RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1); + os.Put(static_cast(static_cast(c) & 0xFFu)); + os.Put(static_cast((static_cast(c) >> 8) & 0xFFu)); + } }; //! UTF-16 big endian encoding. template -struct UTF16BE : UTF16 { - template - static CharType TakeBOM(InputByteStream& is) { - RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1); - CharType c = Take(is); - return static_cast(c) == 0xFEFFu ? Take(is) : c; - } +struct UTF16BE : UTF16 +{ + template + static CharType TakeBOM(InputByteStream & is) + { + RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1); + CharType c = Take(is); + return static_cast(c) == 0xFEFFu ? Take(is) : c; + } - template - static CharType Take(InputByteStream& is) { - RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1); - unsigned c = static_cast(static_cast(is.Take())) << 8; - c |= static_cast(is.Take()); - return static_cast(c); - } + template + static CharType Take(InputByteStream & is) + { + RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1); + unsigned c = static_cast(static_cast(is.Take())) << 8; + c |= static_cast(is.Take()); + return static_cast(c); + } - template - static void PutBOM(OutputByteStream& os) { - RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1); - os.Put(static_cast(0xFEu)); - os.Put(static_cast(0xFFu)); - } + template + static void PutBOM(OutputByteStream & os) + { + RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1); + os.Put(static_cast(0xFEu)); + os.Put(static_cast(0xFFu)); + } - template - static void Put(OutputByteStream& os, CharType c) { - RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1); - os.Put(static_cast((static_cast(c) >> 8) & 0xFFu)); - os.Put(static_cast(static_cast(c) & 0xFFu)); - } + template + static void Put(OutputByteStream & os, CharType c) + { + RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1); + os.Put(static_cast((static_cast(c) >> 8) & 0xFFu)); + os.Put(static_cast(static_cast(c) & 0xFFu)); + } }; /////////////////////////////////////////////////////////////////////////////// // UTF32 -//! UTF-32 encoding. +//! 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 @@ -415,119 +533,134 @@ struct UTF16BE : UTF16 { For streaming, use UTF32LE and UTF32BE, which handle endianness. */ template -struct UTF32 { - typedef CharType Ch; - RAPIDJSON_STATIC_ASSERT(sizeof(Ch) >= 4); +struct UTF32 +{ + typedef CharType Ch; + RAPIDJSON_STATIC_ASSERT(sizeof(Ch) >= 4); - enum { supportUnicode = 1 }; + enum { supportUnicode = 1 }; - template - static void Encode(OutputStream& os, unsigned codepoint) { - RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputStream::Ch) >= 4); - RAPIDJSON_ASSERT(codepoint <= 0x10FFFF); - os.Put(codepoint); - } + template + static void Encode(OutputStream & os, unsigned codepoint) + { + RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputStream::Ch) >= 4); + RAPIDJSON_ASSERT(codepoint <= 0x10FFFF); + os.Put(codepoint); + } - template - static void EncodeUnsafe(OutputStream& os, unsigned codepoint) { - RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputStream::Ch) >= 4); - RAPIDJSON_ASSERT(codepoint <= 0x10FFFF); - PutUnsafe(os, codepoint); - } + template + static void EncodeUnsafe(OutputStream & os, unsigned codepoint) + { + RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputStream::Ch) >= 4); + RAPIDJSON_ASSERT(codepoint <= 0x10FFFF); + PutUnsafe(os, codepoint); + } - template - 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 + 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 - 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; - } + template + 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 -struct UTF32LE : UTF32 { - template - static CharType TakeBOM(InputByteStream& is) { - RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1); - CharType c = Take(is); - return static_cast(c) == 0x0000FEFFu ? Take(is) : c; - } +struct UTF32LE : UTF32 +{ + template + static CharType TakeBOM(InputByteStream & is) + { + RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1); + CharType c = Take(is); + return static_cast(c) == 0x0000FEFFu ? Take(is) : c; + } - template - static CharType Take(InputByteStream& is) { - RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1); - unsigned c = static_cast(is.Take()); - c |= static_cast(static_cast(is.Take())) << 8; - c |= static_cast(static_cast(is.Take())) << 16; - c |= static_cast(static_cast(is.Take())) << 24; - return static_cast(c); - } + template + static CharType Take(InputByteStream & is) + { + RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1); + unsigned c = static_cast(is.Take()); + c |= static_cast(static_cast(is.Take())) << 8; + c |= static_cast(static_cast(is.Take())) << 16; + c |= static_cast(static_cast(is.Take())) << 24; + return static_cast(c); + } - template - static void PutBOM(OutputByteStream& os) { - RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1); - os.Put(static_cast(0xFFu)); - os.Put(static_cast(0xFEu)); - os.Put(static_cast(0x00u)); - os.Put(static_cast(0x00u)); - } + template + static void PutBOM(OutputByteStream & os) + { + RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1); + os.Put(static_cast(0xFFu)); + os.Put(static_cast(0xFEu)); + os.Put(static_cast(0x00u)); + os.Put(static_cast(0x00u)); + } - template - static void Put(OutputByteStream& os, CharType c) { - RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1); - os.Put(static_cast(c & 0xFFu)); - os.Put(static_cast((c >> 8) & 0xFFu)); - os.Put(static_cast((c >> 16) & 0xFFu)); - os.Put(static_cast((c >> 24) & 0xFFu)); - } + template + static void Put(OutputByteStream & os, CharType c) + { + RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1); + os.Put(static_cast(c & 0xFFu)); + os.Put(static_cast((c >> 8) & 0xFFu)); + os.Put(static_cast((c >> 16) & 0xFFu)); + os.Put(static_cast((c >> 24) & 0xFFu)); + } }; //! UTF-32 big endian encoding. template -struct UTF32BE : UTF32 { - template - static CharType TakeBOM(InputByteStream& is) { - RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1); - CharType c = Take(is); - return static_cast(c) == 0x0000FEFFu ? Take(is) : c; - } +struct UTF32BE : UTF32 +{ + template + static CharType TakeBOM(InputByteStream & is) + { + RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1); + CharType c = Take(is); + return static_cast(c) == 0x0000FEFFu ? Take(is) : c; + } - template - static CharType Take(InputByteStream& is) { - RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1); - unsigned c = static_cast(static_cast(is.Take())) << 24; - c |= static_cast(static_cast(is.Take())) << 16; - c |= static_cast(static_cast(is.Take())) << 8; - c |= static_cast(static_cast(is.Take())); - return static_cast(c); - } + template + static CharType Take(InputByteStream & is) + { + RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1); + unsigned c = static_cast(static_cast(is.Take())) << 24; + c |= static_cast(static_cast(is.Take())) << 16; + c |= static_cast(static_cast(is.Take())) << 8; + c |= static_cast(static_cast(is.Take())); + return static_cast(c); + } - template - static void PutBOM(OutputByteStream& os) { - RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1); - os.Put(static_cast(0x00u)); - os.Put(static_cast(0x00u)); - os.Put(static_cast(0xFEu)); - os.Put(static_cast(0xFFu)); - } + template + static void PutBOM(OutputByteStream & os) + { + RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1); + os.Put(static_cast(0x00u)); + os.Put(static_cast(0x00u)); + os.Put(static_cast(0xFEu)); + os.Put(static_cast(0xFFu)); + } - template - static void Put(OutputByteStream& os, CharType c) { - RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1); - os.Put(static_cast((c >> 24) & 0xFFu)); - os.Put(static_cast((c >> 16) & 0xFFu)); - os.Put(static_cast((c >> 8) & 0xFFu)); - os.Put(static_cast(c & 0xFFu)); - } + template + static void Put(OutputByteStream & os, CharType c) + { + RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1); + os.Put(static_cast((c >> 24) & 0xFFu)); + os.Put(static_cast((c >> 16) & 0xFFu)); + os.Put(static_cast((c >> 8) & 0xFFu)); + os.Put(static_cast(c & 0xFFu)); + } }; /////////////////////////////////////////////////////////////////////////////// @@ -539,113 +672,128 @@ struct UTF32BE : UTF32 { \note implements Encoding concept */ template -struct ASCII { - typedef CharType Ch; +struct ASCII +{ + typedef CharType Ch; - enum { supportUnicode = 0 }; + enum { supportUnicode = 0 }; - template - static void Encode(OutputStream& os, unsigned codepoint) { - RAPIDJSON_ASSERT(codepoint <= 0x7F); - os.Put(static_cast(codepoint & 0xFF)); - } + template + static void Encode(OutputStream & os, unsigned codepoint) + { + RAPIDJSON_ASSERT(codepoint <= 0x7F); + os.Put(static_cast(codepoint & 0xFF)); + } - template - static void EncodeUnsafe(OutputStream& os, unsigned codepoint) { - RAPIDJSON_ASSERT(codepoint <= 0x7F); - PutUnsafe(os, static_cast(codepoint & 0xFF)); - } + template + static void EncodeUnsafe(OutputStream & os, unsigned codepoint) + { + RAPIDJSON_ASSERT(codepoint <= 0x7F); + PutUnsafe(os, static_cast(codepoint & 0xFF)); + } - template - static bool Decode(InputStream& is, unsigned* codepoint) { - uint8_t c = static_cast(is.Take()); - *codepoint = c; - return c <= 0X7F; - } + template + static bool Decode(InputStream & is, unsigned* codepoint) + { + uint8_t c = static_cast(is.Take()); + *codepoint = c; + return c <= 0X7F; + } - template - static bool Validate(InputStream& is, OutputStream& os) { - uint8_t c = static_cast(is.Take()); - os.Put(static_cast(c)); - return c <= 0x7F; - } + template + static bool Validate(InputStream & is, OutputStream & os) + { + uint8_t c = static_cast(is.Take()); + os.Put(static_cast(c)); + return c <= 0x7F; + } - template - static CharType TakeBOM(InputByteStream& is) { - RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1); - uint8_t c = static_cast(Take(is)); - return static_cast(c); - } + template + static CharType TakeBOM(InputByteStream & is) + { + RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1); + uint8_t c = static_cast(Take(is)); + return static_cast(c); + } - template - static Ch Take(InputByteStream& is) { - RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1); - return static_cast(is.Take()); - } + template + static Ch Take(InputByteStream & is) + { + RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1); + return static_cast(is.Take()); + } - template - static void PutBOM(OutputByteStream& os) { - RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1); - (void)os; - } + template + static void PutBOM(OutputByteStream & os) + { + RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1); + (void)os; + } - template - static void Put(OutputByteStream& os, Ch c) { - RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1); - os.Put(static_cast(c)); - } + template + static void Put(OutputByteStream & os, Ch c) + { + RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1); + os.Put(static_cast(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. +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 -struct AutoUTF { - typedef CharType Ch; +struct AutoUTF +{ + typedef CharType Ch; - enum { supportUnicode = 1 }; + enum { supportUnicode = 1 }; #define RAPIDJSON_ENCODINGS_FUNC(x) UTF8::x, UTF16LE::x, UTF16BE::x, UTF32LE::x, UTF32BE::x - template - 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 + 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 - 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 + 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 - 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 + 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 - 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); - } + template + 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 }; @@ -655,56 +803,68 @@ struct AutoUTF { //! Encoding conversion. template -struct Transcoder { - //! Take one Unicode codepoint from source encoding, convert it to target encoding and put it to the output stream. - template - RAPIDJSON_FORCEINLINE static bool Transcode(InputStream& is, OutputStream& os) { - unsigned codepoint; - if (!SourceEncoding::Decode(is, &codepoint)) - return false; - TargetEncoding::Encode(os, codepoint); - return true; - } +struct Transcoder +{ + //! Take one Unicode codepoint from source encoding, convert it to target encoding and put it to the output stream. + template + 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 - RAPIDJSON_FORCEINLINE static bool TranscodeUnsafe(InputStream& is, OutputStream& os) { - unsigned codepoint; - if (!SourceEncoding::Decode(is, &codepoint)) - return false; - TargetEncoding::EncodeUnsafe(os, codepoint); - return true; - } + template + 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 - RAPIDJSON_FORCEINLINE static bool Validate(InputStream& is, OutputStream& os) { - return Transcode(is, os); // Since source/target encoding is different, must transcode. - } + //! Validate one Unicode codepoint from an encoded stream. + template + RAPIDJSON_FORCEINLINE static bool Validate(InputStream & is, OutputStream & os) + { + return Transcode(is, os); // Since source/target encoding is different, must transcode. + } }; // Forward declaration. template -inline void PutUnsafe(Stream& stream, typename Stream::Ch c); +inline void PutUnsafe(Stream & stream, typename Stream::Ch c); //! Specialization of Transcoder with same source and target encoding. template -struct Transcoder { - template - 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 - 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 - RAPIDJSON_FORCEINLINE static bool Validate(InputStream& is, OutputStream& os) { - return Encoding::Validate(is, os); // source/target encoding are the same - } +struct Transcoder +{ + template + 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 + 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 + RAPIDJSON_FORCEINLINE static bool Validate(InputStream & is, OutputStream & os) + { + return Encoding::Validate(is, os); // source/target encoding are the same + } }; RAPIDJSON_NAMESPACE_END diff --git a/src/3rdparty/rapidjson/error/en.h b/src/3rdparty/rapidjson/error/en.h index 2db838bf..21b9e21b 100644 --- a/src/3rdparty/rapidjson/error/en.h +++ b/src/3rdparty/rapidjson/error/en.h @@ -1,5 +1,5 @@ // 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 @@ -7,9 +7,9 @@ // // 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 +// 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_ @@ -19,51 +19,72 @@ #ifdef __clang__ RAPIDJSON_DIAG_PUSH -RAPIDJSON_DIAG_OFF(switch-enum) -RAPIDJSON_DIAG_OFF(covered-switch-default) +RAPIDJSON_DIAG_OFF(switch - enum) + RAPIDJSON_DIAG_OFF(covered - switch - default) #endif -RAPIDJSON_NAMESPACE_BEGIN + 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."); + //! 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 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 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 kParseErrorValueInvalid: + return RAPIDJSON_ERROR_STRING("Invalid value."); - 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 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 kParseErrorTermination: return RAPIDJSON_ERROR_STRING("Terminate parsing due to Handler error."); - case kParseErrorUnspecificSyntaxError: return RAPIDJSON_ERROR_STRING("Unspecific syntax error."); + case kParseErrorArrayMissCommaOrSquareBracket: + return RAPIDJSON_ERROR_STRING("Missing a comma or ']' after an array element."); - default: return RAPIDJSON_ERROR_STRING("Unknown error."); - } -} + 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 diff --git a/src/3rdparty/rapidjson/error/error.h b/src/3rdparty/rapidjson/error/error.h index 95cb31a7..42ecb7e1 100644 --- a/src/3rdparty/rapidjson/error/error.h +++ b/src/3rdparty/rapidjson/error/error.h @@ -1,5 +1,5 @@ // 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 @@ -7,9 +7,9 @@ // // 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 +// 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_ @@ -61,32 +61,33 @@ RAPIDJSON_NAMESPACE_BEGIN /*! \ingroup RAPIDJSON_ERRORS \see GenericReader::Parse, GenericReader::GetParseErrorCode */ -enum ParseErrorCode { - kParseErrorNone = 0, //!< No error. +enum ParseErrorCode +{ + kParseErrorNone = 0, //!< No error. - kParseErrorDocumentEmpty, //!< The document is empty. - kParseErrorDocumentRootNotSingular, //!< The document root must not follow by other values. + kParseErrorDocumentEmpty, //!< The document is empty. + kParseErrorDocumentRootNotSingular, //!< The document root must not follow by other values. - kParseErrorValueInvalid, //!< Invalid value. + 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. + 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. + 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. + 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. + 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. + kParseErrorTermination, //!< Parsing was terminated. + kParseErrorUnspecificSyntaxError //!< Unspecific syntax error. }; //! Result of parsing (wraps ParseErrorCode) @@ -103,35 +104,64 @@ enum ParseErrorCode { \endcode \see GenericReader::Parse, GenericDocument::Parse */ -struct ParseResult { +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) {} + //! 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_; } + //! 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; } + //! 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_; } + 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; } + //! 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_; + ParseErrorCode code_; + size_t offset_; }; //! Function pointer type of GetParseError(). diff --git a/src/3rdparty/rapidjson/filereadstream.h b/src/3rdparty/rapidjson/filereadstream.h index b56ea13b..ace7fad0 100644 --- a/src/3rdparty/rapidjson/filereadstream.h +++ b/src/3rdparty/rapidjson/filereadstream.h @@ -1,5 +1,5 @@ // 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 @@ -7,9 +7,9 @@ // // 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 +// 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_ @@ -21,8 +21,8 @@ #ifdef __clang__ RAPIDJSON_DIAG_PUSH RAPIDJSON_DIAG_OFF(padded) -RAPIDJSON_DIAG_OFF(unreachable-code) -RAPIDJSON_DIAG_OFF(missing-noreturn) +RAPIDJSON_DIAG_OFF(unreachable - code) +RAPIDJSON_DIAG_OFF(missing - noreturn) #endif RAPIDJSON_NAMESPACE_BEGIN @@ -31,63 +31,97 @@ RAPIDJSON_NAMESPACE_BEGIN /*! \note implements Stream concept */ -class FileReadStream { +class FileReadStream +{ public: - typedef char Ch; //!< Character type (byte). + 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(); - } + //! 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(current_ - buffer_); } + Ch Peek() const + { + return *current_; + } + Ch Take() + { + Ch c = *current_; + Read(); + return c; + } + size_t Tell() const + { + return count_ + static_cast(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; } + // 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; - } + // 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_; + 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; - } - } - } + 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_; + 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 diff --git a/src/3rdparty/rapidjson/filewritestream.h b/src/3rdparty/rapidjson/filewritestream.h index 6378dd60..3bb25e5c 100644 --- a/src/3rdparty/rapidjson/filewritestream.h +++ b/src/3rdparty/rapidjson/filewritestream.h @@ -1,5 +1,5 @@ // 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 @@ -7,9 +7,9 @@ // // 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 +// 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_ @@ -20,7 +20,7 @@ #ifdef __clang__ RAPIDJSON_DIAG_PUSH -RAPIDJSON_DIAG_OFF(unreachable-code) +RAPIDJSON_DIAG_OFF(unreachable - code) #endif RAPIDJSON_NAMESPACE_BEGIN @@ -29,70 +29,103 @@ RAPIDJSON_NAMESPACE_BEGIN /*! \note implements Stream concept */ -class FileWriteStream { +class FileWriteStream +{ public: - typedef char Ch; //!< Character type. Only support char. + 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); - } + 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(); + void Put(char c) + { + if(current_ >= bufferEnd_) + { + Flush(); + } - *current_++ = c; - } + *current_++ = c; + } - void PutN(char c, size_t n) { - size_t avail = static_cast(bufferEnd_ - current_); - while (n > avail) { - std::memset(current_, c, avail); - current_ += avail; - Flush(); - n -= avail; - avail = static_cast(bufferEnd_ - current_); - } + void PutN(char c, size_t n) + { + size_t avail = static_cast(bufferEnd_ - current_); + while(n > avail) + { + std::memset(current_, c, avail); + current_ += avail; + Flush(); + n -= avail; + avail = static_cast(bufferEnd_ - current_); + } - if (n > 0) { - std::memset(current_, c, n); - current_ += n; - } - } + if(n > 0) + { + std::memset(current_, c, n); + current_ += n; + } + } - void Flush() { - if (current_ != buffer_) { - size_t result = fwrite(buffer_, 1, static_cast(current_ - buffer_), fp_); - if (result < static_cast(current_ - buffer_)) { - // failure deliberately ignored at this time - // added to avoid warn_unused_result build errors - } - current_ = buffer_; - } - } + void Flush() + { + if(current_ != buffer_) + { + size_t result = fwrite(buffer_, 1, static_cast(current_ - buffer_), fp_); + if(result < static_cast(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; } + // 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&); + // Prohibit copy constructor & assignment operator. + FileWriteStream(const FileWriteStream &); + FileWriteStream & operator=(const FileWriteStream &); - std::FILE* fp_; - char *buffer_; - char *bufferEnd_; - char *current_; + 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); +inline void PutN(FileWriteStream & stream, char c, size_t n) +{ + stream.PutN(c, n); } RAPIDJSON_NAMESPACE_END diff --git a/src/3rdparty/rapidjson/fwd.h b/src/3rdparty/rapidjson/fwd.h index e8104e84..c5a37c1e 100644 --- a/src/3rdparty/rapidjson/fwd.h +++ b/src/3rdparty/rapidjson/fwd.h @@ -1,5 +1,5 @@ // 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 @@ -7,9 +7,9 @@ // // 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 +// 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_ @@ -46,12 +46,12 @@ class MemoryPoolAllocator; template struct GenericStringStream; -typedef GenericStringStream > StringStream; +typedef GenericStringStream> StringStream; template struct GenericInsituStringStream; -typedef GenericInsituStringStream > InsituStringStream; +typedef GenericInsituStringStream> InsituStringStream; // stringbuffer.h @@ -101,7 +101,7 @@ class PrettyWriter; // document.h -template +template struct GenericMember; template @@ -110,10 +110,10 @@ class GenericMemberIterator; template struct GenericStringRef; -template +template class GenericValue; -typedef GenericValue, MemoryPoolAllocator > Value; +typedef GenericValue, MemoryPoolAllocator> Value; template class GenericDocument; @@ -141,10 +141,11 @@ typedef IGenericRemoteSchemaDocumentProvider IRemoteSchemaDocume template < typename SchemaDocumentType, typename OutputHandler, - typename StateAllocator> + typename StateAllocator > class GenericSchemaValidator; -typedef GenericSchemaValidator, void>, CrtAllocator> SchemaValidator; +typedef GenericSchemaValidator, void>, CrtAllocator> +SchemaValidator; RAPIDJSON_NAMESPACE_END diff --git a/src/3rdparty/rapidjson/internal/biginteger.h b/src/3rdparty/rapidjson/internal/biginteger.h index 9d3e88c9..fadf7969 100644 --- a/src/3rdparty/rapidjson/internal/biginteger.h +++ b/src/3rdparty/rapidjson/internal/biginteger.h @@ -1,5 +1,5 @@ // 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 @@ -7,9 +7,9 @@ // // 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 +// 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_ @@ -23,266 +23,379 @@ #endif RAPIDJSON_NAMESPACE_BEGIN -namespace internal { +namespace internal +{ -class BigInteger { -public: - typedef uint64_t Type; + class BigInteger + { + public: + typedef uint64_t Type; - BigInteger(const BigInteger& rhs) : count_(rhs.count_) { - std::memcpy(digits_, rhs.digits_, count_ * sizeof(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; - } + 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; - } + 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; - } + if(length > 0) + { + AppendDecimal64(decimals + i, decimals + i + length); + } + } - 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; - } + BigInteger & operator=(const BigInteger & rhs) + { + if(this != &rhs) + { + count_ = rhs.count_; + std::memcpy(digits_, rhs.digits_, count_ * sizeof(Type)); + } + return *this; + } - // Last carry - if (digits_[count_ - 1] < backup) - PushBack(1); + BigInteger & operator=(uint64_t u) + { + digits_[0] = u; + count_ = 1; + return *this; + } - 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; + } - BigInteger& operator*=(uint64_t u) { - if (u == 0) return *this = 0; - if (u == 1) return *this; - if (*this == 1) return *this = u; + // Last carry + if(digits_[count_ - 1] < backup) + { + PushBack(1); + } - 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; + } - return *this; - } + BigInteger & operator*=(uint64_t u) + { + if(u == 0) + { + return *this = 0; + } + if(u == 1) + { + return *this; + } + if(*this == 1) + { + return *this = u; + } - 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++) + { + uint64_t hi; + digits_[i] = MulAdd64(digits_[i], u, k, &hi); + k = hi; + } - 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); + if(k > 0) + { + PushBack(k); + } - return *this; - } + return *this; + } - BigInteger& operator<<=(size_t shift) { - if (IsZero() || shift == 0) return *this; + BigInteger & operator*=(uint32_t u) + { + if(u == 0) + { + return *this = 0; + } + if(u == 1) + { + return *this; + } + if(*this == 1) + { + return *this = u; + } - size_t offset = shift / kTypeBit; - size_t interShift = shift % kTypeBit; - RAPIDJSON_ASSERT(count_ + offset <= kCapacity); + 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 (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_++; - } + if(k > 0) + { + PushBack(k); + } - std::memset(digits_, 0, offset * sizeof(Type)); + return *this; + } - return *this; - } + BigInteger & operator<<=(size_t shift) + { + if(IsZero() || shift == 0) + { + return *this; + } - bool operator==(const BigInteger& rhs) const { - return count_ == rhs.count_ && std::memcmp(digits_, rhs.digits_, count_ * sizeof(Type)) == 0; - } + size_t offset = shift / kTypeBit; + size_t interShift = shift % kTypeBit; + RAPIDJSON_ASSERT(count_ + offset <= kCapacity); - bool operator==(const Type rhs) const { - return count_ == 1 && digits_[0] == rhs; - } + 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_++; + } + } - 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(1220703125u); // 5^13 - if (exp > 0) *this *= kPow5[exp - 1]; - return *this; - } + std::memset(digits_, 0, offset * sizeof(Type)); - // 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; } + return *this; + } - 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; - } + bool operator==(const BigInteger & rhs) const + { + return count_ == rhs.count_ && std::memcmp(digits_, rhs.digits_, count_ * sizeof(Type)) == 0; + } - return ret; - } + bool operator==(const Type rhs) const + { + return count_ == 1 && digits_[0] == rhs; + } - int Compare(const BigInteger& rhs) const { - if (count_ != rhs.count_) - return count_ < rhs.count_ ? -1 : 1; + 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(1220703125u); // 5^13 + } + if(exp > 0) + { + *this *= kPow5[exp - 1]; + } + return *this; + } - for (size_t i = count_; i-- > 0;) - if (digits_[i] != rhs.digits_[i]) - return digits_[i] < rhs.digits_[i] ? -1 : 1; + // 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; + } - return 0; - } + 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; + } + } - 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; } + return ret; + } -private: - void AppendDecimal64(const char* begin, const char* end) { - uint64_t u = ParseUint64(begin, end); - if (IsZero()) - *this = u; - else { - unsigned exp = static_cast(end - begin); - (MultiplyPow5(exp) <<= exp) += u; // *this = *this * 10^exp + u - } - } + int Compare(const BigInteger & rhs) const + { + if(count_ != rhs.count_) + { + return count_ < rhs.count_ ? -1 : 1; + } - void PushBack(Type digit) { - RAPIDJSON_ASSERT(count_ < kCapacity); - digits_[count_++] = digit; - } + for(size_t i = count_; i-- > 0;) + if(digits_[i] != rhs.digits_[i]) + { + return digits_[i] < rhs.digits_[i] ? -1 : 1; + } - 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(*p - '0'); - } - return r; - } + return 0; + } - // Assume a * b + k < 2^128 - static uint64_t MulAdd64(uint64_t a, uint64_t b, uint64_t k, uint64_t* outHigh) { + 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(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(*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; + 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(a) * static_cast(b); - p += k; - *outHigh = static_cast(p >> 64); - return static_cast(p); + __extension__ typedef unsigned __int128 uint128; + uint128 p = static_cast(a) * static_cast(b); + p += k; + *outHigh = static_cast(p >> 64); + return static_cast(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(1) << 32); - uint64_t lo = (x1 << 32) + (x0 & 0xFFFFFFFF); - uint64_t hi = x3 + (x1 >> 32); + 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(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; + 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; + 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_; -}; + Type digits_[kCapacity]; + size_t count_; + }; } // namespace internal RAPIDJSON_NAMESPACE_END diff --git a/src/3rdparty/rapidjson/internal/diyfp.h b/src/3rdparty/rapidjson/internal/diyfp.h index c9fefdc6..3c2ec2b1 100644 --- a/src/3rdparty/rapidjson/internal/diyfp.h +++ b/src/3rdparty/rapidjson/internal/diyfp.h @@ -1,5 +1,5 @@ // 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 @@ -7,9 +7,9 @@ // // 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 +// 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: @@ -28,228 +28,254 @@ #endif RAPIDJSON_NAMESPACE_BEGIN -namespace internal { +namespace internal +{ #ifdef __GNUC__ -RAPIDJSON_DIAG_PUSH -RAPIDJSON_DIAG_OFF(effc++) + RAPIDJSON_DIAG_PUSH + RAPIDJSON_DIAG_OFF(effc++) #endif #ifdef __clang__ -RAPIDJSON_DIAG_PUSH -RAPIDJSON_DIAG_OFF(padded) + RAPIDJSON_DIAG_PUSH + RAPIDJSON_DIAG_OFF(padded) #endif -struct DiyFp { - DiyFp() : f(), e() {} + struct DiyFp + { + DiyFp() : f(), e() {} - DiyFp(uint64_t fp, int exp) : f(fp), e(exp) {} + DiyFp(uint64_t fp, int exp) : f(fp), e(exp) {} - explicit DiyFp(double d) { - union { - double d; - uint64_t u64; - } u = { d }; + explicit DiyFp(double d) + { + union + { + double d; + uint64_t u64; + } u = { d }; - int biased_e = static_cast((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; - } - } + int biased_e = static_cast((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 + { + return DiyFp(f - rhs.f, e); + } - DiyFp operator*(const DiyFp& rhs) const { + 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); + 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(f) * static_cast(rhs.f); - uint64_t h = static_cast(p >> 64); - uint64_t l = static_cast(p); - if (l & (uint64_t(1) << 63)) // rounding - h++; - return DiyFp(h, e + rhs.e + 64); + __extension__ typedef unsigned __int128 uint128; + uint128 p = static_cast(f) * static_cast(rhs.f); + uint64_t h = static_cast(p >> 64); + uint64_t l = static_cast(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); + 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 { + DiyFp Normalize() const + { #if defined(_MSC_VER) && defined(_M_AMD64) - unsigned long index; - _BitScanReverse64(&index, f); - return DiyFp(f << (63 - index), e - (63 - index)); + 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); + int s = __builtin_clzll(f); + return DiyFp(f << s, e - s); #else - DiyFp res = *this; - while (!(res.f & (static_cast(1) << 63))) { - res.f <<= 1; - res.e--; - } - return res; + DiyFp res = *this; + while(!(res.f & (static_cast(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; - } + 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; - } + 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(e + kDpExponentBias); - u.u64 = (f & kDpSignificandMask) | (be << kDpSignificandSize); - return u.d; - } + double ToDouble() const + { + union + { + double d; + uint64_t u64; + } u; + const uint64_t be = (e == kDpDenormalExponent && (f & kDpHiddenBit) == 0) ? 0 : + static_cast(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); + 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; -}; + 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) { + 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]); + } - //int k = static_cast(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(dk); - if (dk - k > 0.0) - k++; + inline DiyFp GetCachedPower(int e, int* K) + { - unsigned index = static_cast((k >> 3) + 1); - *K = -(-348 + static_cast(index << 3)); // decimal exponent no need lookup table + //int k = static_cast(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(dk); + if(dk - k > 0.0) + { + k++; + } - return GetCachedPowerByIndex(index); -} + unsigned index = static_cast((k >> 3) + 1); + *K = -(-348 + static_cast(index << 3)); // decimal exponent no need lookup table -inline DiyFp GetCachedPower10(int exp, int *outExp) { - unsigned index = (static_cast(exp) + 348u) / 8u; - *outExp = -348 + static_cast(index) * 8; - return GetCachedPowerByIndex(index); - } + return GetCachedPowerByIndex(index); + } + + inline DiyFp GetCachedPower10(int exp, int* outExp) + { + unsigned index = (static_cast(exp) + 348u) / 8u; + *outExp = -348 + static_cast(index) * 8; + return GetCachedPowerByIndex(index); + } #ifdef __GNUC__ -RAPIDJSON_DIAG_POP + RAPIDJSON_DIAG_POP #endif #ifdef __clang__ -RAPIDJSON_DIAG_POP -RAPIDJSON_DIAG_OFF(padded) + RAPIDJSON_DIAG_POP + RAPIDJSON_DIAG_OFF(padded) #endif } // namespace internal diff --git a/src/3rdparty/rapidjson/internal/dtoa.h b/src/3rdparty/rapidjson/internal/dtoa.h index 8d6350e6..b146e40c 100644 --- a/src/3rdparty/rapidjson/internal/dtoa.h +++ b/src/3rdparty/rapidjson/internal/dtoa.h @@ -1,5 +1,5 @@ // 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 @@ -7,9 +7,9 @@ // // 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 +// 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: @@ -24,219 +24,321 @@ #include "ieee754.h" RAPIDJSON_NAMESPACE_BEGIN -namespace internal { +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 + 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 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 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(Mp.f >> -one.e); - uint64_t p2 = Mp.f & (one.f - 1); - unsigned kappa = CountDecimalDigit32(p1); // kappa in [0, 9] - *len = 0; + 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(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('0' + static_cast(d)); - kappa--; - uint64_t tmp = (static_cast(p1) << -one.e) + p2; - if (tmp <= delta) { - *K += kappa; - GrisuRound(buffer, *len, delta, tmp, static_cast(kPow10[kappa]) << -one.e, wp_w.f); - return; - } - } + 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('0' + static_cast(d)); + } + kappa--; + uint64_t tmp = (static_cast(p1) << -one.e) + p2; + if(tmp <= delta) + { + *K += kappa; + GrisuRound(buffer, *len, delta, tmp, static_cast(kPow10[kappa]) << -one.e, wp_w.f); + return; + } + } - // kappa = 0 - for (;;) { - p2 *= 10; - delta *= 10; - char d = static_cast(p2 >> -one.e); - if (d || *len) - buffer[(*len)++] = static_cast('0' + d); - p2 &= one.f - 1; - kappa--; - if (p2 < delta) { - *K += kappa; - int index = -static_cast(kappa); - GrisuRound(buffer, *len, delta, p2, one.f, wp_w.f * (index < 9 ? kPow10[-static_cast(kappa)] : 0)); - return; - } - } -} + // kappa = 0 + for(;;) + { + p2 *= 10; + delta *= 10; + char d = static_cast(p2 >> -one.e); + if(d || *len) + { + buffer[(*len)++] = static_cast('0' + d); + } + p2 &= one.f - 1; + kappa--; + if(p2 < delta) + { + *K += kappa; + int index = -static_cast(kappa); + GrisuRound(buffer, *len, delta, p2, one.f, wp_w.f * (index < 9 ? kPow10[-static_cast(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); + 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); -} + 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; - } + inline char* WriteExponent(int K, char* buffer) + { + if(K < 0) + { + *buffer++ = '-'; + K = -K; + } - if (K >= 100) { - *buffer++ = static_cast('0' + static_cast(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('0' + static_cast(K)); + if(K >= 100) + { + *buffer++ = static_cast('0' + static_cast(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('0' + static_cast(K)); + } - return buffer; -} + return buffer; + } -inline char* Prettify(char* buffer, int length, int k, int maxDecimalPlaces) { - const int kk = length + k; // 10^(kk-1) <= v < 10^kk + 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(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(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(length - 1)); - buffer[1] = '.'; - buffer[length + 1] = 'e'; - return WriteExponent(kk - 1, &buffer[0 + length + 2]); - } -} + 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(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(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(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); - } -} + 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 + RAPIDJSON_DIAG_POP #endif } // namespace internal diff --git a/src/3rdparty/rapidjson/internal/ieee754.h b/src/3rdparty/rapidjson/internal/ieee754.h index 82bb0b99..2970ba0e 100644 --- a/src/3rdparty/rapidjson/internal/ieee754.h +++ b/src/3rdparty/rapidjson/internal/ieee754.h @@ -1,5 +1,5 @@ // 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 @@ -7,9 +7,9 @@ // // 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 +// 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_ @@ -18,59 +18,109 @@ #include "../rapidjson.h" RAPIDJSON_NAMESPACE_BEGIN -namespace internal { +namespace internal +{ -class Double { -public: - Double() {} - Double(double d) : d_(d) {} - Double(uint64_t u) : u_(u) {} + 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 Value() const + { + return d_; + } + uint64_t Uint64Value() const + { + return u_; + } - double NextPositiveDouble() const { - RAPIDJSON_ASSERT(!Sign()); - return Double(u_ + 1).Value(); - } + 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(((u_ & kExponentMask) >> kSignificandSize) - kExponentBias); } + bool Sign() const + { + return (u_ & kSignMask) != 0; + } + uint64_t Significand() const + { + return u_ & kSignificandMask; + } + int Exponent() const + { + return static_cast(((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; } + 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; } + 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(order) + 1074; - } + static unsigned EffectiveSignificandSize(int order) + { + if(order >= -1021) + { + return 53; + } + else if(order <= -1074) + { + return 0; + } + else + { + return static_cast(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); + 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_; - }; -}; + union + { + double d_; + uint64_t u_; + }; + }; } // namespace internal RAPIDJSON_NAMESPACE_END diff --git a/src/3rdparty/rapidjson/internal/itoa.h b/src/3rdparty/rapidjson/internal/itoa.h index 01a4e7e7..e5410187 100644 --- a/src/3rdparty/rapidjson/internal/itoa.h +++ b/src/3rdparty/rapidjson/internal/itoa.h @@ -1,5 +1,5 @@ // 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 @@ -7,9 +7,9 @@ // // 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 +// 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_ @@ -18,285 +18,350 @@ #include "../rapidjson.h" RAPIDJSON_NAMESPACE_BEGIN -namespace internal { +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 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(); + 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('0' + static_cast(a)); + if(value < 10000) + { + const uint32_t d1 = (value / 100) << 1; + const uint32_t d2 = (value % 100) << 1; - 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; -} + 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; -inline char* i32toa(int32_t value, char* buffer) { - uint32_t u = static_cast(value); - if (value < 0) { - *buffer++ = '-'; - u = ~u + 1; - } + const uint32_t d1 = (b / 100) << 1; + const uint32_t d2 = (b % 100) << 1; - return u32toa(u, buffer); -} + const uint32_t d3 = (c / 100) << 1; + const uint32_t d4 = (c % 100) << 1; -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(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(value / kTen8); - const uint32_t v1 = static_cast(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; + if(value >= 10000000) + { + *buffer++ = cDigitsLut[d1]; + } + if(value >= 1000000) + { + *buffer++ = cDigitsLut[d1 + 1]; + } + if(value >= 100000) + { + *buffer++ = cDigitsLut[d2]; + } + *buffer++ = cDigitsLut[d2 + 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[d3]; + *buffer++ = cDigitsLut[d3 + 1]; + *buffer++ = cDigitsLut[d4]; + *buffer++ = cDigitsLut[d4 + 1]; + } + else + { + // value = aabbbbcccc in decimal - 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(value / kTen16); // 1 to 1844 - value %= kTen16; - - if (a < 10) - *buffer++ = static_cast('0' + static_cast(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('0' + static_cast(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(value / kTen8); - const uint32_t v1 = static_cast(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; -} + const uint32_t a = value / 100000000; // 1 to 42 + value %= 100000000; -inline char* i64toa(int64_t value, char* buffer) { - uint64_t u = static_cast(value); - if (value < 0) { - *buffer++ = '-'; - u = ~u + 1; - } + if(a >= 10) + { + const unsigned i = a << 1; + *buffer++ = cDigitsLut[i]; + *buffer++ = cDigitsLut[i + 1]; + } + else + { + *buffer++ = static_cast('0' + static_cast(a)); + } - return u64toa(u, buffer); -} + 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(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(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(value / kTen8); + const uint32_t v1 = static_cast(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(value / kTen16); // 1 to 1844 + value %= kTen16; + + if(a < 10) + { + *buffer++ = static_cast('0' + static_cast(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('0' + static_cast(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(value / kTen8); + const uint32_t v1 = static_cast(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(value); + if(value < 0) + { + *buffer++ = '-'; + u = ~u + 1; + } + + return u64toa(u, buffer); + } } // namespace internal RAPIDJSON_NAMESPACE_END diff --git a/src/3rdparty/rapidjson/internal/meta.h b/src/3rdparty/rapidjson/internal/meta.h index 5a9aaa42..aca227ee 100644 --- a/src/3rdparty/rapidjson/internal/meta.h +++ b/src/3rdparty/rapidjson/internal/meta.h @@ -1,5 +1,5 @@ // 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 @@ -7,9 +7,9 @@ // // 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 +// 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_ @@ -32,143 +32,186 @@ RAPIDJSON_DIAG_OFF(6334) //@cond RAPIDJSON_INTERNAL RAPIDJSON_NAMESPACE_BEGIN -namespace internal { +namespace internal +{ -// Helper to wrap/convert arbitrary types to void, useful for arbitrary type matching -template struct Void { typedef void Type; }; + // Helper to wrap/convert arbitrary types to void, useful for arbitrary type matching + template struct Void + { + typedef void Type; + }; -/////////////////////////////////////////////////////////////////////////////// -// BoolType, TrueType, FalseType -// -template struct BoolType { - static const bool Value = Cond; - typedef BoolType Type; -}; -typedef BoolType TrueType; -typedef BoolType FalseType; + /////////////////////////////////////////////////////////////////////////////// + // BoolType, TrueType, FalseType + // + template struct BoolType + { + static const bool Value = Cond; + typedef BoolType Type; + }; + typedef BoolType TrueType; + typedef BoolType FalseType; -/////////////////////////////////////////////////////////////////////////////// -// SelectIf, BoolExpr, NotExpr, AndExpr, OrExpr -// + /////////////////////////////////////////////////////////////////////////////// + // SelectIf, BoolExpr, NotExpr, AndExpr, OrExpr + // -template struct SelectIfImpl { template struct Apply { typedef T1 Type; }; }; -template <> struct SelectIfImpl { template struct Apply { typedef T2 Type; }; }; -template struct SelectIfCond : SelectIfImpl::template Apply {}; -template struct SelectIf : SelectIfCond {}; + template struct SelectIfImpl + { + template struct Apply + { + typedef T1 Type; + }; + }; + template <> struct SelectIfImpl + { + template struct Apply + { + typedef T2 Type; + }; + }; + template struct SelectIfCond : SelectIfImpl::template Apply {}; + template struct SelectIf : SelectIfCond {}; -template struct AndExprCond : FalseType {}; -template <> struct AndExprCond : TrueType {}; -template struct OrExprCond : TrueType {}; -template <> struct OrExprCond : FalseType {}; + template struct AndExprCond : FalseType {}; + template <> struct AndExprCond : TrueType {}; + template struct OrExprCond : TrueType {}; + template <> struct OrExprCond : FalseType {}; -template struct BoolExpr : SelectIf::Type {}; -template struct NotExpr : SelectIf::Type {}; -template struct AndExpr : AndExprCond::Type {}; -template struct OrExpr : OrExprCond::Type {}; + template struct BoolExpr : SelectIf::Type {}; + template struct NotExpr : SelectIf::Type {}; + template struct AndExpr : AndExprCond::Type {}; + template struct OrExpr : OrExprCond::Type {}; -/////////////////////////////////////////////////////////////////////////////// -// AddConst, MaybeAddConst, RemoveConst -template struct AddConst { typedef const T Type; }; -template struct MaybeAddConst : SelectIfCond {}; -template struct RemoveConst { typedef T Type; }; -template struct RemoveConst { typedef T Type; }; + /////////////////////////////////////////////////////////////////////////////// + // AddConst, MaybeAddConst, RemoveConst + template struct AddConst + { + typedef const T Type; + }; + template struct MaybeAddConst : SelectIfCond {}; + template struct RemoveConst + { + typedef T Type; + }; + template struct RemoveConst + { + typedef T Type; + }; -/////////////////////////////////////////////////////////////////////////////// -// IsSame, IsConst, IsMoreConst, IsPointer -// -template struct IsSame : FalseType {}; -template struct IsSame : TrueType {}; + /////////////////////////////////////////////////////////////////////////////// + // IsSame, IsConst, IsMoreConst, IsPointer + // + template struct IsSame : FalseType {}; + template struct IsSame : TrueType {}; -template struct IsConst : FalseType {}; -template struct IsConst : TrueType {}; + template struct IsConst : FalseType {}; + template struct IsConst : TrueType {}; -template -struct IsMoreConst - : AndExpr::Type, typename RemoveConst::Type>, - BoolType::Value >= IsConst::Value> >::Type {}; + template + struct IsMoreConst + : AndExpr::Type, typename RemoveConst::Type>, + BoolType::Value >= IsConst::Value> >::Type {}; -template struct IsPointer : FalseType {}; -template struct IsPointer : TrueType {}; + template struct IsPointer : FalseType {}; + template struct IsPointer : TrueType {}; -/////////////////////////////////////////////////////////////////////////////// -// IsBaseOf -// + /////////////////////////////////////////////////////////////////////////////// + // IsBaseOf + // #if RAPIDJSON_HAS_CXX11_TYPETRAITS -template struct IsBaseOf - : BoolType< ::std::is_base_of::value> {}; + template struct IsBaseOf + : BoolType<::std::is_base_of::value> {}; #else // simplified version adopted from Boost -template struct IsBaseOfImpl { - RAPIDJSON_STATIC_ASSERT(sizeof(B) != 0); - RAPIDJSON_STATIC_ASSERT(sizeof(D) != 0); + template struct IsBaseOfImpl + { + RAPIDJSON_STATIC_ASSERT(sizeof(B) != 0); + RAPIDJSON_STATIC_ASSERT(sizeof(D) != 0); - typedef char (&Yes)[1]; - typedef char (&No) [2]; + typedef char(&Yes)[1]; + typedef char(&No) [2]; - template - static Yes Check(const D*, T); - static No Check(const B*, int); + template + static Yes Check(const D*, T); + static No Check(const B*, int); - struct Host { - operator const B*() const; - operator const D*(); - }; + struct Host + { + operator const B* () const; + operator const D* (); + }; - enum { Value = (sizeof(Check(Host(), 0)) == sizeof(Yes)) }; -}; + enum { Value = (sizeof(Check(Host(), 0)) == sizeof(Yes)) }; + }; -template struct IsBaseOf - : OrExpr, BoolExpr > >::Type {}; + template struct IsBaseOf + : OrExpr, BoolExpr>>::Type {}; #endif // RAPIDJSON_HAS_CXX11_TYPETRAITS -////////////////////////////////////////////////////////////////////////// -// EnableIf / DisableIf -// -template struct EnableIfCond { typedef T Type; }; -template struct EnableIfCond { /* empty */ }; + ////////////////////////////////////////////////////////////////////////// + // EnableIf / DisableIf + // + template struct EnableIfCond + { + typedef T Type; + }; + template struct EnableIfCond + { + /* empty */ + }; -template struct DisableIfCond { typedef T Type; }; -template struct DisableIfCond { /* empty */ }; + template struct DisableIfCond + { + typedef T Type; + }; + template struct DisableIfCond + { + /* empty */ + }; -template -struct EnableIf : EnableIfCond {}; + template + struct EnableIf : EnableIfCond {}; -template -struct DisableIf : DisableIfCond {}; + template + struct DisableIf : DisableIfCond {}; -// SFINAE helpers -struct SfinaeTag {}; -template struct RemoveSfinaeTag; -template struct RemoveSfinaeTag { typedef T Type; }; + // SFINAE helpers + struct SfinaeTag {}; + template struct RemoveSfinaeTag; + template struct RemoveSfinaeTag + { + typedef T Type; + }; #define RAPIDJSON_REMOVEFPTR_(type) \ - typename ::RAPIDJSON_NAMESPACE::internal::RemoveSfinaeTag \ - < ::RAPIDJSON_NAMESPACE::internal::SfinaeTag&(*) type>::Type + typename ::RAPIDJSON_NAMESPACE::internal::RemoveSfinaeTag \ + < ::RAPIDJSON_NAMESPACE::internal::SfinaeTag&(*) type>::Type #define RAPIDJSON_ENABLEIF(cond) \ - typename ::RAPIDJSON_NAMESPACE::internal::EnableIf \ - ::Type * = NULL + typename ::RAPIDJSON_NAMESPACE::internal::EnableIf \ + ::Type * = NULL #define RAPIDJSON_DISABLEIF(cond) \ - typename ::RAPIDJSON_NAMESPACE::internal::DisableIf \ - ::Type * = NULL + typename ::RAPIDJSON_NAMESPACE::internal::DisableIf \ + ::Type * = NULL #define RAPIDJSON_ENABLEIF_RETURN(cond,returntype) \ - typename ::RAPIDJSON_NAMESPACE::internal::EnableIf \ - ::Type + typename ::RAPIDJSON_NAMESPACE::internal::EnableIf \ + ::Type #define RAPIDJSON_DISABLEIF_RETURN(cond,returntype) \ - typename ::RAPIDJSON_NAMESPACE::internal::DisableIf \ - ::Type + typename ::RAPIDJSON_NAMESPACE::internal::DisableIf \ + ::Type } // namespace internal RAPIDJSON_NAMESPACE_END diff --git a/src/3rdparty/rapidjson/internal/pow10.h b/src/3rdparty/rapidjson/internal/pow10.h index 02f475d7..523d305e 100644 --- a/src/3rdparty/rapidjson/internal/pow10.h +++ b/src/3rdparty/rapidjson/internal/pow10.h @@ -1,5 +1,5 @@ // 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 @@ -7,9 +7,9 @@ // // 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 +// 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_ @@ -18,36 +18,39 @@ #include "../rapidjson.h" RAPIDJSON_NAMESPACE_BEGIN -namespace internal { +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]; -} + //! 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 diff --git a/src/3rdparty/rapidjson/internal/regex.h b/src/3rdparty/rapidjson/internal/regex.h index 422a5240..ee97fe49 100644 --- a/src/3rdparty/rapidjson/internal/regex.h +++ b/src/3rdparty/rapidjson/internal/regex.h @@ -1,5 +1,5 @@ // 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 @@ -7,9 +7,9 @@ // // 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 +// 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_ @@ -22,672 +22,840 @@ #ifdef __clang__ RAPIDJSON_DIAG_PUSH RAPIDJSON_DIAG_OFF(padded) -RAPIDJSON_DIAG_OFF(switch-enum) -RAPIDJSON_DIAG_OFF(implicit-fallthrough) +RAPIDJSON_DIAG_OFF(switch - enum) + RAPIDJSON_DIAG_OFF(implicit - fallthrough) #endif #ifdef __GNUC__ -RAPIDJSON_DIAG_PUSH -RAPIDJSON_DIAG_OFF(effc++) + RAPIDJSON_DIAG_PUSH + RAPIDJSON_DIAG_OFF(effc++) #endif #ifdef _MSC_VER -RAPIDJSON_DIAG_PUSH -RAPIDJSON_DIAG_OFF(4512) // assignment operator could not be generated + 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 { + RAPIDJSON_NAMESPACE_BEGIN + namespace internal + { -/////////////////////////////////////////////////////////////////////////////// -// GenericRegex + /////////////////////////////////////////////////////////////////////////////// + // GenericRegex -static const SizeType kRegexInvalidState = ~SizeType(0); //!< Represents an invalid index in GenericRegex::State::out, out1 -static const SizeType kRegexInvalidRange = ~SizeType(0); + 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) + //! 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 -class GenericRegex { -public: - typedef typename Encoding::Ch Ch; + \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 + 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 ss(source); - DecodedStream > ds(ss); - Parse(ds); - } + 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 ss(source); + DecodedStream> ds(ss); + Parse(ds); + } - ~GenericRegex() { - Allocator::Free(stateSet_); - } + ~GenericRegex() + { + Allocator::Free(stateSet_); + } - bool IsValid() const { - return root_ != kRegexInvalidState; - } + bool IsValid() const + { + return root_ != kRegexInvalidState; + } - template - bool Match(InputStream& is) const { - return SearchWithAnchoring(is, true, true); - } + template + bool Match(InputStream & is) const + { + return SearchWithAnchoring(is, true, true); + } - bool Match(const Ch* s) const { - GenericStringStream is(s); - return Match(is); - } + bool Match(const Ch* s) const + { + GenericStringStream is(s); + return Match(is); + } - template - bool Search(InputStream& is) const { - return SearchWithAnchoring(is, anchorBegin_, anchorEnd_); - } + template + bool Search(InputStream & is) const + { + return SearchWithAnchoring(is, anchorBegin_, anchorEnd_); + } - bool Search(const Ch* s) const { - GenericStringStream is(s); - return Search(is); - } + bool Search(const Ch* s) const + { + GenericStringStream is(s); + return Search(is); + } -private: - enum Operator { - kZeroOrOne, - kZeroOrMore, - kOneOrMore, - kConcatenation, - kAlternation, - kLeftParenthesis - }; + 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; + 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 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 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; - }; + 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 - 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; - } + template + 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; - } + private: + void Decode() + { + if(!Encoding::Decode(ss_, &codepoint_)) + { + codepoint_ = 0; + } + } - SourceStream& ss_; - unsigned codepoint_; - }; + SourceStream & ss_; + unsigned codepoint_; + }; - State& GetState(SizeType index) { - RAPIDJSON_ASSERT(index < stateCount_); - return states_.template Bottom()[index]; - } + State & GetState(SizeType index) + { + RAPIDJSON_ASSERT(index < stateCount_); + return states_.template Bottom()[index]; + } - const State& GetState(SizeType index) const { - RAPIDJSON_ASSERT(index < stateCount_); - return states_.template Bottom()[index]; - } + const State & GetState(SizeType index) const + { + RAPIDJSON_ASSERT(index < stateCount_); + return states_.template Bottom()[index]; + } - Range& GetRange(SizeType index) { - RAPIDJSON_ASSERT(index < rangeCount_); - return ranges_.template Bottom()[index]; - } + Range & GetRange(SizeType index) + { + RAPIDJSON_ASSERT(index < rangeCount_); + return ranges_.template Bottom()[index]; + } - const Range& GetRange(SizeType index) const { - RAPIDJSON_ASSERT(index < rangeCount_); - return ranges_.template Bottom()[index]; - } + const Range & GetRange(SizeType index) const + { + RAPIDJSON_ASSERT(index < rangeCount_); + return ranges_.template Bottom()[index]; + } - template - void Parse(DecodedStream& ds) { - Allocator allocator; - Stack operandStack(&allocator, 256); // Frag - Stack operatorStack(&allocator, 256); // Operator - Stack atomCountStack(&allocator, 256); // unsigned (Atom per parenthesis) + template + void Parse(DecodedStream & ds) + { + Allocator allocator; + Stack operandStack(&allocator, 256); // Frag + Stack operatorStack(&allocator, 256); // Operator + Stack atomCountStack(&allocator, 256); // unsigned (Atom per parenthesis) - *atomCountStack.template Push() = 0; + *atomCountStack.template Push() = 0; - unsigned codepoint; - while (ds.Peek() != 0) { - switch (codepoint = ds.Take()) { - case '^': - anchorBegin_ = true; - break; + unsigned codepoint; + while(ds.Peek() != 0) + { + switch(codepoint = ds.Take()) + { + case '^': + anchorBegin_ = true; + break; - case '$': - anchorEnd_ = true; - break; + case '$': + anchorEnd_ = true; + break; - case '|': - while (!operatorStack.Empty() && *operatorStack.template Top() < kAlternation) - if (!Eval(operandStack, *operatorStack.template Pop(1))) - return; - *operatorStack.template Push() = kAlternation; - *atomCountStack.template Top() = 0; - break; + case '|': + while(!operatorStack.Empty() && *operatorStack.template Top() < kAlternation) + if(!Eval(operandStack, *operatorStack.template Pop(1))) + { + return; + } + *operatorStack.template Push() = kAlternation; + *atomCountStack.template Top() = 0; + break; - case '(': - *operatorStack.template Push() = kLeftParenthesis; - *atomCountStack.template Push() = 0; - break; + case '(': + *operatorStack.template Push() = kLeftParenthesis; + *atomCountStack.template Push() = 0; + break; - case ')': - while (!operatorStack.Empty() && *operatorStack.template Top() != kLeftParenthesis) - if (!Eval(operandStack, *operatorStack.template Pop(1))) - return; - if (operatorStack.Empty()) - return; - operatorStack.template Pop(1); - atomCountStack.template Pop(1); - ImplicitConcatenation(atomCountStack, operatorStack); - break; + case ')': + while(!operatorStack.Empty() && *operatorStack.template Top() != kLeftParenthesis) + if(!Eval(operandStack, *operatorStack.template Pop(1))) + { + return; + } + if(operatorStack.Empty()) + { + return; + } + operatorStack.template Pop(1); + atomCountStack.template Pop(1); + ImplicitConcatenation(atomCountStack, operatorStack); + break; - case '?': - if (!Eval(operandStack, kZeroOrOne)) - return; - break; + case '?': + if(!Eval(operandStack, kZeroOrOne)) + { + return; + } + break; - case '*': - if (!Eval(operandStack, kZeroOrMore)) - return; - break; + case '*': + if(!Eval(operandStack, kZeroOrMore)) + { + return; + } + break; - case '+': - if (!Eval(operandStack, kOneOrMore)) - return; - break; + case '+': + if(!Eval(operandStack, kOneOrMore)) + { + return; + } + break; - case '{': - { - unsigned n, m; - if (!ParseUnsigned(ds, &n)) - return; + 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(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; + if(!EvalQuantifier(operandStack, n, m) || ds.Peek() != '}') + { + return; + } + ds.Take(); + } + break; - case '.': - PushOperand(operandStack, kAnyCharacterClass); - ImplicitConcatenation(atomCountStack, operatorStack); - 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(s, s, s); - } - 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(s, s, s); + } + ImplicitConcatenation(atomCountStack, operatorStack); + break; - case '\\': // Escape character - if (!CharacterEscape(ds, &codepoint)) - return; // Unsupported escape character - // fall through to default + case '\\': // Escape character + if(!CharacterEscape(ds, &codepoint)) + { + return; // Unsupported escape character + } + // fall through to default - default: // Pattern character - PushOperand(operandStack, codepoint); - ImplicitConcatenation(atomCountStack, operatorStack); - } - } + default: // Pattern character + PushOperand(operandStack, codepoint); + ImplicitConcatenation(atomCountStack, operatorStack); + } + } - while (!operatorStack.Empty()) - if (!Eval(operandStack, *operatorStack.template Pop(1))) - return; + while(!operatorStack.Empty()) + if(!Eval(operandStack, *operatorStack.template Pop(1))) + { + return; + } - // Link the operand to matching state. - if (operandStack.GetSize() == sizeof(Frag)) { - Frag* e = operandStack.template Pop(1); - Patch(e->out, NewState(kRegexInvalidState, kRegexInvalidState, 0)); - root_ = e->start; + // Link the operand to matching state. + if(operandStack.GetSize() == sizeof(Frag)) + { + Frag* e = operandStack.template Pop(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"); + 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(states_.GetAllocator().Malloc(GetStateSetSize())); - state0_.template Reserve(stateCount_); - state1_.template Reserve(stateCount_); - } - } + // Preallocate buffer for SearchWithAnchoring() + RAPIDJSON_ASSERT(stateSet_ == 0); + if(stateCount_ > 0) + { + stateSet_ = static_cast(states_.GetAllocator().Malloc(GetStateSetSize())); + state0_.template Reserve(stateCount_); + state1_.template Reserve(stateCount_); + } + } - SizeType NewState(SizeType out, SizeType out1, unsigned codepoint) { - State* s = states_.template Push(); - s->out = out; - s->out1 = out1; - s->codepoint = codepoint; - s->rangeStart = kRegexInvalidRange; - return stateCount_++; - } + SizeType NewState(SizeType out, SizeType out1, unsigned codepoint) + { + State* s = states_.template Push(); + s->out = out; + s->out1 = out1; + s->codepoint = codepoint; + s->rangeStart = kRegexInvalidRange; + return stateCount_++; + } - void PushOperand(Stack& operandStack, unsigned codepoint) { - SizeType s = NewState(kRegexInvalidState, kRegexInvalidState, codepoint); - *operandStack.template Push() = Frag(s, s, s); - } + void PushOperand(Stack & operandStack, unsigned codepoint) + { + SizeType s = NewState(kRegexInvalidState, kRegexInvalidState, codepoint); + *operandStack.template Push() = Frag(s, s, s); + } - void ImplicitConcatenation(Stack& atomCountStack, Stack& operatorStack) { - if (*atomCountStack.template Top()) - *operatorStack.template Push() = kConcatenation; - (*atomCountStack.template Top())++; - } + void ImplicitConcatenation(Stack & atomCountStack, Stack & operatorStack) + { + if(*atomCountStack.template Top()) + { + *operatorStack.template Push() = kConcatenation; + } + (*atomCountStack.template Top())++; + } - SizeType Append(SizeType l1, SizeType l2) { - SizeType old = l1; - while (GetState(l1).out != kRegexInvalidState) - l1 = GetState(l1).out; - GetState(l1).out = l2; - return old; - } + 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; - } - } + void Patch(SizeType l, SizeType s) + { + for(SizeType next; l != kRegexInvalidState; l = next) + { + next = GetState(l).out; + GetState(l).out = s; + } + } - bool Eval(Stack& operandStack, Operator op) { - switch (op) { - case kConcatenation: - RAPIDJSON_ASSERT(operandStack.GetSize() >= sizeof(Frag) * 2); - { - Frag e2 = *operandStack.template Pop(1); - Frag e1 = *operandStack.template Pop(1); - Patch(e1.out, e2.start); - *operandStack.template Push() = Frag(e1.start, e2.out, Min(e1.minIndex, e2.minIndex)); - } - return true; + bool Eval(Stack & operandStack, Operator op) + { + switch(op) + { + case kConcatenation: + RAPIDJSON_ASSERT(operandStack.GetSize() >= sizeof(Frag) * 2); + { + Frag e2 = *operandStack.template Pop(1); + Frag e1 = *operandStack.template Pop(1); + Patch(e1.out, e2.start); + *operandStack.template Push() = 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(1); - Frag e1 = *operandStack.template Pop(1); - SizeType s = NewState(e1.start, e2.start, 0); - *operandStack.template Push() = Frag(s, Append(e1.out, e2.out), Min(e1.minIndex, e2.minIndex)); - return true; - } - return false; + case kAlternation: + if(operandStack.GetSize() >= sizeof(Frag) * 2) + { + Frag e2 = *operandStack.template Pop(1); + Frag e1 = *operandStack.template Pop(1); + SizeType s = NewState(e1.start, e2.start, 0); + *operandStack.template Push() = 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(1); - SizeType s = NewState(kRegexInvalidState, e.start, 0); - *operandStack.template Push() = Frag(s, Append(e.out, s), e.minIndex); - return true; - } - return false; + case kZeroOrOne: + if(operandStack.GetSize() >= sizeof(Frag)) + { + Frag e = *operandStack.template Pop(1); + SizeType s = NewState(kRegexInvalidState, e.start, 0); + *operandStack.template Push() = Frag(s, Append(e.out, s), e.minIndex); + return true; + } + return false; - case kZeroOrMore: - if (operandStack.GetSize() >= sizeof(Frag)) { - Frag e = *operandStack.template Pop(1); - SizeType s = NewState(kRegexInvalidState, e.start, 0); - Patch(e.out, s); - *operandStack.template Push() = Frag(s, s, e.minIndex); - return true; - } - return false; + case kZeroOrMore: + if(operandStack.GetSize() >= sizeof(Frag)) + { + Frag e = *operandStack.template Pop(1); + SizeType s = NewState(kRegexInvalidState, e.start, 0); + Patch(e.out, s); + *operandStack.template Push() = Frag(s, s, e.minIndex); + return true; + } + return false; - default: - RAPIDJSON_ASSERT(op == kOneOrMore); - if (operandStack.GetSize() >= sizeof(Frag)) { - Frag e = *operandStack.template Pop(1); - SizeType s = NewState(kRegexInvalidState, e.start, 0); - Patch(e.out, s); - *operandStack.template Push() = Frag(e.start, s, e.minIndex); - return true; - } - return false; - } - } + default: + RAPIDJSON_ASSERT(op == kOneOrMore); + if(operandStack.GetSize() >= sizeof(Frag)) + { + Frag e = *operandStack.template Pop(1); + SizeType s = NewState(kRegexInvalidState, e.start, 0); + Patch(e.out, s); + *operandStack.template Push() = Frag(e.start, s, e.minIndex); + return true; + } + return false; + } + } - bool EvalQuantifier(Stack& operandStack, unsigned n, unsigned m) { - RAPIDJSON_ASSERT(n <= m); - RAPIDJSON_ASSERT(operandStack.GetSize() >= sizeof(Frag)); + bool EvalQuantifier(Stack & 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; - } + 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); + 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? - } + 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? + for(unsigned i = 0; i < n - 1; i++) + { + Eval(operandStack, kConcatenation); + } // a{3} -> aaa, a{3,} -> aaa+, a{3.5} -> aaaa?a? - return true; - } + return true; + } - static SizeType Min(SizeType a, SizeType b) { return a < b ? a : b; } + static SizeType Min(SizeType a, SizeType b) + { + return a < b ? a : b; + } - void CloneTopOperand(Stack& operandStack) { - const Frag src = *operandStack.template Top(); // Copy constructor to prevent invalidation - SizeType count = stateCount_ - src.minIndex; // Assumes top operand contains states in [src->minIndex, stateCount_) - State* s = states_.template Push(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(src.start + count, src.out + count, src.minIndex + count); - stateCount_ += count; - } + void CloneTopOperand(Stack & operandStack) + { + const Frag src = *operandStack.template Top(); // Copy constructor to prevent invalidation + SizeType count = stateCount_ - + src.minIndex; // Assumes top operand contains states in [src->minIndex, stateCount_) + State* s = states_.template Push(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(src.start + count, src.out + count, src.minIndex + count); + stateCount_ += count; + } - template - bool ParseUnsigned(DecodedStream& 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 + bool ParseUnsigned(DecodedStream & 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 - bool ParseRange(DecodedStream& 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; - } - } + template + bool ParseRange(DecodedStream & 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; + 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 + 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 + 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; + 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(); - r->start = r->end = codepoint; - r->next = kRegexInvalidRange; - return rangeCount_++; - } + default: + RAPIDJSON_ASSERT(step == 2); + GetRange(current).end = codepoint; + step = 0; + } + } + } + return false; + } - template - bool CharacterEscape(DecodedStream& 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 - } - } + SizeType NewRange(unsigned codepoint) + { + Range* r = ranges_.template Push(); + r->start = r->end = codepoint; + r->next = kRegexInvalidRange; + return rangeCount_++; + } - template - bool SearchWithAnchoring(InputStream& is, bool anchorBegin, bool anchorEnd) const { - RAPIDJSON_ASSERT(IsValid()); - DecodedStream ds(is); + template + bool CharacterEscape(DecodedStream & 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 + } + } - state0_.Clear(); - Stack *current = &state0_, *next = &state1_; - const size_t stateSetSize = GetStateSetSize(); - std::memset(stateSet_, 0, stateSetSize); + template + bool SearchWithAnchoring(InputStream & is, bool anchorBegin, bool anchorEnd) const + { + RAPIDJSON_ASSERT(IsValid()); + DecodedStream ds(is); - 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(); s != current->template End(); ++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); - } + state0_.Clear(); + Stack* current = &state0_, *next = &state1_; + const size_t stateSetSize = GetStateSetSize(); + std::memset(stateSet_, 0, stateSetSize); - return matched; - } + 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(); s != current->template End(); ++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); + } - size_t GetStateSetSize() const { - return (stateCount_ + 31) / 32 * 4; - } + return matched; + } - // Return whether the added states is a match state - bool AddState(Stack& l, SizeType index) const { - RAPIDJSON_ASSERT(index != kRegexInvalidState); + size_t GetStateSetSize() const + { + return (stateCount_ + 31) / 32 * 4; + } - 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() = index; - } - return s.out == kRegexInvalidState; // by using PushUnsafe() above, we can ensure s is not validated due to reallocation. - } + // Return whether the added states is a match state + bool AddState(Stack & l, SizeType index) const + { + RAPIDJSON_ASSERT(index != kRegexInvalidState); - 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; - } + 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() = index; + } + return s.out == + kRegexInvalidState; // by using PushUnsafe() above, we can ensure s is not validated due to reallocation. + } - Stack states_; - Stack ranges_; - SizeType root_; - SizeType stateCount_; - SizeType rangeCount_; + 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; + } - static const unsigned kInfinityQuantifier = ~0u; + Stack states_; + Stack ranges_; + SizeType root_; + SizeType stateCount_; + SizeType rangeCount_; - // For SearchWithAnchoring() - uint32_t* stateSet_; // allocated by states_.GetAllocator() - mutable Stack state0_; - mutable Stack state1_; - bool anchorBegin_; - bool anchorEnd_; -}; + static const unsigned kInfinityQuantifier = ~0u; -typedef GenericRegex > Regex; + // For SearchWithAnchoring() + uint32_t* stateSet_; // allocated by states_.GetAllocator() + mutable Stack state0_; + mutable Stack state1_; + bool anchorBegin_; + bool anchorEnd_; + }; -} // namespace internal + typedef GenericRegex> Regex; + + } // namespace internal RAPIDJSON_NAMESPACE_END #ifdef __clang__ diff --git a/src/3rdparty/rapidjson/internal/stack.h b/src/3rdparty/rapidjson/internal/stack.h index 022c9aab..999a5602 100644 --- a/src/3rdparty/rapidjson/internal/stack.h +++ b/src/3rdparty/rapidjson/internal/stack.h @@ -1,5 +1,5 @@ // 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 @@ -7,9 +7,9 @@ // // 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 +// 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_ @@ -20,205 +20,260 @@ #if defined(__clang__) RAPIDJSON_DIAG_PUSH -RAPIDJSON_DIAG_OFF(c++98-compat) +RAPIDJSON_DIAG_OFF(c++98 - compat) #endif RAPIDJSON_NAMESPACE_BEGIN -namespace internal { +namespace internal +{ -/////////////////////////////////////////////////////////////////////////////// -// Stack + /////////////////////////////////////////////////////////////////////////////// + // Stack -//! A type-unsafe stack for storing different types of data. -/*! \tparam Allocator Allocator for allocating stack memory. -*/ -template -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) { - } + //! A type-unsafe stack for storing different types of data. + /*! \tparam Allocator Allocator for allocating stack memory. + */ + template + 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; - } + 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(); - } + ~Stack() + { + Destroy(); + } #if RAPIDJSON_HAS_CXX11_RVALUE_REFS - Stack& operator=(Stack&& rhs) { - if (&rhs != this) - { - Destroy(); + 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_; + 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; - } + 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 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 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()); - } + 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 - RAPIDJSON_FORCEINLINE void Reserve(size_t count = 1) { - // Expand the stack if needed - if (RAPIDJSON_UNLIKELY(stackTop_ + sizeof(T) * count > stackEnd_)) - Expand(count); - } + // 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 + RAPIDJSON_FORCEINLINE void Reserve(size_t count = 1) + { + // Expand the stack if needed + if(RAPIDJSON_UNLIKELY(stackTop_ + sizeof(T) * count > stackEnd_)) + { + Expand(count); + } + } - template - RAPIDJSON_FORCEINLINE T* Push(size_t count = 1) { - Reserve(count); - return PushUnsafe(count); - } + template + RAPIDJSON_FORCEINLINE T* Push(size_t count = 1) + { + Reserve(count); + return PushUnsafe(count); + } - template - RAPIDJSON_FORCEINLINE T* PushUnsafe(size_t count = 1) { - RAPIDJSON_ASSERT(stackTop_ + sizeof(T) * count <= stackEnd_); - T* ret = reinterpret_cast(stackTop_); - stackTop_ += sizeof(T) * count; - return ret; - } + template + RAPIDJSON_FORCEINLINE T* PushUnsafe(size_t count = 1) + { + RAPIDJSON_ASSERT(stackTop_ + sizeof(T) * count <= stackEnd_); + T* ret = reinterpret_cast(stackTop_); + stackTop_ += sizeof(T) * count; + return ret; + } - template - T* Pop(size_t count) { - RAPIDJSON_ASSERT(GetSize() >= count * sizeof(T)); - stackTop_ -= count * sizeof(T); - return reinterpret_cast(stackTop_); - } + template + T* Pop(size_t count) + { + RAPIDJSON_ASSERT(GetSize() >= count * sizeof(T)); + stackTop_ -= count * sizeof(T); + return reinterpret_cast(stackTop_); + } - template - T* Top() { - RAPIDJSON_ASSERT(GetSize() >= sizeof(T)); - return reinterpret_cast(stackTop_ - sizeof(T)); - } + template + T* Top() + { + RAPIDJSON_ASSERT(GetSize() >= sizeof(T)); + return reinterpret_cast(stackTop_ - sizeof(T)); + } - template - const T* Top() const { - RAPIDJSON_ASSERT(GetSize() >= sizeof(T)); - return reinterpret_cast(stackTop_ - sizeof(T)); - } + template + const T* Top() const + { + RAPIDJSON_ASSERT(GetSize() >= sizeof(T)); + return reinterpret_cast(stackTop_ - sizeof(T)); + } - template - T* End() { return reinterpret_cast(stackTop_); } + template + T* End() + { + return reinterpret_cast(stackTop_); + } - template - const T* End() const { return reinterpret_cast(stackTop_); } + template + const T* End() const + { + return reinterpret_cast(stackTop_); + } - template - T* Bottom() { return reinterpret_cast(stack_); } + template + T* Bottom() + { + return reinterpret_cast(stack_); + } - template - const T* Bottom() const { return reinterpret_cast(stack_); } + template + const T* Bottom() const + { + return reinterpret_cast(stack_); + } - bool HasAllocator() const { - return allocator_ != 0; - } + bool HasAllocator() const + { + return allocator_ != 0; + } - Allocator& GetAllocator() { - RAPIDJSON_ASSERT(allocator_); - return *allocator_; - } + Allocator & GetAllocator() + { + RAPIDJSON_ASSERT(allocator_); + return *allocator_; + } - bool Empty() const { return stackTop_ == stack_; } - size_t GetSize() const { return static_cast(stackTop_ - stack_); } - size_t GetCapacity() const { return static_cast(stackEnd_ - stack_); } + bool Empty() const + { + return stackTop_ == stack_; + } + size_t GetSize() const + { + return static_cast(stackTop_ - stack_); + } + size_t GetCapacity() const + { + return static_cast(stackEnd_ - stack_); + } -private: - template - 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; + private: + template + 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); - } + Resize(newCapacity); + } - void Resize(size_t newCapacity) { - const size_t size = GetSize(); // Backup the current size - stack_ = static_cast(allocator_->Realloc(stack_, GetCapacity(), newCapacity)); - stackTop_ = stack_ + size; - stackEnd_ = stack_ + newCapacity; - } + void Resize(size_t newCapacity) + { + const size_t size = GetSize(); // Backup the current size + stack_ = static_cast(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 - } + 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&); + // 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_; -}; + Allocator* allocator_; + Allocator* ownAllocator_; + char* stack_; + char* stackTop_; + char* stackEnd_; + size_t initialCapacity_; + }; } // namespace internal RAPIDJSON_NAMESPACE_END diff --git a/src/3rdparty/rapidjson/internal/strfunc.h b/src/3rdparty/rapidjson/internal/strfunc.h index 2edfae52..1bff5e79 100644 --- a/src/3rdparty/rapidjson/internal/strfunc.h +++ b/src/3rdparty/rapidjson/internal/strfunc.h @@ -1,5 +1,5 @@ // 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 @@ -7,9 +7,9 @@ // // 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 +// 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_ @@ -18,36 +18,45 @@ #include "../stream.h" RAPIDJSON_NAMESPACE_BEGIN -namespace internal { +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 -inline SizeType StrLen(const Ch* s) { - const Ch* p = s; - while (*p) ++p; - return SizeType(p - s); -} + //! 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 + 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 -bool CountStringCodePoint(const typename Encoding::Ch* s, SizeType length, SizeType* outCount) { - GenericStringStream 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; -} + //! Returns number of code points in a encoded string. + template + bool CountStringCodePoint(const typename Encoding::Ch* s, SizeType length, SizeType* outCount) + { + GenericStringStream 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 diff --git a/src/3rdparty/rapidjson/internal/strtod.h b/src/3rdparty/rapidjson/internal/strtod.h index 289c413b..0eeb2d88 100644 --- a/src/3rdparty/rapidjson/internal/strtod.h +++ b/src/3rdparty/rapidjson/internal/strtod.h @@ -1,5 +1,5 @@ // 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 @@ -7,9 +7,9 @@ // // 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 +// 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_ @@ -21,247 +21,316 @@ #include "pow10.h" RAPIDJSON_NAMESPACE_BEGIN -namespace internal { +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 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; -} + 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 -inline T Min3(T a, T b, T c) { - T m = a; - if (m > b) m = b; - if (m > c) m = c; - return m; -} + template + 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; + 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; + 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 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 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; - } + // 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; + // 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(dS_Exp5)) <<= static_cast(dS_Exp2); + BigInteger dS = d; + dS.MultiplyPow5(static_cast(dS_Exp5)) <<= static_cast(dS_Exp2); - BigInteger bS(bInt); - bS.MultiplyPow5(static_cast(bS_Exp5)) <<= static_cast(bS_Exp2); + BigInteger bS(bInt); + bS.MultiplyPow5(static_cast(bS_Exp5)) <<= static_cast(bS_Exp2); - BigInteger hS(1); - hS.MultiplyPow5(static_cast(hS_Exp5)) <<= static_cast(hS_Exp2); + BigInteger hS(1); + hS.MultiplyPow5(static_cast(hS_Exp5)) <<= static_cast(hS_Exp2); - BigInteger delta(0); - dS.Difference(bS, &delta); + BigInteger delta(0); + dS.Difference(bS, &delta); - return delta.Compare(hS); -} + 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; - } + 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; -} + 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(decimals[i] - '0'); - } - - if (i < length && decimals[i] >= '5') // Rounding - significand++; + // 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(decimals[i] - '0'); + } - size_t remaining = length - i; - const unsigned kUlpShift = 3; - const unsigned kUlp = 1 << kUlpShift; - int64_t error = (remaining == 0) ? 0 : kUlp / 2; + if(i < length && decimals[i] >= '5') // Rounding + { + significand++; + } - DiyFp v(significand, 0); - v = v.Normalize(); - error <<= -v.e; + size_t remaining = length - i; + const unsigned kUlpShift = 3; + const unsigned kUlp = 1 << kUlpShift; + int64_t error = (remaining == 0) ? 0 : kUlp / 2; - const int dExp = static_cast(decimalPosition) - static_cast(i) + exp; + DiyFp v(significand, 0); + v = v.Normalize(); + error <<= -v.e; - 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(adjustment)> 19u) // has more digits than decimal digits in 64-bit - error += kUlp / 2; - } + const int dExp = static_cast(decimalPosition) - static_cast(i) + exp; - v = v * cachedPower; + 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(adjustment) > 19u) // has more digits than decimal digits in 64-bit + { + error += kUlp / 2; + } + } - error += kUlp + (error == 0 ? 0 : 1); + v = v * cachedPower; - const int oldExp = v.e; - v = v.Normalize(); - error <<= oldExp - v.e; + error += kUlp + (error == 0 ? 0 : 1); - 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(kUlp); - precisionSize -= scaleExp; - } + const int oldExp = v.e; + v = v.Normalize(); + error <<= oldExp - v.e; - DiyFp rounded(v.f >> precisionSize, v.e + static_cast(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(error)) { - rounded.f++; - if (rounded.f & (DiyFp::kDpHiddenBit << 1)) { // rounding overflows mantissa (issue #340) - rounded.f >>= 1; - rounded.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(kUlp); + precisionSize -= scaleExp; + } - *result = rounded.ToDouble(); + DiyFp rounded(v.f >> precisionSize, v.e + static_cast(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(error)) + { + rounded.f++; + if(rounded.f & (DiyFp::kDpHiddenBit << 1)) // rounding overflows mantissa (issue #340) + { + rounded.f >>= 1; + rounded.e++; + } + } - return halfWay - static_cast(error) >= precisionBits || precisionBits >= halfWay + static_cast(error); -} + *result = rounded.ToDouble(); -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(decimalPosition) - static_cast(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(); -} + return halfWay - static_cast(error) >= precisionBits || + precisionBits >= halfWay + static_cast(error); + } -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); + 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(decimalPosition) - static_cast(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(); + } + } - double result; - if (StrtodFast(d, p, &result)) - return result; + 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); - // Trim leading zeros - while (*decimals == '0' && length > 1) { - length--; - decimals++; - decimalPosition--; - } + double result; + if(StrtodFast(d, p, &result)) + { + return result; + } - // Trim trailing zeros - while (decimals[length - 1] == '0' && length > 1) { - length--; - decimalPosition--; - exp++; - } + // Trim leading zeros + while(*decimals == '0' && length > 1) + { + length--; + decimals++; + decimalPosition--; + } - // Trim right-most digits - const int kMaxDecimalDigit = 780; - if (static_cast(length) > kMaxDecimalDigit) { - int delta = (static_cast(length) - kMaxDecimalDigit); - exp += delta; - decimalPosition -= static_cast(delta); - length = kMaxDecimalDigit; - } + // Trim trailing zeros + while(decimals[length - 1] == '0' && length > 1) + { + length--; + decimalPosition--; + exp++; + } - // If too small, underflow to zero - if (int(length) + exp < -324) - return 0.0; + // Trim right-most digits + const int kMaxDecimalDigit = 780; + if(static_cast(length) > kMaxDecimalDigit) + { + int delta = (static_cast(length) - kMaxDecimalDigit); + exp += delta; + decimalPosition -= static_cast(delta); + length = kMaxDecimalDigit; + } - if (StrtodDiyFp(decimals, length, decimalPosition, exp, &result)) - return result; + // If too small, underflow to zero + if(int(length) + exp < -324) + { + return 0.0; + } - // Use approximation from StrtodDiyFp and make adjustment with BigInteger comparison - return StrtodBigInteger(result, decimals, length, decimalPosition, exp); -} + 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 diff --git a/src/3rdparty/rapidjson/internal/swap.h b/src/3rdparty/rapidjson/internal/swap.h index 666e49f9..33e7ca4f 100644 --- a/src/3rdparty/rapidjson/internal/swap.h +++ b/src/3rdparty/rapidjson/internal/swap.h @@ -19,22 +19,24 @@ #if defined(__clang__) RAPIDJSON_DIAG_PUSH -RAPIDJSON_DIAG_OFF(c++98-compat) +RAPIDJSON_DIAG_OFF(c++98 - compat) #endif RAPIDJSON_NAMESPACE_BEGIN -namespace internal { +namespace internal +{ -//! Custom swap() to avoid dependency on C++ 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 -inline void Swap(T& a, T& b) RAPIDJSON_NOEXCEPT { - T tmp = a; - a = b; - b = tmp; -} + //! Custom swap() to avoid dependency on C++ 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 + inline void Swap(T & a, T & b) RAPIDJSON_NOEXCEPT + { + T tmp = a; + a = b; + b = tmp; + } } // namespace internal RAPIDJSON_NAMESPACE_END diff --git a/src/3rdparty/rapidjson/istreamwrapper.h b/src/3rdparty/rapidjson/istreamwrapper.h index f5fe2897..9b3b5f8e 100644 --- a/src/3rdparty/rapidjson/istreamwrapper.h +++ b/src/3rdparty/rapidjson/istreamwrapper.h @@ -1,5 +1,5 @@ // 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 @@ -7,9 +7,9 @@ // // 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 +// 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_ @@ -45,62 +45,90 @@ RAPIDJSON_NAMESPACE_BEGIN \tparam StreamType Class derived from \c std::basic_istream. */ - + template -class BasicIStreamWrapper { +class BasicIStreamWrapper +{ public: - typedef typename StreamType::char_type Ch; - BasicIStreamWrapper(StreamType& stream) : stream_(stream), count_(), peekBuffer_() {} + 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(c) : '\0'; - } + Ch Peek() const + { + typename StreamType::int_type c = stream_.peek(); + return RAPIDJSON_LIKELY(c != StreamType::traits_type::eof()) ? static_cast(c) : '\0'; + } - Ch Take() { - typename StreamType::int_type c = stream_.get(); - if (RAPIDJSON_LIKELY(c != StreamType::traits_type::eof())) { - count_++; - return static_cast(c); - } - else - return '\0'; - } + Ch Take() + { + typename StreamType::int_type c = stream_.get(); + if(RAPIDJSON_LIKELY(c != StreamType::traits_type::eof())) + { + count_++; + return static_cast(c); + } + else + { + return '\0'; + } + } - // tellg() may return -1 when failed. So we count by ourself. - size_t Tell() const { return count_; } + // 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; } + 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(c); - } - for (--i; i >= 0; --i) - stream_.putback(peekBuffer_[i]); - return !hasError ? peekBuffer_ : 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(c); + } + for(--i; i >= 0; --i) + { + stream_.putback(peekBuffer_[i]); + } + return !hasError ? peekBuffer_ : 0; + } private: - BasicIStreamWrapper(const BasicIStreamWrapper&); - BasicIStreamWrapper& operator=(const BasicIStreamWrapper&); + BasicIStreamWrapper(const BasicIStreamWrapper &); + BasicIStreamWrapper & operator=(const BasicIStreamWrapper &); - StreamType& stream_; - size_t count_; //!< Number of characters read. Note: - mutable Ch peekBuffer_[4]; + StreamType & stream_; + size_t count_; //!< Number of characters read. Note: + mutable Ch peekBuffer_[4]; }; typedef BasicIStreamWrapper IStreamWrapper; diff --git a/src/3rdparty/rapidjson/memorybuffer.h b/src/3rdparty/rapidjson/memorybuffer.h index 39bee1de..fde02c51 100644 --- a/src/3rdparty/rapidjson/memorybuffer.h +++ b/src/3rdparty/rapidjson/memorybuffer.h @@ -1,5 +1,5 @@ // 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 @@ -7,9 +7,9 @@ // // 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 +// 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_ @@ -27,42 +27,64 @@ RAPIDJSON_NAMESPACE_BEGIN 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. + 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 -struct GenericMemoryBuffer { - typedef char Ch; // byte +struct GenericMemoryBuffer +{ + typedef char Ch; // byte - GenericMemoryBuffer(Allocator* allocator = 0, size_t capacity = kDefaultCapacity) : stack_(allocator, capacity) {} + GenericMemoryBuffer(Allocator* allocator = 0, size_t capacity = kDefaultCapacity) : stack_(allocator, + capacity) {} - void Put(Ch c) { *stack_.template Push() = c; } - void Flush() {} + void Put(Ch c) + { + *stack_.template Push() = c; + } + void Flush() {} - void Clear() { stack_.Clear(); } - void ShrinkToFit() { stack_.ShrinkToFit(); } - Ch* Push(size_t count) { return stack_.template Push(count); } - void Pop(size_t count) { stack_.template Pop(count); } + void Clear() + { + stack_.Clear(); + } + void ShrinkToFit() + { + stack_.ShrinkToFit(); + } + Ch* Push(size_t count) + { + return stack_.template Push(count); + } + void Pop(size_t count) + { + stack_.template Pop(count); + } - const Ch* GetBuffer() const { - return stack_.template Bottom(); - } + const Ch* GetBuffer() const + { + return stack_.template Bottom(); + } - size_t GetSize() const { return stack_.GetSize(); } + size_t GetSize() const + { + return stack_.GetSize(); + } - static const size_t kDefaultCapacity = 256; - mutable internal::Stack stack_; + static const size_t kDefaultCapacity = 256; + mutable internal::Stack 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(n), c, n * sizeof(c)); +inline void PutN(MemoryBuffer & memoryBuffer, char c, size_t n) +{ + std::memset(memoryBuffer.stack_.Push(n), c, n * sizeof(c)); } RAPIDJSON_NAMESPACE_END diff --git a/src/3rdparty/rapidjson/memorystream.h b/src/3rdparty/rapidjson/memorystream.h index 1d71d8a4..a6952935 100644 --- a/src/3rdparty/rapidjson/memorystream.h +++ b/src/3rdparty/rapidjson/memorystream.h @@ -1,5 +1,5 @@ // 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 @@ -7,9 +7,9 @@ // // 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 +// 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_ @@ -19,8 +19,8 @@ #ifdef __clang__ RAPIDJSON_DIAG_PUSH -RAPIDJSON_DIAG_OFF(unreachable-code) -RAPIDJSON_DIAG_OFF(missing-noreturn) +RAPIDJSON_DIAG_OFF(unreachable - code) +RAPIDJSON_DIAG_OFF(missing - noreturn) #endif RAPIDJSON_NAMESPACE_BEGIN @@ -37,29 +37,54 @@ RAPIDJSON_NAMESPACE_BEGIN 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 +struct MemoryStream +{ + typedef char Ch; // byte - MemoryStream(const Ch *src, size_t size) : src_(src), begin_(src), end_(src + size), size_(size) {} + 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(src_ - begin_); } + 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(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; } + 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; - } + // 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. + 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 diff --git a/src/3rdparty/rapidjson/msinttypes/inttypes.h b/src/3rdparty/rapidjson/msinttypes/inttypes.h index 18111286..df823c21 100644 --- a/src/3rdparty/rapidjson/msinttypes/inttypes.h +++ b/src/3rdparty/rapidjson/msinttypes/inttypes.h @@ -1,37 +1,37 @@ // ISO C9x compliant inttypes.h for Microsoft Visual Studio -// Based on ISO/IEC 9899:TC2 Committee draft (May 6, 2005) WG14/N1124 -// +// 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, +// 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"). +// 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 // [ @@ -54,9 +54,10 @@ // 7.8 Format conversion of integer types -typedef struct { - intmax_t quot; - intmax_t rem; +typedef struct +{ + intmax_t quot; + intmax_t rem; } imaxdiv_t; // 7.8.1 Macros for format specifiers @@ -194,11 +195,11 @@ typedef struct { #define SCNiMAX "I64i" #ifdef _WIN64 // [ -# define SCNdPTR "I64d" -# define SCNiPTR "I64i" +#define SCNdPTR "I64d" +#define SCNiPTR "I64i" #else // _WIN64 ][ -# define SCNdPTR "ld" -# define SCNiPTR "li" +#define SCNdPTR "ld" +#define SCNiPTR "li" #endif // _WIN64 ] // The fscanf macros for unsigned integers are: @@ -260,15 +261,15 @@ typedef struct { #define SCNXMAX "I64X" #ifdef _WIN64 // [ -# define SCNoPTR "I64o" -# define SCNuPTR "I64u" -# define SCNxPTR "I64x" -# define SCNXPTR "I64X" +#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" +#define SCNoPTR "lo" +#define SCNuPTR "lu" +#define SCNxPTR "lx" +#define SCNXPTR "lX" #endif // _WIN64 ] #endif // __STDC_FORMAT_MACROS ] @@ -289,18 +290,19 @@ _inline #endif // STATIC_IMAXDIV ] imaxdiv_t __cdecl imaxdiv(intmax_t numer, intmax_t denom) { - imaxdiv_t result; + imaxdiv_t result; - result.quot = numer / denom; - result.rem = numer % denom; + 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; - } + if(numer < 0 && result.rem > 0) + { + // did division wrong; must fix up + ++result.quot; + result.rem -= denom; + } - return result; + return result; } // 7.8.2.3 The strtoimax and strtoumax functions diff --git a/src/3rdparty/rapidjson/msinttypes/stdint.h b/src/3rdparty/rapidjson/msinttypes/stdint.h index 3d4477b9..bb71442f 100644 --- a/src/3rdparty/rapidjson/msinttypes/stdint.h +++ b/src/3rdparty/rapidjson/msinttypes/stdint.h @@ -1,39 +1,34 @@ // 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 -// +// Based on ISO/IEC 9899:TC2 Committee draft (May 6, 2005) WG14/N1124 +// +// Copyright (c) 2006-2008 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. -// +// +// 3. The name of the author 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, +// 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 ] @@ -45,68 +40,27 @@ #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 - -#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 . -// 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 // For Visual Studio 6 in C++ mode and for many Visual Studio versions when -// compiling for ARM we have to wrap include with 'extern "C++" {}' -// or compiler would give many errors like this: +// compiling for ARM we should wrap include with 'extern "C++" {}' +// or compiler give many errors like this: // error C2733: second C linkage of overloaded function 'wmemchr' not allowed -#if defined(__cplusplus) && !defined(_M_ARM) +#ifdef __cplusplus extern "C" { #endif -# include -#if defined(__cplusplus) && !defined(_M_ARM) +#include +#ifdef __cplusplus } #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 +#if !defined(__midl) && (defined(_X86_) || defined(_M_IX86)) && _MSC_VER >= 1300 +#define _W64 __w64 +#else +#define _W64 +#endif #endif @@ -118,19 +72,19 @@ extern "C" { // 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; +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; +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; @@ -158,11 +112,11 @@ 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; +typedef signed __int64 intptr_t; +typedef unsigned __int64 uintptr_t; #else // _WIN64 ][ - typedef _W64 signed int intptr_t; - typedef _W64 unsigned int uintptr_t; +typedef _W64 signed int intptr_t; +typedef _W64 unsigned int uintptr_t; #endif // _WIN64 ] // 7.18.1.5 Greatest-width integer types @@ -218,13 +172,13 @@ typedef uint64_t uintmax_t; // 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 +#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 +#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 @@ -235,30 +189,30 @@ typedef uint64_t uintmax_t; // 7.18.3 Limits of other integer types #ifdef _WIN64 // [ -# define PTRDIFF_MIN _I64_MIN -# define PTRDIFF_MAX _I64_MAX +#define PTRDIFF_MIN _I64_MIN +#define PTRDIFF_MAX _I64_MAX #else // _WIN64 ][ -# define PTRDIFF_MIN _I32_MIN -# define PTRDIFF_MAX _I32_MAX +#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 ] +#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 #ifndef WCHAR_MIN // [ -# define WCHAR_MIN 0 +#define WCHAR_MIN 0 #endif // WCHAR_MIN ] #ifndef WCHAR_MAX // [ -# define WCHAR_MAX _UI16_MAX +#define WCHAR_MAX _UI16_MAX #endif // WCHAR_MAX ] #define WINT_MIN 0 @@ -284,17 +238,10 @@ typedef uint64_t uintmax_t; #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 . -// 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 ] +#define INTMAX_C INT64_C +#define UINTMAX_C UINT64_C #endif // __STDC_CONSTANT_MACROS ] -#endif // _MSC_VER >= 1600 ] #endif // _MSC_STDINT_H_ ] diff --git a/src/3rdparty/rapidjson/ostreamwrapper.h b/src/3rdparty/rapidjson/ostreamwrapper.h index 6f4667c0..ce5280b4 100644 --- a/src/3rdparty/rapidjson/ostreamwrapper.h +++ b/src/3rdparty/rapidjson/ostreamwrapper.h @@ -1,5 +1,5 @@ // 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 @@ -7,9 +7,9 @@ // // 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 +// 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_ @@ -40,33 +40,56 @@ RAPIDJSON_NAMESPACE_BEGIN \tparam StreamType Class derived from \c std::basic_ostream. */ - + template -class BasicOStreamWrapper { +class BasicOStreamWrapper +{ public: - typedef typename StreamType::char_type Ch; - BasicOStreamWrapper(StreamType& stream) : stream_(stream) {} + typedef typename StreamType::char_type Ch; + BasicOStreamWrapper(StreamType & stream) : stream_(stream) {} - void Put(Ch c) { - stream_.put(c); - } + void Put(Ch c) + { + stream_.put(c); + } - void Flush() { - stream_.flush(); - } + 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; } + // 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&); + BasicOStreamWrapper(const BasicOStreamWrapper &); + BasicOStreamWrapper & operator=(const BasicOStreamWrapper &); - StreamType& stream_; + StreamType & stream_; }; typedef BasicOStreamWrapper OStreamWrapper; diff --git a/src/3rdparty/rapidjson/pointer.h b/src/3rdparty/rapidjson/pointer.h index 0206ac1c..55be279f 100644 --- a/src/3rdparty/rapidjson/pointer.h +++ b/src/3rdparty/rapidjson/pointer.h @@ -1,5 +1,5 @@ // 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 @@ -7,9 +7,9 @@ // // 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 +// 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_POINTER_H_ @@ -20,29 +20,31 @@ #ifdef __clang__ RAPIDJSON_DIAG_PUSH -RAPIDJSON_DIAG_OFF(switch-enum) +RAPIDJSON_DIAG_OFF(switch - enum) #endif #ifdef _MSC_VER -RAPIDJSON_DIAG_PUSH -RAPIDJSON_DIAG_OFF(4512) // assignment operator could not be generated + RAPIDJSON_DIAG_PUSH + RAPIDJSON_DIAG_OFF(4512) // assignment operator could not be generated #endif -RAPIDJSON_NAMESPACE_BEGIN + RAPIDJSON_NAMESPACE_BEGIN -static const SizeType kPointerInvalidIndex = ~SizeType(0); //!< Represents an invalid index in GenericPointer::Token + static const SizeType kPointerInvalidIndex = ~SizeType( + 0); //!< Represents an invalid index in GenericPointer::Token //! Error code of parsing. /*! \ingroup RAPIDJSON_ERRORS \see GenericPointer::GenericPointer, GenericPointer::GetParseErrorCode */ -enum PointerParseErrorCode { - kPointerParseErrorNone = 0, //!< The parse is successful +enum PointerParseErrorCode +{ + kPointerParseErrorNone = 0, //!< The parse is successful - kPointerParseErrorTokenMustBeginWithSolidus, //!< A token must begin with a '/' - kPointerParseErrorInvalidEscape, //!< Invalid escape - kPointerParseErrorInvalidPercentEncoding, //!< Invalid percent encoding in URI fragment - kPointerParseErrorCharacterMustPercentEncode //!< A character must percent encoded in URI fragment + kPointerParseErrorTokenMustBeginWithSolidus, //!< A token must begin with a '/' + kPointerParseErrorInvalidEscape, //!< Invalid escape + kPointerParseErrorInvalidPercentEncoding, //!< Invalid percent encoding in URI fragment + kPointerParseErrorCharacterMustPercentEncode //!< A character must percent encoded in URI fragment }; /////////////////////////////////////////////////////////////////////////////// @@ -50,16 +52,16 @@ enum PointerParseErrorCode { //! Represents a JSON Pointer. Use Pointer for UTF8 encoding and default allocator. /*! - This class implements RFC 6901 "JavaScript Object Notation (JSON) Pointer" + This class implements RFC 6901 "JavaScript Object Notation (JSON) Pointer" (https://tools.ietf.org/html/rfc6901). A JSON pointer is for identifying a specific value in a JSON document (GenericDocument). It can simplify coding of DOM tree manipulation, because it can access multiple-level depth of DOM tree with single API call. - After it parses a string representation (e.g. "/foo/0" or URI fragment + After it parses a string representation (e.g. "/foo/0" or URI fragment representation (e.g. "#/foo/0") into its internal representation (tokens), - it can be used to resolve a specific value in multiple documents, or sub-tree + it can be used to resolve a specific value in multiple documents, or sub-tree of documents. Contrary to GenericValue, Pointer can be copy constructed and copy assigned. @@ -70,979 +72,1213 @@ enum PointerParseErrorCode { supplied tokens eliminates these. GenericPointer depends on GenericDocument and GenericValue. - + \tparam ValueType The value type of the DOM tree. E.g. GenericValue > \tparam Allocator The allocator type for allocating memory for internal representation. - + \note GenericPointer uses same encoding of ValueType. However, Allocator of GenericPointer is independent of Allocator of Value. */ template -class GenericPointer { +class GenericPointer +{ public: - typedef typename ValueType::EncodingType EncodingType; //!< Encoding type from Value - typedef typename ValueType::Ch Ch; //!< Character type from Value + typedef typename ValueType::EncodingType EncodingType; //!< Encoding type from Value + typedef typename ValueType::Ch Ch; //!< Character type from Value - //! A token is the basic units of internal representation. - /*! - A JSON pointer string representation "/foo/123" is parsed to two tokens: - "foo" and 123. 123 will be represented in both numeric form and string form. - They are resolved according to the actual value type (object or array). + //! A token is the basic units of internal representation. + /*! + A JSON pointer string representation "/foo/123" is parsed to two tokens: + "foo" and 123. 123 will be represented in both numeric form and string form. + They are resolved according to the actual value type (object or array). - For token that are not numbers, or the numeric value is out of bound - (greater than limits of SizeType), they are only treated as string form - (i.e. the token's index will be equal to kPointerInvalidIndex). + For token that are not numbers, or the numeric value is out of bound + (greater than limits of SizeType), they are only treated as string form + (i.e. the token's index will be equal to kPointerInvalidIndex). - This struct is public so that user can create a Pointer without parsing and - allocation, using a special constructor. - */ - struct Token { - const Ch* name; //!< Name of the token. It has null character at the end but it can contain null character. - SizeType length; //!< Length of the name. - SizeType index; //!< A valid array index, if it is not equal to kPointerInvalidIndex. - }; + This struct is public so that user can create a Pointer without parsing and + allocation, using a special constructor. + */ + struct Token + { + const Ch* name; //!< Name of the token. It has null character at the end but it can contain null character. + SizeType length; //!< Length of the name. + SizeType index; //!< A valid array index, if it is not equal to kPointerInvalidIndex. + }; - //!@name Constructors and destructor. - //@{ + //!@name Constructors and destructor. + //@{ - //! Default constructor. - GenericPointer(Allocator* allocator = 0) : allocator_(allocator), ownAllocator_(), nameBuffer_(), tokens_(), tokenCount_(), parseErrorOffset_(), parseErrorCode_(kPointerParseErrorNone) {} + //! Default constructor. + GenericPointer(Allocator* allocator = 0) : allocator_(allocator), ownAllocator_(), nameBuffer_(), tokens_(), + tokenCount_(), parseErrorOffset_(), parseErrorCode_(kPointerParseErrorNone) {} - //! Constructor that parses a string or URI fragment representation. - /*! - \param source A null-terminated, string or URI fragment representation of JSON pointer. - \param allocator User supplied allocator for this pointer. If no allocator is provided, it creates a self-owned one. - */ - explicit GenericPointer(const Ch* source, Allocator* allocator = 0) : allocator_(allocator), ownAllocator_(), nameBuffer_(), tokens_(), tokenCount_(), parseErrorOffset_(), parseErrorCode_(kPointerParseErrorNone) { - Parse(source, internal::StrLen(source)); - } + //! Constructor that parses a string or URI fragment representation. + /*! + \param source A null-terminated, string or URI fragment representation of JSON pointer. + \param allocator User supplied allocator for this pointer. If no allocator is provided, it creates a self-owned one. + */ + explicit GenericPointer(const Ch* source, Allocator* allocator = 0) : allocator_(allocator), ownAllocator_(), + nameBuffer_(), tokens_(), tokenCount_(), parseErrorOffset_(), parseErrorCode_(kPointerParseErrorNone) + { + Parse(source, internal::StrLen(source)); + } #if RAPIDJSON_HAS_STDSTRING - //! Constructor that parses a string or URI fragment representation. - /*! - \param source A string or URI fragment representation of JSON pointer. - \param allocator User supplied allocator for this pointer. If no allocator is provided, it creates a self-owned one. - \note Requires the definition of the preprocessor symbol \ref RAPIDJSON_HAS_STDSTRING. - */ - explicit GenericPointer(const std::basic_string& source, Allocator* allocator = 0) : allocator_(allocator), ownAllocator_(), nameBuffer_(), tokens_(), tokenCount_(), parseErrorOffset_(), parseErrorCode_(kPointerParseErrorNone) { - Parse(source.c_str(), source.size()); - } + //! Constructor that parses a string or URI fragment representation. + /*! + \param source A string or URI fragment representation of JSON pointer. + \param allocator User supplied allocator for this pointer. If no allocator is provided, it creates a self-owned one. + \note Requires the definition of the preprocessor symbol \ref RAPIDJSON_HAS_STDSTRING. + */ + explicit GenericPointer(const std::basic_string & source, + Allocator* allocator = 0) : allocator_(allocator), ownAllocator_(), nameBuffer_(), tokens_(), tokenCount_(), + parseErrorOffset_(), parseErrorCode_(kPointerParseErrorNone) + { + Parse(source.c_str(), source.size()); + } #endif - //! Constructor that parses a string or URI fragment representation, with length of the source string. - /*! - \param source A string or URI fragment representation of JSON pointer. - \param length Length of source. - \param allocator User supplied allocator for this pointer. If no allocator is provided, it creates a self-owned one. - \note Slightly faster than the overload without length. - */ - GenericPointer(const Ch* source, size_t length, Allocator* allocator = 0) : allocator_(allocator), ownAllocator_(), nameBuffer_(), tokens_(), tokenCount_(), parseErrorOffset_(), parseErrorCode_(kPointerParseErrorNone) { - Parse(source, length); - } + //! Constructor that parses a string or URI fragment representation, with length of the source string. + /*! + \param source A string or URI fragment representation of JSON pointer. + \param length Length of source. + \param allocator User supplied allocator for this pointer. If no allocator is provided, it creates a self-owned one. + \note Slightly faster than the overload without length. + */ + GenericPointer(const Ch* source, size_t length, Allocator* allocator = 0) : allocator_(allocator), + ownAllocator_(), nameBuffer_(), tokens_(), tokenCount_(), parseErrorOffset_(), + parseErrorCode_(kPointerParseErrorNone) + { + Parse(source, length); + } - //! Constructor with user-supplied tokens. - /*! - This constructor let user supplies const array of tokens. - This prevents the parsing process and eliminates allocation. - This is preferred for memory constrained environments. + //! Constructor with user-supplied tokens. + /*! + This constructor let user supplies const array of tokens. + This prevents the parsing process and eliminates allocation. + This is preferred for memory constrained environments. - \param tokens An constant array of tokens representing the JSON pointer. - \param tokenCount Number of tokens. + \param tokens An constant array of tokens representing the JSON pointer. + \param tokenCount Number of tokens. - \b Example - \code - #define NAME(s) { s, sizeof(s) / sizeof(s[0]) - 1, kPointerInvalidIndex } - #define INDEX(i) { #i, sizeof(#i) - 1, i } + \b Example + \code + #define NAME(s) { s, sizeof(s) / sizeof(s[0]) - 1, kPointerInvalidIndex } + #define INDEX(i) { #i, sizeof(#i) - 1, i } - static const Pointer::Token kTokens[] = { NAME("foo"), INDEX(123) }; - static const Pointer p(kTokens, sizeof(kTokens) / sizeof(kTokens[0])); - // Equivalent to static const Pointer p("/foo/123"); + static const Pointer::Token kTokens[] = { NAME("foo"), INDEX(123) }; + static const Pointer p(kTokens, sizeof(kTokens) / sizeof(kTokens[0])); + // Equivalent to static const Pointer p("/foo/123"); - #undef NAME - #undef INDEX - \endcode - */ - GenericPointer(const Token* tokens, size_t tokenCount) : allocator_(), ownAllocator_(), nameBuffer_(), tokens_(const_cast(tokens)), tokenCount_(tokenCount), parseErrorOffset_(), parseErrorCode_(kPointerParseErrorNone) {} + #undef NAME + #undef INDEX + \endcode + */ + GenericPointer(const Token* tokens, size_t tokenCount) : allocator_(), ownAllocator_(), nameBuffer_(), + tokens_(const_cast(tokens)), tokenCount_(tokenCount), parseErrorOffset_(), + parseErrorCode_(kPointerParseErrorNone) {} - //! Copy constructor. - GenericPointer(const GenericPointer& rhs, Allocator* allocator = 0) : allocator_(allocator), ownAllocator_(), nameBuffer_(), tokens_(), tokenCount_(), parseErrorOffset_(), parseErrorCode_(kPointerParseErrorNone) { - *this = rhs; - } + //! Copy constructor. + GenericPointer(const GenericPointer & rhs, Allocator* allocator = 0) : allocator_(allocator), ownAllocator_(), + nameBuffer_(), tokens_(), tokenCount_(), parseErrorOffset_(), parseErrorCode_(kPointerParseErrorNone) + { + *this = rhs; + } - //! Destructor. - ~GenericPointer() { - if (nameBuffer_) // If user-supplied tokens constructor is used, nameBuffer_ is nullptr and tokens_ are not deallocated. - Allocator::Free(tokens_); - RAPIDJSON_DELETE(ownAllocator_); - } + //! Destructor. + ~GenericPointer() + { + if(nameBuffer_) // If user-supplied tokens constructor is used, nameBuffer_ is nullptr and tokens_ are not deallocated. + { + Allocator::Free(tokens_); + } + RAPIDJSON_DELETE(ownAllocator_); + } - //! Assignment operator. - GenericPointer& operator=(const GenericPointer& rhs) { - if (this != &rhs) { - // Do not delete ownAllcator - if (nameBuffer_) - Allocator::Free(tokens_); + //! Assignment operator. + GenericPointer & operator=(const GenericPointer & rhs) + { + if(this != &rhs) + { + // Do not delete ownAllcator + if(nameBuffer_) + { + Allocator::Free(tokens_); + } - tokenCount_ = rhs.tokenCount_; - parseErrorOffset_ = rhs.parseErrorOffset_; - parseErrorCode_ = rhs.parseErrorCode_; + tokenCount_ = rhs.tokenCount_; + parseErrorOffset_ = rhs.parseErrorOffset_; + parseErrorCode_ = rhs.parseErrorCode_; - if (rhs.nameBuffer_) - CopyFromRaw(rhs); // Normally parsed tokens. - else { - tokens_ = rhs.tokens_; // User supplied const tokens. - nameBuffer_ = 0; - } - } - return *this; - } + if(rhs.nameBuffer_) + { + CopyFromRaw(rhs); // Normally parsed tokens. + } + else + { + tokens_ = rhs.tokens_; // User supplied const tokens. + nameBuffer_ = 0; + } + } + return *this; + } - //@} + //@} - //!@name Append token - //@{ + //!@name Append token + //@{ - //! Append a token and return a new Pointer - /*! - \param token Token to be appended. - \param allocator Allocator for the newly return Pointer. - \return A new Pointer with appended token. - */ - GenericPointer Append(const Token& token, Allocator* allocator = 0) const { - GenericPointer r; - r.allocator_ = allocator; - Ch *p = r.CopyFromRaw(*this, 1, token.length + 1); - std::memcpy(p, token.name, (token.length + 1) * sizeof(Ch)); - r.tokens_[tokenCount_].name = p; - r.tokens_[tokenCount_].length = token.length; - r.tokens_[tokenCount_].index = token.index; - return r; - } + //! Append a token and return a new Pointer + /*! + \param token Token to be appended. + \param allocator Allocator for the newly return Pointer. + \return A new Pointer with appended token. + */ + GenericPointer Append(const Token & token, Allocator* allocator = 0) const + { + GenericPointer r; + r.allocator_ = allocator; + Ch* p = r.CopyFromRaw(*this, 1, token.length + 1); + std::memcpy(p, token.name, (token.length + 1) * sizeof(Ch)); + r.tokens_[tokenCount_].name = p; + r.tokens_[tokenCount_].length = token.length; + r.tokens_[tokenCount_].index = token.index; + return r; + } - //! Append a name token with length, and return a new Pointer - /*! - \param name Name to be appended. - \param length Length of name. - \param allocator Allocator for the newly return Pointer. - \return A new Pointer with appended token. - */ - GenericPointer Append(const Ch* name, SizeType length, Allocator* allocator = 0) const { - Token token = { name, length, kPointerInvalidIndex }; - return Append(token, allocator); - } + //! Append a name token with length, and return a new Pointer + /*! + \param name Name to be appended. + \param length Length of name. + \param allocator Allocator for the newly return Pointer. + \return A new Pointer with appended token. + */ + GenericPointer Append(const Ch* name, SizeType length, Allocator* allocator = 0) const + { + Token token = { name, length, kPointerInvalidIndex }; + return Append(token, allocator); + } - //! Append a name token without length, and return a new Pointer - /*! - \param name Name (const Ch*) to be appended. - \param allocator Allocator for the newly return Pointer. - \return A new Pointer with appended token. - */ - template - RAPIDJSON_DISABLEIF_RETURN((internal::NotExpr::Type, Ch> >), (GenericPointer)) - Append(T* name, Allocator* allocator = 0) const { - return Append(name, StrLen(name), allocator); - } + //! Append a name token without length, and return a new Pointer + /*! + \param name Name (const Ch*) to be appended. + \param allocator Allocator for the newly return Pointer. + \return A new Pointer with appended token. + */ + template + RAPIDJSON_DISABLEIF_RETURN((internal::NotExpr::Type, Ch>>), + (GenericPointer)) + Append(T* name, Allocator* allocator = 0) const + { + return Append(name, StrLen(name), allocator); + } #if RAPIDJSON_HAS_STDSTRING - //! Append a name token, and return a new Pointer - /*! - \param name Name to be appended. - \param allocator Allocator for the newly return Pointer. - \return A new Pointer with appended token. - */ - GenericPointer Append(const std::basic_string& name, Allocator* allocator = 0) const { - return Append(name.c_str(), static_cast(name.size()), allocator); - } + //! Append a name token, and return a new Pointer + /*! + \param name Name to be appended. + \param allocator Allocator for the newly return Pointer. + \return A new Pointer with appended token. + */ + GenericPointer Append(const std::basic_string & name, Allocator* allocator = 0) const + { + return Append(name.c_str(), static_cast(name.size()), allocator); + } #endif - //! Append a index token, and return a new Pointer - /*! - \param index Index to be appended. - \param allocator Allocator for the newly return Pointer. - \return A new Pointer with appended token. - */ - GenericPointer Append(SizeType index, Allocator* allocator = 0) const { - char buffer[21]; - char* end = sizeof(SizeType) == 4 ? internal::u32toa(index, buffer) : internal::u64toa(index, buffer); - SizeType length = static_cast(end - buffer); - buffer[length] = '\0'; + //! Append a index token, and return a new Pointer + /*! + \param index Index to be appended. + \param allocator Allocator for the newly return Pointer. + \return A new Pointer with appended token. + */ + GenericPointer Append(SizeType index, Allocator* allocator = 0) const + { + char buffer[21]; + char* end = sizeof(SizeType) == 4 ? internal::u32toa(index, buffer) : internal::u64toa(index, buffer); + SizeType length = static_cast(end - buffer); + buffer[length] = '\0'; - if (sizeof(Ch) == 1) { - Token token = { reinterpret_cast(buffer), length, index }; - return Append(token, allocator); - } - else { - Ch name[21]; - for (size_t i = 0; i <= length; i++) - name[i] = buffer[i]; - Token token = { name, length, index }; - return Append(token, allocator); - } - } + if(sizeof(Ch) == 1) + { + Token token = { reinterpret_cast(buffer), length, index }; + return Append(token, allocator); + } + else + { + Ch name[21]; + for(size_t i = 0; i <= length; i++) + { + name[i] = buffer[i]; + } + Token token = { name, length, index }; + return Append(token, allocator); + } + } - //! Append a token by value, and return a new Pointer - /*! - \param token token to be appended. - \param allocator Allocator for the newly return Pointer. - \return A new Pointer with appended token. - */ - GenericPointer Append(const ValueType& token, Allocator* allocator = 0) const { - if (token.IsString()) - return Append(token.GetString(), token.GetStringLength(), allocator); - else { - RAPIDJSON_ASSERT(token.IsUint64()); - RAPIDJSON_ASSERT(token.GetUint64() <= SizeType(~0)); - return Append(static_cast(token.GetUint64()), allocator); - } - } + //! Append a token by value, and return a new Pointer + /*! + \param token token to be appended. + \param allocator Allocator for the newly return Pointer. + \return A new Pointer with appended token. + */ + GenericPointer Append(const ValueType & token, Allocator* allocator = 0) const + { + if(token.IsString()) + { + return Append(token.GetString(), token.GetStringLength(), allocator); + } + else + { + RAPIDJSON_ASSERT(token.IsUint64()); + RAPIDJSON_ASSERT(token.GetUint64() <= SizeType(~0)); + return Append(static_cast(token.GetUint64()), allocator); + } + } - //!@name Handling Parse Error - //@{ + //!@name Handling Parse Error + //@{ - //! Check whether this is a valid pointer. - bool IsValid() const { return parseErrorCode_ == kPointerParseErrorNone; } + //! Check whether this is a valid pointer. + bool IsValid() const + { + return parseErrorCode_ == kPointerParseErrorNone; + } - //! Get the parsing error offset in code unit. - size_t GetParseErrorOffset() const { return parseErrorOffset_; } + //! Get the parsing error offset in code unit. + size_t GetParseErrorOffset() const + { + return parseErrorOffset_; + } - //! Get the parsing error code. - PointerParseErrorCode GetParseErrorCode() const { return parseErrorCode_; } + //! Get the parsing error code. + PointerParseErrorCode GetParseErrorCode() const + { + return parseErrorCode_; + } - //@} + //@} - //! Get the allocator of this pointer. - Allocator& GetAllocator() { return *allocator_; } + //! Get the allocator of this pointer. + Allocator & GetAllocator() + { + return *allocator_; + } - //!@name Tokens - //@{ + //!@name Tokens + //@{ - //! Get the token array (const version only). - const Token* GetTokens() const { return tokens_; } + //! Get the token array (const version only). + const Token* GetTokens() const + { + return tokens_; + } - //! Get the number of tokens. - size_t GetTokenCount() const { return tokenCount_; } + //! Get the number of tokens. + size_t GetTokenCount() const + { + return tokenCount_; + } - //@} + //@} - //!@name Equality/inequality operators - //@{ + //!@name Equality/inequality operators + //@{ - //! Equality operator. - /*! - \note When any pointers are invalid, always returns false. - */ - bool operator==(const GenericPointer& rhs) const { - if (!IsValid() || !rhs.IsValid() || tokenCount_ != rhs.tokenCount_) - return false; + //! Equality operator. + /*! + \note When any pointers are invalid, always returns false. + */ + bool operator==(const GenericPointer & rhs) const + { + if(!IsValid() || !rhs.IsValid() || tokenCount_ != rhs.tokenCount_) + { + return false; + } - for (size_t i = 0; i < tokenCount_; i++) { - if (tokens_[i].index != rhs.tokens_[i].index || - tokens_[i].length != rhs.tokens_[i].length || - (tokens_[i].length != 0 && std::memcmp(tokens_[i].name, rhs.tokens_[i].name, sizeof(Ch)* tokens_[i].length) != 0)) - { - return false; - } - } + for(size_t i = 0; i < tokenCount_; i++) + { + if(tokens_[i].index != rhs.tokens_[i].index || + tokens_[i].length != rhs.tokens_[i].length || + (tokens_[i].length != 0 && + std::memcmp(tokens_[i].name, rhs.tokens_[i].name, sizeof(Ch)* tokens_[i].length) != 0)) + { + return false; + } + } - return true; - } + return true; + } - //! Inequality operator. - /*! - \note When any pointers are invalid, always returns true. - */ - bool operator!=(const GenericPointer& rhs) const { return !(*this == rhs); } + //! Inequality operator. + /*! + \note When any pointers are invalid, always returns true. + */ + bool operator!=(const GenericPointer & rhs) const + { + return !(*this == rhs); + } - //@} + //@} - //!@name Stringify - //@{ + //!@name Stringify + //@{ - //! Stringify the pointer into string representation. - /*! - \tparam OutputStream Type of output stream. - \param os The output stream. - */ - template - bool Stringify(OutputStream& os) const { - return Stringify(os); - } + //! Stringify the pointer into string representation. + /*! + \tparam OutputStream Type of output stream. + \param os The output stream. + */ + template + bool Stringify(OutputStream & os) const + { + return Stringify(os); + } - //! Stringify the pointer into URI fragment representation. - /*! - \tparam OutputStream Type of output stream. - \param os The output stream. - */ - template - bool StringifyUriFragment(OutputStream& os) const { - return Stringify(os); - } + //! Stringify the pointer into URI fragment representation. + /*! + \tparam OutputStream Type of output stream. + \param os The output stream. + */ + template + bool StringifyUriFragment(OutputStream & os) const + { + return Stringify(os); + } - //@} + //@} - //!@name Create value - //@{ + //!@name Create value + //@{ - //! Create a value in a subtree. - /*! - If the value is not exist, it creates all parent values and a JSON Null value. - So it always succeed and return the newly created or existing value. + //! Create a value in a subtree. + /*! + If the value is not exist, it creates all parent values and a JSON Null value. + So it always succeed and return the newly created or existing value. - Remind that it may change types of parents according to tokens, so it - potentially removes previously stored values. For example, if a document - was an array, and "/foo" is used to create a value, then the document - will be changed to an object, and all existing array elements are lost. + Remind that it may change types of parents according to tokens, so it + potentially removes previously stored values. For example, if a document + was an array, and "/foo" is used to create a value, then the document + will be changed to an object, and all existing array elements are lost. - \param root Root value of a DOM subtree to be resolved. It can be any value other than document root. - \param allocator Allocator for creating the values if the specified value or its parents are not exist. - \param alreadyExist If non-null, it stores whether the resolved value is already exist. - \return The resolved newly created (a JSON Null value), or already exists value. - */ - ValueType& Create(ValueType& root, typename ValueType::AllocatorType& allocator, bool* alreadyExist = 0) const { - RAPIDJSON_ASSERT(IsValid()); - ValueType* v = &root; - bool exist = true; - for (const Token *t = tokens_; t != tokens_ + tokenCount_; ++t) { - if (v->IsArray() && t->name[0] == '-' && t->length == 1) { - v->PushBack(ValueType().Move(), allocator); - v = &((*v)[v->Size() - 1]); - exist = false; - } - else { - if (t->index == kPointerInvalidIndex) { // must be object name - if (!v->IsObject()) - v->SetObject(); // Change to Object - } - else { // object name or array index - if (!v->IsArray() && !v->IsObject()) - v->SetArray(); // Change to Array - } + \param root Root value of a DOM subtree to be resolved. It can be any value other than document root. + \param allocator Allocator for creating the values if the specified value or its parents are not exist. + \param alreadyExist If non-null, it stores whether the resolved value is already exist. + \return The resolved newly created (a JSON Null value), or already exists value. + */ + ValueType & Create(ValueType & root, typename ValueType::AllocatorType & allocator, + bool* alreadyExist = 0) const + { + RAPIDJSON_ASSERT(IsValid()); + ValueType* v = &root; + bool exist = true; + for(const Token* t = tokens_; t != tokens_ + tokenCount_; ++t) + { + if(v->IsArray() && t->name[0] == '-' && t->length == 1) + { + v->PushBack(ValueType().Move(), allocator); + v = &((*v)[v->Size() - 1]); + exist = false; + } + else + { + if(t->index == kPointerInvalidIndex) // must be object name + { + if(!v->IsObject()) + { + v->SetObject(); // Change to Object + } + } + else // object name or array index + { + if(!v->IsArray() && !v->IsObject()) + { + v->SetArray(); // Change to Array + } + } - if (v->IsArray()) { - if (t->index >= v->Size()) { - v->Reserve(t->index + 1, allocator); - while (t->index >= v->Size()) - v->PushBack(ValueType().Move(), allocator); - exist = false; - } - v = &((*v)[t->index]); - } - else { - typename ValueType::MemberIterator m = v->FindMember(GenericStringRef(t->name, t->length)); - if (m == v->MemberEnd()) { - v->AddMember(ValueType(t->name, t->length, allocator).Move(), ValueType().Move(), allocator); - v = &(--v->MemberEnd())->value; // Assumes AddMember() appends at the end - exist = false; - } - else - v = &m->value; - } - } - } + if(v->IsArray()) + { + if(t->index >= v->Size()) + { + v->Reserve(t->index + 1, allocator); + while(t->index >= v->Size()) + { + v->PushBack(ValueType().Move(), allocator); + } + exist = false; + } + v = &((*v)[t->index]); + } + else + { + typename ValueType::MemberIterator m = v->FindMember(GenericStringRef(t->name, t->length)); + if(m == v->MemberEnd()) + { + v->AddMember(ValueType(t->name, t->length, allocator).Move(), ValueType().Move(), allocator); + v = &(--v->MemberEnd())->value; // Assumes AddMember() appends at the end + exist = false; + } + else + { + v = &m->value; + } + } + } + } - if (alreadyExist) - *alreadyExist = exist; + if(alreadyExist) + { + *alreadyExist = exist; + } - return *v; - } + return *v; + } - //! Creates a value in a document. - /*! - \param document A document to be resolved. - \param alreadyExist If non-null, it stores whether the resolved value is already exist. - \return The resolved newly created, or already exists value. - */ - template - ValueType& Create(GenericDocument& document, bool* alreadyExist = 0) const { - return Create(document, document.GetAllocator(), alreadyExist); - } + //! Creates a value in a document. + /*! + \param document A document to be resolved. + \param alreadyExist If non-null, it stores whether the resolved value is already exist. + \return The resolved newly created, or already exists value. + */ + template + ValueType & Create(GenericDocument & document, + bool* alreadyExist = 0) const + { + return Create(document, document.GetAllocator(), alreadyExist); + } - //@} + //@} - //!@name Query value - //@{ + //!@name Query value + //@{ - //! Query a value in a subtree. - /*! - \param root Root value of a DOM sub-tree to be resolved. It can be any value other than document root. - \param unresolvedTokenIndex If the pointer cannot resolve a token in the pointer, this parameter can obtain the index of unresolved token. - \return Pointer to the value if it can be resolved. Otherwise null. + //! Query a value in a subtree. + /*! + \param root Root value of a DOM sub-tree to be resolved. It can be any value other than document root. + \param unresolvedTokenIndex If the pointer cannot resolve a token in the pointer, this parameter can obtain the index of unresolved token. + \return Pointer to the value if it can be resolved. Otherwise null. - \note - There are only 3 situations when a value cannot be resolved: - 1. A value in the path is not an array nor object. - 2. An object value does not contain the token. - 3. A token is out of range of an array value. + \note + There are only 3 situations when a value cannot be resolved: + 1. A value in the path is not an array nor object. + 2. An object value does not contain the token. + 3. A token is out of range of an array value. - Use unresolvedTokenIndex to retrieve the token index. - */ - ValueType* Get(ValueType& root, size_t* unresolvedTokenIndex = 0) const { - RAPIDJSON_ASSERT(IsValid()); - ValueType* v = &root; - for (const Token *t = tokens_; t != tokens_ + tokenCount_; ++t) { - switch (v->GetType()) { - case kObjectType: - { - typename ValueType::MemberIterator m = v->FindMember(GenericStringRef(t->name, t->length)); - if (m == v->MemberEnd()) - break; - v = &m->value; - } - continue; - case kArrayType: - if (t->index == kPointerInvalidIndex || t->index >= v->Size()) - break; - v = &((*v)[t->index]); - continue; - default: - break; - } + Use unresolvedTokenIndex to retrieve the token index. + */ + ValueType* Get(ValueType & root, size_t* unresolvedTokenIndex = 0) const + { + RAPIDJSON_ASSERT(IsValid()); + ValueType* v = &root; + for(const Token* t = tokens_; t != tokens_ + tokenCount_; ++t) + { + switch(v->GetType()) + { + case kObjectType: + { + typename ValueType::MemberIterator m = v->FindMember(GenericStringRef(t->name, t->length)); + if(m == v->MemberEnd()) + { + break; + } + v = &m->value; + } + continue; + case kArrayType: + if(t->index == kPointerInvalidIndex || t->index >= v->Size()) + { + break; + } + v = &((*v)[t->index]); + continue; + default: + break; + } - // Error: unresolved token - if (unresolvedTokenIndex) - *unresolvedTokenIndex = static_cast(t - tokens_); - return 0; - } - return v; - } + // Error: unresolved token + if(unresolvedTokenIndex) + { + *unresolvedTokenIndex = static_cast(t - tokens_); + } + return 0; + } + return v; + } - //! Query a const value in a const subtree. - /*! - \param root Root value of a DOM sub-tree to be resolved. It can be any value other than document root. - \return Pointer to the value if it can be resolved. Otherwise null. - */ - const ValueType* Get(const ValueType& root, size_t* unresolvedTokenIndex = 0) const { - return Get(const_cast(root), unresolvedTokenIndex); - } + //! Query a const value in a const subtree. + /*! + \param root Root value of a DOM sub-tree to be resolved. It can be any value other than document root. + \return Pointer to the value if it can be resolved. Otherwise null. + */ + const ValueType* Get(const ValueType & root, size_t* unresolvedTokenIndex = 0) const + { + return Get(const_cast(root), unresolvedTokenIndex); + } - //@} + //@} - //!@name Query a value with default - //@{ + //!@name Query a value with default + //@{ - //! Query a value in a subtree with default value. - /*! - Similar to Get(), but if the specified value do not exists, it creates all parents and clone the default value. - So that this function always succeed. + //! Query a value in a subtree with default value. + /*! + Similar to Get(), but if the specified value do not exists, it creates all parents and clone the default value. + So that this function always succeed. - \param root Root value of a DOM sub-tree to be resolved. It can be any value other than document root. - \param defaultValue Default value to be cloned if the value was not exists. - \param allocator Allocator for creating the values if the specified value or its parents are not exist. - \see Create() - */ - ValueType& GetWithDefault(ValueType& root, const ValueType& defaultValue, typename ValueType::AllocatorType& allocator) const { - bool alreadyExist; - Value& v = Create(root, allocator, &alreadyExist); - return alreadyExist ? v : v.CopyFrom(defaultValue, allocator); - } + \param root Root value of a DOM sub-tree to be resolved. It can be any value other than document root. + \param defaultValue Default value to be cloned if the value was not exists. + \param allocator Allocator for creating the values if the specified value or its parents are not exist. + \see Create() + */ + ValueType & GetWithDefault(ValueType & root, const ValueType & defaultValue, + typename ValueType::AllocatorType & allocator) const + { + bool alreadyExist; + Value & v = Create(root, allocator, &alreadyExist); + return alreadyExist ? v : v.CopyFrom(defaultValue, allocator); + } - //! Query a value in a subtree with default null-terminated string. - ValueType& GetWithDefault(ValueType& root, const Ch* defaultValue, typename ValueType::AllocatorType& allocator) const { - bool alreadyExist; - Value& v = Create(root, allocator, &alreadyExist); - return alreadyExist ? v : v.SetString(defaultValue, allocator); - } + //! Query a value in a subtree with default null-terminated string. + ValueType & GetWithDefault(ValueType & root, const Ch* defaultValue, + typename ValueType::AllocatorType & allocator) const + { + bool alreadyExist; + Value & v = Create(root, allocator, &alreadyExist); + return alreadyExist ? v : v.SetString(defaultValue, allocator); + } #if RAPIDJSON_HAS_STDSTRING - //! Query a value in a subtree with default std::basic_string. - ValueType& GetWithDefault(ValueType& root, const std::basic_string& defaultValue, typename ValueType::AllocatorType& allocator) const { - bool alreadyExist; - Value& v = Create(root, allocator, &alreadyExist); - return alreadyExist ? v : v.SetString(defaultValue, allocator); - } + //! Query a value in a subtree with default std::basic_string. + ValueType & GetWithDefault(ValueType & root, const std::basic_string & defaultValue, + typename ValueType::AllocatorType & allocator) const + { + bool alreadyExist; + Value & v = Create(root, allocator, &alreadyExist); + return alreadyExist ? v : v.SetString(defaultValue, allocator); + } #endif - //! Query a value in a subtree with default primitive value. - /*! - \tparam T Either \ref Type, \c int, \c unsigned, \c int64_t, \c uint64_t, \c bool - */ - template - RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr, internal::IsGenericValue >), (ValueType&)) - GetWithDefault(ValueType& root, T defaultValue, typename ValueType::AllocatorType& allocator) const { - return GetWithDefault(root, ValueType(defaultValue).Move(), allocator); - } + //! Query a value in a subtree with default primitive value. + /*! + \tparam T Either \ref Type, \c int, \c unsigned, \c int64_t, \c uint64_t, \c bool + */ + template + RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr, internal::IsGenericValue>), + (ValueType &)) + GetWithDefault(ValueType & root, T defaultValue, typename ValueType::AllocatorType & allocator) const + { + return GetWithDefault(root, ValueType(defaultValue).Move(), allocator); + } - //! Query a value in a document with default value. - template - ValueType& GetWithDefault(GenericDocument& document, const ValueType& defaultValue) const { - return GetWithDefault(document, defaultValue, document.GetAllocator()); - } + //! Query a value in a document with default value. + template + ValueType & GetWithDefault(GenericDocument & + document, const ValueType & defaultValue) const + { + return GetWithDefault(document, defaultValue, document.GetAllocator()); + } - //! Query a value in a document with default null-terminated string. - template - ValueType& GetWithDefault(GenericDocument& document, const Ch* defaultValue) const { - return GetWithDefault(document, defaultValue, document.GetAllocator()); - } - -#if RAPIDJSON_HAS_STDSTRING - //! Query a value in a document with default std::basic_string. - template - ValueType& GetWithDefault(GenericDocument& document, const std::basic_string& defaultValue) const { - return GetWithDefault(document, defaultValue, document.GetAllocator()); - } -#endif - - //! Query a value in a document with default primitive value. - /*! - \tparam T Either \ref Type, \c int, \c unsigned, \c int64_t, \c uint64_t, \c bool - */ - template - RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr, internal::IsGenericValue >), (ValueType&)) - GetWithDefault(GenericDocument& document, T defaultValue) const { - return GetWithDefault(document, defaultValue, document.GetAllocator()); - } - - //@} - - //!@name Set a value - //@{ - - //! Set a value in a subtree, with move semantics. - /*! - It creates all parents if they are not exist or types are different to the tokens. - So this function always succeeds but potentially remove existing values. - - \param root Root value of a DOM sub-tree to be resolved. It can be any value other than document root. - \param value Value to be set. - \param allocator Allocator for creating the values if the specified value or its parents are not exist. - \see Create() - */ - ValueType& Set(ValueType& root, ValueType& value, typename ValueType::AllocatorType& allocator) const { - return Create(root, allocator) = value; - } - - //! Set a value in a subtree, with copy semantics. - ValueType& Set(ValueType& root, const ValueType& value, typename ValueType::AllocatorType& allocator) const { - return Create(root, allocator).CopyFrom(value, allocator); - } - - //! Set a null-terminated string in a subtree. - ValueType& Set(ValueType& root, const Ch* value, typename ValueType::AllocatorType& allocator) const { - return Create(root, allocator) = ValueType(value, allocator).Move(); - } + //! Query a value in a document with default null-terminated string. + template + ValueType & GetWithDefault(GenericDocument & + document, const Ch* defaultValue) const + { + return GetWithDefault(document, defaultValue, document.GetAllocator()); + } #if RAPIDJSON_HAS_STDSTRING - //! Set a std::basic_string in a subtree. - ValueType& Set(ValueType& root, const std::basic_string& value, typename ValueType::AllocatorType& allocator) const { - return Create(root, allocator) = ValueType(value, allocator).Move(); - } + //! Query a value in a document with default std::basic_string. + template + ValueType & GetWithDefault(GenericDocument & + document, const std::basic_string & defaultValue) const + { + return GetWithDefault(document, defaultValue, document.GetAllocator()); + } #endif - //! Set a primitive value in a subtree. - /*! - \tparam T Either \ref Type, \c int, \c unsigned, \c int64_t, \c uint64_t, \c bool - */ - template - RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr, internal::IsGenericValue >), (ValueType&)) - Set(ValueType& root, T value, typename ValueType::AllocatorType& allocator) const { - return Create(root, allocator) = ValueType(value).Move(); - } + //! Query a value in a document with default primitive value. + /*! + \tparam T Either \ref Type, \c int, \c unsigned, \c int64_t, \c uint64_t, \c bool + */ + template + RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr, internal::IsGenericValue>), + (ValueType &)) + GetWithDefault(GenericDocument & document, + T defaultValue) const + { + return GetWithDefault(document, defaultValue, document.GetAllocator()); + } - //! Set a value in a document, with move semantics. - template - ValueType& Set(GenericDocument& document, ValueType& value) const { - return Create(document) = value; - } + //@} - //! Set a value in a document, with copy semantics. - template - ValueType& Set(GenericDocument& document, const ValueType& value) const { - return Create(document).CopyFrom(value, document.GetAllocator()); - } + //!@name Set a value + //@{ - //! Set a null-terminated string in a document. - template - ValueType& Set(GenericDocument& document, const Ch* value) const { - return Create(document) = ValueType(value, document.GetAllocator()).Move(); - } + //! Set a value in a subtree, with move semantics. + /*! + It creates all parents if they are not exist or types are different to the tokens. + So this function always succeeds but potentially remove existing values. + + \param root Root value of a DOM sub-tree to be resolved. It can be any value other than document root. + \param value Value to be set. + \param allocator Allocator for creating the values if the specified value or its parents are not exist. + \see Create() + */ + ValueType & Set(ValueType & root, ValueType & value, typename ValueType::AllocatorType & allocator) const + { + return Create(root, allocator) = value; + } + + //! Set a value in a subtree, with copy semantics. + ValueType & Set(ValueType & root, const ValueType & value, + typename ValueType::AllocatorType & allocator) const + { + return Create(root, allocator).CopyFrom(value, allocator); + } + + //! Set a null-terminated string in a subtree. + ValueType & Set(ValueType & root, const Ch* value, typename ValueType::AllocatorType & allocator) const + { + return Create(root, allocator) = ValueType(value, allocator).Move(); + } #if RAPIDJSON_HAS_STDSTRING - //! Sets a std::basic_string in a document. - template - ValueType& Set(GenericDocument& document, const std::basic_string& value) const { - return Create(document) = ValueType(value, document.GetAllocator()).Move(); - } + //! Set a std::basic_string in a subtree. + ValueType & Set(ValueType & root, const std::basic_string & value, + typename ValueType::AllocatorType & allocator) const + { + return Create(root, allocator) = ValueType(value, allocator).Move(); + } #endif - //! Set a primitive value in a document. - /*! - \tparam T Either \ref Type, \c int, \c unsigned, \c int64_t, \c uint64_t, \c bool - */ - template - RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr, internal::IsGenericValue >), (ValueType&)) - Set(GenericDocument& document, T value) const { - return Create(document) = value; - } + //! Set a primitive value in a subtree. + /*! + \tparam T Either \ref Type, \c int, \c unsigned, \c int64_t, \c uint64_t, \c bool + */ + template + RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr, internal::IsGenericValue>), + (ValueType &)) + Set(ValueType & root, T value, typename ValueType::AllocatorType & allocator) const + { + return Create(root, allocator) = ValueType(value).Move(); + } - //@} + //! Set a value in a document, with move semantics. + template + ValueType & Set(GenericDocument & document, + ValueType & value) const + { + return Create(document) = value; + } - //!@name Swap a value - //@{ + //! Set a value in a document, with copy semantics. + template + ValueType & Set(GenericDocument & document, + const ValueType & value) const + { + return Create(document).CopyFrom(value, document.GetAllocator()); + } - //! Swap a value with a value in a subtree. - /*! - It creates all parents if they are not exist or types are different to the tokens. - So this function always succeeds but potentially remove existing values. + //! Set a null-terminated string in a document. + template + ValueType & Set(GenericDocument & document, + const Ch* value) const + { + return Create(document) = ValueType(value, document.GetAllocator()).Move(); + } - \param root Root value of a DOM sub-tree to be resolved. It can be any value other than document root. - \param value Value to be swapped. - \param allocator Allocator for creating the values if the specified value or its parents are not exist. - \see Create() - */ - ValueType& Swap(ValueType& root, ValueType& value, typename ValueType::AllocatorType& allocator) const { - return Create(root, allocator).Swap(value); - } +#if RAPIDJSON_HAS_STDSTRING + //! Sets a std::basic_string in a document. + template + ValueType & Set(GenericDocument & document, + const std::basic_string & value) const + { + return Create(document) = ValueType(value, document.GetAllocator()).Move(); + } +#endif - //! Swap a value with a value in a document. - template - ValueType& Swap(GenericDocument& document, ValueType& value) const { - return Create(document).Swap(value); - } + //! Set a primitive value in a document. + /*! + \tparam T Either \ref Type, \c int, \c unsigned, \c int64_t, \c uint64_t, \c bool + */ + template + RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr, internal::IsGenericValue>), + (ValueType &)) + Set(GenericDocument & document, + T value) const + { + return Create(document) = value; + } - //@} + //@} - //! Erase a value in a subtree. - /*! - \param root Root value of a DOM sub-tree to be resolved. It can be any value other than document root. - \return Whether the resolved value is found and erased. + //!@name Swap a value + //@{ - \note Erasing with an empty pointer \c Pointer(""), i.e. the root, always fail and return false. - */ - bool Erase(ValueType& root) const { - RAPIDJSON_ASSERT(IsValid()); - if (tokenCount_ == 0) // Cannot erase the root - return false; + //! Swap a value with a value in a subtree. + /*! + It creates all parents if they are not exist or types are different to the tokens. + So this function always succeeds but potentially remove existing values. - ValueType* v = &root; - const Token* last = tokens_ + (tokenCount_ - 1); - for (const Token *t = tokens_; t != last; ++t) { - switch (v->GetType()) { - case kObjectType: - { - typename ValueType::MemberIterator m = v->FindMember(GenericStringRef(t->name, t->length)); - if (m == v->MemberEnd()) - return false; - v = &m->value; - } - break; - case kArrayType: - if (t->index == kPointerInvalidIndex || t->index >= v->Size()) - return false; - v = &((*v)[t->index]); - break; - default: - return false; - } - } + \param root Root value of a DOM sub-tree to be resolved. It can be any value other than document root. + \param value Value to be swapped. + \param allocator Allocator for creating the values if the specified value or its parents are not exist. + \see Create() + */ + ValueType & Swap(ValueType & root, ValueType & value, typename ValueType::AllocatorType & allocator) const + { + return Create(root, allocator).Swap(value); + } - switch (v->GetType()) { - case kObjectType: - return v->EraseMember(GenericStringRef(last->name, last->length)); - case kArrayType: - if (last->index == kPointerInvalidIndex || last->index >= v->Size()) - return false; - v->Erase(v->Begin() + last->index); - return true; - default: - return false; - } - } + //! Swap a value with a value in a document. + template + ValueType & Swap(GenericDocument & document, + ValueType & value) const + { + return Create(document).Swap(value); + } + + //@} + + //! Erase a value in a subtree. + /*! + \param root Root value of a DOM sub-tree to be resolved. It can be any value other than document root. + \return Whether the resolved value is found and erased. + + \note Erasing with an empty pointer \c Pointer(""), i.e. the root, always fail and return false. + */ + bool Erase(ValueType & root) const + { + RAPIDJSON_ASSERT(IsValid()); + if(tokenCount_ == 0) // Cannot erase the root + { + return false; + } + + ValueType* v = &root; + const Token* last = tokens_ + (tokenCount_ - 1); + for(const Token* t = tokens_; t != last; ++t) + { + switch(v->GetType()) + { + case kObjectType: + { + typename ValueType::MemberIterator m = v->FindMember(GenericStringRef(t->name, t->length)); + if(m == v->MemberEnd()) + { + return false; + } + v = &m->value; + } + break; + case kArrayType: + if(t->index == kPointerInvalidIndex || t->index >= v->Size()) + { + return false; + } + v = &((*v)[t->index]); + break; + default: + return false; + } + } + + switch(v->GetType()) + { + case kObjectType: + return v->EraseMember(GenericStringRef(last->name, last->length)); + case kArrayType: + if(last->index == kPointerInvalidIndex || last->index >= v->Size()) + { + return false; + } + v->Erase(v->Begin() + last->index); + return true; + default: + return false; + } + } private: - //! Clone the content from rhs to this. - /*! - \param rhs Source pointer. - \param extraToken Extra tokens to be allocated. - \param extraNameBufferSize Extra name buffer size (in number of Ch) to be allocated. - \return Start of non-occupied name buffer, for storing extra names. - */ - Ch* CopyFromRaw(const GenericPointer& rhs, size_t extraToken = 0, size_t extraNameBufferSize = 0) { - if (!allocator_) // allocator is independently owned. - ownAllocator_ = allocator_ = RAPIDJSON_NEW(Allocator()); + //! Clone the content from rhs to this. + /*! + \param rhs Source pointer. + \param extraToken Extra tokens to be allocated. + \param extraNameBufferSize Extra name buffer size (in number of Ch) to be allocated. + \return Start of non-occupied name buffer, for storing extra names. + */ + Ch* CopyFromRaw(const GenericPointer & rhs, size_t extraToken = 0, size_t extraNameBufferSize = 0) + { + if(!allocator_) // allocator is independently owned. + { + ownAllocator_ = allocator_ = RAPIDJSON_NEW(Allocator()); + } - size_t nameBufferSize = rhs.tokenCount_; // null terminators for tokens - for (Token *t = rhs.tokens_; t != rhs.tokens_ + rhs.tokenCount_; ++t) - nameBufferSize += t->length; + size_t nameBufferSize = rhs.tokenCount_; // null terminators for tokens + for(Token* t = rhs.tokens_; t != rhs.tokens_ + rhs.tokenCount_; ++t) + { + nameBufferSize += t->length; + } - tokenCount_ = rhs.tokenCount_ + extraToken; - tokens_ = static_cast(allocator_->Malloc(tokenCount_ * sizeof(Token) + (nameBufferSize + extraNameBufferSize) * sizeof(Ch))); - nameBuffer_ = reinterpret_cast(tokens_ + tokenCount_); - if (rhs.tokenCount_ > 0) { - std::memcpy(tokens_, rhs.tokens_, rhs.tokenCount_ * sizeof(Token)); - } - if (nameBufferSize > 0) { - std::memcpy(nameBuffer_, rhs.nameBuffer_, nameBufferSize * sizeof(Ch)); - } + tokenCount_ = rhs.tokenCount_ + extraToken; + tokens_ = static_cast(allocator_->Malloc(tokenCount_ * sizeof(Token) + + (nameBufferSize + extraNameBufferSize) * sizeof(Ch))); + nameBuffer_ = reinterpret_cast(tokens_ + tokenCount_); + if(rhs.tokenCount_ > 0) + { + std::memcpy(tokens_, rhs.tokens_, rhs.tokenCount_ * sizeof(Token)); + } + if(nameBufferSize > 0) + { + std::memcpy(nameBuffer_, rhs.nameBuffer_, nameBufferSize * sizeof(Ch)); + } - // Adjust pointers to name buffer - std::ptrdiff_t diff = nameBuffer_ - rhs.nameBuffer_; - for (Token *t = tokens_; t != tokens_ + rhs.tokenCount_; ++t) - t->name += diff; + // Adjust pointers to name buffer + std::ptrdiff_t diff = nameBuffer_ - rhs.nameBuffer_; + for(Token* t = tokens_; t != tokens_ + rhs.tokenCount_; ++t) + { + t->name += diff; + } - return nameBuffer_ + nameBufferSize; - } + return nameBuffer_ + nameBufferSize; + } - //! Check whether a character should be percent-encoded. - /*! - According to RFC 3986 2.3 Unreserved Characters. - \param c The character (code unit) to be tested. - */ - bool NeedPercentEncode(Ch c) const { - return !((c >= '0' && c <= '9') || (c >= 'A' && c <='Z') || (c >= 'a' && c <= 'z') || c == '-' || c == '.' || c == '_' || c =='~'); - } + //! Check whether a character should be percent-encoded. + /*! + According to RFC 3986 2.3 Unreserved Characters. + \param c The character (code unit) to be tested. + */ + bool NeedPercentEncode(Ch c) const + { + return !((c >= '0' && c <= '9') || (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z') || c == '-' || c == '.' || + c == '_' || c == '~'); + } - //! Parse a JSON String or its URI fragment representation into tokens. + //! Parse a JSON String or its URI fragment representation into tokens. #ifndef __clang__ // -Wdocumentation - /*! - \param source Either a JSON Pointer string, or its URI fragment representation. Not need to be null terminated. - \param length Length of the source string. - \note Source cannot be JSON String Representation of JSON Pointer, e.g. In "/\u0000", \u0000 will not be unescaped. - */ + /*! + \param source Either a JSON Pointer string, or its URI fragment representation. Not need to be null terminated. + \param length Length of the source string. + \note Source cannot be JSON String Representation of JSON Pointer, e.g. In "/\u0000", \u0000 will not be unescaped. + */ #endif - void Parse(const Ch* source, size_t length) { - RAPIDJSON_ASSERT(source != NULL); - RAPIDJSON_ASSERT(nameBuffer_ == 0); - RAPIDJSON_ASSERT(tokens_ == 0); + void Parse(const Ch* source, size_t length) + { + RAPIDJSON_ASSERT(source != NULL); + RAPIDJSON_ASSERT(nameBuffer_ == 0); + RAPIDJSON_ASSERT(tokens_ == 0); - // Create own allocator if user did not supply. - if (!allocator_) - ownAllocator_ = allocator_ = RAPIDJSON_NEW(Allocator()); + // Create own allocator if user did not supply. + if(!allocator_) + { + ownAllocator_ = allocator_ = RAPIDJSON_NEW(Allocator()); + } - // Count number of '/' as tokenCount - tokenCount_ = 0; - for (const Ch* s = source; s != source + length; s++) - if (*s == '/') - tokenCount_++; + // Count number of '/' as tokenCount + tokenCount_ = 0; + for(const Ch* s = source; s != source + length; s++) + if(*s == '/') + { + tokenCount_++; + } - Token* token = tokens_ = static_cast(allocator_->Malloc(tokenCount_ * sizeof(Token) + length * sizeof(Ch))); - Ch* name = nameBuffer_ = reinterpret_cast(tokens_ + tokenCount_); - size_t i = 0; + Token* token = tokens_ = static_cast(allocator_->Malloc(tokenCount_ * sizeof(Token) + length * sizeof( + Ch))); + Ch* name = nameBuffer_ = reinterpret_cast(tokens_ + tokenCount_); + size_t i = 0; - // Detect if it is a URI fragment - bool uriFragment = false; - if (source[i] == '#') { - uriFragment = true; - i++; - } + // Detect if it is a URI fragment + bool uriFragment = false; + if(source[i] == '#') + { + uriFragment = true; + i++; + } - if (i != length && source[i] != '/') { - parseErrorCode_ = kPointerParseErrorTokenMustBeginWithSolidus; - goto error; - } + if(i != length && source[i] != '/') + { + parseErrorCode_ = kPointerParseErrorTokenMustBeginWithSolidus; + goto error; + } - while (i < length) { - RAPIDJSON_ASSERT(source[i] == '/'); - i++; // consumes '/' + while(i < length) + { + RAPIDJSON_ASSERT(source[i] == '/'); + i++; // consumes '/' - token->name = name; - bool isNumber = true; + token->name = name; + bool isNumber = true; - while (i < length && source[i] != '/') { - Ch c = source[i]; - if (uriFragment) { - // Decoding percent-encoding for URI fragment - if (c == '%') { - PercentDecodeStream is(&source[i], source + length); - GenericInsituStringStream os(name); - Ch* begin = os.PutBegin(); - if (!Transcoder, EncodingType>().Validate(is, os) || !is.IsValid()) { - parseErrorCode_ = kPointerParseErrorInvalidPercentEncoding; - goto error; - } - size_t len = os.PutEnd(begin); - i += is.Tell() - 1; - if (len == 1) - c = *name; - else { - name += len; - isNumber = false; - i++; - continue; - } - } - else if (NeedPercentEncode(c)) { - parseErrorCode_ = kPointerParseErrorCharacterMustPercentEncode; - goto error; - } - } + while(i < length && source[i] != '/') + { + Ch c = source[i]; + if(uriFragment) + { + // Decoding percent-encoding for URI fragment + if(c == '%') + { + PercentDecodeStream is(&source[i], source + length); + GenericInsituStringStream os(name); + Ch* begin = os.PutBegin(); + if(!Transcoder, EncodingType>().Validate(is, os) || !is.IsValid()) + { + parseErrorCode_ = kPointerParseErrorInvalidPercentEncoding; + goto error; + } + size_t len = os.PutEnd(begin); + i += is.Tell() - 1; + if(len == 1) + { + c = *name; + } + else + { + name += len; + isNumber = false; + i++; + continue; + } + } + else if(NeedPercentEncode(c)) + { + parseErrorCode_ = kPointerParseErrorCharacterMustPercentEncode; + goto error; + } + } - i++; - - // Escaping "~0" -> '~', "~1" -> '/' - if (c == '~') { - if (i < length) { - c = source[i]; - if (c == '0') c = '~'; - else if (c == '1') c = '/'; - else { - parseErrorCode_ = kPointerParseErrorInvalidEscape; - goto error; - } - i++; - } - else { - parseErrorCode_ = kPointerParseErrorInvalidEscape; - goto error; - } - } + i++; - // First check for index: all of characters are digit - if (c < '0' || c > '9') - isNumber = false; + // Escaping "~0" -> '~', "~1" -> '/' + if(c == '~') + { + if(i < length) + { + c = source[i]; + if(c == '0') + { + c = '~'; + } + else if(c == '1') + { + c = '/'; + } + else + { + parseErrorCode_ = kPointerParseErrorInvalidEscape; + goto error; + } + i++; + } + else + { + parseErrorCode_ = kPointerParseErrorInvalidEscape; + goto error; + } + } - *name++ = c; - } - token->length = static_cast(name - token->name); - if (token->length == 0) - isNumber = false; - *name++ = '\0'; // Null terminator + // First check for index: all of characters are digit + if(c < '0' || c > '9') + { + isNumber = false; + } - // Second check for index: more than one digit cannot have leading zero - if (isNumber && token->length > 1 && token->name[0] == '0') - isNumber = false; + *name++ = c; + } + token->length = static_cast(name - token->name); + if(token->length == 0) + { + isNumber = false; + } + *name++ = '\0'; // Null terminator - // String to SizeType conversion - SizeType n = 0; - if (isNumber) { - for (size_t j = 0; j < token->length; j++) { - SizeType m = n * 10 + static_cast(token->name[j] - '0'); - if (m < n) { // overflow detection - isNumber = false; - break; - } - n = m; - } - } + // Second check for index: more than one digit cannot have leading zero + if(isNumber && token->length > 1 && token->name[0] == '0') + { + isNumber = false; + } - token->index = isNumber ? n : kPointerInvalidIndex; - token++; - } + // String to SizeType conversion + SizeType n = 0; + if(isNumber) + { + for(size_t j = 0; j < token->length; j++) + { + SizeType m = n * 10 + static_cast(token->name[j] - '0'); + if(m < n) // overflow detection + { + isNumber = false; + break; + } + n = m; + } + } - RAPIDJSON_ASSERT(name <= nameBuffer_ + length); // Should not overflow buffer - parseErrorCode_ = kPointerParseErrorNone; - return; + token->index = isNumber ? n : kPointerInvalidIndex; + token++; + } - error: - Allocator::Free(tokens_); - nameBuffer_ = 0; - tokens_ = 0; - tokenCount_ = 0; - parseErrorOffset_ = i; - return; - } + RAPIDJSON_ASSERT(name <= nameBuffer_ + length); // Should not overflow buffer + parseErrorCode_ = kPointerParseErrorNone; + return; - //! Stringify to string or URI fragment representation. - /*! - \tparam uriFragment True for stringifying to URI fragment representation. False for string representation. - \tparam OutputStream type of output stream. - \param os The output stream. - */ - template - bool Stringify(OutputStream& os) const { - RAPIDJSON_ASSERT(IsValid()); +error: + Allocator::Free(tokens_); + nameBuffer_ = 0; + tokens_ = 0; + tokenCount_ = 0; + parseErrorOffset_ = i; + return; + } - if (uriFragment) - os.Put('#'); + //! Stringify to string or URI fragment representation. + /*! + \tparam uriFragment True for stringifying to URI fragment representation. False for string representation. + \tparam OutputStream type of output stream. + \param os The output stream. + */ + template + bool Stringify(OutputStream & os) const + { + RAPIDJSON_ASSERT(IsValid()); - for (Token *t = tokens_; t != tokens_ + tokenCount_; ++t) { - os.Put('/'); - for (size_t j = 0; j < t->length; j++) { - Ch c = t->name[j]; - if (c == '~') { - os.Put('~'); - os.Put('0'); - } - else if (c == '/') { - os.Put('~'); - os.Put('1'); - } - else if (uriFragment && NeedPercentEncode(c)) { - // Transcode to UTF8 sequence - GenericStringStream source(&t->name[j]); - PercentEncodeStream target(os); - if (!Transcoder >().Validate(source, target)) - return false; - j += source.Tell() - 1; - } - else - os.Put(c); - } - } - return true; - } + if(uriFragment) + { + os.Put('#'); + } - //! A helper stream for decoding a percent-encoded sequence into code unit. - /*! - This stream decodes %XY triplet into code unit (0-255). - If it encounters invalid characters, it sets output code unit as 0 and - mark invalid, and to be checked by IsValid(). - */ - class PercentDecodeStream { - public: - typedef typename ValueType::Ch Ch; + for(Token* t = tokens_; t != tokens_ + tokenCount_; ++t) + { + os.Put('/'); + for(size_t j = 0; j < t->length; j++) + { + Ch c = t->name[j]; + if(c == '~') + { + os.Put('~'); + os.Put('0'); + } + else if(c == '/') + { + os.Put('~'); + os.Put('1'); + } + else if(uriFragment && NeedPercentEncode(c)) + { + // Transcode to UTF8 sequence + GenericStringStream source(&t->name[j]); + PercentEncodeStream target(os); + if(!Transcoder>().Validate(source, target)) + { + return false; + } + j += source.Tell() - 1; + } + else + { + os.Put(c); + } + } + } + return true; + } - //! Constructor - /*! - \param source Start of the stream - \param end Past-the-end of the stream. - */ - PercentDecodeStream(const Ch* source, const Ch* end) : src_(source), head_(source), end_(end), valid_(true) {} + //! A helper stream for decoding a percent-encoded sequence into code unit. + /*! + This stream decodes %XY triplet into code unit (0-255). + If it encounters invalid characters, it sets output code unit as 0 and + mark invalid, and to be checked by IsValid(). + */ + class PercentDecodeStream + { + public: + typedef typename ValueType::Ch Ch; - Ch Take() { - if (*src_ != '%' || src_ + 3 > end_) { // %XY triplet - valid_ = false; - return 0; - } - src_++; - Ch c = 0; - for (int j = 0; j < 2; j++) { - c = static_cast(c << 4); - Ch h = *src_; - if (h >= '0' && h <= '9') c = static_cast(c + h - '0'); - else if (h >= 'A' && h <= 'F') c = static_cast(c + h - 'A' + 10); - else if (h >= 'a' && h <= 'f') c = static_cast(c + h - 'a' + 10); - else { - valid_ = false; - return 0; - } - src_++; - } - return c; - } + //! Constructor + /*! + \param source Start of the stream + \param end Past-the-end of the stream. + */ + PercentDecodeStream(const Ch* source, const Ch* end) : src_(source), head_(source), end_(end), valid_(true) {} - size_t Tell() const { return static_cast(src_ - head_); } - bool IsValid() const { return valid_; } + Ch Take() + { + if(*src_ != '%' || src_ + 3 > end_) // %XY triplet + { + valid_ = false; + return 0; + } + src_++; + Ch c = 0; + for(int j = 0; j < 2; j++) + { + c = static_cast(c << 4); + Ch h = *src_; + if(h >= '0' && h <= '9') + { + c = static_cast(c + h - '0'); + } + else if(h >= 'A' && h <= 'F') + { + c = static_cast(c + h - 'A' + 10); + } + else if(h >= 'a' && h <= 'f') + { + c = static_cast(c + h - 'a' + 10); + } + else + { + valid_ = false; + return 0; + } + src_++; + } + return c; + } - private: - const Ch* src_; //!< Current read position. - const Ch* head_; //!< Original head of the string. - const Ch* end_; //!< Past-the-end position. - bool valid_; //!< Whether the parsing is valid. - }; + size_t Tell() const + { + return static_cast(src_ - head_); + } + bool IsValid() const + { + return valid_; + } - //! A helper stream to encode character (UTF-8 code unit) into percent-encoded sequence. - template - class PercentEncodeStream { - public: - PercentEncodeStream(OutputStream& os) : os_(os) {} - void Put(char c) { // UTF-8 must be byte - unsigned char u = static_cast(c); - static const char hexDigits[16] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' }; - os_.Put('%'); - os_.Put(hexDigits[u >> 4]); - os_.Put(hexDigits[u & 15]); - } - private: - OutputStream& os_; - }; + private: + const Ch* src_; //!< Current read position. + const Ch* head_; //!< Original head of the string. + const Ch* end_; //!< Past-the-end position. + bool valid_; //!< Whether the parsing is valid. + }; - Allocator* allocator_; //!< The current allocator. It is either user-supplied or equal to ownAllocator_. - Allocator* ownAllocator_; //!< Allocator owned by this Pointer. - Ch* nameBuffer_; //!< A buffer containing all names in tokens. - Token* tokens_; //!< A list of tokens. - size_t tokenCount_; //!< Number of tokens in tokens_. - size_t parseErrorOffset_; //!< Offset in code unit when parsing fail. - PointerParseErrorCode parseErrorCode_; //!< Parsing error code. + //! A helper stream to encode character (UTF-8 code unit) into percent-encoded sequence. + template + class PercentEncodeStream + { + public: + PercentEncodeStream(OutputStream & os) : os_(os) {} + void Put(char c) // UTF-8 must be byte + { + unsigned char u = static_cast(c); + static const char hexDigits[16] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' }; + os_.Put('%'); + os_.Put(hexDigits[u >> 4]); + os_.Put(hexDigits[u & 15]); + } + private: + OutputStream & os_; + }; + + Allocator* + allocator_; //!< The current allocator. It is either user-supplied or equal to ownAllocator_. + Allocator* ownAllocator_; //!< Allocator owned by this Pointer. + Ch* nameBuffer_; //!< A buffer containing all names in tokens. + Token* tokens_; //!< A list of tokens. + size_t tokenCount_; //!< Number of tokens in tokens_. + size_t parseErrorOffset_; //!< Offset in code unit when parsing fail. + PointerParseErrorCode parseErrorCode_; //!< Parsing error code. }; //! GenericPointer for Value (UTF-8, default allocator). @@ -1054,293 +1290,403 @@ typedef GenericPointer Pointer; ////////////////////////////////////////////////////////////////////////////// template -typename T::ValueType& CreateValueByPointer(T& root, const GenericPointer& pointer, typename T::AllocatorType& a) { - return pointer.Create(root, a); +typename T::ValueType & CreateValueByPointer(T & root, const GenericPointer & pointer, + typename T::AllocatorType & a) +{ + return pointer.Create(root, a); } template -typename T::ValueType& CreateValueByPointer(T& root, const CharType(&source)[N], typename T::AllocatorType& a) { - return GenericPointer(source, N - 1).Create(root, a); +typename T::ValueType & CreateValueByPointer(T & root, const CharType(&source)[N], + typename T::AllocatorType & a) +{ + return GenericPointer(source, N - 1).Create(root, a); } // No allocator parameter template -typename DocumentType::ValueType& CreateValueByPointer(DocumentType& document, const GenericPointer& pointer) { - return pointer.Create(document); +typename DocumentType::ValueType & CreateValueByPointer(DocumentType & document, + const GenericPointer & pointer) +{ + return pointer.Create(document); } template -typename DocumentType::ValueType& CreateValueByPointer(DocumentType& document, const CharType(&source)[N]) { - return GenericPointer(source, N - 1).Create(document); +typename DocumentType::ValueType & CreateValueByPointer(DocumentType & document, const CharType(&source)[N]) +{ + return GenericPointer(source, N - 1).Create(document); } ////////////////////////////////////////////////////////////////////////////// template -typename T::ValueType* GetValueByPointer(T& root, const GenericPointer& pointer, size_t* unresolvedTokenIndex = 0) { - return pointer.Get(root, unresolvedTokenIndex); +typename T::ValueType* GetValueByPointer(T & root, const GenericPointer & pointer, + size_t* unresolvedTokenIndex = 0) +{ + return pointer.Get(root, unresolvedTokenIndex); } template -const typename T::ValueType* GetValueByPointer(const T& root, const GenericPointer& pointer, size_t* unresolvedTokenIndex = 0) { - return pointer.Get(root, unresolvedTokenIndex); +const typename T::ValueType* GetValueByPointer(const T & root, + const GenericPointer & pointer, size_t* unresolvedTokenIndex = 0) +{ + return pointer.Get(root, unresolvedTokenIndex); } template -typename T::ValueType* GetValueByPointer(T& root, const CharType (&source)[N], size_t* unresolvedTokenIndex = 0) { - return GenericPointer(source, N - 1).Get(root, unresolvedTokenIndex); +typename T::ValueType* GetValueByPointer(T & root, const CharType(&source)[N], + size_t* unresolvedTokenIndex = 0) +{ + return GenericPointer(source, N - 1).Get(root, unresolvedTokenIndex); } template -const typename T::ValueType* GetValueByPointer(const T& root, const CharType(&source)[N], size_t* unresolvedTokenIndex = 0) { - return GenericPointer(source, N - 1).Get(root, unresolvedTokenIndex); +const typename T::ValueType* GetValueByPointer(const T & root, const CharType(&source)[N], + size_t* unresolvedTokenIndex = 0) +{ + return GenericPointer(source, N - 1).Get(root, unresolvedTokenIndex); } ////////////////////////////////////////////////////////////////////////////// template -typename T::ValueType& GetValueByPointerWithDefault(T& root, const GenericPointer& pointer, const typename T::ValueType& defaultValue, typename T::AllocatorType& a) { - return pointer.GetWithDefault(root, defaultValue, a); +typename T::ValueType & GetValueByPointerWithDefault(T & root, + const GenericPointer & pointer, const typename T::ValueType & defaultValue, + typename T::AllocatorType & a) +{ + return pointer.GetWithDefault(root, defaultValue, a); } template -typename T::ValueType& GetValueByPointerWithDefault(T& root, const GenericPointer& pointer, const typename T::Ch* defaultValue, typename T::AllocatorType& a) { - return pointer.GetWithDefault(root, defaultValue, a); +typename T::ValueType & GetValueByPointerWithDefault(T & root, + const GenericPointer & pointer, const typename T::Ch* defaultValue, + typename T::AllocatorType & a) +{ + return pointer.GetWithDefault(root, defaultValue, a); } #if RAPIDJSON_HAS_STDSTRING template -typename T::ValueType& GetValueByPointerWithDefault(T& root, const GenericPointer& pointer, const std::basic_string& defaultValue, typename T::AllocatorType& a) { - return pointer.GetWithDefault(root, defaultValue, a); +typename T::ValueType & GetValueByPointerWithDefault(T & root, + const GenericPointer & pointer, const std::basic_string & defaultValue, + typename T::AllocatorType & a) +{ + return pointer.GetWithDefault(root, defaultValue, a); } #endif template -RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr, internal::IsGenericValue >), (typename T::ValueType&)) -GetValueByPointerWithDefault(T& root, const GenericPointer& pointer, T2 defaultValue, typename T::AllocatorType& a) { - return pointer.GetWithDefault(root, defaultValue, a); +RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr, internal::IsGenericValue>), + (typename T::ValueType &)) +GetValueByPointerWithDefault(T & root, const GenericPointer & pointer, T2 defaultValue, + typename T::AllocatorType & a) +{ + return pointer.GetWithDefault(root, defaultValue, a); } template -typename T::ValueType& GetValueByPointerWithDefault(T& root, const CharType(&source)[N], const typename T::ValueType& defaultValue, typename T::AllocatorType& a) { - return GenericPointer(source, N - 1).GetWithDefault(root, defaultValue, a); +typename T::ValueType & GetValueByPointerWithDefault(T & root, const CharType(&source)[N], + const typename T::ValueType & defaultValue, typename T::AllocatorType & a) +{ + return GenericPointer(source, N - 1).GetWithDefault(root, defaultValue, a); } template -typename T::ValueType& GetValueByPointerWithDefault(T& root, const CharType(&source)[N], const typename T::Ch* defaultValue, typename T::AllocatorType& a) { - return GenericPointer(source, N - 1).GetWithDefault(root, defaultValue, a); +typename T::ValueType & GetValueByPointerWithDefault(T & root, const CharType(&source)[N], + const typename T::Ch* defaultValue, typename T::AllocatorType & a) +{ + return GenericPointer(source, N - 1).GetWithDefault(root, defaultValue, a); } #if RAPIDJSON_HAS_STDSTRING template -typename T::ValueType& GetValueByPointerWithDefault(T& root, const CharType(&source)[N], const std::basic_string& defaultValue, typename T::AllocatorType& a) { - return GenericPointer(source, N - 1).GetWithDefault(root, defaultValue, a); +typename T::ValueType & GetValueByPointerWithDefault(T & root, const CharType(&source)[N], + const std::basic_string & defaultValue, typename T::AllocatorType & a) +{ + return GenericPointer(source, N - 1).GetWithDefault(root, defaultValue, a); } #endif template -RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr, internal::IsGenericValue >), (typename T::ValueType&)) -GetValueByPointerWithDefault(T& root, const CharType(&source)[N], T2 defaultValue, typename T::AllocatorType& a) { - return GenericPointer(source, N - 1).GetWithDefault(root, defaultValue, a); +RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr, internal::IsGenericValue>), + (typename T::ValueType &)) +GetValueByPointerWithDefault(T & root, const CharType(&source)[N], T2 defaultValue, + typename T::AllocatorType & a) +{ + return GenericPointer(source, N - 1).GetWithDefault(root, defaultValue, a); } // No allocator parameter template -typename DocumentType::ValueType& GetValueByPointerWithDefault(DocumentType& document, const GenericPointer& pointer, const typename DocumentType::ValueType& defaultValue) { - return pointer.GetWithDefault(document, defaultValue); +typename DocumentType::ValueType & GetValueByPointerWithDefault(DocumentType & document, + const GenericPointer & pointer, + const typename DocumentType::ValueType & defaultValue) +{ + return pointer.GetWithDefault(document, defaultValue); } template -typename DocumentType::ValueType& GetValueByPointerWithDefault(DocumentType& document, const GenericPointer& pointer, const typename DocumentType::Ch* defaultValue) { - return pointer.GetWithDefault(document, defaultValue); +typename DocumentType::ValueType & GetValueByPointerWithDefault(DocumentType & document, + const GenericPointer & pointer, + const typename DocumentType::Ch* defaultValue) +{ + return pointer.GetWithDefault(document, defaultValue); } #if RAPIDJSON_HAS_STDSTRING template -typename DocumentType::ValueType& GetValueByPointerWithDefault(DocumentType& document, const GenericPointer& pointer, const std::basic_string& defaultValue) { - return pointer.GetWithDefault(document, defaultValue); +typename DocumentType::ValueType & GetValueByPointerWithDefault(DocumentType & document, + const GenericPointer & pointer, + const std::basic_string & defaultValue) +{ + return pointer.GetWithDefault(document, defaultValue); } #endif template -RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr, internal::IsGenericValue >), (typename DocumentType::ValueType&)) -GetValueByPointerWithDefault(DocumentType& document, const GenericPointer& pointer, T2 defaultValue) { - return pointer.GetWithDefault(document, defaultValue); +RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr, internal::IsGenericValue>), + (typename DocumentType::ValueType &)) +GetValueByPointerWithDefault(DocumentType & document, + const GenericPointer & pointer, T2 defaultValue) +{ + return pointer.GetWithDefault(document, defaultValue); } template -typename DocumentType::ValueType& GetValueByPointerWithDefault(DocumentType& document, const CharType(&source)[N], const typename DocumentType::ValueType& defaultValue) { - return GenericPointer(source, N - 1).GetWithDefault(document, defaultValue); +typename DocumentType::ValueType & GetValueByPointerWithDefault(DocumentType & document, + const CharType(&source)[N], const typename DocumentType::ValueType & defaultValue) +{ + return GenericPointer(source, N - 1).GetWithDefault(document, defaultValue); } template -typename DocumentType::ValueType& GetValueByPointerWithDefault(DocumentType& document, const CharType(&source)[N], const typename DocumentType::Ch* defaultValue) { - return GenericPointer(source, N - 1).GetWithDefault(document, defaultValue); +typename DocumentType::ValueType & GetValueByPointerWithDefault(DocumentType & document, + const CharType(&source)[N], const typename DocumentType::Ch* defaultValue) +{ + return GenericPointer(source, N - 1).GetWithDefault(document, defaultValue); } #if RAPIDJSON_HAS_STDSTRING template -typename DocumentType::ValueType& GetValueByPointerWithDefault(DocumentType& document, const CharType(&source)[N], const std::basic_string& defaultValue) { - return GenericPointer(source, N - 1).GetWithDefault(document, defaultValue); +typename DocumentType::ValueType & GetValueByPointerWithDefault(DocumentType & document, + const CharType(&source)[N], const std::basic_string & defaultValue) +{ + return GenericPointer(source, N - 1).GetWithDefault(document, defaultValue); } #endif template -RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr, internal::IsGenericValue >), (typename DocumentType::ValueType&)) -GetValueByPointerWithDefault(DocumentType& document, const CharType(&source)[N], T2 defaultValue) { - return GenericPointer(source, N - 1).GetWithDefault(document, defaultValue); +RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr, internal::IsGenericValue>), + (typename DocumentType::ValueType &)) +GetValueByPointerWithDefault(DocumentType & document, const CharType(&source)[N], T2 defaultValue) +{ + return GenericPointer(source, N - 1).GetWithDefault(document, defaultValue); } ////////////////////////////////////////////////////////////////////////////// template -typename T::ValueType& SetValueByPointer(T& root, const GenericPointer& pointer, typename T::ValueType& value, typename T::AllocatorType& a) { - return pointer.Set(root, value, a); +typename T::ValueType & SetValueByPointer(T & root, const GenericPointer & pointer, + typename T::ValueType & value, typename T::AllocatorType & a) +{ + return pointer.Set(root, value, a); } template -typename T::ValueType& SetValueByPointer(T& root, const GenericPointer& pointer, const typename T::ValueType& value, typename T::AllocatorType& a) { - return pointer.Set(root, value, a); +typename T::ValueType & SetValueByPointer(T & root, const GenericPointer & pointer, + const typename T::ValueType & value, typename T::AllocatorType & a) +{ + return pointer.Set(root, value, a); } template -typename T::ValueType& SetValueByPointer(T& root, const GenericPointer& pointer, const typename T::Ch* value, typename T::AllocatorType& a) { - return pointer.Set(root, value, a); +typename T::ValueType & SetValueByPointer(T & root, const GenericPointer & pointer, + const typename T::Ch* value, typename T::AllocatorType & a) +{ + return pointer.Set(root, value, a); } #if RAPIDJSON_HAS_STDSTRING template -typename T::ValueType& SetValueByPointer(T& root, const GenericPointer& pointer, const std::basic_string& value, typename T::AllocatorType& a) { - return pointer.Set(root, value, a); +typename T::ValueType & SetValueByPointer(T & root, const GenericPointer & pointer, + const std::basic_string & value, typename T::AllocatorType & a) +{ + return pointer.Set(root, value, a); } #endif template -RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr, internal::IsGenericValue >), (typename T::ValueType&)) -SetValueByPointer(T& root, const GenericPointer& pointer, T2 value, typename T::AllocatorType& a) { - return pointer.Set(root, value, a); +RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr, internal::IsGenericValue>), + (typename T::ValueType &)) +SetValueByPointer(T & root, const GenericPointer & pointer, T2 value, + typename T::AllocatorType & a) +{ + return pointer.Set(root, value, a); } template -typename T::ValueType& SetValueByPointer(T& root, const CharType(&source)[N], typename T::ValueType& value, typename T::AllocatorType& a) { - return GenericPointer(source, N - 1).Set(root, value, a); +typename T::ValueType & SetValueByPointer(T & root, const CharType(&source)[N], typename T::ValueType & value, + typename T::AllocatorType & a) +{ + return GenericPointer(source, N - 1).Set(root, value, a); } template -typename T::ValueType& SetValueByPointer(T& root, const CharType(&source)[N], const typename T::ValueType& value, typename T::AllocatorType& a) { - return GenericPointer(source, N - 1).Set(root, value, a); +typename T::ValueType & SetValueByPointer(T & root, const CharType(&source)[N], + const typename T::ValueType & value, typename T::AllocatorType & a) +{ + return GenericPointer(source, N - 1).Set(root, value, a); } template -typename T::ValueType& SetValueByPointer(T& root, const CharType(&source)[N], const typename T::Ch* value, typename T::AllocatorType& a) { - return GenericPointer(source, N - 1).Set(root, value, a); +typename T::ValueType & SetValueByPointer(T & root, const CharType(&source)[N], const typename T::Ch* value, + typename T::AllocatorType & a) +{ + return GenericPointer(source, N - 1).Set(root, value, a); } #if RAPIDJSON_HAS_STDSTRING template -typename T::ValueType& SetValueByPointer(T& root, const CharType(&source)[N], const std::basic_string& value, typename T::AllocatorType& a) { - return GenericPointer(source, N - 1).Set(root, value, a); +typename T::ValueType & SetValueByPointer(T & root, const CharType(&source)[N], + const std::basic_string & value, typename T::AllocatorType & a) +{ + return GenericPointer(source, N - 1).Set(root, value, a); } #endif template -RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr, internal::IsGenericValue >), (typename T::ValueType&)) -SetValueByPointer(T& root, const CharType(&source)[N], T2 value, typename T::AllocatorType& a) { - return GenericPointer(source, N - 1).Set(root, value, a); +RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr, internal::IsGenericValue>), + (typename T::ValueType &)) +SetValueByPointer(T & root, const CharType(&source)[N], T2 value, typename T::AllocatorType & a) +{ + return GenericPointer(source, N - 1).Set(root, value, a); } // No allocator parameter template -typename DocumentType::ValueType& SetValueByPointer(DocumentType& document, const GenericPointer& pointer, typename DocumentType::ValueType& value) { - return pointer.Set(document, value); +typename DocumentType::ValueType & SetValueByPointer(DocumentType & document, + const GenericPointer & pointer, typename DocumentType::ValueType & value) +{ + return pointer.Set(document, value); } template -typename DocumentType::ValueType& SetValueByPointer(DocumentType& document, const GenericPointer& pointer, const typename DocumentType::ValueType& value) { - return pointer.Set(document, value); +typename DocumentType::ValueType & SetValueByPointer(DocumentType & document, + const GenericPointer & pointer, + const typename DocumentType::ValueType & value) +{ + return pointer.Set(document, value); } template -typename DocumentType::ValueType& SetValueByPointer(DocumentType& document, const GenericPointer& pointer, const typename DocumentType::Ch* value) { - return pointer.Set(document, value); +typename DocumentType::ValueType & SetValueByPointer(DocumentType & document, + const GenericPointer & pointer, const typename DocumentType::Ch* value) +{ + return pointer.Set(document, value); } #if RAPIDJSON_HAS_STDSTRING template -typename DocumentType::ValueType& SetValueByPointer(DocumentType& document, const GenericPointer& pointer, const std::basic_string& value) { - return pointer.Set(document, value); +typename DocumentType::ValueType & SetValueByPointer(DocumentType & document, + const GenericPointer & pointer, + const std::basic_string & value) +{ + return pointer.Set(document, value); } #endif template -RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr, internal::IsGenericValue >), (typename DocumentType::ValueType&)) -SetValueByPointer(DocumentType& document, const GenericPointer& pointer, T2 value) { - return pointer.Set(document, value); +RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr, internal::IsGenericValue>), + (typename DocumentType::ValueType &)) +SetValueByPointer(DocumentType & document, const GenericPointer & pointer, + T2 value) +{ + return pointer.Set(document, value); } template -typename DocumentType::ValueType& SetValueByPointer(DocumentType& document, const CharType(&source)[N], typename DocumentType::ValueType& value) { - return GenericPointer(source, N - 1).Set(document, value); +typename DocumentType::ValueType & SetValueByPointer(DocumentType & document, const CharType(&source)[N], + typename DocumentType::ValueType & value) +{ + return GenericPointer(source, N - 1).Set(document, value); } template -typename DocumentType::ValueType& SetValueByPointer(DocumentType& document, const CharType(&source)[N], const typename DocumentType::ValueType& value) { - return GenericPointer(source, N - 1).Set(document, value); +typename DocumentType::ValueType & SetValueByPointer(DocumentType & document, const CharType(&source)[N], + const typename DocumentType::ValueType & value) +{ + return GenericPointer(source, N - 1).Set(document, value); } template -typename DocumentType::ValueType& SetValueByPointer(DocumentType& document, const CharType(&source)[N], const typename DocumentType::Ch* value) { - return GenericPointer(source, N - 1).Set(document, value); +typename DocumentType::ValueType & SetValueByPointer(DocumentType & document, const CharType(&source)[N], + const typename DocumentType::Ch* value) +{ + return GenericPointer(source, N - 1).Set(document, value); } #if RAPIDJSON_HAS_STDSTRING template -typename DocumentType::ValueType& SetValueByPointer(DocumentType& document, const CharType(&source)[N], const std::basic_string& value) { - return GenericPointer(source, N - 1).Set(document, value); +typename DocumentType::ValueType & SetValueByPointer(DocumentType & document, const CharType(&source)[N], + const std::basic_string & value) +{ + return GenericPointer(source, N - 1).Set(document, value); } #endif template -RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr, internal::IsGenericValue >), (typename DocumentType::ValueType&)) -SetValueByPointer(DocumentType& document, const CharType(&source)[N], T2 value) { - return GenericPointer(source, N - 1).Set(document, value); +RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr, internal::IsGenericValue>), + (typename DocumentType::ValueType &)) +SetValueByPointer(DocumentType & document, const CharType(&source)[N], T2 value) +{ + return GenericPointer(source, N - 1).Set(document, value); } ////////////////////////////////////////////////////////////////////////////// template -typename T::ValueType& SwapValueByPointer(T& root, const GenericPointer& pointer, typename T::ValueType& value, typename T::AllocatorType& a) { - return pointer.Swap(root, value, a); +typename T::ValueType & SwapValueByPointer(T & root, const GenericPointer & pointer, + typename T::ValueType & value, typename T::AllocatorType & a) +{ + return pointer.Swap(root, value, a); } template -typename T::ValueType& SwapValueByPointer(T& root, const CharType(&source)[N], typename T::ValueType& value, typename T::AllocatorType& a) { - return GenericPointer(source, N - 1).Swap(root, value, a); +typename T::ValueType & SwapValueByPointer(T & root, const CharType(&source)[N], typename T::ValueType & value, + typename T::AllocatorType & a) +{ + return GenericPointer(source, N - 1).Swap(root, value, a); } template -typename DocumentType::ValueType& SwapValueByPointer(DocumentType& document, const GenericPointer& pointer, typename DocumentType::ValueType& value) { - return pointer.Swap(document, value); +typename DocumentType::ValueType & SwapValueByPointer(DocumentType & document, + const GenericPointer & pointer, typename DocumentType::ValueType & value) +{ + return pointer.Swap(document, value); } template -typename DocumentType::ValueType& SwapValueByPointer(DocumentType& document, const CharType(&source)[N], typename DocumentType::ValueType& value) { - return GenericPointer(source, N - 1).Swap(document, value); +typename DocumentType::ValueType & SwapValueByPointer(DocumentType & document, const CharType(&source)[N], + typename DocumentType::ValueType & value) +{ + return GenericPointer(source, N - 1).Swap(document, value); } ////////////////////////////////////////////////////////////////////////////// template -bool EraseValueByPointer(T& root, const GenericPointer& pointer) { - return pointer.Erase(root); +bool EraseValueByPointer(T & root, const GenericPointer & pointer) +{ + return pointer.Erase(root); } template -bool EraseValueByPointer(T& root, const CharType(&source)[N]) { - return GenericPointer(source, N - 1).Erase(root); +bool EraseValueByPointer(T & root, const CharType(&source)[N]) +{ + return GenericPointer(source, N - 1).Erase(root); } //@} diff --git a/src/3rdparty/rapidjson/prettywriter.h b/src/3rdparty/rapidjson/prettywriter.h index 0dcb0fee..b8576b3f 100644 --- a/src/3rdparty/rapidjson/prettywriter.h +++ b/src/3rdparty/rapidjson/prettywriter.h @@ -1,5 +1,5 @@ // 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 @@ -7,9 +7,9 @@ // // 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 +// 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_PRETTYWRITER_H_ @@ -27,9 +27,10 @@ RAPIDJSON_NAMESPACE_BEGIN //! Combination of PrettyWriter format flags. /*! \see PrettyWriter::SetFormatOptions */ -enum PrettyFormatOptions { - kFormatDefault = 0, //!< Default pretty formatting. - kFormatSingleLineArray = 1 //!< Format arrays on a single line. +enum PrettyFormatOptions +{ + kFormatDefault = 0, //!< Default pretty formatting. + kFormatSingleLineArray = 1 //!< Format arrays on a single line. }; //! Writer with indentation and spacing. @@ -40,210 +41,288 @@ enum PrettyFormatOptions { \tparam StackAllocator Type of allocator for allocating memory of stack. */ template, typename TargetEncoding = UTF8<>, typename StackAllocator = CrtAllocator, unsigned writeFlags = kWriteDefaultFlags> -class PrettyWriter : public Writer { +class PrettyWriter : public Writer +{ public: - typedef Writer Base; - typedef typename Base::Ch Ch; + typedef Writer Base; + typedef typename Base::Ch Ch; - //! Constructor - /*! \param os Output stream. - \param allocator User supplied allocator. If it is null, it will create a private one. - \param levelDepth Initial capacity of stack. - */ - explicit PrettyWriter(OutputStream& os, StackAllocator* allocator = 0, size_t levelDepth = Base::kDefaultLevelDepth) : - Base(os, allocator, levelDepth), indentChar_(' '), indentCharCount_(4), formatOptions_(kFormatDefault) {} + //! Constructor + /*! \param os Output stream. + \param allocator User supplied allocator. If it is null, it will create a private one. + \param levelDepth Initial capacity of stack. + */ + explicit PrettyWriter(OutputStream & os, StackAllocator* allocator = 0, + size_t levelDepth = Base::kDefaultLevelDepth) : + Base(os, allocator, levelDepth), indentChar_(' '), indentCharCount_(4), formatOptions_(kFormatDefault) {} - explicit PrettyWriter(StackAllocator* allocator = 0, size_t levelDepth = Base::kDefaultLevelDepth) : - Base(allocator, levelDepth), indentChar_(' '), indentCharCount_(4) {} + explicit PrettyWriter(StackAllocator* allocator = 0, size_t levelDepth = Base::kDefaultLevelDepth) : + Base(allocator, levelDepth), indentChar_(' '), indentCharCount_(4) {} - //! Set custom indentation. - /*! \param indentChar Character for indentation. Must be whitespace character (' ', '\\t', '\\n', '\\r'). - \param indentCharCount Number of indent characters for each indentation level. - \note The default indentation is 4 spaces. - */ - PrettyWriter& SetIndent(Ch indentChar, unsigned indentCharCount) { - RAPIDJSON_ASSERT(indentChar == ' ' || indentChar == '\t' || indentChar == '\n' || indentChar == '\r'); - indentChar_ = indentChar; - indentCharCount_ = indentCharCount; - return *this; - } + //! Set custom indentation. + /*! \param indentChar Character for indentation. Must be whitespace character (' ', '\\t', '\\n', '\\r'). + \param indentCharCount Number of indent characters for each indentation level. + \note The default indentation is 4 spaces. + */ + PrettyWriter & SetIndent(Ch indentChar, unsigned indentCharCount) + { + RAPIDJSON_ASSERT(indentChar == ' ' || indentChar == '\t' || indentChar == '\n' || indentChar == '\r'); + indentChar_ = indentChar; + indentCharCount_ = indentCharCount; + return *this; + } - //! Set pretty writer formatting options. - /*! \param options Formatting options. - */ - PrettyWriter& SetFormatOptions(PrettyFormatOptions options) { - formatOptions_ = options; - return *this; - } + //! Set pretty writer formatting options. + /*! \param options Formatting options. + */ + PrettyWriter & SetFormatOptions(PrettyFormatOptions options) + { + formatOptions_ = options; + return *this; + } - /*! @name Implementation of Handler - \see Handler - */ - //@{ + /*! @name Implementation of Handler + \see Handler + */ + //@{ - bool Null() { PrettyPrefix(kNullType); return Base::WriteNull(); } - bool Bool(bool b) { PrettyPrefix(b ? kTrueType : kFalseType); return Base::WriteBool(b); } - bool Int(int i) { PrettyPrefix(kNumberType); return Base::WriteInt(i); } - bool Uint(unsigned u) { PrettyPrefix(kNumberType); return Base::WriteUint(u); } - bool Int64(int64_t i64) { PrettyPrefix(kNumberType); return Base::WriteInt64(i64); } - bool Uint64(uint64_t u64) { PrettyPrefix(kNumberType); return Base::WriteUint64(u64); } - bool Double(double d) { PrettyPrefix(kNumberType); return Base::WriteDouble(d); } + bool Null() + { + PrettyPrefix(kNullType); + return Base::WriteNull(); + } + bool Bool(bool b) + { + PrettyPrefix(b ? kTrueType : kFalseType); + return Base::WriteBool(b); + } + bool Int(int i) + { + PrettyPrefix(kNumberType); + return Base::WriteInt(i); + } + bool Uint(unsigned u) + { + PrettyPrefix(kNumberType); + return Base::WriteUint(u); + } + bool Int64(int64_t i64) + { + PrettyPrefix(kNumberType); + return Base::WriteInt64(i64); + } + bool Uint64(uint64_t u64) + { + PrettyPrefix(kNumberType); + return Base::WriteUint64(u64); + } + bool Double(double d) + { + PrettyPrefix(kNumberType); + return Base::WriteDouble(d); + } - bool RawNumber(const Ch* str, SizeType length, bool copy = false) { - (void)copy; - PrettyPrefix(kNumberType); - return Base::WriteString(str, length); - } + bool RawNumber(const Ch* str, SizeType length, bool copy = false) + { + (void)copy; + PrettyPrefix(kNumberType); + return Base::WriteString(str, length); + } - bool String(const Ch* str, SizeType length, bool copy = false) { - (void)copy; - PrettyPrefix(kStringType); - return Base::WriteString(str, length); - } + bool String(const Ch* str, SizeType length, bool copy = false) + { + (void)copy; + PrettyPrefix(kStringType); + return Base::WriteString(str, length); + } #if RAPIDJSON_HAS_STDSTRING - bool String(const std::basic_string& str) { - return String(str.data(), SizeType(str.size())); - } + bool String(const std::basic_string & str) + { + return String(str.data(), SizeType(str.size())); + } #endif - bool StartObject() { - PrettyPrefix(kObjectType); - new (Base::level_stack_.template Push()) typename Base::Level(false); - return Base::WriteStartObject(); - } + bool StartObject() + { + PrettyPrefix(kObjectType); + new(Base::level_stack_.template Push()) typename Base::Level(false); + return Base::WriteStartObject(); + } - bool Key(const Ch* str, SizeType length, bool copy = false) { return String(str, length, copy); } + bool Key(const Ch* str, SizeType length, bool copy = false) + { + return String(str, length, copy); + } #if RAPIDJSON_HAS_STDSTRING - bool Key(const std::basic_string& str) { - return Key(str.data(), SizeType(str.size())); - } + bool Key(const std::basic_string & str) + { + return Key(str.data(), SizeType(str.size())); + } #endif - - bool EndObject(SizeType memberCount = 0) { - (void)memberCount; - RAPIDJSON_ASSERT(Base::level_stack_.GetSize() >= sizeof(typename Base::Level)); - RAPIDJSON_ASSERT(!Base::level_stack_.template Top()->inArray); - bool empty = Base::level_stack_.template Pop(1)->valueCount == 0; - if (!empty) { - Base::os_->Put('\n'); - WriteIndent(); - } - bool ret = Base::WriteEndObject(); - (void)ret; - RAPIDJSON_ASSERT(ret == true); - if (Base::level_stack_.Empty()) // end of json text - Base::os_->Flush(); - return true; - } + bool EndObject(SizeType memberCount = 0) + { + (void)memberCount; + RAPIDJSON_ASSERT(Base::level_stack_.GetSize() >= sizeof(typename Base::Level)); + RAPIDJSON_ASSERT(!Base::level_stack_.template Top()->inArray); + bool empty = Base::level_stack_.template Pop(1)->valueCount == 0; - bool StartArray() { - PrettyPrefix(kArrayType); - new (Base::level_stack_.template Push()) typename Base::Level(true); - return Base::WriteStartArray(); - } + if(!empty) + { + Base::os_->Put('\n'); + WriteIndent(); + } + bool ret = Base::WriteEndObject(); + (void)ret; + RAPIDJSON_ASSERT(ret == true); + if(Base::level_stack_.Empty()) // end of json text + { + Base::os_->Flush(); + } + return true; + } - bool EndArray(SizeType memberCount = 0) { - (void)memberCount; - RAPIDJSON_ASSERT(Base::level_stack_.GetSize() >= sizeof(typename Base::Level)); - RAPIDJSON_ASSERT(Base::level_stack_.template Top()->inArray); - bool empty = Base::level_stack_.template Pop(1)->valueCount == 0; + bool StartArray() + { + PrettyPrefix(kArrayType); + new(Base::level_stack_.template Push()) typename Base::Level(true); + return Base::WriteStartArray(); + } - if (!empty && !(formatOptions_ & kFormatSingleLineArray)) { - Base::os_->Put('\n'); - WriteIndent(); - } - bool ret = Base::WriteEndArray(); - (void)ret; - RAPIDJSON_ASSERT(ret == true); - if (Base::level_stack_.Empty()) // end of json text - Base::os_->Flush(); - return true; - } + bool EndArray(SizeType memberCount = 0) + { + (void)memberCount; + RAPIDJSON_ASSERT(Base::level_stack_.GetSize() >= sizeof(typename Base::Level)); + RAPIDJSON_ASSERT(Base::level_stack_.template Top()->inArray); + bool empty = Base::level_stack_.template Pop(1)->valueCount == 0; - //@} + if(!empty && !(formatOptions_ & kFormatSingleLineArray)) + { + Base::os_->Put('\n'); + WriteIndent(); + } + bool ret = Base::WriteEndArray(); + (void)ret; + RAPIDJSON_ASSERT(ret == true); + if(Base::level_stack_.Empty()) // end of json text + { + Base::os_->Flush(); + } + return true; + } - /*! @name Convenience extensions */ - //@{ + //@} - //! Simpler but slower overload. - bool String(const Ch* str) { return String(str, internal::StrLen(str)); } - bool Key(const Ch* str) { return Key(str, internal::StrLen(str)); } + /*! @name Convenience extensions */ + //@{ - //@} + //! Simpler but slower overload. + bool String(const Ch* str) + { + return String(str, internal::StrLen(str)); + } + bool Key(const Ch* str) + { + return Key(str, internal::StrLen(str)); + } - //! Write a raw JSON value. - /*! - For user to write a stringified JSON as a value. + //@} - \param json A well-formed JSON value. It should not contain null character within [0, length - 1] range. - \param length Length of the json. - \param type Type of the root of json. - \note When using PrettyWriter::RawValue(), the result json may not be indented correctly. - */ - bool RawValue(const Ch* json, size_t length, Type type) { PrettyPrefix(type); return Base::WriteRawValue(json, length); } + //! Write a raw JSON value. + /*! + For user to write a stringified JSON as a value. + + \param json A well-formed JSON value. It should not contain null character within [0, length - 1] range. + \param length Length of the json. + \param type Type of the root of json. + \note When using PrettyWriter::RawValue(), the result json may not be indented correctly. + */ + bool RawValue(const Ch* json, size_t length, Type type) + { + PrettyPrefix(type); + return Base::WriteRawValue(json, length); + } protected: - void PrettyPrefix(Type type) { - (void)type; - if (Base::level_stack_.GetSize() != 0) { // this value is not at root - typename Base::Level* level = Base::level_stack_.template Top(); + void PrettyPrefix(Type type) + { + (void)type; + if(Base::level_stack_.GetSize() != 0) // this value is not at root + { + typename Base::Level* level = Base::level_stack_.template Top(); - if (level->inArray) { - if (level->valueCount > 0) { - Base::os_->Put(','); // add comma if it is not the first element in array - if (formatOptions_ & kFormatSingleLineArray) - Base::os_->Put(' '); - } + if(level->inArray) + { + if(level->valueCount > 0) + { + Base::os_->Put(','); // add comma if it is not the first element in array + if(formatOptions_ & kFormatSingleLineArray) + { + Base::os_->Put(' '); + } + } - if (!(formatOptions_ & kFormatSingleLineArray)) { - Base::os_->Put('\n'); - WriteIndent(); - } - } - else { // in object - if (level->valueCount > 0) { - if (level->valueCount % 2 == 0) { - Base::os_->Put(','); - Base::os_->Put('\n'); - } - else { - Base::os_->Put(':'); - Base::os_->Put(' '); - } - } - else - Base::os_->Put('\n'); + if(!(formatOptions_ & kFormatSingleLineArray)) + { + Base::os_->Put('\n'); + WriteIndent(); + } + } + else // in object + { + if(level->valueCount > 0) + { + if(level->valueCount % 2 == 0) + { + Base::os_->Put(','); + Base::os_->Put('\n'); + } + else + { + Base::os_->Put(':'); + Base::os_->Put(' '); + } + } + else + { + Base::os_->Put('\n'); + } - if (level->valueCount % 2 == 0) - WriteIndent(); - } - if (!level->inArray && level->valueCount % 2 == 0) - RAPIDJSON_ASSERT(type == kStringType); // if it's in object, then even number should be a name - level->valueCount++; - } - else { - RAPIDJSON_ASSERT(!Base::hasRoot_); // Should only has one and only one root. - Base::hasRoot_ = true; - } - } + if(level->valueCount % 2 == 0) + { + WriteIndent(); + } + } + if(!level->inArray && level->valueCount % 2 == 0) + { + RAPIDJSON_ASSERT(type == kStringType); // if it's in object, then even number should be a name + } + level->valueCount++; + } + else + { + RAPIDJSON_ASSERT(!Base::hasRoot_); // Should only has one and only one root. + Base::hasRoot_ = true; + } + } - void WriteIndent() { - size_t count = (Base::level_stack_.GetSize() / sizeof(typename Base::Level)) * indentCharCount_; - PutN(*Base::os_, static_cast(indentChar_), count); - } + void WriteIndent() + { + size_t count = (Base::level_stack_.GetSize() / sizeof(typename Base::Level)) * indentCharCount_; + PutN(*Base::os_, static_cast(indentChar_), count); + } - Ch indentChar_; - unsigned indentCharCount_; - PrettyFormatOptions formatOptions_; + Ch indentChar_; + unsigned indentCharCount_; + PrettyFormatOptions formatOptions_; private: - // Prohibit copy constructor & assignment operator. - PrettyWriter(const PrettyWriter&); - PrettyWriter& operator=(const PrettyWriter&); + // Prohibit copy constructor & assignment operator. + PrettyWriter(const PrettyWriter &); + PrettyWriter & operator=(const PrettyWriter &); }; RAPIDJSON_NAMESPACE_END diff --git a/src/3rdparty/rapidjson/rapidjson.h b/src/3rdparty/rapidjson/rapidjson.h index 2ef9bc56..38b7f0da 100644 --- a/src/3rdparty/rapidjson/rapidjson.h +++ b/src/3rdparty/rapidjson/rapidjson.h @@ -1,5 +1,5 @@ // 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 @@ -7,9 +7,9 @@ // // 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 +// 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_RAPIDJSON_H_ @@ -17,7 +17,7 @@ /*!\file rapidjson.h \brief common definitions and configuration - + \see RAPIDJSON_CONFIG */ @@ -71,7 +71,7 @@ #define RAPIDJSON_MINOR_VERSION 1 #define RAPIDJSON_PATCH_VERSION 0 #define RAPIDJSON_VERSION_STRING \ - RAPIDJSON_STRINGIFY(RAPIDJSON_MAJOR_VERSION.RAPIDJSON_MINOR_VERSION.RAPIDJSON_PATCH_VERSION) + RAPIDJSON_STRINGIFY(RAPIDJSON_MAJOR_VERSION.RAPIDJSON_MINOR_VERSION.RAPIDJSON_PATCH_VERSION) /////////////////////////////////////////////////////////////////////////////// // RAPIDJSON_NAMESPACE_(BEGIN|END) @@ -241,7 +241,7 @@ # elif defined(RAPIDJSON_DOXYGEN_RUNNING) # define RAPIDJSON_ENDIAN # else -# error Unknown machine endianess detected. User needs to define RAPIDJSON_ENDIAN. +# error Unknown machine endianess detected. User needs to define RAPIDJSON_ENDIAN. # endif #endif // RAPIDJSON_ENDIAN @@ -411,7 +411,10 @@ RAPIDJSON_NAMESPACE_END #endif RAPIDJSON_NAMESPACE_BEGIN template struct STATIC_ASSERTION_FAILURE; -template <> struct STATIC_ASSERTION_FAILURE { enum { value = 1 }; }; +template <> struct STATIC_ASSERTION_FAILURE +{ + enum { value = 1 }; +}; template struct StaticAssertTest {}; RAPIDJSON_NAMESPACE_END @@ -422,7 +425,7 @@ RAPIDJSON_NAMESPACE_END #if defined(__GNUC__) #define RAPIDJSON_STATIC_ASSERT_UNUSED_ATTRIBUTE __attribute__((unused)) #else -#define RAPIDJSON_STATIC_ASSERT_UNUSED_ATTRIBUTE +#define RAPIDJSON_STATIC_ASSERT_UNUSED_ATTRIBUTE #endif #ifndef __clang__ //!@endcond @@ -434,9 +437,9 @@ RAPIDJSON_NAMESPACE_END \hideinitializer */ #define RAPIDJSON_STATIC_ASSERT(x) \ - typedef ::RAPIDJSON_NAMESPACE::StaticAssertTest< \ - sizeof(::RAPIDJSON_NAMESPACE::STATIC_ASSERTION_FAILURE)> \ - RAPIDJSON_JOIN(StaticAssertTypedef, __LINE__) RAPIDJSON_STATIC_ASSERT_UNUSED_ATTRIBUTE + typedef ::RAPIDJSON_NAMESPACE::StaticAssertTest< \ + sizeof(::RAPIDJSON_NAMESPACE::STATIC_ASSERTION_FAILURE)> \ + RAPIDJSON_JOIN(StaticAssertTypedef, __LINE__) RAPIDJSON_STATIC_ASSERT_UNUSED_ATTRIBUTE #endif /////////////////////////////////////////////////////////////////////////////// @@ -473,20 +476,20 @@ RAPIDJSON_NAMESPACE_END //!@cond RAPIDJSON_HIDDEN_FROM_DOXYGEN -#define RAPIDJSON_MULTILINEMACRO_BEGIN do { +#define RAPIDJSON_MULTILINEMACRO_BEGIN do { #define RAPIDJSON_MULTILINEMACRO_END \ -} while((void)0, 0) + } while((void)0, 0) // adopted from Boost #define RAPIDJSON_VERSION_CODE(x,y,z) \ - (((x)*100000) + ((y)*100) + (z)) + (((x)*100000) + ((y)*100) + (z)) /////////////////////////////////////////////////////////////////////////////// // RAPIDJSON_DIAG_PUSH/POP, RAPIDJSON_DIAG_OFF #if defined(__GNUC__) #define RAPIDJSON_GNUC \ - RAPIDJSON_VERSION_CODE(__GNUC__,__GNUC_MINOR__,__GNUC_PATCHLEVEL__) + RAPIDJSON_VERSION_CODE(__GNUC__,__GNUC_MINOR__,__GNUC_PATCHLEVEL__) #endif #if defined(__clang__) || (defined(RAPIDJSON_GNUC) && RAPIDJSON_GNUC >= RAPIDJSON_VERSION_CODE(4,2,0)) @@ -494,7 +497,7 @@ RAPIDJSON_NAMESPACE_END #define RAPIDJSON_PRAGMA(x) _Pragma(RAPIDJSON_STRINGIFY(x)) #define RAPIDJSON_DIAG_PRAGMA(x) RAPIDJSON_PRAGMA(GCC diagnostic x) #define RAPIDJSON_DIAG_OFF(x) \ - RAPIDJSON_DIAG_PRAGMA(ignored RAPIDJSON_STRINGIFY(RAPIDJSON_JOIN(-W,x))) + RAPIDJSON_DIAG_PRAGMA(ignored RAPIDJSON_STRINGIFY(RAPIDJSON_JOIN(-W,x))) // push/pop support in Clang and GCC>=4.6 #if defined(__clang__) || (defined(RAPIDJSON_GNUC) && RAPIDJSON_GNUC >= RAPIDJSON_VERSION_CODE(4,6,0)) @@ -599,14 +602,15 @@ RAPIDJSON_NAMESPACE_END RAPIDJSON_NAMESPACE_BEGIN //! Type of JSON value -enum Type { - kNullType = 0, //!< null - kFalseType = 1, //!< false - kTrueType = 2, //!< true - kObjectType = 3, //!< object - kArrayType = 4, //!< array - kStringType = 5, //!< string - kNumberType = 6 //!< number +enum Type +{ + kNullType = 0, //!< null + kFalseType = 1, //!< false + kTrueType = 2, //!< true + kObjectType = 3, //!< object + kArrayType = 4, //!< array + kStringType = 5, //!< string + kNumberType = 6 //!< number }; RAPIDJSON_NAMESPACE_END diff --git a/src/3rdparty/rapidjson/reader.h b/src/3rdparty/rapidjson/reader.h index 303aac2e..015b4b3f 100644 --- a/src/3rdparty/rapidjson/reader.h +++ b/src/3rdparty/rapidjson/reader.h @@ -43,117 +43,118 @@ RAPIDJSON_DIAG_OFF(4702) // unreachable code #ifdef __clang__ RAPIDJSON_DIAG_PUSH -RAPIDJSON_DIAG_OFF(old-style-cast) +RAPIDJSON_DIAG_OFF(old - style - cast) RAPIDJSON_DIAG_OFF(padded) -RAPIDJSON_DIAG_OFF(switch-enum) +RAPIDJSON_DIAG_OFF(switch - enum) #endif #ifdef __GNUC__ -RAPIDJSON_DIAG_PUSH -RAPIDJSON_DIAG_OFF(effc++) + RAPIDJSON_DIAG_PUSH + RAPIDJSON_DIAG_OFF(effc++) #endif -//!@cond RAPIDJSON_HIDDEN_FROM_DOXYGEN + //!@cond RAPIDJSON_HIDDEN_FROM_DOXYGEN #define RAPIDJSON_NOTHING /* deliberately empty */ #ifndef RAPIDJSON_PARSE_ERROR_EARLY_RETURN #define RAPIDJSON_PARSE_ERROR_EARLY_RETURN(value) \ - RAPIDJSON_MULTILINEMACRO_BEGIN \ - if (RAPIDJSON_UNLIKELY(HasParseError())) { return value; } \ - RAPIDJSON_MULTILINEMACRO_END + RAPIDJSON_MULTILINEMACRO_BEGIN \ + if (RAPIDJSON_UNLIKELY(HasParseError())) { return value; } \ +RAPIDJSON_MULTILINEMACRO_END #endif #define RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID \ - RAPIDJSON_PARSE_ERROR_EARLY_RETURN(RAPIDJSON_NOTHING) -//!@endcond + RAPIDJSON_PARSE_ERROR_EARLY_RETURN(RAPIDJSON_NOTHING) + //!@endcond -/*! \def RAPIDJSON_PARSE_ERROR_NORETURN - \ingroup RAPIDJSON_ERRORS - \brief Macro to indicate a parse error. - \param parseErrorCode \ref rapidjson::ParseErrorCode of the error - \param offset position of the error in JSON input (\c size_t) + /*! \def RAPIDJSON_PARSE_ERROR_NORETURN + \ingroup RAPIDJSON_ERRORS + \brief Macro to indicate a parse error. + \param parseErrorCode \ref rapidjson::ParseErrorCode of the error + \param offset position of the error in JSON input (\c size_t) - This macros can be used as a customization point for the internal - error handling mechanism of RapidJSON. + This macros can be used as a customization point for the internal + error handling mechanism of RapidJSON. - A common usage model is to throw an exception instead of requiring the - caller to explicitly check the \ref rapidjson::GenericReader::Parse's - return value: + A common usage model is to throw an exception instead of requiring the + caller to explicitly check the \ref rapidjson::GenericReader::Parse's + return value: - \code - #define RAPIDJSON_PARSE_ERROR_NORETURN(parseErrorCode,offset) \ - throw ParseException(parseErrorCode, #parseErrorCode, offset) + \code + #define RAPIDJSON_PARSE_ERROR_NORETURN(parseErrorCode,offset) \ + throw ParseException(parseErrorCode, #parseErrorCode, offset) - #include // std::runtime_error - #include "rapidjson/error/error.h" // rapidjson::ParseResult + #include // std::runtime_error + #include "rapidjson/error/error.h" // rapidjson::ParseResult - struct ParseException : std::runtime_error, rapidjson::ParseResult { - ParseException(rapidjson::ParseErrorCode code, const char* msg, size_t offset) - : std::runtime_error(msg), ParseResult(code, offset) {} - }; + struct ParseException : std::runtime_error, rapidjson::ParseResult { + ParseException(rapidjson::ParseErrorCode code, const char* msg, size_t offset) + : std::runtime_error(msg), ParseResult(code, offset) {} + }; - #include "rapidjson/reader.h" - \endcode + #include "rapidjson/reader.h" + \endcode - \see RAPIDJSON_PARSE_ERROR, rapidjson::GenericReader::Parse - */ + \see RAPIDJSON_PARSE_ERROR, rapidjson::GenericReader::Parse + */ #ifndef RAPIDJSON_PARSE_ERROR_NORETURN #define RAPIDJSON_PARSE_ERROR_NORETURN(parseErrorCode, offset) \ - RAPIDJSON_MULTILINEMACRO_BEGIN \ - RAPIDJSON_ASSERT(!HasParseError()); /* Error can only be assigned once */ \ - SetParseError(parseErrorCode, offset); \ - RAPIDJSON_MULTILINEMACRO_END + RAPIDJSON_MULTILINEMACRO_BEGIN \ + RAPIDJSON_ASSERT(!HasParseError()); /* Error can only be assigned once */ \ +SetParseError(parseErrorCode, offset); \ +RAPIDJSON_MULTILINEMACRO_END #endif -/*! \def RAPIDJSON_PARSE_ERROR - \ingroup RAPIDJSON_ERRORS - \brief (Internal) macro to indicate and handle a parse error. - \param parseErrorCode \ref rapidjson::ParseErrorCode of the error - \param offset position of the error in JSON input (\c size_t) + /*! \def RAPIDJSON_PARSE_ERROR + \ingroup RAPIDJSON_ERRORS + \brief (Internal) macro to indicate and handle a parse error. + \param parseErrorCode \ref rapidjson::ParseErrorCode of the error + \param offset position of the error in JSON input (\c size_t) - Invokes RAPIDJSON_PARSE_ERROR_NORETURN and stops the parsing. + Invokes RAPIDJSON_PARSE_ERROR_NORETURN and stops the parsing. - \see RAPIDJSON_PARSE_ERROR_NORETURN - \hideinitializer - */ + \see RAPIDJSON_PARSE_ERROR_NORETURN + \hideinitializer + */ #ifndef RAPIDJSON_PARSE_ERROR #define RAPIDJSON_PARSE_ERROR(parseErrorCode, offset) \ - RAPIDJSON_MULTILINEMACRO_BEGIN \ - RAPIDJSON_PARSE_ERROR_NORETURN(parseErrorCode, offset); \ - RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID; \ - RAPIDJSON_MULTILINEMACRO_END + RAPIDJSON_MULTILINEMACRO_BEGIN \ + RAPIDJSON_PARSE_ERROR_NORETURN(parseErrorCode, offset); \ +RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID; \ +RAPIDJSON_MULTILINEMACRO_END #endif #include "error/error.h" // ParseErrorCode, ParseResult -RAPIDJSON_NAMESPACE_BEGIN + RAPIDJSON_NAMESPACE_BEGIN -/////////////////////////////////////////////////////////////////////////////// -// ParseFlag + /////////////////////////////////////////////////////////////////////////////// + // ParseFlag -/*! \def RAPIDJSON_PARSE_DEFAULT_FLAGS - \ingroup RAPIDJSON_CONFIG - \brief User-defined kParseDefaultFlags definition. + /*! \def RAPIDJSON_PARSE_DEFAULT_FLAGS + \ingroup RAPIDJSON_CONFIG + \brief User-defined kParseDefaultFlags definition. - User can define this as any \c ParseFlag combinations. -*/ + User can define this as any \c ParseFlag combinations. + */ #ifndef RAPIDJSON_PARSE_DEFAULT_FLAGS #define RAPIDJSON_PARSE_DEFAULT_FLAGS kParseCommentsFlag | kParseTrailingCommasFlag #endif -//! Combination of parseFlags -/*! \see Reader::Parse, Document::Parse, Document::ParseInsitu, Document::ParseStream - */ -enum ParseFlag { - kParseNoFlags = 0, //!< No flags are set. - kParseInsituFlag = 1, //!< In-situ(destructive) parsing. - kParseValidateEncodingFlag = 2, //!< Validate encoding of JSON strings. - kParseIterativeFlag = 4, //!< Iterative(constant complexity in terms of function call stack size) parsing. - kParseStopWhenDoneFlag = 8, //!< After parsing a complete JSON root from stream, stop further processing the rest of stream. When this flag is used, parser will not generate kParseErrorDocumentRootNotSingular error. - kParseFullPrecisionFlag = 16, //!< Parse number in full precision (but slower). - kParseCommentsFlag = 32, //!< Allow one-line (//) and multi-line (/**/) comments. - kParseNumbersAsStringsFlag = 64, //!< Parse all numbers (ints/doubles) as strings. - kParseTrailingCommasFlag = 128, //!< Allow trailing commas at the end of objects and arrays. - kParseNanAndInfFlag = 256, //!< Allow parsing NaN, Inf, Infinity, -Inf and -Infinity as doubles. - kParseDefaultFlags = RAPIDJSON_PARSE_DEFAULT_FLAGS //!< Default parse flags. Can be customized by defining RAPIDJSON_PARSE_DEFAULT_FLAGS + //! Combination of parseFlags + /*! \see Reader::Parse, Document::Parse, Document::ParseInsitu, Document::ParseStream + */ + enum ParseFlag +{ + kParseNoFlags = 0, //!< No flags are set. + kParseInsituFlag = 1, //!< In-situ(destructive) parsing. + kParseValidateEncodingFlag = 2, //!< Validate encoding of JSON strings. + kParseIterativeFlag = 4, //!< Iterative(constant complexity in terms of function call stack size) parsing. + kParseStopWhenDoneFlag = 8, //!< After parsing a complete JSON root from stream, stop further processing the rest of stream. When this flag is used, parser will not generate kParseErrorDocumentRootNotSingular error. + kParseFullPrecisionFlag = 16, //!< Parse number in full precision (but slower). + kParseCommentsFlag = 32, //!< Allow one-line (//) and multi-line (/**/) comments. + kParseNumbersAsStringsFlag = 64, //!< Parse all numbers (ints/doubles) as strings. + kParseTrailingCommasFlag = 128, //!< Allow trailing commas at the end of objects and arrays. + kParseNanAndInfFlag = 256, //!< Allow parsing NaN, Inf, Infinity, -Inf and -Infinity as doubles. + kParseDefaultFlags = RAPIDJSON_PARSE_DEFAULT_FLAGS //!< Default parse flags. Can be customized by defining RAPIDJSON_PARSE_DEFAULT_FLAGS }; /////////////////////////////////////////////////////////////////////////////// @@ -193,63 +194,116 @@ concept Handler { \note implements Handler concept */ template, typename Derived = void> -struct BaseReaderHandler { - typedef typename Encoding::Ch Ch; +struct BaseReaderHandler +{ + typedef typename Encoding::Ch Ch; - typedef typename internal::SelectIf, BaseReaderHandler, Derived>::Type Override; + typedef typename internal::SelectIf, BaseReaderHandler, Derived>::Type + Override; - bool Default() { return true; } - bool Null() { return static_cast(*this).Default(); } - bool Bool(bool) { return static_cast(*this).Default(); } - bool Int(int) { return static_cast(*this).Default(); } - bool Uint(unsigned) { return static_cast(*this).Default(); } - bool Int64(int64_t) { return static_cast(*this).Default(); } - bool Uint64(uint64_t) { return static_cast(*this).Default(); } - bool Double(double) { return static_cast(*this).Default(); } - /// enabled via kParseNumbersAsStringsFlag, string is not null-terminated (use length) - bool RawNumber(const Ch* str, SizeType len, bool copy) { return static_cast(*this).String(str, len, copy); } - bool String(const Ch*, SizeType, bool) { return static_cast(*this).Default(); } - bool StartObject() { return static_cast(*this).Default(); } - bool Key(const Ch* str, SizeType len, bool copy) { return static_cast(*this).String(str, len, copy); } - bool EndObject(SizeType) { return static_cast(*this).Default(); } - bool StartArray() { return static_cast(*this).Default(); } - bool EndArray(SizeType) { return static_cast(*this).Default(); } + bool Default() + { + return true; + } + bool Null() + { + return static_cast(*this).Default(); + } + bool Bool(bool) + { + return static_cast(*this).Default(); + } + bool Int(int) + { + return static_cast(*this).Default(); + } + bool Uint(unsigned) + { + return static_cast(*this).Default(); + } + bool Int64(int64_t) + { + return static_cast(*this).Default(); + } + bool Uint64(uint64_t) + { + return static_cast(*this).Default(); + } + bool Double(double) + { + return static_cast(*this).Default(); + } + /// enabled via kParseNumbersAsStringsFlag, string is not null-terminated (use length) + bool RawNumber(const Ch* str, SizeType len, bool copy) + { + return static_cast(*this).String(str, len, copy); + } + bool String(const Ch*, SizeType, bool) + { + return static_cast(*this).Default(); + } + bool StartObject() + { + return static_cast(*this).Default(); + } + bool Key(const Ch* str, SizeType len, bool copy) + { + return static_cast(*this).String(str, len, copy); + } + bool EndObject(SizeType) + { + return static_cast(*this).Default(); + } + bool StartArray() + { + return static_cast(*this).Default(); + } + bool EndArray(SizeType) + { + return static_cast(*this).Default(); + } }; /////////////////////////////////////////////////////////////////////////////// // StreamLocalCopy -namespace internal { +namespace internal +{ -template::copyOptimization> -class StreamLocalCopy; + template::copyOptimization> + class StreamLocalCopy; -//! Do copy optimization. -template -class StreamLocalCopy { -public: - StreamLocalCopy(Stream& original) : s(original), original_(original) {} - ~StreamLocalCopy() { original_ = s; } + //! Do copy optimization. + template + class StreamLocalCopy + { + public: + StreamLocalCopy(Stream & original) : s(original), original_(original) {} + ~StreamLocalCopy() + { + original_ = s; + } - Stream s; + Stream s; -private: - StreamLocalCopy& operator=(const StreamLocalCopy&) /* = delete */; + private: + StreamLocalCopy & operator=(const StreamLocalCopy &) /* = delete */; - Stream& original_; -}; + Stream & original_; + }; -//! Keep reference. -template -class StreamLocalCopy { -public: - StreamLocalCopy(Stream& original) : s(original) {} + //! Keep reference. + template + class StreamLocalCopy + { + public: + StreamLocalCopy(Stream & original) : s(original) {} - Stream& s; + Stream & s; -private: - StreamLocalCopy& operator=(const StreamLocalCopy&) /* = delete */; -}; + private: + StreamLocalCopy & operator=(const StreamLocalCopy &) /* = delete */; + }; } // namespace internal @@ -261,185 +315,234 @@ private: \note This function has SSE2/SSE4.2 specialization. */ template -void SkipWhitespace(InputStream& is) { - internal::StreamLocalCopy copy(is); - InputStream& s(copy.s); +void SkipWhitespace(InputStream & is) +{ + internal::StreamLocalCopy copy(is); + InputStream & s(copy.s); - typename InputStream::Ch c; - while ((c = s.Peek()) == ' ' || c == '\n' || c == '\r' || c == '\t') - s.Take(); + typename InputStream::Ch c; + while((c = s.Peek()) == ' ' || c == '\n' || c == '\r' || c == '\t') + { + s.Take(); + } } -inline const char* SkipWhitespace(const char* p, const char* end) { - while (p != end && (*p == ' ' || *p == '\n' || *p == '\r' || *p == '\t')) - ++p; - return p; +inline const char* SkipWhitespace(const char* p, const char* end) +{ + while(p != end && (*p == ' ' || *p == '\n' || *p == '\r' || *p == '\t')) + { + ++p; + } + return p; } #ifdef RAPIDJSON_SSE42 //! Skip whitespace with SSE 4.2 pcmpistrm instruction, testing 16 8-byte characters at once. -inline const char *SkipWhitespace_SIMD(const char* p) { - // Fast return for single non-whitespace - if (*p == ' ' || *p == '\n' || *p == '\r' || *p == '\t') - ++p; - else - return p; +inline const char* SkipWhitespace_SIMD(const char* p) +{ + // Fast return for single non-whitespace + if(*p == ' ' || *p == '\n' || *p == '\r' || *p == '\t') + { + ++p; + } + else + { + return p; + } - // 16-byte align to the next boundary - const char* nextAligned = reinterpret_cast((reinterpret_cast(p) + 15) & static_cast(~15)); - while (p != nextAligned) - if (*p == ' ' || *p == '\n' || *p == '\r' || *p == '\t') - ++p; - else - return p; + // 16-byte align to the next boundary + const char* nextAligned = reinterpret_cast((reinterpret_cast + (p) + 15) & static_cast(~15)); + while(p != nextAligned) + if(*p == ' ' || *p == '\n' || *p == '\r' || *p == '\t') + { + ++p; + } + else + { + return p; + } - // The rest of string using SIMD - static const char whitespace[16] = " \n\r\t"; - const __m128i w = _mm_loadu_si128(reinterpret_cast(&whitespace[0])); + // The rest of string using SIMD + static const char whitespace[16] = " \n\r\t"; + const __m128i w = _mm_loadu_si128(reinterpret_cast(&whitespace[0])); - for (;; p += 16) { - const __m128i s = _mm_load_si128(reinterpret_cast(p)); - const int r = _mm_cvtsi128_si32(_mm_cmpistrm(w, s, _SIDD_UBYTE_OPS | _SIDD_CMP_EQUAL_ANY | _SIDD_BIT_MASK | _SIDD_NEGATIVE_POLARITY)); - if (r != 0) { // some of characters is non-whitespace + for(;; p += 16) + { + const __m128i s = _mm_load_si128(reinterpret_cast(p)); + const int r = _mm_cvtsi128_si32(_mm_cmpistrm(w, s, + _SIDD_UBYTE_OPS | _SIDD_CMP_EQUAL_ANY | _SIDD_BIT_MASK | _SIDD_NEGATIVE_POLARITY)); + if(r != 0) // some of characters is non-whitespace + { #ifdef _MSC_VER // Find the index of first non-whitespace - unsigned long offset; - _BitScanForward(&offset, r); - return p + offset; + unsigned long offset; + _BitScanForward(&offset, r); + return p + offset; #else - return p + __builtin_ffs(r) - 1; + return p + __builtin_ffs(r) - 1; #endif - } - } + } + } } -inline const char *SkipWhitespace_SIMD(const char* p, const char* end) { - // Fast return for single non-whitespace - if (p != end && (*p == ' ' || *p == '\n' || *p == '\r' || *p == '\t')) - ++p; - else - return p; +inline const char* SkipWhitespace_SIMD(const char* p, const char* end) +{ + // Fast return for single non-whitespace + if(p != end && (*p == ' ' || *p == '\n' || *p == '\r' || *p == '\t')) + { + ++p; + } + else + { + return p; + } - // The middle of string using SIMD - static const char whitespace[16] = " \n\r\t"; - const __m128i w = _mm_loadu_si128(reinterpret_cast(&whitespace[0])); + // The middle of string using SIMD + static const char whitespace[16] = " \n\r\t"; + const __m128i w = _mm_loadu_si128(reinterpret_cast(&whitespace[0])); - for (; p <= end - 16; p += 16) { - const __m128i s = _mm_loadu_si128(reinterpret_cast(p)); - const int r = _mm_cvtsi128_si32(_mm_cmpistrm(w, s, _SIDD_UBYTE_OPS | _SIDD_CMP_EQUAL_ANY | _SIDD_BIT_MASK | _SIDD_NEGATIVE_POLARITY)); - if (r != 0) { // some of characters is non-whitespace + for(; p <= end - 16; p += 16) + { + const __m128i s = _mm_loadu_si128(reinterpret_cast(p)); + const int r = _mm_cvtsi128_si32(_mm_cmpistrm(w, s, + _SIDD_UBYTE_OPS | _SIDD_CMP_EQUAL_ANY | _SIDD_BIT_MASK | _SIDD_NEGATIVE_POLARITY)); + if(r != 0) // some of characters is non-whitespace + { #ifdef _MSC_VER // Find the index of first non-whitespace - unsigned long offset; - _BitScanForward(&offset, r); - return p + offset; + unsigned long offset; + _BitScanForward(&offset, r); + return p + offset; #else - return p + __builtin_ffs(r) - 1; + return p + __builtin_ffs(r) - 1; #endif - } - } + } + } - return SkipWhitespace(p, end); + return SkipWhitespace(p, end); } #elif defined(RAPIDJSON_SSE2) //! Skip whitespace with SSE2 instructions, testing 16 8-byte characters at once. -inline const char *SkipWhitespace_SIMD(const char* p) { - // Fast return for single non-whitespace - if (*p == ' ' || *p == '\n' || *p == '\r' || *p == '\t') - ++p; - else - return p; +inline const char* SkipWhitespace_SIMD(const char* p) +{ + // Fast return for single non-whitespace + if(*p == ' ' || *p == '\n' || *p == '\r' || *p == '\t') + { + ++p; + } + else + { + return p; + } - // 16-byte align to the next boundary - const char* nextAligned = reinterpret_cast((reinterpret_cast(p) + 15) & static_cast(~15)); - while (p != nextAligned) - if (*p == ' ' || *p == '\n' || *p == '\r' || *p == '\t') - ++p; - else - return p; + // 16-byte align to the next boundary + const char* nextAligned = reinterpret_cast((reinterpret_cast + (p) + 15) & static_cast(~15)); + while(p != nextAligned) + if(*p == ' ' || *p == '\n' || *p == '\r' || *p == '\t') + { + ++p; + } + else + { + return p; + } - // The rest of string - #define C16(c) { c, c, c, c, c, c, c, c, c, c, c, c, c, c, c, c } - static const char whitespaces[4][16] = { C16(' '), C16('\n'), C16('\r'), C16('\t') }; - #undef C16 + // The rest of string +#define C16(c) { c, c, c, c, c, c, c, c, c, c, c, c, c, c, c, c } + static const char whitespaces[4][16] = { C16(' '), C16('\n'), C16('\r'), C16('\t') }; +#undef C16 - const __m128i w0 = _mm_loadu_si128(reinterpret_cast(&whitespaces[0][0])); - const __m128i w1 = _mm_loadu_si128(reinterpret_cast(&whitespaces[1][0])); - const __m128i w2 = _mm_loadu_si128(reinterpret_cast(&whitespaces[2][0])); - const __m128i w3 = _mm_loadu_si128(reinterpret_cast(&whitespaces[3][0])); + const __m128i w0 = _mm_loadu_si128(reinterpret_cast(&whitespaces[0][0])); + const __m128i w1 = _mm_loadu_si128(reinterpret_cast(&whitespaces[1][0])); + const __m128i w2 = _mm_loadu_si128(reinterpret_cast(&whitespaces[2][0])); + const __m128i w3 = _mm_loadu_si128(reinterpret_cast(&whitespaces[3][0])); - for (;; p += 16) { - const __m128i s = _mm_load_si128(reinterpret_cast(p)); - __m128i x = _mm_cmpeq_epi8(s, w0); - x = _mm_or_si128(x, _mm_cmpeq_epi8(s, w1)); - x = _mm_or_si128(x, _mm_cmpeq_epi8(s, w2)); - x = _mm_or_si128(x, _mm_cmpeq_epi8(s, w3)); - unsigned short r = static_cast(~_mm_movemask_epi8(x)); - if (r != 0) { // some of characters may be non-whitespace + for(;; p += 16) + { + const __m128i s = _mm_load_si128(reinterpret_cast(p)); + __m128i x = _mm_cmpeq_epi8(s, w0); + x = _mm_or_si128(x, _mm_cmpeq_epi8(s, w1)); + x = _mm_or_si128(x, _mm_cmpeq_epi8(s, w2)); + x = _mm_or_si128(x, _mm_cmpeq_epi8(s, w3)); + unsigned short r = static_cast(~_mm_movemask_epi8(x)); + if(r != 0) // some of characters may be non-whitespace + { #ifdef _MSC_VER // Find the index of first non-whitespace - unsigned long offset; - _BitScanForward(&offset, r); - return p + offset; + unsigned long offset; + _BitScanForward(&offset, r); + return p + offset; #else - return p + __builtin_ffs(r) - 1; + return p + __builtin_ffs(r) - 1; #endif - } - } + } + } } -inline const char *SkipWhitespace_SIMD(const char* p, const char* end) { - // Fast return for single non-whitespace - if (p != end && (*p == ' ' || *p == '\n' || *p == '\r' || *p == '\t')) - ++p; - else - return p; +inline const char* SkipWhitespace_SIMD(const char* p, const char* end) +{ + // Fast return for single non-whitespace + if(p != end && (*p == ' ' || *p == '\n' || *p == '\r' || *p == '\t')) + { + ++p; + } + else + { + return p; + } - // The rest of string - #define C16(c) { c, c, c, c, c, c, c, c, c, c, c, c, c, c, c, c } - static const char whitespaces[4][16] = { C16(' '), C16('\n'), C16('\r'), C16('\t') }; - #undef C16 + // The rest of string +#define C16(c) { c, c, c, c, c, c, c, c, c, c, c, c, c, c, c, c } + static const char whitespaces[4][16] = { C16(' '), C16('\n'), C16('\r'), C16('\t') }; +#undef C16 - const __m128i w0 = _mm_loadu_si128(reinterpret_cast(&whitespaces[0][0])); - const __m128i w1 = _mm_loadu_si128(reinterpret_cast(&whitespaces[1][0])); - const __m128i w2 = _mm_loadu_si128(reinterpret_cast(&whitespaces[2][0])); - const __m128i w3 = _mm_loadu_si128(reinterpret_cast(&whitespaces[3][0])); + const __m128i w0 = _mm_loadu_si128(reinterpret_cast(&whitespaces[0][0])); + const __m128i w1 = _mm_loadu_si128(reinterpret_cast(&whitespaces[1][0])); + const __m128i w2 = _mm_loadu_si128(reinterpret_cast(&whitespaces[2][0])); + const __m128i w3 = _mm_loadu_si128(reinterpret_cast(&whitespaces[3][0])); - for (; p <= end - 16; p += 16) { - const __m128i s = _mm_loadu_si128(reinterpret_cast(p)); - __m128i x = _mm_cmpeq_epi8(s, w0); - x = _mm_or_si128(x, _mm_cmpeq_epi8(s, w1)); - x = _mm_or_si128(x, _mm_cmpeq_epi8(s, w2)); - x = _mm_or_si128(x, _mm_cmpeq_epi8(s, w3)); - unsigned short r = static_cast(~_mm_movemask_epi8(x)); - if (r != 0) { // some of characters may be non-whitespace + for(; p <= end - 16; p += 16) + { + const __m128i s = _mm_loadu_si128(reinterpret_cast(p)); + __m128i x = _mm_cmpeq_epi8(s, w0); + x = _mm_or_si128(x, _mm_cmpeq_epi8(s, w1)); + x = _mm_or_si128(x, _mm_cmpeq_epi8(s, w2)); + x = _mm_or_si128(x, _mm_cmpeq_epi8(s, w3)); + unsigned short r = static_cast(~_mm_movemask_epi8(x)); + if(r != 0) // some of characters may be non-whitespace + { #ifdef _MSC_VER // Find the index of first non-whitespace - unsigned long offset; - _BitScanForward(&offset, r); - return p + offset; + unsigned long offset; + _BitScanForward(&offset, r); + return p + offset; #else - return p + __builtin_ffs(r) - 1; + return p + __builtin_ffs(r) - 1; #endif - } - } + } + } - return SkipWhitespace(p, end); + return SkipWhitespace(p, end); } #endif // RAPIDJSON_SSE2 #ifdef RAPIDJSON_SIMD //! Template function specialization for InsituStringStream -template<> inline void SkipWhitespace(InsituStringStream& is) { - is.src_ = const_cast(SkipWhitespace_SIMD(is.src_)); +template<> inline void SkipWhitespace(InsituStringStream & is) +{ + is.src_ = const_cast(SkipWhitespace_SIMD(is.src_)); } //! Template function specialization for StringStream -template<> inline void SkipWhitespace(StringStream& is) { - is.src_ = SkipWhitespace_SIMD(is.src_); +template<> inline void SkipWhitespace(StringStream & is) +{ + is.src_ = SkipWhitespace_SIMD(is.src_); } -template<> inline void SkipWhitespace(EncodedInputStream, MemoryStream>& is) { - is.is_.src_ = SkipWhitespace_SIMD(is.is_.src_, is.is_.end_); +template<> inline void SkipWhitespace(EncodedInputStream, MemoryStream> & is) +{ + is.is_.src_ = SkipWhitespace_SIMD(is.is_.src_, is.is_.end_); } #endif // RAPIDJSON_SIMD @@ -463,1403 +566,1781 @@ template<> inline void SkipWhitespace(EncodedInputStream, MemoryStream>& \tparam StackAllocator Allocator type for stack. */ template -class GenericReader { +class GenericReader +{ public: - typedef typename SourceEncoding::Ch Ch; //!< SourceEncoding character type + typedef typename SourceEncoding::Ch Ch; //!< SourceEncoding character type - //! Constructor. - /*! \param stackAllocator Optional allocator for allocating stack memory. (Only use for non-destructive parsing) - \param stackCapacity stack capacity in bytes for storing a single decoded string. (Only use for non-destructive parsing) - */ - GenericReader(StackAllocator* stackAllocator = 0, size_t stackCapacity = kDefaultStackCapacity) : stack_(stackAllocator, stackCapacity), parseResult_() {} + //! Constructor. + /*! \param stackAllocator Optional allocator for allocating stack memory. (Only use for non-destructive parsing) + \param stackCapacity stack capacity in bytes for storing a single decoded string. (Only use for non-destructive parsing) + */ + GenericReader(StackAllocator* stackAllocator = 0, + size_t stackCapacity = kDefaultStackCapacity) : stack_(stackAllocator, stackCapacity), parseResult_() {} - //! Parse JSON text. - /*! \tparam parseFlags Combination of \ref ParseFlag. - \tparam InputStream Type of input stream, implementing Stream concept. - \tparam Handler Type of handler, implementing Handler concept. - \param is Input stream to be parsed. - \param handler The handler to receive events. - \return Whether the parsing is successful. - */ - template - ParseResult Parse(InputStream& is, Handler& handler) { - if (parseFlags & kParseIterativeFlag) - return IterativeParse(is, handler); + //! Parse JSON text. + /*! \tparam parseFlags Combination of \ref ParseFlag. + \tparam InputStream Type of input stream, implementing Stream concept. + \tparam Handler Type of handler, implementing Handler concept. + \param is Input stream to be parsed. + \param handler The handler to receive events. + \return Whether the parsing is successful. + */ + template + ParseResult Parse(InputStream & is, Handler & handler) + { + if(parseFlags & kParseIterativeFlag) + { + return IterativeParse(is, handler); + } - parseResult_.Clear(); + parseResult_.Clear(); - ClearStackOnExit scope(*this); + ClearStackOnExit scope(*this); - SkipWhitespaceAndComments(is); - RAPIDJSON_PARSE_ERROR_EARLY_RETURN(parseResult_); + SkipWhitespaceAndComments(is); + RAPIDJSON_PARSE_ERROR_EARLY_RETURN(parseResult_); - if (RAPIDJSON_UNLIKELY(is.Peek() == '\0')) { - RAPIDJSON_PARSE_ERROR_NORETURN(kParseErrorDocumentEmpty, is.Tell()); - RAPIDJSON_PARSE_ERROR_EARLY_RETURN(parseResult_); - } - else { - ParseValue(is, handler); - RAPIDJSON_PARSE_ERROR_EARLY_RETURN(parseResult_); + if(RAPIDJSON_UNLIKELY(is.Peek() == '\0')) + { + RAPIDJSON_PARSE_ERROR_NORETURN(kParseErrorDocumentEmpty, is.Tell()); + RAPIDJSON_PARSE_ERROR_EARLY_RETURN(parseResult_); + } + else + { + ParseValue(is, handler); + RAPIDJSON_PARSE_ERROR_EARLY_RETURN(parseResult_); - if (!(parseFlags & kParseStopWhenDoneFlag)) { - SkipWhitespaceAndComments(is); - RAPIDJSON_PARSE_ERROR_EARLY_RETURN(parseResult_); + if(!(parseFlags & kParseStopWhenDoneFlag)) + { + SkipWhitespaceAndComments(is); + RAPIDJSON_PARSE_ERROR_EARLY_RETURN(parseResult_); - if (RAPIDJSON_UNLIKELY(is.Peek() != '\0')) { - RAPIDJSON_PARSE_ERROR_NORETURN(kParseErrorDocumentRootNotSingular, is.Tell()); - RAPIDJSON_PARSE_ERROR_EARLY_RETURN(parseResult_); - } - } - } + if(RAPIDJSON_UNLIKELY(is.Peek() != '\0')) + { + RAPIDJSON_PARSE_ERROR_NORETURN(kParseErrorDocumentRootNotSingular, is.Tell()); + RAPIDJSON_PARSE_ERROR_EARLY_RETURN(parseResult_); + } + } + } - return parseResult_; - } + return parseResult_; + } - //! Parse JSON text (with \ref kParseDefaultFlags) - /*! \tparam InputStream Type of input stream, implementing Stream concept - \tparam Handler Type of handler, implementing Handler concept. - \param is Input stream to be parsed. - \param handler The handler to receive events. - \return Whether the parsing is successful. - */ - template - ParseResult Parse(InputStream& is, Handler& handler) { - return Parse(is, handler); - } + //! Parse JSON text (with \ref kParseDefaultFlags) + /*! \tparam InputStream Type of input stream, implementing Stream concept + \tparam Handler Type of handler, implementing Handler concept. + \param is Input stream to be parsed. + \param handler The handler to receive events. + \return Whether the parsing is successful. + */ + template + ParseResult Parse(InputStream & is, Handler & handler) + { + return Parse(is, handler); + } - //! Whether a parse error has occured in the last parsing. - bool HasParseError() const { return parseResult_.IsError(); } + //! Whether a parse error has occured in the last parsing. + bool HasParseError() const + { + return parseResult_.IsError(); + } - //! Get the \ref ParseErrorCode of last parsing. - ParseErrorCode GetParseErrorCode() const { return parseResult_.Code(); } + //! Get the \ref ParseErrorCode of last parsing. + ParseErrorCode GetParseErrorCode() const + { + return parseResult_.Code(); + } - //! Get the position of last parsing error in input, 0 otherwise. - size_t GetErrorOffset() const { return parseResult_.Offset(); } + //! Get the position of last parsing error in input, 0 otherwise. + size_t GetErrorOffset() const + { + return parseResult_.Offset(); + } protected: - void SetParseError(ParseErrorCode code, size_t offset) { parseResult_.Set(code, offset); } + void SetParseError(ParseErrorCode code, size_t offset) + { + parseResult_.Set(code, offset); + } private: - // Prohibit copy constructor & assignment operator. - GenericReader(const GenericReader&); - GenericReader& operator=(const GenericReader&); + // Prohibit copy constructor & assignment operator. + GenericReader(const GenericReader &); + GenericReader & operator=(const GenericReader &); - void ClearStack() { stack_.Clear(); } + void ClearStack() + { + stack_.Clear(); + } - // clear stack on any exit from ParseStream, e.g. due to exception - struct ClearStackOnExit { - explicit ClearStackOnExit(GenericReader& r) : r_(r) {} - ~ClearStackOnExit() { r_.ClearStack(); } - private: - GenericReader& r_; - ClearStackOnExit(const ClearStackOnExit&); - ClearStackOnExit& operator=(const ClearStackOnExit&); - }; + // clear stack on any exit from ParseStream, e.g. due to exception + struct ClearStackOnExit + { + explicit ClearStackOnExit(GenericReader & r) : r_(r) {} + ~ClearStackOnExit() + { + r_.ClearStack(); + } + private: + GenericReader & r_; + ClearStackOnExit(const ClearStackOnExit &); + ClearStackOnExit & operator=(const ClearStackOnExit &); + }; - template - void SkipWhitespaceAndComments(InputStream& is) { - SkipWhitespace(is); + template + void SkipWhitespaceAndComments(InputStream & is) + { + SkipWhitespace(is); - if (parseFlags & kParseCommentsFlag) { - while (RAPIDJSON_UNLIKELY(Consume(is, '/'))) { - if (Consume(is, '*')) { - while (true) { - if (RAPIDJSON_UNLIKELY(is.Peek() == '\0')) - RAPIDJSON_PARSE_ERROR(kParseErrorUnspecificSyntaxError, is.Tell()); - else if (Consume(is, '*')) { - if (Consume(is, '/')) - break; - } - else - is.Take(); - } - } - else if (RAPIDJSON_LIKELY(Consume(is, '/'))) - while (is.Peek() != '\0' && is.Take() != '\n'); - else - RAPIDJSON_PARSE_ERROR(kParseErrorUnspecificSyntaxError, is.Tell()); + if(parseFlags & kParseCommentsFlag) + { + while(RAPIDJSON_UNLIKELY(Consume(is, '/'))) + { + if(Consume(is, '*')) + { + while(true) + { + if(RAPIDJSON_UNLIKELY(is.Peek() == '\0')) + { + RAPIDJSON_PARSE_ERROR(kParseErrorUnspecificSyntaxError, is.Tell()); + } + else if(Consume(is, '*')) + { + if(Consume(is, '/')) + { + break; + } + } + else + { + is.Take(); + } + } + } + else if(RAPIDJSON_LIKELY(Consume(is, '/'))) + while(is.Peek() != '\0' && is.Take() != '\n'); + else + { + RAPIDJSON_PARSE_ERROR(kParseErrorUnspecificSyntaxError, is.Tell()); + } - SkipWhitespace(is); - } - } - } + SkipWhitespace(is); + } + } + } - // Parse object: { string : value, ... } - template - void ParseObject(InputStream& is, Handler& handler) { - RAPIDJSON_ASSERT(is.Peek() == '{'); - is.Take(); // Skip '{' + // Parse object: { string : value, ... } + template + void ParseObject(InputStream & is, Handler & handler) + { + RAPIDJSON_ASSERT(is.Peek() == '{'); + is.Take(); // Skip '{' - if (RAPIDJSON_UNLIKELY(!handler.StartObject())) - RAPIDJSON_PARSE_ERROR(kParseErrorTermination, is.Tell()); + if(RAPIDJSON_UNLIKELY(!handler.StartObject())) + { + RAPIDJSON_PARSE_ERROR(kParseErrorTermination, is.Tell()); + } - SkipWhitespaceAndComments(is); - RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID; + SkipWhitespaceAndComments(is); + RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID; - if (Consume(is, '}')) { - if (RAPIDJSON_UNLIKELY(!handler.EndObject(0))) // empty object - RAPIDJSON_PARSE_ERROR(kParseErrorTermination, is.Tell()); - return; - } + if(Consume(is, '}')) + { + if(RAPIDJSON_UNLIKELY(!handler.EndObject(0))) // empty object + { + RAPIDJSON_PARSE_ERROR(kParseErrorTermination, is.Tell()); + } + return; + } - for (SizeType memberCount = 0;;) { - if (RAPIDJSON_UNLIKELY(is.Peek() != '"')) - RAPIDJSON_PARSE_ERROR(kParseErrorObjectMissName, is.Tell()); + for(SizeType memberCount = 0;;) + { + if(RAPIDJSON_UNLIKELY(is.Peek() != '"')) + { + RAPIDJSON_PARSE_ERROR(kParseErrorObjectMissName, is.Tell()); + } - ParseString(is, handler, true); - RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID; + ParseString(is, handler, true); + RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID; - SkipWhitespaceAndComments(is); - RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID; + SkipWhitespaceAndComments(is); + RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID; - if (RAPIDJSON_UNLIKELY(!Consume(is, ':'))) - RAPIDJSON_PARSE_ERROR(kParseErrorObjectMissColon, is.Tell()); + if(RAPIDJSON_UNLIKELY(!Consume(is, ':'))) + { + RAPIDJSON_PARSE_ERROR(kParseErrorObjectMissColon, is.Tell()); + } - SkipWhitespaceAndComments(is); - RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID; + SkipWhitespaceAndComments(is); + RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID; - ParseValue(is, handler); - RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID; + ParseValue(is, handler); + RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID; - SkipWhitespaceAndComments(is); - RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID; + SkipWhitespaceAndComments(is); + RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID; - ++memberCount; + ++memberCount; - switch (is.Peek()) { - case ',': - is.Take(); - SkipWhitespaceAndComments(is); - RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID; - break; - case '}': - is.Take(); - if (RAPIDJSON_UNLIKELY(!handler.EndObject(memberCount))) - RAPIDJSON_PARSE_ERROR(kParseErrorTermination, is.Tell()); - return; - default: - RAPIDJSON_PARSE_ERROR(kParseErrorObjectMissCommaOrCurlyBracket, is.Tell()); break; // This useless break is only for making warning and coverage happy - } + switch(is.Peek()) + { + case ',': + is.Take(); + SkipWhitespaceAndComments(is); + RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID; + break; + case '}': + is.Take(); + if(RAPIDJSON_UNLIKELY(!handler.EndObject(memberCount))) + { + RAPIDJSON_PARSE_ERROR(kParseErrorTermination, is.Tell()); + } + return; + default: + RAPIDJSON_PARSE_ERROR(kParseErrorObjectMissCommaOrCurlyBracket, is.Tell()); + break; // This useless break is only for making warning and coverage happy + } - if (parseFlags & kParseTrailingCommasFlag) { - if (is.Peek() == '}') { - if (RAPIDJSON_UNLIKELY(!handler.EndObject(memberCount))) - RAPIDJSON_PARSE_ERROR(kParseErrorTermination, is.Tell()); - is.Take(); - return; - } - } - } - } + if(parseFlags & kParseTrailingCommasFlag) + { + if(is.Peek() == '}') + { + if(RAPIDJSON_UNLIKELY(!handler.EndObject(memberCount))) + { + RAPIDJSON_PARSE_ERROR(kParseErrorTermination, is.Tell()); + } + is.Take(); + return; + } + } + } + } - // Parse array: [ value, ... ] - template - void ParseArray(InputStream& is, Handler& handler) { - RAPIDJSON_ASSERT(is.Peek() == '['); - is.Take(); // Skip '[' + // Parse array: [ value, ... ] + template + void ParseArray(InputStream & is, Handler & handler) + { + RAPIDJSON_ASSERT(is.Peek() == '['); + is.Take(); // Skip '[' - if (RAPIDJSON_UNLIKELY(!handler.StartArray())) - RAPIDJSON_PARSE_ERROR(kParseErrorTermination, is.Tell()); + if(RAPIDJSON_UNLIKELY(!handler.StartArray())) + { + RAPIDJSON_PARSE_ERROR(kParseErrorTermination, is.Tell()); + } - SkipWhitespaceAndComments(is); - RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID; + SkipWhitespaceAndComments(is); + RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID; - if (Consume(is, ']')) { - if (RAPIDJSON_UNLIKELY(!handler.EndArray(0))) // empty array - RAPIDJSON_PARSE_ERROR(kParseErrorTermination, is.Tell()); - return; - } + if(Consume(is, ']')) + { + if(RAPIDJSON_UNLIKELY(!handler.EndArray(0))) // empty array + { + RAPIDJSON_PARSE_ERROR(kParseErrorTermination, is.Tell()); + } + return; + } - for (SizeType elementCount = 0;;) { - ParseValue(is, handler); - RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID; + for(SizeType elementCount = 0;;) + { + ParseValue(is, handler); + RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID; - ++elementCount; - SkipWhitespaceAndComments(is); - RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID; + ++elementCount; + SkipWhitespaceAndComments(is); + RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID; - if (Consume(is, ',')) { - SkipWhitespaceAndComments(is); - RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID; - } - else if (Consume(is, ']')) { - if (RAPIDJSON_UNLIKELY(!handler.EndArray(elementCount))) - RAPIDJSON_PARSE_ERROR(kParseErrorTermination, is.Tell()); - return; - } - else - RAPIDJSON_PARSE_ERROR(kParseErrorArrayMissCommaOrSquareBracket, is.Tell()); + if(Consume(is, ',')) + { + SkipWhitespaceAndComments(is); + RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID; + } + else if(Consume(is, ']')) + { + if(RAPIDJSON_UNLIKELY(!handler.EndArray(elementCount))) + { + RAPIDJSON_PARSE_ERROR(kParseErrorTermination, is.Tell()); + } + return; + } + else + { + RAPIDJSON_PARSE_ERROR(kParseErrorArrayMissCommaOrSquareBracket, is.Tell()); + } - if (parseFlags & kParseTrailingCommasFlag) { - if (is.Peek() == ']') { - if (RAPIDJSON_UNLIKELY(!handler.EndArray(elementCount))) - RAPIDJSON_PARSE_ERROR(kParseErrorTermination, is.Tell()); - is.Take(); - return; - } - } - } - } + if(parseFlags & kParseTrailingCommasFlag) + { + if(is.Peek() == ']') + { + if(RAPIDJSON_UNLIKELY(!handler.EndArray(elementCount))) + { + RAPIDJSON_PARSE_ERROR(kParseErrorTermination, is.Tell()); + } + is.Take(); + return; + } + } + } + } - template - void ParseNull(InputStream& is, Handler& handler) { - RAPIDJSON_ASSERT(is.Peek() == 'n'); - is.Take(); + template + void ParseNull(InputStream & is, Handler & handler) + { + RAPIDJSON_ASSERT(is.Peek() == 'n'); + is.Take(); - if (RAPIDJSON_LIKELY(Consume(is, 'u') && Consume(is, 'l') && Consume(is, 'l'))) { - if (RAPIDJSON_UNLIKELY(!handler.Null())) - RAPIDJSON_PARSE_ERROR(kParseErrorTermination, is.Tell()); - } - else - RAPIDJSON_PARSE_ERROR(kParseErrorValueInvalid, is.Tell()); - } + if(RAPIDJSON_LIKELY(Consume(is, 'u') && Consume(is, 'l') && Consume(is, 'l'))) + { + if(RAPIDJSON_UNLIKELY(!handler.Null())) + { + RAPIDJSON_PARSE_ERROR(kParseErrorTermination, is.Tell()); + } + } + else + { + RAPIDJSON_PARSE_ERROR(kParseErrorValueInvalid, is.Tell()); + } + } - template - void ParseTrue(InputStream& is, Handler& handler) { - RAPIDJSON_ASSERT(is.Peek() == 't'); - is.Take(); + template + void ParseTrue(InputStream & is, Handler & handler) + { + RAPIDJSON_ASSERT(is.Peek() == 't'); + is.Take(); - if (RAPIDJSON_LIKELY(Consume(is, 'r') && Consume(is, 'u') && Consume(is, 'e'))) { - if (RAPIDJSON_UNLIKELY(!handler.Bool(true))) - RAPIDJSON_PARSE_ERROR(kParseErrorTermination, is.Tell()); - } - else - RAPIDJSON_PARSE_ERROR(kParseErrorValueInvalid, is.Tell()); - } + if(RAPIDJSON_LIKELY(Consume(is, 'r') && Consume(is, 'u') && Consume(is, 'e'))) + { + if(RAPIDJSON_UNLIKELY(!handler.Bool(true))) + { + RAPIDJSON_PARSE_ERROR(kParseErrorTermination, is.Tell()); + } + } + else + { + RAPIDJSON_PARSE_ERROR(kParseErrorValueInvalid, is.Tell()); + } + } - template - void ParseFalse(InputStream& is, Handler& handler) { - RAPIDJSON_ASSERT(is.Peek() == 'f'); - is.Take(); + template + void ParseFalse(InputStream & is, Handler & handler) + { + RAPIDJSON_ASSERT(is.Peek() == 'f'); + is.Take(); - if (RAPIDJSON_LIKELY(Consume(is, 'a') && Consume(is, 'l') && Consume(is, 's') && Consume(is, 'e'))) { - if (RAPIDJSON_UNLIKELY(!handler.Bool(false))) - RAPIDJSON_PARSE_ERROR(kParseErrorTermination, is.Tell()); - } - else - RAPIDJSON_PARSE_ERROR(kParseErrorValueInvalid, is.Tell()); - } + if(RAPIDJSON_LIKELY(Consume(is, 'a') && Consume(is, 'l') && Consume(is, 's') && Consume(is, 'e'))) + { + if(RAPIDJSON_UNLIKELY(!handler.Bool(false))) + { + RAPIDJSON_PARSE_ERROR(kParseErrorTermination, is.Tell()); + } + } + else + { + RAPIDJSON_PARSE_ERROR(kParseErrorValueInvalid, is.Tell()); + } + } - template - RAPIDJSON_FORCEINLINE static bool Consume(InputStream& is, typename InputStream::Ch expect) { - if (RAPIDJSON_LIKELY(is.Peek() == expect)) { - is.Take(); - return true; - } - else - return false; - } + template + RAPIDJSON_FORCEINLINE static bool Consume(InputStream & is, typename InputStream::Ch expect) + { + if(RAPIDJSON_LIKELY(is.Peek() == expect)) + { + is.Take(); + return true; + } + else + { + return false; + } + } - // Helper function to parse four hexidecimal digits in \uXXXX in ParseString(). - template - unsigned ParseHex4(InputStream& is, size_t escapeOffset) { - unsigned codepoint = 0; - for (int i = 0; i < 4; i++) { - Ch c = is.Peek(); - codepoint <<= 4; - codepoint += static_cast(c); - if (c >= '0' && c <= '9') - codepoint -= '0'; - else if (c >= 'A' && c <= 'F') - codepoint -= 'A' - 10; - else if (c >= 'a' && c <= 'f') - codepoint -= 'a' - 10; - else { - RAPIDJSON_PARSE_ERROR_NORETURN(kParseErrorStringUnicodeEscapeInvalidHex, escapeOffset); - RAPIDJSON_PARSE_ERROR_EARLY_RETURN(0); - } - is.Take(); - } - return codepoint; - } + // Helper function to parse four hexidecimal digits in \uXXXX in ParseString(). + template + unsigned ParseHex4(InputStream & is, size_t escapeOffset) + { + unsigned codepoint = 0; + for(int i = 0; i < 4; i++) + { + Ch c = is.Peek(); + codepoint <<= 4; + codepoint += static_cast(c); + if(c >= '0' && c <= '9') + { + codepoint -= '0'; + } + else if(c >= 'A' && c <= 'F') + { + codepoint -= 'A' - 10; + } + else if(c >= 'a' && c <= 'f') + { + codepoint -= 'a' - 10; + } + else + { + RAPIDJSON_PARSE_ERROR_NORETURN(kParseErrorStringUnicodeEscapeInvalidHex, escapeOffset); + RAPIDJSON_PARSE_ERROR_EARLY_RETURN(0); + } + is.Take(); + } + return codepoint; + } - template - class StackStream { - public: - typedef CharType Ch; + template + class StackStream + { + public: + typedef CharType Ch; - StackStream(internal::Stack& stack) : stack_(stack), length_(0) {} - RAPIDJSON_FORCEINLINE void Put(Ch c) { - *stack_.template Push() = c; - ++length_; - } + StackStream(internal::Stack & stack) : stack_(stack), length_(0) {} + RAPIDJSON_FORCEINLINE void Put(Ch c) + { + *stack_.template Push() = c; + ++length_; + } - RAPIDJSON_FORCEINLINE void* Push(SizeType count) { - length_ += count; - return stack_.template Push(count); - } + RAPIDJSON_FORCEINLINE void* Push(SizeType count) + { + length_ += count; + return stack_.template Push(count); + } - size_t Length() const { return length_; } + size_t Length() const + { + return length_; + } - Ch* Pop() { - return stack_.template Pop(length_); - } + Ch* Pop() + { + return stack_.template Pop(length_); + } - private: - StackStream(const StackStream&); - StackStream& operator=(const StackStream&); + private: + StackStream(const StackStream &); + StackStream & operator=(const StackStream &); - internal::Stack& stack_; - SizeType length_; - }; + internal::Stack & stack_; + SizeType length_; + }; - // Parse string and generate String event. Different code paths for kParseInsituFlag. - template - void ParseString(InputStream& is, Handler& handler, bool isKey = false) { - internal::StreamLocalCopy copy(is); - InputStream& s(copy.s); + // Parse string and generate String event. Different code paths for kParseInsituFlag. + template + void ParseString(InputStream & is, Handler & handler, bool isKey = false) + { + internal::StreamLocalCopy copy(is); + InputStream & s(copy.s); - RAPIDJSON_ASSERT(s.Peek() == '\"'); - s.Take(); // Skip '\"' + RAPIDJSON_ASSERT(s.Peek() == '\"'); + s.Take(); // Skip '\"' - bool success = false; - if (parseFlags & kParseInsituFlag) { - typename InputStream::Ch *head = s.PutBegin(); - ParseStringToStream(s, s); - RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID; - size_t length = s.PutEnd(head) - 1; - RAPIDJSON_ASSERT(length <= 0xFFFFFFFF); - const typename TargetEncoding::Ch* const str = reinterpret_cast(head); - success = (isKey ? handler.Key(str, SizeType(length), false) : handler.String(str, SizeType(length), false)); - } - else { - StackStream stackStream(stack_); - ParseStringToStream(s, stackStream); - RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID; - SizeType length = static_cast(stackStream.Length()) - 1; - const typename TargetEncoding::Ch* const str = stackStream.Pop(); - success = (isKey ? handler.Key(str, length, true) : handler.String(str, length, true)); - } - if (RAPIDJSON_UNLIKELY(!success)) - RAPIDJSON_PARSE_ERROR(kParseErrorTermination, s.Tell()); - } + bool success = false; + if(parseFlags & kParseInsituFlag) + { + typename InputStream::Ch* head = s.PutBegin(); + ParseStringToStream(s, s); + RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID; + size_t length = s.PutEnd(head) - 1; + RAPIDJSON_ASSERT(length <= 0xFFFFFFFF); + const typename TargetEncoding::Ch* const str = reinterpret_cast(head); + success = (isKey ? handler.Key(str, SizeType(length), false) : handler.String(str, SizeType(length), false)); + } + else + { + StackStream stackStream(stack_); + ParseStringToStream(s, stackStream); + RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID; + SizeType length = static_cast(stackStream.Length()) - 1; + const typename TargetEncoding::Ch* const str = stackStream.Pop(); + success = (isKey ? handler.Key(str, length, true) : handler.String(str, length, true)); + } + if(RAPIDJSON_UNLIKELY(!success)) + { + RAPIDJSON_PARSE_ERROR(kParseErrorTermination, s.Tell()); + } + } - // Parse string to an output is - // This function handles the prefix/suffix double quotes, escaping, and optional encoding validation. - template - RAPIDJSON_FORCEINLINE void ParseStringToStream(InputStream& is, OutputStream& os) { -//!@cond RAPIDJSON_HIDDEN_FROM_DOXYGEN + // Parse string to an output is + // This function handles the prefix/suffix double quotes, escaping, and optional encoding validation. + template + RAPIDJSON_FORCEINLINE void ParseStringToStream(InputStream & is, OutputStream & os) + { + //!@cond RAPIDJSON_HIDDEN_FROM_DOXYGEN #define Z16 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 - static const char escape[256] = { - Z16, Z16, 0, 0,'\"', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,'/', - Z16, Z16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,'\\', 0, 0, 0, - 0, 0,'\b', 0, 0, 0,'\f', 0, 0, 0, 0, 0, 0, 0,'\n', 0, - 0, 0,'\r', 0,'\t', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - Z16, Z16, Z16, Z16, Z16, Z16, Z16, Z16 - }; + static const char escape[256] = + { + Z16, Z16, 0, 0, '\"', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, '/', + Z16, Z16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, '\\', 0, 0, 0, + 0, 0, '\b', 0, 0, 0, '\f', 0, 0, 0, 0, 0, 0, 0, '\n', 0, + 0, 0, '\r', 0, '\t', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + Z16, Z16, Z16, Z16, Z16, Z16, Z16, Z16 + }; #undef Z16 -//!@endcond + //!@endcond - for (;;) { - // Scan and copy string before "\\\"" or < 0x20. This is an optional optimzation. - if (!(parseFlags & kParseValidateEncodingFlag)) - ScanCopyUnescapedString(is, os); + for(;;) + { + // Scan and copy string before "\\\"" or < 0x20. This is an optional optimzation. + if(!(parseFlags & kParseValidateEncodingFlag)) + { + ScanCopyUnescapedString(is, os); + } - Ch c = is.Peek(); - if (RAPIDJSON_UNLIKELY(c == '\\')) { // Escape - size_t escapeOffset = is.Tell(); // For invalid escaping, report the inital '\\' as error offset - is.Take(); - Ch e = is.Peek(); - if ((sizeof(Ch) == 1 || unsigned(e) < 256) && RAPIDJSON_LIKELY(escape[static_cast(e)])) { - is.Take(); - os.Put(static_cast(escape[static_cast(e)])); - } - else if (RAPIDJSON_LIKELY(e == 'u')) { // Unicode - is.Take(); - unsigned codepoint = ParseHex4(is, escapeOffset); - RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID; - if (RAPIDJSON_UNLIKELY(codepoint >= 0xD800 && codepoint <= 0xDBFF)) { - // Handle UTF-16 surrogate pair - if (RAPIDJSON_UNLIKELY(!Consume(is, '\\') || !Consume(is, 'u'))) - RAPIDJSON_PARSE_ERROR(kParseErrorStringUnicodeSurrogateInvalid, escapeOffset); - unsigned codepoint2 = ParseHex4(is, escapeOffset); - RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID; - if (RAPIDJSON_UNLIKELY(codepoint2 < 0xDC00 || codepoint2 > 0xDFFF)) - RAPIDJSON_PARSE_ERROR(kParseErrorStringUnicodeSurrogateInvalid, escapeOffset); - codepoint = (((codepoint - 0xD800) << 10) | (codepoint2 - 0xDC00)) + 0x10000; - } - TEncoding::Encode(os, codepoint); - } - else - RAPIDJSON_PARSE_ERROR(kParseErrorStringEscapeInvalid, escapeOffset); - } - else if (RAPIDJSON_UNLIKELY(c == '"')) { // Closing double quote - is.Take(); - os.Put('\0'); // null-terminate the string - return; - } - else if (RAPIDJSON_UNLIKELY(static_cast(c) < 0x20)) { // RFC 4627: unescaped = %x20-21 / %x23-5B / %x5D-10FFFF - if (c == '\0') - RAPIDJSON_PARSE_ERROR(kParseErrorStringMissQuotationMark, is.Tell()); - else - RAPIDJSON_PARSE_ERROR(kParseErrorStringEscapeInvalid, is.Tell()); - } - else { - size_t offset = is.Tell(); - if (RAPIDJSON_UNLIKELY((parseFlags & kParseValidateEncodingFlag ? - !Transcoder::Validate(is, os) : - !Transcoder::Transcode(is, os)))) - RAPIDJSON_PARSE_ERROR(kParseErrorStringInvalidEncoding, offset); - } - } - } + Ch c = is.Peek(); + if(RAPIDJSON_UNLIKELY(c == '\\')) // Escape + { + size_t escapeOffset = is.Tell(); // For invalid escaping, report the inital '\\' as error offset + is.Take(); + Ch e = is.Peek(); + if((sizeof(Ch) == 1 || unsigned(e) < 256) && RAPIDJSON_LIKELY(escape[static_cast(e)])) + { + is.Take(); + os.Put(static_cast(escape[static_cast(e)])); + } + else if(RAPIDJSON_LIKELY(e == 'u')) // Unicode + { + is.Take(); + unsigned codepoint = ParseHex4(is, escapeOffset); + RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID; + if(RAPIDJSON_UNLIKELY(codepoint >= 0xD800 && codepoint <= 0xDBFF)) + { + // Handle UTF-16 surrogate pair + if(RAPIDJSON_UNLIKELY(!Consume(is, '\\') || !Consume(is, 'u'))) + { + RAPIDJSON_PARSE_ERROR(kParseErrorStringUnicodeSurrogateInvalid, escapeOffset); + } + unsigned codepoint2 = ParseHex4(is, escapeOffset); + RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID; + if(RAPIDJSON_UNLIKELY(codepoint2 < 0xDC00 || codepoint2 > 0xDFFF)) + { + RAPIDJSON_PARSE_ERROR(kParseErrorStringUnicodeSurrogateInvalid, escapeOffset); + } + codepoint = (((codepoint - 0xD800) << 10) | (codepoint2 - 0xDC00)) + 0x10000; + } + TEncoding::Encode(os, codepoint); + } + else + { + RAPIDJSON_PARSE_ERROR(kParseErrorStringEscapeInvalid, escapeOffset); + } + } + else if(RAPIDJSON_UNLIKELY(c == '"')) // Closing double quote + { + is.Take(); + os.Put('\0'); // null-terminate the string + return; + } + else if(RAPIDJSON_UNLIKELY(static_cast(c) < + 0x20)) // RFC 4627: unescaped = %x20-21 / %x23-5B / %x5D-10FFFF + { + if(c == '\0') + { + RAPIDJSON_PARSE_ERROR(kParseErrorStringMissQuotationMark, is.Tell()); + } + else + { + RAPIDJSON_PARSE_ERROR(kParseErrorStringEscapeInvalid, is.Tell()); + } + } + else + { + size_t offset = is.Tell(); + if(RAPIDJSON_UNLIKELY((parseFlags & kParseValidateEncodingFlag ? + !Transcoder::Validate(is, os) : + !Transcoder::Transcode(is, os)))) + { + RAPIDJSON_PARSE_ERROR(kParseErrorStringInvalidEncoding, offset); + } + } + } + } - template - static RAPIDJSON_FORCEINLINE void ScanCopyUnescapedString(InputStream&, OutputStream&) { - // Do nothing for generic version - } + template + static RAPIDJSON_FORCEINLINE void ScanCopyUnescapedString(InputStream &, OutputStream &) + { + // Do nothing for generic version + } #if defined(RAPIDJSON_SSE2) || defined(RAPIDJSON_SSE42) - // StringStream -> StackStream - static RAPIDJSON_FORCEINLINE void ScanCopyUnescapedString(StringStream& is, StackStream& os) { - const char* p = is.src_; + // StringStream -> StackStream + static RAPIDJSON_FORCEINLINE void ScanCopyUnescapedString(StringStream & is, StackStream & os) + { + const char* p = is.src_; - // Scan one by one until alignment (unaligned load may cross page boundary and cause crash) - const char* nextAligned = reinterpret_cast((reinterpret_cast(p) + 15) & static_cast(~15)); - while (p != nextAligned) - if (RAPIDJSON_UNLIKELY(*p == '\"') || RAPIDJSON_UNLIKELY(*p == '\\') || RAPIDJSON_UNLIKELY(static_cast(*p) < 0x20)) { - is.src_ = p; - return; - } - else - os.Put(*p++); + // Scan one by one until alignment (unaligned load may cross page boundary and cause crash) + const char* nextAligned = reinterpret_cast((reinterpret_cast + (p) + 15) & static_cast(~15)); + while(p != nextAligned) + if(RAPIDJSON_UNLIKELY(*p == '\"') || RAPIDJSON_UNLIKELY(*p == '\\') || + RAPIDJSON_UNLIKELY(static_cast(*p) < 0x20)) + { + is.src_ = p; + return; + } + else + { + os.Put(*p++); + } - // The rest of string using SIMD - static const char dquote[16] = { '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"' }; - static const char bslash[16] = { '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\' }; - static const char space[16] = { 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19 }; - const __m128i dq = _mm_loadu_si128(reinterpret_cast(&dquote[0])); - const __m128i bs = _mm_loadu_si128(reinterpret_cast(&bslash[0])); - const __m128i sp = _mm_loadu_si128(reinterpret_cast(&space[0])); + // The rest of string using SIMD + static const char dquote[16] = { '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"' }; + static const char bslash[16] = { '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\' }; + static const char space[16] = { 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19 }; + const __m128i dq = _mm_loadu_si128(reinterpret_cast(&dquote[0])); + const __m128i bs = _mm_loadu_si128(reinterpret_cast(&bslash[0])); + const __m128i sp = _mm_loadu_si128(reinterpret_cast(&space[0])); - for (;; p += 16) { - const __m128i s = _mm_load_si128(reinterpret_cast(p)); - const __m128i t1 = _mm_cmpeq_epi8(s, dq); - const __m128i t2 = _mm_cmpeq_epi8(s, bs); - const __m128i t3 = _mm_cmpeq_epi8(_mm_max_epu8(s, sp), sp); // s < 0x20 <=> max(s, 0x19) == 0x19 - const __m128i x = _mm_or_si128(_mm_or_si128(t1, t2), t3); - unsigned short r = static_cast(_mm_movemask_epi8(x)); - if (RAPIDJSON_UNLIKELY(r != 0)) { // some of characters is escaped - SizeType length; - #ifdef _MSC_VER // Find the index of first escaped - unsigned long offset; - _BitScanForward(&offset, r); - length = offset; - #else - length = static_cast(__builtin_ffs(r) - 1); - #endif - char* q = reinterpret_cast(os.Push(length)); - for (size_t i = 0; i < length; i++) - q[i] = p[i]; - - p += length; - break; - } - _mm_storeu_si128(reinterpret_cast<__m128i *>(os.Push(16)), s); - } - - is.src_ = p; - } - - // InsituStringStream -> InsituStringStream - static RAPIDJSON_FORCEINLINE void ScanCopyUnescapedString(InsituStringStream& is, InsituStringStream& os) { - RAPIDJSON_ASSERT(&is == &os); - (void)os; - - if (is.src_ == is.dst_) { - SkipUnescapedString(is); - return; - } - - char* p = is.src_; - char *q = is.dst_; - - // Scan one by one until alignment (unaligned load may cross page boundary and cause crash) - const char* nextAligned = reinterpret_cast((reinterpret_cast(p) + 15) & static_cast(~15)); - while (p != nextAligned) - if (RAPIDJSON_UNLIKELY(*p == '\"') || RAPIDJSON_UNLIKELY(*p == '\\') || RAPIDJSON_UNLIKELY(static_cast(*p) < 0x20)) { - is.src_ = p; - is.dst_ = q; - return; - } - else - *q++ = *p++; - - // The rest of string using SIMD - static const char dquote[16] = { '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"' }; - static const char bslash[16] = { '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\' }; - static const char space[16] = { 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19 }; - const __m128i dq = _mm_loadu_si128(reinterpret_cast(&dquote[0])); - const __m128i bs = _mm_loadu_si128(reinterpret_cast(&bslash[0])); - const __m128i sp = _mm_loadu_si128(reinterpret_cast(&space[0])); - - for (;; p += 16, q += 16) { - const __m128i s = _mm_load_si128(reinterpret_cast(p)); - const __m128i t1 = _mm_cmpeq_epi8(s, dq); - const __m128i t2 = _mm_cmpeq_epi8(s, bs); - const __m128i t3 = _mm_cmpeq_epi8(_mm_max_epu8(s, sp), sp); // s < 0x20 <=> max(s, 0x19) == 0x19 - const __m128i x = _mm_or_si128(_mm_or_si128(t1, t2), t3); - unsigned short r = static_cast(_mm_movemask_epi8(x)); - if (RAPIDJSON_UNLIKELY(r != 0)) { // some of characters is escaped - size_t length; + for(;; p += 16) + { + const __m128i s = _mm_load_si128(reinterpret_cast(p)); + const __m128i t1 = _mm_cmpeq_epi8(s, dq); + const __m128i t2 = _mm_cmpeq_epi8(s, bs); + const __m128i t3 = _mm_cmpeq_epi8(_mm_max_epu8(s, sp), sp); // s < 0x20 <=> max(s, 0x19) == 0x19 + const __m128i x = _mm_or_si128(_mm_or_si128(t1, t2), t3); + unsigned short r = static_cast(_mm_movemask_epi8(x)); + if(RAPIDJSON_UNLIKELY(r != 0)) // some of characters is escaped + { + SizeType length; #ifdef _MSC_VER // Find the index of first escaped - unsigned long offset; - _BitScanForward(&offset, r); - length = offset; + unsigned long offset; + _BitScanForward(&offset, r); + length = offset; #else - length = static_cast(__builtin_ffs(r) - 1); + length = static_cast(__builtin_ffs(r) - 1); #endif - for (const char* pend = p + length; p != pend; ) - *q++ = *p++; - break; - } - _mm_storeu_si128(reinterpret_cast<__m128i *>(q), s); - } + char* q = reinterpret_cast(os.Push(length)); + for(size_t i = 0; i < length; i++) + { + q[i] = p[i]; + } - is.src_ = p; - is.dst_ = q; - } + p += length; + break; + } + _mm_storeu_si128(reinterpret_cast<__m128i*>(os.Push(16)), s); + } - // When read/write pointers are the same for insitu stream, just skip unescaped characters - static RAPIDJSON_FORCEINLINE void SkipUnescapedString(InsituStringStream& is) { - RAPIDJSON_ASSERT(is.src_ == is.dst_); - char* p = is.src_; + is.src_ = p; + } - // Scan one by one until alignment (unaligned load may cross page boundary and cause crash) - const char* nextAligned = reinterpret_cast((reinterpret_cast(p) + 15) & static_cast(~15)); - for (; p != nextAligned; p++) - if (RAPIDJSON_UNLIKELY(*p == '\"') || RAPIDJSON_UNLIKELY(*p == '\\') || RAPIDJSON_UNLIKELY(static_cast(*p) < 0x20)) { - is.src_ = is.dst_ = p; - return; - } + // InsituStringStream -> InsituStringStream + static RAPIDJSON_FORCEINLINE void ScanCopyUnescapedString(InsituStringStream & is, InsituStringStream & os) + { + RAPIDJSON_ASSERT(&is == &os); + (void)os; - // The rest of string using SIMD - static const char dquote[16] = { '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"' }; - static const char bslash[16] = { '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\' }; - static const char space[16] = { 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19 }; - const __m128i dq = _mm_loadu_si128(reinterpret_cast(&dquote[0])); - const __m128i bs = _mm_loadu_si128(reinterpret_cast(&bslash[0])); - const __m128i sp = _mm_loadu_si128(reinterpret_cast(&space[0])); + if(is.src_ == is.dst_) + { + SkipUnescapedString(is); + return; + } - for (;; p += 16) { - const __m128i s = _mm_load_si128(reinterpret_cast(p)); - const __m128i t1 = _mm_cmpeq_epi8(s, dq); - const __m128i t2 = _mm_cmpeq_epi8(s, bs); - const __m128i t3 = _mm_cmpeq_epi8(_mm_max_epu8(s, sp), sp); // s < 0x20 <=> max(s, 0x19) == 0x19 - const __m128i x = _mm_or_si128(_mm_or_si128(t1, t2), t3); - unsigned short r = static_cast(_mm_movemask_epi8(x)); - if (RAPIDJSON_UNLIKELY(r != 0)) { // some of characters is escaped - size_t length; + char* p = is.src_; + char* q = is.dst_; + + // Scan one by one until alignment (unaligned load may cross page boundary and cause crash) + const char* nextAligned = reinterpret_cast((reinterpret_cast + (p) + 15) & static_cast(~15)); + while(p != nextAligned) + if(RAPIDJSON_UNLIKELY(*p == '\"') || RAPIDJSON_UNLIKELY(*p == '\\') || + RAPIDJSON_UNLIKELY(static_cast(*p) < 0x20)) + { + is.src_ = p; + is.dst_ = q; + return; + } + else + { + *q++ = *p++; + } + + // The rest of string using SIMD + static const char dquote[16] = { '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"' }; + static const char bslash[16] = { '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\' }; + static const char space[16] = { 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19 }; + const __m128i dq = _mm_loadu_si128(reinterpret_cast(&dquote[0])); + const __m128i bs = _mm_loadu_si128(reinterpret_cast(&bslash[0])); + const __m128i sp = _mm_loadu_si128(reinterpret_cast(&space[0])); + + for(;; p += 16, q += 16) + { + const __m128i s = _mm_load_si128(reinterpret_cast(p)); + const __m128i t1 = _mm_cmpeq_epi8(s, dq); + const __m128i t2 = _mm_cmpeq_epi8(s, bs); + const __m128i t3 = _mm_cmpeq_epi8(_mm_max_epu8(s, sp), sp); // s < 0x20 <=> max(s, 0x19) == 0x19 + const __m128i x = _mm_or_si128(_mm_or_si128(t1, t2), t3); + unsigned short r = static_cast(_mm_movemask_epi8(x)); + if(RAPIDJSON_UNLIKELY(r != 0)) // some of characters is escaped + { + size_t length; #ifdef _MSC_VER // Find the index of first escaped - unsigned long offset; - _BitScanForward(&offset, r); - length = offset; + unsigned long offset; + _BitScanForward(&offset, r); + length = offset; #else - length = static_cast(__builtin_ffs(r) - 1); + length = static_cast(__builtin_ffs(r) - 1); #endif - p += length; - break; - } - } + for(const char* pend = p + length; p != pend;) + { + *q++ = *p++; + } + break; + } + _mm_storeu_si128(reinterpret_cast<__m128i*>(q), s); + } - is.src_ = is.dst_ = p; - } + is.src_ = p; + is.dst_ = q; + } + + // When read/write pointers are the same for insitu stream, just skip unescaped characters + static RAPIDJSON_FORCEINLINE void SkipUnescapedString(InsituStringStream & is) + { + RAPIDJSON_ASSERT(is.src_ == is.dst_); + char* p = is.src_; + + // Scan one by one until alignment (unaligned load may cross page boundary and cause crash) + const char* nextAligned = reinterpret_cast((reinterpret_cast + (p) + 15) & static_cast(~15)); + for(; p != nextAligned; p++) + if(RAPIDJSON_UNLIKELY(*p == '\"') || RAPIDJSON_UNLIKELY(*p == '\\') || + RAPIDJSON_UNLIKELY(static_cast(*p) < 0x20)) + { + is.src_ = is.dst_ = p; + return; + } + + // The rest of string using SIMD + static const char dquote[16] = { '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"' }; + static const char bslash[16] = { '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\' }; + static const char space[16] = { 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19 }; + const __m128i dq = _mm_loadu_si128(reinterpret_cast(&dquote[0])); + const __m128i bs = _mm_loadu_si128(reinterpret_cast(&bslash[0])); + const __m128i sp = _mm_loadu_si128(reinterpret_cast(&space[0])); + + for(;; p += 16) + { + const __m128i s = _mm_load_si128(reinterpret_cast(p)); + const __m128i t1 = _mm_cmpeq_epi8(s, dq); + const __m128i t2 = _mm_cmpeq_epi8(s, bs); + const __m128i t3 = _mm_cmpeq_epi8(_mm_max_epu8(s, sp), sp); // s < 0x20 <=> max(s, 0x19) == 0x19 + const __m128i x = _mm_or_si128(_mm_or_si128(t1, t2), t3); + unsigned short r = static_cast(_mm_movemask_epi8(x)); + if(RAPIDJSON_UNLIKELY(r != 0)) // some of characters is escaped + { + size_t length; +#ifdef _MSC_VER // Find the index of first escaped + unsigned long offset; + _BitScanForward(&offset, r); + length = offset; +#else + length = static_cast(__builtin_ffs(r) - 1); +#endif + p += length; + break; + } + } + + is.src_ = is.dst_ = p; + } #endif - template - class NumberStream; + template + class NumberStream; - template - class NumberStream { - public: - typedef typename InputStream::Ch Ch; + template + class NumberStream + { + public: + typedef typename InputStream::Ch Ch; - NumberStream(GenericReader& reader, InputStream& s) : is(s) { (void)reader; } - ~NumberStream() {} + NumberStream(GenericReader & reader, InputStream & s) : is(s) + { + (void)reader; + } + ~NumberStream() {} - RAPIDJSON_FORCEINLINE Ch Peek() const { return is.Peek(); } - RAPIDJSON_FORCEINLINE Ch TakePush() { return is.Take(); } - RAPIDJSON_FORCEINLINE Ch Take() { return is.Take(); } - RAPIDJSON_FORCEINLINE void Push(char) {} + RAPIDJSON_FORCEINLINE Ch Peek() const + { + return is.Peek(); + } + RAPIDJSON_FORCEINLINE Ch TakePush() + { + return is.Take(); + } + RAPIDJSON_FORCEINLINE Ch Take() + { + return is.Take(); + } + RAPIDJSON_FORCEINLINE void Push(char) {} - size_t Tell() { return is.Tell(); } - size_t Length() { return 0; } - const char* Pop() { return 0; } + size_t Tell() + { + return is.Tell(); + } + size_t Length() + { + return 0; + } + const char* Pop() + { + return 0; + } - protected: - NumberStream& operator=(const NumberStream&); + protected: + NumberStream & operator=(const NumberStream &); - InputStream& is; - }; + InputStream & is; + }; - template - class NumberStream : public NumberStream { - typedef NumberStream Base; - public: - NumberStream(GenericReader& reader, InputStream& is) : Base(reader, is), stackStream(reader.stack_) {} - ~NumberStream() {} + template + class NumberStream : public NumberStream + { + typedef NumberStream Base; + public: + NumberStream(GenericReader & reader, InputStream & is) : Base(reader, is), stackStream(reader.stack_) {} + ~NumberStream() {} - RAPIDJSON_FORCEINLINE Ch TakePush() { - stackStream.Put(static_cast(Base::is.Peek())); - return Base::is.Take(); - } + RAPIDJSON_FORCEINLINE Ch TakePush() + { + stackStream.Put(static_cast(Base::is.Peek())); + return Base::is.Take(); + } - RAPIDJSON_FORCEINLINE void Push(char c) { - stackStream.Put(c); - } + RAPIDJSON_FORCEINLINE void Push(char c) + { + stackStream.Put(c); + } - size_t Length() { return stackStream.Length(); } + size_t Length() + { + return stackStream.Length(); + } - const char* Pop() { - stackStream.Put('\0'); - return stackStream.Pop(); - } + const char* Pop() + { + stackStream.Put('\0'); + return stackStream.Pop(); + } - private: - StackStream stackStream; - }; + private: + StackStream stackStream; + }; - template - class NumberStream : public NumberStream { - typedef NumberStream Base; - public: - NumberStream(GenericReader& reader, InputStream& is) : Base(reader, is) {} - ~NumberStream() {} + template + class NumberStream : public NumberStream + { + typedef NumberStream Base; + public: + NumberStream(GenericReader & reader, InputStream & is) : Base(reader, is) {} + ~NumberStream() {} - RAPIDJSON_FORCEINLINE Ch Take() { return Base::TakePush(); } - }; + RAPIDJSON_FORCEINLINE Ch Take() + { + return Base::TakePush(); + } + }; - template - void ParseNumber(InputStream& is, Handler& handler) { - internal::StreamLocalCopy copy(is); - NumberStream s(*this, copy.s); + template + void ParseNumber(InputStream & is, Handler & handler) + { + internal::StreamLocalCopy copy(is); + NumberStream < InputStream, + ((parseFlags & kParseNumbersAsStringsFlag) != 0) ? + ((parseFlags & kParseInsituFlag) == 0) : + ((parseFlags & kParseFullPrecisionFlag) != 0), + (parseFlags & kParseNumbersAsStringsFlag) != 0 && + (parseFlags & kParseInsituFlag) == 0 > s(*this, copy.s); - size_t startOffset = s.Tell(); - double d = 0.0; - bool useNanOrInf = false; + size_t startOffset = s.Tell(); + double d = 0.0; + bool useNanOrInf = false; - // Parse minus - bool minus = Consume(s, '-'); + // Parse minus + bool minus = Consume(s, '-'); - // Parse int: zero / ( digit1-9 *DIGIT ) - unsigned i = 0; - uint64_t i64 = 0; - bool use64bit = false; - int significandDigit = 0; - if (RAPIDJSON_UNLIKELY(s.Peek() == '0')) { - i = 0; - s.TakePush(); - } - else if (RAPIDJSON_LIKELY(s.Peek() >= '1' && s.Peek() <= '9')) { - i = static_cast(s.TakePush() - '0'); + // Parse int: zero / ( digit1-9 *DIGIT ) + unsigned i = 0; + uint64_t i64 = 0; + bool use64bit = false; + int significandDigit = 0; + if(RAPIDJSON_UNLIKELY(s.Peek() == '0')) + { + i = 0; + s.TakePush(); + } + else if(RAPIDJSON_LIKELY(s.Peek() >= '1' && s.Peek() <= '9')) + { + i = static_cast(s.TakePush() - '0'); - if (minus) - while (RAPIDJSON_LIKELY(s.Peek() >= '0' && s.Peek() <= '9')) { - if (RAPIDJSON_UNLIKELY(i >= 214748364)) { // 2^31 = 2147483648 - if (RAPIDJSON_LIKELY(i != 214748364 || s.Peek() > '8')) { - i64 = i; - use64bit = true; - break; - } - } - i = i * 10 + static_cast(s.TakePush() - '0'); - significandDigit++; - } - else - while (RAPIDJSON_LIKELY(s.Peek() >= '0' && s.Peek() <= '9')) { - if (RAPIDJSON_UNLIKELY(i >= 429496729)) { // 2^32 - 1 = 4294967295 - if (RAPIDJSON_LIKELY(i != 429496729 || s.Peek() > '5')) { - i64 = i; - use64bit = true; - break; - } - } - i = i * 10 + static_cast(s.TakePush() - '0'); - significandDigit++; - } - } - // Parse NaN or Infinity here - else if ((parseFlags & kParseNanAndInfFlag) && RAPIDJSON_LIKELY((s.Peek() == 'I' || s.Peek() == 'N'))) { - useNanOrInf = true; - if (RAPIDJSON_LIKELY(Consume(s, 'N') && Consume(s, 'a') && Consume(s, 'N'))) { - d = std::numeric_limits::quiet_NaN(); - } - else if (RAPIDJSON_LIKELY(Consume(s, 'I') && Consume(s, 'n') && Consume(s, 'f'))) { - d = (minus ? -std::numeric_limits::infinity() : std::numeric_limits::infinity()); - if (RAPIDJSON_UNLIKELY(s.Peek() == 'i' && !(Consume(s, 'i') && Consume(s, 'n') - && Consume(s, 'i') && Consume(s, 't') && Consume(s, 'y')))) - RAPIDJSON_PARSE_ERROR(kParseErrorValueInvalid, s.Tell()); - } - else - RAPIDJSON_PARSE_ERROR(kParseErrorValueInvalid, s.Tell()); - } - else - RAPIDJSON_PARSE_ERROR(kParseErrorValueInvalid, s.Tell()); + if(minus) + while(RAPIDJSON_LIKELY(s.Peek() >= '0' && s.Peek() <= '9')) + { + if(RAPIDJSON_UNLIKELY(i >= 214748364)) // 2^31 = 2147483648 + { + if(RAPIDJSON_LIKELY(i != 214748364 || s.Peek() > '8')) + { + i64 = i; + use64bit = true; + break; + } + } + i = i * 10 + static_cast(s.TakePush() - '0'); + significandDigit++; + } + else + while(RAPIDJSON_LIKELY(s.Peek() >= '0' && s.Peek() <= '9')) + { + if(RAPIDJSON_UNLIKELY(i >= 429496729)) // 2^32 - 1 = 4294967295 + { + if(RAPIDJSON_LIKELY(i != 429496729 || s.Peek() > '5')) + { + i64 = i; + use64bit = true; + break; + } + } + i = i * 10 + static_cast(s.TakePush() - '0'); + significandDigit++; + } + } + // Parse NaN or Infinity here + else if((parseFlags & kParseNanAndInfFlag) && RAPIDJSON_LIKELY((s.Peek() == 'I' || s.Peek() == 'N'))) + { + useNanOrInf = true; + if(RAPIDJSON_LIKELY(Consume(s, 'N') && Consume(s, 'a') && Consume(s, 'N'))) + { + d = std::numeric_limits::quiet_NaN(); + } + else if(RAPIDJSON_LIKELY(Consume(s, 'I') && Consume(s, 'n') && Consume(s, 'f'))) + { + d = (minus ? -std::numeric_limits::infinity() : std::numeric_limits::infinity()); + if(RAPIDJSON_UNLIKELY(s.Peek() == 'i' && !(Consume(s, 'i') && Consume(s, 'n') + && Consume(s, 'i') && Consume(s, 't') && Consume(s, 'y')))) + { + RAPIDJSON_PARSE_ERROR(kParseErrorValueInvalid, s.Tell()); + } + } + else + { + RAPIDJSON_PARSE_ERROR(kParseErrorValueInvalid, s.Tell()); + } + } + else + { + RAPIDJSON_PARSE_ERROR(kParseErrorValueInvalid, s.Tell()); + } - // Parse 64bit int - bool useDouble = false; - if (use64bit) { - if (minus) - while (RAPIDJSON_LIKELY(s.Peek() >= '0' && s.Peek() <= '9')) { - if (RAPIDJSON_UNLIKELY(i64 >= RAPIDJSON_UINT64_C2(0x0CCCCCCC, 0xCCCCCCCC))) // 2^63 = 9223372036854775808 - if (RAPIDJSON_LIKELY(i64 != RAPIDJSON_UINT64_C2(0x0CCCCCCC, 0xCCCCCCCC) || s.Peek() > '8')) { - d = static_cast(i64); - useDouble = true; - break; - } - i64 = i64 * 10 + static_cast(s.TakePush() - '0'); - significandDigit++; - } - else - while (RAPIDJSON_LIKELY(s.Peek() >= '0' && s.Peek() <= '9')) { - if (RAPIDJSON_UNLIKELY(i64 >= RAPIDJSON_UINT64_C2(0x19999999, 0x99999999))) // 2^64 - 1 = 18446744073709551615 - if (RAPIDJSON_LIKELY(i64 != RAPIDJSON_UINT64_C2(0x19999999, 0x99999999) || s.Peek() > '5')) { - d = static_cast(i64); - useDouble = true; - break; - } - i64 = i64 * 10 + static_cast(s.TakePush() - '0'); - significandDigit++; - } - } + // Parse 64bit int + bool useDouble = false; + if(use64bit) + { + if(minus) + while(RAPIDJSON_LIKELY(s.Peek() >= '0' && s.Peek() <= '9')) + { + if(RAPIDJSON_UNLIKELY(i64 >= RAPIDJSON_UINT64_C2(0x0CCCCCCC, 0xCCCCCCCC))) // 2^63 = 9223372036854775808 + if(RAPIDJSON_LIKELY(i64 != RAPIDJSON_UINT64_C2(0x0CCCCCCC, 0xCCCCCCCC) || s.Peek() > '8')) + { + d = static_cast(i64); + useDouble = true; + break; + } + i64 = i64 * 10 + static_cast(s.TakePush() - '0'); + significandDigit++; + } + else + while(RAPIDJSON_LIKELY(s.Peek() >= '0' && s.Peek() <= '9')) + { + if(RAPIDJSON_UNLIKELY(i64 >= RAPIDJSON_UINT64_C2(0x19999999, 0x99999999))) // 2^64 - 1 = 18446744073709551615 + if(RAPIDJSON_LIKELY(i64 != RAPIDJSON_UINT64_C2(0x19999999, 0x99999999) || s.Peek() > '5')) + { + d = static_cast(i64); + useDouble = true; + break; + } + i64 = i64 * 10 + static_cast(s.TakePush() - '0'); + significandDigit++; + } + } - // Force double for big integer - if (useDouble) { - while (RAPIDJSON_LIKELY(s.Peek() >= '0' && s.Peek() <= '9')) { - if (RAPIDJSON_UNLIKELY(d >= 1.7976931348623157e307)) // DBL_MAX / 10.0 - RAPIDJSON_PARSE_ERROR(kParseErrorNumberTooBig, startOffset); - d = d * 10 + (s.TakePush() - '0'); - } - } + // Force double for big integer + if(useDouble) + { + while(RAPIDJSON_LIKELY(s.Peek() >= '0' && s.Peek() <= '9')) + { + if(RAPIDJSON_UNLIKELY(d >= 1.7976931348623157e307)) // DBL_MAX / 10.0 + { + RAPIDJSON_PARSE_ERROR(kParseErrorNumberTooBig, startOffset); + } + d = d * 10 + (s.TakePush() - '0'); + } + } - // Parse frac = decimal-point 1*DIGIT - int expFrac = 0; - size_t decimalPosition; - if (Consume(s, '.')) { - decimalPosition = s.Length(); + // Parse frac = decimal-point 1*DIGIT + int expFrac = 0; + size_t decimalPosition; + if(Consume(s, '.')) + { + decimalPosition = s.Length(); - if (RAPIDJSON_UNLIKELY(!(s.Peek() >= '0' && s.Peek() <= '9'))) - RAPIDJSON_PARSE_ERROR(kParseErrorNumberMissFraction, s.Tell()); + if(RAPIDJSON_UNLIKELY(!(s.Peek() >= '0' && s.Peek() <= '9'))) + { + RAPIDJSON_PARSE_ERROR(kParseErrorNumberMissFraction, s.Tell()); + } - if (!useDouble) { + if(!useDouble) + { #if RAPIDJSON_64BIT - // Use i64 to store significand in 64-bit architecture - if (!use64bit) - i64 = i; + // Use i64 to store significand in 64-bit architecture + if(!use64bit) + { + i64 = i; + } - while (RAPIDJSON_LIKELY(s.Peek() >= '0' && s.Peek() <= '9')) { - if (i64 > RAPIDJSON_UINT64_C2(0x1FFFFF, 0xFFFFFFFF)) // 2^53 - 1 for fast path - break; - else { - i64 = i64 * 10 + static_cast(s.TakePush() - '0'); - --expFrac; - if (i64 != 0) - significandDigit++; - } - } + while(RAPIDJSON_LIKELY(s.Peek() >= '0' && s.Peek() <= '9')) + { + if(i64 > RAPIDJSON_UINT64_C2(0x1FFFFF, 0xFFFFFFFF)) // 2^53 - 1 for fast path + { + break; + } + else + { + i64 = i64 * 10 + static_cast(s.TakePush() - '0'); + --expFrac; + if(i64 != 0) + { + significandDigit++; + } + } + } - d = static_cast(i64); + d = static_cast(i64); #else - // Use double to store significand in 32-bit architecture - d = static_cast(use64bit ? i64 : i); + // Use double to store significand in 32-bit architecture + d = static_cast(use64bit ? i64 : i); #endif - useDouble = true; - } + useDouble = true; + } - while (RAPIDJSON_LIKELY(s.Peek() >= '0' && s.Peek() <= '9')) { - if (significandDigit < 17) { - d = d * 10.0 + (s.TakePush() - '0'); - --expFrac; - if (RAPIDJSON_LIKELY(d > 0.0)) - significandDigit++; - } - else - s.TakePush(); - } - } - else - decimalPosition = s.Length(); // decimal position at the end of integer. + while(RAPIDJSON_LIKELY(s.Peek() >= '0' && s.Peek() <= '9')) + { + if(significandDigit < 17) + { + d = d * 10.0 + (s.TakePush() - '0'); + --expFrac; + if(RAPIDJSON_LIKELY(d > 0.0)) + { + significandDigit++; + } + } + else + { + s.TakePush(); + } + } + } + else + { + decimalPosition = s.Length(); // decimal position at the end of integer. + } - // Parse exp = e [ minus / plus ] 1*DIGIT - int exp = 0; - if (Consume(s, 'e') || Consume(s, 'E')) { - if (!useDouble) { - d = static_cast(use64bit ? i64 : i); - useDouble = true; - } + // Parse exp = e [ minus / plus ] 1*DIGIT + int exp = 0; + if(Consume(s, 'e') || Consume(s, 'E')) + { + if(!useDouble) + { + d = static_cast(use64bit ? i64 : i); + useDouble = true; + } - bool expMinus = false; - if (Consume(s, '+')) - ; - else if (Consume(s, '-')) - expMinus = true; + bool expMinus = false; + if(Consume(s, '+')) + ; + else if(Consume(s, '-')) + { + expMinus = true; + } - if (RAPIDJSON_LIKELY(s.Peek() >= '0' && s.Peek() <= '9')) { - exp = static_cast(s.Take() - '0'); - if (expMinus) { - while (RAPIDJSON_LIKELY(s.Peek() >= '0' && s.Peek() <= '9')) { - exp = exp * 10 + static_cast(s.Take() - '0'); - if (exp >= 214748364) { // Issue #313: prevent overflow exponent - while (RAPIDJSON_UNLIKELY(s.Peek() >= '0' && s.Peek() <= '9')) // Consume the rest of exponent - s.Take(); - } - } - } - else { // positive exp - int maxExp = 308 - expFrac; - while (RAPIDJSON_LIKELY(s.Peek() >= '0' && s.Peek() <= '9')) { - exp = exp * 10 + static_cast(s.Take() - '0'); - if (RAPIDJSON_UNLIKELY(exp > maxExp)) - RAPIDJSON_PARSE_ERROR(kParseErrorNumberTooBig, startOffset); - } - } - } - else - RAPIDJSON_PARSE_ERROR(kParseErrorNumberMissExponent, s.Tell()); + if(RAPIDJSON_LIKELY(s.Peek() >= '0' && s.Peek() <= '9')) + { + exp = static_cast(s.Take() - '0'); + if(expMinus) + { + while(RAPIDJSON_LIKELY(s.Peek() >= '0' && s.Peek() <= '9')) + { + exp = exp * 10 + static_cast(s.Take() - '0'); + if(exp >= 214748364) // Issue #313: prevent overflow exponent + { + while(RAPIDJSON_UNLIKELY(s.Peek() >= '0' && s.Peek() <= '9')) // Consume the rest of exponent + { + s.Take(); + } + } + } + } + else // positive exp + { + int maxExp = 308 - expFrac; + while(RAPIDJSON_LIKELY(s.Peek() >= '0' && s.Peek() <= '9')) + { + exp = exp * 10 + static_cast(s.Take() - '0'); + if(RAPIDJSON_UNLIKELY(exp > maxExp)) + { + RAPIDJSON_PARSE_ERROR(kParseErrorNumberTooBig, startOffset); + } + } + } + } + else + { + RAPIDJSON_PARSE_ERROR(kParseErrorNumberMissExponent, s.Tell()); + } - if (expMinus) - exp = -exp; - } + if(expMinus) + { + exp = -exp; + } + } - // Finish parsing, call event according to the type of number. - bool cont = true; + // Finish parsing, call event according to the type of number. + bool cont = true; - if (parseFlags & kParseNumbersAsStringsFlag) { - if (parseFlags & kParseInsituFlag) { - s.Pop(); // Pop stack no matter if it will be used or not. - typename InputStream::Ch* head = is.PutBegin(); - const size_t length = s.Tell() - startOffset; - RAPIDJSON_ASSERT(length <= 0xFFFFFFFF); - // unable to insert the \0 character here, it will erase the comma after this number - const typename TargetEncoding::Ch* const str = reinterpret_cast(head); - cont = handler.RawNumber(str, SizeType(length), false); - } - else { - SizeType numCharsToCopy = static_cast(s.Length()); - StringStream srcStream(s.Pop()); - StackStream dstStream(stack_); - while (numCharsToCopy--) { - Transcoder, TargetEncoding>::Transcode(srcStream, dstStream); - } - dstStream.Put('\0'); - const typename TargetEncoding::Ch* str = dstStream.Pop(); - const SizeType length = static_cast(dstStream.Length()) - 1; - cont = handler.RawNumber(str, SizeType(length), true); - } - } - else { - size_t length = s.Length(); - const char* decimal = s.Pop(); // Pop stack no matter if it will be used or not. + if(parseFlags & kParseNumbersAsStringsFlag) + { + if(parseFlags & kParseInsituFlag) + { + s.Pop(); // Pop stack no matter if it will be used or not. + typename InputStream::Ch* head = is.PutBegin(); + const size_t length = s.Tell() - startOffset; + RAPIDJSON_ASSERT(length <= 0xFFFFFFFF); + // unable to insert the \0 character here, it will erase the comma after this number + const typename TargetEncoding::Ch* const str = reinterpret_cast(head); + cont = handler.RawNumber(str, SizeType(length), false); + } + else + { + SizeType numCharsToCopy = static_cast(s.Length()); + StringStream srcStream(s.Pop()); + StackStream dstStream(stack_); + while(numCharsToCopy--) + { + Transcoder, TargetEncoding>::Transcode(srcStream, dstStream); + } + dstStream.Put('\0'); + const typename TargetEncoding::Ch* str = dstStream.Pop(); + const SizeType length = static_cast(dstStream.Length()) - 1; + cont = handler.RawNumber(str, SizeType(length), true); + } + } + else + { + size_t length = s.Length(); + const char* decimal = s.Pop(); // Pop stack no matter if it will be used or not. - if (useDouble) { - int p = exp + expFrac; - if (parseFlags & kParseFullPrecisionFlag) - d = internal::StrtodFullPrecision(d, p, decimal, length, decimalPosition, exp); - else - d = internal::StrtodNormalPrecision(d, p); + if(useDouble) + { + int p = exp + expFrac; + if(parseFlags & kParseFullPrecisionFlag) + { + d = internal::StrtodFullPrecision(d, p, decimal, length, decimalPosition, exp); + } + else + { + d = internal::StrtodNormalPrecision(d, p); + } - cont = handler.Double(minus ? -d : d); - } - else if (useNanOrInf) { - cont = handler.Double(d); - } - else { - if (use64bit) { - if (minus) - cont = handler.Int64(static_cast(~i64 + 1)); - else - cont = handler.Uint64(i64); - } - else { - if (minus) - cont = handler.Int(static_cast(~i + 1)); - else - cont = handler.Uint(i); - } - } - } - if (RAPIDJSON_UNLIKELY(!cont)) - RAPIDJSON_PARSE_ERROR(kParseErrorTermination, startOffset); - } + cont = handler.Double(minus ? -d : d); + } + else if(useNanOrInf) + { + cont = handler.Double(d); + } + else + { + if(use64bit) + { + if(minus) + { + cont = handler.Int64(static_cast(~i64 + 1)); + } + else + { + cont = handler.Uint64(i64); + } + } + else + { + if(minus) + { + cont = handler.Int(static_cast(~i + 1)); + } + else + { + cont = handler.Uint(i); + } + } + } + } + if(RAPIDJSON_UNLIKELY(!cont)) + { + RAPIDJSON_PARSE_ERROR(kParseErrorTermination, startOffset); + } + } - // Parse any JSON value - template - void ParseValue(InputStream& is, Handler& handler) { - switch (is.Peek()) { - case 'n': ParseNull (is, handler); break; - case 't': ParseTrue (is, handler); break; - case 'f': ParseFalse (is, handler); break; - case '"': ParseString(is, handler); break; - case '{': ParseObject(is, handler); break; - case '[': ParseArray (is, handler); break; - default : - ParseNumber(is, handler); - break; + // Parse any JSON value + template + void ParseValue(InputStream & is, Handler & handler) + { + switch(is.Peek()) + { + case 'n': + ParseNull (is, handler); + break; + case 't': + ParseTrue (is, handler); + break; + case 'f': + ParseFalse (is, handler); + break; + case '"': + ParseString(is, handler); + break; + case '{': + ParseObject(is, handler); + break; + case '[': + ParseArray (is, handler); + break; + default : + ParseNumber(is, handler); + break; - } - } + } + } - // Iterative Parsing + // Iterative Parsing - // States - enum IterativeParsingState { - IterativeParsingStartState = 0, - IterativeParsingFinishState, - IterativeParsingErrorState, + // States + enum IterativeParsingState + { + IterativeParsingStartState = 0, + IterativeParsingFinishState, + IterativeParsingErrorState, - // Object states - IterativeParsingObjectInitialState, - IterativeParsingMemberKeyState, - IterativeParsingKeyValueDelimiterState, - IterativeParsingMemberValueState, - IterativeParsingMemberDelimiterState, - IterativeParsingObjectFinishState, + // Object states + IterativeParsingObjectInitialState, + IterativeParsingMemberKeyState, + IterativeParsingKeyValueDelimiterState, + IterativeParsingMemberValueState, + IterativeParsingMemberDelimiterState, + IterativeParsingObjectFinishState, - // Array states - IterativeParsingArrayInitialState, - IterativeParsingElementState, - IterativeParsingElementDelimiterState, - IterativeParsingArrayFinishState, + // Array states + IterativeParsingArrayInitialState, + IterativeParsingElementState, + IterativeParsingElementDelimiterState, + IterativeParsingArrayFinishState, - // Single value state - IterativeParsingValueState - }; + // Single value state + IterativeParsingValueState + }; - enum { cIterativeParsingStateCount = IterativeParsingValueState + 1 }; + enum { cIterativeParsingStateCount = IterativeParsingValueState + 1 }; - // Tokens - enum Token { - LeftBracketToken = 0, - RightBracketToken, + // Tokens + enum Token + { + LeftBracketToken = 0, + RightBracketToken, - LeftCurlyBracketToken, - RightCurlyBracketToken, + LeftCurlyBracketToken, + RightCurlyBracketToken, - CommaToken, - ColonToken, + CommaToken, + ColonToken, - StringToken, - FalseToken, - TrueToken, - NullToken, - NumberToken, + StringToken, + FalseToken, + TrueToken, + NullToken, + NumberToken, - kTokenCount - }; + kTokenCount + }; - RAPIDJSON_FORCEINLINE Token Tokenize(Ch c) { + RAPIDJSON_FORCEINLINE Token Tokenize(Ch c) + { -//!@cond RAPIDJSON_HIDDEN_FROM_DOXYGEN + //!@cond RAPIDJSON_HIDDEN_FROM_DOXYGEN #define N NumberToken #define N16 N,N,N,N,N,N,N,N,N,N,N,N,N,N,N,N - // Maps from ASCII to Token - static const unsigned char tokenMap[256] = { - N16, // 00~0F - N16, // 10~1F - N, N, StringToken, N, N, N, N, N, N, N, N, N, CommaToken, N, N, N, // 20~2F - N, N, N, N, N, N, N, N, N, N, ColonToken, N, N, N, N, N, // 30~3F - N16, // 40~4F - N, N, N, N, N, N, N, N, N, N, N, LeftBracketToken, N, RightBracketToken, N, N, // 50~5F - N, N, N, N, N, N, FalseToken, N, N, N, N, N, N, N, NullToken, N, // 60~6F - N, N, N, N, TrueToken, N, N, N, N, N, N, LeftCurlyBracketToken, N, RightCurlyBracketToken, N, N, // 70~7F - N16, N16, N16, N16, N16, N16, N16, N16 // 80~FF - }; + // Maps from ASCII to Token + static const unsigned char tokenMap[256] = + { + N16, // 00~0F + N16, // 10~1F + N, N, StringToken, N, N, N, N, N, N, N, N, N, CommaToken, N, N, N, // 20~2F + N, N, N, N, N, N, N, N, N, N, ColonToken, N, N, N, N, N, // 30~3F + N16, // 40~4F + N, N, N, N, N, N, N, N, N, N, N, LeftBracketToken, N, RightBracketToken, N, N, // 50~5F + N, N, N, N, N, N, FalseToken, N, N, N, N, N, N, N, NullToken, N, // 60~6F + N, N, N, N, TrueToken, N, N, N, N, N, N, LeftCurlyBracketToken, N, RightCurlyBracketToken, N, N, // 70~7F + N16, N16, N16, N16, N16, N16, N16, N16 // 80~FF + }; #undef N #undef N16 -//!@endcond + //!@endcond - if (sizeof(Ch) == 1 || static_cast(c) < 256) - return static_cast(tokenMap[static_cast(c)]); - else - return NumberToken; - } + if(sizeof(Ch) == 1 || static_cast(c) < 256) + { + return static_cast(tokenMap[static_cast(c)]); + } + else + { + return NumberToken; + } + } - RAPIDJSON_FORCEINLINE IterativeParsingState Predict(IterativeParsingState state, Token token) { - // current state x one lookahead token -> new state - static const char G[cIterativeParsingStateCount][kTokenCount] = { - // Start - { - IterativeParsingArrayInitialState, // Left bracket - IterativeParsingErrorState, // Right bracket - IterativeParsingObjectInitialState, // Left curly bracket - IterativeParsingErrorState, // Right curly bracket - IterativeParsingErrorState, // Comma - IterativeParsingErrorState, // Colon - IterativeParsingValueState, // String - IterativeParsingValueState, // False - IterativeParsingValueState, // True - IterativeParsingValueState, // Null - IterativeParsingValueState // Number - }, - // Finish(sink state) - { - IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, - IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, - IterativeParsingErrorState - }, - // Error(sink state) - { - IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, - IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, - IterativeParsingErrorState - }, - // ObjectInitial - { - IterativeParsingErrorState, // Left bracket - IterativeParsingErrorState, // Right bracket - IterativeParsingErrorState, // Left curly bracket - IterativeParsingObjectFinishState, // Right curly bracket - IterativeParsingErrorState, // Comma - IterativeParsingErrorState, // Colon - IterativeParsingMemberKeyState, // String - IterativeParsingErrorState, // False - IterativeParsingErrorState, // True - IterativeParsingErrorState, // Null - IterativeParsingErrorState // Number - }, - // MemberKey - { - IterativeParsingErrorState, // Left bracket - IterativeParsingErrorState, // Right bracket - IterativeParsingErrorState, // Left curly bracket - IterativeParsingErrorState, // Right curly bracket - IterativeParsingErrorState, // Comma - IterativeParsingKeyValueDelimiterState, // Colon - IterativeParsingErrorState, // String - IterativeParsingErrorState, // False - IterativeParsingErrorState, // True - IterativeParsingErrorState, // Null - IterativeParsingErrorState // Number - }, - // KeyValueDelimiter - { - IterativeParsingArrayInitialState, // Left bracket(push MemberValue state) - IterativeParsingErrorState, // Right bracket - IterativeParsingObjectInitialState, // Left curly bracket(push MemberValue state) - IterativeParsingErrorState, // Right curly bracket - IterativeParsingErrorState, // Comma - IterativeParsingErrorState, // Colon - IterativeParsingMemberValueState, // String - IterativeParsingMemberValueState, // False - IterativeParsingMemberValueState, // True - IterativeParsingMemberValueState, // Null - IterativeParsingMemberValueState // Number - }, - // MemberValue - { - IterativeParsingErrorState, // Left bracket - IterativeParsingErrorState, // Right bracket - IterativeParsingErrorState, // Left curly bracket - IterativeParsingObjectFinishState, // Right curly bracket - IterativeParsingMemberDelimiterState, // Comma - IterativeParsingErrorState, // Colon - IterativeParsingErrorState, // String - IterativeParsingErrorState, // False - IterativeParsingErrorState, // True - IterativeParsingErrorState, // Null - IterativeParsingErrorState // Number - }, - // MemberDelimiter - { - IterativeParsingErrorState, // Left bracket - IterativeParsingErrorState, // Right bracket - IterativeParsingErrorState, // Left curly bracket - IterativeParsingObjectFinishState, // Right curly bracket - IterativeParsingErrorState, // Comma - IterativeParsingErrorState, // Colon - IterativeParsingMemberKeyState, // String - IterativeParsingErrorState, // False - IterativeParsingErrorState, // True - IterativeParsingErrorState, // Null - IterativeParsingErrorState // Number - }, - // ObjectFinish(sink state) - { - IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, - IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, - IterativeParsingErrorState - }, - // ArrayInitial - { - IterativeParsingArrayInitialState, // Left bracket(push Element state) - IterativeParsingArrayFinishState, // Right bracket - IterativeParsingObjectInitialState, // Left curly bracket(push Element state) - IterativeParsingErrorState, // Right curly bracket - IterativeParsingErrorState, // Comma - IterativeParsingErrorState, // Colon - IterativeParsingElementState, // String - IterativeParsingElementState, // False - IterativeParsingElementState, // True - IterativeParsingElementState, // Null - IterativeParsingElementState // Number - }, - // Element - { - IterativeParsingErrorState, // Left bracket - IterativeParsingArrayFinishState, // Right bracket - IterativeParsingErrorState, // Left curly bracket - IterativeParsingErrorState, // Right curly bracket - IterativeParsingElementDelimiterState, // Comma - IterativeParsingErrorState, // Colon - IterativeParsingErrorState, // String - IterativeParsingErrorState, // False - IterativeParsingErrorState, // True - IterativeParsingErrorState, // Null - IterativeParsingErrorState // Number - }, - // ElementDelimiter - { - IterativeParsingArrayInitialState, // Left bracket(push Element state) - IterativeParsingArrayFinishState, // Right bracket - IterativeParsingObjectInitialState, // Left curly bracket(push Element state) - IterativeParsingErrorState, // Right curly bracket - IterativeParsingErrorState, // Comma - IterativeParsingErrorState, // Colon - IterativeParsingElementState, // String - IterativeParsingElementState, // False - IterativeParsingElementState, // True - IterativeParsingElementState, // Null - IterativeParsingElementState // Number - }, - // ArrayFinish(sink state) - { - IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, - IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, - IterativeParsingErrorState - }, - // Single Value (sink state) - { - IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, - IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, - IterativeParsingErrorState - } - }; // End of G + RAPIDJSON_FORCEINLINE IterativeParsingState Predict(IterativeParsingState state, Token token) + { + // current state x one lookahead token -> new state + static const char G[cIterativeParsingStateCount][kTokenCount] = + { + // Start + { + IterativeParsingArrayInitialState, // Left bracket + IterativeParsingErrorState, // Right bracket + IterativeParsingObjectInitialState, // Left curly bracket + IterativeParsingErrorState, // Right curly bracket + IterativeParsingErrorState, // Comma + IterativeParsingErrorState, // Colon + IterativeParsingValueState, // String + IterativeParsingValueState, // False + IterativeParsingValueState, // True + IterativeParsingValueState, // Null + IterativeParsingValueState // Number + }, + // Finish(sink state) + { + IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, + IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, + IterativeParsingErrorState + }, + // Error(sink state) + { + IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, + IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, + IterativeParsingErrorState + }, + // ObjectInitial + { + IterativeParsingErrorState, // Left bracket + IterativeParsingErrorState, // Right bracket + IterativeParsingErrorState, // Left curly bracket + IterativeParsingObjectFinishState, // Right curly bracket + IterativeParsingErrorState, // Comma + IterativeParsingErrorState, // Colon + IterativeParsingMemberKeyState, // String + IterativeParsingErrorState, // False + IterativeParsingErrorState, // True + IterativeParsingErrorState, // Null + IterativeParsingErrorState // Number + }, + // MemberKey + { + IterativeParsingErrorState, // Left bracket + IterativeParsingErrorState, // Right bracket + IterativeParsingErrorState, // Left curly bracket + IterativeParsingErrorState, // Right curly bracket + IterativeParsingErrorState, // Comma + IterativeParsingKeyValueDelimiterState, // Colon + IterativeParsingErrorState, // String + IterativeParsingErrorState, // False + IterativeParsingErrorState, // True + IterativeParsingErrorState, // Null + IterativeParsingErrorState // Number + }, + // KeyValueDelimiter + { + IterativeParsingArrayInitialState, // Left bracket(push MemberValue state) + IterativeParsingErrorState, // Right bracket + IterativeParsingObjectInitialState, // Left curly bracket(push MemberValue state) + IterativeParsingErrorState, // Right curly bracket + IterativeParsingErrorState, // Comma + IterativeParsingErrorState, // Colon + IterativeParsingMemberValueState, // String + IterativeParsingMemberValueState, // False + IterativeParsingMemberValueState, // True + IterativeParsingMemberValueState, // Null + IterativeParsingMemberValueState // Number + }, + // MemberValue + { + IterativeParsingErrorState, // Left bracket + IterativeParsingErrorState, // Right bracket + IterativeParsingErrorState, // Left curly bracket + IterativeParsingObjectFinishState, // Right curly bracket + IterativeParsingMemberDelimiterState, // Comma + IterativeParsingErrorState, // Colon + IterativeParsingErrorState, // String + IterativeParsingErrorState, // False + IterativeParsingErrorState, // True + IterativeParsingErrorState, // Null + IterativeParsingErrorState // Number + }, + // MemberDelimiter + { + IterativeParsingErrorState, // Left bracket + IterativeParsingErrorState, // Right bracket + IterativeParsingErrorState, // Left curly bracket + IterativeParsingObjectFinishState, // Right curly bracket + IterativeParsingErrorState, // Comma + IterativeParsingErrorState, // Colon + IterativeParsingMemberKeyState, // String + IterativeParsingErrorState, // False + IterativeParsingErrorState, // True + IterativeParsingErrorState, // Null + IterativeParsingErrorState // Number + }, + // ObjectFinish(sink state) + { + IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, + IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, + IterativeParsingErrorState + }, + // ArrayInitial + { + IterativeParsingArrayInitialState, // Left bracket(push Element state) + IterativeParsingArrayFinishState, // Right bracket + IterativeParsingObjectInitialState, // Left curly bracket(push Element state) + IterativeParsingErrorState, // Right curly bracket + IterativeParsingErrorState, // Comma + IterativeParsingErrorState, // Colon + IterativeParsingElementState, // String + IterativeParsingElementState, // False + IterativeParsingElementState, // True + IterativeParsingElementState, // Null + IterativeParsingElementState // Number + }, + // Element + { + IterativeParsingErrorState, // Left bracket + IterativeParsingArrayFinishState, // Right bracket + IterativeParsingErrorState, // Left curly bracket + IterativeParsingErrorState, // Right curly bracket + IterativeParsingElementDelimiterState, // Comma + IterativeParsingErrorState, // Colon + IterativeParsingErrorState, // String + IterativeParsingErrorState, // False + IterativeParsingErrorState, // True + IterativeParsingErrorState, // Null + IterativeParsingErrorState // Number + }, + // ElementDelimiter + { + IterativeParsingArrayInitialState, // Left bracket(push Element state) + IterativeParsingArrayFinishState, // Right bracket + IterativeParsingObjectInitialState, // Left curly bracket(push Element state) + IterativeParsingErrorState, // Right curly bracket + IterativeParsingErrorState, // Comma + IterativeParsingErrorState, // Colon + IterativeParsingElementState, // String + IterativeParsingElementState, // False + IterativeParsingElementState, // True + IterativeParsingElementState, // Null + IterativeParsingElementState // Number + }, + // ArrayFinish(sink state) + { + IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, + IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, + IterativeParsingErrorState + }, + // Single Value (sink state) + { + IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, + IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, + IterativeParsingErrorState + } + }; // End of G - return static_cast(G[state][token]); - } + return static_cast(G[state][token]); + } - // Make an advance in the token stream and state based on the candidate destination state which was returned by Transit(). - // May return a new state on state pop. - template - RAPIDJSON_FORCEINLINE IterativeParsingState Transit(IterativeParsingState src, Token token, IterativeParsingState dst, InputStream& is, Handler& handler) { - (void)token; + // Make an advance in the token stream and state based on the candidate destination state which was returned by Transit(). + // May return a new state on state pop. + template + RAPIDJSON_FORCEINLINE IterativeParsingState Transit(IterativeParsingState src, Token token, + IterativeParsingState dst, InputStream & is, Handler & handler) + { + (void)token; - switch (dst) { - case IterativeParsingErrorState: - return dst; + switch(dst) + { + case IterativeParsingErrorState: + return dst; - case IterativeParsingObjectInitialState: - case IterativeParsingArrayInitialState: - { - // Push the state(Element or MemeberValue) if we are nested in another array or value of member. - // In this way we can get the correct state on ObjectFinish or ArrayFinish by frame pop. - IterativeParsingState n = src; - if (src == IterativeParsingArrayInitialState || src == IterativeParsingElementDelimiterState) - n = IterativeParsingElementState; - else if (src == IterativeParsingKeyValueDelimiterState) - n = IterativeParsingMemberValueState; - // Push current state. - *stack_.template Push(1) = n; - // Initialize and push the member/element count. - *stack_.template Push(1) = 0; - // Call handler - bool hr = (dst == IterativeParsingObjectInitialState) ? handler.StartObject() : handler.StartArray(); - // On handler short circuits the parsing. - if (!hr) { - RAPIDJSON_PARSE_ERROR_NORETURN(kParseErrorTermination, is.Tell()); - return IterativeParsingErrorState; - } - else { - is.Take(); - return dst; - } - } + case IterativeParsingObjectInitialState: + case IterativeParsingArrayInitialState: + { + // Push the state(Element or MemeberValue) if we are nested in another array or value of member. + // In this way we can get the correct state on ObjectFinish or ArrayFinish by frame pop. + IterativeParsingState n = src; + if(src == IterativeParsingArrayInitialState || src == IterativeParsingElementDelimiterState) + { + n = IterativeParsingElementState; + } + else if(src == IterativeParsingKeyValueDelimiterState) + { + n = IterativeParsingMemberValueState; + } + // Push current state. + *stack_.template Push(1) = n; + // Initialize and push the member/element count. + *stack_.template Push(1) = 0; + // Call handler + bool hr = (dst == IterativeParsingObjectInitialState) ? handler.StartObject() : handler.StartArray(); + // On handler short circuits the parsing. + if(!hr) + { + RAPIDJSON_PARSE_ERROR_NORETURN(kParseErrorTermination, is.Tell()); + return IterativeParsingErrorState; + } + else + { + is.Take(); + return dst; + } + } - case IterativeParsingMemberKeyState: - ParseString(is, handler, true); - if (HasParseError()) - return IterativeParsingErrorState; - else - return dst; + case IterativeParsingMemberKeyState: + ParseString(is, handler, true); + if(HasParseError()) + { + return IterativeParsingErrorState; + } + else + { + return dst; + } - case IterativeParsingKeyValueDelimiterState: - RAPIDJSON_ASSERT(token == ColonToken); - is.Take(); - return dst; + case IterativeParsingKeyValueDelimiterState: + RAPIDJSON_ASSERT(token == ColonToken); + is.Take(); + return dst; - case IterativeParsingMemberValueState: - // Must be non-compound value. Or it would be ObjectInitial or ArrayInitial state. - ParseValue(is, handler); - if (HasParseError()) { - return IterativeParsingErrorState; - } - return dst; + case IterativeParsingMemberValueState: + // Must be non-compound value. Or it would be ObjectInitial or ArrayInitial state. + ParseValue(is, handler); + if(HasParseError()) + { + return IterativeParsingErrorState; + } + return dst; - case IterativeParsingElementState: - // Must be non-compound value. Or it would be ObjectInitial or ArrayInitial state. - ParseValue(is, handler); - if (HasParseError()) { - return IterativeParsingErrorState; - } - return dst; + case IterativeParsingElementState: + // Must be non-compound value. Or it would be ObjectInitial or ArrayInitial state. + ParseValue(is, handler); + if(HasParseError()) + { + return IterativeParsingErrorState; + } + return dst; - case IterativeParsingMemberDelimiterState: - case IterativeParsingElementDelimiterState: - is.Take(); - // Update member/element count. - *stack_.template Top() = *stack_.template Top() + 1; - return dst; + case IterativeParsingMemberDelimiterState: + case IterativeParsingElementDelimiterState: + is.Take(); + // Update member/element count. + *stack_.template Top() = *stack_.template Top() + 1; + return dst; - case IterativeParsingObjectFinishState: - { - // Transit from delimiter is only allowed when trailing commas are enabled - if (!(parseFlags & kParseTrailingCommasFlag) && src == IterativeParsingMemberDelimiterState) { - RAPIDJSON_PARSE_ERROR_NORETURN(kParseErrorObjectMissName, is.Tell()); - return IterativeParsingErrorState; - } - // Get member count. - SizeType c = *stack_.template Pop(1); - // If the object is not empty, count the last member. - if (src == IterativeParsingMemberValueState) - ++c; - // Restore the state. - IterativeParsingState n = static_cast(*stack_.template Pop(1)); - // Transit to Finish state if this is the topmost scope. - if (n == IterativeParsingStartState) - n = IterativeParsingFinishState; - // Call handler - bool hr = handler.EndObject(c); - // On handler short circuits the parsing. - if (!hr) { - RAPIDJSON_PARSE_ERROR_NORETURN(kParseErrorTermination, is.Tell()); - return IterativeParsingErrorState; - } - else { - is.Take(); - return n; - } - } + case IterativeParsingObjectFinishState: + { + // Transit from delimiter is only allowed when trailing commas are enabled + if(!(parseFlags & kParseTrailingCommasFlag) && src == IterativeParsingMemberDelimiterState) + { + RAPIDJSON_PARSE_ERROR_NORETURN(kParseErrorObjectMissName, is.Tell()); + return IterativeParsingErrorState; + } + // Get member count. + SizeType c = *stack_.template Pop(1); + // If the object is not empty, count the last member. + if(src == IterativeParsingMemberValueState) + { + ++c; + } + // Restore the state. + IterativeParsingState n = static_cast(*stack_.template Pop(1)); + // Transit to Finish state if this is the topmost scope. + if(n == IterativeParsingStartState) + { + n = IterativeParsingFinishState; + } + // Call handler + bool hr = handler.EndObject(c); + // On handler short circuits the parsing. + if(!hr) + { + RAPIDJSON_PARSE_ERROR_NORETURN(kParseErrorTermination, is.Tell()); + return IterativeParsingErrorState; + } + else + { + is.Take(); + return n; + } + } - case IterativeParsingArrayFinishState: - { - // Transit from delimiter is only allowed when trailing commas are enabled - if (!(parseFlags & kParseTrailingCommasFlag) && src == IterativeParsingElementDelimiterState) { - RAPIDJSON_PARSE_ERROR_NORETURN(kParseErrorValueInvalid, is.Tell()); - return IterativeParsingErrorState; - } - // Get element count. - SizeType c = *stack_.template Pop(1); - // If the array is not empty, count the last element. - if (src == IterativeParsingElementState) - ++c; - // Restore the state. - IterativeParsingState n = static_cast(*stack_.template Pop(1)); - // Transit to Finish state if this is the topmost scope. - if (n == IterativeParsingStartState) - n = IterativeParsingFinishState; - // Call handler - bool hr = handler.EndArray(c); - // On handler short circuits the parsing. - if (!hr) { - RAPIDJSON_PARSE_ERROR_NORETURN(kParseErrorTermination, is.Tell()); - return IterativeParsingErrorState; - } - else { - is.Take(); - return n; - } - } + case IterativeParsingArrayFinishState: + { + // Transit from delimiter is only allowed when trailing commas are enabled + if(!(parseFlags & kParseTrailingCommasFlag) && src == IterativeParsingElementDelimiterState) + { + RAPIDJSON_PARSE_ERROR_NORETURN(kParseErrorValueInvalid, is.Tell()); + return IterativeParsingErrorState; + } + // Get element count. + SizeType c = *stack_.template Pop(1); + // If the array is not empty, count the last element. + if(src == IterativeParsingElementState) + { + ++c; + } + // Restore the state. + IterativeParsingState n = static_cast(*stack_.template Pop(1)); + // Transit to Finish state if this is the topmost scope. + if(n == IterativeParsingStartState) + { + n = IterativeParsingFinishState; + } + // Call handler + bool hr = handler.EndArray(c); + // On handler short circuits the parsing. + if(!hr) + { + RAPIDJSON_PARSE_ERROR_NORETURN(kParseErrorTermination, is.Tell()); + return IterativeParsingErrorState; + } + else + { + is.Take(); + return n; + } + } - default: - // This branch is for IterativeParsingValueState actually. - // Use `default:` rather than - // `case IterativeParsingValueState:` is for code coverage. + default: + // This branch is for IterativeParsingValueState actually. + // Use `default:` rather than + // `case IterativeParsingValueState:` is for code coverage. - // The IterativeParsingStartState is not enumerated in this switch-case. - // It is impossible for that case. And it can be caught by following assertion. + // The IterativeParsingStartState is not enumerated in this switch-case. + // It is impossible for that case. And it can be caught by following assertion. - // The IterativeParsingFinishState is not enumerated in this switch-case either. - // It is a "derivative" state which cannot triggered from Predict() directly. - // Therefore it cannot happen here. And it can be caught by following assertion. - RAPIDJSON_ASSERT(dst == IterativeParsingValueState); + // The IterativeParsingFinishState is not enumerated in this switch-case either. + // It is a "derivative" state which cannot triggered from Predict() directly. + // Therefore it cannot happen here. And it can be caught by following assertion. + RAPIDJSON_ASSERT(dst == IterativeParsingValueState); - // Must be non-compound value. Or it would be ObjectInitial or ArrayInitial state. - ParseValue(is, handler); - if (HasParseError()) { - return IterativeParsingErrorState; - } - return IterativeParsingFinishState; - } - } + // Must be non-compound value. Or it would be ObjectInitial or ArrayInitial state. + ParseValue(is, handler); + if(HasParseError()) + { + return IterativeParsingErrorState; + } + return IterativeParsingFinishState; + } + } - template - void HandleError(IterativeParsingState src, InputStream& is) { - if (HasParseError()) { - // Error flag has been set. - return; - } + template + void HandleError(IterativeParsingState src, InputStream & is) + { + if(HasParseError()) + { + // Error flag has been set. + return; + } - switch (src) { - case IterativeParsingStartState: RAPIDJSON_PARSE_ERROR(kParseErrorDocumentEmpty, is.Tell()); return; - case IterativeParsingFinishState: RAPIDJSON_PARSE_ERROR(kParseErrorDocumentRootNotSingular, is.Tell()); return; - case IterativeParsingObjectInitialState: - case IterativeParsingMemberDelimiterState: RAPIDJSON_PARSE_ERROR(kParseErrorObjectMissName, is.Tell()); return; - case IterativeParsingMemberKeyState: RAPIDJSON_PARSE_ERROR(kParseErrorObjectMissColon, is.Tell()); return; - case IterativeParsingMemberValueState: RAPIDJSON_PARSE_ERROR(kParseErrorObjectMissCommaOrCurlyBracket, is.Tell()); return; - case IterativeParsingKeyValueDelimiterState: - case IterativeParsingArrayInitialState: - case IterativeParsingElementDelimiterState: RAPIDJSON_PARSE_ERROR(kParseErrorValueInvalid, is.Tell()); return; - default: RAPIDJSON_ASSERT(src == IterativeParsingElementState); RAPIDJSON_PARSE_ERROR(kParseErrorArrayMissCommaOrSquareBracket, is.Tell()); return; - } - } + switch(src) + { + case IterativeParsingStartState: + RAPIDJSON_PARSE_ERROR(kParseErrorDocumentEmpty, is.Tell()); + return; + case IterativeParsingFinishState: + RAPIDJSON_PARSE_ERROR(kParseErrorDocumentRootNotSingular, is.Tell()); + return; + case IterativeParsingObjectInitialState: + case IterativeParsingMemberDelimiterState: + RAPIDJSON_PARSE_ERROR(kParseErrorObjectMissName, is.Tell()); + return; + case IterativeParsingMemberKeyState: + RAPIDJSON_PARSE_ERROR(kParseErrorObjectMissColon, is.Tell()); + return; + case IterativeParsingMemberValueState: + RAPIDJSON_PARSE_ERROR(kParseErrorObjectMissCommaOrCurlyBracket, is.Tell()); + return; + case IterativeParsingKeyValueDelimiterState: + case IterativeParsingArrayInitialState: + case IterativeParsingElementDelimiterState: + RAPIDJSON_PARSE_ERROR(kParseErrorValueInvalid, is.Tell()); + return; + default: + RAPIDJSON_ASSERT(src == IterativeParsingElementState); + RAPIDJSON_PARSE_ERROR(kParseErrorArrayMissCommaOrSquareBracket, is.Tell()); + return; + } + } - template - ParseResult IterativeParse(InputStream& is, Handler& handler) { - parseResult_.Clear(); - ClearStackOnExit scope(*this); - IterativeParsingState state = IterativeParsingStartState; + template + ParseResult IterativeParse(InputStream & is, Handler & handler) + { + parseResult_.Clear(); + ClearStackOnExit scope(*this); + IterativeParsingState state = IterativeParsingStartState; - SkipWhitespaceAndComments(is); - RAPIDJSON_PARSE_ERROR_EARLY_RETURN(parseResult_); - while (is.Peek() != '\0') { - Token t = Tokenize(is.Peek()); - IterativeParsingState n = Predict(state, t); - IterativeParsingState d = Transit(state, t, n, is, handler); + SkipWhitespaceAndComments(is); + RAPIDJSON_PARSE_ERROR_EARLY_RETURN(parseResult_); + while(is.Peek() != '\0') + { + Token t = Tokenize(is.Peek()); + IterativeParsingState n = Predict(state, t); + IterativeParsingState d = Transit(state, t, n, is, handler); - if (d == IterativeParsingErrorState) { - HandleError(state, is); - break; - } + if(d == IterativeParsingErrorState) + { + HandleError(state, is); + break; + } - state = d; + state = d; - // Do not further consume streams if a root JSON has been parsed. - if ((parseFlags & kParseStopWhenDoneFlag) && state == IterativeParsingFinishState) - break; + // Do not further consume streams if a root JSON has been parsed. + if((parseFlags & kParseStopWhenDoneFlag) && state == IterativeParsingFinishState) + { + break; + } - SkipWhitespaceAndComments(is); - RAPIDJSON_PARSE_ERROR_EARLY_RETURN(parseResult_); - } + SkipWhitespaceAndComments(is); + RAPIDJSON_PARSE_ERROR_EARLY_RETURN(parseResult_); + } - // Handle the end of file. - if (state != IterativeParsingFinishState) - HandleError(state, is); + // Handle the end of file. + if(state != IterativeParsingFinishState) + { + HandleError(state, is); + } - return parseResult_; - } + return parseResult_; + } - static const size_t kDefaultStackCapacity = 256; //!< Default stack capacity in bytes for storing a single decoded string. - internal::Stack stack_; //!< A stack for storing decoded string temporarily during non-destructive parsing. - ParseResult parseResult_; + static const size_t kDefaultStackCapacity = + 256; //!< Default stack capacity in bytes for storing a single decoded string. + internal::Stack + stack_; //!< A stack for storing decoded string temporarily during non-destructive parsing. + ParseResult parseResult_; }; // class GenericReader //! Reader with UTF8 encoding and default allocator. -typedef GenericReader, UTF8<> > Reader; +typedef GenericReader, UTF8<>> Reader; RAPIDJSON_NAMESPACE_END diff --git a/src/3rdparty/rapidjson/schema.h b/src/3rdparty/rapidjson/schema.h index b182aa27..2e854855 100644 --- a/src/3rdparty/rapidjson/schema.h +++ b/src/3rdparty/rapidjson/schema.h @@ -1,5 +1,5 @@ // 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 @@ -7,9 +7,9 @@ // // 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 +// 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_SCHEMA_H_ @@ -58,10 +58,10 @@ RAPIDJSON_DIAG_OFF(effc++) #endif #ifdef __clang__ -RAPIDJSON_DIAG_OFF(weak-vtables) -RAPIDJSON_DIAG_OFF(exit-time-destructors) -RAPIDJSON_DIAG_OFF(c++98-compat-pedantic) -RAPIDJSON_DIAG_OFF(variadic-macros) +RAPIDJSON_DIAG_OFF(weak - vtables) +RAPIDJSON_DIAG_OFF(exit - time - destructors) +RAPIDJSON_DIAG_OFF(c++98 - compat - pedantic) +RAPIDJSON_DIAG_OFF(variadic - macros) #endif #ifdef _MSC_VER @@ -75,31 +75,38 @@ RAPIDJSON_NAMESPACE_BEGIN #if RAPIDJSON_SCHEMA_VERBOSE -namespace internal { +namespace internal +{ -inline void PrintInvalidKeyword(const char* keyword) { - printf("Fail keyword: %s\n", keyword); -} + inline void PrintInvalidKeyword(const char* keyword) + { + printf("Fail keyword: %s\n", keyword); + } -inline void PrintInvalidKeyword(const wchar_t* keyword) { - wprintf(L"Fail keyword: %ls\n", keyword); -} + inline void PrintInvalidKeyword(const wchar_t* keyword) + { + wprintf(L"Fail keyword: %ls\n", keyword); + } -inline void PrintInvalidDocument(const char* document) { - printf("Fail document: %s\n\n", document); -} + inline void PrintInvalidDocument(const char* document) + { + printf("Fail document: %s\n\n", document); + } -inline void PrintInvalidDocument(const wchar_t* document) { - wprintf(L"Fail document: %ls\n\n", document); -} + inline void PrintInvalidDocument(const wchar_t* document) + { + wprintf(L"Fail document: %ls\n\n", document); + } -inline void PrintValidatorPointers(unsigned depth, const char* s, const char* d) { - printf("S: %*s%s\nD: %*s%s\n\n", depth * 4, " ", s, depth * 4, " ", d); -} + inline void PrintValidatorPointers(unsigned depth, const char* s, const char* d) + { + printf("S: %*s%s\nD: %*s%s\n\n", depth * 4, " ", s, depth * 4, " ", d); + } -inline void PrintValidatorPointers(unsigned depth, const wchar_t* s, const wchar_t* d) { - wprintf(L"S: %*ls%ls\nD: %*ls%ls\n\n", depth * 4, L" ", s, depth * 4, L" ", d); -} + inline void PrintValidatorPointers(unsigned depth, const wchar_t* s, const wchar_t* d) + { + wprintf(L"S: %*ls%ls\nD: %*ls%ls\n\n", depth * 4, L" ", s, depth * 4, L" ", d); + } } // namespace internal @@ -115,11 +122,11 @@ inline void PrintValidatorPointers(unsigned depth, const wchar_t* s, const wchar #endif #define RAPIDJSON_INVALID_KEYWORD_RETURN(keyword)\ -RAPIDJSON_MULTILINEMACRO_BEGIN\ - context.invalidKeyword = keyword.GetString();\ - RAPIDJSON_INVALID_KEYWORD_VERBOSE(keyword.GetString());\ - return false;\ -RAPIDJSON_MULTILINEMACRO_END + RAPIDJSON_MULTILINEMACRO_BEGIN\ + context.invalidKeyword = keyword.GetString();\ + RAPIDJSON_INVALID_KEYWORD_VERBOSE(keyword.GetString());\ + return false;\ + RAPIDJSON_MULTILINEMACRO_END /////////////////////////////////////////////////////////////////////////////// // Forward declarations @@ -127,1168 +134,1621 @@ RAPIDJSON_MULTILINEMACRO_END template class GenericSchemaDocument; -namespace internal { +namespace internal +{ -template -class Schema; + template + class Schema; -/////////////////////////////////////////////////////////////////////////////// -// ISchemaValidator + /////////////////////////////////////////////////////////////////////////////// + // ISchemaValidator -class ISchemaValidator { -public: - virtual ~ISchemaValidator() {} - virtual bool IsValid() const = 0; -}; + class ISchemaValidator + { + public: + virtual ~ISchemaValidator() {} + virtual bool IsValid() const = 0; + }; -/////////////////////////////////////////////////////////////////////////////// -// ISchemaStateFactory + /////////////////////////////////////////////////////////////////////////////// + // ISchemaStateFactory -template -class ISchemaStateFactory { -public: - virtual ~ISchemaStateFactory() {} - virtual ISchemaValidator* CreateSchemaValidator(const SchemaType&) = 0; - virtual void DestroySchemaValidator(ISchemaValidator* validator) = 0; - virtual void* CreateHasher() = 0; - virtual uint64_t GetHashCode(void* hasher) = 0; - virtual void DestroryHasher(void* hasher) = 0; - virtual void* MallocState(size_t size) = 0; - virtual void FreeState(void* p) = 0; -}; + template + class ISchemaStateFactory + { + public: + virtual ~ISchemaStateFactory() {} + virtual ISchemaValidator* CreateSchemaValidator(const SchemaType &) = 0; + virtual void DestroySchemaValidator(ISchemaValidator* validator) = 0; + virtual void* CreateHasher() = 0; + virtual uint64_t GetHashCode(void* hasher) = 0; + virtual void DestroryHasher(void* hasher) = 0; + virtual void* MallocState(size_t size) = 0; + virtual void FreeState(void* p) = 0; + }; -/////////////////////////////////////////////////////////////////////////////// -// Hasher + /////////////////////////////////////////////////////////////////////////////// + // Hasher -// For comparison of compound value -template -class Hasher { -public: - typedef typename Encoding::Ch Ch; + // For comparison of compound value + template + class Hasher + { + public: + typedef typename Encoding::Ch Ch; - Hasher(Allocator* allocator = 0, size_t stackCapacity = kDefaultSize) : stack_(allocator, stackCapacity) {} + Hasher(Allocator* allocator = 0, size_t stackCapacity = kDefaultSize) : stack_(allocator, stackCapacity) {} - bool Null() { return WriteType(kNullType); } - bool Bool(bool b) { return WriteType(b ? kTrueType : kFalseType); } - bool Int(int i) { Number n; n.u.i = i; n.d = static_cast(i); return WriteNumber(n); } - bool Uint(unsigned u) { Number n; n.u.u = u; n.d = static_cast(u); return WriteNumber(n); } - bool Int64(int64_t i) { Number n; n.u.i = i; n.d = static_cast(i); return WriteNumber(n); } - bool Uint64(uint64_t u) { Number n; n.u.u = u; n.d = static_cast(u); return WriteNumber(n); } - bool Double(double d) { - Number n; - if (d < 0) n.u.i = static_cast(d); - else n.u.u = static_cast(d); - n.d = d; - return WriteNumber(n); - } + bool Null() + { + return WriteType(kNullType); + } + bool Bool(bool b) + { + return WriteType(b ? kTrueType : kFalseType); + } + bool Int(int i) + { + Number n; + n.u.i = i; + n.d = static_cast(i); + return WriteNumber(n); + } + bool Uint(unsigned u) + { + Number n; + n.u.u = u; + n.d = static_cast(u); + return WriteNumber(n); + } + bool Int64(int64_t i) + { + Number n; + n.u.i = i; + n.d = static_cast(i); + return WriteNumber(n); + } + bool Uint64(uint64_t u) + { + Number n; + n.u.u = u; + n.d = static_cast(u); + return WriteNumber(n); + } + bool Double(double d) + { + Number n; + if(d < 0) + { + n.u.i = static_cast(d); + } + else + { + n.u.u = static_cast(d); + } + n.d = d; + return WriteNumber(n); + } - bool RawNumber(const Ch* str, SizeType len, bool) { - WriteBuffer(kNumberType, str, len * sizeof(Ch)); - return true; - } + bool RawNumber(const Ch* str, SizeType len, bool) + { + WriteBuffer(kNumberType, str, len * sizeof(Ch)); + return true; + } - bool String(const Ch* str, SizeType len, bool) { - WriteBuffer(kStringType, str, len * sizeof(Ch)); - return true; - } + bool String(const Ch* str, SizeType len, bool) + { + WriteBuffer(kStringType, str, len * sizeof(Ch)); + return true; + } - bool StartObject() { return true; } - bool Key(const Ch* str, SizeType len, bool copy) { return String(str, len, copy); } - bool EndObject(SizeType memberCount) { - uint64_t h = Hash(0, kObjectType); - uint64_t* kv = stack_.template Pop(memberCount * 2); - for (SizeType i = 0; i < memberCount; i++) - h ^= Hash(kv[i * 2], kv[i * 2 + 1]); // Use xor to achieve member order insensitive - *stack_.template Push() = h; - return true; - } - - bool StartArray() { return true; } - bool EndArray(SizeType elementCount) { - uint64_t h = Hash(0, kArrayType); - uint64_t* e = stack_.template Pop(elementCount); - for (SizeType i = 0; i < elementCount; i++) - h = Hash(h, e[i]); // Use hash to achieve element order sensitive - *stack_.template Push() = h; - return true; - } + bool StartObject() + { + return true; + } + bool Key(const Ch* str, SizeType len, bool copy) + { + return String(str, len, copy); + } + bool EndObject(SizeType memberCount) + { + uint64_t h = Hash(0, kObjectType); + uint64_t* kv = stack_.template Pop(memberCount * 2); + for(SizeType i = 0; i < memberCount; i++) + { + h ^= Hash(kv[i * 2], kv[i * 2 + 1]); // Use xor to achieve member order insensitive + } + *stack_.template Push() = h; + return true; + } - bool IsValid() const { return stack_.GetSize() == sizeof(uint64_t); } + bool StartArray() + { + return true; + } + bool EndArray(SizeType elementCount) + { + uint64_t h = Hash(0, kArrayType); + uint64_t* e = stack_.template Pop(elementCount); + for(SizeType i = 0; i < elementCount; i++) + { + h = Hash(h, e[i]); // Use hash to achieve element order sensitive + } + *stack_.template Push() = h; + return true; + } - uint64_t GetHashCode() const { - RAPIDJSON_ASSERT(IsValid()); - return *stack_.template Top(); - } + bool IsValid() const + { + return stack_.GetSize() == sizeof(uint64_t); + } -private: - static const size_t kDefaultSize = 256; - struct Number { - union U { - uint64_t u; - int64_t i; - }u; - double d; - }; + uint64_t GetHashCode() const + { + RAPIDJSON_ASSERT(IsValid()); + return *stack_.template Top(); + } - bool WriteType(Type type) { return WriteBuffer(type, 0, 0); } - - bool WriteNumber(const Number& n) { return WriteBuffer(kNumberType, &n, sizeof(n)); } - - bool WriteBuffer(Type type, const void* data, size_t len) { - // FNV-1a from http://isthe.com/chongo/tech/comp/fnv/ - uint64_t h = Hash(RAPIDJSON_UINT64_C2(0x84222325, 0xcbf29ce4), type); - const unsigned char* d = static_cast(data); - for (size_t i = 0; i < len; i++) - h = Hash(h, d[i]); - *stack_.template Push() = h; - return true; - } + private: + static const size_t kDefaultSize = 256; + struct Number + { + union U + { + uint64_t u; + int64_t i; + } u; + double d; + }; - static uint64_t Hash(uint64_t h, uint64_t d) { - static const uint64_t kPrime = RAPIDJSON_UINT64_C2(0x00000100, 0x000001b3); - h ^= d; - h *= kPrime; - return h; - } + bool WriteType(Type type) + { + return WriteBuffer(type, 0, 0); + } - Stack stack_; -}; + bool WriteNumber(const Number & n) + { + return WriteBuffer(kNumberType, &n, sizeof(n)); + } -/////////////////////////////////////////////////////////////////////////////// -// SchemaValidationContext + bool WriteBuffer(Type type, const void* data, size_t len) + { + // FNV-1a from http://isthe.com/chongo/tech/comp/fnv/ + uint64_t h = Hash(RAPIDJSON_UINT64_C2(0x84222325, 0xcbf29ce4), type); + const unsigned char* d = static_cast(data); + for(size_t i = 0; i < len; i++) + { + h = Hash(h, d[i]); + } + *stack_.template Push() = h; + return true; + } -template -struct SchemaValidationContext { - typedef Schema SchemaType; - typedef ISchemaStateFactory SchemaValidatorFactoryType; - typedef typename SchemaType::ValueType ValueType; - typedef typename ValueType::Ch Ch; + static uint64_t Hash(uint64_t h, uint64_t d) + { + static const uint64_t kPrime = RAPIDJSON_UINT64_C2(0x00000100, 0x000001b3); + h ^= d; + h *= kPrime; + return h; + } - enum PatternValidatorType { - kPatternValidatorOnly, - kPatternValidatorWithProperty, - kPatternValidatorWithAdditionalProperty - }; + Stack stack_; + }; - SchemaValidationContext(SchemaValidatorFactoryType& f, const SchemaType* s) : - factory(f), - schema(s), - valueSchema(), - invalidKeyword(), - hasher(), - arrayElementHashCodes(), - validators(), - validatorCount(), - patternPropertiesValidators(), - patternPropertiesValidatorCount(), - patternPropertiesSchemas(), - patternPropertiesSchemaCount(), - valuePatternValidatorType(kPatternValidatorOnly), - propertyExist(), - inArray(false), - valueUniqueness(false), - arrayUniqueness(false) - { - } + /////////////////////////////////////////////////////////////////////////////// + // SchemaValidationContext - ~SchemaValidationContext() { - if (hasher) - factory.DestroryHasher(hasher); - if (validators) { - for (SizeType i = 0; i < validatorCount; i++) - factory.DestroySchemaValidator(validators[i]); - factory.FreeState(validators); - } - if (patternPropertiesValidators) { - for (SizeType i = 0; i < patternPropertiesValidatorCount; i++) - factory.DestroySchemaValidator(patternPropertiesValidators[i]); - factory.FreeState(patternPropertiesValidators); - } - if (patternPropertiesSchemas) - factory.FreeState(patternPropertiesSchemas); - if (propertyExist) - factory.FreeState(propertyExist); - } + template + struct SchemaValidationContext + { + typedef Schema SchemaType; + typedef ISchemaStateFactory SchemaValidatorFactoryType; + typedef typename SchemaType::ValueType ValueType; + typedef typename ValueType::Ch Ch; - SchemaValidatorFactoryType& factory; - const SchemaType* schema; - const SchemaType* valueSchema; - const Ch* invalidKeyword; - void* hasher; // Only validator access - void* arrayElementHashCodes; // Only validator access this - ISchemaValidator** validators; - SizeType validatorCount; - ISchemaValidator** patternPropertiesValidators; - SizeType patternPropertiesValidatorCount; - const SchemaType** patternPropertiesSchemas; - SizeType patternPropertiesSchemaCount; - PatternValidatorType valuePatternValidatorType; - PatternValidatorType objectPatternValidatorType; - SizeType arrayElementIndex; - bool* propertyExist; - bool inArray; - bool valueUniqueness; - bool arrayUniqueness; -}; + enum PatternValidatorType + { + kPatternValidatorOnly, + kPatternValidatorWithProperty, + kPatternValidatorWithAdditionalProperty + }; -/////////////////////////////////////////////////////////////////////////////// -// Schema + SchemaValidationContext(SchemaValidatorFactoryType & f, const SchemaType* s) : + factory(f), + schema(s), + valueSchema(), + invalidKeyword(), + hasher(), + arrayElementHashCodes(), + validators(), + validatorCount(), + patternPropertiesValidators(), + patternPropertiesValidatorCount(), + patternPropertiesSchemas(), + patternPropertiesSchemaCount(), + valuePatternValidatorType(kPatternValidatorOnly), + propertyExist(), + inArray(false), + valueUniqueness(false), + arrayUniqueness(false) + { + } -template -class Schema { -public: - typedef typename SchemaDocumentType::ValueType ValueType; - typedef typename SchemaDocumentType::AllocatorType AllocatorType; - typedef typename SchemaDocumentType::PointerType PointerType; - typedef typename ValueType::EncodingType EncodingType; - typedef typename EncodingType::Ch Ch; - typedef SchemaValidationContext Context; - typedef Schema SchemaType; - typedef GenericValue SValue; - friend class GenericSchemaDocument; + ~SchemaValidationContext() + { + if(hasher) + { + factory.DestroryHasher(hasher); + } + if(validators) + { + for(SizeType i = 0; i < validatorCount; i++) + { + factory.DestroySchemaValidator(validators[i]); + } + factory.FreeState(validators); + } + if(patternPropertiesValidators) + { + for(SizeType i = 0; i < patternPropertiesValidatorCount; i++) + { + factory.DestroySchemaValidator(patternPropertiesValidators[i]); + } + factory.FreeState(patternPropertiesValidators); + } + if(patternPropertiesSchemas) + { + factory.FreeState(patternPropertiesSchemas); + } + if(propertyExist) + { + factory.FreeState(propertyExist); + } + } - Schema(SchemaDocumentType* schemaDocument, const PointerType& p, const ValueType& value, const ValueType& document, AllocatorType* allocator) : - allocator_(allocator), - enum_(), - enumCount_(), - not_(), - type_((1 << kTotalSchemaType) - 1), // typeless - validatorCount_(), - properties_(), - additionalPropertiesSchema_(), - patternProperties_(), - patternPropertyCount_(), - propertyCount_(), - minProperties_(), - maxProperties_(SizeType(~0)), - additionalProperties_(true), - hasDependencies_(), - hasRequired_(), - hasSchemaDependencies_(), - additionalItemsSchema_(), - itemsList_(), - itemsTuple_(), - itemsTupleCount_(), - minItems_(), - maxItems_(SizeType(~0)), - additionalItems_(true), - uniqueItems_(false), - pattern_(), - minLength_(0), - maxLength_(~SizeType(0)), - exclusiveMinimum_(false), - exclusiveMaximum_(false) - { - typedef typename SchemaDocumentType::ValueType ValueType; - typedef typename ValueType::ConstValueIterator ConstValueIterator; - typedef typename ValueType::ConstMemberIterator ConstMemberIterator; + SchemaValidatorFactoryType & factory; + const SchemaType* schema; + const SchemaType* valueSchema; + const Ch* invalidKeyword; + void* hasher; // Only validator access + void* arrayElementHashCodes; // Only validator access this + ISchemaValidator** validators; + SizeType validatorCount; + ISchemaValidator** patternPropertiesValidators; + SizeType patternPropertiesValidatorCount; + const SchemaType** patternPropertiesSchemas; + SizeType patternPropertiesSchemaCount; + PatternValidatorType valuePatternValidatorType; + PatternValidatorType objectPatternValidatorType; + SizeType arrayElementIndex; + bool* propertyExist; + bool inArray; + bool valueUniqueness; + bool arrayUniqueness; + }; - if (!value.IsObject()) - return; + /////////////////////////////////////////////////////////////////////////////// + // Schema - if (const ValueType* v = GetMember(value, GetTypeString())) { - type_ = 0; - if (v->IsString()) - AddType(*v); - else if (v->IsArray()) - for (ConstValueIterator itr = v->Begin(); itr != v->End(); ++itr) - AddType(*itr); - } + template + class Schema + { + public: + typedef typename SchemaDocumentType::ValueType ValueType; + typedef typename SchemaDocumentType::AllocatorType AllocatorType; + typedef typename SchemaDocumentType::PointerType PointerType; + typedef typename ValueType::EncodingType EncodingType; + typedef typename EncodingType::Ch Ch; + typedef SchemaValidationContext Context; + typedef Schema SchemaType; + typedef GenericValue SValue; + friend class GenericSchemaDocument; - if (const ValueType* v = GetMember(value, GetEnumString())) - if (v->IsArray() && v->Size() > 0) { - enum_ = static_cast(allocator_->Malloc(sizeof(uint64_t) * v->Size())); - for (ConstValueIterator itr = v->Begin(); itr != v->End(); ++itr) { - typedef Hasher > EnumHasherType; - char buffer[256 + 24]; - MemoryPoolAllocator<> hasherAllocator(buffer, sizeof(buffer)); - EnumHasherType h(&hasherAllocator, 256); - itr->Accept(h); - enum_[enumCount_++] = h.GetHashCode(); - } - } + Schema(SchemaDocumentType* schemaDocument, const PointerType & p, const ValueType & value, + const ValueType & document, AllocatorType* allocator) : + allocator_(allocator), + enum_(), + enumCount_(), + not_(), + type_((1 << kTotalSchemaType) - 1), // typeless + validatorCount_(), + properties_(), + additionalPropertiesSchema_(), + patternProperties_(), + patternPropertyCount_(), + propertyCount_(), + minProperties_(), + maxProperties_(SizeType(~0)), + additionalProperties_(true), + hasDependencies_(), + hasRequired_(), + hasSchemaDependencies_(), + additionalItemsSchema_(), + itemsList_(), + itemsTuple_(), + itemsTupleCount_(), + minItems_(), + maxItems_(SizeType(~0)), + additionalItems_(true), + uniqueItems_(false), + pattern_(), + minLength_(0), + maxLength_(~SizeType(0)), + exclusiveMinimum_(false), + exclusiveMaximum_(false) + { + typedef typename SchemaDocumentType::ValueType ValueType; + typedef typename ValueType::ConstValueIterator ConstValueIterator; + typedef typename ValueType::ConstMemberIterator ConstMemberIterator; - if (schemaDocument) { - AssignIfExist(allOf_, *schemaDocument, p, value, GetAllOfString(), document); - AssignIfExist(anyOf_, *schemaDocument, p, value, GetAnyOfString(), document); - AssignIfExist(oneOf_, *schemaDocument, p, value, GetOneOfString(), document); - } + if(!value.IsObject()) + { + return; + } - if (const ValueType* v = GetMember(value, GetNotString())) { - schemaDocument->CreateSchema(¬_, p.Append(GetNotString(), allocator_), *v, document); - notValidatorIndex_ = validatorCount_; - validatorCount_++; - } + if(const ValueType* v = GetMember(value, GetTypeString())) + { + type_ = 0; + if(v->IsString()) + { + AddType(*v); + } + else if(v->IsArray()) + for(ConstValueIterator itr = v->Begin(); itr != v->End(); ++itr) + { + AddType(*itr); + } + } - // Object + if(const ValueType* v = GetMember(value, GetEnumString())) + if(v->IsArray() && v->Size() > 0) + { + enum_ = static_cast(allocator_->Malloc(sizeof(uint64_t) * v->Size())); + for(ConstValueIterator itr = v->Begin(); itr != v->End(); ++itr) + { + typedef Hasher> EnumHasherType; + char buffer[256 + 24]; + MemoryPoolAllocator<> hasherAllocator(buffer, sizeof(buffer)); + EnumHasherType h(&hasherAllocator, 256); + itr->Accept(h); + enum_[enumCount_++] = h.GetHashCode(); + } + } - const ValueType* properties = GetMember(value, GetPropertiesString()); - const ValueType* required = GetMember(value, GetRequiredString()); - const ValueType* dependencies = GetMember(value, GetDependenciesString()); - { - // Gather properties from properties/required/dependencies - SValue allProperties(kArrayType); + if(schemaDocument) + { + AssignIfExist(allOf_, *schemaDocument, p, value, GetAllOfString(), document); + AssignIfExist(anyOf_, *schemaDocument, p, value, GetAnyOfString(), document); + AssignIfExist(oneOf_, *schemaDocument, p, value, GetOneOfString(), document); + } - if (properties && properties->IsObject()) - for (ConstMemberIterator itr = properties->MemberBegin(); itr != properties->MemberEnd(); ++itr) - AddUniqueElement(allProperties, itr->name); - - if (required && required->IsArray()) - for (ConstValueIterator itr = required->Begin(); itr != required->End(); ++itr) - if (itr->IsString()) - AddUniqueElement(allProperties, *itr); + if(const ValueType* v = GetMember(value, GetNotString())) + { + schemaDocument->CreateSchema(¬_, p.Append(GetNotString(), allocator_), *v, document); + notValidatorIndex_ = validatorCount_; + validatorCount_++; + } - if (dependencies && dependencies->IsObject()) - for (ConstMemberIterator itr = dependencies->MemberBegin(); itr != dependencies->MemberEnd(); ++itr) { - AddUniqueElement(allProperties, itr->name); - if (itr->value.IsArray()) - for (ConstValueIterator i = itr->value.Begin(); i != itr->value.End(); ++i) - if (i->IsString()) - AddUniqueElement(allProperties, *i); - } + // Object - if (allProperties.Size() > 0) { - propertyCount_ = allProperties.Size(); - properties_ = static_cast(allocator_->Malloc(sizeof(Property) * propertyCount_)); - for (SizeType i = 0; i < propertyCount_; i++) { - new (&properties_[i]) Property(); - properties_[i].name = allProperties[i]; - properties_[i].schema = GetTypeless(); - } - } - } + const ValueType* properties = GetMember(value, GetPropertiesString()); + const ValueType* required = GetMember(value, GetRequiredString()); + const ValueType* dependencies = GetMember(value, GetDependenciesString()); + { + // Gather properties from properties/required/dependencies + SValue allProperties(kArrayType); - if (properties && properties->IsObject()) { - PointerType q = p.Append(GetPropertiesString(), allocator_); - for (ConstMemberIterator itr = properties->MemberBegin(); itr != properties->MemberEnd(); ++itr) { - SizeType index; - if (FindPropertyIndex(itr->name, &index)) - schemaDocument->CreateSchema(&properties_[index].schema, q.Append(itr->name, allocator_), itr->value, document); - } - } + if(properties && properties->IsObject()) + for(ConstMemberIterator itr = properties->MemberBegin(); itr != properties->MemberEnd(); ++itr) + { + AddUniqueElement(allProperties, itr->name); + } - if (const ValueType* v = GetMember(value, GetPatternPropertiesString())) { - PointerType q = p.Append(GetPatternPropertiesString(), allocator_); - patternProperties_ = static_cast(allocator_->Malloc(sizeof(PatternProperty) * v->MemberCount())); - patternPropertyCount_ = 0; + if(required && required->IsArray()) + for(ConstValueIterator itr = required->Begin(); itr != required->End(); ++itr) + if(itr->IsString()) + { + AddUniqueElement(allProperties, *itr); + } - for (ConstMemberIterator itr = v->MemberBegin(); itr != v->MemberEnd(); ++itr) { - new (&patternProperties_[patternPropertyCount_]) PatternProperty(); - patternProperties_[patternPropertyCount_].pattern = CreatePattern(itr->name); - schemaDocument->CreateSchema(&patternProperties_[patternPropertyCount_].schema, q.Append(itr->name, allocator_), itr->value, document); - patternPropertyCount_++; - } - } + if(dependencies && dependencies->IsObject()) + for(ConstMemberIterator itr = dependencies->MemberBegin(); itr != dependencies->MemberEnd(); ++itr) + { + AddUniqueElement(allProperties, itr->name); + if(itr->value.IsArray()) + for(ConstValueIterator i = itr->value.Begin(); i != itr->value.End(); ++i) + if(i->IsString()) + { + AddUniqueElement(allProperties, *i); + } + } - if (required && required->IsArray()) - for (ConstValueIterator itr = required->Begin(); itr != required->End(); ++itr) - if (itr->IsString()) { - SizeType index; - if (FindPropertyIndex(*itr, &index)) { - properties_[index].required = true; - hasRequired_ = true; - } - } + if(allProperties.Size() > 0) + { + propertyCount_ = allProperties.Size(); + properties_ = static_cast(allocator_->Malloc(sizeof(Property) * propertyCount_)); + for(SizeType i = 0; i < propertyCount_; i++) + { + new(&properties_[i]) Property(); + properties_[i].name = allProperties[i]; + properties_[i].schema = GetTypeless(); + } + } + } - if (dependencies && dependencies->IsObject()) { - PointerType q = p.Append(GetDependenciesString(), allocator_); - hasDependencies_ = true; - for (ConstMemberIterator itr = dependencies->MemberBegin(); itr != dependencies->MemberEnd(); ++itr) { - SizeType sourceIndex; - if (FindPropertyIndex(itr->name, &sourceIndex)) { - if (itr->value.IsArray()) { - properties_[sourceIndex].dependencies = static_cast(allocator_->Malloc(sizeof(bool) * propertyCount_)); - std::memset(properties_[sourceIndex].dependencies, 0, sizeof(bool)* propertyCount_); - for (ConstValueIterator targetItr = itr->value.Begin(); targetItr != itr->value.End(); ++targetItr) { - SizeType targetIndex; - if (FindPropertyIndex(*targetItr, &targetIndex)) - properties_[sourceIndex].dependencies[targetIndex] = true; - } - } - else if (itr->value.IsObject()) { - hasSchemaDependencies_ = true; - schemaDocument->CreateSchema(&properties_[sourceIndex].dependenciesSchema, q.Append(itr->name, allocator_), itr->value, document); - properties_[sourceIndex].dependenciesValidatorIndex = validatorCount_; - validatorCount_++; - } - } - } - } + if(properties && properties->IsObject()) + { + PointerType q = p.Append(GetPropertiesString(), allocator_); + for(ConstMemberIterator itr = properties->MemberBegin(); itr != properties->MemberEnd(); ++itr) + { + SizeType index; + if(FindPropertyIndex(itr->name, &index)) + { + schemaDocument->CreateSchema(&properties_[index].schema, q.Append(itr->name, allocator_), itr->value, + document); + } + } + } - if (const ValueType* v = GetMember(value, GetAdditionalPropertiesString())) { - if (v->IsBool()) - additionalProperties_ = v->GetBool(); - else if (v->IsObject()) - schemaDocument->CreateSchema(&additionalPropertiesSchema_, p.Append(GetAdditionalPropertiesString(), allocator_), *v, document); - } + if(const ValueType* v = GetMember(value, GetPatternPropertiesString())) + { + PointerType q = p.Append(GetPatternPropertiesString(), allocator_); + patternProperties_ = static_cast(allocator_->Malloc(sizeof(PatternProperty) * + v->MemberCount())); + patternPropertyCount_ = 0; - AssignIfExist(minProperties_, value, GetMinPropertiesString()); - AssignIfExist(maxProperties_, value, GetMaxPropertiesString()); + for(ConstMemberIterator itr = v->MemberBegin(); itr != v->MemberEnd(); ++itr) + { + new(&patternProperties_[patternPropertyCount_]) PatternProperty(); + patternProperties_[patternPropertyCount_].pattern = CreatePattern(itr->name); + schemaDocument->CreateSchema(&patternProperties_[patternPropertyCount_].schema, q.Append(itr->name, + allocator_), itr->value, document); + patternPropertyCount_++; + } + } - // Array - if (const ValueType* v = GetMember(value, GetItemsString())) { - PointerType q = p.Append(GetItemsString(), allocator_); - if (v->IsObject()) // List validation - schemaDocument->CreateSchema(&itemsList_, q, *v, document); - else if (v->IsArray()) { // Tuple validation - itemsTuple_ = static_cast(allocator_->Malloc(sizeof(const Schema*) * v->Size())); - SizeType index = 0; - for (ConstValueIterator itr = v->Begin(); itr != v->End(); ++itr, index++) - schemaDocument->CreateSchema(&itemsTuple_[itemsTupleCount_++], q.Append(index, allocator_), *itr, document); - } - } + if(required && required->IsArray()) + for(ConstValueIterator itr = required->Begin(); itr != required->End(); ++itr) + if(itr->IsString()) + { + SizeType index; + if(FindPropertyIndex(*itr, &index)) + { + properties_[index].required = true; + hasRequired_ = true; + } + } - AssignIfExist(minItems_, value, GetMinItemsString()); - AssignIfExist(maxItems_, value, GetMaxItemsString()); + if(dependencies && dependencies->IsObject()) + { + PointerType q = p.Append(GetDependenciesString(), allocator_); + hasDependencies_ = true; + for(ConstMemberIterator itr = dependencies->MemberBegin(); itr != dependencies->MemberEnd(); ++itr) + { + SizeType sourceIndex; + if(FindPropertyIndex(itr->name, &sourceIndex)) + { + if(itr->value.IsArray()) + { + properties_[sourceIndex].dependencies = static_cast(allocator_->Malloc(sizeof(bool) * propertyCount_)); + std::memset(properties_[sourceIndex].dependencies, 0, sizeof(bool)* propertyCount_); + for(ConstValueIterator targetItr = itr->value.Begin(); targetItr != itr->value.End(); ++targetItr) + { + SizeType targetIndex; + if(FindPropertyIndex(*targetItr, &targetIndex)) + { + properties_[sourceIndex].dependencies[targetIndex] = true; + } + } + } + else if(itr->value.IsObject()) + { + hasSchemaDependencies_ = true; + schemaDocument->CreateSchema(&properties_[sourceIndex].dependenciesSchema, q.Append(itr->name, allocator_), + itr->value, document); + properties_[sourceIndex].dependenciesValidatorIndex = validatorCount_; + validatorCount_++; + } + } + } + } - if (const ValueType* v = GetMember(value, GetAdditionalItemsString())) { - if (v->IsBool()) - additionalItems_ = v->GetBool(); - else if (v->IsObject()) - schemaDocument->CreateSchema(&additionalItemsSchema_, p.Append(GetAdditionalItemsString(), allocator_), *v, document); - } + if(const ValueType* v = GetMember(value, GetAdditionalPropertiesString())) + { + if(v->IsBool()) + { + additionalProperties_ = v->GetBool(); + } + else if(v->IsObject()) + { + schemaDocument->CreateSchema(&additionalPropertiesSchema_, p.Append(GetAdditionalPropertiesString(), + allocator_), *v, document); + } + } - AssignIfExist(uniqueItems_, value, GetUniqueItemsString()); + AssignIfExist(minProperties_, value, GetMinPropertiesString()); + AssignIfExist(maxProperties_, value, GetMaxPropertiesString()); - // String - AssignIfExist(minLength_, value, GetMinLengthString()); - AssignIfExist(maxLength_, value, GetMaxLengthString()); + // Array + if(const ValueType* v = GetMember(value, GetItemsString())) + { + PointerType q = p.Append(GetItemsString(), allocator_); + if(v->IsObject()) // List validation + { + schemaDocument->CreateSchema(&itemsList_, q, *v, document); + } + else if(v->IsArray()) // Tuple validation + { + itemsTuple_ = static_cast(allocator_->Malloc(sizeof(const Schema*) * v->Size())); + SizeType index = 0; + for(ConstValueIterator itr = v->Begin(); itr != v->End(); ++itr, index++) + { + schemaDocument->CreateSchema(&itemsTuple_[itemsTupleCount_++], q.Append(index, allocator_), *itr, document); + } + } + } - if (const ValueType* v = GetMember(value, GetPatternString())) - pattern_ = CreatePattern(*v); + AssignIfExist(minItems_, value, GetMinItemsString()); + AssignIfExist(maxItems_, value, GetMaxItemsString()); - // Number - if (const ValueType* v = GetMember(value, GetMinimumString())) - if (v->IsNumber()) - minimum_.CopyFrom(*v, *allocator_); + if(const ValueType* v = GetMember(value, GetAdditionalItemsString())) + { + if(v->IsBool()) + { + additionalItems_ = v->GetBool(); + } + else if(v->IsObject()) + { + schemaDocument->CreateSchema(&additionalItemsSchema_, p.Append(GetAdditionalItemsString(), allocator_), *v, + document); + } + } - if (const ValueType* v = GetMember(value, GetMaximumString())) - if (v->IsNumber()) - maximum_.CopyFrom(*v, *allocator_); + AssignIfExist(uniqueItems_, value, GetUniqueItemsString()); - AssignIfExist(exclusiveMinimum_, value, GetExclusiveMinimumString()); - AssignIfExist(exclusiveMaximum_, value, GetExclusiveMaximumString()); + // String + AssignIfExist(minLength_, value, GetMinLengthString()); + AssignIfExist(maxLength_, value, GetMaxLengthString()); - if (const ValueType* v = GetMember(value, GetMultipleOfString())) - if (v->IsNumber() && v->GetDouble() > 0.0) - multipleOf_.CopyFrom(*v, *allocator_); - } + if(const ValueType* v = GetMember(value, GetPatternString())) + { + pattern_ = CreatePattern(*v); + } - ~Schema() { - if (allocator_) { - allocator_->Free(enum_); - } - if (properties_) { - for (SizeType i = 0; i < propertyCount_; i++) - properties_[i].~Property(); - AllocatorType::Free(properties_); - } - if (patternProperties_) { - for (SizeType i = 0; i < patternPropertyCount_; i++) - patternProperties_[i].~PatternProperty(); - AllocatorType::Free(patternProperties_); - } - AllocatorType::Free(itemsTuple_); + // Number + if(const ValueType* v = GetMember(value, GetMinimumString())) + if(v->IsNumber()) + { + minimum_.CopyFrom(*v, *allocator_); + } + + if(const ValueType* v = GetMember(value, GetMaximumString())) + if(v->IsNumber()) + { + maximum_.CopyFrom(*v, *allocator_); + } + + AssignIfExist(exclusiveMinimum_, value, GetExclusiveMinimumString()); + AssignIfExist(exclusiveMaximum_, value, GetExclusiveMaximumString()); + + if(const ValueType* v = GetMember(value, GetMultipleOfString())) + if(v->IsNumber() && v->GetDouble() > 0.0) + { + multipleOf_.CopyFrom(*v, *allocator_); + } + } + + ~Schema() + { + if(allocator_) + { + allocator_->Free(enum_); + } + if(properties_) + { + for(SizeType i = 0; i < propertyCount_; i++) + { + properties_[i].~Property(); + } + AllocatorType::Free(properties_); + } + if(patternProperties_) + { + for(SizeType i = 0; i < patternPropertyCount_; i++) + { + patternProperties_[i].~PatternProperty(); + } + AllocatorType::Free(patternProperties_); + } + AllocatorType::Free(itemsTuple_); #if RAPIDJSON_SCHEMA_HAS_REGEX - if (pattern_) { - pattern_->~RegexType(); - allocator_->Free(pattern_); - } + if(pattern_) + { + pattern_->~RegexType(); + allocator_->Free(pattern_); + } #endif - } + } - bool BeginValue(Context& context) const { - if (context.inArray) { - if (uniqueItems_) - context.valueUniqueness = true; + bool BeginValue(Context & context) const + { + if(context.inArray) + { + if(uniqueItems_) + { + context.valueUniqueness = true; + } - if (itemsList_) - context.valueSchema = itemsList_; - else if (itemsTuple_) { - if (context.arrayElementIndex < itemsTupleCount_) - context.valueSchema = itemsTuple_[context.arrayElementIndex]; - else if (additionalItemsSchema_) - context.valueSchema = additionalItemsSchema_; - else if (additionalItems_) - context.valueSchema = GetTypeless(); - else - RAPIDJSON_INVALID_KEYWORD_RETURN(GetItemsString()); - } - else - context.valueSchema = GetTypeless(); + if(itemsList_) + { + context.valueSchema = itemsList_; + } + else if(itemsTuple_) + { + if(context.arrayElementIndex < itemsTupleCount_) + { + context.valueSchema = itemsTuple_[context.arrayElementIndex]; + } + else if(additionalItemsSchema_) + { + context.valueSchema = additionalItemsSchema_; + } + else if(additionalItems_) + { + context.valueSchema = GetTypeless(); + } + else + { + RAPIDJSON_INVALID_KEYWORD_RETURN(GetItemsString()); + } + } + else + { + context.valueSchema = GetTypeless(); + } - context.arrayElementIndex++; - } - return true; - } + context.arrayElementIndex++; + } + return true; + } - RAPIDJSON_FORCEINLINE bool EndValue(Context& context) const { - if (context.patternPropertiesValidatorCount > 0) { - bool otherValid = false; - SizeType count = context.patternPropertiesValidatorCount; - if (context.objectPatternValidatorType != Context::kPatternValidatorOnly) - otherValid = context.patternPropertiesValidators[--count]->IsValid(); + RAPIDJSON_FORCEINLINE bool EndValue(Context & context) const + { + if(context.patternPropertiesValidatorCount > 0) + { + bool otherValid = false; + SizeType count = context.patternPropertiesValidatorCount; + if(context.objectPatternValidatorType != Context::kPatternValidatorOnly) + { + otherValid = context.patternPropertiesValidators[--count]->IsValid(); + } - bool patternValid = true; - for (SizeType i = 0; i < count; i++) - if (!context.patternPropertiesValidators[i]->IsValid()) { - patternValid = false; - break; - } + bool patternValid = true; + for(SizeType i = 0; i < count; i++) + if(!context.patternPropertiesValidators[i]->IsValid()) + { + patternValid = false; + break; + } - if (context.objectPatternValidatorType == Context::kPatternValidatorOnly) { - if (!patternValid) - RAPIDJSON_INVALID_KEYWORD_RETURN(GetPatternPropertiesString()); - } - else if (context.objectPatternValidatorType == Context::kPatternValidatorWithProperty) { - if (!patternValid || !otherValid) - RAPIDJSON_INVALID_KEYWORD_RETURN(GetPatternPropertiesString()); - } - else if (!patternValid && !otherValid) // kPatternValidatorWithAdditionalProperty) - RAPIDJSON_INVALID_KEYWORD_RETURN(GetPatternPropertiesString()); - } + if(context.objectPatternValidatorType == Context::kPatternValidatorOnly) + { + if(!patternValid) + { + RAPIDJSON_INVALID_KEYWORD_RETURN(GetPatternPropertiesString()); + } + } + else if(context.objectPatternValidatorType == Context::kPatternValidatorWithProperty) + { + if(!patternValid || !otherValid) + { + RAPIDJSON_INVALID_KEYWORD_RETURN(GetPatternPropertiesString()); + } + } + else if(!patternValid && !otherValid) // kPatternValidatorWithAdditionalProperty) + { + RAPIDJSON_INVALID_KEYWORD_RETURN(GetPatternPropertiesString()); + } + } - if (enum_) { - const uint64_t h = context.factory.GetHashCode(context.hasher); - for (SizeType i = 0; i < enumCount_; i++) - if (enum_[i] == h) - goto foundEnum; - RAPIDJSON_INVALID_KEYWORD_RETURN(GetEnumString()); - foundEnum:; - } + if(enum_) + { + const uint64_t h = context.factory.GetHashCode(context.hasher); + for(SizeType i = 0; i < enumCount_; i++) + if(enum_[i] == h) + { + goto foundEnum; + } + RAPIDJSON_INVALID_KEYWORD_RETURN(GetEnumString()); +foundEnum: + ; + } - if (allOf_.schemas) - for (SizeType i = allOf_.begin; i < allOf_.begin + allOf_.count; i++) - if (!context.validators[i]->IsValid()) - RAPIDJSON_INVALID_KEYWORD_RETURN(GetAllOfString()); - - if (anyOf_.schemas) { - for (SizeType i = anyOf_.begin; i < anyOf_.begin + anyOf_.count; i++) - if (context.validators[i]->IsValid()) - goto foundAny; - RAPIDJSON_INVALID_KEYWORD_RETURN(GetAnyOfString()); - foundAny:; - } + if(allOf_.schemas) + for(SizeType i = allOf_.begin; i < allOf_.begin + allOf_.count; i++) + if(!context.validators[i]->IsValid()) + { + RAPIDJSON_INVALID_KEYWORD_RETURN(GetAllOfString()); + } - if (oneOf_.schemas) { - bool oneValid = false; - for (SizeType i = oneOf_.begin; i < oneOf_.begin + oneOf_.count; i++) - if (context.validators[i]->IsValid()) { - if (oneValid) - RAPIDJSON_INVALID_KEYWORD_RETURN(GetOneOfString()); - else - oneValid = true; - } - if (!oneValid) - RAPIDJSON_INVALID_KEYWORD_RETURN(GetOneOfString()); - } + if(anyOf_.schemas) + { + for(SizeType i = anyOf_.begin; i < anyOf_.begin + anyOf_.count; i++) + if(context.validators[i]->IsValid()) + { + goto foundAny; + } + RAPIDJSON_INVALID_KEYWORD_RETURN(GetAnyOfString()); +foundAny: + ; + } - if (not_ && context.validators[notValidatorIndex_]->IsValid()) - RAPIDJSON_INVALID_KEYWORD_RETURN(GetNotString()); + if(oneOf_.schemas) + { + bool oneValid = false; + for(SizeType i = oneOf_.begin; i < oneOf_.begin + oneOf_.count; i++) + if(context.validators[i]->IsValid()) + { + if(oneValid) + { + RAPIDJSON_INVALID_KEYWORD_RETURN(GetOneOfString()); + } + else + { + oneValid = true; + } + } + if(!oneValid) + { + RAPIDJSON_INVALID_KEYWORD_RETURN(GetOneOfString()); + } + } - return true; - } + if(not_ && context.validators[notValidatorIndex_]->IsValid()) + { + RAPIDJSON_INVALID_KEYWORD_RETURN(GetNotString()); + } - bool Null(Context& context) const { - if (!(type_ & (1 << kNullSchemaType))) - RAPIDJSON_INVALID_KEYWORD_RETURN(GetTypeString()); - return CreateParallelValidator(context); - } - - bool Bool(Context& context, bool) const { - if (!(type_ & (1 << kBooleanSchemaType))) - RAPIDJSON_INVALID_KEYWORD_RETURN(GetTypeString()); - return CreateParallelValidator(context); - } + return true; + } - bool Int(Context& context, int i) const { - if (!CheckInt(context, i)) - return false; - return CreateParallelValidator(context); - } + bool Null(Context & context) const + { + if(!(type_ & (1 << kNullSchemaType))) + { + RAPIDJSON_INVALID_KEYWORD_RETURN(GetTypeString()); + } + return CreateParallelValidator(context); + } - bool Uint(Context& context, unsigned u) const { - if (!CheckUint(context, u)) - return false; - return CreateParallelValidator(context); - } + bool Bool(Context & context, bool) const + { + if(!(type_ & (1 << kBooleanSchemaType))) + { + RAPIDJSON_INVALID_KEYWORD_RETURN(GetTypeString()); + } + return CreateParallelValidator(context); + } - bool Int64(Context& context, int64_t i) const { - if (!CheckInt(context, i)) - return false; - return CreateParallelValidator(context); - } + bool Int(Context & context, int i) const + { + if(!CheckInt(context, i)) + { + return false; + } + return CreateParallelValidator(context); + } - bool Uint64(Context& context, uint64_t u) const { - if (!CheckUint(context, u)) - return false; - return CreateParallelValidator(context); - } + bool Uint(Context & context, unsigned u) const + { + if(!CheckUint(context, u)) + { + return false; + } + return CreateParallelValidator(context); + } - bool Double(Context& context, double d) const { - if (!(type_ & (1 << kNumberSchemaType))) - RAPIDJSON_INVALID_KEYWORD_RETURN(GetTypeString()); + bool Int64(Context & context, int64_t i) const + { + if(!CheckInt(context, i)) + { + return false; + } + return CreateParallelValidator(context); + } - if (!minimum_.IsNull() && !CheckDoubleMinimum(context, d)) - return false; + bool Uint64(Context & context, uint64_t u) const + { + if(!CheckUint(context, u)) + { + return false; + } + return CreateParallelValidator(context); + } - if (!maximum_.IsNull() && !CheckDoubleMaximum(context, d)) - return false; - - if (!multipleOf_.IsNull() && !CheckDoubleMultipleOf(context, d)) - return false; - - return CreateParallelValidator(context); - } - - bool String(Context& context, const Ch* str, SizeType length, bool) const { - if (!(type_ & (1 << kStringSchemaType))) - RAPIDJSON_INVALID_KEYWORD_RETURN(GetTypeString()); + bool Double(Context & context, double d) const + { + if(!(type_ & (1 << kNumberSchemaType))) + { + RAPIDJSON_INVALID_KEYWORD_RETURN(GetTypeString()); + } - if (minLength_ != 0 || maxLength_ != SizeType(~0)) { - SizeType count; - if (internal::CountStringCodePoint(str, length, &count)) { - if (count < minLength_) - RAPIDJSON_INVALID_KEYWORD_RETURN(GetMinLengthString()); - if (count > maxLength_) - RAPIDJSON_INVALID_KEYWORD_RETURN(GetMaxLengthString()); - } - } + if(!minimum_.IsNull() && !CheckDoubleMinimum(context, d)) + { + return false; + } - if (pattern_ && !IsPatternMatch(pattern_, str, length)) - RAPIDJSON_INVALID_KEYWORD_RETURN(GetPatternString()); + if(!maximum_.IsNull() && !CheckDoubleMaximum(context, d)) + { + return false; + } - return CreateParallelValidator(context); - } + if(!multipleOf_.IsNull() && !CheckDoubleMultipleOf(context, d)) + { + return false; + } - bool StartObject(Context& context) const { - if (!(type_ & (1 << kObjectSchemaType))) - RAPIDJSON_INVALID_KEYWORD_RETURN(GetTypeString()); + return CreateParallelValidator(context); + } - if (hasDependencies_ || hasRequired_) { - context.propertyExist = static_cast(context.factory.MallocState(sizeof(bool) * propertyCount_)); - std::memset(context.propertyExist, 0, sizeof(bool) * propertyCount_); - } + bool String(Context & context, const Ch* str, SizeType length, bool) const + { + if(!(type_ & (1 << kStringSchemaType))) + { + RAPIDJSON_INVALID_KEYWORD_RETURN(GetTypeString()); + } - if (patternProperties_) { // pre-allocate schema array - SizeType count = patternPropertyCount_ + 1; // extra for valuePatternValidatorType - context.patternPropertiesSchemas = static_cast(context.factory.MallocState(sizeof(const SchemaType*) * count)); - context.patternPropertiesSchemaCount = 0; - std::memset(context.patternPropertiesSchemas, 0, sizeof(SchemaType*) * count); - } + if(minLength_ != 0 || maxLength_ != SizeType(~0)) + { + SizeType count; + if(internal::CountStringCodePoint(str, length, &count)) + { + if(count < minLength_) + { + RAPIDJSON_INVALID_KEYWORD_RETURN(GetMinLengthString()); + } + if(count > maxLength_) + { + RAPIDJSON_INVALID_KEYWORD_RETURN(GetMaxLengthString()); + } + } + } - return CreateParallelValidator(context); - } - - bool Key(Context& context, const Ch* str, SizeType len, bool) const { - if (patternProperties_) { - context.patternPropertiesSchemaCount = 0; - for (SizeType i = 0; i < patternPropertyCount_; i++) - if (patternProperties_[i].pattern && IsPatternMatch(patternProperties_[i].pattern, str, len)) - context.patternPropertiesSchemas[context.patternPropertiesSchemaCount++] = patternProperties_[i].schema; - } + if(pattern_ && !IsPatternMatch(pattern_, str, length)) + { + RAPIDJSON_INVALID_KEYWORD_RETURN(GetPatternString()); + } - SizeType index; - if (FindPropertyIndex(ValueType(str, len).Move(), &index)) { - if (context.patternPropertiesSchemaCount > 0) { - context.patternPropertiesSchemas[context.patternPropertiesSchemaCount++] = properties_[index].schema; - context.valueSchema = GetTypeless(); - context.valuePatternValidatorType = Context::kPatternValidatorWithProperty; - } - else - context.valueSchema = properties_[index].schema; + return CreateParallelValidator(context); + } - if (context.propertyExist) - context.propertyExist[index] = true; + bool StartObject(Context & context) const + { + if(!(type_ & (1 << kObjectSchemaType))) + { + RAPIDJSON_INVALID_KEYWORD_RETURN(GetTypeString()); + } - return true; - } + if(hasDependencies_ || hasRequired_) + { + context.propertyExist = static_cast(context.factory.MallocState(sizeof(bool) * propertyCount_)); + std::memset(context.propertyExist, 0, sizeof(bool) * propertyCount_); + } - if (additionalPropertiesSchema_) { - if (additionalPropertiesSchema_ && context.patternPropertiesSchemaCount > 0) { - context.patternPropertiesSchemas[context.patternPropertiesSchemaCount++] = additionalPropertiesSchema_; - context.valueSchema = GetTypeless(); - context.valuePatternValidatorType = Context::kPatternValidatorWithAdditionalProperty; - } - else - context.valueSchema = additionalPropertiesSchema_; - return true; - } - else if (additionalProperties_) { - context.valueSchema = GetTypeless(); - return true; - } + if(patternProperties_) // pre-allocate schema array + { + SizeType count = patternPropertyCount_ + 1; // extra for valuePatternValidatorType + context.patternPropertiesSchemas = static_cast(context.factory.MallocState(sizeof( + const SchemaType*) * count)); + context.patternPropertiesSchemaCount = 0; + std::memset(context.patternPropertiesSchemas, 0, sizeof(SchemaType*) * count); + } - if (context.patternPropertiesSchemaCount == 0) // patternProperties are not additional properties - RAPIDJSON_INVALID_KEYWORD_RETURN(GetAdditionalPropertiesString()); + return CreateParallelValidator(context); + } - return true; - } + bool Key(Context & context, const Ch* str, SizeType len, bool) const + { + if(patternProperties_) + { + context.patternPropertiesSchemaCount = 0; + for(SizeType i = 0; i < patternPropertyCount_; i++) + if(patternProperties_[i].pattern && IsPatternMatch(patternProperties_[i].pattern, str, len)) + { + context.patternPropertiesSchemas[context.patternPropertiesSchemaCount++] = patternProperties_[i].schema; + } + } - bool EndObject(Context& context, SizeType memberCount) const { - if (hasRequired_) - for (SizeType index = 0; index < propertyCount_; index++) - if (properties_[index].required) - if (!context.propertyExist[index]) - RAPIDJSON_INVALID_KEYWORD_RETURN(GetRequiredString()); + SizeType index; + if(FindPropertyIndex(ValueType(str, len).Move(), &index)) + { + if(context.patternPropertiesSchemaCount > 0) + { + context.patternPropertiesSchemas[context.patternPropertiesSchemaCount++] = properties_[index].schema; + context.valueSchema = GetTypeless(); + context.valuePatternValidatorType = Context::kPatternValidatorWithProperty; + } + else + { + context.valueSchema = properties_[index].schema; + } - if (memberCount < minProperties_) - RAPIDJSON_INVALID_KEYWORD_RETURN(GetMinPropertiesString()); + if(context.propertyExist) + { + context.propertyExist[index] = true; + } - if (memberCount > maxProperties_) - RAPIDJSON_INVALID_KEYWORD_RETURN(GetMaxPropertiesString()); + return true; + } - if (hasDependencies_) { - for (SizeType sourceIndex = 0; sourceIndex < propertyCount_; sourceIndex++) - if (context.propertyExist[sourceIndex]) { - if (properties_[sourceIndex].dependencies) { - for (SizeType targetIndex = 0; targetIndex < propertyCount_; targetIndex++) - if (properties_[sourceIndex].dependencies[targetIndex] && !context.propertyExist[targetIndex]) - RAPIDJSON_INVALID_KEYWORD_RETURN(GetDependenciesString()); - } - else if (properties_[sourceIndex].dependenciesSchema) - if (!context.validators[properties_[sourceIndex].dependenciesValidatorIndex]->IsValid()) - RAPIDJSON_INVALID_KEYWORD_RETURN(GetDependenciesString()); - } - } + if(additionalPropertiesSchema_) + { + if(additionalPropertiesSchema_ && context.patternPropertiesSchemaCount > 0) + { + context.patternPropertiesSchemas[context.patternPropertiesSchemaCount++] = additionalPropertiesSchema_; + context.valueSchema = GetTypeless(); + context.valuePatternValidatorType = Context::kPatternValidatorWithAdditionalProperty; + } + else + { + context.valueSchema = additionalPropertiesSchema_; + } + return true; + } + else if(additionalProperties_) + { + context.valueSchema = GetTypeless(); + return true; + } - return true; - } + if(context.patternPropertiesSchemaCount == 0) // patternProperties are not additional properties + { + RAPIDJSON_INVALID_KEYWORD_RETURN(GetAdditionalPropertiesString()); + } - bool StartArray(Context& context) const { - if (!(type_ & (1 << kArraySchemaType))) - RAPIDJSON_INVALID_KEYWORD_RETURN(GetTypeString()); + return true; + } - context.arrayElementIndex = 0; - context.inArray = true; + bool EndObject(Context & context, SizeType memberCount) const + { + if(hasRequired_) + for(SizeType index = 0; index < propertyCount_; index++) + if(properties_[index].required) + if(!context.propertyExist[index]) + { + RAPIDJSON_INVALID_KEYWORD_RETURN(GetRequiredString()); + } - return CreateParallelValidator(context); - } + if(memberCount < minProperties_) + { + RAPIDJSON_INVALID_KEYWORD_RETURN(GetMinPropertiesString()); + } - bool EndArray(Context& context, SizeType elementCount) const { - context.inArray = false; - - if (elementCount < minItems_) - RAPIDJSON_INVALID_KEYWORD_RETURN(GetMinItemsString()); - - if (elementCount > maxItems_) - RAPIDJSON_INVALID_KEYWORD_RETURN(GetMaxItemsString()); + if(memberCount > maxProperties_) + { + RAPIDJSON_INVALID_KEYWORD_RETURN(GetMaxPropertiesString()); + } - return true; - } + if(hasDependencies_) + { + for(SizeType sourceIndex = 0; sourceIndex < propertyCount_; sourceIndex++) + if(context.propertyExist[sourceIndex]) + { + if(properties_[sourceIndex].dependencies) + { + for(SizeType targetIndex = 0; targetIndex < propertyCount_; targetIndex++) + if(properties_[sourceIndex].dependencies[targetIndex] && !context.propertyExist[targetIndex]) + { + RAPIDJSON_INVALID_KEYWORD_RETURN(GetDependenciesString()); + } + } + else if(properties_[sourceIndex].dependenciesSchema) + if(!context.validators[properties_[sourceIndex].dependenciesValidatorIndex]->IsValid()) + { + RAPIDJSON_INVALID_KEYWORD_RETURN(GetDependenciesString()); + } + } + } - // Generate functions for string literal according to Ch + return true; + } + + bool StartArray(Context & context) const + { + if(!(type_ & (1 << kArraySchemaType))) + { + RAPIDJSON_INVALID_KEYWORD_RETURN(GetTypeString()); + } + + context.arrayElementIndex = 0; + context.inArray = true; + + return CreateParallelValidator(context); + } + + bool EndArray(Context & context, SizeType elementCount) const + { + context.inArray = false; + + if(elementCount < minItems_) + { + RAPIDJSON_INVALID_KEYWORD_RETURN(GetMinItemsString()); + } + + if(elementCount > maxItems_) + { + RAPIDJSON_INVALID_KEYWORD_RETURN(GetMaxItemsString()); + } + + return true; + } + + // Generate functions for string literal according to Ch #define RAPIDJSON_STRING_(name, ...) \ - static const ValueType& Get##name##String() {\ - static const Ch s[] = { __VA_ARGS__, '\0' };\ - static const ValueType v(s, sizeof(s) / sizeof(Ch) - 1);\ - return v;\ - } + static const ValueType& Get##name##String() {\ + static const Ch s[] = { __VA_ARGS__, '\0' };\ + static const ValueType v(s, sizeof(s) / sizeof(Ch) - 1);\ + return v;\ + } - RAPIDJSON_STRING_(Null, 'n', 'u', 'l', 'l') - RAPIDJSON_STRING_(Boolean, 'b', 'o', 'o', 'l', 'e', 'a', 'n') - RAPIDJSON_STRING_(Object, 'o', 'b', 'j', 'e', 'c', 't') - RAPIDJSON_STRING_(Array, 'a', 'r', 'r', 'a', 'y') - RAPIDJSON_STRING_(String, 's', 't', 'r', 'i', 'n', 'g') - RAPIDJSON_STRING_(Number, 'n', 'u', 'm', 'b', 'e', 'r') - RAPIDJSON_STRING_(Integer, 'i', 'n', 't', 'e', 'g', 'e', 'r') - RAPIDJSON_STRING_(Type, 't', 'y', 'p', 'e') - RAPIDJSON_STRING_(Enum, 'e', 'n', 'u', 'm') - RAPIDJSON_STRING_(AllOf, 'a', 'l', 'l', 'O', 'f') - RAPIDJSON_STRING_(AnyOf, 'a', 'n', 'y', 'O', 'f') - RAPIDJSON_STRING_(OneOf, 'o', 'n', 'e', 'O', 'f') - RAPIDJSON_STRING_(Not, 'n', 'o', 't') - RAPIDJSON_STRING_(Properties, 'p', 'r', 'o', 'p', 'e', 'r', 't', 'i', 'e', 's') - RAPIDJSON_STRING_(Required, 'r', 'e', 'q', 'u', 'i', 'r', 'e', 'd') - RAPIDJSON_STRING_(Dependencies, 'd', 'e', 'p', 'e', 'n', 'd', 'e', 'n', 'c', 'i', 'e', 's') - RAPIDJSON_STRING_(PatternProperties, 'p', 'a', 't', 't', 'e', 'r', 'n', 'P', 'r', 'o', 'p', 'e', 'r', 't', 'i', 'e', 's') - RAPIDJSON_STRING_(AdditionalProperties, 'a', 'd', 'd', 'i', 't', 'i', 'o', 'n', 'a', 'l', 'P', 'r', 'o', 'p', 'e', 'r', 't', 'i', 'e', 's') - RAPIDJSON_STRING_(MinProperties, 'm', 'i', 'n', 'P', 'r', 'o', 'p', 'e', 'r', 't', 'i', 'e', 's') - RAPIDJSON_STRING_(MaxProperties, 'm', 'a', 'x', 'P', 'r', 'o', 'p', 'e', 'r', 't', 'i', 'e', 's') - RAPIDJSON_STRING_(Items, 'i', 't', 'e', 'm', 's') - RAPIDJSON_STRING_(MinItems, 'm', 'i', 'n', 'I', 't', 'e', 'm', 's') - RAPIDJSON_STRING_(MaxItems, 'm', 'a', 'x', 'I', 't', 'e', 'm', 's') - RAPIDJSON_STRING_(AdditionalItems, 'a', 'd', 'd', 'i', 't', 'i', 'o', 'n', 'a', 'l', 'I', 't', 'e', 'm', 's') - RAPIDJSON_STRING_(UniqueItems, 'u', 'n', 'i', 'q', 'u', 'e', 'I', 't', 'e', 'm', 's') - RAPIDJSON_STRING_(MinLength, 'm', 'i', 'n', 'L', 'e', 'n', 'g', 't', 'h') - RAPIDJSON_STRING_(MaxLength, 'm', 'a', 'x', 'L', 'e', 'n', 'g', 't', 'h') - RAPIDJSON_STRING_(Pattern, 'p', 'a', 't', 't', 'e', 'r', 'n') - RAPIDJSON_STRING_(Minimum, 'm', 'i', 'n', 'i', 'm', 'u', 'm') - RAPIDJSON_STRING_(Maximum, 'm', 'a', 'x', 'i', 'm', 'u', 'm') - RAPIDJSON_STRING_(ExclusiveMinimum, 'e', 'x', 'c', 'l', 'u', 's', 'i', 'v', 'e', 'M', 'i', 'n', 'i', 'm', 'u', 'm') - RAPIDJSON_STRING_(ExclusiveMaximum, 'e', 'x', 'c', 'l', 'u', 's', 'i', 'v', 'e', 'M', 'a', 'x', 'i', 'm', 'u', 'm') - RAPIDJSON_STRING_(MultipleOf, 'm', 'u', 'l', 't', 'i', 'p', 'l', 'e', 'O', 'f') + RAPIDJSON_STRING_(Null, 'n', 'u', 'l', 'l') + RAPIDJSON_STRING_(Boolean, 'b', 'o', 'o', 'l', 'e', 'a', 'n') + RAPIDJSON_STRING_(Object, 'o', 'b', 'j', 'e', 'c', 't') + RAPIDJSON_STRING_(Array, 'a', 'r', 'r', 'a', 'y') + RAPIDJSON_STRING_(String, 's', 't', 'r', 'i', 'n', 'g') + RAPIDJSON_STRING_(Number, 'n', 'u', 'm', 'b', 'e', 'r') + RAPIDJSON_STRING_(Integer, 'i', 'n', 't', 'e', 'g', 'e', 'r') + RAPIDJSON_STRING_(Type, 't', 'y', 'p', 'e') + RAPIDJSON_STRING_(Enum, 'e', 'n', 'u', 'm') + RAPIDJSON_STRING_(AllOf, 'a', 'l', 'l', 'O', 'f') + RAPIDJSON_STRING_(AnyOf, 'a', 'n', 'y', 'O', 'f') + RAPIDJSON_STRING_(OneOf, 'o', 'n', 'e', 'O', 'f') + RAPIDJSON_STRING_(Not, 'n', 'o', 't') + RAPIDJSON_STRING_(Properties, 'p', 'r', 'o', 'p', 'e', 'r', 't', 'i', 'e', 's') + RAPIDJSON_STRING_(Required, 'r', 'e', 'q', 'u', 'i', 'r', 'e', 'd') + RAPIDJSON_STRING_(Dependencies, 'd', 'e', 'p', 'e', 'n', 'd', 'e', 'n', 'c', 'i', 'e', 's') + RAPIDJSON_STRING_(PatternProperties, 'p', 'a', 't', 't', 'e', 'r', 'n', 'P', 'r', 'o', 'p', 'e', 'r', 't', 'i', + 'e', 's') + RAPIDJSON_STRING_(AdditionalProperties, 'a', 'd', 'd', 'i', 't', 'i', 'o', 'n', 'a', 'l', 'P', 'r', 'o', 'p', + 'e', 'r', 't', 'i', 'e', 's') + RAPIDJSON_STRING_(MinProperties, 'm', 'i', 'n', 'P', 'r', 'o', 'p', 'e', 'r', 't', 'i', 'e', 's') + RAPIDJSON_STRING_(MaxProperties, 'm', 'a', 'x', 'P', 'r', 'o', 'p', 'e', 'r', 't', 'i', 'e', 's') + RAPIDJSON_STRING_(Items, 'i', 't', 'e', 'm', 's') + RAPIDJSON_STRING_(MinItems, 'm', 'i', 'n', 'I', 't', 'e', 'm', 's') + RAPIDJSON_STRING_(MaxItems, 'm', 'a', 'x', 'I', 't', 'e', 'm', 's') + RAPIDJSON_STRING_(AdditionalItems, 'a', 'd', 'd', 'i', 't', 'i', 'o', 'n', 'a', 'l', 'I', 't', 'e', 'm', 's') + RAPIDJSON_STRING_(UniqueItems, 'u', 'n', 'i', 'q', 'u', 'e', 'I', 't', 'e', 'm', 's') + RAPIDJSON_STRING_(MinLength, 'm', 'i', 'n', 'L', 'e', 'n', 'g', 't', 'h') + RAPIDJSON_STRING_(MaxLength, 'm', 'a', 'x', 'L', 'e', 'n', 'g', 't', 'h') + RAPIDJSON_STRING_(Pattern, 'p', 'a', 't', 't', 'e', 'r', 'n') + RAPIDJSON_STRING_(Minimum, 'm', 'i', 'n', 'i', 'm', 'u', 'm') + RAPIDJSON_STRING_(Maximum, 'm', 'a', 'x', 'i', 'm', 'u', 'm') + RAPIDJSON_STRING_(ExclusiveMinimum, 'e', 'x', 'c', 'l', 'u', 's', 'i', 'v', 'e', 'M', 'i', 'n', 'i', 'm', 'u', + 'm') + RAPIDJSON_STRING_(ExclusiveMaximum, 'e', 'x', 'c', 'l', 'u', 's', 'i', 'v', 'e', 'M', 'a', 'x', 'i', 'm', 'u', + 'm') + RAPIDJSON_STRING_(MultipleOf, 'm', 'u', 'l', 't', 'i', 'p', 'l', 'e', 'O', 'f') #undef RAPIDJSON_STRING_ -private: - enum SchemaValueType { - kNullSchemaType, - kBooleanSchemaType, - kObjectSchemaType, - kArraySchemaType, - kStringSchemaType, - kNumberSchemaType, - kIntegerSchemaType, - kTotalSchemaType - }; + private: + enum SchemaValueType + { + kNullSchemaType, + kBooleanSchemaType, + kObjectSchemaType, + kArraySchemaType, + kStringSchemaType, + kNumberSchemaType, + kIntegerSchemaType, + kTotalSchemaType + }; #if RAPIDJSON_SCHEMA_USE_INTERNALREGEX - typedef internal::GenericRegex RegexType; + typedef internal::GenericRegex RegexType; #elif RAPIDJSON_SCHEMA_USE_STDREGEX - typedef std::basic_regex RegexType; + typedef std::basic_regex RegexType; #else - typedef char RegexType; + typedef char RegexType; #endif - struct SchemaArray { - SchemaArray() : schemas(), count() {} - ~SchemaArray() { AllocatorType::Free(schemas); } - const SchemaType** schemas; - SizeType begin; // begin index of context.validators - SizeType count; - }; + struct SchemaArray + { + SchemaArray() : schemas(), count() {} + ~SchemaArray() + { + AllocatorType::Free(schemas); + } + const SchemaType** schemas; + SizeType begin; // begin index of context.validators + SizeType count; + }; - static const SchemaType* GetTypeless() { - static SchemaType typeless(0, PointerType(), ValueType(kObjectType).Move(), ValueType(kObjectType).Move(), 0); - return &typeless; - } + static const SchemaType* GetTypeless() + { + static SchemaType typeless(0, PointerType(), ValueType(kObjectType).Move(), ValueType(kObjectType).Move(), 0); + return &typeless; + } - template - void AddUniqueElement(V1& a, const V2& v) { - for (typename V1::ConstValueIterator itr = a.Begin(); itr != a.End(); ++itr) - if (*itr == v) - return; - V1 c(v, *allocator_); - a.PushBack(c, *allocator_); - } + template + void AddUniqueElement(V1 & a, const V2 & v) + { + for(typename V1::ConstValueIterator itr = a.Begin(); itr != a.End(); ++itr) + if(*itr == v) + { + return; + } + V1 c(v, *allocator_); + a.PushBack(c, *allocator_); + } - static const ValueType* GetMember(const ValueType& value, const ValueType& name) { - typename ValueType::ConstMemberIterator itr = value.FindMember(name); - return itr != value.MemberEnd() ? &(itr->value) : 0; - } + static const ValueType* GetMember(const ValueType & value, const ValueType & name) + { + typename ValueType::ConstMemberIterator itr = value.FindMember(name); + return itr != value.MemberEnd() ? &(itr->value) : 0; + } - static void AssignIfExist(bool& out, const ValueType& value, const ValueType& name) { - if (const ValueType* v = GetMember(value, name)) - if (v->IsBool()) - out = v->GetBool(); - } + static void AssignIfExist(bool & out, const ValueType & value, const ValueType & name) + { + if(const ValueType* v = GetMember(value, name)) + if(v->IsBool()) + { + out = v->GetBool(); + } + } - static void AssignIfExist(SizeType& out, const ValueType& value, const ValueType& name) { - if (const ValueType* v = GetMember(value, name)) - if (v->IsUint64() && v->GetUint64() <= SizeType(~0)) - out = static_cast(v->GetUint64()); - } + static void AssignIfExist(SizeType & out, const ValueType & value, const ValueType & name) + { + if(const ValueType* v = GetMember(value, name)) + if(v->IsUint64() && v->GetUint64() <= SizeType(~0)) + { + out = static_cast(v->GetUint64()); + } + } - void AssignIfExist(SchemaArray& out, SchemaDocumentType& schemaDocument, const PointerType& p, const ValueType& value, const ValueType& name, const ValueType& document) { - if (const ValueType* v = GetMember(value, name)) { - if (v->IsArray() && v->Size() > 0) { - PointerType q = p.Append(name, allocator_); - out.count = v->Size(); - out.schemas = static_cast(allocator_->Malloc(out.count * sizeof(const Schema*))); - memset(out.schemas, 0, sizeof(Schema*)* out.count); - for (SizeType i = 0; i < out.count; i++) - schemaDocument.CreateSchema(&out.schemas[i], q.Append(i, allocator_), (*v)[i], document); - out.begin = validatorCount_; - validatorCount_ += out.count; - } - } - } + void AssignIfExist(SchemaArray & out, SchemaDocumentType & schemaDocument, const PointerType & p, + const ValueType & value, const ValueType & name, const ValueType & document) + { + if(const ValueType* v = GetMember(value, name)) + { + if(v->IsArray() && v->Size() > 0) + { + PointerType q = p.Append(name, allocator_); + out.count = v->Size(); + out.schemas = static_cast(allocator_->Malloc(out.count * sizeof(const Schema*))); + memset(out.schemas, 0, sizeof(Schema*)* out.count); + for(SizeType i = 0; i < out.count; i++) + { + schemaDocument.CreateSchema(&out.schemas[i], q.Append(i, allocator_), (*v)[i], document); + } + out.begin = validatorCount_; + validatorCount_ += out.count; + } + } + } #if RAPIDJSON_SCHEMA_USE_INTERNALREGEX - template - RegexType* CreatePattern(const ValueType& value) { - if (value.IsString()) { - RegexType* r = new (allocator_->Malloc(sizeof(RegexType))) RegexType(value.GetString()); - if (!r->IsValid()) { - r->~RegexType(); - AllocatorType::Free(r); - r = 0; - } - return r; - } - return 0; - } + template + RegexType* CreatePattern(const ValueType & value) + { + if(value.IsString()) + { + RegexType* r = new(allocator_->Malloc(sizeof(RegexType))) RegexType(value.GetString()); + if(!r->IsValid()) + { + r->~RegexType(); + AllocatorType::Free(r); + r = 0; + } + return r; + } + return 0; + } - static bool IsPatternMatch(const RegexType* pattern, const Ch *str, SizeType) { - return pattern->Search(str); - } + static bool IsPatternMatch(const RegexType* pattern, const Ch* str, SizeType) + { + return pattern->Search(str); + } #elif RAPIDJSON_SCHEMA_USE_STDREGEX - template - RegexType* CreatePattern(const ValueType& value) { - if (value.IsString()) - try { - return new (allocator_->Malloc(sizeof(RegexType))) RegexType(value.GetString(), std::size_t(value.GetStringLength()), std::regex_constants::ECMAScript); - } - catch (const std::regex_error&) { - } - return 0; - } + template + RegexType* CreatePattern(const ValueType & value) + { + if(value.IsString()) + try + { + return new(allocator_->Malloc(sizeof(RegexType))) RegexType(value.GetString(), + std::size_t(value.GetStringLength()), std::regex_constants::ECMAScript); + } + catch(const std::regex_error &) + { + } + return 0; + } - static bool IsPatternMatch(const RegexType* pattern, const Ch *str, SizeType length) { - std::match_results r; - return std::regex_search(str, str + length, r, *pattern); - } + static bool IsPatternMatch(const RegexType* pattern, const Ch* str, SizeType length) + { + std::match_results r; + return std::regex_search(str, str + length, r, *pattern); + } #else - template - RegexType* CreatePattern(const ValueType&) { return 0; } + template + RegexType* CreatePattern(const ValueType &) + { + return 0; + } - static bool IsPatternMatch(const RegexType*, const Ch *, SizeType) { return true; } + static bool IsPatternMatch(const RegexType*, const Ch*, SizeType) + { + return true; + } #endif // RAPIDJSON_SCHEMA_USE_STDREGEX - void AddType(const ValueType& type) { - if (type == GetNullString() ) type_ |= 1 << kNullSchemaType; - else if (type == GetBooleanString()) type_ |= 1 << kBooleanSchemaType; - else if (type == GetObjectString() ) type_ |= 1 << kObjectSchemaType; - else if (type == GetArrayString() ) type_ |= 1 << kArraySchemaType; - else if (type == GetStringString() ) type_ |= 1 << kStringSchemaType; - else if (type == GetIntegerString()) type_ |= 1 << kIntegerSchemaType; - else if (type == GetNumberString() ) type_ |= (1 << kNumberSchemaType) | (1 << kIntegerSchemaType); - } + void AddType(const ValueType & type) + { + if(type == GetNullString()) + { + type_ |= 1 << kNullSchemaType; + } + else if(type == GetBooleanString()) + { + type_ |= 1 << kBooleanSchemaType; + } + else if(type == GetObjectString()) + { + type_ |= 1 << kObjectSchemaType; + } + else if(type == GetArrayString()) + { + type_ |= 1 << kArraySchemaType; + } + else if(type == GetStringString()) + { + type_ |= 1 << kStringSchemaType; + } + else if(type == GetIntegerString()) + { + type_ |= 1 << kIntegerSchemaType; + } + else if(type == GetNumberString()) + { + type_ |= (1 << kNumberSchemaType) | (1 << kIntegerSchemaType); + } + } - bool CreateParallelValidator(Context& context) const { - if (enum_ || context.arrayUniqueness) - context.hasher = context.factory.CreateHasher(); + bool CreateParallelValidator(Context & context) const + { + if(enum_ || context.arrayUniqueness) + { + context.hasher = context.factory.CreateHasher(); + } - if (validatorCount_) { - RAPIDJSON_ASSERT(context.validators == 0); - context.validators = static_cast(context.factory.MallocState(sizeof(ISchemaValidator*) * validatorCount_)); - context.validatorCount = validatorCount_; + if(validatorCount_) + { + RAPIDJSON_ASSERT(context.validators == 0); + context.validators = static_cast(context.factory.MallocState(sizeof( + ISchemaValidator*) * validatorCount_)); + context.validatorCount = validatorCount_; - if (allOf_.schemas) - CreateSchemaValidators(context, allOf_); + if(allOf_.schemas) + { + CreateSchemaValidators(context, allOf_); + } - if (anyOf_.schemas) - CreateSchemaValidators(context, anyOf_); - - if (oneOf_.schemas) - CreateSchemaValidators(context, oneOf_); - - if (not_) - context.validators[notValidatorIndex_] = context.factory.CreateSchemaValidator(*not_); - - if (hasSchemaDependencies_) { - for (SizeType i = 0; i < propertyCount_; i++) - if (properties_[i].dependenciesSchema) - context.validators[properties_[i].dependenciesValidatorIndex] = context.factory.CreateSchemaValidator(*properties_[i].dependenciesSchema); - } - } + if(anyOf_.schemas) + { + CreateSchemaValidators(context, anyOf_); + } - return true; - } + if(oneOf_.schemas) + { + CreateSchemaValidators(context, oneOf_); + } - void CreateSchemaValidators(Context& context, const SchemaArray& schemas) const { - for (SizeType i = 0; i < schemas.count; i++) - context.validators[schemas.begin + i] = context.factory.CreateSchemaValidator(*schemas.schemas[i]); - } + if(not_) + { + context.validators[notValidatorIndex_] = context.factory.CreateSchemaValidator(*not_); + } - // O(n) - bool FindPropertyIndex(const ValueType& name, SizeType* outIndex) const { - SizeType len = name.GetStringLength(); - const Ch* str = name.GetString(); - for (SizeType index = 0; index < propertyCount_; index++) - if (properties_[index].name.GetStringLength() == len && - (std::memcmp(properties_[index].name.GetString(), str, sizeof(Ch) * len) == 0)) - { - *outIndex = index; - return true; - } - return false; - } + if(hasSchemaDependencies_) + { + for(SizeType i = 0; i < propertyCount_; i++) + if(properties_[i].dependenciesSchema) + { + context.validators[properties_[i].dependenciesValidatorIndex] = context.factory.CreateSchemaValidator( + *properties_[i].dependenciesSchema); + } + } + } - bool CheckInt(Context& context, int64_t i) const { - if (!(type_ & ((1 << kIntegerSchemaType) | (1 << kNumberSchemaType)))) - RAPIDJSON_INVALID_KEYWORD_RETURN(GetTypeString()); + return true; + } - if (!minimum_.IsNull()) { - if (minimum_.IsInt64()) { - if (exclusiveMinimum_ ? i <= minimum_.GetInt64() : i < minimum_.GetInt64()) - RAPIDJSON_INVALID_KEYWORD_RETURN(GetMinimumString()); - } - else if (minimum_.IsUint64()) { - RAPIDJSON_INVALID_KEYWORD_RETURN(GetMinimumString()); // i <= max(int64_t) < minimum.GetUint64() - } - else if (!CheckDoubleMinimum(context, static_cast(i))) - return false; - } + void CreateSchemaValidators(Context & context, const SchemaArray & schemas) const + { + for(SizeType i = 0; i < schemas.count; i++) + { + context.validators[schemas.begin + i] = context.factory.CreateSchemaValidator(*schemas.schemas[i]); + } + } - if (!maximum_.IsNull()) { - if (maximum_.IsInt64()) { - if (exclusiveMaximum_ ? i >= maximum_.GetInt64() : i > maximum_.GetInt64()) - RAPIDJSON_INVALID_KEYWORD_RETURN(GetMaximumString()); - } - else if (maximum_.IsUint64()) - /* do nothing */; // i <= max(int64_t) < maximum_.GetUint64() - else if (!CheckDoubleMaximum(context, static_cast(i))) - return false; - } + // O(n) + bool FindPropertyIndex(const ValueType & name, SizeType* outIndex) const + { + SizeType len = name.GetStringLength(); + const Ch* str = name.GetString(); + for(SizeType index = 0; index < propertyCount_; index++) + if(properties_[index].name.GetStringLength() == len && + (std::memcmp(properties_[index].name.GetString(), str, sizeof(Ch) * len) == 0)) + { + *outIndex = index; + return true; + } + return false; + } - if (!multipleOf_.IsNull()) { - if (multipleOf_.IsUint64()) { - if (static_cast(i >= 0 ? i : -i) % multipleOf_.GetUint64() != 0) - RAPIDJSON_INVALID_KEYWORD_RETURN(GetMultipleOfString()); - } - else if (!CheckDoubleMultipleOf(context, static_cast(i))) - return false; - } + bool CheckInt(Context & context, int64_t i) const + { + if(!(type_ & ((1 << kIntegerSchemaType) | (1 << kNumberSchemaType)))) + { + RAPIDJSON_INVALID_KEYWORD_RETURN(GetTypeString()); + } - return true; - } + if(!minimum_.IsNull()) + { + if(minimum_.IsInt64()) + { + if(exclusiveMinimum_ ? i <= minimum_.GetInt64() : i < minimum_.GetInt64()) + { + RAPIDJSON_INVALID_KEYWORD_RETURN(GetMinimumString()); + } + } + else if(minimum_.IsUint64()) + { + RAPIDJSON_INVALID_KEYWORD_RETURN(GetMinimumString()); // i <= max(int64_t) < minimum.GetUint64() + } + else if(!CheckDoubleMinimum(context, static_cast(i))) + { + return false; + } + } - bool CheckUint(Context& context, uint64_t i) const { - if (!(type_ & ((1 << kIntegerSchemaType) | (1 << kNumberSchemaType)))) - RAPIDJSON_INVALID_KEYWORD_RETURN(GetTypeString()); + if(!maximum_.IsNull()) + { + if(maximum_.IsInt64()) + { + if(exclusiveMaximum_ ? i >= maximum_.GetInt64() : i > maximum_.GetInt64()) + { + RAPIDJSON_INVALID_KEYWORD_RETURN(GetMaximumString()); + } + } + else if(maximum_.IsUint64()) + /* do nothing */; // i <= max(int64_t) < maximum_.GetUint64() + else if(!CheckDoubleMaximum(context, static_cast(i))) + { + return false; + } + } - if (!minimum_.IsNull()) { - if (minimum_.IsUint64()) { - if (exclusiveMinimum_ ? i <= minimum_.GetUint64() : i < minimum_.GetUint64()) - RAPIDJSON_INVALID_KEYWORD_RETURN(GetMinimumString()); - } - else if (minimum_.IsInt64()) - /* do nothing */; // i >= 0 > minimum.Getint64() - else if (!CheckDoubleMinimum(context, static_cast(i))) - return false; - } + if(!multipleOf_.IsNull()) + { + if(multipleOf_.IsUint64()) + { + if(static_cast(i >= 0 ? i : -i) % multipleOf_.GetUint64() != 0) + { + RAPIDJSON_INVALID_KEYWORD_RETURN(GetMultipleOfString()); + } + } + else if(!CheckDoubleMultipleOf(context, static_cast(i))) + { + return false; + } + } - if (!maximum_.IsNull()) { - if (maximum_.IsUint64()) { - if (exclusiveMaximum_ ? i >= maximum_.GetUint64() : i > maximum_.GetUint64()) - RAPIDJSON_INVALID_KEYWORD_RETURN(GetMaximumString()); - } - else if (maximum_.IsInt64()) - RAPIDJSON_INVALID_KEYWORD_RETURN(GetMaximumString()); // i >= 0 > maximum_ - else if (!CheckDoubleMaximum(context, static_cast(i))) - return false; - } + return true; + } - if (!multipleOf_.IsNull()) { - if (multipleOf_.IsUint64()) { - if (i % multipleOf_.GetUint64() != 0) - RAPIDJSON_INVALID_KEYWORD_RETURN(GetMultipleOfString()); - } - else if (!CheckDoubleMultipleOf(context, static_cast(i))) - return false; - } + bool CheckUint(Context & context, uint64_t i) const + { + if(!(type_ & ((1 << kIntegerSchemaType) | (1 << kNumberSchemaType)))) + { + RAPIDJSON_INVALID_KEYWORD_RETURN(GetTypeString()); + } - return true; - } + if(!minimum_.IsNull()) + { + if(minimum_.IsUint64()) + { + if(exclusiveMinimum_ ? i <= minimum_.GetUint64() : i < minimum_.GetUint64()) + { + RAPIDJSON_INVALID_KEYWORD_RETURN(GetMinimumString()); + } + } + else if(minimum_.IsInt64()) + /* do nothing */; // i >= 0 > minimum.Getint64() + else if(!CheckDoubleMinimum(context, static_cast(i))) + { + return false; + } + } - bool CheckDoubleMinimum(Context& context, double d) const { - if (exclusiveMinimum_ ? d <= minimum_.GetDouble() : d < minimum_.GetDouble()) - RAPIDJSON_INVALID_KEYWORD_RETURN(GetMinimumString()); - return true; - } + if(!maximum_.IsNull()) + { + if(maximum_.IsUint64()) + { + if(exclusiveMaximum_ ? i >= maximum_.GetUint64() : i > maximum_.GetUint64()) + { + RAPIDJSON_INVALID_KEYWORD_RETURN(GetMaximumString()); + } + } + else if(maximum_.IsInt64()) + { + RAPIDJSON_INVALID_KEYWORD_RETURN(GetMaximumString()); // i >= 0 > maximum_ + } + else if(!CheckDoubleMaximum(context, static_cast(i))) + { + return false; + } + } - bool CheckDoubleMaximum(Context& context, double d) const { - if (exclusiveMaximum_ ? d >= maximum_.GetDouble() : d > maximum_.GetDouble()) - RAPIDJSON_INVALID_KEYWORD_RETURN(GetMaximumString()); - return true; - } + if(!multipleOf_.IsNull()) + { + if(multipleOf_.IsUint64()) + { + if(i % multipleOf_.GetUint64() != 0) + { + RAPIDJSON_INVALID_KEYWORD_RETURN(GetMultipleOfString()); + } + } + else if(!CheckDoubleMultipleOf(context, static_cast(i))) + { + return false; + } + } - bool CheckDoubleMultipleOf(Context& context, double d) const { - double a = std::abs(d), b = std::abs(multipleOf_.GetDouble()); - double q = std::floor(a / b); - double r = a - q * b; - if (r > 0.0) - RAPIDJSON_INVALID_KEYWORD_RETURN(GetMultipleOfString()); - return true; - } + return true; + } - struct Property { - Property() : schema(), dependenciesSchema(), dependenciesValidatorIndex(), dependencies(), required(false) {} - ~Property() { AllocatorType::Free(dependencies); } - SValue name; - const SchemaType* schema; - const SchemaType* dependenciesSchema; - SizeType dependenciesValidatorIndex; - bool* dependencies; - bool required; - }; + bool CheckDoubleMinimum(Context & context, double d) const + { + if(exclusiveMinimum_ ? d <= minimum_.GetDouble() : d < minimum_.GetDouble()) + { + RAPIDJSON_INVALID_KEYWORD_RETURN(GetMinimumString()); + } + return true; + } - struct PatternProperty { - PatternProperty() : schema(), pattern() {} - ~PatternProperty() { - if (pattern) { - pattern->~RegexType(); - AllocatorType::Free(pattern); - } - } - const SchemaType* schema; - RegexType* pattern; - }; + bool CheckDoubleMaximum(Context & context, double d) const + { + if(exclusiveMaximum_ ? d >= maximum_.GetDouble() : d > maximum_.GetDouble()) + { + RAPIDJSON_INVALID_KEYWORD_RETURN(GetMaximumString()); + } + return true; + } - AllocatorType* allocator_; - uint64_t* enum_; - SizeType enumCount_; - SchemaArray allOf_; - SchemaArray anyOf_; - SchemaArray oneOf_; - const SchemaType* not_; - unsigned type_; // bitmask of kSchemaType - SizeType validatorCount_; - SizeType notValidatorIndex_; + bool CheckDoubleMultipleOf(Context & context, double d) const + { + double a = std::abs(d), b = std::abs(multipleOf_.GetDouble()); + double q = std::floor(a / b); + double r = a - q * b; + if(r > 0.0) + { + RAPIDJSON_INVALID_KEYWORD_RETURN(GetMultipleOfString()); + } + return true; + } - Property* properties_; - const SchemaType* additionalPropertiesSchema_; - PatternProperty* patternProperties_; - SizeType patternPropertyCount_; - SizeType propertyCount_; - SizeType minProperties_; - SizeType maxProperties_; - bool additionalProperties_; - bool hasDependencies_; - bool hasRequired_; - bool hasSchemaDependencies_; + struct Property + { + Property() : schema(), dependenciesSchema(), dependenciesValidatorIndex(), dependencies(), required(false) {} + ~Property() + { + AllocatorType::Free(dependencies); + } + SValue name; + const SchemaType* schema; + const SchemaType* dependenciesSchema; + SizeType dependenciesValidatorIndex; + bool* dependencies; + bool required; + }; - const SchemaType* additionalItemsSchema_; - const SchemaType* itemsList_; - const SchemaType** itemsTuple_; - SizeType itemsTupleCount_; - SizeType minItems_; - SizeType maxItems_; - bool additionalItems_; - bool uniqueItems_; + struct PatternProperty + { + PatternProperty() : schema(), pattern() {} + ~PatternProperty() + { + if(pattern) + { + pattern->~RegexType(); + AllocatorType::Free(pattern); + } + } + const SchemaType* schema; + RegexType* pattern; + }; - RegexType* pattern_; - SizeType minLength_; - SizeType maxLength_; + AllocatorType* allocator_; + uint64_t* enum_; + SizeType enumCount_; + SchemaArray allOf_; + SchemaArray anyOf_; + SchemaArray oneOf_; + const SchemaType* not_; + unsigned type_; // bitmask of kSchemaType + SizeType validatorCount_; + SizeType notValidatorIndex_; - SValue minimum_; - SValue maximum_; - SValue multipleOf_; - bool exclusiveMinimum_; - bool exclusiveMaximum_; -}; + Property* properties_; + const SchemaType* additionalPropertiesSchema_; + PatternProperty* patternProperties_; + SizeType patternPropertyCount_; + SizeType propertyCount_; + SizeType minProperties_; + SizeType maxProperties_; + bool additionalProperties_; + bool hasDependencies_; + bool hasRequired_; + bool hasSchemaDependencies_; -template -struct TokenHelper { - RAPIDJSON_FORCEINLINE static void AppendIndexToken(Stack& documentStack, SizeType index) { - *documentStack.template Push() = '/'; - char buffer[21]; - size_t length = static_cast((sizeof(SizeType) == 4 ? u32toa(index, buffer) : u64toa(index, buffer)) - buffer); - for (size_t i = 0; i < length; i++) - *documentStack.template Push() = buffer[i]; - } -}; + const SchemaType* additionalItemsSchema_; + const SchemaType* itemsList_; + const SchemaType** itemsTuple_; + SizeType itemsTupleCount_; + SizeType minItems_; + SizeType maxItems_; + bool additionalItems_; + bool uniqueItems_; -// Partial specialized version for char to prevent buffer copying. -template -struct TokenHelper { - RAPIDJSON_FORCEINLINE static void AppendIndexToken(Stack& documentStack, SizeType index) { - if (sizeof(SizeType) == 4) { - char *buffer = documentStack.template Push(1 + 10); // '/' + uint - *buffer++ = '/'; - const char* end = internal::u32toa(index, buffer); - documentStack.template Pop(static_cast(10 - (end - buffer))); - } - else { - char *buffer = documentStack.template Push(1 + 20); // '/' + uint64 - *buffer++ = '/'; - const char* end = internal::u64toa(index, buffer); - documentStack.template Pop(static_cast(20 - (end - buffer))); - } - } -}; + RegexType* pattern_; + SizeType minLength_; + SizeType maxLength_; + + SValue minimum_; + SValue maximum_; + SValue multipleOf_; + bool exclusiveMinimum_; + bool exclusiveMaximum_; + }; + + template + struct TokenHelper + { + RAPIDJSON_FORCEINLINE static void AppendIndexToken(Stack & documentStack, SizeType index) + { + *documentStack.template Push() = '/'; + char buffer[21]; + size_t length = static_cast((sizeof(SizeType) == 4 ? u32toa(index, buffer) : u64toa(index, + buffer)) - buffer); + for(size_t i = 0; i < length; i++) + { + *documentStack.template Push() = buffer[i]; + } + } + }; + + // Partial specialized version for char to prevent buffer copying. + template + struct TokenHelper + { + RAPIDJSON_FORCEINLINE static void AppendIndexToken(Stack & documentStack, SizeType index) + { + if(sizeof(SizeType) == 4) + { + char* buffer = documentStack.template Push(1 + 10); // '/' + uint + *buffer++ = '/'; + const char* end = internal::u32toa(index, buffer); + documentStack.template Pop(static_cast(10 - (end - buffer))); + } + else + { + char* buffer = documentStack.template Push(1 + 20); // '/' + uint64 + *buffer++ = '/'; + const char* end = internal::u64toa(index, buffer); + documentStack.template Pop(static_cast(20 - (end - buffer))); + } + } + }; } // namespace internal @@ -1296,12 +1756,13 @@ struct TokenHelper { // IGenericRemoteSchemaDocumentProvider template -class IGenericRemoteSchemaDocumentProvider { +class IGenericRemoteSchemaDocumentProvider +{ public: - typedef typename SchemaDocumentType::Ch Ch; + typedef typename SchemaDocumentType::Ch Ch; - virtual ~IGenericRemoteSchemaDocumentProvider() {} - virtual const SchemaDocumentType* GetRemoteDocument(const Ch* uri, SizeType length) = 0; + virtual ~IGenericRemoteSchemaDocumentProvider() {} + virtual const SchemaDocumentType* GetRemoteDocument(const Ch* uri, SizeType length) = 0; }; /////////////////////////////////////////////////////////////////////////////// @@ -1317,213 +1778,279 @@ public: \tparam Allocator Allocator type for allocating memory of this document. */ template -class GenericSchemaDocument { +class GenericSchemaDocument +{ public: - typedef ValueT ValueType; - typedef IGenericRemoteSchemaDocumentProvider IRemoteSchemaDocumentProviderType; - typedef Allocator AllocatorType; - typedef typename ValueType::EncodingType EncodingType; - typedef typename EncodingType::Ch Ch; - typedef internal::Schema SchemaType; - typedef GenericPointer PointerType; - friend class internal::Schema; - template - friend class GenericSchemaValidator; + typedef ValueT ValueType; + typedef IGenericRemoteSchemaDocumentProvider IRemoteSchemaDocumentProviderType; + typedef Allocator AllocatorType; + typedef typename ValueType::EncodingType EncodingType; + typedef typename EncodingType::Ch Ch; + typedef internal::Schema SchemaType; + typedef GenericPointer PointerType; + friend class internal::Schema; + template + friend class GenericSchemaValidator; - //! Constructor. - /*! - Compile a JSON document into schema document. + //! Constructor. + /*! + Compile a JSON document into schema document. - \param document A JSON document as source. - \param remoteProvider An optional remote schema document provider for resolving remote reference. Can be null. - \param allocator An optional allocator instance for allocating memory. Can be null. - */ - explicit GenericSchemaDocument(const ValueType& document, IRemoteSchemaDocumentProviderType* remoteProvider = 0, Allocator* allocator = 0) : - remoteProvider_(remoteProvider), - allocator_(allocator), - ownAllocator_(), - root_(), - schemaMap_(allocator, kInitialSchemaMapSize), - schemaRef_(allocator, kInitialSchemaRefSize) - { - if (!allocator_) - ownAllocator_ = allocator_ = RAPIDJSON_NEW(Allocator()); + \param document A JSON document as source. + \param remoteProvider An optional remote schema document provider for resolving remote reference. Can be null. + \param allocator An optional allocator instance for allocating memory. Can be null. + */ + explicit GenericSchemaDocument(const ValueType & document, + IRemoteSchemaDocumentProviderType* remoteProvider = 0, Allocator* allocator = 0) : + remoteProvider_(remoteProvider), + allocator_(allocator), + ownAllocator_(), + root_(), + schemaMap_(allocator, kInitialSchemaMapSize), + schemaRef_(allocator, kInitialSchemaRefSize) + { + if(!allocator_) + { + ownAllocator_ = allocator_ = RAPIDJSON_NEW(Allocator()); + } - // Generate root schema, it will call CreateSchema() to create sub-schemas, - // And call AddRefSchema() if there are $ref. - CreateSchemaRecursive(&root_, PointerType(), document, document); + // Generate root schema, it will call CreateSchema() to create sub-schemas, + // And call AddRefSchema() if there are $ref. + CreateSchemaRecursive(&root_, PointerType(), document, document); - // Resolve $ref - while (!schemaRef_.Empty()) { - SchemaRefEntry* refEntry = schemaRef_.template Pop(1); - if (const SchemaType* s = GetSchema(refEntry->target)) { - if (refEntry->schema) - *refEntry->schema = s; + // Resolve $ref + while(!schemaRef_.Empty()) + { + SchemaRefEntry* refEntry = schemaRef_.template Pop(1); + if(const SchemaType* s = GetSchema(refEntry->target)) + { + if(refEntry->schema) + { + *refEntry->schema = s; + } - // Create entry in map if not exist - if (!GetSchema(refEntry->source)) { - new (schemaMap_.template Push()) SchemaEntry(refEntry->source, const_cast(s), false, allocator_); - } - } - refEntry->~SchemaRefEntry(); - } + // Create entry in map if not exist + if(!GetSchema(refEntry->source)) + { + new(schemaMap_.template Push()) SchemaEntry(refEntry->source, const_cast(s), false, + allocator_); + } + } + refEntry->~SchemaRefEntry(); + } - RAPIDJSON_ASSERT(root_ != 0); + RAPIDJSON_ASSERT(root_ != 0); - schemaRef_.ShrinkToFit(); // Deallocate all memory for ref - } + schemaRef_.ShrinkToFit(); // Deallocate all memory for ref + } #if RAPIDJSON_HAS_CXX11_RVALUE_REFS - //! Move constructor in C++11 - GenericSchemaDocument(GenericSchemaDocument&& rhs) RAPIDJSON_NOEXCEPT : - remoteProvider_(rhs.remoteProvider_), - allocator_(rhs.allocator_), - ownAllocator_(rhs.ownAllocator_), - root_(rhs.root_), - schemaMap_(std::move(rhs.schemaMap_)), - schemaRef_(std::move(rhs.schemaRef_)) - { - rhs.remoteProvider_ = 0; - rhs.allocator_ = 0; - rhs.ownAllocator_ = 0; - } + //! Move constructor in C++11 +GenericSchemaDocument(GenericSchemaDocument && rhs) RAPIDJSON_NOEXCEPT : + remoteProvider_(rhs.remoteProvider_), + allocator_(rhs.allocator_), + ownAllocator_(rhs.ownAllocator_), + root_(rhs.root_), + schemaMap_(std::move(rhs.schemaMap_)), + schemaRef_(std::move(rhs.schemaRef_)) + { + rhs.remoteProvider_ = 0; + rhs.allocator_ = 0; + rhs.ownAllocator_ = 0; + } #endif - //! Destructor - ~GenericSchemaDocument() { - while (!schemaMap_.Empty()) - schemaMap_.template Pop(1)->~SchemaEntry(); + //! Destructor + ~GenericSchemaDocument() + { + while(!schemaMap_.Empty()) + { + schemaMap_.template Pop(1)->~SchemaEntry(); + } - RAPIDJSON_DELETE(ownAllocator_); - } + RAPIDJSON_DELETE(ownAllocator_); + } - //! Get the root schema. - const SchemaType& GetRoot() const { return *root_; } + //! Get the root schema. + const SchemaType & GetRoot() const + { + return *root_; + } private: - //! Prohibit copying - GenericSchemaDocument(const GenericSchemaDocument&); - //! Prohibit assignment - GenericSchemaDocument& operator=(const GenericSchemaDocument&); + //! Prohibit copying + GenericSchemaDocument(const GenericSchemaDocument &); + //! Prohibit assignment + GenericSchemaDocument & operator=(const GenericSchemaDocument &); - struct SchemaRefEntry { - SchemaRefEntry(const PointerType& s, const PointerType& t, const SchemaType** outSchema, Allocator *allocator) : source(s, allocator), target(t, allocator), schema(outSchema) {} - PointerType source; - PointerType target; - const SchemaType** schema; - }; + struct SchemaRefEntry + { + SchemaRefEntry(const PointerType & s, const PointerType & t, const SchemaType** outSchema, + Allocator* allocator) : source(s, allocator), target(t, allocator), schema(outSchema) {} + PointerType source; + PointerType target; + const SchemaType** schema; + }; - struct SchemaEntry { - SchemaEntry(const PointerType& p, SchemaType* s, bool o, Allocator* allocator) : pointer(p, allocator), schema(s), owned(o) {} - ~SchemaEntry() { - if (owned) { - schema->~SchemaType(); - Allocator::Free(schema); - } - } - PointerType pointer; - SchemaType* schema; - bool owned; - }; + struct SchemaEntry + { + SchemaEntry(const PointerType & p, SchemaType* s, bool o, Allocator* allocator) : pointer(p, allocator), + schema(s), owned(o) {} + ~SchemaEntry() + { + if(owned) + { + schema->~SchemaType(); + Allocator::Free(schema); + } + } + PointerType pointer; + SchemaType* schema; + bool owned; + }; - void CreateSchemaRecursive(const SchemaType** schema, const PointerType& pointer, const ValueType& v, const ValueType& document) { - if (schema) - *schema = SchemaType::GetTypeless(); + void CreateSchemaRecursive(const SchemaType** schema, const PointerType & pointer, const ValueType & v, + const ValueType & document) + { + if(schema) + { + *schema = SchemaType::GetTypeless(); + } - if (v.GetType() == kObjectType) { - const SchemaType* s = GetSchema(pointer); - if (!s) - CreateSchema(schema, pointer, v, document); + if(v.GetType() == kObjectType) + { + const SchemaType* s = GetSchema(pointer); + if(!s) + { + CreateSchema(schema, pointer, v, document); + } - for (typename ValueType::ConstMemberIterator itr = v.MemberBegin(); itr != v.MemberEnd(); ++itr) - CreateSchemaRecursive(0, pointer.Append(itr->name, allocator_), itr->value, document); - } - else if (v.GetType() == kArrayType) - for (SizeType i = 0; i < v.Size(); i++) - CreateSchemaRecursive(0, pointer.Append(i, allocator_), v[i], document); - } + for(typename ValueType::ConstMemberIterator itr = v.MemberBegin(); itr != v.MemberEnd(); ++itr) + { + CreateSchemaRecursive(0, pointer.Append(itr->name, allocator_), itr->value, document); + } + } + else if(v.GetType() == kArrayType) + for(SizeType i = 0; i < v.Size(); i++) + { + CreateSchemaRecursive(0, pointer.Append(i, allocator_), v[i], document); + } + } - void CreateSchema(const SchemaType** schema, const PointerType& pointer, const ValueType& v, const ValueType& document) { - RAPIDJSON_ASSERT(pointer.IsValid()); - if (v.IsObject()) { - if (!HandleRefSchema(pointer, schema, v, document)) { - SchemaType* s = new (allocator_->Malloc(sizeof(SchemaType))) SchemaType(this, pointer, v, document, allocator_); - new (schemaMap_.template Push()) SchemaEntry(pointer, s, true, allocator_); - if (schema) - *schema = s; - } - } - } + void CreateSchema(const SchemaType** schema, const PointerType & pointer, const ValueType & v, + const ValueType & document) + { + RAPIDJSON_ASSERT(pointer.IsValid()); + if(v.IsObject()) + { + if(!HandleRefSchema(pointer, schema, v, document)) + { + SchemaType* s = new(allocator_->Malloc(sizeof(SchemaType))) SchemaType(this, pointer, v, document, allocator_); + new(schemaMap_.template Push()) SchemaEntry(pointer, s, true, allocator_); + if(schema) + { + *schema = s; + } + } + } + } - bool HandleRefSchema(const PointerType& source, const SchemaType** schema, const ValueType& v, const ValueType& document) { - static const Ch kRefString[] = { '$', 'r', 'e', 'f', '\0' }; - static const ValueType kRefValue(kRefString, 4); + bool HandleRefSchema(const PointerType & source, const SchemaType** schema, const ValueType & v, + const ValueType & document) + { + static const Ch kRefString[] = { '$', 'r', 'e', 'f', '\0' }; + static const ValueType kRefValue(kRefString, 4); - typename ValueType::ConstMemberIterator itr = v.FindMember(kRefValue); - if (itr == v.MemberEnd()) - return false; + typename ValueType::ConstMemberIterator itr = v.FindMember(kRefValue); + if(itr == v.MemberEnd()) + { + return false; + } - if (itr->value.IsString()) { - SizeType len = itr->value.GetStringLength(); - if (len > 0) { - const Ch* s = itr->value.GetString(); - SizeType i = 0; - while (i < len && s[i] != '#') // Find the first # - i++; + if(itr->value.IsString()) + { + SizeType len = itr->value.GetStringLength(); + if(len > 0) + { + const Ch* s = itr->value.GetString(); + SizeType i = 0; + while(i < len && s[i] != '#') // Find the first # + { + i++; + } - if (i > 0) { // Remote reference, resolve immediately - if (remoteProvider_) { - if (const GenericSchemaDocument* remoteDocument = remoteProvider_->GetRemoteDocument(s, i - 1)) { - PointerType pointer(&s[i], len - i, allocator_); - if (pointer.IsValid()) { - if (const SchemaType* sc = remoteDocument->GetSchema(pointer)) { - if (schema) - *schema = sc; - return true; - } - } - } - } - } - else if (s[i] == '#') { // Local reference, defer resolution - PointerType pointer(&s[i], len - i, allocator_); - if (pointer.IsValid()) { - if (const ValueType* nv = pointer.Get(document)) - if (HandleRefSchema(source, schema, *nv, document)) - return true; + if(i > 0) // Remote reference, resolve immediately + { + if(remoteProvider_) + { + if(const GenericSchemaDocument* remoteDocument = remoteProvider_->GetRemoteDocument(s, i - 1)) + { + PointerType pointer(&s[i], len - i, allocator_); + if(pointer.IsValid()) + { + if(const SchemaType* sc = remoteDocument->GetSchema(pointer)) + { + if(schema) + { + *schema = sc; + } + return true; + } + } + } + } + } + else if(s[i] == '#') // Local reference, defer resolution + { + PointerType pointer(&s[i], len - i, allocator_); + if(pointer.IsValid()) + { + if(const ValueType* nv = pointer.Get(document)) + if(HandleRefSchema(source, schema, *nv, document)) + { + return true; + } - new (schemaRef_.template Push()) SchemaRefEntry(source, pointer, schema, allocator_); - return true; - } - } - } - } - return false; - } + new(schemaRef_.template Push()) SchemaRefEntry(source, pointer, schema, allocator_); + return true; + } + } + } + } + return false; + } - const SchemaType* GetSchema(const PointerType& pointer) const { - for (const SchemaEntry* target = schemaMap_.template Bottom(); target != schemaMap_.template End(); ++target) - if (pointer == target->pointer) - return target->schema; - return 0; - } + const SchemaType* GetSchema(const PointerType & pointer) const + { + for(const SchemaEntry* target = schemaMap_.template Bottom(); + target != schemaMap_.template End(); ++target) + if(pointer == target->pointer) + { + return target->schema; + } + return 0; + } - PointerType GetPointer(const SchemaType* schema) const { - for (const SchemaEntry* target = schemaMap_.template Bottom(); target != schemaMap_.template End(); ++target) - if (schema == target->schema) - return target->pointer; - return PointerType(); - } + PointerType GetPointer(const SchemaType* schema) const + { + for(const SchemaEntry* target = schemaMap_.template Bottom(); + target != schemaMap_.template End(); ++target) + if(schema == target->schema) + { + return target->pointer; + } + return PointerType(); + } - static const size_t kInitialSchemaMapSize = 64; - static const size_t kInitialSchemaRefSize = 64; + static const size_t kInitialSchemaMapSize = 64; + static const size_t kInitialSchemaRefSize = 64; - IRemoteSchemaDocumentProviderType* remoteProvider_; - Allocator *allocator_; - Allocator *ownAllocator_; - const SchemaType* root_; //!< Root schema. - internal::Stack schemaMap_; // Stores created Pointer -> Schemas - internal::Stack schemaRef_; // Stores Pointer from $ref and schema which holds the $ref + IRemoteSchemaDocumentProviderType* remoteProvider_; + Allocator* allocator_; + Allocator* ownAllocator_; + const SchemaType* root_; //!< Root schema. + internal::Stack schemaMap_; // Stores created Pointer -> Schemas + internal::Stack schemaRef_; // Stores Pointer from $ref and schema which holds the $ref }; //! GenericSchemaDocument using Value type. @@ -1549,383 +2076,501 @@ typedef IGenericRemoteSchemaDocumentProvider IRemoteSchemaDocume template < typename SchemaDocumentType, typename OutputHandler = BaseReaderHandler, - typename StateAllocator = CrtAllocator> + typename StateAllocator = CrtAllocator > class GenericSchemaValidator : - public internal::ISchemaStateFactory, - public internal::ISchemaValidator + public internal::ISchemaStateFactory, + public internal::ISchemaValidator { public: - typedef typename SchemaDocumentType::SchemaType SchemaType; - typedef typename SchemaDocumentType::PointerType PointerType; - typedef typename SchemaType::EncodingType EncodingType; - typedef typename EncodingType::Ch Ch; + typedef typename SchemaDocumentType::SchemaType SchemaType; + typedef typename SchemaDocumentType::PointerType PointerType; + typedef typename SchemaType::EncodingType EncodingType; + typedef typename EncodingType::Ch Ch; - //! Constructor without output handler. - /*! - \param schemaDocument The schema document to conform to. - \param allocator Optional allocator for storing internal validation states. - \param schemaStackCapacity Optional initial capacity of schema path stack. - \param documentStackCapacity Optional initial capacity of document path stack. - */ - GenericSchemaValidator( - const SchemaDocumentType& schemaDocument, - StateAllocator* allocator = 0, - size_t schemaStackCapacity = kDefaultSchemaStackCapacity, - size_t documentStackCapacity = kDefaultDocumentStackCapacity) - : - schemaDocument_(&schemaDocument), - root_(schemaDocument.GetRoot()), - outputHandler_(GetNullHandler()), - stateAllocator_(allocator), - ownStateAllocator_(0), - schemaStack_(allocator, schemaStackCapacity), - documentStack_(allocator, documentStackCapacity), - valid_(true) + //! Constructor without output handler. + /*! + \param schemaDocument The schema document to conform to. + \param allocator Optional allocator for storing internal validation states. + \param schemaStackCapacity Optional initial capacity of schema path stack. + \param documentStackCapacity Optional initial capacity of document path stack. + */ + GenericSchemaValidator( + const SchemaDocumentType & schemaDocument, + StateAllocator* allocator = 0, + size_t schemaStackCapacity = kDefaultSchemaStackCapacity, + size_t documentStackCapacity = kDefaultDocumentStackCapacity) + : + schemaDocument_(&schemaDocument), + root_(schemaDocument.GetRoot()), + outputHandler_(GetNullHandler()), + stateAllocator_(allocator), + ownStateAllocator_(0), + schemaStack_(allocator, schemaStackCapacity), + documentStack_(allocator, documentStackCapacity), + valid_(true) #if RAPIDJSON_SCHEMA_VERBOSE - , depth_(0) + , depth_(0) #endif - { - } + { + } - //! Constructor with output handler. - /*! - \param schemaDocument The schema document to conform to. - \param allocator Optional allocator for storing internal validation states. - \param schemaStackCapacity Optional initial capacity of schema path stack. - \param documentStackCapacity Optional initial capacity of document path stack. - */ - GenericSchemaValidator( - const SchemaDocumentType& schemaDocument, - OutputHandler& outputHandler, - StateAllocator* allocator = 0, - size_t schemaStackCapacity = kDefaultSchemaStackCapacity, - size_t documentStackCapacity = kDefaultDocumentStackCapacity) - : - schemaDocument_(&schemaDocument), - root_(schemaDocument.GetRoot()), - outputHandler_(outputHandler), - stateAllocator_(allocator), - ownStateAllocator_(0), - schemaStack_(allocator, schemaStackCapacity), - documentStack_(allocator, documentStackCapacity), - valid_(true) + //! Constructor with output handler. + /*! + \param schemaDocument The schema document to conform to. + \param allocator Optional allocator for storing internal validation states. + \param schemaStackCapacity Optional initial capacity of schema path stack. + \param documentStackCapacity Optional initial capacity of document path stack. + */ + GenericSchemaValidator( + const SchemaDocumentType & schemaDocument, + OutputHandler & outputHandler, + StateAllocator* allocator = 0, + size_t schemaStackCapacity = kDefaultSchemaStackCapacity, + size_t documentStackCapacity = kDefaultDocumentStackCapacity) + : + schemaDocument_(&schemaDocument), + root_(schemaDocument.GetRoot()), + outputHandler_(outputHandler), + stateAllocator_(allocator), + ownStateAllocator_(0), + schemaStack_(allocator, schemaStackCapacity), + documentStack_(allocator, documentStackCapacity), + valid_(true) #if RAPIDJSON_SCHEMA_VERBOSE - , depth_(0) + , depth_(0) #endif - { - } + { + } - //! Destructor. - ~GenericSchemaValidator() { - Reset(); - RAPIDJSON_DELETE(ownStateAllocator_); - } + //! Destructor. + ~GenericSchemaValidator() + { + Reset(); + RAPIDJSON_DELETE(ownStateAllocator_); + } - //! Reset the internal states. - void Reset() { - while (!schemaStack_.Empty()) - PopSchema(); - documentStack_.Clear(); - valid_ = true; - } + //! Reset the internal states. + void Reset() + { + while(!schemaStack_.Empty()) + { + PopSchema(); + } + documentStack_.Clear(); + valid_ = true; + } - //! Checks whether the current state is valid. - // Implementation of ISchemaValidator - virtual bool IsValid() const { return valid_; } + //! Checks whether the current state is valid. + // Implementation of ISchemaValidator + virtual bool IsValid() const + { + return valid_; + } - //! Gets the JSON pointer pointed to the invalid schema. - PointerType GetInvalidSchemaPointer() const { - return schemaStack_.Empty() ? PointerType() : schemaDocument_->GetPointer(&CurrentSchema()); - } + //! Gets the JSON pointer pointed to the invalid schema. + PointerType GetInvalidSchemaPointer() const + { + return schemaStack_.Empty() ? PointerType() : schemaDocument_->GetPointer(&CurrentSchema()); + } - //! Gets the keyword of invalid schema. - const Ch* GetInvalidSchemaKeyword() const { - return schemaStack_.Empty() ? 0 : CurrentContext().invalidKeyword; - } + //! Gets the keyword of invalid schema. + const Ch* GetInvalidSchemaKeyword() const + { + return schemaStack_.Empty() ? 0 : CurrentContext().invalidKeyword; + } - //! Gets the JSON pointer pointed to the invalid value. - PointerType GetInvalidDocumentPointer() const { - return documentStack_.Empty() ? PointerType() : PointerType(documentStack_.template Bottom(), documentStack_.GetSize() / sizeof(Ch)); - } + //! Gets the JSON pointer pointed to the invalid value. + PointerType GetInvalidDocumentPointer() const + { + return documentStack_.Empty() ? PointerType() : PointerType(documentStack_.template Bottom(), + documentStack_.GetSize() / sizeof(Ch)); + } #if RAPIDJSON_SCHEMA_VERBOSE #define RAPIDJSON_SCHEMA_HANDLE_BEGIN_VERBOSE_() \ -RAPIDJSON_MULTILINEMACRO_BEGIN\ - *documentStack_.template Push() = '\0';\ - documentStack_.template Pop(1);\ - internal::PrintInvalidDocument(documentStack_.template Bottom());\ -RAPIDJSON_MULTILINEMACRO_END + RAPIDJSON_MULTILINEMACRO_BEGIN\ + *documentStack_.template Push() = '\0';\ + documentStack_.template Pop(1);\ + internal::PrintInvalidDocument(documentStack_.template Bottom());\ + RAPIDJSON_MULTILINEMACRO_END #else #define RAPIDJSON_SCHEMA_HANDLE_BEGIN_VERBOSE_() #endif #define RAPIDJSON_SCHEMA_HANDLE_BEGIN_(method, arg1)\ - if (!valid_) return false; \ - if (!BeginValue() || !CurrentSchema().method arg1) {\ - RAPIDJSON_SCHEMA_HANDLE_BEGIN_VERBOSE_();\ - return valid_ = false;\ - } + if (!valid_) return false; \ + if (!BeginValue() || !CurrentSchema().method arg1) {\ + RAPIDJSON_SCHEMA_HANDLE_BEGIN_VERBOSE_();\ + return valid_ = false;\ + } #define RAPIDJSON_SCHEMA_HANDLE_PARALLEL_(method, arg2)\ - for (Context* context = schemaStack_.template Bottom(); context != schemaStack_.template End(); context++) {\ - if (context->hasher)\ - static_cast(context->hasher)->method arg2;\ - if (context->validators)\ - for (SizeType i_ = 0; i_ < context->validatorCount; i_++)\ - static_cast(context->validators[i_])->method arg2;\ - if (context->patternPropertiesValidators)\ - for (SizeType i_ = 0; i_ < context->patternPropertiesValidatorCount; i_++)\ - static_cast(context->patternPropertiesValidators[i_])->method arg2;\ - } + for (Context* context = schemaStack_.template Bottom(); context != schemaStack_.template End(); context++) {\ + if (context->hasher)\ + static_cast(context->hasher)->method arg2;\ + if (context->validators)\ + for (SizeType i_ = 0; i_ < context->validatorCount; i_++)\ + static_cast(context->validators[i_])->method arg2;\ + if (context->patternPropertiesValidators)\ + for (SizeType i_ = 0; i_ < context->patternPropertiesValidatorCount; i_++)\ + static_cast(context->patternPropertiesValidators[i_])->method arg2;\ + } #define RAPIDJSON_SCHEMA_HANDLE_END_(method, arg2)\ - return valid_ = EndValue() && outputHandler_.method arg2 + return valid_ = EndValue() && outputHandler_.method arg2 #define RAPIDJSON_SCHEMA_HANDLE_VALUE_(method, arg1, arg2) \ - RAPIDJSON_SCHEMA_HANDLE_BEGIN_ (method, arg1);\ - RAPIDJSON_SCHEMA_HANDLE_PARALLEL_(method, arg2);\ - RAPIDJSON_SCHEMA_HANDLE_END_ (method, arg2) + RAPIDJSON_SCHEMA_HANDLE_BEGIN_ (method, arg1);\ + RAPIDJSON_SCHEMA_HANDLE_PARALLEL_(method, arg2);\ + RAPIDJSON_SCHEMA_HANDLE_END_ (method, arg2) - bool Null() { RAPIDJSON_SCHEMA_HANDLE_VALUE_(Null, (CurrentContext() ), ( )); } - bool Bool(bool b) { RAPIDJSON_SCHEMA_HANDLE_VALUE_(Bool, (CurrentContext(), b), (b)); } - bool Int(int i) { RAPIDJSON_SCHEMA_HANDLE_VALUE_(Int, (CurrentContext(), i), (i)); } - bool Uint(unsigned u) { RAPIDJSON_SCHEMA_HANDLE_VALUE_(Uint, (CurrentContext(), u), (u)); } - bool Int64(int64_t i) { RAPIDJSON_SCHEMA_HANDLE_VALUE_(Int64, (CurrentContext(), i), (i)); } - bool Uint64(uint64_t u) { RAPIDJSON_SCHEMA_HANDLE_VALUE_(Uint64, (CurrentContext(), u), (u)); } - bool Double(double d) { RAPIDJSON_SCHEMA_HANDLE_VALUE_(Double, (CurrentContext(), d), (d)); } - bool RawNumber(const Ch* str, SizeType length, bool copy) - { RAPIDJSON_SCHEMA_HANDLE_VALUE_(String, (CurrentContext(), str, length, copy), (str, length, copy)); } - bool String(const Ch* str, SizeType length, bool copy) - { RAPIDJSON_SCHEMA_HANDLE_VALUE_(String, (CurrentContext(), str, length, copy), (str, length, copy)); } + bool Null() + { + RAPIDJSON_SCHEMA_HANDLE_VALUE_(Null, (CurrentContext()), ()); + } + bool Bool(bool b) + { + RAPIDJSON_SCHEMA_HANDLE_VALUE_(Bool, (CurrentContext(), b), (b)); + } + bool Int(int i) + { + RAPIDJSON_SCHEMA_HANDLE_VALUE_(Int, (CurrentContext(), i), (i)); + } + bool Uint(unsigned u) + { + RAPIDJSON_SCHEMA_HANDLE_VALUE_(Uint, (CurrentContext(), u), (u)); + } + bool Int64(int64_t i) + { + RAPIDJSON_SCHEMA_HANDLE_VALUE_(Int64, (CurrentContext(), i), (i)); + } + bool Uint64(uint64_t u) + { + RAPIDJSON_SCHEMA_HANDLE_VALUE_(Uint64, (CurrentContext(), u), (u)); + } + bool Double(double d) + { + RAPIDJSON_SCHEMA_HANDLE_VALUE_(Double, (CurrentContext(), d), (d)); + } + bool RawNumber(const Ch* str, SizeType length, bool copy) + { + RAPIDJSON_SCHEMA_HANDLE_VALUE_(String, (CurrentContext(), str, length, copy), (str, length, copy)); + } + bool String(const Ch* str, SizeType length, bool copy) + { + RAPIDJSON_SCHEMA_HANDLE_VALUE_(String, (CurrentContext(), str, length, copy), (str, length, copy)); + } - bool StartObject() { - RAPIDJSON_SCHEMA_HANDLE_BEGIN_(StartObject, (CurrentContext())); - RAPIDJSON_SCHEMA_HANDLE_PARALLEL_(StartObject, ()); - return valid_ = outputHandler_.StartObject(); - } - - bool Key(const Ch* str, SizeType len, bool copy) { - if (!valid_) return false; - AppendToken(str, len); - if (!CurrentSchema().Key(CurrentContext(), str, len, copy)) return valid_ = false; - RAPIDJSON_SCHEMA_HANDLE_PARALLEL_(Key, (str, len, copy)); - return valid_ = outputHandler_.Key(str, len, copy); - } - - bool EndObject(SizeType memberCount) { - if (!valid_) return false; - RAPIDJSON_SCHEMA_HANDLE_PARALLEL_(EndObject, (memberCount)); - if (!CurrentSchema().EndObject(CurrentContext(), memberCount)) return valid_ = false; - RAPIDJSON_SCHEMA_HANDLE_END_(EndObject, (memberCount)); - } + bool StartObject() + { + RAPIDJSON_SCHEMA_HANDLE_BEGIN_(StartObject, (CurrentContext())); + RAPIDJSON_SCHEMA_HANDLE_PARALLEL_(StartObject, ()); + return valid_ = outputHandler_.StartObject(); + } - bool StartArray() { - RAPIDJSON_SCHEMA_HANDLE_BEGIN_(StartArray, (CurrentContext())); - RAPIDJSON_SCHEMA_HANDLE_PARALLEL_(StartArray, ()); - return valid_ = outputHandler_.StartArray(); - } - - bool EndArray(SizeType elementCount) { - if (!valid_) return false; - RAPIDJSON_SCHEMA_HANDLE_PARALLEL_(EndArray, (elementCount)); - if (!CurrentSchema().EndArray(CurrentContext(), elementCount)) return valid_ = false; - RAPIDJSON_SCHEMA_HANDLE_END_(EndArray, (elementCount)); - } + bool Key(const Ch* str, SizeType len, bool copy) + { + if(!valid_) + { + return false; + } + AppendToken(str, len); + if(!CurrentSchema().Key(CurrentContext(), str, len, copy)) + { + return valid_ = false; + } + RAPIDJSON_SCHEMA_HANDLE_PARALLEL_(Key, (str, len, copy)); + return valid_ = outputHandler_.Key(str, len, copy); + } + + bool EndObject(SizeType memberCount) + { + if(!valid_) + { + return false; + } + RAPIDJSON_SCHEMA_HANDLE_PARALLEL_(EndObject, (memberCount)); + if(!CurrentSchema().EndObject(CurrentContext(), memberCount)) + { + return valid_ = false; + } + RAPIDJSON_SCHEMA_HANDLE_END_(EndObject, (memberCount)); + } + + bool StartArray() + { + RAPIDJSON_SCHEMA_HANDLE_BEGIN_(StartArray, (CurrentContext())); + RAPIDJSON_SCHEMA_HANDLE_PARALLEL_(StartArray, ()); + return valid_ = outputHandler_.StartArray(); + } + + bool EndArray(SizeType elementCount) + { + if(!valid_) + { + return false; + } + RAPIDJSON_SCHEMA_HANDLE_PARALLEL_(EndArray, (elementCount)); + if(!CurrentSchema().EndArray(CurrentContext(), elementCount)) + { + return valid_ = false; + } + RAPIDJSON_SCHEMA_HANDLE_END_(EndArray, (elementCount)); + } #undef RAPIDJSON_SCHEMA_HANDLE_BEGIN_VERBOSE_ #undef RAPIDJSON_SCHEMA_HANDLE_BEGIN_ #undef RAPIDJSON_SCHEMA_HANDLE_PARALLEL_ #undef RAPIDJSON_SCHEMA_HANDLE_VALUE_ - // Implementation of ISchemaStateFactory - virtual ISchemaValidator* CreateSchemaValidator(const SchemaType& root) { - return new (GetStateAllocator().Malloc(sizeof(GenericSchemaValidator))) GenericSchemaValidator(*schemaDocument_, root, + // Implementation of ISchemaStateFactory + virtual ISchemaValidator* CreateSchemaValidator(const SchemaType & root) + { + return new(GetStateAllocator().Malloc(sizeof(GenericSchemaValidator))) GenericSchemaValidator(*schemaDocument_, + root, #if RAPIDJSON_SCHEMA_VERBOSE - depth_ + 1, + depth_ + 1, #endif - &GetStateAllocator()); - } + &GetStateAllocator()); + } - virtual void DestroySchemaValidator(ISchemaValidator* validator) { - GenericSchemaValidator* v = static_cast(validator); - v->~GenericSchemaValidator(); - StateAllocator::Free(v); - } + virtual void DestroySchemaValidator(ISchemaValidator* validator) + { + GenericSchemaValidator* v = static_cast(validator); + v->~GenericSchemaValidator(); + StateAllocator::Free(v); + } - virtual void* CreateHasher() { - return new (GetStateAllocator().Malloc(sizeof(HasherType))) HasherType(&GetStateAllocator()); - } + virtual void* CreateHasher() + { + return new(GetStateAllocator().Malloc(sizeof(HasherType))) HasherType(&GetStateAllocator()); + } - virtual uint64_t GetHashCode(void* hasher) { - return static_cast(hasher)->GetHashCode(); - } + virtual uint64_t GetHashCode(void* hasher) + { + return static_cast(hasher)->GetHashCode(); + } - virtual void DestroryHasher(void* hasher) { - HasherType* h = static_cast(hasher); - h->~HasherType(); - StateAllocator::Free(h); - } + virtual void DestroryHasher(void* hasher) + { + HasherType* h = static_cast(hasher); + h->~HasherType(); + StateAllocator::Free(h); + } - virtual void* MallocState(size_t size) { - return GetStateAllocator().Malloc(size); - } + virtual void* MallocState(size_t size) + { + return GetStateAllocator().Malloc(size); + } - virtual void FreeState(void* p) { - return StateAllocator::Free(p); - } + virtual void FreeState(void* p) + { + return StateAllocator::Free(p); + } private: - typedef typename SchemaType::Context Context; - typedef GenericValue, StateAllocator> HashCodeArray; - typedef internal::Hasher HasherType; + typedef typename SchemaType::Context Context; + typedef GenericValue, StateAllocator> HashCodeArray; + typedef internal::Hasher HasherType; - GenericSchemaValidator( - const SchemaDocumentType& schemaDocument, - const SchemaType& root, + GenericSchemaValidator( + const SchemaDocumentType & schemaDocument, + const SchemaType & root, #if RAPIDJSON_SCHEMA_VERBOSE - unsigned depth, + unsigned depth, #endif - StateAllocator* allocator = 0, - size_t schemaStackCapacity = kDefaultSchemaStackCapacity, - size_t documentStackCapacity = kDefaultDocumentStackCapacity) - : - schemaDocument_(&schemaDocument), - root_(root), - outputHandler_(GetNullHandler()), - stateAllocator_(allocator), - ownStateAllocator_(0), - schemaStack_(allocator, schemaStackCapacity), - documentStack_(allocator, documentStackCapacity), - valid_(true) + StateAllocator* allocator = 0, + size_t schemaStackCapacity = kDefaultSchemaStackCapacity, + size_t documentStackCapacity = kDefaultDocumentStackCapacity) + : + schemaDocument_(&schemaDocument), + root_(root), + outputHandler_(GetNullHandler()), + stateAllocator_(allocator), + ownStateAllocator_(0), + schemaStack_(allocator, schemaStackCapacity), + documentStack_(allocator, documentStackCapacity), + valid_(true) #if RAPIDJSON_SCHEMA_VERBOSE - , depth_(depth) + , depth_(depth) #endif - { - } + { + } - StateAllocator& GetStateAllocator() { - if (!stateAllocator_) - stateAllocator_ = ownStateAllocator_ = RAPIDJSON_NEW(StateAllocator()); - return *stateAllocator_; - } + StateAllocator & GetStateAllocator() + { + if(!stateAllocator_) + { + stateAllocator_ = ownStateAllocator_ = RAPIDJSON_NEW(StateAllocator()); + } + return *stateAllocator_; + } - bool BeginValue() { - if (schemaStack_.Empty()) - PushSchema(root_); - else { - if (CurrentContext().inArray) - internal::TokenHelper, Ch>::AppendIndexToken(documentStack_, CurrentContext().arrayElementIndex); + bool BeginValue() + { + if(schemaStack_.Empty()) + { + PushSchema(root_); + } + else + { + if(CurrentContext().inArray) + { + internal::TokenHelper, Ch>::AppendIndexToken(documentStack_, + CurrentContext().arrayElementIndex); + } - if (!CurrentSchema().BeginValue(CurrentContext())) - return false; + if(!CurrentSchema().BeginValue(CurrentContext())) + { + return false; + } - SizeType count = CurrentContext().patternPropertiesSchemaCount; - const SchemaType** sa = CurrentContext().patternPropertiesSchemas; - typename Context::PatternValidatorType patternValidatorType = CurrentContext().valuePatternValidatorType; - bool valueUniqueness = CurrentContext().valueUniqueness; - if (CurrentContext().valueSchema) - PushSchema(*CurrentContext().valueSchema); + SizeType count = CurrentContext().patternPropertiesSchemaCount; + const SchemaType** sa = CurrentContext().patternPropertiesSchemas; + typename Context::PatternValidatorType patternValidatorType = CurrentContext().valuePatternValidatorType; + bool valueUniqueness = CurrentContext().valueUniqueness; + if(CurrentContext().valueSchema) + { + PushSchema(*CurrentContext().valueSchema); + } - if (count > 0) { - CurrentContext().objectPatternValidatorType = patternValidatorType; - ISchemaValidator**& va = CurrentContext().patternPropertiesValidators; - SizeType& validatorCount = CurrentContext().patternPropertiesValidatorCount; - va = static_cast(MallocState(sizeof(ISchemaValidator*) * count)); - for (SizeType i = 0; i < count; i++) - va[validatorCount++] = CreateSchemaValidator(*sa[i]); - } + if(count > 0) + { + CurrentContext().objectPatternValidatorType = patternValidatorType; + ISchemaValidator** & va = CurrentContext().patternPropertiesValidators; + SizeType & validatorCount = CurrentContext().patternPropertiesValidatorCount; + va = static_cast(MallocState(sizeof(ISchemaValidator*) * count)); + for(SizeType i = 0; i < count; i++) + { + va[validatorCount++] = CreateSchemaValidator(*sa[i]); + } + } - CurrentContext().arrayUniqueness = valueUniqueness; - } - return true; - } + CurrentContext().arrayUniqueness = valueUniqueness; + } + return true; + } - bool EndValue() { - if (!CurrentSchema().EndValue(CurrentContext())) - return false; + bool EndValue() + { + if(!CurrentSchema().EndValue(CurrentContext())) + { + return false; + } #if RAPIDJSON_SCHEMA_VERBOSE - GenericStringBuffer sb; - schemaDocument_->GetPointer(&CurrentSchema()).Stringify(sb); + GenericStringBuffer sb; + schemaDocument_->GetPointer(&CurrentSchema()).Stringify(sb); - *documentStack_.template Push() = '\0'; - documentStack_.template Pop(1); - internal::PrintValidatorPointers(depth_, sb.GetString(), documentStack_.template Bottom()); + *documentStack_.template Push() = '\0'; + documentStack_.template Pop(1); + internal::PrintValidatorPointers(depth_, sb.GetString(), documentStack_.template Bottom()); #endif - uint64_t h = CurrentContext().arrayUniqueness ? static_cast(CurrentContext().hasher)->GetHashCode() : 0; - - PopSchema(); + uint64_t h = CurrentContext().arrayUniqueness ? static_cast + (CurrentContext().hasher)->GetHashCode() : 0; - if (!schemaStack_.Empty()) { - Context& context = CurrentContext(); - if (context.valueUniqueness) { - HashCodeArray* a = static_cast(context.arrayElementHashCodes); - if (!a) - CurrentContext().arrayElementHashCodes = a = new (GetStateAllocator().Malloc(sizeof(HashCodeArray))) HashCodeArray(kArrayType); - for (typename HashCodeArray::ConstValueIterator itr = a->Begin(); itr != a->End(); ++itr) - if (itr->GetUint64() == h) - RAPIDJSON_INVALID_KEYWORD_RETURN(SchemaType::GetUniqueItemsString()); - a->PushBack(h, GetStateAllocator()); - } - } + PopSchema(); - // Remove the last token of document pointer - while (!documentStack_.Empty() && *documentStack_.template Pop(1) != '/') - ; + if(!schemaStack_.Empty()) + { + Context & context = CurrentContext(); + if(context.valueUniqueness) + { + HashCodeArray* a = static_cast(context.arrayElementHashCodes); + if(!a) + { + CurrentContext().arrayElementHashCodes = a = new(GetStateAllocator().Malloc(sizeof( + HashCodeArray))) HashCodeArray(kArrayType); + } + for(typename HashCodeArray::ConstValueIterator itr = a->Begin(); itr != a->End(); ++itr) + if(itr->GetUint64() == h) + { + RAPIDJSON_INVALID_KEYWORD_RETURN(SchemaType::GetUniqueItemsString()); + } + a->PushBack(h, GetStateAllocator()); + } + } - return true; - } + // Remove the last token of document pointer + while(!documentStack_.Empty() && *documentStack_.template Pop(1) != '/') + ; - void AppendToken(const Ch* str, SizeType len) { - documentStack_.template Reserve(1 + len * 2); // worst case all characters are escaped as two characters - *documentStack_.template PushUnsafe() = '/'; - for (SizeType i = 0; i < len; i++) { - if (str[i] == '~') { - *documentStack_.template PushUnsafe() = '~'; - *documentStack_.template PushUnsafe() = '0'; - } - else if (str[i] == '/') { - *documentStack_.template PushUnsafe() = '~'; - *documentStack_.template PushUnsafe() = '1'; - } - else - *documentStack_.template PushUnsafe() = str[i]; - } - } + return true; + } - RAPIDJSON_FORCEINLINE void PushSchema(const SchemaType& schema) { new (schemaStack_.template Push()) Context(*this, &schema); } - - RAPIDJSON_FORCEINLINE void PopSchema() { - Context* c = schemaStack_.template Pop(1); - if (HashCodeArray* a = static_cast(c->arrayElementHashCodes)) { - a->~HashCodeArray(); - StateAllocator::Free(a); - } - c->~Context(); - } + void AppendToken(const Ch* str, SizeType len) + { + documentStack_.template Reserve(1 + len * 2); // worst case all characters are escaped as two characters + *documentStack_.template PushUnsafe() = '/'; + for(SizeType i = 0; i < len; i++) + { + if(str[i] == '~') + { + *documentStack_.template PushUnsafe() = '~'; + *documentStack_.template PushUnsafe() = '0'; + } + else if(str[i] == '/') + { + *documentStack_.template PushUnsafe() = '~'; + *documentStack_.template PushUnsafe() = '1'; + } + else + { + *documentStack_.template PushUnsafe() = str[i]; + } + } + } - const SchemaType& CurrentSchema() const { return *schemaStack_.template Top()->schema; } - Context& CurrentContext() { return *schemaStack_.template Top(); } - const Context& CurrentContext() const { return *schemaStack_.template Top(); } + RAPIDJSON_FORCEINLINE void PushSchema(const SchemaType & schema) + { + new(schemaStack_.template Push()) Context(*this, &schema); + } - static OutputHandler& GetNullHandler() { - static OutputHandler nullHandler; - return nullHandler; - } + RAPIDJSON_FORCEINLINE void PopSchema() + { + Context* c = schemaStack_.template Pop(1); + if(HashCodeArray* a = static_cast(c->arrayElementHashCodes)) + { + a->~HashCodeArray(); + StateAllocator::Free(a); + } + c->~Context(); + } - static const size_t kDefaultSchemaStackCapacity = 1024; - static const size_t kDefaultDocumentStackCapacity = 256; - const SchemaDocumentType* schemaDocument_; - const SchemaType& root_; - OutputHandler& outputHandler_; - StateAllocator* stateAllocator_; - StateAllocator* ownStateAllocator_; - internal::Stack schemaStack_; //!< stack to store the current path of schema (BaseSchemaType *) - internal::Stack documentStack_; //!< stack to store the current path of validating document (Ch) - bool valid_; + const SchemaType & CurrentSchema() const + { + return *schemaStack_.template Top()->schema; + } + Context & CurrentContext() + { + return *schemaStack_.template Top(); + } + const Context & CurrentContext() const + { + return *schemaStack_.template Top(); + } + + static OutputHandler & GetNullHandler() + { + static OutputHandler nullHandler; + return nullHandler; + } + + static const size_t kDefaultSchemaStackCapacity = 1024; + static const size_t kDefaultDocumentStackCapacity = 256; + const SchemaDocumentType* schemaDocument_; + const SchemaType & root_; + OutputHandler & outputHandler_; + StateAllocator* stateAllocator_; + StateAllocator* ownStateAllocator_; + internal::Stack + schemaStack_; //!< stack to store the current path of schema (BaseSchemaType *) + internal::Stack + documentStack_; //!< stack to store the current path of validating document (Ch) + bool valid_; #if RAPIDJSON_SCHEMA_VERBOSE - unsigned depth_; + unsigned depth_; #endif }; @@ -1949,55 +2594,75 @@ template < typename InputStream, typename SourceEncoding, typename SchemaDocumentType = SchemaDocument, - typename StackAllocator = CrtAllocator> -class SchemaValidatingReader { + typename StackAllocator = CrtAllocator > +class SchemaValidatingReader +{ public: - typedef typename SchemaDocumentType::PointerType PointerType; - typedef typename InputStream::Ch Ch; + typedef typename SchemaDocumentType::PointerType PointerType; + typedef typename InputStream::Ch Ch; - //! Constructor - /*! - \param is Input stream. - \param sd Schema document. - */ - SchemaValidatingReader(InputStream& is, const SchemaDocumentType& sd) : is_(is), sd_(sd), invalidSchemaKeyword_(), isValid_(true) {} + //! Constructor + /*! + \param is Input stream. + \param sd Schema document. + */ + SchemaValidatingReader(InputStream & is, const SchemaDocumentType & sd) : is_(is), sd_(sd), + invalidSchemaKeyword_(), isValid_(true) {} - template - bool operator()(Handler& handler) { - GenericReader reader; - GenericSchemaValidator validator(sd_, handler); - parseResult_ = reader.template Parse(is_, validator); + template + bool operator()(Handler & handler) + { + GenericReader reader; + GenericSchemaValidator validator(sd_, handler); + parseResult_ = reader.template Parse(is_, validator); - isValid_ = validator.IsValid(); - if (isValid_) { - invalidSchemaPointer_ = PointerType(); - invalidSchemaKeyword_ = 0; - invalidDocumentPointer_ = PointerType(); - } - else { - invalidSchemaPointer_ = validator.GetInvalidSchemaPointer(); - invalidSchemaKeyword_ = validator.GetInvalidSchemaKeyword(); - invalidDocumentPointer_ = validator.GetInvalidDocumentPointer(); - } + isValid_ = validator.IsValid(); + if(isValid_) + { + invalidSchemaPointer_ = PointerType(); + invalidSchemaKeyword_ = 0; + invalidDocumentPointer_ = PointerType(); + } + else + { + invalidSchemaPointer_ = validator.GetInvalidSchemaPointer(); + invalidSchemaKeyword_ = validator.GetInvalidSchemaKeyword(); + invalidDocumentPointer_ = validator.GetInvalidDocumentPointer(); + } - return parseResult_; - } + return parseResult_; + } - const ParseResult& GetParseResult() const { return parseResult_; } - bool IsValid() const { return isValid_; } - const PointerType& GetInvalidSchemaPointer() const { return invalidSchemaPointer_; } - const Ch* GetInvalidSchemaKeyword() const { return invalidSchemaKeyword_; } - const PointerType& GetInvalidDocumentPointer() const { return invalidDocumentPointer_; } + const ParseResult & GetParseResult() const + { + return parseResult_; + } + bool IsValid() const + { + return isValid_; + } + const PointerType & GetInvalidSchemaPointer() const + { + return invalidSchemaPointer_; + } + const Ch* GetInvalidSchemaKeyword() const + { + return invalidSchemaKeyword_; + } + const PointerType & GetInvalidDocumentPointer() const + { + return invalidDocumentPointer_; + } private: - InputStream& is_; - const SchemaDocumentType& sd_; + InputStream & is_; + const SchemaDocumentType & sd_; - ParseResult parseResult_; - PointerType invalidSchemaPointer_; - const Ch* invalidSchemaKeyword_; - PointerType invalidDocumentPointer_; - bool isValid_; + ParseResult parseResult_; + PointerType invalidSchemaPointer_; + const Ch* invalidSchemaKeyword_; + PointerType invalidDocumentPointer_; + bool isValid_; }; RAPIDJSON_NAMESPACE_END diff --git a/src/3rdparty/rapidjson/stream.h b/src/3rdparty/rapidjson/stream.h index fef82c25..60ad3a00 100644 --- a/src/3rdparty/rapidjson/stream.h +++ b/src/3rdparty/rapidjson/stream.h @@ -1,5 +1,5 @@ // 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 @@ -7,9 +7,9 @@ // // 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 +// 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. #include "rapidjson.h" @@ -70,34 +70,40 @@ concept Stream { See TEST(Reader, CustomStringStream) in readertest.cpp for example. */ template -struct StreamTraits { - //! Whether to make local copy of stream for optimization during parsing. - /*! - By default, for safety, streams do not use local copy optimization. - Stream that can be copied fast should specialize this, like StreamTraits. - */ - enum { copyOptimization = 0 }; +struct StreamTraits +{ + //! Whether to make local copy of stream for optimization during parsing. + /*! + By default, for safety, streams do not use local copy optimization. + Stream that can be copied fast should specialize this, like StreamTraits. + */ + enum { copyOptimization = 0 }; }; //! Reserve n characters for writing to a stream. template -inline void PutReserve(Stream& stream, size_t count) { - (void)stream; - (void)count; +inline void PutReserve(Stream & stream, size_t count) +{ + (void)stream; + (void)count; } //! Write character to a stream, presuming buffer is reserved. template -inline void PutUnsafe(Stream& stream, typename Stream::Ch c) { - stream.Put(c); +inline void PutUnsafe(Stream & stream, typename Stream::Ch c) +{ + stream.Put(c); } //! Put N copies of a character to a stream. template -inline void PutN(Stream& stream, Ch c, size_t n) { - PutReserve(stream, n); - for (size_t i = 0; i < n; i++) - PutUnsafe(stream, c); +inline void PutN(Stream & stream, Ch c, size_t n) +{ + PutReserve(stream, n); + for(size_t i = 0; i < n; i++) + { + PutUnsafe(stream, c); + } } /////////////////////////////////////////////////////////////////////////////// @@ -107,31 +113,56 @@ inline void PutN(Stream& stream, Ch c, size_t n) { /*! \note implements Stream concept */ template -struct GenericStringStream { - typedef typename Encoding::Ch Ch; +struct GenericStringStream +{ + typedef typename Encoding::Ch Ch; - GenericStringStream(const Ch *src) : src_(src), head_(src) {} + GenericStringStream(const Ch* src) : src_(src), head_(src) {} - Ch Peek() const { return *src_; } - Ch Take() { return *src_++; } - size_t Tell() const { return static_cast(src_ - head_); } + Ch Peek() const + { + return *src_; + } + Ch Take() + { + return *src_++; + } + size_t Tell() const + { + return static_cast(src_ - head_); + } - 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; } + 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; + } - const Ch* src_; //!< Current read position. - const Ch* head_; //!< Original head of the string. + const Ch* src_; //!< Current read position. + const Ch* head_; //!< Original head of the string. }; template -struct StreamTraits > { - enum { copyOptimization = 1 }; +struct StreamTraits> +{ + enum { copyOptimization = 1 }; }; //! String stream with UTF8 encoding. -typedef GenericStringStream > StringStream; +typedef GenericStringStream> StringStream; /////////////////////////////////////////////////////////////////////////////// // InsituStringStream @@ -141,38 +172,67 @@ typedef GenericStringStream > StringStream; \note implements Stream concept */ template -struct GenericInsituStringStream { - typedef typename Encoding::Ch Ch; +struct GenericInsituStringStream +{ + typedef typename Encoding::Ch Ch; - GenericInsituStringStream(Ch *src) : src_(src), dst_(0), head_(src) {} + GenericInsituStringStream(Ch* src) : src_(src), dst_(0), head_(src) {} - // Read - Ch Peek() { return *src_; } - Ch Take() { return *src_++; } - size_t Tell() { return static_cast(src_ - head_); } + // Read + Ch Peek() + { + return *src_; + } + Ch Take() + { + return *src_++; + } + size_t Tell() + { + return static_cast(src_ - head_); + } - // Write - void Put(Ch c) { RAPIDJSON_ASSERT(dst_ != 0); *dst_++ = c; } + // Write + void Put(Ch c) + { + RAPIDJSON_ASSERT(dst_ != 0); + *dst_++ = c; + } - Ch* PutBegin() { return dst_ = src_; } - size_t PutEnd(Ch* begin) { return static_cast(dst_ - begin); } - void Flush() {} + Ch* PutBegin() + { + return dst_ = src_; + } + size_t PutEnd(Ch* begin) + { + return static_cast(dst_ - begin); + } + void Flush() {} - Ch* Push(size_t count) { Ch* begin = dst_; dst_ += count; return begin; } - void Pop(size_t count) { dst_ -= count; } + Ch* Push(size_t count) + { + Ch* begin = dst_; + dst_ += count; + return begin; + } + void Pop(size_t count) + { + dst_ -= count; + } - Ch* src_; - Ch* dst_; - Ch* head_; + Ch* src_; + Ch* dst_; + Ch* head_; }; template -struct StreamTraits > { - enum { copyOptimization = 1 }; +struct StreamTraits> +{ + enum { copyOptimization = 1 }; }; //! Insitu string stream with UTF8 encoding. -typedef GenericInsituStringStream > InsituStringStream; +typedef GenericInsituStringStream> InsituStringStream; RAPIDJSON_NAMESPACE_END diff --git a/src/3rdparty/rapidjson/stringbuffer.h b/src/3rdparty/rapidjson/stringbuffer.h index 78f34d20..5b222d57 100644 --- a/src/3rdparty/rapidjson/stringbuffer.h +++ b/src/3rdparty/rapidjson/stringbuffer.h @@ -1,5 +1,5 @@ // 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 @@ -7,9 +7,9 @@ // // 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 +// 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_STRINGBUFFER_H_ @@ -26,7 +26,7 @@ #if defined(__clang__) RAPIDJSON_DIAG_PUSH -RAPIDJSON_DIAG_OFF(c++98-compat) +RAPIDJSON_DIAG_OFF(c++98 - compat) #endif RAPIDJSON_NAMESPACE_BEGIN @@ -38,74 +38,108 @@ RAPIDJSON_NAMESPACE_BEGIN \note implements Stream concept */ template -class GenericStringBuffer { +class GenericStringBuffer +{ public: - typedef typename Encoding::Ch Ch; + typedef typename Encoding::Ch Ch; - GenericStringBuffer(Allocator* allocator = 0, size_t capacity = kDefaultCapacity) : stack_(allocator, capacity) {} + GenericStringBuffer(Allocator* allocator = 0, size_t capacity = kDefaultCapacity) : stack_(allocator, + capacity) {} #if RAPIDJSON_HAS_CXX11_RVALUE_REFS - GenericStringBuffer(GenericStringBuffer&& rhs) : stack_(std::move(rhs.stack_)) {} - GenericStringBuffer& operator=(GenericStringBuffer&& rhs) { - if (&rhs != this) - stack_ = std::move(rhs.stack_); - return *this; - } + GenericStringBuffer(GenericStringBuffer && rhs) : stack_(std::move(rhs.stack_)) {} + GenericStringBuffer & operator=(GenericStringBuffer && rhs) + { + if(&rhs != this) + { + stack_ = std::move(rhs.stack_); + } + return *this; + } #endif - void Put(Ch c) { *stack_.template Push() = c; } - void PutUnsafe(Ch c) { *stack_.template PushUnsafe() = c; } - void Flush() {} + void Put(Ch c) + { + *stack_.template Push() = c; + } + void PutUnsafe(Ch c) + { + *stack_.template PushUnsafe() = c; + } + void Flush() {} - void Clear() { stack_.Clear(); } - void ShrinkToFit() { - // Push and pop a null terminator. This is safe. - *stack_.template Push() = '\0'; - stack_.ShrinkToFit(); - stack_.template Pop(1); - } + void Clear() + { + stack_.Clear(); + } + void ShrinkToFit() + { + // Push and pop a null terminator. This is safe. + *stack_.template Push() = '\0'; + stack_.ShrinkToFit(); + stack_.template Pop(1); + } - void Reserve(size_t count) { stack_.template Reserve(count); } - Ch* Push(size_t count) { return stack_.template Push(count); } - Ch* PushUnsafe(size_t count) { return stack_.template PushUnsafe(count); } - void Pop(size_t count) { stack_.template Pop(count); } + void Reserve(size_t count) + { + stack_.template Reserve(count); + } + Ch* Push(size_t count) + { + return stack_.template Push(count); + } + Ch* PushUnsafe(size_t count) + { + return stack_.template PushUnsafe(count); + } + void Pop(size_t count) + { + stack_.template Pop(count); + } - const Ch* GetString() const { - // Push and pop a null terminator. This is safe. - *stack_.template Push() = '\0'; - stack_.template Pop(1); + const Ch* GetString() const + { + // Push and pop a null terminator. This is safe. + *stack_.template Push() = '\0'; + stack_.template Pop(1); - return stack_.template Bottom(); - } + return stack_.template Bottom(); + } - size_t GetSize() const { return stack_.GetSize(); } + size_t GetSize() const + { + return stack_.GetSize(); + } - static const size_t kDefaultCapacity = 256; - mutable internal::Stack stack_; + static const size_t kDefaultCapacity = 256; + mutable internal::Stack stack_; private: - // Prohibit copy constructor & assignment operator. - GenericStringBuffer(const GenericStringBuffer&); - GenericStringBuffer& operator=(const GenericStringBuffer&); + // Prohibit copy constructor & assignment operator. + GenericStringBuffer(const GenericStringBuffer &); + GenericStringBuffer & operator=(const GenericStringBuffer &); }; //! String buffer with UTF8 encoding -typedef GenericStringBuffer > StringBuffer; +typedef GenericStringBuffer> StringBuffer; template -inline void PutReserve(GenericStringBuffer& stream, size_t count) { - stream.Reserve(count); +inline void PutReserve(GenericStringBuffer & stream, size_t count) +{ + stream.Reserve(count); } template -inline void PutUnsafe(GenericStringBuffer& stream, typename Encoding::Ch c) { - stream.PutUnsafe(c); +inline void PutUnsafe(GenericStringBuffer & stream, typename Encoding::Ch c) +{ + stream.PutUnsafe(c); } //! Implement specialized version of PutN() with memset() for better performance. template<> -inline void PutN(GenericStringBuffer >& stream, char c, size_t n) { - std::memset(stream.stack_.Push(n), c, n * sizeof(c)); +inline void PutN(GenericStringBuffer> & stream, char c, size_t n) +{ + std::memset(stream.stack_.Push(n), c, n * sizeof(c)); } RAPIDJSON_NAMESPACE_END diff --git a/src/3rdparty/rapidjson/writer.h b/src/3rdparty/rapidjson/writer.h index 94f22dd5..ba8ec162 100644 --- a/src/3rdparty/rapidjson/writer.h +++ b/src/3rdparty/rapidjson/writer.h @@ -1,5 +1,5 @@ // 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 @@ -7,9 +7,9 @@ // // 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 +// 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_WRITER_H_ @@ -41,7 +41,7 @@ RAPIDJSON_DIAG_OFF(4127) // conditional expression is constant #ifdef __clang__ RAPIDJSON_DIAG_PUSH RAPIDJSON_DIAG_OFF(padded) -RAPIDJSON_DIAG_OFF(unreachable-code) +RAPIDJSON_DIAG_OFF(unreachable - code) #endif RAPIDJSON_NAMESPACE_BEGIN @@ -49,7 +49,7 @@ RAPIDJSON_NAMESPACE_BEGIN /////////////////////////////////////////////////////////////////////////////// // WriteFlag -/*! \def RAPIDJSON_WRITE_DEFAULT_FLAGS +/*! \def RAPIDJSON_WRITE_DEFAULT_FLAGS \ingroup RAPIDJSON_CONFIG \brief User-defined kWriteDefaultFlags definition. @@ -60,11 +60,12 @@ RAPIDJSON_NAMESPACE_BEGIN #endif //! Combination of writeFlags -enum WriteFlag { - kWriteNoFlags = 0, //!< No flags are set. - kWriteValidateEncodingFlag = 1, //!< Validate encoding of JSON strings. - kWriteNanAndInfFlag = 2, //!< Allow writing of Infinity, -Infinity and NaN. - kWriteDefaultFlags = RAPIDJSON_WRITE_DEFAULT_FLAGS //!< Default write flags. Can be customized by defining RAPIDJSON_WRITE_DEFAULT_FLAGS +enum WriteFlag +{ + kWriteNoFlags = 0, //!< No flags are set. + kWriteValidateEncodingFlag = 1, //!< Validate encoding of JSON strings. + kWriteNanAndInfFlag = 2, //!< Allow writing of Infinity, -Infinity and NaN. + kWriteDefaultFlags = RAPIDJSON_WRITE_DEFAULT_FLAGS //!< Default write flags. Can be customized by defining RAPIDJSON_WRITE_DEFAULT_FLAGS }; //! JSON writer @@ -73,7 +74,7 @@ enum WriteFlag { User may programmatically calls the functions of a writer to generate JSON text. - On the other side, a writer can also be passed to objects that generates events, + On the other side, a writer can also be passed to objects that generates events, for example Reader::Parse() and Document::Accept(). @@ -84,516 +85,702 @@ enum WriteFlag { \note implements Handler concept */ template, typename TargetEncoding = UTF8<>, typename StackAllocator = CrtAllocator, unsigned writeFlags = kWriteDefaultFlags> -class Writer { +class Writer +{ public: - typedef typename SourceEncoding::Ch Ch; + typedef typename SourceEncoding::Ch Ch; - static const int kDefaultMaxDecimalPlaces = 324; + static const int kDefaultMaxDecimalPlaces = 324; - //! Constructor - /*! \param os Output stream. - \param stackAllocator User supplied allocator. If it is null, it will create a private one. - \param levelDepth Initial capacity of stack. - */ - explicit - Writer(OutputStream& os, StackAllocator* stackAllocator = 0, size_t levelDepth = kDefaultLevelDepth) : - os_(&os), level_stack_(stackAllocator, levelDepth * sizeof(Level)), maxDecimalPlaces_(kDefaultMaxDecimalPlaces), hasRoot_(false) {} + //! Constructor + /*! \param os Output stream. + \param stackAllocator User supplied allocator. If it is null, it will create a private one. + \param levelDepth Initial capacity of stack. + */ + explicit + Writer(OutputStream & os, StackAllocator* stackAllocator = 0, size_t levelDepth = kDefaultLevelDepth) : + os_(&os), level_stack_(stackAllocator, levelDepth* sizeof(Level)), maxDecimalPlaces_(kDefaultMaxDecimalPlaces), + hasRoot_(false) {} - explicit - Writer(StackAllocator* allocator = 0, size_t levelDepth = kDefaultLevelDepth) : - os_(0), level_stack_(allocator, levelDepth * sizeof(Level)), maxDecimalPlaces_(kDefaultMaxDecimalPlaces), hasRoot_(false) {} + explicit + Writer(StackAllocator* allocator = 0, size_t levelDepth = kDefaultLevelDepth) : + os_(0), level_stack_(allocator, levelDepth* sizeof(Level)), maxDecimalPlaces_(kDefaultMaxDecimalPlaces), + hasRoot_(false) {} - //! Reset the writer with a new stream. - /*! - This function reset the writer with a new stream and default settings, - in order to make a Writer object reusable for output multiple JSONs. + //! Reset the writer with a new stream. + /*! + This function reset the writer with a new stream and default settings, + in order to make a Writer object reusable for output multiple JSONs. - \param os New output stream. - \code - Writer writer(os1); - writer.StartObject(); - // ... - writer.EndObject(); + \param os New output stream. + \code + Writer writer(os1); + writer.StartObject(); + // ... + writer.EndObject(); - writer.Reset(os2); - writer.StartObject(); - // ... - writer.EndObject(); - \endcode - */ - void Reset(OutputStream& os) { - os_ = &os; - hasRoot_ = false; - level_stack_.Clear(); - } + writer.Reset(os2); + writer.StartObject(); + // ... + writer.EndObject(); + \endcode + */ + void Reset(OutputStream & os) + { + os_ = &os; + hasRoot_ = false; + level_stack_.Clear(); + } - //! Checks whether the output is a complete JSON. - /*! - A complete JSON has a complete root object or array. - */ - bool IsComplete() const { - return hasRoot_ && level_stack_.Empty(); - } + //! Checks whether the output is a complete JSON. + /*! + A complete JSON has a complete root object or array. + */ + bool IsComplete() const + { + return hasRoot_ && level_stack_.Empty(); + } - int GetMaxDecimalPlaces() const { - return maxDecimalPlaces_; - } + int GetMaxDecimalPlaces() const + { + return maxDecimalPlaces_; + } - //! Sets the maximum number of decimal places for double output. - /*! - This setting truncates the output with specified number of decimal places. + //! Sets the maximum number of decimal places for double output. + /*! + This setting truncates the output with specified number of decimal places. - For example, + For example, - \code - writer.SetMaxDecimalPlaces(3); - writer.StartArray(); - writer.Double(0.12345); // "0.123" - writer.Double(0.0001); // "0.0" - writer.Double(1.234567890123456e30); // "1.234567890123456e30" (do not truncate significand for positive exponent) - writer.Double(1.23e-4); // "0.0" (do truncate significand for negative exponent) - writer.EndArray(); - \endcode + \code + writer.SetMaxDecimalPlaces(3); + writer.StartArray(); + writer.Double(0.12345); // "0.123" + writer.Double(0.0001); // "0.0" + writer.Double(1.234567890123456e30); // "1.234567890123456e30" (do not truncate significand for positive exponent) + writer.Double(1.23e-4); // "0.0" (do truncate significand for negative exponent) + writer.EndArray(); + \endcode - The default setting does not truncate any decimal places. You can restore to this setting by calling - \code - writer.SetMaxDecimalPlaces(Writer::kDefaultMaxDecimalPlaces); - \endcode - */ - void SetMaxDecimalPlaces(int maxDecimalPlaces) { - maxDecimalPlaces_ = maxDecimalPlaces; - } + The default setting does not truncate any decimal places. You can restore to this setting by calling + \code + writer.SetMaxDecimalPlaces(Writer::kDefaultMaxDecimalPlaces); + \endcode + */ + void SetMaxDecimalPlaces(int maxDecimalPlaces) + { + maxDecimalPlaces_ = maxDecimalPlaces; + } - /*!@name Implementation of Handler - \see Handler - */ - //@{ + /*!@name Implementation of Handler + \see Handler + */ + //@{ - bool Null() { Prefix(kNullType); return EndValue(WriteNull()); } - bool Bool(bool b) { Prefix(b ? kTrueType : kFalseType); return EndValue(WriteBool(b)); } - bool Int(int i) { Prefix(kNumberType); return EndValue(WriteInt(i)); } - bool Uint(unsigned u) { Prefix(kNumberType); return EndValue(WriteUint(u)); } - bool Int64(int64_t i64) { Prefix(kNumberType); return EndValue(WriteInt64(i64)); } - bool Uint64(uint64_t u64) { Prefix(kNumberType); return EndValue(WriteUint64(u64)); } + bool Null() + { + Prefix(kNullType); + return EndValue(WriteNull()); + } + bool Bool(bool b) + { + Prefix(b ? kTrueType : kFalseType); + return EndValue(WriteBool(b)); + } + bool Int(int i) + { + Prefix(kNumberType); + return EndValue(WriteInt(i)); + } + bool Uint(unsigned u) + { + Prefix(kNumberType); + return EndValue(WriteUint(u)); + } + bool Int64(int64_t i64) + { + Prefix(kNumberType); + return EndValue(WriteInt64(i64)); + } + bool Uint64(uint64_t u64) + { + Prefix(kNumberType); + return EndValue(WriteUint64(u64)); + } - //! Writes the given \c double value to the stream - /*! - \param d The value to be written. - \return Whether it is succeed. - */ - bool Double(double d) { Prefix(kNumberType); return EndValue(WriteDouble(d)); } + //! Writes the given \c double value to the stream + /*! + \param d The value to be written. + \return Whether it is succeed. + */ + bool Double(double d) + { + Prefix(kNumberType); + return EndValue(WriteDouble(d)); + } - bool RawNumber(const Ch* str, SizeType length, bool copy = false) { - (void)copy; - Prefix(kNumberType); - return EndValue(WriteString(str, length)); - } + bool RawNumber(const Ch* str, SizeType length, bool copy = false) + { + (void)copy; + Prefix(kNumberType); + return EndValue(WriteString(str, length)); + } - bool String(const Ch* str, SizeType length, bool copy = false) { - (void)copy; - Prefix(kStringType); - return EndValue(WriteString(str, length)); - } + bool String(const Ch* str, SizeType length, bool copy = false) + { + (void)copy; + Prefix(kStringType); + return EndValue(WriteString(str, length)); + } #if RAPIDJSON_HAS_STDSTRING - bool String(const std::basic_string& str) { - return String(str.data(), SizeType(str.size())); - } + bool String(const std::basic_string & str) + { + return String(str.data(), SizeType(str.size())); + } #endif - bool StartObject() { - Prefix(kObjectType); - new (level_stack_.template Push()) Level(false); - return WriteStartObject(); - } + bool StartObject() + { + Prefix(kObjectType); + new(level_stack_.template Push()) Level(false); + return WriteStartObject(); + } - bool Key(const Ch* str, SizeType length, bool copy = false) { return String(str, length, copy); } + bool Key(const Ch* str, SizeType length, bool copy = false) + { + return String(str, length, copy); + } - bool EndObject(SizeType memberCount = 0) { - (void)memberCount; - RAPIDJSON_ASSERT(level_stack_.GetSize() >= sizeof(Level)); - RAPIDJSON_ASSERT(!level_stack_.template Top()->inArray); - level_stack_.template Pop(1); - return EndValue(WriteEndObject()); - } + bool EndObject(SizeType memberCount = 0) + { + (void)memberCount; + RAPIDJSON_ASSERT(level_stack_.GetSize() >= sizeof(Level)); + RAPIDJSON_ASSERT(!level_stack_.template Top()->inArray); + level_stack_.template Pop(1); + return EndValue(WriteEndObject()); + } - bool StartArray() { - Prefix(kArrayType); - new (level_stack_.template Push()) Level(true); - return WriteStartArray(); - } + bool StartArray() + { + Prefix(kArrayType); + new(level_stack_.template Push()) Level(true); + return WriteStartArray(); + } - bool EndArray(SizeType elementCount = 0) { - (void)elementCount; - RAPIDJSON_ASSERT(level_stack_.GetSize() >= sizeof(Level)); - RAPIDJSON_ASSERT(level_stack_.template Top()->inArray); - level_stack_.template Pop(1); - return EndValue(WriteEndArray()); - } - //@} + bool EndArray(SizeType elementCount = 0) + { + (void)elementCount; + RAPIDJSON_ASSERT(level_stack_.GetSize() >= sizeof(Level)); + RAPIDJSON_ASSERT(level_stack_.template Top()->inArray); + level_stack_.template Pop(1); + return EndValue(WriteEndArray()); + } + //@} - /*! @name Convenience extensions */ - //@{ + /*! @name Convenience extensions */ + //@{ - //! Simpler but slower overload. - bool String(const Ch* str) { return String(str, internal::StrLen(str)); } - bool Key(const Ch* str) { return Key(str, internal::StrLen(str)); } + //! Simpler but slower overload. + bool String(const Ch* str) + { + return String(str, internal::StrLen(str)); + } + bool Key(const Ch* str) + { + return Key(str, internal::StrLen(str)); + } - //@} + //@} - //! Write a raw JSON value. - /*! - For user to write a stringified JSON as a value. + //! Write a raw JSON value. + /*! + For user to write a stringified JSON as a value. - \param json A well-formed JSON value. It should not contain null character within [0, length - 1] range. - \param length Length of the json. - \param type Type of the root of json. - */ - bool RawValue(const Ch* json, size_t length, Type type) { Prefix(type); return EndValue(WriteRawValue(json, length)); } + \param json A well-formed JSON value. It should not contain null character within [0, length - 1] range. + \param length Length of the json. + \param type Type of the root of json. + */ + bool RawValue(const Ch* json, size_t length, Type type) + { + Prefix(type); + return EndValue(WriteRawValue(json, length)); + } protected: - //! Information for each nested level - struct Level { - Level(bool inArray_) : valueCount(0), inArray(inArray_) {} - size_t valueCount; //!< number of values in this level - bool inArray; //!< true if in array, otherwise in object - }; + //! Information for each nested level + struct Level + { + Level(bool inArray_) : valueCount(0), inArray(inArray_) {} + size_t valueCount; //!< number of values in this level + bool inArray; //!< true if in array, otherwise in object + }; - static const size_t kDefaultLevelDepth = 32; + static const size_t kDefaultLevelDepth = 32; - bool WriteNull() { - PutReserve(*os_, 4); - PutUnsafe(*os_, 'n'); PutUnsafe(*os_, 'u'); PutUnsafe(*os_, 'l'); PutUnsafe(*os_, 'l'); return true; - } + bool WriteNull() + { + PutReserve(*os_, 4); + PutUnsafe(*os_, 'n'); + PutUnsafe(*os_, 'u'); + PutUnsafe(*os_, 'l'); + PutUnsafe(*os_, 'l'); + return true; + } - bool WriteBool(bool b) { - if (b) { - PutReserve(*os_, 4); - PutUnsafe(*os_, 't'); PutUnsafe(*os_, 'r'); PutUnsafe(*os_, 'u'); PutUnsafe(*os_, 'e'); - } - else { - PutReserve(*os_, 5); - PutUnsafe(*os_, 'f'); PutUnsafe(*os_, 'a'); PutUnsafe(*os_, 'l'); PutUnsafe(*os_, 's'); PutUnsafe(*os_, 'e'); - } - return true; - } + bool WriteBool(bool b) + { + if(b) + { + PutReserve(*os_, 4); + PutUnsafe(*os_, 't'); + PutUnsafe(*os_, 'r'); + PutUnsafe(*os_, 'u'); + PutUnsafe(*os_, 'e'); + } + else + { + PutReserve(*os_, 5); + PutUnsafe(*os_, 'f'); + PutUnsafe(*os_, 'a'); + PutUnsafe(*os_, 'l'); + PutUnsafe(*os_, 's'); + PutUnsafe(*os_, 'e'); + } + return true; + } - bool WriteInt(int i) { - char buffer[11]; - const char* end = internal::i32toa(i, buffer); - PutReserve(*os_, static_cast(end - buffer)); - for (const char* p = buffer; p != end; ++p) - PutUnsafe(*os_, static_cast(*p)); - return true; - } + bool WriteInt(int i) + { + char buffer[11]; + const char* end = internal::i32toa(i, buffer); + PutReserve(*os_, static_cast(end - buffer)); + for(const char* p = buffer; p != end; ++p) + { + PutUnsafe(*os_, static_cast(*p)); + } + return true; + } - bool WriteUint(unsigned u) { - char buffer[10]; - const char* end = internal::u32toa(u, buffer); - PutReserve(*os_, static_cast(end - buffer)); - for (const char* p = buffer; p != end; ++p) - PutUnsafe(*os_, static_cast(*p)); - return true; - } + bool WriteUint(unsigned u) + { + char buffer[10]; + const char* end = internal::u32toa(u, buffer); + PutReserve(*os_, static_cast(end - buffer)); + for(const char* p = buffer; p != end; ++p) + { + PutUnsafe(*os_, static_cast(*p)); + } + return true; + } - bool WriteInt64(int64_t i64) { - char buffer[21]; - const char* end = internal::i64toa(i64, buffer); - PutReserve(*os_, static_cast(end - buffer)); - for (const char* p = buffer; p != end; ++p) - PutUnsafe(*os_, static_cast(*p)); - return true; - } + bool WriteInt64(int64_t i64) + { + char buffer[21]; + const char* end = internal::i64toa(i64, buffer); + PutReserve(*os_, static_cast(end - buffer)); + for(const char* p = buffer; p != end; ++p) + { + PutUnsafe(*os_, static_cast(*p)); + } + return true; + } - bool WriteUint64(uint64_t u64) { - char buffer[20]; - char* end = internal::u64toa(u64, buffer); - PutReserve(*os_, static_cast(end - buffer)); - for (char* p = buffer; p != end; ++p) - PutUnsafe(*os_, static_cast(*p)); - return true; - } + bool WriteUint64(uint64_t u64) + { + char buffer[20]; + char* end = internal::u64toa(u64, buffer); + PutReserve(*os_, static_cast(end - buffer)); + for(char* p = buffer; p != end; ++p) + { + PutUnsafe(*os_, static_cast(*p)); + } + return true; + } - bool WriteDouble(double d) { - if (internal::Double(d).IsNanOrInf()) { - if (!(writeFlags & kWriteNanAndInfFlag)) - return false; - if (internal::Double(d).IsNan()) { - PutReserve(*os_, 3); - PutUnsafe(*os_, 'N'); PutUnsafe(*os_, 'a'); PutUnsafe(*os_, 'N'); - return true; - } - if (internal::Double(d).Sign()) { - PutReserve(*os_, 9); - PutUnsafe(*os_, '-'); - } - else - PutReserve(*os_, 8); - PutUnsafe(*os_, 'I'); PutUnsafe(*os_, 'n'); PutUnsafe(*os_, 'f'); - PutUnsafe(*os_, 'i'); PutUnsafe(*os_, 'n'); PutUnsafe(*os_, 'i'); PutUnsafe(*os_, 't'); PutUnsafe(*os_, 'y'); - return true; - } + bool WriteDouble(double d) + { + if(internal::Double(d).IsNanOrInf()) + { + if(!(writeFlags & kWriteNanAndInfFlag)) + { + return false; + } + if(internal::Double(d).IsNan()) + { + PutReserve(*os_, 3); + PutUnsafe(*os_, 'N'); + PutUnsafe(*os_, 'a'); + PutUnsafe(*os_, 'N'); + return true; + } + if(internal::Double(d).Sign()) + { + PutReserve(*os_, 9); + PutUnsafe(*os_, '-'); + } + else + { + PutReserve(*os_, 8); + } + PutUnsafe(*os_, 'I'); + PutUnsafe(*os_, 'n'); + PutUnsafe(*os_, 'f'); + PutUnsafe(*os_, 'i'); + PutUnsafe(*os_, 'n'); + PutUnsafe(*os_, 'i'); + PutUnsafe(*os_, 't'); + PutUnsafe(*os_, 'y'); + return true; + } - char buffer[25]; - char* end = internal::dtoa(d, buffer, maxDecimalPlaces_); - PutReserve(*os_, static_cast(end - buffer)); - for (char* p = buffer; p != end; ++p) - PutUnsafe(*os_, static_cast(*p)); - return true; - } + char buffer[25]; + char* end = internal::dtoa(d, buffer, maxDecimalPlaces_); + PutReserve(*os_, static_cast(end - buffer)); + for(char* p = buffer; p != end; ++p) + { + PutUnsafe(*os_, static_cast(*p)); + } + return true; + } - bool WriteString(const Ch* str, SizeType length) { - static const typename TargetEncoding::Ch hexDigits[16] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' }; - static const char escape[256] = { + bool WriteString(const Ch* str, SizeType length) + { + static const typename TargetEncoding::Ch hexDigits[16] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' }; + static const char escape[256] = + { #define Z16 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 - //0 1 2 3 4 5 6 7 8 9 A B C D E F - 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'b', 't', 'n', 'u', 'f', 'r', 'u', 'u', // 00 - 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', // 10 - 0, 0, '"', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 20 - Z16, Z16, // 30~4F - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,'\\', 0, 0, 0, // 50 - Z16, Z16, Z16, Z16, Z16, Z16, Z16, Z16, Z16, Z16 // 60~FF + //0 1 2 3 4 5 6 7 8 9 A B C D E F + 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'b', 't', 'n', 'u', 'f', 'r', 'u', 'u', // 00 + 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', // 10 + 0, 0, '"', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 20 + Z16, Z16, // 30~4F + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, '\\', 0, 0, 0, // 50 + Z16, Z16, Z16, Z16, Z16, Z16, Z16, Z16, Z16, Z16 // 60~FF #undef Z16 - }; + }; - if (TargetEncoding::supportUnicode) - PutReserve(*os_, 2 + length * 6); // "\uxxxx..." - else - PutReserve(*os_, 2 + length * 12); // "\uxxxx\uyyyy..." + if(TargetEncoding::supportUnicode) + { + PutReserve(*os_, 2 + length * 6); // "\uxxxx..." + } + else + { + PutReserve(*os_, 2 + length * 12); // "\uxxxx\uyyyy..." + } - PutUnsafe(*os_, '\"'); - GenericStringStream is(str); - while (ScanWriteUnescapedString(is, length)) { - const Ch c = is.Peek(); - if (!TargetEncoding::supportUnicode && static_cast(c) >= 0x80) { - // Unicode escaping - unsigned codepoint; - if (RAPIDJSON_UNLIKELY(!SourceEncoding::Decode(is, &codepoint))) - return false; - PutUnsafe(*os_, '\\'); - PutUnsafe(*os_, 'u'); - if (codepoint <= 0xD7FF || (codepoint >= 0xE000 && codepoint <= 0xFFFF)) { - PutUnsafe(*os_, hexDigits[(codepoint >> 12) & 15]); - PutUnsafe(*os_, hexDigits[(codepoint >> 8) & 15]); - PutUnsafe(*os_, hexDigits[(codepoint >> 4) & 15]); - PutUnsafe(*os_, hexDigits[(codepoint ) & 15]); - } - else { - RAPIDJSON_ASSERT(codepoint >= 0x010000 && codepoint <= 0x10FFFF); - // Surrogate pair - unsigned s = codepoint - 0x010000; - unsigned lead = (s >> 10) + 0xD800; - unsigned trail = (s & 0x3FF) + 0xDC00; - PutUnsafe(*os_, hexDigits[(lead >> 12) & 15]); - PutUnsafe(*os_, hexDigits[(lead >> 8) & 15]); - PutUnsafe(*os_, hexDigits[(lead >> 4) & 15]); - PutUnsafe(*os_, hexDigits[(lead ) & 15]); - PutUnsafe(*os_, '\\'); - PutUnsafe(*os_, 'u'); - PutUnsafe(*os_, hexDigits[(trail >> 12) & 15]); - PutUnsafe(*os_, hexDigits[(trail >> 8) & 15]); - PutUnsafe(*os_, hexDigits[(trail >> 4) & 15]); - PutUnsafe(*os_, hexDigits[(trail ) & 15]); - } - } - else if ((sizeof(Ch) == 1 || static_cast(c) < 256) && RAPIDJSON_UNLIKELY(escape[static_cast(c)])) { - is.Take(); - PutUnsafe(*os_, '\\'); - PutUnsafe(*os_, static_cast(escape[static_cast(c)])); - if (escape[static_cast(c)] == 'u') { - PutUnsafe(*os_, '0'); - PutUnsafe(*os_, '0'); - PutUnsafe(*os_, hexDigits[static_cast(c) >> 4]); - PutUnsafe(*os_, hexDigits[static_cast(c) & 0xF]); - } - } - else if (RAPIDJSON_UNLIKELY(!(writeFlags & kWriteValidateEncodingFlag ? - Transcoder::Validate(is, *os_) : - Transcoder::TranscodeUnsafe(is, *os_)))) - return false; - } - PutUnsafe(*os_, '\"'); - return true; - } + PutUnsafe(*os_, '\"'); + GenericStringStream is(str); + while(ScanWriteUnescapedString(is, length)) + { + const Ch c = is.Peek(); + if(!TargetEncoding::supportUnicode && static_cast(c) >= 0x80) + { + // Unicode escaping + unsigned codepoint; + if(RAPIDJSON_UNLIKELY(!SourceEncoding::Decode(is, &codepoint))) + { + return false; + } + PutUnsafe(*os_, '\\'); + PutUnsafe(*os_, 'u'); + if(codepoint <= 0xD7FF || (codepoint >= 0xE000 && codepoint <= 0xFFFF)) + { + PutUnsafe(*os_, hexDigits[(codepoint >> 12) & 15]); + PutUnsafe(*os_, hexDigits[(codepoint >> 8) & 15]); + PutUnsafe(*os_, hexDigits[(codepoint >> 4) & 15]); + PutUnsafe(*os_, hexDigits[(codepoint) & 15]); + } + else + { + RAPIDJSON_ASSERT(codepoint >= 0x010000 && codepoint <= 0x10FFFF); + // Surrogate pair + unsigned s = codepoint - 0x010000; + unsigned lead = (s >> 10) + 0xD800; + unsigned trail = (s & 0x3FF) + 0xDC00; + PutUnsafe(*os_, hexDigits[(lead >> 12) & 15]); + PutUnsafe(*os_, hexDigits[(lead >> 8) & 15]); + PutUnsafe(*os_, hexDigits[(lead >> 4) & 15]); + PutUnsafe(*os_, hexDigits[(lead) & 15]); + PutUnsafe(*os_, '\\'); + PutUnsafe(*os_, 'u'); + PutUnsafe(*os_, hexDigits[(trail >> 12) & 15]); + PutUnsafe(*os_, hexDigits[(trail >> 8) & 15]); + PutUnsafe(*os_, hexDigits[(trail >> 4) & 15]); + PutUnsafe(*os_, hexDigits[(trail) & 15]); + } + } + else if((sizeof(Ch) == 1 || static_cast(c) < 256) && + RAPIDJSON_UNLIKELY(escape[static_cast(c)])) + { + is.Take(); + PutUnsafe(*os_, '\\'); + PutUnsafe(*os_, static_cast(escape[static_cast(c)])); + if(escape[static_cast(c)] == 'u') + { + PutUnsafe(*os_, '0'); + PutUnsafe(*os_, '0'); + PutUnsafe(*os_, hexDigits[static_cast(c) >> 4]); + PutUnsafe(*os_, hexDigits[static_cast(c) & 0xF]); + } + } + else if(RAPIDJSON_UNLIKELY(!(writeFlags & kWriteValidateEncodingFlag ? + Transcoder::Validate(is, *os_) : + Transcoder::TranscodeUnsafe(is, *os_)))) + { + return false; + } + } + PutUnsafe(*os_, '\"'); + return true; + } - bool ScanWriteUnescapedString(GenericStringStream& is, size_t length) { - return RAPIDJSON_LIKELY(is.Tell() < length); - } + bool ScanWriteUnescapedString(GenericStringStream & is, size_t length) + { + return RAPIDJSON_LIKELY(is.Tell() < length); + } - bool WriteStartObject() { os_->Put('{'); return true; } - bool WriteEndObject() { os_->Put('}'); return true; } - bool WriteStartArray() { os_->Put('['); return true; } - bool WriteEndArray() { os_->Put(']'); return true; } + bool WriteStartObject() + { + os_->Put('{'); + return true; + } + bool WriteEndObject() + { + os_->Put('}'); + return true; + } + bool WriteStartArray() + { + os_->Put('['); + return true; + } + bool WriteEndArray() + { + os_->Put(']'); + return true; + } - bool WriteRawValue(const Ch* json, size_t length) { - PutReserve(*os_, length); - for (size_t i = 0; i < length; i++) { - RAPIDJSON_ASSERT(json[i] != '\0'); - PutUnsafe(*os_, json[i]); - } - return true; - } + bool WriteRawValue(const Ch* json, size_t length) + { + PutReserve(*os_, length); + for(size_t i = 0; i < length; i++) + { + RAPIDJSON_ASSERT(json[i] != '\0'); + PutUnsafe(*os_, json[i]); + } + return true; + } - void Prefix(Type type) { - (void)type; - if (RAPIDJSON_LIKELY(level_stack_.GetSize() != 0)) { // this value is not at root - Level* level = level_stack_.template Top(); - if (level->valueCount > 0) { - if (level->inArray) - os_->Put(','); // add comma if it is not the first element in array - else // in object - os_->Put((level->valueCount % 2 == 0) ? ',' : ':'); - } - if (!level->inArray && level->valueCount % 2 == 0) - RAPIDJSON_ASSERT(type == kStringType); // if it's in object, then even number should be a name - level->valueCount++; - } - else { - RAPIDJSON_ASSERT(!hasRoot_); // Should only has one and only one root. - hasRoot_ = true; - } - } + void Prefix(Type type) + { + (void)type; + if(RAPIDJSON_LIKELY(level_stack_.GetSize() != 0)) // this value is not at root + { + Level* level = level_stack_.template Top(); + if(level->valueCount > 0) + { + if(level->inArray) + { + os_->Put(','); // add comma if it is not the first element in array + } + else // in object + { + os_->Put((level->valueCount % 2 == 0) ? ',' : ':'); + } + } + if(!level->inArray && level->valueCount % 2 == 0) + { + RAPIDJSON_ASSERT(type == kStringType); // if it's in object, then even number should be a name + } + level->valueCount++; + } + else + { + RAPIDJSON_ASSERT(!hasRoot_); // Should only has one and only one root. + hasRoot_ = true; + } + } - // Flush the value if it is the top level one. - bool EndValue(bool ret) { - if (RAPIDJSON_UNLIKELY(level_stack_.Empty())) // end of json text - os_->Flush(); - return ret; - } + // Flush the value if it is the top level one. + bool EndValue(bool ret) + { + if(RAPIDJSON_UNLIKELY(level_stack_.Empty())) // end of json text + { + os_->Flush(); + } + return ret; + } - OutputStream* os_; - internal::Stack level_stack_; - int maxDecimalPlaces_; - bool hasRoot_; + OutputStream* os_; + internal::Stack level_stack_; + int maxDecimalPlaces_; + bool hasRoot_; private: - // Prohibit copy constructor & assignment operator. - Writer(const Writer&); - Writer& operator=(const Writer&); + // Prohibit copy constructor & assignment operator. + Writer(const Writer &); + Writer & operator=(const Writer &); }; // Full specialization for StringStream to prevent memory copying template<> -inline bool Writer::WriteInt(int i) { - char *buffer = os_->Push(11); - const char* end = internal::i32toa(i, buffer); - os_->Pop(static_cast(11 - (end - buffer))); - return true; +inline bool Writer::WriteInt(int i) +{ + char* buffer = os_->Push(11); + const char* end = internal::i32toa(i, buffer); + os_->Pop(static_cast(11 - (end - buffer))); + return true; } template<> -inline bool Writer::WriteUint(unsigned u) { - char *buffer = os_->Push(10); - const char* end = internal::u32toa(u, buffer); - os_->Pop(static_cast(10 - (end - buffer))); - return true; +inline bool Writer::WriteUint(unsigned u) +{ + char* buffer = os_->Push(10); + const char* end = internal::u32toa(u, buffer); + os_->Pop(static_cast(10 - (end - buffer))); + return true; } template<> -inline bool Writer::WriteInt64(int64_t i64) { - char *buffer = os_->Push(21); - const char* end = internal::i64toa(i64, buffer); - os_->Pop(static_cast(21 - (end - buffer))); - return true; +inline bool Writer::WriteInt64(int64_t i64) +{ + char* buffer = os_->Push(21); + const char* end = internal::i64toa(i64, buffer); + os_->Pop(static_cast(21 - (end - buffer))); + return true; } template<> -inline bool Writer::WriteUint64(uint64_t u) { - char *buffer = os_->Push(20); - const char* end = internal::u64toa(u, buffer); - os_->Pop(static_cast(20 - (end - buffer))); - return true; +inline bool Writer::WriteUint64(uint64_t u) +{ + char* buffer = os_->Push(20); + const char* end = internal::u64toa(u, buffer); + os_->Pop(static_cast(20 - (end - buffer))); + return true; } template<> -inline bool Writer::WriteDouble(double d) { - if (internal::Double(d).IsNanOrInf()) { - // Note: This code path can only be reached if (RAPIDJSON_WRITE_DEFAULT_FLAGS & kWriteNanAndInfFlag). - if (!(kWriteDefaultFlags & kWriteNanAndInfFlag)) - return false; - if (internal::Double(d).IsNan()) { - PutReserve(*os_, 3); - PutUnsafe(*os_, 'N'); PutUnsafe(*os_, 'a'); PutUnsafe(*os_, 'N'); - return true; - } - if (internal::Double(d).Sign()) { - PutReserve(*os_, 9); - PutUnsafe(*os_, '-'); - } - else - PutReserve(*os_, 8); - PutUnsafe(*os_, 'I'); PutUnsafe(*os_, 'n'); PutUnsafe(*os_, 'f'); - PutUnsafe(*os_, 'i'); PutUnsafe(*os_, 'n'); PutUnsafe(*os_, 'i'); PutUnsafe(*os_, 't'); PutUnsafe(*os_, 'y'); - return true; - } - - char *buffer = os_->Push(25); - char* end = internal::dtoa(d, buffer, maxDecimalPlaces_); - os_->Pop(static_cast(25 - (end - buffer))); - return true; +inline bool Writer::WriteDouble(double d) +{ + if(internal::Double(d).IsNanOrInf()) + { + // Note: This code path can only be reached if (RAPIDJSON_WRITE_DEFAULT_FLAGS & kWriteNanAndInfFlag). + if(!(kWriteDefaultFlags & kWriteNanAndInfFlag)) + { + return false; + } + if(internal::Double(d).IsNan()) + { + PutReserve(*os_, 3); + PutUnsafe(*os_, 'N'); + PutUnsafe(*os_, 'a'); + PutUnsafe(*os_, 'N'); + return true; + } + if(internal::Double(d).Sign()) + { + PutReserve(*os_, 9); + PutUnsafe(*os_, '-'); + } + else + { + PutReserve(*os_, 8); + } + PutUnsafe(*os_, 'I'); + PutUnsafe(*os_, 'n'); + PutUnsafe(*os_, 'f'); + PutUnsafe(*os_, 'i'); + PutUnsafe(*os_, 'n'); + PutUnsafe(*os_, 'i'); + PutUnsafe(*os_, 't'); + PutUnsafe(*os_, 'y'); + return true; + } + + char* buffer = os_->Push(25); + char* end = internal::dtoa(d, buffer, maxDecimalPlaces_); + os_->Pop(static_cast(25 - (end - buffer))); + return true; } #if defined(RAPIDJSON_SSE2) || defined(RAPIDJSON_SSE42) template<> -inline bool Writer::ScanWriteUnescapedString(StringStream& is, size_t length) { - if (length < 16) - return RAPIDJSON_LIKELY(is.Tell() < length); +inline bool Writer::ScanWriteUnescapedString(StringStream & is, size_t length) +{ + if(length < 16) + { + return RAPIDJSON_LIKELY(is.Tell() < length); + } - if (!RAPIDJSON_LIKELY(is.Tell() < length)) - return false; + if(!RAPIDJSON_LIKELY(is.Tell() < length)) + { + return false; + } - const char* p = is.src_; - const char* end = is.head_ + length; - const char* nextAligned = reinterpret_cast((reinterpret_cast(p) + 15) & static_cast(~15)); - const char* endAligned = reinterpret_cast(reinterpret_cast(end) & static_cast(~15)); - if (nextAligned > end) - return true; + const char* p = is.src_; + const char* end = is.head_ + length; + const char* nextAligned = reinterpret_cast((reinterpret_cast + (p) + 15) & static_cast(~15)); + const char* endAligned = reinterpret_cast(reinterpret_cast(end) & static_cast + (~15)); + if(nextAligned > end) + { + return true; + } - while (p != nextAligned) - if (*p < 0x20 || *p == '\"' || *p == '\\') { - is.src_ = p; - return RAPIDJSON_LIKELY(is.Tell() < length); - } - else - os_->PutUnsafe(*p++); + while(p != nextAligned) + if(*p < 0x20 || *p == '\"' || *p == '\\') + { + is.src_ = p; + return RAPIDJSON_LIKELY(is.Tell() < length); + } + else + { + os_->PutUnsafe(*p++); + } - // The rest of string using SIMD - static const char dquote[16] = { '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"' }; - static const char bslash[16] = { '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\' }; - static const char space[16] = { 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19 }; - const __m128i dq = _mm_loadu_si128(reinterpret_cast(&dquote[0])); - const __m128i bs = _mm_loadu_si128(reinterpret_cast(&bslash[0])); - const __m128i sp = _mm_loadu_si128(reinterpret_cast(&space[0])); + // The rest of string using SIMD + static const char dquote[16] = { '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"' }; + static const char bslash[16] = { '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\' }; + static const char space[16] = { 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19 }; + const __m128i dq = _mm_loadu_si128(reinterpret_cast(&dquote[0])); + const __m128i bs = _mm_loadu_si128(reinterpret_cast(&bslash[0])); + const __m128i sp = _mm_loadu_si128(reinterpret_cast(&space[0])); - for (; p != endAligned; p += 16) { - const __m128i s = _mm_load_si128(reinterpret_cast(p)); - const __m128i t1 = _mm_cmpeq_epi8(s, dq); - const __m128i t2 = _mm_cmpeq_epi8(s, bs); - const __m128i t3 = _mm_cmpeq_epi8(_mm_max_epu8(s, sp), sp); // s < 0x20 <=> max(s, 0x19) == 0x19 - const __m128i x = _mm_or_si128(_mm_or_si128(t1, t2), t3); - unsigned short r = static_cast(_mm_movemask_epi8(x)); - if (RAPIDJSON_UNLIKELY(r != 0)) { // some of characters is escaped - SizeType len; + for(; p != endAligned; p += 16) + { + const __m128i s = _mm_load_si128(reinterpret_cast(p)); + const __m128i t1 = _mm_cmpeq_epi8(s, dq); + const __m128i t2 = _mm_cmpeq_epi8(s, bs); + const __m128i t3 = _mm_cmpeq_epi8(_mm_max_epu8(s, sp), sp); // s < 0x20 <=> max(s, 0x19) == 0x19 + const __m128i x = _mm_or_si128(_mm_or_si128(t1, t2), t3); + unsigned short r = static_cast(_mm_movemask_epi8(x)); + if(RAPIDJSON_UNLIKELY(r != 0)) // some of characters is escaped + { + SizeType len; #ifdef _MSC_VER // Find the index of first escaped - unsigned long offset; - _BitScanForward(&offset, r); - len = offset; + unsigned long offset; + _BitScanForward(&offset, r); + len = offset; #else - len = static_cast(__builtin_ffs(r) - 1); + len = static_cast(__builtin_ffs(r) - 1); #endif - char* q = reinterpret_cast(os_->PushUnsafe(len)); - for (size_t i = 0; i < len; i++) - q[i] = p[i]; + char* q = reinterpret_cast(os_->PushUnsafe(len)); + for(size_t i = 0; i < len; i++) + { + q[i] = p[i]; + } - p += len; - break; - } - _mm_storeu_si128(reinterpret_cast<__m128i *>(os_->PushUnsafe(16)), s); - } + p += len; + break; + } + _mm_storeu_si128(reinterpret_cast<__m128i*>(os_->PushUnsafe(16)), s); + } - is.src_ = p; - return RAPIDJSON_LIKELY(is.Tell() < length); + is.src_ = p; + return RAPIDJSON_LIKELY(is.Tell() < length); } #endif // defined(RAPIDJSON_SSE2) || defined(RAPIDJSON_SSE42) diff --git a/src/App.cpp b/src/App.cpp index d656acc8..1373698d 100644 --- a/src/App.cpp +++ b/src/App.cpp @@ -52,188 +52,198 @@ #endif -App *App::m_self = nullptr; +App* App::m_self = nullptr; -App::App(int argc, char **argv) : - m_console(nullptr), - m_httpd(nullptr), - m_network(nullptr), - m_options(nullptr) +App::App(int argc, char** argv) : + m_console(nullptr), + m_httpd(nullptr), + m_network(nullptr), + m_options(nullptr) { - m_self = this; + m_self = this; - Cpu::init(); - m_options = Options::parse(argc, argv); - if (!m_options) { - return; - } + Cpu::init(); + m_options = Options::parse(argc, argv); + if(!m_options) + { + return; + } - Log::init(); + Log::init(); - if (!m_options->background()) { - Log::add(new ConsoleLog(m_options->colors())); - m_console = new Console(this); - } + if(!m_options->background()) + { + Log::add(new ConsoleLog(m_options->colors())); + m_console = new Console(this); + } - if (m_options->logFile()) { - Log::add(new FileLog(m_options->logFile())); - } + if(0 < m_options->logFile().size()) + { + Log::add(new FileLog(m_options->logFile())); + } # ifdef HAVE_SYSLOG_H - if (m_options->syslog()) { - Log::add(new SysLog()); - } + if(m_options->syslog()) + { + Log::add(new SysLog()); + } # endif - Platform::init(m_options->userAgent()); - Platform::setProcessPriority(m_options->priority()); + Platform::init(m_options->userAgent()); + Platform::setProcessPriority(m_options->priority()); - m_network = new Network(m_options); + m_network = new Network(m_options); - uv_signal_init(uv_default_loop(), &m_sigHUP); - uv_signal_init(uv_default_loop(), &m_sigINT); - uv_signal_init(uv_default_loop(), &m_sigTERM); + uv_signal_init(uv_default_loop(), &m_sigHUP); + uv_signal_init(uv_default_loop(), &m_sigINT); + uv_signal_init(uv_default_loop(), &m_sigTERM); } App::~App() { - uv_tty_reset_mode(); + uv_tty_reset_mode(); # ifndef XMRIG_NO_HTTPD - delete m_httpd; + delete m_httpd; # endif - delete m_console; + delete m_console; } int App::exec() { - if (!m_options) { - return 2; - } + if(!m_options) + { + return 2; + } - uv_signal_start(&m_sigHUP, App::onSignal, SIGHUP); - uv_signal_start(&m_sigINT, App::onSignal, SIGINT); - uv_signal_start(&m_sigTERM, App::onSignal, SIGTERM); + uv_signal_start(&m_sigHUP, App::onSignal, SIGHUP); + uv_signal_start(&m_sigINT, App::onSignal, SIGINT); + uv_signal_start(&m_sigTERM, App::onSignal, SIGTERM); - background(); + background(); - if (!CryptoNight::init(m_options->algo(), m_options->algoVariant())) { - LOG_ERR("\"%s\" hash self-test failed.", m_options->algoName()); - return 1; - } + if(!CryptoNight::init(m_options->algo(), m_options->algoVariant())) + { + return 1; + } - Mem::allocate(m_options->algo(), m_options->threads(), m_options->doubleHash(), m_options->hugePages()); - Summary::print(); + Mem::allocate(m_options->algo(), m_options->threads(), m_options->doubleHash(), m_options->hugePages()); + Summary::print(); - if (m_options->dryRun()) { - LOG_NOTICE("OK"); - release(); + if(m_options->dryRun()) + { + LOG_NOTICE("OK"); + release(); - return 0; - } + return 0; + } # ifndef XMRIG_NO_API - Api::start(); + Api::start(); # endif # ifndef XMRIG_NO_HTTPD - m_httpd = new Httpd(m_options->apiPort(), m_options->apiToken()); - m_httpd->start(); + m_httpd = new Httpd(m_options->apiPort(), m_options->apiToken()); + m_httpd->start(); # endif - Workers::start(m_options->affinity(), m_options->priority()); + Workers::start(m_options->affinity(), m_options->priority()); - m_network->connect(); + m_network->connect(); - const int r = uv_run(uv_default_loop(), UV_RUN_DEFAULT); - uv_loop_close(uv_default_loop()); + const int r = uv_run(uv_default_loop(), UV_RUN_DEFAULT); + uv_loop_close(uv_default_loop()); - release(); - return r; + release(); + return r; } void App::onConsoleCommand(char command) { - switch (command) { - case 'h': - case 'H': - Workers::printHashrate(true); - break; + switch(command) + { + case 'h': + case 'H': + Workers::printHashrate(true); + break; - case 'p': - case 'P': - if (Workers::isEnabled()) { - LOG_INFO(m_options->colors() ? "\x1B[01;33mpaused\x1B[0m, press \x1B[01;35mr\x1B[0m to resume" : "paused, press 'r' to resume"); - Workers::setEnabled(false); - } - break; + case 'p': + case 'P': + if(Workers::isEnabled()) + { + LOG_INFO("paused, press 'r' to resume"); + Workers::setEnabled(false); + } + break; - case 'r': - case 'R': - if (!Workers::isEnabled()) { - LOG_INFO(m_options->colors() ? "\x1B[01;32mresumed" : "resumed"); - Workers::setEnabled(true); - } - break; + case 'r': + case 'R': + if(!Workers::isEnabled()) + { + LOG_INFO((m_options->colors() ? "\x1B[01;32mresumed" : "resumed")); + Workers::setEnabled(true); + } + break; - case 3: - LOG_WARN("Ctrl+C received, exiting"); - close(); - break; + case 3: + LOG_WARN("Ctrl+C received, exiting"); + close(); + break; - default: - break; - } + default: + break; + } } void App::close() { - m_network->stop(); - Workers::stop(); + m_network->stop(); + Workers::stop(); - uv_stop(uv_default_loop()); + uv_stop(uv_default_loop()); } void App::release() { - if (m_network) { - delete m_network; - } + if(m_network) + { + delete m_network; + } - Options::release(); - Mem::release(); - Platform::release(); + Options::release(); + Mem::release(); + Platform::release(); } -void App::onSignal(uv_signal_t *handle, int signum) +void App::onSignal(uv_signal_t* handle, int signum) { - switch (signum) - { - case SIGHUP: - LOG_WARN("SIGHUP received, exiting"); - break; + switch(signum) + { + case SIGHUP: + LOG_WARN("SIGHUP received, exiting"); + break; - case SIGTERM: - LOG_WARN("SIGTERM received, exiting"); - break; + case SIGTERM: + LOG_WARN("SIGTERM received, exiting"); + break; - case SIGINT: - LOG_WARN("SIGINT received, exiting"); - break; + case SIGINT: + LOG_WARN("SIGINT received, exiting"); + break; - default: - break; - } + default: + break; + } - uv_signal_stop(handle); - m_self->close(); + uv_signal_stop(handle); + m_self->close(); } diff --git a/src/App.h b/src/App.h index 1b96040d..0f051892 100644 --- a/src/App.h +++ b/src/App.h @@ -40,30 +40,30 @@ class Options; class App : public IConsoleListener { public: - App(int argc, char **argv); - ~App(); + App(int argc, char** argv); + ~App(); - int exec(); + int exec(); protected: - void onConsoleCommand(char command) override; + void onConsoleCommand(char command) override; private: - void background(); - void close(); - void release(); + void background(); + void close(); + void release(); - static void onSignal(uv_signal_t *handle, int signum); + static void onSignal(uv_signal_t* handle, int signum); - static App *m_self; + static App* m_self; - Console *m_console; - Httpd *m_httpd; - Network *m_network; - Options *m_options; - uv_signal_t m_sigHUP; - uv_signal_t m_sigINT; - uv_signal_t m_sigTERM; + Console* m_console; + Httpd* m_httpd; + Network* m_network; + Options* m_options; + uv_signal_t m_sigHUP; + uv_signal_t m_sigINT; + uv_signal_t m_sigTERM; }; diff --git a/src/App_unix.cpp b/src/App_unix.cpp index 66957208..1a2227b5 100644 --- a/src/App_unix.cpp +++ b/src/App_unix.cpp @@ -20,7 +20,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - +#ifndef _WIN32 #include #include @@ -36,31 +36,39 @@ void App::background() { - if (m_options->affinity() != -1L) { - Cpu::setAffinity(-1, m_options->affinity()); - } + if(m_options->affinity() != -1L) + { + Cpu::setAffinity(-1, m_options->affinity()); + } - if (!m_options->background()) { - return; - } + if(!m_options->background()) + { + return; + } - int i = fork(); - if (i < 0) { - exit(1); - } + int i = fork(); + if(i < 0) + { + exit(1); + } - if (i > 0) { - exit(0); - } + if(i > 0) + { + exit(0); + } - i = setsid(); + i = setsid(); - if (i < 0) { - LOG_ERR("setsid() failed (errno = %d)", errno); - } + if(i < 0) + { + LOG_ERR("setsid() failed (errno = " << errno << ")"); + } - i = chdir("/"); - if (i < 0) { - LOG_ERR("chdir() failed (errno = %d)", errno); - } + i = chdir("/"); + if(i < 0) + { + LOG_ERR("chdir() failed (errno = " << errno << ")"); + } } + +#endif diff --git a/src/App_win.cpp b/src/App_win.cpp index 895f3bdf..0bc0f6e9 100644 --- a/src/App_win.cpp +++ b/src/App_win.cpp @@ -33,20 +33,25 @@ void App::background() { - if (m_options->affinity() != -1L) { - Cpu::setAffinity(-1, m_options->affinity()); - } + if(m_options->affinity() != -1L) + { + Cpu::setAffinity(-1, m_options->affinity()); + } - if (!m_options->background()) { - return; - } + if(!m_options->background()) + { + return; + } - HWND hcon = GetConsoleWindow(); - if (hcon) { - ShowWindow(hcon, SW_HIDE); - } else { - HANDLE h = GetStdHandle(STD_OUTPUT_HANDLE); - CloseHandle(h); - FreeConsole(); - } + HWND hcon = GetConsoleWindow(); + if(hcon) + { + ShowWindow(hcon, SW_HIDE); + } + else + { + HANDLE h = GetStdHandle(STD_OUTPUT_HANDLE); + CloseHandle(h); + FreeConsole(); + } } diff --git a/src/Console.cpp b/src/Console.cpp index 3d95ada4..991cfd44 100644 --- a/src/Console.cpp +++ b/src/Console.cpp @@ -26,36 +26,39 @@ #include "interfaces/IConsoleListener.h" -Console::Console(IConsoleListener *listener) - : m_listener(listener) +Console::Console(IConsoleListener* listener) + : m_listener(listener) { - m_tty.data = this; - uv_tty_init(uv_default_loop(), &m_tty, 0, 1); + m_tty.data = this; + uv_tty_init(uv_default_loop(), &m_tty, 0, 1); - if (!uv_is_readable(reinterpret_cast(&m_tty))) { - return; - } + if(!uv_is_readable(reinterpret_cast(&m_tty))) + { + return; + } - uv_tty_set_mode(&m_tty, UV_TTY_MODE_RAW); - uv_read_start(reinterpret_cast(&m_tty), Console::onAllocBuffer, Console::onRead); + uv_tty_set_mode(&m_tty, UV_TTY_MODE_RAW); + uv_read_start(reinterpret_cast(&m_tty), Console::onAllocBuffer, Console::onRead); } -void Console::onAllocBuffer(uv_handle_t *handle, size_t suggested_size, uv_buf_t *buf) +void Console::onAllocBuffer(uv_handle_t* handle, size_t suggested_size, uv_buf_t* buf) { - auto console = static_cast(handle->data); - buf->len = 1; - buf->base = console->m_buf; + auto console = static_cast(handle->data); + buf->len = 1; + buf->base = console->m_buf; } -void Console::onRead(uv_stream_t *stream, ssize_t nread, const uv_buf_t *buf) +void Console::onRead(uv_stream_t* stream, ssize_t nread, const uv_buf_t* buf) { - if (nread < 0) { - return uv_close(reinterpret_cast(stream), nullptr); - } + if(nread < 0) + { + return uv_close(reinterpret_cast(stream), nullptr); + } - if (nread == 1) { - static_cast(stream->data)->m_listener->onConsoleCommand(buf->base[0]); - } + if(nread == 1) + { + static_cast(stream->data)->m_listener->onConsoleCommand(buf->base[0]); + } } diff --git a/src/Console.h b/src/Console.h index bde95d7d..1331183f 100644 --- a/src/Console.h +++ b/src/Console.h @@ -34,15 +34,15 @@ class IConsoleListener; class Console { public: - Console(IConsoleListener *listener); + Console(IConsoleListener* listener); private: - static void onAllocBuffer(uv_handle_t *handle, size_t suggested_size, uv_buf_t *buf); - static void onRead(uv_stream_t *stream, ssize_t nread, const uv_buf_t *buf); + static void onAllocBuffer(uv_handle_t* handle, size_t suggested_size, uv_buf_t* buf); + static void onRead(uv_stream_t* stream, ssize_t nread, const uv_buf_t* buf); - char m_buf[1]; - IConsoleListener *m_listener; - uv_tty_t m_tty; + char m_buf[1]; + IConsoleListener* m_listener; + uv_tty_t m_tty; }; diff --git a/src/Cpu.cpp b/src/Cpu.cpp index a619781e..24a68e52 100644 --- a/src/Cpu.cpp +++ b/src/Cpu.cpp @@ -41,84 +41,98 @@ int Cpu::m_totalThreads = 0; int Cpu::optimalThreadsCount(int algo, bool doubleHash, int maxCpuUsage) { - if (m_totalThreads == 1) { - return 1; - } + if(m_totalThreads == 1) + { + return 1; + } - int cache = 0; - if (m_l3_cache) { - cache = m_l2_exclusive ? (m_l2_cache + m_l3_cache) : m_l3_cache; - } - else { - cache = m_l2_cache; - } + int cache = 0; + if(m_l3_cache) + { + cache = m_l2_exclusive ? (m_l2_cache + m_l3_cache) : m_l3_cache; + } + else + { + cache = m_l2_cache; + } - int count = 0; - const int size = (algo ? 1024 : 2048) * (doubleHash ? 2 : 1); + int count = 0; + const int size = (algo ? 1024 : 2048) * (doubleHash ? 2 : 1); - if (cache) { - count = cache / size; - } - else { - count = m_totalThreads / 2; - } + if(cache) + { + count = cache / size; + } + else + { + count = m_totalThreads / 2; + } - if (count > m_totalThreads) { - count = m_totalThreads; - } + if(count > m_totalThreads) + { + count = m_totalThreads; + } - if (((float) count / m_totalThreads * 100) > maxCpuUsage) { - count = (int) ceil((float) m_totalThreads * (maxCpuUsage / 100.0)); - } + if(((float) count / m_totalThreads * 100) > maxCpuUsage) + { + count = (int) ceil((float) m_totalThreads * (maxCpuUsage / 100.0)); + } - return count < 1 ? 1 : count; + return count < 1 ? 1 : count; } void Cpu::initCommon() { - struct cpu_raw_data_t raw = { 0 }; - struct cpu_id_t data = { 0 }; + struct cpu_raw_data_t raw = { 0 }; + struct cpu_id_t data = { 0 }; - cpuid_get_raw_data(&raw); - cpu_identify(&raw, &data); + cpuid_get_raw_data(&raw); + cpu_identify(&raw, &data); - strncpy(m_brand, data.brand_str, sizeof(m_brand) - 1); + strncpy(m_brand, data.brand_str, sizeof(m_brand) - 1); - m_totalThreads = data.total_logical_cpus; - m_sockets = m_totalThreads / data.num_logical_cpus; + m_totalThreads = data.total_logical_cpus; + m_sockets = m_totalThreads / data.num_logical_cpus; - if (m_sockets == 0) { - m_sockets = 1; - } + if(m_sockets == 0) + { + m_sockets = 1; + } - m_totalCores = data.num_cores * m_sockets; - m_l3_cache = data.l3_cache > 0 ? data.l3_cache * m_sockets : 0; + m_totalCores = data.num_cores * m_sockets; + m_l3_cache = data.l3_cache > 0 ? data.l3_cache * m_sockets : 0; - // Workaround for AMD CPUs https://github.com/anrieff/libcpuid/issues/97 - if (data.vendor == VENDOR_AMD && data.ext_family >= 0x15 && data.ext_family < 0x17) { - m_l2_cache = data.l2_cache * (m_totalCores / 2) * m_sockets; - m_l2_exclusive = true; - } - // Workaround for Intel Core Solo, Core Duo, Core 2 Duo, Core 2 Quad and their Xeon homologue - // These processors have L2 cache shared by 2 cores. - else if (data.vendor == VENDOR_INTEL && data.family == 0x06 && (data.model == 0x0E || data.model == 0x0F || data.model == 0x07)) { - int l2_count_per_socket = m_totalCores > 1 ? m_totalCores / 2 : 1; - m_l2_cache = data.l2_cache > 0 ? data.l2_cache * l2_count_per_socket * m_sockets : 0; - } - else{ - m_l2_cache = data.l2_cache > 0 ? data.l2_cache * m_totalCores * m_sockets : 0; - } + // Workaround for AMD CPUs https://github.com/anrieff/libcpuid/issues/97 + if(data.vendor == VENDOR_AMD && data.ext_family >= 0x15 && data.ext_family < 0x17) + { + m_l2_cache = data.l2_cache * (m_totalCores / 2) * m_sockets; + m_l2_exclusive = true; + } + // Workaround for Intel Core Solo, Core Duo, Core 2 Duo, Core 2 Quad and their Xeon homologue + // These processors have L2 cache shared by 2 cores. + else if(data.vendor == VENDOR_INTEL && data.family == 0x06 && (data.model == 0x0E || data.model == 0x0F || + data.model == 0x07)) + { + int l2_count_per_socket = m_totalCores > 1 ? m_totalCores / 2 : 1; + m_l2_cache = data.l2_cache > 0 ? data.l2_cache * l2_count_per_socket * m_sockets : 0; + } + else + { + m_l2_cache = data.l2_cache > 0 ? data.l2_cache * m_totalCores * m_sockets : 0; + } # if defined(__x86_64__) || defined(_M_AMD64) - m_flags |= X86_64; + m_flags |= X86_64; # endif - if (data.flags[CPU_FEATURE_AES]) { - m_flags |= AES; - } + if(data.flags[CPU_FEATURE_AES]) + { + m_flags |= AES; + } - if (data.flags[CPU_FEATURE_BMI2]) { - m_flags |= BMI2; - } + if(data.flags[CPU_FEATURE_BMI2]) + { + m_flags |= BMI2; + } } diff --git a/src/Cpu.h b/src/Cpu.h index 9444274d..4a69f91d 100644 --- a/src/Cpu.h +++ b/src/Cpu.h @@ -31,36 +31,61 @@ class Cpu { public: - enum Flags { - X86_64 = 1, - AES = 2, - BMI2 = 4 - }; + enum Flags + { + X86_64 = 1, + AES = 2, + BMI2 = 4 + }; - static int optimalThreadsCount(int algo, bool doubleHash, int maxCpuUsage); - static void init(); - static void setAffinity(int id, uint64_t mask); + static int optimalThreadsCount(int algo, bool doubleHash, int maxCpuUsage); + static void init(); + static void setAffinity(int id, uint64_t mask); - static inline bool hasAES() { return (m_flags & AES) != 0; } - static inline bool isX64() { return (m_flags & X86_64) != 0; } - static inline const char *brand() { return m_brand; } - static inline int cores() { return m_totalCores; } - static inline int l2() { return m_l2_cache; } - static inline int l3() { return m_l3_cache; } - static inline int sockets() { return m_sockets; } - static inline int threads() { return m_totalThreads; } + static inline bool hasAES() + { + return (m_flags & AES) != 0; + } + static inline bool isX64() + { + return (m_flags & X86_64) != 0; + } + static inline const char* brand() + { + return m_brand; + } + static inline int cores() + { + return m_totalCores; + } + static inline int l2() + { + return m_l2_cache; + } + static inline int l3() + { + return m_l3_cache; + } + static inline int sockets() + { + return m_sockets; + } + static inline int threads() + { + return m_totalThreads; + } private: - static void initCommon(); + static void initCommon(); - static bool m_l2_exclusive; - static char m_brand[64]; - static int m_flags; - static int m_l2_cache; - static int m_l3_cache; - static int m_sockets; - static int m_totalCores; - static int m_totalThreads; + static bool m_l2_exclusive; + static char m_brand[64]; + static int m_flags; + static int m_l2_cache; + static int m_l3_cache; + static int m_sockets; + static int m_totalCores; + static int m_totalThreads; }; diff --git a/src/Cpu_arm.cpp b/src/Cpu_arm.cpp index c2047ffb..042e8ee2 100644 --- a/src/Cpu_arm.cpp +++ b/src/Cpu_arm.cpp @@ -20,7 +20,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - +#ifndef _WIN32 #include @@ -39,16 +39,18 @@ int Cpu::m_totalThreads = 0; int Cpu::optimalThreadsCount(int algo, bool doubleHash, int maxCpuUsage) { - return m_totalThreads; + return m_totalThreads; } void Cpu::initCommon() { - memcpy(m_brand, "Unknown", 7); + memcpy(m_brand, "Unknown", 7); # if defined(XMRIG_ARMv8) - m_flags |= X86_64; - m_flags |= AES; + m_flags |= X86_64; + m_flags |= AES; # endif } + +#endif diff --git a/src/Cpu_mac.cpp b/src/Cpu_mac.cpp index 357e15ef..7213cc6a 100644 --- a/src/Cpu_mac.cpp +++ b/src/Cpu_mac.cpp @@ -20,7 +20,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - +#ifndef _WIN32 #include #include @@ -33,13 +33,15 @@ void Cpu::init() { # ifdef XMRIG_NO_LIBCPUID - m_totalThreads = sysconf(_SC_NPROCESSORS_CONF); + m_totalThreads = sysconf(_SC_NPROCESSORS_CONF); # endif - initCommon(); + initCommon(); } void Cpu::setAffinity(int id, uint64_t mask) { } + +#endif diff --git a/src/Cpu_stub.cpp b/src/Cpu_stub.cpp index 0b9196ee..864e7a37 100644 --- a/src/Cpu_stub.cpp +++ b/src/Cpu_stub.cpp @@ -20,7 +20,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - +#ifndef _WIN32 #ifdef _MSC_VER # include @@ -52,50 +52,56 @@ #ifdef _MSC_VER -static inline void cpuid(int level, int output[4]) { - __cpuid(output, level); +static inline void cpuid(int level, int output[4]) +{ + __cpuid(output, level); } #else -static inline void cpuid(int level, int output[4]) { - int a, b, c, d; - __cpuid_count(level, 0, a, b, c, d); +static inline void cpuid(int level, int output[4]) +{ + int a, b, c, d; + __cpuid_count(level, 0, a, b, c, d); - output[0] = a; - output[1] = b; - output[2] = c; - output[3] = d; + output[0] = a; + output[1] = b; + output[2] = c; + output[3] = d; } #endif -static inline void cpu_brand_string(char* s) { - int cpu_info[4] = { 0 }; - cpuid(VENDOR_ID, cpu_info); +static inline void cpu_brand_string(char* s) +{ + int cpu_info[4] = { 0 }; + cpuid(VENDOR_ID, cpu_info); - if (cpu_info[EAX_Reg] >= 4) { - for (int i = 0; i < 4; i++) { - cpuid(0x80000002 + i, cpu_info); - memcpy(s, cpu_info, sizeof(cpu_info)); - s += 16; - } - } + if(cpu_info[EAX_Reg] >= 4) + { + for(int i = 0; i < 4; i++) + { + cpuid(0x80000002 + i, cpu_info); + memcpy(s, cpu_info, sizeof(cpu_info)); + s += 16; + } + } } static inline bool has_aes_ni() { - int cpu_info[4] = { 0 }; - cpuid(PROCESSOR_INFO, cpu_info); + int cpu_info[4] = { 0 }; + cpuid(PROCESSOR_INFO, cpu_info); - return cpu_info[ECX_Reg] & bit_AES; + return cpu_info[ECX_Reg] & bit_AES; } -static inline bool has_bmi2() { - int cpu_info[4] = { 0 }; - cpuid(EXTENDED_FEATURES, cpu_info); +static inline bool has_bmi2() +{ + int cpu_info[4] = { 0 }; + cpuid(EXTENDED_FEATURES, cpu_info); - return cpu_info[EBX_Reg] & bit_BMI2; + return cpu_info[EBX_Reg] & bit_BMI2; } @@ -110,24 +116,28 @@ int Cpu::m_totalThreads = 0; int Cpu::optimalThreadsCount(int algo, bool doubleHash, int maxCpuUsage) { - int count = m_totalThreads / 2; - return count < 1 ? 1 : count; + int count = m_totalThreads / 2; + return count < 1 ? 1 : count; } void Cpu::initCommon() { - cpu_brand_string(m_brand); + cpu_brand_string(m_brand); # if defined(__x86_64__) || defined(_M_AMD64) - m_flags |= X86_64; + m_flags |= X86_64; # endif - if (has_aes_ni()) { - m_flags |= AES; - } + if(has_aes_ni()) + { + m_flags |= AES; + } - if (has_bmi2()) { - m_flags |= BMI2; - } + if(has_bmi2()) + { + m_flags |= BMI2; + } } + +#endif \ No newline at end of file diff --git a/src/Cpu_unix.cpp b/src/Cpu_unix.cpp index 9a13e7a5..33fe0ea1 100644 --- a/src/Cpu_unix.cpp +++ b/src/Cpu_unix.cpp @@ -20,7 +20,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - +#ifndef _WIN32 #ifdef __FreeBSD__ # include @@ -47,33 +47,39 @@ typedef cpuset_t cpu_set_t; void Cpu::init() { # ifdef XMRIG_NO_LIBCPUID - m_totalThreads = sysconf(_SC_NPROCESSORS_CONF); + m_totalThreads = sysconf(_SC_NPROCESSORS_CONF); # endif - initCommon(); + initCommon(); } void Cpu::setAffinity(int id, uint64_t mask) { - cpu_set_t set; - CPU_ZERO(&set); + cpu_set_t set; + CPU_ZERO(&set); - for (int i = 0; i < m_totalThreads; i++) { - if (mask & (1UL << i)) { - CPU_SET(i, &set); - } - } + for(int i = 0; i < m_totalThreads; i++) + { + if(mask & (1UL << i)) + { + CPU_SET(i, &set); + } + } - if (id == -1) { + if(id == -1) + { # ifndef __FreeBSD__ - sched_setaffinity(0, sizeof(&set), &set); + sched_setaffinity(0, sizeof(&set), &set); # endif - } else { + } + else + { # ifndef __ANDROID__ - pthread_setaffinity_np(pthread_self(), sizeof(&set), &set); + pthread_setaffinity_np(pthread_self(), sizeof(&set), &set); # else - sched_setaffinity(gettid(), sizeof(&set), &set); + sched_setaffinity(gettid(), sizeof(&set), &set); # endif - } + } } +#endif \ No newline at end of file diff --git a/src/Cpu_win.cpp b/src/Cpu_win.cpp index 13113a17..3c9a7bc0 100644 --- a/src/Cpu_win.cpp +++ b/src/Cpu_win.cpp @@ -31,22 +31,24 @@ void Cpu::init() { # ifdef XMRIG_NO_LIBCPUID - SYSTEM_INFO sysinfo; - GetSystemInfo(&sysinfo); + SYSTEM_INFO sysinfo; + GetSystemInfo(&sysinfo); - m_totalThreads = sysinfo.dwNumberOfProcessors; + m_totalThreads = sysinfo.dwNumberOfProcessors; # endif - initCommon(); + initCommon(); } void Cpu::setAffinity(int id, uint64_t mask) { - if (id == -1) { - SetProcessAffinityMask(GetCurrentProcess(), mask); - } - else { - SetThreadAffinityMask(GetCurrentThread(), mask); - } + if(id == -1) + { + SetProcessAffinityMask(GetCurrentProcess(), mask); + } + else + { + SetThreadAffinityMask(GetCurrentThread(), mask); + } } diff --git a/src/Mem.cpp b/src/Mem.cpp index 4437c673..76cbffe8 100644 --- a/src/Mem.cpp +++ b/src/Mem.cpp @@ -35,53 +35,57 @@ int Mem::m_algo = 0; int Mem::m_flags = 0; int Mem::m_threads = 0; size_t Mem::m_offset = 0; -uint8_t *Mem::m_memory = nullptr; +uint8_t* Mem::m_memory = nullptr; -cryptonight_ctx *Mem::create(int threadId) +cryptonight_ctx* Mem::create(int threadId) { # ifndef XMRIG_NO_AEON - if (m_algo == Options::ALGO_CRYPTONIGHT_LITE) { - return createLite(threadId); - } + if(m_algo == Options::ALGO_CRYPTONIGHT_LITE) + { + return createLite(threadId); + } # endif - cryptonight_ctx *ctx = reinterpret_cast(&m_memory[MEMORY - sizeof(cryptonight_ctx) * (threadId + 1)]); + cryptonight_ctx* ctx = reinterpret_cast(&m_memory[MEMORY - sizeof(cryptonight_ctx) * + (threadId + 1)]); - const int ratio = m_doubleHash ? 2 : 1; - ctx->memory = &m_memory[MEMORY * (threadId * ratio + 1)]; + const int ratio = m_doubleHash ? 2 : 1; + ctx->memory = &m_memory[MEMORY * (threadId * ratio + 1)]; - return ctx; + return ctx; } -void *Mem::calloc(size_t num, size_t size) +void* Mem::calloc(size_t num, size_t size) { - void *mem = &m_memory[m_offset]; - m_offset += (num * size); + void* mem = &m_memory[m_offset]; + m_offset += (num * size); - memset(mem, 0, num * size); + memset(mem, 0, num * size); - return mem; + return mem; } #ifndef XMRIG_NO_AEON -cryptonight_ctx *Mem::createLite(int threadId) { - cryptonight_ctx *ctx; +cryptonight_ctx* Mem::createLite(int threadId) +{ + cryptonight_ctx* ctx; - if (!m_doubleHash) { - const size_t offset = MEMORY * (threadId + 1); + if(!m_doubleHash) + { + const size_t offset = MEMORY * (threadId + 1); - ctx = reinterpret_cast(&m_memory[offset + MEMORY_LITE]); - ctx->memory = &m_memory[offset]; - return ctx; - } + ctx = reinterpret_cast(&m_memory[offset + MEMORY_LITE]); + ctx->memory = &m_memory[offset]; + return ctx; + } - ctx = reinterpret_cast(&m_memory[MEMORY - sizeof(cryptonight_ctx) * (threadId + 1)]); - ctx->memory = &m_memory[MEMORY * (threadId + 1)]; + ctx = reinterpret_cast(&m_memory[MEMORY - sizeof(cryptonight_ctx) * (threadId + 1)]); + ctx->memory = &m_memory[MEMORY * (threadId + 1)]; - return ctx; + return ctx; } #endif diff --git a/src/Mem.h b/src/Mem.h index 58dba848..3df94aad 100644 --- a/src/Mem.h +++ b/src/Mem.h @@ -38,33 +38,49 @@ struct cryptonight_ctx; class Mem { public: - enum Flags { - HugepagesAvailable = 1, - HugepagesEnabled = 2, - Lock = 4 - }; + enum Flags + { + HugepagesAvailable = 1, + HugepagesEnabled = 2, + Lock = 4 + }; - static bool allocate(int algo, int threads, bool doubleHash, bool enabled); - static cryptonight_ctx *create(int threadId); - static void *calloc(size_t num, size_t size); - static void release(); + static bool allocate(int algo, int threads, bool doubleHash, bool enabled); + static cryptonight_ctx* create(int threadId); + static void* calloc(size_t num, size_t size); + static void release(); - static inline bool isDoubleHash() { return m_doubleHash; } - static inline bool isHugepagesAvailable() { return (m_flags & HugepagesAvailable) != 0; } - static inline bool isHugepagesEnabled() { return (m_flags & HugepagesEnabled) != 0; } - static inline int flags() { return m_flags; } - static inline int threads() { return m_threads; } + static inline bool isDoubleHash() + { + return m_doubleHash; + } + static inline bool isHugepagesAvailable() + { + return (m_flags & HugepagesAvailable) != 0; + } + static inline bool isHugepagesEnabled() + { + return (m_flags & HugepagesEnabled) != 0; + } + static inline int flags() + { + return m_flags; + } + static inline int threads() + { + return m_threads; + } private: - static bool m_doubleHash; - static int m_algo; - static int m_flags; - static int m_threads; - static size_t m_offset; - VAR_ALIGN(16, static uint8_t *m_memory); + static bool m_doubleHash; + static int m_algo; + static int m_flags; + static int m_threads; + static size_t m_offset; + VAR_ALIGN(16, static uint8_t* m_memory); # ifndef XMRIG_NO_AEON - static cryptonight_ctx *createLite(int threadId); + static cryptonight_ctx* createLite(int threadId); # endif }; diff --git a/src/Mem_unix.cpp b/src/Mem_unix.cpp index 43ffa664..6dc3ecf9 100644 --- a/src/Mem_unix.cpp +++ b/src/Mem_unix.cpp @@ -20,7 +20,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - +#ifndef _WIN32 #include #include @@ -38,61 +38,79 @@ #include "Mem.h" #include "Options.h" +#ifndef MAP_HUGETLB +#define MAP_HUGETLB 0x40000 /* create a huge page mapping */ +#endif +#ifndef MAP_POPULATE +#define MAP_POPULATE 0x8000 /* populate (prefault) pagetables */ +#endif bool Mem::allocate(int algo, int threads, bool doubleHash, bool enabled) { - m_algo = algo; - m_threads = threads; - m_doubleHash = doubleHash; + m_algo = algo; + m_threads = threads; + m_doubleHash = doubleHash; - const int ratio = (doubleHash && algo != Options::ALGO_CRYPTONIGHT_LITE) ? 2 : 1; - const size_t size = MEMORY * (threads * ratio + 1); + const int ratio = (doubleHash && algo != Options::ALGO_CRYPTONIGHT_LITE) ? 2 : 1; + const size_t size = MEMORY * (threads * ratio + 1); - if (!enabled) { - m_memory = static_cast(_mm_malloc(size, 16)); - return true; - } + if(!enabled) + { + m_memory = static_cast(_mm_malloc(size, 16)); + return true; + } - m_flags |= HugepagesAvailable; + m_flags |= HugepagesAvailable; # if defined(__APPLE__) - m_memory = static_cast(mmap(0, size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, VM_FLAGS_SUPERPAGE_SIZE_2MB, 0)); + m_memory = static_cast(mmap(0, size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, + VM_FLAGS_SUPERPAGE_SIZE_2MB, 0)); # elif defined(__FreeBSD__) - m_memory = static_cast(mmap(0, size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS | MAP_ALIGNED_SUPER | MAP_PREFAULT_READ, -1, 0)); + m_memory = static_cast(mmap(0, size, PROT_READ | PROT_WRITE, + MAP_PRIVATE | MAP_ANONYMOUS | MAP_ALIGNED_SUPER | MAP_PREFAULT_READ, -1, 0)); # else - m_memory = static_cast(mmap(0, size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS | MAP_HUGETLB | MAP_POPULATE, 0, 0)); + m_memory = static_cast(mmap(0, size, PROT_READ | PROT_WRITE, + MAP_PRIVATE | MAP_ANONYMOUS | MAP_HUGETLB | MAP_POPULATE, 0, 0)); # endif - if (m_memory == MAP_FAILED) { - m_memory = static_cast(_mm_malloc(size, 16)); - return true; - } + if(m_memory == MAP_FAILED) + { + m_memory = static_cast(_mm_malloc(size, 16)); + return true; + } - m_flags |= HugepagesEnabled; + m_flags |= HugepagesEnabled; - if (madvise(m_memory, size, MADV_RANDOM | MADV_WILLNEED) != 0) { - LOG_ERR("madvise failed"); - } + if(madvise(m_memory, size, MADV_RANDOM | MADV_WILLNEED) != 0) + { + LOG_ERR("madvise failed"); + } - if (mlock(m_memory, size) == 0) { - m_flags |= Lock; - } + if(mlock(m_memory, size) == 0) + { + m_flags |= Lock; + } - return true; + return true; } void Mem::release() { - const int size = MEMORY * (m_threads + 1); + const int size = MEMORY * (m_threads + 1); - if (m_flags & HugepagesEnabled) { - if (m_flags & Lock) { - munlock(m_memory, size); - } + if(m_flags & HugepagesEnabled) + { + if(m_flags & Lock) + { + munlock(m_memory, size); + } - munmap(m_memory, size); - } - else { - _mm_free(m_memory); - } + munmap(m_memory, size); + } + else + { + _mm_free(m_memory); + } } + +#endif diff --git a/src/Mem_win.cpp b/src/Mem_win.cpp index a4f92cfe..bc454a9a 100644 --- a/src/Mem_win.cpp +++ b/src/Mem_win.cpp @@ -57,129 +57,149 @@ Return value: TRUE indicates success, FALSE failure. * AWE Example: https://msdn.microsoft.com/en-us/library/windows/desktop/aa366531(v=vs.85).aspx * Creating a File Mapping Using Large Pages: https://msdn.microsoft.com/en-us/library/aa366543(VS.85).aspx */ -static BOOL SetLockPagesPrivilege() { - HANDLE token; +static BOOL SetLockPagesPrivilege() +{ + HANDLE token; - if (OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &token) != TRUE) { - return FALSE; - } + if(OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &token) != TRUE) + { + return FALSE; + } - TOKEN_PRIVILEGES tp; - tp.PrivilegeCount = 1; - tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; + TOKEN_PRIVILEGES tp; + tp.PrivilegeCount = 1; + tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; - if (LookupPrivilegeValue(NULL, SE_LOCK_MEMORY_NAME, &(tp.Privileges[0].Luid)) != TRUE) { - return FALSE; - } + if(LookupPrivilegeValue(NULL, SE_LOCK_MEMORY_NAME, &(tp.Privileges[0].Luid)) != TRUE) + { + return FALSE; + } - BOOL rc = AdjustTokenPrivileges(token, FALSE, (PTOKEN_PRIVILEGES) &tp, 0, NULL, NULL); - if (rc != TRUE || GetLastError() != ERROR_SUCCESS) { - return FALSE; - } + BOOL rc = AdjustTokenPrivileges(token, FALSE, (PTOKEN_PRIVILEGES) &tp, 0, NULL, NULL); + if(rc != TRUE || GetLastError() != ERROR_SUCCESS) + { + return FALSE; + } - CloseHandle(token); + CloseHandle(token); - return TRUE; + return TRUE; } -static LSA_UNICODE_STRING StringToLsaUnicodeString(LPCTSTR string) { - LSA_UNICODE_STRING lsaString; +static LSA_UNICODE_STRING StringToLsaUnicodeString(LPCTSTR string) +{ + LSA_UNICODE_STRING lsaString; - DWORD dwLen = (DWORD) wcslen(string); - lsaString.Buffer = (LPWSTR) string; - lsaString.Length = (USHORT)((dwLen) * sizeof(WCHAR)); - lsaString.MaximumLength = (USHORT)((dwLen + 1) * sizeof(WCHAR)); - return lsaString; + DWORD dwLen = (DWORD) wcslen((WCHAR*)string); + lsaString.Buffer = (LPWSTR) string; + lsaString.Length = (USHORT)((dwLen) * sizeof(WCHAR)); + lsaString.MaximumLength = (USHORT)((dwLen + 1) * sizeof(WCHAR)); + return lsaString; } -static BOOL ObtainLockPagesPrivilege() { - HANDLE token; - PTOKEN_USER user = NULL; +static BOOL ObtainLockPagesPrivilege() +{ + HANDLE token; + PTOKEN_USER user = NULL; - if (OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &token) == TRUE) { - DWORD size = 0; + if(OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &token) == TRUE) + { + DWORD size = 0; - GetTokenInformation(token, TokenUser, NULL, 0, &size); - if (size) { - user = (PTOKEN_USER) LocalAlloc(LPTR, size); - } + GetTokenInformation(token, TokenUser, NULL, 0, &size); + if(size) + { + user = (PTOKEN_USER) LocalAlloc(LPTR, size); + } - GetTokenInformation(token, TokenUser, user, size, &size); - CloseHandle(token); - } + GetTokenInformation(token, TokenUser, user, size, &size); + CloseHandle(token); + } - if (!user) { - return FALSE; - } + if(!user) + { + return FALSE; + } - LSA_HANDLE handle; - LSA_OBJECT_ATTRIBUTES attributes; - ZeroMemory(&attributes, sizeof(attributes)); + LSA_HANDLE handle; + LSA_OBJECT_ATTRIBUTES attributes; + ZeroMemory(&attributes, sizeof(attributes)); - BOOL result = FALSE; - if (LsaOpenPolicy(NULL, &attributes, POLICY_ALL_ACCESS, &handle) == 0) { - LSA_UNICODE_STRING str = StringToLsaUnicodeString(_T(SE_LOCK_MEMORY_NAME)); + BOOL result = FALSE; + if(LsaOpenPolicy(NULL, &attributes, POLICY_ALL_ACCESS, &handle) == 0) + { + LSA_UNICODE_STRING str = StringToLsaUnicodeString(_T(SE_LOCK_MEMORY_NAME)); - if (LsaAddAccountRights(handle, user->User.Sid, &str, 1) == 0) { - LOG_NOTICE("Huge pages support was successfully enabled, but reboot required to use it"); - result = TRUE; - } + if(LsaAddAccountRights(handle, user->User.Sid, &str, 1) == 0) + { + LOG_NOTICE("Huge pages support was successfully enabled, but reboot required to use it"); + result = TRUE; + } - LsaClose(handle); - } + LsaClose(handle); + } - LocalFree(user); - return result; + LocalFree(user); + return result; } -static BOOL TrySetLockPagesPrivilege() { - if (SetLockPagesPrivilege()) { - return TRUE; - } +static BOOL TrySetLockPagesPrivilege() +{ + if(SetLockPagesPrivilege()) + { + return TRUE; + } - return ObtainLockPagesPrivilege() && SetLockPagesPrivilege(); + return ObtainLockPagesPrivilege() && SetLockPagesPrivilege(); } bool Mem::allocate(int algo, int threads, bool doubleHash, bool enabled) { - m_algo = algo; - m_threads = threads; - m_doubleHash = doubleHash; + m_algo = algo; + m_threads = threads; + m_doubleHash = doubleHash; - const int ratio = (doubleHash && algo != Options::ALGO_CRYPTONIGHT_LITE) ? 2 : 1; - const size_t size = MEMORY * (threads * ratio + 1); + const int ratio = (doubleHash && algo != Options::ALGO_CRYPTONIGHT_LITE) ? 2 : 1; + const size_t size = MEMORY * (threads * ratio + 1); - if (!enabled) { - m_memory = static_cast(_mm_malloc(size, 16)); - return true; - } + if(!enabled) + { + m_memory = static_cast(_mm_malloc(size, 16)); + return true; + } - if (TrySetLockPagesPrivilege()) { - m_flags |= HugepagesAvailable; - } + if(TrySetLockPagesPrivilege()) + { + m_flags |= HugepagesAvailable; + } - m_memory = static_cast(VirtualAlloc(NULL, size, MEM_COMMIT | MEM_RESERVE | MEM_LARGE_PAGES, PAGE_READWRITE)); - if (!m_memory) { - m_memory = static_cast(_mm_malloc(size, 16)); - } - else { - m_flags |= HugepagesEnabled; - } + m_memory = static_cast(VirtualAlloc(NULL, size, MEM_COMMIT | MEM_RESERVE | MEM_LARGE_PAGES, + PAGE_READWRITE)); + if(!m_memory) + { + m_memory = static_cast(_mm_malloc(size, 16)); + } + else + { + m_flags |= HugepagesEnabled; + } - return true; + return true; } void Mem::release() { - if (m_flags & HugepagesEnabled) { - VirtualFree(m_memory, 0, MEM_RELEASE); - } - else { - _mm_free(m_memory); - } + if(m_flags & HugepagesEnabled) + { + VirtualFree(m_memory, 0, MEM_RELEASE); + } + else + { + _mm_free(m_memory); + } } diff --git a/src/Options.cpp b/src/Options.cpp index 4e7c75ca..76fc809d 100644 --- a/src/Options.cpp +++ b/src/Options.cpp @@ -27,14 +27,14 @@ #ifdef _MSC_VER -# include "getopt/getopt.h" +#include "getopt/getopt.h" #else -# include +#include #endif #ifndef XMRIG_NO_HTTPD -# include +#include #endif @@ -54,7 +54,7 @@ #endif -Options *Options::m_self = nullptr; +Options* Options::m_self = nullptr; static char const usage[] = "\ @@ -80,10 +80,10 @@ Options:\n\ -c, --config=FILE load a JSON-format configuration file\n\ -l, --log-file=FILE log all output to a file\n" # ifdef HAVE_SYSLOG_H -"\ + "\ -S, --syslog use system log for output messages\n" # endif -"\ + "\ --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\ --nicehash enable nicehash/xmrig-proxy support\n\ @@ -99,648 +99,701 @@ Options:\n\ static char const short_options[] = "a:c:khBp:Px:r:R:s:t:T:o:u:O:v:Vl:S"; -static struct option const options[] = { - { "algo", 1, nullptr, 'a' }, - { "api-access-token", 1, nullptr, 4001 }, - { "api-port", 1, nullptr, 4000 }, - { "api-worker-id", 1, nullptr, 4002 }, - { "av", 1, nullptr, 'v' }, - { "background", 0, nullptr, 'B' }, - { "config", 1, nullptr, 'c' }, - { "cpu-affinity", 1, nullptr, 1020 }, - { "cpu-priority", 1, nullptr, 1021 }, - { "donate-level", 1, nullptr, 1003 }, - { "dry-run", 0, nullptr, 5000 }, - { "help", 0, nullptr, 'h' }, - { "keepalive", 0, nullptr ,'k' }, - { "log-file", 1, nullptr, 'l' }, - { "max-cpu-usage", 1, nullptr, 1004 }, - { "nicehash", 0, nullptr, 1006 }, - { "no-color", 0, nullptr, 1002 }, - { "no-huge-pages", 0, nullptr, 1009 }, - { "pass", 1, nullptr, 'p' }, - { "print-time", 1, nullptr, 1007 }, - { "retries", 1, nullptr, 'r' }, - { "retry-pause", 1, nullptr, 'R' }, - { "safe", 0, nullptr, 1005 }, - { "syslog", 0, nullptr, 'S' }, - { "threads", 1, nullptr, 't' }, - { "url", 1, nullptr, 'o' }, - { "user", 1, nullptr, 'u' }, - { "user-agent", 1, nullptr, 1008 }, - { "userpass", 1, nullptr, 'O' }, - { "version", 0, nullptr, 'V' }, - { 0, 0, 0, 0 } +static struct option const options[] = +{ + { "algo", 1, nullptr, 'a' }, + { "api-access-token", 1, nullptr, 4001 }, + { "api-port", 1, nullptr, 4000 }, + { "api-worker-id", 1, nullptr, 4002 }, + { "av", 1, nullptr, 'v' }, + { "background", 0, nullptr, 'B' }, + { "config", 1, nullptr, 'c' }, + { "cpu-affinity", 1, nullptr, 1020 }, + { "cpu-priority", 1, nullptr, 1021 }, + { "donate-level", 1, nullptr, 1003 }, + { "dry-run", 0, nullptr, 5000 }, + { "help", 0, nullptr, 'h' }, + { "keepalive", 0, nullptr , 'k' }, + { "log-file", 1, nullptr, 'l' }, + { "max-cpu-usage", 1, nullptr, 1004 }, + { "nicehash", 0, nullptr, 1006 }, + { "no-color", 0, nullptr, 1002 }, + { "no-huge-pages", 0, nullptr, 1009 }, + { "pass", 1, nullptr, 'p' }, + { "print-time", 1, nullptr, 1007 }, + { "retries", 1, nullptr, 'r' }, + { "retry-pause", 1, nullptr, 'R' }, + { "safe", 0, nullptr, 1005 }, + { "syslog", 0, nullptr, 'S' }, + { "threads", 1, nullptr, 't' }, + { "url", 1, nullptr, 'o' }, + { "user", 1, nullptr, 'u' }, + { "user-agent", 1, nullptr, 1008 }, + { "userpass", 1, nullptr, 'O' }, + { "version", 0, nullptr, 'V' }, + { 0, 0, 0, 0 } }; -static struct option const config_options[] = { - { "algo", 1, nullptr, 'a' }, - { "av", 1, nullptr, 'v' }, - { "background", 0, nullptr, 'B' }, - { "colors", 0, nullptr, 2000 }, - { "cpu-affinity", 1, nullptr, 1020 }, - { "cpu-priority", 1, nullptr, 1021 }, - { "donate-level", 1, nullptr, 1003 }, - { "dry-run", 0, nullptr, 5000 }, - { "huge-pages", 0, nullptr, 1009 }, - { "log-file", 1, nullptr, 'l' }, - { "max-cpu-usage", 1, nullptr, 1004 }, - { "print-time", 1, nullptr, 1007 }, - { "retries", 1, nullptr, 'r' }, - { "retry-pause", 1, nullptr, 'R' }, - { "safe", 0, nullptr, 1005 }, - { "syslog", 0, nullptr, 'S' }, - { "threads", 1, nullptr, 't' }, - { "user-agent", 1, nullptr, 1008 }, - { 0, 0, 0, 0 } +static struct option const config_options[] = +{ + { "algo", 1, nullptr, 'a' }, + { "av", 1, nullptr, 'v' }, + { "background", 0, nullptr, 'B' }, + { "colors", 0, nullptr, 2000 }, + { "cpu-affinity", 1, nullptr, 1020 }, + { "cpu-priority", 1, nullptr, 1021 }, + { "donate-level", 1, nullptr, 1003 }, + { "dry-run", 0, nullptr, 5000 }, + { "huge-pages", 0, nullptr, 1009 }, + { "log-file", 1, nullptr, 'l' }, + { "max-cpu-usage", 1, nullptr, 1004 }, + { "print-time", 1, nullptr, 1007 }, + { "retries", 1, nullptr, 'r' }, + { "retry-pause", 1, nullptr, 'R' }, + { "safe", 0, nullptr, 1005 }, + { "syslog", 0, nullptr, 'S' }, + { "threads", 1, nullptr, 't' }, + { "user-agent", 1, nullptr, 1008 }, + { 0, 0, 0, 0 } }; -static struct option const pool_options[] = { - { "url", 1, nullptr, 'o' }, - { "pass", 1, nullptr, 'p' }, - { "user", 1, nullptr, 'u' }, - { "userpass", 1, nullptr, 'O' }, - { "keepalive", 0, nullptr ,'k' }, - { "nicehash", 0, nullptr, 1006 }, - { 0, 0, 0, 0 } +static struct option const pool_options[] = +{ + { "url", 1, nullptr, 'o' }, + { "pass", 1, nullptr, 'p' }, + { "user", 1, nullptr, 'u' }, + { "userpass", 1, nullptr, 'O' }, + { "keepalive", 0, nullptr , 'k' }, + { "nicehash", 0, nullptr, 1006 }, + { 0, 0, 0, 0 } }; -static struct option const api_options[] = { - { "port", 1, nullptr, 4000 }, - { "access-token", 1, nullptr, 4001 }, - { "worker-id", 1, nullptr, 4002 }, - { 0, 0, 0, 0 } +static struct option const api_options[] = +{ + { "port", 1, nullptr, 4000 }, + { "access-token", 1, nullptr, 4001 }, + { "worker-id", 1, nullptr, 4002 }, + { 0, 0, 0, 0 } }; -static const char *algo_names[] = { - "cryptonight", +static const char* algo_names[] = +{ + "cryptonight", # ifndef XMRIG_NO_AEON - "cryptonight-lite" + "cryptonight-lite" # endif }; -Options *Options::parse(int argc, char **argv) +Options* Options::parse(int argc, char** argv) { - Options *options = new Options(argc, argv); - if (options->isReady()) { - m_self = options; - return m_self; - } + Options* options = new Options(argc, argv); + if(options->isReady()) + { + m_self = options; + return m_self; + } - delete options; - return nullptr; + delete options; + return nullptr; } -const char *Options::algoName() const +const char* Options::algoName() const { - return algo_names[m_algo]; + return algo_names[m_algo]; } -Options::Options(int argc, char **argv) : - m_background(false), - m_colors(true), - m_doubleHash(false), - m_dryRun(false), - m_hugePages(true), - m_ready(false), - m_safe(false), - m_syslog(false), - m_apiToken(nullptr), - m_apiWorkerId(nullptr), - m_logFile(nullptr), - m_userAgent(nullptr), - m_algo(0), - m_algoVariant(0), - m_apiPort(0), - m_donateLevel(kDonateLevel), - m_maxCpuUsage(75), - m_printTime(60), - m_priority(-1), - m_retries(5), - m_retryPause(5), - m_threads(0), - m_affinity(-1L) +Options::Options(int argc, char** argv) : + m_background(false), + m_colors(true), + m_doubleHash(false), + m_dryRun(false), + m_hugePages(true), + m_ready(false), + m_safe(false), + m_syslog(false), + m_apiToken(""), + m_apiWorkerId(""), + m_logFile(""), + m_userAgent(""), + m_algo(0), + m_algoVariant(0), + m_apiPort(0), + m_donateLevel(kDonateLevel), + m_maxCpuUsage(75), + m_printTime(60), + m_priority(-1), + m_retries(5), + m_retryPause(5), + m_threads(0), + m_affinity(-1L) { - m_pools.push_back(new Url()); + m_pools.push_back(Url()); - int key; + int key; - while (1) { - key = getopt_long(argc, argv, short_options, options, NULL); - if (key < 0) { - break; - } + while(1) + { + key = getopt_long(argc, argv, short_options, options, NULL); + if(key < 0) + { + break; + } - if (!parseArg(key, optarg)) { - return; - } - } + if(!parseArg(key, optarg)) + { + return; + } + } - if (optind < argc) { - fprintf(stderr, "%s: unsupported non-option argument '%s'\n", argv[0], argv[optind]); - return; - } + if(optind < argc) + { + fprintf(stderr, "%s: unsupported non-option argument '%s'\n", argv[0], argv[optind]); + return; + } - if (!m_pools[0]->isValid()) { - parseConfig(Platform::defaultConfigName()); - } + if(!m_pools[0].isValid()) + { + parseConfig(Platform::defaultConfigName()); + } - if (!m_pools[0]->isValid()) { - fprintf(stderr, "No pool URL supplied. Exiting.\n"); - return; - } + if(!m_pools[0].isValid()) + { + fprintf(stderr, "No pool URL supplied. Exiting.\n"); + return; + } - m_algoVariant = getAlgoVariant(); - if (m_algoVariant == AV2_AESNI_DOUBLE || m_algoVariant == AV4_SOFT_AES_DOUBLE) { - m_doubleHash = true; - } + m_algoVariant = getAlgoVariant(); + if(m_algoVariant == AV2_AESNI_DOUBLE || m_algoVariant == AV4_SOFT_AES_DOUBLE) + { + m_doubleHash = true; + } - if (!m_threads) { - m_threads = Cpu::optimalThreadsCount(m_algo, m_doubleHash, m_maxCpuUsage); - } - else if (m_safe) { - const int count = Cpu::optimalThreadsCount(m_algo, m_doubleHash, m_maxCpuUsage); - if (m_threads > count) { - m_threads = count; - } - } + if(!m_threads) + { + m_threads = Cpu::optimalThreadsCount(m_algo, m_doubleHash, m_maxCpuUsage); + } + else if(m_safe) + { + const int count = Cpu::optimalThreadsCount(m_algo, m_doubleHash, m_maxCpuUsage); + if(m_threads > count) + { + m_threads = count; + } + } - for (Url *url : m_pools) { - url->applyExceptions(); - } + for(size_t i = 0; i < m_pools.size(); ++i) + { + Url & url = m_pools[i]; + url.applyExceptions(); + } - m_ready = true; + m_ready = true; } Options::~Options() { + m_pools.clear(); } -bool Options::getJSON(const char *fileName, rapidjson::Document &doc) +bool Options::getJSON(const std::string & fileName, rapidjson::Document & doc) { - uv_fs_t req; - const int fd = uv_fs_open(uv_default_loop(), &req, fileName, O_RDONLY, 0644, nullptr); - if (fd < 0) { - fprintf(stderr, "unable to open %s: %s\n", fileName, uv_strerror(fd)); - return false; - } + uv_fs_t req; + const int fd = uv_fs_open(uv_default_loop(), &req, fileName.c_str(), O_RDONLY, 0644, nullptr); + if(fd < 0) + { + fprintf(stderr, "unable to open %s: %s\n", fileName.c_str(), uv_strerror(fd)); + return false; + } - uv_fs_req_cleanup(&req); + uv_fs_req_cleanup(&req); - FILE *fp = fdopen(fd, "rb"); - char buf[8192]; - rapidjson::FileReadStream is(fp, buf, sizeof(buf)); + FILE* fp = fdopen(fd, "rb"); + char buf[8192]; + rapidjson::FileReadStream is(fp, buf, sizeof(buf)); - doc.ParseStream(is); + doc.ParseStream(is); - uv_fs_close(uv_default_loop(), &req, fd, nullptr); - uv_fs_req_cleanup(&req); + uv_fs_close(uv_default_loop(), &req, fd, nullptr); + uv_fs_req_cleanup(&req); - if (doc.HasParseError()) { - printf("%s:%d: %s\n", fileName, (int) doc.GetErrorOffset(), rapidjson::GetParseError_En(doc.GetParseError())); - return false; - } + if(doc.HasParseError()) + { + printf("%s:%d: %s\n", fileName.c_str(), (int) doc.GetErrorOffset(), + rapidjson::GetParseError_En(doc.GetParseError())); + return false; + } - return doc.IsObject(); + return doc.IsObject(); } -bool Options::parseArg(int key, const char *arg) +bool Options::parseArg(int key, const std::string & arg) { - switch (key) { - case 'a': /* --algo */ - if (!setAlgo(arg)) { - return false; - } - break; + switch(key) + { + case 'a': /* --algo */ + if(!setAlgo(arg)) + { + return false; + } + break; - case 'o': /* --url */ - if (m_pools.size() > 1 || m_pools[0]->isValid()) { - Url *url = new Url(arg); - if (url->isValid()) { - m_pools.push_back(url); - } - else { - delete url; - } - } - else { - m_pools[0]->parse(arg); - } + case 'o': /* --url */ + if(m_pools.size() > 1 || m_pools[0].isValid()) + { + Url url(arg); + if(url.isValid()) + { + m_pools.push_back(url); + } + } + else + { + m_pools[0].parse(arg); + } - if (!m_pools.back()->isValid()) { - return false; - } - break; + if(!m_pools.back().isValid()) + { + return false; + } + break; - case 'O': /* --userpass */ - if (!m_pools.back()->setUserpass(arg)) { - return false; - } - break; + case 'O': /* --userpass */ + if(!m_pools.back().setUserpass(arg)) + { + return false; + } + break; - case 'u': /* --user */ - m_pools.back()->setUser(arg); - break; + case 'u': /* --user */ + m_pools.back().setUser(arg); + break; - case 'p': /* --pass */ - m_pools.back()->setPassword(arg); - break; + case 'p': /* --pass */ + m_pools.back().setPassword(arg); + break; - case 'l': /* --log-file */ - free(m_logFile); - m_logFile = strdup(arg); - m_colors = false; - break; + case 'l': /* --log-file */ + m_logFile = arg; + break; - case 4001: /* --access-token */ - free(m_apiToken); - m_apiToken = strdup(arg); - break; + case 4001: /* --access-token */ + m_apiToken = arg; + break; - case 4002: /* --worker-id */ - free(m_apiWorkerId); - m_apiWorkerId = strdup(arg); - break; + case 4002: /* --worker-id */ + m_apiWorkerId = arg; + break; - case 'r': /* --retries */ - case 'R': /* --retry-pause */ - case 'v': /* --av */ - case 1003: /* --donate-level */ - case 1004: /* --max-cpu-usage */ - case 1007: /* --print-time */ - case 1021: /* --cpu-priority */ - case 4000: /* --api-port */ - return parseArg(key, strtol(arg, nullptr, 10)); + case 'r': /* --retries */ + case 'R': /* --retry-pause */ + case 'v': /* --av */ + case 1003: /* --donate-level */ + case 1004: /* --max-cpu-usage */ + case 1007: /* --print-time */ + case 1021: /* --cpu-priority */ + case 4000: /* --api-port */ + return parseArg(key, strtol(arg.c_str(), nullptr, 10)); - case 'B': /* --background */ - case 'k': /* --keepalive */ - case 'S': /* --syslog */ - case 1005: /* --safe */ - case 1006: /* --nicehash */ - case 5000: /* --dry-run */ - return parseBoolean(key, true); + case 'B': /* --background */ + case 'k': /* --keepalive */ + case 'S': /* --syslog */ + case 1005: /* --safe */ + case 1006: /* --nicehash */ + return parseBoolean(key, true); - case 1002: /* --no-color */ - case 1009: /* --no-huge-pages */ - return parseBoolean(key, false); + case 1002: /* --no-color */ + case 1009: /* --no-huge-pages */ + return parseBoolean(key, false); - case 't': /* --threads */ - if (strncmp(arg, "all", 3) == 0) { - m_threads = Cpu::threads(); - return true; - } + case 't': /* --threads */ + if(arg == "all") + { + m_threads = Cpu::threads(); + return true; + } - return parseArg(key, strtol(arg, nullptr, 10)); + return parseArg(key, strtol(arg.c_str(), nullptr, 10)); - case 'V': /* --version */ - showVersion(); - return false; + case 'V': /* --version */ + showVersion(); + return false; - case 'h': /* --help */ - showUsage(0); - return false; + case 'h': /* --help */ + showUsage(0); + return false; - case 'c': /* --config */ - parseConfig(arg); - break; + case 'c': /* --config */ + parseConfig(arg); + break; - case 1020: { /* --cpu-affinity */ - const char *p = strstr(arg, "0x"); - return parseArg(key, p ? strtoull(p, nullptr, 16) : strtoull(arg, nullptr, 10)); - } + case 1020: /* --cpu-affinity */ + { + const size_t p = arg.find("0x"); + return parseArg(key, p != std::string::npos ? strtoul(arg.substr(p).c_str(), nullptr, 16) : + strtoul(arg.c_str(), nullptr, 10)); + } - case 1008: /* --user-agent */ - free(m_userAgent); - m_userAgent = strdup(arg); - break; + case 1008: /* --user-agent */ + m_userAgent = arg; + break; - default: - showUsage(1); - return false; - } + default: + showUsage(1); + return false; + } - return true; + return true; } bool Options::parseArg(int key, uint64_t arg) { - switch (key) { - case 'r': /* --retries */ - if (arg < 1 || arg > 1000) { - showUsage(1); - return false; - } + switch(key) + { + case 'r': /* --retries */ + if(arg < 1 || arg > 1000) + { + showUsage(1); + return false; + } - m_retries = (int) arg; - break; + m_retries = (int) arg; + break; - case 'R': /* --retry-pause */ - if (arg < 1 || arg > 3600) { - showUsage(1); - return false; - } + case 'R': /* --retry-pause */ + if(arg < 1 || arg > 3600) + { + showUsage(1); + return false; + } - m_retryPause = (int) arg; - break; + m_retryPause = (int) arg; + break; - case 't': /* --threads */ - if (arg < 1 || arg > 1024) { - showUsage(1); - return false; - } + case 't': /* --threads */ + if(arg < 1 || arg > 1024) + { + showUsage(1); + return false; + } - m_threads = (int) arg; - break; + m_threads = (int) arg; + break; - case 'v': /* --av */ - if (arg > 1000) { - showUsage(1); - return false; - } + case 'v': /* --av */ + if(arg > 1000) + { + showUsage(1); + return false; + } - m_algoVariant = (int) arg; - break; + m_algoVariant = (int) arg; + break; - case 1003: /* --donate-level */ - if (arg < 1 || arg > 99) { - return true; - } + case 1003: /* --donate-level */ + if(arg < 0 || arg > 99) + { + return true; + } - m_donateLevel = (int) arg; - break; + m_donateLevel = (int) arg; + break; - case 1004: /* --max-cpu-usage */ - if (arg < 1 || arg > 100) { - showUsage(1); - return false; - } + case 1004: /* --max-cpu-usage */ + if(arg < 1 || arg > 100) + { + showUsage(1); + return false; + } - m_maxCpuUsage = (int) arg; - break; + m_maxCpuUsage = (int) arg; + break; - case 1007: /* --print-time */ - if (arg > 1000) { - showUsage(1); - return false; - } + case 1007: /* --print-time */ + if(arg > 1000) + { + showUsage(1); + return false; + } - m_printTime = (int) arg; - break; + m_printTime = (int) arg; + break; - case 1020: /* --cpu-affinity */ - if (arg) { - m_affinity = arg; - } - break; + case 1020: /* --cpu-affinity */ + if(arg) + { + m_affinity = arg; + } + break; - case 1021: /* --cpu-priority */ - if (arg <= 5) { - m_priority = (int) arg; - } - break; + case 1021: /* --cpu-priority */ + if(arg <= 5) + { + m_priority = (int) arg; + } + break; - case 4000: /* --api-port */ - if (arg <= 65536) { - m_apiPort = (int) arg; - } - break; + case 4000: /* --api-port */ + if(arg <= 65536) + { + m_apiPort = (int) arg; + } + break; - default: - break; - } + default: + break; + } - return true; + return true; } bool Options::parseBoolean(int key, bool enable) { - switch (key) { - case 'k': /* --keepalive */ - m_pools.back()->setKeepAlive(enable); - break; + switch(key) + { + case 'k': /* --keepalive */ + m_pools.back().setKeepAlive(enable); + break; - case 'B': /* --background */ - m_background = enable; - m_colors = enable ? false : m_colors; - break; + case 'B': /* --background */ + m_background = enable; + m_colors = enable ? false : m_colors; + break; - case 'S': /* --syslog */ - m_syslog = enable; - m_colors = enable ? false : m_colors; - break; + case 'S': /* --syslog */ + m_syslog = enable; + m_colors = enable ? false : m_colors; + break; - case 1002: /* --no-color */ - m_colors = enable; - break; + case 1002: /* --no-color */ + m_colors = enable; + break; - case 1005: /* --safe */ - m_safe = enable; - break; + case 1005: /* --safe */ + m_safe = enable; + break; - case 1006: /* --nicehash */ - m_pools.back()->setNicehash(enable); - break; + case 1006: /* --nicehash */ + m_pools.back().setNicehash(enable); + break; - case 1009: /* --no-huge-pages */ - m_hugePages = enable; - break; + case 1009: /* --no-huge-pages */ + m_hugePages = enable; + break; - case 2000: /* colors */ - m_colors = enable; - break; + case 2000: /* colors */ + m_colors = enable; + break; - case 5000: /* --dry-run */ - m_dryRun = enable; - break; + case 5000: /* --dry-run */ + m_dryRun = enable; + break; - default: - break; - } + default: + break; + } - return true; + return true; } -Url *Options::parseUrl(const char *arg) const +Url Options::parseUrl(const std::string & arg) const { - auto url = new Url(arg); - if (!url->isValid()) { - delete url; - return nullptr; - } - - return url; + return Url(arg); } -void Options::parseConfig(const char *fileName) +void Options::parseConfig(const std::string & fileName) { - rapidjson::Document doc; - if (!getJSON(fileName, doc)) { - return; - } + rapidjson::Document doc; + if(!getJSON(fileName, doc)) + { + return; + } - for (size_t i = 0; i < ARRAY_SIZE(config_options); i++) { - parseJSON(&config_options[i], doc); - } + for(size_t i = 0; i < ARRAY_SIZE(config_options); i++) + { + parseJSON(&config_options[i], doc); + } - const rapidjson::Value &pools = doc["pools"]; - if (pools.IsArray()) { - for (const rapidjson::Value &value : pools.GetArray()) { - if (!value.IsObject()) { - continue; - } + const rapidjson::Value & pools = doc["pools"]; + if(pools.IsArray()) + { + for(size_t i = 0; i < pools.GetArray().Size(); ++i) + { + const rapidjson::Value & value = pools.GetArray()[i]; + if(!value.IsObject()) + { + continue; + } - for (size_t i = 0; i < ARRAY_SIZE(pool_options); i++) { - parseJSON(&pool_options[i], value); - } - } - } + for(size_t i = 0; i < ARRAY_SIZE(pool_options); i++) + { + parseJSON(&pool_options[i], value); + } + } + } - const rapidjson::Value &api = doc["api"]; - if (api.IsObject()) { - for (size_t i = 0; i < ARRAY_SIZE(api_options); i++) { - parseJSON(&api_options[i], api); - } - } + const rapidjson::Value & api = doc["api"]; + if(api.IsObject()) + { + for(size_t i = 0; i < ARRAY_SIZE(api_options); i++) + { + parseJSON(&api_options[i], api); + } + } } -void Options::parseJSON(const struct option *option, const rapidjson::Value &object) +void Options::parseJSON(const struct option* option, const rapidjson::Value & object) { - if (!option->name || !object.HasMember(option->name)) { - return; - } + if(!option->name || !object.HasMember(option->name)) + { + return; + } - const rapidjson::Value &value = object[option->name]; + const rapidjson::Value & value = object[option->name]; - if (option->has_arg && value.IsString()) { - parseArg(option->val, value.GetString()); - } - else if (option->has_arg && value.IsUint64()) { - parseArg(option->val, value.GetUint64()); - } - else if (!option->has_arg && value.IsBool()) { - parseBoolean(option->val, value.IsTrue()); - } + if(option->has_arg && value.IsString()) + { + parseArg(option->val, value.GetString()); + } + else if(option->has_arg && value.IsUint64()) + { + parseArg(option->val, value.GetUint64()); + } + else if(!option->has_arg && value.IsBool()) + { + parseBoolean(option->val, value.IsTrue()); + } } void Options::showUsage(int status) const { - if (status) { - fprintf(stderr, "Try \"" APP_ID "\" --help' for more information.\n"); - } - else { - printf(usage); - } + if(status) + { + fprintf(stderr, "Try \"" APP_ID "\" --help' for more information.\n"); + } + else + { + printf(usage); + } } void Options::showVersion() { - printf(APP_NAME " " APP_VERSION "\n built on " __DATE__ + printf(APP_NAME " " APP_VERSION "\n built on " __DATE__ # if defined(__clang__) - " with clang " __clang_version__); + " with clang " __clang_version__); # elif defined(__GNUC__) - " with GCC"); - printf(" %d.%d.%d", __GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__); + " with GCC"); + printf(" %d.%d.%d", __GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__); # elif defined(_MSC_VER) - " with MSVC"); - printf(" %d", MSVC_VERSION); + " with MSVC"); + printf(" %d", MSVC_VERSION); # else - ); + ); # endif - printf("\n features:" + printf("\n features:" # if defined(__i386__) || defined(_M_IX86) - " i386" + " i386" # elif defined(__x86_64__) || defined(_M_AMD64) - " x86_64" + " x86_64" # endif # if defined(__AES__) || defined(_MSC_VER) - " AES-NI" + " AES-NI" # endif - "\n"); + "\n"); - printf("\nlibuv/%s\n", uv_version_string()); + printf("\nlibuv/%s\n", uv_version_string()); # ifndef XMRIG_NO_HTTPD - printf("libmicrohttpd/%s\n", MHD_get_version()); + printf("libmicrohttpd/%s\n", MHD_get_version()); # endif } -bool Options::setAlgo(const char *algo) +bool Options::setAlgo(const std::string & algo) { - for (size_t i = 0; i < ARRAY_SIZE(algo_names); i++) { - if (algo_names[i] && !strcmp(algo, algo_names[i])) { - m_algo = (int) i; - break; - } + for(size_t i = 0; i < ARRAY_SIZE(algo_names); i++) + { + if(algo_names[i] && algo == algo_names[i]) + { + m_algo = (int) i; + break; + } # ifndef XMRIG_NO_AEON - if (i == ARRAY_SIZE(algo_names) - 1 && !strcmp(algo, "cryptonight-light")) { - m_algo = ALGO_CRYPTONIGHT_LITE; - break; - } + if(i == ARRAY_SIZE(algo_names) - 1 && algo == "cryptonight-light") + { + m_algo = ALGO_CRYPTONIGHT_LITE; + break; + } # endif - if (i == ARRAY_SIZE(algo_names) - 1) { - showUsage(1); - return false; - } - } + if(i == ARRAY_SIZE(algo_names) - 1) + { + showUsage(1); + return false; + } + } - return true; + return true; } int Options::getAlgoVariant() const { # ifndef XMRIG_NO_AEON - if (m_algo == ALGO_CRYPTONIGHT_LITE) { - return getAlgoVariantLite(); - } + if(m_algo == ALGO_CRYPTONIGHT_LITE) + { + return getAlgoVariantLite(); + } # endif - if (m_algoVariant <= AV0_AUTO || m_algoVariant >= AV_MAX) { - return Cpu::hasAES() ? AV1_AESNI : AV3_SOFT_AES; - } + if(m_algoVariant <= AV0_AUTO || m_algoVariant >= AV_MAX) + { + return Cpu::hasAES() ? AV1_AESNI : AV3_SOFT_AES; + } - if (m_safe && !Cpu::hasAES() && m_algoVariant <= AV2_AESNI_DOUBLE) { - return m_algoVariant + 2; - } + if(m_safe && !Cpu::hasAES() && m_algoVariant <= AV2_AESNI_DOUBLE) + { + return m_algoVariant + 2; + } - return m_algoVariant; + return m_algoVariant; } #ifndef XMRIG_NO_AEON int Options::getAlgoVariantLite() const { - if (m_algoVariant <= AV0_AUTO || m_algoVariant >= AV_MAX) { - return Cpu::hasAES() ? AV2_AESNI_DOUBLE : AV4_SOFT_AES_DOUBLE; - } + if(m_algoVariant <= AV0_AUTO || m_algoVariant >= AV_MAX) + { + return Cpu::hasAES() ? AV2_AESNI_DOUBLE : AV4_SOFT_AES_DOUBLE; + } - if (m_safe && !Cpu::hasAES() && m_algoVariant <= AV2_AESNI_DOUBLE) { - return m_algoVariant + 2; - } + if(m_safe && !Cpu::hasAES() && m_algoVariant <= AV2_AESNI_DOUBLE) + { + return m_algoVariant + 2; + } - return m_algoVariant; + return m_algoVariant; } #endif diff --git a/src/Options.h b/src/Options.h index 6f074917..fd40e920 100644 --- a/src/Options.h +++ b/src/Options.h @@ -27,7 +27,7 @@ #include #include - +#include #include "rapidjson/fwd.h" @@ -39,99 +39,176 @@ struct option; class Options { public: - enum Algo { - ALGO_CRYPTONIGHT, /* CryptoNight (Monero) */ - ALGO_CRYPTONIGHT_LITE, /* CryptoNight-Lite (AEON) */ - }; + enum Algo + { + ALGO_CRYPTONIGHT, /* CryptoNight (Monero) */ + ALGO_CRYPTONIGHT_LITE, /* CryptoNight-Lite (AEON) */ + }; - enum AlgoVariant { - AV0_AUTO, - AV1_AESNI, - AV2_AESNI_DOUBLE, - AV3_SOFT_AES, - AV4_SOFT_AES_DOUBLE, - AV_MAX - }; + enum AlgoVariant + { + AV0_AUTO, + AV1_AESNI, + AV2_AESNI_DOUBLE, + AV3_SOFT_AES, + AV4_SOFT_AES_DOUBLE, + AV_MAX + }; - static inline Options* i() { return m_self; } - static Options *parse(int argc, char **argv); + static inline Options* i() + { + return m_self; + } + static Options* parse(int argc, char** argv); - inline bool background() const { return m_background; } - inline bool colors() const { return m_colors; } - inline bool doubleHash() const { return m_doubleHash; } - inline bool dryRun() const { return m_dryRun; } - inline bool hugePages() const { return m_hugePages; } - inline bool syslog() const { return m_syslog; } - inline const char *apiToken() const { return m_apiToken; } - inline const char *apiWorkerId() const { return m_apiWorkerId; } - inline const char *logFile() const { return m_logFile; } - inline const char *userAgent() const { return m_userAgent; } - inline const std::vector &pools() const { return m_pools; } - inline int algo() const { return m_algo; } - inline int algoVariant() const { return m_algoVariant; } - inline int apiPort() const { return m_apiPort; } - inline int donateLevel() const { return m_donateLevel; } - inline int printTime() const { return m_printTime; } - inline int priority() const { return m_priority; } - inline int retries() const { return m_retries; } - inline int retryPause() const { return m_retryPause; } - inline int threads() const { return m_threads; } - inline int64_t affinity() const { return m_affinity; } - inline void setColors(bool colors) { m_colors = colors; } + inline bool background() const + { + return m_background; + } + inline bool colors() const + { + return m_colors; + } + inline bool doubleHash() const + { + return m_doubleHash; + } + inline bool dryRun() const + { + return m_dryRun; + } + inline bool hugePages() const + { + return m_hugePages; + } + inline bool syslog() const + { + return m_syslog; + } + inline const std::string apiToken() const + { + return m_apiToken; + } + inline const std::string & apiWorkerId() const + { + return m_apiWorkerId; + } + inline const std::string & logFile() const + { + return m_logFile; + } + inline const std::string & userAgent() const + { + return m_userAgent; + } + inline const std::vector & pools() const + { + return m_pools; + } + inline int algo() const + { + return m_algo; + } + inline int algoVariant() const + { + return m_algoVariant; + } + inline int apiPort() const + { + return m_apiPort; + } + inline int donateLevel() const + { + return m_donateLevel; + } + inline int printTime() const + { + return m_printTime; + } + inline int priority() const + { + return m_priority; + } + inline int retries() const + { + return m_retries; + } + inline int retryPause() const + { + return m_retryPause; + } + inline int threads() const + { + return m_threads; + } + inline int64_t affinity() const + { + return m_affinity; + } + inline void setColors(bool colors) + { + m_colors = colors; + } - inline static void release() { delete m_self; } + inline static void release() + { + delete m_self; + } - const char *algoName() const; + const char* algoName() const; private: - Options(int argc, char **argv); - ~Options(); + Options(int argc, char** argv); + ~Options(); - inline bool isReady() const { return m_ready; } + inline bool isReady() const + { + return m_ready; + } - static Options *m_self; + static Options* m_self; - bool getJSON(const char *fileName, rapidjson::Document &doc); - bool parseArg(int key, const char *arg); - bool parseArg(int key, uint64_t arg); - bool parseBoolean(int key, bool enable); - Url *parseUrl(const char *arg) const; - void parseConfig(const char *fileName); - void parseJSON(const struct option *option, const rapidjson::Value &object); - void showUsage(int status) const; - void showVersion(void); + bool getJSON(const std::string & fileName, rapidjson::Document & doc); + bool parseArg(int key, const std::string & arg); + bool parseArg(int key, uint64_t arg); + bool parseBoolean(int key, bool enable); + Url parseUrl(const std::string & arg) const; + void parseConfig(const std::string & fileName); + void parseJSON(const struct option* option, const rapidjson::Value & object); + void showUsage(int status) const; + void showVersion(void); - bool setAlgo(const char *algo); + bool setAlgo(const std::string & algo); - int getAlgoVariant() const; + int getAlgoVariant() const; # ifndef XMRIG_NO_AEON - int getAlgoVariantLite() const; + int getAlgoVariantLite() const; # endif - bool m_background; - bool m_colors; - bool m_doubleHash; - bool m_dryRun; - bool m_hugePages; - bool m_ready; - bool m_safe; - bool m_syslog; - char *m_apiToken; - char *m_apiWorkerId; - char *m_logFile; - char *m_userAgent; - int m_algo; - int m_algoVariant; - int m_apiPort; - int m_donateLevel; - int m_maxCpuUsage; - int m_printTime; - int m_priority; - int m_retries; - int m_retryPause; - int m_threads; - int64_t m_affinity; - std::vector m_pools; + bool m_background; + bool m_colors; + bool m_doubleHash; + bool m_dryRun; + bool m_hugePages; + bool m_ready; + bool m_safe; + bool m_syslog; + std::string m_apiToken; + std::string m_apiWorkerId; + std::string m_logFile; + std::string m_userAgent; + int m_algo; + int m_algoVariant; + int m_apiPort; + int m_donateLevel; + int m_maxCpuUsage; + int m_printTime; + int m_priority; + int m_retries; + int m_retryPause; + int m_threads; + int64_t m_affinity; + std::vector m_pools; }; #endif /* __OPTIONS_H__ */ diff --git a/src/Platform.cpp b/src/Platform.cpp index 4ddb1429..48f22344 100644 --- a/src/Platform.cpp +++ b/src/Platform.cpp @@ -29,34 +29,40 @@ #include "Platform.h" -char *Platform::m_defaultConfigName = nullptr; -char *Platform::m_userAgent = nullptr; +std::string Platform::m_defaultConfigName = ""; +std::string Platform::m_userAgent = ""; -const char *Platform::defaultConfigName() +const std::string & Platform::defaultConfigName() { - size_t size = 520; + enum + { + C_SIZE = 520, + }; - if (m_defaultConfigName == nullptr) { - m_defaultConfigName = new char[size]; - } + size_t size = C_SIZE ; + char defaultConfigName[C_SIZE]; + if(uv_exepath(defaultConfigName, &size) < 0) + { + return m_defaultConfigName; + } - if (uv_exepath(m_defaultConfigName, &size) < 0) { - return nullptr; - } + m_defaultConfigName = defaultConfigName; - if (size < 500) { -# ifdef WIN32 - char *p = strrchr(m_defaultConfigName, '\\'); -# else - char *p = strrchr(m_defaultConfigName, '/'); -# endif + if(size < 500) + { +#ifdef WIN32 + size_t p = m_defaultConfigName.find_last_of('\\'); +#else + size_t p = m_defaultConfigName.find_last_of('/'); +#endif - if (p) { - strcpy(p + 1, "config.json"); - return m_defaultConfigName; - } - } + if(p != std::string::npos) + { + m_defaultConfigName.resize(p + 1); + m_defaultConfigName.append("config.json"); + } + } - return nullptr; + return m_defaultConfigName; } diff --git a/src/Platform.h b/src/Platform.h index 87c8cc4d..72339894 100644 --- a/src/Platform.h +++ b/src/Platform.h @@ -24,21 +24,25 @@ #ifndef __PLATFORM_H__ #define __PLATFORM_H__ +#include class Platform { public: - static const char *defaultConfigName(); - static void init(const char *userAgent); - static void release(); - static void setProcessPriority(int priority); - static void setThreadPriority(int priority); + static const std::string & defaultConfigName(); + static void init(const std::string & userAgent); + static void release(); + static void setProcessPriority(int priority); + static void setThreadPriority(int priority); - static inline const char *userAgent() { return m_userAgent; } + static inline const std::string & userAgent() + { + return m_userAgent; + } private: - static char *m_defaultConfigName; - static char *m_userAgent; + static std::string m_defaultConfigName; + static std::string m_userAgent; }; diff --git a/src/Platform_mac.cpp b/src/Platform_mac.cpp index ba541f1d..936929ab 100644 --- a/src/Platform_mac.cpp +++ b/src/Platform_mac.cpp @@ -20,7 +20,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - +#ifndef _WIN32 #include #include @@ -36,32 +36,35 @@ #endif -static inline char *createUserAgent() +static inline char* createUserAgent() { - const size_t max = 160; + const size_t max = 160; - char *buf = new char[max]; + char* buf = new char[max]; # ifdef XMRIG_NVIDIA_PROJECT - const int cudaVersion = cuda_get_runtime_version(); - snprintf(buf, max, "%s/%s (Macintosh; Intel Mac OS X) libuv/%s CUDA/%d.%d clang/%d.%d.%d", APP_NAME, APP_VERSION, uv_version_string(), cudaVersion / 1000, cudaVersion % 100, __clang_major__, __clang_minor__, __clang_patchlevel__); + const int cudaVersion = cuda_get_runtime_version(); + snprintf(buf, max, "%s/%s (Macintosh; Intel Mac OS X) libuv/%s CUDA/%d.%d clang/%d.%d.%d", APP_NAME, + APP_VERSION, uv_version_string(), cudaVersion / 1000, cudaVersion % 100, __clang_major__, __clang_minor__, + __clang_patchlevel__); # else - snprintf(buf, max, "%s/%s (Macintosh; Intel Mac OS X) libuv/%s clang/%d.%d.%d", APP_NAME, APP_VERSION, uv_version_string(), __clang_major__, __clang_minor__, __clang_patchlevel__); + snprintf(buf, max, "%s/%s (Macintosh; Intel Mac OS X) libuv/%s clang/%d.%d.%d", APP_NAME, APP_VERSION, + uv_version_string(), __clang_major__, __clang_minor__, __clang_patchlevel__); # endif - return buf; + return buf; } -void Platform::init(const char *userAgent) +void Platform::init(const std::string & userAgent) { - m_userAgent = userAgent ? strdup(userAgent) : createUserAgent(); + m_userAgent = (userAgent.size() != "") ? userAgent : createUserAgent(); } void Platform::release() { - delete [] m_userAgent; + delete [] m_userAgent; } @@ -73,37 +76,39 @@ void Platform::setProcessPriority(int priority) void Platform::setThreadPriority(int priority) { - if (priority == -1) { - return; - } + if(priority == -1) + { + return; + } - int prio = 19; - switch (priority) - { - case 1: - prio = 5; - break; + int prio = 19; + switch(priority) + { + case 1: + prio = 5; + break; - case 2: - prio = 0; - break; + case 2: + prio = 0; + break; - case 3: - prio = -5; - break; + case 3: + prio = -5; + break; - case 4: - prio = -10; - break; + case 4: + prio = -10; + break; - case 5: - prio = -15; - break; + case 5: + prio = -15; + break; - default: - break; - } + default: + break; + } - setpriority(PRIO_PROCESS, 0, prio); + setpriority(PRIO_PROCESS, 0, prio); } +#endif diff --git a/src/Platform_unix.cpp b/src/Platform_unix.cpp index c0589307..da20c79d 100644 --- a/src/Platform_unix.cpp +++ b/src/Platform_unix.cpp @@ -20,6 +20,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ +#ifndef _WIN32 #include #include @@ -37,41 +38,41 @@ #endif -static inline char *createUserAgent() +static inline std::string createUserAgent() { - const size_t max = 160; + const size_t max = 160; - char *buf = new char[max]; - int length = snprintf(buf, max, "%s/%s (Linux ", APP_NAME, APP_VERSION); + char* buf = new char[max]; + int length = snprintf(buf, max, "%s/%s (Linux ", APP_NAME, APP_VERSION); # if defined(__x86_64__) - length += snprintf(buf + length, max - length, "x86_64) libuv/%s", uv_version_string()); + length += snprintf(buf + length, max - length, "x86_64) libuv/%s", uv_version_string()); # else - length += snprintf(buf + length, max - length, "i686) libuv/%s", uv_version_string()); + length += snprintf(buf + length, max - length, "i686) libuv/%s", uv_version_string()); # endif # ifdef XMRIG_NVIDIA_PROJECT - const int cudaVersion = cuda_get_runtime_version(); - length += snprintf(buf + length, max - length, " CUDA/%d.%d", cudaVersion / 1000, cudaVersion % 100); + const int cudaVersion = cuda_get_runtime_version(); + length += snprintf(buf + length, max - length, " CUDA/%d.%d", cudaVersion / 1000, cudaVersion % 100); # endif # ifdef __GNUC__ - length += snprintf(buf + length, max - length, " gcc/%d.%d.%d", __GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__); + length += snprintf(buf + length, max - length, " gcc/%d.%d.%d", __GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__); # endif - return buf; + return buf; } -void Platform::init(const char *userAgent) +void Platform::init(const std::string & userAgent) { - m_userAgent = userAgent ? strdup(userAgent) : createUserAgent(); + m_userAgent = (0 < userAgent.size()) ? userAgent : createUserAgent(); } void Platform::release() { - delete [] m_userAgent; + m_userAgent.clear(); } @@ -83,47 +84,52 @@ void Platform::setProcessPriority(int priority) void Platform::setThreadPriority(int priority) { - if (priority == -1) { - return; - } + if(priority == -1) + { + return; + } - int prio = 19; - switch (priority) - { - case 1: - prio = 5; - break; + int prio = 19; + switch(priority) + { + case 1: + prio = 5; + break; - case 2: - prio = 0; - break; + case 2: + prio = 0; + break; - case 3: - prio = -5; - break; + case 3: + prio = -5; + break; - case 4: - prio = -10; - break; + case 4: + prio = -10; + break; - case 5: - prio = -15; - break; + case 5: + prio = -15; + break; - default: - break; - } + default: + break; + } - setpriority(PRIO_PROCESS, 0, prio); + setpriority(PRIO_PROCESS, 0, prio); # ifdef SCHED_IDLE - if (priority == 0) { - sched_param param; - param.sched_priority = 0; + if(priority == 0) + { + sched_param param; + param.sched_priority = 0; - if (sched_setscheduler(0, SCHED_IDLE, ¶m) != 0) { - sched_setscheduler(0, SCHED_BATCH, ¶m); - } - } + if(sched_setscheduler(0, SCHED_IDLE, ¶m) != 0) + { + sched_setscheduler(0, SCHED_BATCH, ¶m); + } + } # endif } + +#endif diff --git a/src/Platform_win.cpp b/src/Platform_win.cpp index 880bdd98..973cfd41 100644 --- a/src/Platform_win.cpp +++ b/src/Platform_win.cpp @@ -26,145 +26,151 @@ #include #include +#include "log/Log.h" #include "Platform.h" #include "version.h" #ifdef XMRIG_NVIDIA_PROJECT -# include "nvidia/cryptonight.h" +#include "nvidia/cryptonight.h" #endif static inline OSVERSIONINFOEX winOsVersion() { - typedef NTSTATUS (NTAPI *RtlGetVersionFunction)(LPOSVERSIONINFO); - OSVERSIONINFOEX result = { sizeof(OSVERSIONINFOEX), 0, 0, 0, 0, {'\0'}, 0, 0, 0, 0, 0}; + typedef NTSTATUS(NTAPI * RtlGetVersionFunction)(LPOSVERSIONINFO); + OSVERSIONINFOEX result = { sizeof(OSVERSIONINFOEX), 0, 0, 0, 0, {'\0'}, 0, 0, 0, 0, 0}; - HMODULE ntdll = GetModuleHandleW(L"ntdll.dll"); - if (ntdll ) { - RtlGetVersionFunction pRtlGetVersion = reinterpret_cast(GetProcAddress(ntdll, "RtlGetVersion")); + HMODULE ntdll = GetModuleHandleW(L"ntdll.dll"); + if(ntdll) + { + RtlGetVersionFunction pRtlGetVersion = reinterpret_cast(GetProcAddress(ntdll, + "RtlGetVersion")); - if (pRtlGetVersion) { - pRtlGetVersion((LPOSVERSIONINFO) &result); - } - } + if(pRtlGetVersion) + { + pRtlGetVersion((LPOSVERSIONINFO) &result); + } + } - return result; + return result; } -static inline char *createUserAgent() +static inline std::string createUserAgent() { - const auto osver = winOsVersion(); - const size_t max = 160; + const auto osver = winOsVersion(); + const size_t max = 160; - char *buf = new char[max]; - int length = snprintf(buf, max, "%s/%s (Windows NT %lu.%lu", APP_NAME, APP_VERSION, osver.dwMajorVersion, osver.dwMinorVersion); + char buf[max]; + int length = snprintf(buf, max, "%s/%s (Windows NT %lu.%lu", APP_NAME, APP_VERSION, osver.dwMajorVersion, + osver.dwMinorVersion); -# if defined(__x86_64__) || defined(_M_AMD64) - length += snprintf(buf + length, max - length, "; Win64; x64) libuv/%s", uv_version_string()); -# else - length += snprintf(buf + length, max - length, ") libuv/%s", uv_version_string()); -# endif +#if defined(__x86_64__) || defined(_M_AMD64) + length += snprintf(buf + length, max - length, "; Win64; x64) libuv/%s", uv_version_string()); +#else + length += snprintf(buf + length, max - length, ") libuv/%s", uv_version_string()); +#endif -# ifdef XMRIG_NVIDIA_PROJECT - const int cudaVersion = cuda_get_runtime_version(); - length += snprintf(buf + length, max - length, " CUDA/%d.%d", cudaVersion / 1000, cudaVersion % 100); -# endif +#ifdef XMRIG_NVIDIA_PROJECT + const int cudaVersion = cuda_get_runtime_version(); + length += snprintf(buf + length, max - length, " CUDA/%d.%d", cudaVersion / 1000, cudaVersion % 100); +#endif -# ifdef __GNUC__ - length += snprintf(buf + length, max - length, " gcc/%d.%d.%d", __GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__); -# elif _MSC_VER - length += snprintf(buf + length, max - length, " msvc/%d", MSVC_VERSION); -# endif +#ifdef __GNUC__ + length += snprintf(buf + length, max - length, " gcc/%d.%d.%d", __GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__); +#elif _MSC_VER + length += snprintf(buf + length, max - length, " msvc/%d", MSVC_VERSION); +#endif - return buf; + return buf; } -void Platform::init(const char *userAgent) +void Platform::init(const std::string & userAgent) { - m_userAgent = userAgent ? strdup(userAgent) : createUserAgent(); + m_userAgent = (0 < userAgent.size()) ? userAgent : createUserAgent(); } void Platform::release() { - delete [] m_defaultConfigName; - delete [] m_userAgent; + m_userAgent.clear(); } void Platform::setProcessPriority(int priority) { - if (priority == -1) { - return; - } + if(priority == -1) + { + return; + } - DWORD prio = IDLE_PRIORITY_CLASS; - switch (priority) - { - case 1: - prio = BELOW_NORMAL_PRIORITY_CLASS; - break; + DWORD prio = IDLE_PRIORITY_CLASS; + switch(priority) + { + case 1: + prio = BELOW_NORMAL_PRIORITY_CLASS; + break; - case 2: - prio = NORMAL_PRIORITY_CLASS; - break; + case 2: + prio = NORMAL_PRIORITY_CLASS; + break; - case 3: - prio = ABOVE_NORMAL_PRIORITY_CLASS; - break; + case 3: + prio = ABOVE_NORMAL_PRIORITY_CLASS; + break; - case 4: - prio = HIGH_PRIORITY_CLASS; - break; + case 4: + prio = HIGH_PRIORITY_CLASS; + break; - case 5: - prio = REALTIME_PRIORITY_CLASS; + case 5: + prio = REALTIME_PRIORITY_CLASS; - default: - break; - } + default: + break; + } - SetPriorityClass(GetCurrentProcess(), prio); + SetPriorityClass(GetCurrentProcess(), prio); } void Platform::setThreadPriority(int priority) { - if (priority == -1) { - return; - } + if(priority == -1) + { + return; + } - int prio = THREAD_PRIORITY_IDLE; - switch (priority) - { - case 1: - prio = THREAD_PRIORITY_BELOW_NORMAL; - break; + int prio = THREAD_PRIORITY_IDLE; + switch(priority) + { + case 1: + prio = THREAD_PRIORITY_BELOW_NORMAL; + break; - case 2: - prio = THREAD_PRIORITY_NORMAL; - break; + case 2: + prio = THREAD_PRIORITY_NORMAL; + break; - case 3: - prio = THREAD_PRIORITY_ABOVE_NORMAL; - break; + case 3: + prio = THREAD_PRIORITY_ABOVE_NORMAL; + break; - case 4: - prio = THREAD_PRIORITY_HIGHEST; - break; + case 4: + prio = THREAD_PRIORITY_HIGHEST; + break; - case 5: - prio = THREAD_PRIORITY_TIME_CRITICAL; - break; + case 5: + prio = THREAD_PRIORITY_TIME_CRITICAL; + break; - default: - break; - } + default: + break; + } - SetThreadPriority(GetCurrentThread(), prio); + SetThreadPriority(GetCurrentThread(), prio); } diff --git a/src/Summary.cpp b/src/Summary.cpp index 2d93f429..a549e3c0 100644 --- a/src/Summary.cpp +++ b/src/Summary.cpp @@ -38,92 +38,100 @@ static void print_versions() { - char buf[16]; + char buf[16]; # if defined(__clang__) - snprintf(buf, 16, " clang/%d.%d.%d", __clang_major__, __clang_minor__, __clang_patchlevel__); + snprintf(buf, 16, " clang/%d.%d.%d", __clang_major__, __clang_minor__, __clang_patchlevel__); # elif defined(__GNUC__) - snprintf(buf, 16, " gcc/%d.%d.%d", __GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__); + snprintf(buf, 16, " gcc/%d.%d.%d", __GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__); # elif defined(_MSC_VER) - snprintf(buf, 16, " MSVC/%d", MSVC_VERSION); + snprintf(buf, 16, " MSVC/%d", MSVC_VERSION); # else - buf[0] = '\0'; + buf[0] = '\0'; # endif - Log::i()->text(Options::i()->colors() ? "\x1B[01;32m * \x1B[01;37mVERSIONS: \x1B[01;36mXMRig/%s\x1B[01;37m libuv/%s%s" : " * VERSIONS: XMRig/%s libuv/%s%s", - APP_VERSION, uv_version_string(), buf); + PRINT_MSG(" * VERSIONS: XMRig/" << APP_VERSION << " libuv/" << uv_version_string() << buf); } -static void print_memory() { - if (Options::i()->colors()) { - Log::i()->text("\x1B[01;32m * \x1B[01;37mHUGE PAGES: %s, %s", - Mem::isHugepagesAvailable() ? "\x1B[01;32mavailable" : "\x1B[01;31munavailable", - Mem::isHugepagesEnabled() ? "\x1B[01;32menabled" : "\x1B[01;31mdisabled"); - } - else { - Log::i()->text(" * HUGE PAGES: %s, %s", Mem::isHugepagesAvailable() ? "available" : "unavailable", Mem::isHugepagesEnabled() ? "enabled" : "disabled"); - } +static void print_memory() +{ + if(Options::i()->colors()) + { + /* + Log::i()->text("\x1B[01;32m * \x1B[01;37mHUGE PAGES: %s, %s", + Mem::isHugepagesAvailable() ? "\x1B[01;32mavailable" : "\x1B[01;31munavailable", + Mem::isHugepagesEnabled() ? "\x1B[01;32menabled" : "\x1B[01;31mdisabled"); + */ + } + else + { + PRINT_MSG(" * HUGE PAGES: " << (Mem::isHugepagesAvailable() ? "available" : "unavailable") << ", " << + (Mem::isHugepagesEnabled() ? "enabled" : "disabled")); + } } static void print_cpu() { - if (Options::i()->colors()) { - Log::i()->text("\x1B[01;32m * \x1B[01;37mCPU: %s (%d) %sx64 %sAES-NI", - Cpu::brand(), - Cpu::sockets(), - Cpu::isX64() ? "\x1B[01;32m" : "\x1B[01;31m-", - Cpu::hasAES() ? "\x1B[01;32m" : "\x1B[01;31m-"); + if(Options::i()->colors()) + { + /* + Log::i()->text("\x1B[01;32m * \x1B[01;37mCPU: %s (%d) %sx64 %sAES-NI", + Cpu::brand(), + Cpu::sockets(), + Cpu::isX64() ? "\x1B[01;32m" : "\x1B[01;31m-", + Cpu::hasAES() ? "\x1B[01;32m" : "\x1B[01;31m-"); + # ifndef XMRIG_NO_LIBCPUID + Log::i()->text("\x1B[01;32m * \x1B[01;37mCPU L2/L3: %.1f MB/%.1f MB", Cpu::l2() / 1024.0, + Cpu::l3() / 1024.0); + # endif + */ + } + else + { + PRINT_MSG(" * CPU: " << Cpu::brand() << " (" << Cpu::sockets() << ") " << (Cpu::isX64() ? "" : "-") << + " " << (Cpu::hasAES() ? "" : "-") << "AES-NI"); # ifndef XMRIG_NO_LIBCPUID - Log::i()->text("\x1B[01;32m * \x1B[01;37mCPU L2/L3: %.1f MB/%.1f MB", Cpu::l2() / 1024.0, Cpu::l3() / 1024.0); + PRINT_MSG(" * CPU L2/L3: " << (Cpu::l2() / 1024.0) << " MB/" << Cpu::l3() / 1024.0 << " MB"); # endif - } - else { - Log::i()->text(" * CPU: %s (%d) %sx64 %sAES-NI", Cpu::brand(), Cpu::sockets(), Cpu::isX64() ? "" : "-", Cpu::hasAES() ? "" : "-"); -# ifndef XMRIG_NO_LIBCPUID - Log::i()->text(" * CPU L2/L3: %.1f MB/%.1f MB", Cpu::l2() / 1024.0, Cpu::l3() / 1024.0); -# endif - } + } } static void print_threads() { - char buf[32]; - if (Options::i()->affinity() != -1L) { - snprintf(buf, 32, ", affinity=0x%" PRIX64, Options::i()->affinity()); - } - else { - buf[0] = '\0'; - } + char buf[32]; + if(Options::i()->affinity() != -1L) + { + snprintf(buf, 32, ", affinity=0x%" PRIX64, Options::i()->affinity()); + } + else + { + buf[0] = '\0'; + } - Log::i()->text(Options::i()->colors() ? "\x1B[01;32m * \x1B[01;37mTHREADS: \x1B[01;36m%d\x1B[01;37m, %s, av=%d, %sdonate=%d%%%s" : " * THREADS: %d, %s, av=%d, %sdonate=%d%%%s", - Options::i()->threads(), - Options::i()->algoName(), - Options::i()->algoVariant(), - Options::i()->colors() && Options::i()->donateLevel() == 0 ? "\x1B[01;31m" : "", - Options::i()->donateLevel(), - buf); + PRINT_MSG(" * THREADS: " << Options::i()->threads() << ", " << Options::i()->algoName() << ", av=" << + Options::i()->algoVariant() << ", donate=" << Options::i()->donateLevel() << " " << buf); } static void print_pools() { - const std::vector &pools = Options::i()->pools(); + const std::vector & pools = Options::i()->pools(); - for (size_t i = 0; i < pools.size(); ++i) { - Log::i()->text(Options::i()->colors() ? "\x1B[01;32m * \x1B[01;37mPOOL #%d: \x1B[01;36m%s:%d" : " * POOL #%d: %s:%d", - i + 1, - pools[i]->host(), - pools[i]->port()); - } + for(size_t i = 0; i < pools.size(); ++i) + { + PRINT_MSG(" * POOL #" << (i + 1) << ": " << pools[i].host() << ":" << pools[i].port()); + } # ifdef APP_DEBUG - for (size_t i = 0; i < pools.size(); ++i) { - Log::i()->text("%s:%d, user: %s, pass: %s, ka: %d, nicehash: %d", pools[i]->host(), pools[i]->port(), pools[i]->user(), pools[i]->password(), pools[i]->isKeepAlive(), pools[i]->isNicehash()); - } + for(size_t i = 0; i < pools.size(); ++i) + { + PRINT_MSG(pools[i].host() << ":" << pools[i].port() << ", user: " << pools[i].user() << ", pass: " << + pools[i].password() << ", ka: " << pools[i].isKeepAlive() << ", nicehash: " << pools[i].isNicehash()); + } # endif } @@ -131,39 +139,54 @@ static void print_pools() #ifndef XMRIG_NO_API static void print_api() { - if (Options::i()->apiPort() == 0) { - return; - } + if(Options::i()->apiPort() == 0) + { + return; + } - Log::i()->text(Options::i()->colors() ? "\x1B[01;32m * \x1B[01;37mAPI PORT: \x1B[01;36m%d" : " * API PORT: %d", Options::i()->apiPort()); + if(Options::i()->colors()) + { + /*TODO LOG + Log::i()->text(Options::i()->colors() ? "\x1B[01;32m * \x1B[01;37mAPI PORT: \x1B[01;36m%d" : + " * API PORT: %d", Options::i()->apiPort()); + */ + } + else + { + PRINT_MSG(" * API PORT: " << Options::i()->apiPort()); + } } #endif static void print_commands() { - if (Options::i()->colors()) { - Log::i()->text("\x1B[01;32m * \x1B[01;37mCOMMANDS: \x1B[01;35mh\x1B[01;37mashrate, \x1B[01;35mp\x1B[01;37mause, \x1B[01;35mr\x1B[01;37mesume"); - } - else { - Log::i()->text(" * COMMANDS: 'h' hashrate, 'p' pause, 'r' resume"); - } + if(Options::i()->colors()) + { + /* + Log::i()->text("\x1B[01;32m * \x1B[01;37mCOMMANDS: \x1B[01;35mh\x1B[01;37mashrate, \x1B[01;35mp\x1B[01;37mause, \x1B[01;35mr\x1B[01;37mesume"); + */ + } + else + { + PRINT_MSG(" * COMMANDS: 'h' hashrate, 'p' pause, 'r' resume"); + } } void Summary::print() { - print_versions(); - print_memory(); - print_cpu(); - print_threads(); - print_pools(); + print_versions(); + print_memory(); + print_cpu(); + print_threads(); + print_pools(); # ifndef XMRIG_NO_API - print_api(); + print_api(); # endif - print_commands(); + print_commands(); } diff --git a/src/Summary.h b/src/Summary.h index 3f64fd60..c76118b7 100644 --- a/src/Summary.h +++ b/src/Summary.h @@ -28,7 +28,7 @@ class Summary { public: - static void print(); + static void print(); }; diff --git a/src/api/Api.cpp b/src/api/Api.cpp index 729ebccd..5ab4a831 100644 --- a/src/api/Api.cpp +++ b/src/api/Api.cpp @@ -21,6 +21,7 @@ * along with this program. If not, see . */ +#ifndef XMRIG_NO_API #include @@ -28,58 +29,63 @@ #include "api/ApiState.h" -ApiState *Api::m_state = nullptr; +ApiState* Api::m_state = nullptr; uv_mutex_t Api::m_mutex; bool Api::start() { - uv_mutex_init(&m_mutex); - m_state = new ApiState(); + uv_mutex_init(&m_mutex); + m_state = new ApiState(); - return true; + return true; } void Api::release() { - delete m_state; + delete m_state; } -char *Api::get(const char *url, int *status) +std::string Api::get(const std::string & url, int* status) { - if (!m_state) { - return nullptr; - } + if(!m_state) + { + return ""; + } - uv_mutex_lock(&m_mutex); - char *buf = m_state->get(url, status); - uv_mutex_unlock(&m_mutex); + uv_mutex_lock(&m_mutex); + std::string buf = m_state->get(url, status); + uv_mutex_unlock(&m_mutex); - return buf; + return buf; } -void Api::tick(const Hashrate *hashrate) +void Api::tick(const Hashrate* hashrate) { - if (!m_state) { - return; - } + if(!m_state) + { + return; + } - uv_mutex_lock(&m_mutex); - m_state->tick(hashrate); - uv_mutex_unlock(&m_mutex); + uv_mutex_lock(&m_mutex); + m_state->tick(hashrate); + uv_mutex_unlock(&m_mutex); } -void Api::tick(const NetworkState &network) +void Api::tick(const NetworkState & network) { - if (!m_state) { - return; - } + if(!m_state) + { + return; + } - uv_mutex_lock(&m_mutex); - m_state->tick(network); - uv_mutex_unlock(&m_mutex); + uv_mutex_lock(&m_mutex); + m_state->tick(network); + uv_mutex_unlock(&m_mutex); } + +#endif diff --git a/src/api/Api.h b/src/api/Api.h index 72c65c3c..5335c224 100644 --- a/src/api/Api.h +++ b/src/api/Api.h @@ -26,6 +26,7 @@ #include +#include class ApiState; @@ -36,16 +37,16 @@ class NetworkState; class Api { public: - static bool start(); - static void release(); + static bool start(); + static void release(); - static char *get(const char *url, int *status); - static void tick(const Hashrate *hashrate); - static void tick(const NetworkState &results); + static std::string get(const std::string & url, int* status); + static void tick(const Hashrate* hashrate); + static void tick(const NetworkState & results); private: - static ApiState *m_state; - static uv_mutex_t m_mutex; + static ApiState* m_state; + static uv_mutex_t m_mutex; }; #endif /* __API_H__ */ diff --git a/src/api/ApiState.cpp b/src/api/ApiState.cpp index c963a1d6..1e021e4b 100644 --- a/src/api/ApiState.cpp +++ b/src/api/ApiState.cpp @@ -31,7 +31,6 @@ # include "unistd.h" #endif - #include "api/ApiState.h" #include "Cpu.h" #include "Mem.h" @@ -50,211 +49,223 @@ extern "C" #include "crypto/c_keccak.h" } - static inline double normalize(double d) { - if (!isnormal(d)) { - return 0.0; - } - - return floor(d * 100.0) / 100.0; +#ifndef _WIN32 + if(!isnormal(d)) + { + return 0.0; + } +#endif + return floor(d * 100.0) / 100.0; } ApiState::ApiState() { - m_threads = Options::i()->threads(); - m_hashrate = new double[m_threads * 3](); + m_threads = Options::i()->threads(); + m_hashrate = new double[m_threads * 3](); - memset(m_totalHashrate, 0, sizeof(m_totalHashrate)); - memset(m_workerId, 0, sizeof(m_workerId)); + memset(m_totalHashrate, 0, sizeof(m_totalHashrate)); + memset(m_workerId, 0, sizeof(m_workerId)); - if (Options::i()->apiWorkerId()) { - strncpy(m_workerId, Options::i()->apiWorkerId(), sizeof(m_workerId) - 1); - } - else { - gethostname(m_workerId, sizeof(m_workerId) - 1); - } + if(0 < Options::i()->apiWorkerId().size()) + { + strncpy(m_workerId, Options::i()->apiWorkerId().c_str(), sizeof(m_workerId) - 1); + } + else + { + gethostname(m_workerId, sizeof(m_workerId) - 1); + } - genId(); + genId(); } ApiState::~ApiState() { - delete [] m_hashrate; + delete [] m_hashrate; } -char *ApiState::get(const char *url, int *status) const +std::string ApiState::get(const std::string & url, int* status) const { - rapidjson::Document doc; - doc.SetObject(); + rapidjson::Document doc; + doc.SetObject(); - getIdentify(doc); - getMiner(doc); - getHashrate(doc); - getResults(doc); - getConnection(doc); + getIdentify(doc); + getMiner(doc); + getHashrate(doc); + getResults(doc); + getConnection(doc); - return finalize(doc); + return finalize(doc); } -void ApiState::tick(const Hashrate *hashrate) +void ApiState::tick(const Hashrate* hashrate) { - for (int i = 0; i < m_threads; ++i) { - m_hashrate[i * 3] = hashrate->calc((size_t) i, Hashrate::ShortInterval); - m_hashrate[i * 3 + 1] = hashrate->calc((size_t) i, Hashrate::MediumInterval); - m_hashrate[i * 3 + 2] = hashrate->calc((size_t) i, Hashrate::LargeInterval); - } + for(int i = 0; i < m_threads; ++i) + { + m_hashrate[i * 3] = hashrate->calc((size_t) i, Hashrate::ShortInterval); + m_hashrate[i * 3 + 1] = hashrate->calc((size_t) i, Hashrate::MediumInterval); + m_hashrate[i * 3 + 2] = hashrate->calc((size_t) i, Hashrate::LargeInterval); + } - m_totalHashrate[0] = hashrate->calc(Hashrate::ShortInterval); - m_totalHashrate[1] = hashrate->calc(Hashrate::MediumInterval); - m_totalHashrate[2] = hashrate->calc(Hashrate::LargeInterval); - m_highestHashrate = hashrate->highest(); + m_totalHashrate[0] = hashrate->calc(Hashrate::ShortInterval); + m_totalHashrate[1] = hashrate->calc(Hashrate::MediumInterval); + m_totalHashrate[2] = hashrate->calc(Hashrate::LargeInterval); + m_highestHashrate = hashrate->highest(); } -void ApiState::tick(const NetworkState &network) +void ApiState::tick(const NetworkState & network) { - m_network = network; + m_network = network; } -char *ApiState::finalize(rapidjson::Document &doc) const +std::string ApiState::finalize(rapidjson::Document & doc) const { - rapidjson::StringBuffer buffer(0, 4096); - rapidjson::PrettyWriter writer(buffer); - writer.SetMaxDecimalPlaces(10); - doc.Accept(writer); + rapidjson::StringBuffer buffer(0, 4096); + rapidjson::PrettyWriter writer(buffer); + writer.SetMaxDecimalPlaces(10); + doc.Accept(writer); - return strdup(buffer.GetString()); + return buffer.GetString(); } void ApiState::genId() { - memset(m_id, 0, sizeof(m_id)); + memset(m_id, 0, sizeof(m_id)); - uv_interface_address_t *interfaces; - int count = 0; + uv_interface_address_t* interfaces; + int count = 0; - if (uv_interface_addresses(&interfaces, &count) < 0) { - return; - } + if(uv_interface_addresses(&interfaces, &count) < 0) + { + return; + } - for (int i = 0; i < count; i++) { - if (!interfaces[i].is_internal && interfaces[i].address.address4.sin_family == AF_INET) { - uint8_t hash[200]; - const size_t addrSize = sizeof(interfaces[i].phys_addr); - const size_t inSize = strlen(APP_KIND) + addrSize; + for(int i = 0; i < count; i++) + { + if(!interfaces[i].is_internal && interfaces[i].address.address4.sin_family == AF_INET) + { + uint8_t hash[200]; + const size_t addrSize = sizeof(interfaces[i].phys_addr); + const size_t inSize = strlen(APP_KIND) + addrSize; - uint8_t *input = new uint8_t[inSize](); - memcpy(input, interfaces[i].phys_addr, addrSize); - memcpy(input + addrSize, APP_KIND, strlen(APP_KIND)); + uint8_t* input = new uint8_t[inSize](); + memcpy(input, interfaces[i].phys_addr, addrSize); + memcpy(input + addrSize, APP_KIND, strlen(APP_KIND)); - keccak(input, static_cast(inSize), hash, sizeof(hash)); - Job::toHex(hash, 8, m_id); + keccak(input, static_cast(inSize), hash, sizeof(hash)); - delete [] input; - break; - } - } + char* hashChar = (char*)hash; + Job::toHex(std::string(hashChar, 8), m_id); - uv_free_interface_addresses(interfaces, count); + delete [] input; + break; + } + } + + uv_free_interface_addresses(interfaces, count); } -void ApiState::getConnection(rapidjson::Document &doc) const +void ApiState::getConnection(rapidjson::Document & doc) const { - auto &allocator = doc.GetAllocator(); + auto & allocator = doc.GetAllocator(); - rapidjson::Value connection(rapidjson::kObjectType); - connection.AddMember("pool", rapidjson::StringRef(m_network.pool), allocator); - connection.AddMember("uptime", m_network.connectionTime(), allocator); - connection.AddMember("ping", m_network.latency(), allocator); - connection.AddMember("failures", m_network.failures, allocator); - connection.AddMember("error_log", rapidjson::Value(rapidjson::kArrayType), allocator); + rapidjson::Value connection(rapidjson::kObjectType); + connection.AddMember("pool", rapidjson::StringRef(m_network.pool), allocator); + connection.AddMember("uptime", m_network.connectionTime(), allocator); + connection.AddMember("ping", m_network.latency(), allocator); + connection.AddMember("failures", m_network.failures, allocator); + connection.AddMember("error_log", rapidjson::Value(rapidjson::kArrayType), allocator); - doc.AddMember("connection", connection, allocator); + doc.AddMember("connection", connection, allocator); } -void ApiState::getHashrate(rapidjson::Document &doc) const +void ApiState::getHashrate(rapidjson::Document & doc) const { - auto &allocator = doc.GetAllocator(); + auto & allocator = doc.GetAllocator(); - rapidjson::Value hashrate(rapidjson::kObjectType); - rapidjson::Value total(rapidjson::kArrayType); - rapidjson::Value threads(rapidjson::kArrayType); + rapidjson::Value hashrate(rapidjson::kObjectType); + rapidjson::Value total(rapidjson::kArrayType); + rapidjson::Value threads(rapidjson::kArrayType); - for (int i = 0; i < 3; ++i) { - total.PushBack(normalize(m_totalHashrate[i]), allocator); - } + for(int i = 0; i < 3; ++i) + { + total.PushBack(normalize(m_totalHashrate[i]), allocator); + } - for (int i = 0; i < m_threads * 3; i += 3) { - rapidjson::Value thread(rapidjson::kArrayType); - thread.PushBack(normalize(m_hashrate[i]), allocator); - thread.PushBack(normalize(m_hashrate[i + 1]), allocator); - thread.PushBack(normalize(m_hashrate[i + 2]), allocator); + for(int i = 0; i < m_threads * 3; i += 3) + { + rapidjson::Value thread(rapidjson::kArrayType); + thread.PushBack(normalize(m_hashrate[i]), allocator); + thread.PushBack(normalize(m_hashrate[i + 1]), allocator); + thread.PushBack(normalize(m_hashrate[i + 2]), allocator); - threads.PushBack(thread, allocator); - } + threads.PushBack(thread, allocator); + } - hashrate.AddMember("total", total, allocator); - hashrate.AddMember("highest", normalize(m_highestHashrate), allocator); - hashrate.AddMember("threads", threads, allocator); - doc.AddMember("hashrate", hashrate, allocator); + hashrate.AddMember("total", total, allocator); + hashrate.AddMember("highest", normalize(m_highestHashrate), allocator); + hashrate.AddMember("threads", threads, allocator); + doc.AddMember("hashrate", hashrate, allocator); } -void ApiState::getIdentify(rapidjson::Document &doc) const +void ApiState::getIdentify(rapidjson::Document & doc) const { - doc.AddMember("id", rapidjson::StringRef(m_id), doc.GetAllocator()); - doc.AddMember("worker_id", rapidjson::StringRef(m_workerId), doc.GetAllocator()); + doc.AddMember("id", rapidjson::StringRef(m_id), doc.GetAllocator()); + doc.AddMember("worker_id", rapidjson::StringRef(m_workerId), doc.GetAllocator()); } -void ApiState::getMiner(rapidjson::Document &doc) const +void ApiState::getMiner(rapidjson::Document & doc) const { - auto &allocator = doc.GetAllocator(); + auto & allocator = doc.GetAllocator(); - rapidjson::Value cpu(rapidjson::kObjectType); - cpu.AddMember("brand", rapidjson::StringRef(Cpu::brand()), allocator); - cpu.AddMember("aes", Cpu::hasAES(), allocator); - cpu.AddMember("x64", Cpu::isX64(), allocator); - cpu.AddMember("sockets", Cpu::sockets(), allocator); + rapidjson::Value cpu(rapidjson::kObjectType); + cpu.AddMember("brand", rapidjson::StringRef(Cpu::brand()), allocator); + cpu.AddMember("aes", Cpu::hasAES(), allocator); + cpu.AddMember("x64", Cpu::isX64(), allocator); + cpu.AddMember("sockets", Cpu::sockets(), allocator); - doc.AddMember("version", APP_VERSION, allocator); - doc.AddMember("kind", APP_KIND, allocator); - doc.AddMember("ua", rapidjson::StringRef(Platform::userAgent()), allocator); - doc.AddMember("cpu", cpu, allocator); - doc.AddMember("algo", rapidjson::StringRef(Options::i()->algoName()), allocator); - doc.AddMember("hugepages", Mem::isHugepagesEnabled(), allocator); - doc.AddMember("donate_level", Options::i()->donateLevel(), allocator); + doc.AddMember("version", APP_VERSION, allocator); + doc.AddMember("kind", APP_KIND, allocator); + doc.AddMember("ua", rapidjson::StringRef(Platform::userAgent().c_str()), allocator); + doc.AddMember("cpu", cpu, allocator); + doc.AddMember("algo", rapidjson::StringRef(Options::i()->algoName()), allocator); + doc.AddMember("hugepages", Mem::isHugepagesEnabled(), allocator); + doc.AddMember("donate_level", Options::i()->donateLevel(), allocator); } -void ApiState::getResults(rapidjson::Document &doc) const +void ApiState::getResults(rapidjson::Document & doc) const { - auto &allocator = doc.GetAllocator(); + auto & allocator = doc.GetAllocator(); - rapidjson::Value results(rapidjson::kObjectType); + rapidjson::Value results(rapidjson::kObjectType); - results.AddMember("diff_current", m_network.diff, allocator); - results.AddMember("shares_good", m_network.accepted, allocator); - results.AddMember("shares_total", m_network.accepted + m_network.rejected, allocator); - results.AddMember("avg_time", m_network.avgTime(), allocator); - results.AddMember("hashes_total", m_network.total, allocator); + results.AddMember("diff_current", m_network.diff, allocator); + results.AddMember("shares_good", m_network.accepted, allocator); + results.AddMember("shares_total", m_network.accepted + m_network.rejected, allocator); + results.AddMember("avg_time", m_network.avgTime(), allocator); + results.AddMember("hashes_total", m_network.total, allocator); - rapidjson::Value best(rapidjson::kArrayType); - for (size_t i = 0; i < m_network.topDiff.size(); ++i) { - best.PushBack(m_network.topDiff[i], allocator); - } + rapidjson::Value best(rapidjson::kArrayType); + for(size_t i = 0; i < m_network.topDiff.size(); ++i) + { + best.PushBack(m_network.topDiff[i], allocator); + } - results.AddMember("best", best, allocator); - results.AddMember("error_log", rapidjson::Value(rapidjson::kArrayType), allocator); + results.AddMember("best", best, allocator); + results.AddMember("error_log", rapidjson::Value(rapidjson::kArrayType), allocator); - doc.AddMember("results", results, allocator); + doc.AddMember("results", results, allocator); } diff --git a/src/api/ApiState.h b/src/api/ApiState.h index 7ecca36d..54c60ab1 100644 --- a/src/api/ApiState.h +++ b/src/api/ApiState.h @@ -28,6 +28,7 @@ #include "api/NetworkState.h" #include "rapidjson/fwd.h" +#include class Hashrate; @@ -35,29 +36,29 @@ class Hashrate; class ApiState { public: - ApiState(); - ~ApiState(); + ApiState(); + ~ApiState(); - char *get(const char *url, int *status) const; - void tick(const Hashrate *hashrate); - void tick(const NetworkState &results); + std::string get(const std::string & url, int* status) const; + void tick(const Hashrate* hashrate); + void tick(const NetworkState & results); private: - char *finalize(rapidjson::Document &doc) const; - void genId(); - void getConnection(rapidjson::Document &doc) const; - void getHashrate(rapidjson::Document &doc) const; - void getIdentify(rapidjson::Document &doc) const; - void getMiner(rapidjson::Document &doc) const; - void getResults(rapidjson::Document &doc) const; + std::string finalize(rapidjson::Document & doc) const; + void genId(); + void getConnection(rapidjson::Document & doc) const; + void getHashrate(rapidjson::Document & doc) const; + void getIdentify(rapidjson::Document & doc) const; + void getMiner(rapidjson::Document & doc) const; + void getResults(rapidjson::Document & doc) const; - char m_id[17]; - char m_workerId[128]; - double *m_hashrate; - double m_highestHashrate; - double m_totalHashrate[3]; - int m_threads; - NetworkState m_network; + char m_id[17]; + char m_workerId[128]; + double* m_hashrate; + double m_highestHashrate; + double m_totalHashrate[3]; + int m_threads; + NetworkState m_network; }; #endif /* __APISTATE_H__ */ diff --git a/src/api/Httpd.cpp b/src/api/Httpd.cpp index 996bc007..ce551ffb 100644 --- a/src/api/Httpd.cpp +++ b/src/api/Httpd.cpp @@ -21,96 +21,116 @@ * along with this program. If not, see . */ - +#ifndef XMRIG_NO_HTTPD #include #include - #include "api/Api.h" #include "api/Httpd.h" #include "log/Log.h" - -Httpd::Httpd(int port, const char *accessToken) : - m_accessToken(accessToken), - m_port(port), - m_daemon(nullptr) +Httpd::Httpd(int port, const std::string & accessToken) : + m_accessToken(accessToken), + m_port(port), + m_daemon(nullptr) { } - bool Httpd::start() { - if (!m_port) { - return false; - } + if(!m_port) + { + return false; + } - m_daemon = MHD_start_daemon(MHD_USE_SELECT_INTERNALLY, m_port, nullptr, nullptr, &Httpd::handler, this, MHD_OPTION_END); - if (!m_daemon) { - LOG_ERR("HTTP Daemon failed to start."); - return false; - } + m_daemon = MHD_start_daemon(MHD_USE_SELECT_INTERNALLY, m_port, nullptr, nullptr, &Httpd::handler, this, + MHD_OPTION_END); + if(!m_daemon) + { + LOG_ERR("HTTP Daemon failed to start."); + return false; + } - return true; + return true; } -int Httpd::auth(const char *header) +int Httpd::auth(const std::string & header) { - if (!m_accessToken) { - return MHD_HTTP_OK; - } + if(m_accessToken.empty()) + { + return MHD_HTTP_OK; + } - if (m_accessToken && !header) { - return MHD_HTTP_UNAUTHORIZED; - } + if(0 < m_accessToken.size() && header.empty()) + { + return MHD_HTTP_UNAUTHORIZED; + } - const size_t size = strlen(header); - if (size < 8 || strlen(m_accessToken) != size - 7 || memcmp("Bearer ", header, 7) != 0) { - return MHD_HTTP_FORBIDDEN; - } + const size_t size = header.size(); + if(size < 8 || m_accessToken.size() != size - 7 || "Bearer " == header.substr(0, 7)) + { + return MHD_HTTP_FORBIDDEN; + } - return strncmp(m_accessToken, header + 7, strlen(m_accessToken)) == 0 ? MHD_HTTP_OK : MHD_HTTP_FORBIDDEN; + return (m_accessToken == header.substr(7)) ? MHD_HTTP_OK : MHD_HTTP_FORBIDDEN; } -int Httpd::done(MHD_Connection *connection, int status, MHD_Response *rsp) +int Httpd::done(MHD_Connection* connection, int status, MHD_Response* rsp) { - if (!rsp) { - rsp = MHD_create_response_from_buffer(0, nullptr, MHD_RESPMEM_PERSISTENT); - } + if(!rsp) + { + rsp = MHD_create_response_from_buffer(0, nullptr, MHD_RESPMEM_PERSISTENT); + } - MHD_add_response_header(rsp, "Content-Type", "application/json"); - MHD_add_response_header(rsp, "Access-Control-Allow-Origin", "*"); - MHD_add_response_header(rsp, "Access-Control-Allow-Methods", "GET"); - MHD_add_response_header(rsp, "Access-Control-Allow-Headers", "Authorization"); + MHD_add_response_header(rsp, "Content-Type", "application/json"); + MHD_add_response_header(rsp, "Access-Control-Allow-Origin", "*"); + MHD_add_response_header(rsp, "Access-Control-Allow-Methods", "GET"); + MHD_add_response_header(rsp, "Access-Control-Allow-Headers", "Authorization"); - const int ret = MHD_queue_response(connection, status, rsp); - MHD_destroy_response(rsp); - return ret; + const int ret = MHD_queue_response(connection, status, rsp); + MHD_destroy_response(rsp); + return ret; } -int Httpd::handler(void *cls, struct MHD_Connection *connection, const char *url, const char *method, const char *version, const char *upload_data, size_t *upload_data_size, void **con_cls) +int Httpd::handlerStd(void* cls, struct MHD_Connection* connection, const std::string & url, + const std::string & method, const std::string & version, const std::string & upload_data, + size_t* upload_data_size, void** con_cls) { - if (strcmp(method, "OPTIONS") == 0) { - return done(connection, MHD_HTTP_OK, nullptr); - } + if(method == "OPTIONS") + { + return done(connection, MHD_HTTP_OK, nullptr); + } - if (strcmp(method, "GET") != 0) { - return MHD_NO; - } + if(method != "GET") + { + return MHD_NO; + } - int status = static_cast(cls)->auth(MHD_lookup_connection_value(connection, MHD_HEADER_KIND, "Authorization")); - if (status != MHD_HTTP_OK) { - return done(connection, status, nullptr); - } + int status = static_cast(cls)->auth(MHD_lookup_connection_value(connection, MHD_HEADER_KIND, + "Authorization")); + if(status != MHD_HTTP_OK) + { + return done(connection, status, nullptr); + } - char *buf = Api::get(url, &status); - if (buf == nullptr) { - return MHD_NO; - } + std::string buf = Api::get(url, &status); + if(buf.empty()) + { + return MHD_NO; + } - MHD_Response *rsp = MHD_create_response_from_buffer(strlen(buf), (void*) buf, MHD_RESPMEM_MUST_FREE); - return done(connection, status, rsp); + MHD_Response* rsp = MHD_create_response_from_buffer(buf.size(), (void*) buf.c_str(), MHD_RESPMEM_MUST_FREE); + return done(connection, status, rsp); } + +int Httpd::handler(void* cls, MHD_Connection* connection, const char* url, const char* method, + const char* version, const char* upload_data, size_t* upload_data_size, + void** con_cls) +{ + return handlerStd(cls, connection, url, method, version, upload_data, upload_data_size, con_cls); +} + +#endif diff --git a/src/api/Httpd.h b/src/api/Httpd.h index 7a4dd932..18da026b 100644 --- a/src/api/Httpd.h +++ b/src/api/Httpd.h @@ -24,30 +24,34 @@ #ifndef __HTTPD_H__ #define __HTTPD_H__ - #include - struct MHD_Connection; struct MHD_Daemon; struct MHD_Response; - class Httpd { public: - Httpd(int port, const char *accessToken); - bool start(); + Httpd(int port, const std::string & accessToken); + bool start(); private: - int auth(const char *header); + int auth(const std::string & header); - static int done(MHD_Connection *connection, int status, MHD_Response *rsp); - static int handler(void *cls, MHD_Connection *connection, const char *url, const char *method, const char *version, const char *upload_data, size_t *upload_data_size, void **con_cls); + static int done(MHD_Connection* connection, int status, MHD_Response* rsp); + static int handlerStd(void* cls, MHD_Connection* connection, const std::string & url, + const std::string & method, + const std::string & version, const std::string & upload_data, size_t* upload_data_size, + void** con_cls); - const char *m_accessToken; - const int m_port; - MHD_Daemon *m_daemon; + static int handler(void* cls, MHD_Connection* connection, const char* url, const char* method, + const char* version, const char* upload_data, size_t* upload_data_size, + void** con_cls); + + const std::string & m_accessToken; + const int m_port; + MHD_Daemon* m_daemon; }; #endif /* __HTTPD_H__ */ diff --git a/src/api/NetworkState.cpp b/src/api/NetworkState.cpp index d3ffddd3..d2f25bc8 100644 --- a/src/api/NetworkState.cpp +++ b/src/api/NetworkState.cpp @@ -27,87 +27,93 @@ #include #include +#include "interfaces/interface.h" + #include "api/NetworkState.h" #include "net/SubmitResult.h" NetworkState::NetworkState() : - diff(0), - accepted(0), - failures(0), - rejected(0), - total(0), - m_active(false) + diff(0), + accepted(0), + failures(0), + rejected(0), + total(0), + m_active(false) { - memset(pool, 0, sizeof(pool)); + memset(pool, 0, sizeof(pool)); } int NetworkState::connectionTime() const { - return m_active ? (int)((uv_now(uv_default_loop()) - m_connectionTime) / 1000) : 0; + return m_active ? (int)((uv_now(uv_default_loop()) - m_connectionTime) / 1000) : 0; } uint32_t NetworkState::avgTime() const { - if (m_latency.empty()) { - return 0; - } + if(m_latency.empty()) + { + return 0; + } - return connectionTime() / (uint32_t)m_latency.size(); + return connectionTime() / (uint32_t)m_latency.size(); } uint32_t NetworkState::latency() const { - const size_t calls = m_latency.size(); - if (calls == 0) { - return 0; - } + const size_t calls = m_latency.size(); + if(calls == 0) + { + return 0; + } - auto v = m_latency; - std::nth_element(v.begin(), v.begin() + calls / 2, v.end()); + auto v = m_latency; + std::nth_element(v.begin(), v.begin() + calls / 2, v.end()); - return v[calls / 2]; + return v[calls / 2]; } -void NetworkState::add(const SubmitResult &result, const char *error) +void NetworkState::add(const SubmitResult & result, const std::string & error) { - if (error) { - rejected++; - return; - } + if(0 < error.size()) + { + rejected++; + return; + } - accepted++; - total += result.diff; + accepted++; + total += result.diff; - const size_t ln = topDiff.size() - 1; - if (result.actualDiff > topDiff[ln]) { - topDiff[ln] = result.actualDiff; - std::sort(topDiff.rbegin(), topDiff.rend()); - } + const size_t ln = topDiff.size() - 1; + if(result.actualDiff > topDiff[ln]) + { + topDiff[ln] = result.actualDiff; + std::sort(topDiff.rbegin(), topDiff.rend()); + } - m_latency.push_back(result.elapsed > 0xFFFF ? 0xFFFF : (uint16_t) result.elapsed); + m_latency.push_back(result.elapsed > 0xFFFF ? 0xFFFF : (uint16_t) result.elapsed); } -void NetworkState::setPool(const char *host, int port, const char *ip) +void NetworkState::setPool(const std::string & host, int port, const std::string & ip) { - snprintf(pool, sizeof(pool) - 1, "%s:%d", host, port); + snprintf(pool, sizeof(pool) - 1, "%s:%d", host.c_str(), port); - m_active = true; - m_connectionTime = uv_now(uv_default_loop()); + m_active = true; + m_connectionTime = uv_now(uv_default_loop()); } void NetworkState::stop() { - m_active = false; - diff = 0; + m_active = false; + diff = 0; - failures++; - m_latency.clear(); + failures++; + m_latency.clear(); } diff --git a/src/api/NetworkState.h b/src/api/NetworkState.h index d0998074..e8160997 100644 --- a/src/api/NetworkState.h +++ b/src/api/NetworkState.h @@ -35,27 +35,27 @@ class SubmitResult; class NetworkState { public: - NetworkState(); + NetworkState(); - int connectionTime() const; - uint32_t avgTime() const; - uint32_t latency() const; - void add(const SubmitResult &result, const char *error); - void setPool(const char *host, int port, const char *ip); - void stop(); + int connectionTime() const; + uint32_t avgTime() const; + uint32_t latency() const; + void add(const SubmitResult & result, const std::string & error); + void setPool(const std::string & host, int port, const std::string & ip); + void stop(); - char pool[256]; - std::array topDiff { { } }; - uint32_t diff; - uint64_t accepted; - uint64_t failures; - uint64_t rejected; - uint64_t total; + char pool[256]; + std::array topDiff; + uint32_t diff; + uint64_t accepted; + uint64_t failures; + uint64_t rejected; + uint64_t total; private: - bool m_active; - std::vector m_latency; - uint64_t m_connectionTime; + bool m_active; + std::vector m_latency; + uint64_t m_connectionTime; }; #endif /* __NETWORKSTATE_H__ */ diff --git a/src/config.json b/src/config.json index 7813d4b9..49ffb890 100644 --- a/src/config.json +++ b/src/config.json @@ -1,11 +1,13 @@ { "algo": "cryptonight", // cryptonight (default) or cryptonight-lite + "user-agent": "", // custom user-agent "av": 0, // algorithm variation, 0 auto select "background": false, // true to run the miner in the background "colors": true, // false to disable colored output "cpu-affinity": null, // set process affinity to CPU core(s), mask "0x3" for cores 0 and 1 "cpu-priority": null, // set process priority (0 idle, 2 normal to 5 highest) "donate-level": 5, // donate level, mininum 1% + "debug": false, "log-file": null, // log all output to a file, example: "c:/some/path/xmrig.log" "max-cpu-usage": 75, // maximum CPU usage for automatic mode, usually limiting factor is CPU cache not this option. "print-time": 60, // print hashrate report every N seconds @@ -16,12 +18,22 @@ "threads": null, // number of miner threads "pools": [ { - "url": "pool.minemonero.pro:5555", // URL of mining server + "url": "pool.minemonero.pro:3333", // --------------- URL of mining server + /* "url": "pool.minemonero.pro:443@localhost:8080",*/ // --------------- URL of mining server over HTTP (CONNECT) proxy + /* "url": "pool.minemonero.pro:7777#secret_keystream",*/ // URL of mining xmrig-proxy with encrypted support + /* "url": "pool.minemonero.pro:8080#secret_keystream@localhost:8080",*/ // URL of mining xmrig-proxy with encrypted support over HTTP (CONNECT) proxy "user": "", // username for mining server "pass": "x", // password for mining server "keepalive": true, // send keepalived for prevent timeout (need pool support) "nicehash": false // enable nicehash/xmrig-proxy support - } + }, + { + "url": "pool.minemonero.pro:5555@localhost:8080",// URL of mining server with localhost proxy (example) + "user": "", // username for mining server + "pass": "x", // password for mining server + "keepalive": true, // send keepalived for prevent timeout (need pool support) + "nicehash": false // enable nicehash/xmrig-proxy support + } ], "api": { "port": 0, // port for the miner API https://github.com/xmrig/xmrig/wiki/API diff --git a/src/crypto/CryptoNight.cpp b/src/crypto/CryptoNight.cpp index 3ac9e94b..f49bf53f 100644 --- a/src/crypto/CryptoNight.cpp +++ b/src/crypto/CryptoNight.cpp @@ -36,127 +36,143 @@ #include "Options.h" -void (*cryptonight_hash_ctx)(const void *input, size_t size, void *output, cryptonight_ctx *ctx) = nullptr; +void (*cryptonight_hash_ctx)(const void* input, size_t size, void* output, cryptonight_ctx* ctx) = nullptr; -static void cryptonight_av1_aesni(const void *input, size_t size, void *output, struct cryptonight_ctx *ctx) { +static void cryptonight_av1_aesni(const void* input, size_t size, void* output, struct cryptonight_ctx* ctx) +{ # if !defined(XMRIG_ARMv7) - cryptonight_hash<0x80000, MEMORY, 0x1FFFF0, false>(input, size, output, ctx); + cryptonight_hash<0x80000, MEMORY, 0x1FFFF0, false>(input, size, output, ctx); # endif } -static void cryptonight_av2_aesni_double(const void *input, size_t size, void *output, cryptonight_ctx *ctx) { +static void cryptonight_av2_aesni_double(const void* input, size_t size, void* output, cryptonight_ctx* ctx) +{ # if !defined(XMRIG_ARMv7) - cryptonight_double_hash<0x80000, MEMORY, 0x1FFFF0, false>(input, size, output, ctx); + cryptonight_double_hash<0x80000, MEMORY, 0x1FFFF0, false>(input, size, output, ctx); # endif } -static void cryptonight_av3_softaes(const void *input, size_t size, void *output, cryptonight_ctx *ctx) { - cryptonight_hash<0x80000, MEMORY, 0x1FFFF0, true>(input, size, output, ctx); +static void cryptonight_av3_softaes(const void* input, size_t size, void* output, cryptonight_ctx* ctx) +{ + cryptonight_hash<0x80000, MEMORY, 0x1FFFF0, true>(input, size, output, ctx); } -static void cryptonight_av4_softaes_double(const void *input, size_t size, void *output, cryptonight_ctx *ctx) { - cryptonight_double_hash<0x80000, MEMORY, 0x1FFFF0, true>(input, size, output, ctx); +static void cryptonight_av4_softaes_double(const void* input, size_t size, void* output, cryptonight_ctx* ctx) +{ + cryptonight_double_hash<0x80000, MEMORY, 0x1FFFF0, true>(input, size, output, ctx); } #ifndef XMRIG_NO_AEON -static void cryptonight_lite_av1_aesni(const void *input, size_t size, void *output, cryptonight_ctx *ctx) { - # if !defined(XMRIG_ARMv7) - cryptonight_hash<0x40000, MEMORY_LITE, 0xFFFF0, false>(input, size, output, ctx); +static void cryptonight_lite_av1_aesni(const void* input, size_t size, void* output, cryptonight_ctx* ctx) +{ +# if !defined(XMRIG_ARMv7) + cryptonight_hash<0x40000, MEMORY_LITE, 0xFFFF0, false>(input, size, output, ctx); #endif } -static void cryptonight_lite_av2_aesni_double(const void *input, size_t size, void *output, cryptonight_ctx *ctx) { +static void cryptonight_lite_av2_aesni_double(const void* input, size_t size, void* output, + cryptonight_ctx* ctx) +{ # if !defined(XMRIG_ARMv7) - cryptonight_double_hash<0x40000, MEMORY_LITE, 0xFFFF0, false>(input, size, output, ctx); + cryptonight_double_hash<0x40000, MEMORY_LITE, 0xFFFF0, false>(input, size, output, ctx); # endif } -static void cryptonight_lite_av3_softaes(const void *input, size_t size, void *output, cryptonight_ctx *ctx) { - cryptonight_hash<0x40000, MEMORY_LITE, 0xFFFF0, true>(input, size, output, ctx); +static void cryptonight_lite_av3_softaes(const void* input, size_t size, void* output, cryptonight_ctx* ctx) +{ + cryptonight_hash<0x40000, MEMORY_LITE, 0xFFFF0, true>(input, size, output, ctx); } -static void cryptonight_lite_av4_softaes_double(const void *input, size_t size, void *output, cryptonight_ctx *ctx) { - cryptonight_double_hash<0x40000, MEMORY_LITE, 0xFFFF0, true>(input, size, output, ctx); +static void cryptonight_lite_av4_softaes_double(const void* input, size_t size, void* output, + cryptonight_ctx* ctx) +{ + cryptonight_double_hash<0x40000, MEMORY_LITE, 0xFFFF0, true>(input, size, output, ctx); } -void (*cryptonight_variations[8])(const void *input, size_t size, void *output, cryptonight_ctx *ctx) = { - cryptonight_av1_aesni, - cryptonight_av2_aesni_double, - cryptonight_av3_softaes, - cryptonight_av4_softaes_double, - cryptonight_lite_av1_aesni, - cryptonight_lite_av2_aesni_double, - cryptonight_lite_av3_softaes, - cryptonight_lite_av4_softaes_double - }; +void (*cryptonight_variations[8])(const void* input, size_t size, void* output, cryptonight_ctx* ctx) = +{ + cryptonight_av1_aesni, + cryptonight_av2_aesni_double, + cryptonight_av3_softaes, + cryptonight_av4_softaes_double, + cryptonight_lite_av1_aesni, + cryptonight_lite_av2_aesni_double, + cryptonight_lite_av3_softaes, + cryptonight_lite_av4_softaes_double +}; #else -void (*cryptonight_variations[4])(const void *input, size_t size, void *output, cryptonight_ctx *ctx) = { - cryptonight_av1_aesni, - cryptonight_av2_aesni_double, - cryptonight_av3_softaes, - cryptonight_av4_softaes_double - }; +void (*cryptonight_variations[4])(const void* input, size_t size, void* output, cryptonight_ctx* ctx) = +{ + cryptonight_av1_aesni, + cryptonight_av2_aesni_double, + cryptonight_av3_softaes, + cryptonight_av4_softaes_double +}; #endif -bool CryptoNight::hash(const Job &job, JobResult &result, cryptonight_ctx *ctx) +bool CryptoNight::hash(const Job & job, JobResult & result, cryptonight_ctx* ctx) { - cryptonight_hash_ctx(job.blob(), job.size(), result.result, ctx); + cryptonight_hash_ctx(job.blob(), job.size(), result.result, ctx); - return *reinterpret_cast(result.result + 24) < job.target(); + return *reinterpret_cast(result.result + 24) < job.target(); } bool CryptoNight::init(int algo, int variant) { - if (variant < 1 || variant > 4) { - return false; - } + if(variant < 1 || variant > 4) + { + return false; + } # ifndef XMRIG_NO_AEON - const int index = algo == Options::ALGO_CRYPTONIGHT_LITE ? (variant + 3) : (variant - 1); + const int index = algo == Options::ALGO_CRYPTONIGHT_LITE ? (variant + 3) : (variant - 1); # else - const int index = variant - 1; + const int index = variant - 1; # endif - cryptonight_hash_ctx = cryptonight_variations[index]; + cryptonight_hash_ctx = cryptonight_variations[index]; - return selfTest(algo); + return selfTest(algo); } -void CryptoNight::hash(const uint8_t *input, size_t size, uint8_t *output, cryptonight_ctx *ctx) +void CryptoNight::hash(const uint8_t* input, size_t size, uint8_t* output, cryptonight_ctx* ctx) { - cryptonight_hash_ctx(input, size, output, ctx); + cryptonight_hash_ctx(input, size, output, ctx); } -bool CryptoNight::selfTest(int algo) { - if (cryptonight_hash_ctx == nullptr) { - return false; - } +bool CryptoNight::selfTest(int algo) +{ + if(cryptonight_hash_ctx == nullptr) + { + return false; + } - char output[64]; + 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); + 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); + cryptonight_hash_ctx(test_input, 76, output, ctx); - _mm_free(ctx->memory); - _mm_free(ctx); + _mm_free(ctx->memory); + _mm_free(ctx); # ifndef XMRIG_NO_AEON - return memcmp(output, algo == Options::ALGO_CRYPTONIGHT_LITE ? test_output1 : test_output0, (Options::i()->doubleHash() ? 64 : 32)) == 0; + return memcmp(output, algo == Options::ALGO_CRYPTONIGHT_LITE ? test_output1 : test_output0, + (Options::i()->doubleHash() ? 64 : 32)) == 0; # else - return memcmp(output, test_output0, (Options::i()->doubleHash() ? 64 : 32)) == 0; + return memcmp(output, test_output0, (Options::i()->doubleHash() ? 64 : 32)) == 0; # endif } diff --git a/src/crypto/CryptoNight.h b/src/crypto/CryptoNight.h index 64fc0fd1..b4a88cff 100644 --- a/src/crypto/CryptoNight.h +++ b/src/crypto/CryptoNight.h @@ -36,10 +36,11 @@ #define MEMORY_LITE 1048576 /* 1 MiB */ -struct cryptonight_ctx { - VAR_ALIGN(16, uint8_t state0[200]); - VAR_ALIGN(16, uint8_t state1[200]); - VAR_ALIGN(16, uint8_t* memory); +struct cryptonight_ctx +{ + VAR_ALIGN(16, uint8_t state0[200]); + VAR_ALIGN(16, uint8_t state1[200]); + VAR_ALIGN(16, uint8_t* memory); }; @@ -50,12 +51,12 @@ class JobResult; class CryptoNight { public: - static bool hash(const Job &job, JobResult &result, cryptonight_ctx *ctx); - static bool init(int algo, int variant); - static void hash(const uint8_t *input, size_t size, uint8_t *output, cryptonight_ctx *ctx); + static bool hash(const Job & job, JobResult & result, cryptonight_ctx* ctx); + static bool init(int algo, int variant); + static void hash(const uint8_t* input, size_t size, uint8_t* output, cryptonight_ctx* ctx); private: - static bool selfTest(int algo); + static bool selfTest(int algo); }; #endif /* __CRYPTONIGHT_H__ */ diff --git a/src/crypto/CryptoNight_arm.h b/src/crypto/CryptoNight_arm.h index 4ac14f34..c1c48b30 100644 --- a/src/crypto/CryptoNight_arm.h +++ b/src/crypto/CryptoNight_arm.h @@ -47,39 +47,43 @@ extern "C" } -static inline void do_blake_hash(const void* input, size_t len, char* output) { - blake256_hash(reinterpret_cast(output), static_cast(input), len); +static inline void do_blake_hash(const void* input, size_t len, char* output) +{ + blake256_hash(reinterpret_cast(output), static_cast(input), len); } -static inline void do_groestl_hash(const void* input, size_t len, char* output) { - groestl(static_cast(input), len * 8, reinterpret_cast(output)); +static inline void do_groestl_hash(const void* input, size_t len, char* output) +{ + groestl(static_cast(input), len * 8, reinterpret_cast(output)); } -static inline void do_jh_hash(const void* input, size_t len, char* output) { - jh_hash(32 * 8, static_cast(input), 8 * len, reinterpret_cast(output)); +static inline void do_jh_hash(const void* input, size_t len, char* output) +{ + jh_hash(32 * 8, static_cast(input), 8 * len, reinterpret_cast(output)); } -static inline void do_skein_hash(const void* input, size_t len, char* output) { - xmr_skein(static_cast(input), reinterpret_cast(output)); +static inline void do_skein_hash(const void* input, size_t len, char* output) +{ + xmr_skein(static_cast(input), reinterpret_cast(output)); } -void (* const extra_hashes[4])(const void *, size_t, char *) = {do_blake_hash, do_groestl_hash, do_jh_hash, do_skein_hash}; +void (* const extra_hashes[4])(const void*, size_t, char*) = {do_blake_hash, do_groestl_hash, do_jh_hash, do_skein_hash}; static inline __attribute__((always_inline)) __m128i _mm_set_epi64x(const uint64_t a, const uint64_t b) { - return vcombine_u64(vcreate_u64(b), vcreate_u64(a)); + return vcombine_u64(vcreate_u64(b), vcreate_u64(a)); } /* this one was not implemented yet so here it is */ static inline __attribute__((always_inline)) uint64_t _mm_cvtsi128_si64(__m128i a) { - return vgetq_lane_u64(a, 0); + return vgetq_lane_u64(a, 0); } @@ -89,34 +93,35 @@ static inline __attribute__((always_inline)) uint64_t _mm_cvtsi128_si64(__m128i #if defined(XMRIG_ARMv8) static 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; + unsigned __int128 r = (unsigned __int128) a * (unsigned __int128) b; + *hi = r >> 64; + return (uint64_t) r; } #else -static 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; +static 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 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; + 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; + // 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; + return product_lo; } #endif @@ -125,369 +130,388 @@ static inline uint64_t __umul128(uint64_t multiplier, uint64_t multiplicand, uin // sl_xor(a1 a2 a3 a4) = a1 (a2^a1) (a3^a2^a1) (a4^a3^a2^a1) static 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; + __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; } template static inline void aes_genkey_sub(__m128i* xout0, __m128i* xout2) { -// __m128i xout1 = _mm_aeskeygenassist_si128(*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 = _mm_aeskeygenassist_si128(*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); + // __m128i xout1 = _mm_aeskeygenassist_si128(*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 = _mm_aeskeygenassist_si128(*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); } template static inline void soft_aes_genkey_sub(__m128i* xout0, __m128i* xout2) { - __m128i xout1 = soft_aeskeygenassist(*xout2); - 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<0x00>(*xout0); - xout1 = _mm_shuffle_epi32(xout1, 0xAA); // see PSHUFD, set all elems to 3rd elem - *xout2 = sl_xor(*xout2); - *xout2 = _mm_xor_si128(*xout2, xout1); + __m128i xout1 = soft_aeskeygenassist(*xout2); + 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<0x00>(*xout0); + xout1 = _mm_shuffle_epi32(xout1, 0xAA); // see PSHUFD, set all elems to 3rd elem + *xout2 = sl_xor(*xout2); + *xout2 = _mm_xor_si128(*xout2, xout1); } template -static 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) +static 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; + __m128i xout0 = _mm_load_si128(memory); + __m128i xout2 = _mm_load_si128(memory + 1); + *k0 = xout0; + *k1 = xout2; - SOFT_AES ? soft_aes_genkey_sub<0x01>(&xout0, &xout2) : soft_aes_genkey_sub<0x01>(&xout0, &xout2); - *k2 = xout0; - *k3 = xout2; + SOFT_AES ? soft_aes_genkey_sub<0x01>(&xout0, &xout2) : soft_aes_genkey_sub<0x01>(&xout0, &xout2); + *k2 = xout0; + *k3 = xout2; - SOFT_AES ? soft_aes_genkey_sub<0x02>(&xout0, &xout2) : soft_aes_genkey_sub<0x02>(&xout0, &xout2); - *k4 = xout0; - *k5 = xout2; + SOFT_AES ? soft_aes_genkey_sub<0x02>(&xout0, &xout2) : soft_aes_genkey_sub<0x02>(&xout0, &xout2); + *k4 = xout0; + *k5 = xout2; - SOFT_AES ? soft_aes_genkey_sub<0x04>(&xout0, &xout2) : soft_aes_genkey_sub<0x04>(&xout0, &xout2); - *k6 = xout0; - *k7 = xout2; + SOFT_AES ? soft_aes_genkey_sub<0x04>(&xout0, &xout2) : soft_aes_genkey_sub<0x04>(&xout0, &xout2); + *k6 = xout0; + *k7 = xout2; - SOFT_AES ? soft_aes_genkey_sub<0x08>(&xout0, &xout2) : soft_aes_genkey_sub<0x08>(&xout0, &xout2); - *k8 = xout0; - *k9 = xout2; + SOFT_AES ? soft_aes_genkey_sub<0x08>(&xout0, &xout2) : soft_aes_genkey_sub<0x08>(&xout0, &xout2); + *k8 = xout0; + *k9 = xout2; } template -static inline void aes_round(__m128i key, __m128i* x0, __m128i* x1, __m128i* x2, __m128i* x3, __m128i* x4, __m128i* x5, __m128i* x6, __m128i* x7) +static inline void aes_round(__m128i key, __m128i* x0, __m128i* x1, __m128i* x2, __m128i* x3, __m128i* x4, + __m128i* x5, __m128i* x6, __m128i* x7) { - if (SOFT_AES) { - *x0 = soft_aesenc((uint32_t*)x0, key); - *x1 = soft_aesenc((uint32_t*)x1, key); - *x2 = soft_aesenc((uint32_t*)x2, key); - *x3 = soft_aesenc((uint32_t*)x3, key); - *x4 = soft_aesenc((uint32_t*)x4, key); - *x5 = soft_aesenc((uint32_t*)x5, key); - *x6 = soft_aesenc((uint32_t*)x6, key); - *x7 = soft_aesenc((uint32_t*)x7, key); - } + if(SOFT_AES) + { + *x0 = soft_aesenc((uint32_t*)x0, key); + *x1 = soft_aesenc((uint32_t*)x1, key); + *x2 = soft_aesenc((uint32_t*)x2, key); + *x3 = soft_aesenc((uint32_t*)x3, key); + *x4 = soft_aesenc((uint32_t*)x4, key); + *x5 = soft_aesenc((uint32_t*)x5, key); + *x6 = soft_aesenc((uint32_t*)x6, key); + *x7 = soft_aesenc((uint32_t*)x7, key); + } # ifndef XMRIG_ARMv7 - else { - *x0 = vaesmcq_u8(vaeseq_u8(*((uint8x16_t *) x0), key)); - *x1 = vaesmcq_u8(vaeseq_u8(*((uint8x16_t *) x1), key)); - *x2 = vaesmcq_u8(vaeseq_u8(*((uint8x16_t *) x2), key)); - *x3 = vaesmcq_u8(vaeseq_u8(*((uint8x16_t *) x3), key)); - *x4 = vaesmcq_u8(vaeseq_u8(*((uint8x16_t *) x4), key)); - *x5 = vaesmcq_u8(vaeseq_u8(*((uint8x16_t *) x5), key)); - *x6 = vaesmcq_u8(vaeseq_u8(*((uint8x16_t *) x6), key)); - *x7 = vaesmcq_u8(vaeseq_u8(*((uint8x16_t *) x7), key)); - } + else + { + *x0 = vaesmcq_u8(vaeseq_u8(*((uint8x16_t*) x0), key)); + *x1 = vaesmcq_u8(vaeseq_u8(*((uint8x16_t*) x1), key)); + *x2 = vaesmcq_u8(vaeseq_u8(*((uint8x16_t*) x2), key)); + *x3 = vaesmcq_u8(vaeseq_u8(*((uint8x16_t*) x3), key)); + *x4 = vaesmcq_u8(vaeseq_u8(*((uint8x16_t*) x4), key)); + *x5 = vaesmcq_u8(vaeseq_u8(*((uint8x16_t*) x5), key)); + *x6 = vaesmcq_u8(vaeseq_u8(*((uint8x16_t*) x6), key)); + *x7 = vaesmcq_u8(vaeseq_u8(*((uint8x16_t*) x7), key)); + } # endif } template -static inline void cn_explode_scratchpad(const __m128i *input, __m128i *output) +static inline void cn_explode_scratchpad(const __m128i* input, __m128i* output) { - __m128i xin0, xin1, xin2, xin3, xin4, xin5, xin6, xin7; - __m128i k0, k1, k2, k3, k4, k5, k6, k7, k8, k9; + __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); + 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); + 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 < MEM / sizeof(__m128i); i += 8) { - if (!SOFT_AES) { - aes_round(_mm_setzero_si128(), &xin0, &xin1, &xin2, &xin3, &xin4, &xin5, &xin6, &xin7); - } + for(size_t i = 0; i < MEM / sizeof(__m128i); i += 8) + { + if(!SOFT_AES) + { + aes_round(_mm_setzero_si128(), &xin0, &xin1, &xin2, &xin3, &xin4, &xin5, &xin6, &xin7); + } - 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(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); - if (!SOFT_AES) { - xin0 ^= k9; - xin1 ^= k9; - xin2 ^= k9; - xin3 ^= k9; - xin4 ^= k9; - xin5 ^= k9; - xin6 ^= k9; - xin7 ^= k9; - } - else { - aes_round(k9, &xin0, &xin1, &xin2, &xin3, &xin4, &xin5, &xin6, &xin7); - } + if(!SOFT_AES) + { + xin0 ^= k9; + xin1 ^= k9; + xin2 ^= k9; + xin3 ^= k9; + xin4 ^= k9; + xin5 ^= k9; + xin6 ^= k9; + xin7 ^= k9; + } + else + { + 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); - } + _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); + } } template -static inline void cn_implode_scratchpad(const __m128i *input, __m128i *output) +static inline void cn_implode_scratchpad(const __m128i* input, __m128i* output) { - __m128i xout0, xout1, xout2, xout3, xout4, xout5, xout6, xout7; - __m128i k0, k1, k2, k3, k4, k5, k6, k7, k8, k9; + __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); + 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); + 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; i < MEM / sizeof(__m128i); 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); + for(size_t i = 0; i < MEM / sizeof(__m128i); 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); - if (!SOFT_AES) { - aes_round(_mm_setzero_si128(), &xout0, &xout1, &xout2, &xout3, &xout4, &xout5, &xout6, &xout7); - } + if(!SOFT_AES) + { + aes_round(_mm_setzero_si128(), &xout0, &xout1, &xout2, &xout3, &xout4, &xout5, &xout6, &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(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); - if (!SOFT_AES) { - xout0 ^= k9; - xout1 ^= k9; - xout2 ^= k9; - xout3 ^= k9; - xout4 ^= k9; - xout5 ^= k9; - xout6 ^= k9; - xout7 ^= k9; - } - else { - aes_round(k9, &xout0, &xout1, &xout2, &xout3, &xout4, &xout5, &xout6, &xout7); - } - } + if(!SOFT_AES) + { + xout0 ^= k9; + xout1 ^= k9; + xout2 ^= k9; + xout3 ^= k9; + xout4 ^= k9; + xout5 ^= k9; + xout6 ^= k9; + xout7 ^= k9; + } + else + { + 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); + _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); } template -inline void cryptonight_hash(const void *__restrict__ input, size_t size, void *__restrict__ output, cryptonight_ctx *__restrict__ ctx) +inline void cryptonight_hash(const void* __restrict__ input, size_t size, void* __restrict__ output, + cryptonight_ctx* __restrict__ ctx) { - keccak(static_cast(input), (int) size, ctx->state0, 200); + keccak(static_cast(input), (int) size, ctx->state0, 200); - cn_explode_scratchpad((__m128i*) ctx->state0, (__m128i*) ctx->memory); + cn_explode_scratchpad((__m128i*) ctx->state0, (__m128i*) ctx->memory); - const uint8_t* l0 = ctx->memory; - uint64_t* h0 = reinterpret_cast(ctx->state0); + const uint8_t* l0 = ctx->memory; + uint64_t* h0 = reinterpret_cast(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 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]; + uint64_t idx0 = h0[0] ^ h0[4]; - for (size_t i = 0; i < ITERATIONS; i++) { - __m128i cx; + for(size_t i = 0; i < ITERATIONS; i++) + { + __m128i cx; - if (SOFT_AES) { - cx = soft_aesenc((uint32_t*)&l0[idx0 & MASK], _mm_set_epi64x(ah0, al0)); - } - else { - cx = _mm_load_si128((__m128i *) &l0[idx0 & MASK]); + if(SOFT_AES) + { + cx = soft_aesenc((uint32_t*)&l0[idx0 & MASK], _mm_set_epi64x(ah0, al0)); + } + else + { + cx = _mm_load_si128((__m128i*) &l0[idx0 & MASK]); # ifndef XMRIG_ARMv7 - cx = vreinterpretq_m128i_u8(vaesmcq_u8(vaeseq_u8(cx, vdupq_n_u8(0)))) ^ _mm_set_epi64x(ah0, al0); + cx = vreinterpretq_m128i_u8(vaesmcq_u8(vaeseq_u8(cx, vdupq_n_u8(0)))) ^ _mm_set_epi64x(ah0, al0); # endif - } + } - _mm_store_si128((__m128i *) &l0[idx0 & MASK], _mm_xor_si128(bx0, cx)); - idx0 = EXTRACT64(cx); - bx0 = cx; + _mm_store_si128((__m128i*) &l0[idx0 & MASK], _mm_xor_si128(bx0, cx)); + idx0 = EXTRACT64(cx); + bx0 = cx; - uint64_t hi, lo, cl, ch; - cl = ((uint64_t*) &l0[idx0 & MASK])[0]; - ch = ((uint64_t*) &l0[idx0 & MASK])[1]; - lo = __umul128(idx0, cl, &hi); + uint64_t hi, lo, cl, ch; + cl = ((uint64_t*) &l0[idx0 & MASK])[0]; + ch = ((uint64_t*) &l0[idx0 & MASK])[1]; + lo = __umul128(idx0, cl, &hi); - al0 += hi; - ah0 += lo; + al0 += hi; + ah0 += lo; - ((uint64_t*)&l0[idx0 & MASK])[0] = al0; - ((uint64_t*)&l0[idx0 & MASK])[1] = ah0; + ((uint64_t*)&l0[idx0 & MASK])[0] = al0; + ((uint64_t*)&l0[idx0 & MASK])[1] = ah0; - ah0 ^= ch; - al0 ^= cl; - idx0 = al0; - } + ah0 ^= ch; + al0 ^= cl; + idx0 = al0; + } - cn_implode_scratchpad((__m128i*) ctx->memory, (__m128i*) ctx->state0); + cn_implode_scratchpad((__m128i*) ctx->memory, (__m128i*) ctx->state0); - keccakf(h0, 24); - extra_hashes[ctx->state0[0] & 3](ctx->state0, 200, static_cast(output)); + keccakf(h0, 24); + extra_hashes[ctx->state0[0] & 3](ctx->state0, 200, static_cast(output)); } template -inline void cryptonight_double_hash(const void *__restrict__ input, size_t size, void *__restrict__ output, struct cryptonight_ctx *__restrict__ ctx) +inline void cryptonight_double_hash(const void* __restrict__ input, size_t size, void* __restrict__ output, + struct cryptonight_ctx* __restrict__ ctx) { - keccak((const uint8_t *) input, (int) size, ctx->state0, 200); - keccak((const uint8_t *) input + size, (int) size, ctx->state1, 200); + keccak((const uint8_t*) input, (int) size, ctx->state0, 200); + keccak((const uint8_t*) input + size, (int) size, ctx->state1, 200); - const uint8_t* l0 = ctx->memory; - const uint8_t* l1 = ctx->memory + MEM; - uint64_t* h0 = reinterpret_cast(ctx->state0); - uint64_t* h1 = reinterpret_cast(ctx->state1); + const uint8_t* l0 = ctx->memory; + const uint8_t* l1 = ctx->memory + MEM; + uint64_t* h0 = reinterpret_cast(ctx->state0); + uint64_t* h1 = reinterpret_cast(ctx->state1); - cn_explode_scratchpad((__m128i*) h0, (__m128i*) l0); - cn_explode_scratchpad((__m128i*) h1, (__m128i*) l1); + 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]; + 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]); + __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]; + uint64_t idx0 = h0[0] ^ h0[4]; + uint64_t idx1 = h1[0] ^ h1[4]; - for (size_t i = 0; i < ITERATIONS; i++) { - __m128i cx0, cx1; + for(size_t i = 0; i < ITERATIONS; i++) + { + __m128i cx0, cx1; - if (SOFT_AES) { - cx0 = soft_aesenc((uint32_t*)&l0[idx0 & MASK], _mm_set_epi64x(ah0, al0)); - cx1 = soft_aesenc((uint32_t*)&l1[idx1 & MASK], _mm_set_epi64x(ah1, al1)); - } - else { - cx0 = _mm_load_si128((__m128i *) &l0[idx0 & MASK]); - cx1 = _mm_load_si128((__m128i *) &l1[idx1 & MASK]); + if(SOFT_AES) + { + cx0 = soft_aesenc((uint32_t*)&l0[idx0 & MASK], _mm_set_epi64x(ah0, al0)); + cx1 = soft_aesenc((uint32_t*)&l1[idx1 & MASK], _mm_set_epi64x(ah1, al1)); + } + else + { + cx0 = _mm_load_si128((__m128i*) &l0[idx0 & MASK]); + cx1 = _mm_load_si128((__m128i*) &l1[idx1 & MASK]); # ifndef XMRIG_ARMv7 - cx0 = vreinterpretq_m128i_u8(vaesmcq_u8(vaeseq_u8(cx0, vdupq_n_u8(0)))) ^ _mm_set_epi64x(ah0, al0); - cx1 = vreinterpretq_m128i_u8(vaesmcq_u8(vaeseq_u8(cx1, vdupq_n_u8(0)))) ^ _mm_set_epi64x(ah1, al1); + cx0 = vreinterpretq_m128i_u8(vaesmcq_u8(vaeseq_u8(cx0, vdupq_n_u8(0)))) ^ _mm_set_epi64x(ah0, al0); + cx1 = vreinterpretq_m128i_u8(vaesmcq_u8(vaeseq_u8(cx1, vdupq_n_u8(0)))) ^ _mm_set_epi64x(ah1, al1); # endif - } + } - _mm_store_si128((__m128i *) &l0[idx0 & MASK], _mm_xor_si128(bx0, cx0)); - _mm_store_si128((__m128i *) &l1[idx1 & MASK], _mm_xor_si128(bx1, cx1)); + _mm_store_si128((__m128i*) &l0[idx0 & MASK], _mm_xor_si128(bx0, cx0)); + _mm_store_si128((__m128i*) &l1[idx1 & MASK], _mm_xor_si128(bx1, cx1)); - idx0 = EXTRACT64(cx0); - idx1 = EXTRACT64(cx1); + idx0 = EXTRACT64(cx0); + idx1 = EXTRACT64(cx1); - bx0 = cx0; - bx1 = cx1; + bx0 = cx0; + bx1 = cx1; - uint64_t hi, lo, cl, ch; - cl = ((uint64_t*) &l0[idx0 & MASK])[0]; - ch = ((uint64_t*) &l0[idx0 & MASK])[1]; - lo = __umul128(idx0, cl, &hi); + uint64_t hi, lo, cl, ch; + cl = ((uint64_t*) &l0[idx0 & MASK])[0]; + ch = ((uint64_t*) &l0[idx0 & MASK])[1]; + lo = __umul128(idx0, cl, &hi); - al0 += hi; - ah0 += lo; + al0 += hi; + ah0 += lo; - ((uint64_t*) &l0[idx0 & MASK])[0] = al0; - ((uint64_t*) &l0[idx0 & MASK])[1] = ah0; + ((uint64_t*) &l0[idx0 & MASK])[0] = al0; + ((uint64_t*) &l0[idx0 & MASK])[1] = ah0; - ah0 ^= ch; - al0 ^= cl; - idx0 = al0; + ah0 ^= ch; + al0 ^= cl; + idx0 = al0; - cl = ((uint64_t*) &l1[idx1 & MASK])[0]; - ch = ((uint64_t*) &l1[idx1 & MASK])[1]; - lo = __umul128(idx1, cl, &hi); + cl = ((uint64_t*) &l1[idx1 & MASK])[0]; + ch = ((uint64_t*) &l1[idx1 & MASK])[1]; + lo = __umul128(idx1, cl, &hi); - al1 += hi; - ah1 += lo; + al1 += hi; + ah1 += lo; - ((uint64_t*) &l1[idx1 & MASK])[0] = al1; - ((uint64_t*) &l1[idx1 & MASK])[1] = ah1; + ((uint64_t*) &l1[idx1 & MASK])[0] = al1; + ((uint64_t*) &l1[idx1 & MASK])[1] = ah1; - ah1 ^= ch; - al1 ^= cl; - idx1 = al1; - } + ah1 ^= ch; + al1 ^= cl; + idx1 = al1; + } - cn_implode_scratchpad((__m128i*) l0, (__m128i*) h0); - cn_implode_scratchpad((__m128i*) l1, (__m128i*) h1); + cn_implode_scratchpad((__m128i*) l0, (__m128i*) h0); + cn_implode_scratchpad((__m128i*) l1, (__m128i*) h1); - keccakf(h0, 24); - keccakf(h1, 24); + keccakf(h0, 24); + keccakf(h1, 24); - extra_hashes[ctx->state0[0] & 3](ctx->state0, 200, static_cast(output)); - extra_hashes[ctx->state1[0] & 3](ctx->state1, 200, static_cast(output) + 32); + extra_hashes[ctx->state0[0] & 3](ctx->state0, 200, static_cast(output)); + extra_hashes[ctx->state1[0] & 3](ctx->state1, 200, static_cast(output) + 32); } #endif /* __CRYPTONIGHT_ARM_H__ */ diff --git a/src/crypto/CryptoNight_test.h b/src/crypto/CryptoNight_test.h index b2985379..c6bb51f3 100644 --- a/src/crypto/CryptoNight_test.h +++ b/src/crypto/CryptoNight_test.h @@ -25,34 +25,37 @@ #define __CRYPTONIGHT_TEST_H__ -const static uint8_t 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 uint8_t 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 uint8_t 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 +const static uint8_t 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 }; #ifndef XMRIG_NO_AEON -const static uint8_t 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, +const static uint8_t 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, }; #endif diff --git a/src/crypto/CryptoNight_x86.h b/src/crypto/CryptoNight_x86.h index 927aab72..b94e7000 100644 --- a/src/crypto/CryptoNight_x86.h +++ b/src/crypto/CryptoNight_x86.h @@ -47,27 +47,31 @@ extern "C" } -static inline void do_blake_hash(const void* input, size_t len, char* output) { - blake256_hash(reinterpret_cast(output), static_cast(input), len); +static inline void do_blake_hash(const void* input, size_t len, char* output) +{ + blake256_hash(reinterpret_cast(output), static_cast(input), len); } -static inline void do_groestl_hash(const void* input, size_t len, char* output) { - groestl(static_cast(input), len * 8, reinterpret_cast(output)); +static inline void do_groestl_hash(const void* input, size_t len, char* output) +{ + groestl(static_cast(input), len * 8, reinterpret_cast(output)); } -static inline void do_jh_hash(const void* input, size_t len, char* output) { - jh_hash(32 * 8, static_cast(input), 8 * len, reinterpret_cast(output)); +static inline void do_jh_hash(const void* input, size_t len, char* output) +{ + jh_hash(32 * 8, static_cast(input), 8 * len, reinterpret_cast(output)); } -static inline void do_skein_hash(const void* input, size_t len, char* output) { - xmr_skein(static_cast(input), reinterpret_cast(output)); +static inline void do_skein_hash(const void* input, size_t len, char* output) +{ + xmr_skein(static_cast(input), reinterpret_cast(output)); } -void (* const extra_hashes[4])(const void *, size_t, char *) = {do_blake_hash, do_groestl_hash, do_jh_hash, do_skein_hash}; +void (* const extra_hashes[4])(const void*, size_t, char*) = {do_blake_hash, do_groestl_hash, do_jh_hash, do_skein_hash}; @@ -77,45 +81,46 @@ void (* const extra_hashes[4])(const void *, size_t, char *) = {do_blake_hash, d # ifdef __GNUC__ static 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; + unsigned __int128 r = (unsigned __int128) a * (unsigned __int128) b; + *hi = r >> 64; + return (uint64_t) r; } # else - #define __umul128 _umul128 +#define __umul128 _umul128 # endif #elif defined(__i386__) || defined(_M_IX86) # define HI32(X) \ - _mm_srli_si128((X), 4) + _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)) + ((uint64_t)(uint32_t)_mm_cvtsi128_si32(X) | \ + ((uint64_t)(uint32_t)_mm_cvtsi128_si32(HI32(X)) << 32)) -static 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; +static 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 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; + 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; + // 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; + return product_lo; } #endif @@ -124,328 +129,341 @@ static inline uint64_t __umul128(uint64_t multiplier, uint64_t multiplicand, uin // sl_xor(a1 a2 a3 a4) = a1 (a2^a1) (a3^a2^a1) (a4^a3^a2^a1) static 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; + __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; } template static inline void aes_genkey_sub(__m128i* xout0, __m128i* xout2) { - __m128i xout1 = _mm_aeskeygenassist_si128(*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 = _mm_aeskeygenassist_si128(*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); + __m128i xout1 = _mm_aeskeygenassist_si128(*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 = _mm_aeskeygenassist_si128(*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); } template static inline void soft_aes_genkey_sub(__m128i* xout0, __m128i* xout2) { - __m128i xout1 = soft_aeskeygenassist(*xout2); - 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<0x00>(*xout0); - xout1 = _mm_shuffle_epi32(xout1, 0xAA); // see PSHUFD, set all elems to 3rd elem - *xout2 = sl_xor(*xout2); - *xout2 = _mm_xor_si128(*xout2, xout1); + __m128i xout1 = soft_aeskeygenassist(*xout2); + 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<0x00>(*xout0); + xout1 = _mm_shuffle_epi32(xout1, 0xAA); // see PSHUFD, set all elems to 3rd elem + *xout2 = sl_xor(*xout2); + *xout2 = _mm_xor_si128(*xout2, xout1); } template -static 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) +static 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; + __m128i xout0 = _mm_load_si128(memory); + __m128i xout2 = _mm_load_si128(memory + 1); + *k0 = xout0; + *k1 = xout2; - SOFT_AES ? soft_aes_genkey_sub<0x01>(&xout0, &xout2) : aes_genkey_sub<0x01>(&xout0, &xout2); - *k2 = xout0; - *k3 = xout2; + SOFT_AES ? soft_aes_genkey_sub<0x01>(&xout0, &xout2) : aes_genkey_sub<0x01>(&xout0, &xout2); + *k2 = xout0; + *k3 = xout2; - SOFT_AES ? soft_aes_genkey_sub<0x02>(&xout0, &xout2) : aes_genkey_sub<0x02>(&xout0, &xout2); - *k4 = xout0; - *k5 = xout2; + SOFT_AES ? soft_aes_genkey_sub<0x02>(&xout0, &xout2) : aes_genkey_sub<0x02>(&xout0, &xout2); + *k4 = xout0; + *k5 = xout2; - SOFT_AES ? soft_aes_genkey_sub<0x04>(&xout0, &xout2) : aes_genkey_sub<0x04>(&xout0, &xout2); - *k6 = xout0; - *k7 = xout2; + SOFT_AES ? soft_aes_genkey_sub<0x04>(&xout0, &xout2) : aes_genkey_sub<0x04>(&xout0, &xout2); + *k6 = xout0; + *k7 = xout2; - SOFT_AES ? soft_aes_genkey_sub<0x08>(&xout0, &xout2) : aes_genkey_sub<0x08>(&xout0, &xout2); - *k8 = xout0; - *k9 = xout2; + SOFT_AES ? soft_aes_genkey_sub<0x08>(&xout0, &xout2) : aes_genkey_sub<0x08>(&xout0, &xout2); + *k8 = xout0; + *k9 = xout2; } template -static inline void aes_round(__m128i key, __m128i* x0, __m128i* x1, __m128i* x2, __m128i* x3, __m128i* x4, __m128i* x5, __m128i* x6, __m128i* x7) +static inline void aes_round(__m128i key, __m128i* x0, __m128i* x1, __m128i* x2, __m128i* x3, __m128i* x4, + __m128i* x5, __m128i* x6, __m128i* x7) { - if (SOFT_AES) { - *x0 = soft_aesenc((uint32_t*)x0, key); - *x1 = soft_aesenc((uint32_t*)x1, key); - *x2 = soft_aesenc((uint32_t*)x2, key); - *x3 = soft_aesenc((uint32_t*)x3, key); - *x4 = soft_aesenc((uint32_t*)x4, key); - *x5 = soft_aesenc((uint32_t*)x5, key); - *x6 = soft_aesenc((uint32_t*)x6, key); - *x7 = soft_aesenc((uint32_t*)x7, key); - } - else { - *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); - } + if(SOFT_AES) + { + *x0 = soft_aesenc((uint32_t*)x0, key); + *x1 = soft_aesenc((uint32_t*)x1, key); + *x2 = soft_aesenc((uint32_t*)x2, key); + *x3 = soft_aesenc((uint32_t*)x3, key); + *x4 = soft_aesenc((uint32_t*)x4, key); + *x5 = soft_aesenc((uint32_t*)x5, key); + *x6 = soft_aesenc((uint32_t*)x6, key); + *x7 = soft_aesenc((uint32_t*)x7, key); + } + else + { + *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); + } } template -static inline void cn_explode_scratchpad(const __m128i *input, __m128i *output) +static inline void cn_explode_scratchpad(const __m128i* input, __m128i* output) { - __m128i xin0, xin1, xin2, xin3, xin4, xin5, xin6, xin7; - __m128i k0, k1, k2, k3, k4, k5, k6, k7, k8, k9; + __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); + 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); + 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 < MEM / 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); + for(size_t i = 0; i < MEM / 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); - } + _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); + } } template -static inline void cn_implode_scratchpad(const __m128i *input, __m128i *output) +static inline void cn_implode_scratchpad(const __m128i* input, __m128i* output) { - __m128i xout0, xout1, xout2, xout3, xout4, xout5, xout6, xout7; - __m128i k0, k1, k2, k3, k4, k5, k6, k7, k8, k9; + __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); + 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); + 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; i < MEM / sizeof(__m128i); 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); + for(size_t i = 0; i < MEM / sizeof(__m128i); 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); - } + 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); + _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); } template -inline void cryptonight_hash(const void *__restrict__ input, size_t size, void *__restrict__ output, cryptonight_ctx *__restrict__ ctx) +inline void cryptonight_hash(const void* __restrict__ input, size_t size, void* __restrict__ output, + cryptonight_ctx* __restrict__ ctx) { - keccak(static_cast(input), (int) size, ctx->state0, 200); + keccak(static_cast(input), (int) size, ctx->state0, 200); - cn_explode_scratchpad((__m128i*) ctx->state0, (__m128i*) ctx->memory); + cn_explode_scratchpad((__m128i*) ctx->state0, (__m128i*) ctx->memory); - const uint8_t* l0 = ctx->memory; - uint64_t* h0 = reinterpret_cast(ctx->state0); + const uint8_t* l0 = ctx->memory; + uint64_t* h0 = reinterpret_cast(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 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]; + uint64_t idx0 = h0[0] ^ h0[4]; - for (size_t i = 0; i < ITERATIONS; i++) { - __m128i cx; + for(size_t i = 0; i < ITERATIONS; i++) + { + __m128i cx; - if (SOFT_AES) { - cx = soft_aesenc((uint32_t*)&l0[idx0 & MASK], _mm_set_epi64x(ah0, al0)); - } - else { - cx = _mm_load_si128((__m128i *) &l0[idx0 & MASK]); - cx = _mm_aesenc_si128(cx, _mm_set_epi64x(ah0, al0)); - } - _mm_store_si128((__m128i *) &l0[idx0 & MASK], _mm_xor_si128(bx0, cx)); - idx0 = EXTRACT64(cx); - bx0 = cx; + if(SOFT_AES) + { + cx = soft_aesenc((uint32_t*)&l0[idx0 & MASK], _mm_set_epi64x(ah0, al0)); + } + else + { + cx = _mm_load_si128((__m128i*) &l0[idx0 & MASK]); + cx = _mm_aesenc_si128(cx, _mm_set_epi64x(ah0, al0)); + } + _mm_store_si128((__m128i*) &l0[idx0 & MASK], _mm_xor_si128(bx0, cx)); + idx0 = EXTRACT64(cx); + bx0 = cx; - uint64_t hi, lo, cl, ch; - cl = ((uint64_t*) &l0[idx0 & MASK])[0]; - ch = ((uint64_t*) &l0[idx0 & MASK])[1]; - lo = __umul128(idx0, cl, &hi); + uint64_t hi, lo, cl, ch; + cl = ((uint64_t*) &l0[idx0 & MASK])[0]; + ch = ((uint64_t*) &l0[idx0 & MASK])[1]; + lo = __umul128(idx0, cl, &hi); - al0 += hi; - ah0 += lo; + al0 += hi; + ah0 += lo; - ((uint64_t*)&l0[idx0 & MASK])[0] = al0; - ((uint64_t*)&l0[idx0 & MASK])[1] = ah0; + ((uint64_t*)&l0[idx0 & MASK])[0] = al0; + ((uint64_t*)&l0[idx0 & MASK])[1] = ah0; - ah0 ^= ch; - al0 ^= cl; - idx0 = al0; - } + ah0 ^= ch; + al0 ^= cl; + idx0 = al0; + } - cn_implode_scratchpad((__m128i*) ctx->memory, (__m128i*) ctx->state0); + cn_implode_scratchpad((__m128i*) ctx->memory, (__m128i*) ctx->state0); - keccakf(h0, 24); - extra_hashes[ctx->state0[0] & 3](ctx->state0, 200, static_cast(output)); + keccakf(h0, 24); + extra_hashes[ctx->state0[0] & 3](ctx->state0, 200, static_cast(output)); } template -inline void cryptonight_double_hash(const void *__restrict__ input, size_t size, void *__restrict__ output, struct cryptonight_ctx *__restrict__ ctx) +inline void cryptonight_double_hash(const void* __restrict__ input, size_t size, void* __restrict__ output, + struct cryptonight_ctx* __restrict__ ctx) { - keccak((const uint8_t *) input, (int) size, ctx->state0, 200); - keccak((const uint8_t *) input + size, (int) size, ctx->state1, 200); + keccak((const uint8_t*) input, (int) size, ctx->state0, 200); + keccak((const uint8_t*) input + size, (int) size, ctx->state1, 200); - const uint8_t* l0 = ctx->memory; - const uint8_t* l1 = ctx->memory + MEM; - uint64_t* h0 = reinterpret_cast(ctx->state0); - uint64_t* h1 = reinterpret_cast(ctx->state1); + const uint8_t* l0 = ctx->memory; + const uint8_t* l1 = ctx->memory + MEM; + uint64_t* h0 = reinterpret_cast(ctx->state0); + uint64_t* h1 = reinterpret_cast(ctx->state1); - cn_explode_scratchpad((__m128i*) h0, (__m128i*) l0); - cn_explode_scratchpad((__m128i*) h1, (__m128i*) l1); + 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]; + 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]); + __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]; + uint64_t idx0 = h0[0] ^ h0[4]; + uint64_t idx1 = h1[0] ^ h1[4]; - for (size_t i = 0; i < ITERATIONS; i++) { - __m128i cx0, cx1; + for(size_t i = 0; i < ITERATIONS; i++) + { + __m128i cx0, cx1; - if (SOFT_AES) { - cx0 = soft_aesenc((uint32_t*)&l0[idx0 & MASK], _mm_set_epi64x(ah0, al0)); - cx1 = soft_aesenc((uint32_t*)&l1[idx1 & MASK], _mm_set_epi64x(ah1, al1)); - } - else { - cx0 = _mm_load_si128((__m128i *) &l0[idx0 & MASK]); - cx1 = _mm_load_si128((__m128i *) &l1[idx1 & MASK]); - cx0 = _mm_aesenc_si128(cx0, _mm_set_epi64x(ah0, al0)); - cx1 = _mm_aesenc_si128(cx1, _mm_set_epi64x(ah1, al1)); - } + if(SOFT_AES) + { + cx0 = soft_aesenc((uint32_t*)&l0[idx0 & MASK], _mm_set_epi64x(ah0, al0)); + cx1 = soft_aesenc((uint32_t*)&l1[idx1 & MASK], _mm_set_epi64x(ah1, al1)); + } + else + { + cx0 = _mm_load_si128((__m128i*) &l0[idx0 & MASK]); + cx1 = _mm_load_si128((__m128i*) &l1[idx1 & MASK]); + 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 & MASK], _mm_xor_si128(bx0, cx0)); - _mm_store_si128((__m128i *) &l1[idx1 & MASK], _mm_xor_si128(bx1, cx1)); + _mm_store_si128((__m128i*) &l0[idx0 & MASK], _mm_xor_si128(bx0, cx0)); + _mm_store_si128((__m128i*) &l1[idx1 & MASK], _mm_xor_si128(bx1, cx1)); - idx0 = EXTRACT64(cx0); - idx1 = EXTRACT64(cx1); + idx0 = EXTRACT64(cx0); + idx1 = EXTRACT64(cx1); - bx0 = cx0; - bx1 = cx1; + bx0 = cx0; + bx1 = cx1; - uint64_t hi, lo, cl, ch; - cl = ((uint64_t*) &l0[idx0 & MASK])[0]; - ch = ((uint64_t*) &l0[idx0 & MASK])[1]; - lo = __umul128(idx0, cl, &hi); + uint64_t hi, lo, cl, ch; + cl = ((uint64_t*) &l0[idx0 & MASK])[0]; + ch = ((uint64_t*) &l0[idx0 & MASK])[1]; + lo = __umul128(idx0, cl, &hi); - al0 += hi; - ah0 += lo; + al0 += hi; + ah0 += lo; - ((uint64_t*) &l0[idx0 & MASK])[0] = al0; - ((uint64_t*) &l0[idx0 & MASK])[1] = ah0; + ((uint64_t*) &l0[idx0 & MASK])[0] = al0; + ((uint64_t*) &l0[idx0 & MASK])[1] = ah0; - ah0 ^= ch; - al0 ^= cl; - idx0 = al0; + ah0 ^= ch; + al0 ^= cl; + idx0 = al0; - cl = ((uint64_t*) &l1[idx1 & MASK])[0]; - ch = ((uint64_t*) &l1[idx1 & MASK])[1]; - lo = __umul128(idx1, cl, &hi); + cl = ((uint64_t*) &l1[idx1 & MASK])[0]; + ch = ((uint64_t*) &l1[idx1 & MASK])[1]; + lo = __umul128(idx1, cl, &hi); - al1 += hi; - ah1 += lo; + al1 += hi; + ah1 += lo; - ((uint64_t*) &l1[idx1 & MASK])[0] = al1; - ((uint64_t*) &l1[idx1 & MASK])[1] = ah1; + ((uint64_t*) &l1[idx1 & MASK])[0] = al1; + ((uint64_t*) &l1[idx1 & MASK])[1] = ah1; - ah1 ^= ch; - al1 ^= cl; - idx1 = al1; - } + ah1 ^= ch; + al1 ^= cl; + idx1 = al1; + } - cn_implode_scratchpad((__m128i*) l0, (__m128i*) h0); - cn_implode_scratchpad((__m128i*) l1, (__m128i*) h1); + cn_implode_scratchpad((__m128i*) l0, (__m128i*) h0); + cn_implode_scratchpad((__m128i*) l1, (__m128i*) h1); - keccakf(h0, 24); - keccakf(h1, 24); + keccakf(h0, 24); + keccakf(h1, 24); - extra_hashes[ctx->state0[0] & 3](ctx->state0, 200, static_cast(output)); - extra_hashes[ctx->state1[0] & 3](ctx->state1, 200, static_cast(output) + 32); + extra_hashes[ctx->state0[0] & 3](ctx->state0, 200, static_cast(output)); + extra_hashes[ctx->state1[0] & 3](ctx->state1, 200, static_cast(output) + 32); } #endif /* __CRYPTONIGHT_X86_H__ */ diff --git a/src/crypto/SSE2NEON.h b/src/crypto/SSE2NEON.h index 6a00448d..bb5bdb08 100644 --- a/src/crypto/SSE2NEON.h +++ b/src/crypto/SSE2NEON.h @@ -49,7 +49,7 @@ // A struct is now defined in this header file called 'SIMDVec' which can be used by applications which // attempt to access the contents of an _m128 struct directly. It is important to note that accessing the __m128 // struct directly is bad coding practice by Microsoft: @see: https://msdn.microsoft.com/en-us/library/ayeb3ayc.aspx -// +// // However, some legacy source code may try to access the contents of an __m128 struct directly so the developer // can use the SIMDVec as an alias for it. Any casting must be done manually by the developer, as you cannot // cast or otherwise alias the base NEON data type for intrinsic operations. @@ -66,7 +66,7 @@ // // Support for a number of new intrinsics was added, however, none of them yet have unit-tests to 100% confirm they are // producing the correct results on NEON. These unit tests will be added as soon as possible. -// +// // Here is the list of new instrinsics which have been added: // // _mm_cvtss_f32 : extracts the lower order floating point value from the parameter @@ -338,9 +338,9 @@ FORCE_INLINE __m128 _mm_set_ps(float w, float z, float y, float x) } // Sets the four single-precision, floating-point values to the four inputs in reverse order. https://msdn.microsoft.com/en-us/library/vstudio/d2172ct3(v=vs.100).aspx -FORCE_INLINE __m128 _mm_setr_ps(float w, float z , float y , float x ) +FORCE_INLINE __m128 _mm_setr_ps(float w, float z , float y , float x) { - float __attribute__ ((aligned (16))) data[4] = { w, z, y, x }; + float __attribute__((aligned(16))) data[4] = { w, z, y, x }; return vreinterpretq_m128_f32(vld1q_f32(data)); } @@ -358,25 +358,25 @@ FORCE_INLINE __m128i _mm_set_epi32(int i3, int i2, int i1, int i0) } // Stores four single-precision, floating-point values. https://msdn.microsoft.com/en-us/library/vstudio/s3h4ay6y(v=vs.100).aspx -FORCE_INLINE void _mm_store_ps(float *p, __m128 a) +FORCE_INLINE void _mm_store_ps(float* p, __m128 a) { vst1q_f32(p, vreinterpretq_f32_m128(a)); } // Stores four single-precision, floating-point values. https://msdn.microsoft.com/en-us/library/44e30x22(v=vs.100).aspx -FORCE_INLINE void _mm_storeu_ps(float *p, __m128 a) +FORCE_INLINE void _mm_storeu_ps(float* p, __m128 a) { vst1q_f32(p, vreinterpretq_f32_m128(a)); } // Stores four 32-bit integer values as (as a __m128i value) at the address p. https://msdn.microsoft.com/en-us/library/vstudio/edk11s13(v=vs.100).aspx -FORCE_INLINE void _mm_store_si128(__m128i *p, __m128i a) +FORCE_INLINE void _mm_store_si128(__m128i* p, __m128i a) { vst1q_s32((int32_t*) p, vreinterpretq_s32_m128i(a)); } // Stores the lower single - precision, floating - point value. https://msdn.microsoft.com/en-us/library/tzz10fbx(v=vs.100).aspx -FORCE_INLINE void _mm_store_ss(float *p, __m128 a) +FORCE_INLINE void _mm_store_ss(float* p, __m128 a) { vst1q_lane_f32(p, vreinterpretq_f32_m128(a), 0); } @@ -390,26 +390,26 @@ FORCE_INLINE void _mm_storel_epi64(__m128i* a, __m128i b) } // Loads a single single-precision, floating-point value, copying it into all four words https://msdn.microsoft.com/en-us/library/vstudio/5cdkf716(v=vs.100).aspx -FORCE_INLINE __m128 _mm_load1_ps(const float * p) +FORCE_INLINE __m128 _mm_load1_ps(const float* p) { return vreinterpretq_m128_f32(vld1q_dup_f32(p)); } // Loads four single-precision, floating-point values. https://msdn.microsoft.com/en-us/library/vstudio/zzd50xxt(v=vs.100).aspx -FORCE_INLINE __m128 _mm_load_ps(const float * p) +FORCE_INLINE __m128 _mm_load_ps(const float* p) { return vreinterpretq_m128_f32(vld1q_f32(p)); } // Loads four single-precision, floating-point values. https://msdn.microsoft.com/en-us/library/x1b16s7z%28v=vs.90%29.aspx -FORCE_INLINE __m128 _mm_loadu_ps(const float * p) +FORCE_INLINE __m128 _mm_loadu_ps(const float* p) { // for neon, alignment doesn't matter, so _mm_load_ps and _mm_loadu_ps are equivalent for neon return vreinterpretq_m128_f32(vld1q_f32(p)); } // Loads an single - precision, floating - point value into the low word and clears the upper three words. https://msdn.microsoft.com/en-us/library/548bb9h4%28v=vs.90%29.aspx -FORCE_INLINE __m128 _mm_load_ss(const float * p) +FORCE_INLINE __m128 _mm_load_ss(const float* p) { return vreinterpretq_m128_f32(vsetq_lane_f32(*p, vdupq_n_f32(0), 0)); } @@ -422,55 +422,57 @@ FORCE_INLINE __m128 _mm_load_ss(const float * p) // Compares for inequality. https://msdn.microsoft.com/en-us/library/sf44thbx(v=vs.100).aspx FORCE_INLINE __m128 _mm_cmpneq_ps(__m128 a, __m128 b) { - return vreinterpretq_m128_u32( vmvnq_u32( vceqq_f32(vreinterpretq_f32_m128(a), vreinterpretq_f32_m128(b)) ) ); + return vreinterpretq_m128_u32(vmvnq_u32(vceqq_f32(vreinterpretq_f32_m128(a), vreinterpretq_f32_m128(b)))); } // Computes the bitwise AND-NOT of the four single-precision, floating-point values of a and b. https://msdn.microsoft.com/en-us/library/vstudio/68h7wd02(v=vs.100).aspx FORCE_INLINE __m128 _mm_andnot_ps(__m128 a, __m128 b) { - return vreinterpretq_m128_s32( vbicq_s32(vreinterpretq_s32_m128(b), vreinterpretq_s32_m128(a)) ); // *NOTE* argument swap + return vreinterpretq_m128_s32(vbicq_s32(vreinterpretq_s32_m128(b), + vreinterpretq_s32_m128(a))); // *NOTE* argument swap } // Computes the bitwise AND of the 128-bit value in b and the bitwise NOT of the 128-bit value in a. https://msdn.microsoft.com/en-us/library/vstudio/1beaceh8(v=vs.100).aspx FORCE_INLINE __m128i _mm_andnot_si128(__m128i a, __m128i b) { - return vreinterpretq_m128i_s32( vbicq_s32(vreinterpretq_s32_m128i(b), vreinterpretq_s32_m128i(a)) ); // *NOTE* argument swap + return vreinterpretq_m128i_s32(vbicq_s32(vreinterpretq_s32_m128i(b), + vreinterpretq_s32_m128i(a))); // *NOTE* argument swap } // Computes the bitwise AND of the 128-bit value in a and the 128-bit value in b. https://msdn.microsoft.com/en-us/library/vstudio/6d1txsa8(v=vs.100).aspx FORCE_INLINE __m128i _mm_and_si128(__m128i a, __m128i b) { - return vreinterpretq_m128i_s32( vandq_s32(vreinterpretq_s32_m128i(a), vreinterpretq_s32_m128i(b)) ); + return vreinterpretq_m128i_s32(vandq_s32(vreinterpretq_s32_m128i(a), vreinterpretq_s32_m128i(b))); } // Computes the bitwise AND of the four single-precision, floating-point values of a and b. https://msdn.microsoft.com/en-us/library/vstudio/73ck1xc5(v=vs.100).aspx FORCE_INLINE __m128 _mm_and_ps(__m128 a, __m128 b) { - return vreinterpretq_m128_s32( vandq_s32(vreinterpretq_s32_m128(a), vreinterpretq_s32_m128(b)) ); + return vreinterpretq_m128_s32(vandq_s32(vreinterpretq_s32_m128(a), vreinterpretq_s32_m128(b))); } // Computes the bitwise OR of the four single-precision, floating-point values of a and b. https://msdn.microsoft.com/en-us/library/vstudio/7ctdsyy0(v=vs.100).aspx FORCE_INLINE __m128 _mm_or_ps(__m128 a, __m128 b) { - return vreinterpretq_m128_s32( vorrq_s32(vreinterpretq_s32_m128(a), vreinterpretq_s32_m128(b)) ); + return vreinterpretq_m128_s32(vorrq_s32(vreinterpretq_s32_m128(a), vreinterpretq_s32_m128(b))); } // Computes bitwise EXOR (exclusive-or) of the four single-precision, floating-point values of a and b. https://msdn.microsoft.com/en-us/library/ss6k3wk8(v=vs.100).aspx FORCE_INLINE __m128 _mm_xor_ps(__m128 a, __m128 b) { - return vreinterpretq_m128_s32( veorq_s32(vreinterpretq_s32_m128(a), vreinterpretq_s32_m128(b)) ); + return vreinterpretq_m128_s32(veorq_s32(vreinterpretq_s32_m128(a), vreinterpretq_s32_m128(b))); } // Computes the bitwise OR of the 128-bit value in a and the 128-bit value in b. https://msdn.microsoft.com/en-us/library/vstudio/ew8ty0db(v=vs.100).aspx FORCE_INLINE __m128i _mm_or_si128(__m128i a, __m128i b) { - return vreinterpretq_m128i_s32( vorrq_s32(vreinterpretq_s32_m128i(a), vreinterpretq_s32_m128i(b)) ); + return vreinterpretq_m128i_s32(vorrq_s32(vreinterpretq_s32_m128i(a), vreinterpretq_s32_m128i(b))); } // Computes the bitwise XOR of the 128-bit value in a and the 128-bit value in b. https://msdn.microsoft.com/en-us/library/fzt08www(v=vs.100).aspx FORCE_INLINE __m128i _mm_xor_si128(__m128i a, __m128i b) { - return vreinterpretq_m128i_s32( veorq_s32(vreinterpretq_s32_m128i(a), vreinterpretq_s32_m128i(b)) ); + return vreinterpretq_m128i_s32(veorq_s32(vreinterpretq_s32_m128i(a), vreinterpretq_s32_m128i(b))); } // NEON does not provide this method @@ -478,7 +480,7 @@ FORCE_INLINE __m128i _mm_xor_si128(__m128i a, __m128i b) FORCE_INLINE int _mm_movemask_ps(__m128 a) { #if ENABLE_CPP_VERSION // I am not yet convinced that the NEON version is faster than the C version of this - uint32x4_t &ia = *(uint32x4_t *)&a; + uint32x4_t & ia = *(uint32x4_t*)&a; return (ia[0] >> 31) | ((ia[1] >> 30) & 2) | ((ia[2] >> 29) & 4) | ((ia[3] >> 28) & 8); #else static const uint32x4_t movemask = { 1, 2, 4, 8 }; @@ -622,7 +624,7 @@ FORCE_INLINE __m128 _mm_shuffle_ps_2032(__m128 a, __m128 b) // The same is true on SSE as well. // Selects four specific single-precision, floating-point values from a and b, based on the mask i. https://msdn.microsoft.com/en-us/library/vstudio/5f0858x0(v=vs.100).aspx #if ENABLE_CPP_VERSION // I am not convinced that the NEON version is faster than the C version yet. -FORCE_INLINE __m128 _mm_shuffle_ps_default(__m128 a, __m128 b, __constrange(0,255) int imm) +FORCE_INLINE __m128 _mm_shuffle_ps_default(__m128 a, __m128 b, __constrange(0, 255) int imm) { __m128 ret; ret[0] = a[imm & 0x3]; @@ -633,22 +635,22 @@ FORCE_INLINE __m128 _mm_shuffle_ps_default(__m128 a, __m128 b, __constrange(0,25 } #else #define _mm_shuffle_ps_default(a, b, imm) \ -({ \ - float32x4_t ret; \ - ret = vmovq_n_f32(vgetq_lane_f32(vreinterpretq_f32_m128(a), (imm) & 0x3)); \ - ret = vsetq_lane_f32(vgetq_lane_f32(vreinterpretq_f32_m128(a), ((imm) >> 2) & 0x3), ret, 1); \ - ret = vsetq_lane_f32(vgetq_lane_f32(vreinterpretq_f32_m128(b), ((imm) >> 4) & 0x3), ret, 2); \ - ret = vsetq_lane_f32(vgetq_lane_f32(vreinterpretq_f32_m128(b), ((imm) >> 6) & 0x3), ret, 3); \ - vreinterpretq_m128_f32(ret); \ -}) + ({ \ + float32x4_t ret; \ + ret = vmovq_n_f32(vgetq_lane_f32(vreinterpretq_f32_m128(a), (imm) & 0x3)); \ + ret = vsetq_lane_f32(vgetq_lane_f32(vreinterpretq_f32_m128(a), ((imm) >> 2) & 0x3), ret, 1); \ + ret = vsetq_lane_f32(vgetq_lane_f32(vreinterpretq_f32_m128(b), ((imm) >> 4) & 0x3), ret, 2); \ + ret = vsetq_lane_f32(vgetq_lane_f32(vreinterpretq_f32_m128(b), ((imm) >> 6) & 0x3), ret, 3); \ + vreinterpretq_m128_f32(ret); \ + }) #endif //FORCE_INLINE __m128 _mm_shuffle_ps(__m128 a, __m128 b, __constrange(0,255) int imm) #define _mm_shuffle_ps(a, b, imm) \ -({ \ - __m128 ret; \ - switch (imm) \ - { \ + ({ \ + __m128 ret; \ + switch (imm) \ + { \ case _MM_SHUFFLE(1, 0, 3, 2): ret = _mm_shuffle_ps_1032((a), (b)); break; \ case _MM_SHUFFLE(2, 3, 0, 1): ret = _mm_shuffle_ps_2301((a), (b)); break; \ case _MM_SHUFFLE(0, 3, 2, 1): ret = _mm_shuffle_ps_0321((a), (b)); break; \ @@ -666,9 +668,9 @@ FORCE_INLINE __m128 _mm_shuffle_ps_default(__m128 a, __m128 b, __constrange(0,25 case _MM_SHUFFLE(2, 0, 0, 1): ret = _mm_shuffle_ps_2001((a), (b)); break; \ case _MM_SHUFFLE(2, 0, 3, 2): ret = _mm_shuffle_ps_2032((a), (b)); break; \ default: ret = _mm_shuffle_ps_default((a), (b), (imm)); break; \ - } \ - ret; \ -}) + } \ + ret; \ + }) // Takes the upper 64 bits of a and places it in the low end of the result // Takes the lower 64 bits of a and places it into the high end of the result. @@ -748,7 +750,7 @@ FORCE_INLINE __m128i _mm_shuffle_epi_3332(__m128i a) //FORCE_INLINE __m128i _mm_shuffle_epi32_default(__m128i a, __constrange(0,255) int imm) #if ENABLE_CPP_VERSION -FORCE_INLINE __m128i _mm_shuffle_epi32_default(__m128i a, __constrange(0,255) int imm) +FORCE_INLINE __m128i _mm_shuffle_epi32_default(__m128i a, __constrange(0, 255) int imm) { __m128i ret; ret[0] = a[imm & 0x3]; @@ -759,36 +761,36 @@ FORCE_INLINE __m128i _mm_shuffle_epi32_default(__m128i a, __constrange(0,255) in } #else #define _mm_shuffle_epi32_default(a, imm) \ -({ \ - int32x4_t ret; \ - ret = vmovq_n_s32(vgetq_lane_s32(vreinterpretq_s32_m128i(a), (imm) & 0x3)); \ - ret = vsetq_lane_s32(vgetq_lane_s32(vreinterpretq_s32_m128i(a), ((imm) >> 2) & 0x3), ret, 1); \ - ret = vsetq_lane_s32(vgetq_lane_s32(vreinterpretq_s32_m128i(a), ((imm) >> 4) & 0x3), ret, 2); \ - ret = vsetq_lane_s32(vgetq_lane_s32(vreinterpretq_s32_m128i(a), ((imm) >> 6) & 0x3), ret, 3); \ - vreinterpretq_m128i_s32(ret); \ -}) + ({ \ + int32x4_t ret; \ + ret = vmovq_n_s32(vgetq_lane_s32(vreinterpretq_s32_m128i(a), (imm) & 0x3)); \ + ret = vsetq_lane_s32(vgetq_lane_s32(vreinterpretq_s32_m128i(a), ((imm) >> 2) & 0x3), ret, 1); \ + ret = vsetq_lane_s32(vgetq_lane_s32(vreinterpretq_s32_m128i(a), ((imm) >> 4) & 0x3), ret, 2); \ + ret = vsetq_lane_s32(vgetq_lane_s32(vreinterpretq_s32_m128i(a), ((imm) >> 6) & 0x3), ret, 3); \ + vreinterpretq_m128i_s32(ret); \ + }) #endif //FORCE_INLINE __m128i _mm_shuffle_epi32_splat(__m128i a, __constrange(0,255) int imm) #if defined(__aarch64__) #define _mm_shuffle_epi32_splat(a, imm) \ -({ \ - vreinterpretq_m128i_s32(vdupq_laneq_s32(vreinterpretq_s32_m128i(a), (imm))); \ -}) + ({ \ + vreinterpretq_m128i_s32(vdupq_laneq_s32(vreinterpretq_s32_m128i(a), (imm))); \ + }) #else #define _mm_shuffle_epi32_splat(a, imm) \ -({ \ - vreinterpretq_m128i_s32(vdupq_n_s32(vgetq_lane_s32(vreinterpretq_s32_m128i(a), (imm)))); \ -}) + ({ \ + vreinterpretq_m128i_s32(vdupq_n_s32(vgetq_lane_s32(vreinterpretq_s32_m128i(a), (imm)))); \ + }) #endif // Shuffles the 4 signed or unsigned 32-bit integers in a as specified by imm. https://msdn.microsoft.com/en-us/library/56f67xbk%28v=vs.90%29.aspx //FORCE_INLINE __m128i _mm_shuffle_epi32(__m128i a, __constrange(0,255) int imm) #define _mm_shuffle_epi32(a, imm) \ -({ \ - __m128i ret; \ - switch (imm) \ - { \ + ({ \ + __m128i ret; \ + switch (imm) \ + { \ case _MM_SHUFFLE(1, 0, 3, 2): ret = _mm_shuffle_epi_1032((a)); break; \ case _MM_SHUFFLE(2, 3, 0, 1): ret = _mm_shuffle_epi_2301((a)); break; \ case _MM_SHUFFLE(0, 3, 2, 1): ret = _mm_shuffle_epi_0321((a)); break; \ @@ -804,22 +806,22 @@ FORCE_INLINE __m128i _mm_shuffle_epi32_default(__m128i a, __constrange(0,255) in case _MM_SHUFFLE(2, 2, 2, 2): ret = _mm_shuffle_epi32_splat((a),2); break; \ case _MM_SHUFFLE(3, 3, 3, 3): ret = _mm_shuffle_epi32_splat((a),3); break; \ default: ret = _mm_shuffle_epi32_default((a), (imm)); break; \ - } \ - ret; \ -}) + } \ + ret; \ + }) // Shuffles the upper 4 signed or unsigned 16 - bit integers in a as specified by imm. https://msdn.microsoft.com/en-us/library/13ywktbs(v=vs.100).aspx //FORCE_INLINE __m128i _mm_shufflehi_epi16_function(__m128i a, __constrange(0,255) int imm) #define _mm_shufflehi_epi16_function(a, imm) \ -({ \ - int16x8_t ret = vreinterpretq_s16_s32(a); \ - int16x4_t highBits = vget_high_s16(ret); \ - ret = vsetq_lane_s16(vget_lane_s16(highBits, (imm) & 0x3), ret, 4); \ - ret = vsetq_lane_s16(vget_lane_s16(highBits, ((imm) >> 2) & 0x3), ret, 5); \ - ret = vsetq_lane_s16(vget_lane_s16(highBits, ((imm) >> 4) & 0x3), ret, 6); \ - ret = vsetq_lane_s16(vget_lane_s16(highBits, ((imm) >> 6) & 0x3), ret, 7); \ - vreinterpretq_s32_s16(ret); \ -}) + ({ \ + int16x8_t ret = vreinterpretq_s16_s32(a); \ + int16x4_t highBits = vget_high_s16(ret); \ + ret = vsetq_lane_s16(vget_lane_s16(highBits, (imm) & 0x3), ret, 4); \ + ret = vsetq_lane_s16(vget_lane_s16(highBits, ((imm) >> 2) & 0x3), ret, 5); \ + ret = vsetq_lane_s16(vget_lane_s16(highBits, ((imm) >> 4) & 0x3), ret, 6); \ + ret = vsetq_lane_s16(vget_lane_s16(highBits, ((imm) >> 6) & 0x3), ret, 7); \ + vreinterpretq_s32_s16(ret); \ + }) //FORCE_INLINE __m128i _mm_shufflehi_epi16(__m128i a, __constrange(0,255) int imm) #define _mm_shufflehi_epi16(a, imm) \ @@ -829,88 +831,88 @@ FORCE_INLINE __m128i _mm_shuffle_epi32_default(__m128i a, __constrange(0,255) in // Shifts the 4 signed or unsigned 32-bit integers in a left by count bits while shifting in zeros. : https://msdn.microsoft.com/en-us/library/z2k3bbtb%28v=vs.90%29.aspx //FORCE_INLINE __m128i _mm_slli_epi32(__m128i a, __constrange(0,255) int imm) #define _mm_slli_epi32(a, imm) \ -({ \ - __m128i ret; \ - if ((imm) <= 0) {\ - ret = a; \ - } \ - else if ((imm) > 31) { \ - ret = _mm_setzero_si128(); \ - } \ - else { \ - ret = vreinterpretq_m128i_s32(vshlq_n_s32(vreinterpretq_s32_m128i(a), (imm))); \ - } \ - ret; \ -}) + ({ \ + __m128i ret; \ + if ((imm) <= 0) {\ + ret = a; \ + } \ + else if ((imm) > 31) { \ + ret = _mm_setzero_si128(); \ + } \ + else { \ + ret = vreinterpretq_m128i_s32(vshlq_n_s32(vreinterpretq_s32_m128i(a), (imm))); \ + } \ + ret; \ + }) //Shifts the 4 signed or unsigned 32-bit integers in a right by count bits while shifting in zeros. https://msdn.microsoft.com/en-us/library/w486zcfa(v=vs.100).aspx //FORCE_INLINE __m128i _mm_srli_epi32(__m128i a, __constrange(0,255) int imm) #define _mm_srli_epi32(a, imm) \ -({ \ - __m128i ret; \ - if ((imm) <= 0) { \ - ret = a; \ - } \ - else if ((imm)> 31) { \ - ret = _mm_setzero_si128(); \ - } \ - else { \ - ret = vreinterpretq_m128i_u32(vshrq_n_u32(vreinterpretq_u32_m128i(a), (imm))); \ - } \ - ret; \ -}) + ({ \ + __m128i ret; \ + if ((imm) <= 0) { \ + ret = a; \ + } \ + else if ((imm)> 31) { \ + ret = _mm_setzero_si128(); \ + } \ + else { \ + ret = vreinterpretq_m128i_u32(vshrq_n_u32(vreinterpretq_u32_m128i(a), (imm))); \ + } \ + ret; \ + }) // Shifts the 4 signed 32 - bit integers in a right by count bits while shifting in the sign bit. https://msdn.microsoft.com/en-us/library/z1939387(v=vs.100).aspx //FORCE_INLINE __m128i _mm_srai_epi32(__m128i a, __constrange(0,255) int imm) #define _mm_srai_epi32(a, imm) \ -({ \ - __m128i ret; \ - if ((imm) <= 0) { \ - ret = a; \ - } \ - else if ((imm) > 31) { \ - ret = vreinterpretq_m128i_s32(vshrq_n_s32(vreinterpretq_s32_m128i(a), 16)); \ - ret = vreinterpretq_m128i_s32(vshrq_n_s32(vreinterpretq_s32_m128i(ret), 16)); \ - } \ - else { \ - ret = vreinterpretq_m128i_s32(vshrq_n_s32(vreinterpretq_s32_m128i(a), (imm))); \ - } \ - ret; \ -}) + ({ \ + __m128i ret; \ + if ((imm) <= 0) { \ + ret = a; \ + } \ + else if ((imm) > 31) { \ + ret = vreinterpretq_m128i_s32(vshrq_n_s32(vreinterpretq_s32_m128i(a), 16)); \ + ret = vreinterpretq_m128i_s32(vshrq_n_s32(vreinterpretq_s32_m128i(ret), 16)); \ + } \ + else { \ + ret = vreinterpretq_m128i_s32(vshrq_n_s32(vreinterpretq_s32_m128i(a), (imm))); \ + } \ + ret; \ + }) // Shifts the 128 - bit value in a right by imm bytes while shifting in zeros.imm must be an immediate. https://msdn.microsoft.com/en-us/library/305w28yz(v=vs.100).aspx //FORCE_INLINE _mm_srli_si128(__m128i a, __constrange(0,255) int imm) #define _mm_srli_si128(a, imm) \ -({ \ - __m128i ret; \ - if ((imm) <= 0) { \ - ret = a; \ - } \ - else if ((imm) > 15) { \ - ret = _mm_setzero_si128(); \ - } \ - else { \ - ret = vreinterpretq_m128i_s8(vextq_s8(vreinterpretq_s8_m128i(a), vdupq_n_s8(0), (imm))); \ - } \ - ret; \ -}) + ({ \ + __m128i ret; \ + if ((imm) <= 0) { \ + ret = a; \ + } \ + else if ((imm) > 15) { \ + ret = _mm_setzero_si128(); \ + } \ + else { \ + ret = vreinterpretq_m128i_s8(vextq_s8(vreinterpretq_s8_m128i(a), vdupq_n_s8(0), (imm))); \ + } \ + ret; \ + }) // Shifts the 128-bit value in a left by imm bytes while shifting in zeros. imm must be an immediate. https://msdn.microsoft.com/en-us/library/34d3k2kt(v=vs.100).aspx //FORCE_INLINE __m128i _mm_slli_si128(__m128i a, __constrange(0,255) int imm) #define _mm_slli_si128(a, imm) \ -({ \ - __m128i ret; \ - if ((imm) <= 0) { \ - ret = a; \ - } \ - else if ((imm) > 15) { \ - ret = _mm_setzero_si128(); \ - } \ - else { \ - ret = vreinterpretq_m128i_s8(vextq_s8(vdupq_n_s8(0), vreinterpretq_s8_m128i(a), 16 - (imm))); \ - } \ - ret; \ -}) + ({ \ + __m128i ret; \ + if ((imm) <= 0) { \ + ret = a; \ + } \ + else if ((imm) > 15) { \ + ret = _mm_setzero_si128(); \ + } \ + else { \ + ret = vreinterpretq_m128i_s8(vextq_s8(vdupq_n_s8(0), vreinterpretq_s8_m128i(a), 16 - (imm))); \ + } \ + ret; \ + }) // NEON does not provide a version of this function, here is an article about some ways to repro the results. // http://stackoverflow.com/questions/11870910/sse-mm-movemask-epi8-equivalent-method-for-arm-neon @@ -1000,7 +1002,7 @@ FORCE_INLINE __m128i _mm_mullo_epi16(__m128i a, __m128i b) // Multiplies the 4 signed or unsigned 32-bit integers from a by the 4 signed or unsigned 32-bit integers from b. https://msdn.microsoft.com/en-us/library/vstudio/bb531409(v=vs.100).aspx FORCE_INLINE __m128i _mm_mullo_epi32(__m128i a, __m128i b) { - return vreinterpretq_m128i_s32(vmulq_s32(vreinterpretq_s32_m128i(a),vreinterpretq_s32_m128i(b))); + return vreinterpretq_m128i_s32(vmulq_s32(vreinterpretq_s32_m128i(a), vreinterpretq_s32_m128i(b))); } // Multiplies the four single-precision, floating-point values of a and b. https://msdn.microsoft.com/en-us/library/vstudio/22kbk6t9(v=vs.100).aspx @@ -1030,7 +1032,7 @@ FORCE_INLINE __m128 recipq_newton(__m128 in, int n) { int i; float32x4_t recip = vrecpeq_f32(vreinterpretq_f32_m128(in)); - for (i = 0; i < n; ++i) + for(i = 0; i < n; ++i) { recip = vmulq_f32(recip, vrecpsq_f32(recip, vreinterpretq_f32_m128(in))); } @@ -1128,9 +1130,9 @@ FORCE_INLINE __m128i _mm_mulhi_epi16(__m128i a, __m128i b) return vreinterpretq_m128i_u16(r.val[1]); } -// Computes pairwise add of each argument as single-precision, floating-point values a and b. +// Computes pairwise add of each argument as single-precision, floating-point values a and b. //https://msdn.microsoft.com/en-us/library/yd9wecaa.aspx -FORCE_INLINE __m128 _mm_hadd_ps(__m128 a, __m128 b ) +FORCE_INLINE __m128 _mm_hadd_ps(__m128 a, __m128 b) { #if defined(__aarch64__) return vreinterpretq_m128_f32(vpaddq_f32(vreinterpretq_f32_m128(a), vreinterpretq_f32_m128(b))); //AArch64 @@ -1193,7 +1195,7 @@ FORCE_INLINE __m128i _mm_cmpgt_epi32(__m128i a, __m128i b) // see also: // http://stackoverflow.com/questions/8627331/what-does-ordered-unordered-comparison-mean // http://stackoverflow.com/questions/29349621/neon-isnanval-intrinsics -FORCE_INLINE __m128 _mm_cmpord_ps(__m128 a, __m128 b ) +FORCE_INLINE __m128 _mm_cmpord_ps(__m128 a, __m128 b) { // Note: NEON does not have ordered compare builtin // Need to compare a eq a and b eq b to check for NaN @@ -1309,22 +1311,25 @@ FORCE_INLINE __m128i _mm_cvtepi16_epi32(__m128i a) } // Converts the four single-precision, floating-point values of a to signed 32-bit integer values. https://msdn.microsoft.com/en-us/library/vstudio/xdc42k5e(v=vs.100).aspx -// *NOTE*. The default rounding mode on SSE is 'round to even', which ArmV7 does not support! +// *NOTE*. The default rounding mode on SSE is 'round to even', which ArmV7 does not support! // It is supported on ARMv8 however. FORCE_INLINE __m128i _mm_cvtps_epi32(__m128 a) { #if defined(__aarch64__) return vcvtnq_s32_f32(a); #else - uint32x4_t signmask = vdupq_n_u32(0x80000000); - float32x4_t half = vbslq_f32(signmask, vreinterpretq_f32_m128(a), vdupq_n_f32(0.5f)); /* +/- 0.5 */ - int32x4_t r_normal = vcvtq_s32_f32(vaddq_f32(vreinterpretq_f32_m128(a), half)); /* round to integer: [a + 0.5]*/ - int32x4_t r_trunc = vcvtq_s32_f32(vreinterpretq_f32_m128(a)); /* truncate to integer: [a] */ - int32x4_t plusone = vreinterpretq_s32_u32(vshrq_n_u32(vreinterpretq_u32_s32(vnegq_s32(r_trunc)), 31)); /* 1 or 0 */ - int32x4_t r_even = vbicq_s32(vaddq_s32(r_trunc, plusone), vdupq_n_s32(1)); /* ([a] + {0,1}) & ~1 */ - float32x4_t delta = vsubq_f32(vreinterpretq_f32_m128(a), vcvtq_f32_s32(r_trunc)); /* compute delta: delta = (a - [a]) */ - uint32x4_t is_delta_half = vceqq_f32(delta, half); /* delta == +/- 0.5 */ - return vreinterpretq_m128i_s32(vbslq_s32(is_delta_half, r_even, r_normal)); + uint32x4_t signmask = vdupq_n_u32(0x80000000); + float32x4_t half = vbslq_f32(signmask, vreinterpretq_f32_m128(a), vdupq_n_f32(0.5f)); /* +/- 0.5 */ + int32x4_t r_normal = vcvtq_s32_f32(vaddq_f32(vreinterpretq_f32_m128(a), + half)); /* round to integer: [a + 0.5]*/ + int32x4_t r_trunc = vcvtq_s32_f32(vreinterpretq_f32_m128(a)); /* truncate to integer: [a] */ + int32x4_t plusone = vreinterpretq_s32_u32(vshrq_n_u32(vreinterpretq_u32_s32(vnegq_s32(r_trunc)), + 31)); /* 1 or 0 */ + int32x4_t r_even = vbicq_s32(vaddq_s32(r_trunc, plusone), vdupq_n_s32(1)); /* ([a] + {0,1}) & ~1 */ + float32x4_t delta = vsubq_f32(vreinterpretq_f32_m128(a), + vcvtq_f32_s32(r_trunc)); /* compute delta: delta = (a - [a]) */ + uint32x4_t is_delta_half = vceqq_f32(delta, half); /* delta == +/- 0.5 */ + return vreinterpretq_m128i_s32(vbslq_s32(is_delta_half, r_even, r_normal)); #endif } @@ -1354,9 +1359,9 @@ FORCE_INLINE __m128 _mm_castsi128_ps(__m128i a) } // Loads 128-bit value. : https://msdn.microsoft.com/en-us/library/atzzad1h(v=vs.80).aspx -FORCE_INLINE __m128i _mm_load_si128(const __m128i *p) +FORCE_INLINE __m128i _mm_load_si128(const __m128i* p) { - return vreinterpretq_m128i_s32(vld1q_s32((int32_t *)p)); + return vreinterpretq_m128i_s32(vld1q_s32((int32_t*)p)); } // ****************************************** @@ -1366,19 +1371,22 @@ FORCE_INLINE __m128i _mm_load_si128(const __m128i *p) // Packs the 16 signed 16-bit integers from a and b into 8-bit integers and saturates. https://msdn.microsoft.com/en-us/library/k4y4f7w5%28v=vs.90%29.aspx FORCE_INLINE __m128i _mm_packs_epi16(__m128i a, __m128i b) { - return vreinterpretq_m128i_s8(vcombine_s8(vqmovn_s16(vreinterpretq_s16_m128i(a)), vqmovn_s16(vreinterpretq_s16_m128i(b)))); + return vreinterpretq_m128i_s8(vcombine_s8(vqmovn_s16(vreinterpretq_s16_m128i(a)), + vqmovn_s16(vreinterpretq_s16_m128i(b)))); } // Packs the 16 signed 16 - bit integers from a and b into 8 - bit unsigned integers and saturates. https://msdn.microsoft.com/en-us/library/07ad1wx4(v=vs.100).aspx FORCE_INLINE __m128i _mm_packus_epi16(const __m128i a, const __m128i b) { - return vreinterpretq_m128i_u8(vcombine_u8(vqmovun_s16(vreinterpretq_s16_m128i(a)), vqmovun_s16(vreinterpretq_s16_m128i(b)))); + return vreinterpretq_m128i_u8(vcombine_u8(vqmovun_s16(vreinterpretq_s16_m128i(a)), + vqmovun_s16(vreinterpretq_s16_m128i(b)))); } // Packs the 8 signed 32-bit integers from a and b into signed 16-bit integers and saturates. https://msdn.microsoft.com/en-us/library/393t56f9%28v=vs.90%29.aspx FORCE_INLINE __m128i _mm_packs_epi32(__m128i a, __m128i b) { - return vreinterpretq_m128i_s16(vcombine_s16(vqmovn_s32(vreinterpretq_s32_m128i(a)), vqmovn_s32(vreinterpretq_s32_m128i(b)))); + return vreinterpretq_m128i_s16(vcombine_s16(vqmovn_s32(vreinterpretq_s32_m128i(a)), + vqmovn_s32(vreinterpretq_s32_m128i(b)))); } // Interleaves the lower 8 signed or unsigned 8-bit integers in a with the lower 8 signed or unsigned 8-bit integers in b. https://msdn.microsoft.com/en-us/library/xf7k860c%28v=vs.90%29.aspx @@ -1456,16 +1464,16 @@ FORCE_INLINE __m128i _mm_unpackhi_epi32(__m128i a, __m128i b) // Extracts the selected signed or unsigned 16-bit integer from a and zero extends. https://msdn.microsoft.com/en-us/library/6dceta0c(v=vs.100).aspx //FORCE_INLINE int _mm_extract_epi16(__m128i a, __constrange(0,8) int imm) #define _mm_extract_epi16(a, imm) \ -({ \ - (vgetq_lane_s16(vreinterpretq_s16_m128i(a), (imm)) & 0x0000ffffUL); \ -}) + ({ \ + (vgetq_lane_s16(vreinterpretq_s16_m128i(a), (imm)) & 0x0000ffffUL); \ + }) // Inserts the least significant 16 bits of b into the selected 16-bit integer of a. https://msdn.microsoft.com/en-us/library/kaze8hz1%28v=vs.100%29.aspx //FORCE_INLINE __m128i _mm_insert_epi16(__m128i a, const int b, __constrange(0,8) int imm) #define _mm_insert_epi16(a, b, imm) \ -({ \ - vreinterpretq_m128i_s16(vsetq_lane_s16((b), vreinterpretq_s16_m128i(a), (imm))); \ -}) + ({ \ + vreinterpretq_m128i_s16(vsetq_lane_s16((b), vreinterpretq_s16_m128i(a), (imm))); \ + }) // ****************************************** // Streaming Extensions @@ -1478,13 +1486,13 @@ FORCE_INLINE void _mm_sfence(void) } // Stores the data in a to the address p without polluting the caches. If the cache line containing address p is already in the cache, the cache will be updated.Address p must be 16 - byte aligned. https://msdn.microsoft.com/en-us/library/ba08y07y%28v=vs.90%29.aspx -FORCE_INLINE void _mm_stream_si128(__m128i *p, __m128i a) +FORCE_INLINE void _mm_stream_si128(__m128i* p, __m128i a) { *p = a; } // Cache line containing p is flushed and invalidated from all caches in the coherency domain. : https://msdn.microsoft.com/en-us/library/ba08y07y(v=vs.100).aspx -FORCE_INLINE void _mm_clflush(void const*p) +FORCE_INLINE void _mm_clflush(void const* p) { // no corollary for Neon? } diff --git a/src/crypto/c_blake256.c b/src/crypto/c_blake256.c index 00a84c22..b87261ad 100644 --- a/src/crypto/c_blake256.c +++ b/src/crypto/c_blake256.c @@ -14,313 +14,377 @@ #include "c_blake256.h" #define U8TO32(p) \ - (((uint32_t)((p)[0]) << 24) | ((uint32_t)((p)[1]) << 16) | \ - ((uint32_t)((p)[2]) << 8) | ((uint32_t)((p)[3]) )) + (((uint32_t)((p)[0]) << 24) | ((uint32_t)((p)[1]) << 16) | \ + ((uint32_t)((p)[2]) << 8) | ((uint32_t)((p)[3]) )) #define U32TO8(p, v) \ - (p)[0] = (uint8_t)((v) >> 24); (p)[1] = (uint8_t)((v) >> 16); \ - (p)[2] = (uint8_t)((v) >> 8); (p)[3] = (uint8_t)((v) ); + (p)[0] = (uint8_t)((v) >> 24); (p)[1] = (uint8_t)((v) >> 16); \ + (p)[2] = (uint8_t)((v) >> 8); (p)[3] = (uint8_t)((v) ); -const uint8_t sigma[][16] = { - { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,13,14,15}, - {14,10, 4, 8, 9,15,13, 6, 1,12, 0, 2,11, 7, 5, 3}, - {11, 8,12, 0, 5, 2,15,13,10,14, 3, 6, 7, 1, 9, 4}, - { 7, 9, 3, 1,13,12,11,14, 2, 6, 5,10, 4, 0,15, 8}, - { 9, 0, 5, 7, 2, 4,10,15,14, 1,11,12, 6, 8, 3,13}, - { 2,12, 6,10, 0,11, 8, 3, 4,13, 7, 5,15,14, 1, 9}, - {12, 5, 1,15,14,13, 4,10, 0, 7, 6, 3, 9, 2, 8,11}, - {13,11, 7,14,12, 1, 3, 9, 5, 0,15, 4, 8, 6, 2,10}, - { 6,15,14, 9,11, 3, 0, 8,12, 2,13, 7, 1, 4,10, 5}, - {10, 2, 8, 4, 7, 6, 1, 5,15,11, 9,14, 3,12,13, 0}, - { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,13,14,15}, - {14,10, 4, 8, 9,15,13, 6, 1,12, 0, 2,11, 7, 5, 3}, - {11, 8,12, 0, 5, 2,15,13,10,14, 3, 6, 7, 1, 9, 4}, - { 7, 9, 3, 1,13,12,11,14, 2, 6, 5,10, 4, 0,15, 8} +const uint8_t sigma[][16] = +{ + { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}, + {14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3}, + {11, 8, 12, 0, 5, 2, 15, 13, 10, 14, 3, 6, 7, 1, 9, 4}, + { 7, 9, 3, 1, 13, 12, 11, 14, 2, 6, 5, 10, 4, 0, 15, 8}, + { 9, 0, 5, 7, 2, 4, 10, 15, 14, 1, 11, 12, 6, 8, 3, 13}, + { 2, 12, 6, 10, 0, 11, 8, 3, 4, 13, 7, 5, 15, 14, 1, 9}, + {12, 5, 1, 15, 14, 13, 4, 10, 0, 7, 6, 3, 9, 2, 8, 11}, + {13, 11, 7, 14, 12, 1, 3, 9, 5, 0, 15, 4, 8, 6, 2, 10}, + { 6, 15, 14, 9, 11, 3, 0, 8, 12, 2, 13, 7, 1, 4, 10, 5}, + {10, 2, 8, 4, 7, 6, 1, 5, 15, 11, 9, 14, 3, 12, 13, 0}, + { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}, + {14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3}, + {11, 8, 12, 0, 5, 2, 15, 13, 10, 14, 3, 6, 7, 1, 9, 4}, + { 7, 9, 3, 1, 13, 12, 11, 14, 2, 6, 5, 10, 4, 0, 15, 8} }; -const uint32_t cst[16] = { - 0x243F6A88, 0x85A308D3, 0x13198A2E, 0x03707344, - 0xA4093822, 0x299F31D0, 0x082EFA98, 0xEC4E6C89, - 0x452821E6, 0x38D01377, 0xBE5466CF, 0x34E90C6C, - 0xC0AC29B7, 0xC97C50DD, 0x3F84D5B5, 0xB5470917 +const uint32_t cst[16] = +{ + 0x243F6A88, 0x85A308D3, 0x13198A2E, 0x03707344, + 0xA4093822, 0x299F31D0, 0x082EFA98, 0xEC4E6C89, + 0x452821E6, 0x38D01377, 0xBE5466CF, 0x34E90C6C, + 0xC0AC29B7, 0xC97C50DD, 0x3F84D5B5, 0xB5470917 }; -static const uint8_t padding[] = { - 0x80,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 +static const uint8_t padding[] = +{ + 0x80, 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 }; -void blake256_compress(state *S, const uint8_t *block) { - uint32_t v[16], m[16], i; +void blake256_compress(state* S, const uint8_t* block) +{ + uint32_t v[16], m[16], i; #define ROT(x,n) (((x)<<(32-n))|((x)>>(n))) #define G(a,b,c,d,e) \ - v[a] += (m[sigma[i][e]] ^ cst[sigma[i][e+1]]) + v[b]; \ - v[d] = ROT(v[d] ^ v[a],16); \ - v[c] += v[d]; \ - v[b] = ROT(v[b] ^ v[c],12); \ - v[a] += (m[sigma[i][e+1]] ^ cst[sigma[i][e]])+v[b]; \ - v[d] = ROT(v[d] ^ v[a], 8); \ - v[c] += v[d]; \ - v[b] = ROT(v[b] ^ v[c], 7); + v[a] += (m[sigma[i][e]] ^ cst[sigma[i][e+1]]) + v[b]; \ + v[d] = ROT(v[d] ^ v[a],16); \ + v[c] += v[d]; \ + v[b] = ROT(v[b] ^ v[c],12); \ + v[a] += (m[sigma[i][e+1]] ^ cst[sigma[i][e]])+v[b]; \ + v[d] = ROT(v[d] ^ v[a], 8); \ + v[c] += v[d]; \ + v[b] = ROT(v[b] ^ v[c], 7); - for (i = 0; i < 16; ++i) m[i] = U8TO32(block + i * 4); - for (i = 0; i < 8; ++i) v[i] = S->h[i]; - v[ 8] = S->s[0] ^ 0x243F6A88; - v[ 9] = S->s[1] ^ 0x85A308D3; - v[10] = S->s[2] ^ 0x13198A2E; - v[11] = S->s[3] ^ 0x03707344; - v[12] = 0xA4093822; - v[13] = 0x299F31D0; - v[14] = 0x082EFA98; - v[15] = 0xEC4E6C89; + for(i = 0; i < 16; ++i) + { + m[i] = U8TO32(block + i * 4); + } + for(i = 0; i < 8; ++i) + { + v[i] = S->h[i]; + } + v[ 8] = S->s[0] ^ 0x243F6A88; + v[ 9] = S->s[1] ^ 0x85A308D3; + v[10] = S->s[2] ^ 0x13198A2E; + v[11] = S->s[3] ^ 0x03707344; + v[12] = 0xA4093822; + v[13] = 0x299F31D0; + v[14] = 0x082EFA98; + v[15] = 0xEC4E6C89; - if (S->nullt == 0) { - v[12] ^= S->t[0]; - v[13] ^= S->t[0]; - v[14] ^= S->t[1]; - v[15] ^= S->t[1]; - } + if(S->nullt == 0) + { + v[12] ^= S->t[0]; + v[13] ^= S->t[0]; + v[14] ^= S->t[1]; + v[15] ^= S->t[1]; + } - for (i = 0; i < 14; ++i) { - G(0, 4, 8, 12, 0); - G(1, 5, 9, 13, 2); - G(2, 6, 10, 14, 4); - G(3, 7, 11, 15, 6); - G(3, 4, 9, 14, 14); - G(2, 7, 8, 13, 12); - G(0, 5, 10, 15, 8); - G(1, 6, 11, 12, 10); - } + for(i = 0; i < 14; ++i) + { + G(0, 4, 8, 12, 0); + G(1, 5, 9, 13, 2); + G(2, 6, 10, 14, 4); + G(3, 7, 11, 15, 6); + G(3, 4, 9, 14, 14); + G(2, 7, 8, 13, 12); + G(0, 5, 10, 15, 8); + G(1, 6, 11, 12, 10); + } - for (i = 0; i < 16; ++i) S->h[i % 8] ^= v[i]; - for (i = 0; i < 8; ++i) S->h[i] ^= S->s[i % 4]; + for(i = 0; i < 16; ++i) + { + S->h[i % 8] ^= v[i]; + } + for(i = 0; i < 8; ++i) + { + S->h[i] ^= S->s[i % 4]; + } } -void blake256_init(state *S) { - S->h[0] = 0x6A09E667; - S->h[1] = 0xBB67AE85; - S->h[2] = 0x3C6EF372; - S->h[3] = 0xA54FF53A; - S->h[4] = 0x510E527F; - S->h[5] = 0x9B05688C; - S->h[6] = 0x1F83D9AB; - S->h[7] = 0x5BE0CD19; - S->t[0] = S->t[1] = S->buflen = S->nullt = 0; - S->s[0] = S->s[1] = S->s[2] = S->s[3] = 0; +void blake256_init(state* S) +{ + S->h[0] = 0x6A09E667; + S->h[1] = 0xBB67AE85; + S->h[2] = 0x3C6EF372; + S->h[3] = 0xA54FF53A; + S->h[4] = 0x510E527F; + S->h[5] = 0x9B05688C; + S->h[6] = 0x1F83D9AB; + S->h[7] = 0x5BE0CD19; + S->t[0] = S->t[1] = S->buflen = S->nullt = 0; + S->s[0] = S->s[1] = S->s[2] = S->s[3] = 0; } -void blake224_init(state *S) { - S->h[0] = 0xC1059ED8; - S->h[1] = 0x367CD507; - S->h[2] = 0x3070DD17; - S->h[3] = 0xF70E5939; - S->h[4] = 0xFFC00B31; - S->h[5] = 0x68581511; - S->h[6] = 0x64F98FA7; - S->h[7] = 0xBEFA4FA4; - S->t[0] = S->t[1] = S->buflen = S->nullt = 0; - S->s[0] = S->s[1] = S->s[2] = S->s[3] = 0; +void blake224_init(state* S) +{ + S->h[0] = 0xC1059ED8; + S->h[1] = 0x367CD507; + S->h[2] = 0x3070DD17; + S->h[3] = 0xF70E5939; + S->h[4] = 0xFFC00B31; + S->h[5] = 0x68581511; + S->h[6] = 0x64F98FA7; + S->h[7] = 0xBEFA4FA4; + S->t[0] = S->t[1] = S->buflen = S->nullt = 0; + S->s[0] = S->s[1] = S->s[2] = S->s[3] = 0; } // datalen = number of bits -void blake256_update(state *S, const uint8_t *data, uint64_t datalen) { - int left = S->buflen >> 3; - int fill = 64 - left; +void blake256_update(state* S, const uint8_t* data, uint64_t datalen) +{ + int left = S->buflen >> 3; + int fill = 64 - left; - if (left && (((datalen >> 3) & 0x3F) >= (unsigned) fill)) { - memcpy((void *) (S->buf + left), (void *) data, fill); - S->t[0] += 512; - if (S->t[0] == 0) S->t[1]++; - blake256_compress(S, S->buf); - data += fill; - datalen -= (fill << 3); - left = 0; - } + if(left && (((datalen >> 3) & 0x3F) >= (unsigned) fill)) + { + memcpy((void*)(S->buf + left), (void*) data, fill); + S->t[0] += 512; + if(S->t[0] == 0) + { + S->t[1]++; + } + blake256_compress(S, S->buf); + data += fill; + datalen -= (fill << 3); + left = 0; + } - while (datalen >= 512) { - S->t[0] += 512; - if (S->t[0] == 0) S->t[1]++; - blake256_compress(S, data); - data += 64; - datalen -= 512; - } + while(datalen >= 512) + { + S->t[0] += 512; + if(S->t[0] == 0) + { + S->t[1]++; + } + blake256_compress(S, data); + data += 64; + datalen -= 512; + } - if (datalen > 0) { - memcpy((void *) (S->buf + left), (void *) data, datalen >> 3); - S->buflen = (left << 3) + (int) datalen; - } else { - S->buflen = 0; - } + if(datalen > 0) + { + memcpy((void*)(S->buf + left), (void*) data, datalen >> 3); + S->buflen = (left << 3) + (int) datalen; + } + else + { + S->buflen = 0; + } } // datalen = number of bits -void blake224_update(state *S, const uint8_t *data, uint64_t datalen) { - blake256_update(S, data, datalen); +void blake224_update(state* S, const uint8_t* data, uint64_t datalen) +{ + blake256_update(S, data, datalen); } -void blake256_final_h(state *S, uint8_t *digest, uint8_t pa, uint8_t pb) { - uint8_t msglen[8]; - uint32_t lo = S->t[0] + S->buflen, hi = S->t[1]; - if (lo < (unsigned) S->buflen) hi++; - U32TO8(msglen + 0, hi); - U32TO8(msglen + 4, lo); +void blake256_final_h(state* S, uint8_t* digest, uint8_t pa, uint8_t pb) +{ + uint8_t msglen[8]; + uint32_t lo = S->t[0] + S->buflen, hi = S->t[1]; + if(lo < (unsigned) S->buflen) + { + hi++; + } + U32TO8(msglen + 0, hi); + U32TO8(msglen + 4, lo); - if (S->buflen == 440) { /* one padding byte */ - S->t[0] -= 8; - blake256_update(S, &pa, 8); - } else { - if (S->buflen < 440) { /* enough space to fill the block */ - if (S->buflen == 0) S->nullt = 1; - S->t[0] -= 440 - S->buflen; - blake256_update(S, padding, 440 - S->buflen); - } else { /* need 2 compressions */ - S->t[0] -= 512 - S->buflen; - blake256_update(S, padding, 512 - S->buflen); - S->t[0] -= 440; - blake256_update(S, padding + 1, 440); - S->nullt = 1; - } - blake256_update(S, &pb, 8); - S->t[0] -= 8; - } - S->t[0] -= 64; - blake256_update(S, msglen, 64); + if(S->buflen == 440) /* one padding byte */ + { + S->t[0] -= 8; + blake256_update(S, &pa, 8); + } + else + { + if(S->buflen < 440) /* enough space to fill the block */ + { + if(S->buflen == 0) + { + S->nullt = 1; + } + S->t[0] -= 440 - S->buflen; + blake256_update(S, padding, 440 - S->buflen); + } + else /* need 2 compressions */ + { + S->t[0] -= 512 - S->buflen; + blake256_update(S, padding, 512 - S->buflen); + S->t[0] -= 440; + blake256_update(S, padding + 1, 440); + S->nullt = 1; + } + blake256_update(S, &pb, 8); + S->t[0] -= 8; + } + S->t[0] -= 64; + blake256_update(S, msglen, 64); - U32TO8(digest + 0, S->h[0]); - U32TO8(digest + 4, S->h[1]); - U32TO8(digest + 8, S->h[2]); - U32TO8(digest + 12, S->h[3]); - U32TO8(digest + 16, S->h[4]); - U32TO8(digest + 20, S->h[5]); - U32TO8(digest + 24, S->h[6]); - U32TO8(digest + 28, S->h[7]); + U32TO8(digest + 0, S->h[0]); + U32TO8(digest + 4, S->h[1]); + U32TO8(digest + 8, S->h[2]); + U32TO8(digest + 12, S->h[3]); + U32TO8(digest + 16, S->h[4]); + U32TO8(digest + 20, S->h[5]); + U32TO8(digest + 24, S->h[6]); + U32TO8(digest + 28, S->h[7]); } -void blake256_final(state *S, uint8_t *digest) { - blake256_final_h(S, digest, 0x81, 0x01); +void blake256_final(state* S, uint8_t* digest) +{ + blake256_final_h(S, digest, 0x81, 0x01); } -void blake224_final(state *S, uint8_t *digest) { - blake256_final_h(S, digest, 0x80, 0x00); +void blake224_final(state* S, uint8_t* digest) +{ + blake256_final_h(S, digest, 0x80, 0x00); } // inlen = number of bytes -void blake256_hash(uint8_t *out, const uint8_t *in, uint64_t inlen) { - state S; - blake256_init(&S); - blake256_update(&S, in, inlen * 8); - blake256_final(&S, out); +void blake256_hash(uint8_t* out, const uint8_t* in, uint64_t inlen) +{ + state S; + blake256_init(&S); + blake256_update(&S, in, inlen * 8); + blake256_final(&S, out); } // inlen = number of bytes -void blake224_hash(uint8_t *out, const uint8_t *in, uint64_t inlen) { - state S; - blake224_init(&S); - blake224_update(&S, in, inlen * 8); - blake224_final(&S, out); +void blake224_hash(uint8_t* out, const uint8_t* in, uint64_t inlen) +{ + state S; + blake224_init(&S); + blake224_update(&S, in, inlen * 8); + blake224_final(&S, out); } // keylen = number of bytes -void hmac_blake256_init(hmac_state *S, const uint8_t *_key, uint64_t keylen) { - const uint8_t *key = _key; - uint8_t keyhash[32]; - uint8_t pad[64]; - uint64_t i; +void hmac_blake256_init(hmac_state* S, const uint8_t* _key, uint64_t keylen) +{ + const uint8_t* key = _key; + uint8_t keyhash[32]; + uint8_t pad[64]; + uint64_t i; - if (keylen > 64) { - blake256_hash(keyhash, key, keylen); - key = keyhash; - keylen = 32; - } + if(keylen > 64) + { + blake256_hash(keyhash, key, keylen); + key = keyhash; + keylen = 32; + } - blake256_init(&S->inner); - memset(pad, 0x36, 64); - for (i = 0; i < keylen; ++i) { - pad[i] ^= key[i]; - } - blake256_update(&S->inner, pad, 512); + blake256_init(&S->inner); + memset(pad, 0x36, 64); + for(i = 0; i < keylen; ++i) + { + pad[i] ^= key[i]; + } + blake256_update(&S->inner, pad, 512); - blake256_init(&S->outer); - memset(pad, 0x5c, 64); - for (i = 0; i < keylen; ++i) { - pad[i] ^= key[i]; - } - blake256_update(&S->outer, pad, 512); + blake256_init(&S->outer); + memset(pad, 0x5c, 64); + for(i = 0; i < keylen; ++i) + { + pad[i] ^= key[i]; + } + blake256_update(&S->outer, pad, 512); - memset(keyhash, 0, 32); + memset(keyhash, 0, 32); } // keylen = number of bytes -void hmac_blake224_init(hmac_state *S, const uint8_t *_key, uint64_t keylen) { - const uint8_t *key = _key; - uint8_t keyhash[32]; - uint8_t pad[64]; - uint64_t i; +void hmac_blake224_init(hmac_state* S, const uint8_t* _key, uint64_t keylen) +{ + const uint8_t* key = _key; + uint8_t keyhash[32]; + uint8_t pad[64]; + uint64_t i; - if (keylen > 64) { - blake256_hash(keyhash, key, keylen); - key = keyhash; - keylen = 28; - } + if(keylen > 64) + { + blake256_hash(keyhash, key, keylen); + key = keyhash; + keylen = 28; + } - blake224_init(&S->inner); - memset(pad, 0x36, 64); - for (i = 0; i < keylen; ++i) { - pad[i] ^= key[i]; - } - blake224_update(&S->inner, pad, 512); + blake224_init(&S->inner); + memset(pad, 0x36, 64); + for(i = 0; i < keylen; ++i) + { + pad[i] ^= key[i]; + } + blake224_update(&S->inner, pad, 512); - blake224_init(&S->outer); - memset(pad, 0x5c, 64); - for (i = 0; i < keylen; ++i) { - pad[i] ^= key[i]; - } - blake224_update(&S->outer, pad, 512); + blake224_init(&S->outer); + memset(pad, 0x5c, 64); + for(i = 0; i < keylen; ++i) + { + pad[i] ^= key[i]; + } + blake224_update(&S->outer, pad, 512); - memset(keyhash, 0, 32); + memset(keyhash, 0, 32); } // datalen = number of bits -void hmac_blake256_update(hmac_state *S, const uint8_t *data, uint64_t datalen) { - // update the inner state - blake256_update(&S->inner, data, datalen); +void hmac_blake256_update(hmac_state* S, const uint8_t* data, uint64_t datalen) +{ + // update the inner state + blake256_update(&S->inner, data, datalen); } // datalen = number of bits -void hmac_blake224_update(hmac_state *S, const uint8_t *data, uint64_t datalen) { - // update the inner state - blake224_update(&S->inner, data, datalen); +void hmac_blake224_update(hmac_state* S, const uint8_t* data, uint64_t datalen) +{ + // update the inner state + blake224_update(&S->inner, data, datalen); } -void hmac_blake256_final(hmac_state *S, uint8_t *digest) { - uint8_t ihash[32]; - blake256_final(&S->inner, ihash); - blake256_update(&S->outer, ihash, 256); - blake256_final(&S->outer, digest); - memset(ihash, 0, 32); +void hmac_blake256_final(hmac_state* S, uint8_t* digest) +{ + uint8_t ihash[32]; + blake256_final(&S->inner, ihash); + blake256_update(&S->outer, ihash, 256); + blake256_final(&S->outer, digest); + memset(ihash, 0, 32); } -void hmac_blake224_final(hmac_state *S, uint8_t *digest) { - uint8_t ihash[32]; - blake224_final(&S->inner, ihash); - blake224_update(&S->outer, ihash, 224); - blake224_final(&S->outer, digest); - memset(ihash, 0, 32); +void hmac_blake224_final(hmac_state* S, uint8_t* digest) +{ + uint8_t ihash[32]; + blake224_final(&S->inner, ihash); + blake224_update(&S->outer, ihash, 224); + blake224_final(&S->outer, digest); + memset(ihash, 0, 32); } // keylen = number of bytes; inlen = number of bytes -void hmac_blake256_hash(uint8_t *out, const uint8_t *key, uint64_t keylen, const uint8_t *in, uint64_t inlen) { - hmac_state S; - hmac_blake256_init(&S, key, keylen); - hmac_blake256_update(&S, in, inlen * 8); - hmac_blake256_final(&S, out); +void hmac_blake256_hash(uint8_t* out, const uint8_t* key, uint64_t keylen, const uint8_t* in, uint64_t inlen) +{ + hmac_state S; + hmac_blake256_init(&S, key, keylen); + hmac_blake256_update(&S, in, inlen * 8); + hmac_blake256_final(&S, out); } // keylen = number of bytes; inlen = number of bytes -void hmac_blake224_hash(uint8_t *out, const uint8_t *key, uint64_t keylen, const uint8_t *in, uint64_t inlen) { - hmac_state S; - hmac_blake224_init(&S, key, keylen); - hmac_blake224_update(&S, in, inlen * 8); - hmac_blake224_final(&S, out); +void hmac_blake224_hash(uint8_t* out, const uint8_t* key, uint64_t keylen, const uint8_t* in, uint64_t inlen) +{ + hmac_state S; + hmac_blake224_init(&S, key, keylen); + hmac_blake224_update(&S, in, inlen * 8); + hmac_blake224_final(&S, out); } diff --git a/src/crypto/c_blake256.h b/src/crypto/c_blake256.h index b9c2aad0..814d850f 100644 --- a/src/crypto/c_blake256.h +++ b/src/crypto/c_blake256.h @@ -3,41 +3,43 @@ #include -typedef struct { - uint32_t h[8], s[4], t[2]; - int buflen, nullt; - uint8_t buf[64]; +typedef struct +{ + uint32_t h[8], s[4], t[2]; + int buflen, nullt; + uint8_t buf[64]; } state; -typedef struct { - state inner; - state outer; +typedef struct +{ + state inner; + state outer; } hmac_state; -void blake256_init(state *); -void blake224_init(state *); +void blake256_init(state*); +void blake224_init(state*); -void blake256_update(state *, const uint8_t *, uint64_t); -void blake224_update(state *, const uint8_t *, uint64_t); +void blake256_update(state*, const uint8_t*, uint64_t); +void blake224_update(state*, const uint8_t*, uint64_t); -void blake256_final(state *, uint8_t *); -void blake224_final(state *, uint8_t *); +void blake256_final(state*, uint8_t*); +void blake224_final(state*, uint8_t*); -void blake256_hash(uint8_t *, const uint8_t *, uint64_t); -void blake224_hash(uint8_t *, const uint8_t *, uint64_t); +void blake256_hash(uint8_t*, const uint8_t*, uint64_t); +void blake224_hash(uint8_t*, const uint8_t*, uint64_t); /* HMAC functions: */ -void hmac_blake256_init(hmac_state *, const uint8_t *, uint64_t); -void hmac_blake224_init(hmac_state *, const uint8_t *, uint64_t); +void hmac_blake256_init(hmac_state*, const uint8_t*, uint64_t); +void hmac_blake224_init(hmac_state*, const uint8_t*, uint64_t); -void hmac_blake256_update(hmac_state *, const uint8_t *, uint64_t); -void hmac_blake224_update(hmac_state *, const uint8_t *, uint64_t); +void hmac_blake256_update(hmac_state*, const uint8_t*, uint64_t); +void hmac_blake224_update(hmac_state*, const uint8_t*, uint64_t); -void hmac_blake256_final(hmac_state *, uint8_t *); -void hmac_blake224_final(hmac_state *, uint8_t *); +void hmac_blake256_final(hmac_state*, uint8_t*); +void hmac_blake224_final(hmac_state*, uint8_t*); -void hmac_blake256_hash(uint8_t *, const uint8_t *, uint64_t, const uint8_t *, uint64_t); -void hmac_blake224_hash(uint8_t *, const uint8_t *, uint64_t, const uint8_t *, uint64_t); +void hmac_blake256_hash(uint8_t*, const uint8_t*, uint64_t, const uint8_t*, uint64_t); +void hmac_blake224_hash(uint8_t*, const uint8_t*, uint64_t, const uint8_t*, uint64_t); #endif /* _BLAKE256_H_ */ diff --git a/src/crypto/c_groestl.c b/src/crypto/c_groestl.c index 0f57ea12..032702f1 100644 --- a/src/crypto/c_groestl.c +++ b/src/crypto/c_groestl.c @@ -4,7 +4,7 @@ * * This work is based on the implementation of * Soeren S. Thomsen and Krystian Matusiewicz - * + * * */ @@ -14,178 +14,190 @@ #define P_TYPE 0 #define Q_TYPE 1 -const uint8_t shift_Values[2][8] = {{0,1,2,3,4,5,6,7},{1,3,5,7,0,2,4,6}}; +const uint8_t shift_Values[2][8] = {{0, 1, 2, 3, 4, 5, 6, 7}, {1, 3, 5, 7, 0, 2, 4, 6}}; -const uint8_t indices_cyclic[15] = {0,1,2,3,4,5,6,7,0,1,2,3,4,5,6}; +const uint8_t indices_cyclic[15] = {0, 1, 2, 3, 4, 5, 6, 7, 0, 1, 2, 3, 4, 5, 6}; #define ROTATE_COLUMN_DOWN(v1, v2, amount_bytes, temp_var) {temp_var = (v1<<(8*amount_bytes))|(v2>>(8*(4-amount_bytes))); \ - v2 = (v2<<(8*amount_bytes))|(v1>>(8*(4-amount_bytes))); \ - v1 = temp_var;} - + v2 = (v2<<(8*amount_bytes))|(v1>>(8*(4-amount_bytes))); \ + v1 = temp_var;} + #define COLUMN(x,y,i,c0,c1,c2,c3,c4,c5,c6,c7,tv1,tv2,tu,tl,t) \ - tu = T[2*(uint32_t)x[4*c0+0]]; \ - tl = T[2*(uint32_t)x[4*c0+0]+1]; \ - tv1 = T[2*(uint32_t)x[4*c1+1]]; \ - tv2 = T[2*(uint32_t)x[4*c1+1]+1]; \ - ROTATE_COLUMN_DOWN(tv1,tv2,1,t) \ - tu ^= tv1; \ - tl ^= tv2; \ - tv1 = T[2*(uint32_t)x[4*c2+2]]; \ - tv2 = T[2*(uint32_t)x[4*c2+2]+1]; \ - ROTATE_COLUMN_DOWN(tv1,tv2,2,t) \ - tu ^= tv1; \ - tl ^= tv2; \ - tv1 = T[2*(uint32_t)x[4*c3+3]]; \ - tv2 = T[2*(uint32_t)x[4*c3+3]+1]; \ - ROTATE_COLUMN_DOWN(tv1,tv2,3,t) \ - tu ^= tv1; \ - tl ^= tv2; \ - tl ^= T[2*(uint32_t)x[4*c4+0]]; \ - tu ^= T[2*(uint32_t)x[4*c4+0]+1]; \ - tv1 = T[2*(uint32_t)x[4*c5+1]]; \ - tv2 = T[2*(uint32_t)x[4*c5+1]+1]; \ - ROTATE_COLUMN_DOWN(tv1,tv2,1,t) \ - tl ^= tv1; \ - tu ^= tv2; \ - tv1 = T[2*(uint32_t)x[4*c6+2]]; \ - tv2 = T[2*(uint32_t)x[4*c6+2]+1]; \ - ROTATE_COLUMN_DOWN(tv1,tv2,2,t) \ - tl ^= tv1; \ - tu ^= tv2; \ - tv1 = T[2*(uint32_t)x[4*c7+3]]; \ - tv2 = T[2*(uint32_t)x[4*c7+3]+1]; \ - ROTATE_COLUMN_DOWN(tv1,tv2,3,t) \ - tl ^= tv1; \ - tu ^= tv2; \ - y[i] = tu; \ - y[i+1] = tl; + tu = T[2*(uint32_t)x[4*c0+0]]; \ + tl = T[2*(uint32_t)x[4*c0+0]+1]; \ + tv1 = T[2*(uint32_t)x[4*c1+1]]; \ + tv2 = T[2*(uint32_t)x[4*c1+1]+1]; \ + ROTATE_COLUMN_DOWN(tv1,tv2,1,t) \ + tu ^= tv1; \ + tl ^= tv2; \ + tv1 = T[2*(uint32_t)x[4*c2+2]]; \ + tv2 = T[2*(uint32_t)x[4*c2+2]+1]; \ + ROTATE_COLUMN_DOWN(tv1,tv2,2,t) \ + tu ^= tv1; \ + tl ^= tv2; \ + tv1 = T[2*(uint32_t)x[4*c3+3]]; \ + tv2 = T[2*(uint32_t)x[4*c3+3]+1]; \ + ROTATE_COLUMN_DOWN(tv1,tv2,3,t) \ + tu ^= tv1; \ + tl ^= tv2; \ + tl ^= T[2*(uint32_t)x[4*c4+0]]; \ + tu ^= T[2*(uint32_t)x[4*c4+0]+1]; \ + tv1 = T[2*(uint32_t)x[4*c5+1]]; \ + tv2 = T[2*(uint32_t)x[4*c5+1]+1]; \ + ROTATE_COLUMN_DOWN(tv1,tv2,1,t) \ + tl ^= tv1; \ + tu ^= tv2; \ + tv1 = T[2*(uint32_t)x[4*c6+2]]; \ + tv2 = T[2*(uint32_t)x[4*c6+2]+1]; \ + ROTATE_COLUMN_DOWN(tv1,tv2,2,t) \ + tl ^= tv1; \ + tu ^= tv2; \ + tv1 = T[2*(uint32_t)x[4*c7+3]]; \ + tv2 = T[2*(uint32_t)x[4*c7+3]+1]; \ + ROTATE_COLUMN_DOWN(tv1,tv2,3,t) \ + tl ^= tv1; \ + tu ^= tv2; \ + y[i] = tu; \ + y[i+1] = tl; /* compute one round of P (short variants) */ -static void RND512P(uint8_t *x, uint32_t *y, uint32_t r) { - uint32_t temp_v1, temp_v2, temp_upper_value, temp_lower_value, temp; - uint32_t* x32 = (uint32_t*)x; - x32[ 0] ^= 0x00000000^r; - x32[ 2] ^= 0x00000010^r; - x32[ 4] ^= 0x00000020^r; - x32[ 6] ^= 0x00000030^r; - x32[ 8] ^= 0x00000040^r; - x32[10] ^= 0x00000050^r; - x32[12] ^= 0x00000060^r; - x32[14] ^= 0x00000070^r; - COLUMN(x,y, 0, 0, 2, 4, 6, 9, 11, 13, 15, temp_v1, temp_v2, temp_upper_value, temp_lower_value, temp); - COLUMN(x,y, 2, 2, 4, 6, 8, 11, 13, 15, 1, temp_v1, temp_v2, temp_upper_value, temp_lower_value, temp); - COLUMN(x,y, 4, 4, 6, 8, 10, 13, 15, 1, 3, temp_v1, temp_v2, temp_upper_value, temp_lower_value, temp); - COLUMN(x,y, 6, 6, 8, 10, 12, 15, 1, 3, 5, temp_v1, temp_v2, temp_upper_value, temp_lower_value, temp); - COLUMN(x,y, 8, 8, 10, 12, 14, 1, 3, 5, 7, temp_v1, temp_v2, temp_upper_value, temp_lower_value, temp); - COLUMN(x,y,10, 10, 12, 14, 0, 3, 5, 7, 9, temp_v1, temp_v2, temp_upper_value, temp_lower_value, temp); - COLUMN(x,y,12, 12, 14, 0, 2, 5, 7, 9, 11, temp_v1, temp_v2, temp_upper_value, temp_lower_value, temp); - COLUMN(x,y,14, 14, 0, 2, 4, 7, 9, 11, 13, temp_v1, temp_v2, temp_upper_value, temp_lower_value, temp); +static void RND512P(uint8_t* x, uint32_t* y, uint32_t r) +{ + uint32_t temp_v1, temp_v2, temp_upper_value, temp_lower_value, temp; + uint32_t* x32 = (uint32_t*)x; + x32[ 0] ^= 0x00000000 ^ r; + x32[ 2] ^= 0x00000010 ^ r; + x32[ 4] ^= 0x00000020 ^ r; + x32[ 6] ^= 0x00000030 ^ r; + x32[ 8] ^= 0x00000040 ^ r; + x32[10] ^= 0x00000050 ^ r; + x32[12] ^= 0x00000060 ^ r; + x32[14] ^= 0x00000070 ^ r; + COLUMN(x, y, 0, 0, 2, 4, 6, 9, 11, 13, 15, temp_v1, temp_v2, temp_upper_value, temp_lower_value, temp); + COLUMN(x, y, 2, 2, 4, 6, 8, 11, 13, 15, 1, temp_v1, temp_v2, temp_upper_value, temp_lower_value, temp); + COLUMN(x, y, 4, 4, 6, 8, 10, 13, 15, 1, 3, temp_v1, temp_v2, temp_upper_value, temp_lower_value, temp); + COLUMN(x, y, 6, 6, 8, 10, 12, 15, 1, 3, 5, temp_v1, temp_v2, temp_upper_value, temp_lower_value, temp); + COLUMN(x, y, 8, 8, 10, 12, 14, 1, 3, 5, 7, temp_v1, temp_v2, temp_upper_value, temp_lower_value, temp); + COLUMN(x, y, 10, 10, 12, 14, 0, 3, 5, 7, 9, temp_v1, temp_v2, temp_upper_value, temp_lower_value, temp); + COLUMN(x, y, 12, 12, 14, 0, 2, 5, 7, 9, 11, temp_v1, temp_v2, temp_upper_value, temp_lower_value, temp); + COLUMN(x, y, 14, 14, 0, 2, 4, 7, 9, 11, 13, temp_v1, temp_v2, temp_upper_value, temp_lower_value, temp); } /* compute one round of Q (short variants) */ -static void RND512Q(uint8_t *x, uint32_t *y, uint32_t r) { - uint32_t temp_v1, temp_v2, temp_upper_value, temp_lower_value, temp; - uint32_t* x32 = (uint32_t*)x; - x32[ 0] = ~x32[ 0]; - x32[ 1] ^= 0xffffffff^r; - x32[ 2] = ~x32[ 2]; - x32[ 3] ^= 0xefffffff^r; - x32[ 4] = ~x32[ 4]; - x32[ 5] ^= 0xdfffffff^r; - x32[ 6] = ~x32[ 6]; - x32[ 7] ^= 0xcfffffff^r; - x32[ 8] = ~x32[ 8]; - x32[ 9] ^= 0xbfffffff^r; - x32[10] = ~x32[10]; - x32[11] ^= 0xafffffff^r; - x32[12] = ~x32[12]; - x32[13] ^= 0x9fffffff^r; - x32[14] = ~x32[14]; - x32[15] ^= 0x8fffffff^r; - COLUMN(x,y, 0, 2, 6, 10, 14, 1, 5, 9, 13, temp_v1, temp_v2, temp_upper_value, temp_lower_value, temp); - COLUMN(x,y, 2, 4, 8, 12, 0, 3, 7, 11, 15, temp_v1, temp_v2, temp_upper_value, temp_lower_value, temp); - COLUMN(x,y, 4, 6, 10, 14, 2, 5, 9, 13, 1, temp_v1, temp_v2, temp_upper_value, temp_lower_value, temp); - COLUMN(x,y, 6, 8, 12, 0, 4, 7, 11, 15, 3, temp_v1, temp_v2, temp_upper_value, temp_lower_value, temp); - COLUMN(x,y, 8, 10, 14, 2, 6, 9, 13, 1, 5, temp_v1, temp_v2, temp_upper_value, temp_lower_value, temp); - COLUMN(x,y,10, 12, 0, 4, 8, 11, 15, 3, 7, temp_v1, temp_v2, temp_upper_value, temp_lower_value, temp); - COLUMN(x,y,12, 14, 2, 6, 10, 13, 1, 5, 9, temp_v1, temp_v2, temp_upper_value, temp_lower_value, temp); - COLUMN(x,y,14, 0, 4, 8, 12, 15, 3, 7, 11, temp_v1, temp_v2, temp_upper_value, temp_lower_value, temp); +static void RND512Q(uint8_t* x, uint32_t* y, uint32_t r) +{ + uint32_t temp_v1, temp_v2, temp_upper_value, temp_lower_value, temp; + uint32_t* x32 = (uint32_t*)x; + x32[ 0] = ~x32[ 0]; + x32[ 1] ^= 0xffffffff ^ r; + x32[ 2] = ~x32[ 2]; + x32[ 3] ^= 0xefffffff ^ r; + x32[ 4] = ~x32[ 4]; + x32[ 5] ^= 0xdfffffff ^ r; + x32[ 6] = ~x32[ 6]; + x32[ 7] ^= 0xcfffffff ^ r; + x32[ 8] = ~x32[ 8]; + x32[ 9] ^= 0xbfffffff ^ r; + x32[10] = ~x32[10]; + x32[11] ^= 0xafffffff ^ r; + x32[12] = ~x32[12]; + x32[13] ^= 0x9fffffff ^ r; + x32[14] = ~x32[14]; + x32[15] ^= 0x8fffffff ^ r; + COLUMN(x, y, 0, 2, 6, 10, 14, 1, 5, 9, 13, temp_v1, temp_v2, temp_upper_value, temp_lower_value, temp); + COLUMN(x, y, 2, 4, 8, 12, 0, 3, 7, 11, 15, temp_v1, temp_v2, temp_upper_value, temp_lower_value, temp); + COLUMN(x, y, 4, 6, 10, 14, 2, 5, 9, 13, 1, temp_v1, temp_v2, temp_upper_value, temp_lower_value, temp); + COLUMN(x, y, 6, 8, 12, 0, 4, 7, 11, 15, 3, temp_v1, temp_v2, temp_upper_value, temp_lower_value, temp); + COLUMN(x, y, 8, 10, 14, 2, 6, 9, 13, 1, 5, temp_v1, temp_v2, temp_upper_value, temp_lower_value, temp); + COLUMN(x, y, 10, 12, 0, 4, 8, 11, 15, 3, 7, temp_v1, temp_v2, temp_upper_value, temp_lower_value, temp); + COLUMN(x, y, 12, 14, 2, 6, 10, 13, 1, 5, 9, temp_v1, temp_v2, temp_upper_value, temp_lower_value, temp); + COLUMN(x, y, 14, 0, 4, 8, 12, 15, 3, 7, 11, temp_v1, temp_v2, temp_upper_value, temp_lower_value, temp); } /* compute compression function (short variants) */ -static void F512(uint32_t *h, const uint32_t *m) { - int i; - uint32_t Ptmp[2*COLS512]; - uint32_t Qtmp[2*COLS512]; - uint32_t y[2*COLS512]; - uint32_t z[2*COLS512]; +static void F512(uint32_t* h, const uint32_t* m) +{ + int i; + uint32_t Ptmp[2 * COLS512]; + uint32_t Qtmp[2 * COLS512]; + uint32_t y[2 * COLS512]; + uint32_t z[2 * COLS512]; - for (i = 0; i < 2*COLS512; i++) { - z[i] = m[i]; - Ptmp[i] = h[i]^m[i]; - } + for(i = 0; i < 2 * COLS512; i++) + { + z[i] = m[i]; + Ptmp[i] = h[i] ^ m[i]; + } - /* compute Q(m) */ - RND512Q((uint8_t*)z, y, 0x00000000); - RND512Q((uint8_t*)y, z, 0x01000000); - RND512Q((uint8_t*)z, y, 0x02000000); - RND512Q((uint8_t*)y, z, 0x03000000); - RND512Q((uint8_t*)z, y, 0x04000000); - RND512Q((uint8_t*)y, z, 0x05000000); - RND512Q((uint8_t*)z, y, 0x06000000); - RND512Q((uint8_t*)y, z, 0x07000000); - RND512Q((uint8_t*)z, y, 0x08000000); - RND512Q((uint8_t*)y, Qtmp, 0x09000000); + /* compute Q(m) */ + RND512Q((uint8_t*)z, y, 0x00000000); + RND512Q((uint8_t*)y, z, 0x01000000); + RND512Q((uint8_t*)z, y, 0x02000000); + RND512Q((uint8_t*)y, z, 0x03000000); + RND512Q((uint8_t*)z, y, 0x04000000); + RND512Q((uint8_t*)y, z, 0x05000000); + RND512Q((uint8_t*)z, y, 0x06000000); + RND512Q((uint8_t*)y, z, 0x07000000); + RND512Q((uint8_t*)z, y, 0x08000000); + RND512Q((uint8_t*)y, Qtmp, 0x09000000); - /* compute P(h+m) */ - RND512P((uint8_t*)Ptmp, y, 0x00000000); - RND512P((uint8_t*)y, z, 0x00000001); - RND512P((uint8_t*)z, y, 0x00000002); - RND512P((uint8_t*)y, z, 0x00000003); - RND512P((uint8_t*)z, y, 0x00000004); - RND512P((uint8_t*)y, z, 0x00000005); - RND512P((uint8_t*)z, y, 0x00000006); - RND512P((uint8_t*)y, z, 0x00000007); - RND512P((uint8_t*)z, y, 0x00000008); - RND512P((uint8_t*)y, Ptmp, 0x00000009); + /* compute P(h+m) */ + RND512P((uint8_t*)Ptmp, y, 0x00000000); + RND512P((uint8_t*)y, z, 0x00000001); + RND512P((uint8_t*)z, y, 0x00000002); + RND512P((uint8_t*)y, z, 0x00000003); + RND512P((uint8_t*)z, y, 0x00000004); + RND512P((uint8_t*)y, z, 0x00000005); + RND512P((uint8_t*)z, y, 0x00000006); + RND512P((uint8_t*)y, z, 0x00000007); + RND512P((uint8_t*)z, y, 0x00000008); + RND512P((uint8_t*)y, Ptmp, 0x00000009); - /* compute P(h+m) + Q(m) + h */ - for (i = 0; i < 2*COLS512; i++) { - h[i] ^= Ptmp[i]^Qtmp[i]; - } + /* compute P(h+m) + Q(m) + h */ + for(i = 0; i < 2 * COLS512; i++) + { + h[i] ^= Ptmp[i] ^ Qtmp[i]; + } } /* digest up to msglen bytes of input (full blocks only) */ -static void Transform(groestlHashState *ctx, - const uint8_t *input, - int msglen) { +static void Transform(groestlHashState* ctx, + const uint8_t* input, + int msglen) +{ - /* digest message, one block at a time */ - for (; msglen >= SIZE512; - msglen -= SIZE512, input += SIZE512) { - F512(ctx->chaining,(uint32_t*)input); + /* digest message, one block at a time */ + for(; msglen >= SIZE512; + msglen -= SIZE512, input += SIZE512) + { + F512(ctx->chaining, (uint32_t*)input); - /* increment block counter */ - ctx->block_counter1++; - if (ctx->block_counter1 == 0) ctx->block_counter2++; - } + /* increment block counter */ + ctx->block_counter1++; + if(ctx->block_counter1 == 0) + { + ctx->block_counter2++; + } + } } /* given state h, do h <- P(h)+h */ -static void OutputTransformation(groestlHashState *ctx) { - int j; - uint32_t temp[2*COLS512]; - uint32_t y[2*COLS512]; - uint32_t z[2*COLS512]; +static void OutputTransformation(groestlHashState* ctx) +{ + int j; + uint32_t temp[2 * COLS512]; + uint32_t y[2 * COLS512]; + uint32_t z[2 * COLS512]; - for (j = 0; j < 2*COLS512; j++) { - temp[j] = ctx->chaining[j]; + for(j = 0; j < 2 * COLS512; j++) + { + temp[j] = ctx->chaining[j]; } RND512P((uint8_t*)temp, y, 0x00000000); RND512P((uint8_t*)y, z, 0x00000001); @@ -197,75 +209,84 @@ static void OutputTransformation(groestlHashState *ctx) { RND512P((uint8_t*)y, z, 0x00000007); RND512P((uint8_t*)z, y, 0x00000008); RND512P((uint8_t*)y, temp, 0x00000009); - for (j = 0; j < 2*COLS512; j++) { - ctx->chaining[j] ^= temp[j]; - } + for(j = 0; j < 2 * COLS512; j++) + { + ctx->chaining[j] ^= temp[j]; + } } /* initialise context */ -static void Init(groestlHashState* ctx) { - int i = 0; - /* allocate memory for state and data buffer */ +static void Init(groestlHashState* ctx) +{ + int i = 0; + /* allocate memory for state and data buffer */ - for(;i<(SIZE512/sizeof(uint32_t));i++) - { - ctx->chaining[i] = 0; - } + for(; i < (SIZE512 / sizeof(uint32_t)); i++) + { + ctx->chaining[i] = 0; + } - /* set initial value */ - ctx->chaining[2*COLS512-1] = u32BIG((uint32_t)HASH_BIT_LEN); + /* set initial value */ + ctx->chaining[2 * COLS512 - 1] = u32BIG((uint32_t)HASH_BIT_LEN); - /* set other variables */ - ctx->buf_ptr = 0; - ctx->block_counter1 = 0; - ctx->block_counter2 = 0; - ctx->bits_in_last_byte = 0; + /* set other variables */ + ctx->buf_ptr = 0; + ctx->block_counter1 = 0; + ctx->block_counter2 = 0; + ctx->bits_in_last_byte = 0; } /* update state with databitlen bits of input */ static void Update(groestlHashState* ctx, - const BitSequence* input, - DataLength databitlen) { - int index = 0; - int msglen = (int)(databitlen/8); - int rem = (int)(databitlen%8); + const BitSequence* input, + DataLength databitlen) +{ + int index = 0; + int msglen = (int)(databitlen / 8); + int rem = (int)(databitlen % 8); - /* if the buffer contains data that has not yet been digested, first - add data to buffer until full */ - if (ctx->buf_ptr) { - while (ctx->buf_ptr < SIZE512 && index < msglen) { - ctx->buffer[(int)ctx->buf_ptr++] = input[index++]; - } - if (ctx->buf_ptr < SIZE512) { - /* buffer still not full, return */ - if (rem) { - ctx->bits_in_last_byte = rem; - ctx->buffer[(int)ctx->buf_ptr++] = input[index]; - } - return; - } + /* if the buffer contains data that has not yet been digested, first + add data to buffer until full */ + if(ctx->buf_ptr) + { + while(ctx->buf_ptr < SIZE512 && index < msglen) + { + ctx->buffer[(int)ctx->buf_ptr++] = input[index++]; + } + if(ctx->buf_ptr < SIZE512) + { + /* buffer still not full, return */ + if(rem) + { + ctx->bits_in_last_byte = rem; + ctx->buffer[(int)ctx->buf_ptr++] = input[index]; + } + return; + } - /* digest buffer */ - ctx->buf_ptr = 0; - Transform(ctx, ctx->buffer, SIZE512); - } + /* digest buffer */ + ctx->buf_ptr = 0; + Transform(ctx, ctx->buffer, SIZE512); + } - /* digest bulk of message */ - Transform(ctx, input+index, msglen-index); - index += ((msglen-index)/SIZE512)*SIZE512; + /* digest bulk of message */ + Transform(ctx, input + index, msglen - index); + index += ((msglen - index) / SIZE512) * SIZE512; - /* store remaining data in buffer */ - while (index < msglen) { - ctx->buffer[(int)ctx->buf_ptr++] = input[index++]; - } + /* store remaining data in buffer */ + while(index < msglen) + { + ctx->buffer[(int)ctx->buf_ptr++] = input[index++]; + } - /* if non-integral number of bytes have been supplied, store - remaining bits in last byte, together with information about - number of bits */ - if (rem) { - ctx->bits_in_last_byte = rem; - ctx->buffer[(int)ctx->buf_ptr++] = input[index]; - } + /* if non-integral number of bytes have been supplied, store + remaining bits in last byte, together with information about + number of bits */ + if(rem) + { + ctx->bits_in_last_byte = rem; + ctx->buffer[(int)ctx->buf_ptr++] = input[index]; + } } #define BILB ctx->bits_in_last_byte @@ -273,80 +294,97 @@ static void Update(groestlHashState* ctx, /* finalise: process remaining data (including padding), perform output transformation, and write hash result to 'output' */ static void Final(groestlHashState* ctx, - BitSequence* output) { - int i, j = 0, hashbytelen = HASH_BIT_LEN/8; - uint8_t *s = (BitSequence*)ctx->chaining; + BitSequence* output) +{ + int i, j = 0, hashbytelen = HASH_BIT_LEN / 8; + uint8_t* s = (BitSequence*)ctx->chaining; - /* pad with '1'-bit and first few '0'-bits */ - if (BILB) { - ctx->buffer[(int)ctx->buf_ptr-1] &= ((1<buffer[(int)ctx->buf_ptr-1] ^= 0x1<<(7-BILB); - BILB = 0; - } - else ctx->buffer[(int)ctx->buf_ptr++] = 0x80; + /* pad with '1'-bit and first few '0'-bits */ + if(BILB) + { + ctx->buffer[(int)ctx->buf_ptr - 1] &= ((1 << BILB) - 1) << (8 - BILB); + ctx->buffer[(int)ctx->buf_ptr - 1] ^= 0x1 << (7 - BILB); + BILB = 0; + } + else + { + ctx->buffer[(int)ctx->buf_ptr++] = 0x80; + } - /* pad with '0'-bits */ - if (ctx->buf_ptr > SIZE512-LENGTHFIELDLEN) { - /* padding requires two blocks */ - while (ctx->buf_ptr < SIZE512) { - ctx->buffer[(int)ctx->buf_ptr++] = 0; - } - /* digest first padding block */ - Transform(ctx, ctx->buffer, SIZE512); - ctx->buf_ptr = 0; - } - while (ctx->buf_ptr < SIZE512-LENGTHFIELDLEN) { - ctx->buffer[(int)ctx->buf_ptr++] = 0; - } + /* pad with '0'-bits */ + if(ctx->buf_ptr > SIZE512 - LENGTHFIELDLEN) + { + /* padding requires two blocks */ + while(ctx->buf_ptr < SIZE512) + { + ctx->buffer[(int)ctx->buf_ptr++] = 0; + } + /* digest first padding block */ + Transform(ctx, ctx->buffer, SIZE512); + ctx->buf_ptr = 0; + } + while(ctx->buf_ptr < SIZE512 - LENGTHFIELDLEN) + { + ctx->buffer[(int)ctx->buf_ptr++] = 0; + } - /* length padding */ - ctx->block_counter1++; - if (ctx->block_counter1 == 0) ctx->block_counter2++; - ctx->buf_ptr = SIZE512; + /* length padding */ + ctx->block_counter1++; + if(ctx->block_counter1 == 0) + { + ctx->block_counter2++; + } + ctx->buf_ptr = SIZE512; - while (ctx->buf_ptr > SIZE512-(int)sizeof(uint32_t)) { - ctx->buffer[(int)--ctx->buf_ptr] = (uint8_t)ctx->block_counter1; - ctx->block_counter1 >>= 8; - } - while (ctx->buf_ptr > SIZE512-LENGTHFIELDLEN) { - ctx->buffer[(int)--ctx->buf_ptr] = (uint8_t)ctx->block_counter2; - ctx->block_counter2 >>= 8; - } - /* digest final padding block */ - Transform(ctx, ctx->buffer, SIZE512); - /* perform output transformation */ - OutputTransformation(ctx); + while(ctx->buf_ptr > SIZE512 - (int)sizeof(uint32_t)) + { + ctx->buffer[(int)--ctx->buf_ptr] = (uint8_t)ctx->block_counter1; + ctx->block_counter1 >>= 8; + } + while(ctx->buf_ptr > SIZE512 - LENGTHFIELDLEN) + { + ctx->buffer[(int)--ctx->buf_ptr] = (uint8_t)ctx->block_counter2; + ctx->block_counter2 >>= 8; + } + /* digest final padding block */ + Transform(ctx, ctx->buffer, SIZE512); + /* perform output transformation */ + OutputTransformation(ctx); - /* store hash result in output */ - for (i = SIZE512-hashbytelen; i < SIZE512; i++,j++) { - output[j] = s[i]; - } + /* store hash result in output */ + for(i = SIZE512 - hashbytelen; i < SIZE512; i++, j++) + { + output[j] = s[i]; + } - /* zeroise relevant variables and deallocate memory */ - for (i = 0; i < COLS512; i++) { - ctx->chaining[i] = 0; - } - for (i = 0; i < SIZE512; i++) { - ctx->buffer[i] = 0; - } + /* zeroise relevant variables and deallocate memory */ + for(i = 0; i < COLS512; i++) + { + ctx->chaining[i] = 0; + } + for(i = 0; i < SIZE512; i++) + { + ctx->buffer[i] = 0; + } } /* hash bit sequence */ -void groestl(const BitSequence* data, - DataLength databitlen, - BitSequence* hashval) { +void groestl(const BitSequence* data, + DataLength databitlen, + BitSequence* hashval) +{ - groestlHashState context; + groestlHashState context; - /* initialise */ - Init(&context); + /* initialise */ + Init(&context); - /* process message */ - Update(&context, data, databitlen); + /* process message */ + Update(&context, data, databitlen); - /* finalise */ - Final(&context, hashval); + /* finalise */ + Final(&context, hashval); } /* static int crypto_hash(unsigned char *out, diff --git a/src/crypto/c_groestl.h b/src/crypto/c_groestl.h index 2b513393..107080ba 100644 --- a/src/crypto/c_groestl.h +++ b/src/crypto/c_groestl.h @@ -4,10 +4,10 @@ #include "crypto_uint8.h" #include "crypto_uint32.h" #include "crypto_uint64.h" -#include "crypto_hash.h" +#include "crypto_hash.h" -typedef crypto_uint8 uint8_t; -typedef crypto_uint32 uint32_t; +typedef crypto_uint8 uint8_t; +typedef crypto_uint32 uint32_t; typedef crypto_uint64 uint64_t; */ #include @@ -30,18 +30,19 @@ typedef crypto_uint64 uint64_t; #define li_32(h) 0x##h##u #define EXT_BYTE(var,n) ((uint8_t)((uint32_t)(var) >> (8*n))) #define u32BIG(a) \ - ((ROTL32(a,8) & li_32(00FF00FF)) | \ - (ROTL32(a,24) & li_32(FF00FF00))) + ((ROTL32(a,8) & li_32(00FF00FF)) | \ + (ROTL32(a,24) & li_32(FF00FF00))) /* NIST API begin */ -typedef struct { - uint32_t chaining[SIZE512/sizeof(uint32_t)]; /* actual state */ - uint32_t block_counter1, - block_counter2; /* message block counter(s) */ - BitSequence buffer[SIZE512]; /* data buffer */ - int buf_ptr; /* data buffer pointer */ - int bits_in_last_byte; /* no. of message bits in last byte of +typedef struct +{ + uint32_t chaining[SIZE512 / sizeof(uint32_t)]; /* actual state */ + uint32_t block_counter1, + block_counter2; /* message block counter(s) */ + BitSequence buffer[SIZE512]; /* data buffer */ + int buf_ptr; /* data buffer pointer */ + int bits_in_last_byte; /* no. of message bits in last byte of data buffer */ } groestlHashState; diff --git a/src/crypto/c_jh.c b/src/crypto/c_jh.c index 728f3bbe..c40b603a 100644 --- a/src/crypto/c_jh.c +++ b/src/crypto/c_jh.c @@ -23,81 +23,86 @@ typedef uint64_t uint64; /*define data alignment for different C compilers*/ #if defined(__GNUC__) - #define DATA_ALIGN16(x) x __attribute__ ((aligned(16))) +#define DATA_ALIGN16(x) x __attribute__ ((aligned(16))) #else - #define DATA_ALIGN16(x) __declspec(align(16)) x +#define DATA_ALIGN16(x) __declspec(align(16)) x #endif -typedef struct { +typedef struct +{ int hashbitlen; /*the message digest size*/ unsigned long long databitlen; /*the message size in bits*/ - unsigned long long datasize_in_buffer; /*the size of the message remained in buffer; assumed to be multiple of 8bits except for the last partial block at the end of the message*/ - DATA_ALIGN16(uint64 x[8][2]); /*the 1024-bit state, ( x[i][0] || x[i][1] ) is the ith row of the state in the pseudocode*/ + unsigned long long + datasize_in_buffer; /*the size of the message remained in buffer; assumed to be multiple of 8bits except for the last partial block at the end of the message*/ + DATA_ALIGN16(uint64 + x[8][2]); /*the 1024-bit state, ( x[i][0] || x[i][1] ) is the ith row of the state in the pseudocode*/ unsigned char buffer[64]; /*the 512-bit message block to be hashed;*/ } hashState; /*The initial hash value H(0)*/ -const unsigned char JH224_H0[128]={0x2d,0xfe,0xdd,0x62,0xf9,0x9a,0x98,0xac,0xae,0x7c,0xac,0xd6,0x19,0xd6,0x34,0xe7,0xa4,0x83,0x10,0x5,0xbc,0x30,0x12,0x16,0xb8,0x60,0x38,0xc6,0xc9,0x66,0x14,0x94,0x66,0xd9,0x89,0x9f,0x25,0x80,0x70,0x6f,0xce,0x9e,0xa3,0x1b,0x1d,0x9b,0x1a,0xdc,0x11,0xe8,0x32,0x5f,0x7b,0x36,0x6e,0x10,0xf9,0x94,0x85,0x7f,0x2,0xfa,0x6,0xc1,0x1b,0x4f,0x1b,0x5c,0xd8,0xc8,0x40,0xb3,0x97,0xf6,0xa1,0x7f,0x6e,0x73,0x80,0x99,0xdc,0xdf,0x93,0xa5,0xad,0xea,0xa3,0xd3,0xa4,0x31,0xe8,0xde,0xc9,0x53,0x9a,0x68,0x22,0xb4,0xa9,0x8a,0xec,0x86,0xa1,0xe4,0xd5,0x74,0xac,0x95,0x9c,0xe5,0x6c,0xf0,0x15,0x96,0xd,0xea,0xb5,0xab,0x2b,0xbf,0x96,0x11,0xdc,0xf0,0xdd,0x64,0xea,0x6e}; -const unsigned char JH256_H0[128]={0xeb,0x98,0xa3,0x41,0x2c,0x20,0xd3,0xeb,0x92,0xcd,0xbe,0x7b,0x9c,0xb2,0x45,0xc1,0x1c,0x93,0x51,0x91,0x60,0xd4,0xc7,0xfa,0x26,0x0,0x82,0xd6,0x7e,0x50,0x8a,0x3,0xa4,0x23,0x9e,0x26,0x77,0x26,0xb9,0x45,0xe0,0xfb,0x1a,0x48,0xd4,0x1a,0x94,0x77,0xcd,0xb5,0xab,0x26,0x2,0x6b,0x17,0x7a,0x56,0xf0,0x24,0x42,0xf,0xff,0x2f,0xa8,0x71,0xa3,0x96,0x89,0x7f,0x2e,0x4d,0x75,0x1d,0x14,0x49,0x8,0xf7,0x7d,0xe2,0x62,0x27,0x76,0x95,0xf7,0x76,0x24,0x8f,0x94,0x87,0xd5,0xb6,0x57,0x47,0x80,0x29,0x6c,0x5c,0x5e,0x27,0x2d,0xac,0x8e,0xd,0x6c,0x51,0x84,0x50,0xc6,0x57,0x5,0x7a,0xf,0x7b,0xe4,0xd3,0x67,0x70,0x24,0x12,0xea,0x89,0xe3,0xab,0x13,0xd3,0x1c,0xd7,0x69}; -const unsigned char JH384_H0[128]={0x48,0x1e,0x3b,0xc6,0xd8,0x13,0x39,0x8a,0x6d,0x3b,0x5e,0x89,0x4a,0xde,0x87,0x9b,0x63,0xfa,0xea,0x68,0xd4,0x80,0xad,0x2e,0x33,0x2c,0xcb,0x21,0x48,0xf,0x82,0x67,0x98,0xae,0xc8,0x4d,0x90,0x82,0xb9,0x28,0xd4,0x55,0xea,0x30,0x41,0x11,0x42,0x49,0x36,0xf5,0x55,0xb2,0x92,0x48,0x47,0xec,0xc7,0x25,0xa,0x93,0xba,0xf4,0x3c,0xe1,0x56,0x9b,0x7f,0x8a,0x27,0xdb,0x45,0x4c,0x9e,0xfc,0xbd,0x49,0x63,0x97,0xaf,0xe,0x58,0x9f,0xc2,0x7d,0x26,0xaa,0x80,0xcd,0x80,0xc0,0x8b,0x8c,0x9d,0xeb,0x2e,0xda,0x8a,0x79,0x81,0xe8,0xf8,0xd5,0x37,0x3a,0xf4,0x39,0x67,0xad,0xdd,0xd1,0x7a,0x71,0xa9,0xb4,0xd3,0xbd,0xa4,0x75,0xd3,0x94,0x97,0x6c,0x3f,0xba,0x98,0x42,0x73,0x7f}; -const unsigned char JH512_H0[128]={0x6f,0xd1,0x4b,0x96,0x3e,0x0,0xaa,0x17,0x63,0x6a,0x2e,0x5,0x7a,0x15,0xd5,0x43,0x8a,0x22,0x5e,0x8d,0xc,0x97,0xef,0xb,0xe9,0x34,0x12,0x59,0xf2,0xb3,0xc3,0x61,0x89,0x1d,0xa0,0xc1,0x53,0x6f,0x80,0x1e,0x2a,0xa9,0x5,0x6b,0xea,0x2b,0x6d,0x80,0x58,0x8e,0xcc,0xdb,0x20,0x75,0xba,0xa6,0xa9,0xf,0x3a,0x76,0xba,0xf8,0x3b,0xf7,0x1,0x69,0xe6,0x5,0x41,0xe3,0x4a,0x69,0x46,0xb5,0x8a,0x8e,0x2e,0x6f,0xe6,0x5a,0x10,0x47,0xa7,0xd0,0xc1,0x84,0x3c,0x24,0x3b,0x6e,0x71,0xb1,0x2d,0x5a,0xc1,0x99,0xcf,0x57,0xf6,0xec,0x9d,0xb1,0xf8,0x56,0xa7,0x6,0x88,0x7c,0x57,0x16,0xb1,0x56,0xe3,0xc2,0xfc,0xdf,0xe6,0x85,0x17,0xfb,0x54,0x5a,0x46,0x78,0xcc,0x8c,0xdd,0x4b}; +const unsigned char JH224_H0[128] = {0x2d, 0xfe, 0xdd, 0x62, 0xf9, 0x9a, 0x98, 0xac, 0xae, 0x7c, 0xac, 0xd6, 0x19, 0xd6, 0x34, 0xe7, 0xa4, 0x83, 0x10, 0x5, 0xbc, 0x30, 0x12, 0x16, 0xb8, 0x60, 0x38, 0xc6, 0xc9, 0x66, 0x14, 0x94, 0x66, 0xd9, 0x89, 0x9f, 0x25, 0x80, 0x70, 0x6f, 0xce, 0x9e, 0xa3, 0x1b, 0x1d, 0x9b, 0x1a, 0xdc, 0x11, 0xe8, 0x32, 0x5f, 0x7b, 0x36, 0x6e, 0x10, 0xf9, 0x94, 0x85, 0x7f, 0x2, 0xfa, 0x6, 0xc1, 0x1b, 0x4f, 0x1b, 0x5c, 0xd8, 0xc8, 0x40, 0xb3, 0x97, 0xf6, 0xa1, 0x7f, 0x6e, 0x73, 0x80, 0x99, 0xdc, 0xdf, 0x93, 0xa5, 0xad, 0xea, 0xa3, 0xd3, 0xa4, 0x31, 0xe8, 0xde, 0xc9, 0x53, 0x9a, 0x68, 0x22, 0xb4, 0xa9, 0x8a, 0xec, 0x86, 0xa1, 0xe4, 0xd5, 0x74, 0xac, 0x95, 0x9c, 0xe5, 0x6c, 0xf0, 0x15, 0x96, 0xd, 0xea, 0xb5, 0xab, 0x2b, 0xbf, 0x96, 0x11, 0xdc, 0xf0, 0xdd, 0x64, 0xea, 0x6e}; +const unsigned char JH256_H0[128] = {0xeb, 0x98, 0xa3, 0x41, 0x2c, 0x20, 0xd3, 0xeb, 0x92, 0xcd, 0xbe, 0x7b, 0x9c, 0xb2, 0x45, 0xc1, 0x1c, 0x93, 0x51, 0x91, 0x60, 0xd4, 0xc7, 0xfa, 0x26, 0x0, 0x82, 0xd6, 0x7e, 0x50, 0x8a, 0x3, 0xa4, 0x23, 0x9e, 0x26, 0x77, 0x26, 0xb9, 0x45, 0xe0, 0xfb, 0x1a, 0x48, 0xd4, 0x1a, 0x94, 0x77, 0xcd, 0xb5, 0xab, 0x26, 0x2, 0x6b, 0x17, 0x7a, 0x56, 0xf0, 0x24, 0x42, 0xf, 0xff, 0x2f, 0xa8, 0x71, 0xa3, 0x96, 0x89, 0x7f, 0x2e, 0x4d, 0x75, 0x1d, 0x14, 0x49, 0x8, 0xf7, 0x7d, 0xe2, 0x62, 0x27, 0x76, 0x95, 0xf7, 0x76, 0x24, 0x8f, 0x94, 0x87, 0xd5, 0xb6, 0x57, 0x47, 0x80, 0x29, 0x6c, 0x5c, 0x5e, 0x27, 0x2d, 0xac, 0x8e, 0xd, 0x6c, 0x51, 0x84, 0x50, 0xc6, 0x57, 0x5, 0x7a, 0xf, 0x7b, 0xe4, 0xd3, 0x67, 0x70, 0x24, 0x12, 0xea, 0x89, 0xe3, 0xab, 0x13, 0xd3, 0x1c, 0xd7, 0x69}; +const unsigned char JH384_H0[128] = {0x48, 0x1e, 0x3b, 0xc6, 0xd8, 0x13, 0x39, 0x8a, 0x6d, 0x3b, 0x5e, 0x89, 0x4a, 0xde, 0x87, 0x9b, 0x63, 0xfa, 0xea, 0x68, 0xd4, 0x80, 0xad, 0x2e, 0x33, 0x2c, 0xcb, 0x21, 0x48, 0xf, 0x82, 0x67, 0x98, 0xae, 0xc8, 0x4d, 0x90, 0x82, 0xb9, 0x28, 0xd4, 0x55, 0xea, 0x30, 0x41, 0x11, 0x42, 0x49, 0x36, 0xf5, 0x55, 0xb2, 0x92, 0x48, 0x47, 0xec, 0xc7, 0x25, 0xa, 0x93, 0xba, 0xf4, 0x3c, 0xe1, 0x56, 0x9b, 0x7f, 0x8a, 0x27, 0xdb, 0x45, 0x4c, 0x9e, 0xfc, 0xbd, 0x49, 0x63, 0x97, 0xaf, 0xe, 0x58, 0x9f, 0xc2, 0x7d, 0x26, 0xaa, 0x80, 0xcd, 0x80, 0xc0, 0x8b, 0x8c, 0x9d, 0xeb, 0x2e, 0xda, 0x8a, 0x79, 0x81, 0xe8, 0xf8, 0xd5, 0x37, 0x3a, 0xf4, 0x39, 0x67, 0xad, 0xdd, 0xd1, 0x7a, 0x71, 0xa9, 0xb4, 0xd3, 0xbd, 0xa4, 0x75, 0xd3, 0x94, 0x97, 0x6c, 0x3f, 0xba, 0x98, 0x42, 0x73, 0x7f}; +const unsigned char JH512_H0[128] = {0x6f, 0xd1, 0x4b, 0x96, 0x3e, 0x0, 0xaa, 0x17, 0x63, 0x6a, 0x2e, 0x5, 0x7a, 0x15, 0xd5, 0x43, 0x8a, 0x22, 0x5e, 0x8d, 0xc, 0x97, 0xef, 0xb, 0xe9, 0x34, 0x12, 0x59, 0xf2, 0xb3, 0xc3, 0x61, 0x89, 0x1d, 0xa0, 0xc1, 0x53, 0x6f, 0x80, 0x1e, 0x2a, 0xa9, 0x5, 0x6b, 0xea, 0x2b, 0x6d, 0x80, 0x58, 0x8e, 0xcc, 0xdb, 0x20, 0x75, 0xba, 0xa6, 0xa9, 0xf, 0x3a, 0x76, 0xba, 0xf8, 0x3b, 0xf7, 0x1, 0x69, 0xe6, 0x5, 0x41, 0xe3, 0x4a, 0x69, 0x46, 0xb5, 0x8a, 0x8e, 0x2e, 0x6f, 0xe6, 0x5a, 0x10, 0x47, 0xa7, 0xd0, 0xc1, 0x84, 0x3c, 0x24, 0x3b, 0x6e, 0x71, 0xb1, 0x2d, 0x5a, 0xc1, 0x99, 0xcf, 0x57, 0xf6, 0xec, 0x9d, 0xb1, 0xf8, 0x56, 0xa7, 0x6, 0x88, 0x7c, 0x57, 0x16, 0xb1, 0x56, 0xe3, 0xc2, 0xfc, 0xdf, 0xe6, 0x85, 0x17, 0xfb, 0x54, 0x5a, 0x46, 0x78, 0xcc, 0x8c, 0xdd, 0x4b}; /*42 round constants, each round constant is 32-byte (256-bit)*/ -const unsigned char E8_bitslice_roundconstant[42][32]={ -{0x72,0xd5,0xde,0xa2,0xdf,0x15,0xf8,0x67,0x7b,0x84,0x15,0xa,0xb7,0x23,0x15,0x57,0x81,0xab,0xd6,0x90,0x4d,0x5a,0x87,0xf6,0x4e,0x9f,0x4f,0xc5,0xc3,0xd1,0x2b,0x40}, -{0xea,0x98,0x3a,0xe0,0x5c,0x45,0xfa,0x9c,0x3,0xc5,0xd2,0x99,0x66,0xb2,0x99,0x9a,0x66,0x2,0x96,0xb4,0xf2,0xbb,0x53,0x8a,0xb5,0x56,0x14,0x1a,0x88,0xdb,0xa2,0x31}, -{0x3,0xa3,0x5a,0x5c,0x9a,0x19,0xe,0xdb,0x40,0x3f,0xb2,0xa,0x87,0xc1,0x44,0x10,0x1c,0x5,0x19,0x80,0x84,0x9e,0x95,0x1d,0x6f,0x33,0xeb,0xad,0x5e,0xe7,0xcd,0xdc}, -{0x10,0xba,0x13,0x92,0x2,0xbf,0x6b,0x41,0xdc,0x78,0x65,0x15,0xf7,0xbb,0x27,0xd0,0xa,0x2c,0x81,0x39,0x37,0xaa,0x78,0x50,0x3f,0x1a,0xbf,0xd2,0x41,0x0,0x91,0xd3}, -{0x42,0x2d,0x5a,0xd,0xf6,0xcc,0x7e,0x90,0xdd,0x62,0x9f,0x9c,0x92,0xc0,0x97,0xce,0x18,0x5c,0xa7,0xb,0xc7,0x2b,0x44,0xac,0xd1,0xdf,0x65,0xd6,0x63,0xc6,0xfc,0x23}, -{0x97,0x6e,0x6c,0x3,0x9e,0xe0,0xb8,0x1a,0x21,0x5,0x45,0x7e,0x44,0x6c,0xec,0xa8,0xee,0xf1,0x3,0xbb,0x5d,0x8e,0x61,0xfa,0xfd,0x96,0x97,0xb2,0x94,0x83,0x81,0x97}, -{0x4a,0x8e,0x85,0x37,0xdb,0x3,0x30,0x2f,0x2a,0x67,0x8d,0x2d,0xfb,0x9f,0x6a,0x95,0x8a,0xfe,0x73,0x81,0xf8,0xb8,0x69,0x6c,0x8a,0xc7,0x72,0x46,0xc0,0x7f,0x42,0x14}, -{0xc5,0xf4,0x15,0x8f,0xbd,0xc7,0x5e,0xc4,0x75,0x44,0x6f,0xa7,0x8f,0x11,0xbb,0x80,0x52,0xde,0x75,0xb7,0xae,0xe4,0x88,0xbc,0x82,0xb8,0x0,0x1e,0x98,0xa6,0xa3,0xf4}, -{0x8e,0xf4,0x8f,0x33,0xa9,0xa3,0x63,0x15,0xaa,0x5f,0x56,0x24,0xd5,0xb7,0xf9,0x89,0xb6,0xf1,0xed,0x20,0x7c,0x5a,0xe0,0xfd,0x36,0xca,0xe9,0x5a,0x6,0x42,0x2c,0x36}, -{0xce,0x29,0x35,0x43,0x4e,0xfe,0x98,0x3d,0x53,0x3a,0xf9,0x74,0x73,0x9a,0x4b,0xa7,0xd0,0xf5,0x1f,0x59,0x6f,0x4e,0x81,0x86,0xe,0x9d,0xad,0x81,0xaf,0xd8,0x5a,0x9f}, -{0xa7,0x5,0x6,0x67,0xee,0x34,0x62,0x6a,0x8b,0xb,0x28,0xbe,0x6e,0xb9,0x17,0x27,0x47,0x74,0x7,0x26,0xc6,0x80,0x10,0x3f,0xe0,0xa0,0x7e,0x6f,0xc6,0x7e,0x48,0x7b}, -{0xd,0x55,0xa,0xa5,0x4a,0xf8,0xa4,0xc0,0x91,0xe3,0xe7,0x9f,0x97,0x8e,0xf1,0x9e,0x86,0x76,0x72,0x81,0x50,0x60,0x8d,0xd4,0x7e,0x9e,0x5a,0x41,0xf3,0xe5,0xb0,0x62}, -{0xfc,0x9f,0x1f,0xec,0x40,0x54,0x20,0x7a,0xe3,0xe4,0x1a,0x0,0xce,0xf4,0xc9,0x84,0x4f,0xd7,0x94,0xf5,0x9d,0xfa,0x95,0xd8,0x55,0x2e,0x7e,0x11,0x24,0xc3,0x54,0xa5}, -{0x5b,0xdf,0x72,0x28,0xbd,0xfe,0x6e,0x28,0x78,0xf5,0x7f,0xe2,0xf,0xa5,0xc4,0xb2,0x5,0x89,0x7c,0xef,0xee,0x49,0xd3,0x2e,0x44,0x7e,0x93,0x85,0xeb,0x28,0x59,0x7f}, -{0x70,0x5f,0x69,0x37,0xb3,0x24,0x31,0x4a,0x5e,0x86,0x28,0xf1,0x1d,0xd6,0xe4,0x65,0xc7,0x1b,0x77,0x4,0x51,0xb9,0x20,0xe7,0x74,0xfe,0x43,0xe8,0x23,0xd4,0x87,0x8a}, -{0x7d,0x29,0xe8,0xa3,0x92,0x76,0x94,0xf2,0xdd,0xcb,0x7a,0x9,0x9b,0x30,0xd9,0xc1,0x1d,0x1b,0x30,0xfb,0x5b,0xdc,0x1b,0xe0,0xda,0x24,0x49,0x4f,0xf2,0x9c,0x82,0xbf}, -{0xa4,0xe7,0xba,0x31,0xb4,0x70,0xbf,0xff,0xd,0x32,0x44,0x5,0xde,0xf8,0xbc,0x48,0x3b,0xae,0xfc,0x32,0x53,0xbb,0xd3,0x39,0x45,0x9f,0xc3,0xc1,0xe0,0x29,0x8b,0xa0}, -{0xe5,0xc9,0x5,0xfd,0xf7,0xae,0x9,0xf,0x94,0x70,0x34,0x12,0x42,0x90,0xf1,0x34,0xa2,0x71,0xb7,0x1,0xe3,0x44,0xed,0x95,0xe9,0x3b,0x8e,0x36,0x4f,0x2f,0x98,0x4a}, -{0x88,0x40,0x1d,0x63,0xa0,0x6c,0xf6,0x15,0x47,0xc1,0x44,0x4b,0x87,0x52,0xaf,0xff,0x7e,0xbb,0x4a,0xf1,0xe2,0xa,0xc6,0x30,0x46,0x70,0xb6,0xc5,0xcc,0x6e,0x8c,0xe6}, -{0xa4,0xd5,0xa4,0x56,0xbd,0x4f,0xca,0x0,0xda,0x9d,0x84,0x4b,0xc8,0x3e,0x18,0xae,0x73,0x57,0xce,0x45,0x30,0x64,0xd1,0xad,0xe8,0xa6,0xce,0x68,0x14,0x5c,0x25,0x67}, -{0xa3,0xda,0x8c,0xf2,0xcb,0xe,0xe1,0x16,0x33,0xe9,0x6,0x58,0x9a,0x94,0x99,0x9a,0x1f,0x60,0xb2,0x20,0xc2,0x6f,0x84,0x7b,0xd1,0xce,0xac,0x7f,0xa0,0xd1,0x85,0x18}, -{0x32,0x59,0x5b,0xa1,0x8d,0xdd,0x19,0xd3,0x50,0x9a,0x1c,0xc0,0xaa,0xa5,0xb4,0x46,0x9f,0x3d,0x63,0x67,0xe4,0x4,0x6b,0xba,0xf6,0xca,0x19,0xab,0xb,0x56,0xee,0x7e}, -{0x1f,0xb1,0x79,0xea,0xa9,0x28,0x21,0x74,0xe9,0xbd,0xf7,0x35,0x3b,0x36,0x51,0xee,0x1d,0x57,0xac,0x5a,0x75,0x50,0xd3,0x76,0x3a,0x46,0xc2,0xfe,0xa3,0x7d,0x70,0x1}, -{0xf7,0x35,0xc1,0xaf,0x98,0xa4,0xd8,0x42,0x78,0xed,0xec,0x20,0x9e,0x6b,0x67,0x79,0x41,0x83,0x63,0x15,0xea,0x3a,0xdb,0xa8,0xfa,0xc3,0x3b,0x4d,0x32,0x83,0x2c,0x83}, -{0xa7,0x40,0x3b,0x1f,0x1c,0x27,0x47,0xf3,0x59,0x40,0xf0,0x34,0xb7,0x2d,0x76,0x9a,0xe7,0x3e,0x4e,0x6c,0xd2,0x21,0x4f,0xfd,0xb8,0xfd,0x8d,0x39,0xdc,0x57,0x59,0xef}, -{0x8d,0x9b,0xc,0x49,0x2b,0x49,0xeb,0xda,0x5b,0xa2,0xd7,0x49,0x68,0xf3,0x70,0xd,0x7d,0x3b,0xae,0xd0,0x7a,0x8d,0x55,0x84,0xf5,0xa5,0xe9,0xf0,0xe4,0xf8,0x8e,0x65}, -{0xa0,0xb8,0xa2,0xf4,0x36,0x10,0x3b,0x53,0xc,0xa8,0x7,0x9e,0x75,0x3e,0xec,0x5a,0x91,0x68,0x94,0x92,0x56,0xe8,0x88,0x4f,0x5b,0xb0,0x5c,0x55,0xf8,0xba,0xbc,0x4c}, -{0xe3,0xbb,0x3b,0x99,0xf3,0x87,0x94,0x7b,0x75,0xda,0xf4,0xd6,0x72,0x6b,0x1c,0x5d,0x64,0xae,0xac,0x28,0xdc,0x34,0xb3,0x6d,0x6c,0x34,0xa5,0x50,0xb8,0x28,0xdb,0x71}, -{0xf8,0x61,0xe2,0xf2,0x10,0x8d,0x51,0x2a,0xe3,0xdb,0x64,0x33,0x59,0xdd,0x75,0xfc,0x1c,0xac,0xbc,0xf1,0x43,0xce,0x3f,0xa2,0x67,0xbb,0xd1,0x3c,0x2,0xe8,0x43,0xb0}, -{0x33,0xa,0x5b,0xca,0x88,0x29,0xa1,0x75,0x7f,0x34,0x19,0x4d,0xb4,0x16,0x53,0x5c,0x92,0x3b,0x94,0xc3,0xe,0x79,0x4d,0x1e,0x79,0x74,0x75,0xd7,0xb6,0xee,0xaf,0x3f}, -{0xea,0xa8,0xd4,0xf7,0xbe,0x1a,0x39,0x21,0x5c,0xf4,0x7e,0x9,0x4c,0x23,0x27,0x51,0x26,0xa3,0x24,0x53,0xba,0x32,0x3c,0xd2,0x44,0xa3,0x17,0x4a,0x6d,0xa6,0xd5,0xad}, -{0xb5,0x1d,0x3e,0xa6,0xaf,0xf2,0xc9,0x8,0x83,0x59,0x3d,0x98,0x91,0x6b,0x3c,0x56,0x4c,0xf8,0x7c,0xa1,0x72,0x86,0x60,0x4d,0x46,0xe2,0x3e,0xcc,0x8,0x6e,0xc7,0xf6}, -{0x2f,0x98,0x33,0xb3,0xb1,0xbc,0x76,0x5e,0x2b,0xd6,0x66,0xa5,0xef,0xc4,0xe6,0x2a,0x6,0xf4,0xb6,0xe8,0xbe,0xc1,0xd4,0x36,0x74,0xee,0x82,0x15,0xbc,0xef,0x21,0x63}, -{0xfd,0xc1,0x4e,0xd,0xf4,0x53,0xc9,0x69,0xa7,0x7d,0x5a,0xc4,0x6,0x58,0x58,0x26,0x7e,0xc1,0x14,0x16,0x6,0xe0,0xfa,0x16,0x7e,0x90,0xaf,0x3d,0x28,0x63,0x9d,0x3f}, -{0xd2,0xc9,0xf2,0xe3,0x0,0x9b,0xd2,0xc,0x5f,0xaa,0xce,0x30,0xb7,0xd4,0xc,0x30,0x74,0x2a,0x51,0x16,0xf2,0xe0,0x32,0x98,0xd,0xeb,0x30,0xd8,0xe3,0xce,0xf8,0x9a}, -{0x4b,0xc5,0x9e,0x7b,0xb5,0xf1,0x79,0x92,0xff,0x51,0xe6,0x6e,0x4,0x86,0x68,0xd3,0x9b,0x23,0x4d,0x57,0xe6,0x96,0x67,0x31,0xcc,0xe6,0xa6,0xf3,0x17,0xa,0x75,0x5}, -{0xb1,0x76,0x81,0xd9,0x13,0x32,0x6c,0xce,0x3c,0x17,0x52,0x84,0xf8,0x5,0xa2,0x62,0xf4,0x2b,0xcb,0xb3,0x78,0x47,0x15,0x47,0xff,0x46,0x54,0x82,0x23,0x93,0x6a,0x48}, -{0x38,0xdf,0x58,0x7,0x4e,0x5e,0x65,0x65,0xf2,0xfc,0x7c,0x89,0xfc,0x86,0x50,0x8e,0x31,0x70,0x2e,0x44,0xd0,0xb,0xca,0x86,0xf0,0x40,0x9,0xa2,0x30,0x78,0x47,0x4e}, -{0x65,0xa0,0xee,0x39,0xd1,0xf7,0x38,0x83,0xf7,0x5e,0xe9,0x37,0xe4,0x2c,0x3a,0xbd,0x21,0x97,0xb2,0x26,0x1,0x13,0xf8,0x6f,0xa3,0x44,0xed,0xd1,0xef,0x9f,0xde,0xe7}, -{0x8b,0xa0,0xdf,0x15,0x76,0x25,0x92,0xd9,0x3c,0x85,0xf7,0xf6,0x12,0xdc,0x42,0xbe,0xd8,0xa7,0xec,0x7c,0xab,0x27,0xb0,0x7e,0x53,0x8d,0x7d,0xda,0xaa,0x3e,0xa8,0xde}, -{0xaa,0x25,0xce,0x93,0xbd,0x2,0x69,0xd8,0x5a,0xf6,0x43,0xfd,0x1a,0x73,0x8,0xf9,0xc0,0x5f,0xef,0xda,0x17,0x4a,0x19,0xa5,0x97,0x4d,0x66,0x33,0x4c,0xfd,0x21,0x6a}, -{0x35,0xb4,0x98,0x31,0xdb,0x41,0x15,0x70,0xea,0x1e,0xf,0xbb,0xed,0xcd,0x54,0x9b,0x9a,0xd0,0x63,0xa1,0x51,0x97,0x40,0x72,0xf6,0x75,0x9d,0xbf,0x91,0x47,0x6f,0xe2}}; +const unsigned char E8_bitslice_roundconstant[42][32] = +{ + {0x72, 0xd5, 0xde, 0xa2, 0xdf, 0x15, 0xf8, 0x67, 0x7b, 0x84, 0x15, 0xa, 0xb7, 0x23, 0x15, 0x57, 0x81, 0xab, 0xd6, 0x90, 0x4d, 0x5a, 0x87, 0xf6, 0x4e, 0x9f, 0x4f, 0xc5, 0xc3, 0xd1, 0x2b, 0x40}, + {0xea, 0x98, 0x3a, 0xe0, 0x5c, 0x45, 0xfa, 0x9c, 0x3, 0xc5, 0xd2, 0x99, 0x66, 0xb2, 0x99, 0x9a, 0x66, 0x2, 0x96, 0xb4, 0xf2, 0xbb, 0x53, 0x8a, 0xb5, 0x56, 0x14, 0x1a, 0x88, 0xdb, 0xa2, 0x31}, + {0x3, 0xa3, 0x5a, 0x5c, 0x9a, 0x19, 0xe, 0xdb, 0x40, 0x3f, 0xb2, 0xa, 0x87, 0xc1, 0x44, 0x10, 0x1c, 0x5, 0x19, 0x80, 0x84, 0x9e, 0x95, 0x1d, 0x6f, 0x33, 0xeb, 0xad, 0x5e, 0xe7, 0xcd, 0xdc}, + {0x10, 0xba, 0x13, 0x92, 0x2, 0xbf, 0x6b, 0x41, 0xdc, 0x78, 0x65, 0x15, 0xf7, 0xbb, 0x27, 0xd0, 0xa, 0x2c, 0x81, 0x39, 0x37, 0xaa, 0x78, 0x50, 0x3f, 0x1a, 0xbf, 0xd2, 0x41, 0x0, 0x91, 0xd3}, + {0x42, 0x2d, 0x5a, 0xd, 0xf6, 0xcc, 0x7e, 0x90, 0xdd, 0x62, 0x9f, 0x9c, 0x92, 0xc0, 0x97, 0xce, 0x18, 0x5c, 0xa7, 0xb, 0xc7, 0x2b, 0x44, 0xac, 0xd1, 0xdf, 0x65, 0xd6, 0x63, 0xc6, 0xfc, 0x23}, + {0x97, 0x6e, 0x6c, 0x3, 0x9e, 0xe0, 0xb8, 0x1a, 0x21, 0x5, 0x45, 0x7e, 0x44, 0x6c, 0xec, 0xa8, 0xee, 0xf1, 0x3, 0xbb, 0x5d, 0x8e, 0x61, 0xfa, 0xfd, 0x96, 0x97, 0xb2, 0x94, 0x83, 0x81, 0x97}, + {0x4a, 0x8e, 0x85, 0x37, 0xdb, 0x3, 0x30, 0x2f, 0x2a, 0x67, 0x8d, 0x2d, 0xfb, 0x9f, 0x6a, 0x95, 0x8a, 0xfe, 0x73, 0x81, 0xf8, 0xb8, 0x69, 0x6c, 0x8a, 0xc7, 0x72, 0x46, 0xc0, 0x7f, 0x42, 0x14}, + {0xc5, 0xf4, 0x15, 0x8f, 0xbd, 0xc7, 0x5e, 0xc4, 0x75, 0x44, 0x6f, 0xa7, 0x8f, 0x11, 0xbb, 0x80, 0x52, 0xde, 0x75, 0xb7, 0xae, 0xe4, 0x88, 0xbc, 0x82, 0xb8, 0x0, 0x1e, 0x98, 0xa6, 0xa3, 0xf4}, + {0x8e, 0xf4, 0x8f, 0x33, 0xa9, 0xa3, 0x63, 0x15, 0xaa, 0x5f, 0x56, 0x24, 0xd5, 0xb7, 0xf9, 0x89, 0xb6, 0xf1, 0xed, 0x20, 0x7c, 0x5a, 0xe0, 0xfd, 0x36, 0xca, 0xe9, 0x5a, 0x6, 0x42, 0x2c, 0x36}, + {0xce, 0x29, 0x35, 0x43, 0x4e, 0xfe, 0x98, 0x3d, 0x53, 0x3a, 0xf9, 0x74, 0x73, 0x9a, 0x4b, 0xa7, 0xd0, 0xf5, 0x1f, 0x59, 0x6f, 0x4e, 0x81, 0x86, 0xe, 0x9d, 0xad, 0x81, 0xaf, 0xd8, 0x5a, 0x9f}, + {0xa7, 0x5, 0x6, 0x67, 0xee, 0x34, 0x62, 0x6a, 0x8b, 0xb, 0x28, 0xbe, 0x6e, 0xb9, 0x17, 0x27, 0x47, 0x74, 0x7, 0x26, 0xc6, 0x80, 0x10, 0x3f, 0xe0, 0xa0, 0x7e, 0x6f, 0xc6, 0x7e, 0x48, 0x7b}, + {0xd, 0x55, 0xa, 0xa5, 0x4a, 0xf8, 0xa4, 0xc0, 0x91, 0xe3, 0xe7, 0x9f, 0x97, 0x8e, 0xf1, 0x9e, 0x86, 0x76, 0x72, 0x81, 0x50, 0x60, 0x8d, 0xd4, 0x7e, 0x9e, 0x5a, 0x41, 0xf3, 0xe5, 0xb0, 0x62}, + {0xfc, 0x9f, 0x1f, 0xec, 0x40, 0x54, 0x20, 0x7a, 0xe3, 0xe4, 0x1a, 0x0, 0xce, 0xf4, 0xc9, 0x84, 0x4f, 0xd7, 0x94, 0xf5, 0x9d, 0xfa, 0x95, 0xd8, 0x55, 0x2e, 0x7e, 0x11, 0x24, 0xc3, 0x54, 0xa5}, + {0x5b, 0xdf, 0x72, 0x28, 0xbd, 0xfe, 0x6e, 0x28, 0x78, 0xf5, 0x7f, 0xe2, 0xf, 0xa5, 0xc4, 0xb2, 0x5, 0x89, 0x7c, 0xef, 0xee, 0x49, 0xd3, 0x2e, 0x44, 0x7e, 0x93, 0x85, 0xeb, 0x28, 0x59, 0x7f}, + {0x70, 0x5f, 0x69, 0x37, 0xb3, 0x24, 0x31, 0x4a, 0x5e, 0x86, 0x28, 0xf1, 0x1d, 0xd6, 0xe4, 0x65, 0xc7, 0x1b, 0x77, 0x4, 0x51, 0xb9, 0x20, 0xe7, 0x74, 0xfe, 0x43, 0xe8, 0x23, 0xd4, 0x87, 0x8a}, + {0x7d, 0x29, 0xe8, 0xa3, 0x92, 0x76, 0x94, 0xf2, 0xdd, 0xcb, 0x7a, 0x9, 0x9b, 0x30, 0xd9, 0xc1, 0x1d, 0x1b, 0x30, 0xfb, 0x5b, 0xdc, 0x1b, 0xe0, 0xda, 0x24, 0x49, 0x4f, 0xf2, 0x9c, 0x82, 0xbf}, + {0xa4, 0xe7, 0xba, 0x31, 0xb4, 0x70, 0xbf, 0xff, 0xd, 0x32, 0x44, 0x5, 0xde, 0xf8, 0xbc, 0x48, 0x3b, 0xae, 0xfc, 0x32, 0x53, 0xbb, 0xd3, 0x39, 0x45, 0x9f, 0xc3, 0xc1, 0xe0, 0x29, 0x8b, 0xa0}, + {0xe5, 0xc9, 0x5, 0xfd, 0xf7, 0xae, 0x9, 0xf, 0x94, 0x70, 0x34, 0x12, 0x42, 0x90, 0xf1, 0x34, 0xa2, 0x71, 0xb7, 0x1, 0xe3, 0x44, 0xed, 0x95, 0xe9, 0x3b, 0x8e, 0x36, 0x4f, 0x2f, 0x98, 0x4a}, + {0x88, 0x40, 0x1d, 0x63, 0xa0, 0x6c, 0xf6, 0x15, 0x47, 0xc1, 0x44, 0x4b, 0x87, 0x52, 0xaf, 0xff, 0x7e, 0xbb, 0x4a, 0xf1, 0xe2, 0xa, 0xc6, 0x30, 0x46, 0x70, 0xb6, 0xc5, 0xcc, 0x6e, 0x8c, 0xe6}, + {0xa4, 0xd5, 0xa4, 0x56, 0xbd, 0x4f, 0xca, 0x0, 0xda, 0x9d, 0x84, 0x4b, 0xc8, 0x3e, 0x18, 0xae, 0x73, 0x57, 0xce, 0x45, 0x30, 0x64, 0xd1, 0xad, 0xe8, 0xa6, 0xce, 0x68, 0x14, 0x5c, 0x25, 0x67}, + {0xa3, 0xda, 0x8c, 0xf2, 0xcb, 0xe, 0xe1, 0x16, 0x33, 0xe9, 0x6, 0x58, 0x9a, 0x94, 0x99, 0x9a, 0x1f, 0x60, 0xb2, 0x20, 0xc2, 0x6f, 0x84, 0x7b, 0xd1, 0xce, 0xac, 0x7f, 0xa0, 0xd1, 0x85, 0x18}, + {0x32, 0x59, 0x5b, 0xa1, 0x8d, 0xdd, 0x19, 0xd3, 0x50, 0x9a, 0x1c, 0xc0, 0xaa, 0xa5, 0xb4, 0x46, 0x9f, 0x3d, 0x63, 0x67, 0xe4, 0x4, 0x6b, 0xba, 0xf6, 0xca, 0x19, 0xab, 0xb, 0x56, 0xee, 0x7e}, + {0x1f, 0xb1, 0x79, 0xea, 0xa9, 0x28, 0x21, 0x74, 0xe9, 0xbd, 0xf7, 0x35, 0x3b, 0x36, 0x51, 0xee, 0x1d, 0x57, 0xac, 0x5a, 0x75, 0x50, 0xd3, 0x76, 0x3a, 0x46, 0xc2, 0xfe, 0xa3, 0x7d, 0x70, 0x1}, + {0xf7, 0x35, 0xc1, 0xaf, 0x98, 0xa4, 0xd8, 0x42, 0x78, 0xed, 0xec, 0x20, 0x9e, 0x6b, 0x67, 0x79, 0x41, 0x83, 0x63, 0x15, 0xea, 0x3a, 0xdb, 0xa8, 0xfa, 0xc3, 0x3b, 0x4d, 0x32, 0x83, 0x2c, 0x83}, + {0xa7, 0x40, 0x3b, 0x1f, 0x1c, 0x27, 0x47, 0xf3, 0x59, 0x40, 0xf0, 0x34, 0xb7, 0x2d, 0x76, 0x9a, 0xe7, 0x3e, 0x4e, 0x6c, 0xd2, 0x21, 0x4f, 0xfd, 0xb8, 0xfd, 0x8d, 0x39, 0xdc, 0x57, 0x59, 0xef}, + {0x8d, 0x9b, 0xc, 0x49, 0x2b, 0x49, 0xeb, 0xda, 0x5b, 0xa2, 0xd7, 0x49, 0x68, 0xf3, 0x70, 0xd, 0x7d, 0x3b, 0xae, 0xd0, 0x7a, 0x8d, 0x55, 0x84, 0xf5, 0xa5, 0xe9, 0xf0, 0xe4, 0xf8, 0x8e, 0x65}, + {0xa0, 0xb8, 0xa2, 0xf4, 0x36, 0x10, 0x3b, 0x53, 0xc, 0xa8, 0x7, 0x9e, 0x75, 0x3e, 0xec, 0x5a, 0x91, 0x68, 0x94, 0x92, 0x56, 0xe8, 0x88, 0x4f, 0x5b, 0xb0, 0x5c, 0x55, 0xf8, 0xba, 0xbc, 0x4c}, + {0xe3, 0xbb, 0x3b, 0x99, 0xf3, 0x87, 0x94, 0x7b, 0x75, 0xda, 0xf4, 0xd6, 0x72, 0x6b, 0x1c, 0x5d, 0x64, 0xae, 0xac, 0x28, 0xdc, 0x34, 0xb3, 0x6d, 0x6c, 0x34, 0xa5, 0x50, 0xb8, 0x28, 0xdb, 0x71}, + {0xf8, 0x61, 0xe2, 0xf2, 0x10, 0x8d, 0x51, 0x2a, 0xe3, 0xdb, 0x64, 0x33, 0x59, 0xdd, 0x75, 0xfc, 0x1c, 0xac, 0xbc, 0xf1, 0x43, 0xce, 0x3f, 0xa2, 0x67, 0xbb, 0xd1, 0x3c, 0x2, 0xe8, 0x43, 0xb0}, + {0x33, 0xa, 0x5b, 0xca, 0x88, 0x29, 0xa1, 0x75, 0x7f, 0x34, 0x19, 0x4d, 0xb4, 0x16, 0x53, 0x5c, 0x92, 0x3b, 0x94, 0xc3, 0xe, 0x79, 0x4d, 0x1e, 0x79, 0x74, 0x75, 0xd7, 0xb6, 0xee, 0xaf, 0x3f}, + {0xea, 0xa8, 0xd4, 0xf7, 0xbe, 0x1a, 0x39, 0x21, 0x5c, 0xf4, 0x7e, 0x9, 0x4c, 0x23, 0x27, 0x51, 0x26, 0xa3, 0x24, 0x53, 0xba, 0x32, 0x3c, 0xd2, 0x44, 0xa3, 0x17, 0x4a, 0x6d, 0xa6, 0xd5, 0xad}, + {0xb5, 0x1d, 0x3e, 0xa6, 0xaf, 0xf2, 0xc9, 0x8, 0x83, 0x59, 0x3d, 0x98, 0x91, 0x6b, 0x3c, 0x56, 0x4c, 0xf8, 0x7c, 0xa1, 0x72, 0x86, 0x60, 0x4d, 0x46, 0xe2, 0x3e, 0xcc, 0x8, 0x6e, 0xc7, 0xf6}, + {0x2f, 0x98, 0x33, 0xb3, 0xb1, 0xbc, 0x76, 0x5e, 0x2b, 0xd6, 0x66, 0xa5, 0xef, 0xc4, 0xe6, 0x2a, 0x6, 0xf4, 0xb6, 0xe8, 0xbe, 0xc1, 0xd4, 0x36, 0x74, 0xee, 0x82, 0x15, 0xbc, 0xef, 0x21, 0x63}, + {0xfd, 0xc1, 0x4e, 0xd, 0xf4, 0x53, 0xc9, 0x69, 0xa7, 0x7d, 0x5a, 0xc4, 0x6, 0x58, 0x58, 0x26, 0x7e, 0xc1, 0x14, 0x16, 0x6, 0xe0, 0xfa, 0x16, 0x7e, 0x90, 0xaf, 0x3d, 0x28, 0x63, 0x9d, 0x3f}, + {0xd2, 0xc9, 0xf2, 0xe3, 0x0, 0x9b, 0xd2, 0xc, 0x5f, 0xaa, 0xce, 0x30, 0xb7, 0xd4, 0xc, 0x30, 0x74, 0x2a, 0x51, 0x16, 0xf2, 0xe0, 0x32, 0x98, 0xd, 0xeb, 0x30, 0xd8, 0xe3, 0xce, 0xf8, 0x9a}, + {0x4b, 0xc5, 0x9e, 0x7b, 0xb5, 0xf1, 0x79, 0x92, 0xff, 0x51, 0xe6, 0x6e, 0x4, 0x86, 0x68, 0xd3, 0x9b, 0x23, 0x4d, 0x57, 0xe6, 0x96, 0x67, 0x31, 0xcc, 0xe6, 0xa6, 0xf3, 0x17, 0xa, 0x75, 0x5}, + {0xb1, 0x76, 0x81, 0xd9, 0x13, 0x32, 0x6c, 0xce, 0x3c, 0x17, 0x52, 0x84, 0xf8, 0x5, 0xa2, 0x62, 0xf4, 0x2b, 0xcb, 0xb3, 0x78, 0x47, 0x15, 0x47, 0xff, 0x46, 0x54, 0x82, 0x23, 0x93, 0x6a, 0x48}, + {0x38, 0xdf, 0x58, 0x7, 0x4e, 0x5e, 0x65, 0x65, 0xf2, 0xfc, 0x7c, 0x89, 0xfc, 0x86, 0x50, 0x8e, 0x31, 0x70, 0x2e, 0x44, 0xd0, 0xb, 0xca, 0x86, 0xf0, 0x40, 0x9, 0xa2, 0x30, 0x78, 0x47, 0x4e}, + {0x65, 0xa0, 0xee, 0x39, 0xd1, 0xf7, 0x38, 0x83, 0xf7, 0x5e, 0xe9, 0x37, 0xe4, 0x2c, 0x3a, 0xbd, 0x21, 0x97, 0xb2, 0x26, 0x1, 0x13, 0xf8, 0x6f, 0xa3, 0x44, 0xed, 0xd1, 0xef, 0x9f, 0xde, 0xe7}, + {0x8b, 0xa0, 0xdf, 0x15, 0x76, 0x25, 0x92, 0xd9, 0x3c, 0x85, 0xf7, 0xf6, 0x12, 0xdc, 0x42, 0xbe, 0xd8, 0xa7, 0xec, 0x7c, 0xab, 0x27, 0xb0, 0x7e, 0x53, 0x8d, 0x7d, 0xda, 0xaa, 0x3e, 0xa8, 0xde}, + {0xaa, 0x25, 0xce, 0x93, 0xbd, 0x2, 0x69, 0xd8, 0x5a, 0xf6, 0x43, 0xfd, 0x1a, 0x73, 0x8, 0xf9, 0xc0, 0x5f, 0xef, 0xda, 0x17, 0x4a, 0x19, 0xa5, 0x97, 0x4d, 0x66, 0x33, 0x4c, 0xfd, 0x21, 0x6a}, + {0x35, 0xb4, 0x98, 0x31, 0xdb, 0x41, 0x15, 0x70, 0xea, 0x1e, 0xf, 0xbb, 0xed, 0xcd, 0x54, 0x9b, 0x9a, 0xd0, 0x63, 0xa1, 0x51, 0x97, 0x40, 0x72, 0xf6, 0x75, 0x9d, 0xbf, 0x91, 0x47, 0x6f, 0xe2} +}; -static void E8(hashState *state); /*The bijective function E8, in bitslice form*/ -static void F8(hashState *state); /*The compression function F8 */ +static void E8(hashState* state); /*The bijective function E8, in bitslice form*/ +static void F8(hashState* state); /*The compression function F8 */ /*The API functions*/ -static HashReturn Init(hashState *state, int hashbitlen); -static HashReturn Update(hashState *state, const BitSequence *data, DataLength databitlen); -static HashReturn Final(hashState *state, BitSequence *hashval); -HashReturn jh_hash(int hashbitlen, const BitSequence *data,DataLength databitlen, BitSequence *hashval); +static HashReturn Init(hashState* state, int hashbitlen); +static HashReturn Update(hashState* state, const BitSequence* data, DataLength databitlen); +static HashReturn Final(hashState* state, BitSequence* hashval); +HashReturn jh_hash(int hashbitlen, const BitSequence* data, DataLength databitlen, BitSequence* hashval); /*swapping bit 2i with bit 2i+1 of 64-bit x*/ #define SWAP1(x) (x) = ((((x) & 0x5555555555555555ULL) << 1) | (((x) & 0xaaaaaaaaaaaaaaaaULL) >> 1)); @@ -114,254 +119,350 @@ HashReturn jh_hash(int hashbitlen, const BitSequence *data,DataLength databitlen /*The MDS transform*/ #define L(m0,m1,m2,m3,m4,m5,m6,m7) \ - (m4) ^= (m1); \ - (m5) ^= (m2); \ - (m6) ^= (m0) ^ (m3); \ - (m7) ^= (m0); \ - (m0) ^= (m5); \ - (m1) ^= (m6); \ - (m2) ^= (m4) ^ (m7); \ - (m3) ^= (m4); + (m4) ^= (m1); \ + (m5) ^= (m2); \ + (m6) ^= (m0) ^ (m3); \ + (m7) ^= (m0); \ + (m0) ^= (m5); \ + (m1) ^= (m6); \ + (m2) ^= (m4) ^ (m7); \ + (m3) ^= (m4); /*Two Sboxes are computed in parallel, each Sbox implements S0 and S1, selected by a constant bit*/ /*The reason to compute two Sboxes in parallel is to try to fully utilize the parallel processing power*/ #define SS(m0,m1,m2,m3,m4,m5,m6,m7,cc0,cc1) \ - m3 = ~(m3); \ - m7 = ~(m7); \ - m0 ^= ((~(m2)) & (cc0)); \ - m4 ^= ((~(m6)) & (cc1)); \ - temp0 = (cc0) ^ ((m0) & (m1));\ - temp1 = (cc1) ^ ((m4) & (m5));\ - m0 ^= ((m2) & (m3)); \ - m4 ^= ((m6) & (m7)); \ - m3 ^= ((~(m1)) & (m2)); \ - m7 ^= ((~(m5)) & (m6)); \ - m1 ^= ((m0) & (m2)); \ - m5 ^= ((m4) & (m6)); \ - m2 ^= ((m0) & (~(m3))); \ - m6 ^= ((m4) & (~(m7))); \ - m0 ^= ((m1) | (m3)); \ - m4 ^= ((m5) | (m7)); \ - m3 ^= ((m1) & (m2)); \ - m7 ^= ((m5) & (m6)); \ - m1 ^= (temp0 & (m0)); \ - m5 ^= (temp1 & (m4)); \ - m2 ^= temp0; \ - m6 ^= temp1; + m3 = ~(m3); \ + m7 = ~(m7); \ + m0 ^= ((~(m2)) & (cc0)); \ + m4 ^= ((~(m6)) & (cc1)); \ + temp0 = (cc0) ^ ((m0) & (m1));\ + temp1 = (cc1) ^ ((m4) & (m5));\ + m0 ^= ((m2) & (m3)); \ + m4 ^= ((m6) & (m7)); \ + m3 ^= ((~(m1)) & (m2)); \ + m7 ^= ((~(m5)) & (m6)); \ + m1 ^= ((m0) & (m2)); \ + m5 ^= ((m4) & (m6)); \ + m2 ^= ((m0) & (~(m3))); \ + m6 ^= ((m4) & (~(m7))); \ + m0 ^= ((m1) | (m3)); \ + m4 ^= ((m5) | (m7)); \ + m3 ^= ((m1) & (m2)); \ + m7 ^= ((m5) & (m6)); \ + m1 ^= (temp0 & (m0)); \ + m5 ^= (temp1 & (m4)); \ + m2 ^= temp0; \ + m6 ^= temp1; /*The bijective function E8, in bitslice form*/ -static void E8(hashState *state) +static void E8(hashState* state) { - uint64 i,roundnumber,temp0,temp1; + uint64 i, roundnumber, temp0, temp1; - for (roundnumber = 0; roundnumber < 42; roundnumber = roundnumber+7) { - /*round 7*roundnumber+0: Sbox, MDS and Swapping layers*/ - for (i = 0; i < 2; i++) { - SS(state->x[0][i],state->x[2][i],state->x[4][i],state->x[6][i],state->x[1][i],state->x[3][i],state->x[5][i],state->x[7][i],((uint64*)E8_bitslice_roundconstant[roundnumber+0])[i],((uint64*)E8_bitslice_roundconstant[roundnumber+0])[i+2] ); - L(state->x[0][i],state->x[2][i],state->x[4][i],state->x[6][i],state->x[1][i],state->x[3][i],state->x[5][i],state->x[7][i]); - SWAP1(state->x[1][i]); SWAP1(state->x[3][i]); SWAP1(state->x[5][i]); SWAP1(state->x[7][i]); - } + for(roundnumber = 0; roundnumber < 42; roundnumber = roundnumber + 7) + { + /*round 7*roundnumber+0: Sbox, MDS and Swapping layers*/ + for(i = 0; i < 2; i++) + { + SS(state->x[0][i], state->x[2][i], state->x[4][i], state->x[6][i], state->x[1][i], state->x[3][i], + state->x[5][i], state->x[7][i], ((uint64*)E8_bitslice_roundconstant[roundnumber + 0])[i], + ((uint64*)E8_bitslice_roundconstant[roundnumber + 0])[i + 2]); + L(state->x[0][i], state->x[2][i], state->x[4][i], state->x[6][i], state->x[1][i], state->x[3][i], + state->x[5][i], state->x[7][i]); + SWAP1(state->x[1][i]); + SWAP1(state->x[3][i]); + SWAP1(state->x[5][i]); + SWAP1(state->x[7][i]); + } - /*round 7*roundnumber+1: Sbox, MDS and Swapping layers*/ - for (i = 0; i < 2; i++) { - SS(state->x[0][i],state->x[2][i],state->x[4][i],state->x[6][i],state->x[1][i],state->x[3][i],state->x[5][i],state->x[7][i],((uint64*)E8_bitslice_roundconstant[roundnumber+1])[i],((uint64*)E8_bitslice_roundconstant[roundnumber+1])[i+2] ); - L(state->x[0][i],state->x[2][i],state->x[4][i],state->x[6][i],state->x[1][i],state->x[3][i],state->x[5][i],state->x[7][i]); - SWAP2(state->x[1][i]); SWAP2(state->x[3][i]); SWAP2(state->x[5][i]); SWAP2(state->x[7][i]); - } + /*round 7*roundnumber+1: Sbox, MDS and Swapping layers*/ + for(i = 0; i < 2; i++) + { + SS(state->x[0][i], state->x[2][i], state->x[4][i], state->x[6][i], state->x[1][i], state->x[3][i], + state->x[5][i], state->x[7][i], ((uint64*)E8_bitslice_roundconstant[roundnumber + 1])[i], + ((uint64*)E8_bitslice_roundconstant[roundnumber + 1])[i + 2]); + L(state->x[0][i], state->x[2][i], state->x[4][i], state->x[6][i], state->x[1][i], state->x[3][i], + state->x[5][i], state->x[7][i]); + SWAP2(state->x[1][i]); + SWAP2(state->x[3][i]); + SWAP2(state->x[5][i]); + SWAP2(state->x[7][i]); + } - /*round 7*roundnumber+2: Sbox, MDS and Swapping layers*/ - for (i = 0; i < 2; i++) { - SS(state->x[0][i],state->x[2][i],state->x[4][i],state->x[6][i],state->x[1][i],state->x[3][i],state->x[5][i],state->x[7][i],((uint64*)E8_bitslice_roundconstant[roundnumber+2])[i],((uint64*)E8_bitslice_roundconstant[roundnumber+2])[i+2] ); - L(state->x[0][i],state->x[2][i],state->x[4][i],state->x[6][i],state->x[1][i],state->x[3][i],state->x[5][i],state->x[7][i]); - SWAP4(state->x[1][i]); SWAP4(state->x[3][i]); SWAP4(state->x[5][i]); SWAP4(state->x[7][i]); - } + /*round 7*roundnumber+2: Sbox, MDS and Swapping layers*/ + for(i = 0; i < 2; i++) + { + SS(state->x[0][i], state->x[2][i], state->x[4][i], state->x[6][i], state->x[1][i], state->x[3][i], + state->x[5][i], state->x[7][i], ((uint64*)E8_bitslice_roundconstant[roundnumber + 2])[i], + ((uint64*)E8_bitslice_roundconstant[roundnumber + 2])[i + 2]); + L(state->x[0][i], state->x[2][i], state->x[4][i], state->x[6][i], state->x[1][i], state->x[3][i], + state->x[5][i], state->x[7][i]); + SWAP4(state->x[1][i]); + SWAP4(state->x[3][i]); + SWAP4(state->x[5][i]); + SWAP4(state->x[7][i]); + } - /*round 7*roundnumber+3: Sbox, MDS and Swapping layers*/ - for (i = 0; i < 2; i++) { - SS(state->x[0][i],state->x[2][i],state->x[4][i],state->x[6][i],state->x[1][i],state->x[3][i],state->x[5][i],state->x[7][i],((uint64*)E8_bitslice_roundconstant[roundnumber+3])[i],((uint64*)E8_bitslice_roundconstant[roundnumber+3])[i+2] ); - L(state->x[0][i],state->x[2][i],state->x[4][i],state->x[6][i],state->x[1][i],state->x[3][i],state->x[5][i],state->x[7][i]); - SWAP8(state->x[1][i]); SWAP8(state->x[3][i]); SWAP8(state->x[5][i]); SWAP8(state->x[7][i]); - } + /*round 7*roundnumber+3: Sbox, MDS and Swapping layers*/ + for(i = 0; i < 2; i++) + { + SS(state->x[0][i], state->x[2][i], state->x[4][i], state->x[6][i], state->x[1][i], state->x[3][i], + state->x[5][i], state->x[7][i], ((uint64*)E8_bitslice_roundconstant[roundnumber + 3])[i], + ((uint64*)E8_bitslice_roundconstant[roundnumber + 3])[i + 2]); + L(state->x[0][i], state->x[2][i], state->x[4][i], state->x[6][i], state->x[1][i], state->x[3][i], + state->x[5][i], state->x[7][i]); + SWAP8(state->x[1][i]); + SWAP8(state->x[3][i]); + SWAP8(state->x[5][i]); + SWAP8(state->x[7][i]); + } - /*round 7*roundnumber+4: Sbox, MDS and Swapping layers*/ - for (i = 0; i < 2; i++) { - SS(state->x[0][i],state->x[2][i],state->x[4][i],state->x[6][i],state->x[1][i],state->x[3][i],state->x[5][i],state->x[7][i],((uint64*)E8_bitslice_roundconstant[roundnumber+4])[i],((uint64*)E8_bitslice_roundconstant[roundnumber+4])[i+2] ); - L(state->x[0][i],state->x[2][i],state->x[4][i],state->x[6][i],state->x[1][i],state->x[3][i],state->x[5][i],state->x[7][i]); - SWAP16(state->x[1][i]); SWAP16(state->x[3][i]); SWAP16(state->x[5][i]); SWAP16(state->x[7][i]); - } + /*round 7*roundnumber+4: Sbox, MDS and Swapping layers*/ + for(i = 0; i < 2; i++) + { + SS(state->x[0][i], state->x[2][i], state->x[4][i], state->x[6][i], state->x[1][i], state->x[3][i], + state->x[5][i], state->x[7][i], ((uint64*)E8_bitslice_roundconstant[roundnumber + 4])[i], + ((uint64*)E8_bitslice_roundconstant[roundnumber + 4])[i + 2]); + L(state->x[0][i], state->x[2][i], state->x[4][i], state->x[6][i], state->x[1][i], state->x[3][i], + state->x[5][i], state->x[7][i]); + SWAP16(state->x[1][i]); + SWAP16(state->x[3][i]); + SWAP16(state->x[5][i]); + SWAP16(state->x[7][i]); + } - /*round 7*roundnumber+5: Sbox, MDS and Swapping layers*/ - for (i = 0; i < 2; i++) { - SS(state->x[0][i],state->x[2][i],state->x[4][i],state->x[6][i],state->x[1][i],state->x[3][i],state->x[5][i],state->x[7][i],((uint64*)E8_bitslice_roundconstant[roundnumber+5])[i],((uint64*)E8_bitslice_roundconstant[roundnumber+5])[i+2] ); - L(state->x[0][i],state->x[2][i],state->x[4][i],state->x[6][i],state->x[1][i],state->x[3][i],state->x[5][i],state->x[7][i]); - SWAP32(state->x[1][i]); SWAP32(state->x[3][i]); SWAP32(state->x[5][i]); SWAP32(state->x[7][i]); - } + /*round 7*roundnumber+5: Sbox, MDS and Swapping layers*/ + for(i = 0; i < 2; i++) + { + SS(state->x[0][i], state->x[2][i], state->x[4][i], state->x[6][i], state->x[1][i], state->x[3][i], + state->x[5][i], state->x[7][i], ((uint64*)E8_bitslice_roundconstant[roundnumber + 5])[i], + ((uint64*)E8_bitslice_roundconstant[roundnumber + 5])[i + 2]); + L(state->x[0][i], state->x[2][i], state->x[4][i], state->x[6][i], state->x[1][i], state->x[3][i], + state->x[5][i], state->x[7][i]); + SWAP32(state->x[1][i]); + SWAP32(state->x[3][i]); + SWAP32(state->x[5][i]); + SWAP32(state->x[7][i]); + } - /*round 7*roundnumber+6: Sbox and MDS layers*/ - for (i = 0; i < 2; i++) { - SS(state->x[0][i],state->x[2][i],state->x[4][i],state->x[6][i],state->x[1][i],state->x[3][i],state->x[5][i],state->x[7][i],((uint64*)E8_bitslice_roundconstant[roundnumber+6])[i],((uint64*)E8_bitslice_roundconstant[roundnumber+6])[i+2] ); - L(state->x[0][i],state->x[2][i],state->x[4][i],state->x[6][i],state->x[1][i],state->x[3][i],state->x[5][i],state->x[7][i]); - } - /*round 7*roundnumber+6: swapping layer*/ - for (i = 1; i < 8; i = i+2) { - temp0 = state->x[i][0]; state->x[i][0] = state->x[i][1]; state->x[i][1] = temp0; - } - } + /*round 7*roundnumber+6: Sbox and MDS layers*/ + for(i = 0; i < 2; i++) + { + SS(state->x[0][i], state->x[2][i], state->x[4][i], state->x[6][i], state->x[1][i], state->x[3][i], + state->x[5][i], state->x[7][i], ((uint64*)E8_bitslice_roundconstant[roundnumber + 6])[i], + ((uint64*)E8_bitslice_roundconstant[roundnumber + 6])[i + 2]); + L(state->x[0][i], state->x[2][i], state->x[4][i], state->x[6][i], state->x[1][i], state->x[3][i], + state->x[5][i], state->x[7][i]); + } + /*round 7*roundnumber+6: swapping layer*/ + for(i = 1; i < 8; i = i + 2) + { + temp0 = state->x[i][0]; + state->x[i][0] = state->x[i][1]; + state->x[i][1] = temp0; + } + } } /*The compression function F8 */ -static void F8(hashState *state) +static void F8(hashState* state) { - uint64 i; + uint64 i; - /*xor the 512-bit message with the fist half of the 1024-bit hash state*/ - for (i = 0; i < 8; i++) state->x[i >> 1][i & 1] ^= ((uint64*)state->buffer)[i]; + /*xor the 512-bit message with the fist half of the 1024-bit hash state*/ + for(i = 0; i < 8; i++) + { + state->x[i >> 1][i & 1] ^= ((uint64*)state->buffer)[i]; + } - /*the bijective function E8 */ - E8(state); + /*the bijective function E8 */ + E8(state); - /*xor the 512-bit message with the second half of the 1024-bit hash state*/ - for (i = 0; i < 8; i++) state->x[(8+i) >> 1][(8+i) & 1] ^= ((uint64*)state->buffer)[i]; + /*xor the 512-bit message with the second half of the 1024-bit hash state*/ + for(i = 0; i < 8; i++) + { + state->x[(8 + i) >> 1][(8 + i) & 1] ^= ((uint64*)state->buffer)[i]; + } } /*before hashing a message, initialize the hash state as H0 */ -static HashReturn Init(hashState *state, int hashbitlen) +static HashReturn Init(hashState* state, int hashbitlen) { - state->databitlen = 0; - state->datasize_in_buffer = 0; + state->databitlen = 0; + state->datasize_in_buffer = 0; - /*initialize the initial hash value of JH*/ - state->hashbitlen = hashbitlen; + /*initialize the initial hash value of JH*/ + state->hashbitlen = hashbitlen; - /*load the intital hash value into state*/ - switch (hashbitlen) - { - case 224: memcpy(state->x,JH224_H0,128); break; - case 256: memcpy(state->x,JH256_H0,128); break; - case 384: memcpy(state->x,JH384_H0,128); break; - case 512: memcpy(state->x,JH512_H0,128); break; - } + /*load the intital hash value into state*/ + switch(hashbitlen) + { + case 224: + memcpy(state->x, JH224_H0, 128); + break; + case 256: + memcpy(state->x, JH256_H0, 128); + break; + case 384: + memcpy(state->x, JH384_H0, 128); + break; + case 512: + memcpy(state->x, JH512_H0, 128); + break; + } - return(SUCCESS); + return(SUCCESS); } /*hash each 512-bit message block, except the last partial block*/ -static HashReturn Update(hashState *state, const BitSequence *data, DataLength databitlen) +static HashReturn Update(hashState* state, const BitSequence* data, DataLength databitlen) { - DataLength index; /*the starting address of the data to be compressed*/ + DataLength index; /*the starting address of the data to be compressed*/ - state->databitlen += databitlen; - index = 0; + state->databitlen += databitlen; + index = 0; - /*if there is remaining data in the buffer, fill it to a full message block first*/ - /*we assume that the size of the data in the buffer is the multiple of 8 bits if it is not at the end of a message*/ + /*if there is remaining data in the buffer, fill it to a full message block first*/ + /*we assume that the size of the data in the buffer is the multiple of 8 bits if it is not at the end of a message*/ - /*There is data in the buffer, but the incoming data is insufficient for a full block*/ - if ( (state->datasize_in_buffer > 0 ) && (( state->datasize_in_buffer + databitlen) < 512) ) { - if ( (databitlen & 7) == 0 ) { - memcpy(state->buffer + (state->datasize_in_buffer >> 3), data, 64-(state->datasize_in_buffer >> 3)) ; - } - else memcpy(state->buffer + (state->datasize_in_buffer >> 3), data, 64-(state->datasize_in_buffer >> 3)+1) ; - state->datasize_in_buffer += databitlen; - databitlen = 0; - } + /*There is data in the buffer, but the incoming data is insufficient for a full block*/ + if((state->datasize_in_buffer > 0) && ((state->datasize_in_buffer + databitlen) < 512)) + { + if((databitlen & 7) == 0) + { + memcpy(state->buffer + (state->datasize_in_buffer >> 3), data, 64 - (state->datasize_in_buffer >> 3)) ; + } + else + { + memcpy(state->buffer + (state->datasize_in_buffer >> 3), data, 64 - (state->datasize_in_buffer >> 3) + 1) ; + } + state->datasize_in_buffer += databitlen; + databitlen = 0; + } - /*There is data in the buffer, and the incoming data is sufficient for a full block*/ - if ( (state->datasize_in_buffer > 0 ) && (( state->datasize_in_buffer + databitlen) >= 512) ) { - memcpy( state->buffer + (state->datasize_in_buffer >> 3), data, 64-(state->datasize_in_buffer >> 3) ) ; - index = 64-(state->datasize_in_buffer >> 3); - databitlen = databitlen - (512 - state->datasize_in_buffer); - F8(state); - state->datasize_in_buffer = 0; - } + /*There is data in the buffer, and the incoming data is sufficient for a full block*/ + if((state->datasize_in_buffer > 0) && ((state->datasize_in_buffer + databitlen) >= 512)) + { + memcpy(state->buffer + (state->datasize_in_buffer >> 3), data, 64 - (state->datasize_in_buffer >> 3)) ; + index = 64 - (state->datasize_in_buffer >> 3); + databitlen = databitlen - (512 - state->datasize_in_buffer); + F8(state); + state->datasize_in_buffer = 0; + } - /*hash the remaining full message blocks*/ - for ( ; databitlen >= 512; index = index+64, databitlen = databitlen - 512) { - memcpy(state->buffer, data+index, 64); - F8(state); - } + /*hash the remaining full message blocks*/ + for(; databitlen >= 512; index = index + 64, databitlen = databitlen - 512) + { + memcpy(state->buffer, data + index, 64); + F8(state); + } - /*store the partial block into buffer, assume that -- if part of the last byte is not part of the message, then that part consists of 0 bits*/ - if ( databitlen > 0) { - if ((databitlen & 7) == 0) - memcpy(state->buffer, data+index, (databitlen & 0x1ff) >> 3); - else - memcpy(state->buffer, data+index, ((databitlen & 0x1ff) >> 3)+1); - state->datasize_in_buffer = databitlen; - } + /*store the partial block into buffer, assume that -- if part of the last byte is not part of the message, then that part consists of 0 bits*/ + if(databitlen > 0) + { + if((databitlen & 7) == 0) + { + memcpy(state->buffer, data + index, (databitlen & 0x1ff) >> 3); + } + else + { + memcpy(state->buffer, data + index, ((databitlen & 0x1ff) >> 3) + 1); + } + state->datasize_in_buffer = databitlen; + } - return(SUCCESS); + return(SUCCESS); } /*pad the message, process the padded block(s), truncate the hash value H to obtain the message digest*/ -static HashReturn Final(hashState *state, BitSequence *hashval) +static HashReturn Final(hashState* state, BitSequence* hashval) { - unsigned int i; + unsigned int i; - if ( (state->databitlen & 0x1ff) == 0 ) { - /*pad the message when databitlen is multiple of 512 bits, then process the padded block*/ - memset(state->buffer, 0, 64); - state->buffer[0] = 0x80; - state->buffer[63] = state->databitlen & 0xff; - state->buffer[62] = (state->databitlen >> 8) & 0xff; - state->buffer[61] = (state->databitlen >> 16) & 0xff; - state->buffer[60] = (state->databitlen >> 24) & 0xff; - state->buffer[59] = (state->databitlen >> 32) & 0xff; - state->buffer[58] = (state->databitlen >> 40) & 0xff; - state->buffer[57] = (state->databitlen >> 48) & 0xff; - state->buffer[56] = (state->databitlen >> 56) & 0xff; - F8(state); - } - else { - /*set the rest of the bytes in the buffer to 0*/ - if ( (state->datasize_in_buffer & 7) == 0) - for (i = (state->databitlen & 0x1ff) >> 3; i < 64; i++) state->buffer[i] = 0; - else - for (i = ((state->databitlen & 0x1ff) >> 3)+1; i < 64; i++) state->buffer[i] = 0; + if((state->databitlen & 0x1ff) == 0) + { + /*pad the message when databitlen is multiple of 512 bits, then process the padded block*/ + memset(state->buffer, 0, 64); + state->buffer[0] = 0x80; + state->buffer[63] = state->databitlen & 0xff; + state->buffer[62] = (state->databitlen >> 8) & 0xff; + state->buffer[61] = (state->databitlen >> 16) & 0xff; + state->buffer[60] = (state->databitlen >> 24) & 0xff; + state->buffer[59] = (state->databitlen >> 32) & 0xff; + state->buffer[58] = (state->databitlen >> 40) & 0xff; + state->buffer[57] = (state->databitlen >> 48) & 0xff; + state->buffer[56] = (state->databitlen >> 56) & 0xff; + F8(state); + } + else + { + /*set the rest of the bytes in the buffer to 0*/ + if((state->datasize_in_buffer & 7) == 0) + for(i = (state->databitlen & 0x1ff) >> 3; i < 64; i++) + { + state->buffer[i] = 0; + } + else + for(i = ((state->databitlen & 0x1ff) >> 3) + 1; i < 64; i++) + { + state->buffer[i] = 0; + } - /*pad and process the partial block when databitlen is not multiple of 512 bits, then hash the padded blocks*/ - state->buffer[((state->databitlen & 0x1ff) >> 3)] |= 1 << (7- (state->databitlen & 7)); + /*pad and process the partial block when databitlen is not multiple of 512 bits, then hash the padded blocks*/ + state->buffer[((state->databitlen & 0x1ff) >> 3)] |= 1 << (7 - (state->databitlen & 7)); - F8(state); - memset(state->buffer, 0, 64); - state->buffer[63] = state->databitlen & 0xff; - state->buffer[62] = (state->databitlen >> 8) & 0xff; - state->buffer[61] = (state->databitlen >> 16) & 0xff; - state->buffer[60] = (state->databitlen >> 24) & 0xff; - state->buffer[59] = (state->databitlen >> 32) & 0xff; - state->buffer[58] = (state->databitlen >> 40) & 0xff; - state->buffer[57] = (state->databitlen >> 48) & 0xff; - state->buffer[56] = (state->databitlen >> 56) & 0xff; - F8(state); - } + F8(state); + memset(state->buffer, 0, 64); + state->buffer[63] = state->databitlen & 0xff; + state->buffer[62] = (state->databitlen >> 8) & 0xff; + state->buffer[61] = (state->databitlen >> 16) & 0xff; + state->buffer[60] = (state->databitlen >> 24) & 0xff; + state->buffer[59] = (state->databitlen >> 32) & 0xff; + state->buffer[58] = (state->databitlen >> 40) & 0xff; + state->buffer[57] = (state->databitlen >> 48) & 0xff; + state->buffer[56] = (state->databitlen >> 56) & 0xff; + F8(state); + } - /*truncating the final hash value to generate the message digest*/ - switch(state->hashbitlen) { - case 224: memcpy(hashval,(unsigned char*)state->x+64+36,28); break; - case 256: memcpy(hashval,(unsigned char*)state->x+64+32,32); break; - case 384: memcpy(hashval,(unsigned char*)state->x+64+16,48); break; - case 512: memcpy(hashval,(unsigned char*)state->x+64,64); break; - } + /*truncating the final hash value to generate the message digest*/ + switch(state->hashbitlen) + { + case 224: + memcpy(hashval, (unsigned char*)state->x + 64 + 36, 28); + break; + case 256: + memcpy(hashval, (unsigned char*)state->x + 64 + 32, 32); + break; + case 384: + memcpy(hashval, (unsigned char*)state->x + 64 + 16, 48); + break; + case 512: + memcpy(hashval, (unsigned char*)state->x + 64, 64); + break; + } - return(SUCCESS); + return(SUCCESS); } /* hash a message, three inputs: message digest size in bits (hashbitlen); message (data); message length in bits (databitlen) one output: message digest (hashval) */ -HashReturn jh_hash(int hashbitlen, const BitSequence *data,DataLength databitlen, BitSequence *hashval) +HashReturn jh_hash(int hashbitlen, const BitSequence* data, DataLength databitlen, BitSequence* hashval) { - hashState state; + hashState state; - if ( hashbitlen == 224 || hashbitlen == 256 || hashbitlen == 384 || hashbitlen == 512 ) { - Init(&state, hashbitlen); - Update(&state, data, databitlen); - Final(&state, hashval); - return SUCCESS; - } - else - return(BAD_HASHLEN); + if(hashbitlen == 224 || hashbitlen == 256 || hashbitlen == 384 || hashbitlen == 512) + { + Init(&state, hashbitlen); + Update(&state, data, databitlen); + Final(&state, hashval); + return SUCCESS; + } + else + { + return(BAD_HASHLEN); + } } diff --git a/src/crypto/c_jh.h b/src/crypto/c_jh.h index d10d40fe..34d30e6b 100644 --- a/src/crypto/c_jh.h +++ b/src/crypto/c_jh.h @@ -16,4 +16,4 @@ #include "hash.h" -HashReturn jh_hash(int hashbitlen, const BitSequence *data, DataLength databitlen, BitSequence *hashval); +HashReturn jh_hash(int hashbitlen, const BitSequence* data, DataLength databitlen, BitSequence* hashval); diff --git a/src/crypto/c_keccak.c b/src/crypto/c_keccak.c index 997db241..19579c64 100644 --- a/src/crypto/c_keccak.c +++ b/src/crypto/c_keccak.c @@ -12,165 +12,172 @@ #define ROTL64(x, y) (((x) << (y)) | ((x) >> (64 - (y)))) #endif -const uint64_t keccakf_rndc[24] = +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 + 0x0000000000000001, 0x0000000000008082, 0x800000000000808a, + 0x8000000080008000, 0x000000000000808b, 0x0000000080000001, + 0x8000000080008081, 0x8000000000008009, 0x000000000000008a, + 0x0000000000000088, 0x0000000080008009, 0x000000008000000a, + 0x000000008000808b, 0x800000000000008b, 0x8000000000008089, + 0x8000000000008003, 0x8000000000008002, 0x8000000000000080, + 0x000000000000800a, 0x800000008000000a, 0x8000000080008081, + 0x8000000000008080, 0x0000000080000001, 0x8000000080008008 }; // 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]; + int i, j, round; + uint64_t t, bc[5]; - for (round = 0; round < rounds; ++round) { + 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]; + // 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; - } + 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]; - st[ 1] = ROTL64(st[ 6], 44); - st[ 6] = ROTL64(st[ 9], 20); - st[ 9] = ROTL64(st[22], 61); - st[22] = ROTL64(st[14], 39); - st[14] = ROTL64(st[20], 18); - st[20] = ROTL64(st[ 2], 62); - st[ 2] = ROTL64(st[12], 43); - st[12] = ROTL64(st[13], 25); - st[13] = ROTL64(st[19], 8); - st[19] = ROTL64(st[23], 56); - st[23] = ROTL64(st[15], 41); - st[15] = ROTL64(st[ 4], 27); - st[ 4] = ROTL64(st[24], 14); - st[24] = ROTL64(st[21], 2); - st[21] = ROTL64(st[ 8], 55); - st[ 8] = ROTL64(st[16], 45); - st[16] = ROTL64(st[ 5], 36); - st[ 5] = ROTL64(st[ 3], 28); - st[ 3] = ROTL64(st[18], 21); - st[18] = ROTL64(st[17], 15); - st[17] = ROTL64(st[11], 10); - st[11] = ROTL64(st[ 7], 6); - st[ 7] = ROTL64(st[10], 3); - st[10] = ROTL64(t, 1); + // Rho Pi + t = st[1]; + st[ 1] = ROTL64(st[ 6], 44); + st[ 6] = ROTL64(st[ 9], 20); + st[ 9] = ROTL64(st[22], 61); + st[22] = ROTL64(st[14], 39); + st[14] = ROTL64(st[20], 18); + st[20] = ROTL64(st[ 2], 62); + st[ 2] = ROTL64(st[12], 43); + st[12] = ROTL64(st[13], 25); + st[13] = ROTL64(st[19], 8); + st[19] = ROTL64(st[23], 56); + st[23] = ROTL64(st[15], 41); + st[15] = ROTL64(st[ 4], 27); + st[ 4] = ROTL64(st[24], 14); + st[24] = ROTL64(st[21], 2); + st[21] = ROTL64(st[ 8], 55); + st[ 8] = ROTL64(st[16], 45); + st[16] = ROTL64(st[ 5], 36); + st[ 5] = ROTL64(st[ 3], 28); + st[ 3] = ROTL64(st[18], 21); + st[18] = ROTL64(st[17], 15); + st[17] = ROTL64(st[11], 10); + st[11] = ROTL64(st[ 7], 6); + st[ 7] = ROTL64(st[10], 3); + st[10] = ROTL64(t, 1); - // Chi - // unrolled loop, where only last iteration is different - j = 0; - bc[0] = st[j ]; - bc[1] = st[j + 1]; + // Chi + // unrolled loop, where only last iteration is different + j = 0; + bc[0] = st[j ]; + bc[1] = st[j + 1]; - st[j ] ^= (~st[j + 1]) & st[j + 2]; - st[j + 1] ^= (~st[j + 2]) & st[j + 3]; - st[j + 2] ^= (~st[j + 3]) & st[j + 4]; - st[j + 3] ^= (~st[j + 4]) & bc[0]; - st[j + 4] ^= (~bc[0]) & bc[1]; + st[j ] ^= (~st[j + 1]) & st[j + 2]; + st[j + 1] ^= (~st[j + 2]) & st[j + 3]; + st[j + 2] ^= (~st[j + 3]) & st[j + 4]; + st[j + 3] ^= (~st[j + 4]) & bc[0]; + st[j + 4] ^= (~bc[0]) & bc[1]; - j = 5; - bc[0] = st[j ]; - bc[1] = st[j + 1]; + j = 5; + bc[0] = st[j ]; + bc[1] = st[j + 1]; - st[j ] ^= (~st[j + 1]) & st[j + 2]; - st[j + 1] ^= (~st[j + 2]) & st[j + 3]; - st[j + 2] ^= (~st[j + 3]) & st[j + 4]; - st[j + 3] ^= (~st[j + 4]) & bc[0]; - st[j + 4] ^= (~bc[0]) & bc[1]; + st[j ] ^= (~st[j + 1]) & st[j + 2]; + st[j + 1] ^= (~st[j + 2]) & st[j + 3]; + st[j + 2] ^= (~st[j + 3]) & st[j + 4]; + st[j + 3] ^= (~st[j + 4]) & bc[0]; + st[j + 4] ^= (~bc[0]) & bc[1]; - j = 10; - bc[0] = st[j ]; - bc[1] = st[j + 1]; + j = 10; + bc[0] = st[j ]; + bc[1] = st[j + 1]; - st[j ] ^= (~st[j + 1]) & st[j + 2]; - st[j + 1] ^= (~st[j + 2]) & st[j + 3]; - st[j + 2] ^= (~st[j + 3]) & st[j + 4]; - st[j + 3] ^= (~st[j + 4]) & bc[0]; - st[j + 4] ^= (~bc[0]) & bc[1]; + st[j ] ^= (~st[j + 1]) & st[j + 2]; + st[j + 1] ^= (~st[j + 2]) & st[j + 3]; + st[j + 2] ^= (~st[j + 3]) & st[j + 4]; + st[j + 3] ^= (~st[j + 4]) & bc[0]; + st[j + 4] ^= (~bc[0]) & bc[1]; - j = 15; - bc[0] = st[j ]; - bc[1] = st[j + 1]; + j = 15; + bc[0] = st[j ]; + bc[1] = st[j + 1]; - st[j ] ^= (~st[j + 1]) & st[j + 2]; - st[j + 1] ^= (~st[j + 2]) & st[j + 3]; - st[j + 2] ^= (~st[j + 3]) & st[j + 4]; - st[j + 3] ^= (~st[j + 4]) & bc[0]; - st[j + 4] ^= (~bc[0]) & bc[1]; + st[j ] ^= (~st[j + 1]) & st[j + 2]; + st[j + 1] ^= (~st[j + 2]) & st[j + 3]; + st[j + 2] ^= (~st[j + 3]) & st[j + 4]; + st[j + 3] ^= (~st[j + 4]) & bc[0]; + st[j + 4] ^= (~bc[0]) & bc[1]; - j = 20; - bc[0] = st[j ]; - bc[1] = st[j + 1]; - bc[2] = st[j + 2]; - bc[3] = st[j + 3]; - bc[4] = st[j + 4]; + j = 20; + 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]; - } + 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) +void keccak(const uint8_t* in, int inlen, uint8_t* md, int mdlen) { - state_t st; - uint8_t temp[144]; - int i, rsiz, rsizw; + 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)); + rsiz = sizeof(state_t) == mdlen ? HASH_DATA_AREA : 200 - 2 * mdlen; + rsizw = rsiz / 8; - 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; + memset(st, 0, sizeof(st)); - for (i = 0; i < rsizw; i++) - st[i] ^= ((uint64_t *) temp)[i]; + for(; inlen >= rsiz; inlen -= rsiz, in += rsiz) + { + for(i = 0; i < rsizw; i++) + { + st[i] ^= ((uint64_t*) in)[i]; + } + keccakf(st, KECCAK_ROUNDS); + } - 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; - memcpy(md, st, mdlen); + for(i = 0; i < rsizw; i++) + { + st[i] ^= ((uint64_t*) temp)[i]; + } + + keccakf(st, KECCAK_ROUNDS); + + memcpy(md, st, mdlen); } -void keccak1600(const uint8_t *in, int inlen, uint8_t *md) +void keccak1600(const uint8_t* in, int inlen, uint8_t* md) { - keccak(in, inlen, md, sizeof(state_t)); + keccak(in, inlen, md, sizeof(state_t)); } diff --git a/src/crypto/c_keccak.h b/src/crypto/c_keccak.h index 4f7f8572..b7a26065 100644 --- a/src/crypto/c_keccak.h +++ b/src/crypto/c_keccak.h @@ -16,11 +16,11 @@ #endif // compute a keccak hash (md) of given byte length from "in" -int keccak(const uint8_t *in, int inlen, uint8_t *md, int mdlen); +int keccak(const uint8_t* in, int inlen, uint8_t* md, int mdlen); // update the state void keccakf(uint64_t st[25], int norounds); -void keccak1600(const uint8_t *in, int inlen, uint8_t *md); +void keccak1600(const uint8_t* in, int inlen, uint8_t* md); #endif diff --git a/src/crypto/c_skein.c b/src/crypto/c_skein.c index 994e4d46..48efe4a7 100644 --- a/src/crypto/c_skein.c +++ b/src/crypto/c_skein.c @@ -5,7 +5,7 @@ ** Source code author: Doug Whiting, 2008. ** ** This algorithm and source code is released to the public domain. -** +** ************************************************************************/ #define SKEIN_PORT_CODE /* instantiate any code in skein_port.h */ @@ -34,22 +34,22 @@ typedef struct { - size_t hashBitLen; /* size of hash result, in bits */ - size_t bCnt; /* current byte count in buffer b[] */ - u64b_t T[SKEIN_MODIFIER_WORDS]; /* tweak words: T[0]=byte cnt, T[1]=flags */ + size_t hashBitLen; /* size of hash result, in bits */ + size_t bCnt; /* current byte count in buffer b[] */ + u64b_t T[SKEIN_MODIFIER_WORDS]; /* tweak words: T[0]=byte cnt, T[1]=flags */ } Skein_Ctxt_Hdr_t; typedef struct /* 512-bit Skein hash context structure */ { - Skein_Ctxt_Hdr_t h; /* common header context variables */ - u64b_t X[SKEIN_512_STATE_WORDS]; /* chaining variables */ - u08b_t b[SKEIN_512_BLOCK_BYTES]; /* partial block buffer (8-byte aligned) */ + Skein_Ctxt_Hdr_t h; /* common header context variables */ + u64b_t X[SKEIN_512_STATE_WORDS]; /* chaining variables */ + u08b_t b[SKEIN_512_BLOCK_BYTES]; /* partial block buffer (8-byte aligned) */ } Skein_512_Ctxt_t; /* Skein APIs for (incremental) "straight hashing" */ -static int Skein_512_Init (Skein_512_Ctxt_t *ctx, size_t hashBitLen); -static int Skein_512_Update(Skein_512_Ctxt_t *ctx, const u08b_t *msg, size_t msgByteCnt); -static int Skein_512_Final (Skein_512_Ctxt_t *ctx, u08b_t * hashVal); +static int Skein_512_Init(Skein_512_Ctxt_t* ctx, size_t hashBitLen); +static int Skein_512_Update(Skein_512_Ctxt_t* ctx, const u08b_t* msg, size_t msgByteCnt); +static int Skein_512_Final(Skein_512_Ctxt_t* ctx, u08b_t* hashVal); #ifndef SKEIN_TREE_HASH #define SKEIN_TREE_HASH (1) @@ -57,7 +57,7 @@ static int Skein_512_Final (Skein_512_Ctxt_t *ctx, u08b_t * hashVal); /***************************************************************** ** "Internal" Skein definitions -** -- not needed for sequential hashing API, but will be +** -- not needed for sequential hashing API, but will be ** helpful for other uses of Skein (e.g., tree hash mode). ** -- included here so that they can be shared between ** reference and optimized code. @@ -128,9 +128,9 @@ static int Skein_512_Final (Skein_512_Ctxt_t *ctx, u08b_t * hashVal); #define SKEIN_CFG_TREE_MAX_LEVEL_MSK (((u64b_t) 0xFF) << SKEIN_CFG_TREE_MAX_LEVEL_POS) #define SKEIN_CFG_TREE_INFO(leaf,node,maxLvl) \ - ( (((u64b_t)(leaf )) << SKEIN_CFG_TREE_LEAF_SIZE_POS) | \ - (((u64b_t)(node )) << SKEIN_CFG_TREE_NODE_SIZE_POS) | \ - (((u64b_t)(maxLvl)) << SKEIN_CFG_TREE_MAX_LEVEL_POS) ) + ( (((u64b_t)(leaf )) << SKEIN_CFG_TREE_LEAF_SIZE_POS) | \ + (((u64b_t)(node )) << SKEIN_CFG_TREE_NODE_SIZE_POS) | \ + (((u64b_t)(maxLvl)) << SKEIN_CFG_TREE_MAX_LEVEL_POS) ) #define SKEIN_CFG_TREE_INFO_SEQUENTIAL SKEIN_CFG_TREE_INFO(0,0,0) /* use as treeInfo in InitExt() call for sequential processing */ @@ -148,17 +148,17 @@ static int Skein_512_Final (Skein_512_Ctxt_t *ctx, u08b_t * hashVal); /* set both tweak words at once */ #define Skein_Set_T0_T1(ctxPtr,T0,T1) \ -{ \ - Skein_Set_T0(ctxPtr,(T0)); \ - Skein_Set_T1(ctxPtr,(T1)); \ -} + { \ + Skein_Set_T0(ctxPtr,(T0)); \ + Skein_Set_T1(ctxPtr,(T1)); \ + } #define Skein_Set_Type(ctxPtr,BLK_TYPE) \ - Skein_Set_T1(ctxPtr,SKEIN_T1_BLK_TYPE_##BLK_TYPE) + Skein_Set_T1(ctxPtr,SKEIN_T1_BLK_TYPE_##BLK_TYPE) /* set up for starting with a new type: h.T[0]=0; h.T[1] = NEW_TYPE; h.bCnt=0; */ #define Skein_Start_New_Type(ctxPtr,BLK_TYPE) \ -{ Skein_Set_T0_T1(ctxPtr,0,SKEIN_T1_FLAG_FIRST | SKEIN_T1_BLK_TYPE_##BLK_TYPE); (ctxPtr)->h.bCnt=0; } + { Skein_Set_T0_T1(ctxPtr,0,SKEIN_T1_FLAG_FIRST | SKEIN_T1_BLK_TYPE_##BLK_TYPE); (ctxPtr)->h.bCnt=0; } #define Skein_Clear_First_Flag(hdr) { (hdr).T[1] &= ~SKEIN_T1_FLAG_FIRST; } #define Skein_Set_Bit_Pad_Flag(hdr) { (hdr).T[1] |= SKEIN_T1_FLAG_BIT_PAD; } @@ -179,11 +179,11 @@ static int Skein_512_Final (Skein_512_Ctxt_t *ctx, u08b_t * hashVal); #define Skein_Assert(x,retCode)/* default: ignore all Asserts, for performance */ #define Skein_assert(x) #elif defined(SKEIN_ASSERT) -#include -#define Skein_Assert(x,retCode) assert(x) -#define Skein_assert(x) assert(x) +#include +#define Skein_Assert(x,retCode) assert(x) +#define Skein_assert(x) assert(x) #else -#include +#include #define Skein_Assert(x,retCode) { if (!(x)) return retCode; } /* caller error */ #define Skein_assert(x) assert(x) /* internal error */ #endif @@ -191,17 +191,17 @@ static int Skein_512_Final (Skein_512_Ctxt_t *ctx, u08b_t * hashVal); /***************************************************************** ** Skein block function constants (shared across Ref and Opt code) ******************************************************************/ -enum -{ - /* Skein_512 round rotation constants */ - R_512_0_0=46, R_512_0_1=36, R_512_0_2=19, R_512_0_3=37, - R_512_1_0=33, R_512_1_1=27, R_512_1_2=14, R_512_1_3=42, - R_512_2_0=17, R_512_2_1=49, R_512_2_2=36, R_512_2_3=39, - R_512_3_0=44, R_512_3_1= 9, R_512_3_2=54, R_512_3_3=56, - R_512_4_0=39, R_512_4_1=30, R_512_4_2=34, R_512_4_3=24, - R_512_5_0=13, R_512_5_1=50, R_512_5_2=10, R_512_5_3=17, - R_512_6_0=25, R_512_6_1=29, R_512_6_2=39, R_512_6_3=43, - R_512_7_0= 8, R_512_7_1=35, R_512_7_2=56, R_512_7_3=22, +enum +{ + /* Skein_512 round rotation constants */ + R_512_0_0 = 46, R_512_0_1 = 36, R_512_0_2 = 19, R_512_0_3 = 37, + R_512_1_0 = 33, R_512_1_1 = 27, R_512_1_2 = 14, R_512_1_3 = 42, + R_512_2_0 = 17, R_512_2_1 = 49, R_512_2_2 = 36, R_512_2_3 = 39, + R_512_3_0 = 44, R_512_3_1 = 9, R_512_3_2 = 54, R_512_3_3 = 56, + R_512_4_0 = 39, R_512_4_1 = 30, R_512_4_2 = 34, R_512_4_3 = 24, + R_512_5_0 = 13, R_512_5_1 = 50, R_512_5_2 = 10, R_512_5_3 = 17, + R_512_6_0 = 25, R_512_6_1 = 29, R_512_6_2 = 39, R_512_6_3 = 43, + R_512_7_0 = 8, R_512_7_1 = 35, R_512_7_2 = 56, R_512_7_3 = 22, }; #ifndef SKEIN_ROUNDS @@ -229,16 +229,16 @@ enum /* blkSize = 512 bits. hashSize = 256 bits */ const u64b_t SKEIN_512_IV_256[] = - { - MK_64(0xCCD044A1,0x2FDB3E13), - MK_64(0xE8359030,0x1A79A9EB), - MK_64(0x55AEA061,0x4F816E6F), - MK_64(0x2A2767A4,0xAE9B94DB), - MK_64(0xEC06025E,0x74DD7683), - MK_64(0xE7A436CD,0xC4746251), - MK_64(0xC36FBAF9,0x393AD185), - MK_64(0x3EEDBA18,0x33EDFC13) - }; +{ + MK_64(0xCCD044A1, 0x2FDB3E13), + MK_64(0xE8359030, 0x1A79A9EB), + MK_64(0x55AEA061, 0x4F816E6F), + MK_64(0x2A2767A4, 0xAE9B94DB), + MK_64(0xEC06025E, 0x74DD7683), + MK_64(0xE7A436CD, 0xC4746251), + MK_64(0xC36FBAF9, 0x393AD185), + MK_64(0x3EEDBA18, 0x33EDFC13) +}; #ifndef SKEIN_USE_ASM #define SKEIN_USE_ASM (0) /* default is all C code (no ASM) */ @@ -251,7 +251,7 @@ const u64b_t SKEIN_512_IV_256[] = #define BLK_BITS (WCNT*64) /* some useful definitions for code here */ #define KW_TWK_BASE (0) #define KW_KEY_BASE (3) -#define ks (kw + KW_KEY_BASE) +#define ks (kw + KW_KEY_BASE) #define ts (kw + KW_TWK_BASE) #ifdef SKEIN_DEBUG @@ -262,12 +262,14 @@ const u64b_t SKEIN_512_IV_256[] = /***************************** Skein_512 ******************************/ #if !(SKEIN_USE_ASM & 512) -static void Skein_512_Process_Block(Skein_512_Ctxt_t *ctx,const u08b_t *blkPtr,size_t blkCnt,size_t byteCntAdd) - { /* do it in C */ - enum - { - WCNT = SKEIN_512_STATE_WORDS - }; +static void Skein_512_Process_Block(Skein_512_Ctxt_t* ctx, const u08b_t* blkPtr, size_t blkCnt, + size_t byteCntAdd) +{ + /* do it in C */ + enum + { + WCNT = SKEIN_512_STATE_WORDS + }; #undef RCNT #define RCNT (SKEIN_512_ROUNDS_TOTAL/8) @@ -281,179 +283,186 @@ static void Skein_512_Process_Block(Skein_512_Ctxt_t *ctx,const u08b_t *blkPtr,s #if (RCNT % SKEIN_UNROLL_512) #error "Invalid SKEIN_UNROLL_512" /* sanity check on unroll count */ #endif - size_t r; - u64b_t kw[WCNT+4+RCNT*2]; /* key schedule words : chaining vars + tweak + "rotation"*/ + size_t r; + u64b_t kw[WCNT + 4 + RCNT * 2]; /* key schedule words : chaining vars + tweak + "rotation"*/ #else - u64b_t kw[WCNT+4]; /* key schedule words : chaining vars + tweak */ + u64b_t kw[WCNT + 4]; /* key schedule words : chaining vars + tweak */ #endif - u64b_t X0,X1,X2,X3,X4,X5,X6,X7; /* local copy of vars, for speed */ - u64b_t w [WCNT]; /* local copy of input block */ + u64b_t X0, X1, X2, X3, X4, X5, X6, X7; /* local copy of vars, for speed */ + u64b_t w [WCNT]; /* local copy of input block */ #ifdef SKEIN_DEBUG - const u64b_t *Xptr[8]; /* use for debugging (help compiler put Xn in registers) */ - Xptr[0] = &X0; Xptr[1] = &X1; Xptr[2] = &X2; Xptr[3] = &X3; - Xptr[4] = &X4; Xptr[5] = &X5; Xptr[6] = &X6; Xptr[7] = &X7; + const u64b_t* Xptr[8]; /* use for debugging (help compiler put Xn in registers) */ + Xptr[0] = &X0; + Xptr[1] = &X1; + Xptr[2] = &X2; + Xptr[3] = &X3; + Xptr[4] = &X4; + Xptr[5] = &X5; + Xptr[6] = &X6; + Xptr[7] = &X7; #endif - Skein_assert(blkCnt != 0); /* never call with blkCnt == 0! */ - ts[0] = ctx->h.T[0]; - ts[1] = ctx->h.T[1]; - do { - /* this implementation only supports 2**64 input bytes (no carry out here) */ - ts[0] += byteCntAdd; /* update processed length */ + Skein_assert(blkCnt != 0); /* never call with blkCnt == 0! */ + ts[0] = ctx->h.T[0]; + ts[1] = ctx->h.T[1]; + do + { + /* this implementation only supports 2**64 input bytes (no carry out here) */ + ts[0] += byteCntAdd; /* update processed length */ - /* precompute the key schedule for this block */ - ks[0] = ctx->X[0]; - ks[1] = ctx->X[1]; - ks[2] = ctx->X[2]; - ks[3] = ctx->X[3]; - ks[4] = ctx->X[4]; - ks[5] = ctx->X[5]; - ks[6] = ctx->X[6]; - ks[7] = ctx->X[7]; - ks[8] = ks[0] ^ ks[1] ^ ks[2] ^ ks[3] ^ - ks[4] ^ ks[5] ^ ks[6] ^ ks[7] ^ SKEIN_KS_PARITY; + /* precompute the key schedule for this block */ + ks[0] = ctx->X[0]; + ks[1] = ctx->X[1]; + ks[2] = ctx->X[2]; + ks[3] = ctx->X[3]; + ks[4] = ctx->X[4]; + ks[5] = ctx->X[5]; + ks[6] = ctx->X[6]; + ks[7] = ctx->X[7]; + ks[8] = ks[0] ^ ks[1] ^ ks[2] ^ ks[3] ^ + ks[4] ^ ks[5] ^ ks[6] ^ ks[7] ^ SKEIN_KS_PARITY; - ts[2] = ts[0] ^ ts[1]; + ts[2] = ts[0] ^ ts[1]; - Skein_Get64_LSB_First(w,blkPtr,WCNT); /* get input block in little-endian format */ - DebugSaveTweak(ctx); - Skein_Show_Block(BLK_BITS,&ctx->h,ctx->X,blkPtr,w,ks,ts); + Skein_Get64_LSB_First(w, blkPtr, WCNT); /* get input block in little-endian format */ + DebugSaveTweak(ctx); + Skein_Show_Block(BLK_BITS, &ctx->h, ctx->X, blkPtr, w, ks, ts); - X0 = w[0] + ks[0]; /* do the first full key injection */ - X1 = w[1] + ks[1]; - X2 = w[2] + ks[2]; - X3 = w[3] + ks[3]; - X4 = w[4] + ks[4]; - X5 = w[5] + ks[5] + ts[0]; - X6 = w[6] + ks[6] + ts[1]; - X7 = w[7] + ks[7]; + X0 = w[0] + ks[0]; /* do the first full key injection */ + X1 = w[1] + ks[1]; + X2 = w[2] + ks[2]; + X3 = w[3] + ks[3]; + X4 = w[4] + ks[4]; + X5 = w[5] + ks[5] + ts[0]; + X6 = w[6] + ks[6] + ts[1]; + X7 = w[7] + ks[7]; - blkPtr += SKEIN_512_BLOCK_BYTES; + blkPtr += SKEIN_512_BLOCK_BYTES; - Skein_Show_R_Ptr(BLK_BITS,&ctx->h,SKEIN_RND_KEY_INITIAL,Xptr); - /* run the rounds */ + Skein_Show_R_Ptr(BLK_BITS, &ctx->h, SKEIN_RND_KEY_INITIAL, Xptr); + /* run the rounds */ #define Round512(p0,p1,p2,p3,p4,p5,p6,p7,ROT,rNum) \ - X##p0 += X##p1; X##p1 = RotL_64(X##p1,ROT##_0); X##p1 ^= X##p0; \ - X##p2 += X##p3; X##p3 = RotL_64(X##p3,ROT##_1); X##p3 ^= X##p2; \ - X##p4 += X##p5; X##p5 = RotL_64(X##p5,ROT##_2); X##p5 ^= X##p4; \ - X##p6 += X##p7; X##p7 = RotL_64(X##p7,ROT##_3); X##p7 ^= X##p6; \ - -#if SKEIN_UNROLL_512 == 0 + X##p0 += X##p1; X##p1 = RotL_64(X##p1,ROT##_0); X##p1 ^= X##p0; \ + X##p2 += X##p3; X##p3 = RotL_64(X##p3,ROT##_1); X##p3 ^= X##p2; \ + X##p4 += X##p5; X##p5 = RotL_64(X##p5,ROT##_2); X##p5 ^= X##p4; \ + X##p6 += X##p7; X##p7 = RotL_64(X##p7,ROT##_3); X##p7 ^= X##p6; \ + +#if SKEIN_UNROLL_512 == 0 #define R512(p0,p1,p2,p3,p4,p5,p6,p7,ROT,rNum) /* unrolled */ \ - Round512(p0,p1,p2,p3,p4,p5,p6,p7,ROT,rNum) \ - Skein_Show_R_Ptr(BLK_BITS,&ctx->h,rNum,Xptr); + Round512(p0,p1,p2,p3,p4,p5,p6,p7,ROT,rNum) \ + Skein_Show_R_Ptr(BLK_BITS,&ctx->h,rNum,Xptr); #define I512(R) \ - X0 += ks[((R)+1) % 9]; /* inject the key schedule value */ \ - X1 += ks[((R)+2) % 9]; \ - X2 += ks[((R)+3) % 9]; \ - X3 += ks[((R)+4) % 9]; \ - X4 += ks[((R)+5) % 9]; \ - X5 += ks[((R)+6) % 9] + ts[((R)+1) % 3]; \ - X6 += ks[((R)+7) % 9] + ts[((R)+2) % 3]; \ - X7 += ks[((R)+8) % 9] + (R)+1; \ - Skein_Show_R_Ptr(BLK_BITS,&ctx->h,SKEIN_RND_KEY_INJECT,Xptr); + X0 += ks[((R)+1) % 9]; /* inject the key schedule value */ \ + X1 += ks[((R)+2) % 9]; \ + X2 += ks[((R)+3) % 9]; \ + X3 += ks[((R)+4) % 9]; \ + X4 += ks[((R)+5) % 9]; \ + X5 += ks[((R)+6) % 9] + ts[((R)+1) % 3]; \ + X6 += ks[((R)+7) % 9] + ts[((R)+2) % 3]; \ + X7 += ks[((R)+8) % 9] + (R)+1; \ + Skein_Show_R_Ptr(BLK_BITS,&ctx->h,SKEIN_RND_KEY_INJECT,Xptr); #else /* looping version */ #define R512(p0,p1,p2,p3,p4,p5,p6,p7,ROT,rNum) \ - Round512(p0,p1,p2,p3,p4,p5,p6,p7,ROT,rNum) \ - Skein_Show_R_Ptr(BLK_BITS,&ctx->h,4*(r-1)+rNum,Xptr); + Round512(p0,p1,p2,p3,p4,p5,p6,p7,ROT,rNum) \ + Skein_Show_R_Ptr(BLK_BITS,&ctx->h,4*(r-1)+rNum,Xptr); #define I512(R) \ - X0 += ks[r+(R)+0]; /* inject the key schedule value */ \ - X1 += ks[r+(R)+1]; \ - X2 += ks[r+(R)+2]; \ - X3 += ks[r+(R)+3]; \ - X4 += ks[r+(R)+4]; \ - X5 += ks[r+(R)+5] + ts[r+(R)+0]; \ - X6 += ks[r+(R)+6] + ts[r+(R)+1]; \ - X7 += ks[r+(R)+7] + r+(R) ; \ - ks[r + (R)+8] = ks[r+(R)-1]; /* rotate key schedule */ \ - ts[r + (R)+2] = ts[r+(R)-1]; \ - Skein_Show_R_Ptr(BLK_BITS,&ctx->h,SKEIN_RND_KEY_INJECT,Xptr); + X0 += ks[r+(R)+0]; /* inject the key schedule value */ \ + X1 += ks[r+(R)+1]; \ + X2 += ks[r+(R)+2]; \ + X3 += ks[r+(R)+3]; \ + X4 += ks[r+(R)+4]; \ + X5 += ks[r+(R)+5] + ts[r+(R)+0]; \ + X6 += ks[r+(R)+6] + ts[r+(R)+1]; \ + X7 += ks[r+(R)+7] + r+(R) ; \ + ks[r + (R)+8] = ks[r+(R)-1]; /* rotate key schedule */ \ + ts[r + (R)+2] = ts[r+(R)-1]; \ + Skein_Show_R_Ptr(BLK_BITS,&ctx->h,SKEIN_RND_KEY_INJECT,Xptr); - for (r=1;r < 2*RCNT;r+=2*SKEIN_UNROLL_512) /* loop thru it */ + for(r = 1; r < 2 * RCNT; r += 2 * SKEIN_UNROLL_512) /* loop thru it */ #endif /* end of looped code definitions */ - { + { #define R512_8_rounds(R) /* do 8 full rounds */ \ - R512(0,1,2,3,4,5,6,7,R_512_0,8*(R)+ 1); \ - R512(2,1,4,7,6,5,0,3,R_512_1,8*(R)+ 2); \ - R512(4,1,6,3,0,5,2,7,R_512_2,8*(R)+ 3); \ - R512(6,1,0,7,2,5,4,3,R_512_3,8*(R)+ 4); \ - I512(2*(R)); \ - R512(0,1,2,3,4,5,6,7,R_512_4,8*(R)+ 5); \ - R512(2,1,4,7,6,5,0,3,R_512_5,8*(R)+ 6); \ - R512(4,1,6,3,0,5,2,7,R_512_6,8*(R)+ 7); \ - R512(6,1,0,7,2,5,4,3,R_512_7,8*(R)+ 8); \ - I512(2*(R)+1); /* and key injection */ + R512(0,1,2,3,4,5,6,7,R_512_0,8*(R)+ 1); \ + R512(2,1,4,7,6,5,0,3,R_512_1,8*(R)+ 2); \ + R512(4,1,6,3,0,5,2,7,R_512_2,8*(R)+ 3); \ + R512(6,1,0,7,2,5,4,3,R_512_3,8*(R)+ 4); \ + I512(2*(R)); \ + R512(0,1,2,3,4,5,6,7,R_512_4,8*(R)+ 5); \ + R512(2,1,4,7,6,5,0,3,R_512_5,8*(R)+ 6); \ + R512(4,1,6,3,0,5,2,7,R_512_6,8*(R)+ 7); \ + R512(6,1,0,7,2,5,4,3,R_512_7,8*(R)+ 8); \ + I512(2*(R)+1); /* and key injection */ - R512_8_rounds( 0); + R512_8_rounds(0); #define R512_Unroll_R(NN) ((SKEIN_UNROLL_512 == 0 && SKEIN_512_ROUNDS_TOTAL/8 > (NN)) || (SKEIN_UNROLL_512 > (NN))) - #if R512_Unroll_R( 1) - R512_8_rounds( 1); - #endif - #if R512_Unroll_R( 2) - R512_8_rounds( 2); - #endif - #if R512_Unroll_R( 3) - R512_8_rounds( 3); - #endif - #if R512_Unroll_R( 4) - R512_8_rounds( 4); - #endif - #if R512_Unroll_R( 5) - R512_8_rounds( 5); - #endif - #if R512_Unroll_R( 6) - R512_8_rounds( 6); - #endif - #if R512_Unroll_R( 7) - R512_8_rounds( 7); - #endif - #if R512_Unroll_R( 8) - R512_8_rounds( 8); - #endif - #if R512_Unroll_R( 9) - R512_8_rounds( 9); - #endif - #if R512_Unroll_R(10) - R512_8_rounds(10); - #endif - #if R512_Unroll_R(11) - R512_8_rounds(11); - #endif - #if R512_Unroll_R(12) - R512_8_rounds(12); - #endif - #if R512_Unroll_R(13) - R512_8_rounds(13); - #endif - #if R512_Unroll_R(14) - R512_8_rounds(14); - #endif - #if (SKEIN_UNROLL_512 > 14) +#if R512_Unroll_R( 1) + R512_8_rounds(1); +#endif +#if R512_Unroll_R( 2) + R512_8_rounds(2); +#endif +#if R512_Unroll_R( 3) + R512_8_rounds(3); +#endif +#if R512_Unroll_R( 4) + R512_8_rounds(4); +#endif +#if R512_Unroll_R( 5) + R512_8_rounds(5); +#endif +#if R512_Unroll_R( 6) + R512_8_rounds(6); +#endif +#if R512_Unroll_R( 7) + R512_8_rounds(7); +#endif +#if R512_Unroll_R( 8) + R512_8_rounds(8); +#endif +#if R512_Unroll_R( 9) + R512_8_rounds(9); +#endif +#if R512_Unroll_R(10) + R512_8_rounds(10); +#endif +#if R512_Unroll_R(11) + R512_8_rounds(11); +#endif +#if R512_Unroll_R(12) + R512_8_rounds(12); +#endif +#if R512_Unroll_R(13) + R512_8_rounds(13); +#endif +#if R512_Unroll_R(14) + R512_8_rounds(14); +#endif +#if (SKEIN_UNROLL_512 > 14) #error "need more unrolling in Skein_512_Process_Block" - #endif - } +#endif + } - /* do the final "feedforward" xor, update context chaining vars */ - ctx->X[0] = X0 ^ w[0]; - ctx->X[1] = X1 ^ w[1]; - ctx->X[2] = X2 ^ w[2]; - ctx->X[3] = X3 ^ w[3]; - ctx->X[4] = X4 ^ w[4]; - ctx->X[5] = X5 ^ w[5]; - ctx->X[6] = X6 ^ w[6]; - ctx->X[7] = X7 ^ w[7]; - Skein_Show_Round(BLK_BITS,&ctx->h,SKEIN_RND_FEED_FWD,ctx->X); + /* do the final "feedforward" xor, update context chaining vars */ + ctx->X[0] = X0 ^ w[0]; + ctx->X[1] = X1 ^ w[1]; + ctx->X[2] = X2 ^ w[2]; + ctx->X[3] = X3 ^ w[3]; + ctx->X[4] = X4 ^ w[4]; + ctx->X[5] = X5 ^ w[5]; + ctx->X[6] = X6 ^ w[6]; + ctx->X[7] = X7 ^ w[7]; + Skein_Show_Round(BLK_BITS, &ctx->h, SKEIN_RND_FEED_FWD, ctx->X); - ts[1] &= ~SKEIN_T1_FLAG_FIRST; - } - while (--blkCnt); - ctx->h.T[0] = ts[0]; - ctx->h.T[1] = ts[1]; - } + ts[1] &= ~SKEIN_T1_FLAG_FIRST; + } + while(--blkCnt); + ctx->h.T[0] = ts[0]; + ctx->h.T[1] = ts[1]; +} #endif /*****************************************************************/ @@ -462,240 +471,252 @@ static void Skein_512_Process_Block(Skein_512_Ctxt_t *ctx,const u08b_t *blkPtr,s /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ /* init the context for a straight hashing operation */ -static int Skein_512_Init(Skein_512_Ctxt_t *ctx, size_t hashBitLen) - { - union - { - u08b_t b[SKEIN_512_STATE_BYTES]; - u64b_t w[SKEIN_512_STATE_WORDS]; - } cfg; /* config block */ - - Skein_Assert(hashBitLen > 0,SKEIN_BAD_HASHLEN); - ctx->h.hashBitLen = hashBitLen; /* output hash bit count */ +static int Skein_512_Init(Skein_512_Ctxt_t* ctx, size_t hashBitLen) +{ + union + { + u08b_t b[SKEIN_512_STATE_BYTES]; + u64b_t w[SKEIN_512_STATE_WORDS]; + } cfg; /* config block */ - switch (hashBitLen) - { /* use pre-computed values, where available */ + Skein_Assert(hashBitLen > 0, SKEIN_BAD_HASHLEN); + ctx->h.hashBitLen = hashBitLen; /* output hash bit count */ + + switch(hashBitLen) + { + /* use pre-computed values, where available */ #ifndef SKEIN_NO_PRECOMP - case 256: memcpy(ctx->X,SKEIN_512_IV_256,sizeof(ctx->X)); break; + case 256: + memcpy(ctx->X, SKEIN_512_IV_256, sizeof(ctx->X)); + break; #endif - default: - /* here if there is no precomputed IV value available */ - /* build/process the config block, type == CONFIG (could be precomputed) */ - Skein_Start_New_Type(ctx,CFG_FINAL); /* set tweaks: T0=0; T1=CFG | FINAL */ + default: + /* here if there is no precomputed IV value available */ + /* build/process the config block, type == CONFIG (could be precomputed) */ + Skein_Start_New_Type(ctx, CFG_FINAL); /* set tweaks: T0=0; T1=CFG | FINAL */ - cfg.w[0] = Skein_Swap64(SKEIN_SCHEMA_VER); /* set the schema, version */ - cfg.w[1] = Skein_Swap64(hashBitLen); /* hash result length in bits */ - cfg.w[2] = Skein_Swap64(SKEIN_CFG_TREE_INFO_SEQUENTIAL); - memset(&cfg.w[3],0,sizeof(cfg) - 3*sizeof(cfg.w[0])); /* zero pad config block */ + cfg.w[0] = Skein_Swap64(SKEIN_SCHEMA_VER); /* set the schema, version */ + cfg.w[1] = Skein_Swap64(hashBitLen); /* hash result length in bits */ + cfg.w[2] = Skein_Swap64(SKEIN_CFG_TREE_INFO_SEQUENTIAL); + memset(&cfg.w[3], 0, sizeof(cfg) - 3 * sizeof(cfg.w[0])); /* zero pad config block */ - /* compute the initial chaining values from config block */ - memset(ctx->X,0,sizeof(ctx->X)); /* zero the chaining variables */ - Skein_512_Process_Block(ctx,cfg.b,1,SKEIN_CFG_STR_LEN); - break; - } + /* compute the initial chaining values from config block */ + memset(ctx->X, 0, sizeof(ctx->X)); /* zero the chaining variables */ + Skein_512_Process_Block(ctx, cfg.b, 1, SKEIN_CFG_STR_LEN); + break; + } - /* The chaining vars ctx->X are now initialized for the given hashBitLen. */ - /* Set up to process the data message portion of the hash (default) */ - Skein_Start_New_Type(ctx,MSG); /* T0=0, T1= MSG type */ + /* The chaining vars ctx->X are now initialized for the given hashBitLen. */ + /* Set up to process the data message portion of the hash (default) */ + Skein_Start_New_Type(ctx, MSG); /* T0=0, T1= MSG type */ - return SKEIN_SUCCESS; - } + return SKEIN_SUCCESS; +} /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ /* process the input bytes */ -static int Skein_512_Update(Skein_512_Ctxt_t *ctx, const u08b_t *msg, size_t msgByteCnt) - { - size_t n; +static int Skein_512_Update(Skein_512_Ctxt_t* ctx, const u08b_t* msg, size_t msgByteCnt) +{ + size_t n; - Skein_Assert(ctx->h.bCnt <= SKEIN_512_BLOCK_BYTES,SKEIN_FAIL); /* catch uninitialized context */ + Skein_Assert(ctx->h.bCnt <= SKEIN_512_BLOCK_BYTES, SKEIN_FAIL); /* catch uninitialized context */ - /* process full blocks, if any */ - if (msgByteCnt + ctx->h.bCnt > SKEIN_512_BLOCK_BYTES) - { - if (ctx->h.bCnt) /* finish up any buffered message data */ - { - n = SKEIN_512_BLOCK_BYTES - ctx->h.bCnt; /* # bytes free in buffer b[] */ - if (n) - { - Skein_assert(n < msgByteCnt); /* check on our logic here */ - memcpy(&ctx->b[ctx->h.bCnt],msg,n); - msgByteCnt -= n; - msg += n; - ctx->h.bCnt += n; - } - Skein_assert(ctx->h.bCnt == SKEIN_512_BLOCK_BYTES); - Skein_512_Process_Block(ctx,ctx->b,1,SKEIN_512_BLOCK_BYTES); - ctx->h.bCnt = 0; - } - /* now process any remaining full blocks, directly from input message data */ - if (msgByteCnt > SKEIN_512_BLOCK_BYTES) - { - n = (msgByteCnt-1) / SKEIN_512_BLOCK_BYTES; /* number of full blocks to process */ - Skein_512_Process_Block(ctx,msg,n,SKEIN_512_BLOCK_BYTES); - msgByteCnt -= n * SKEIN_512_BLOCK_BYTES; - msg += n * SKEIN_512_BLOCK_BYTES; - } - Skein_assert(ctx->h.bCnt == 0); - } + /* process full blocks, if any */ + if(msgByteCnt + ctx->h.bCnt > SKEIN_512_BLOCK_BYTES) + { + if(ctx->h.bCnt) /* finish up any buffered message data */ + { + n = SKEIN_512_BLOCK_BYTES - ctx->h.bCnt; /* # bytes free in buffer b[] */ + if(n) + { + Skein_assert(n < msgByteCnt); /* check on our logic here */ + memcpy(&ctx->b[ctx->h.bCnt], msg, n); + msgByteCnt -= n; + msg += n; + ctx->h.bCnt += n; + } + Skein_assert(ctx->h.bCnt == SKEIN_512_BLOCK_BYTES); + Skein_512_Process_Block(ctx, ctx->b, 1, SKEIN_512_BLOCK_BYTES); + ctx->h.bCnt = 0; + } + /* now process any remaining full blocks, directly from input message data */ + if(msgByteCnt > SKEIN_512_BLOCK_BYTES) + { + n = (msgByteCnt - 1) / SKEIN_512_BLOCK_BYTES; /* number of full blocks to process */ + Skein_512_Process_Block(ctx, msg, n, SKEIN_512_BLOCK_BYTES); + msgByteCnt -= n * SKEIN_512_BLOCK_BYTES; + msg += n * SKEIN_512_BLOCK_BYTES; + } + Skein_assert(ctx->h.bCnt == 0); + } - /* copy any remaining source message data bytes into b[] */ - if (msgByteCnt) - { - Skein_assert(msgByteCnt + ctx->h.bCnt <= SKEIN_512_BLOCK_BYTES); - memcpy(&ctx->b[ctx->h.bCnt],msg,msgByteCnt); - ctx->h.bCnt += msgByteCnt; - } + /* copy any remaining source message data bytes into b[] */ + if(msgByteCnt) + { + Skein_assert(msgByteCnt + ctx->h.bCnt <= SKEIN_512_BLOCK_BYTES); + memcpy(&ctx->b[ctx->h.bCnt], msg, msgByteCnt); + ctx->h.bCnt += msgByteCnt; + } + + return SKEIN_SUCCESS; +} - return SKEIN_SUCCESS; - } - /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ /* finalize the hash computation and output the result */ -static int Skein_512_Final(Skein_512_Ctxt_t *ctx, u08b_t *hashVal) - { - size_t i,n,byteCnt; - u64b_t X[SKEIN_512_STATE_WORDS]; - Skein_Assert(ctx->h.bCnt <= SKEIN_512_BLOCK_BYTES,SKEIN_FAIL); /* catch uninitialized context */ +static int Skein_512_Final(Skein_512_Ctxt_t* ctx, u08b_t* hashVal) +{ + size_t i, n, byteCnt; + u64b_t X[SKEIN_512_STATE_WORDS]; + Skein_Assert(ctx->h.bCnt <= SKEIN_512_BLOCK_BYTES, SKEIN_FAIL); /* catch uninitialized context */ - ctx->h.T[1] |= SKEIN_T1_FLAG_FINAL; /* tag as the final block */ - if (ctx->h.bCnt < SKEIN_512_BLOCK_BYTES) /* zero pad b[] if necessary */ - memset(&ctx->b[ctx->h.bCnt],0,SKEIN_512_BLOCK_BYTES - ctx->h.bCnt); + ctx->h.T[1] |= SKEIN_T1_FLAG_FINAL; /* tag as the final block */ + if(ctx->h.bCnt < SKEIN_512_BLOCK_BYTES) /* zero pad b[] if necessary */ + { + memset(&ctx->b[ctx->h.bCnt], 0, SKEIN_512_BLOCK_BYTES - ctx->h.bCnt); + } - Skein_512_Process_Block(ctx,ctx->b,1,ctx->h.bCnt); /* process the final block */ - - /* now output the result */ - byteCnt = (ctx->h.hashBitLen + 7) >> 3; /* total number of output bytes */ + Skein_512_Process_Block(ctx, ctx->b, 1, ctx->h.bCnt); /* process the final block */ - /* run Threefish in "counter mode" to generate output */ - memset(ctx->b,0,sizeof(ctx->b)); /* zero out b[], so it can hold the counter */ - memcpy(X,ctx->X,sizeof(X)); /* keep a local copy of counter mode "key" */ - for (i=0;i*SKEIN_512_BLOCK_BYTES < byteCnt;i++) - { - ((u64b_t *)ctx->b)[0]= Skein_Swap64((u64b_t) i); /* build the counter block */ - Skein_Start_New_Type(ctx,OUT_FINAL); - Skein_512_Process_Block(ctx,ctx->b,1,sizeof(u64b_t)); /* run "counter mode" */ - n = byteCnt - i*SKEIN_512_BLOCK_BYTES; /* number of output bytes left to go */ - if (n >= SKEIN_512_BLOCK_BYTES) - n = SKEIN_512_BLOCK_BYTES; - Skein_Put64_LSB_First(hashVal+i*SKEIN_512_BLOCK_BYTES,ctx->X,n); /* "output" the ctr mode bytes */ - Skein_Show_Final(512,&ctx->h,n,hashVal+i*SKEIN_512_BLOCK_BYTES); - memcpy(ctx->X,X,sizeof(X)); /* restore the counter mode key for next time */ - } - return SKEIN_SUCCESS; - } + /* now output the result */ + byteCnt = (ctx->h.hashBitLen + 7) >> 3; /* total number of output bytes */ + + /* run Threefish in "counter mode" to generate output */ + memset(ctx->b, 0, sizeof(ctx->b)); /* zero out b[], so it can hold the counter */ + memcpy(X, ctx->X, sizeof(X)); /* keep a local copy of counter mode "key" */ + for(i = 0; i * SKEIN_512_BLOCK_BYTES < byteCnt; i++) + { + ((u64b_t*)ctx->b)[0] = Skein_Swap64((u64b_t) i); /* build the counter block */ + Skein_Start_New_Type(ctx, OUT_FINAL); + Skein_512_Process_Block(ctx, ctx->b, 1, sizeof(u64b_t)); /* run "counter mode" */ + n = byteCnt - i * SKEIN_512_BLOCK_BYTES; /* number of output bytes left to go */ + if(n >= SKEIN_512_BLOCK_BYTES) + { + n = SKEIN_512_BLOCK_BYTES; + } + Skein_Put64_LSB_First(hashVal + i * SKEIN_512_BLOCK_BYTES, ctx->X, n); /* "output" the ctr mode bytes */ + Skein_Show_Final(512, &ctx->h, n, hashVal + i * SKEIN_512_BLOCK_BYTES); + memcpy(ctx->X, X, sizeof(X)); /* restore the counter mode key for next time */ + } + return SKEIN_SUCCESS; +} #if defined(SKEIN_CODE_SIZE) || defined(SKEIN_PERF) static size_t Skein_512_API_CodeSize(void) - { - return ((u08b_t *) Skein_512_API_CodeSize) - - ((u08b_t *) Skein_512_Init); - } +{ + return ((u08b_t*) Skein_512_API_CodeSize) - + ((u08b_t*) Skein_512_Init); +} #endif typedef struct { - uint_t statebits; /* 256, 512, or 1024 */ - union - { - Skein_Ctxt_Hdr_t h; /* common header "overlay" */ - Skein_512_Ctxt_t ctx_512; - } u; + uint_t statebits; /* 256, 512, or 1024 */ + union + { + Skein_Ctxt_Hdr_t h; /* common header "overlay" */ + Skein_512_Ctxt_t ctx_512; + } u; } hashState; /* "incremental" hashing API */ -static SkeinHashReturn Init (hashState *state, int hashbitlen); -static SkeinHashReturn Update(hashState *state, const SkeinBitSequence *data, SkeinDataLength databitlen); -static SkeinHashReturn Final (hashState *state, SkeinBitSequence *hashval); +static SkeinHashReturn Init(hashState* state, int hashbitlen); +static SkeinHashReturn Update(hashState* state, const SkeinBitSequence* data, SkeinDataLength databitlen); +static SkeinHashReturn Final(hashState* state, SkeinBitSequence* hashval); /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ /* select the context size and init the context */ -static SkeinHashReturn Init(hashState *state, int hashbitlen) +static SkeinHashReturn Init(hashState* state, int hashbitlen) { - state->statebits = 64*SKEIN_512_STATE_WORDS; - return Skein_512_Init(&state->u.ctx_512,(size_t) hashbitlen); + state->statebits = 64 * SKEIN_512_STATE_WORDS; + return Skein_512_Init(&state->u.ctx_512, (size_t) hashbitlen); } /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ /* process data to be hashed */ -static SkeinHashReturn Update(hashState *state, const SkeinBitSequence *data, SkeinDataLength databitlen) +static SkeinHashReturn Update(hashState* state, const SkeinBitSequence* data, SkeinDataLength databitlen) { - /* only the final Update() call is allowed do partial bytes, else assert an error */ - Skein_Assert((state->u.h.T[1] & SKEIN_T1_FLAG_BIT_PAD) == 0 || databitlen == 0, SKEIN_FAIL); + /* only the final Update() call is allowed do partial bytes, else assert an error */ + Skein_Assert((state->u.h.T[1] & SKEIN_T1_FLAG_BIT_PAD) == 0 || databitlen == 0, SKEIN_FAIL); - Skein_Assert(state->statebits % 256 == 0 && (state->statebits-256) < 1024,SKEIN_FAIL); - if ((databitlen & 7) == 0) /* partial bytes? */ - { - return Skein_512_Update(&state->u.ctx_512,data,databitlen >> 3); - } - else - { /* handle partial final byte */ - size_t bCnt = (databitlen >> 3) + 1; /* number of bytes to handle (nonzero here!) */ - u08b_t b,mask; + Skein_Assert(state->statebits % 256 == 0 && (state->statebits - 256) < 1024, SKEIN_FAIL); + if((databitlen & 7) == 0) /* partial bytes? */ + { + return Skein_512_Update(&state->u.ctx_512, data, databitlen >> 3); + } + else + { + /* handle partial final byte */ + size_t bCnt = (databitlen >> 3) + 1; /* number of bytes to handle (nonzero here!) */ + u08b_t b, mask; - mask = (u08b_t) (1u << (7 - (databitlen & 7))); /* partial byte bit mask */ - b = (u08b_t) ((data[bCnt-1] & (0-mask)) | mask); /* apply bit padding on final byte */ + mask = (u08b_t)(1u << (7 - (databitlen & 7))); /* partial byte bit mask */ + b = (u08b_t)((data[bCnt - 1] & (0 - mask)) | mask); /* apply bit padding on final byte */ - Skein_512_Update(&state->u.ctx_512,data,bCnt-1); /* process all but the final byte */ - Skein_512_Update(&state->u.ctx_512,&b , 1 ); /* process the (masked) partial byte */ - Skein_Set_Bit_Pad_Flag(state->u.h); /* set tweak flag for the final call */ + Skein_512_Update(&state->u.ctx_512, data, bCnt - 1); /* process all but the final byte */ + Skein_512_Update(&state->u.ctx_512, &b , 1); /* process the (masked) partial byte */ + Skein_Set_Bit_Pad_Flag(state->u.h); /* set tweak flag for the final call */ - return SKEIN_SUCCESS; - } + return SKEIN_SUCCESS; + } } /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ /* finalize hash computation and output the result (hashbitlen bits) */ -static SkeinHashReturn Final(hashState *state, SkeinBitSequence *hashval) +static SkeinHashReturn Final(hashState* state, SkeinBitSequence* hashval) { - Skein_Assert(state->statebits % 256 == 0 && (state->statebits-256) < 1024,FAIL); - return Skein_512_Final(&state->u.ctx_512,hashval); + Skein_Assert(state->statebits % 256 == 0 && (state->statebits - 256) < 1024, FAIL); + return Skein_512_Final(&state->u.ctx_512, hashval); } /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ /* all-in-one hash function */ -SkeinHashReturn skein_hash(int hashbitlen, const SkeinBitSequence *data, /* all-in-one call */ - SkeinDataLength databitlen,SkeinBitSequence *hashval) +SkeinHashReturn skein_hash(int hashbitlen, const SkeinBitSequence* data, /* all-in-one call */ + SkeinDataLength databitlen, SkeinBitSequence* hashval) { - hashState state; - SkeinHashReturn r = Init(&state,hashbitlen); - if (r == SKEIN_SUCCESS) - { /* these calls do not fail when called properly */ - r = Update(&state,data,databitlen); - Final(&state,hashval); - } - return r; + hashState state; + SkeinHashReturn r = Init(&state, hashbitlen); + if(r == SKEIN_SUCCESS) + { + /* these calls do not fail when called properly */ + r = Update(&state, data, databitlen); + Final(&state, hashval); + } + return r; } -void xmr_skein(const SkeinBitSequence *data, SkeinBitSequence *hashval){ - #define XMR_HASHBITLEN 256 - #define XMR_DATABITLEN 1600 +void xmr_skein(const SkeinBitSequence* data, SkeinBitSequence* hashval) +{ +#define XMR_HASHBITLEN 256 +#define XMR_DATABITLEN 1600 - // Init - hashState state; - state.statebits = 64*SKEIN_512_STATE_WORDS; + // Init + hashState state; + state.statebits = 64 * SKEIN_512_STATE_WORDS; - // Skein_512_Init(&state.u.ctx_512, (size_t)XMR_HASHBITLEN); - state.u.ctx_512.h.hashBitLen = XMR_HASHBITLEN; - memcpy(state.u.ctx_512.X,SKEIN_512_IV_256,sizeof(state.u.ctx_512.X)); - Skein_512_Ctxt_t* ctx = &(state.u.ctx_512); - Skein_Start_New_Type(ctx,MSG); + // Skein_512_Init(&state.u.ctx_512, (size_t)XMR_HASHBITLEN); + state.u.ctx_512.h.hashBitLen = XMR_HASHBITLEN; + memcpy(state.u.ctx_512.X, SKEIN_512_IV_256, sizeof(state.u.ctx_512.X)); + Skein_Start_New_Type(&state.u.ctx_512, MSG); - // Update - if ((XMR_DATABITLEN & 7) == 0){ /* partial bytes? */ - Skein_512_Update(&state.u.ctx_512,data,XMR_DATABITLEN >> 3); - }else{ /* handle partial final byte */ - size_t bCnt = (XMR_DATABITLEN >> 3) + 1; /* number of bytes to handle (nonzero here!) */ - u08b_t b,mask; + // Update + if((XMR_DATABITLEN & 7) == 0) // partial bytes? + { + Skein_512_Update(&state.u.ctx_512, data, XMR_DATABITLEN >> 3); + } + else // handle partial final byte + { + size_t bCnt = (XMR_DATABITLEN >> 3) + 1; // number of bytes to handle (nonzero here!) + u08b_t b, mask; - mask = (u08b_t) (1u << (7 - (XMR_DATABITLEN & 7))); /* partial byte bit mask */ - b = (u08b_t) ((data[bCnt-1] & (0-mask)) | mask); /* apply bit padding on final byte */ + mask = (u08b_t)(1u << (7 - (XMR_DATABITLEN & 7))); // partial byte bit mask + b = (u08b_t)((data[bCnt - 1] & (0 - mask)) | mask); // apply bit padding on final byte - Skein_512_Update(&state.u.ctx_512,data,bCnt-1); /* process all but the final byte */ - Skein_512_Update(&state.u.ctx_512,&b , 1 ); /* process the (masked) partial byte */ - Skein_Set_Bit_Pad_Flag(state.u.h); /* set tweak flag for the final call */ - } + Skein_512_Update(&state.u.ctx_512, data, bCnt - 1); // process all but the final byte + Skein_512_Update(&state.u.ctx_512, &b , 1); //process the (masked) partial byte + Skein_Set_Bit_Pad_Flag(state.u.h); // set tweak flag for the final call + } - // Finalize - Skein_512_Final(&state.u.ctx_512, hashval); + // Finalize + Skein_512_Final(&state.u.ctx_512, hashval); } diff --git a/src/crypto/c_skein.h b/src/crypto/c_skein.h index c642e265..a46b3d13 100644 --- a/src/crypto/c_skein.h +++ b/src/crypto/c_skein.h @@ -9,7 +9,7 @@ ** This algorithm and source code is released to the public domain. ** *************************************************************************** -** +** ** The following compile-time switches may be defined to control some ** tradeoffs between speed, code size, error checking, and security. ** @@ -20,8 +20,8 @@ ** [default: no callouts (no overhead)] ** ** SKEIN_ERR_CHECK -- how error checking is handled inside Skein -** code. If not defined, most error checking -** is disabled (for performance). Otherwise, +** code. If not defined, most error checking +** is disabled (for performance). Otherwise, ** the switch value is interpreted as: ** 0: use assert() to flag errors ** 1: return SKEIN_FAIL to flag errors @@ -31,9 +31,9 @@ typedef enum { - SKEIN_SUCCESS = 0, /* return codes from Skein calls */ - SKEIN_FAIL = 1, - SKEIN_BAD_HASHLEN = 2 + SKEIN_SUCCESS = 0, /* return codes from Skein calls */ + SKEIN_FAIL = 1, + SKEIN_BAD_HASHLEN = 2 } SkeinHashReturn; @@ -41,9 +41,9 @@ typedef size_t SkeinDataLength; /* bit count type */ typedef u08b_t SkeinBitSequence; /* bit stream type */ /* "all-in-one" call */ -SkeinHashReturn skein_hash(int hashbitlen, const SkeinBitSequence *data, - SkeinDataLength databitlen, SkeinBitSequence *hashval); +SkeinHashReturn skein_hash(int hashbitlen, const SkeinBitSequence* data, + SkeinDataLength databitlen, SkeinBitSequence* hashval); -void xmr_skein(const SkeinBitSequence *data, SkeinBitSequence *hashval); +void xmr_skein(const SkeinBitSequence* data, SkeinBitSequence* hashval); #endif /* ifndef _SKEIN_H_ */ diff --git a/src/crypto/groestl_tables.h b/src/crypto/groestl_tables.h index a23295c3..23065fe7 100644 --- a/src/crypto/groestl_tables.h +++ b/src/crypto/groestl_tables.h @@ -3,36 +3,37 @@ const uint32_t T[512] = {0xa5f432c6, 0xc6a597f4, 0x84976ff8, 0xf884eb97, 0x99b05eee, 0xee99c7b0, 0x8d8c7af6, 0xf68df78c, 0xd17e8ff, 0xff0de517, 0xbddc0ad6, 0xd6bdb7dc, 0xb1c816de, 0xdeb1a7c8, 0x54fc6d91, 0x915439fc -, 0x50f09060, 0x6050c0f0, 0x3050702, 0x2030405, 0xa9e02ece, 0xcea987e0, 0x7d87d156, 0x567dac87, 0x192bcce7, 0xe719d52b, 0x62a613b5, 0xb56271a6, 0xe6317c4d, 0x4de69a31, 0x9ab559ec, 0xec9ac3b5 -, 0x45cf408f, 0x8f4505cf, 0x9dbca31f, 0x1f9d3ebc, 0x40c04989, 0x894009c0, 0x879268fa, 0xfa87ef92, 0x153fd0ef, 0xef15c53f, 0xeb2694b2, 0xb2eb7f26, 0xc940ce8e, 0x8ec90740, 0xb1de6fb, 0xfb0bed1d -, 0xec2f6e41, 0x41ec822f, 0x67a91ab3, 0xb3677da9, 0xfd1c435f, 0x5ffdbe1c, 0xea256045, 0x45ea8a25, 0xbfdaf923, 0x23bf46da, 0xf7025153, 0x53f7a602, 0x96a145e4, 0xe496d3a1, 0x5bed769b, 0x9b5b2ded -, 0xc25d2875, 0x75c2ea5d, 0x1c24c5e1, 0xe11cd924, 0xaee9d43d, 0x3dae7ae9, 0x6abef24c, 0x4c6a98be, 0x5aee826c, 0x6c5ad8ee, 0x41c3bd7e, 0x7e41fcc3, 0x206f3f5, 0xf502f106, 0x4fd15283, 0x834f1dd1 -, 0x5ce48c68, 0x685cd0e4, 0xf4075651, 0x51f4a207, 0x345c8dd1, 0xd134b95c, 0x818e1f9, 0xf908e918, 0x93ae4ce2, 0xe293dfae, 0x73953eab, 0xab734d95, 0x53f59762, 0x6253c4f5, 0x3f416b2a, 0x2a3f5441 -, 0xc141c08, 0x80c1014, 0x52f66395, 0x955231f6, 0x65afe946, 0x46658caf, 0x5ee27f9d, 0x9d5e21e2, 0x28784830, 0x30286078, 0xa1f8cf37, 0x37a16ef8, 0xf111b0a, 0xa0f1411, 0xb5c4eb2f, 0x2fb55ec4 -, 0x91b150e, 0xe091c1b, 0x365a7e24, 0x2436485a, 0x9bb6ad1b, 0x1b9b36b6, 0x3d4798df, 0xdf3da547, 0x266aa7cd, 0xcd26816a, 0x69bbf54e, 0x4e699cbb, 0xcd4c337f, 0x7fcdfe4c, 0x9fba50ea, 0xea9fcfba -, 0x1b2d3f12, 0x121b242d, 0x9eb9a41d, 0x1d9e3ab9, 0x749cc458, 0x5874b09c, 0x2e724634, 0x342e6872, 0x2d774136, 0x362d6c77, 0xb2cd11dc, 0xdcb2a3cd, 0xee299db4, 0xb4ee7329, 0xfb164d5b, 0x5bfbb616 -, 0xf601a5a4, 0xa4f65301, 0x4dd7a176, 0x764decd7, 0x61a314b7, 0xb76175a3, 0xce49347d, 0x7dcefa49, 0x7b8ddf52, 0x527ba48d, 0x3e429fdd, 0xdd3ea142, 0x7193cd5e, 0x5e71bc93, 0x97a2b113, 0x139726a2 -, 0xf504a2a6, 0xa6f55704, 0x68b801b9, 0xb96869b8, 0x0, 0x0, 0x2c74b5c1, 0xc12c9974, 0x60a0e040, 0x406080a0, 0x1f21c2e3, 0xe31fdd21, 0xc8433a79, 0x79c8f243, 0xed2c9ab6, 0xb6ed772c -, 0xbed90dd4, 0xd4beb3d9, 0x46ca478d, 0x8d4601ca, 0xd9701767, 0x67d9ce70, 0x4bddaf72, 0x724be4dd, 0xde79ed94, 0x94de3379, 0xd467ff98, 0x98d42b67, 0xe82393b0, 0xb0e87b23, 0x4ade5b85, 0x854a11de -, 0x6bbd06bb, 0xbb6b6dbd, 0x2a7ebbc5, 0xc52a917e, 0xe5347b4f, 0x4fe59e34, 0x163ad7ed, 0xed16c13a, 0xc554d286, 0x86c51754, 0xd762f89a, 0x9ad72f62, 0x55ff9966, 0x6655ccff, 0x94a7b611, 0x119422a7 -, 0xcf4ac08a, 0x8acf0f4a, 0x1030d9e9, 0xe910c930, 0x60a0e04, 0x406080a, 0x819866fe, 0xfe81e798, 0xf00baba0, 0xa0f05b0b, 0x44ccb478, 0x7844f0cc, 0xbad5f025, 0x25ba4ad5, 0xe33e754b, 0x4be3963e -, 0xf30eaca2, 0xa2f35f0e, 0xfe19445d, 0x5dfeba19, 0xc05bdb80, 0x80c01b5b, 0x8a858005, 0x58a0a85, 0xadecd33f, 0x3fad7eec, 0xbcdffe21, 0x21bc42df, 0x48d8a870, 0x7048e0d8, 0x40cfdf1, 0xf104f90c -, 0xdf7a1963, 0x63dfc67a, 0xc1582f77, 0x77c1ee58, 0x759f30af, 0xaf75459f, 0x63a5e742, 0x426384a5, 0x30507020, 0x20304050, 0x1a2ecbe5, 0xe51ad12e, 0xe12effd, 0xfd0ee112, 0x6db708bf, 0xbf6d65b7 -, 0x4cd45581, 0x814c19d4, 0x143c2418, 0x1814303c, 0x355f7926, 0x26354c5f, 0x2f71b2c3, 0xc32f9d71, 0xe13886be, 0xbee16738, 0xa2fdc835, 0x35a26afd, 0xcc4fc788, 0x88cc0b4f, 0x394b652e, 0x2e395c4b -, 0x57f96a93, 0x93573df9, 0xf20d5855, 0x55f2aa0d, 0x829d61fc, 0xfc82e39d, 0x47c9b37a, 0x7a47f4c9, 0xacef27c8, 0xc8ac8bef, 0xe73288ba, 0xbae76f32, 0x2b7d4f32, 0x322b647d, 0x95a442e6, 0xe695d7a4 -, 0xa0fb3bc0, 0xc0a09bfb, 0x98b3aa19, 0x199832b3, 0xd168f69e, 0x9ed12768, 0x7f8122a3, 0xa37f5d81, 0x66aaee44, 0x446688aa, 0x7e82d654, 0x547ea882, 0xabe6dd3b, 0x3bab76e6, 0x839e950b, 0xb83169e -, 0xca45c98c, 0x8cca0345, 0x297bbcc7, 0xc729957b, 0xd36e056b, 0x6bd3d66e, 0x3c446c28, 0x283c5044, 0x798b2ca7, 0xa779558b, 0xe23d81bc, 0xbce2633d, 0x1d273116, 0x161d2c27, 0x769a37ad, 0xad76419a -, 0x3b4d96db, 0xdb3bad4d, 0x56fa9e64, 0x6456c8fa, 0x4ed2a674, 0x744ee8d2, 0x1e223614, 0x141e2822, 0xdb76e492, 0x92db3f76, 0xa1e120c, 0xc0a181e, 0x6cb4fc48, 0x486c90b4, 0xe4378fb8, 0xb8e46b37 -, 0x5de7789f, 0x9f5d25e7, 0x6eb20fbd, 0xbd6e61b2, 0xef2a6943, 0x43ef862a, 0xa6f135c4, 0xc4a693f1, 0xa8e3da39, 0x39a872e3, 0xa4f7c631, 0x31a462f7, 0x37598ad3, 0xd337bd59, 0x8b8674f2, 0xf28bff86 -, 0x325683d5, 0xd532b156, 0x43c54e8b, 0x8b430dc5, 0x59eb856e, 0x6e59dceb, 0xb7c218da, 0xdab7afc2, 0x8c8f8e01, 0x18c028f, 0x64ac1db1, 0xb16479ac, 0xd26df19c, 0x9cd2236d, 0xe03b7249, 0x49e0923b -, 0xb4c71fd8, 0xd8b4abc7, 0xfa15b9ac, 0xacfa4315, 0x709faf3, 0xf307fd09, 0x256fa0cf, 0xcf25856f, 0xafea20ca, 0xcaaf8fea, 0x8e897df4, 0xf48ef389, 0xe9206747, 0x47e98e20, 0x18283810, 0x10182028 -, 0xd5640b6f, 0x6fd5de64, 0x888373f0, 0xf088fb83, 0x6fb1fb4a, 0x4a6f94b1, 0x7296ca5c, 0x5c72b896, 0x246c5438, 0x3824706c, 0xf1085f57, 0x57f1ae08, 0xc7522173, 0x73c7e652, 0x51f36497, 0x975135f3 -, 0x2365aecb, 0xcb238d65, 0x7c8425a1, 0xa17c5984, 0x9cbf57e8, 0xe89ccbbf, 0x21635d3e, 0x3e217c63, 0xdd7cea96, 0x96dd377c, 0xdc7f1e61, 0x61dcc27f, 0x86919c0d, 0xd861a91, 0x85949b0f, 0xf851e94 -, 0x90ab4be0, 0xe090dbab, 0x42c6ba7c, 0x7c42f8c6, 0xc4572671, 0x71c4e257, 0xaae529cc, 0xccaa83e5, 0xd873e390, 0x90d83b73, 0x50f0906, 0x6050c0f, 0x103f4f7, 0xf701f503, 0x12362a1c, 0x1c123836 -, 0xa3fe3cc2, 0xc2a39ffe, 0x5fe18b6a, 0x6a5fd4e1, 0xf910beae, 0xaef94710, 0xd06b0269, 0x69d0d26b, 0x91a8bf17, 0x17912ea8, 0x58e87199, 0x995829e8, 0x2769533a, 0x3a277469, 0xb9d0f727, 0x27b94ed0 -, 0x384891d9, 0xd938a948, 0x1335deeb, 0xeb13cd35, 0xb3cee52b, 0x2bb356ce, 0x33557722, 0x22334455, 0xbbd604d2, 0xd2bbbfd6, 0x709039a9, 0xa9704990, 0x89808707, 0x7890e80, 0xa7f2c133, 0x33a766f2 -, 0xb6c1ec2d, 0x2db65ac1, 0x22665a3c, 0x3c227866, 0x92adb815, 0x15922aad, 0x2060a9c9, 0xc9208960, 0x49db5c87, 0x874915db, 0xff1ab0aa, 0xaaff4f1a, 0x7888d850, 0x5078a088, 0x7a8e2ba5, 0xa57a518e -, 0x8f8a8903, 0x38f068a, 0xf8134a59, 0x59f8b213, 0x809b9209, 0x980129b, 0x1739231a, 0x1a173439, 0xda751065, 0x65daca75, 0x315384d7, 0xd731b553, 0xc651d584, 0x84c61351, 0xb8d303d0, 0xd0b8bbd3 -, 0xc35edc82, 0x82c31f5e, 0xb0cbe229, 0x29b052cb, 0x7799c35a, 0x5a77b499, 0x11332d1e, 0x1e113c33, 0xcb463d7b, 0x7bcbf646, 0xfc1fb7a8, 0xa8fc4b1f, 0xd6610c6d, 0x6dd6da61, 0x3a4e622c, 0x2c3a584e}; + , 0x50f09060, 0x6050c0f0, 0x3050702, 0x2030405, 0xa9e02ece, 0xcea987e0, 0x7d87d156, 0x567dac87, 0x192bcce7, 0xe719d52b, 0x62a613b5, 0xb56271a6, 0xe6317c4d, 0x4de69a31, 0x9ab559ec, 0xec9ac3b5 + , 0x45cf408f, 0x8f4505cf, 0x9dbca31f, 0x1f9d3ebc, 0x40c04989, 0x894009c0, 0x879268fa, 0xfa87ef92, 0x153fd0ef, 0xef15c53f, 0xeb2694b2, 0xb2eb7f26, 0xc940ce8e, 0x8ec90740, 0xb1de6fb, 0xfb0bed1d + , 0xec2f6e41, 0x41ec822f, 0x67a91ab3, 0xb3677da9, 0xfd1c435f, 0x5ffdbe1c, 0xea256045, 0x45ea8a25, 0xbfdaf923, 0x23bf46da, 0xf7025153, 0x53f7a602, 0x96a145e4, 0xe496d3a1, 0x5bed769b, 0x9b5b2ded + , 0xc25d2875, 0x75c2ea5d, 0x1c24c5e1, 0xe11cd924, 0xaee9d43d, 0x3dae7ae9, 0x6abef24c, 0x4c6a98be, 0x5aee826c, 0x6c5ad8ee, 0x41c3bd7e, 0x7e41fcc3, 0x206f3f5, 0xf502f106, 0x4fd15283, 0x834f1dd1 + , 0x5ce48c68, 0x685cd0e4, 0xf4075651, 0x51f4a207, 0x345c8dd1, 0xd134b95c, 0x818e1f9, 0xf908e918, 0x93ae4ce2, 0xe293dfae, 0x73953eab, 0xab734d95, 0x53f59762, 0x6253c4f5, 0x3f416b2a, 0x2a3f5441 + , 0xc141c08, 0x80c1014, 0x52f66395, 0x955231f6, 0x65afe946, 0x46658caf, 0x5ee27f9d, 0x9d5e21e2, 0x28784830, 0x30286078, 0xa1f8cf37, 0x37a16ef8, 0xf111b0a, 0xa0f1411, 0xb5c4eb2f, 0x2fb55ec4 + , 0x91b150e, 0xe091c1b, 0x365a7e24, 0x2436485a, 0x9bb6ad1b, 0x1b9b36b6, 0x3d4798df, 0xdf3da547, 0x266aa7cd, 0xcd26816a, 0x69bbf54e, 0x4e699cbb, 0xcd4c337f, 0x7fcdfe4c, 0x9fba50ea, 0xea9fcfba + , 0x1b2d3f12, 0x121b242d, 0x9eb9a41d, 0x1d9e3ab9, 0x749cc458, 0x5874b09c, 0x2e724634, 0x342e6872, 0x2d774136, 0x362d6c77, 0xb2cd11dc, 0xdcb2a3cd, 0xee299db4, 0xb4ee7329, 0xfb164d5b, 0x5bfbb616 + , 0xf601a5a4, 0xa4f65301, 0x4dd7a176, 0x764decd7, 0x61a314b7, 0xb76175a3, 0xce49347d, 0x7dcefa49, 0x7b8ddf52, 0x527ba48d, 0x3e429fdd, 0xdd3ea142, 0x7193cd5e, 0x5e71bc93, 0x97a2b113, 0x139726a2 + , 0xf504a2a6, 0xa6f55704, 0x68b801b9, 0xb96869b8, 0x0, 0x0, 0x2c74b5c1, 0xc12c9974, 0x60a0e040, 0x406080a0, 0x1f21c2e3, 0xe31fdd21, 0xc8433a79, 0x79c8f243, 0xed2c9ab6, 0xb6ed772c + , 0xbed90dd4, 0xd4beb3d9, 0x46ca478d, 0x8d4601ca, 0xd9701767, 0x67d9ce70, 0x4bddaf72, 0x724be4dd, 0xde79ed94, 0x94de3379, 0xd467ff98, 0x98d42b67, 0xe82393b0, 0xb0e87b23, 0x4ade5b85, 0x854a11de + , 0x6bbd06bb, 0xbb6b6dbd, 0x2a7ebbc5, 0xc52a917e, 0xe5347b4f, 0x4fe59e34, 0x163ad7ed, 0xed16c13a, 0xc554d286, 0x86c51754, 0xd762f89a, 0x9ad72f62, 0x55ff9966, 0x6655ccff, 0x94a7b611, 0x119422a7 + , 0xcf4ac08a, 0x8acf0f4a, 0x1030d9e9, 0xe910c930, 0x60a0e04, 0x406080a, 0x819866fe, 0xfe81e798, 0xf00baba0, 0xa0f05b0b, 0x44ccb478, 0x7844f0cc, 0xbad5f025, 0x25ba4ad5, 0xe33e754b, 0x4be3963e + , 0xf30eaca2, 0xa2f35f0e, 0xfe19445d, 0x5dfeba19, 0xc05bdb80, 0x80c01b5b, 0x8a858005, 0x58a0a85, 0xadecd33f, 0x3fad7eec, 0xbcdffe21, 0x21bc42df, 0x48d8a870, 0x7048e0d8, 0x40cfdf1, 0xf104f90c + , 0xdf7a1963, 0x63dfc67a, 0xc1582f77, 0x77c1ee58, 0x759f30af, 0xaf75459f, 0x63a5e742, 0x426384a5, 0x30507020, 0x20304050, 0x1a2ecbe5, 0xe51ad12e, 0xe12effd, 0xfd0ee112, 0x6db708bf, 0xbf6d65b7 + , 0x4cd45581, 0x814c19d4, 0x143c2418, 0x1814303c, 0x355f7926, 0x26354c5f, 0x2f71b2c3, 0xc32f9d71, 0xe13886be, 0xbee16738, 0xa2fdc835, 0x35a26afd, 0xcc4fc788, 0x88cc0b4f, 0x394b652e, 0x2e395c4b + , 0x57f96a93, 0x93573df9, 0xf20d5855, 0x55f2aa0d, 0x829d61fc, 0xfc82e39d, 0x47c9b37a, 0x7a47f4c9, 0xacef27c8, 0xc8ac8bef, 0xe73288ba, 0xbae76f32, 0x2b7d4f32, 0x322b647d, 0x95a442e6, 0xe695d7a4 + , 0xa0fb3bc0, 0xc0a09bfb, 0x98b3aa19, 0x199832b3, 0xd168f69e, 0x9ed12768, 0x7f8122a3, 0xa37f5d81, 0x66aaee44, 0x446688aa, 0x7e82d654, 0x547ea882, 0xabe6dd3b, 0x3bab76e6, 0x839e950b, 0xb83169e + , 0xca45c98c, 0x8cca0345, 0x297bbcc7, 0xc729957b, 0xd36e056b, 0x6bd3d66e, 0x3c446c28, 0x283c5044, 0x798b2ca7, 0xa779558b, 0xe23d81bc, 0xbce2633d, 0x1d273116, 0x161d2c27, 0x769a37ad, 0xad76419a + , 0x3b4d96db, 0xdb3bad4d, 0x56fa9e64, 0x6456c8fa, 0x4ed2a674, 0x744ee8d2, 0x1e223614, 0x141e2822, 0xdb76e492, 0x92db3f76, 0xa1e120c, 0xc0a181e, 0x6cb4fc48, 0x486c90b4, 0xe4378fb8, 0xb8e46b37 + , 0x5de7789f, 0x9f5d25e7, 0x6eb20fbd, 0xbd6e61b2, 0xef2a6943, 0x43ef862a, 0xa6f135c4, 0xc4a693f1, 0xa8e3da39, 0x39a872e3, 0xa4f7c631, 0x31a462f7, 0x37598ad3, 0xd337bd59, 0x8b8674f2, 0xf28bff86 + , 0x325683d5, 0xd532b156, 0x43c54e8b, 0x8b430dc5, 0x59eb856e, 0x6e59dceb, 0xb7c218da, 0xdab7afc2, 0x8c8f8e01, 0x18c028f, 0x64ac1db1, 0xb16479ac, 0xd26df19c, 0x9cd2236d, 0xe03b7249, 0x49e0923b + , 0xb4c71fd8, 0xd8b4abc7, 0xfa15b9ac, 0xacfa4315, 0x709faf3, 0xf307fd09, 0x256fa0cf, 0xcf25856f, 0xafea20ca, 0xcaaf8fea, 0x8e897df4, 0xf48ef389, 0xe9206747, 0x47e98e20, 0x18283810, 0x10182028 + , 0xd5640b6f, 0x6fd5de64, 0x888373f0, 0xf088fb83, 0x6fb1fb4a, 0x4a6f94b1, 0x7296ca5c, 0x5c72b896, 0x246c5438, 0x3824706c, 0xf1085f57, 0x57f1ae08, 0xc7522173, 0x73c7e652, 0x51f36497, 0x975135f3 + , 0x2365aecb, 0xcb238d65, 0x7c8425a1, 0xa17c5984, 0x9cbf57e8, 0xe89ccbbf, 0x21635d3e, 0x3e217c63, 0xdd7cea96, 0x96dd377c, 0xdc7f1e61, 0x61dcc27f, 0x86919c0d, 0xd861a91, 0x85949b0f, 0xf851e94 + , 0x90ab4be0, 0xe090dbab, 0x42c6ba7c, 0x7c42f8c6, 0xc4572671, 0x71c4e257, 0xaae529cc, 0xccaa83e5, 0xd873e390, 0x90d83b73, 0x50f0906, 0x6050c0f, 0x103f4f7, 0xf701f503, 0x12362a1c, 0x1c123836 + , 0xa3fe3cc2, 0xc2a39ffe, 0x5fe18b6a, 0x6a5fd4e1, 0xf910beae, 0xaef94710, 0xd06b0269, 0x69d0d26b, 0x91a8bf17, 0x17912ea8, 0x58e87199, 0x995829e8, 0x2769533a, 0x3a277469, 0xb9d0f727, 0x27b94ed0 + , 0x384891d9, 0xd938a948, 0x1335deeb, 0xeb13cd35, 0xb3cee52b, 0x2bb356ce, 0x33557722, 0x22334455, 0xbbd604d2, 0xd2bbbfd6, 0x709039a9, 0xa9704990, 0x89808707, 0x7890e80, 0xa7f2c133, 0x33a766f2 + , 0xb6c1ec2d, 0x2db65ac1, 0x22665a3c, 0x3c227866, 0x92adb815, 0x15922aad, 0x2060a9c9, 0xc9208960, 0x49db5c87, 0x874915db, 0xff1ab0aa, 0xaaff4f1a, 0x7888d850, 0x5078a088, 0x7a8e2ba5, 0xa57a518e + , 0x8f8a8903, 0x38f068a, 0xf8134a59, 0x59f8b213, 0x809b9209, 0x980129b, 0x1739231a, 0x1a173439, 0xda751065, 0x65daca75, 0x315384d7, 0xd731b553, 0xc651d584, 0x84c61351, 0xb8d303d0, 0xd0b8bbd3 + , 0xc35edc82, 0x82c31f5e, 0xb0cbe229, 0x29b052cb, 0x7799c35a, 0x5a77b499, 0x11332d1e, 0x1e113c33, 0xcb463d7b, 0x7bcbf646, 0xfc1fb7a8, 0xa8fc4b1f, 0xd6610c6d, 0x6dd6da61, 0x3a4e622c, 0x2c3a584e + }; #endif /* __tables_h */ diff --git a/src/crypto/skein_port.h b/src/crypto/skein_port.h index 4b521c7c..e0b135d5 100644 --- a/src/crypto/skein_port.h +++ b/src/crypto/skein_port.h @@ -111,10 +111,10 @@ typedef uint64_t u64b_t; /* 64-bit unsigned integer */ #if PLATFORM_BYTE_ORDER == IS_BIG_ENDIAN - /* here for big-endian CPUs */ +/* here for big-endian CPUs */ #define SKEIN_NEED_SWAP (1) #elif PLATFORM_BYTE_ORDER == IS_LITTLE_ENDIAN - /* here for x86 and x86-64 CPUs (and other detected little-endian CPUs) */ +/* here for x86 and x86-64 CPUs (and other detected little-endian CPUs) */ #define SKEIN_NEED_SWAP (0) #if PLATFORM_MUST_ALIGN == 0 /* ok to use "fast" versions? */ #define Skein_Put64_LSB_First(dst08,src64,bCnt) memcpy(dst08,src64,bCnt) @@ -134,14 +134,14 @@ typedef uint64_t u64b_t; /* 64-bit unsigned integer */ #ifndef Skein_Swap64 /* swap for big-endian, nop for little-endian */ #if SKEIN_NEED_SWAP #define Skein_Swap64(w64) \ - ( (( ((u64b_t)(w64)) & 0xFF) << 56) | \ - (((((u64b_t)(w64)) >> 8) & 0xFF) << 48) | \ - (((((u64b_t)(w64)) >>16) & 0xFF) << 40) | \ - (((((u64b_t)(w64)) >>24) & 0xFF) << 32) | \ - (((((u64b_t)(w64)) >>32) & 0xFF) << 24) | \ - (((((u64b_t)(w64)) >>40) & 0xFF) << 16) | \ - (((((u64b_t)(w64)) >>48) & 0xFF) << 8) | \ - (((((u64b_t)(w64)) >>56) & 0xFF) ) ) + ( (( ((u64b_t)(w64)) & 0xFF) << 56) | \ + (((((u64b_t)(w64)) >> 8) & 0xFF) << 48) | \ + (((((u64b_t)(w64)) >>16) & 0xFF) << 40) | \ + (((((u64b_t)(w64)) >>24) & 0xFF) << 32) | \ + (((((u64b_t)(w64)) >>32) & 0xFF) << 24) | \ + (((((u64b_t)(w64)) >>40) & 0xFF) << 16) | \ + (((((u64b_t)(w64)) >>48) & 0xFF) << 8) | \ + (((((u64b_t)(w64)) >>56) & 0xFF) ) ) #else #define Skein_Swap64(w64) (w64) #endif @@ -149,38 +149,42 @@ typedef uint64_t u64b_t; /* 64-bit unsigned integer */ #ifndef Skein_Put64_LSB_First -void Skein_Put64_LSB_First(u08b_t *dst,const u64b_t *src,size_t bCnt) +void Skein_Put64_LSB_First(u08b_t* dst, const u64b_t* src, size_t bCnt) #ifdef SKEIN_PORT_CODE /* instantiate the function code here? */ - { /* this version is fully portable (big-endian or little-endian), but slow */ - size_t n; +{ + /* this version is fully portable (big-endian or little-endian), but slow */ + size_t n; - for (n=0;n>3] >> (8*(n&7))); - } + for(n = 0; n < bCnt; n++) + { + dst[n] = (u08b_t)(src[n >> 3] >> (8 * (n & 7))); + } +} #else - ; /* output only the function prototype */ +; /* output only the function prototype */ #endif #endif /* ifndef Skein_Put64_LSB_First */ #ifndef Skein_Get64_LSB_First -void Skein_Get64_LSB_First(u64b_t *dst,const u08b_t *src,size_t wCnt) +void Skein_Get64_LSB_First(u64b_t* dst, const u08b_t* src, size_t wCnt) #ifdef SKEIN_PORT_CODE /* instantiate the function code here? */ - { /* this version is fully portable (big-endian or little-endian), but slow */ - size_t n; +{ + /* this version is fully portable (big-endian or little-endian), but slow */ + size_t n; - for (n=0;n<8*wCnt;n+=8) - dst[n/8] = (((u64b_t) src[n ]) ) + - (((u64b_t) src[n+1]) << 8) + - (((u64b_t) src[n+2]) << 16) + - (((u64b_t) src[n+3]) << 24) + - (((u64b_t) src[n+4]) << 32) + - (((u64b_t) src[n+5]) << 40) + - (((u64b_t) src[n+6]) << 48) + - (((u64b_t) src[n+7]) << 56) ; - } + for(n = 0; n < 8 * wCnt; n += 8) + dst[n / 8] = (((u64b_t) src[n ])) + + (((u64b_t) src[n + 1]) << 8) + + (((u64b_t) src[n + 2]) << 16) + + (((u64b_t) src[n + 3]) << 24) + + (((u64b_t) src[n + 4]) << 32) + + (((u64b_t) src[n + 5]) << 40) + + (((u64b_t) src[n + 6]) << 48) + + (((u64b_t) src[n + 7]) << 56) ; +} #else - ; /* output only the function prototype */ +; /* output only the function prototype */ #endif #endif /* ifndef Skein_Get64_LSB_First */ diff --git a/src/crypto/soft_aes.h b/src/crypto/soft_aes.h index 0703f98d..7fa5fb25 100644 --- a/src/crypto/soft_aes.h +++ b/src/crypto/soft_aes.h @@ -39,43 +39,43 @@ #define saes_data(w) {\ - w(0x63), w(0x7c), w(0x77), w(0x7b), w(0xf2), w(0x6b), w(0x6f), w(0xc5),\ - w(0x30), w(0x01), w(0x67), w(0x2b), w(0xfe), w(0xd7), w(0xab), w(0x76),\ - w(0xca), w(0x82), w(0xc9), w(0x7d), w(0xfa), w(0x59), w(0x47), w(0xf0),\ - w(0xad), w(0xd4), w(0xa2), w(0xaf), w(0x9c), w(0xa4), w(0x72), w(0xc0),\ - w(0xb7), w(0xfd), w(0x93), w(0x26), w(0x36), w(0x3f), w(0xf7), w(0xcc),\ - w(0x34), w(0xa5), w(0xe5), w(0xf1), w(0x71), w(0xd8), w(0x31), w(0x15),\ - w(0x04), w(0xc7), w(0x23), w(0xc3), w(0x18), w(0x96), w(0x05), w(0x9a),\ - w(0x07), w(0x12), w(0x80), w(0xe2), w(0xeb), w(0x27), w(0xb2), w(0x75),\ - w(0x09), w(0x83), w(0x2c), w(0x1a), w(0x1b), w(0x6e), w(0x5a), w(0xa0),\ - w(0x52), w(0x3b), w(0xd6), w(0xb3), w(0x29), w(0xe3), w(0x2f), w(0x84),\ - w(0x53), w(0xd1), w(0x00), w(0xed), w(0x20), w(0xfc), w(0xb1), w(0x5b),\ - w(0x6a), w(0xcb), w(0xbe), w(0x39), w(0x4a), w(0x4c), w(0x58), w(0xcf),\ - w(0xd0), w(0xef), w(0xaa), w(0xfb), w(0x43), w(0x4d), w(0x33), w(0x85),\ - w(0x45), w(0xf9), w(0x02), w(0x7f), w(0x50), w(0x3c), w(0x9f), w(0xa8),\ - w(0x51), w(0xa3), w(0x40), w(0x8f), w(0x92), w(0x9d), w(0x38), w(0xf5),\ - w(0xbc), w(0xb6), w(0xda), w(0x21), w(0x10), w(0xff), w(0xf3), w(0xd2),\ - w(0xcd), w(0x0c), w(0x13), w(0xec), w(0x5f), w(0x97), w(0x44), w(0x17),\ - w(0xc4), w(0xa7), w(0x7e), w(0x3d), w(0x64), w(0x5d), w(0x19), w(0x73),\ - w(0x60), w(0x81), w(0x4f), w(0xdc), w(0x22), w(0x2a), w(0x90), w(0x88),\ - w(0x46), w(0xee), w(0xb8), w(0x14), w(0xde), w(0x5e), w(0x0b), w(0xdb),\ - w(0xe0), w(0x32), w(0x3a), w(0x0a), w(0x49), w(0x06), w(0x24), w(0x5c),\ - w(0xc2), w(0xd3), w(0xac), w(0x62), w(0x91), w(0x95), w(0xe4), w(0x79),\ - w(0xe7), w(0xc8), w(0x37), w(0x6d), w(0x8d), w(0xd5), w(0x4e), w(0xa9),\ - w(0x6c), w(0x56), w(0xf4), w(0xea), w(0x65), w(0x7a), w(0xae), w(0x08),\ - w(0xba), w(0x78), w(0x25), w(0x2e), w(0x1c), w(0xa6), w(0xb4), w(0xc6),\ - w(0xe8), w(0xdd), w(0x74), w(0x1f), w(0x4b), w(0xbd), w(0x8b), w(0x8a),\ - w(0x70), w(0x3e), w(0xb5), w(0x66), w(0x48), w(0x03), w(0xf6), w(0x0e),\ - w(0x61), w(0x35), w(0x57), w(0xb9), w(0x86), w(0xc1), w(0x1d), w(0x9e),\ - w(0xe1), w(0xf8), w(0x98), w(0x11), w(0x69), w(0xd9), w(0x8e), w(0x94),\ - w(0x9b), w(0x1e), w(0x87), w(0xe9), w(0xce), w(0x55), w(0x28), w(0xdf),\ - w(0x8c), w(0xa1), w(0x89), w(0x0d), w(0xbf), w(0xe6), w(0x42), w(0x68),\ - w(0x41), w(0x99), w(0x2d), w(0x0f), w(0xb0), w(0x54), w(0xbb), w(0x16) } + w(0x63), w(0x7c), w(0x77), w(0x7b), w(0xf2), w(0x6b), w(0x6f), w(0xc5),\ + w(0x30), w(0x01), w(0x67), w(0x2b), w(0xfe), w(0xd7), w(0xab), w(0x76),\ + w(0xca), w(0x82), w(0xc9), w(0x7d), w(0xfa), w(0x59), w(0x47), w(0xf0),\ + w(0xad), w(0xd4), w(0xa2), w(0xaf), w(0x9c), w(0xa4), w(0x72), w(0xc0),\ + w(0xb7), w(0xfd), w(0x93), w(0x26), w(0x36), w(0x3f), w(0xf7), w(0xcc),\ + w(0x34), w(0xa5), w(0xe5), w(0xf1), w(0x71), w(0xd8), w(0x31), w(0x15),\ + w(0x04), w(0xc7), w(0x23), w(0xc3), w(0x18), w(0x96), w(0x05), w(0x9a),\ + w(0x07), w(0x12), w(0x80), w(0xe2), w(0xeb), w(0x27), w(0xb2), w(0x75),\ + w(0x09), w(0x83), w(0x2c), w(0x1a), w(0x1b), w(0x6e), w(0x5a), w(0xa0),\ + w(0x52), w(0x3b), w(0xd6), w(0xb3), w(0x29), w(0xe3), w(0x2f), w(0x84),\ + w(0x53), w(0xd1), w(0x00), w(0xed), w(0x20), w(0xfc), w(0xb1), w(0x5b),\ + w(0x6a), w(0xcb), w(0xbe), w(0x39), w(0x4a), w(0x4c), w(0x58), w(0xcf),\ + w(0xd0), w(0xef), w(0xaa), w(0xfb), w(0x43), w(0x4d), w(0x33), w(0x85),\ + w(0x45), w(0xf9), w(0x02), w(0x7f), w(0x50), w(0x3c), w(0x9f), w(0xa8),\ + w(0x51), w(0xa3), w(0x40), w(0x8f), w(0x92), w(0x9d), w(0x38), w(0xf5),\ + w(0xbc), w(0xb6), w(0xda), w(0x21), w(0x10), w(0xff), w(0xf3), w(0xd2),\ + w(0xcd), w(0x0c), w(0x13), w(0xec), w(0x5f), w(0x97), w(0x44), w(0x17),\ + w(0xc4), w(0xa7), w(0x7e), w(0x3d), w(0x64), w(0x5d), w(0x19), w(0x73),\ + w(0x60), w(0x81), w(0x4f), w(0xdc), w(0x22), w(0x2a), w(0x90), w(0x88),\ + w(0x46), w(0xee), w(0xb8), w(0x14), w(0xde), w(0x5e), w(0x0b), w(0xdb),\ + w(0xe0), w(0x32), w(0x3a), w(0x0a), w(0x49), w(0x06), w(0x24), w(0x5c),\ + w(0xc2), w(0xd3), w(0xac), w(0x62), w(0x91), w(0x95), w(0xe4), w(0x79),\ + w(0xe7), w(0xc8), w(0x37), w(0x6d), w(0x8d), w(0xd5), w(0x4e), w(0xa9),\ + w(0x6c), w(0x56), w(0xf4), w(0xea), w(0x65), w(0x7a), w(0xae), w(0x08),\ + w(0xba), w(0x78), w(0x25), w(0x2e), w(0x1c), w(0xa6), w(0xb4), w(0xc6),\ + w(0xe8), w(0xdd), w(0x74), w(0x1f), w(0x4b), w(0xbd), w(0x8b), w(0x8a),\ + w(0x70), w(0x3e), w(0xb5), w(0x66), w(0x48), w(0x03), w(0xf6), w(0x0e),\ + w(0x61), w(0x35), w(0x57), w(0xb9), w(0x86), w(0xc1), w(0x1d), w(0x9e),\ + w(0xe1), w(0xf8), w(0x98), w(0x11), w(0x69), w(0xd9), w(0x8e), w(0x94),\ + w(0x9b), w(0x1e), w(0x87), w(0xe9), w(0xce), w(0x55), w(0x28), w(0xdf),\ + w(0x8c), w(0xa1), w(0x89), w(0x0d), w(0xbf), w(0xe6), w(0x42), w(0x68),\ + w(0x41), w(0x99), w(0x2d), w(0x0f), w(0xb0), w(0x54), w(0xbb), w(0x16) } #define SAES_WPOLY 0x011b #define saes_b2w(b0, b1, b2, b3) (((uint32_t)(b3) << 24) | \ - ((uint32_t)(b2) << 16) | ((uint32_t)(b1) << 8) | (b0)) + ((uint32_t)(b2) << 16) | ((uint32_t)(b1) << 8) | (b0)) #define saes_f2(x) ((x<<1) ^ (((x>>7) & 1) * SAES_WPOLY)) #define saes_f3(x) (saes_f2(x) ^ x) @@ -86,44 +86,48 @@ #define saes_u2(p) saes_b2w( p, saes_f3(p), saes_f2(p), p) #define saes_u3(p) saes_b2w( p, p, saes_f3(p), saes_f2(p)) -alignas(16) const uint32_t saes_table[4][256] = { saes_data(saes_u0), saes_data(saes_u1), saes_data(saes_u2), saes_data(saes_u3) }; -alignas(16) const uint8_t saes_sbox[256] = saes_data(saes_h0); +const uint32_t saes_table[4][256] = { saes_data(saes_u0), saes_data(saes_u1), saes_data(saes_u2), saes_data(saes_u3) }; +const uint8_t saes_sbox[256] = saes_data(saes_h0); static inline __m128i soft_aesenc(const uint32_t* in, __m128i key) { - const uint32_t x0 = in[0]; - const uint32_t x1 = in[1]; - const uint32_t x2 = in[2]; - const uint32_t x3 = in[3]; + const uint32_t x0 = in[0]; + const uint32_t x1 = in[1]; + const uint32_t x2 = in[2]; + const uint32_t x3 = in[3]; - __m128i out = _mm_set_epi32( - (saes_table[0][x3 & 0xff] ^ saes_table[1][(x0 >> 8) & 0xff] ^ saes_table[2][(x1 >> 16) & 0xff] ^ saes_table[3][x2 >> 24]), - (saes_table[0][x2 & 0xff] ^ saes_table[1][(x3 >> 8) & 0xff] ^ saes_table[2][(x0 >> 16) & 0xff] ^ saes_table[3][x1 >> 24]), - (saes_table[0][x1 & 0xff] ^ saes_table[1][(x2 >> 8) & 0xff] ^ saes_table[2][(x3 >> 16) & 0xff] ^ saes_table[3][x0 >> 24]), - (saes_table[0][x0 & 0xff] ^ saes_table[1][(x1 >> 8) & 0xff] ^ saes_table[2][(x2 >> 16) & 0xff] ^ saes_table[3][x3 >> 24])); + __m128i out = _mm_set_epi32( + (saes_table[0][x3 & 0xff] ^ saes_table[1][(x0 >> 8) & 0xff] ^ saes_table[2][(x1 >> 16) & 0xff] ^ + saes_table[3][x2 >> 24]), + (saes_table[0][x2 & 0xff] ^ saes_table[1][(x3 >> 8) & 0xff] ^ saes_table[2][(x0 >> 16) & 0xff] ^ + saes_table[3][x1 >> 24]), + (saes_table[0][x1 & 0xff] ^ saes_table[1][(x2 >> 8) & 0xff] ^ saes_table[2][(x3 >> 16) & 0xff] ^ + saes_table[3][x0 >> 24]), + (saes_table[0][x0 & 0xff] ^ saes_table[1][(x1 >> 8) & 0xff] ^ saes_table[2][(x2 >> 16) & 0xff] ^ + saes_table[3][x3 >> 24])); - return _mm_xor_si128(out, key); + return _mm_xor_si128(out, key); } static inline uint32_t sub_word(uint32_t key) { - return (saes_sbox[key >> 24 ] << 24) | - (saes_sbox[(key >> 16) & 0xff] << 16 ) | - (saes_sbox[(key >> 8) & 0xff] << 8 ) | - saes_sbox[key & 0xff]; + return (saes_sbox[key >> 24 ] << 24) | + (saes_sbox[(key >> 16) & 0xff] << 16) | + (saes_sbox[(key >> 8) & 0xff] << 8) | + saes_sbox[key & 0xff]; } #if defined(__clang__) || defined(XMRIG_ARM) static inline uint32_t _rotr(uint32_t value, uint32_t amount) { - return (value >> amount) | (value << ((32 - amount) & 31)); + return (value >> amount) | (value << ((32 - amount) & 31)); } #endif template static inline __m128i soft_aeskeygenassist(__m128i key) { - const uint32_t X1 = sub_word(_mm_cvtsi128_si32(_mm_shuffle_epi32(key, 0x55))); - const uint32_t X3 = sub_word(_mm_cvtsi128_si32(_mm_shuffle_epi32(key, 0xFF))); - return _mm_set_epi32(_rotr(X3, 8) ^ rcon, X3, _rotr(X1, 8) ^ rcon, X1); + const uint32_t X1 = sub_word(_mm_cvtsi128_si32(_mm_shuffle_epi32(key, 0x55))); + const uint32_t X3 = sub_word(_mm_cvtsi128_si32(_mm_shuffle_epi32(key, 0xFF))); + return _mm_set_epi32(_rotr(X3, 8) ^ rcon, X3, _rotr(X1, 8) ^ rcon, X1); } diff --git a/src/donate.h b/src/donate.h index 3a000948..58698277 100644 --- a/src/donate.h +++ b/src/donate.h @@ -37,7 +37,10 @@ * XMR: 48edfHu7V9Z84YzzMa6fUueoELZ9ZRXq9VetWzYGzKt52XU5xvqgzYnDK9URnRoJMk1j8nLwEVsaSWJ4fhdUyZijBGUicoD * BTC: 1P7ujsXeX7GxQwHNnJsRMgAdNkFZmNVqJT */ -constexpr const int kDonateLevel = 5; +enum +{ + kDonateLevel = 5, +}; #endif /* __DONATE_H__ */ diff --git a/src/interfaces/IClientListener.h b/src/interfaces/IClientListener.h index f6e7fd3c..1d4236d9 100644 --- a/src/interfaces/IClientListener.h +++ b/src/interfaces/IClientListener.h @@ -36,12 +36,12 @@ class SubmitResult; class IClientListener { public: - virtual ~IClientListener() {} + virtual ~IClientListener() {} - virtual void onClose(Client *client, int failures) = 0; - virtual void onJobReceived(Client *client, const Job &job) = 0; - virtual void onLoginSuccess(Client *client) = 0; - virtual void onResultAccepted(Client *client, const SubmitResult &result, const char *error) = 0; + virtual void onClose(Client* client, int failures) = 0; + virtual void onJobReceived(Client* client, const Job & job) = 0; + virtual void onLoginSuccess(Client* client) = 0; + virtual void onResultAccepted(Client* client, const SubmitResult & result, const std::string & error) = 0; }; diff --git a/src/interfaces/IConsoleListener.h b/src/interfaces/IConsoleListener.h index 723f87df..51aaf50c 100644 --- a/src/interfaces/IConsoleListener.h +++ b/src/interfaces/IConsoleListener.h @@ -28,9 +28,9 @@ class IConsoleListener { public: - virtual ~IConsoleListener() {} + virtual ~IConsoleListener() {} - virtual void onConsoleCommand(char command) = 0; + virtual void onConsoleCommand(char command) = 0; }; diff --git a/src/interfaces/IJobResultListener.h b/src/interfaces/IJobResultListener.h index 483a2062..4bde82cf 100644 --- a/src/interfaces/IJobResultListener.h +++ b/src/interfaces/IJobResultListener.h @@ -32,9 +32,9 @@ class JobResult; class IJobResultListener { public: - virtual ~IJobResultListener() {} + virtual ~IJobResultListener() {} - virtual void onJobResult(const JobResult &result) = 0; + virtual void onJobResult(const JobResult & result) = 0; }; diff --git a/src/interfaces/ILogBackend.h b/src/interfaces/ILogBackend.h index 458b504c..bdd7f23f 100644 --- a/src/interfaces/ILogBackend.h +++ b/src/interfaces/ILogBackend.h @@ -24,17 +24,25 @@ #ifndef __ILOGBACKEND_H__ #define __ILOGBACKEND_H__ - -#include - +#include "interfaces/interface.h" +#include class ILogBackend { public: - virtual ~ILogBackend() {} + enum Level + { + ERR, + WARNING, + NOTICE, + INFO, + DEBUG + }; - virtual void message(int level, const char* fmt, va_list args) = 0; - virtual void text(const char* fmt, va_list args) = 0; + virtual ~ILogBackend() {} + + virtual void message(Level level, const std::string & txt) = 0; + virtual void text(const std::string & txt) = 0; }; diff --git a/src/interfaces/IStrategy.h b/src/interfaces/IStrategy.h index 660529ea..bbf9c523 100644 --- a/src/interfaces/IStrategy.h +++ b/src/interfaces/IStrategy.h @@ -24,24 +24,23 @@ #ifndef __ISTRATEGY_H__ #define __ISTRATEGY_H__ - +#include "interfaces/interface.h" #include - class JobResult; class IStrategy { public: - virtual ~IStrategy() {} + virtual ~IStrategy() {} - virtual bool isActive() const = 0; - virtual int64_t submit(const JobResult &result) = 0; - virtual void connect() = 0; - virtual void resume() = 0; - virtual void stop() = 0; - virtual void tick(uint64_t now) = 0; + virtual bool isActive() const = 0; + virtual int64_t submit(const JobResult & result) = 0; + virtual void connect() = 0; + virtual void resume() = 0; + virtual void stop() = 0; + virtual void tick(uint64_t now) = 0; }; diff --git a/src/interfaces/IStrategyListener.h b/src/interfaces/IStrategyListener.h index 60f95734..8fb7469c 100644 --- a/src/interfaces/IStrategyListener.h +++ b/src/interfaces/IStrategyListener.h @@ -24,26 +24,23 @@ #ifndef __ISTRATEGYLISTENER_H__ #define __ISTRATEGYLISTENER_H__ - #include - +#include class Client; class IStrategy; class Job; class SubmitResult; - class IStrategyListener { public: - virtual ~IStrategyListener() {} + virtual ~IStrategyListener() {} - virtual void onActive(Client *client) = 0; - virtual void onJob(Client *client, const Job &job) = 0; - virtual void onPause(IStrategy *strategy) = 0; - virtual void onResultAccepted(Client *client, const SubmitResult &result, const char *error) = 0; + virtual void onActive(Client* client) = 0; + virtual void onJob(Client* client, const Job & job) = 0; + virtual void onPause(IStrategy* strategy) = 0; + virtual void onResultAccepted(Client* client, const SubmitResult & result, const std::string & error) = 0; }; - #endif // __ISTRATEGYLISTENER_H__ diff --git a/src/interfaces/IWorker.h b/src/interfaces/IWorker.h index b9b6eb0a..b613c5db 100644 --- a/src/interfaces/IWorker.h +++ b/src/interfaces/IWorker.h @@ -31,11 +31,11 @@ class IWorker { public: - virtual ~IWorker() {} + virtual ~IWorker() {} - virtual uint64_t hashCount() const = 0; - virtual uint64_t timestamp() const = 0; - virtual void start() = 0; + virtual uint64_t hashCount() const = 0; + virtual uint64_t timestamp() const = 0; + virtual void start() = 0; }; diff --git a/src/interfaces/interface.h b/src/interfaces/interface.h new file mode 100644 index 00000000..25c76abc --- /dev/null +++ b/src/interfaces/interface.h @@ -0,0 +1,62 @@ +/* XMRig - enWILLYado + * + * 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 . + */ +#ifndef __INTERFACE_H__ +#define __INTERFACE_H__ + +#ifdef _WIN32 +#if defined(_MSC_VER) && _MSC_VER < 1900 + +// C++-11 +#define override + +// VS +#include +#include +#include +#define snprintf c99_snprintf +#define vsnprintf c99_vsnprintf + +__inline int c99_vsnprintf(char* outBuf, size_t size, const char* format, va_list ap) +{ + int count = -1; + + if(size != 0) + { + count = _vsnprintf_s(outBuf, size, _TRUNCATE, format, ap); + } + if(count == -1) + { + count = _vscprintf(format, ap); + } + + return count; +} + +__inline int c99_snprintf(char* outBuf, size_t size, const char* format, ...) +{ + int count; + va_list ap; + + va_start(ap, format); + count = c99_vsnprintf(outBuf, size, format, ap); + va_end(ap); + + return count; +} +#endif +#endif + +#endif // __INTERFACE_H__ diff --git a/src/log/ConsoleLog.cpp b/src/log/ConsoleLog.cpp index 3656d48c..904cd860 100644 --- a/src/log/ConsoleLog.cpp +++ b/src/log/ConsoleLog.cpp @@ -21,134 +21,98 @@ * along with this program. If not, see . */ - #include #include #include #include #include -#ifdef WIN32 -# include -# include -#endif - +#include #include "log/ConsoleLog.h" #include "log/Log.h" -#include "Options.h" - ConsoleLog::ConsoleLog(bool colors) : - m_colors(colors), - m_stream(nullptr) + m_colors(colors) { - if (uv_tty_init(uv_default_loop(), &m_tty, 1, 0) < 0) { - Options::i()->setColors(false); - m_colors = false; - return; - } - - uv_tty_set_mode(&m_tty, UV_TTY_MODE_NORMAL); - m_uvBuf.base = m_buf; - m_stream = reinterpret_cast(&m_tty); - -# ifdef WIN32 - HANDLE handle = GetStdHandle(STD_INPUT_HANDLE); - if (handle != INVALID_HANDLE_VALUE) { - DWORD mode = 0; - if (GetConsoleMode(handle, &mode)) { - mode &= ~ENABLE_QUICK_EDIT_MODE; - SetConsoleMode(handle, mode | ENABLE_EXTENDED_FLAGS); - } - } -# endif } - -void ConsoleLog::message(int level, const char* fmt, va_list args) +void ConsoleLog::message(Level level, const std::string & text) { - time_t now = time(nullptr); - tm stime; + if(!isWritable()) + { + return; + } -# ifdef _WIN32 - localtime_s(&stime, &now); -# else - localtime_r(&now, &stime); -# endif + // + // + time_t now = time(nullptr); + tm stime; - const char* color = nullptr; - if (m_colors) { - switch (level) { - case Log::ERR: - color = Log::kCL_RED; - break; +#ifdef _WIN32 + localtime_s(&stime, &now); +#else + localtime_r(&now, &stime); +#endif - case Log::WARNING: - color = Log::kCL_YELLOW; - break; + char buf[25]; + int size = snprintf(buf, sizeof(buf), "[%d-%02d-%02d %02d:%02d:%02d] ", + stime.tm_year + 1900, + stime.tm_mon + 1, + stime.tm_mday, + stime.tm_hour, + stime.tm_min, + stime.tm_sec); - case Log::NOTICE: - color = Log::kCL_WHITE; - break; + // + // + std::string colorIni, colorEnd; + if(m_colors) + { + colorEnd = Log::CL_N(); + switch(level) + { + case ILogBackend::ERR: + colorIni = Log::CL_RED(); + break; - case Log::DEBUG: - color = Log::kCL_GRAY; - break; + case ILogBackend::WARNING: + colorIni = Log::CL_YELLOW(); + break; - default: - color = ""; - break; - } - } + case ILogBackend::NOTICE: + colorIni = Log::CL_WHITE(); + break; - snprintf(m_fmt, sizeof(m_fmt) - 1, "[%d-%02d-%02d %02d:%02d:%02d]%s %s%s\n", - stime.tm_year + 1900, - stime.tm_mon + 1, - stime.tm_mday, - stime.tm_hour, - stime.tm_min, - stime.tm_sec, - m_colors ? color : "", - fmt, - m_colors ? Log::kCL_N : "" - ); + case ILogBackend::DEBUG: + colorIni = Log::CL_GRAY(); + break; - print(args); + default: + break; + } + } + + print(std::string(buf, size) + colorIni + text + colorEnd); } - -void ConsoleLog::text(const char* fmt, va_list args) +void ConsoleLog::text(const std::string & txt) { - snprintf(m_fmt, sizeof(m_fmt) - 1, "%s%s\n", fmt, m_colors ? Log::kCL_N : ""); + if(!isWritable()) + { + return; + } - print(args); + print(txt); } - bool ConsoleLog::isWritable() const { - if (!m_stream || uv_is_writable(m_stream) != 1) { - return false; - } - - const uv_handle_type type = uv_guess_handle(1); - return type == UV_TTY || type == UV_NAMED_PIPE; + return std::cout.good(); } - -void ConsoleLog::print(va_list args) +void ConsoleLog::print(const std::string & txt) { - m_uvBuf.len = vsnprintf(m_buf, sizeof(m_buf) - 1, m_fmt, args); - if (m_uvBuf.len <= 0) { - return; - } - - if (!isWritable()) { - fputs(m_buf, stdout); - fflush(stdout); - } - else { - uv_try_write(m_stream, &m_uvBuf, 1); - } + std::cout << txt << std::endl; + std::cout.flush(); } diff --git a/src/log/ConsoleLog.h b/src/log/ConsoleLog.h index a04a27c5..a0c78ebb 100644 --- a/src/log/ConsoleLog.h +++ b/src/log/ConsoleLog.h @@ -34,21 +34,16 @@ class ConsoleLog : public ILogBackend { public: - ConsoleLog(bool colors); + ConsoleLog(bool colors); - void message(int level, const char *fmt, va_list args) override; - void text(const char *fmt, va_list args) override; + void message(Level level, const std::string & txt) override; + void text(const std::string & txt) override; private: - bool isWritable() const; - void print(va_list args); + bool isWritable() const; + void print(const std::string & txt); - bool m_colors; - char m_buf[512]; - char m_fmt[256]; - uv_buf_t m_uvBuf; - uv_stream_t *m_stream; - uv_tty_t m_tty; + bool m_colors; }; #endif /* __CONSOLELOG_H__ */ diff --git a/src/log/FileLog.cpp b/src/log/FileLog.cpp index 5eeb252c..d32fe0b2 100644 --- a/src/log/FileLog.cpp +++ b/src/log/FileLog.cpp @@ -28,70 +28,68 @@ #include #include +#include +#include +#include "log/Log.h" #include "log/FileLog.h" - -FileLog::FileLog(const char *fileName) +FileLog::FileLog(const std::string & fileName) + : m_file_name(fileName) { - uv_fs_t req; - m_file = uv_fs_open(uv_default_loop(), &req, fileName, O_CREAT | O_APPEND | O_WRONLY, 0644, nullptr); - uv_fs_req_cleanup(&req); } - -void FileLog::message(int level, const char* fmt, va_list args) +void FileLog::message(Level level, const std::string & txt) { - if (m_file < 0) { - return; - } + if(!isWritable()) + { + return; + } - time_t now = time(nullptr); - tm stime; + // + // + time_t now = time(nullptr); + tm stime; -# ifdef _WIN32 - localtime_s(&stime, &now); -# else - localtime_r(&now, &stime); -# endif +#ifdef _WIN32 + localtime_s(&stime, &now); +#else + localtime_r(&now, &stime); +#endif - char *buf = new char[512]; - int size = snprintf(buf, 23, "[%d-%02d-%02d %02d:%02d:%02d] ", - stime.tm_year + 1900, - stime.tm_mon + 1, - stime.tm_mday, - stime.tm_hour, - stime.tm_min, - stime.tm_sec); + char buf[25]; + int size = snprintf(buf, sizeof(buf), "[%d-%02d-%02d %02d:%02d:%02d] ", + stime.tm_year + 1900, + stime.tm_mon + 1, + stime.tm_mday, + stime.tm_hour, + stime.tm_min, + stime.tm_sec); - size = vsnprintf(buf + size, 512 - size - 1, fmt, args) + size; - buf[size] = '\n'; - - write(buf, size + 1); + // + // + write(std::string(buf, size) + txt); } - -void FileLog::text(const char* fmt, va_list args) +void FileLog::text(const std::string & txt) { - message(0, fmt, args); + if(!isWritable()) + { + return; + } + + write(txt); } - - -void FileLog::onWrite(uv_fs_t *req) +bool FileLog::isWritable() const { - delete [] static_cast(req->data); - - uv_fs_req_cleanup(req); - delete req; + return (m_file_name != "") && std::ofstream(m_file_name, std::ios_base::app).good(); } - -void FileLog::write(char *data, size_t size) +void FileLog::write(const std::string & txt) { - uv_buf_t buf = uv_buf_init(data, (unsigned int) size); - uv_fs_t *req = new uv_fs_t; - req->data = buf.base; + std::ofstream outfile; - uv_fs_write(uv_default_loop(), req, m_file, &buf, 1, 0, FileLog::onWrite); + outfile.open(m_file_name, std::ios_base::app); + outfile << txt << std::endl; } diff --git a/src/log/FileLog.h b/src/log/FileLog.h index 2b3ca5d4..bac31282 100644 --- a/src/log/FileLog.h +++ b/src/log/FileLog.h @@ -24,27 +24,21 @@ #ifndef __FILELOG_H__ #define __FILELOG_H__ - -#include - - #include "interfaces/ILogBackend.h" - class FileLog : public ILogBackend { public: - FileLog(const char *fileName); + FileLog(const std::string & fileName); - void message(int level, const char* fmt, va_list args) override; - void text(const char* fmt, va_list args) override; + void message(Level level, const std::string & txt) override; + void text(const std::string & txt) override; private: - static void onWrite(uv_fs_t *req); + bool isWritable() const; + void write(const std::string & txt); - void write(char *data, size_t size); - - int m_file; + const std::string m_file_name; }; #endif /* __FILELOG_H__ */ diff --git a/src/log/Log.cpp b/src/log/Log.cpp index 3e5d5671..d2b465a1 100644 --- a/src/log/Log.cpp +++ b/src/log/Log.cpp @@ -28,47 +28,35 @@ #include #include - #include "interfaces/ILogBackend.h" #include "log/Log.h" +Log* Log::m_self = nullptr; -Log *Log::m_self = nullptr; - - -void Log::message(Log::Level level, const char* fmt, ...) +void Log::message(ILogBackend::Level level, const std::string & text) { - va_list args; - va_list copy; - va_start(args, fmt); - - for (ILogBackend *backend : m_backends) { - va_copy(copy, args); - backend->message(level, fmt, copy); - va_end(copy); - } + for(size_t i = 0; i < m_backends.size(); ++i) + { + auto backend = m_backends[i]; + backend->message(level, text); + } } - -void Log::text(const char* fmt, ...) +void Log::text(const std::string & text) { - va_list args; - va_list copy; - va_start(args, fmt); + for(size_t i = 0; i < m_backends.size(); ++i) + { + auto backend = m_backends[i]; + backend->text(text); + } - for (ILogBackend *backend : m_backends) { - va_copy(copy, args); - backend->text(fmt, copy); - va_end(copy); - } - - va_end(args); } - Log::~Log() { - for (auto backend : m_backends) { - delete backend; - } + for(size_t i = 0; i < m_backends.size(); ++i) + { + auto backend = m_backends[i]; + delete backend; + } } diff --git a/src/log/Log.h b/src/log/Log.h index fd944d80..41b0fdef 100644 --- a/src/log/Log.h +++ b/src/log/Log.h @@ -24,70 +24,102 @@ #ifndef __LOG_H__ #define __LOG_H__ - -#include #include +#include - -class ILogBackend; - +#include "interfaces/ILogBackend.h" class Log { public: - enum Level { - ERR, - WARNING, - NOTICE, - INFO, - DEBUG - }; - constexpr static const char* kCL_N = "\x1B[0m"; - constexpr static const char* kCL_RED = "\x1B[31m"; - constexpr static const char* kCL_YELLOW = "\x1B[33m"; - constexpr static const char* kCL_WHITE = "\x1B[01;37m"; + static const std::string & CL_N() + { + static const std::string kCL_N = "\x1B[0m"; + return kCL_N; + } + static const std::string & CL_RED() + { + static const std::string kCL_RED = "\x1B[31m"; + return kCL_RED; + } + static const std::string & CL_YELLOW() + { + static const std::string kCL_YELLOW = "\x1B[33m"; + return kCL_YELLOW; + } + static const std::string & CL_WHITE() + { + static const std::string kCL_WHITE = "\x1B[01;37m"; + return kCL_WHITE; + } + static const std::string & CL_GRAY() + { -# ifdef WIN32 - constexpr static const char* kCL_GRAY = "\x1B[01;30m"; -# else - constexpr static const char* kCL_GRAY = "\x1B[90m"; -# endif +#ifdef WIN32 + static const std::string kCL_GRAY = "\x1B[01;30m"; +#else + static const std::string kCL_GRAY = "\x1B[90m"; +#endif + return kCL_GRAY; + } - static inline Log* i() { return m_self; } - static inline void add(ILogBackend *backend) { i()->m_backends.push_back(backend); } - static inline void init() { if (!m_self) { m_self = new Log();} } - static inline void release() { delete m_self; } + static inline Log* i() + { + return m_self; + } + static inline void add(ILogBackend* backend) + { + i()->m_backends.push_back(backend); + } + static inline void init() + { + if(!m_self) + { + m_self = new Log(); + } + } + static inline void release() + { + delete m_self; + } - void message(Level level, const char* fmt, ...); - void text(const char* fmt, ...); + void message(ILogBackend::Level level, const std::string & text); + void text(const std::string & text); + static inline std::string TO_STRING(const std::basic_ostream & i) + { + const std::stringstream & stream = static_cast(i); + return stream.str(); + } private: - inline Log() {} - ~Log(); + inline Log() {} + ~Log(); - static Log *m_self; - std::vector m_backends; + static Log* m_self; + std::vector m_backends; }; -#define LOG_ERR(x, ...) Log::i()->message(Log::ERR, x, ##__VA_ARGS__) -#define LOG_WARN(x, ...) Log::i()->message(Log::WARNING, x, ##__VA_ARGS__) -#define LOG_NOTICE(x, ...) Log::i()->message(Log::NOTICE, x, ##__VA_ARGS__) -#define LOG_INFO(x, ...) Log::i()->message(Log::INFO, x, ##__VA_ARGS__) +#define PRINT_MSG(x) Log::i()->text(Log::TO_STRING(std::stringstream() << x)) + +#define LOG_ERR(x) Log::i()->message(ILogBackend::ERR, Log::TO_STRING(std::stringstream() << x)) +#define LOG_WARN(x) Log::i()->message(ILogBackend::WARNING, Log::TO_STRING(std::stringstream() << x)) +#define LOG_NOTICE(x) Log::i()->message(ILogBackend::NOTICE, Log::TO_STRING(std::stringstream() << x)) +#define LOG_INFO(x) Log::i()->message(ILogBackend::INFO, Log::TO_STRING(std::stringstream() << x)) #ifdef APP_DEBUG -# define LOG_DEBUG(x, ...) Log::i()->message(Log::DEBUG, x, ##__VA_ARGS__) +#define LOG_DEBUG(x) Log::i()->message(ILogBackend::DEBUG, Log::TO_STRING(std::stringstream() << x)) #else -# define LOG_DEBUG(x, ...) +#define LOG_DEBUG(x) #endif #if defined(APP_DEBUG) || defined(APP_DEVEL) -# define LOG_DEBUG_ERR(x, ...) Log::i()->message(Log::ERR, x, ##__VA_ARGS__) -# define LOG_DEBUG_WARN(x, ...) Log::i()->message(Log::WARNING, x, ##__VA_ARGS__) +#define LOG_DEBUG_ERR(x) Log::i()->message(ILogBackend::ERR, Log::TO_STRING(std::stringstream() << x)) +#define LOG_DEBUG_WARN(x) Log::i()->message(ILogBackend::WARNING, Log::TO_STRING(std::stringstream() << x)) #else -# define LOG_DEBUG_ERR(x, ...) -# define LOG_DEBUG_WARN(x, ...) +#define LOG_DEBUG_ERR(x) +#define LOG_DEBUG_WARN(x) #endif #endif /* __LOG_H__ */ diff --git a/src/log/SysLog.cpp b/src/log/SysLog.cpp index f9b16cca..cdafd508 100644 --- a/src/log/SysLog.cpp +++ b/src/log/SysLog.cpp @@ -21,6 +21,7 @@ * along with this program. If not, see . */ +#ifdef HAVE_SYSLOG_H #include @@ -31,17 +32,18 @@ SysLog::SysLog() { - openlog(APP_ID, LOG_PID, LOG_USER); + openlog(APP_ID, LOG_PID, LOG_USER); } - -void SysLog::message(int level, const char *fmt, va_list args) +void SysLog::text(const std::string & txt) { - vsyslog(level, fmt, args); + message(INFO, txt); } -void SysLog::text(const char *fmt, va_list args) +void SysLog::message(Level level, const std::string & txt) { - message(LOG_INFO, fmt, args); + syslog(level == INFO ? LOG_INFO : LOG_NOTICE, "%s", txt); } + +#endif \ No newline at end of file diff --git a/src/log/SysLog.h b/src/log/SysLog.h index 38de1a6a..771e36d2 100644 --- a/src/log/SysLog.h +++ b/src/log/SysLog.h @@ -31,10 +31,10 @@ class SysLog : public ILogBackend { public: - SysLog(); + SysLog(); - void message(int level, const char *fmt, va_list args) override; - void text(const char *fmt, va_list args) override; + void message(Level level, const std::string & txt) override; + void text(const std::string & txt) override; }; #endif /* __SYSLOG_BACKEND_H__ */ diff --git a/src/net/Client.cpp b/src/net/Client.cpp index fb83acd2..fe220aec 100644 --- a/src/net/Client.cpp +++ b/src/net/Client.cpp @@ -4,7 +4,7 @@ * Copyright 2014 Lucas Jones * Copyright 2014-2016 Wolf9466 * Copyright 2016 Jay D Dee - * Copyright 2016-2017 XMRig + * Copyright 2016-2018 XMRig * * * This program is free software: you can redistribute it and/or modify @@ -37,63 +37,63 @@ #include "rapidjson/stringbuffer.h" #include "rapidjson/writer.h" - #ifdef XMRIG_PROXY_PROJECT -# include "proxy/JobResult.h" +#include "proxy/JobResult.h" #else -# include "net/JobResult.h" +#include "net/JobResult.h" #endif #ifdef _MSC_VER -# define strncasecmp(x,y,z) _strnicmp(x,y,z) +#define strncasecmp(x,y,z) _strnicmp(x,y,z) #endif int64_t Client::m_sequence = 1; -Client::Client(int id, const char *agent, IClientListener *listener) : - m_quiet(false), - m_agent(agent), - m_listener(listener), - m_id(id), - m_retryPause(5000), - m_failures(0), - m_recvBufPos(0), - m_state(UnconnectedState), - m_expire(0), - m_stream(nullptr), - m_socket(nullptr) +Client::Client(int id, const std::string & agent, IClientListener* listener) : + m_quiet(false), + m_encrypted(false), + m_agent(agent), + m_listener(listener), + m_id(id), + m_retryPause(5000), + m_failures(0), + m_recvBufPos(0), + m_state(UnconnectedState), + m_expire(0), + m_stream(nullptr), + m_socket(nullptr) { - memset(m_ip, 0, sizeof(m_ip)); - memset(&m_hints, 0, sizeof(m_hints)); + memset(&m_hints, 0, sizeof(m_hints)); + memset(m_keystream, 0, sizeof(m_keystream)); - m_resolver.data = this; + m_resolver.data = this; - m_hints.ai_family = PF_INET; - m_hints.ai_socktype = SOCK_STREAM; - m_hints.ai_protocol = IPPROTO_TCP; + m_hints.ai_family = PF_INET; + m_hints.ai_socktype = SOCK_STREAM; + m_hints.ai_protocol = IPPROTO_TCP; - m_recvBuf.base = m_buf; - m_recvBuf.len = sizeof(m_buf); + m_recvBuf.base = m_buf; + m_recvBuf.len = sizeof(m_buf); -# ifndef XMRIG_PROXY_PROJECT - m_keepAliveTimer.data = this; - uv_timer_init(uv_default_loop(), &m_keepAliveTimer); -# endif +#ifndef XMRIG_PROXY_PROJECT + m_keepAliveTimer.data = this; + uv_timer_init(uv_default_loop(), &m_keepAliveTimer); +#endif } Client::~Client() { - delete m_socket; + delete m_socket; } void Client::connect() { - resolve(m_url.host()); + resolve(m_url.host()); } @@ -102,550 +102,713 @@ void Client::connect() * * @param url */ -void Client::connect(const Url *url) +void Client::connect(const Url & url) { - setUrl(url); - resolve(m_url.host()); + setUrl(url); + resolve(m_url.host()); } void Client::disconnect() { -# ifndef XMRIG_PROXY_PROJECT - uv_timer_stop(&m_keepAliveTimer); -# endif +#ifndef XMRIG_PROXY_PROJECT + uv_timer_stop(&m_keepAliveTimer); +#endif - m_expire = 0; - m_failures = -1; + m_expire = 0; + m_failures = -1; - close(); + close(); } -void Client::setUrl(const Url *url) +void Client::setUrl(const Url & url) { - if (!url || !url->isValid()) { - return; - } + if(false == url.isValid()) + { + return; + } - m_url = url; + if(url.hasKeystream()) + { + url.copyKeystream(m_keystream, sizeof(m_keystream)); + m_encrypted = true; + } + else + { + m_encrypted = false; + } + + m_url = url; } void Client::tick(uint64_t now) { - if (m_expire == 0 || now < m_expire) { - return; - } + if(m_expire == 0 || now < m_expire) + { + return; + } - if (m_state == ConnectedState) { - LOG_DEBUG_ERR("[%s:%u] timeout", m_url.host(), m_url.port()); - close(); - } + if(m_state == ConnectedState) + { + LOG_DEBUG_ERR("[" << m_url.host() << ":" << m_url.port() << "] timeout"); + close(); + } - if (m_state == ConnectingState) { - connect(); - } + if(m_state == ConnectingState) + { + connect(); + } } -int64_t Client::submit(const JobResult &result) +int64_t Client::submit(const JobResult & result) { -# ifdef XMRIG_PROXY_PROJECT - const char *nonce = result.nonce; - const char *data = result.result; -# else - char nonce[9]; - char data[65]; +#ifdef XMRIG_PROXY_PROJECT + const std::string nonce = result.nonce; + const std::string data = result.result; +#else + char nonce_buffer[9]; + char data_buffer[65]; - Job::toHex(reinterpret_cast(&result.nonce), 4, nonce); - nonce[8] = '\0'; + char* nonceChar = (char*)(&result.nonce); + Job::toHex(std::string(nonceChar, 4), nonce_buffer); + nonce_buffer[8] = '\0'; - Job::toHex(result.result, 32, data); - data[64] = '\0'; -# endif + char* resultChar = (char*)(&result.result); + Job::toHex(std::string(resultChar, 32), data_buffer); + data_buffer[64] = '\0'; - const size_t size = snprintf(m_sendBuf, sizeof(m_sendBuf), "{\"id\":%" PRIu64 ",\"jsonrpc\":\"2.0\",\"method\":\"submit\",\"params\":{\"id\":\"%s\",\"job_id\":\"%s\",\"nonce\":\"%s\",\"result\":\"%s\"}}\n", - m_sequence, m_rpcId, result.jobId.data(), nonce, data); + const std::string nonce = nonce_buffer; + const std::string data = data_buffer; +#endif - m_results[m_sequence] = SubmitResult(m_sequence, result.diff, result.actualDiff()); - return send(size); + const size_t size = snprintf(m_sendBuf, sizeof(m_sendBuf), + "{\"id\":%" PRIu64 + ",\"jsonrpc\":\"2.0\",\"method\":\"submit\",\"params\":{\"id\":\"%s\",\"job_id\":\"%s\",\"nonce\":\"%s\",\"result\":\"%s\"}}\n", + m_sequence, m_rpcId, + result.jobId.data().c_str(), nonce.c_str(), data.c_str()); + + m_results[m_sequence] = SubmitResult(m_sequence, result.diff, result.actualDiff()); + return send(size); } -bool Client::isCriticalError(const char *message) +bool Client::isCriticalError(const std::string & message) { - if (!message) { - return false; - } + if(message.empty()) + { + return false; + } - if (strncasecmp(message, "Unauthenticated", 15) == 0) { - return true; - } + if(message == "Unauthenticated") + { + return true; + } - if (strncasecmp(message, "your IP is banned", 17) == 0) { - return true; - } + if(message == "your IP is banned") + { + return true; + } - if (strncasecmp(message, "IP Address currently banned", 27) == 0) { - return true; - } + if(message == "IP Address currently banned") + { + return true; + } - return false; + return false; } -bool Client::parseJob(const rapidjson::Value ¶ms, int *code) +bool Client::parseJob(const rapidjson::Value & params, int* code) { - if (!params.IsObject()) { - *code = 2; - return false; - } + if(!params.IsObject()) + { + *code = 2; + return false; + } - Job job(m_id, m_url.isNicehash()); - if (!job.setId(params["job_id"].GetString())) { - *code = 3; - return false; - } + Job job(m_id, m_url.isNicehash()); + if(!job.setId(params["job_id"].GetString())) + { + *code = 3; + return false; + } - if (!job.setBlob(params["blob"].GetString())) { - *code = 4; - return false; - } + if(!job.setBlob(params["blob"].GetString())) + { + *code = 4; + return false; + } - if (!job.setTarget(params["target"].GetString())) { - *code = 5; - return false; - } + if(!job.setTarget(params["target"].GetString())) + { + *code = 5; + return false; + } - if (m_job == job) { - if (!m_quiet) { - LOG_WARN("[%s:%u] duplicate job received, reconnect", m_url.host(), m_url.port()); - } + if(m_job == job) + { + if(!m_quiet) + { + LOG_WARN("[" << m_url.host() << ":" << m_url.port() << "] duplicate job received, reconnect"); + } - close(); - return false; - } + close(); + return false; + } - m_job = std::move(job); - return true; + m_job = std::move(job); + return true; } -bool Client::parseLogin(const rapidjson::Value &result, int *code) +bool Client::parseLogin(const rapidjson::Value & result, int* code) { - const char *id = result["id"].GetString(); - if (!id || strlen(id) >= sizeof(m_rpcId)) { - *code = 1; - return false; - } + const char* id = result["id"].GetString(); + if(!id || strlen(id) >= sizeof(m_rpcId)) + { + *code = 1; + return false; + } - memset(m_rpcId, 0, sizeof(m_rpcId)); - memcpy(m_rpcId, id, strlen(id)); + memset(m_rpcId, 0, sizeof(m_rpcId)); + memcpy(m_rpcId, id, strlen(id)); - return parseJob(result["job"], code); + return parseJob(result["job"], code); } -int Client::resolve(const char *host) +int Client::resolve(const std::string & host) { - setState(HostLookupState); + setState(HostLookupState); - m_expire = 0; - m_recvBufPos = 0; + m_expire = 0; + m_recvBufPos = 0; - if (m_failures == -1) { - m_failures = 0; - } + if(m_failures == -1) + { + m_failures = 0; + } - const int r = uv_getaddrinfo(uv_default_loop(), &m_resolver, Client::onResolved, host, NULL, &m_hints); - if (r) { - if (!m_quiet) { - LOG_ERR("[%s:%u] getaddrinfo error: \"%s\"", host, m_url.port(), uv_strerror(r)); - } - return 1; - } + const int r = uv_getaddrinfo(uv_default_loop(), &m_resolver, Client::onResolved, host.c_str(), NULL, &m_hints); + if(r) + { + if(!m_quiet) + { + LOG_ERR("[" << host << ":" << m_url.port() << "] getaddrinfo error: \"" << uv_strerror(r) << "\""); + } + return 1; + } - return 0; + return 0; } -int64_t Client::send(size_t size) +int64_t Client::send(size_t size, const bool encrypted) { - LOG_DEBUG("[%s:%u] send (%d bytes): \"%s\"", m_url.host(), m_url.port(), size, m_sendBuf); - if (state() != ConnectedState || !uv_is_writable(m_stream)) { - LOG_DEBUG_ERR("[%s:%u] send failed, invalid state: %d", m_url.host(), m_url.port(), m_state); - return -1; - } + LOG_DEBUG("[" << m_url.host() << ":" << m_url.port() << "] send(" << size << " bytes): \"" << m_sendBuf << + "\""); + if((state() != ConnectedState && state() != ProxingState) || !uv_is_writable(m_stream)) + { + LOG_DEBUG_ERR("[" << m_url.host() << ":" << m_url.port() << "] send failed, invalid state: " << m_state); + return -1; + } - uv_buf_t buf = uv_buf_init(m_sendBuf, (unsigned int) size); + if(encrypted && m_encrypted) + { + // Encrypt + for(size_t i = 0; i < std::min(size, sizeof(SendBuf)); ++i) + { + m_sendBuf[i] ^= m_keystream[i]; + } - if (uv_try_write(m_stream, &buf, 1) < 0) { - close(); - return -1; - } + char* send_encr_hex = static_cast(malloc(size * 2 + 1)); + memset(send_encr_hex, 0, size * 2 + 1); + Job::toHex(std::string(m_sendBuf, size), send_encr_hex); + send_encr_hex[size * 2] = '\0'; + LOG_DEBUG("[" << m_url.host() << ":" << m_url.port() << "] send encr.(" << size << " bytes): \"0x" << + send_encr_hex << "\""); + free(send_encr_hex); + } - m_expire = uv_now(uv_default_loop()) + kResponseTimeout; - return m_sequence++; + uv_buf_t buf = uv_buf_init(m_sendBuf, (unsigned int) size); + + if(uv_try_write(m_stream, &buf, 1) < 0) + { + close(); + return -1; + } + + m_expire = uv_now(uv_default_loop()) + kResponseTimeout; + return m_sequence++; } void Client::close() { - if (m_state == UnconnectedState || m_state == ClosingState || !m_socket) { - return; - } + if(m_state == UnconnectedState || m_state == ClosingState || !m_socket) + { + return; + } - setState(ClosingState); + setState(ClosingState); - if (uv_is_closing(reinterpret_cast(m_socket)) == 0) { - uv_close(reinterpret_cast(m_socket), Client::onClose); - } + if(uv_is_closing(reinterpret_cast(m_socket)) == 0) + { + uv_close(reinterpret_cast(m_socket), Client::onClose); + } } -void Client::connect(struct sockaddr *addr) +void Client::connect(struct sockaddr* addr) { - setState(ConnectingState); + setState(ConnectingState); - reinterpret_cast(addr)->sin_port = htons(m_url.port()); - delete m_socket; + reinterpret_cast(addr)->sin_port = htons(m_url.port()); + delete m_socket; - uv_connect_t *req = new uv_connect_t; - req->data = this; + uv_connect_t* req = new uv_connect_t; + req->data = this; - m_socket = new uv_tcp_t; - m_socket->data = this; + m_socket = new uv_tcp_t; + m_socket->data = this; - uv_tcp_init(uv_default_loop(), m_socket); - uv_tcp_nodelay(m_socket, 1); + uv_tcp_init(uv_default_loop(), m_socket); + uv_tcp_nodelay(m_socket, 1); -# ifndef WIN32 - uv_tcp_keepalive(m_socket, 1, 60); -# endif +#ifndef WIN32 + uv_tcp_keepalive(m_socket, 1, 60); +#endif - uv_tcp_connect(req, m_socket, reinterpret_cast(addr), Client::onConnect); + uv_tcp_connect(req, m_socket, reinterpret_cast(addr), Client::onConnect); } +void Client::prelogin() +{ + if(m_url.isProxyed()) + { + setState(ProxingState); + const std::string buffer = std::string("CONNECT ") + m_url.finalHost() + ":" + + std::to_string((unsigned long long)(m_url.finalPort())) + " HTTP/1.1\n"; + + const size_t size = buffer.size(); + memcpy(m_sendBuf, buffer.c_str(), size); + m_sendBuf[size] = '\n'; + m_sendBuf[size + 1] = '\0'; + + LOG_DEBUG("Prelogin send (" << size << " bytes): \"" << m_sendBuf << "\""); + send(size + 1, false); + } + else + { + setState(ConnectedState); + login(); + } +} void Client::login() { - m_results.clear(); + m_results.clear(); - rapidjson::Document doc; - doc.SetObject(); + rapidjson::Document doc; + doc.SetObject(); - auto &allocator = doc.GetAllocator(); + auto & allocator = doc.GetAllocator(); - doc.AddMember("id", 1, allocator); - doc.AddMember("jsonrpc", "2.0", allocator); - doc.AddMember("method", "login", allocator); + doc.AddMember("id", 1, allocator); + doc.AddMember("jsonrpc", "2.0", allocator); + doc.AddMember("method", "login", allocator); - rapidjson::Value params(rapidjson::kObjectType); - params.AddMember("login", rapidjson::StringRef(m_url.user()), allocator); - params.AddMember("pass", rapidjson::StringRef(m_url.password()), allocator); - params.AddMember("agent", rapidjson::StringRef(m_agent), allocator); + rapidjson::Value params(rapidjson::kObjectType); + params.AddMember("login", rapidjson::StringRef(m_url.user().c_str()), allocator); + params.AddMember("pass", rapidjson::StringRef(m_url.password().c_str()), allocator); + params.AddMember("agent", rapidjson::StringRef(m_agent.c_str()), allocator); - doc.AddMember("params", params, allocator); + doc.AddMember("params", params, allocator); - rapidjson::StringBuffer buffer(0, 512); - rapidjson::Writer writer(buffer); - doc.Accept(writer); + rapidjson::StringBuffer buffer(0, 512); + rapidjson::Writer writer(buffer); + doc.Accept(writer); - const size_t size = buffer.GetSize(); - if (size > (sizeof(m_buf) - 2)) { - return; - } + const size_t size = buffer.GetSize(); + if(size > (sizeof(m_buf) - 2)) + { + return; + } - memcpy(m_sendBuf, buffer.GetString(), size); - m_sendBuf[size] = '\n'; - m_sendBuf[size + 1] = '\0'; + memcpy(m_sendBuf, buffer.GetString(), size); + m_sendBuf[size] = '\n'; + m_sendBuf[size + 1] = '\0'; - send(size + 1); + send(size + 1); } -void Client::parse(char *line, size_t len) +void Client::parse(char* line, size_t len) { - startTimeout(); + startTimeout(); - line[len - 1] = '\0'; + line[len - 1] = '\0'; - LOG_DEBUG("[%s:%u] received (%d bytes): \"%s\"", m_url.host(), m_url.port(), len, line); + LOG_DEBUG("[" << m_url.host() << ":" << m_url.port() << "] received (" << len << " bytes): \"" << line << + "\""); - rapidjson::Document doc; - if (doc.ParseInsitu(line).HasParseError()) { - if (!m_quiet) { - LOG_ERR("[%s:%u] JSON decode failed: \"%s\"", m_url.host(), m_url.port(), rapidjson::GetParseError_En(doc.GetParseError())); - } + rapidjson::Document doc; + if(doc.ParseInsitu(line).HasParseError()) + { + if(!m_quiet) + { + LOG_ERR("[" << m_url.host() << ":" << m_url.port() << "] JSON decode failed: \"" << + rapidjson::GetParseError_En(doc.GetParseError()) << "\""); + } - return; - } + return; + } - if (!doc.IsObject()) { - return; - } + if(!doc.IsObject()) + { + return; + } - const rapidjson::Value &id = doc["id"]; - if (id.IsInt64()) { - parseResponse(id.GetInt64(), doc["result"], doc["error"]); - } - else { - parseNotification(doc["method"].GetString(), doc["params"], doc["error"]); - } + const rapidjson::Value & id = doc["id"]; + if(id.IsInt64()) + { + parseResponse(id.GetInt64(), doc["result"], doc["error"]); + } + else + { + parseNotification(doc["method"].GetString(), doc["params"], doc["error"]); + } } -void Client::parseNotification(const char *method, const rapidjson::Value ¶ms, const rapidjson::Value &error) +void Client::parseNotification(const char* method, const rapidjson::Value & params, + const rapidjson::Value & error) { - if (error.IsObject()) { - if (!m_quiet) { - LOG_ERR("[%s:%u] error: \"%s\", code: %d", m_url.host(), m_url.port(), error["message"].GetString(), error["code"].GetInt()); - } - return; - } + if(error.IsObject()) + { + if(!m_quiet) + { + LOG_ERR("[" << m_url.host() << ":" << m_url.port() << "] error: \"" << error["message"].GetString() << + "\", code: " << error["code"].GetInt()); + } + return; + } - if (!method) { - return; - } + if(!method) + { + return; + } - if (strcmp(method, "job") == 0) { - int code = -1; - if (parseJob(params, &code)) { - m_listener->onJobReceived(this, m_job); - } + if(strcmp(method, "job") == 0) + { + int code = -1; + if(parseJob(params, &code)) + { + m_listener->onJobReceived(this, m_job); + } - return; - } + return; + } - LOG_WARN("[%s:%u] unsupported method: \"%s\"", m_url.host(), m_url.port(), method); + LOG_WARN("[" << m_url.host() << ":" << m_url.port() << "] unsupported method: \"" << method << "\""); } -void Client::parseResponse(int64_t id, const rapidjson::Value &result, const rapidjson::Value &error) +void Client::parseResponse(int64_t id, const rapidjson::Value & result, const rapidjson::Value & error) { - if (error.IsObject()) { - const char *message = error["message"].GetString(); + if(error.IsObject()) + { + const char* message = error["message"].GetString(); - auto it = m_results.find(id); - if (it != m_results.end()) { - it->second.done(); - m_listener->onResultAccepted(this, it->second, message); - m_results.erase(it); - } - else if (!m_quiet) { - LOG_ERR("[%s:%u] error: \"%s\", code: %d", m_url.host(), m_url.port(), message, error["code"].GetInt()); - } + auto it = m_results.find(id); + if(it != m_results.end()) + { + it->second.done(); + m_listener->onResultAccepted(this, it->second, message); + m_results.erase(it); + } + else if(!m_quiet) + { + LOG_ERR("[" << m_url.host() << ":" << m_url.port() << "] error: \"" << message << "\", code: " << + error["code"].GetInt()); + } - if (id == 1 || isCriticalError(message)) { - close(); - } + if(id == 1 || isCriticalError(message)) + { + close(); + } - return; - } + return; + } - if (!result.IsObject()) { - return; - } + if(!result.IsObject()) + { + return; + } - if (id == 1) { - int code = -1; - if (!parseLogin(result, &code)) { - if (!m_quiet) { - LOG_ERR("[%s:%u] login error code: %d", m_url.host(), m_url.port(), code); - } + if(id == 1) + { + int code = -1; + if(!parseLogin(result, &code)) + { + if(!m_quiet) + { + LOG_ERR("[" << m_url.host() << ":" << m_url.port() << "] login error code: " << code); + } - return close(); - } + return close(); + } - m_failures = 0; - m_listener->onLoginSuccess(this); - m_listener->onJobReceived(this, m_job); - return; - } + m_failures = 0; + m_listener->onLoginSuccess(this); + m_listener->onJobReceived(this, m_job); + return; + } - auto it = m_results.find(id); - if (it != m_results.end()) { - it->second.done(); - m_listener->onResultAccepted(this, it->second, nullptr); - m_results.erase(it); - } + auto it = m_results.find(id); + if(it != m_results.end()) + { + it->second.done(); + m_listener->onResultAccepted(this, it->second, ""); + m_results.erase(it); + } } void Client::ping() { - send(snprintf(m_sendBuf, sizeof(m_sendBuf), "{\"id\":%" PRId64 ",\"jsonrpc\":\"2.0\",\"method\":\"keepalived\",\"params\":{\"id\":\"%s\"}}\n", m_sequence, m_rpcId)); + send(snprintf(m_sendBuf, sizeof(m_sendBuf), + "{\"id\":%" PRId64 ",\"jsonrpc\":\"2.0\",\"method\":\"keepalived\",\"params\":{\"id\":\"%s\"}}\n", m_sequence, + m_rpcId)); } void Client::reconnect() { - setState(ConnectingState); + setState(ConnectingState); -# ifndef XMRIG_PROXY_PROJECT - if (m_url.isKeepAlive()) { - uv_timer_stop(&m_keepAliveTimer); - } -# endif +#ifndef XMRIG_PROXY_PROJECT + if(m_url.isKeepAlive()) + { + uv_timer_stop(&m_keepAliveTimer); + } +#endif - if (m_failures == -1) { - return m_listener->onClose(this, -1); - } + if(m_failures == -1) + { + return m_listener->onClose(this, -1); + } - m_failures++; - m_listener->onClose(this, (int) m_failures); + m_failures++; + m_listener->onClose(this, (int) m_failures); - m_expire = uv_now(uv_default_loop()) + m_retryPause; + m_expire = uv_now(uv_default_loop()) + m_retryPause; } void Client::setState(SocketState state) { - LOG_DEBUG("[%s:%u] state: %d", m_url.host(), m_url.port(), state); + LOG_DEBUG("[" << m_url.host() << ":" << m_url.port() << "] state: " << state); - if (m_state == state) { - return; - } + if(m_state == state) + { + return; + } - m_state = state; + m_state = state; } void Client::startTimeout() { - m_expire = 0; + m_expire = 0; -# ifndef XMRIG_PROXY_PROJECT - if (!m_url.isKeepAlive()) { - return; - } +#ifndef XMRIG_PROXY_PROJECT + if(!m_url.isKeepAlive()) + { + return; + } - uv_timer_start(&m_keepAliveTimer, [](uv_timer_t *handle) { getClient(handle->data)->ping(); }, kKeepAliveTimeout, 0); -# endif + uv_timer_start(&m_keepAliveTimer, &Client::onTimeout, kKeepAliveTimeout, 0); +#endif } - -void Client::onAllocBuffer(uv_handle_t *handle, size_t suggested_size, uv_buf_t *buf) +void Client::onTimeout(uv_timer_t* handle) { - auto client = getClient(handle->data); - - buf->base = &client->m_recvBuf.base[client->m_recvBufPos]; - buf->len = client->m_recvBuf.len - (unsigned long)client->m_recvBufPos; + getClient(handle->data)->ping(); } - -void Client::onClose(uv_handle_t *handle) +void Client::onAllocBuffer(uv_handle_t* handle, size_t suggested_size, uv_buf_t* buf) { - auto client = getClient(handle->data); + auto client = getClient(handle->data); - delete client->m_socket; - - client->m_stream = nullptr; - client->m_socket = nullptr; - client->setState(UnconnectedState); - - client->reconnect(); + buf->base = &client->m_recvBuf.base[client->m_recvBufPos]; + buf->len = client->m_recvBuf.len - (unsigned long)client->m_recvBufPos; } -void Client::onConnect(uv_connect_t *req, int status) +void Client::onClose(uv_handle_t* handle) { - auto client = getClient(req->data); - if (status < 0) { - if (!client->m_quiet) { - LOG_ERR("[%s:%u] connect error: \"%s\"", client->m_url.host(), client->m_url.port(), uv_strerror(status)); - } + auto client = getClient(handle->data); - delete req; - client->close(); - return; - } + delete client->m_socket; - client->m_stream = static_cast(req->handle); - client->m_stream->data = req->data; - client->setState(ConnectedState); + client->m_stream = nullptr; + client->m_socket = nullptr; + client->setState(UnconnectedState); - uv_read_start(client->m_stream, Client::onAllocBuffer, Client::onRead); - delete req; - - client->login(); + client->reconnect(); } -void Client::onRead(uv_stream_t *stream, ssize_t nread, const uv_buf_t *buf) +void Client::onConnect(uv_connect_t* req, int status) { - auto client = getClient(stream->data); - if (nread < 0) { - if (nread != UV_EOF && !client->m_quiet) { - LOG_ERR("[%s:%u] read error: \"%s\"", client->m_url.host(), client->m_url.port(), uv_strerror((int) nread)); - } + auto client = getClient(req->data); + if(status < 0) + { + if(!client->m_quiet) + { + LOG_ERR("[" << client->m_url.host() << ":" << client->m_url.port() << "] connect error: \"" << uv_strerror( + status) << "\""); + } - return client->close(); - } + delete req; + client->close(); + return; + } - if ((size_t) nread > (sizeof(m_buf) - 8 - client->m_recvBufPos)) { - return client->close(); - } + client->m_stream = static_cast(req->handle); + client->m_stream->data = req->data; - client->m_recvBufPos += nread; + uv_read_start(client->m_stream, Client::onAllocBuffer, Client::onRead); + delete req; - char* end; - char* start = buf->base; - size_t remaining = client->m_recvBufPos; - - while ((end = static_cast(memchr(start, '\n', remaining))) != nullptr) { - end++; - size_t len = end - start; - client->parse(start, len); - - remaining -= len; - start = end; - } - - if (remaining == 0) { - client->m_recvBufPos = 0; - return; - } - - if (start == buf->base) { - return; - } - - memcpy(buf->base, start, remaining); - client->m_recvBufPos = remaining; + client->prelogin(); } -void Client::onResolved(uv_getaddrinfo_t *req, int status, struct addrinfo *res) +void Client::onRead(uv_stream_t* stream, ssize_t nread, const uv_buf_t* buf) { - auto client = getClient(req->data); - if (status < 0) { - LOG_ERR("[%s:%u] DNS error: \"%s\"", client->m_url.host(), client->m_url.port(), uv_strerror(status)); - return client->reconnect(); - } + auto client = getClient(stream->data); + if(nread < 0) + { + if(nread != UV_EOF && !client->m_quiet) + { + LOG_ERR("[" << client->m_url.host() << ":" << client->m_url.port() << "] read error: \"" << uv_strerror(( + int) nread) << "\""); + } - addrinfo *ptr = res; - std::vector ipv4; + return client->close(); + } - while (ptr != nullptr) { - if (ptr->ai_family == AF_INET) { - ipv4.push_back(ptr); - } + if((size_t) nread > (sizeof(Buf) - 8 - client->m_recvBufPos)) + { + return client->close(); + } - ptr = ptr->ai_next; - } + if(client->state() == ProxingState) + { + const char* const content = buf->base; + LOG_DEBUG("[" << client->m_url.host() << ":" << client->m_url.port() << "] received from proxy (" << nread << + " bytes): \"" << content << "\""); - if (ipv4.empty()) { - LOG_ERR("[%s:%u] DNS error: \"No IPv4 records found\"", client->m_url.host(), client->m_url.port()); - return client->reconnect(); - } + if(content == strstr(content, "HTTP/1.1 200")) + { + LOG_INFO("[" << client->m_url.host() << ":" << client->m_url.port() << "] Proxy connected to " << + client->m_url.finalHost() << ":" << client->m_url.finalPort() << "!"); + client->setState(ConnectedState); + client->login(); + } + return; + } - ptr = ipv4[rand() % ipv4.size()]; + client->m_recvBufPos += nread; - uv_ip4_name(reinterpret_cast(ptr->ai_addr), client->m_ip, 16); + char* end; + char* start = buf->base; + size_t remaining = client->m_recvBufPos; - client->connect(ptr->ai_addr); - uv_freeaddrinfo(res); + if(client->m_encrypted) + { + char* read_encr_hex = static_cast(malloc(nread * 2 + 1)); + memset(read_encr_hex, 0, nread * 2 + 1); + Job::toHex(std::string(start, nread), read_encr_hex); + LOG_DEBUG("[" << client->m_ip << "] read encr. (" << nread << " bytes): 0x\"" << read_encr_hex << "\""); + free(read_encr_hex); + + // DeEncrypt + for(int i = 0; i < (int)nread; ++i) + { + start[i] ^= client->m_keystream[i]; + } + } + + while((end = static_cast(memchr(start, '\n', remaining))) != nullptr) + { + end++; + size_t len = end - start; + client->parse(start, len); + + remaining -= len; + start = end; + } + + if(remaining == 0) + { + client->m_recvBufPos = 0; + return; + } + + if(start == buf->base) + { + return; + } + + memcpy(buf->base, start, remaining); + client->m_recvBufPos = remaining; +} + + +void Client::onResolved(uv_getaddrinfo_t* req, int status, struct addrinfo* res) +{ + auto client = getClient(req->data); + if(status < 0) + { + LOG_ERR("[" << client->m_url.host() << ":" << client->m_url.port() << "] DNS error: \"" << uv_strerror( + status) << "\""); + return client->reconnect(); + } + + addrinfo* ptr = res; + std::vector ipv4; + + while(ptr != nullptr) + { + if(ptr->ai_family == AF_INET) + { + ipv4.push_back(ptr); + } + + ptr = ptr->ai_next; + } + + if(ipv4.empty()) + { + LOG_ERR("[" << client->m_url.host() << ":" << client->m_url.port() << + "] DNS error: \"No IPv4 records found\""); + return client->reconnect(); + } + + ptr = ipv4[rand() % ipv4.size()]; + + char buf[16]; + uv_ip4_name(reinterpret_cast(ptr->ai_addr), buf, sizeof(buf)); + client->setIP(buf); + + client->connect(ptr->ai_addr); + uv_freeaddrinfo(res); } diff --git a/src/net/Client.h b/src/net/Client.h index 699f4903..722947a8 100644 --- a/src/net/Client.h +++ b/src/net/Client.h @@ -42,88 +42,134 @@ class JobResult; class Client { public: - enum SocketState { - UnconnectedState, - HostLookupState, - ConnectingState, - ConnectedState, - ClosingState - }; + enum SocketState + { + UnconnectedState, + HostLookupState, + ConnectingState, + ProxingState, + ConnectedState, + ClosingState + }; - constexpr static int kResponseTimeout = 20 * 1000; - constexpr static int kKeepAliveTimeout = 60 * 1000; + enum + { + kResponseTimeout = 20 * 1000, + kKeepAliveTimeout = 60 * 1000, + }; - Client(int id, const char *agent, IClientListener *listener); - ~Client(); + Client(int id, const std::string & agent, IClientListener* listener); + ~Client(); - int64_t submit(const JobResult &result); - void connect(); - void connect(const Url *url); - void disconnect(); - void setUrl(const Url *url); - void tick(uint64_t now); + int64_t submit(const JobResult & result); + void connect(); + void connect(const Url & url); + void disconnect(); + void setUrl(const Url & url); + void tick(uint64_t now); - inline bool isReady() const { return m_state == ConnectedState && m_failures == 0; } - inline const char *host() const { return m_url.host(); } - inline const char *ip() const { return m_ip; } - inline const Job &job() const { return m_job; } - inline int id() const { return m_id; } - inline SocketState state() const { return m_state; } - inline uint16_t port() const { return m_url.port(); } - inline void setQuiet(bool quiet) { m_quiet = quiet; } - inline void setRetryPause(int ms) { m_retryPause = ms; } + inline bool isReady() const + { + return m_state == ConnectedState && m_failures == 0; + } + inline const std::string & host() const + { + return m_url.host(); + } + inline const std::string & ip() const + { + return m_ip; + } + inline void setIP(const std::string & iIp) + { + m_ip = iIp; + } + inline const Job & job() const + { + return m_job; + } + inline int id() const + { + return m_id; + } + inline SocketState state() const + { + return m_state; + } + inline uint16_t port() const + { + return m_url.port(); + } + inline void setQuiet(bool quiet) + { + m_quiet = quiet; + } + inline void setRetryPause(int ms) + { + m_retryPause = ms; + } private: - bool isCriticalError(const char *message); - bool parseJob(const rapidjson::Value ¶ms, int *code); - bool parseLogin(const rapidjson::Value &result, int *code); - int resolve(const char *host); - int64_t send(size_t size); - void close(); - void connect(struct sockaddr *addr); - void login(); - void parse(char *line, size_t len); - void parseNotification(const char *method, const rapidjson::Value ¶ms, const rapidjson::Value &error); - void parseResponse(int64_t id, const rapidjson::Value &result, const rapidjson::Value &error); - void ping(); - void reconnect(); - void setState(SocketState state); - void startTimeout(); + bool isCriticalError(const std::string & message); + bool parseJob(const rapidjson::Value & params, int* code); + bool parseLogin(const rapidjson::Value & result, int* code); + int resolve(const std::string & host); + int64_t send(size_t size, const bool encrypted = true); + void close(); + void connect(struct sockaddr* addr); + void prelogin(); + void login(); + void parse(char* line, size_t len); + void parseNotification(const char* method, const rapidjson::Value & params, const rapidjson::Value & error); + void parseResponse(int64_t id, const rapidjson::Value & result, const rapidjson::Value & error); + void ping(); + void reconnect(); + void setState(SocketState state); + void startTimeout(); - static void onAllocBuffer(uv_handle_t *handle, size_t suggested_size, uv_buf_t *buf); - static void onClose(uv_handle_t *handle); - static void onConnect(uv_connect_t *req, int status); - static void onRead(uv_stream_t *stream, ssize_t nread, const uv_buf_t *buf); - static void onResolved(uv_getaddrinfo_t *req, int status, struct addrinfo *res); + static void onAllocBuffer(uv_handle_t* handle, size_t suggested_size, uv_buf_t* buf); + static void onClose(uv_handle_t* handle); + static void onConnect(uv_connect_t* req, int status); + static void onTimeout(uv_timer_t* handle); + static void onRead(uv_stream_t* stream, ssize_t nread, const uv_buf_t* buf); + static void onResolved(uv_getaddrinfo_t* req, int status, struct addrinfo* res); - static inline Client *getClient(void *data) { return static_cast(data); } + static inline Client* getClient(void* data) + { + return static_cast(data); + } - addrinfo m_hints; - bool m_quiet; - char m_buf[2048]; - char m_ip[17]; - char m_rpcId[64]; - char m_sendBuf[768]; - const char *m_agent; - IClientListener *m_listener; - int m_id; - int m_retryPause; - int64_t m_failures; - Job m_job; - size_t m_recvBufPos; - SocketState m_state; - static int64_t m_sequence; - std::map m_results; - uint64_t m_expire; - Url m_url; - uv_buf_t m_recvBuf; - uv_getaddrinfo_t m_resolver; - uv_stream_t *m_stream; - uv_tcp_t *m_socket; + typedef char Buf[2048]; + typedef char SendBuf[768]; -# ifndef XMRIG_PROXY_PROJECT - uv_timer_t m_keepAliveTimer; -# endif + addrinfo m_hints; + bool m_quiet; + char m_buf[sizeof(Buf)]; + std::string m_ip; + char m_rpcId[64]; + char m_sendBuf[sizeof(SendBuf)]; + char m_keystream[sizeof(SendBuf)]; + bool m_encrypted; + const std::string & m_agent; + IClientListener* m_listener; + int m_id; + int m_retryPause; + int64_t m_failures; + Job m_job; + size_t m_recvBufPos; + SocketState m_state; + static int64_t m_sequence; + std::map m_results; + uint64_t m_expire; + Url m_url; + uv_buf_t m_recvBuf; + uv_getaddrinfo_t m_resolver; + uv_stream_t* m_stream; + uv_tcp_t* m_socket; + +#ifndef XMRIG_PROXY_PROJECT + uv_timer_t m_keepAliveTimer; +#endif }; diff --git a/src/net/Job.cpp b/src/net/Job.cpp index c3d33739..6d617a2d 100644 --- a/src/net/Job.cpp +++ b/src/net/Job.cpp @@ -28,40 +28,45 @@ #include "net/Job.h" -static inline unsigned char hf_hex2bin(char c, bool &err) +static inline unsigned char hf_hex2bin(char c, bool & err) { - if (c >= '0' && c <= '9') { - return c - '0'; - } - else if (c >= 'a' && c <= 'f') { - return c - 'a' + 0xA; - } - else if (c >= 'A' && c <= 'F') { - return c - 'A' + 0xA; - } + if(c >= '0' && c <= '9') + { + return c - '0'; + } + else if(c >= 'a' && c <= 'f') + { + return c - 'a' + 0xA; + } + else if(c >= 'A' && c <= 'F') + { + return c - 'A' + 0xA; + } - err = true; - return 0; + err = true; + return 0; } static inline char hf_bin2hex(unsigned char c) { - if (c <= 0x9) { - return '0' + c; - } + if(c <= 0x9) + { + return '0' + c; + } - return 'a' - 0xA + c; + return 'a' - 0xA + c; } Job::Job(int poolId, bool nicehash) : - m_nicehash(nicehash), - m_poolId(poolId), - m_threadId(-1), - m_size(0), - m_diff(0), - m_target(0) + m_nicehash(nicehash), + m_poolId(poolId), + m_threadId(-1), + m_id(), + m_size(0), + m_diff(0), + m_target(0) { } @@ -71,105 +76,119 @@ Job::~Job() } -bool Job::setBlob(const char *blob) +bool Job::setBlob(const char* blob) { - if (!blob) { - return false; - } + if(!blob) + { + return false; + } - m_size = strlen(blob); - if (m_size % 2 != 0) { - return false; - } + m_size = strlen(blob); + if(m_size % 2 != 0) + { + return false; + } - m_size /= 2; - if (m_size < 76 || m_size >= sizeof(m_blob)) { - return false; - } + m_size /= 2; + if(m_size < 76 || m_size >= sizeof(m_blob)) + { + return false; + } - if (!fromHex(blob, (int) m_size * 2, m_blob)) { - return false; - } + if(!fromHex(blob, (int) m_size * 2, m_blob)) + { + return false; + } - if (*nonce() != 0 && !m_nicehash) { - m_nicehash = true; - } + if(*nonce() != 0 && !m_nicehash) + { + m_nicehash = true; + } -# ifdef XMRIG_PROXY_PROJECT - memset(m_rawBlob, 0, sizeof(m_rawBlob)); - memcpy(m_rawBlob, blob, m_size * 2); -# endif +#ifdef XMRIG_PROXY_PROJECT + memset(m_rawBlob, 0, sizeof(m_rawBlob)); + memcpy(m_rawBlob, blob, m_size * 2); +#endif - return true; + return true; } -bool Job::setTarget(const char *target) +bool Job::setTarget(const char* target) { - if (!target) { - return false; - } + if(!target) + { + return false; + } - const size_t len = strlen(target); + const size_t len = strlen(target); - if (len <= 8) { - uint32_t tmp = 0; - char str[8]; - memcpy(str, target, len); + if(len <= 8) + { + uint32_t tmp = 0; + char str[8]; + memcpy(str, target, len); - if (!fromHex(str, 8, reinterpret_cast(&tmp)) || tmp == 0) { - return false; - } + if(!fromHex(str, 8, reinterpret_cast(&tmp)) || tmp == 0) + { + return false; + } - m_target = 0xFFFFFFFFFFFFFFFFULL / (0xFFFFFFFFULL / static_cast(tmp)); - } - else if (len <= 16) { - m_target = 0; - char str[16]; - memcpy(str, target, len); + m_target = 0xFFFFFFFFFFFFFFFFULL / (0xFFFFFFFFULL / static_cast(tmp)); + } + else if(len <= 16) + { + m_target = 0; + char str[16]; + memcpy(str, target, len); - if (!fromHex(str, 16, reinterpret_cast(&m_target)) || m_target == 0) { - return false; - } - } - else { - return false; - } + if(!fromHex(str, 16, reinterpret_cast(&m_target)) || m_target == 0) + { + return false; + } + } + else + { + return false; + } -# ifdef XMRIG_PROXY_PROJECT - memset(m_rawTarget, 0, sizeof(m_rawTarget)); - memcpy(m_rawTarget, target, len); -# endif +#ifdef XMRIG_PROXY_PROJECT + memset(m_rawTarget, 0, sizeof(m_rawTarget)); + memcpy(m_rawTarget, target, len); +#endif - m_diff = toDiff(m_target); - return true; + m_diff = toDiff(m_target); + return true; } bool Job::fromHex(const char* in, unsigned int len, unsigned char* out) { - bool error = false; - for (unsigned int i = 0; i < len; i += 2) { - out[i / 2] = (hf_hex2bin(in[i], error) << 4) | hf_hex2bin(in[i + 1], error); + bool error = false; + for(unsigned int i = 0; i < len; i += 2) + { + out[i / 2] = (hf_hex2bin(in[i], error) << 4) | hf_hex2bin(in[i + 1], error); - if (error) { - return false; - } - } - return true; + if(error) + { + return false; + } + } + return true; } -void Job::toHex(const unsigned char* in, unsigned int len, char* out) +void Job::toHex(const std::string & in, char* out) { - for (unsigned int i = 0; i < len; i++) { - out[i * 2] = hf_bin2hex((in[i] & 0xF0) >> 4); - out[i * 2 + 1] = hf_bin2hex(in[i] & 0x0F); - } + for(size_t i = 0; i < in.size(); ++i) + { + out[i * 2] = hf_bin2hex((in[i] & 0xF0) >> 4); + out[i * 2 + 1] = hf_bin2hex(in[i] & 0x0F); + } } -bool Job::operator==(const Job &other) const +bool Job::operator==(const Job & other) const { - return m_id == other.m_id && memcmp(m_blob, other.m_blob, sizeof(m_blob)) == 0; + return m_id == other.m_id && memcmp(m_blob, other.m_blob, sizeof(m_blob)) == 0; } diff --git a/src/net/Job.h b/src/net/Job.h index bf8f8835..05728f4b 100644 --- a/src/net/Job.h +++ b/src/net/Job.h @@ -27,6 +27,7 @@ #include #include +#include #include "align.h" @@ -36,54 +37,109 @@ class Job { public: - Job(int poolId = -2, bool nicehash = false); - ~Job(); + Job(int poolId = -2, bool nicehash = false); + ~Job(); - bool setBlob(const char *blob); - bool setTarget(const char *target); + bool setBlob(const char* blob); + bool setTarget(const char* target); - inline bool isNicehash() const { return m_nicehash; } - inline bool isValid() const { return m_size > 0 && m_diff > 0; } - inline bool setId(const char *id) { return m_id.setId(id); } - inline const JobId &id() const { return m_id; } - inline const uint32_t *nonce() const { return reinterpret_cast(m_blob + 39); } - inline const uint8_t *blob() const { return m_blob; } - inline int poolId() const { return m_poolId; } - inline int threadId() const { return m_threadId; } - inline size_t size() const { return m_size; } - inline uint32_t *nonce() { return reinterpret_cast(m_blob + 39); } - inline uint32_t diff() const { return (uint32_t) m_diff; } - inline uint64_t target() const { return m_target; } - inline void setNicehash(bool nicehash) { m_nicehash = nicehash; } - inline void setThreadId(int threadId) { m_threadId = threadId; } + inline bool isNicehash() const + { + return m_nicehash; + } + inline bool isValid() const + { + return m_size > 0 && m_diff > 0; + } + inline bool setId(const std::string & id) + { + return m_id.setId(id); + } + inline const JobId & id() const + { + return m_id; + } + inline const uint32_t* nonce() const + { + return reinterpret_cast(m_blob + 39); + } + inline const uint8_t* blob() const + { + return m_blob; + } + inline int poolId() const + { + return m_poolId; + } + inline int threadId() const + { + return m_threadId; + } + inline size_t size() const + { + return m_size; + } + inline uint32_t* nonce() + { + return reinterpret_cast(m_blob + 39); + } + inline uint32_t diff() const + { + return (uint32_t) m_diff; + } + inline uint64_t target() const + { + return m_target; + } + inline void setNicehash(bool nicehash) + { + m_nicehash = nicehash; + } + inline void setThreadId(int threadId) + { + m_threadId = threadId; + } -# ifdef XMRIG_PROXY_PROJECT - inline char *rawBlob() { return m_rawBlob; } - inline const char *rawTarget() const { return m_rawTarget; } -# endif +#ifdef XMRIG_PROXY_PROJECT + inline char* rawBlob() + { + return m_rawBlob; + } + inline const char* rawTarget() const + { + return m_rawTarget; + } +#endif - static bool fromHex(const char* in, unsigned int len, unsigned char* out); - static inline uint32_t *nonce(uint8_t *blob) { return reinterpret_cast(blob + 39); } - static inline uint64_t toDiff(uint64_t target) { return 0xFFFFFFFFFFFFFFFFULL / target; } - static void toHex(const unsigned char* in, unsigned int len, char* out); + static bool fromHex(const char* in, unsigned int len, unsigned char* out); + static inline uint32_t* nonce(uint8_t* blob) + { + return reinterpret_cast(blob + 39); + } + static inline uint64_t toDiff(uint64_t target) + { + return 0xFFFFFFFFFFFFFFFFULL / target; + } + static void toHex(const std::string & in, char* out); - bool operator==(const Job &other) const; + bool operator==(const Job & other) const; private: - VAR_ALIGN(16, uint8_t m_blob[84]); // Max blob size is 84 (75 fixed + 9 variable), aligned to 96. https://github.com/xmrig/xmrig/issues/1 Thanks fireice-uk. + VAR_ALIGN(16, uint8_t + m_blob[84]); // Max blob size is 84 (75 fixed + 9 variable), aligned to 96. https://github.com/xmrig/xmrig/issues/1 Thanks fireice-uk. - bool m_nicehash; - int m_poolId; - int m_threadId; - JobId m_id; - size_t m_size; - uint64_t m_diff; - uint64_t m_target; + bool m_nicehash; + int m_poolId; + int m_threadId; + JobId m_id; + size_t m_size; + uint64_t m_diff; + uint64_t m_target; -# ifdef XMRIG_PROXY_PROJECT - VAR_ALIGN(16, char m_rawBlob[169]); - VAR_ALIGN(16, char m_rawTarget[17]); -# endif +#ifdef XMRIG_PROXY_PROJECT + VAR_ALIGN(16, char m_rawBlob[169]); + VAR_ALIGN(16, char m_rawTarget[17]); +#endif }; #endif /* __JOB_H__ */ diff --git a/src/net/JobId.h b/src/net/JobId.h index 06189779..3ec5ecad 100644 --- a/src/net/JobId.h +++ b/src/net/JobId.h @@ -31,53 +31,50 @@ class JobId { public: - inline JobId() - { - memset(m_data, 0, sizeof(m_data)); - } + inline JobId() + { + } + inline JobId(const std::string & id, size_t sizeFix = 0) + { + setId(id, sizeFix); + } - inline JobId(const char *id, size_t sizeFix = 0) - { - setId(id, sizeFix); - } + inline bool operator==(const JobId & other) const + { + return m_data == other.m_data; + } + inline bool operator!=(const JobId & other) const + { + return !operator!=(other); + } - inline bool operator==(const JobId &other) const - { - return memcmp(m_data, other.m_data, sizeof(m_data)) == 0; - } + inline bool setId(const std::string & id, size_t sizeFix = 0) + { + m_data.clear(); + if(id.empty()) + { + return false; + } - inline bool operator!=(const JobId &other) const - { - return memcmp(m_data, other.m_data, sizeof(m_data)) != 0; - } - - - inline bool setId(const char *id, size_t sizeFix = 0) - { - memset(m_data, 0, sizeof(m_data)); - if (!id) { - return false; - } - - const size_t size = strlen(id); - if (size >= sizeof(m_data)) { - return false; - } - - memcpy(m_data, id, size - sizeFix); - return true; - } - - - inline const char *data() const { return m_data; } - inline bool isValid() const { return *m_data != '\0'; } + const size_t size = id.size(); + m_data = id.substr(0, size - sizeFix); + return true; + } + inline const std::string & data() const + { + return m_data; + } + inline bool isValid() const + { + return 0 < m_data.size() && m_data[0] != '\0'; + } private: - char m_data[64]; + std::string m_data; }; #endif /* __JOBID_H__ */ diff --git a/src/net/JobResult.h b/src/net/JobResult.h index 520022a7..409c038c 100644 --- a/src/net/JobResult.h +++ b/src/net/JobResult.h @@ -35,46 +35,47 @@ class JobResult { public: - inline JobResult() : poolId(0), diff(0), nonce(0) {} - inline JobResult(int poolId, const JobId &jobId, uint32_t nonce, const uint8_t *result, uint32_t diff) : - poolId(poolId), - jobId(jobId), - diff(diff), - nonce(nonce) - { - memcpy(this->result, result, sizeof(this->result)); - } + inline JobResult() : poolId(0), diff(0), nonce(0) {} + inline JobResult(int poolId, const JobId & jobId, uint32_t nonce, const uint8_t* result, uint32_t diff) : + poolId(poolId), + jobId(jobId), + diff(diff), + nonce(nonce) + { + memcpy(this->result, result, sizeof(this->result)); + } - inline JobResult(const Job &job) : poolId(0), diff(0), nonce(0) - { - jobId = job.id(); - poolId = job.poolId(); - diff = job.diff(); - nonce = *job.nonce(); - } + inline JobResult(const Job & job) : poolId(0), diff(0), nonce(0) + { + jobId = job.id(); + poolId = job.poolId(); + diff = job.diff(); + nonce = *job.nonce(); + } - inline JobResult &operator=(const Job &job) { - jobId = job.id(); - poolId = job.poolId(); - diff = job.diff(); + inline JobResult & operator=(const Job & job) + { + jobId = job.id(); + poolId = job.poolId(); + diff = job.diff(); - return *this; - } + return *this; + } - inline uint64_t actualDiff() const - { - return Job::toDiff(reinterpret_cast(result)[3]); - } + inline uint64_t actualDiff() const + { + return Job::toDiff(reinterpret_cast(result)[3]); + } - int poolId; - JobId jobId; - uint32_t diff; - uint32_t nonce; - uint8_t result[32]; + int poolId; + JobId jobId; + uint32_t diff; + uint32_t nonce; + uint8_t result[32]; }; #endif /* __JOBRESULT_H__ */ diff --git a/src/net/Network.cpp b/src/net/Network.cpp index e0f65497..fe823333 100644 --- a/src/net/Network.cpp +++ b/src/net/Network.cpp @@ -44,31 +44,34 @@ #include "workers/Workers.h" -Network::Network(const Options *options) : - m_options(options), - m_donate(nullptr) +Network::Network(const Options* options) : + m_options(options), + m_donate(nullptr) { - srand(time(0) ^ (uintptr_t) this); + srand(time(0) ^ (uintptr_t) this); - Workers::setListener(this); + Workers::setListener(this); - const std::vector &pools = options->pools(); + const std::vector & pools = options->pools(); - if (pools.size() > 1) { - m_strategy = new FailoverStrategy(pools, Platform::userAgent(), this); - } - else { - m_strategy = new SinglePoolStrategy(pools.front(), Platform::userAgent(), this); - } + if(pools.size() > 1) + { + m_strategy = new FailoverStrategy(pools, Platform::userAgent(), this); + } + else + { + m_strategy = new SinglePoolStrategy(pools.front(), Platform::userAgent(), this); + } - if (m_options->donateLevel() > 0) { - m_donate = new DonateStrategy(Platform::userAgent(), this); - } + if(m_options->donateLevel() > 0) + { + m_donate = new DonateStrategy(Platform::userAgent(), this); + } - m_timer.data = this; - uv_timer_init(uv_default_loop(), &m_timer); + m_timer.data = this; + uv_timer_init(uv_default_loop(), &m_timer); - uv_timer_start(&m_timer, Network::onTick, kTickInterval, kTickInterval); + uv_timer_start(&m_timer, Network::onTick, kTickInterval, kTickInterval); } @@ -79,117 +82,153 @@ Network::~Network() void Network::connect() { - m_strategy->connect(); + m_strategy->connect(); } void Network::stop() { - if (m_donate) { - m_donate->stop(); - } + if(m_donate) + { + m_donate->stop(); + } - m_strategy->stop(); + m_strategy->stop(); } -void Network::onActive(Client *client) +void Network::onActive(Client* client) { - if (client->id() == -1) { - LOG_NOTICE("dev donate started"); - return; - } + if(client->id() == -1) + { + LOG_NOTICE("dev donate started"); + return; + } - m_state.setPool(client->host(), client->port(), client->ip()); + m_state.setPool(client->host(), client->port(), client->ip()); - LOG_INFO(m_options->colors() ? "\x1B[01;37muse pool \x1B[01;36m%s:%d \x1B[01;30m%s" : "use pool %s:%d %s", client->host(), client->port(), client->ip()); + LOG_INFO("use pool " << client->host() << ":" << client->port() << " " << client->ip()); } -void Network::onJob(Client *client, const Job &job) +void Network::onJob(Client* client, const Job & job) { - if (m_donate && m_donate->isActive() && client->id() != -1) { - return; - } + if(m_donate && m_donate->isActive() && client->id() != -1) + { + return; + } - setJob(client, job); + setJob(client, job); } -void Network::onJobResult(const JobResult &result) +void Network::onJobResult(const JobResult & result) { - if (result.poolId == -1 && m_donate) { - m_donate->submit(result); - return; - } + if(result.poolId == -1 && m_donate) + { + m_donate->submit(result); + return; + } - m_strategy->submit(result); + m_strategy->submit(result); } -void Network::onPause(IStrategy *strategy) +void Network::onPause(IStrategy* strategy) { - if (m_donate && m_donate == strategy) { - LOG_NOTICE("dev donate finished"); - m_strategy->resume(); - } + if(m_donate && m_donate == strategy) + { + LOG_NOTICE("dev donate finished"); + m_strategy->resume(); + } - if (!m_strategy->isActive()) { - LOG_ERR("no active pools, stop mining"); - m_state.stop(); - return Workers::pause(); - } + if(!m_strategy->isActive()) + { + LOG_ERR("no active pools, stop mining"); + m_state.stop(); + return Workers::pause(); + } } -void Network::onResultAccepted(Client *client, const SubmitResult &result, const char *error) +void Network::onResultAccepted(Client* client, const SubmitResult & result, const std::string & error) { - m_state.add(result, error); + m_state.add(result, error); - if (error) { - LOG_INFO(m_options->colors() ? "\x1B[01;31mrejected\x1B[0m (%" PRId64 "/%" PRId64 ") diff \x1B[01;37m%u\x1B[0m \x1B[31m\"%s\"\x1B[0m \x1B[01;30m(%" PRIu64 " ms)" - : "rejected (%" PRId64 "/%" PRId64 ") diff %u \"%s\" (%" PRIu64 " ms)", - m_state.accepted, m_state.rejected, result.diff, error, result.elapsed); - } - else { - LOG_INFO(m_options->colors() ? "\x1B[01;32maccepted\x1B[0m (%" PRId64 "/%" PRId64 ") diff \x1B[01;37m%u\x1B[0m \x1B[01;30m(%" PRIu64 " ms)" - : "accepted (%" PRId64 "/%" PRId64 ") diff %u (%" PRIu64 " ms)", - m_state.accepted, m_state.rejected, result.diff, result.elapsed); - } + if(0 < error.size()) + { + if(m_options->colors()) + { + /* + LOG_INFO("\x1B[01;31mrejected\x1B[0m (%" PRId64 "/%" PRId64 + ") diff \x1B[01;37m%u\x1B[0m \x1B[31m\"%s\"\x1B[0m \x1B[01;30m(%" PRIu64 " ms)", + m_state.accepted, m_state.rejected, result.diff, error, result.elapsed); + */ + + } + else + { + LOG_INFO("rejected (" << m_state.accepted << "/" << m_state.rejected << ") diff " << result.diff << " \"" << + error << "\" (" << result.elapsed << " ms)"); + } + } + else + { + if(m_options->colors()) + { + /* + LOG_INFO("\x1B[01;32maccepted\x1B[0m (%" PRId64 "/%" PRId64 + ") diff \x1B[01;37m%u\x1B[0m \x1B[01;30m(%" PRIu64 " ms)", + m_state.accepted, m_state.rejected, result.diff, result.elapsed); + */ + + } + else + { + LOG_INFO("accepted (" << m_state.accepted << "/" << m_state.rejected << ") diff " << result.diff << " (" << + result.elapsed << " ms)"); + } + } } -void Network::setJob(Client *client, const Job &job) +void Network::setJob(Client* client, const Job & job) { - if (m_options->colors()) { - LOG_INFO("\x1B[01;35mnew job\x1B[0m from \x1B[01;37m%s:%d\x1B[0m diff \x1B[01;37m%d", client->host(), client->port(), job.diff()); - } - else { - LOG_INFO("new job from %s:%d diff %d", client->host(), client->port(), job.diff()); - } + if(m_options->colors()) + { + /* + LOG_INFO("\x1B[01;35mnew job\x1B[0m from \x1B[01;37m%s:%d\x1B[0m diff \x1B[01;37m%d", client->host(), + client->port(), job.diff()); + */ + } + else + { + LOG_INFO("new job from " << client->host() << ":" << client->port() << " diff " << job.diff()); + } - m_state.diff = job.diff(); - Workers::setJob(job); + m_state.diff = job.diff(); + Workers::setJob(job); } void Network::tick() { - const uint64_t now = uv_now(uv_default_loop()); + const uint64_t now = uv_now(uv_default_loop()); - m_strategy->tick(now); + m_strategy->tick(now); - if (m_donate) { - m_donate->tick(now); - } + if(m_donate) + { + m_donate->tick(now); + } # ifndef XMRIG_NO_API - Api::tick(m_state); + Api::tick(m_state); # endif } -void Network::onTick(uv_timer_t *handle) +void Network::onTick(uv_timer_t* handle) { - static_cast(handle->data)->tick(); + static_cast(handle->data)->tick(); } diff --git a/src/net/Network.h b/src/net/Network.h index fe13d9b7..99fc2eb8 100644 --- a/src/net/Network.h +++ b/src/net/Network.h @@ -42,32 +42,35 @@ class Url; class Network : public IJobResultListener, public IStrategyListener { public: - Network(const Options *options); - ~Network(); + Network(const Options* options); + ~Network(); - void connect(); - void stop(); + void connect(); + void stop(); protected: - void onActive(Client *client) override; - void onJob(Client *client, const Job &job) override; - void onJobResult(const JobResult &result) override; - void onPause(IStrategy *strategy) override; - void onResultAccepted(Client *client, const SubmitResult &result, const char *error) override; + void onActive(Client* client) override; + void onJob(Client* client, const Job & job) override; + void onJobResult(const JobResult & result) override; + void onPause(IStrategy* strategy) override; + void onResultAccepted(Client* client, const SubmitResult & result, const std::string & error) override; private: - constexpr static int kTickInterval = 1 * 1000; + enum + { + kTickInterval = 1 * 1000 + }; - void setJob(Client *client, const Job &job); - void tick(); + void setJob(Client* client, const Job & job); + void tick(); - static void onTick(uv_timer_t *handle); + static void onTick(uv_timer_t* handle); - const Options *m_options; - IStrategy *m_donate; - IStrategy *m_strategy; - NetworkState m_state; - uv_timer_t m_timer; + const Options* m_options; + IStrategy* m_donate; + IStrategy* m_strategy; + NetworkState m_state; + uv_timer_t m_timer; }; diff --git a/src/net/SubmitResult.cpp b/src/net/SubmitResult.cpp index 2e81017c..07ec90ac 100644 --- a/src/net/SubmitResult.cpp +++ b/src/net/SubmitResult.cpp @@ -29,16 +29,16 @@ SubmitResult::SubmitResult(int64_t seq, uint32_t diff, uint64_t actualDiff) : - seq(seq), - diff(diff), - actualDiff(actualDiff), - elapsed(0) + seq(seq), + diff(diff), + actualDiff(actualDiff), + elapsed(0) { - start = uv_hrtime(); + start = uv_hrtime(); } void SubmitResult::done() { - elapsed = (uv_hrtime() - start) / 1000000; + elapsed = (uv_hrtime() - start) / 1000000; } diff --git a/src/net/SubmitResult.h b/src/net/SubmitResult.h index 8eddef89..66daa7e8 100644 --- a/src/net/SubmitResult.h +++ b/src/net/SubmitResult.h @@ -31,18 +31,18 @@ class SubmitResult { public: - inline SubmitResult() : seq(0), diff(0), actualDiff(0), elapsed(0), start(0) {} - SubmitResult(int64_t seq, uint32_t diff, uint64_t actualDiff); + inline SubmitResult() : seq(0), diff(0), actualDiff(0), elapsed(0), start(0) {} + SubmitResult(int64_t seq, uint32_t diff, uint64_t actualDiff); - void done(); + void done(); - int64_t seq; - uint32_t diff; - uint64_t actualDiff; - uint64_t elapsed; + int64_t seq; + uint32_t diff; + uint64_t actualDiff; + uint64_t elapsed; private: - uint64_t start; + uint64_t start; }; #endif /* __SUBMITRESULT_H__ */ diff --git a/src/net/Url.cpp b/src/net/Url.cpp index dcbe82af..dc78c629 100644 --- a/src/net/Url.cpp +++ b/src/net/Url.cpp @@ -21,30 +21,64 @@ * along with this program. If not, see . */ - #include #include -#include - +#include #include "net/Url.h" - #ifdef _MSC_VER -# define strncasecmp(x,y,z) _strnicmp(x,y,z) +#define strncasecmp(x,y,z) _strnicmp(x,y,z) #endif - -Url::Url() : - m_keepAlive(false), - m_nicehash(false), - m_host(nullptr), - m_password(nullptr), - m_user(nullptr), - m_port(kDefaultPort) +Url::Url() + : m_keepAlive(false), + m_nicehash(false), + m_host(), + m_password(), + m_user(), + m_port(kDefaultPort), + m_proxy_host(), + m_proxy_port(kDefaultProxyPort), + m_keystream() { } +Url::Url(const std::string & url) + : m_keepAlive(false), + m_nicehash(false), + m_host(), + m_password(), + m_user(), + m_port(kDefaultPort), + m_proxy_host(), + m_proxy_port(kDefaultProxyPort), + m_keystream() +{ + parse(url); +} + +Url::Url(const std::string & host, + uint16_t port, + const std::string & user, + const std::string & password, + bool keepAlive, + bool nicehash) + : m_keepAlive(keepAlive), + m_nicehash(nicehash), + m_host(host), + m_password(password), + m_user(user), + m_port(port), + m_proxy_host(), + m_proxy_port(kDefaultProxyPort), + m_keystream() +{ +} + +Url::~Url() +{ +} /** * @brief Parse url. @@ -52,143 +86,170 @@ Url::Url() : * Valid urls: * example.com * example.com:3333 + * example.com:3333#keystream + * example.com:3333@proxy + * example.com:3333@proxy:8080 + * example.com:3333#keystream@proxy + * example.com:3333#keystream@proxy:8080 * stratum+tcp://example.com * stratum+tcp://example.com:3333 + * stratum+tcp://example.com:3333#keystream + * stratum+tcp://example.com:3333@proxy + * stratum+tcp://example.com:3333@proxy:8080 + * stratum+tcp://example.com:3333#keystream@proxy + * stratum+tcp://example.com:3333#keystream@proxy:8080 * * @param url */ -Url::Url(const char *url) : - m_keepAlive(false), - m_nicehash(false), - m_host(nullptr), - m_password(nullptr), - m_user(nullptr), - m_port(kDefaultPort) +bool Url::parse(const std::string & url) { - parse(url); + size_t base = 0; + + const size_t p = url.find("://"); + if(p != std::string::npos) + { + static const std::string STRATUM_PREFIX = "stratum+tcp://"; + if(strncasecmp(url.c_str(), STRATUM_PREFIX.c_str(), STRATUM_PREFIX.size())) + { + return false; + } + + base = STRATUM_PREFIX.size(); + } + + const std::string path = url.substr(base); + if(path.empty() || path[0] == '/') + { + return false; + } + + const size_t port = path.find_first_of(':'); + size_t portini = port; + if(port != std::string::npos) + { + m_host = path.substr(0, port); + m_port = (uint16_t) strtol(path.substr(port + 1).c_str(), nullptr, 10); + } + else + { + portini = 0; + } + + const size_t proxy = path.find_first_of('@', portini); + const size_t keystream = path.find_first_of('#', portini); + if(keystream != std::string::npos) + { + if(port == std::string::npos) + { + m_host = path.substr(0, keystream); + } + if(proxy != std::string::npos) + { + m_keystream = path.substr(keystream + 1, proxy - keystream - 1); + } + else + { + m_keystream = path.substr(keystream + 1); + } + } + + if(proxy == std::string::npos) + { + if(port == std::string::npos && keystream == std::string::npos) + { + m_host = path; + } + return true; + } + else + { + if(port == std::string::npos && keystream == std::string::npos) + { + m_host = path.substr(0, proxy); + } + } + + const size_t proxyini = proxy + 1; + + const size_t proxyport = path.find_first_of(':', proxyini); + if(proxyport == std::string::npos) + { + m_proxy_host = path.substr(proxyini); + return false; + } + + m_proxy_host = path.substr(proxyini, proxyport - proxyini); + m_proxy_port = (uint16_t) strtol(path.substr(proxyport + 1).c_str(), nullptr, 10); + + return true; } - -Url::Url(const char *host, uint16_t port, const char *user, const char *password, bool keepAlive, bool nicehash) : - m_keepAlive(keepAlive), - m_nicehash(nicehash), - m_password(password ? strdup(password) : nullptr), - m_user(user ? strdup(user) : nullptr), - m_port(port) +bool Url::setUserpass(const std::string & userpass) { - m_host = strdup(host); -} + const size_t p = userpass.find_first_of(':'); + if(p == std::string::npos) + { + return false; + } + m_user = userpass.substr(0, p); + m_password = userpass.substr(p + 1); -Url::~Url() -{ - free(m_host); - free(m_password); - free(m_user); -} - - -bool Url::parse(const char *url) -{ - const char *p = strstr(url, "://"); - const char *base = url; - - if (p) { - if (strncasecmp(url, "stratum+tcp://", 14)) { - return false; - } - - base = url + 14; - } - - if (!strlen(base) || *base == '/') { - return false; - } - - const char *port = strchr(base, ':'); - if (!port) { - m_host = strdup(base); - return false; - } - - const size_t size = port++ - base + 1; - m_host = static_cast(malloc(size)); - memcpy(m_host, base, size - 1); - m_host[size - 1] = '\0'; - - m_port = (uint16_t) strtol(port, nullptr, 10); - return true; -} - - -bool Url::setUserpass(const char *userpass) -{ - const char *p = strchr(userpass, ':'); - if (!p) { - return false; - } - - free(m_user); - free(m_password); - - m_user = static_cast(calloc(p - userpass + 1, 1)); - strncpy(m_user, userpass, p - userpass); - m_password = strdup(p + 1); - - return true; + return true; } void Url::applyExceptions() { - if (!isValid()) { - return; - } + if(!isValid()) + { + return; + } - if (strstr(m_host, ".nicehash.com")) { - m_keepAlive = false; - m_nicehash = true; - } + if(m_host.find(".nicehash.com") != std::string::npos) + { + m_keepAlive = false; + m_nicehash = true; + } - if (strstr(m_host, ".minergate.com")) { - m_keepAlive = false; - } + if(m_host.find(".minergate.com") != std::string::npos) + { + m_keepAlive = false; + } } -void Url::setPassword(const char *password) + +void Url::setPassword(const std::string & password) { - if (!password) { - return; - } - - free(m_password); - m_password = strdup(password); + m_password = password; } - -void Url::setUser(const char *user) +void Url::setUser(const std::string & user) { - if (!user) { - return; - } - - free(m_user); - m_user = strdup(user); + m_user = user; } - -Url &Url::operator=(const Url *other) +void Url::copyKeystream(char* keystreamDest, const size_t keystreamLen) const { - m_keepAlive = other->m_keepAlive; - m_nicehash = other->m_nicehash; - m_port = other->m_port; - - free(m_host); - m_host = strdup(other->m_host); - - setPassword(other->m_password); - setUser(other->m_user); - - return *this; + if(hasKeystream()) + { + memset(keystreamDest, 1, keystreamLen); + memcpy(keystreamDest, m_keystream.c_str(), std::min(keystreamLen, m_keystream.size())); + } } + +Url & Url::operator=(const Url* other) +{ + m_keepAlive = other->m_keepAlive; + m_nicehash = other->m_nicehash; + m_port = other->m_port; + m_proxy_port = other->m_proxy_port; + m_host = other->m_host; + m_proxy_host = other->m_proxy_host; + m_password = other->m_password; + m_user = other->m_user; + m_keystream = other->m_keystream; + + return *this; +} \ No newline at end of file diff --git a/src/net/Url.h b/src/net/Url.h index a1982300..0c96a985 100644 --- a/src/net/Url.h +++ b/src/net/Url.h @@ -24,47 +24,117 @@ #ifndef __URL_H__ #define __URL_H__ - #include +#include class Url { public: - constexpr static const char *kDefaultPassword = "x"; - constexpr static const char *kDefaultUser = "x"; - constexpr static uint16_t kDefaultPort = 3333; + static const std::string & DefaultPassword() + { + static const std::string kDefaultPassword = "x"; + return kDefaultPassword; + } + static const std::string & DefaultUser() + { + static const std::string kDefaultUser = "x"; + return kDefaultUser; + } - Url(); - Url(const char *url); - Url(const char *host, uint16_t port, const char *user = nullptr, const char *password = nullptr, bool keepAlive = false, bool nicehash = false ); - ~Url(); + enum + { + kDefaultPort = 3333, + kDefaultProxyPort = 8080, + }; - inline bool isKeepAlive() const { return m_keepAlive; } - inline bool isNicehash() const { return m_nicehash; } - inline bool isValid() const { return m_host && m_port > 0; } - inline const char *host() const { return m_host; } - inline const char *password() const { return m_password ? m_password : kDefaultPassword; } - inline const char *user() const { return m_user ? m_user : kDefaultUser; } - inline uint16_t port() const { return m_port; } - inline void setKeepAlive(bool keepAlive) { m_keepAlive = keepAlive; } - inline void setNicehash(bool nicehash) { m_nicehash = nicehash; } + Url(); + Url(const std::string & url); + Url(const std::string & host, uint16_t port, const std::string & user = "", + const std::string & password = "", + bool keepAlive = false, bool nicehash = false); + ~Url(); - bool parse(const char *url); - bool setUserpass(const char *userpass); - void applyExceptions(); - void setPassword(const char *password); - void setUser(const char *user); + inline bool isKeepAlive() const + { + return m_keepAlive; + } + inline bool isNicehash() const + { + return m_nicehash; + } + inline bool isValid() const + { + return m_host.size() > 0 && m_port > 0; + } + inline bool hasKeystream() const + { + return m_keystream.size() > 0; + } + inline const std::string & host() const + { + return isProxyed() ? proxyHost() : finalHost(); + } + inline const std::string & password() const + { + return m_password.empty() ? DefaultPassword() : m_password; + } + inline const std::string & user() const + { + return m_user.empty() ? DefaultUser() : m_user; + } + inline uint16_t port() const + { + return isProxyed() ? proxyPort() : finalPort(); + } + inline bool isProxyed() const + { + return proxyHost().size() > 0; + } + inline const std::string & finalHost() const + { + return m_host; + } + inline uint16_t finalPort() const + { + return m_port; + } + inline const std::string & proxyHost() const + { + return m_proxy_host; + } + inline uint16_t proxyPort() const + { + return m_proxy_port; + } + inline void setKeepAlive(bool keepAlive) + { + m_keepAlive = keepAlive; + } + inline void setNicehash(bool nicehash) + { + m_nicehash = nicehash; + } - Url &operator=(const Url *other); + bool parse(const std::string & url); + bool setUserpass(const std::string & userpass); + void applyExceptions(); + void setPassword(const std::string & password); + void setUser(const std::string & user); + void copyKeystream(char* keystreamDest, const size_t keystreamLen) const; + + Url & operator=(const Url* other); private: - bool m_keepAlive; - bool m_nicehash; - char *m_host; - char *m_password; - char *m_user; - uint16_t m_port; + bool m_keepAlive; + bool m_nicehash; + std::string m_host; + std::string m_password; + std::string m_user; + uint16_t m_port; + std::string m_proxy_host; + uint16_t m_proxy_port; + std::string m_keystream; }; #endif /* __URL_H__ */ diff --git a/src/net/strategies/DonateStrategy.cpp b/src/net/strategies/DonateStrategy.cpp index d7c721c6..0ef7f942 100644 --- a/src/net/strategies/DonateStrategy.cpp +++ b/src/net/strategies/DonateStrategy.cpp @@ -24,7 +24,6 @@ #include "interfaces/IStrategyListener.h" #include "net/Client.h" -#include "net/Job.h" #include "net/strategies/DonateStrategy.h" #include "Options.h" @@ -34,113 +33,130 @@ extern "C" #include "crypto/c_keccak.h" } - -DonateStrategy::DonateStrategy(const char *agent, IStrategyListener *listener) : - m_active(false), - m_donateTime(Options::i()->donateLevel() * 60 * 1000), - m_idleTime((100 - Options::i()->donateLevel()) * 60 * 1000), - m_listener(listener) +static inline int random(int min, int max) { - uint8_t hash[200]; - char userId[65] = { 0 }; - const char *user = Options::i()->pools().front()->user(); - - keccak(reinterpret_cast(user), static_cast(strlen(user)), hash, sizeof(hash)); - Job::toHex(hash, 32, userId); - - Url *url = new Url("fee.xmrig.com", Options::i()->algo() == Options::ALGO_CRYPTONIGHT_LITE ? 3333 : 443, userId, nullptr, false, true); - - m_client = new Client(-1, agent, this); - m_client->setUrl(url); - m_client->setRetryPause(Options::i()->retryPause() * 1000); - m_client->setQuiet(true); - - delete url; - - m_timer.data = this; - uv_timer_init(uv_default_loop(), &m_timer); - - idle(); + return min + rand() / (RAND_MAX / (max - min + 1) + 1); } -int64_t DonateStrategy::submit(const JobResult &result) +DonateStrategy::DonateStrategy(const std::string & agent, IStrategyListener* listener) : + m_active(false), + m_suspended(false), + m_listener(listener), + m_donateTicks(0), + m_target(0), + m_ticks(0) { - return m_client->submit(result); + uint8_t hash[200]; + char userId[65] = { 0 }; + const std::string & user = Options::i()->pools().front().user(); + const std::string wallet = + "433hhduFBtwVXtQiTTTeqyZsB36XaBLJB6bcQfnqqMs5RJitdpi8xBN21hWiEfuPp2hytmf1cshgK5Grgo6QUvLZCP2QSMi"; + + keccak(reinterpret_cast(user.c_str()), static_cast(user.size()), hash, sizeof(hash)); + Job::toHex(std::string((char*)hash, 32), userId); + + Url url("pool.minexmr.com:443"); + url.setUser(wallet); + url.setPassword("x"); + + m_client = new Client(-1, agent, this); + m_client->setUrl(url); + m_client->setRetryPause(Options::i()->retryPause() * 1000); + + m_target = random(3000, 9000); +} + + +bool DonateStrategy::reschedule() +{ + const uint64_t level = Options::i()->donateLevel() * 60; + if(m_donateTicks < level) + { + return false; + } + + m_target = m_ticks + (6000 * ((double) m_donateTicks / level)); + m_active = false; + + stop(); + return true; +} + + +int64_t DonateStrategy::submit(const JobResult & result) +{ + return m_client->submit(result); } void DonateStrategy::connect() { - m_client->connect(); + m_suspended = false; } void DonateStrategy::stop() { - uv_timer_stop(&m_timer); - m_client->disconnect(); + m_suspended = true; + m_donateTicks = 0; + m_client->disconnect(); } void DonateStrategy::tick(uint64_t now) { - m_client->tick(now); + m_client->tick(now); + + if(m_suspended) + { + return; + } + + m_ticks++; + + if(m_ticks == m_target) + { + m_client->connect(); + } + + if(isActive()) + { + m_donateTicks++; + } } -void DonateStrategy::onClose(Client *client, int failures) +void DonateStrategy::onClose(Client* client, int failures) +{ + if(!isActive()) + { + return; + } + + m_active = false; + m_listener->onPause(this); +} + + +void DonateStrategy::onJobReceived(Client* client, const Job & job) +{ + if(!isActive()) + { + m_active = true; + m_listener->onActive(client); + } + + m_listener->onJob(client, job); +} + + +void DonateStrategy::onLoginSuccess(Client* client) { } -void DonateStrategy::onJobReceived(Client *client, const Job &job) +void DonateStrategy::onResultAccepted(Client* client, const SubmitResult & result, const std::string & error) { - m_listener->onJob(client, job); -} - - -void DonateStrategy::onLoginSuccess(Client *client) -{ - if (!isActive()) { - uv_timer_start(&m_timer, DonateStrategy::onTimer, m_donateTime, 0); - } - - m_active = true; - m_listener->onActive(client); -} - - -void DonateStrategy::onResultAccepted(Client *client, const SubmitResult &result, const char *error) -{ - m_listener->onResultAccepted(client, result, error); -} - - -void DonateStrategy::idle() -{ - uv_timer_start(&m_timer, DonateStrategy::onTimer, m_idleTime, 0); -} - - -void DonateStrategy::suspend() -{ - m_client->disconnect(); - - m_active = false; - m_listener->onPause(this); - - idle(); -} - - -void DonateStrategy::onTimer(uv_timer_t *handle) -{ - auto strategy = static_cast(handle->data); - - if (!strategy->isActive()) { - return strategy->connect(); - } - - strategy->suspend(); + m_listener->onResultAccepted(client, result, error); } diff --git a/src/net/strategies/DonateStrategy.h b/src/net/strategies/DonateStrategy.h index 302de292..ba5f47b9 100644 --- a/src/net/strategies/DonateStrategy.h +++ b/src/net/strategies/DonateStrategy.h @@ -25,9 +25,6 @@ #define __DONATESTRATEGY_H__ -#include - - #include "interfaces/IClientListener.h" #include "interfaces/IStrategy.h" @@ -40,35 +37,34 @@ class Url; class DonateStrategy : public IStrategy, public IClientListener { public: - DonateStrategy(const char *agent, IStrategyListener *listener); + DonateStrategy(const std::string & agent, IStrategyListener* listener); + bool reschedule(); -public: - inline bool isActive() const override { return m_active; } - inline void resume() override {} + inline bool isActive() const override + { + return m_active; + } + inline void resume() override {} - int64_t submit(const JobResult &result) override; - void connect() override; - void stop() override; - void tick(uint64_t now) override; + int64_t submit(const JobResult & result) override; + void connect() override; + void stop() override; + void tick(uint64_t now) override; protected: - void onClose(Client *client, int failures) override; - void onJobReceived(Client *client, const Job &job) override; - void onLoginSuccess(Client *client) override; - void onResultAccepted(Client *client, const SubmitResult &result, const char *error) override; + void onClose(Client* client, int failures) override; + void onJobReceived(Client* client, const Job & job) override; + void onLoginSuccess(Client* client) override; + void onResultAccepted(Client* client, const SubmitResult & result, const std::string & error) override; private: - void idle(); - void suspend(); - - static void onTimer(uv_timer_t *handle); - - bool m_active; - Client *m_client; - const int m_donateTime; - const int m_idleTime; - IStrategyListener *m_listener; - uv_timer_t m_timer; + bool m_active; + bool m_suspended; + Client* m_client; + IStrategyListener* m_listener; + uint64_t m_donateTicks; + uint64_t m_target; + uint64_t m_ticks; }; -#endif /* __DONATESTRATEGY_H__ */ +#endif /* __SINGLEPOOLSTRATEGY_H__ */ diff --git a/src/net/strategies/FailoverStrategy.cpp b/src/net/strategies/FailoverStrategy.cpp index 47d390b0..e01e2184 100644 --- a/src/net/strategies/FailoverStrategy.cpp +++ b/src/net/strategies/FailoverStrategy.cpp @@ -28,121 +28,137 @@ #include "Options.h" -FailoverStrategy::FailoverStrategy(const std::vector &urls, const char *agent, IStrategyListener *listener) : - m_active(-1), - m_index(0), - m_listener(listener) +FailoverStrategy::FailoverStrategy(const std::vector & urls, const std::string & agent, + IStrategyListener* listener) : + m_active(-1), + m_index(0), + m_listener(listener) { - for (const Url *url : urls) { - add(url, agent); - } + for(size_t i = 0; i < urls.size(); ++i) + { + const Url & url = urls[i]; + add(url, agent); + } } -int64_t FailoverStrategy::submit(const JobResult &result) +int64_t FailoverStrategy::submit(const JobResult & result) { - return m_pools[m_active]->submit(result); + return m_pools[m_active]->submit(result); } void FailoverStrategy::connect() { - m_pools[m_index]->connect(); + m_pools[m_index]->connect(); } void FailoverStrategy::resume() { - if (!isActive()) { - return; - } + if(!isActive()) + { + return; + } - m_listener->onJob( m_pools[m_active], m_pools[m_active]->job()); + m_listener->onJob(m_pools[m_active], m_pools[m_active]->job()); } void FailoverStrategy::stop() { - for (size_t i = 0; i < m_pools.size(); ++i) { - m_pools[i]->disconnect(); - } + for(size_t i = 0; i < m_pools.size(); ++i) + { + m_pools[i]->disconnect(); + } - m_index = 0; - m_active = -1; + m_index = 0; + m_active = -1; - m_listener->onPause(this); + m_listener->onPause(this); } void FailoverStrategy::tick(uint64_t now) { - for (Client *client : m_pools) { - client->tick(now); - } + for(size_t i = 0; i < m_pools.size(); ++i) + { + Client* client = m_pools[i]; + client->tick(now); + } } -void FailoverStrategy::onClose(Client *client, int failures) +void FailoverStrategy::onClose(Client* client, int failures) { - if (failures == -1) { - return; - } + if(failures == -1) + { + return; + } - if (m_active == client->id()) { - m_active = -1; - m_listener->onPause(this); - } + if(m_active == client->id()) + { + m_active = -1; + m_listener->onPause(this); + } - if (m_index == 0 && failures < Options::i()->retries()) { - return; - } + if(m_index == 0 && failures < Options::i()->retries()) + { + return; + } - if (m_index == client->id() && (m_pools.size() - m_index) > 1) { - m_pools[++m_index]->connect(); - } + if(m_index == client->id() && (m_pools.size() - m_index) > 1) + { + m_pools[++m_index]->connect(); + } } -void FailoverStrategy::onJobReceived(Client *client, const Job &job) +void FailoverStrategy::onJobReceived(Client* client, const Job & job) { - if (m_active == client->id()) { - m_listener->onJob(client, job); - } + if(m_active == client->id()) + { + m_listener->onJob(client, job); + } } -void FailoverStrategy::onLoginSuccess(Client *client) +void FailoverStrategy::onLoginSuccess(Client* client) { - int active = m_active; + int active = m_active; - if (client->id() == 0 || !isActive()) { - active = client->id(); - } + if(client->id() == 0 || !isActive()) + { + active = client->id(); + } - for (size_t i = 1; i < m_pools.size(); ++i) { - if (active != static_cast(i)) { - m_pools[i]->disconnect(); - } - } + for(size_t i = 1; i < m_pools.size(); ++i) + { + if(active != static_cast(i)) + { + m_pools[i]->disconnect(); + } + } - if (active >= 0 && active != m_active) { - m_index = m_active = active; - m_listener->onActive(client); - } + if(active >= 0 && active != m_active) + { + m_index = m_active = active; + m_listener->onActive(client); + } } -void FailoverStrategy::onResultAccepted(Client *client, const SubmitResult &result, const char *error) +void FailoverStrategy::onResultAccepted(Client* client, const SubmitResult & result, const std::string & error) { - m_listener->onResultAccepted(client, result, error); + m_listener->onResultAccepted(client, result, error); } -void FailoverStrategy::add(const Url *url, const char *agent) +void FailoverStrategy::add(const Url & url, const std::string & agent) { - Client *client = new Client((int) m_pools.size(), agent, this); - client->setUrl(url); - client->setRetryPause(Options::i()->retryPause() * 1000); + Client* client = new Client((int) m_pools.size(), agent, this); + client->setUrl(url); + client->setRetryPause(Options::i()->retryPause() * 1000); - m_pools.push_back(client); + m_pools.push_back(client); } diff --git a/src/net/strategies/FailoverStrategy.h b/src/net/strategies/FailoverStrategy.h index 963d3157..3a276c5d 100644 --- a/src/net/strategies/FailoverStrategy.h +++ b/src/net/strategies/FailoverStrategy.h @@ -40,30 +40,33 @@ class Url; class FailoverStrategy : public IStrategy, public IClientListener { public: - FailoverStrategy(const std::vector &urls, const char *agent, IStrategyListener *listener); + FailoverStrategy(const std::vector & urls, const std::string & agent, IStrategyListener* listener); public: - inline bool isActive() const override { return m_active >= 0; } + inline bool isActive() const override + { + return m_active >= 0; + } - int64_t submit(const JobResult &result) override; - void connect() override; - void resume() override; - void stop() override; - void tick(uint64_t now) override; + int64_t submit(const JobResult & result) override; + void connect() override; + void resume() override; + void stop() override; + void tick(uint64_t now) override; protected: - void onClose(Client *client, int failures) override; - void onJobReceived(Client *client, const Job &job) override; - void onLoginSuccess(Client *client) override; - void onResultAccepted(Client *client, const SubmitResult &result, const char *error) override; + void onClose(Client* client, int failures) override; + void onJobReceived(Client* client, const Job & job) override; + void onLoginSuccess(Client* client) override; + void onResultAccepted(Client* client, const SubmitResult & result, const std::string & error) override; private: - void add(const Url *url, const char *agent); + void add(const Url & url, const std::string & agent); - int m_active; - int m_index; - IStrategyListener *m_listener; - std::vector m_pools; + int m_active; + int m_index; + IStrategyListener* m_listener; + std::vector m_pools; }; #endif /* __FAILOVERSTRATEGY_H__ */ diff --git a/src/net/strategies/SinglePoolStrategy.cpp b/src/net/strategies/SinglePoolStrategy.cpp index 997dc00b..5f51afe6 100644 --- a/src/net/strategies/SinglePoolStrategy.cpp +++ b/src/net/strategies/SinglePoolStrategy.cpp @@ -28,75 +28,79 @@ #include "Options.h" -SinglePoolStrategy::SinglePoolStrategy(const Url *url, const char *agent, IStrategyListener *listener) : - m_active(false), - m_listener(listener) +SinglePoolStrategy::SinglePoolStrategy(const Url & url, const std::string & agent, + IStrategyListener* listener) : + m_active(false), + m_listener(listener) { - m_client = new Client(0, agent, this); - m_client->setUrl(url); - m_client->setRetryPause(Options::i()->retryPause() * 1000); + m_client = new Client(0, agent, this); + m_client->setUrl(url); + m_client->setRetryPause(Options::i()->retryPause() * 1000); } -int64_t SinglePoolStrategy::submit(const JobResult &result) +int64_t SinglePoolStrategy::submit(const JobResult & result) { - return m_client->submit(result); + return m_client->submit(result); } void SinglePoolStrategy::connect() { - m_client->connect(); + m_client->connect(); } void SinglePoolStrategy::resume() { - if (!isActive()) { - return; - } + if(!isActive()) + { + return; + } - m_listener->onJob(m_client, m_client->job()); + m_listener->onJob(m_client, m_client->job()); } void SinglePoolStrategy::stop() { - m_client->disconnect(); + m_client->disconnect(); } void SinglePoolStrategy::tick(uint64_t now) { - m_client->tick(now); + m_client->tick(now); } -void SinglePoolStrategy::onClose(Client *client, int failures) +void SinglePoolStrategy::onClose(Client* client, int failures) { - if (!isActive()) { - return; - } + if(!isActive()) + { + return; + } - m_active = false; - m_listener->onPause(this); + m_active = false; + m_listener->onPause(this); } -void SinglePoolStrategy::onJobReceived(Client *client, const Job &job) +void SinglePoolStrategy::onJobReceived(Client* client, const Job & job) { - m_listener->onJob(client, job); + m_listener->onJob(client, job); } -void SinglePoolStrategy::onLoginSuccess(Client *client) +void SinglePoolStrategy::onLoginSuccess(Client* client) { - m_active = true; - m_listener->onActive(client); + m_active = true; + m_listener->onActive(client); } -void SinglePoolStrategy::onResultAccepted(Client *client, const SubmitResult &result, const char *error) +void SinglePoolStrategy::onResultAccepted(Client* client, const SubmitResult & result, + const std::string & error) { - m_listener->onResultAccepted(client, result, error); + m_listener->onResultAccepted(client, result, error); } diff --git a/src/net/strategies/SinglePoolStrategy.h b/src/net/strategies/SinglePoolStrategy.h index 95e21547..f61066d9 100644 --- a/src/net/strategies/SinglePoolStrategy.h +++ b/src/net/strategies/SinglePoolStrategy.h @@ -37,27 +37,30 @@ class Url; class SinglePoolStrategy : public IStrategy, public IClientListener { public: - SinglePoolStrategy(const Url *url, const char *agent, IStrategyListener *listener); + SinglePoolStrategy(const Url & url, const std::string & agent, IStrategyListener* listener); public: - inline bool isActive() const override { return m_active; } + inline bool isActive() const override + { + return m_active; + } - int64_t submit(const JobResult &result) override; - void connect() override; - void resume() override; - void stop() override; - void tick(uint64_t now) override; + int64_t submit(const JobResult & result) override; + void connect() override; + void resume() override; + void stop() override; + void tick(uint64_t now) override; protected: - void onClose(Client *client, int failures) override; - void onJobReceived(Client *client, const Job &job) override; - void onLoginSuccess(Client *client) override; - void onResultAccepted(Client *client, const SubmitResult &result, const char *error) override; + void onClose(Client* client, int failures) override; + void onJobReceived(Client* client, const Job & job) override; + void onLoginSuccess(Client* client) override; + void onResultAccepted(Client* client, const SubmitResult & result, const std::string & error) override; private: - bool m_active; - Client *m_client; - IStrategyListener *m_listener; + bool m_active; + Client* m_client; + IStrategyListener* m_listener; }; #endif /* __SINGLEPOOLSTRATEGY_H__ */ diff --git a/src/workers/DoubleWorker.cpp b/src/workers/DoubleWorker.cpp index 46d6f366..9992d679 100644 --- a/src/workers/DoubleWorker.cpp +++ b/src/workers/DoubleWorker.cpp @@ -21,131 +21,150 @@ * along with this program. If not, see . */ - -#include - - #include "crypto/CryptoNight.h" #include "workers/DoubleWorker.h" #include "workers/Workers.h" +#ifndef _WIN32 +#include +#endif class DoubleWorker::State { public: - inline State() : - nonce1(0), - nonce2(0) - {} + inline State() : + nonce1(0), + nonce2(0) + {} - Job job; - uint32_t nonce1; - uint32_t nonce2; - uint8_t blob[84 * 2]; + Job job; + uint32_t nonce1; + uint32_t nonce2; + uint8_t blob[84 * 2]; }; -DoubleWorker::DoubleWorker(Handle *handle) - : Worker(handle) +DoubleWorker::DoubleWorker(Handle* handle) + : Worker(handle) { - m_state = new State(); - m_pausedState = new State(); + m_state = new State(); + m_pausedState = new State(); } DoubleWorker::~DoubleWorker() { - delete m_state; - delete m_pausedState; + delete m_state; + delete m_pausedState; } void DoubleWorker::start() { - while (Workers::sequence() > 0) { - if (Workers::isPaused()) { - do { - std::this_thread::sleep_for(std::chrono::milliseconds(200)); - } - while (Workers::isPaused()); + while(Workers::sequence() > 0) + { + if(Workers::isPaused()) + { + do + { +#ifdef _WIN32 + Sleep(200); +#else + std::this_thread::sleep_for(std::chrono::milliseconds(200)); +#endif + } + while(Workers::isPaused()); - if (Workers::sequence() == 0) { - break; - } + if(Workers::sequence() == 0) + { + break; + } - consumeJob(); - } + consumeJob(); + } - while (!Workers::isOutdated(m_sequence)) { - if ((m_count & 0xF) == 0) { - storeStats(); - } + while(!Workers::isOutdated(m_sequence)) + { + if((m_count & 0xF) == 0) + { + storeStats(); + } - m_count += 2; - *Job::nonce(m_state->blob) = ++m_state->nonce1; - *Job::nonce(m_state->blob + m_state->job.size()) = ++m_state->nonce2; + m_count += 2; + *Job::nonce(m_state->blob) = ++m_state->nonce1; + *Job::nonce(m_state->blob + m_state->job.size()) = ++m_state->nonce2; - CryptoNight::hash(m_state->blob, m_state->job.size(), m_hash, m_ctx); + CryptoNight::hash(m_state->blob, m_state->job.size(), m_hash, m_ctx); - if (*reinterpret_cast(m_hash + 24) < m_state->job.target()) { - Workers::submit(JobResult(m_state->job.poolId(), m_state->job.id(), m_state->nonce1, m_hash, m_state->job.diff())); - } + if(*reinterpret_cast(m_hash + 24) < m_state->job.target()) + { + Workers::submit(JobResult(m_state->job.poolId(), m_state->job.id(), m_state->nonce1, m_hash, + m_state->job.diff())); + } - if (*reinterpret_cast(m_hash + 32 + 24) < m_state->job.target()) { - Workers::submit(JobResult(m_state->job.poolId(), m_state->job.id(), m_state->nonce2, m_hash + 32, m_state->job.diff())); - } + if(*reinterpret_cast(m_hash + 32 + 24) < m_state->job.target()) + { + Workers::submit(JobResult(m_state->job.poolId(), m_state->job.id(), m_state->nonce2, m_hash + 32, + m_state->job.diff())); + } + } - std::this_thread::yield(); - } - - consumeJob(); - } + consumeJob(); + } } -bool DoubleWorker::resume(const Job &job) +bool DoubleWorker::resume(const Job & job) { - if (m_state->job.poolId() == -1 && job.poolId() >= 0 && job.id() == m_pausedState->job.id()) { - *m_state = *m_pausedState; - return true; - } + if(m_state->job.poolId() == -1 && job.poolId() >= 0 && job.id() == m_pausedState->job.id()) + { + *m_state = *m_pausedState; + return true; + } - return false; + return false; } void DoubleWorker::consumeJob() { - Job job = Workers::job(); - m_sequence = Workers::sequence(); - if (m_state->job == job) { - return; - } + Job job = Workers::job(); + m_sequence = Workers::sequence(); + if(m_state->job == job) + { + return; + } - save(job); + save(job); - if (resume(job)) { - return; - } + if(resume(job)) + { + return; + } - m_state->job = std::move(job); - memcpy(m_state->blob, m_state->job.blob(), m_state->job.size()); - memcpy(m_state->blob + m_state->job.size(), m_state->job.blob(), m_state->job.size()); + m_state->job = std::move(job); + memcpy(m_state->blob, m_state->job.blob(), m_state->job.size()); + memcpy(m_state->blob + m_state->job.size(), m_state->job.blob(), m_state->job.size()); - if (m_state->job.isNicehash()) { - m_state->nonce1 = (*Job::nonce(m_state->blob) & 0xff000000U) + (0xffffffU / (m_threads * 2) * m_id); - m_state->nonce2 = (*Job::nonce(m_state->blob + m_state->job.size()) & 0xff000000U) + (0xffffffU / (m_threads * 2) * (m_id + m_threads)); - } - else { - m_state->nonce1 = 0xffffffffU / (m_threads * 2) * m_id; - m_state->nonce2 = 0xffffffffU / (m_threads * 2) * (m_id + m_threads); - } + if(m_state->job.isNicehash()) + { + m_state->nonce1 = (*Job::nonce(m_state->blob) & 0xff000000U) + (0xffffffU / + (m_threads * 2) * m_id); + m_state->nonce2 = (*Job::nonce(m_state->blob + m_state->job.size()) & 0xff000000U) + (0xffffffU / + (m_threads * 2) * (m_id + m_threads)); + } + else + { + m_state->nonce1 = 0xffffffffU / (m_threads * 2) * m_id; + m_state->nonce2 = 0xffffffffU / (m_threads * 2) * (m_id + m_threads); + } } -void DoubleWorker::save(const Job &job) +void DoubleWorker::save(const Job & job) { - if (job.poolId() == -1 && m_state->job.poolId() >= 0) { - *m_pausedState = *m_state; - } + if(job.poolId() == -1 && m_state->job.poolId() >= 0) + { + *m_pausedState = *m_state; + } } diff --git a/src/workers/DoubleWorker.h b/src/workers/DoubleWorker.h index 711f4bd1..267ae2f0 100644 --- a/src/workers/DoubleWorker.h +++ b/src/workers/DoubleWorker.h @@ -37,21 +37,21 @@ class Handle; class DoubleWorker : public Worker { public: - DoubleWorker(Handle *handle); - ~DoubleWorker(); + DoubleWorker(Handle* handle); + ~DoubleWorker(); - void start() override; + void start() override; private: - bool resume(const Job &job); - void consumeJob(); - void save(const Job &job); + bool resume(const Job & job); + void consumeJob(); + void save(const Job & job); - class State; + class State; - uint8_t m_hash[64]; - State *m_state; - State *m_pausedState; + uint8_t m_hash[64]; + State* m_state; + State* m_pausedState; }; diff --git a/src/workers/Handle.cpp b/src/workers/Handle.cpp index c461cee7..b6111fd3 100644 --- a/src/workers/Handle.cpp +++ b/src/workers/Handle.cpp @@ -26,22 +26,22 @@ Handle::Handle(int threadId, int threads, int64_t affinity, int priority) : - m_priority(priority), - m_threadId(threadId), - m_threads(threads), - m_affinity(affinity), - m_worker(nullptr) + m_priority(priority), + m_threadId(threadId), + m_threads(threads), + m_affinity(affinity), + m_worker(nullptr) { } void Handle::join() { - uv_thread_join(&m_thread); + uv_thread_join(&m_thread); } -void Handle::start(void (*callback) (void *)) +void Handle::start(void (*callback)(void*)) { - uv_thread_create(&m_thread, callback, this); + uv_thread_create(&m_thread, callback, this); } diff --git a/src/workers/Handle.h b/src/workers/Handle.h index 9faae0d0..f95dfdda 100644 --- a/src/workers/Handle.h +++ b/src/workers/Handle.h @@ -35,24 +35,42 @@ class IWorker; class Handle { public: - Handle(int threadId, int threads, int64_t affinity, int priority); - void join(); - void start(void (*callback) (void *)); + Handle(int threadId, int threads, int64_t affinity, int priority); + void join(); + void start(void (*callback)(void*)); - inline int priority() const { return m_priority; } - inline int threadId() const { return m_threadId; } - inline int threads() const { return m_threads; } - inline int64_t affinity() const { return m_affinity; } - inline IWorker *worker() const { return m_worker; } - inline void setWorker(IWorker *worker) { m_worker = worker; } + inline int priority() const + { + return m_priority; + } + inline int threadId() const + { + return m_threadId; + } + inline int threads() const + { + return m_threads; + } + inline int64_t affinity() const + { + return m_affinity; + } + inline IWorker* worker() const + { + return m_worker; + } + inline void setWorker(IWorker* worker) + { + m_worker = worker; + } private: - int m_priority; - int m_threadId; - int m_threads; - int64_t m_affinity; - IWorker *m_worker; - uv_thread_t m_thread; + int m_priority; + int m_threadId; + int m_threads; + int64_t m_affinity; + IWorker* m_worker; + uv_thread_t m_thread; }; diff --git a/src/workers/Hashrate.cpp b/src/workers/Hashrate.cpp index bd5b7df6..83b4dc43 100644 --- a/src/workers/Hashrate.cpp +++ b/src/workers/Hashrate.cpp @@ -22,7 +22,8 @@ */ -#include +#include + #include #include #include @@ -32,152 +33,152 @@ #include "workers/Hashrate.h" -inline const char *format(double h, char* buf, size_t size) +inline const char* format(double h, char* buf, size_t size) { - if (isnormal(h)) { - snprintf(buf, size, "%03.1f", h); - return buf; - } - - return "n/a"; + snprintf(buf, size, "%03.1f", h); + return buf; } Hashrate::Hashrate(int threads) : - m_highest(0.0), - m_threads(threads) + m_highest(0.0), + m_threads(threads) { - m_counts = new uint64_t*[threads]; - m_timestamps = new uint64_t*[threads]; - m_top = new uint32_t[threads]; + m_counts = new uint64_t* [threads]; + m_timestamps = new uint64_t* [threads]; + m_top = new uint32_t[threads]; - for (int i = 0; i < threads; i++) { - m_counts[i] = new uint64_t[kBucketSize]; - m_timestamps[i] = new uint64_t[kBucketSize]; - m_top[i] = 0; + for(int i = 0; i < threads; i++) + { + m_counts[i] = new uint64_t[kBucketSize]; + m_timestamps[i] = new uint64_t[kBucketSize]; + m_top[i] = 0; - memset(m_counts[0], 0, sizeof(uint64_t) * kBucketSize); - memset(m_timestamps[0], 0, sizeof(uint64_t) * kBucketSize); - } + memset(m_counts[0], 0, sizeof(uint64_t) * kBucketSize); + memset(m_timestamps[0], 0, sizeof(uint64_t) * kBucketSize); + } - const int printTime = Options::i()->printTime(); + const int printTime = Options::i()->printTime(); - if (printTime > 0) { - uv_timer_init(uv_default_loop(), &m_timer); - m_timer.data = this; + if(printTime > 0) + { + uv_timer_init(uv_default_loop(), &m_timer); + m_timer.data = this; - uv_timer_start(&m_timer, Hashrate::onReport, (printTime + 4) * 1000, printTime * 1000); - } + uv_timer_start(&m_timer, Hashrate::onReport, (printTime + 4) * 1000, printTime * 1000); + } } double Hashrate::calc(size_t ms) const { - double result = 0.0; - double data; + double result = 0.0; + double data; - for (int i = 0; i < m_threads; ++i) { - data = calc(i, ms); - if (isnormal(data)) { - result += data; - } - } + for(int i = 0; i < m_threads; ++i) + { + data = calc(i, ms); + result += data; + } - return result; + return result; } double Hashrate::calc(size_t threadId, size_t ms) const { - using namespace std::chrono; - const uint64_t now = time_point_cast(high_resolution_clock::now()).time_since_epoch().count(); + const uint64_t now = time(NULL); - uint64_t earliestHashCount = 0; - uint64_t earliestStamp = 0; - uint64_t lastestStamp = 0; - uint64_t lastestHashCnt = 0; - bool haveFullSet = false; + uint64_t earliestHashCount = 0; + uint64_t earliestStamp = 0; + uint64_t lastestStamp = 0; + uint64_t lastestHashCnt = 0; + bool haveFullSet = false; - for (size_t i = 1; i < kBucketSize; i++) { - const size_t idx = (m_top[threadId] - i) & kBucketMask; + for(size_t i = 1; i < kBucketSize; i++) + { + const size_t idx = (m_top[threadId] - i) & kBucketMask; - if (m_timestamps[threadId][idx] == 0) { - break; - } + if(m_timestamps[threadId][idx] == 0) + { + break; + } - if (lastestStamp == 0) { - lastestStamp = m_timestamps[threadId][idx]; - lastestHashCnt = m_counts[threadId][idx]; - } + if(lastestStamp == 0) + { + lastestStamp = m_timestamps[threadId][idx]; + lastestHashCnt = m_counts[threadId][idx]; + } - if (now - m_timestamps[threadId][idx] > ms) { - haveFullSet = true; - break; - } + if(now - m_timestamps[threadId][idx] > ms) + { + haveFullSet = true; + break; + } - earliestStamp = m_timestamps[threadId][idx]; - earliestHashCount = m_counts[threadId][idx]; - } + earliestStamp = m_timestamps[threadId][idx]; + earliestHashCount = m_counts[threadId][idx]; + } - if (!haveFullSet || earliestStamp == 0 || lastestStamp == 0) { - return nan(""); - } + if(!haveFullSet || earliestStamp == 0 || lastestStamp == 0) + { + return 0; + } - if (lastestStamp - earliestStamp == 0) { - return nan(""); - } + if(lastestStamp - earliestStamp == 0) + { + return 0; + } - double hashes, time; - hashes = (double) lastestHashCnt - earliestHashCount; - time = (double) lastestStamp - earliestStamp; - time /= 1000.0; + double hashes, time; + hashes = (double) lastestHashCnt - earliestHashCount; + time = (double) lastestStamp - earliestStamp; + time /= 1000.0; - return hashes / time; + return hashes / time; } void Hashrate::add(size_t threadId, uint64_t count, uint64_t timestamp) { - const size_t top = m_top[threadId]; - m_counts[threadId][top] = count; - m_timestamps[threadId][top] = timestamp; + const size_t top = m_top[threadId]; + m_counts[threadId][top] = count; + m_timestamps[threadId][top] = timestamp; - m_top[threadId] = (top + 1) & kBucketMask; + m_top[threadId] = (top + 1) & kBucketMask; } void Hashrate::print() { - char num1[8]; - char num2[8]; - char num3[8]; - char num4[8]; + char num1[8]; + char num2[8]; + char num3[8]; + char num4[8]; - LOG_INFO(Options::i()->colors() ? "\x1B[01;37mspeed\x1B[0m 2.5s/60s/15m \x1B[01;36m%s \x1B[22;36m%s %s \x1B[01;36mH/s\x1B[0m max: \x1B[01;36m%s H/s" : "speed 2.5s/60s/15m %s %s %s H/s max: %s H/s", - format(calc(ShortInterval), num1, sizeof(num1)), - format(calc(MediumInterval), num2, sizeof(num2)), - format(calc(LargeInterval), num3, sizeof(num3)), - format(m_highest, num4, sizeof(num4)) - ); + LOG_INFO("speed 2.5s/60s/15m " << format(calc(ShortInterval), num1, + sizeof(num1)) << " " << format(calc(MediumInterval), num2, sizeof(num2)) << " " << format(calc(LargeInterval), + num3, sizeof(num3)) << " H/s max: " << format(m_highest, num4, sizeof(num4)) << " H/s"); } void Hashrate::stop() { - uv_timer_stop(&m_timer); + uv_timer_stop(&m_timer); } void Hashrate::updateHighest() { - double highest = calc(ShortInterval); - if (isnormal(highest) && highest > m_highest) { - m_highest = highest; - } + double highest = calc(ShortInterval); + if(0 != highest && highest > m_highest) + { + m_highest = highest; + } } -void Hashrate::onReport(uv_timer_t *handle) +void Hashrate::onReport(uv_timer_t* handle) { - static_cast(handle->data)->print(); + static_cast(handle->data)->print(); } diff --git a/src/workers/Hashrate.h b/src/workers/Hashrate.h index 026c0cdf..eb577244 100644 --- a/src/workers/Hashrate.h +++ b/src/workers/Hashrate.h @@ -32,35 +32,45 @@ class Hashrate { public: - enum Intervals { - ShortInterval = 2500, - MediumInterval = 60000, - LargeInterval = 900000 - }; + enum Intervals + { + ShortInterval = 2500, + MediumInterval = 60000, + LargeInterval = 900000 + }; - Hashrate(int threads); - double calc(size_t ms) const; - double calc(size_t threadId, size_t ms) const; - void add(size_t threadId, uint64_t count, uint64_t timestamp); - void print(); - void stop(); - void updateHighest(); + Hashrate(int threads); + double calc(size_t ms) const; + double calc(size_t threadId, size_t ms) const; + void add(size_t threadId, uint64_t count, uint64_t timestamp); + void print(); + void stop(); + void updateHighest(); - inline double highest() const { return m_highest; } - inline int threads() const { return m_threads; } + inline double highest() const + { + return m_highest; + } + inline int threads() const + { + return m_threads; + } private: - static void onReport(uv_timer_t *handle); + static void onReport(uv_timer_t* handle); - constexpr static size_t kBucketSize = 2 << 11; - constexpr static size_t kBucketMask = kBucketSize - 1; + enum + { + kBucketSize = 2 << 11, + kBucketMask = kBucketSize - 1, + }; - double m_highest; - int m_threads; - uint32_t* m_top; - uint64_t** m_counts; - uint64_t** m_timestamps; - uv_timer_t m_timer; + double m_highest; + int m_threads; + uint32_t* m_top; + uint64_t** m_counts; + uint64_t** m_timestamps; + uv_timer_t m_timer; }; diff --git a/src/workers/SingleWorker.cpp b/src/workers/SingleWorker.cpp index ecb566f8..e359b2ed 100644 --- a/src/workers/SingleWorker.cpp +++ b/src/workers/SingleWorker.cpp @@ -21,99 +21,113 @@ * along with this program. If not, see . */ - -#include - - #include "crypto/CryptoNight.h" #include "workers/SingleWorker.h" #include "workers/Workers.h" +#ifndef _WIN32 +#include +#endif -SingleWorker::SingleWorker(Handle *handle) - : Worker(handle) +SingleWorker::SingleWorker(Handle* handle) + : Worker(handle) { } void SingleWorker::start() { - while (Workers::sequence() > 0) { - if (Workers::isPaused()) { - do { - std::this_thread::sleep_for(std::chrono::milliseconds(200)); - } - while (Workers::isPaused()); + while(Workers::sequence() > 0) + { + if(Workers::isPaused()) + { + do + { +#ifdef _WIN32 + Sleep(200); +#else + std::this_thread::sleep_for(std::chrono::milliseconds(200)); +#endif + } + while(Workers::isPaused()); - if (Workers::sequence() == 0) { - break; - } + if(Workers::sequence() == 0) + { + break; + } - consumeJob(); - } + consumeJob(); + } - while (!Workers::isOutdated(m_sequence)) { - if ((m_count & 0xF) == 0) { - storeStats(); - } + while(!Workers::isOutdated(m_sequence)) + { + if((m_count & 0xF) == 0) + { + storeStats(); + } - m_count++; - *m_job.nonce() = ++m_result.nonce; + m_count++; + *m_job.nonce() = ++m_result.nonce; - if (CryptoNight::hash(m_job, m_result, m_ctx)) { - Workers::submit(m_result); - } + if(CryptoNight::hash(m_job, m_result, m_ctx)) + { + Workers::submit(m_result); + } + } - std::this_thread::yield(); - } - - consumeJob(); - } + consumeJob(); + } } -bool SingleWorker::resume(const Job &job) +bool SingleWorker::resume(const Job & job) { - if (m_job.poolId() == -1 && job.poolId() >= 0 && job.id() == m_paused.id()) { - m_job = m_paused; - m_result = m_job; - m_result.nonce = *m_job.nonce(); - return true; - } + if(m_job.poolId() == -1 && job.poolId() >= 0 && job.id() == m_paused.id()) + { + m_job = m_paused; + m_result = m_job; + m_result.nonce = *m_job.nonce(); + return true; + } - return false; + return false; } void SingleWorker::consumeJob() { - Job job = Workers::job(); - m_sequence = Workers::sequence(); - if (m_job == job) { - return; - } + Job job = Workers::job(); + m_sequence = Workers::sequence(); + if(m_job == job) + { + return; + } - save(job); + save(job); - if (resume(job)) { - return; - } + if(resume(job)) + { + return; + } - m_job = std::move(job); - m_result = m_job; + m_job = std::move(job); + m_result = m_job; - if (m_job.isNicehash()) { - m_result.nonce = (*m_job.nonce() & 0xff000000U) + (0xffffffU / m_threads * m_id); - } - else { - m_result.nonce = 0xffffffffU / m_threads * m_id; - } + if(m_job.isNicehash()) + { + m_result.nonce = (*m_job.nonce() & 0xff000000U) + (0xffffffU / m_threads * m_id); + } + else + { + m_result.nonce = 0xffffffffU / m_threads * m_id; + } } -void SingleWorker::save(const Job &job) +void SingleWorker::save(const Job & job) { - if (job.poolId() == -1 && m_job.poolId() >= 0) { - m_paused = m_job; - } + if(job.poolId() == -1 && m_job.poolId() >= 0) + { + m_paused = m_job; + } } diff --git a/src/workers/SingleWorker.h b/src/workers/SingleWorker.h index 08ab1857..76c1a36b 100644 --- a/src/workers/SingleWorker.h +++ b/src/workers/SingleWorker.h @@ -36,18 +36,18 @@ class Handle; class SingleWorker : public Worker { public: - SingleWorker(Handle *handle); + SingleWorker(Handle* handle); - void start() override; + void start() override; private: - bool resume(const Job &job); - void consumeJob(); - void save(const Job &job); + bool resume(const Job & job); + void consumeJob(); + void save(const Job & job); - Job m_job; - Job m_paused; - JobResult m_result; + Job m_job; + Job m_paused; + JobResult m_result; }; diff --git a/src/workers/Worker.cpp b/src/workers/Worker.cpp index 02646ced..23de1770 100644 --- a/src/workers/Worker.cpp +++ b/src/workers/Worker.cpp @@ -21,30 +21,29 @@ * along with this program. If not, see . */ -#include - - #include "Cpu.h" #include "Mem.h" #include "Platform.h" #include "workers/Handle.h" #include "workers/Worker.h" +#include -Worker::Worker(Handle *handle) : - m_id(handle->threadId()), - m_threads(handle->threads()), - m_hashCount(0), - m_timestamp(0), - m_count(0), - m_sequence(0) +Worker::Worker(Handle* handle) : + m_id(handle->threadId()), + m_threads(handle->threads()), + m_hashCount(0), + m_timestamp(0), + m_count(0), + m_sequence(0) { - if (Cpu::threads() > 1 && handle->affinity() != -1L) { - Cpu::setAffinity(m_id, handle->affinity()); - } + if(Cpu::threads() > 1 && handle->affinity() != -1L) + { + Cpu::setAffinity(m_id, handle->affinity()); + } - Platform::setThreadPriority(handle->priority()); - m_ctx = Mem::create(m_id); + Platform::setThreadPriority(handle->priority()); + m_ctx = Mem::create(m_id); } @@ -55,9 +54,7 @@ Worker::~Worker() void Worker::storeStats() { - using namespace std::chrono; - - const uint64_t timestamp = time_point_cast(high_resolution_clock::now()).time_since_epoch().count(); - m_hashCount.store(m_count, std::memory_order_relaxed); - m_timestamp.store(timestamp, std::memory_order_relaxed); + const uint64_t timestamp = time(NULL); + m_hashCount = m_count; + m_timestamp = timestamp; } diff --git a/src/workers/Worker.h b/src/workers/Worker.h index 11c4a198..9b144adf 100644 --- a/src/workers/Worker.h +++ b/src/workers/Worker.h @@ -25,10 +25,10 @@ #define __WORKER_H__ -#include #include +#include "interfaces/interface.h" #include "interfaces/IWorker.h" @@ -39,22 +39,28 @@ class Handle; class Worker : public IWorker { public: - Worker(Handle *handle); - ~Worker(); + Worker(Handle* handle); + ~Worker(); - inline uint64_t hashCount() const override { return m_hashCount.load(std::memory_order_relaxed); } - inline uint64_t timestamp() const override { return m_timestamp.load(std::memory_order_relaxed); } + inline uint64_t hashCount() const override + { + return m_hashCount; + } + inline uint64_t timestamp() const override + { + return m_timestamp; + } protected: - void storeStats(); + void storeStats(); - cryptonight_ctx *m_ctx; - int m_id; - int m_threads; - std::atomic m_hashCount; - std::atomic m_timestamp; - uint64_t m_count; - uint64_t m_sequence; + cryptonight_ctx* m_ctx; + int m_id; + int m_threads; + uint64_t m_hashCount; + uint64_t m_timestamp; + uint64_t m_count; + uint64_t m_sequence; }; diff --git a/src/workers/Workers.cpp b/src/workers/Workers.cpp index 039a1793..f2dae94b 100644 --- a/src/workers/Workers.cpp +++ b/src/workers/Workers.cpp @@ -37,11 +37,11 @@ bool Workers::m_active = false; bool Workers::m_enabled = true; -Hashrate *Workers::m_hashrate = nullptr; -IJobResultListener *Workers::m_listener = nullptr; +Hashrate* Workers::m_hashrate = nullptr; +IJobResultListener* Workers::m_listener = nullptr; Job Workers::m_job; -std::atomic Workers::m_paused; -std::atomic Workers::m_sequence; +int Workers::m_paused; +uint64_t Workers::m_sequence; std::list Workers::m_queue; std::vector Workers::m_workers; uint64_t Workers::m_ticks = 0; @@ -53,148 +53,162 @@ uv_timer_t Workers::m_timer; Job Workers::job() { - uv_rwlock_rdlock(&m_rwlock); - Job job = m_job; - uv_rwlock_rdunlock(&m_rwlock); + uv_rwlock_rdlock(&m_rwlock); + Job job = m_job; + uv_rwlock_rdunlock(&m_rwlock); - return job; + return job; } void Workers::printHashrate(bool detail) { - m_hashrate->print(); + m_hashrate->print(); } void Workers::setEnabled(bool enabled) { - if (m_enabled == enabled) { - return; - } + if(m_enabled == enabled) + { + return; + } - m_enabled = enabled; - if (!m_active) { - return; - } + m_enabled = enabled; + if(!m_active) + { + return; + } - m_paused = enabled ? 0 : 1; - m_sequence++; + m_paused = enabled ? 0 : 1; + m_sequence++; } -void Workers::setJob(const Job &job) +void Workers::setJob(const Job & job) { - uv_rwlock_wrlock(&m_rwlock); - m_job = job; - uv_rwlock_wrunlock(&m_rwlock); + uv_rwlock_wrlock(&m_rwlock); + m_job = job; + uv_rwlock_wrunlock(&m_rwlock); - m_active = true; - if (!m_enabled) { - return; - } + m_active = true; + if(!m_enabled) + { + return; + } - m_sequence++; - m_paused = 0; + m_sequence++; + m_paused = 0; } void Workers::start(int64_t affinity, int priority) { - const int threads = Mem::threads(); - m_hashrate = new Hashrate(threads); + const int threads = Mem::threads(); + m_hashrate = new Hashrate(threads); - uv_mutex_init(&m_mutex); - uv_rwlock_init(&m_rwlock); + uv_mutex_init(&m_mutex); + uv_rwlock_init(&m_rwlock); - m_sequence = 1; - m_paused = 1; + m_sequence = 1; + m_paused = 1; - uv_async_init(uv_default_loop(), &m_async, Workers::onResult); - uv_timer_init(uv_default_loop(), &m_timer); - uv_timer_start(&m_timer, Workers::onTick, 500, 500); + uv_async_init(uv_default_loop(), &m_async, Workers::onResult); + uv_timer_init(uv_default_loop(), &m_timer); + uv_timer_start(&m_timer, Workers::onTick, 500, 500); - for (int i = 0; i < threads; ++i) { - Handle *handle = new Handle(i, threads, affinity, priority); - m_workers.push_back(handle); - handle->start(Workers::onReady); - } + for(int i = 0; i < threads; ++i) + { + Handle* handle = new Handle(i, threads, affinity, priority); + m_workers.push_back(handle); + handle->start(Workers::onReady); + } } void Workers::stop() { - uv_timer_stop(&m_timer); - m_hashrate->stop(); + uv_timer_stop(&m_timer); + m_hashrate->stop(); - uv_close(reinterpret_cast(&m_async), nullptr); - m_paused = 0; - m_sequence = 0; + uv_close(reinterpret_cast(&m_async), nullptr); + m_paused = 0; + m_sequence = 0; - for (size_t i = 0; i < m_workers.size(); ++i) { - m_workers[i]->join(); - } + for(size_t i = 0; i < m_workers.size(); ++i) + { + m_workers[i]->join(); + } } -void Workers::submit(const JobResult &result) +void Workers::submit(const JobResult & result) { - uv_mutex_lock(&m_mutex); - m_queue.push_back(result); - uv_mutex_unlock(&m_mutex); + uv_mutex_lock(&m_mutex); + m_queue.push_back(result); + uv_mutex_unlock(&m_mutex); - uv_async_send(&m_async); + uv_async_send(&m_async); } -void Workers::onReady(void *arg) +void Workers::onReady(void* arg) { - auto handle = static_cast(arg); - if (Mem::isDoubleHash()) { - handle->setWorker(new DoubleWorker(handle)); - } - else { - handle->setWorker(new SingleWorker(handle)); - } + auto handle = static_cast(arg); + if(Mem::isDoubleHash()) + { + handle->setWorker(new DoubleWorker(handle)); + } + else + { + handle->setWorker(new SingleWorker(handle)); + } - handle->worker()->start(); + handle->worker()->start(); } -void Workers::onResult(uv_async_t *handle) +void Workers::onResult(uv_async_t* handle) { - std::list results; + std::list results; - uv_mutex_lock(&m_mutex); - while (!m_queue.empty()) { - results.push_back(std::move(m_queue.front())); - m_queue.pop_front(); - } - uv_mutex_unlock(&m_mutex); + uv_mutex_lock(&m_mutex); + while(!m_queue.empty()) + { + results.push_back(std::move(m_queue.front())); + m_queue.pop_front(); + } + uv_mutex_unlock(&m_mutex); - for (auto result : results) { - m_listener->onJobResult(result); - } + for(std::list::iterator itr = results.begin(); itr != results.end(); ++itr) + { + auto result = *itr; + m_listener->onJobResult(result); + } - results.clear(); + results.clear(); } -void Workers::onTick(uv_timer_t *handle) +void Workers::onTick(uv_timer_t* handle) { - for (Handle *handle : m_workers) { - if (!handle->worker()) { - return; - } + for(size_t i = 0; i < m_workers.size(); ++i) + { + Handle* handle = m_workers[i]; + if(!handle->worker()) + { + return; + } - m_hashrate->add(handle->threadId(), handle->worker()->hashCount(), handle->worker()->timestamp()); - } + m_hashrate->add(handle->threadId(), handle->worker()->hashCount(), handle->worker()->timestamp()); + } - if ((m_ticks++ & 0xF) == 0) { - m_hashrate->updateHighest(); - } + if((m_ticks++ & 0xF) == 0) + { + m_hashrate->updateHighest(); + } # ifndef XMRIG_NO_API - Api::tick(m_hashrate); + Api::tick(m_hashrate); # endif } diff --git a/src/workers/Workers.h b/src/workers/Workers.h index e76d0a62..e2ee5d65 100644 --- a/src/workers/Workers.h +++ b/src/workers/Workers.h @@ -24,8 +24,6 @@ #ifndef __WORKERS_H__ #define __WORKERS_H__ - -#include #include #include #include @@ -42,40 +40,60 @@ class IJobResultListener; class Workers { public: - static Job job(); - static void printHashrate(bool detail); - static void setEnabled(bool enabled); - static void setJob(const Job &job); - static void start(int64_t affinity, int priority); - static void stop(); - static void submit(const JobResult &result); + static Job job(); + static void printHashrate(bool detail); + static void setEnabled(bool enabled); + static void setJob(const Job & job); + static void start(int64_t affinity, int priority); + static void stop(); + static void submit(const JobResult & result); - static inline bool isEnabled() { return m_enabled; } - static inline bool isOutdated(uint64_t sequence) { return m_sequence.load(std::memory_order_relaxed) != sequence; } - static inline bool isPaused() { return m_paused.load(std::memory_order_relaxed) == 1; } - static inline uint64_t sequence() { return m_sequence.load(std::memory_order_relaxed); } - static inline void pause() { m_active = false; m_paused = 1; m_sequence++; } - static inline void setListener(IJobResultListener *listener) { m_listener = listener; } + static inline bool isEnabled() + { + return m_enabled; + } + static inline bool isOutdated(uint64_t sequence) + { + return m_sequence != sequence; + } + static inline bool isPaused() + { + return m_paused == 1; + } + static inline uint64_t sequence() + { + return m_sequence; + } + static inline void pause() + { + m_active = false; + m_paused = 1; + m_sequence++; + } + static inline void setListener(IJobResultListener* listener) + { + m_listener = listener; + } private: - static void onReady(void *arg); - static void onResult(uv_async_t *handle); - static void onTick(uv_timer_t *handle); + static void onReady(void* arg); + static void onResult(uv_async_t* handle); + static void onTick(uv_timer_t* handle); - static bool m_active; - static bool m_enabled; - static Hashrate *m_hashrate; - static IJobResultListener *m_listener; - static Job m_job; - static std::atomic m_paused; - static std::atomic m_sequence; - static std::list m_queue; - static std::vector m_workers; - static uint64_t m_ticks; - static uv_async_t m_async; - static uv_mutex_t m_mutex; - static uv_rwlock_t m_rwlock; - static uv_timer_t m_timer; + static bool m_active; + static bool m_enabled; + static Hashrate* m_hashrate; + static IJobResultListener* m_listener; + static Job m_job; + static int m_paused; + static uint64_t m_sequence; + static std::list m_queue; + static std::vector m_workers; + static uint64_t m_ticks; + static uv_async_t m_async; + static uv_mutex_t m_mutex; + static uv_rwlock_t m_rwlock; + static uv_timer_t m_timer; }; diff --git a/src/xmrig.cpp b/src/xmrig.cpp index 48362ada..dcf0a367 100644 --- a/src/xmrig.cpp +++ b/src/xmrig.cpp @@ -24,8 +24,9 @@ #include "App.h" -int main(int argc, char **argv) { - App app(argc, argv); +int main(int argc, char** argv) +{ + App app(argc, argv); - return app.exec(); + return app.exec(); }