package com.mpatric.mp3agic;
import java.io.UnsupportedEncodingException;
public class BufferTools {
protected static final String defaultCharsetName = "ISO-8859-1";
public static String byteBufferToStringIgnoringEncodingIssues(byte[] bytes, int offset, int length) {
try {
return byteBufferToString(bytes, offset, length, defaultCharsetName);
} catch (UnsupportedEncodingException e) {
return null;
}
}
public static String byteBufferToString(byte[] bytes, int offset, int length) throws UnsupportedEncodingException {
return byteBufferToString(bytes, offset, length, defaultCharsetName);
}
public static String byteBufferToString(byte[] bytes, int offset, int length, String charsetName) throws UnsupportedEncodingException {
if (length < 1) return "";
return new String(bytes, offset, length, charsetName);
}
public static byte[] stringToByteBufferIgnoringEncodingIssues(String s, int offset, int length) {
try {
return stringToByteBuffer(s, offset, length);
} catch (UnsupportedEncodingException e) {
return null;
}
}
public static byte[] stringToByteBuffer(String s, int offset, int length) throws UnsupportedEncodingException {
return stringToByteBuffer(s, offset, length, defaultCharsetName);
}
public static byte[] stringToByteBuffer(String s, int offset, int length, String charsetName) throws UnsupportedEncodingException {
String stringToCopy = s.substring(offset, offset + length);
byte[] bytes = stringToCopy.getBytes(charsetName);
return bytes;
}
public static void stringIntoByteBuffer(String s, int offset, int length, byte[] bytes, int destOffset) throws UnsupportedEncodingException {
stringIntoByteBuffer(s, offset, length, bytes, destOffset, defaultCharsetName);
}
public static void stringIntoByteBuffer(String s, int offset, int length, byte[] bytes, int destOffset, String charsetName) throws UnsupportedEncodingException {
String stringToCopy = s.substring(offset, offset + length);
byte[] srcBytes = stringToCopy.getBytes(charsetName);
if (srcBytes.length > 0) {
System.arraycopy(srcBytes, 0, bytes, destOffset, srcBytes.length);
}
}
public static String trimStringRight(String s) {
int endPosition = s.length() - 1;
char endChar;
while (endPosition >= 0) {
endChar = s.charAt(endPosition);
if (endChar > 32) {
break;
}
endPosition--;
}
if (endPosition == s.length() - 1) return s;
else if (endPosition < 0) return "";
return s.substring(0, endPosition + 1);
}
public static String padStringRight(String s, int length, char padWith) {
if (s.length() >= length) return s;
StringBuffer stringBuffer = new StringBuffer(s);
while (stringBuffer.length() < length) {
stringBuffer.append(padWith);
}
return stringBuffer.toString();
}
public static boolean checkBit(byte b, int bitPosition) {
return ((b & (0x01 << bitPosition)) != 0);
}
public static byte setBit(byte b, int bitPosition, boolean value) {
byte newByte;
if (value) {
newByte = (byte) (b | ((byte)0x01 << bitPosition));
} else {
newByte = (byte) (b & (~ ((byte)0x01 << bitPosition)));
}
return newByte;
}
public static int shiftByte(byte c, int places) {
int i = c & 0xff;
if (places < 0) {
return i << -places;
} else if (places > 0) {
return i >> places;
}
return i;
}
public static int unpackInteger(byte b1, byte b2, byte b3, byte b4) {
int value = b4 & 0xff;
value += BufferTools.shiftByte(b3, -8);
value += BufferTools.shiftByte(b2, -16);
value += BufferTools.shiftByte(b1, -24);
return value;
}
public static byte[] packInteger(int i) {
byte[] bytes = new byte[4];
bytes[3] = (byte) (i & 0xff);
bytes[2] = (byte) ((i >> 8) & 0xff);
bytes[1] = (byte) ((i >> 16) & 0xff);
bytes[0] = (byte) ((i >> 24) & 0xff);
return bytes;
}
public static int unpackSynchsafeInteger(byte b1, byte b2, byte b3, byte b4) {
int value = ((byte)(b4 & 0x7f));
value += shiftByte((byte)(b3 & 0x7f), -7);
value += shiftByte((byte)(b2 & 0x7f), -14);
value += shiftByte((byte)(b1 & 0x7f), -21);
return value;
}
public static byte[] packSynchsafeInteger(int i) {
byte[] bytes = new byte[4];
packSynchsafeInteger(i, bytes, 0);
return bytes;
}
public static void packSynchsafeInteger(int i, byte[] bytes, int offset) {
bytes[offset + 3] = (byte) (i & 0x7f);
bytes[offset + 2] = (byte) ((i >> 7) & 0x7f);
bytes[offset + 1] = (byte) ((i >> 14) & 0x7f);
bytes[offset + 0] = (byte) ((i >> 21) & 0x7f);
}
public static byte[] copyBuffer(byte[] bytes, int offset, int length) {
byte[] copy = new byte[length];
if (length > 0) {
System.arraycopy(bytes, offset, copy, 0, length);
}
return copy;
}
public static void copyIntoByteBuffer(byte[] bytes, int offset, int length, byte[] destBuffer, int destOffset) {
if (length > 0) {
System.arraycopy(bytes, offset, destBuffer, destOffset, length);
}
}
public static int sizeUnsynchronisationWouldAdd(byte[] bytes) {
int count = 0;
for (int i = 0; i < bytes.length - 1; i++) {
if (bytes[i] == (byte)0xff && ((bytes[i + 1] & (byte)0xe0) == (byte)0xe0 || bytes[i + 1] == 0)) {
count++;
}
}
if (bytes.length > 0 && bytes[bytes.length - 1] == (byte)0xff) count++;
return count;
}
public static byte[] unsynchroniseBuffer(byte[] bytes) {
// unsynchronisation is replacing instances of:
// 11111111 111xxxxx with 11111111 00000000 111xxxxx and
// 11111111 00000000 with 11111111 00000000 00000000
int count = sizeUnsynchronisationWouldAdd(bytes);
if (count == 0) return bytes;
byte[] newBuffer = new byte[bytes.length + count];
int j = 0;
for (int i = 0; i < bytes.length - 1; i++) {
newBuffer[j++] = bytes[i];
if (bytes[i] == (byte)0xff && ((bytes[i + 1] & (byte)0xe0) == (byte)0xe0 || bytes[i + 1] == 0)) {
newBuffer[j++] = 0;
}
}
newBuffer[j++] = bytes[bytes.length - 1];
if (bytes[bytes.length - 1] == (byte)0xff) {
newBuffer[j++] = 0;
}
return newBuffer;
}
public static int sizeSynchronisationWouldSubtract(byte[] bytes) {
int count = 0;
for (int i = 0; i < bytes.length - 2; i++) {
if (bytes[i] == (byte)0xff && bytes[i + 1] == 0 && ((bytes[i + 2] & (byte)0xe0) == (byte)0xe0 || bytes[i + 2] == 0)) {
count++;
}
}
if (bytes.length > 1 && bytes[bytes.length - 2] == (byte)0xff && bytes[bytes.length - 1] == 0) count++;
return count;
}
public static byte[] synchroniseBuffer(byte[] bytes) {
// synchronisation is replacing instances of:
// 11111111 00000000 111xxxxx with 11111111 111xxxxx and
// 11111111 00000000 00000000 with 11111111 00000000
int count = sizeSynchronisationWouldSubtract(bytes);
if (count == 0) return bytes;
byte[] newBuffer = new byte[bytes.length - count];
int i = 0;
for (int j = 0; j < newBuffer.length - 1; j++) {
newBuffer[j] = bytes[i];
if (bytes[i] == (byte)0xff && bytes[i + 1] == 0 && ((bytes[i + 2] & (byte)0xe0) == (byte)0xe0 || bytes[i + 2] == 0)) {
i++;
}
i++;
}
newBuffer[newBuffer.length - 1] = bytes[i];
return newBuffer;
}
public static String substitute(String s, String replaceThis, String withThis) {
if (replaceThis.length() < 1 || s.indexOf(replaceThis) < 0) {
return s;
}
StringBuffer newString = new StringBuffer();
int lastPosition = 0;
int position = 0;
while ((position = s.indexOf(replaceThis, position)) >= 0) {
if (position > lastPosition) {
newString.append(s.substring(lastPosition, position));
}
if (withThis != null) {
newString.append(withThis);
}
lastPosition = position + replaceThis.length();
position++;
}
if (lastPosition < s.length()) {
newString.append(s.substring(lastPosition));
}
return newString.toString();
}
public static String asciiOnly(String s) {
StringBuffer newString = new StringBuffer();
for (int i = 0; i < s.length(); i++) {
char ch = s.charAt(i);
if (ch < 32 || ch > 126) {
newString.append('?');
} else {
newString.append(ch);
}
}
return newString.toString();
}
public static int indexOfTerminator(byte[] bytes) {
return indexOfTerminator(bytes, 0);
}
public static int indexOfTerminator(byte[] bytes, int fromIndex) {
return indexOfTerminator(bytes, 0, 1);
}
public static int indexOfTerminator(byte[] bytes, int fromIndex, int terminatorLength) {
int marker = -1;
for (int i = fromIndex; i <= bytes.length - terminatorLength; i++) {
if ((i - fromIndex) % terminatorLength == 0) {
int matched;
for (matched = 0; matched < terminatorLength; matched++) {
if (bytes[i + matched] != 0) break;
}
if (matched == terminatorLength) {
marker = i;
break;
}
}
}
return marker;
}
public static int indexOfTerminatorForEncoding(byte[] bytes, int fromIndex, int encoding) {
int terminatorLength = (encoding == EncodedText.TEXT_ENCODING_UTF_16 || encoding == EncodedText.TEXT_ENCODING_UTF_16BE) ? 2 : 1;
return indexOfTerminator(bytes, fromIndex, terminatorLength);
}
}