char *BufferProtocol::gather(size_t size) { if(!input || size > bufsize) return NULL; if(size + bufpos > insize) { if(end) return NULL; size_t adjust = outsize - bufpos; memmove(input, input + bufpos, adjust); insize = adjust + _pull(input, bufsize - adjust); bufpos = 0; if(insize < bufsize) end = true; } if(size + bufpos <= insize) { char *bp = input + bufpos; bufpos += size; return bp; } return NULL; }
int BufferProtocol::_getch(void) { if(!input) return EOF; if(back) { back = 0; return back; } if(bufpos == insize) { if(end) return EOF; insize = _pull(input, bufsize); bufpos = 0; if(insize == 0) end = true; else if(insize < bufsize && !_blocking()) end = true; if(!insize) return EOF; } return input[bufpos++]; }
size_t BufferProtocol::get(void *address, size_t size) { size_t count = 0; if(!input || !address || !size) return 0; char *cp = (char *)address; while(count < size) { if(bufpos == insize) { if(end) return count; insize = _pull(input, bufsize); bufpos = 0; if(insize == 0) end = true; else if(insize < bufsize && !_blocking()) end = true; if(!insize) return count; } cp[count++] = input[bufpos++]; } return count; }
size_t rbs_read(void *ptr, size_t size, size_t nmemb, rbstream_p rbsp) { medvdbg("[%s] ptr %p nmemb %lu\n", __FUNCTION__, ptr, nmemb); RETURN_VAL_IF_FAIL(ptr != NULL, SIZE_ZERO); RETURN_VAL_IF_FAIL(rbsp != NULL, SIZE_ZERO); // only size:1 supported assert(size == 1); size_t len = size * nmemb; size_t read = SIZE_ZERO; while (read < len) { void *_ptr = (void *) ((uint8_t *) ptr + read); size_t need = len - read; size_t offset = rbsp->cur_pos - rbsp->rd_size; // read data desired size_t rlen = rb_read_ext(rbsp->rbp, _ptr, need, offset); read += rlen; rbsp->cur_pos += rlen; // increase cur_pos if (read < len) { // need to read more data size_t least = len - read; size_t avail = rb_avail(rbsp->rbp); if (least > avail) { // need to dequeue data if (RBS_OPTION_TEST(rbsp, OPTION_ALLOW_TO_DEQUEUE)) { offset = rbsp->cur_pos - rbsp->rd_size; size_t _len = MINIMUM(offset, (least - avail)); size_t _rlen = rb_read(rbsp->rbp, NULL, _len); assert(_rlen == _len); rbsp->rd_size += _rlen; } } // pull stream data, then it's available to read more. if (_pull(rb_avail(rbsp->rbp), least, rbsp) == SIZE_ZERO) { // pull data failed break; } } } medvdbg("[%s] done, read %lu\n", __FUNCTION__, read); return read; }
int rbs_seek(rbstream_p rbsp, ssize_t offset, int whence) { medvdbg("[%s] offset %ld, whence %d\n", __FUNCTION__, offset, whence); RETURN_VAL_IF_FAIL(rbsp != NULL, ERROR); switch (whence) { case SEEK_SET: // checking underflow RETURN_VAL_IF_FAIL(((size_t) offset >= rbsp->rd_size), ERROR); while ((size_t) offset > rbsp->wr_size) { size_t least = (size_t) offset - rbsp->wr_size; size_t wlen; // pull stream data, then wr_size will be increased wlen = _pull(rb_avail(rbsp->rbp), least, rbsp); if ((size_t) offset > rbsp->wr_size) { // not enough if (rb_avail(rbsp->rbp) == SIZE_ZERO) { // ring-buffer is full RETURN_VAL_IF_FAIL((RBS_OPTION_TEST(rbsp, OPTION_ALLOW_TO_DEQUEUE)), ERROR); // overflow // dequeue minimal data from ring-buffer size_t len = rbsp->wr_size - rbsp->rd_size; least = (size_t) offset - rbsp->wr_size; len = MINIMUM(len, least); size_t rlen = rb_read(rbsp->rbp, NULL, len); assert(rlen == len); rbsp->rd_size += rlen; } else { RETURN_VAL_IF_FAIL((wlen != SIZE_ZERO), ERROR); // EOS } // request more data continue; } // got enough data break; } rbsp->cur_pos = (size_t) offset; break; } return OK; }