2 * Licensed under a two-clause BSD-style license.
3 * See LICENSE for details.
6 #include "git-compat-util.h"
7 #include "sliding_window.h"
8 #include "line_buffer.h"
11 static void strbuf_remove_from_left(struct strbuf
*sb
, size_t nbytes
)
13 assert(nbytes
<= sb
->len
);
14 memmove(sb
->buf
, sb
->buf
+ nbytes
, sb
->len
- nbytes
);
15 strbuf_setlen(sb
, sb
->len
- nbytes
);
18 static int check_overflow(off_t a
, size_t b
)
21 return error("Unrepresentable length: "
22 "%"PRIu64
" > OFF_MAX", (uint64_t) b
);
23 if (signed_add_overflows(a
, (off_t
) b
))
24 return error("Unrepresentable offset: "
25 "%"PRIu64
" + %"PRIu64
" > OFF_MAX",
26 (uint64_t) a
, (uint64_t) b
);
30 int move_window(struct view
*view
, off_t off
, size_t len
)
33 assert(view
&& view
->file
);
34 assert(!check_overflow(view
->off
, view
->buf
.len
));
36 if (check_overflow(off
, len
))
38 if (off
< view
->off
|| off
+ len
< view
->off
+ view
->buf
.len
)
39 return error("Invalid delta: window slides left");
41 file_offset
= view
->off
+ view
->buf
.len
;
42 if (off
< file_offset
)
43 /* Move the overlapping region into place. */
44 strbuf_remove_from_left(&view
->buf
, off
- view
->off
);
46 strbuf_setlen(&view
->buf
, 0);
47 if (off
> file_offset
) {
48 /* Seek ahead to skip the gap. */
49 const off_t gap
= off
- file_offset
;
50 const off_t nread
= buffer_skip_bytes(view
->file
, gap
);
52 if (!buffer_ferror(view
->file
)) /* View ends early. */
54 return error("Cannot seek forward in input: %s",
59 buffer_read_binary(&view
->buf
, len
- view
->buf
.len
, view
->file
);
60 if (buffer_ferror(view
->file
))
61 return error("Cannot read preimage: %s", strerror(errno
));