X-Git-Url: https://gitweb.ps.run/toc/blobdiff_plain/9f94b672a5dc32da5ad01742bd4e976315a30d9c..c6ad2948bb98d42f8e0883ef82cd14cd2d5eda60:/antlr4-cpp-runtime-4.9.2-source/runtime/src/support/CPPUtils.cpp diff --git a/antlr4-cpp-runtime-4.9.2-source/runtime/src/support/CPPUtils.cpp b/antlr4-cpp-runtime-4.9.2-source/runtime/src/support/CPPUtils.cpp new file mode 100644 index 0000000..86a3751 --- /dev/null +++ b/antlr4-cpp-runtime-4.9.2-source/runtime/src/support/CPPUtils.cpp @@ -0,0 +1,248 @@ +/* Copyright (c) 2012-2017 The ANTLR Project. All rights reserved. + * Use of this file is governed by the BSD 3-clause license that + * can be found in the LICENSE.txt file in the project root. + */ + +#include "support/CPPUtils.h" + +namespace antlrcpp { + + std::string join(std::vector strings, const std::string &separator) { + std::string str; + bool firstItem = true; + for (std::string s : strings) { + if (!firstItem) { + str.append(separator); + } + firstItem = false; + str.append(s); + } + return str; + } + + std::map toMap(const std::vector &keys) { + std::map result; + for (size_t i = 0; i < keys.size(); ++i) { + result.insert({ keys[i], i }); + } + return result; + } + + std::string escapeWhitespace(std::string str, bool escapeSpaces) { + std::string result; + for (auto c : str) { + switch (c) { + case '\n': + result += "\\n"; + break; + + case '\r': + result += "\\r"; + break; + + case '\t': + result += "\\t"; + break; + + case ' ': + if (escapeSpaces) { + result += "\u00B7"; + break; + } + // else fall through +#ifndef _MSC_VER +#if __has_cpp_attribute(clang::fallthrough) + [[clang::fallthrough]]; +#endif +#endif + + default: + result += c; + } + } + + return result; + } + + std::string toHexString(const int t) { + std::stringstream stream; + stream << std::uppercase << std::hex << t; + return stream.str(); + } + + std::string arrayToString(const std::vector &data) { + std::string answer; + for (auto sub: data) { + answer += sub; + } + return answer; + } + + std::string replaceString(const std::string &s, const std::string &from, const std::string &to) { + std::string::size_type p; + std::string ss, res; + + ss = s; + p = ss.find(from); + while (p != std::string::npos) { + if (p > 0) + res.append(ss.substr(0, p)).append(to); + else + res.append(to); + ss = ss.substr(p + from.size()); + p = ss.find(from); + } + res.append(ss); + + return res; + } + + std::vector split(const std::string &s, const std::string &sep, int count) { + std::vector parts; + std::string ss = s; + + std::string::size_type p; + + if (s.empty()) + return parts; + + if (count == 0) + count= -1; + + p = ss.find(sep); + while (!ss.empty() && p != std::string::npos && (count < 0 || count > 0)) { + parts.push_back(ss.substr(0, p)); + ss = ss.substr(p+sep.size()); + + --count; + p = ss.find(sep); + } + parts.push_back(ss); + + return parts; + } + + //-------------------------------------------------------------------------------------------------- + + // Debugging helper. Adds indentation to all lines in the given string. + std::string indent(const std::string &s, const std::string &indentation, bool includingFirst) { + std::vector parts = split(s, "\n", -1); + for (size_t i = 0; i < parts.size(); ++i) { + if (i == 0 && !includingFirst) + continue; + parts[i].insert(0, indentation); + } + + return join(parts, "\n"); + } + + //-------------------------------------------------------------------------------------------------- + + // Recursively get the error from a, possibly nested, exception. +#if defined(_MSC_FULL_VER) && _MSC_FULL_VER < 190023026 + // No nested exceptions before VS 2015. + template + std::exception_ptr get_nested(const T &/*e*/) { + try { + return nullptr; + } + catch (const std::bad_cast &) { + return nullptr; + } + } +#else + template + std::exception_ptr get_nested(const T &e) { + try { + auto nested = dynamic_cast(e); + return nested.nested_ptr(); + } + catch (const std::bad_cast &) { + return nullptr; + } + } +#endif + + std::string what(std::exception_ptr eptr) { + if (!eptr) { + throw std::bad_exception(); + } + + std::string result; + std::size_t nestCount = 0; + + next: { + try { + std::exception_ptr yeptr; + std::swap(eptr, yeptr); + std::rethrow_exception(yeptr); + } + catch (const std::exception &e) { + result += e.what(); + eptr = get_nested(e); + } + catch (const std::string &e) { + result += e; + } + catch (const char *e) { + result += e; + } + catch (...) { + result += "cannot be determined"; + } + + if (eptr) { + result += " ("; + ++nestCount; + goto next; + } + } + + result += std::string(nestCount, ')'); + return result; + } + + //----------------- FinallyAction ------------------------------------------------------------------------------------ + + FinalAction finally(std::function f) { + return FinalAction(f); + } + + //----------------- SingleWriteMultipleRead -------------------------------------------------------------------------- + + void SingleWriteMultipleReadLock::readLock() { + std::unique_lock lock(_mutex); + while (_waitingWriters != 0) + _readerGate.wait(lock); + ++_activeReaders; + lock.unlock(); + } + + void SingleWriteMultipleReadLock::readUnlock() { + std::unique_lock lock(_mutex); + --_activeReaders; + lock.unlock(); + _writerGate.notify_one(); + } + + void SingleWriteMultipleReadLock::writeLock() { + std::unique_lock lock(_mutex); + ++_waitingWriters; + while (_activeReaders != 0 || _activeWriters != 0) + _writerGate.wait(lock); + ++_activeWriters; + lock.unlock(); + } + + void SingleWriteMultipleReadLock::writeUnlock() { + std::unique_lock lock(_mutex); + --_waitingWriters; + --_activeWriters; + if (_waitingWriters > 0) + _writerGate.notify_one(); + else + _readerGate.notify_all(); + lock.unlock(); + } + +} // namespace antlrcpp