Code

Add stream helper library
[git.git] / vcs-svn / line_buffer.c
diff --git a/vcs-svn/line_buffer.c b/vcs-svn/line_buffer.c
new file mode 100644 (file)
index 0000000..1543567
--- /dev/null
@@ -0,0 +1,97 @@
+/*
+ * Licensed under a two-clause BSD-style license.
+ * See LICENSE for details.
+ */
+
+#include "git-compat-util.h"
+#include "line_buffer.h"
+#include "obj_pool.h"
+
+#define LINE_BUFFER_LEN 10000
+#define COPY_BUFFER_LEN 4096
+
+/* Create memory pool for char sequence of known length */
+obj_pool_gen(blob, char, 4096)
+
+static char line_buffer[LINE_BUFFER_LEN];
+static char byte_buffer[COPY_BUFFER_LEN];
+static FILE *infile;
+
+int buffer_init(const char *filename)
+{
+       infile = filename ? fopen(filename, "r") : stdin;
+       if (!infile)
+               return -1;
+       return 0;
+}
+
+int buffer_deinit(void)
+{
+       int err;
+       if (infile == stdin)
+               return ferror(infile);
+       err = ferror(infile);
+       err |= fclose(infile);
+       return err;
+}
+
+/* Read a line without trailing newline. */
+char *buffer_read_line(void)
+{
+       char *end;
+       if (!fgets(line_buffer, sizeof(line_buffer), infile))
+               /* Error or data exhausted. */
+               return NULL;
+       end = line_buffer + strlen(line_buffer);
+       if (end[-1] == '\n')
+               end[-1] = '\0';
+       else if (feof(infile))
+               ; /* No newline at end of file.  That's fine. */
+       else
+               /*
+                * Line was too long.
+                * There is probably a saner way to deal with this,
+                * but for now let's return an error.
+                */
+               return NULL;
+       return line_buffer;
+}
+
+char *buffer_read_string(uint32_t len)
+{
+       char *s;
+       blob_free(blob_pool.size);
+       s = blob_pointer(blob_alloc(len + 1));
+       s[fread(s, 1, len, infile)] = '\0';
+       return ferror(infile) ? NULL : s;
+}
+
+void buffer_copy_bytes(uint32_t len)
+{
+       uint32_t in;
+       while (len > 0 && !feof(infile) && !ferror(infile)) {
+               in = len < COPY_BUFFER_LEN ? len : COPY_BUFFER_LEN;
+               in = fread(byte_buffer, 1, in, infile);
+               len -= in;
+               fwrite(byte_buffer, 1, in, stdout);
+               if (ferror(stdout)) {
+                       buffer_skip_bytes(len);
+                       return;
+               }
+       }
+}
+
+void buffer_skip_bytes(uint32_t len)
+{
+       uint32_t in;
+       while (len > 0 && !feof(infile) && !ferror(infile)) {
+               in = len < COPY_BUFFER_LEN ? len : COPY_BUFFER_LEN;
+               in = fread(byte_buffer, 1, in, infile);
+               len -= in;
+       }
+}
+
+void buffer_reset(void)
+{
+       blob_reset();
+}