1 /* Copyright (c) 2012-2017 The ANTLR Project. All rights reserved.
2 * Use of this file is governed by the BSD 3-clause license that
3 * can be found in the LICENSE.txt file in the project root.
6 #include "support/CPPUtils.h"
10 std::string join(std::vector<std::string> strings, const std::string &separator) {
12 bool firstItem = true;
13 for (std::string s : strings) {
15 str.append(separator);
23 std::map<std::string, size_t> toMap(const std::vector<std::string> &keys) {
24 std::map<std::string, size_t> result;
25 for (size_t i = 0; i < keys.size(); ++i) {
26 result.insert({ keys[i], i });
31 std::string escapeWhitespace(std::string str, bool escapeSpaces) {
54 #if __has_cpp_attribute(clang::fallthrough)
55 [[clang::fallthrough]];
67 std::string toHexString(const int t) {
68 std::stringstream stream;
69 stream << std::uppercase << std::hex << t;
73 std::string arrayToString(const std::vector<std::string> &data) {
75 for (auto sub: data) {
81 std::string replaceString(const std::string &s, const std::string &from, const std::string &to) {
82 std::string::size_type p;
87 while (p != std::string::npos) {
89 res.append(ss.substr(0, p)).append(to);
92 ss = ss.substr(p + from.size());
100 std::vector<std::string> split(const std::string &s, const std::string &sep, int count) {
101 std::vector<std::string> parts;
104 std::string::size_type p;
113 while (!ss.empty() && p != std::string::npos && (count < 0 || count > 0)) {
114 parts.push_back(ss.substr(0, p));
115 ss = ss.substr(p+sep.size());
125 //--------------------------------------------------------------------------------------------------
127 // Debugging helper. Adds indentation to all lines in the given string.
128 std::string indent(const std::string &s, const std::string &indentation, bool includingFirst) {
129 std::vector<std::string> parts = split(s, "\n", -1);
130 for (size_t i = 0; i < parts.size(); ++i) {
131 if (i == 0 && !includingFirst)
133 parts[i].insert(0, indentation);
136 return join(parts, "\n");
139 //--------------------------------------------------------------------------------------------------
141 // Recursively get the error from a, possibly nested, exception.
142 #if defined(_MSC_FULL_VER) && _MSC_FULL_VER < 190023026
143 // No nested exceptions before VS 2015.
144 template <typename T>
145 std::exception_ptr get_nested(const T &/*e*/) {
149 catch (const std::bad_cast &) {
154 template <typename T>
155 std::exception_ptr get_nested(const T &e) {
157 auto nested = dynamic_cast<const std::nested_exception&>(e);
158 return nested.nested_ptr();
160 catch (const std::bad_cast &) {
166 std::string what(std::exception_ptr eptr) {
168 throw std::bad_exception();
172 std::size_t nestCount = 0;
176 std::exception_ptr yeptr;
177 std::swap(eptr, yeptr);
178 std::rethrow_exception(yeptr);
180 catch (const std::exception &e) {
182 eptr = get_nested(e);
184 catch (const std::string &e) {
187 catch (const char *e) {
191 result += "cannot be determined";
201 result += std::string(nestCount, ')');
205 //----------------- FinallyAction ------------------------------------------------------------------------------------
207 FinalAction finally(std::function<void ()> f) {
208 return FinalAction(f);
211 //----------------- SingleWriteMultipleRead --------------------------------------------------------------------------
213 void SingleWriteMultipleReadLock::readLock() {
214 std::unique_lock<std::mutex> lock(_mutex);
215 while (_waitingWriters != 0)
216 _readerGate.wait(lock);
221 void SingleWriteMultipleReadLock::readUnlock() {
222 std::unique_lock<std::mutex> lock(_mutex);
225 _writerGate.notify_one();
228 void SingleWriteMultipleReadLock::writeLock() {
229 std::unique_lock<std::mutex> lock(_mutex);
231 while (_activeReaders != 0 || _activeWriters != 0)
232 _writerGate.wait(lock);
237 void SingleWriteMultipleReadLock::writeUnlock() {
238 std::unique_lock<std::mutex> lock(_mutex);
241 if (_waitingWriters > 0)
242 _writerGate.notify_one();
244 _readerGate.notify_all();
248 } // namespace antlrcpp