mirror of
https://github.com/gyurix1968/guacamole-client.git
synced 2025-09-06 05:07:41 +00:00
Converted ReaderGuacamoleReader to real parser of new instruction format (should be more efficient, and no more chance of invalid reads due to semicolons).
This commit is contained in:
@@ -65,31 +65,88 @@ public class ReaderGuacamoleReader implements GuacamoleReader {
|
|||||||
this.input = input;
|
this.input = input;
|
||||||
}
|
}
|
||||||
|
|
||||||
private int usedLength = 0;
|
private int parseStart;
|
||||||
private char[] buffer = new char[20000];
|
|
||||||
|
|
||||||
private int instructionStart;
|
private char[] buffer = new char[20480];
|
||||||
private char[] instructionBuffer;
|
private int usedLength = 0;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public char[] read() throws GuacamoleException {
|
public char[] read() throws GuacamoleException {
|
||||||
|
|
||||||
// If data was previously read via readInstruction(), return remaining
|
|
||||||
// data instead of reading more.
|
|
||||||
if (instructionBuffer != null) {
|
|
||||||
|
|
||||||
char[] chunk = new char[instructionBuffer.length - instructionStart];
|
|
||||||
System.arraycopy(instructionBuffer, instructionStart, chunk, 0, chunk.length);
|
|
||||||
instructionBuffer = null;
|
|
||||||
|
|
||||||
return chunk;
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
|
||||||
// While we're blocking, or input is available
|
// While we're blocking, or input is available
|
||||||
for (;;) {
|
for (;;) {
|
||||||
|
|
||||||
|
// Length of element
|
||||||
|
int elementLength = 0;
|
||||||
|
|
||||||
|
// Resume where we left off
|
||||||
|
int i = parseStart;
|
||||||
|
|
||||||
|
// Parse instruction in buffer
|
||||||
|
while (i < usedLength) {
|
||||||
|
|
||||||
|
// Read character
|
||||||
|
char readChar = buffer[i++];
|
||||||
|
|
||||||
|
// If digit, update length
|
||||||
|
if (readChar >= '0' && readChar <= '9')
|
||||||
|
elementLength = elementLength * 10 + readChar - '0';
|
||||||
|
|
||||||
|
// If not digit, check for end-of-length character
|
||||||
|
else if (readChar == '.') {
|
||||||
|
|
||||||
|
// Check if element present in buffer
|
||||||
|
if (i + elementLength < usedLength) {
|
||||||
|
|
||||||
|
// Get terminator
|
||||||
|
char terminator = buffer[i + elementLength];
|
||||||
|
|
||||||
|
// Move to character after terminator
|
||||||
|
i += elementLength + 1;
|
||||||
|
|
||||||
|
// Reset length
|
||||||
|
elementLength = 0;
|
||||||
|
|
||||||
|
// Continue here if necessary
|
||||||
|
parseStart = i;
|
||||||
|
|
||||||
|
// If terminator is semicolon, we have a full
|
||||||
|
// instruction.
|
||||||
|
if (terminator == ';') {
|
||||||
|
|
||||||
|
// Copy instruction data
|
||||||
|
char[] instruction = new char[i];
|
||||||
|
System.arraycopy(buffer, 0, instruction, 0, i);
|
||||||
|
|
||||||
|
// Update buffer
|
||||||
|
usedLength -= i;
|
||||||
|
parseStart = 0;
|
||||||
|
System.arraycopy(buffer, i, buffer, 0, usedLength);
|
||||||
|
|
||||||
|
return instruction;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handle invalid terminator characters
|
||||||
|
else if (terminator != ',')
|
||||||
|
throw new GuacamoleException("Element terminator of instruction was not ';' nor ','");
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// Otherwise, read more data
|
||||||
|
else
|
||||||
|
break;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// Otherwise, parse error
|
||||||
|
else
|
||||||
|
throw new GuacamoleException("Non-numeric character in element length.");
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
// If past threshold, resize buffer before reading
|
// If past threshold, resize buffer before reading
|
||||||
if (usedLength > buffer.length/2) {
|
if (usedLength > buffer.length/2) {
|
||||||
char[] biggerBuffer = new char[buffer.length*2];
|
char[] biggerBuffer = new char[buffer.length*2];
|
||||||
@@ -102,30 +159,9 @@ public class ReaderGuacamoleReader implements GuacamoleReader {
|
|||||||
if (numRead == -1)
|
if (numRead == -1)
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
int prevLength = usedLength;
|
// Update used length
|
||||||
usedLength += numRead;
|
usedLength += numRead;
|
||||||
|
|
||||||
for (int i=usedLength-1; i>=prevLength; i--) {
|
|
||||||
|
|
||||||
char readChar = buffer[i];
|
|
||||||
|
|
||||||
// If end of instruction, return it.
|
|
||||||
if (readChar == ';') {
|
|
||||||
|
|
||||||
// Get instruction
|
|
||||||
char[] chunk = new char[i+1];
|
|
||||||
System.arraycopy(buffer, 0, chunk, 0, i+1);
|
|
||||||
|
|
||||||
// Reset buffer
|
|
||||||
usedLength -= i+1;
|
|
||||||
System.arraycopy(buffer, i+1, buffer, 0, usedLength);
|
|
||||||
|
|
||||||
// Return instruction string
|
|
||||||
return chunk;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
} // End read loop
|
} // End read loop
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -138,35 +174,35 @@ public class ReaderGuacamoleReader implements GuacamoleReader {
|
|||||||
@Override
|
@Override
|
||||||
public GuacamoleInstruction readInstruction() throws GuacamoleException {
|
public GuacamoleInstruction readInstruction() throws GuacamoleException {
|
||||||
|
|
||||||
// Fill instructionBuffer if not already filled
|
// Get instruction
|
||||||
if (instructionBuffer == null) {
|
char[] instructionBuffer = read();
|
||||||
instructionBuffer = read();
|
|
||||||
instructionStart = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// If EOF, return EOF
|
// If EOF, return EOF
|
||||||
if (instructionBuffer == null)
|
if (instructionBuffer == null)
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
|
// Start of element
|
||||||
|
int elementStart = 0;
|
||||||
|
|
||||||
// Build list of elements
|
// Build list of elements
|
||||||
LinkedList<String> elements = new LinkedList<String>();
|
LinkedList<String> elements = new LinkedList<String>();
|
||||||
while (instructionStart < instructionBuffer.length) {
|
while (elementStart < instructionBuffer.length) {
|
||||||
|
|
||||||
// Find end of length
|
// Find end of length
|
||||||
int lengthEnd = ArrayUtils.indexOf(instructionBuffer, '.', instructionStart);
|
int lengthEnd = ArrayUtils.indexOf(instructionBuffer, '.', elementStart);
|
||||||
|
|
||||||
// Parse length
|
// Parse length
|
||||||
int length = Integer.parseInt(new String(
|
int length = Integer.parseInt(new String(
|
||||||
instructionBuffer,
|
instructionBuffer,
|
||||||
instructionStart,
|
elementStart,
|
||||||
lengthEnd - instructionStart
|
lengthEnd - elementStart
|
||||||
));
|
));
|
||||||
|
|
||||||
// Parse element from just after period
|
// Parse element from just after period
|
||||||
instructionStart = lengthEnd + 1;
|
elementStart = lengthEnd + 1;
|
||||||
String element = new String(
|
String element = new String(
|
||||||
instructionBuffer,
|
instructionBuffer,
|
||||||
instructionStart,
|
elementStart,
|
||||||
length
|
length
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -174,11 +210,11 @@ public class ReaderGuacamoleReader implements GuacamoleReader {
|
|||||||
elements.addLast(element);
|
elements.addLast(element);
|
||||||
|
|
||||||
// Read terminator after element
|
// Read terminator after element
|
||||||
instructionStart += length;
|
elementStart += length;
|
||||||
char terminator = instructionBuffer[instructionStart];
|
char terminator = instructionBuffer[elementStart];
|
||||||
|
|
||||||
// Continue reading instructions after terminator
|
// Continue reading instructions after terminator
|
||||||
instructionStart++;
|
elementStart++;
|
||||||
|
|
||||||
// If we've reached the end of the instruction
|
// If we've reached the end of the instruction
|
||||||
if (terminator == ';')
|
if (terminator == ';')
|
||||||
@@ -195,10 +231,6 @@ public class ReaderGuacamoleReader implements GuacamoleReader {
|
|||||||
elements.toArray(new String[elements.size()])
|
elements.toArray(new String[elements.size()])
|
||||||
);
|
);
|
||||||
|
|
||||||
// Detect end of buffer
|
|
||||||
if (instructionStart >= instructionBuffer.length)
|
|
||||||
instructionBuffer = null;
|
|
||||||
|
|
||||||
// Return parsed instruction
|
// Return parsed instruction
|
||||||
return instruction;
|
return instruction;
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user