001: /*
002: * ====================================================================
003: * Copyright (c) 2004-2008 TMate Software Ltd. All rights reserved.
004: *
005: * This software is licensed as described in the file COPYING, which
006: * you should have received as part of this distribution. The terms
007: * are also available at http://svnkit.com/license.html
008: * If newer versions of this license are posted there, you may use a
009: * newer version instead, at your option.
010: * ====================================================================
011: */
012:
013: package org.tmatesoft.svn.core.io.diff;
014:
015: import java.nio.ByteBuffer;
016:
017: /**
018: * The <b>SVNDiffInstruction</b> class represents instructions used as delta
019: * applying rules.
020: *
021: * <p>
022: * For now there are three types of copy instructions:
023: * <ul>
024: * <li>
025: * {@link SVNDiffInstruction#COPY_FROM_SOURCE}: that is when bytes are copied from
026: * a source view (for example, existing revision of a file) to the target
027: * one.
028: * </li>
029: * <li>
030: * {@link SVNDiffInstruction#COPY_FROM_NEW_DATA}: new data bytes (e.g. new
031: * text) are copied to the target view.
032: * </li>
033: * <li>
034: * {@link SVNDiffInstruction#COPY_FROM_TARGET}: that is, when a sequence of bytes in the
035: * target must be repeated.
036: * </li>
037: * </ul>
038: *
039: * These are three different ways how full text representation bytes are
040: * obtained.
041: *
042: * @version 1.1.1
043: * @author TMate Software Ltd.
044: */
045: public class SVNDiffInstruction {
046: /**
047: * A type of an instruction that says that data must be copied
048: * from the source view to the target one.
049: */
050: public static final int COPY_FROM_SOURCE = 0x00;
051:
052: /**
053: * A type of an instruction that says that data must be copied
054: * from the target view to the target itself.
055: */
056: public static final int COPY_FROM_TARGET = 0x01;
057:
058: /**
059: * A type of an instruction that says that data must be copied
060: * from the new data to the target view.
061: */
062: public static final int COPY_FROM_NEW_DATA = 0x02;
063:
064: /**
065: * Creates a particular type of a diff instruction.
066: * Instruction offsets are relative to the bounds of views, i.e.
067: * a source/target view is a window of bytes (specified in a concrete
068: * diff window) in the source/target stream (this can be a file, a buffer).
069: *
070: * @param t a type of an instruction
071: * @param l a number of bytes to copy
072: * @param o an offset in the source (which may be a source or a target
073: * view, or a new data stream) from where
074: * the bytes are to be copied
075: * @see SVNDiffWindow
076: */
077: public SVNDiffInstruction(int t, int l, int o) {
078: type = t;
079: length = l;
080: offset = o;
081: }
082:
083: /**
084: * Creates a new instruction object.
085: * It's the instruction for the empty contents file.
086: *
087: */
088: public SVNDiffInstruction() {
089: this (0, 0, 0);
090:
091: }
092:
093: /**
094: * A type of this instruction.
095: */
096: public int type;
097:
098: /**
099: * A length bytes to copy.
100: */
101: public int length;
102:
103: /**
104: * An offset in the source from where the bytes
105: * should be copied. Instruction offsets are relative to the bounds of
106: * views, i.e. a source/target view is a window of bytes (specified in a concrete
107: * diff window) in the source/target stream (this can be a file, a buffer).
108: *
109: */
110: public int offset;
111:
112: /**
113: * Gives a string representation of this object.
114: *
115: * @return a string representation of this object
116: */
117: public String toString() {
118: StringBuffer b = new StringBuffer();
119: switch (type) {
120: case COPY_FROM_SOURCE:
121: b.append("S->");
122: break;
123: case COPY_FROM_TARGET:
124: b.append("T->");
125: break;
126: case COPY_FROM_NEW_DATA:
127: b.append("D->");
128: break;
129: }
130: if (type == 0 || type == 1) {
131: b.append(offset);
132: } else {
133: b.append(offset);
134: }
135: b.append(":");
136: b.append(length);
137: return b.toString();
138: }
139:
140: /**
141: * Wirtes this instruction to a byte buffer.
142: *
143: * @param target a byte buffer to write to
144: */
145: public void writeTo(ByteBuffer target) {
146: byte first = (byte) (type << 6);
147: if (length <= 0x3f && length > 0) {
148: // single-byte lenght;
149: first |= (length & 0x3f);
150: target.put((byte) (first & 0xff));
151: } else {
152: target.put((byte) (first & 0xff));
153: writeInt(target, length);
154: }
155: if (type == 0 || type == 1) {
156: writeInt(target, offset);
157: }
158: }
159:
160: /**
161: * Writes an integer to a byte buffer.
162: *
163: * @param os a byte buffer to write to
164: * @param i an integer to write
165: */
166: public static void writeInt(ByteBuffer os, int i) {
167: if (i == 0) {
168: os.put((byte) 0);
169: return;
170: }
171: int count = 1;
172: long v = i >> 7;
173: while (v > 0) {
174: v = v >> 7;
175: count++;
176: }
177: byte b;
178: int r;
179: while (--count >= 0) {
180: b = (byte) ((count > 0 ? 0x1 : 0x0) << 7);
181: r = ((byte) ((i >> (7 * count)) & 0x7f)) | b;
182: os.put((byte) r);
183: }
184: }
185:
186: /**
187: * Writes a long to a byte buffer.
188: *
189: * @param os a byte buffer to write to
190: * @param i a long number to write
191: */
192: public static void writeLong(ByteBuffer os, long i) {
193: if (i == 0) {
194: os.put((byte) 0);
195: return;
196: }
197: // how many bytes there are:
198: int count = 1;
199: long v = i >> 7;
200: while (v > 0) {
201: v = v >> 7;
202: count++;
203: }
204: byte b;
205: int r;
206: while (--count >= 0) {
207: b = (byte) ((count > 0 ? 0x1 : 0x0) << 7);
208: r = ((byte) ((i >> (7 * count)) & 0x7f)) | b;
209: os.put((byte) r);
210: }
211: }
212: }
|