diff --git a/exp/main.cpp b/exp/main.cpp index 77d4aa00f..a88023fae 100644 --- a/exp/main.cpp +++ b/exp/main.cpp @@ -19,290 +19,39 @@ * @date 2014 * Ethereum client. */ -#if 0 -#define BOOST_RESULT_OF_USE_DECLTYPE -#define BOOST_SPIRIT_USE_PHOENIX_V3 -#include -#include -#include -#endif #include #include #include #include #include +#include #include -#if 0 -#include -#include "BuildInfo.h" -#endif using namespace std; using namespace dev; using namespace dev::eth; using namespace dev::p2p; using namespace dev::shh; -#if 0 -#if 0 -namespace qi = boost::spirit::qi; -namespace px = boost::phoenix; -namespace sp = boost::spirit; - -class ASTSymbol: public string -{ -public: - ASTSymbol() {} -}; - -enum class ASTType -{ - Symbol, - IntegerLiteral, - StringLiteral, - Call, - Return, - Operator, - Compound -}; - -class ASTNode: public vector -{ -public: - ASTNode() {} - ASTNode(ASTSymbol const& _s): m_type(ASTType::Symbol), m_s(_s) {} - ASTNode(string const& _s): m_type(ASTType::StringLiteral), m_s(_s) {} - ASTNode(bigint const& _i): m_type(ASTType::IntegerLiteral), m_i(_i) {} - ASTNode(ASTType _t): m_type(_t) {} - - ASTNode& operator=(ASTSymbol const& _s) { m_type = ASTType::Symbol; m_s = _s; return *this; } - ASTNode& operator=(string const& _s) { m_type = ASTType::StringLiteral; m_s = _s; return *this; } - ASTNode& operator=(bigint const& _i) { m_type = ASTType::IntegerLiteral; m_i = _i; return *this; } - ASTNode& operator=(ASTType const& _s) { m_type = _s; return *this; } - - void debugOut(ostream& _out) const; - -private: - ASTType m_type; - string m_s; - bigint m_i; -}; - -void parseTree(string const& _s, ASTNode& o_out) +int main() { - using qi::standard::space; - using qi::standard::space_type; - typedef string::const_iterator it; - -/* static const u256 ether = u256(1000000000) * 1000000000; - static const u256 finney = u256(1000000000) * 1000000; - static const u256 szabo = u256(1000000000) * 1000;*/ - - qi::rule element; - qi::rule call; - qi::rule str = '"' > qi::lexeme[+(~qi::char_(std::string("\"") + '\0'))] > '"'; - qi::rule symbol = qi::lexeme[+(~qi::char_(std::string(" $@[]{}:();\"\x01-\x1f\x7f") + '\0'))]; -/* qi::rule strsh = '\'' > qi::lexeme[+(~qi::char_(std::string(" ;$@()[]{}:\n\t") + '\0'))]; - qi::rule intstr = qi::lexeme[ qi::no_case["0x"][qi::_val = "0x"] >> *qi::char_("0-9a-fA-F")[qi::_val += qi::_1]] | qi::lexeme[+qi::char_("0-9")[qi::_val += qi::_1]]; - qi::rule integer = intstr; - qi::rule multiplier = qi::lit("wei")[qi::_val = 1] | qi::lit("szabo")[qi::_val = szabo] | qi::lit("finney")[qi::_val = finney] | qi::lit("ether")[qi::_val = ether]; - qi::rule quantity = integer[qi::_val = qi::_1] >> -multiplier[qi::_val *= qi::_1]; - qi::rule atom = quantity[qi::_val = px::construct(px::new_(qi::_1))] | (str | strsh)[qi::_val = qi::_1] | symbol[qi::_val = qi::_1]; - qi::rule seq = '{' > *element > '}'; - qi::rule mload = '@' > element; - qi::rule sload = qi::lit("@@") > element; - qi::rule mstore = '[' > element > ']' > -qi::lit(":") > element; - qi::rule sstore = qi::lit("[[") > element > qi::lit("]]") > -qi::lit(":") > element; - qi::rule calldataload = qi::lit("$") > element; - qi::rule list = '(' > *element > ')'; - - qi::rule extra = sload[tagNode<2>()] | mload[tagNode<1>()] | sstore[tagNode<4>()] | mstore[tagNode<3>()] | seq[tagNode<5>()] | calldataload[tagNode<6>()];*/ - qi::rule value = call[qi::_val = ASTType::Call] | str[qi::_val = qi::_1] | symbol[qi::_val = qi::_1]; - qi::rule compound = '{' > *element > '}'; - call = '(' > *value > ')'; //symbol > '(' > !(value > *(',' > value)) > ')'; - element = compound[qi::_val = ASTType::Compound] | value[qi::_val = qi::_1]; - - auto ret = _s.cbegin(); - qi::phrase_parse(ret, _s.cend(), element, space, qi::skip_flag::dont_postskip, o_out); - for (auto i = ret; i != _s.cend(); ++i) - if (!isspace(*i)) - throw std::exception(); -} - -void ASTNode::debugOut(ostream& _out) const -{ - switch (m_type) - { - case ASTType::StringLiteral: - _out << "\"" << m_s << "\""; - break; - case ASTType::Symbol: - _out << m_s; - break; - case ASTType::Compound: - { - unsigned n = 0; - _out << "{"; - for (auto const& i: *this) - { - i.debugOut(_out); - _out << ";"; - ++n; - } - _out << "}"; - break; - } - case ASTType::Call: - { - unsigned n = 0; - for (auto const& i: *this) - { - i.debugOut(_out); - if (n == 0) - _out << "("; - else if (n < size() - 1) - _out << ","; - if (n == size() - 1) - _out << ")"; - ++n; - } - break; - } - default: - _out << "nil"; - } -} - -int main(int, char**) -{ - ASTNode out; - parseTree("{x}", out); - out.debugOut(cout); - cout << endl; + RangeMask m(0, 100); + cnote << m; + m += UnsignedRange(3, 10); + cnote << m; + m += UnsignedRange(11, 16); + cnote << m; + m += UnsignedRange(10, 11); + cnote << m; + cnote << ~m; + cnote << (~m).lowest(10); + for (auto i: (~m).lowest(10)) + cnote << i; return 0; } -#endif -void killBigints(sp::utree const& _this) -{ - switch (_this.which()) - { - case sp::utree_type::list_type: for (auto const& i: _this) killBigints(i); break; - case sp::utree_type::any_type: delete _this.get(); break; - default:; - } -} - -void debugOutAST(ostream& _out, sp::utree const& _this) -{ - switch (_this.which()) - { - case sp::utree_type::list_type: - switch (_this.tag()) - { - case 0: { int n = 0; for (auto const& i: _this) { debugOutAST(_out, i); if (n++) _out << ", "; } break; } - case 1: _out << "@ "; debugOutAST(_out, _this.front()); break; - case 2: _out << "@@ "; debugOutAST(_out, _this.front()); break; - case 3: _out << "[ "; debugOutAST(_out, _this.front()); _out << " ] "; debugOutAST(_out, _this.back()); break; - case 4: _out << "[[ "; debugOutAST(_out, _this.front()); _out << " ]] "; debugOutAST(_out, _this.back()); break; - case 5: _out << "{ "; for (auto const& i: _this) { debugOutAST(_out, i); _out << " "; } _out << "}"; break; - case 6: _out << "$ "; debugOutAST(_out, _this.front()); break; - default: - { _out << _this.tag() << ": "; int n = 0; for (auto const& i: _this) { debugOutAST(_out, i); if (n++) _out << ", "; } break; } - } - - break; - case sp::utree_type::int_type: _out << _this.get(); break; - case sp::utree_type::string_type: _out << "\"" << _this.get, sp::utree_type::string_type>>() << "\""; break; - case sp::utree_type::symbol_type: _out << _this.get, sp::utree_type::symbol_type>>(); break; - case sp::utree_type::any_type: _out << *_this.get(); break; - default: _out << "nil"; - } -} - -namespace dev { -namespace eth { -namespace parseTreeLLL_ { - -template -struct tagNode -{ - void operator()(sp::utree& n, qi::rule::context_type& c) const - { - (boost::fusion::at_c<0>(c.attributes) = n).tag(N); - } -}; - -}}} - -void parseTree(string const& _s, sp::utree& o_out) -{ - using qi::standard::space; - using qi::standard::space_type; - using dev::eth::parseTreeLLL_::tagNode; - typedef sp::basic_string symbol_type; - typedef string::const_iterator it; - - static const u256 ether = u256(1000000000) * 1000000000; - static const u256 finney = u256(1000000000) * 1000000; - static const u256 szabo = u256(1000000000) * 1000; -#if 0 - qi::rule element; - qi::rule statement; - qi::rule str = '"' > qi::lexeme[+(~qi::char_(std::string("\"") + '\0'))] > '"'; - qi::rule strsh = '\'' > qi::lexeme[+(~qi::char_(std::string(" ;$@()[]{}:\n\t") + '\0'))]; - qi::rule symbol = qi::lexeme[+(~qi::char_(std::string(" $@[]{}:();\"\x01-\x1f\x7f") + '\0'))]; - qi::rule intstr = qi::lexeme[ qi::no_case["0x"][qi::_val = "0x"] >> *qi::char_("0-9a-fA-F")[qi::_val += qi::_1]] | qi::lexeme[+qi::char_("0-9")[qi::_val += qi::_1]]; - qi::rule integer = intstr; - qi::rule multiplier = qi::lit("wei")[qi::_val = 1] | qi::lit("szabo")[qi::_val = szabo] | qi::lit("finney")[qi::_val = finney] | qi::lit("ether")[qi::_val = ether]; - qi::rule quantity = integer[qi::_val = qi::_1] >> -multiplier[qi::_val *= qi::_1]; - qi::rule atom = quantity[qi::_val = px::construct(px::new_(qi::_1))] | (str | strsh)[qi::_val = qi::_1] | symbol[qi::_val = qi::_1]; - qi::rule compound = '{' > *statement > '}'; -/* qi::rule mload = '@' > element; - qi::rule sload = qi::lit("@@") > element; - qi::rule mstore = '[' > element > ']' > -qi::lit(":") > element; - qi::rule sstore = qi::lit("[[") > element > qi::lit("]]") > -qi::lit(":") > element; - qi::rule calldataload = qi::lit("$") > element;*/ -// qi::rule args = '(' > (element % ',') > ')'; - - qi::rule expression; - qi::rule group = '(' >> expression[qi::_val = qi::_1] >> ')'; - qi::rule factor = atom | group; - qi::rule mul = '*' >> factor; - qi::rule div = '/' >> factor; - qi::rule op = mul[tagNode<10>()] | div[tagNode<11>()]; - qi::rule term = factor >> !op; - expression = term >> !(('+' >> term) | ('-' >> term)); - - // qi::rule extra = sload[tagNode<2>()] | mload[tagNode<1>()] | sstore[tagNode<4>()] | mstore[tagNode<3>()] | calldataload[tagNode<6>()]; - statement = compound[tagNode<5>()] | (element > ';')[qi::_val = qi::_1]; - element %= expression;// | extra; -#endif - qi::rule symbol = qi::lexeme[+(~qi::char_(std::string(" $@[]{}:();\"\x01-\x1f\x7f") + '\0'))]; - qi::rule intstr = qi::lexeme[ qi::no_case["0x"][qi::_val = "0x"] >> *qi::char_("0-9a-fA-F")[qi::_val += qi::_1]] | qi::lexeme[+qi::char_("0-9")[qi::_val += qi::_1]]; - qi::rule integer = intstr; - qi::rule intnode = integer[qi::_val = px::construct(px::new_(qi::_1))]; - qi::rule funcname = symbol; - qi::rule statement; - qi::rule call = funcname > '(' > funcname > ')'; - statement = call | intnode | symbol; - - auto ret = _s.cbegin(); - qi::phrase_parse(ret, _s.cend(), statement, space, qi::skip_flag::dont_postskip, o_out); - for (auto i = ret; i != _s.cend(); ++i) - if (!isspace(*i)) - throw std::exception(); -} -#endif +/* int main(int argc, char** argv) { -#if 0 - sp::utree out; - parseTree("x(2)", out); - debugOutAST(cout, out); - killBigints(out); - cout << endl; -#endif - g_logVerbosity = 20; short listenPort = 30303; @@ -341,6 +90,6 @@ int main(int argc, char** argv) for (auto i: wh->checkWatch(w)) cnote << "New message:" << (u256)h256(wh->message(i).payload); } - return 0; } +*/ diff --git a/libdevcore/RangeMask.cpp b/libdevcore/RangeMask.cpp new file mode 100644 index 000000000..5ba4a1f73 --- /dev/null +++ b/libdevcore/RangeMask.cpp @@ -0,0 +1,5 @@ +#include "RangeMask.h" + +RangeMask::RangeMask() +{ +} diff --git a/libdevcore/RangeMask.h b/libdevcore/RangeMask.h new file mode 100644 index 000000000..ba8594779 --- /dev/null +++ b/libdevcore/RangeMask.h @@ -0,0 +1,192 @@ +/* + This file is part of cpp-ethereum. + + cpp-ethereum 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. + + cpp-ethereum 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 cpp-ethereum. If not, see . +*/ +/** @file EthereumHost.h + * @author Gav Wood + * @date 2014 + */ + +#pragma once + +#include +#include +#include + +namespace dev +{ + +class RLPStream; + +using UnsignedRange = std::pair; +using UnsignedRanges = std::vector; + +template +class RangeMask +{ + template friend std::ostream& operator<<(std::ostream& _out, RangeMask const& _r); + +public: + using Range = std::pair; + using Ranges = std::vector; + + RangeMask() {} + RangeMask(T _begin, T _end): m_all(_begin, _end) {} + RangeMask(Range const& _c): m_all(_c) {} + + RangeMask operator+(RangeMask const& _m) const { return RangeMask(*this) += _m; } + + RangeMask lowest(T _items) const + { + RangeMask ret(m_all); + for (auto i = m_ranges.begin(); i != m_ranges.end() && _items; ++i) + _items -= (ret.m_ranges[i->first] = std::min(i->first + _items, i->second)); + return ret; + } + + RangeMask operator~() const + { + RangeMask ret(m_all); + T last = m_all.first; + for (auto i: m_ranges) + { + if (i.first != last) + ret.m_ranges[last] = i.first; + last = i.second; + } + if (last != m_all.second) + ret.m_ranges[last] = m_all.second; + return ret; + } + + RangeMask& operator+=(RangeMask const& _m) + { + for (auto const& i: _m.m_ranges) + operator+=(i); + return *this; + } + RangeMask& operator+=(UnsignedRange const& _m) + { + for (auto i = _m.first; i < _m.second;) + { + // for each number, we find the element equal or next lower. this, if any, must contain the value. + auto uit = m_ranges.upper_bound(i); + auto it = uit == m_ranges.begin() ? m_ranges.end() : std::prev(uit); + if (it == m_ranges.end() || it->second < i) + // lower range is too low to merge. + // if the next higher range is too high. + if (uit == m_ranges.end() || uit->first > _m.second) + { + // just create a new range + m_ranges[i] = _m.second; + break; + } + else + { + if (uit->first == i) + // move i to end of range + i = uit->second; + else + { + // merge with the next higher range + // move i to end of range + i = m_ranges[i] = uit->second; + i = uit->second; + m_ranges.erase(uit); + } + } + else if (it->second == i) + { + // if the next higher range is too high. + if (uit == m_ranges.end() || uit->first > _m.second) + { + // merge with the next lower range + m_ranges[it->first] = _m.second; + break; + } + else + { + // merge with both next lower & next higher. + i = m_ranges[it->first] = uit->second; + m_ranges.erase(uit); + } + } + else + i = it->second; + } + return *this; + } + + RangeMask& operator+=(T _i) + { + return operator+=(Range(_i, _i + 1)); + } + + bool contains(T _i) const + { + auto it = m_ranges.lower_bound(_i); + return it != m_ranges.end() && it->first <= _i && it->second > _i; + } + + class const_iterator + { + friend class RangeMask; + + public: + const_iterator() {} + + T operator*() const { return m_value; } + const_iterator& operator++() { if (m_owner) m_value = m_owner->next(m_value); return *this; } + const_iterator operator++(int) { auto ret = *this; if (m_owner) m_value = m_owner->next(m_value); return ret; } + + bool operator==(const_iterator const& _i) const { return m_owner == _i.m_owner && m_value == _i.m_value; } + bool operator!=(const_iterator const& _i) const { return !operator==(_i); } + bool operator<(const_iterator const& _i) const { return m_value < _i.m_value; } + + private: + const_iterator(RangeMask const& _m, bool _end): m_owner(&_m), m_value(_m.m_ranges.empty() || _end ? _m.m_all.second : _m.m_ranges.begin()->first) {} + + RangeMask const* m_owner = nullptr; + T m_value = 0; + }; + + const_iterator begin() const { return const_iterator(*this, false); } + const_iterator end() const { return const_iterator(*this, true); } + T next(T _t) const + { + _t++; + // find next item in range at least _t + auto uit = m_ranges.upper_bound(_t); // > _t + auto it = uit == m_ranges.begin() ? m_ranges.end() : std::prev(uit); + if (it != m_ranges.end() && it->first <= _t && it->second > _t) + return _t; + return uit == m_ranges.end() ? m_all.second : uit->first; + } + +private: + UnsignedRange m_all; + std::map m_ranges; +}; + +template inline std::ostream& operator<<(std::ostream& _out, RangeMask const& _r) +{ + _out << _r.m_all.first << "{ "; + for (auto const& i: _r.m_ranges) + _out << "[" << i.first << ", " << i.second << ") "; + _out << "}" << _r.m_all.second; + return _out; +} + +} diff --git a/libethereum/EthereumHost.h b/libethereum/EthereumHost.h index c875d74fe..b038e0785 100644 --- a/libethereum/EthereumHost.h +++ b/libethereum/EthereumHost.h @@ -46,88 +46,6 @@ namespace eth class TransactionQueue; class BlockQueue; -using UnsignedRange = std::pair; -using UnsignedRanges = std::vector; - -class RangeMask -{ -public: - RangeMask() {} - RangeMask(unsigned _begin, unsigned _end): m_ranges({{_begin, _end}}) {} - - RangeMask& operator+=(RangeMask const& _m) - { - for (auto const& i: _m.m_ranges) - operator+=(i); - return *this; - } - RangeMask& operator+=(UnsignedRange const& _m) - { - for (auto i = _m.first; i < _m.second;) - { - // for each number, we find the element equal or next lower. this must contain the value. - auto it = m_ranges.lower_bound(i); - auto uit = m_ranges.upper_bound(i + 1); - if (it == m_ranges.end() || it->second < i) - // lower range is too low to merge. - // if the next higher range is too high. - if (uit == m_ranges.end() || uit->first > _m.second) - { - // just create a new range - m_ranges[i] = _m.second; - break; - } - else - { - if (uit->first == i) - // move i to end of range - i = uit->second; - else - { - // merge with the next higher range - // move i to end of range - i = m_ranges[i] = uit->second; - i = uit->second; - m_ranges.erase(uit); - } - } - else if (it->second == i) - { - // if the next higher range is too high. - if (uit == m_ranges.end() || uit->first > _m.second) - { - // merge with the next lower range - m_ranges[it->first] = _m.second; - break; - } - else - { - // merge with both next lower & next higher. - i = m_ranges[it->first] = uit->second; - m_ranges.erase(uit); - } - } - else - i = it->second; - } - return *this; - } - - RangeMask& operator+=(unsigned _i) - { - return operator+=(UnsignedRange(_i, _i + 1)); - } - - bool contains(unsigned _i) const - { - auto it = m_ranges.lower_bound(_i); - return it != m_ranges.end() && it->first <= _i && it->second > _i; - } - -private: - std::map m_ranges; -}; - #if 0 class DownloadSub {