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 | ||
cb3f87cf JN |
20 | int buffer_fdinit(struct line_buffer *buf, int fd) |
21 | { | |
22 | buf->infile = fdopen(fd, "r"); | |
23 | if (!buf->infile) | |
24 | return -1; | |
25 | return 0; | |
26 | } | |
27 | ||
b1c9b798 JN |
28 | int buffer_tmpfile_init(struct line_buffer *buf) |
29 | { | |
30 | buf->infile = tmpfile(); | |
31 | if (!buf->infile) | |
32 | return -1; | |
33 | return 0; | |
34 | } | |
35 | ||
e5e45ca1 | 36 | int buffer_deinit(struct line_buffer *buf) |
3bbaec00 DB |
37 | { |
38 | int err; | |
d350822f JN |
39 | if (buf->infile == stdin) |
40 | return ferror(buf->infile); | |
41 | err = ferror(buf->infile); | |
42 | err |= fclose(buf->infile); | |
3bbaec00 DB |
43 | return err; |
44 | } | |
45 | ||
b1c9b798 JN |
46 | FILE *buffer_tmpfile_rewind(struct line_buffer *buf) |
47 | { | |
48 | rewind(buf->infile); | |
49 | return buf->infile; | |
50 | } | |
51 | ||
52 | long buffer_tmpfile_prepare_to_read(struct line_buffer *buf) | |
53 | { | |
54 | long pos = ftell(buf->infile); | |
55 | if (pos < 0) | |
1c8ead97 | 56 | return error_errno("ftell error"); |
b1c9b798 | 57 | if (fseek(buf->infile, 0, SEEK_SET)) |
1c8ead97 | 58 | return error_errno("seek error"); |
b1c9b798 JN |
59 | return pos; |
60 | } | |
61 | ||
efc749b4 JN |
62 | int buffer_ferror(struct line_buffer *buf) |
63 | { | |
64 | return ferror(buf->infile); | |
65 | } | |
66 | ||
cc193f1f JN |
67 | int buffer_read_char(struct line_buffer *buf) |
68 | { | |
69 | return fgetc(buf->infile); | |
70 | } | |
71 | ||
3bbaec00 | 72 | /* Read a line without trailing newline. */ |
e5e45ca1 | 73 | char *buffer_read_line(struct line_buffer *buf) |
3bbaec00 DB |
74 | { |
75 | char *end; | |
d350822f | 76 | if (!fgets(buf->line_buffer, sizeof(buf->line_buffer), buf->infile)) |
3bbaec00 DB |
77 | /* Error or data exhausted. */ |
78 | return NULL; | |
d350822f | 79 | end = buf->line_buffer + strlen(buf->line_buffer); |
3bbaec00 DB |
80 | if (end[-1] == '\n') |
81 | end[-1] = '\0'; | |
d350822f | 82 | else if (feof(buf->infile)) |
3bbaec00 DB |
83 | ; /* No newline at end of file. That's fine. */ |
84 | else | |
85 | /* | |
86 | * Line was too long. | |
87 | * There is probably a saner way to deal with this, | |
88 | * but for now let's return an error. | |
89 | */ | |
90 | return NULL; | |
d350822f | 91 | return buf->line_buffer; |
3bbaec00 DB |
92 | } |
93 | ||
896e4bfc JN |
94 | size_t buffer_read_binary(struct line_buffer *buf, |
95 | struct strbuf *sb, size_t size) | |
e832f43c | 96 | { |
896e4bfc | 97 | return strbuf_fread(sb, size, buf->infile); |
e832f43c JN |
98 | } |
99 | ||
26557fc1 | 100 | off_t buffer_copy_bytes(struct line_buffer *buf, off_t nbytes) |
3bbaec00 | 101 | { |
4d21bec0 | 102 | char byte_buffer[COPY_BUFFER_LEN]; |
26557fc1 JN |
103 | off_t done = 0; |
104 | while (done < nbytes && !feof(buf->infile) && !ferror(buf->infile)) { | |
105 | off_t len = nbytes - done; | |
106 | size_t in = len < COPY_BUFFER_LEN ? len : COPY_BUFFER_LEN; | |
d350822f | 107 | in = fread(byte_buffer, 1, in, buf->infile); |
26557fc1 | 108 | done += in; |
3bbaec00 | 109 | fwrite(byte_buffer, 1, in, stdout); |
26557fc1 JN |
110 | if (ferror(stdout)) |
111 | return done + buffer_skip_bytes(buf, nbytes - done); | |
3bbaec00 | 112 | } |
26557fc1 | 113 | return done; |
3bbaec00 DB |
114 | } |
115 | ||
d234f54b | 116 | off_t buffer_skip_bytes(struct line_buffer *buf, off_t nbytes) |
3bbaec00 | 117 | { |
4d21bec0 | 118 | char byte_buffer[COPY_BUFFER_LEN]; |
d234f54b JN |
119 | off_t done = 0; |
120 | while (done < nbytes && !feof(buf->infile) && !ferror(buf->infile)) { | |
121 | off_t len = nbytes - done; | |
122 | size_t in = len < COPY_BUFFER_LEN ? len : COPY_BUFFER_LEN; | |
123 | done += fread(byte_buffer, 1, in, buf->infile); | |
3bbaec00 | 124 | } |
d234f54b | 125 | return done; |
3bbaec00 | 126 | } |