/* Append data to the front of the buffer */ static int buffer_read_from(struct buffer *buf, int fd) { int bytes_read, total_bytes_read = 0; unsigned nbytes; /* Empty list needs initialized */ if(!buf->head) { buf->head = buffer_node_new(buf); buf->tail = buf->head; } do { nbytes = buf->node_size - buf->tail->end; bytes_read = read(fd, buf->tail->data + buf->tail->end, nbytes); if(bytes_read < 1) { if(errno != EAGAIN) rb_sys_fail("read"); return total_bytes_read; } total_bytes_read += bytes_read; buf->tail->end += nbytes; buf->size += nbytes; if(buf->tail->end == buf->node_size) { buf->tail->next = buffer_node_new(buf); buf->tail = buf->tail->next; } } while(bytes_read == nbytes); return total_bytes_read; }
/* Append data to the front of the buffer */ static void buffer_append(struct buffer *buf, char *str, unsigned len) { unsigned nbytes; buf->size += len; /* If it fits in the remaining space in the tail */ if(buf->tail && len <= buf->node_size - buf->tail->end) { memcpy(buf->tail->data + buf->tail->end, str, len); buf->tail->end += len; return; } /* Empty list needs initialized */ if(!buf->head) { buf->head = buffer_node_new(buf); buf->tail = buf->head; } /* Build links out of the data */ while(len > 0) { nbytes = buf->node_size - buf->tail->end; if(len < nbytes) nbytes = len; memcpy(buf->tail->data + buf->tail->end, str, nbytes); str += nbytes; len -= nbytes; buf->tail->end += nbytes; if(len > 0) { buf->tail->next = buffer_node_new(buf); buf->tail = buf->tail->next; } } }
/* Prepend data to the front of the buffer */ static void buffer_prepend(struct buffer *buf, char *str, unsigned len) { struct buffer_node *node, *tmp; buf->size += len; /* If it fits in the beginning of the head */ if(buf->head && buf->head->start >= len) { buf->head->start -= len; memcpy(buf->head->data + buf->head->start, str, len); } else { node = buffer_node_new(buf); node->next = buf->head; buf->head = node; if(!buf->tail) buf->tail = node; while(len > buf->node_size) { memcpy(node->data, str, buf->node_size); node->end = buf->node_size; tmp = buffer_node_new(buf); tmp->next = node->next; node->next = tmp; if(buf->tail == node) buf->tail = tmp; node = tmp; str += buf->node_size; len -= buf->node_size; } if(len > 0) { memcpy(node->data, str, len); node->end = len; } } }
static inline void buffer_push(struct buffer *b, char *data, int size) { if (b->offset == DATA_SIZE) { _again: b->cur = b->cur->next = buffer_node_new(); b->offset = 0; } if (b->offset <= DATA_SIZE - size) { memcpy(b->cur->data+b->offset, data, size); b->offset += size; b->size += size; } else { int _size = DATA_SIZE-b->offset; memcpy(b->cur->data+b->offset, data, _size); data += _size; b->size += _size; size -= _size; goto _again; } }