mirror of
				https://github.com/gyurix1968/guacamole-client.git
				synced 2025-10-31 00:53:21 +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; | ||||
|     } | ||||
|  | ||||
|     private int usedLength = 0; | ||||
|     private char[] buffer = new char[20000]; | ||||
|     private int parseStart; | ||||
|  | ||||
|     private int instructionStart; | ||||
|     private char[] instructionBuffer; | ||||
|     private char[] buffer = new char[20480]; | ||||
|     private int usedLength = 0; | ||||
|  | ||||
|     @Override | ||||
|     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 { | ||||
|  | ||||
|             // While we're blocking, or input is available | ||||
|             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 (usedLength > buffer.length/2) { | ||||
|                     char[] biggerBuffer = new char[buffer.length*2]; | ||||
| @@ -102,30 +159,9 @@ public class ReaderGuacamoleReader implements GuacamoleReader { | ||||
|                 if (numRead == -1) | ||||
|                     return null; | ||||
|  | ||||
|                 int prevLength = usedLength; | ||||
|                 // Update used length | ||||
|                 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 | ||||
|  | ||||
|         } | ||||
| @@ -138,35 +174,35 @@ public class ReaderGuacamoleReader implements GuacamoleReader { | ||||
|     @Override | ||||
|     public GuacamoleInstruction readInstruction() throws GuacamoleException { | ||||
|  | ||||
|         // Fill instructionBuffer if not already filled | ||||
|         if (instructionBuffer == null) { | ||||
|             instructionBuffer = read(); | ||||
|             instructionStart = 0; | ||||
|         } | ||||
|  | ||||
|         // Get instruction | ||||
|         char[] instructionBuffer = read(); | ||||
|          | ||||
|         // If EOF, return EOF | ||||
|         if (instructionBuffer == null) | ||||
|             return null; | ||||
|          | ||||
|         // Start of element | ||||
|         int elementStart = 0; | ||||
|          | ||||
|         // Build list of elements | ||||
|         LinkedList<String> elements = new LinkedList<String>(); | ||||
|         while (instructionStart < instructionBuffer.length) { | ||||
|         while (elementStart < instructionBuffer.length) { | ||||
|  | ||||
|             // Find end of length  | ||||
|             int lengthEnd = ArrayUtils.indexOf(instructionBuffer, '.', instructionStart); | ||||
|             int lengthEnd = ArrayUtils.indexOf(instructionBuffer, '.', elementStart); | ||||
|  | ||||
|             // Parse length | ||||
|             int length = Integer.parseInt(new String( | ||||
|                     instructionBuffer, | ||||
|                     instructionStart, | ||||
|                     lengthEnd - instructionStart | ||||
|                     elementStart, | ||||
|                     lengthEnd - elementStart | ||||
|             )); | ||||
|  | ||||
|             // Parse element from just after period | ||||
|             instructionStart = lengthEnd + 1; | ||||
|             elementStart = lengthEnd + 1; | ||||
|             String element = new String( | ||||
|                     instructionBuffer, | ||||
|                     instructionStart, | ||||
|                     elementStart, | ||||
|                     length | ||||
|             ); | ||||
|  | ||||
| @@ -174,11 +210,11 @@ public class ReaderGuacamoleReader implements GuacamoleReader { | ||||
|             elements.addLast(element); | ||||
|              | ||||
|             // Read terminator after element | ||||
|             instructionStart += length; | ||||
|             char terminator = instructionBuffer[instructionStart]; | ||||
|             elementStart += length; | ||||
|             char terminator = instructionBuffer[elementStart]; | ||||
|  | ||||
|             // Continue reading instructions after terminator | ||||
|             instructionStart++; | ||||
|             elementStart++; | ||||
|             | ||||
|             // If we've reached the end of the instruction | ||||
|             if (terminator == ';') | ||||
| @@ -195,10 +231,6 @@ public class ReaderGuacamoleReader implements GuacamoleReader { | ||||
|                 elements.toArray(new String[elements.size()]) | ||||
|         ); | ||||
|  | ||||
|         // Detect end of buffer | ||||
|         if (instructionStart >= instructionBuffer.length) | ||||
|             instructionBuffer = null; | ||||
|  | ||||
|         // Return parsed instruction | ||||
|         return instruction; | ||||
|  | ||||
|   | ||||
		Reference in New Issue
	
	Block a user