@matheusbsbs / matheus-bagliano / commits / e5e45ca1e3
Fork 0

vcs-svn: teach line_buffer to handle multiple input files

Collect the line_buffer state in a newly public line_buffer struct. Callers can use multiple line_buffers to manage input from multiple files at a time. svn-fe's delta applier will use this to stream a delta from svnrdump and the preimage it applies to from fast-import at the same time. The tests don't take advantage of the new features, but I think that's okay. It is easier to find lingering examples of nonreentrant code by searching for "static" in line_buffer.c. Signed-off-by: Jonathan Nieder <jrnieder@gmail.com>

Jonathan Nieder committed Oct 10, 2010 at 21:41 UTC e5e45ca1e35482d120a7ce776cf208369edcc459
7 files changed +50 -46
test-line-buffer.c
+9 -8
@@ -22,25 +22,26 @@ static uint32_t strtouint32(const char *s)
22
23 int main(int argc, char *argv[])
24 {
25 + struct line_buffer buf = LINE_BUFFER_INIT;
26 char *s;
27
28 if (argc != 1)
29 usage("test-line-buffer < input.txt");
29 - if (buffer_init(NULL))
30 + if (buffer_init(&buf, NULL))
31 die_errno("open error");
31 - while ((s = buffer_read_line())) {
32 - s = buffer_read_string(strtouint32(s));
32 + while ((s = buffer_read_line(&buf))) {
33 + s = buffer_read_string(&buf, strtouint32(s));
34 fputs(s, stdout);
35 fputc('\n', stdout);
35 - buffer_skip_bytes(1);
36 - if (!(s = buffer_read_line()))
36 + buffer_skip_bytes(&buf, 1);
37 + if (!(s = buffer_read_line(&buf)))
38 break;
38 - buffer_copy_bytes(strtouint32(s) + 1);
39 + buffer_copy_bytes(&buf, strtouint32(s) + 1);
40 }
40 - if (buffer_deinit())
41 + if (buffer_deinit(&buf))
42 die("input error");
43 if (ferror(stdout))
44 die("output error");
44 - buffer_reset();
45 + buffer_reset(&buf);
46 return 0;
47 }
vcs-svn/fast_export.c
+3 -3
@@ -63,14 +63,14 @@ void fast_export_commit(uint32_t revision, uint32_t author, char *log,
63 printf("progress Imported commit %"PRIu32".\n\n", revision);
64 }
65
66 -void fast_export_blob(uint32_t mode, uint32_t mark, uint32_t len)
66 +void fast_export_blob(uint32_t mode, uint32_t mark, uint32_t len, struct line_buffer *input)
67 {
68 if (mode == REPO_MODE_LNK) {
69 /* svn symlink blobs start with "link " */
70 - buffer_skip_bytes(5);
70 + buffer_skip_bytes(input, 5);
71 len -= 5;
72 }
73 printf("blob\nmark :%"PRIu32"\ndata %"PRIu32"\n", mark, len);
74 - buffer_copy_bytes(len);
74 + buffer_copy_bytes(input, len);
75 fputc('\n', stdout);
76 }
vcs-svn/fast_export.h
+4 -1
@@ -1,11 +1,14 @@
1 #ifndef FAST_EXPORT_H_
2 #define FAST_EXPORT_H_
3
4 +#include "line_buffer.h"
5 +
6 void fast_export_delete(uint32_t depth, uint32_t *path);
7 void fast_export_modify(uint32_t depth, uint32_t *path, uint32_t mode,
8 uint32_t mark);
9 void fast_export_commit(uint32_t revision, uint32_t author, char *log,
10 uint32_t uuid, uint32_t url, unsigned long timestamp);
9 -void fast_export_blob(uint32_t mode, uint32_t mark, uint32_t len);
11 +void fast_export_blob(uint32_t mode, uint32_t mark, uint32_t len,
12 + struct line_buffer *input);
13
14 #endif
vcs-svn/line_buffer.c
+8 -12
@@ -8,20 +8,16 @@
8 #include "strbuf.h"
9
10 #define COPY_BUFFER_LEN 4096
11 -static struct line_buffer buf_ = LINE_BUFFER_INIT;
12 -static struct line_buffer *buf;
11
14 -int buffer_init(const char *filename)
12 +int buffer_init(struct line_buffer *buf, const char *filename)
13 {
16 - buf = &buf_;
17 -
14 buf->infile = filename ? fopen(filename, "r") : stdin;
15 if (!buf->infile)
16 return -1;
17 return 0;
18 }
19
24 -int buffer_deinit(void)
20 +int buffer_deinit(struct line_buffer *buf)
21 {
22 int err;
23 if (buf->infile == stdin)
@@ -32,7 +28,7 @@ int buffer_deinit(void)
28 }
29
30 /* Read a line without trailing newline. */
35 -char *buffer_read_line(void)
31 +char *buffer_read_line(struct line_buffer *buf)
32 {
33 char *end;
34 if (!fgets(buf->line_buffer, sizeof(buf->line_buffer), buf->infile))
@@ -53,14 +49,14 @@ char *buffer_read_line(void)
49 return buf->line_buffer;
50 }
51
56 -char *buffer_read_string(uint32_t len)
52 +char *buffer_read_string(struct line_buffer *buf, uint32_t len)
53 {
54 strbuf_reset(&buf->blob_buffer);
55 strbuf_fread(&buf->blob_buffer, len, buf->infile);
56 return ferror(buf->infile) ? NULL : buf->blob_buffer.buf;
57 }
58
63 -void buffer_copy_bytes(uint32_t len)
59 +void buffer_copy_bytes(struct line_buffer *buf, uint32_t len)
60 {
61 char byte_buffer[COPY_BUFFER_LEN];
62 uint32_t in;
@@ -70,13 +66,13 @@ void buffer_copy_bytes(uint32_t len)
66 len -= in;
67 fwrite(byte_buffer, 1, in, stdout);
68 if (ferror(stdout)) {
73 - buffer_skip_bytes(len);
69 + buffer_skip_bytes(buf, len);
70 return;
71 }
72 }
73 }
74
79 -void buffer_skip_bytes(uint32_t len)
75 +void buffer_skip_bytes(struct line_buffer *buf, uint32_t len)
76 {
77 char byte_buffer[COPY_BUFFER_LEN];
78 uint32_t in;
@@ -87,7 +83,7 @@ void buffer_skip_bytes(uint32_t len)
83 }
84 }
85
90 -void buffer_reset(void)
86 +void buffer_reset(struct line_buffer *buf)
87 {
88 strbuf_release(&buf->blob_buffer);
89 }
vcs-svn/line_buffer.h
+7 -7
@@ -12,12 +12,12 @@ struct line_buffer {
12 };
13 #define LINE_BUFFER_INIT {"", STRBUF_INIT, NULL}
14
15 -int buffer_init(const char *filename);
16 -int buffer_deinit(void);
17 -char *buffer_read_line(void);
18 -char *buffer_read_string(uint32_t len);
19 -void buffer_copy_bytes(uint32_t len);
20 -void buffer_skip_bytes(uint32_t len);
21 -void buffer_reset(void);
15 +int buffer_init(struct line_buffer *buf, const char *filename);
16 +int buffer_deinit(struct line_buffer *buf);
17 +char *buffer_read_line(struct line_buffer *buf);
18 +char *buffer_read_string(struct line_buffer *buf, uint32_t len);
19 +void buffer_copy_bytes(struct line_buffer *buf, uint32_t len);
20 +void buffer_skip_bytes(struct line_buffer *buf, uint32_t len);
21 +void buffer_reset(struct line_buffer *buf);
22
23 #endif
vcs-svn/line_buffer.txt
+3 -2
@@ -14,14 +14,15 @@ Calling sequence
14
15 The calling program:
16
17 + - initializes a `struct line_buffer` to LINE_BUFFER_INIT
18 - specifies a file to read with `buffer_init`
19 - processes input with `buffer_read_line`, `buffer_read_string`,
20 `buffer_skip_bytes`, and `buffer_copy_bytes`
21 - closes the file with `buffer_deinit`, perhaps to start over and
22 read another file.
23
23 -Before exiting, the caller can use `buffer_reset` to deallocate
24 -resources for the benefit of profiling tools.
24 +When finished, the caller can use `buffer_reset` to deallocate
25 +resources.
26
27 Functions
28 ---------
vcs-svn/svndump.c
+16 -13
@@ -30,6 +30,8 @@
30 /* Create memory pool for log messages */
31 obj_pool_gen(log, char, 4096)
32
33 +static struct line_buffer input = LINE_BUFFER_INIT;
34 +
35 static char* log_copy(uint32_t length, char *log)
36 {
37 char *buffer;
@@ -115,14 +117,14 @@ static void read_props(void)
117 uint32_t key = ~0;
118 char *val = NULL;
119 char *t;
118 - while ((t = buffer_read_line()) && strcmp(t, "PROPS-END")) {
120 + while ((t = buffer_read_line(&input)) && strcmp(t, "PROPS-END")) {
121 if (!strncmp(t, "K ", 2)) {
122 len = atoi(&t[2]);
121 - key = pool_intern(buffer_read_string(len));
122 - buffer_read_line();
123 + key = pool_intern(buffer_read_string(&input, len));
124 + buffer_read_line(&input);
125 } else if (!strncmp(t, "V ", 2)) {
126 len = atoi(&t[2]);
125 - val = buffer_read_string(len);
127 + val = buffer_read_string(&input, len);
128 if (key == keys.svn_log) {
129 /* Value length excludes terminating nul. */
130 rev_ctx.log = log_copy(len + 1, val);
@@ -137,7 +139,7 @@ static void read_props(void)
139 node_ctx.type = REPO_MODE_LNK;
140 }
141 key = ~0;
140 - buffer_read_line();
142 + buffer_read_line(&input);
143 }
144 }
145 }
@@ -179,9 +181,10 @@ static void handle_node(void)
181 node_ctx.type = node_ctx.srcMode;
182
183 if (node_ctx.mark)
182 - fast_export_blob(node_ctx.type, node_ctx.mark, node_ctx.textLength);
184 + fast_export_blob(node_ctx.type,
185 + node_ctx.mark, node_ctx.textLength, &input);
186 else if (node_ctx.textLength != LENGTH_UNKNOWN)
184 - buffer_skip_bytes(node_ctx.textLength);
187 + buffer_skip_bytes(&input, node_ctx.textLength);
188 }
189
190 static void handle_revision(void)
@@ -200,7 +203,7 @@ void svndump_read(const char *url)
203 uint32_t key;
204
205 reset_dump_ctx(pool_intern(url));
203 - while ((t = buffer_read_line())) {
206 + while ((t = buffer_read_line(&input))) {
207 val = strstr(t, ": ");
208 if (!val)
209 continue;
@@ -257,7 +260,7 @@ void svndump_read(const char *url)
260 node_ctx.propLength = atoi(val);
261 } else if (key == keys.content_length) {
262 len = atoi(val);
260 - buffer_read_line();
263 + buffer_read_line(&input);
264 if (active_ctx == REV_CTX) {
265 read_props();
266 } else if (active_ctx == NODE_CTX) {
@@ -265,7 +268,7 @@ void svndump_read(const char *url)
268 active_ctx = REV_CTX;
269 } else {
270 fprintf(stderr, "Unexpected content length header: %"PRIu32"\n", len);
268 - buffer_skip_bytes(len);
271 + buffer_skip_bytes(&input, len);
272 }
273 }
274 }
@@ -277,7 +280,7 @@ void svndump_read(const char *url)
280
281 void svndump_init(const char *filename)
282 {
280 - buffer_init(filename);
283 + buffer_init(&input, filename);
284 repo_init();
285 reset_dump_ctx(~0);
286 reset_rev_ctx(0);
@@ -292,7 +295,7 @@ void svndump_deinit(void)
295 reset_dump_ctx(~0);
296 reset_rev_ctx(0);
297 reset_node_ctx(NULL);
295 - if (buffer_deinit())
298 + if (buffer_deinit(&input))
299 fprintf(stderr, "Input error\n");
300 if (ferror(stdout))
301 fprintf(stderr, "Output error\n");
@@ -301,7 +304,7 @@ void svndump_deinit(void)
304 void svndump_reset(void)
305 {
306 log_reset();
304 - buffer_reset();
307 + buffer_reset(&input);
308 repo_reset();
309 reset_dump_ctx(~0);
310 reset_rev_ctx(0);