1 /*
2 * Copyright (C) 2008, Google Inc.
3 * Copyright (C) 2008, Robin Rosenberg <robin.rosenberg@dewire.com> and others
4 *
5 * This program and the accompanying materials are made available under the
6 * terms of the Eclipse Distribution License v. 1.0 which is available at
7 * https://www.eclipse.org/org/documents/edl-v10.php.
8 *
9 * SPDX-License-Identifier: BSD-3-Clause
10 */
11
12 package org.eclipse.jgit.patch;
13
14 import static org.eclipse.jgit.lib.Constants.encodeASCII;
15 import static org.eclipse.jgit.util.RawParseUtils.match;
16 import static org.eclipse.jgit.util.RawParseUtils.nextLF;
17 import static org.eclipse.jgit.util.RawParseUtils.parseBase10;
18
19 /**
20 * Part of a "GIT binary patch" to describe the pre-image or post-image
21 */
22 public class BinaryHunk {
23 private static final byte[] LITERAL = encodeASCII("literal "); //$NON-NLS-1$
24
25 private static final byte[] DELTA = encodeASCII("delta "); //$NON-NLS-1$
26
27 /** Type of information stored in a binary hunk. */
28 public enum Type {
29 /** The full content is stored, deflated. */
30 LITERAL_DEFLATED,
31
32 /** A Git pack-style delta is stored, deflated. */
33 DELTA_DEFLATED;
34 }
35
36 private final FileHeader file;
37
38 /** Offset within {@link #file}.buf to the "literal" or "delta " line. */
39 final int startOffset;
40
41 /** Position 1 past the end of this hunk within {@link #file}'s buf. */
42 int endOffset;
43
44 /** Type of the data meaning. */
45 private Type type;
46
47 /** Inflated length of the data. */
48 private int length;
49
50 BinaryHunk(FileHeader fh, int offset) {
51 file = fh;
52 startOffset = offset;
53 }
54
55 /**
56 * Get header for the file this hunk applies to.
57 *
58 * @return header for the file this hunk applies to.
59 */
60 public FileHeader getFileHeader() {
61 return file;
62 }
63
64 /**
65 * Get the byte array holding this hunk's patch script.
66 *
67 * @return the byte array holding this hunk's patch script.
68 */
69 public byte[] getBuffer() {
70 return file.buf;
71 }
72
73 /**
74 * Get offset the start of this hunk in {@link #getBuffer()}.
75 *
76 * @return offset the start of this hunk in {@link #getBuffer()}.
77 */
78 public int getStartOffset() {
79 return startOffset;
80 }
81
82 /**
83 * Get offset one past the end of the hunk in {@link #getBuffer()}.
84 *
85 * @return offset one past the end of the hunk in {@link #getBuffer()}.
86 */
87 public int getEndOffset() {
88 return endOffset;
89 }
90
91 /**
92 * Get type of this binary hunk.
93 *
94 * @return type of this binary hunk.
95 */
96 public Type getType() {
97 return type;
98 }
99
100 /**
101 * Get inflated size of this hunk's data.
102 *
103 * @return inflated size of this hunk's data.
104 */
105 public int getSize() {
106 return length;
107 }
108
109 int parseHunk(int ptr, int end) {
110 final byte[] buf = file.buf;
111
112 if (match(buf, ptr, LITERAL) >= 0) {
113 type = Type.LITERAL_DEFLATED;
114 length = parseBase10(buf, ptr + LITERAL.length, null);
115
116 } else if (match(buf, ptr, DELTA) >= 0) {
117 type = Type.DELTA_DEFLATED;
118 length = parseBase10(buf, ptr + DELTA.length, null);
119
120 } else {
121 // Not a valid binary hunk. Signal to the caller that
122 // we cannot parse any further and that this line should
123 // be treated otherwise.
124 //
125 return -1;
126 }
127 ptr = nextLF(buf, ptr);
128
129 // Skip until the first blank line; that is the end of the binary
130 // encoded information in this hunk. To save time we don't do a
131 // validation of the binary data at this point.
132 //
133 while (ptr < end) {
134 final boolean empty = buf[ptr] == '\n';
135 ptr = nextLF(buf, ptr);
136 if (empty)
137 break;
138 }
139
140 return ptr;
141 }
142 }