2 changed files with 118 additions and 1 deletions
-
8src/main/java/com/corundumstudio/socketio/protocol/PacketDecoder.java
-
111src/main/java/com/corundumstudio/socketio/protocol/UTF8CharsScanner.java
@ -0,0 +1,111 @@ |
|||
package com.corundumstudio.socketio.protocol; |
|||
|
|||
import io.netty.buffer.ByteBuf; |
|||
|
|||
public class UTF8CharsScanner { |
|||
|
|||
/** |
|||
* Lookup table used for determining which input characters need special |
|||
* handling when contained in text segment. |
|||
*/ |
|||
final static int[] sInputCodes; |
|||
static { |
|||
/* |
|||
* 96 would do for most cases (backslash is ascii 94) but if we want to |
|||
* do lookups by raw bytes it's better to have full table |
|||
*/ |
|||
int[] table = new int[256]; |
|||
// Control chars and non-space white space are not allowed unquoted |
|||
for (int i = 0; i < 32; ++i) { |
|||
table[i] = -1; |
|||
} |
|||
// And then string end and quote markers are special too |
|||
table['"'] = 1; |
|||
table['\\'] = 1; |
|||
sInputCodes = table; |
|||
} |
|||
|
|||
/** |
|||
* Additionally we can combine UTF-8 decoding info into similar data table. |
|||
*/ |
|||
final static int[] sInputCodesUtf8; |
|||
static { |
|||
int[] table = new int[sInputCodes.length]; |
|||
System.arraycopy(sInputCodes, 0, table, 0, sInputCodes.length); |
|||
for (int c = 128; c < 256; ++c) { |
|||
int code; |
|||
|
|||
// We'll add number of bytes needed for decoding |
|||
if ((c & 0xE0) == 0xC0) { // 2 bytes (0x0080 - 0x07FF) |
|||
code = 2; |
|||
} else if ((c & 0xF0) == 0xE0) { // 3 bytes (0x0800 - 0xFFFF) |
|||
code = 3; |
|||
} else if ((c & 0xF8) == 0xF0) { |
|||
// 4 bytes; double-char with surrogates and all... |
|||
code = 4; |
|||
} else { |
|||
// And -1 seems like a good "universal" error marker... |
|||
code = -1; |
|||
} |
|||
table[c] = code; |
|||
} |
|||
sInputCodesUtf8 = table; |
|||
} |
|||
|
|||
private int getCharTailIndex(ByteBuf inputBuffer, int i) { |
|||
int c = (int) inputBuffer.getByte(i) & 0xFF; |
|||
switch (sInputCodesUtf8[c]) { |
|||
case 2: // 2-byte UTF |
|||
i += 2; |
|||
break; |
|||
case 3: // 3-byte UTF |
|||
i += 3; |
|||
break; |
|||
case 4: // 4-byte UTF |
|||
i += 4; |
|||
break; |
|||
default: |
|||
i++; |
|||
break; |
|||
} |
|||
return i; |
|||
} |
|||
|
|||
public int getLength(ByteBuf inputBuffer, int start) { |
|||
int len = 0; |
|||
for (int i = start; i < inputBuffer.writerIndex();) { |
|||
i = getCharTailIndex(inputBuffer, i); |
|||
len++; |
|||
} |
|||
return len; |
|||
} |
|||
|
|||
public int getActualLength(ByteBuf inputBuffer, int length) { |
|||
int len = 0; |
|||
int start = inputBuffer.readerIndex(); |
|||
for (int i = inputBuffer.readerIndex(); i < inputBuffer.readableBytes() + inputBuffer.readerIndex();) { |
|||
i = getCharTailIndex(inputBuffer, i); |
|||
len++; |
|||
if (length == len) { |
|||
return i-start; |
|||
} |
|||
} |
|||
throw new IllegalStateException(); |
|||
} |
|||
|
|||
|
|||
public int findTailIndex(ByteBuf inputBuffer, int start, int end, |
|||
int charsToRead) { |
|||
int len = 0; |
|||
int i = start; |
|||
while (i < end) { |
|||
i = getCharTailIndex(inputBuffer, i); |
|||
len++; |
|||
if (charsToRead == len) { |
|||
break; |
|||
} |
|||
} |
|||
return i; |
|||
} |
|||
|
|||
} |
Write
Preview
Loading…
Cancel
Save
Reference in new issue