-
Notifications
You must be signed in to change notification settings - Fork 0
/
lines.c
113 lines (101 loc) · 2.37 KB
/
lines.c
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
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
/* lines.c */
/* Part of hhttppss, a simple HTTP server skeleton
* Author: Berke Durak
* Released in the public domain
*/
/*
* Converts a byte stream to a string stream
* strings being delimited by CR LF pairs
*/
#include <string.h>
#include "memory.h"
#include "lines.h"
#include "params.h"
/*(*** lines_create */
lines *lines_create(void (*eater)(void *data, char *p, int m), void *data)
{
lines *ls;
ls = xmalloc(sizeof(lines));
ls->ls_size = PARAM_AVERAGE_LINE_LENGTH;
ls->ls_buffer = xmalloc(ls->ls_size);
ls->ls_length = 0;
ls->ls_line_eater = eater;
ls->ls_state = LINES_INIT;
ls->ls_data = data;
ls->ls_limit = PARAM_REASONABLE_LINE_LIMIT;
return ls;
}
/***)*/
/*(*** lines_delete */
void lines_delete(lines *ls)
{
xfree(ls->ls_buffer);
xfree(ls);
}
/***)*/
/*(*** lines_add_char */
static inline void lines_add_char(lines *ls, char c)
{
if(ls->ls_length >= ls->ls_size) {
/* We need to grow the buffer... */
ls->ls_size <<= 1;
ls->ls_buffer = xrealloc(ls->ls_buffer, ls->ls_size);
}
ls->ls_buffer[ls->ls_length ++] = c;
}
/***)*/
/*(*** lines_add_bytes */
void lines_add_bytes(lines *ls, char *p, int m)
{
int i;
for(i = 0; i < m; i ++) {
char c;
c = p[i];
if(ls->ls_limit && ls->ls_length > ls->ls_limit) goto eat;
switch(ls->ls_state) {
case LINES_INIT:
switch(c) {
case '\r':
ls->ls_state = LINES_CR;
break;
default:
lines_add_char(ls, c);
break;
}
break;
case LINES_CR:
switch(c) {
case '\n':
/* That's it, we've got a CR LF. */
eat:
if(ls->ls_line_eater) {
ls->ls_line_eater(ls->ls_data, ls->ls_buffer, ls->ls_length);
}
ls->ls_state = LINES_INIT;
ls->ls_length = 0;
break;
case '\r':
ls->ls_state = LINES_CR;
break;
default:
/* Was expecting a LF. Assume it is a standard character. */
lines_add_char(ls, '\r');
lines_add_char(ls, c);
ls->ls_state = LINES_INIT;
break;
}
break;
}
}
}
/***)*/
/*(*** lines_contents */
char *lines_contents(lines *ls)
{
char *p;
p = xmalloc(ls->ls_length + 1);
memcpy(p, ls->ls_buffer, ls->ls_length);
p[ls->ls_length] = 0;
return p;
}
/***)*/