aboutsummaryrefslogtreecommitdiffstats
path: root/libdevcore
diff options
context:
space:
mode:
Diffstat (limited to 'libdevcore')
-rw-r--r--libdevcore/CMakeLists.txt20
-rw-r--r--libdevcore/CommonData.cpp22
-rw-r--r--libdevcore/CommonData.h22
-rw-r--r--libdevcore/FixedHash.h2
-rw-r--r--libdevcore/IndentedWriter.cpp2
-rw-r--r--libdevcore/IndentedWriter.h4
-rw-r--r--libdevcore/Result.h66
-rw-r--r--libdevcore/StringUtils.cpp2
-rw-r--r--libdevcore/StringUtils.h82
9 files changed, 204 insertions, 18 deletions
diff --git a/libdevcore/CMakeLists.txt b/libdevcore/CMakeLists.txt
index 01a8bcc6..e68ac10a 100644
--- a/libdevcore/CMakeLists.txt
+++ b/libdevcore/CMakeLists.txt
@@ -1,18 +1,36 @@
set(sources
+ Algorithms.h
+ Assertions.h
+ boost_multiprecision_number_compare_bug_workaround.hpp
+ Common.h
CommonData.cpp
+ CommonData.h
CommonIO.cpp
+ CommonIO.h
Exceptions.cpp
+ Exceptions.h
+ FixedHash.h
IndentedWriter.cpp
+ IndentedWriter.h
JSON.cpp
+ JSON.h
Keccak256.cpp
+ Keccak256.h
+ Result.h
StringUtils.cpp
+ StringUtils.h
SwarmHash.cpp
+ SwarmHash.h
UTF8.cpp
+ UTF8.h
+ vector_ref.h
+ Visitor.h
Whiskers.cpp
+ Whiskers.h
)
add_library(devcore ${sources})
-target_link_libraries(devcore PRIVATE jsoncpp ${Boost_FILESYSTEM_LIBRARIES} ${Boost_REGEX_LIBRARIES} ${Boost_SYSTEM_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT})
+target_link_libraries(devcore PUBLIC jsoncpp ${Boost_FILESYSTEM_LIBRARIES} ${Boost_REGEX_LIBRARIES} ${Boost_SYSTEM_LIBRARIES} Threads::Threads)
target_include_directories(devcore PUBLIC "${CMAKE_SOURCE_DIR}")
target_include_directories(devcore SYSTEM PUBLIC ${Boost_INCLUDE_DIRS})
add_dependencies(devcore solidity_BuildInfo.h)
diff --git a/libdevcore/CommonData.cpp b/libdevcore/CommonData.cpp
index 8d2639c9..1b0e9720 100644
--- a/libdevcore/CommonData.cpp
+++ b/libdevcore/CommonData.cpp
@@ -29,6 +29,28 @@
using namespace std;
using namespace dev;
+string dev::toHex(bytes const& _data, HexPrefix _prefix, HexCase _case)
+{
+ std::ostringstream ret;
+ if (_prefix == HexPrefix::Add)
+ ret << "0x";
+
+ int rix = _data.size() - 1;
+ for (uint8_t c: _data)
+ {
+ // switch hex case every four hexchars
+ auto hexcase = std::nouppercase;
+ if (_case == HexCase::Upper)
+ hexcase = std::uppercase;
+ else if (_case == HexCase::Mixed)
+ hexcase = (rix-- & 2) == 0 ? std::nouppercase : std::uppercase;
+
+ ret << std::hex << hexcase << std::setfill('0') << std::setw(2) << size_t(c);
+ }
+
+ return ret.str();
+}
+
int dev::fromHex(char _i, WhenError _throw)
{
if (_i >= '0' && _i <= '9')
diff --git a/libdevcore/CommonData.h b/libdevcore/CommonData.h
index fedd3af2..7c59c505 100644
--- a/libdevcore/CommonData.h
+++ b/libdevcore/CommonData.h
@@ -50,18 +50,18 @@ enum class HexPrefix
DontAdd = 0,
Add = 1,
};
+
+enum class HexCase
+{
+ Lower = 0,
+ Upper = 1,
+ Mixed = 2,
+};
+
/// Convert a series of bytes to the corresponding string of hex duplets.
/// @param _w specifies the width of the first of the elements. Defaults to two - enough to represent a byte.
/// @example toHex("A\x69") == "4169"
-template <class T>
-std::string toHex(T const& _data, int _w = 2, HexPrefix _prefix = HexPrefix::DontAdd)
-{
- std::ostringstream ret;
- unsigned ii = 0;
- for (auto i: _data)
- ret << std::hex << std::setfill('0') << std::setw(ii++ ? 2 : _w) << (int)(typename std::make_unsigned<decltype(i)>::type)i;
- return (_prefix == HexPrefix::Add) ? "0x" + ret.str() : ret.str();
-}
+std::string toHex(bytes const& _data, HexPrefix _prefix = HexPrefix::DontAdd, HexCase _case = HexCase::Lower);
/// Converts a (printable) ASCII hex character into the correspnding integer value.
/// @example fromHex('A') == 10 && fromHex('f') == 15 && fromHex('5') == 5
@@ -153,7 +153,7 @@ inline std::string formatNumber(bigint const& _value)
if (_value < 0)
return "-" + formatNumber(-_value);
if (_value > 0x1000000)
- return toHex(toCompactBigEndian(_value), 2, HexPrefix::Add);
+ return toHex(toCompactBigEndian(_value), HexPrefix::Add);
else
return _value.str();
}
@@ -161,7 +161,7 @@ inline std::string formatNumber(bigint const& _value)
inline std::string formatNumber(u256 const& _value)
{
if (_value > 0x1000000)
- return toHex(toCompactBigEndian(_value), 2, HexPrefix::Add);
+ return toHex(toCompactBigEndian(_value), HexPrefix::Add);
else
return _value.str();
}
diff --git a/libdevcore/FixedHash.h b/libdevcore/FixedHash.h
index 24b89840..9245d726 100644
--- a/libdevcore/FixedHash.h
+++ b/libdevcore/FixedHash.h
@@ -95,7 +95,7 @@ public:
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()); }
+ std::string hex() const { return toHex(asBytes()); }
/// @returns a mutable byte vector_ref to the object's data.
bytesRef ref() { return bytesRef(m_data.data(), N); }
diff --git a/libdevcore/IndentedWriter.cpp b/libdevcore/IndentedWriter.cpp
index 96aaf0fa..1a85957b 100644
--- a/libdevcore/IndentedWriter.cpp
+++ b/libdevcore/IndentedWriter.cpp
@@ -36,7 +36,7 @@ string IndentedWriter::format() const
void IndentedWriter::newLine()
{
if (!m_lines.back().contents.empty())
- m_lines.push_back({ string(), m_lines.back().indentation });
+ m_lines.emplace_back(Line{string(), m_lines.back().indentation});
}
void IndentedWriter::indent()
diff --git a/libdevcore/IndentedWriter.h b/libdevcore/IndentedWriter.h
index 4ddd87ed..563c4c96 100644
--- a/libdevcore/IndentedWriter.h
+++ b/libdevcore/IndentedWriter.h
@@ -34,8 +34,6 @@ DEV_SIMPLE_EXCEPTION(IndentedWriterError);
class IndentedWriter
{
public:
- explicit IndentedWriter(): m_lines(std::vector<Line>{{std::string(), 0}}) {}
-
// Returns the formatted output.
std::string format() const;
@@ -61,7 +59,7 @@ private:
unsigned indentation;
};
- std::vector<Line> m_lines;
+ std::vector<Line> m_lines{{std::string(), 0}};
};
}
diff --git a/libdevcore/Result.h b/libdevcore/Result.h
new file mode 100644
index 00000000..4f7a063b
--- /dev/null
+++ b/libdevcore/Result.h
@@ -0,0 +1,66 @@
+/*
+ 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/>.
+*/
+#pragma once
+
+#include <string>
+
+namespace dev
+{
+
+/// Simple generic result that holds a value and an optional error message.
+/// Results can be implicitly converted to and created from the type of
+/// the value they hold. The class is mainly designed for a result type of
+/// bool or pointer type. The idea is that the default constructed value of
+/// the result type is interpreted as an error value.
+///
+/// Result<bool> check()
+/// {
+/// if (false)
+/// return Result<bool>("Error message.")
+/// return true;
+/// }
+///
+
+template <class ResultType>
+class Result
+{
+public:
+ Result(ResultType _value): Result(_value, std::string{}) {}
+ Result(std::string _message): Result(ResultType{}, std::move(_message)) {}
+
+ /// @{
+ /// @name Wrapper functions
+ /// Wrapper functions that provide implicit conversions to and explicit retrieval of
+ /// the value this result holds.
+ operator ResultType const&() const { return m_value; }
+ ResultType const& get() const { return m_value; }
+ /// @}
+
+ /// @returns the error message (can be empty).
+ std::string const& message() const { return m_message; }
+
+private:
+ explicit Result(ResultType _value, std::string _message):
+ m_value(std::move(_value)),
+ m_message(std::move(_message))
+ {}
+
+ ResultType m_value;
+ std::string m_message;
+};
+
+}
diff --git a/libdevcore/StringUtils.cpp b/libdevcore/StringUtils.cpp
index 50bf7cce..196ac8f7 100644
--- a/libdevcore/StringUtils.cpp
+++ b/libdevcore/StringUtils.cpp
@@ -91,7 +91,7 @@ string dev::quotedAlternativesList(vector<string> const& suggestions)
vector<string> quotedSuggestions;
for (auto& suggestion: suggestions)
- quotedSuggestions.push_back("\"" + suggestion + "\"");
+ quotedSuggestions.emplace_back("\"" + suggestion + "\"");
return joinHumanReadable(quotedSuggestions, ", ", " or ");
}
diff --git a/libdevcore/StringUtils.h b/libdevcore/StringUtils.h
index b02b9d12..64044cb2 100644
--- a/libdevcore/StringUtils.h
+++ b/libdevcore/StringUtils.h
@@ -26,6 +26,8 @@
#include <string>
#include <vector>
+#include <libdevcore/CommonData.h>
+
namespace dev
{
@@ -72,4 +74,84 @@ std::string joinHumanReadable
return result;
}
+/// Formats large numbers to be easily readable by humans.
+/// Returns decimal representation for smaller numbers; hex for large numbers.
+/// "Special" numbers, powers-of-two and powers-of-two minus 1, are returned in
+/// formulaic form like 0x01 * 2**24 - 1.
+/// @a T will typically by unsigned, u160, u256 or bigint.
+/// @param _value to be formatted
+/// @param _useTruncation if true, internal truncation is also applied,
+/// like 0x5555...{+56 more}...5555
+/// @example formatNumber((u256)0x7ffffff)
+template <class T>
+inline std::string formatNumberReadable(
+ T const& _value,
+ bool _useTruncation = false
+)
+{
+ static_assert(
+ std::is_same<bigint, T>::value || !std::numeric_limits<T>::is_signed,
+ "only unsigned types or bigint supported"
+ ); //bigint does not carry sign bit on shift
+
+ // smaller numbers return as decimal
+ if (_value <= 0x1000000)
+ return _value.str();
+
+ HexCase hexcase = HexCase::Mixed;
+ HexPrefix prefix = HexPrefix::Add;
+
+ // when multiple trailing zero bytes, format as N * 2**x
+ int i = 0;
+ T v = _value;
+ for (; (v & 0xff) == 0; v >>= 8)
+ ++i;
+ if (i > 2)
+ {
+ // 0x100 yields 2**8 (N is 1 and redundant)
+ if (v == 1)
+ return "2**" + std::to_string(i * 8);
+ return toHex(toCompactBigEndian(v), prefix, hexcase) +
+ " * 2**" +
+ std::to_string(i * 8);
+ }
+
+ // when multiple trailing FF bytes, format as N * 2**x - 1
+ i = 0;
+ for (v = _value; (v & 0xff) == 0xff; v >>= 8)
+ ++i;
+ if (i > 2)
+ {
+ // 0xFF yields 2**8 - 1 (v is 0 in that case)
+ if (v == 0)
+ return "2**" + std::to_string(i * 8) + " - 1";
+ return toHex(toCompactBigEndian(T(v + 1)), prefix, hexcase) +
+ " * 2**" + std::to_string(i * 8) +
+ " - 1";
+ }
+
+ std::string str = toHex(toCompactBigEndian(_value), prefix, hexcase);
+ if (_useTruncation)
+ {
+ // return as interior-truncated hex.
+ int len = str.size();
+
+ if (len < 24)
+ return str;
+
+ const int initialChars = (prefix == HexPrefix::Add) ? 6 : 4;
+ const int finalChars = 4;
+ int numSkipped = len - initialChars - finalChars;
+
+ return str.substr(0, initialChars) +
+ "...{+" +
+ std::to_string(numSkipped) +
+ " more}..." +
+ str.substr(len-finalChars, len);
+ }
+
+ // otherwise, show whole value.
+ return str;
+}
+
}