/* * fread — читает nmemb элементов по size байт из потока в ptr * (буферизованно, вариант B+). * * Порядок: hold-байт → хвост буфера (memcpy) → большой остаток * (>= BUFSIZ) одним read() напрямую в ptr мимо буфера → мелкий * остаток через дозаполнение буфера. Возвращает число ПОЛНЫХ * элементов; короткое чтение ставит _F_EOF, ошибка — _F_ERROR. * Консольный поток — посимвольно через getchar(). */ #include #include #include #include "_file.h" size_t fread(void *ptr, size_t size, size_t nmemb, FILE *fp) { #ifndef LIBC_NOCHECK if (!ptr || !fp) return 0; #endif if (size == 0 || nmemb == 0) return 0; uint8_t *p = (uint8_t *)ptr; uint16_t total = size * nmemb; uint16_t got = 0; uint16_t n; int r; if (fp->hold != EOF) { *p++ = (uint8_t)fp->hold; fp->hold = EOF; got = 1; } if (fp->flags & _F_CONIN) { while (got < total) { int c = getchar(); if (c == EOF) break; *p++ = (uint8_t)c; got++; } goto done; } #ifndef LIBC_NOCHECK if (!(fp->flags & _F_READ)) { errno = EBADF; return 0; } #endif if (fp->flags & _F_DIROUT) { if (_file_sync(fp)) return 0; /* сброс накопленной записи */ } /* 1) хвост readahead-буфера */ if (fp->level) { n = total - got; if (n > fp->level) n = fp->level; memcpy(p, fp->curp, n); fp->curp += n; fp->level -= n; p += n; got += n; } n = total - got; if (n == 0) goto done; if (n >= BUFSIZ || !_file_buf(fp)) { /* 2а) большой остаток (или нет буфера) — напрямую мимо буфера */ r = read(fp->fd, p, n); } else { /* 2б) мелкий остаток — дозаполнить буфер и скопировать */ r = read(fp->fd, fp->buf, BUFSIZ); if (r >= 0) { fp->level = (uint16_t)r; fp->curp = fp->buf; if ((uint16_t)r < n) n = (uint16_t)r; memcpy(p, fp->curp, n); fp->curp += n; fp->level -= n; r = (int)n; } } if (r < 0) { fp->flags |= _F_ERROR; goto done; } got += (uint16_t)r; if (got < total) fp->flags |= _F_EOF; done: return size == 1 ? got : got / size; }