|
|
1.1 ! root 1: /* This is part of libio/iostream, providing -*- C++ -*- input/output. ! 2: Copyright (C) 1993 Free Software Foundation ! 3: ! 4: This file is part of the GNU IO Library. This library is free ! 5: software; you can redistribute it and/or modify it under the ! 6: terms of the GNU General Public License as published by the ! 7: Free Software Foundation; either version 2, or (at your option) ! 8: any later version. ! 9: ! 10: This library is distributed in the hope that it will be useful, ! 11: but WITHOUT ANY WARRANTY; without even the implied warranty of ! 12: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ! 13: GNU General Public License for more details. ! 14: ! 15: You should have received a copy of the GNU General Public License ! 16: along with GNU CC; see the file COPYING. If not, write to ! 17: the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. ! 18: ! 19: As a special exception, if you link this library with files ! 20: compiled with a GNU compiler to produce an executable, this does not cause ! 21: the resulting executable to be covered by the GNU General Public License. ! 22: This exception does not however invalidate any other reasons why ! 23: the executable file might be covered by the GNU General Public License. ! 24: ! 25: Written by Per Bothner ([email protected]). */ ! 26: ! 27: #ifdef __GNUG__ ! 28: #pragma implementation ! 29: #endif ! 30: #include "libioP.h" ! 31: #include "parsestream.h" ! 32: extern "C" { ! 33: #include <stdlib.h> ! 34: } ! 35: streambuf* parsebuf::setbuf(char*, int) ! 36: { ! 37: return NULL; ! 38: } ! 39: ! 40: int parsebuf::tell_in_line() ! 41: { ! 42: return 0; ! 43: } ! 44: ! 45: int parsebuf::pbackfail(int c) ! 46: { ! 47: if (c == EOF) ! 48: return 0; ! 49: if (seekoff(-1, ios::cur) == EOF) ! 50: return EOF; ! 51: return (unsigned char)c; ! 52: } ! 53: ! 54: char* parsebuf::current_line() { return NULL; } ! 55: ! 56: streampos parsebuf::seekoff(streamoff offset, _seek_dir dir, int) ! 57: { ! 58: // Make offset relative to line start. ! 59: switch (dir) { ! 60: case ios::beg: ! 61: offset -= pos_at_line_start; ! 62: break; ! 63: case ios::cur: ! 64: offset += tell_in_line(); ! 65: break; ! 66: default: ! 67: return EOF; ! 68: } ! 69: if (offset < -1) ! 70: return EOF; ! 71: if (offset > _line_length + 1) ! 72: return EOF; ! 73: return seek_in_line(offset) + pos_at_line_start; ! 74: } ! 75: ! 76: // string_parsebuf invariants: ! 77: // The reserve ares (base() .. ebuf()) is always the entire string. ! 78: // The get area (eback() .. egptr()) is the extended current line ! 79: // (i.e. with the '\n' at either end, if these exist). ! 80: ! 81: string_parsebuf::string_parsebuf(char *buf, int len, ! 82: int delete_at_close /* = 0*/) ! 83: : parsebuf() ! 84: { ! 85: setb(buf, buf+len, delete_at_close); ! 86: register char *ptr = buf; ! 87: while (ptr < ebuf() && *ptr != '\n') ptr++; ! 88: _line_length = ptr - buf; ! 89: setg(buf, buf, ptr); ! 90: } ! 91: ! 92: int string_parsebuf::underflow() ! 93: { ! 94: register char* ptr = egptr(); // Point to end of current_line ! 95: do { ! 96: int i = right() - ptr; ! 97: if (i <= 0) ! 98: return EOF; ! 99: ptr++; i--; // Skip '\n'. ! 100: char *line_start = ptr; ! 101: while (ptr < right() && *ptr == '\n') ptr++; ! 102: setg(line_start-1, line_start, ptr + (ptr < right())); ! 103: pos_at_line_start = line_start - left(); ! 104: _line_length = ptr - line_start; ! 105: __line_number++; ! 106: } while (gptr() == ptr); ! 107: return *gptr(); ! 108: } ! 109: ! 110: char* string_parsebuf::current_line() ! 111: { ! 112: char *ptr = eback(); ! 113: if (__line_number > 0) ! 114: ptr++; // Skip '\n' at end of previous line. ! 115: return ptr; ! 116: } ! 117: ! 118: int string_parsebuf::tell_in_line() ! 119: { ! 120: int offset = gptr() - eback(); ! 121: if (__line_number > 0) ! 122: offset--; ! 123: return offset; ! 124: } ! 125: ! 126: int string_parsebuf::seek_in_line(int i) ! 127: { ! 128: int delta = i - tell_in_line(); ! 129: gbump(delta); // FIXME: Needs error (bounds) checking! ! 130: return i; ! 131: } ! 132: ! 133: static const char NewLine[1] = { '\n' }; ! 134: ! 135: general_parsebuf::general_parsebuf(streambuf *buf, int delete_arg_buf) ! 136: : parsebuf() ! 137: { ! 138: delete_buf = delete_arg_buf; ! 139: sbuf = buf; ! 140: int buf_size = 128; ! 141: char* buffer = ALLOC_BUF(buf_size); ! 142: setb(buffer, buffer+buf_size, 1); ! 143: // setg(buffer, buffer, buffer); ! 144: } ! 145: ! 146: general_parsebuf::~general_parsebuf() ! 147: { ! 148: if (delete_buf) ! 149: delete sbuf; ! 150: } ! 151: ! 152: int general_parsebuf::underflow() ! 153: { ! 154: register char *ptr = base(); ! 155: int has_newline = eback() < gptr() && gptr()[-1] == '\n'; ! 156: if (has_newline) ! 157: *ptr++ = '\n'; ! 158: register streambuf *sb = sbuf; ! 159: register int ch; ! 160: for (;;) { ! 161: ch = sb->sbumpc(); ! 162: if (ch == EOF) ! 163: break; ! 164: if (ptr == ebuf()) { ! 165: int old_size = ebuf() - base(); ! 166: char *new_buffer = new char[old_size * 2]; ! 167: memcpy(new_buffer, base(), old_size); ! 168: setb(new_buffer, new_buffer + 2 * old_size, 1); ! 169: ptr = new_buffer + old_size; ! 170: } ! 171: *ptr++ = ch; ! 172: if (ch == '\n') ! 173: break; ! 174: } ! 175: char *cur_pos = base() + has_newline; ! 176: pos_at_line_start += _line_length + 1; ! 177: _line_length = ptr - cur_pos; ! 178: if (ch != EOF || _line_length > 0) ! 179: __line_number++; ! 180: setg(base(), cur_pos, ptr); ! 181: return ptr == cur_pos ? EOF : cur_pos[0]; ! 182: } ! 183: ! 184: char* general_parsebuf::current_line() ! 185: { ! 186: char* ret = base(); ! 187: if (__line_number > 1) ! 188: ret++; // Move past '\n' from end of previous line. ! 189: return ret; ! 190: } ! 191: ! 192: int general_parsebuf::tell_in_line() ! 193: { ! 194: int off = gptr() - base(); ! 195: if (__line_number > 1) ! 196: off--; // Subtract 1 for '\n' from end of previous line. ! 197: return off; ! 198: } ! 199: ! 200: int general_parsebuf::seek_in_line(int i) ! 201: { ! 202: if (__line_number == 0) ! 203: (void)general_parsebuf::underflow(); ! 204: if (__line_number > 1) ! 205: i++; // Add 1 for '\n' from end of previous line. ! 206: if (i < 0) i = 0; ! 207: int len = egptr() - eback(); ! 208: if (i > len) i = len; ! 209: setg(base(), base() + i, egptr()); ! 210: return i; ! 211: } ! 212: ! 213: func_parsebuf::func_parsebuf(CharReader func, void *argm) : parsebuf() ! 214: { ! 215: read_func = func; ! 216: arg = argm; ! 217: buf_start = NULL; ! 218: buf_end = NULL; ! 219: setb((char*)NewLine, (char*)NewLine+1, 0); ! 220: setg((char*)NewLine, (char*)NewLine+1, (char*)NewLine+1); ! 221: backed_up_to_newline = 0; ! 222: } ! 223: ! 224: int func_parsebuf::tell_in_line() ! 225: { ! 226: if (buf_start == NULL) ! 227: return 0; ! 228: if (egptr() != (char*)NewLine+1) ! 229: // Get buffer was line buffer. ! 230: return gptr() - buf_start; ! 231: if (backed_up_to_newline) ! 232: return -1; // Get buffer is '\n' preceding current line. ! 233: // Get buffer is '\n' following current line. ! 234: return (buf_end - buf_start) + (gptr() - (char*)NewLine); ! 235: } ! 236: ! 237: char* func_parsebuf::current_line() ! 238: { ! 239: return buf_start; ! 240: } ! 241: ! 242: int func_parsebuf::seek_in_line(int i) ! 243: { ! 244: if (i < 0) { ! 245: // Back up to preceding '\n'. ! 246: if (i < -1) i = -1; ! 247: backed_up_to_newline = 1; ! 248: setg((char*)NewLine, (char*)NewLine+(i+1), (char*)NewLine+1); ! 249: return i; ! 250: } ! 251: backed_up_to_newline = 0; ! 252: int line_length = buf_end-buf_start; ! 253: if (i <= line_length) { ! 254: setg(buf_start, buf_start+i, buf_end); ! 255: return i; ! 256: } ! 257: i -= line_length; ! 258: if (i > 0) i = 1; ! 259: setg((char*)NewLine, (char*)NewLine+i, (char*)NewLine+1); ! 260: return line_length + i; ! 261: } ! 262: ! 263: int func_parsebuf::underflow() ! 264: { ! 265: retry: ! 266: if (gptr() < egptr()) ! 267: return *gptr(); ! 268: if (gptr() != (char*)NewLine+1) { ! 269: // Get buffer was line buffer. Move to following '\n'. ! 270: setg((char*)NewLine, (char*)NewLine, (char*)NewLine+1); ! 271: return *gptr(); ! 272: } ! 273: if (backed_up_to_newline) ! 274: // Get buffer was '\n' preceding current line. Move to current line. ! 275: backed_up_to_newline = 0; ! 276: else { ! 277: // Get buffer was '\n' following current line. Read new line. ! 278: if (buf_start) free(buf_start); ! 279: char *str = (*read_func)(arg); ! 280: buf_start = str; ! 281: if (str == NULL) ! 282: return EOF; ! 283: // Initially, _line_length == -1, so pos_at_line_start becomes 0. ! 284: pos_at_line_start += _line_length + 1; ! 285: _line_length = strlen(str); ! 286: buf_end = str + _line_length; ! 287: __line_number++; ! 288: } ! 289: setg(buf_start, buf_start, buf_end); ! 290: goto retry; ! 291: } ! 292: ! 293: #if 0 ! 294: size_t parsebuf::line_length() ! 295: { ! 296: if (current_line_length == (size_t)(-1)) // Initial value; ! 297: (void)sgetc(); ! 298: return current_line_length; ! 299: } ! 300: #endif ! 301: ! 302: int parsebuf::seek_in_line(int i) ! 303: { ! 304: #if 1 ! 305: abort(); ! 306: return 0; // Suppress warning. ! 307: #else ! 308: if (i > 0) { ! 309: size_t len = line_length(); ! 310: if ((unsigned)i > len) i = len; ! 311: } ! 312: else if (i < -1) i = -1; ! 313: int new_pos = seekoff(pos_at_line_start + i, ios::beg); ! 314: if (new_pos == EOF) ! 315: return tell_in_line(); ! 316: else return new_pos - pos_at_line_start; ! 317: #endif ! 318: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.