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 std::string Mark::str(char *end) {
 34     cursor->isValid(end);
 35     return std::string(ptr, end - ptr);
 36 }
 37 
 38 size_t Mark::getSize() {
 39     cursor->isValid((char *) (cursor->get() - ptr));
 40     return cursor->get() - ptr;
 41 }
 42 
 43 std::string Mark::str() {
 44     return std::string(ptr, getSize());
 45 }
 46 
 47 std::string Mark::str(int delta) {
 48     return std::string(ptr, getSize()+delta);
 49 }
 50 
 51 
 52 char *Mark::getStart(){
 53     return ptr;
 54 }
 55 char *Mark::getEnd(){
 56     return setEnd();
 57 }
 58 
 59 char *Mark::setEnd(){
 60     if (end == nullptr){
 61         end = cursor->get();
 62     }
 63     return end;
 64 }
 65 
 66 char *BufferCursor::get() {
 67     isValid(ptr);
 68     return ptr;
 69 }
 70 
 71 bool BufferCursor::isValid(char *p) {
 72   // if (p> endPtr){
 73      // std::cerr << "p beyond end " << endPtr-p << std::endl;
 74   // }
 75   // if (p< startPtr){
 76    //   std::cerr << "p before start " << p-startPtr << std::endl;
 77   // }
 78     return p >= startPtr && p <= endPtr;
 79 }
 80 
 81 bool BufferCursor::end() {
 82     // isValid(ptr);
 83     return ptr >= endPtr;
 84 }
 85 
 86 BufferCursor *BufferCursor::advance(int i) {
 87     if (isValid(ptr)) {
 88         ptr += i;
 89      //   if (isValid(ptr)) {
 90             return this;
 91         //} else {
 92            // std::cerr << "ptr after advance is invalid";
 93           //  return this;
 94          //   std::exit(1);
 95 
 96     } else {
 97         std::cerr << "ptr before advance is invalid";
 98         std::exit(1);
 99     }
100 
101 }
102 
103 BufferCursor *BufferCursor::backup(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 
119 BufferCursor *BufferCursor::advance() {
120     return advance(1);
121 }
122 
123 BufferCursor *BufferCursor::backup() {
124     return backup(1);
125 }
126 
127 char BufferCursor::ch() {
128     if (!isValid(ptr)){
129        std::cerr << "read past end!" << std::endl;
130        std::exit(1);
131     }
132     return *ptr;
133 }
134 
135 int BufferCursor::chAsDigit() {
136     isValid(ptr);
137     if (!isLookingAtDigit()) {
138         std::cerr << "not a digit" << std::endl;
139         std::exit(1);
140     }
141     return ch() - '0';
142 }
143 
144 int BufferCursor::chAsHexDigit() {
145     isValid(ptr);
146     if (!isLookingAtHexDigit()) {
147         std::cerr << "not a digit" << std::endl;
148         std::exit(1);
149     }
150     if (isLookingAtDigit()) {
151         return chAsDigit();
152     } else {
153         return tolower(ch()) - 'a' + 10;
154     }
155 }
156 
157 char BufferCursor::chAndAdvance() {
158     char c = ch();
159     advance();
160     return c;
161 }
162 
163 bool BufferCursor::isLookingAt(const char c) {
164     return (ch() == c);
165 }
166 
167 bool BufferCursor::isLookingAtAlpha() {
168     return (::isalpha(ch()));
169 }
170 
171 bool BufferCursor::isLookingAtDigit() {
172     return (isLookingAtOneOf("0123456789"));
173 }
174 bool BufferCursor::isLookingAtOctalDigit() {
175     return (isLookingAtOneOf("01234567"));
176 }
177 bool BufferCursor::isLookingAtHexDigit() {
178     return (isLookingAtOneOf("0123456789abcdefABCDEF"));
179 }
180 
181 bool BufferCursor::isLookingAtAlphaNum() {
182     return (isLookingAtAlpha() || isLookingAtDigit());
183 }
184 
185 bool BufferCursor::isLookingAtAlphaNumOr(const char *s) {
186     return (isLookingAtAlphaNum() || isLookingAtOneOf(s));
187 }
188 
189 BufferCursor *BufferCursor::skipWhiteSpace() {
190     return skipWhileLookingAt(" ");
191 }
192 
193 BufferCursor *BufferCursor::skipWhiteSpaceOrNewLine() {
194     return skipWhileLookingAtOneOf(" \n\t\r");
195 }
196 
197 
198 bool BufferCursor::isLookingAt(const char *str) {
199     char *p = ptr;
200     isValid(p + strlen(str));
201     while ((*p == *str) && (*str != '\0')) {
202         p++;
203         str++;
204     }
205     return (!*str);
206 }
207 
208 bool BufferCursor::isLookingAtAndStepOver(const char *str) {
209     if (isLookingAt(str)) {
210         stepOver(str);
211         return true;
212     }
213     return false;
214 }
215 
216 BufferCursor *BufferCursor::skipUntilLookingAt(const char *str) {
217     while (!isLookingAt(str)) {
218         advance();
219     }
220     return this;
221 }
222 
223 BufferCursor *BufferCursor::backupUntilLookingAt(const char *str) {
224     while (!isLookingAt(str)) {
225         backup();
226     }
227     return this;
228 }
229 
230 BufferCursor *BufferCursor::skipWhileLookingAt(const char *str) {
231     while (isLookingAt(str)) {
232         advance();
233     }
234     return this;
235 }
236 
237 BufferCursor *BufferCursor::skipWhileLookingAtOneOf(const char *str) {
238     while (isLookingAtOneOf(str)) {
239         advance();
240     }
241     return this;
242 }
243 
244 BufferCursor *BufferCursor::skipUntilLookingAtOneOf(const char *str) {
245     while (!isLookingAtOneOf(str)) {
246         advance();
247     }
248     return this;
249 }
250 
251 bool BufferCursor::isLookingAtOneOf(const char *str) {
252     while (*str) {
253         if (isLookingAt(*str++)) {
254             return true;
255         }
256     }
257 
258     return false;
259 }
260 
261 
262 BufferCursor *BufferCursor::moveTo(Mark *mark) {
263     ptr = mark->ptr;
264     isValid(ptr);
265     return this;
266 }
267 
268 bool BufferCursor::isLookingAtCRNL() {
269     return isLookingAt("\r\n");
270 }
271 
272 BufferCursor *BufferCursor::stepOverCRNL() {
273     return stepOver("\r\n");
274 }
275 
276 bool BufferCursor::isLookingAtNL() {
277     return isLookingAt("\n");
278 }
279 
280 BufferCursor *BufferCursor::stepOverNL() {
281     return stepOver("\n");
282 }
283 
284 Mark *BufferCursor::mark() {
285     Mark *mark = new Mark(this);
286     mark->cursor = this;
287     mark->ptr = ptr;
288     marks.push_back(mark);
289     return mark;
290 }
291 
292 Mark *BufferCursor::markUntil(const char *s) {
293     Mark *newMark = mark();
294     skipTill(s);
295     newMark->setEnd();
296     return newMark;
297 }
298 
299 BufferCursor *BufferCursor::stepOver(const char c) {
300     if (isLookingAt(c)) {
301         advance(1);
302     } else {
303         std::cerr << " expecting '" << c << "'" << std::endl;
304         std::exit(0);
305     }
306     return this;
307 }
308 
309 BufferCursor *BufferCursor::stepOver(const char *s) {
310     int len = strlen(s);
311     if (isLookingAt(s)) {
312         advance(len);
313     } else {
314         std::cerr << " expecting to step over '" << s << "'" << std::endl;
315         std::exit(0);
316     }
317     return this;
318 }
319 
320 
321 BufferCursor *BufferCursor::skipTill(const char *str) {
322     while (!end() && *ptr) {
323         if (isLookingAt(str)) {
324             return this;
325         }
326         advance();
327     }
328     return this;
329 }
330 
331 BufferCursor *BufferCursor::reset() {
332     ptr = startPtr;
333     return this;
334 }
335 
336 BufferCursor::BufferCursor(PureRange *pureRange)
337         : startPtr(pureRange->getStart()), ptr(pureRange->getStart()), endPtr(pureRange->getEnd()) {
338 
339 }
340 
341 BufferCursor::BufferCursor(char *ptr, size_t
342 len)
343         : startPtr(ptr), ptr(ptr), endPtr(ptr + len) {
344 
345 }
346 
347 BufferCursor::BufferCursor(char *ptr)
348         : startPtr(ptr), ptr(ptr), endPtr(ptr + ::strlen(ptr)) {
349 
350 }
351 BufferCursor::~BufferCursor(){
352    for (auto mark:marks){
353       delete mark;
354    }
355    marks.clear();
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 }