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