⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 filebuf.c

📁 早期freebsd实现
💻 C
📖 第 1 页 / 共 2 页
字号:
//    This is part of the iostream library, providing input/output for C++.//    Copyright (C) 1991, 1992 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.#include "ioprivate.h"#include <sys/types.h>#include <sys/stat.h>#include <fcntl.h>#include <errno.h>// An fstream can be in at most one of put mode, get mode, or putback mode.// Putback mode is a variant of get mode.// In a filebuf, there is only one current position, instead of two// separate get and put pointers.  In get mode, the current posistion// is that of gptr(); in put mode that of pptr().// The position in the buffer that corresponds to the position// in external file system is file_ptr().// This is normally egptr(), except in putback mode, when it is _save_egptr.// If the field _fb._offset is >= 0, it gives the offset in// the file as a whole corresponding to eGptr(). (???)// PUT MODE:// If a filebuf is in put mode, pbase() is non-NULL and equal to base().// Also, epptr() == ebuf().// Also, eback() == gptr() && gptr() == egptr().// The un-flushed character are those between pbase() and pptr().// GET MODE:// If a filebuf is in get or putback mode, eback() != egptr().// In get mode, the unread characters are between gptr() and egptr().// The OS file position corresponds to that of egptr().// PUTBACK MODE:// Putback mode is used to remember "excess" characters that have// been sputbackc'd in a separate putback buffer.// In putback mode, the get buffer points to the special putback buffer.// The unread characters are the characters between gptr() and egptr()// in the putback buffer, as well as the area between save_gptr()// and save_egptr(), which point into the original reserve buffer.// (The pointers save_gptr() and save_egptr() are the values// of gptr() and egptr() at the time putback mode was entered.)// The OS position corresponds to that of save_egptr().//// LINE BUFFERED OUTPUT:// During line buffered output, pbase()==base() && epptr()==base().// However, ptr() may be anywhere between base() and ebuf().// This forces a call to filebuf::overflow(int C) on every put.// If there is more space in the buffer, and C is not a '\n',// then C is inserted, and pptr() incremented.//// UNBUFFERED STREAMS:// If a filebuf is unbuffered(), the _shortbuf[1] is used as the buffer.#define CLOSED_FILEBUF_FLAGS \  (_S_IS_FILEBUF+_S_NO_READS+_S_NO_WRITES+_S_TIED_PUT_GET)void filebuf::init(){    _fb._offset = 0;    _link_in();    _fb._fileno = -1;}filebuf::filebuf() : backupbuf(CLOSED_FILEBUF_FLAGS){    init();}filebuf::filebuf(int fd) : backupbuf(CLOSED_FILEBUF_FLAGS){    init();    attach(fd);}filebuf::filebuf(int fd, char* p, int len) : backupbuf(CLOSED_FILEBUF_FLAGS){    init();    attach(fd);    setbuf(p, len);}filebuf::~filebuf(){    if (!(xflags() & _S_DELETE_DONT_CLOSE))	close();    _un_link();}filebuf* filebuf::open(const char *filename, ios::openmode mode, int prot){    if (is_open())	return NULL;    int posix_mode;    int read_write;    if (mode & ios::app)	mode |= ios::out;    if ((mode & (ios::in|ios::out)) == (ios::in|ios::out)) {	posix_mode = O_RDWR;	read_write = 0;    }    else if (mode & ios::out)	posix_mode = O_WRONLY, read_write = _S_NO_READS;    else if (mode & (int)ios::in)	posix_mode = O_RDONLY, read_write = _S_NO_WRITES;    else	posix_mode = 0, read_write = _S_NO_READS+_S_NO_WRITES;    if ((mode & (int)ios::trunc) || mode == (int)ios::out)	posix_mode |= O_TRUNC;    if (mode & ios::app)	posix_mode |= O_APPEND, read_write |= _S_IS_APPENDING;    if (!(mode & (int)ios::nocreate) && mode != ios::in)	posix_mode |= O_CREAT;    if (mode & (int)ios::noreplace)	posix_mode |= O_EXCL;    int fd = ::open(filename, posix_mode, prot);    if (fd < 0)	return NULL;    _fb._fileno = fd;    xsetflags(read_write, _S_NO_READS+_S_NO_WRITES+_S_IS_APPENDING);    if (mode & (ios::ate|ios::app)) {	if (seekoff(0, ios::end) == EOF)	    return NULL;    }    _link_in();    return this;}filebuf* filebuf::open(const char *filename, const char *mode){    if (is_open())	return NULL;    int oflags = 0, omode;    int read_write;    int oprot = 0666;    switch (*mode++) {      case 'r':	omode = O_RDONLY;	read_write = _S_NO_WRITES;	break;      case 'w':	omode = O_WRONLY;	oflags = O_CREAT|O_TRUNC;	read_write = _S_NO_READS;	break;      case 'a':	omode = O_WRONLY;	oflags = O_CREAT|O_APPEND;	read_write = _S_NO_READS|_S_IS_APPENDING;	break;      default:	errno = EINVAL;	return NULL;    }    if (mode[0] == '+' || (mode[0] == 'b' && mode[1] == '+')) {	omode = O_RDWR;	read_write = 0;    }    int fdesc = ::open(filename, omode|oflags, oprot);    if (fdesc < 0)	return NULL;    _fb._fileno = fdesc;    xsetflags(read_write, _S_NO_READS+_S_NO_WRITES+_S_IS_APPENDING);    if (read_write & _S_IS_APPENDING)	if (seekoff(0, ios::end) == EOF)	    return NULL;    _link_in();    return this;}filebuf* filebuf::attach(int fd){    if (is_open())	return NULL;    _fb._fileno = fd;    xsetflags(0, _S_NO_READS+_S_NO_WRITES);    return this;}streambuf* filebuf::setbuf(char* p, int len){    if (streambuf::setbuf(p, len) == NULL)	return NULL;    setp(_base, _base);    setg(_base, _base, _base);    return this;}int filebuf::overflow(int c){    if (xflags() & _S_NO_WRITES) // SET ERROR	return EOF;    // Allocate a buffer if needed.    if (base() == NULL) {	doallocbuf();	if (xflags() & _S_LINE_BUF+_S_UNBUFFERED) setp(_base, _base);	else setp(_base, _ebuf);	setg(_base, _base, _base);	_flags |= _S_CURRENTLY_PUTTING;    }    // If currently reading, switch to writing.    else if ((_flags & _S_CURRENTLY_PUTTING) == 0) {	if (xflags() & _S_LINE_BUF+_S_UNBUFFERED) setp(gptr(), gptr());	else setp(gptr(), ebuf());	setg(egptr(), egptr(), egptr());	_flags |= _S_CURRENTLY_PUTTING;    }    if (c == EOF)	return do_flush();    if (pptr() == ebuf() ) // Buffer is really full	if (do_flush() == EOF)	    return EOF;    xput_char(c);    if (unbuffered() || (linebuffered() && c == '\n'))	if (do_flush() == EOF)	    return EOF;    return (unsigned char)c;}int filebuf::underflow(){#if 0    /* SysV does not make this test; take it out for compatibility */    if (fp->_flags & __SEOF)	return (EOF);#endif    if (xflags() & _S_NO_READS)	return EOF;    if (gptr() < egptr())	return *(unsigned char*)gptr();    allocbuf();    // FIXME This can/should be moved to __streambuf ??    if ((xflags() & _S_LINE_BUF) || unbuffered()) {	// Flush all line buffered files before reading.	streambuf::flush_all_linebuffered();    }#if 1    if (pptr() > pbase())	if (do_flush()) return EOF;#endif    _G_ssize_t count = sys_read(base(), ebuf() - base());    if (count <= 0) {	if (count == 0)	    xsetflags(_S_EOF_SEEN);	else	    xsetflags(_S_ERR_SEEN), count = 0;    }    setg(base(), base(), base() + count);    setp(base(), base());    if (count == 0)	return EOF;    if (_fb._offset >= 0)	_fb._offset += count;    return *(unsigned char*)gptr();}int filebuf::do_write(const char *data, int to_do){    if (to_do == 0)	return 0;    if (xflags() & _S_IS_APPENDING) {	// On a system without a proper O_APPEND implementation,	// you would need to sys_seek(0, ios::end) here, but is	// is not needed nor desirable for Unix- or Posix-like systems.	// Instead, just indicate that offset (before and after) is	// unpredictable.	_fb._offset = -1;    }    else if (egptr() != pbase()) {	long new_pos = sys_seek(pbase()-egptr(), ios::cur);	if (new_pos == -1)	    return EOF;	_fb._offset = new_pos;    }

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -