// Automatically translated by XLang.py to Java from cbx.h.
/// SinkWorld split buffer class
/// Copyright 2001 Neil Hodgson
/// All implementations use the intrinsic char type which is 1 byte
/// in C++ and 2 bytes in Java and C#.
class cbx {
char[] body;
int size;
int length;
int part1Length;
int gapLength;
int growSize;
/// Move the gap to a particular position so that insertion and
/// deletion at that point will not require much copying and
/// hence be fast.
private void GapTo(int position) {
if (position != part1Length) {
if (position < part1Length) {
int diff = part1Length - position;
for (int i = 0; i < diff; i++)
body[part1Length + gapLength - i - 1] =
body[part1Length - i - 1];
} else { // position > part1Length
int diff = position - part1Length;
for (int i = 0; i < diff; i++)
body[part1Length + i] =
body[part1Length + gapLength + i];
}
part1Length = position;
}
}
/// Reallocate the storage for the buffer to be newSize and
/// copy exisiting contents to the new buffer.
/// Must not be used to decrease the size of the buffer.
private void ReAllocate(int newSize) {
// Move the gap to the end
GapTo(length);
char[] newBody = new char[newSize];
if (size != 0) {
for (int i = 0; i < size; i++)
newBody[i] = body[i];
// delete []body;
}
body = newBody;
gapLength += newSize - size;
size = newSize;
}
/// Check that there is room in the buffer for an insertion,
/// reallocating if more space needed.
private void RoomFor(int insertionLength) {
if (gapLength <= insertionLength) {
if (growSize * 6 < size)
growSize *= 2;
ReAllocate(size + insertionLength + growSize);
}
}
/// Construct a split buffer.
public cbx(int initialLength, int growSize_) {
growSize = growSize_;
size = 0;
length = 0;
part1Length = 0;
gapLength = 0;
ReAllocate(initialLength);
}
/// Retrieve the character at a particular position.
/// Retrieving positions outside the range of the buffer works
/// and returns 0.
public char CharAt(int position) {
if (position < part1Length) {
if (position < 0) {
return '\0';
} else {
return body[position];
}
} else {
if (position >= length) {
return '\0';
} else {
return body[gapLength + position];
}
}
}
/// Retrieve the length of the buffer.
public int Length() {
return length;
}
/// Retrieve a range of text from the buffer.
/// Retrieving positions outside the range of the buffer fails.
public void RetrieveString(int position, char[] s, int retrieveLength) {
int i = 0;
int pos = position;
while ((i < retrieveLength) && (pos < part1Length)) {
s[i++] = body[pos++];
}
while (i < retrieveLength) {
s[i++] = body[gapLength + pos++];
}
}
/// Insert text into the buffer.
/// Inserting at positions outside the current range throws a
/// BadPositionException.
public void InsertString(int position, char[] s, int insertLength) {
if (insertLength > 0) {
if ((position < 0) || (position > length)) {
throw new BadPositionException();
}
RoomFor(insertLength);
GapTo(position);
for (int i = 0; i < insertLength; i++)
body[part1Length + i] = s[i];
length += insertLength;
part1Length += insertLength;
gapLength -= insertLength;
}
}
/// Fill an already allocated range with a value.
/// Modifying outside the current range throws a
/// BadPositionException.
public void FillRange(int position, char ch, int fillLength) {
if (fillLength > 0) {
if ((position < 0) || ((position + fillLength) > length)) {
throw new BadPositionException();
}
int i = 0;
int pos = position;
while ((i < fillLength) && (pos < part1Length)) {
body[pos++] = ch;
i++;
}
while (i < fillLength) {
body[gapLength + pos++] = ch;
i++;
}
}
}
/// Insert a number of zero characters into the buffer.
/// Inserting at positions outside the current range fails.
public void InsertZeros(int position, int insertLength) {
if (insertLength > 0) {
RoomFor(insertLength);
GapTo(position);
for (int i = 0; i < insertLength; i++)
body[part1Length + i] = '\0';
length += insertLength;
part1Length += insertLength;
gapLength -= insertLength;
}
}
/// Delete a range from the buffer.
/// Deleting positions outside the current range fails.
public void DeleteChars(int position, int deleteLength) {
if (deleteLength > 0) {
GapTo(position);
length -= deleteLength;
gapLength += deleteLength;
}
}
};