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

📄 filebuf.c

📁 早期freebsd实现
💻 C
📖 第 1 页 / 共 2 页
字号:
    _G_ssize_t count = sys_write(data, to_do);    if (_cur_column)	_cur_column = __adjust_column(_cur_column - 1, data, to_do) + 1;    if (count != to_do)	return EOF;    setg(base(), base(), base());    if (xflags() & _S_LINE_BUF+_S_UNBUFFERED) setp(base(), base());    else setp(base(), ebuf());    return 0;}int filebuf::sync(){//    char* ptr = cur_ptr();    if (pptr() > pbase())	if (do_flush()) return EOF;    if (gptr() != egptr()) {	streampos delta = gptr() - egptr();	if (in_backup())	    delta -= eGptr() - Gbase();	if (sys_seek(delta, ios::cur) == EOF)	    return EOF;    }    // FIXME: Cleanup - can this be shared?//    setg(base(), ptr, ptr);    return 0;}streampos filebuf::seekoff(streamoff offset, _seek_dir dir, int mode){    streampos result, new_offset, delta;    _G_ssize_t count;    if (mode == 0) // Don't move any pointers.	dir = ios::cur, offset = 0;    // Flush unwritten characters.    // (This may do an unneeded write if we seek within the buffer.    // But to be able to switch to reading, we would need to set    // egptr to ptr.  That can't be done in the current design,    // which assumes file_ptr() is eGptr.  Anyway, since we probably    // end up flushing when we close(), it doesn't make much difference.)    if (pptr() > pbase() || put_mode())	if (switch_to_get_mode()) return EOF;    if (base() == NULL) {	doallocbuf();	setp(base(), base());	setg(base(), base(), base());    }    switch (dir) {      case ios::cur:	if (_fb._offset < 0) {	    _fb._offset = sys_seek(0, ios::cur);	    if (_fb._offset < 0)		return EOF;	}	// Make offset absolute, assuming current pointer is file_ptr().	offset += _fb._offset;	offset -= _egptr - _gptr;	if (in_backup())	    offset -= _other_egptr - _other_gbase;	dir = ios::beg;	break;      case ios::beg:	break;      case ios::end:	struct stat st;	if (sys_stat(&st) == 0 && S_ISREG(st.st_mode)) {	    offset += st.st_size;	    dir = ios::beg;	}	else	    goto dumb;    }    // At this point, dir==ios::beg.    // If destination is within current buffer, optimize:    if (_fb._offset >= 0 && _eback != NULL) {	// Offset relative to start of main get area.	fpos_t rel_offset = offset - _fb._offset	    + (eGptr()-Gbase());	if (rel_offset >= 0) {	    if (in_backup())		switch_to_main_get_area();	    if (rel_offset <= _egptr - _eback) {		setg(base(), base() + rel_offset, egptr());		setp(base(), base());		return offset;	    }	    // If we have streammarkers, seek forward by reading ahead.	    if (have_markers()) {		int to_skip = rel_offset - (_gptr - _eback);		if (ignore(to_skip) != to_skip)		    goto dumb;		return offset;	    }	}	if (rel_offset < 0 && rel_offset >= Bbase() - Bptr()) {	    if (!in_backup())		switch_to_backup_area();	    gbump(_egptr + rel_offset - gptr());	    return offset;	}    }    unsave_markers();    // Try to seek to a block boundary, to improve kernel page management.    new_offset = offset & ~(ebuf() - base() - 1);    delta = offset - new_offset;    if (delta > ebuf() - base()) {	new_offset = offset;	delta = 0;    }    result = sys_seek(new_offset, ios::beg);    if (result < 0)	return EOF;    if (delta == 0)	count = 0;    else {	count = sys_read(base(), ebuf()-base());	if (count < delta) {	    // We weren't allowed to read, but try to seek the remainder.	    offset = count == EOF ? delta : delta-count;	    dir = ios::cur;	    goto dumb;	}    }    setg(base(), base()+delta, base()+count);    setp(base(), base());    _fb._offset = result + count;    xflags(xflags() & ~ _S_EOF_SEEN);    return offset;  dumb:    unsave_markers();    result = sys_seek(offset, dir);    if (result != EOF) {	xflags(xflags() & ~_S_EOF_SEEN);    }    _fb._offset = result;    setg(base(), base(), base());    setp(base(), base());    return result;}filebuf* filebuf::close(){    if (!is_open())	return NULL;    // This flushes as well as switching mode.    if (pptr() > pbase() || put_mode())	if (switch_to_get_mode()) return NULL;    unsave_markers();    int status = sys_close();    // Free buffer.    setb(NULL, NULL, 0);    setg(NULL, NULL, NULL);    setp(NULL, NULL);    _un_link();    _flags = _IO_MAGIC|CLOSED_FILEBUF_FLAGS;    _fb._fileno = EOF;    _fb._offset = 0;    return status < 0 ? NULL : this;}_G_ssize_t filebuf::sys_read(char* buf, size_t size){    for (;;) {	_G_ssize_t count = ::read(_fb._fileno, buf, size);	if (count != -1 || errno != EINTR)	    return count;    }}fpos_t filebuf::sys_seek(fpos_t offset, _seek_dir dir){    return ::lseek(fd(), offset, (int)dir);}_G_ssize_t filebuf::sys_write(const void *buf, long n){    long to_do = n;    while (to_do > 0) {	_G_ssize_t count = ::write(fd(), buf, to_do);	if (count == EOF) {	    if (errno == EINTR)		continue;	    else {		_flags |= _S_ERR_SEEN;		break;	    }	}	to_do -= count;	buf = (void*)((char*)buf + count);    }    n -= to_do;    if (_fb._offset >= 0)	_fb._offset += n;    return n;}int filebuf::sys_stat(void* st){    return ::_fstat(fd(), (struct stat*)st);}int filebuf::sys_close(){    return ::close(fd());}int filebuf::xsputn(const char *s, int n){    if (n <= 0)	return 0;    // This is an optimized implementation.    // If the amount to be written straddles a block boundary    // (or the filebuf is unbuffered), use sys_write directly.    int to_do = n;    int must_flush = 0;    // First figure out how much space is available in the buffer.    int count = _epptr - _pptr; // Space available.    if (linebuffered() && (_flags & _S_CURRENTLY_PUTTING)) {	count =_ebuf - _pptr;	if (count >= n) {	    for (register const char *p = s + n; p > s; ) {		if (*--p == '\n') {		    count = p - s + 1;		    must_flush = 1;		    break;		}	    }	}    }    // Then fill the buffer.    if (count > 0) {	if (count > to_do)	    count = to_do;	if (count > 20) {	    memcpy(pptr(), s, count);	    s += count;	}	else {	    register char *p = pptr();;	    for (register int i = count; --i >= 0; ) *p++ = *s++;	}	pbump(count);	to_do -= count;    }    if (to_do + must_flush > 0) {	// Next flush the (full) buffer.	if (__overflow(this, EOF) == EOF)	    return n - to_do;	// Try to maintain alignment: write a whole number of blocks.	// dont_write is what gets left over.	int block_size = _ebuf - _base;	int dont_write = block_size >= 128 ? to_do % block_size : 0;	_G_ssize_t count = to_do - dont_write;	if (do_write(s, count) == EOF)	    return n - to_do;	to_do = dont_write;	// Now write out the remainder.  Normally, this will fit in the	// buffer, but it's somewhat messier for line-buffered files,	// so we let streambuf::sputn handle the general case.	if (dont_write)	    to_do -= streambuf::sputn(s+count, dont_write);    }    return n - to_do;}int filebuf::xsgetn(char *s, int n){    // FIXME: OPTIMIZE THIS (specifically, when unbuffered()).    return streambuf::xsgetn(s, n);}// Non-ANSI AT&T-ism:  Default open protection.const int filebuf::openprot = 0644;

⌨️ 快捷键说明

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