diff options
Diffstat (limited to 'libdevcore')
-rw-r--r-- | libdevcore/Algorithms.h | 76 | ||||
-rw-r--r-- | libdevcore/CMakeLists.txt | 6 | ||||
-rw-r--r-- | libdevcore/CommonIO.cpp | 69 | ||||
-rw-r--r-- | libdevcore/CommonIO.h | 8 |
4 files changed, 155 insertions, 4 deletions
diff --git a/libdevcore/Algorithms.h b/libdevcore/Algorithms.h new file mode 100644 index 00000000..b2540668 --- /dev/null +++ b/libdevcore/Algorithms.h @@ -0,0 +1,76 @@ +/* + 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 <functional> +#include <set> + +namespace dev +{ + +/** + * Detector for cycles in directed graphs. It returns the first + * vertex on the path towards a cycle or a nullptr if there is + * no reachable cycle starting from a given vertex. + */ +template <typename V> +class CycleDetector +{ +public: + /// 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): + m_visit(std::move(_visit)) + { } + + /// Recursively perform cycle detection starting + /// (or continuing) with @param _vertex + /// @returns the first vertex on the path towards a cycle from @a _vertex + /// or nullptr if no cycle is reachable from @a _vertex. + V const* run(V const& _vertex) + { + if (m_firstCycleVertex) + return m_firstCycleVertex; + if (m_processed.count(&_vertex)) + return nullptr; + else if (m_processing.count(&_vertex)) + return m_firstCycleVertex = &_vertex; + m_processing.insert(&_vertex); + + m_depth++; + m_visit(_vertex, *this); + m_depth--; + if (m_firstCycleVertex && m_depth == 1) + m_firstCycleVertex = &_vertex; + + m_processing.erase(&_vertex); + m_processed.insert(&_vertex); + return m_firstCycleVertex; + } + +private: + std::function<void(V const&, CycleDetector&)> m_visit; + std::set<V const*> m_processing; + std::set<V const*> m_processed; + size_t m_depth = 0; + V const* m_firstCycleVertex = nullptr; +}; + +} diff --git a/libdevcore/CMakeLists.txt b/libdevcore/CMakeLists.txt index d107f701..fa7e3f48 100644 --- a/libdevcore/CMakeLists.txt +++ b/libdevcore/CMakeLists.txt @@ -2,9 +2,7 @@ file(GLOB sources "*.cpp") file(GLOB headers "*.h") add_library(devcore ${sources} ${headers}) -target_link_libraries(devcore PRIVATE ${JSONCPP_LIBRARY} ${Boost_FILESYSTEM_LIBRARIES} ${Boost_REGEX_LIBRARIES} ${Boost_SYSTEM_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT}) -target_include_directories(devcore SYSTEM PUBLIC ${Boost_INCLUDE_DIRS}) +target_link_libraries(devcore PRIVATE jsoncpp ${Boost_FILESYSTEM_LIBRARIES} ${Boost_REGEX_LIBRARIES} ${Boost_SYSTEM_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT}) target_include_directories(devcore PUBLIC "${CMAKE_SOURCE_DIR}") -target_include_directories(devcore PUBLIC "${JSONCPP_INCLUDE_DIR}") -add_dependencies(devcore jsoncpp) +target_include_directories(devcore SYSTEM PUBLIC ${Boost_INCLUDE_DIRS}) add_dependencies(devcore solidity_BuildInfo.h) diff --git a/libdevcore/CommonIO.cpp b/libdevcore/CommonIO.cpp index 8c7e08f6..0063a8d4 100644 --- a/libdevcore/CommonIO.cpp +++ b/libdevcore/CommonIO.cpp @@ -27,6 +27,7 @@ #if defined(_WIN32) #include <windows.h> #else +#include <unistd.h> #include <termios.h> #endif #include <boost/filesystem.hpp> @@ -118,3 +119,71 @@ void dev::writeFile(std::string const& _file, bytesConstRef _data, bool _writeDe } } } + +#if defined(_WIN32) +class DisableConsoleBuffering +{ +public: + DisableConsoleBuffering() + { + m_stdin = GetStdHandle(STD_INPUT_HANDLE); + GetConsoleMode(m_stdin, &m_oldMode); + SetConsoleMode(m_stdin, m_oldMode & (~(ENABLE_ECHO_INPUT | ENABLE_LINE_INPUT))); + } + ~DisableConsoleBuffering() + { + SetConsoleMode(m_stdin, m_oldMode); + } +private: + HANDLE m_stdin; + DWORD m_oldMode; +}; +#else +class DisableConsoleBuffering +{ +public: + DisableConsoleBuffering() + { + tcgetattr(0, &m_termios); + m_termios.c_lflag &= ~ICANON; + m_termios.c_lflag &= ~ECHO; + m_termios.c_cc[VMIN] = 1; + m_termios.c_cc[VTIME] = 0; + tcsetattr(0, TCSANOW, &m_termios); + } + ~DisableConsoleBuffering() + { + m_termios.c_lflag |= ICANON; + m_termios.c_lflag |= ECHO; + tcsetattr(0, TCSADRAIN, &m_termios); + } +private: + struct termios m_termios; +}; +#endif + +int dev::readStandardInputChar() +{ + DisableConsoleBuffering disableConsoleBuffering; + return cin.get(); +} + +boost::filesystem::path dev::weaklyCanonicalFilesystemPath(boost::filesystem::path const &_path) +{ + if (boost::filesystem::exists(_path)) + return boost::filesystem::canonical(_path); + else + { + boost::filesystem::path head(_path); + boost::filesystem::path tail; + for (auto it = --_path.end(); !head.empty(); --it) + { + if (boost::filesystem::exists(head)) + break; + tail = (*it) / tail; + head.remove_filename(); + } + head = boost::filesystem::canonical(head); + return head / tail; + } +} diff --git a/libdevcore/CommonIO.h b/libdevcore/CommonIO.h index 33769ec3..9ba68e74 100644 --- a/libdevcore/CommonIO.h +++ b/libdevcore/CommonIO.h @@ -25,6 +25,7 @@ #include <sstream> #include <string> +#include <boost/filesystem.hpp> #include "Common.h" namespace dev @@ -37,6 +38,9 @@ std::string readFileAsString(std::string const& _file); /// Retrieve and returns the contents of standard input (until EOF). 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 @@ -54,4 +58,8 @@ std::string toString(_T const& _t) return o.str(); } +/// Partial implementation of boost::filesystem::weakly_canonical (available in boost>=1.60). +/// 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); + } |