summaryrefslogtreecommitdiff
path: root/vcs-svn/line_buffer.c
diff options
context:
space:
mode:
authorDavid Barr <david.barr@cordelta.com>2010-08-09 22:39:43 (GMT)
committerJunio C Hamano <gitster@pobox.com>2010-08-15 02:35:37 (GMT)
commit3bbaec00a8ffc6ea7e71c3b707851fe663d93a45 (patch)
tree5af41401b9e6764754058d4305a0d212190828b9 /vcs-svn/line_buffer.c
parent1d73b52f5ba4184de6acf474f14668001304a10c (diff)
downloadgit-3bbaec00a8ffc6ea7e71c3b707851fe663d93a45.zip
git-3bbaec00a8ffc6ea7e71c3b707851fe663d93a45.tar.gz
git-3bbaec00a8ffc6ea7e71c3b707851fe663d93a45.tar.bz2
Add stream helper library
This library provides thread-unsafe fgets()- and fread()-like functions where the caller does not have to supply a buffer. It maintains a couple of static buffers and provides an API to use them. [rr: allow input from files other than stdin] [jn: with tests, documentation, and error handling improvements] Signed-off-by: David Barr <david.barr@cordelta.com> Signed-off-by: Ramkumar Ramachandra <artagnon@gmail.com> Signed-off-by: Jonathan Nieder <jrnieder@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
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();
+}