vcs-svn: add binary-safe read function
buffer_read_string works well for non line-oriented input except for one problem: it does not tell the caller how many bytes were actually written. This means that unless one is very careful about checking for errors (and eof) the calling program cannot tell the difference between the string "foo" followed by an early end of file and the string "foo\0bar\0baz". So introduce a variant that reports the length, too, a thinner wrapper around strbuf_fread. Its result is written to a strbuf so the caller does not need to keep track of the number of bytes read. Signed-off-by: Jonathan Nieder <jrnieder@gmail.com>
Jonathan Nieder committed
Jan 2, 2011 at 21:05 UTC
e832f43c1d26bf70611d98b62d95870a99292add
4 files changed
+35
t/t0081-line-buffer.sh
+18
@@ -151,6 +151,15 @@ test_expect_success 'skip, copy null byte' '
151
test_cmp expect actual
152
'
153
154
+test_expect_success 'read null byte' '
155
+ echo ">QhelloQ" | q_to_nul >expect &&
156
+ q_to_nul <<-\EOF | test-line-buffer >actual &&
157
+ binary 8
158
+ QhelloQ
159
+ EOF
160
+ test_cmp expect actual
161
+'
162
+
163
test_expect_success 'long reads are truncated' '
164
echo foo >expect &&
165
test-line-buffer <<-\EOF >actual &&
@@ -171,4 +180,13 @@ test_expect_success 'long copies are truncated' '
180
test_cmp expect actual
181
'
182
183
+test_expect_success 'long binary reads are truncated' '
184
+ echo ">foo" >expect &&
185
+ test-line-buffer <<-\EOF >actual &&
186
+ binary 5
187
+ foo
188
+ EOF
189
+ test_cmp expect actual
190
+'
191
+
192
test_done
test-line-buffer.c
+10
@@ -3,6 +3,7 @@
3
*/
4
5
#include "git-compat-util.h"
6
+#include "strbuf.h"
7
#include "vcs-svn/line_buffer.h"
8
9
static uint32_t strtouint32(const char *s)
@@ -17,6 +18,15 @@ static uint32_t strtouint32(const char *s)
18
static void handle_command(const char *command, const char *arg, struct line_buffer *buf)
19
{
20
switch (*command) {
21
+ case 'b':
22
+ if (!prefixcmp(command, "binary ")) {
23
+ struct strbuf sb = STRBUF_INIT;
24
+ strbuf_addch(&sb, '>');
25
+ buffer_read_binary(buf, &sb, strtouint32(arg));
26
+ fwrite(sb.buf, 1, sb.len, stdout);
27
+ strbuf_release(&sb);
28
+ return;
29
+ }
30
case 'c':
31
if (!prefixcmp(command, "copy ")) {
32
buffer_copy_bytes(buf, strtouint32(arg));
vcs-svn/line_buffer.c
+6
@@ -56,6 +56,12 @@ char *buffer_read_string(struct line_buffer *buf, uint32_t len)
56
return ferror(buf->infile) ? NULL : buf->blob_buffer.buf;
57
}
58
59
+void buffer_read_binary(struct line_buffer *buf,
60
+ struct strbuf *sb, uint32_t size)
61
+{
62
+ strbuf_fread(sb, size, buf->infile);
63
+}
64
+
65
void buffer_copy_bytes(struct line_buffer *buf, uint32_t len)
66
{
67
char byte_buffer[COPY_BUFFER_LEN];
vcs-svn/line_buffer.h
+1
@@ -16,6 +16,7 @@ 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_read_binary(struct line_buffer *buf, struct strbuf *sb, uint32_t len);
20
void buffer_copy_bytes(struct line_buffer *buf, uint32_t len);
21
void buffer_skip_bytes(struct line_buffer *buf, uint32_t len);
22
void buffer_reset(struct line_buffer *buf);