diff options
Diffstat (limited to 'generator/src/main/java/com/google/archivepatcher/generator/bsdiff/BsUtil.java')
-rw-r--r-- | generator/src/main/java/com/google/archivepatcher/generator/bsdiff/BsUtil.java | 106 |
1 files changed, 106 insertions, 0 deletions
diff --git a/generator/src/main/java/com/google/archivepatcher/generator/bsdiff/BsUtil.java b/generator/src/main/java/com/google/archivepatcher/generator/bsdiff/BsUtil.java new file mode 100644 index 0000000..3631dcc --- /dev/null +++ b/generator/src/main/java/com/google/archivepatcher/generator/bsdiff/BsUtil.java @@ -0,0 +1,106 @@ +// Copyright 2016 Google Inc. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package com.google.archivepatcher.generator.bsdiff; + +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; + +/** + * Utility functions to be shared between BsDiff and BsPatch. + */ +class BsUtil { + /** + * Mask to determine whether a long written by {@link #writeFormattedLong(long, OutputStream)} + * is negative. + */ + private static final long NEGATIVE_MASK = 1L << 63; + + /** + * Writes a 64-bit signed integer to the specified {@link OutputStream}. The least significant + * byte is written first and the most significant byte is written last. + * @param value the value to write + * @param outputStream the stream to write to + */ + static void writeFormattedLong(final long value, OutputStream outputStream) + throws IOException { + long y = value; + if (y < 0) { + y = (-y) | NEGATIVE_MASK; + } + + for (int i = 0; i < 8; ++i) { + outputStream.write((byte) (y & 0xff)); + y >>>= 8; + } + } + + /** + * Reads a 64-bit signed integer written by {@link #writeFormattedLong(long, OutputStream)} from + * the specified {@link InputStream}. + * @param inputStream the stream to read from + */ + static long readFormattedLong(InputStream inputStream) throws IOException { + long result = 0; + for (int bitshift = 0; bitshift < 64; bitshift += 8) { + result |= ((long) inputStream.read()) << bitshift; + } + + if ((result - NEGATIVE_MASK) > 0) { + result = (result & ~NEGATIVE_MASK) * -1; + } + return result; + } + + /** + * Provides functional equivalent to C/C++ lexicographical_compare. Warning: this calls {@link + * RandomAccessObject#seek(long)}, so the internal state of the data objects will be modified. + * + * @param data1 first byte array + * @param start1 index in the first array at which to start comparing + * @param length1 length of first byte array + * @param data2 second byte array + * @param start2 index in the second array at which to start comparing + * @param length2 length of second byte array + * @return result of lexicographical compare: negative if the first difference has a lower value + * in the first array, positive if the first difference has a lower value in the second array. + * If both arrays compare equal until one of them ends, the shorter sequence is + * lexicographically less than the longer one (i.e., it returns len(first array) - + * len(second array)). + */ + static int lexicographicalCompare( + final RandomAccessObject data1, + final int start1, + final int length1, + final RandomAccessObject data2, + final int start2, + final int length2) + throws IOException { + int bytesLeft = Math.min(length1, length2); + + data1.seek(start1); + data2.seek(start2); + while (bytesLeft-- > 0) { + final int i1 = data1.readUnsignedByte(); + final int i2 = data2.readUnsignedByte(); + + if (i1 != i2) { + return i1 - i2; + } + } + + return length1 - length2; + } +} |