]>
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" | |
deadcef4 | 8 | #include "strbuf.h" |
3bbaec00 | 9 | |
3bbaec00 | 10 | #define COPY_BUFFER_LEN 4096 |
3bbaec00 | 11 | |
e5e45ca1 | 12 | int buffer_init(struct line_buffer *buf, const char *filename) |
3bbaec00 | 13 | { |
d350822f JN |
14 | buf->infile = filename ? fopen(filename, "r") : stdin; |
15 | if (!buf->infile) | |
3bbaec00 DB |
16 | return -1; |
17 | return 0; | |
18 | } | |
19 | ||
e5e45ca1 | 20 | int buffer_deinit(struct line_buffer *buf) |
3bbaec00 DB |
21 | { |
22 | int err; | |
d350822f JN |
23 | if (buf->infile == stdin) |
24 | return ferror(buf->infile); | |
25 | err = ferror(buf->infile); | |
26 | err |= fclose(buf->infile); | |
3bbaec00 DB |
27 | return err; |
28 | } | |
29 | ||
cc193f1f JN |
30 | int buffer_read_char(struct line_buffer *buf) |
31 | { | |
32 | return fgetc(buf->infile); | |
33 | } | |
34 | ||
3bbaec00 | 35 | /* Read a line without trailing newline. */ |
e5e45ca1 | 36 | char *buffer_read_line(struct line_buffer *buf) |
3bbaec00 DB |
37 | { |
38 | char *end; | |
d350822f | 39 | if (!fgets(buf->line_buffer, sizeof(buf->line_buffer), buf->infile)) |
3bbaec00 DB |
40 | /* Error or data exhausted. */ |
41 | return NULL; | |
d350822f | 42 | end = buf->line_buffer + strlen(buf->line_buffer); |
3bbaec00 DB |
43 | if (end[-1] == '\n') |
44 | end[-1] = '\0'; | |
d350822f | 45 | else if (feof(buf->infile)) |
3bbaec00 DB |
46 | ; /* No newline at end of file. That's fine. */ |
47 | else | |
48 | /* | |
49 | * Line was too long. | |
50 | * There is probably a saner way to deal with this, | |
51 | * but for now let's return an error. | |
52 | */ | |
53 | return NULL; | |
d350822f | 54 | return buf->line_buffer; |
3bbaec00 DB |
55 | } |
56 | ||
e5e45ca1 | 57 | char *buffer_read_string(struct line_buffer *buf, uint32_t len) |
3bbaec00 | 58 | { |
d350822f JN |
59 | strbuf_reset(&buf->blob_buffer); |
60 | strbuf_fread(&buf->blob_buffer, len, buf->infile); | |
61 | return ferror(buf->infile) ? NULL : buf->blob_buffer.buf; | |
3bbaec00 DB |
62 | } |
63 | ||
e832f43c JN |
64 | void buffer_read_binary(struct line_buffer *buf, |
65 | struct strbuf *sb, uint32_t size) | |
66 | { | |
67 | strbuf_fread(sb, size, buf->infile); | |
68 | } | |
69 | ||
e5e45ca1 | 70 | void buffer_copy_bytes(struct line_buffer *buf, uint32_t len) |
3bbaec00 | 71 | { |
4d21bec0 | 72 | char byte_buffer[COPY_BUFFER_LEN]; |
3bbaec00 | 73 | uint32_t in; |
d350822f | 74 | while (len > 0 && !feof(buf->infile) && !ferror(buf->infile)) { |
3bbaec00 | 75 | in = len < COPY_BUFFER_LEN ? len : COPY_BUFFER_LEN; |
d350822f | 76 | in = fread(byte_buffer, 1, in, buf->infile); |
3bbaec00 DB |
77 | len -= in; |
78 | fwrite(byte_buffer, 1, in, stdout); | |
79 | if (ferror(stdout)) { | |
e5e45ca1 | 80 | buffer_skip_bytes(buf, len); |
3bbaec00 DB |
81 | return; |
82 | } | |
83 | } | |
84 | } | |
85 | ||
e5e45ca1 | 86 | void buffer_skip_bytes(struct line_buffer *buf, uint32_t len) |
3bbaec00 | 87 | { |
4d21bec0 | 88 | char byte_buffer[COPY_BUFFER_LEN]; |
3bbaec00 | 89 | uint32_t in; |
d350822f | 90 | while (len > 0 && !feof(buf->infile) && !ferror(buf->infile)) { |
3bbaec00 | 91 | in = len < COPY_BUFFER_LEN ? len : COPY_BUFFER_LEN; |
d350822f | 92 | in = fread(byte_buffer, 1, in, buf->infile); |
3bbaec00 DB |
93 | len -= in; |
94 | } | |
95 | } | |
96 | ||
e5e45ca1 | 97 | void buffer_reset(struct line_buffer *buf) |
3bbaec00 | 98 | { |
d350822f | 99 | strbuf_release(&buf->blob_buffer); |
3bbaec00 | 100 | } |