summaryrefslogtreecommitdiff
path: root/vcs-svn/line_buffer.c
diff options
context:
space:
mode:
Diffstat (limited to 'vcs-svn/line_buffer.c')
-rw-r--r--vcs-svn/line_buffer.c97
1 files changed, 97 insertions, 0 deletions
diff --git a/vcs-svn/line_buffer.c b/vcs-svn/line_buffer.c
new file mode 100644
index 0000000..1543567
--- /dev/null
+++ b/vcs-svn/line_buffer.c
@@ -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();
+}