/*
* ====================================================================
* Copyright (c) 2004-2012 TMate Software Ltd. All rights reserved.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
* are also available at http://svnkit.com/license.html
* If newer versions of this license are posted there, you may use a
* newer version instead, at your option.
* ====================================================================
*/
package org.tmatesoft.svn.core.io.diff;
import java.nio.ByteBuffer;
/**
* The <b>SVNDiffInstruction</b> class represents instructions used as delta
* applying rules.
*
* <p>
* For now there are three types of copy instructions:
* <ul>
* <li>
* {@link SVNDiffInstruction#COPY_FROM_SOURCE}: that is when bytes are copied from
* a source view (for example, existing revision of a file) to the target
* one.
* </li>
* <li>
* {@link SVNDiffInstruction#COPY_FROM_NEW_DATA}: new data bytes (e.g. new
* text) are copied to the target view.
* </li>
* <li>
* {@link SVNDiffInstruction#COPY_FROM_TARGET}: that is, when a sequence of bytes in the
* target must be repeated.
* </li>
* </ul>
*
* These are three different ways how full text representation bytes are
* obtained.
*
* @version 1.3
* @author TMate Software Ltd.
* @since 1.2
*/
public class SVNDiffInstruction {
/**
* A type of an instruction that says that data must be copied
* from the source view to the target one.
*/
public static final int COPY_FROM_SOURCE = 0x00;
/**
* A type of an instruction that says that data must be copied
* from the target view to the target itself.
*/
public static final int COPY_FROM_TARGET = 0x01;
/**
* A type of an instruction that says that data must be copied
* from the new data to the target view.
*/
public static final int COPY_FROM_NEW_DATA = 0x02;
/**
* Creates a particular type of a diff instruction.
* Instruction offsets are relative to the bounds of views, i.e.
* a source/target view is a window of bytes (specified in a concrete
* diff window) in the source/target stream (this can be a file, a buffer).
*
* @param t a type of an instruction
* @param l a number of bytes to copy
* @param o an offset in the source (which may be a source or a target
* view, or a new data stream) from where
* the bytes are to be copied
* @see SVNDiffWindow
*/
public SVNDiffInstruction(int t, int l, int o) {
type = t;
length = l;
offset = o;
}
/**
* Creates a new instruction object.
* It's the instruction for the empty contents file.
*
*/
public SVNDiffInstruction() {
this(0,0,0);
}
/**
* A type of this instruction.
*/
public int type;
/**
* A length bytes to copy.
*/
public int length;
/**
* An offset in the source from where the bytes
* should be copied. Instruction offsets are relative to the bounds of
* views, i.e. a source/target view is a window of bytes (specified in a concrete
* diff window) in the source/target stream (this can be a file, a buffer).
*
*/
public int offset;
/**
* Gives a string representation of this object.
*
* @return a string representation of this object
*/
public String toString() {
StringBuffer b = new StringBuffer();
switch(type) {
case COPY_FROM_SOURCE:
b.append("S->");
break;
case COPY_FROM_TARGET:
b.append("T->");
break;
case COPY_FROM_NEW_DATA:
b.append("D->");
break;
}
if (type == 0 || type == 1) {
b.append(offset);
} else {
b.append(offset);
}
b.append(":");
b.append(length);
return b.toString();
}
/**
* Wirtes this instruction to a byte buffer.
*
* @param target a byte buffer to write to
*/
public void writeTo(ByteBuffer target) {
byte first = (byte) (type << 6);
if (length <= 0x3f && length > 0) {
// single-byte lenght;
first |= (length & 0x3f);
target.put((byte) (first & 0xff));
} else {
target.put((byte) (first & 0xff));
writeInt(target, length);
}
if (type == 0 || type == 1) {
writeInt(target, offset);
}
}
/**
* Writes an integer to a byte buffer.
*
* @param os a byte buffer to write to
* @param i an integer to write
*/
public static void writeInt(ByteBuffer os, int i) {
if (i == 0) {
os.put((byte) 0);
return;
}
int count = 1;
long v = i >> 7;
while(v > 0) {
v = v >> 7;
count++;
}
byte b;
int r;
while(--count >= 0) {
b = (byte) ((count > 0 ? 0x1 : 0x0) << 7);
r = ((byte) ((i >> (7 * count)) & 0x7f)) | b;
os.put((byte) r);
}
}
/**
* Writes a long to a byte buffer.
*
* @param os a byte buffer to write to
* @param i a long number to write
*/
public static void writeLong(ByteBuffer os, long i) {
if (i == 0) {
os.put((byte) 0);
return;
}
// how many bytes there are:
int count = 1;
long v = i >> 7;
while(v > 0) {
v = v >> 7;
count++;
}
byte b;
int r;
while(--count >= 0) {
b = (byte) ((count > 0 ? 0x1 : 0x0) << 7);
r = ((byte) ((i >> (7 * count)) & 0x7f)) | b;
os.put((byte) r);
}
}
}