vcs-svn: Extend svndump to parse version 3 format
[svn-fe.git] / line_buffer.c
blob882894bea5a3ed981cdff2c3aa9d76343f27f67b
1 /*
2 * Licensed under a two-clause BSD-style license.
3 * See LICENSE for details.
4 */
6 #include <stdio.h>
7 #include <stdlib.h>
8 #include <string.h>
10 #include "line_buffer.h"
11 #include "strbuf.h"
13 #define COPY_BUFFER_LEN 4096
15 int buffer_init(struct line_buffer *buf, const char *filename)
17 buf->infile = filename ? fopen(filename, "r") : stdin;
18 if (!buf->infile)
19 return -1;
20 return 0;
23 int buffer_deinit(struct line_buffer *buf)
25 int err;
26 if (buf->infile == stdin)
27 return ferror(buf->infile);
28 err = ferror(buf->infile);
29 err |= fclose(buf->infile);
30 return err;
33 int buffer_ferror(struct line_buffer *buf)
35 return ferror(buf->infile);
38 int buffer_at_eof(struct line_buffer *buf)
40 int ch;
41 if ((ch = fgetc(buf->infile)) == EOF)
42 return 1;
43 if (ungetc(ch, buf->infile) == EOF)
44 return error("cannot unget %c: %s\n", ch, strerror(errno));
45 return 0;
48 int buffer_read_char(struct line_buffer *buf)
50 return fgetc(buf->infile);
53 /* Read a line without trailing newline. */
54 char *buffer_read_line(struct line_buffer *buf)
56 char *end;
57 if (!fgets(buf->line_buffer, sizeof(buf->line_buffer), buf->infile))
58 /* Error or data exhausted. */
59 return NULL;
60 end = buf->line_buffer + strlen(buf->line_buffer);
61 if (end[-1] == '\n')
62 end[-1] = '\0';
63 else if (feof(buf->infile))
64 ; /* No newline at end of file. That's fine. */
65 else
67 * Line was too long.
68 * There is probably a saner way to deal with this,
69 * but for now let's return an error.
71 return NULL;
72 return buf->line_buffer;
75 char *buffer_read_string(struct line_buffer *buf, uint32_t len)
77 strbuf_reset(&buf->blob_buffer);
78 strbuf_fread(&buf->blob_buffer, len, buf->infile);
79 return ferror(buf->infile) ? NULL : buf->blob_buffer.buf;
82 void buffer_read_binary(struct strbuf *sb, uint32_t size,
83 struct line_buffer *buf)
85 strbuf_fread(sb, size, buf->infile);
88 void buffer_copy_bytes(struct line_buffer *buf, off_t len)
90 char byte_buffer[COPY_BUFFER_LEN];
91 uint32_t in;
92 while (len > 0 && !feof(buf->infile) && !ferror(buf->infile)) {
93 in = len < COPY_BUFFER_LEN ? len : COPY_BUFFER_LEN;
94 in = fread(byte_buffer, 1, in, buf->infile);
95 len -= in;
96 fwrite(byte_buffer, 1, in, stdout);
97 if (ferror(stdout)) {
98 buffer_skip_bytes(buf, len);
99 return;
104 off_t buffer_skip_bytes(struct line_buffer *buf, off_t nbytes)
106 off_t done = 0;
107 while (done < nbytes && !feof(buf->infile) && !ferror(buf->infile)) {
108 char byte_buffer[COPY_BUFFER_LEN];
109 off_t len = nbytes - done;
110 uint32_t in = len < COPY_BUFFER_LEN ? len : COPY_BUFFER_LEN;
111 done += fread(byte_buffer, 1, in, buf->infile);
113 return done;
116 void buffer_reset(struct line_buffer *buf)
118 strbuf_release(&buf->blob_buffer);