Annotation of GNUtools/libg++/libio/parsestream.cc, revision 1.1.1.1

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: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.