Annotation of GNUtools/libg++/libio/parsestream.cc, revision 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.