1
2
3
4
5
6
7
8
9
10
11
12 package org.eclipse.jgit.internal.storage.pack;
13
14 import org.eclipse.jgit.internal.JGitText;
15 import org.eclipse.jgit.util.QuotedString;
16 import org.eclipse.jgit.util.RawParseUtils;
17
18
19
20
21
22
23
24
25
26 public class BinaryDelta {
27
28
29
30
31
32
33
34 public static long getBaseSize(byte[] delta) {
35 int p = 0;
36 long baseLen = 0;
37 int c, shift = 0;
38 do {
39 c = delta[p++] & 0xff;
40 baseLen |= ((long) (c & 0x7f)) << shift;
41 shift += 7;
42 } while ((c & 0x80) != 0);
43 return baseLen;
44 }
45
46
47
48
49
50
51
52
53 public static long getResultSize(byte[] delta) {
54 int p = 0;
55
56
57
58 int c;
59 do {
60 c = delta[p++] & 0xff;
61 } while ((c & 0x80) != 0);
62
63 long resLen = 0;
64 int shift = 0;
65 do {
66 c = delta[p++] & 0xff;
67 resLen |= ((long) (c & 0x7f)) << shift;
68 shift += 7;
69 } while ((c & 0x80) != 0);
70 return resLen;
71 }
72
73
74
75
76
77
78
79
80
81
82
83
84 public static final byte[] apply(byte[] base, byte[] delta) {
85 return apply(base, delta, null);
86 }
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102 public static final byte[] apply(final byte[] base, final byte[] delta,
103 byte[] result) {
104 int deltaPtr = 0;
105
106
107
108 int baseLen = 0;
109 int c, shift = 0;
110 do {
111 c = delta[deltaPtr++] & 0xff;
112 baseLen |= (c & 0x7f) << shift;
113 shift += 7;
114 } while ((c & 0x80) != 0);
115 if (base.length != baseLen)
116 throw new IllegalArgumentException(
117 JGitText.get().baseLengthIncorrect);
118
119
120
121 int resLen = 0;
122 shift = 0;
123 do {
124 c = delta[deltaPtr++] & 0xff;
125 resLen |= (c & 0x7f) << shift;
126 shift += 7;
127 } while ((c & 0x80) != 0);
128
129 if (result == null)
130 result = new byte[resLen];
131 else if (result.length != resLen)
132 throw new IllegalArgumentException(
133 JGitText.get().resultLengthIncorrect);
134
135 int resultPtr = 0;
136 while (deltaPtr < delta.length) {
137 final int cmd = delta[deltaPtr++] & 0xff;
138 if ((cmd & 0x80) != 0) {
139
140
141
142
143 int copyOffset = 0;
144 if ((cmd & 0x01) != 0)
145 copyOffset = delta[deltaPtr++] & 0xff;
146 if ((cmd & 0x02) != 0)
147 copyOffset |= (delta[deltaPtr++] & 0xff) << 8;
148 if ((cmd & 0x04) != 0)
149 copyOffset |= (delta[deltaPtr++] & 0xff) << 16;
150 if ((cmd & 0x08) != 0)
151 copyOffset |= (delta[deltaPtr++] & 0xff) << 24;
152
153 int copySize = 0;
154 if ((cmd & 0x10) != 0)
155 copySize = delta[deltaPtr++] & 0xff;
156 if ((cmd & 0x20) != 0)
157 copySize |= (delta[deltaPtr++] & 0xff) << 8;
158 if ((cmd & 0x40) != 0)
159 copySize |= (delta[deltaPtr++] & 0xff) << 16;
160 if (copySize == 0)
161 copySize = 0x10000;
162
163 System.arraycopy(base, copyOffset, result, resultPtr, copySize);
164 resultPtr += copySize;
165 } else if (cmd != 0) {
166
167
168
169 System.arraycopy(delta, deltaPtr, result, resultPtr, cmd);
170 deltaPtr += cmd;
171 resultPtr += cmd;
172 } else {
173
174
175
176 throw new IllegalArgumentException(
177 JGitText.get().unsupportedCommand0);
178 }
179 }
180
181 return result;
182 }
183
184
185
186
187
188
189
190
191 public static String format(byte[] delta) {
192 return format(delta, true);
193 }
194
195
196
197
198
199
200
201
202
203
204
205 public static String format(byte[] delta, boolean includeHeader) {
206 StringBuilder r = new StringBuilder();
207 int deltaPtr = 0;
208
209 long baseLen = 0;
210 int c, shift = 0;
211 do {
212 c = delta[deltaPtr++] & 0xff;
213 baseLen |= ((long) (c & 0x7f)) << shift;
214 shift += 7;
215 } while ((c & 0x80) != 0);
216
217 long resLen = 0;
218 shift = 0;
219 do {
220 c = delta[deltaPtr++] & 0xff;
221 resLen |= ((long) (c & 0x7f)) << shift;
222 shift += 7;
223 } while ((c & 0x80) != 0);
224
225 if (includeHeader) {
226 r.append("DELTA( BASE=");
227 r.append(baseLen);
228 r.append(" RESULT=");
229 r.append(resLen);
230 r.append(" )\n");
231 }
232
233 while (deltaPtr < delta.length) {
234 final int cmd = delta[deltaPtr++] & 0xff;
235 if ((cmd & 0x80) != 0) {
236
237
238
239
240 int copyOffset = 0;
241 if ((cmd & 0x01) != 0)
242 copyOffset = delta[deltaPtr++] & 0xff;
243 if ((cmd & 0x02) != 0)
244 copyOffset |= (delta[deltaPtr++] & 0xff) << 8;
245 if ((cmd & 0x04) != 0)
246 copyOffset |= (delta[deltaPtr++] & 0xff) << 16;
247 if ((cmd & 0x08) != 0)
248 copyOffset |= (delta[deltaPtr++] & 0xff) << 24;
249
250 int copySize = 0;
251 if ((cmd & 0x10) != 0)
252 copySize = delta[deltaPtr++] & 0xff;
253 if ((cmd & 0x20) != 0)
254 copySize |= (delta[deltaPtr++] & 0xff) << 8;
255 if ((cmd & 0x40) != 0)
256 copySize |= (delta[deltaPtr++] & 0xff) << 16;
257 if (copySize == 0)
258 copySize = 0x10000;
259
260 r.append(" COPY (");
261 r.append(copyOffset);
262 r.append(", ");
263 r.append(copySize);
264 r.append(")\n");
265 } else if (cmd != 0) {
266
267
268
269 r.append(" INSERT(");
270 r.append(QuotedString.GIT_PATH.quote(RawParseUtils.decode(
271 delta, deltaPtr, deltaPtr + cmd)));
272 r.append(")\n");
273 deltaPtr += cmd;
274 } else {
275
276
277
278 throw new IllegalArgumentException(
279 JGitText.get().unsupportedCommand0);
280 }
281 }
282
283 return r.toString();
284 }
285 }