-
Notifications
You must be signed in to change notification settings - Fork 2
Expand file tree
/
Copy pathbuffer.c
More file actions
92 lines (80 loc) · 2.55 KB
/
Copy pathbuffer.c
File metadata and controls
92 lines (80 loc) · 2.55 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
#define _GNU_SOURCE
#include <stdlib.h>
#include <stddef.h>
#include <string.h>
#include <unistd.h>
#include "buffer.h"
#include "list.h"
typedef struct {
int fd;
char data[BUFFER_SIZE];
char *end;
size_t shift;
} buffer_t;
static plist *buffers = NULL;
ssize_t buffer_readline(int fd, char **line) {
return buffer_readline_r(fd, line, NULL, NULL);
}
ssize_t buffer_readline_r(int fd, char **line, size_t *rsize, char **rdata ) {
buffer_t *buffer = NULL;
for (plist *item = buffers; item != NULL; item = item->tail) {
buffer_t *itemb = (buffer_t *) item->head;
if (itemb->fd == fd) {
buffer = itemb;
break;
}
}
if (buffer == NULL) {
buffer = malloc(sizeof(buffer_t));
buffer->fd = fd;
buffer->end = &buffer->data[0];
buffer->shift = 0;
buffers = plist_add(buffers, buffer);
}
char *start = buffer->end;
ssize_t bytes;
for (;;) {
size_t dsize = buffer->end - &buffer->data[buffer->shift];
char *endl = memchr(&buffer->data[buffer->shift], '\n', dsize);
if (endl != NULL) {
// A line has been found within the buffer.
*line = &buffer->data[buffer->shift];
buffer->shift += bytes = 1 + endl - &buffer->data[buffer->shift];
break;
}
if (buffer->shift) {
memmove(&buffer->data[0], &buffer->data[buffer->shift],
buffer->end - &buffer->data[buffer->shift]);
buffer->end -= buffer->shift;
start -= buffer->shift;
buffer->shift = 0;
}
size_t space = BUFFER_SIZE - (buffer->end - &buffer->data[0]);
if (space == 0) {
// The buffer is full and no newline has been found.
*line = &buffer->data[0];
buffer->shift = bytes = BUFFER_SIZE;
break;
}
// The buffer is not yet full, and no newline has been found.
bytes = read(buffer->fd, buffer->end, space);
if (bytes == -1 || bytes == 0) break;
buffer->end += bytes;
}
if (rdata != NULL) *rdata = start;
if (rsize != NULL) *rsize = buffer->end - start;
return bytes;
}
void buffer_clear(int fd) {
plist head = { NULL, buffers };
for (plist *prev = &head; prev->tail != NULL; prev = prev->tail) {
plist *node = prev->tail;
if (fd == ((buffer_t *)node->head)->fd) {
prev->tail = node->tail;
free(node->head);
free(node);
break;
}
}
buffers = head.tail;
}