blob: 2b1b4c269d4b49ee878136f1b983408ecfdf1823 [file] [log] [blame]
/*
* Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package nsk.share.jdwp;
import java.io.*;
import nsk.share.*;
/**
* This class represents a byte buffer of variable size.
*/
public class ByteBuffer {
/**
* Empty byte value (zero).
*/
private static final byte EMPTY_BYTE = (byte)0;
/**
* Current number of bytes in the buffer.
*/
private int CurrentSize;
/**
* Delta to increase buffer size.
*/
private int Delta;
/**
* Current offset from the buffer begin during parsing packet.
*/
int parseOffset;
/**
* Array of bytes in the buffer.
*/
protected byte[] bytes;
/**
* Make an empty <code>ByteBuffer</code> object.
*/
public ByteBuffer() {
this(128, 128);
}
/**
* Make an empty <code>ByteBuffer</code> object with given initial capacity.
* When there is no space for a new byte in a buffer it's capacity
* grows by Delta.
*/
public ByteBuffer(int InitialSize, int Delta) {
if (Delta <= 0)
Delta = 16;
this.Delta = Delta;
CurrentSize = 0;
bytes = new byte[InitialSize];
parseOffset = 0;
}
/**
* Make a copy of specified byte buffer.
*/
public ByteBuffer(ByteBuffer buffer) {
int InitialSize = buffer.bytes.length;
Delta = buffer.Delta;
CurrentSize = buffer.CurrentSize;
bytes = new byte[InitialSize];
for (int i = 0; i < CurrentSize; i++ ) {
bytes[i] = buffer.bytes[i];
}
parseOffset = 0;
}
/**
* Return number of bytes in this buffer.
*/
public int length() {
return CurrentSize;
}
/**
* Return array of bytes in this buffer.
*/
public byte[] getBytes() {
return bytes;
}
//////////////////////////////////////////////////////////////////////////
/**
* Replace the byte at the specified offset in this buffer with the
* less significant byte from the int value.
*
* @throws BoundException if specified offset is out of buffer bounds
*/
public void putByte(int off, byte value) throws BoundException {
if ((off < 0) || (off >= CurrentSize))
throw new BoundException("Unable to put one byte at " + offsetString(off));
bytes[off] = value;
}
/**
* Replace len bytes starting at offset off with the bytes from the
* given byte array.
*
* @throws BoundException if offset and length are out of buffer bounds
*/
public void putBytes(int off, byte[] value, int start, int len) throws BoundException {
if (len > (CurrentSize - off)) {
throw new BoundException("Unable to put " + len + " bytes at " + offsetString(off) +
" (available bytes: " + (CurrentSize - off) + ")" );
}
try {
for (int i = 0; i < len; i++)
putByte(off++, value[start++]);
} catch (BoundException e) {
throw new Failure("Caught unexpected bound exception while putting " + len +
"bytes at " + offsetString(off) + ":\n\t" + e);
}
}
/**
* Replace count (1 - 8) bytes starting at offset off with the less
* significant bytes from the specified ID value.
*
* @throws BoundException if offset and count are out of buffer bounds
*/
public void putID(int off, long value, int count) throws BoundException {
if ((count <= 0) || (count > 8))
throw new TestBug("Illegal number of bytes of ID value to put: " + count);
if (count > CurrentSize - off) {
throw new BoundException("Unable to put " + count + " bytes of ID value at " +
offsetString(off) + " (available bytes: " + (CurrentSize - off) + ")" );
}
try {
putValueBytes(off, value, count);
} catch (BoundException e) {
throw new Failure("Caught unexpected bound exception while putting " + count +
"bytes of ID value at " + offsetString(off) + ":\n\t" + e);
}
}
/**
* Replace four bytes starting at offset off with the bytes from the
* specified int value.
*
* @throws BoundException if offset is out of buffer bounds
*/
public void putInt(int off, int value) throws BoundException {
final int count = JDWP.TypeSize.INT;
if (count > CurrentSize - off) {
throw new BoundException("Unable to put " + count + " bytes of int value at " +
offsetString(off) + " (available bytes: " + (CurrentSize - off) + ")" );
}
try {
putValueBytes(off, value, count);
} catch (BoundException e) {
throw new Failure("Caught unexpected bound exception while putting " + count +
"bytes of int value at " + offsetString(off) + ":\n\t" + e);
}
}
/**
* Replace two bytes starting at offset off with the bytes
* from the specified short value.
*
* @throws BoundException if offset is out of buffer bounds
*/
public void putShort(int off, short value) throws BoundException {
final int count = JDWP.TypeSize.SHORT;
if (count > CurrentSize - off) {
throw new BoundException("Unable to put " + count + " bytes of short value at " +
offsetString(off) + " (available bytes: " + (CurrentSize - off) + ")" );
}
try {
putValueBytes(off, value, count);
} catch (BoundException e) {
throw new Failure("Caught unexpected bound exception while putting " + count +
"bytes of short value at " + offsetString(off) + ":\n\t" + e);
}
}
/**
* Replace eight bytes starting at offset off with the bytes
* from the specified long value.
*
* @throws BoundException if offset is out of buffer bounds
*/
public void putLong(int off, long value) throws BoundException {
final int count = JDWP.TypeSize.LONG;
if (count > CurrentSize - off) {
throw new BoundException("Unable to put " + count + " bytes of long value at " +
offsetString(off) + " (available bytes: " + (CurrentSize - off) + ")" );
}
try {
putValueBytes(off, value, count);
} catch (BoundException e) {
throw new Failure("Caught unexpected bound exception while putting " + count +
"bytes of long value at " + offsetString(off) + ":\n\t" + e);
}
}
/**
* Replace four bytes starting at offset off with the bytes
* from the specified float value.
*
* @throws BoundException if offset is out of buffer bounds
*/
public void putFloat(int off, float value) throws BoundException {
final int count = JDWP.TypeSize.FLOAT;
if (count > CurrentSize - off) {
throw new BoundException("Unable to put " + count + " bytes of float value at " +
offsetString(off) + " (available bytes: " + (CurrentSize - off) + ")" );
}
try {
long l = Float.floatToIntBits(value);
putValueBytes(off, l, count);
} catch (BoundException e) {
throw new Failure("Caught unexpected bound exception while putting " + count +
"bytes of float value at " + offsetString(off) + ":\n\t" + e);
}
}
/**
* Replace eight bytes starting at offset off with the bytes
* from the specified double value.
*
* @throws BoundException if offset is out of buffer bounds
*/
public void putDouble(int off, double value) throws BoundException {
final int count = JDWP.TypeSize.DOUBLE;
if (count > CurrentSize - off) {
throw new BoundException("Unable to put " + count + " bytes of double value at " +
offsetString(off) + " (available bytes: " + (CurrentSize - off) + ")" );
}
try {
long l = Double.doubleToLongBits(value);
putValueBytes(off, l, count);
} catch (BoundException e) {
throw new Failure("Caught unexpected bound exception while putting " + count +
"bytes of double value at " + offsetString(off) + ": \n\t" + e);
}
}
/**
* Replace two bytes starting at offset off with the bytes
* from the specified char value.
*
* @throws BoundException if offset is out of buffer bounds
*/
public void putChar(int off, char value) throws BoundException {
final int count = JDWP.TypeSize.CHAR;
if (count > CurrentSize - off) {
throw new BoundException("Unable to put " + count + " bytes of char value at " +
offsetString(off) + " (available bytes: " + (CurrentSize - off) + ")" );
}
try {
long l = (long)value;
putValueBytes(off, l, count);
} catch (BoundException e) {
throw new Failure("Caught unexpected bound exception while putting " + count +
"bytes of char value at " + offsetString(off) + ":\n\t" + e);
}
}
//////////////////////////////////////////////////////////////////////////
/**
* Append the specified byte to the end of this buffer.
*/
public void addByte(byte value) {
checkSpace(1);
int where = CurrentSize;
CurrentSize++;
try {
putByte(where, value);
}
catch (BoundException e) {
throw new TestBug("Caught unexpected bound exception while adding one byte:\n\t"
+ e);
};
}
/**
* Append specified byte value repeated count to the end of this buffer.
*/
public void addBytes(byte value, int count) {
checkSpace(count);
for (int i = 0; i < count; i++) {
addByte(value);
}
}
/**
* Append the bytes from the specified byte array to the end of this buffer.
*/
public void addBytes(byte[] value, int start, int len) {
checkSpace(len);
int where = CurrentSize;
CurrentSize = CurrentSize + len;
try {
putBytes(where, value, start, len);
}
catch (BoundException e) {
throw new TestBug("Caught unexpected bound exception while adding " +
len + " bytes:\n\t" + e);
};
}
/**
* Appends the count (1 - 8) less significant bytes from the
* specified ID value to the end of this buffer.
*/
public void addID(long value, int count) {
if ((count <= 0) || (count > 8))
throw new TestBug("Illegal number bytes of ID value to add: " + count);
final int where = CurrentSize;
addBytes(EMPTY_BYTE, count);
try {
putID(where, value, count);
}
catch (BoundException e) {
throw new TestBug("Caught unexpected bound exception while adding " +
count + " bytes of ID value:\n\t" + e);
};
}
/**
* Append four bytes from the specified int value to the
* end of this buffer.
*/
public void addInt(int value) {
final int count = JDWP.TypeSize.INT;
final int where = CurrentSize;
addBytes(EMPTY_BYTE, count);
try {
putInt(where, value);
}
catch (BoundException e) {
throw new TestBug("Caught unexpected bound exception while adding " +
count + " bytes of int value:\n\t" + e);
};
}
/**
* Append two bytes from the specified int value to the
* end of this buffer.
*/
public void addShort(short value) {
final int count = JDWP.TypeSize.SHORT;
final int where = CurrentSize;
addBytes(EMPTY_BYTE, count);
try {
putShort(where, value);
}
catch (BoundException e) {
throw new TestBug("Caught unexpected bound exception while adding " +
count + " bytes of short value:\n\t" + e);
};
}
/**
* Appends eight bytes from the specified long
* value to the end of this buffer.
*/
public void addLong(long value) {
final int count = JDWP.TypeSize.LONG;
final int where = CurrentSize;
addBytes(EMPTY_BYTE, count);
try {
putLong(where, value);
}
catch (BoundException e) {
throw new TestBug("Caught unexpected bound exception while adding " +
count + " bytes of long value:\n\t" + e);
};
}
/**
* Appends four bytes from the specified float
* value to the end of this buffer.
*/
public void addFloat(float value) {
final int count = JDWP.TypeSize.FLOAT;
final int where = CurrentSize;
addBytes(EMPTY_BYTE, count);
try {
putFloat(where, value);
}
catch (BoundException e) {
throw new TestBug("Caught unexpected bound exception while adding " +
count + " bytes of float value:\n\t" + e);
};
}
/**
* Appends eight bytes from the specified double
* value to the end of this buffer.
*/
public void addDouble(double value) {
final int count = JDWP.TypeSize.DOUBLE;
final int where = CurrentSize;
addBytes(EMPTY_BYTE, count);
try {
putDouble(where, value);
}
catch (BoundException e) {
throw new TestBug("Caught unexpected bound exception while adding " +
count + " bytes of double value:\n\t" + e);
};
}
/**
* Appends four bytes from the specified char
* value to the end of this buffer.
*/
public void addChar(char value) {
final int count = JDWP.TypeSize.CHAR;
final int where = CurrentSize;
addBytes(EMPTY_BYTE, count);
try {
putChar(where, value);
}
catch (BoundException e) {
throw new TestBug("Caught unexpected bound exception while adding " +
count + " bytes of float value:\n\t" + e);
};
}
//////////////////////////////////////////////////////////////////////////
/**
* Read a byte value from this buffer at the specified position.
*
* @throws BoundException if there are no bytes at this position
*/
public byte getByte(int off) throws BoundException {
if (off < 0 || off >= CurrentSize) {
throw new BoundException("Unable to get one byte at " + offsetString(off) +
": no bytes available");
}
return bytes[off];
}
/**
* Read count bytes (1-8) from this buffer at the specified
* position and returns a long value composed of these bytes.
*
* @throws BoundException if there are no so many bytes at this position
*/
public long getID(int off, int count) throws BoundException {
if ((count <= 0) || (count > 8))
throw new TestBug("Illegal number of bytes of ID value to get: " + count);
if (count > CurrentSize - off) {
throw new BoundException("Unable to get " + count + " bytes of ID value at " +
offsetString(off) + " (available bytes: " + (CurrentSize - off) + ")" );
}
try {
return getValueBytes(off, count);
}
catch (BoundException e) {
throw new TestBug("Caught unexpected bound exception while getting " +
count + " bytes of ID value at " + offsetString(off) + ":\n\t" + e);
}
}
/**
* Read four bytes from this buffer at the specified
* position and returns an integer value composed of these bytes.
*
* @throws BoundException if there are no so many bytes at this position
*/
public int getInt(int off) throws BoundException {
final int count = JDWP.TypeSize.INT;
if (count > CurrentSize - off) {
throw new BoundException("Unable to get " + count + " bytes of int value at " +
offsetString(off) + " (available bytes: " + (CurrentSize - off) + ")" );
}
try {
return (int)getValueBytes(off, count);
}
catch (BoundException e) {
throw new TestBug("Caught unexpected bound exception while getting " +
count + " bytes of int value at " + offsetString(off) + ":\n\t" + e);
}
}
/**
* Read two bytes from this buffer at the specified
* position and returns a short value composed of these bytes.
*
* @throws BoundException if there are no so many bytes at this position
*/
public short getShort(int off) throws BoundException {
final int count = JDWP.TypeSize.SHORT;
if (count > CurrentSize - off) {
throw new BoundException("Unable to get " + count + " bytes of short value at " +
offsetString(off) + " (available bytes: " + (CurrentSize - off) + ")" );
}
try {
return (short)getValueBytes(off, count);
}
catch (BoundException e) {
throw new TestBug("Caught unexpected bound exception while getting " +
count + " bytes of short value at " + offsetString(off) + ":\n\t" + e);
}
}
/**
* Read eight bytes from this buffer at the specified
* position and returns a long value composed of these bytes.
*
* @throws BoundException if there are no so many bytes at this position
*/
public long getLong(int off) throws BoundException {
final int count = JDWP.TypeSize.LONG;
if (count > CurrentSize - off) {
throw new BoundException("Unable to get " + count + " bytes of long value at " +
offsetString(off) + " (available bytes: " + (CurrentSize - off) + ")" );
}
try {
return getValueBytes(off, count);
}
catch (BoundException e) {
throw new TestBug("Caught unexpected bound exception while getting " +
count + " bytes of long value at " + offsetString(off) + ":\n\t" + e);
}
}
/**
* Read eight bytes from this buffer at the specified
* position and returns a double value composed of these bytes.
*
* @throws BoundException if there are no so many bytes at this position
*/
public double getDouble(int off) throws BoundException {
final int count = JDWP.TypeSize.DOUBLE;
if (count > CurrentSize - off) {
throw new BoundException("Unable to get " + count + " bytes of double value at " +
offsetString(off) + " (available bytes: " + (CurrentSize - off) + ")" );
}
try {
long value = getValueBytes(off, count);
return Double.longBitsToDouble(value);
}
catch (BoundException e) {
throw new TestBug("Caught unexpected bound exception while getting " +
count + " bytes of long value at " + offsetString(off) + ":\n\t" + e);
}
}
/**
* Read four bytes from this buffer at the specified
* position and returns a float value composed of these bytes.
*
* @throws BoundException if there are no so many bytes at this position
*/
public float getFloat(int off) throws BoundException {
final int count = JDWP.TypeSize.FLOAT;
if (count > CurrentSize - off) {
throw new BoundException("Unable to get " + count + " bytes of float value at " +
offsetString(off) + " (available bytes: " + (CurrentSize - off) + ")" );
}
try {
int value = (int)getValueBytes(off, count);
return Float.intBitsToFloat(value);
}
catch (BoundException e) {
throw new TestBug("Caught unexpected bound exception while getting " +
count + " bytes of float value at " + offsetString(off) + ":\n\t" + e);
}
}
/**
* Read two bytes from this buffer at the specified
* position and returns a char value composed of these bytes.
*
* @throws BoundException if there are no so many bytes at this position
*/
public char getChar(int off) throws BoundException {
final int count = JDWP.TypeSize.CHAR;
if (count > CurrentSize - off) {
throw new BoundException("Unable to get " + count + " bytes of char value at " +
offsetString(off) + " (available bytes: " + (CurrentSize - off) + ")" );
}
try {
int value = (int)getValueBytes(off, count);
return (char)value;
}
catch (BoundException e) {
throw new TestBug("Caught unexpected bound exception while getting " +
count + " bytes of char value at " + offsetString(off) + ":\n\t" + e);
}
}
//////////////////////////////////////////////////////////////////////////
/**
* Set the current parser position to 0.
*/
public void resetPosition() {
resetPosition(0);
}
/**
* Set the current parser position to the specified value.
*/
public void resetPosition(int i) {
parseOffset = i;
}
/**
* Return current parser position.
*/
public int currentPosition() {
return parseOffset;
}
/**
* Return true if the parser pointer is set to the end of buffer.
*/
public boolean isParsed() {
return (parseOffset == CurrentSize);
}
/**
* Read a byte value from this buffer at the current parser position.
*
* @throws BoundException if there are no more bytes in the buffer
*/
public byte getByte() throws BoundException {
return getByte(parseOffset++);
}
/**
* Read count bytes (1-8) from this buffer at the current parser
* position and returns a long value composed of these bytes.
*
* @throws BoundException if there are no so many bytes in the buffer
*/
public long getID(int count) throws BoundException {
long value = getID(parseOffset, count);
parseOffset += count;
return value;
}
/**
* Read four bytes from this buffer at the current parser
* position and returns an integer value composed of these bytes.
*
* @throws BoundException if there are no so many bytes in the buffer
*/
public int getInt() throws BoundException {
final int count = JDWP.TypeSize.INT;
int value = getInt(parseOffset);
parseOffset += count;
return value;
}
/**
* Read two bytes from this buffer at the current parser
* position and returns a short value composed of these bytes.
*
* @throws BoundException if there are no so many bytes in the buffer
*/
public short getShort() throws BoundException {
final int count = JDWP.TypeSize.SHORT;
short value = getShort(parseOffset);
parseOffset += count;
return value;
}
/**
* Read eight bytes from this buffer at the current parser
* position and returns a long value composed of these bytes.
*
* @throws BoundException if there are no so many bytes in the buffer
*/
public long getLong() throws BoundException {
final int count = JDWP.TypeSize.LONG;
long value = getLong(parseOffset);
parseOffset += count;
return value;
}
/**
* Read eight bytes from this buffer at the current parser
* position and returns a double value composed of these bytes.
*
* @throws BoundException if there are no so many bytes in the buffer
*/
public double getDouble() throws BoundException {
final int count = JDWP.TypeSize.DOUBLE;
double value = getDouble(parseOffset);
parseOffset += count;
return value;
}
/**
* Read four bytes from this buffer at the current parser
* position and returns a float value composed of these bytes.
*
* @throws BoundException if there are no so many bytes in the buffer
*/
public float getFloat() throws BoundException {
final int count = JDWP.TypeSize.FLOAT;
float value = getFloat(parseOffset);
parseOffset += count;
return value;
}
/**
* Read two bytes from this buffer at the current parser
* position and returns a char value composed of these bytes.
*
* @throws BoundException if there are no so many bytes in the buffer
*/
public char getChar() throws BoundException {
final int count = JDWP.TypeSize.CHAR;
char value = getChar(parseOffset);
parseOffset += count;
return value;
}
/**
* Remove at least first count bytes from the buffer.
*/
public void deleteBytes(int count) {
int j = 0;
while (count < CurrentSize)
bytes[j++] = bytes[count++];
CurrentSize = j;
}
/**
* Clear the buffer.
*/
public void resetBuffer() {
CurrentSize = 0;
}
/**
* Return string representation of the buffer starting at given offset.
*/
public String toString(int start) {
String Result = "", HexLine = "", DisplayLine = "";
int j = 0;
for (int i = start; i < length(); i++) {
HexLine = HexLine + toHexString(bytes[i], 2) + " ";
String ch = ".";
if (bytes[i] >= 0x20 && bytes[i] < 0x80) {
try {
ch = new String(bytes, i, 1, "US-ASCII");
} catch (UnsupportedEncodingException ignore) {
}
}
DisplayLine = DisplayLine + ch;
if ((i == length() - 1) || (((i - start) & 0x0F) == 0x0F)) {
Result = Result +
" " +
toHexString(j, 4) + ": " +
PadR(HexLine, 48) + " " +
DisplayLine + "\n";
HexLine = "";
DisplayLine = "";
j = j + 16;
}
}
return Result;
}
/**
* Return string representation of the buffer.
*/
public String toString() {
return toString(0);
}
/**
* Return string with hexadecimal representation of bytes.
*/
public static String toHexString(long b, int length) {
return Right(Long.toHexString(b), length).replace(' ', '0');
}
/**
* Return string with hexadecimal representation of bytes.
*/
public static String toHexDecString(long b, int length) {
return toHexString(b, length) + " (" + b + ")";
}
// -----
/**
* Return string with hexadecimal representation of offset.
*/
public static String offsetString(int off) {
return "0x" + toHexString(off, 4);
}
/**
* Return string with hexadecimal representation of the current offset.
*/
public String offsetString() {
return offsetString(currentPosition());
}
// -----
/**
* Check if there space for new bytes in the buffer.
*/
protected void checkSpace(int space) {
int newSize = CurrentSize + space;
if (bytes.length >= newSize)
return;
byte[] newBytes = new byte[newSize];
for (int i = 0; i < CurrentSize; i++)
newBytes[i] = bytes[i];
bytes = newBytes;
}
/**
* Replace count (1 - 8) bytes starting at offset off with the less
* significant bytes from the specified long value.
*
* @throws BoundException if offset and count are out of buffer bounds
*/
protected void putValueBytes(int off, long value, int count) throws BoundException {
if ((count <= 0) || (count > 8))
throw new TestBug("Illegal number of bytes of value to put: " + count);
if (count > CurrentSize - off) {
throw new BoundException("Unable to put " + count + " bytes of value at " +
off + " (available bytes: " + (CurrentSize - off) + ")" );
}
int shift = (count - 1) * 8;
for (int i = 0; i < count; i++) {
putByte(off++, (byte) ((value >>> shift) & 0xFF));
shift = shift - 8;
}
}
/**
* Appends the count (1 - 8) less significant bytes from the
* specified long value to the end of this buffer.
*/
protected void addValueBytes(long value, int count) throws BoundException {
if ((count <= 0) || (count > 8))
throw new TestBug("Illegal number of bytes of value to add: " + count);
checkSpace(count);
int where = CurrentSize;
CurrentSize += count;
putValueBytes(where, value, count);
}
/**
* Read count bytes (1-8) from this buffer at the specified
* position and returns a long value composed of these bytes.
*
* @throws BoundException if there are no so many bytes in the buffer
*/
public long getValueBytes(int off, int count) throws BoundException {
if ((count <= 0) || (count > 8))
throw new TestBug("Illegal number of bytes of value to get: " + count);
long l = 0;
for (int i = 0; i < count; i++) {
l = (l * 0x100) + ((long) getByte(off + i) & 0xFF);
}
return l;
}
/**
* Read count bytes (1-8) from this buffer at the current parser
* position and returns a long value composed of these bytes.
*
* @throws BoundException if there are no so many bytes in the buffer
*/
/*
protected long getValueBytes(int count) throws BoundException {
long value = getValueBytes(parseOffset);
parseOffset += count;
return value;
}
*/
// ---
private static String PadL(String source, int length, String what) {
if (length <= 0)
return "";
if (source.length() > length)
return PadL("", length, "*");
while (source.length() < length)
source = what + source;
return source;
}
private static String PadL(String source, int length) {
return PadL(source, length, " ");
}
private static String PadR(String source, int length, String what) {
if (length <= 0)
return "";
if (source.length() > length)
return PadR("", length, "*");
while (source.length() < length)
source = source + what;
return source;
}
private static String PadR(String source, int length) {
return PadR(source, length, " ");
}
private static String Left(String source, int length) {
if (length <= 0)
return "";
if (length <= source.length())
return source.substring(0, length);
else
return PadR(source, length);
}
private static String Right(String source, int length) {
if (length <= 0)
return "";
if (length <= source.length())
return source.substring(source.length() - length, source.length());
else
return PadL(source, length);
}
}