1 /*
  2  * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved.
  3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  4  *
  5  * This code is free software; you can redistribute it and/or modify it
  6  * under the terms of the GNU General Public License version 2 only, as
  7  * published by the Free Software Foundation.  Oracle designates this
  8  * particular file as subject to the "Classpath" exception as provided
  9  * by Oracle in the LICENSE file that accompanied this code.
 10  *
 11  * This code is distributed in the hope that it will be useful, but WITHOUT
 12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 14  * version 2 for more details (a copy is included in the LICENSE file that
 15  * accompanied this code).
 16  *
 17  * You should have received a copy of the GNU General Public License version
 18  * 2 along with this work; if not, write to the Free Software Foundation,
 19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 20  *
 21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 22  * or visit www.oracle.com if you need additional information or have any
 23  * questions.
 24  */
 25 #include <string.h>
 26 #include <iostream>
 27 #include "buffer_cursor.h"
 28 
 29 
 30 Mark::Mark(BufferCursor *cursor)
 31     : cursor(cursor), ptr(nullptr), end(nullptr) {
 32 }
 33 
 34 std::string Mark::str(char *end) const {
 35     cursor->isValid(end);
 36     return std::string(ptr, end - ptr);
 37 }
 38 
 39 size_t Mark::getSize() {
 40     cursor->isValid(reinterpret_cast<char *>(cursor->get() - ptr));
 41     return cursor->get() - ptr;
 42 }
 43 
 44 std::string Mark::str() {
 45     return std::string(ptr, getSize());
 46 }
 47 
 48 std::string Mark::str(int delta) {
 49     return std::string(ptr, getSize() + delta);
 50 }
 51 
 52 
 53 char *Mark::getStart() {
 54     return ptr;
 55 }
 56 
 57 char *Mark::getEnd() {
 58     return setEnd();
 59 }
 60 
 61 char *Mark::setEnd() {
 62     if (end == nullptr) {
 63         end = cursor->get();
 64     }
 65     return end;
 66 }
 67 
 68 char *BufferCursor::get() {
 69     isValid(ptr);
 70     return ptr;
 71 }
 72 
 73 bool BufferCursor::isValid(char *p) {
 74     // if (p> endPtr){
 75     // std::cerr << "p beyond end " << endPtr-p << std::endl;
 76     // }
 77     // if (p< startPtr){
 78     //   std::cerr << "p before start " << p-startPtr << std::endl;
 79     // }
 80     return p >= startPtr && p <= endPtr;
 81 }
 82 
 83 bool BufferCursor::end() const {
 84     // isValid(ptr);
 85     return ptr >= endPtr;
 86 }
 87 
 88 BufferCursor *BufferCursor::advance(int i) {
 89     if (isValid(ptr)) {
 90         ptr += i;
 91         //   if (isValid(ptr)) {
 92         return this;
 93         //} else {
 94         // std::cerr << "ptr after advance is invalid";
 95         //  return this;
 96         //   std::exit(1);
 97     } else {
 98         std::cerr << "ptr before advance is invalid";
 99         std::exit(1);
100     }
101 }
102 
103 BufferCursor *BufferCursor::backup(const int i) {
104     if (isValid(ptr)) {
105         ptr -= i;
106         if (isValid(ptr)) {
107             return this;
108         } else {
109             std::cerr << "ptr after backup is invalid";
110             std::exit(1);
111         }
112     } else {
113         std::cerr << "ptr before backup is invalid";
114         std::exit(1);
115     }
116 }
117 
118 BufferCursor *BufferCursor::advance() {
119     return advance(1);
120 }
121 
122 BufferCursor *BufferCursor::backup() {
123     return backup(1);
124 }
125 
126 char BufferCursor::ch() {
127     if (!isValid(ptr)) {
128         std::cerr << "read past end!" << std::endl;
129         std::exit(1);
130     }
131     return *ptr;
132 }
133 
134 int BufferCursor::chAsDigit() {
135     isValid(ptr);
136     if (!isLookingAtDigit()) {
137         std::cerr << "not a digit" << std::endl;
138         std::exit(1);
139     }
140     return ch() - '0';
141 }
142 
143 int BufferCursor::chAsHexDigit() {
144     isValid(ptr);
145     if (!isLookingAtHexDigit()) {
146         std::cerr << "not a digit" << std::endl;
147         std::exit(1);
148     }
149     if (isLookingAtDigit()) {
150         return chAsDigit();
151     } else {
152         return tolower(ch()) - 'a' + 10;
153     }
154 }
155 
156 char BufferCursor::chAndAdvance() {
157     char c = ch();
158     advance();
159     return c;
160 }
161 
162 bool BufferCursor::isLookingAt(const char c) {
163     return (ch() == c);
164 }
165 
166 bool BufferCursor::isLookingAtAlpha() {
167     return (::isalpha(ch()));
168 }
169 
170 bool BufferCursor::isLookingAtDigit() {
171     return (isLookingAtOneOf("0123456789"));
172 }
173 
174 bool BufferCursor::isLookingAtOctalDigit() {
175     return (isLookingAtOneOf("01234567"));
176 }
177 
178 bool BufferCursor::isLookingAtHexDigit() {
179     return (isLookingAtOneOf("0123456789abcdefABCDEF"));
180 }
181 
182 bool BufferCursor::isLookingAtAlphaNum() {
183     return (isLookingAtAlpha() || isLookingAtDigit());
184 }
185 
186 bool BufferCursor::isLookingAtAlphaNumOr(const char *s) {
187     return (isLookingAtAlphaNum() || isLookingAtOneOf(s));
188 }
189 
190 BufferCursor *BufferCursor::skipWhiteSpace() {
191     return skipWhileLookingAt(" ");
192 }
193 
194 BufferCursor *BufferCursor::skipWhiteSpaceOrNewLine() {
195     return skipWhileLookingAtOneOf(" \n\t\r");
196 }
197 
198 
199 bool BufferCursor::isLookingAt(const char *str) {
200     char *p = ptr;
201     isValid(p + strlen(str));
202     while ((*p == *str) && (*str != '\0')) {
203         p++;
204         str++;
205     }
206     return (!*str);
207 }
208 
209 bool BufferCursor::isLookingAtAndStepOver(const char *str) {
210     if (isLookingAt(str)) {
211         stepOver(str);
212         return true;
213     }
214     return false;
215 }
216 
217 BufferCursor *BufferCursor::skipUntilLookingAt(const char *str) {
218     while (!isLookingAt(str)) {
219         advance();
220     }
221     return this;
222 }
223 
224 BufferCursor *BufferCursor::backupUntilLookingAt(const char *str) {
225     while (!isLookingAt(str)) {
226         backup();
227     }
228     return this;
229 }
230 
231 BufferCursor *BufferCursor::skipWhileLookingAt(const char *str) {
232     while (isLookingAt(str)) {
233         advance();
234     }
235     return this;
236 }
237 
238 BufferCursor *BufferCursor::skipWhileLookingAtOneOf(const char *str) {
239     while (isLookingAtOneOf(str)) {
240         advance();
241     }
242     return this;
243 }
244 
245 BufferCursor *BufferCursor::skipUntilLookingAtOneOf(const char *str) {
246     while (!isLookingAtOneOf(str)) {
247         advance();
248     }
249     return this;
250 }
251 
252 bool BufferCursor::isLookingAtOneOf(const char *str) {
253     while (*str) {
254         if (isLookingAt(*str++)) {
255             return true;
256         }
257     }
258 
259     return false;
260 }
261 
262 
263 BufferCursor *BufferCursor::moveTo(Mark *mark) {
264     ptr = mark->ptr;
265     isValid(ptr);
266     return this;
267 }
268 
269 bool BufferCursor::isLookingAtCRNL() {
270     return isLookingAt("\r\n");
271 }
272 
273 BufferCursor *BufferCursor::stepOverCRNL() {
274     return stepOver("\r\n");
275 }
276 
277 bool BufferCursor::isLookingAtNL() {
278     return isLookingAt("\n");
279 }
280 
281 BufferCursor *BufferCursor::stepOverNL() {
282     return stepOver("\n");
283 }
284 
285 Mark *BufferCursor::mark() {
286     Mark *mark = new Mark(this);
287     mark->cursor = this;
288     mark->ptr = ptr;
289     marks.push_back(mark);
290     return mark;
291 }
292 
293 Mark *BufferCursor::markUntil(const char *s) {
294     Mark *newMark = mark();
295     skipTill(s);
296     newMark->setEnd();
297     return newMark;
298 }
299 
300 BufferCursor *BufferCursor::stepOver(const char c) {
301     if (isLookingAt(c)) {
302         advance(1);
303     } else {
304         std::cerr << " expecting '" << c << "'" << std::endl;
305         std::exit(0);
306     }
307     return this;
308 }
309 
310 BufferCursor *BufferCursor::stepOver(const char *s) {
311     int len = strlen(s);
312     if (isLookingAt(s)) {
313         advance(len);
314     } else {
315         std::cerr << " expecting to step over '" << s << "'" << std::endl;
316         std::exit(0);
317     }
318     return this;
319 }
320 
321 
322 BufferCursor *BufferCursor::skipTill(const char *str) {
323     while (!end() && *ptr) {
324         if (isLookingAt(str)) {
325             return this;
326         }
327         advance();
328     }
329     return this;
330 }
331 
332 BufferCursor *BufferCursor::reset() {
333     ptr = startPtr;
334     return this;
335 }
336 
337 BufferCursor::BufferCursor(PureRange *pureRange)
338     : startPtr(pureRange->getStart()), ptr(pureRange->getStart()), endPtr(pureRange->getEnd()) {
339 }
340 
341 BufferCursor::BufferCursor(char *ptr, size_t
342                            len)
343     : startPtr(ptr), ptr(ptr), endPtr(ptr + len) {
344 }
345 
346 BufferCursor::BufferCursor(char *ptr)
347     : startPtr(ptr), ptr(ptr), endPtr(ptr + ::strlen(ptr)) {
348 }
349 
350 BufferCursor::~BufferCursor() {
351     for (auto mark: marks) {
352         delete mark;
353     }
354     marks.clear();
355 }
356 
357 void BufferCursor::show(std::ostream &o) {
358     char *safe = ptr;
359     while (!end()) {
360         o << *ptr;
361         advance();
362     }
363     ptr = safe;
364 }
365 
366 std::ostream &operator<<(std::ostream &o, BufferCursor &c) {
367     c.show(o);
368     return o;
369 }
370 
371 std::ostream &operator<<(std::ostream &o, BufferCursor *c) {
372     c->show(o);
373     return o;
374 }
375 
376 
377 char *BufferCursor::getStart() {
378     return startPtr;
379 }
380 
381 char *BufferCursor::getEnd() {
382     return endPtr;
383 }
384 
385 size_t BufferCursor::getSize() {
386     return endPtr - startPtr;
387 }
388 
389 BufferCursor *BufferCursor::moveToOffset(int offset) {
390     if (offset < 0) {
391         ptr = endPtr + offset;
392     } else {
393         ptr = startPtr + offset;
394     }
395     if (!isValid(ptr)) {
396         std::cerr << "ptr after moveOffset is invalid";
397         std::exit(1);
398     }
399     return this;
400 }