View Javadoc
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 }