]>
Commit | Line | Data |
---|---|---|
3bbaec00 DB |
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 | } |