2 * Copyright (c) 2018 Stefan Sperling <stsp@openbsd.org>
4 * Permission to use, copy, modify, and distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above
6 * copyright notice and this permission notice appear in all copies.
8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 #include <sys/queue.h>
25 #include "got_object.h"
27 #include "got_error.h"
28 #include "got_lib_delta.h"
29 #include "got_lib_inflate.h"
30 #include "got_lib_object.h"
31 #include "got_lib_diffoffset.h"
34 * A line offset between an old file and a new file, derived from diff chunk
35 * header info @@ -old_lineno,old_length +new_lineno,new_length @@ in a diff
36 * with zero context lines (as in diff -U0 old-file new-file).
38 struct got_diffoffset_chunk {
39 int lineno; /* first line which has shifted */
40 int offset; /* applies to subsequent lines until next chunk */
41 SIMPLEQ_ENTRY(got_diffoffset_chunk) entry;
44 static struct got_diffoffset_chunk *
45 alloc_chunk(int lineno, int offset)
47 struct got_diffoffset_chunk *chunk;
49 chunk = calloc(1, sizeof(*chunk));
53 chunk->lineno = lineno;
54 chunk->offset = offset;
59 const struct got_error *
60 got_diffoffset_alloc(struct got_diffoffset_chunks **chunks)
62 const struct got_error *err = NULL;
63 struct got_diffoffset_chunk *first;
65 first = alloc_chunk(0, 0);
67 return got_error_from_errno();
69 *chunks = calloc(1, sizeof(**chunks));
70 if (*chunks == NULL) {
71 err = got_error_from_errno();
76 SIMPLEQ_INIT(*chunks);
77 SIMPLEQ_INSERT_HEAD(*chunks, first, entry);
83 got_diffoffset_free(struct got_diffoffset_chunks *chunks)
85 struct got_diffoffset_chunk *chunk;
87 while (!SIMPLEQ_EMPTY(chunks)) {
88 chunk = SIMPLEQ_FIRST(chunks);
89 SIMPLEQ_REMOVE_HEAD(chunks, entry);
95 const struct got_error *
96 got_diffoffset_add(struct got_diffoffset_chunks *chunks,
97 int old_lineno, int old_length, int new_lineno, int new_length)
99 struct got_diffoffset_chunk *chunk1, *chunk2;
101 chunk1 = alloc_chunk(old_lineno, new_lineno - old_lineno);
103 return got_error_from_errno();
105 chunk2 = alloc_chunk(old_lineno + old_length,
106 new_lineno - old_lineno + new_length - old_length);
107 if (chunk2 == NULL) {
108 const struct got_error *err = got_error_from_errno();
113 SIMPLEQ_INSERT_TAIL(chunks, chunk1, entry);
114 SIMPLEQ_INSERT_TAIL(chunks, chunk2, entry);
119 got_diffoffset_get(struct got_diffoffset_chunks *chunks, int lineno)
121 struct got_diffoffset_chunk *chunk, *prev;
123 prev = SIMPLEQ_FIRST(chunks);
124 SIMPLEQ_FOREACH(chunk, chunks, entry) {
125 if (chunk->lineno > lineno)
130 return lineno + prev->offset;