while (want > 0) { have = fp->_IO_read_end - fp->_IO_read_ptr; //enough data for request->copy all the data to user if (want <= have) { memcpy (s, fp->_IO_read_ptr, want); fp->_IO_read_ptr += want; want = 0; } else { //not enough,read the remainder first if (have > 0) { memcpy (s, fp->_IO_read_ptr, have); s += have; want -= have; fp->_IO_read_ptr += have; } /* If we now want less than a buffer, underflow and repeat the copy. Otherwise, _IO_SYSREAD directly to the user buffer. */ if (fp->_IO_buf_base && want < (size_t) (fp->_IO_buf_end - fp->_IO_buf_base)) { if (__underflow (fp) == EOF) break; continue; }
/* These must be set before the sysread as we might longjmp out waiting for input. */ _IO_setg (fp, fp->_IO_buf_base, fp->_IO_buf_base, fp->_IO_buf_base); _IO_setp (fp, fp->_IO_buf_base, fp->_IO_buf_base);
/* Try to maintain alignment: read a whole number of blocks. */ count = want; if (fp->_IO_buf_base) { _IO_size_t block_size = fp->_IO_buf_end - fp->_IO_buf_base; if (block_size >= 128) count -= want % block_size; }
_IO_size_t _IO_new_file_xsputn (_IO_FILE *f, constvoid *data, _IO_size_t n) { constchar *s = (constchar *) data; _IO_size_t to_do = n; int must_flush = 0; _IO_size_t count = 0; //if there is no needbuf or is putting now->out put the line if ((f->_flags & _IO_LINE_BUF) && (f->_flags & _IO_CURRENTLY_PUTTING)) { count = f->_IO_buf_end - f->_IO_write_ptr; if (count >= n) { constchar *p; for (p = s + n; p > s; ) { if (*--p == '\n') { count = p - s + 1; must_flush = 1; break; } } } } //count means how many empty buf we have and then we will fill it elseif (f->_IO_write_end > f->_IO_write_ptr) count = f->_IO_write_end - f->_IO_write_ptr;
//fill the buffer if (count > 0) { if (count > to_do) count = to_do; memcpy (f->_IO_write_ptr, s, count); f->_IO_write_ptr += count; s += count; to_do -= count; } //if we fill the whole space but we need more output if (to_do + must_flush > 0) { _IO_size_t block_size, do_write; //call overflow to output the buffer now if (_IO_OVERFLOW (f, EOF) == EOF)//end of the file return to_do == 0 ? EOF : n - to_do;
//try to output one by one block block_size = f->_IO_buf_end - f->_IO_buf_base; do_write = to_do - (block_size >= 128 ? to_do % block_size : 0); //output the whole blocks if (do_write) { count = new_do_write (f, s, do_write); to_do -= count; if (count < do_write) return n - to_do; }
/* Now write out the remainder. Normally, this will fit in the buffer, but it's somewhat messier for line-buffered files, so we let _IO_default_xsputn handle the general case. */ if (to_do) to_do -= _IO_default_xsputn (f, s+do_write, to_do); } return n - to_do; }
_IO_size_t _IO_default_xsputn (_IO_FILE *f, constvoid *data, _IO_size_t n) { constchar *s = (char *) data; _IO_size_t more = n; for (;;) { if (f->_IO_write_ptr < f->_IO_write_end) { //get the free space of write buf _IO_size_t count = f->_IO_write_end - f->_IO_write_ptr; if (count > more) count = more; //first way to copy if (count > 20) { memcpy (f->_IO_write_ptr, s, count); f->_IO_write_ptr += count; s += count; } //second way to copy elseif (count) { char *p = f->_IO_write_ptr; _IO_ssize_t i; for (i = count; --i >= 0; ) *p++ = *s++; f->_IO_write_ptr = p; } //finish copy more -= count; } //call syswrite until all the needs are done of file end if (more == 0 || _IO_OVERFLOW (f, (unsignedchar) *s++) == EOF) break; more--; } return n - more; }
_IO_doallocate:申请缓冲区并设置buf与read指针
1 2 3 4 5 6 7 8 9
int _IO_file_doallocate (_IO_FILE *fp) { size = _IO_BUFSIZ;//8192 bytes //some options dealing with size…… p = malloc (size); //set buf base and end _IO_setb (fp, p, p + size, 1); return1; }
int _IO_new_file_overflow (_IO_FILE *f, int ch) { // If currently reading or no buffer allocated. if ((f->_flags & _IO_CURRENTLY_PUTTING) == 0 || f->_IO_write_base == NULL) { //condition1:need a buffer if (f->_IO_write_base == NULL) { //alloc the buffer and set buf base/buf end _IO_doallocbuf (f); _IO_setg (f, f->_IO_buf_base, f->_IO_buf_base, f->_IO_buf_base); } //if read has done,put the read ptr at the buf begin if (f->_IO_read_ptr == f->_IO_buf_end) f->_IO_read_end = f->_IO_read_ptr = f->_IO_buf_base; //the rest of buffer are used to write f->_IO_write_ptr = f->_IO_read_ptr; f->_IO_write_base = f->_IO_write_ptr; f->_IO_write_end = f->_IO_buf_end; f->_IO_read_base = f->_IO_read_ptr = f->_IO_read_end;
f->_flags |= _IO_CURRENTLY_PUTTING; if (f->_mode <= 0 && f->_flags & (_IO_LINE_BUF | _IO_UNBUFFERED)) f->_IO_write_end = f->_IO_write_ptr; } //if the last char is EOF if (ch == EOF) return _IO_do_write (f, f->_IO_write_base,f->_IO_write_ptr - f->_IO_write_base); //buffer is full if (f->_IO_write_ptr == f->_IO_buf_end ) if (_IO_do_flush (f) == EOF) return EOF; *f->_IO_write_ptr++ = ch; if ((f->_flags & _IO_UNBUFFERED) || ((f->_flags & _IO_LINE_BUF) && ch == '\n')) if (_IO_do_write (f, f->_IO_write_base, f->_IO_write_ptr - f->_IO_write_base) == EOF) return EOF; return (unsignedchar) ch; }