vcs-svn: add binary-safe read function
authorJonathan Nieder <jrnieder@gmail.com>
Mon, 3 Jan 2011 03:05:46 +0000 (21:05 -0600)
committerJonathan Nieder <jrnieder@gmail.com>
Sat, 26 Feb 2011 10:59:37 +0000 (04:59 -0600)
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>
t/t0081-line-buffer.sh
test-line-buffer.c
vcs-svn/line_buffer.c
vcs-svn/line_buffer.h

index 33a728ed98edba5c963be666472824e9f493842e..a8eeb206457be723ac35c35e557f45967650dc89 100755 (executable)
@@ -151,6 +151,15 @@ test_expect_success 'skip, copy null byte' '
        test_cmp expect actual
 '
 
+test_expect_success 'read null byte' '
+       echo ">QhelloQ" | q_to_nul >expect &&
+       q_to_nul <<-\EOF | test-line-buffer >actual &&
+       binary 8
+       QhelloQ
+       EOF
+       test_cmp expect actual
+'
+
 test_expect_success 'long reads are truncated' '
        echo foo >expect &&
        test-line-buffer <<-\EOF >actual &&
@@ -171,4 +180,13 @@ test_expect_success 'long copies are truncated' '
        test_cmp expect actual
 '
 
+test_expect_success 'long binary reads are truncated' '
+       echo ">foo" >expect &&
+       test-line-buffer <<-\EOF >actual &&
+       binary 5
+       foo
+       EOF
+       test_cmp expect actual
+'
+
 test_done
index ec19b13ee23d0de5a2423941655452627d3d00cc..19bf2d4403d03498b5c246367e59265535d2f90c 100644 (file)
@@ -3,6 +3,7 @@
  */
 
 #include "git-compat-util.h"
+#include "strbuf.h"
 #include "vcs-svn/line_buffer.h"
 
 static uint32_t strtouint32(const char *s)
@@ -17,6 +18,15 @@ static uint32_t strtouint32(const char *s)
 static void handle_command(const char *command, const char *arg, struct line_buffer *buf)
 {
        switch (*command) {
+       case 'b':
+               if (!prefixcmp(command, "binary ")) {
+                       struct strbuf sb = STRBUF_INIT;
+                       strbuf_addch(&sb, '>');
+                       buffer_read_binary(buf, &sb, strtouint32(arg));
+                       fwrite(sb.buf, 1, sb.len, stdout);
+                       strbuf_release(&sb);
+                       return;
+               }
        case 'c':
                if (!prefixcmp(command, "copy ")) {
                        buffer_copy_bytes(buf, strtouint32(arg));
index 806932b32187bece9076131c69e8f80ae0c3a58a..661b007092247add3d7d5121345a999b8af53f7b 100644 (file)
@@ -56,6 +56,12 @@ char *buffer_read_string(struct line_buffer *buf, uint32_t len)
        return ferror(buf->infile) ? NULL : buf->blob_buffer.buf;
 }
 
+void buffer_read_binary(struct line_buffer *buf,
+                               struct strbuf *sb, uint32_t size)
+{
+       strbuf_fread(sb, size, buf->infile);
+}
+
 void buffer_copy_bytes(struct line_buffer *buf, uint32_t len)
 {
        char byte_buffer[COPY_BUFFER_LEN];
index fb373903d20318da44ddc784842c56521b41e141..0c2d3d955a7d5ee3b6562ae44bbfededd603c478 100644 (file)
@@ -16,6 +16,7 @@ int buffer_init(struct line_buffer *buf, const char *filename);
 int buffer_deinit(struct line_buffer *buf);
 char *buffer_read_line(struct line_buffer *buf);
 char *buffer_read_string(struct line_buffer *buf, uint32_t len);
+void buffer_read_binary(struct line_buffer *buf, struct strbuf *sb, uint32_t len);
 void buffer_copy_bytes(struct line_buffer *buf, uint32_t len);
 void buffer_skip_bytes(struct line_buffer *buf, uint32_t len);
 void buffer_reset(struct line_buffer *buf);