]> gitweb.ps.run Git - toc/blob - antlr4-cpp-runtime-4.9.2-source/runtime/src/UnbufferedCharStream.cpp
add antlr source code and ReadMe
[toc] / antlr4-cpp-runtime-4.9.2-source / runtime / src / UnbufferedCharStream.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 "misc/Interval.h"
7 #include "Exceptions.h"
8 #include "support/StringUtils.h"
9
10 #include "UnbufferedCharStream.h"
11
12 using namespace antlrcpp;
13 using namespace antlr4;
14 using namespace antlr4::misc;
15
16 UnbufferedCharStream::UnbufferedCharStream(std::wistream &input) : _input(input) {
17   InitializeInstanceFields();
18
19   // The vector's size is what used to be n in Java code.
20   fill(1); // prime
21 }
22
23 void UnbufferedCharStream::consume() {
24   if (LA(1) == EOF) {
25     throw IllegalStateException("cannot consume EOF");
26   }
27
28   // buf always has at least data[p==0] in this method due to ctor
29   _lastChar = _data[_p]; // track last char for LA(-1)
30
31   if (_p == _data.size() - 1 && _numMarkers == 0) {
32     size_t capacity = _data.capacity();
33     _data.clear();
34     _data.reserve(capacity);
35
36     _p = 0;
37     _lastCharBufferStart = _lastChar;
38   } else {
39     _p++;
40   }
41
42   _currentCharIndex++;
43   sync(1);
44 }
45
46 void UnbufferedCharStream::sync(size_t want) {
47   if (_p + want <= _data.size()) // Already enough data loaded?
48     return;
49
50   fill(_p + want - _data.size());
51 }
52
53 size_t UnbufferedCharStream::fill(size_t n) {
54   for (size_t i = 0; i < n; i++) {
55     if (_data.size() > 0 && _data.back() == 0xFFFF) {
56       return i;
57     }
58
59     try {
60       char32_t c = nextChar();
61       add(c);
62 #if defined(_MSC_FULL_VER) && _MSC_FULL_VER < 190023026
63     } catch (IOException &ioe) {
64       // throw_with_nested is not available before VS 2015.
65       throw ioe;
66 #else
67     } catch (IOException & /*ioe*/) {
68       std::throw_with_nested(RuntimeException());
69 #endif
70     }
71   }
72
73   return n;
74 }
75
76 char32_t UnbufferedCharStream::nextChar()  {
77   wchar_t result = 0;
78   _input >> result;
79   return result;
80 }
81
82 void UnbufferedCharStream::add(char32_t c) {
83   _data += c;
84 }
85
86 size_t UnbufferedCharStream::LA(ssize_t i) {
87   if (i == -1) { // special case
88     return _lastChar;
89   }
90
91   // We can look back only as many chars as we have buffered.
92   ssize_t index = static_cast<ssize_t>(_p) + i - 1;
93   if (index < 0) {
94     throw IndexOutOfBoundsException();
95   }
96
97   if (i > 0) {
98     sync(static_cast<size_t>(i)); // No need to sync if we look back.
99   }
100   if (static_cast<size_t>(index) >= _data.size()) {
101     return EOF;
102   }
103
104   if (_data[static_cast<size_t>(index)] == 0xFFFF) {
105     return EOF;
106   }
107
108   return _data[static_cast<size_t>(index)];
109 }
110
111 ssize_t UnbufferedCharStream::mark() {
112   if (_numMarkers == 0) {
113     _lastCharBufferStart = _lastChar;
114   }
115
116   ssize_t mark = -static_cast<ssize_t>(_numMarkers) - 1;
117   _numMarkers++;
118   return mark;
119 }
120
121 void UnbufferedCharStream::release(ssize_t marker) {
122   ssize_t expectedMark = -static_cast<ssize_t>(_numMarkers);
123   if (marker != expectedMark) {
124     throw IllegalStateException("release() called with an invalid marker.");
125   }
126
127   _numMarkers--;
128   if (_numMarkers == 0 && _p > 0) {
129     _data.erase(0, _p);
130     _p = 0;
131     _lastCharBufferStart = _lastChar;
132   }
133 }
134
135 size_t UnbufferedCharStream::index() {
136   return _currentCharIndex;
137 }
138
139 void UnbufferedCharStream::seek(size_t index) {
140   if (index == _currentCharIndex) {
141     return;
142   }
143
144   if (index > _currentCharIndex) {
145     sync(index - _currentCharIndex);
146     index = std::min(index, getBufferStartIndex() + _data.size() - 1);
147   }
148
149   // index == to bufferStartIndex should set p to 0
150   ssize_t i = static_cast<ssize_t>(index) - static_cast<ssize_t>(getBufferStartIndex());
151   if (i < 0) {
152     throw IllegalArgumentException(std::string("cannot seek to negative index ") + std::to_string(index));
153   } else if (i >= static_cast<ssize_t>(_data.size())) {
154     throw UnsupportedOperationException("Seek to index outside buffer: " + std::to_string(index) +
155                                         " not in " + std::to_string(getBufferStartIndex()) + ".." +
156                                         std::to_string(getBufferStartIndex() + _data.size()));
157   }
158
159   _p = static_cast<size_t>(i);
160   _currentCharIndex = index;
161   if (_p == 0) {
162     _lastChar = _lastCharBufferStart;
163   } else {
164     _lastChar = _data[_p - 1];
165   }
166 }
167
168 size_t UnbufferedCharStream::size() {
169   throw UnsupportedOperationException("Unbuffered stream cannot know its size");
170 }
171
172 std::string UnbufferedCharStream::getSourceName() const {
173   if (name.empty()) {
174     return UNKNOWN_SOURCE_NAME;
175   }
176
177   return name;
178 }
179
180 std::string UnbufferedCharStream::getText(const misc::Interval &interval) {
181   if (interval.a < 0 || interval.b >= interval.a - 1) {
182     throw IllegalArgumentException("invalid interval");
183   }
184
185   size_t bufferStartIndex = getBufferStartIndex();
186   if (!_data.empty() && _data.back() == 0xFFFF) {
187     if (interval.a + interval.length() > bufferStartIndex + _data.size()) {
188       throw IllegalArgumentException("the interval extends past the end of the stream");
189     }
190   }
191
192   if (interval.a < static_cast<ssize_t>(bufferStartIndex) || interval.b >= ssize_t(bufferStartIndex + _data.size())) {
193     throw UnsupportedOperationException("interval " + interval.toString() + " outside buffer: " +
194       std::to_string(bufferStartIndex) + ".." + std::to_string(bufferStartIndex + _data.size() - 1));
195   }
196   // convert from absolute to local index
197   size_t i = interval.a - bufferStartIndex;
198   return utf32_to_utf8(_data.substr(i, interval.length()));
199 }
200
201 size_t UnbufferedCharStream::getBufferStartIndex() const {
202   return _currentCharIndex - _p;
203 }
204
205 void UnbufferedCharStream::InitializeInstanceFields() {
206   _p = 0;
207   _numMarkers = 0;
208   _lastChar = 0;
209   _lastCharBufferStart = 0;
210   _currentCharIndex = 0;
211 }