📄 parsestream.c
字号:
// This is part of the iostream library, providing input/output for C++.// Copyright (C) 1991 Per Bothner.//// This library is free software; you can redistribute it and/or// modify it under the terms of the GNU Library General Public// License as published by the Free Software Foundation; either// version 2 of the License, or (at your option) any later version.//// This library is distributed in the hope that it will be useful,// but WITHOUT ANY WARRANTY; without even the implied warranty of// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU// Library General Public License for more details.//// You should have received a copy of the GNU Library General Public// License along with this library; if not, write to the Free// Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.#ifdef __GNUG__#pragma implementation#endif#include "ioprivate.h"#include "parsestream.h"streambuf* parsebuf::setbuf(char*, int){ return NULL;}int parsebuf::tell_in_line(){ return 0;}int parsebuf::pbackfail(int c){ if (c == EOF) return 0; if (seekoff(-1, ios::cur) == EOF) return EOF; return (unsigned char)c;}char* parsebuf::current_line() { return NULL; }streampos parsebuf::seekoff(streamoff offset, _seek_dir dir, int){ // Make offset relative to line start. switch (dir) { case ios::beg: offset -= pos_at_line_start; break; case ios::cur: offset += tell_in_line(); break; default: return EOF; } if (offset < -1) return EOF; if (offset > _line_length + 1) return EOF; return seek_in_line(offset) + pos_at_line_start;}// string_parsebuf invariants:// The reserve ares (base() .. ebuf()) is always the entire string.// The get area (eback() .. egptr()) is the extended current line// (i.e. with the '\n' at either end, if these exist).string_parsebuf::string_parsebuf(char *buf, int len, int delete_at_close /* = 0*/): parsebuf(){ setb(buf, buf+len, delete_at_close); register char *ptr = buf; while (ptr < ebuf() && *ptr != '\n') ptr++; _line_length = ptr - buf; setg(buf, buf, ptr);}int string_parsebuf::underflow(){ register char* ptr = egptr(); // Point to end of current_line do { int i = right() - ptr; if (i <= 0) return EOF; ptr++; i--; // Skip '\n'. char *line_start = ptr; while (ptr < right() && *ptr == '\n') ptr++; setg(line_start-1, line_start, ptr + (ptr < right())); pos_at_line_start = line_start - left(); _line_length = ptr - line_start; __line_number++; } while (gptr() == ptr); return *gptr();}char* string_parsebuf::current_line(){ char *ptr = eback(); if (__line_number > 0) ptr++; // Skip '\n' at end of previous line. return ptr;}int string_parsebuf::tell_in_line(){ int offset = gptr() - eback(); if (__line_number > 0) offset--; return offset;}int string_parsebuf::seek_in_line(int i){ int delta = i - tell_in_line(); gbump(delta); // FIXME: Needs error (bounds) checking! return i;}static const char NewLine[1] = { '\n' };general_parsebuf::general_parsebuf(streambuf *buf, int delete_arg_buf) : parsebuf(){ delete_buf = delete_arg_buf; sbuf = buf; int buf_size = 128; char* buffer = ALLOC_BUF(buf_size); setb(buffer, buffer+buf_size, 1);// setg(buffer, buffer, buffer);}general_parsebuf::~general_parsebuf(){ if (delete_buf) delete sbuf;}int general_parsebuf::underflow(){ register char *ptr = base(); int has_newline = eback() < gptr() && gptr()[-1] == '\n'; if (has_newline) *ptr++ = '\n'; register streambuf *sb = sbuf; register int ch; for (;;) { ch = sb->sbumpc(); if (ch == EOF) break; if (ptr == ebuf()) { int old_size = ebuf() - base(); char *new_buffer = new char[old_size * 2]; memcpy(new_buffer, base(), old_size); setb(new_buffer, new_buffer + 2 * old_size, 1); ptr = new_buffer + old_size; } *ptr++ = ch; if (ch == '\n') break; } char *cur_pos = base() + has_newline; pos_at_line_start += _line_length + 1; _line_length = ptr - cur_pos; if (ch != EOF || _line_length > 0) __line_number++; setg(base(), cur_pos, ptr); return ptr == cur_pos ? EOF : cur_pos[0];}char* general_parsebuf::current_line(){ char* ret = base(); if (__line_number > 1) ret++; // Move past '\n' from end of previous line. return ret;}int general_parsebuf::tell_in_line(){ int off = gptr() - base(); if (__line_number > 1) off--; // Subtract 1 for '\n' from end of previous line. return off;}int general_parsebuf::seek_in_line(int i){ if (__line_number == 0) (void)general_parsebuf::underflow(); if (__line_number > 1) i++; // Add 1 for '\n' from end of previous line. if (i < 0) i = 0; int len = egptr() - eback(); if (i > len) i = len; setg(base(), base() + i, egptr()); return i;}func_parsebuf::func_parsebuf(CharReader func, void *argm) : parsebuf(){ read_func = func; arg = argm; buf_start = NULL; buf_end = NULL; setb((char*)NewLine, (char*)NewLine+1, 0); setg((char*)NewLine, (char*)NewLine+1, (char*)NewLine+1); backed_up_to_newline = 0;}int func_parsebuf::tell_in_line(){ if (buf_start == NULL) return 0; if (egptr() != (char*)NewLine+1) // Get buffer was line buffer. return gptr() - buf_start; if (backed_up_to_newline) return -1; // Get buffer is '\n' preceding current line. // Get buffer is '\n' following current line. return (buf_end - buf_start) + (gptr() - (char*)NewLine);}char* func_parsebuf::current_line(){ return buf_start;}int func_parsebuf::seek_in_line(int i){ if (i < 0) { // Back up to preceding '\n'. if (i < -1) i = -1; backed_up_to_newline = 1; setg((char*)NewLine, (char*)NewLine+(i+1), (char*)NewLine+1); return i; } backed_up_to_newline = 0; int line_length = buf_end-buf_start; if (i <= line_length) { setg(buf_start, buf_start+i, buf_end); return i; } i -= line_length; if (i > 0) i = 1; setg((char*)NewLine, (char*)NewLine+i, (char*)NewLine+1); return line_length + i;}int func_parsebuf::underflow(){ retry: if (gptr() < egptr()) return *gptr(); if (gptr() != (char*)NewLine+1) { // Get buffer was line buffer. Move to following '\n'. setg((char*)NewLine, (char*)NewLine, (char*)NewLine+1); return *gptr(); } if (backed_up_to_newline) // Get buffer was '\n' preceding current line. Move to current line. backed_up_to_newline = 0; else { // Get buffer was '\n' following current line. Read new line. if (buf_start) free(buf_start); char *str = (*read_func)(arg); buf_start = str; if (str == NULL) return EOF; // Initially, _line_length == -1, so pos_at_line_start becomes 0. pos_at_line_start += _line_length + 1; _line_length = strlen(str); buf_end = str + _line_length; __line_number++; } setg(buf_start, buf_start, buf_end); goto retry;}#if 0size_t parsebuf::line_length(){ if (current_line_length == (size_t)(-1)) // Initial value; (void)sgetc(); return current_line_length;}#endifint parsebuf::seek_in_line(int i){#if 1 abort(); return 0; // Suppress warning.#else if (i > 0) { size_t len = line_length(); if ((unsigned)i > len) i = len; } else if (i < -1) i = -1; int new_pos = seekoff(pos_at_line_start + i, ios::beg); if (new_pos == EOF) return tell_in_line(); else return new_pos - pos_at_line_start;#endif}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -