diff options
author | chriseth <chris@ethereum.org> | 2018-11-14 02:33:35 +0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2018-11-14 02:33:35 +0800 |
commit | 1d4f565a64988a3400847d2655ca24f73f234bc6 (patch) | |
tree | caaa6c26e307513505349b50ca4f2a8a9506752b /libdevcore | |
parent | 59dbf8f1085b8b92e8b7eb0ce380cbeb642e97eb (diff) | |
parent | 91b6b8a88e76016e0324036cb7a7f9300a1e2439 (diff) | |
download | dexon-solidity-1d4f565a64988a3400847d2655ca24f73f234bc6.tar dexon-solidity-1d4f565a64988a3400847d2655ca24f73f234bc6.tar.gz dexon-solidity-1d4f565a64988a3400847d2655ca24f73f234bc6.tar.bz2 dexon-solidity-1d4f565a64988a3400847d2655ca24f73f234bc6.tar.lz dexon-solidity-1d4f565a64988a3400847d2655ca24f73f234bc6.tar.xz dexon-solidity-1d4f565a64988a3400847d2655ca24f73f234bc6.tar.zst dexon-solidity-1d4f565a64988a3400847d2655ca24f73f234bc6.zip |
Merge pull request #5416 from ethereum/develop
Merge develop into release for 0.5.0
Diffstat (limited to 'libdevcore')
-rw-r--r-- | libdevcore/Algorithms.h | 8 | ||||
-rw-r--r-- | libdevcore/Common.h | 10 | ||||
-rw-r--r-- | libdevcore/CommonData.cpp | 37 | ||||
-rw-r--r-- | libdevcore/CommonData.h | 43 | ||||
-rw-r--r-- | libdevcore/CommonIO.cpp | 60 | ||||
-rw-r--r-- | libdevcore/CommonIO.h | 14 | ||||
-rw-r--r-- | libdevcore/Exceptions.cpp | 6 | ||||
-rw-r--r-- | libdevcore/FixedHash.h | 16 | ||||
-rw-r--r-- | libdevcore/Keccak256.cpp | 186 | ||||
-rw-r--r-- | libdevcore/Keccak256.h (renamed from libdevcore/SHA3.h) | 8 | ||||
-rw-r--r-- | libdevcore/SHA3.cpp | 240 | ||||
-rw-r--r-- | libdevcore/StringUtils.cpp | 19 | ||||
-rw-r--r-- | libdevcore/StringUtils.h | 38 | ||||
-rw-r--r-- | libdevcore/SwarmHash.cpp | 2 | ||||
-rw-r--r-- | libdevcore/Visitor.h | 128 | ||||
-rw-r--r-- | libdevcore/boost_multiprecision_number_compare_bug_workaround.hpp | 68 |
16 files changed, 509 insertions, 374 deletions
diff --git a/libdevcore/Algorithms.h b/libdevcore/Algorithms.h index b2540668..7fe2472d 100644 --- a/libdevcore/Algorithms.h +++ b/libdevcore/Algorithms.h @@ -32,11 +32,13 @@ template <typename V> class CycleDetector { public: + using Visitor = std::function<void(V const&, CycleDetector&, size_t)>; + /// Initializes the cycle detector /// @param _visit function that is given the current vertex /// and is supposed to call @a run on all /// adjacent vertices. - explicit CycleDetector(std::function<void(V const&, CycleDetector&)> _visit): + explicit CycleDetector(Visitor _visit): m_visit(std::move(_visit)) { } @@ -55,7 +57,7 @@ public: m_processing.insert(&_vertex); m_depth++; - m_visit(_vertex, *this); + m_visit(_vertex, *this, m_depth); m_depth--; if (m_firstCycleVertex && m_depth == 1) m_firstCycleVertex = &_vertex; @@ -66,7 +68,7 @@ public: } private: - std::function<void(V const&, CycleDetector&)> m_visit; + Visitor m_visit; std::set<V const*> m_processing; std::set<V const*> m_processed; size_t m_depth = 0; diff --git a/libdevcore/Common.h b/libdevcore/Common.h index 2543855d..6208424e 100644 --- a/libdevcore/Common.h +++ b/libdevcore/Common.h @@ -40,7 +40,6 @@ #include <libdevcore/vector_ref.h> #if defined(__GNUC__) -#pragma warning(push) #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wunused-parameter" #endif // defined(__GNUC__) @@ -57,7 +56,6 @@ #include <boost/multiprecision/cpp_int.hpp> #if defined(__GNUC__) -#pragma warning(pop) #pragma GCC diagnostic pop #endif // defined(__GNUC__) @@ -66,15 +64,13 @@ #include <functional> #include <string> -using byte = uint8_t; - namespace dev { // Binary data types. -using bytes = std::vector<byte>; -using bytesRef = vector_ref<byte>; -using bytesConstRef = vector_ref<byte const>; +using bytes = std::vector<uint8_t>; +using bytesRef = vector_ref<uint8_t>; +using bytesConstRef = vector_ref<uint8_t const>; // Numeric types. using bigint = boost::multiprecision::number<boost::multiprecision::cpp_int_backend<>>; diff --git a/libdevcore/CommonData.cpp b/libdevcore/CommonData.cpp index 445d11cd..8d2639c9 100644 --- a/libdevcore/CommonData.cpp +++ b/libdevcore/CommonData.cpp @@ -22,7 +22,7 @@ #include <libdevcore/CommonData.h> #include <libdevcore/Exceptions.h> #include <libdevcore/Assertions.h> -#include <libdevcore/SHA3.h> +#include <libdevcore/Keccak256.h> #include <boost/algorithm/string.hpp> @@ -64,7 +64,7 @@ bytes dev::fromHex(std::string const& _s, WhenError _throw) int h = fromHex(_s[i], WhenError::DontThrow); int l = fromHex(_s[i + 1], WhenError::DontThrow); if (h != -1 && l != -1) - ret.push_back((byte)(h * 16 + l)); + ret.push_back((uint8_t)(h * 16 + l)); else if (_throw == WhenError::Throw) BOOST_THROW_EXCEPTION(BadHexCharacter()); else @@ -76,18 +76,18 @@ bytes dev::fromHex(std::string const& _s, WhenError _throw) bool dev::passesAddressChecksum(string const& _str, bool _strict) { - string s = _str.substr(0, 2) == "0x" ? _str.substr(2) : _str; + string s = _str.substr(0, 2) == "0x" ? _str : "0x" + _str; - if (s.length() != 40) + if (s.length() != 42) return false; if (!_strict && ( - _str.find_first_of("abcdef") == string::npos || - _str.find_first_of("ABCDEF") == string::npos + s.find_first_of("abcdef") == string::npos || + s.find_first_of("ABCDEF") == string::npos )) return true; - return _str == dev::getChecksummedAddress(_str); + return s == dev::getChecksummedAddress(s); } string dev::getChecksummedAddress(string const& _addr) @@ -110,3 +110,26 @@ string dev::getChecksummedAddress(string const& _addr) } return ret; } + +bool dev::isValidHex(string const& _string) +{ + if (_string.substr(0, 2) != "0x") + return false; + if (_string.find_first_not_of("0123456789abcdefABCDEF", 2) != string::npos) + return false; + return true; +} + +bool dev::isValidDecimal(string const& _string) +{ + if (_string.empty()) + return false; + if (_string == "0") + return true; + // No leading zeros + if (_string.front() == '0') + return false; + if (_string.find_first_not_of("0123456789") != string::npos) + return false; + return true; +} diff --git a/libdevcore/CommonData.h b/libdevcore/CommonData.h index e410af5c..fedd3af2 100644 --- a/libdevcore/CommonData.h +++ b/libdevcore/CommonData.h @@ -25,11 +25,14 @@ #include <libdevcore/Common.h> +#include <boost/optional.hpp> + #include <vector> #include <type_traits> #include <cstring> #include <string> #include <set> +#include <functional> namespace dev { @@ -85,7 +88,7 @@ inline std::string asString(bytesConstRef _b) /// Converts a string to a byte array containing the string's (byte) data. inline bytes asBytes(std::string const& _b) { - return bytes((byte const*)_b.data(), (byte const*)(_b.data() + _b.size())); + return bytes((uint8_t const*)_b.data(), (uint8_t const*)(_b.data() + _b.size())); } // Big-endian to/from host endian conversion functions. @@ -114,7 +117,7 @@ inline T fromBigEndian(_In const& _bytes) { T ret = (T)0; for (auto i: _bytes) - ret = (T)((ret << 8) | (byte)(typename std::make_unsigned<typename _In::value_type>::type)i); + ret = (T)((ret << 8) | (uint8_t)(typename std::make_unsigned<typename _In::value_type>::type)i); return ret; } inline bytes toBigEndian(u256 _val) { bytes ret(32); toBigEndian(_val, ret); return ret; } @@ -132,7 +135,7 @@ inline bytes toCompactBigEndian(T _val, unsigned _min = 0) toBigEndian(_val, ret); return ret; } -inline bytes toCompactBigEndian(byte _val, unsigned _min = 0) +inline bytes toCompactBigEndian(uint8_t _val, unsigned _min = 0) { return (_min || _val) ? bytes{ _val } : bytes{}; } @@ -229,6 +232,37 @@ bool contains(T const& _t, V const& _v) return std::end(_t) != std::find(std::begin(_t), std::end(_t), _v); } + +/// Function that iterates over a vector, calling a function on each of its +/// elements. If that function returns a vector, the element is replaced by +/// the returned vector. During the iteration, the original vector is only valid +/// on the current element and after that. The actual replacement takes +/// place at the end, but already visited elements might be invalidated. +/// If nothing is replaced, no copy is performed. +template <typename T, typename F> +void iterateReplacing(std::vector<T>& _vector, const F& _f) +{ + // Concept: _f must be Callable, must accept param T&, must return optional<vector<T>> + bool useModified = false; + std::vector<T> modifiedVector; + for (size_t i = 0; i < _vector.size(); ++i) + { + if (boost::optional<std::vector<T>> r = _f(_vector[i])) + { + if (!useModified) + { + std::move(_vector.begin(), _vector.begin() + i, back_inserter(modifiedVector)); + useModified = true; + } + modifiedVector += std::move(*r); + } + else if (useModified) + modifiedVector.emplace_back(std::move(_vector[i])); + } + if (useModified) + _vector = std::move(modifiedVector); +} + /// @returns true iff @a _str passess the hex address checksum test. /// @param _strict if false, hex strings with only uppercase or only lowercase letters /// are considered valid. @@ -238,4 +272,7 @@ bool passesAddressChecksum(std::string const& _str, bool _strict); /// @param hex strings that look like an address std::string getChecksummedAddress(std::string const& _addr); +bool isValidHex(std::string const& _string); +bool isValidDecimal(std::string const& _string); + } diff --git a/libdevcore/CommonIO.cpp b/libdevcore/CommonIO.cpp index 0063a8d4..cc730575 100644 --- a/libdevcore/CommonIO.cpp +++ b/libdevcore/CommonIO.cpp @@ -23,7 +23,6 @@ #include <iostream> #include <cstdlib> #include <fstream> -#include <stdio.h> #if defined(_WIN32) #include <windows.h> #else @@ -81,45 +80,6 @@ string dev::readStandardInput() return ret; } -void dev::writeFile(std::string const& _file, bytesConstRef _data, bool _writeDeleteRename) -{ - namespace fs = boost::filesystem; - if (_writeDeleteRename) - { - fs::path tempPath = fs::unique_path(_file + "-%%%%%%"); - writeFile(tempPath.string(), _data, false); - // will delete _file if it exists - fs::rename(tempPath, _file); - } - else - { - // create directory if not existent - fs::path p(_file); - if (!fs::exists(p.parent_path())) - { - fs::create_directories(p.parent_path()); - try - { - fs::permissions(p.parent_path(), fs::owner_all); - } - catch (...) - { - } - } - - ofstream s(_file, ios::trunc | ios::binary); - s.write(reinterpret_cast<char const*>(_data.data()), _data.size()); - assertThrow(s, FileError, "Could not write to file: " + _file); - try - { - fs::permissions(_file, fs::owner_read|fs::owner_write); - } - catch (...) - { - } - } -} - #if defined(_WIN32) class DisableConsoleBuffering { @@ -187,3 +147,23 @@ boost::filesystem::path dev::weaklyCanonicalFilesystemPath(boost::filesystem::pa return head / tail; } } + +string dev::absolutePath(string const& _path, string const& _reference) +{ + boost::filesystem::path p(_path); + // Anything that does not start with `.` is an absolute path. + if (p.begin() == p.end() || (*p.begin() != "." && *p.begin() != "..")) + return _path; + boost::filesystem::path result(_reference); + result.remove_filename(); + for (boost::filesystem::path::iterator it = p.begin(); it != p.end(); ++it) + if (*it == "..") + result = result.parent_path(); + else if (*it != ".") + result /= *it; + return result.generic_string(); +} + +string dev::sanitizePath(string const& _path) { + return boost::filesystem::path(_path).generic_string(); +} diff --git a/libdevcore/CommonIO.h b/libdevcore/CommonIO.h index 9ba68e74..b9f941ea 100644 --- a/libdevcore/CommonIO.h +++ b/libdevcore/CommonIO.h @@ -41,14 +41,6 @@ std::string readStandardInput(); /// Retrieve and returns a character from standard input (without waiting for EOL). int readStandardInputChar(); -/// Write the given binary data into the given file, replacing the file if it pre-exists. -/// Throws exception on error. -/// @param _writeDeleteRename useful not to lose any data: If set, first writes to another file in -/// the same directory and then moves that file. -void writeFile(std::string const& _file, bytesConstRef _data, bool _writeDeleteRename = false); -/// Write the given binary data into the given file, replacing the file if it pre-exists. -inline void writeFile(std::string const& _file, bytes const& _data, bool _writeDeleteRename = false) { writeFile(_file, bytesConstRef(&_data), _writeDeleteRename); } -inline void writeFile(std::string const& _file, std::string const& _data, bool _writeDeleteRename = false) { writeFile(_file, bytesConstRef(_data), _writeDeleteRename); } /// Converts arbitrary value to string representation using std::stringstream. template <class _T> std::string toString(_T const& _t) @@ -62,4 +54,10 @@ std::string toString(_T const& _t) /// Should be replaced by the boost implementation as soon as support for boost<1.60 can be dropped. boost::filesystem::path weaklyCanonicalFilesystemPath(boost::filesystem::path const &_path); +/// @returns the absolute path corresponding to @a _path relative to @a _reference. +std::string absolutePath(std::string const& _path, std::string const& _reference); + +/// Helper function to return path converted strings. +std::string sanitizePath(std::string const& _path); + } diff --git a/libdevcore/Exceptions.cpp b/libdevcore/Exceptions.cpp index f204dbc2..cff5abf4 100644 --- a/libdevcore/Exceptions.cpp +++ b/libdevcore/Exceptions.cpp @@ -17,8 +17,6 @@ #include <libdevcore/Exceptions.h> -#include <boost/lexical_cast.hpp> - using namespace std; using namespace dev; @@ -27,7 +25,7 @@ char const* Exception::what() const noexcept // Return the comment if available. if (string const* cmt = comment()) return cmt->data(); - + // Fallback to base what(). // Boost accepts nullptr, but the C++ standard doesn't // and crashes on some platforms. @@ -43,7 +41,7 @@ string Exception::lineInfo() const ret += *file; ret += ':'; if (line) - ret += boost::lexical_cast<string>(*line); + ret += to_string(*line); return ret; } diff --git a/libdevcore/FixedHash.h b/libdevcore/FixedHash.h index cd6e1da1..24b89840 100644 --- a/libdevcore/FixedHash.h +++ b/libdevcore/FixedHash.h @@ -79,7 +79,7 @@ public: operator Arith() const { return fromBigEndian<Arith>(m_data); } /// @returns true iff this is the empty hash. - explicit operator bool() const { return std::any_of(m_data.begin(), m_data.end(), [](byte _b) { return _b != 0; }); } + explicit operator bool() const { return std::any_of(m_data.begin(), m_data.end(), [](uint8_t _b) { return _b != 0; }); } // The obvious comparison operators. bool operator==(FixedHash const& _c) const { return m_data == _c.m_data; } @@ -90,9 +90,9 @@ public: FixedHash operator~() const { FixedHash ret; for (unsigned i = 0; i < N; ++i) ret[i] = ~m_data[i]; return ret; } /// @returns a particular byte from the hash. - byte& operator[](unsigned _i) { return m_data[_i]; } + uint8_t& operator[](unsigned _i) { return m_data[_i]; } /// @returns a particular byte from the hash. - byte operator[](unsigned _i) const { return m_data[_i]; } + uint8_t operator[](unsigned _i) const { return m_data[_i]; } /// @returns the hash as a user-readable hex string. std::string hex() const { return toHex(ref()); } @@ -104,19 +104,19 @@ public: bytesConstRef ref() const { return bytesConstRef(m_data.data(), N); } /// @returns a mutable byte pointer to the object's data. - byte* data() { return m_data.data(); } + uint8_t* data() { return m_data.data(); } /// @returns a constant byte pointer to the object's data. - byte const* data() const { return m_data.data(); } + uint8_t const* data() const { return m_data.data(); } /// @returns a copy of the object's data as a byte vector. bytes asBytes() const { return bytes(data(), data() + N); } /// @returns a mutable reference to the object's data as an STL array. - std::array<byte, N>& asArray() { return m_data; } + std::array<uint8_t, N>& asArray() { return m_data; } /// @returns a constant reference to the object's data as an STL array. - std::array<byte, N> const& asArray() const { return m_data; } + std::array<uint8_t, N> const& asArray() const { return m_data; } /// Returns the index of the first bit set to one, or size() * 8 if no bits are set. inline unsigned firstBitSet() const @@ -137,7 +137,7 @@ public: void clear() { m_data.fill(0); } private: - std::array<byte, N> m_data; ///< The binary data. + std::array<uint8_t, N> m_data; ///< The binary data. }; /// Stream I/O for the FixedHash class. diff --git a/libdevcore/Keccak256.cpp b/libdevcore/Keccak256.cpp new file mode 100644 index 00000000..7933fc7e --- /dev/null +++ b/libdevcore/Keccak256.cpp @@ -0,0 +1,186 @@ +/* + This file is part of solidity. + + solidity 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. + + solidity 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 solidity. If not, see <http://www.gnu.org/licenses/>. +*/ +/** @file SHA3.cpp + * @author Gav Wood <i@gavwood.com> + * @date 2014 + */ + +#include <libdevcore/Keccak256.h> + +#include <cstdint> +#include <cstdio> +#include <cstdlib> +#include <cstring> + +using namespace std; +using namespace dev; + +namespace dev +{ + +namespace +{ + +/** libkeccak-tiny + * + * A single-file implementation of SHA-3 and SHAKE. + * + * Implementor: David Leon Gil + * License: CC0, attribution kindly requested. Blame taken too, + * but not liability. + */ + +/******** The Keccak-f[1600] permutation ********/ + +/*** Constants. ***/ +static const uint8_t rho[24] = \ + { 1, 3, 6, 10, 15, 21, + 28, 36, 45, 55, 2, 14, + 27, 41, 56, 8, 25, 43, + 62, 18, 39, 61, 20, 44}; +static const uint8_t pi[24] = \ + {10, 7, 11, 17, 18, 3, + 5, 16, 8, 21, 24, 4, + 15, 23, 19, 13, 12, 2, + 20, 14, 22, 9, 6, 1}; +static const uint64_t RC[24] = \ + {1ULL, 0x8082ULL, 0x800000000000808aULL, 0x8000000080008000ULL, + 0x808bULL, 0x80000001ULL, 0x8000000080008081ULL, 0x8000000000008009ULL, + 0x8aULL, 0x88ULL, 0x80008009ULL, 0x8000000aULL, + 0x8000808bULL, 0x800000000000008bULL, 0x8000000000008089ULL, 0x8000000000008003ULL, + 0x8000000000008002ULL, 0x8000000000000080ULL, 0x800aULL, 0x800000008000000aULL, + 0x8000000080008081ULL, 0x8000000000008080ULL, 0x80000001ULL, 0x8000000080008008ULL}; + +/*** Helper macros to unroll the permutation. ***/ +#define rol(x, s) (((x) << s) | ((x) >> (64 - s))) +#define REPEAT6(e) e e e e e e +#define REPEAT24(e) REPEAT6(e e e e) +#define REPEAT5(e) e e e e e +#define FOR5(v, s, e) \ + v = 0; \ + REPEAT5(e; v += s;) + +/*** Keccak-f[1600] ***/ +static inline void keccakf(void* state) { + uint64_t* a = (uint64_t*)state; + uint64_t b[5] = {0}; + + for (int i = 0; i < 24; i++) + { + uint8_t x, y; + // Theta + FOR5(x, 1, + b[x] = 0; + FOR5(y, 5, + b[x] ^= a[x + y]; )) + FOR5(x, 1, + FOR5(y, 5, + a[y + x] ^= b[(x + 4) % 5] ^ rol(b[(x + 1) % 5], 1); )) + // Rho and pi + uint64_t t = a[1]; + x = 0; + REPEAT24(b[0] = a[pi[x]]; + a[pi[x]] = rol(t, rho[x]); + t = b[0]; + x++; ) + // Chi + FOR5(y, + 5, + FOR5(x, 1, + b[x] = a[y + x];) + FOR5(x, 1, + a[y + x] = b[x] ^ ((~b[(x + 1) % 5]) & b[(x + 2) % 5]); )) + // Iota + a[0] ^= RC[i]; + } +} + +/******** The FIPS202-defined functions. ********/ + +/*** Some helper macros. ***/ + +#define _(S) do { S } while (0) +#define FOR(i, ST, L, S) \ + _(for (size_t i = 0; i < L; i += ST) { S; }) +#define mkapply_ds(NAME, S) \ + static inline void NAME(uint8_t* dst, \ + const uint8_t* src, \ + size_t len) { \ + FOR(i, 1, len, S); \ + } +#define mkapply_sd(NAME, S) \ + static inline void NAME(const uint8_t* src, \ + uint8_t* dst, \ + size_t len) { \ + FOR(i, 1, len, S); \ + } + +mkapply_ds(xorin, dst[i] ^= src[i]) // xorin +mkapply_sd(setout, dst[i] = src[i]) // setout + +#define P keccakf +#define Plen 200 + +// Fold P*F over the full blocks of an input. +#define foldP(I, L, F) \ + while (L >= rate) { \ + F(a, I, rate); \ + P(a); \ + I += rate; \ + L -= rate; \ + } + +/** The sponge-based hash construction. **/ +inline void hash( + uint8_t* out, + size_t outlen, + const uint8_t* in, + size_t inlen, + size_t rate, + uint8_t delim +) +{ + uint8_t a[Plen] = {0}; + // Absorb input. + foldP(in, inlen, xorin); + // Xor in the DS and pad frame. + a[inlen] ^= delim; + a[rate - 1] ^= 0x80; + // Xor in the last block. + xorin(a, in, inlen); + // Apply P + P(a); + // Squeeze output. + foldP(out, outlen, setout); + setout(a, out, outlen); + memset(a, 0, 200); +} + +} + +h256 keccak256(bytesConstRef _input) +{ + h256 output; + // Parameters used: + // The 0x01 is the specific padding for keccak (sha3 uses 0x06) and + // the way the round size (or window or whatever it was) is calculated. + // 200 - (256 / 4) is the "rate" + hash(output.data(), output.size, _input.data(), _input.size(), 200 - (256 / 4), 0x01); + return output; +} + +} diff --git a/libdevcore/SHA3.h b/libdevcore/Keccak256.h index d1e2cc98..0d5f69bb 100644 --- a/libdevcore/SHA3.h +++ b/libdevcore/Keccak256.h @@ -30,14 +30,8 @@ namespace dev { -// Keccak-256 convenience routines. - -/// Calculate Keccak-256 hash of the given input and load it into the given output. -/// @returns false if o_output.size() != 32. -bool keccak256(bytesConstRef _input, bytesRef o_output); - /// Calculate Keccak-256 hash of the given input, returning as a 256-bit hash. -inline h256 keccak256(bytesConstRef _input) { h256 ret; keccak256(_input, ret.ref()); return ret; } +h256 keccak256(bytesConstRef _input); /// Calculate Keccak-256 hash of the given input, returning as a 256-bit hash. inline h256 keccak256(bytes const& _input) { return keccak256(bytesConstRef(&_input)); } diff --git a/libdevcore/SHA3.cpp b/libdevcore/SHA3.cpp deleted file mode 100644 index b0e40ccb..00000000 --- a/libdevcore/SHA3.cpp +++ /dev/null @@ -1,240 +0,0 @@ -/* - This file is part of solidity. - - solidity 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. - - solidity 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 solidity. If not, see <http://www.gnu.org/licenses/>. -*/ -/** @file SHA3.cpp - * @author Gav Wood <i@gavwood.com> - * @date 2014 - */ - -#include "SHA3.h" -#include <cstdint> -#include <cstdio> -#include <cstdlib> -#include <cstring> - -using namespace std; -using namespace dev; - -namespace dev -{ - -namespace keccak -{ - -/** libkeccak-tiny - * - * A single-file implementation of SHA-3 and SHAKE. - * - * Implementor: David Leon Gil - * License: CC0, attribution kindly requested. Blame taken too, - * but not liability. - */ - -#define decshake(bits) \ - int shake##bits(uint8_t*, size_t, const uint8_t*, size_t); - -#define decsha3(bits) \ - int sha3_##bits(uint8_t*, size_t, const uint8_t*, size_t); - -#define deckeccak(bits) \ - int keccak##bits(uint8_t*, size_t, const uint8_t*, size_t); - -decshake(128) -decshake(256) -decsha3(224) -decsha3(256) -decsha3(384) -decsha3(512) -deckeccak(224) -deckeccak(256) -deckeccak(384) -deckeccak(512) - -/******** The Keccak-f[1600] permutation ********/ - -/*** Constants. ***/ -static const uint8_t rho[24] = \ - { 1, 3, 6, 10, 15, 21, - 28, 36, 45, 55, 2, 14, - 27, 41, 56, 8, 25, 43, - 62, 18, 39, 61, 20, 44}; -static const uint8_t pi[24] = \ - {10, 7, 11, 17, 18, 3, - 5, 16, 8, 21, 24, 4, - 15, 23, 19, 13, 12, 2, - 20, 14, 22, 9, 6, 1}; -static const uint64_t RC[24] = \ - {1ULL, 0x8082ULL, 0x800000000000808aULL, 0x8000000080008000ULL, - 0x808bULL, 0x80000001ULL, 0x8000000080008081ULL, 0x8000000000008009ULL, - 0x8aULL, 0x88ULL, 0x80008009ULL, 0x8000000aULL, - 0x8000808bULL, 0x800000000000008bULL, 0x8000000000008089ULL, 0x8000000000008003ULL, - 0x8000000000008002ULL, 0x8000000000000080ULL, 0x800aULL, 0x800000008000000aULL, - 0x8000000080008081ULL, 0x8000000000008080ULL, 0x80000001ULL, 0x8000000080008008ULL}; - -/*** Helper macros to unroll the permutation. ***/ -#define rol(x, s) (((x) << s) | ((x) >> (64 - s))) -#define REPEAT6(e) e e e e e e -#define REPEAT24(e) REPEAT6(e e e e) -#define REPEAT5(e) e e e e e -#define FOR5(v, s, e) \ - v = 0; \ - REPEAT5(e; v += s;) - -/*** Keccak-f[1600] ***/ -static inline void keccakf(void* state) { - uint64_t* a = (uint64_t*)state; - uint64_t b[5] = {0}; - - for (int i = 0; i < 24; i++) { - uint8_t x, y; - // Theta - FOR5(x, 1, - b[x] = 0; - FOR5(y, 5, - b[x] ^= a[x + y]; )) - FOR5(x, 1, - FOR5(y, 5, - a[y + x] ^= b[(x + 4) % 5] ^ rol(b[(x + 1) % 5], 1); )) - // Rho and pi - uint64_t t = a[1]; - x = 0; - REPEAT24(b[0] = a[pi[x]]; - a[pi[x]] = rol(t, rho[x]); - t = b[0]; - x++; ) - // Chi - FOR5(y, - 5, - FOR5(x, 1, - b[x] = a[y + x];) - FOR5(x, 1, - a[y + x] = b[x] ^ ((~b[(x + 1) % 5]) & b[(x + 2) % 5]); )) - // Iota - a[0] ^= RC[i]; - } -} - -/******** The FIPS202-defined functions. ********/ - -/*** Some helper macros. ***/ - -#define _(S) do { S } while (0) -#define FOR(i, ST, L, S) \ - _(for (size_t i = 0; i < L; i += ST) { S; }) -#define mkapply_ds(NAME, S) \ - static inline void NAME(uint8_t* dst, \ - const uint8_t* src, \ - size_t len) { \ - FOR(i, 1, len, S); \ - } -#define mkapply_sd(NAME, S) \ - static inline void NAME(const uint8_t* src, \ - uint8_t* dst, \ - size_t len) { \ - FOR(i, 1, len, S); \ - } - -mkapply_ds(xorin, dst[i] ^= src[i]) // xorin -mkapply_sd(setout, dst[i] = src[i]) // setout - -#define P keccakf -#define Plen 200 - -// Fold P*F over the full blocks of an input. -#define foldP(I, L, F) \ - while (L >= rate) { \ - F(a, I, rate); \ - P(a); \ - I += rate; \ - L -= rate; \ - } - -/** The sponge-based hash construction. **/ -static inline int hash(uint8_t* out, size_t outlen, - const uint8_t* in, size_t inlen, - size_t rate, uint8_t delim) { - if ((out == NULL) || ((in == NULL) && inlen != 0) || (rate >= Plen)) { - return -1; - } - uint8_t a[Plen] = {0}; - // Absorb input. - foldP(in, inlen, xorin); - // Xor in the DS and pad frame. - a[inlen] ^= delim; - a[rate - 1] ^= 0x80; - // Xor in the last block. - xorin(a, in, inlen); - // Apply P - P(a); - // Squeeze output. - foldP(out, outlen, setout); - setout(a, out, outlen); - memset(a, 0, 200); - return 0; -} - -/*** Helper macros to define SHA3 and SHAKE instances. ***/ -#define defshake(bits) \ - int shake##bits(uint8_t* out, size_t outlen, \ - const uint8_t* in, size_t inlen) { \ - return hash(out, outlen, in, inlen, 200 - (bits / 4), 0x1f); \ - } -#define defsha3(bits) \ - int sha3_##bits(uint8_t* out, size_t outlen, \ - const uint8_t* in, size_t inlen) { \ - if (outlen > (bits/8)) { \ - return -1; \ - } \ - return hash(out, outlen, in, inlen, 200 - (bits / 4), 0x06); \ - } -#define defkeccak(bits) \ - int keccak##bits(uint8_t* out, size_t outlen, \ - const uint8_t* in, size_t inlen) { \ - if (outlen > (bits/8)) { \ - return -1; \ - } \ - return hash(out, outlen, in, inlen, 200 - (bits / 4), 0x01); \ - } - -/*** FIPS202 SHAKE VOFs ***/ -defshake(128) -defshake(256) - -/*** FIPS202 SHA3 FOFs ***/ -defsha3(224) -defsha3(256) -defsha3(384) -defsha3(512) - -/*** KECCAK FOFs ***/ -defkeccak(224) -defkeccak(256) -defkeccak(384) -defkeccak(512) - -} - -bool keccak256(bytesConstRef _input, bytesRef o_output) -{ - // FIXME: What with unaligned memory? - if (o_output.size() != 32) - return false; - keccak::keccak256(o_output.data(), 32, _input.data(), _input.size()); -// keccak::keccak(ret.data(), 32, (uint64_t const*)_input.data(), _input.size()); - return true; -} - -} diff --git a/libdevcore/StringUtils.cpp b/libdevcore/StringUtils.cpp index 2ff86bd5..50bf7cce 100644 --- a/libdevcore/StringUtils.cpp +++ b/libdevcore/StringUtils.cpp @@ -29,13 +29,16 @@ using namespace std; using namespace dev; -bool dev::stringWithinDistance(string const& _str1, string const& _str2, size_t _maxDistance) +bool dev::stringWithinDistance(string const& _str1, string const& _str2, size_t _maxDistance, size_t _lenThreshold) { if (_str1 == _str2) return true; size_t n1 = _str1.size(); size_t n2 = _str2.size(); + if (_lenThreshold > 0 && n1 * n2 > _lenThreshold) + return false; + size_t distance = stringDistance(_str1, _str2); // if distance is not greater than _maxDistance, and distance is strictly less than length of both names, they can be considered similar @@ -85,17 +88,11 @@ size_t dev::stringDistance(string const& _str1, string const& _str2) string dev::quotedAlternativesList(vector<string> const& suggestions) { - if (suggestions.empty()) - return ""; - if (suggestions.size() == 1) - return "\"" + suggestions.front() + "\""; - - string choices = "\"" + suggestions.front() + "\""; - for (size_t i = 1; i + 1 < suggestions.size(); ++i) - choices += ", \"" + suggestions[i] + "\""; + vector<string> quotedSuggestions; - choices += " or \"" + suggestions.back() + "\""; + for (auto& suggestion: suggestions) + quotedSuggestions.push_back("\"" + suggestion + "\""); - return choices; + return joinHumanReadable(quotedSuggestions, ", ", " or "); } diff --git a/libdevcore/StringUtils.h b/libdevcore/StringUtils.h index acd93e32..b02b9d12 100644 --- a/libdevcore/StringUtils.h +++ b/libdevcore/StringUtils.h @@ -30,10 +30,46 @@ namespace dev { // Calculates the Damerau–Levenshtein distance between _str1 and _str2 and returns true if that distance is not greater than _maxDistance -bool stringWithinDistance(std::string const& _str1, std::string const& _str2, size_t _maxDistance); +// if _lenThreshold > 0 and the product of the strings length is greater than _lenThreshold, the function will return false +bool stringWithinDistance(std::string const& _str1, std::string const& _str2, size_t _maxDistance, size_t _lenThreshold = 0); // Calculates the Damerau–Levenshtein distance between _str1 and _str2 size_t stringDistance(std::string const& _str1, std::string const& _str2); // Return a string having elements of suggestions as quoted, alternative suggestions. e.g. "a", "b" or "c" std::string quotedAlternativesList(std::vector<std::string> const& suggestions); +/// Joins collection of strings into one string with separators between, last separator can be different. +/// @param _list collection of strings to join +/// @param _separator defaults to ", " +/// @param _lastSeparator (optional) will be used to separate last two strings instead of _separator +/// @example join(vector<string>{"a", "b", "c"}, "; ", " or ") == "a; b or c" +template<class T> +std::string joinHumanReadable +( + T const& _list, + std::string const& _separator = ", ", + std::string const& _lastSeparator = "" +) +{ + auto const itEnd = end(_list); + + std::string result; + + for (auto it = begin(_list); it != itEnd; ) + { + std::string element = *it; + bool first = (it == begin(_list)); + ++it; + if (!first) + { + if (it == itEnd && !_lastSeparator.empty()) + result += _lastSeparator; // last iteration + else + result += _separator; + } + result += std::move(element); + } + + return result; +} + } diff --git a/libdevcore/SwarmHash.cpp b/libdevcore/SwarmHash.cpp index 1c718200..3b8d2f3e 100644 --- a/libdevcore/SwarmHash.cpp +++ b/libdevcore/SwarmHash.cpp @@ -19,7 +19,7 @@ #include <libdevcore/SwarmHash.h> -#include <libdevcore/SHA3.h> +#include <libdevcore/Keccak256.h> using namespace std; using namespace dev; diff --git a/libdevcore/Visitor.h b/libdevcore/Visitor.h new file mode 100644 index 00000000..4030c928 --- /dev/null +++ b/libdevcore/Visitor.h @@ -0,0 +1,128 @@ +/* + This file is part of solidity. + + solidity 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. + + solidity 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 solidity. If not, see <http://www.gnu.org/licenses/>. +*/ +/** + * Visitor templates. + */ + +#pragma once + +#include <functional> +#include <boost/variant/static_visitor.hpp> + +namespace dev +{ + +/// Generic visitor used as follows: +/// boost::apply_visitor(GenericVisitor<Class1, Class2>( +/// [](Class1& _c) { _c.f(); }, +/// [](Class2& _c) { _c.g(); } +/// ), variant); +/// This one does not have a fallback and will fail at +/// compile-time if you do not specify all variants. + +template <class...> +struct GenericVisitor{}; + +template <class Visitable, class... Others> +struct GenericVisitor<Visitable, Others...>: public GenericVisitor<Others...> +{ + using GenericVisitor<Others...>::operator (); + explicit GenericVisitor( + std::function<void(Visitable&)> _visitor, + std::function<void(Others&)>... _otherVisitors + ): + GenericVisitor<Others...>(std::move(_otherVisitors)...), + m_visitor(std::move(_visitor)) + {} + + void operator()(Visitable& _v) const { m_visitor(_v); } + + std::function<void(Visitable&)> m_visitor; +}; +template <> +struct GenericVisitor<>: public boost::static_visitor<> { + void operator()() const {} +}; + +/// Generic visitor with fallback: +/// boost::apply_visitor(GenericFallbackVisitor<Class1, Class2>( +/// [](Class1& _c) { _c.f(); }, +/// [](Class2& _c) { _c.g(); } +/// ), variant); +/// This one DOES have a fallback and will NOT fail at +/// compile-time if you do not specify all variants. + +template <class...> +struct GenericFallbackVisitor{}; + +template <class Visitable, class... Others> +struct GenericFallbackVisitor<Visitable, Others...>: public GenericFallbackVisitor<Others...> +{ + explicit GenericFallbackVisitor( + std::function<void(Visitable&)> _visitor, + std::function<void(Others&)>... _otherVisitors + ): + GenericFallbackVisitor<Others...>(std::move(_otherVisitors)...), + m_visitor(std::move(_visitor)) + {} + + using GenericFallbackVisitor<Others...>::operator (); + void operator()(Visitable& _v) const { m_visitor(_v); } + + std::function<void(Visitable&)> m_visitor; +}; +template <> +struct GenericFallbackVisitor<>: public boost::static_visitor<> { + template <class T> + void operator()(T&) const { } +}; + +/// Generic visitor with fallback that can return a value: +/// boost::apply_visitor(GenericFallbackReturnsVisitor<ReturnType, Class1, Class2>( +/// [](Class1& _c) { return _c.f(); }, +/// [](Class2& _c) { return _c.g(); } +/// ), variant); +/// This one DOES have a fallback and will NOT fail at +/// compile-time if you do not specify all variants. +/// The fallback {}-constructs the return value. + +template <class R, class...> +struct GenericFallbackReturnsVisitor{}; + +template <class R, class Visitable, class... Others> +struct GenericFallbackReturnsVisitor<R, Visitable, Others...>: public GenericFallbackReturnsVisitor<R, Others...> +{ + explicit GenericFallbackReturnsVisitor( + std::function<R(Visitable&)> _visitor, + std::function<R(Others&)>... _otherVisitors + ): + GenericFallbackReturnsVisitor<R, Others...>(std::move(_otherVisitors)...), + m_visitor(std::move(_visitor)) + {} + + using GenericFallbackReturnsVisitor<R, Others...>::operator (); + R operator()(Visitable& _v) const { return m_visitor(_v); } + + std::function<R(Visitable&)> m_visitor; +}; +template <class R> +struct GenericFallbackReturnsVisitor<R>: public boost::static_visitor<R> { + template <class T> + R operator()(T&) const { return {}; } +}; + +} diff --git a/libdevcore/boost_multiprecision_number_compare_bug_workaround.hpp b/libdevcore/boost_multiprecision_number_compare_bug_workaround.hpp index dae591df..2568e17d 100644 --- a/libdevcore/boost_multiprecision_number_compare_bug_workaround.hpp +++ b/libdevcore/boost_multiprecision_number_compare_bug_workaround.hpp @@ -1,8 +1,8 @@ -// This is a copy of boost/multiprecision/detail/number_compare.hpp from boost 1.59 to replace buggy version from 1.58. +// This is a copy of boost/multiprecision/detail/number_compare.hpp from boost 1.59 to replace buggy version from 1.58. #ifdef BOOST_MP_COMPARE_HPP -#error This bug workaround header must be included before original boost/multiprecision/detail/number_compare.hpp +#error This bug workaround header must be included before original boost/multiprecision/detail/number_compare.hpp #endif /////////////////////////////////////////////////////////////////////////////// @@ -150,11 +150,11 @@ template <class B, expression_template_option ET> struct is_valid_mixed_compare<number<B, ET>, number<B, ET> > : public mpl::false_ {}; template <class B, expression_template_option ET, class tag, class Arg1, class Arg2, class Arg3, class Arg4> -struct is_valid_mixed_compare<number<B, ET>, expression<tag, Arg1, Arg2, Arg3, Arg4> > +struct is_valid_mixed_compare<number<B, ET>, expression<tag, Arg1, Arg2, Arg3, Arg4> > : public mpl::bool_<is_convertible<expression<tag, Arg1, Arg2, Arg3, Arg4>, number<B, ET> >::value> {}; template <class tag, class Arg1, class Arg2, class Arg3, class Arg4, class B, expression_template_option ET> -struct is_valid_mixed_compare<expression<tag, Arg1, Arg2, Arg3, Arg4>, number<B, ET> > +struct is_valid_mixed_compare<expression<tag, Arg1, Arg2, Arg3, Arg4>, number<B, ET> > : public mpl::bool_<is_convertible<expression<tag, Arg1, Arg2, Arg3, Arg4>, number<B, ET> >::value> {}; template <class Backend, expression_template_option ExpressionTemplates> @@ -196,7 +196,7 @@ inline bool operator == (const number<Backend, ExpressionTemplates>& a, const nu return eval_eq(a.backend(), b.backend()); } template <class Backend, expression_template_option ExpressionTemplates, class Arithmetic> -inline typename enable_if_c<detail::is_valid_mixed_compare<number<Backend, ExpressionTemplates>, Arithmetic>::value, bool>::type +inline typename enable_if_c<detail::is_valid_mixed_compare<number<Backend, ExpressionTemplates>, Arithmetic>::value, bool>::type operator == (const number<Backend, ExpressionTemplates>& a, const Arithmetic& b) { using default_ops::eval_eq; @@ -204,7 +204,7 @@ inline typename enable_if_c<detail::is_valid_mixed_compare<number<Backend, Expre return eval_eq(a.backend(), number<Backend, ExpressionTemplates>::canonical_value(b)); } template <class Arithmetic, class Backend, expression_template_option ExpressionTemplates> -inline typename enable_if_c<detail::is_valid_mixed_compare<number<Backend, ExpressionTemplates>, Arithmetic>::value, bool>::type +inline typename enable_if_c<detail::is_valid_mixed_compare<number<Backend, ExpressionTemplates>, Arithmetic>::value, bool>::type operator == (const Arithmetic& a, const number<Backend, ExpressionTemplates>& b) { using default_ops::eval_eq; @@ -212,7 +212,7 @@ inline typename enable_if_c<detail::is_valid_mixed_compare<number<Backend, Expre return eval_eq(b.backend(), number<Backend, ExpressionTemplates>::canonical_value(a)); } template <class Arithmetic, class Tag, class A1, class A2, class A3, class A4> -inline typename enable_if_c<detail::is_valid_mixed_compare<typename detail::expression<Tag, A1, A2, A3, A4>::result_type, Arithmetic>::value, bool>::type +inline typename enable_if_c<detail::is_valid_mixed_compare<typename detail::expression<Tag, A1, A2, A3, A4>::result_type, Arithmetic>::value, bool>::type operator == (const Arithmetic& a, const detail::expression<Tag, A1, A2, A3, A4>& b) { typedef typename detail::expression<Tag, A1, A2, A3, A4>::result_type result_type; @@ -222,7 +222,7 @@ inline typename enable_if_c<detail::is_valid_mixed_compare<typename detail::expr return eval_eq(t.backend(), result_type::canonical_value(a)); } template <class Tag, class A1, class A2, class A3, class A4, class Arithmetic> -inline typename enable_if_c<detail::is_valid_mixed_compare<typename detail::expression<Tag, A1, A2, A3, A4>::result_type, Arithmetic>::value, bool>::type +inline typename enable_if_c<detail::is_valid_mixed_compare<typename detail::expression<Tag, A1, A2, A3, A4>::result_type, Arithmetic>::value, bool>::type operator == (const detail::expression<Tag, A1, A2, A3, A4>& a, const Arithmetic& b) { typedef typename detail::expression<Tag, A1, A2, A3, A4>::result_type result_type; @@ -232,7 +232,7 @@ inline typename enable_if_c<detail::is_valid_mixed_compare<typename detail::expr return eval_eq(t.backend(), result_type::canonical_value(b)); } template <class Tag, class A1, class A2, class A3, class A4, class Tagb, class A1b, class A2b, class A3b, class A4b> -inline typename enable_if<is_same<typename detail::expression<Tag, A1, A2, A3, A4>::result_type, typename detail::expression<Tagb, A1b, A2b, A3b, A4b>::result_type>, bool>::type +inline typename enable_if<is_same<typename detail::expression<Tag, A1, A2, A3, A4>::result_type, typename detail::expression<Tagb, A1b, A2b, A3b, A4b>::result_type>, bool>::type operator == (const detail::expression<Tag, A1, A2, A3, A4>& a, const detail::expression<Tagb, A1b, A2b, A3b, A4b>& b) { using default_ops::eval_eq; @@ -250,7 +250,7 @@ inline bool operator != (const number<Backend, ExpressionTemplates>& a, const nu return !eval_eq(a.backend(), b.backend()); } template <class Backend, expression_template_option ExpressionTemplates, class Arithmetic> -inline typename enable_if_c<detail::is_valid_mixed_compare<number<Backend, ExpressionTemplates>, Arithmetic>::value, bool>::type +inline typename enable_if_c<detail::is_valid_mixed_compare<number<Backend, ExpressionTemplates>, Arithmetic>::value, bool>::type operator != (const number<Backend, ExpressionTemplates>& a, const Arithmetic& b) { using default_ops::eval_eq; @@ -258,7 +258,7 @@ inline typename enable_if_c<detail::is_valid_mixed_compare<number<Backend, Expre return !eval_eq(a.backend(), number<Backend, et_on>::canonical_value(b)); } template <class Arithmetic, class Backend, expression_template_option ExpressionTemplates> -inline typename enable_if_c<detail::is_valid_mixed_compare<number<Backend, ExpressionTemplates>, Arithmetic>::value, bool>::type +inline typename enable_if_c<detail::is_valid_mixed_compare<number<Backend, ExpressionTemplates>, Arithmetic>::value, bool>::type operator != (const Arithmetic& a, const number<Backend, ExpressionTemplates>& b) { using default_ops::eval_eq; @@ -266,7 +266,7 @@ inline typename enable_if_c<detail::is_valid_mixed_compare<number<Backend, Expre return !eval_eq(b.backend(), number<Backend, et_on>::canonical_value(a)); } template <class Arithmetic, class Tag, class A1, class A2, class A3, class A4> -inline typename enable_if_c<detail::is_valid_mixed_compare<typename detail::expression<Tag, A1, A2, A3, A4>::result_type, Arithmetic>::value, bool>::type +inline typename enable_if_c<detail::is_valid_mixed_compare<typename detail::expression<Tag, A1, A2, A3, A4>::result_type, Arithmetic>::value, bool>::type operator != (const Arithmetic& a, const detail::expression<Tag, A1, A2, A3, A4>& b) { typedef typename detail::expression<Tag, A1, A2, A3, A4>::result_type result_type; @@ -276,7 +276,7 @@ inline typename enable_if_c<detail::is_valid_mixed_compare<typename detail::expr return !eval_eq(t.backend(), result_type::canonical_value(a)); } template <class Tag, class A1, class A2, class A3, class A4, class Arithmetic> -inline typename enable_if_c<detail::is_valid_mixed_compare<typename detail::expression<Tag, A1, A2, A3, A4>::result_type, Arithmetic>::value, bool>::type +inline typename enable_if_c<detail::is_valid_mixed_compare<typename detail::expression<Tag, A1, A2, A3, A4>::result_type, Arithmetic>::value, bool>::type operator != (const detail::expression<Tag, A1, A2, A3, A4>& a, const Arithmetic& b) { typedef typename detail::expression<Tag, A1, A2, A3, A4>::result_type result_type; @@ -286,7 +286,7 @@ inline typename enable_if_c<detail::is_valid_mixed_compare<typename detail::expr return !eval_eq(t.backend(), result_type::canonical_value(b)); } template <class Tag, class A1, class A2, class A3, class A4, class Tagb, class A1b, class A2b, class A3b, class A4b> -inline typename enable_if<is_same<typename detail::expression<Tag, A1, A2, A3, A4>::result_type, typename detail::expression<Tagb, A1b, A2b, A3b, A4b>::result_type>, bool>::type +inline typename enable_if<is_same<typename detail::expression<Tag, A1, A2, A3, A4>::result_type, typename detail::expression<Tagb, A1b, A2b, A3b, A4b>::result_type>, bool>::type operator != (const detail::expression<Tag, A1, A2, A3, A4>& a, const detail::expression<Tagb, A1b, A2b, A3b, A4b>& b) { using default_ops::eval_eq; @@ -304,7 +304,7 @@ inline bool operator < (const number<Backend, ExpressionTemplates>& a, const num return eval_lt(a.backend(), b.backend()); } template <class Backend, expression_template_option ExpressionTemplates, class Arithmetic> -inline typename enable_if_c<detail::is_valid_mixed_compare<number<Backend, ExpressionTemplates>, Arithmetic>::value, bool>::type +inline typename enable_if_c<detail::is_valid_mixed_compare<number<Backend, ExpressionTemplates>, Arithmetic>::value, bool>::type operator < (const number<Backend, ExpressionTemplates>& a, const Arithmetic& b) { using default_ops::eval_lt; @@ -312,7 +312,7 @@ inline typename enable_if_c<detail::is_valid_mixed_compare<number<Backend, Expre return eval_lt(a.backend(), number<Backend, ExpressionTemplates>::canonical_value(b)); } template <class Arithmetic, class Backend, expression_template_option ExpressionTemplates> -inline typename enable_if_c<detail::is_valid_mixed_compare<number<Backend, ExpressionTemplates>, Arithmetic>::value, bool>::type +inline typename enable_if_c<detail::is_valid_mixed_compare<number<Backend, ExpressionTemplates>, Arithmetic>::value, bool>::type operator < (const Arithmetic& a, const number<Backend, ExpressionTemplates>& b) { using default_ops::eval_gt; @@ -320,7 +320,7 @@ inline typename enable_if_c<detail::is_valid_mixed_compare<number<Backend, Expre return eval_gt(b.backend(), number<Backend, ExpressionTemplates>::canonical_value(a)); } template <class Arithmetic, class Tag, class A1, class A2, class A3, class A4> -inline typename enable_if_c<detail::is_valid_mixed_compare<typename detail::expression<Tag, A1, A2, A3, A4>::result_type, Arithmetic>::value, bool>::type +inline typename enable_if_c<detail::is_valid_mixed_compare<typename detail::expression<Tag, A1, A2, A3, A4>::result_type, Arithmetic>::value, bool>::type operator < (const Arithmetic& a, const detail::expression<Tag, A1, A2, A3, A4>& b) { typedef typename detail::expression<Tag, A1, A2, A3, A4>::result_type result_type; @@ -330,7 +330,7 @@ inline typename enable_if_c<detail::is_valid_mixed_compare<typename detail::expr return eval_gt(t.backend(), result_type::canonical_value(a)); } template <class Tag, class A1, class A2, class A3, class A4, class Arithmetic> -inline typename enable_if_c<detail::is_valid_mixed_compare<typename detail::expression<Tag, A1, A2, A3, A4>::result_type, Arithmetic>::value, bool>::type +inline typename enable_if_c<detail::is_valid_mixed_compare<typename detail::expression<Tag, A1, A2, A3, A4>::result_type, Arithmetic>::value, bool>::type operator < (const detail::expression<Tag, A1, A2, A3, A4>& a, const Arithmetic& b) { typedef typename detail::expression<Tag, A1, A2, A3, A4>::result_type result_type; @@ -340,7 +340,7 @@ inline typename enable_if_c<detail::is_valid_mixed_compare<typename detail::expr return eval_lt(t.backend(), result_type::canonical_value(b)); } template <class Tag, class A1, class A2, class A3, class A4, class Tagb, class A1b, class A2b, class A3b, class A4b> -inline typename enable_if<is_same<typename detail::expression<Tag, A1, A2, A3, A4>::result_type, typename detail::expression<Tagb, A1b, A2b, A3b, A4b>::result_type>, bool>::type +inline typename enable_if<is_same<typename detail::expression<Tag, A1, A2, A3, A4>::result_type, typename detail::expression<Tagb, A1b, A2b, A3b, A4b>::result_type>, bool>::type operator < (const detail::expression<Tag, A1, A2, A3, A4>& a, const detail::expression<Tagb, A1b, A2b, A3b, A4b>& b) { using default_ops::eval_lt; @@ -358,7 +358,7 @@ inline bool operator > (const number<Backend, ExpressionTemplates>& a, const num return eval_gt(a.backend(), b.backend()); } template <class Backend, expression_template_option ExpressionTemplates, class Arithmetic> -inline typename enable_if_c<detail::is_valid_mixed_compare<number<Backend, ExpressionTemplates>, Arithmetic>::value, bool>::type +inline typename enable_if_c<detail::is_valid_mixed_compare<number<Backend, ExpressionTemplates>, Arithmetic>::value, bool>::type operator > (const number<Backend, ExpressionTemplates>& a, const Arithmetic& b) { using default_ops::eval_gt; @@ -366,7 +366,7 @@ inline typename enable_if_c<detail::is_valid_mixed_compare<number<Backend, Expre return eval_gt(a.backend(), number<Backend, ExpressionTemplates>::canonical_value(b)); } template <class Arithmetic, class Backend, expression_template_option ExpressionTemplates> -inline typename enable_if_c<detail::is_valid_mixed_compare<number<Backend, ExpressionTemplates>, Arithmetic>::value, bool>::type +inline typename enable_if_c<detail::is_valid_mixed_compare<number<Backend, ExpressionTemplates>, Arithmetic>::value, bool>::type operator > (const Arithmetic& a, const number<Backend, ExpressionTemplates>& b) { using default_ops::eval_lt; @@ -374,7 +374,7 @@ inline typename enable_if_c<detail::is_valid_mixed_compare<number<Backend, Expre return eval_lt(b.backend(), number<Backend, ExpressionTemplates>::canonical_value(a)); } template <class Arithmetic, class Tag, class A1, class A2, class A3, class A4> -inline typename enable_if_c<detail::is_valid_mixed_compare<typename detail::expression<Tag, A1, A2, A3, A4>::result_type, Arithmetic>::value, bool>::type +inline typename enable_if_c<detail::is_valid_mixed_compare<typename detail::expression<Tag, A1, A2, A3, A4>::result_type, Arithmetic>::value, bool>::type operator > (const Arithmetic& a, const detail::expression<Tag, A1, A2, A3, A4>& b) { typedef typename detail::expression<Tag, A1, A2, A3, A4>::result_type result_type; @@ -384,7 +384,7 @@ inline typename enable_if_c<detail::is_valid_mixed_compare<typename detail::expr return a > t; } template <class Tag, class A1, class A2, class A3, class A4, class Arithmetic> -inline typename enable_if_c<detail::is_valid_mixed_compare<typename detail::expression<Tag, A1, A2, A3, A4>::result_type, Arithmetic>::value, bool>::type +inline typename enable_if_c<detail::is_valid_mixed_compare<typename detail::expression<Tag, A1, A2, A3, A4>::result_type, Arithmetic>::value, bool>::type operator > (const detail::expression<Tag, A1, A2, A3, A4>& a, const Arithmetic& b) { typedef typename detail::expression<Tag, A1, A2, A3, A4>::result_type result_type; @@ -394,7 +394,7 @@ inline typename enable_if_c<detail::is_valid_mixed_compare<typename detail::expr return t > b; } template <class Tag, class A1, class A2, class A3, class A4, class Tagb, class A1b, class A2b, class A3b, class A4b> -inline typename enable_if<is_same<typename detail::expression<Tag, A1, A2, A3, A4>::result_type, typename detail::expression<Tagb, A1b, A2b, A3b, A4b>::result_type>, bool>::type +inline typename enable_if<is_same<typename detail::expression<Tag, A1, A2, A3, A4>::result_type, typename detail::expression<Tagb, A1b, A2b, A3b, A4b>::result_type>, bool>::type operator > (const detail::expression<Tag, A1, A2, A3, A4>& a, const detail::expression<Tagb, A1b, A2b, A3b, A4b>& b) { using default_ops::eval_gt; @@ -412,7 +412,7 @@ inline bool operator <= (const number<Backend, ExpressionTemplates>& a, const nu return !eval_gt(a.backend(), b.backend()); } template <class Backend, expression_template_option ExpressionTemplates, class Arithmetic> -inline typename enable_if_c<detail::is_valid_mixed_compare<number<Backend, ExpressionTemplates>, Arithmetic>::value, bool>::type +inline typename enable_if_c<detail::is_valid_mixed_compare<number<Backend, ExpressionTemplates>, Arithmetic>::value, bool>::type operator <= (const number<Backend, ExpressionTemplates>& a, const Arithmetic& b) { using default_ops::eval_gt; @@ -420,7 +420,7 @@ inline typename enable_if_c<detail::is_valid_mixed_compare<number<Backend, Expre return !eval_gt(a.backend(), number<Backend, ExpressionTemplates>::canonical_value(b)); } template <class Arithmetic, class Backend, expression_template_option ExpressionTemplates> -inline typename enable_if_c<detail::is_valid_mixed_compare<number<Backend, ExpressionTemplates>, Arithmetic>::value, bool>::type +inline typename enable_if_c<detail::is_valid_mixed_compare<number<Backend, ExpressionTemplates>, Arithmetic>::value, bool>::type operator <= (const Arithmetic& a, const number<Backend, ExpressionTemplates>& b) { using default_ops::eval_lt; @@ -428,7 +428,7 @@ inline typename enable_if_c<detail::is_valid_mixed_compare<number<Backend, Expre return !eval_lt(b.backend(), number<Backend, ExpressionTemplates>::canonical_value(a)); } template <class Arithmetic, class Tag, class A1, class A2, class A3, class A4> -inline typename enable_if_c<detail::is_valid_mixed_compare<typename detail::expression<Tag, A1, A2, A3, A4>::result_type, Arithmetic>::value, bool>::type +inline typename enable_if_c<detail::is_valid_mixed_compare<typename detail::expression<Tag, A1, A2, A3, A4>::result_type, Arithmetic>::value, bool>::type operator <= (const Arithmetic& a, const detail::expression<Tag, A1, A2, A3, A4>& b) { typedef typename detail::expression<Tag, A1, A2, A3, A4>::result_type result_type; @@ -440,7 +440,7 @@ inline typename enable_if_c<detail::is_valid_mixed_compare<typename detail::expr return !eval_lt(t.backend(), result_type::canonical_value(a)); } template <class Tag, class A1, class A2, class A3, class A4, class Arithmetic> -inline typename enable_if_c<detail::is_valid_mixed_compare<typename detail::expression<Tag, A1, A2, A3, A4>::result_type, Arithmetic>::value, bool>::type +inline typename enable_if_c<detail::is_valid_mixed_compare<typename detail::expression<Tag, A1, A2, A3, A4>::result_type, Arithmetic>::value, bool>::type operator <= (const detail::expression<Tag, A1, A2, A3, A4>& a, const Arithmetic& b) { typedef typename detail::expression<Tag, A1, A2, A3, A4>::result_type result_type; @@ -450,7 +450,7 @@ inline typename enable_if_c<detail::is_valid_mixed_compare<typename detail::expr return !eval_gt(t.backend(), result_type::canonical_value(b)); } template <class Tag, class A1, class A2, class A3, class A4, class Tagb, class A1b, class A2b, class A3b, class A4b> -inline typename enable_if<is_same<typename detail::expression<Tag, A1, A2, A3, A4>::result_type, typename detail::expression<Tagb, A1b, A2b, A3b, A4b>::result_type>, bool>::type +inline typename enable_if<is_same<typename detail::expression<Tag, A1, A2, A3, A4>::result_type, typename detail::expression<Tagb, A1b, A2b, A3b, A4b>::result_type>, bool>::type operator <= (const detail::expression<Tag, A1, A2, A3, A4>& a, const detail::expression<Tagb, A1b, A2b, A3b, A4b>& b) { using default_ops::eval_gt; @@ -468,7 +468,7 @@ inline bool operator >= (const number<Backend, ExpressionTemplates>& a, const nu return !eval_lt(a.backend(), b.backend()); } template <class Backend, expression_template_option ExpressionTemplates, class Arithmetic> -inline typename enable_if_c<detail::is_valid_mixed_compare<number<Backend, ExpressionTemplates>, Arithmetic>::value, bool>::type +inline typename enable_if_c<detail::is_valid_mixed_compare<number<Backend, ExpressionTemplates>, Arithmetic>::value, bool>::type operator >= (const number<Backend, ExpressionTemplates>& a, const Arithmetic& b) { using default_ops::eval_lt; @@ -476,7 +476,7 @@ inline typename enable_if_c<detail::is_valid_mixed_compare<number<Backend, Expre return !eval_lt(a.backend(), number<Backend, ExpressionTemplates>::canonical_value(b)); } template <class Arithmetic, class Backend, expression_template_option ExpressionTemplates> -inline typename enable_if_c<detail::is_valid_mixed_compare<number<Backend, ExpressionTemplates>, Arithmetic>::value, bool>::type +inline typename enable_if_c<detail::is_valid_mixed_compare<number<Backend, ExpressionTemplates>, Arithmetic>::value, bool>::type operator >= (const Arithmetic& a, const number<Backend, ExpressionTemplates>& b) { using default_ops::eval_gt; @@ -484,7 +484,7 @@ inline typename enable_if_c<detail::is_valid_mixed_compare<number<Backend, Expre return !eval_gt(b.backend(), number<Backend, ExpressionTemplates>::canonical_value(a)); } template <class Arithmetic, class Tag, class A1, class A2, class A3, class A4> -inline typename enable_if_c<detail::is_valid_mixed_compare<typename detail::expression<Tag, A1, A2, A3, A4>::result_type, Arithmetic>::value, bool>::type +inline typename enable_if_c<detail::is_valid_mixed_compare<typename detail::expression<Tag, A1, A2, A3, A4>::result_type, Arithmetic>::value, bool>::type operator >= (const Arithmetic& a, const detail::expression<Tag, A1, A2, A3, A4>& b) { typedef typename detail::expression<Tag, A1, A2, A3, A4>::result_type result_type; @@ -494,7 +494,7 @@ inline typename enable_if_c<detail::is_valid_mixed_compare<typename detail::expr return !eval_gt(t.backend(), result_type::canonical_value(a)); } template <class Tag, class A1, class A2, class A3, class A4, class Arithmetic> -inline typename enable_if_c<detail::is_valid_mixed_compare<typename detail::expression<Tag, A1, A2, A3, A4>::result_type, Arithmetic>::value, bool>::type +inline typename enable_if_c<detail::is_valid_mixed_compare<typename detail::expression<Tag, A1, A2, A3, A4>::result_type, Arithmetic>::value, bool>::type operator >= (const detail::expression<Tag, A1, A2, A3, A4>& a, const Arithmetic& b) { typedef typename detail::expression<Tag, A1, A2, A3, A4>::result_type result_type; @@ -504,7 +504,7 @@ inline typename enable_if_c<detail::is_valid_mixed_compare<typename detail::expr return !eval_lt(t.backend(), result_type::canonical_value(b)); } template <class Tag, class A1, class A2, class A3, class A4, class Tagb, class A1b, class A2b, class A3b, class A4b> -inline typename enable_if<is_same<typename detail::expression<Tag, A1, A2, A3, A4>::result_type, typename detail::expression<Tagb, A1b, A2b, A3b, A4b>::result_type>, bool>::type +inline typename enable_if<is_same<typename detail::expression<Tag, A1, A2, A3, A4>::result_type, typename detail::expression<Tagb, A1b, A2b, A3b, A4b>::result_type>, bool>::type operator >= (const detail::expression<Tag, A1, A2, A3, A4>& a, const detail::expression<Tagb, A1b, A2b, A3b, A4b>& b) { using default_ops::eval_lt; |