Merge branch 'jc/maint-rev-list-culled-boundary' into maint
[git] / vcs-svn / line_buffer.c
1 /*
2  * Licensed under a two-clause BSD-style license.
3  * See LICENSE for details.
4  */
5
6 #include "git-compat-util.h"
7 #include "line_buffer.h"
8 #include "obj_pool.h"
9
10 #define LINE_BUFFER_LEN 10000
11 #define COPY_BUFFER_LEN 4096
12
13 /* Create memory pool for char sequence of known length */
14 obj_pool_gen(blob, char, 4096)
15
16 static char line_buffer[LINE_BUFFER_LEN];
17 static char byte_buffer[COPY_BUFFER_LEN];
18 static FILE *infile;
19
20 int buffer_init(const char *filename)
21 {
22         infile = filename ? fopen(filename, "r") : stdin;
23         if (!infile)
24                 return -1;
25         return 0;
26 }
27
28 int buffer_deinit(void)
29 {
30         int err;
31         if (infile == stdin)
32                 return ferror(infile);
33         err = ferror(infile);
34         err |= fclose(infile);
35         return err;
36 }
37
38 /* Read a line without trailing newline. */
39 char *buffer_read_line(void)
40 {
41         char *end;
42         if (!fgets(line_buffer, sizeof(line_buffer), infile))
43                 /* Error or data exhausted. */
44                 return NULL;
45         end = line_buffer + strlen(line_buffer);
46         if (end[-1] == '\n')
47                 end[-1] = '\0';
48         else if (feof(infile))
49                 ; /* No newline at end of file.  That's fine. */
50         else
51                 /*
52                  * Line was too long.
53                  * There is probably a saner way to deal with this,
54                  * but for now let's return an error.
55                  */
56                 return NULL;
57         return line_buffer;
58 }
59
60 char *buffer_read_string(uint32_t len)
61 {
62         char *s;
63         blob_free(blob_pool.size);
64         s = blob_pointer(blob_alloc(len + 1));
65         s[fread(s, 1, len, infile)] = '\0';
66         return ferror(infile) ? NULL : s;
67 }
68
69 void buffer_copy_bytes(uint32_t len)
70 {
71         uint32_t in;
72         while (len > 0 && !feof(infile) && !ferror(infile)) {
73                 in = len < COPY_BUFFER_LEN ? len : COPY_BUFFER_LEN;
74                 in = fread(byte_buffer, 1, in, infile);
75                 len -= in;
76                 fwrite(byte_buffer, 1, in, stdout);
77                 if (ferror(stdout)) {
78                         buffer_skip_bytes(len);
79                         return;
80                 }
81         }
82 }
83
84 void buffer_skip_bytes(uint32_t len)
85 {
86         uint32_t in;
87         while (len > 0 && !feof(infile) && !ferror(infile)) {
88                 in = len < COPY_BUFFER_LEN ? len : COPY_BUFFER_LEN;
89                 in = fread(byte_buffer, 1, in, infile);
90                 len -= in;
91         }
92 }
93
94 void buffer_reset(void)
95 {
96         blob_reset();
97 }