]> gitweb.ps.run Git - toc/blob - antlr4-cpp-runtime-4.9.2-source/runtime/src/support/CPPUtils.cpp
add antlr source code and ReadMe
[toc] / antlr4-cpp-runtime-4.9.2-source / runtime / src / support / CPPUtils.cpp
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.
4  */
5
6 #include "support/CPPUtils.h"
7
8 namespace antlrcpp {
9
10   std::string join(std::vector<std::string> strings, const std::string &separator) {
11     std::string str;
12     bool firstItem = true;
13     for (std::string s : strings) {
14       if (!firstItem) {
15         str.append(separator);
16       }
17       firstItem = false;
18       str.append(s);
19     }
20     return str;
21   }
22
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 });
27     }
28     return result;
29   }
30
31   std::string escapeWhitespace(std::string str, bool escapeSpaces) {
32     std::string result;
33     for (auto c : str) {
34       switch (c) {
35         case '\n':
36           result += "\\n";
37           break;
38
39         case '\r':
40           result += "\\r";
41           break;
42
43         case '\t':
44           result += "\\t";
45           break;
46
47         case ' ':
48           if (escapeSpaces) {
49             result += "\u00B7";
50             break;
51           }
52           // else fall through
53 #ifndef _MSC_VER
54 #if __has_cpp_attribute(clang::fallthrough)
55           [[clang::fallthrough]];
56 #endif
57 #endif
58
59         default:
60           result += c;
61       }
62     }
63
64     return result;
65   }
66
67   std::string toHexString(const int t) {
68     std::stringstream stream;
69     stream << std::uppercase << std::hex << t;
70     return stream.str();
71   }
72
73   std::string arrayToString(const std::vector<std::string> &data) {
74     std::string answer;
75     for (auto sub: data) {
76       answer += sub;
77     }
78     return answer;
79   }
80
81   std::string replaceString(const std::string &s, const std::string &from, const std::string &to) {
82     std::string::size_type p;
83     std::string ss, res;
84
85     ss = s;
86     p = ss.find(from);
87     while (p != std::string::npos) {
88       if (p > 0)
89         res.append(ss.substr(0, p)).append(to);
90       else
91         res.append(to);
92       ss = ss.substr(p + from.size());
93       p = ss.find(from);
94     }
95     res.append(ss);
96
97     return res;
98   }
99
100   std::vector<std::string> split(const std::string &s, const std::string &sep, int count) {
101     std::vector<std::string> parts;
102     std::string ss = s;
103
104     std::string::size_type p;
105
106     if (s.empty())
107       return parts;
108
109     if (count == 0)
110       count= -1;
111
112     p = ss.find(sep);
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());
116
117       --count;
118       p = ss.find(sep);
119     }
120     parts.push_back(ss);
121
122     return parts;
123   }
124
125   //--------------------------------------------------------------------------------------------------
126
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)
132         continue;
133       parts[i].insert(0, indentation);
134     }
135
136     return join(parts, "\n");
137   }
138
139   //--------------------------------------------------------------------------------------------------
140
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*/) {
146     try {
147       return nullptr;
148     }
149     catch (const std::bad_cast &) {
150       return nullptr;
151     }
152   }
153 #else
154   template <typename T>
155   std::exception_ptr get_nested(const T &e) {
156     try {
157       auto nested = dynamic_cast<const std::nested_exception&>(e);
158       return nested.nested_ptr();
159     }
160     catch (const std::bad_cast &) {
161       return nullptr;
162     }
163   }
164 #endif
165
166   std::string what(std::exception_ptr eptr) {
167     if (!eptr) {
168       throw std::bad_exception();
169     }
170
171     std::string result;
172     std::size_t nestCount = 0;
173
174     next: {
175       try {
176         std::exception_ptr yeptr;
177         std::swap(eptr, yeptr);
178         std::rethrow_exception(yeptr);
179       }
180       catch (const std::exception &e) {
181         result += e.what();
182         eptr = get_nested(e);
183       }
184       catch (const std::string &e) {
185         result += e;
186       }
187       catch (const char *e) {
188         result += e;
189       }
190       catch (...) {
191         result += "cannot be determined";
192       }
193
194       if (eptr) {
195         result += " (";
196         ++nestCount;
197         goto next;
198       }
199     }
200
201     result += std::string(nestCount, ')');
202     return result;
203   }
204
205   //----------------- FinallyAction ------------------------------------------------------------------------------------
206
207   FinalAction finally(std::function<void ()> f) {
208     return FinalAction(f);
209   }
210
211   //----------------- SingleWriteMultipleRead --------------------------------------------------------------------------
212
213   void SingleWriteMultipleReadLock::readLock() {
214     std::unique_lock<std::mutex> lock(_mutex);
215     while (_waitingWriters != 0)
216       _readerGate.wait(lock);
217     ++_activeReaders;
218     lock.unlock();
219   }
220
221   void SingleWriteMultipleReadLock::readUnlock() {
222     std::unique_lock<std::mutex> lock(_mutex);
223     --_activeReaders;
224     lock.unlock();
225     _writerGate.notify_one();
226   }
227
228   void SingleWriteMultipleReadLock::writeLock() {
229     std::unique_lock<std::mutex> lock(_mutex);
230     ++_waitingWriters;
231     while (_activeReaders != 0 || _activeWriters != 0)
232       _writerGate.wait(lock);
233     ++_activeWriters;
234     lock.unlock();
235   }
236
237   void SingleWriteMultipleReadLock::writeUnlock() {
238     std::unique_lock<std::mutex> lock(_mutex);
239     --_waitingWriters;
240     --_activeWriters;
241     if (_waitingWriters > 0)
242       _writerGate.notify_one();
243     else
244       _readerGate.notify_all();
245     lock.unlock();
246   }
247
248 } // namespace antlrcpp