Add support for unicode escapes outside of the char limit

This commit is contained in:
ME1312 2018-10-30 15:12:53 -04:00
parent b2bbff0692
commit 114f4f2209
No known key found for this signature in database
GPG Key ID: FEFFE2F698E88FA8
6 changed files with 251 additions and 111 deletions

View File

@ -328,29 +328,29 @@ public final class Util {
* @return Unescaped String
*/
public static String unescapeJavaString(String str) {
StringBuilder sb = new StringBuilder(str.length());
for (int i = 0; i < str.length(); i++) {
char ch = str.charAt(i);
int ch = str.codePointAt(i);
if (ch == '\\') {
char nextChar = (i == str.length() - 1) ? '\\' : str
.charAt(i + 1);
int nextChar = (i == str.length() - 1) ? '\\' : str
.codePointAt(i + 1);
// Octal escape?
if (nextChar >= '0' && nextChar <= '7') {
String code = "" + nextChar;
StringBuilder code = new StringBuilder();
code.appendCodePoint(nextChar);
i++;
if ((i < str.length() - 1) && str.charAt(i + 1) >= '0'
&& str.charAt(i + 1) <= '7') {
code += str.charAt(i + 1);
if ((i < str.length() - 1) && str.codePointAt(i + 1) >= '0'
&& str.codePointAt(i + 1) <= '7') {
code.appendCodePoint(str.codePointAt(i + 1));
i++;
if ((i < str.length() - 1) && str.charAt(i + 1) >= '0'
&& str.charAt(i + 1) <= '7') {
code += str.charAt(i + 1);
if ((i < str.length() - 1) && str.codePointAt(i + 1) >= '0'
&& str.codePointAt(i + 1) <= '7') {
code.appendCodePoint(str.codePointAt(i + 1));
i++;
}
}
sb.append((char) Integer.parseInt(code, 8));
sb.append((char) Integer.parseInt(code.toString(), 8));
continue;
}
switch (nextChar) {
@ -378,22 +378,45 @@ public final class Util {
case '\'':
ch = '\'';
break;
// Hex Unicode: u????
// Hex Unicode Char: u????
// Hex Unicode Codepoint: u{??????}
case 'u':
if (i >= str.length() - 5) {
try {
if (i >= str.length() - 4) throw new IllegalStateException();
StringBuilder escape = new StringBuilder();
int offset = 2;
if (str.codePointAt(i + 2) != '{') {
if (i >= str.length() - 5) throw new IllegalStateException();
while (offset <= 5) {
Integer.toString(str.codePointAt(i + offset), 16);
escape.appendCodePoint(str.codePointAt(i + offset));
offset++;
}
offset--;
} else {
offset++;
while (str.codePointAt(i + offset) != '}') {
Integer.toString(str.codePointAt(i + offset), 16);
escape.appendCodePoint(str.codePointAt(i + offset));
offset++;
}
}
sb.append(new String(new int[]{
Integer.parseInt(escape.toString(), 16)
}, 0, 1));
i += offset;
continue;
} catch (Throwable e){
sb.append('\\');
ch = 'u';
break;
}
int code = Integer.parseInt(
"" + str.charAt(i + 2) + str.charAt(i + 3)
+ str.charAt(i + 4) + str.charAt(i + 5), 16);
sb.append(Character.toChars(code));
i += 5;
continue;
}
i++;
}
sb.append(ch);
sb.appendCodePoint(ch);
}
return sb.toString();
}

View File

@ -249,29 +249,29 @@ public final class Util {
* @return Unescaped String
*/
public static String unescapeJavaString(String str) {
StringBuilder sb = new StringBuilder(str.length());
for (int i = 0; i < str.length(); i++) {
char ch = str.charAt(i);
int ch = str.codePointAt(i);
if (ch == '\\') {
char nextChar = (i == str.length() - 1) ? '\\' : str
.charAt(i + 1);
int nextChar = (i == str.length() - 1) ? '\\' : str
.codePointAt(i + 1);
// Octal escape?
if (nextChar >= '0' && nextChar <= '7') {
String code = "" + nextChar;
StringBuilder code = new StringBuilder();
code.appendCodePoint(nextChar);
i++;
if ((i < str.length() - 1) && str.charAt(i + 1) >= '0'
&& str.charAt(i + 1) <= '7') {
code += str.charAt(i + 1);
if ((i < str.length() - 1) && str.codePointAt(i + 1) >= '0'
&& str.codePointAt(i + 1) <= '7') {
code.appendCodePoint(str.codePointAt(i + 1));
i++;
if ((i < str.length() - 1) && str.charAt(i + 1) >= '0'
&& str.charAt(i + 1) <= '7') {
code += str.charAt(i + 1);
if ((i < str.length() - 1) && str.codePointAt(i + 1) >= '0'
&& str.codePointAt(i + 1) <= '7') {
code.appendCodePoint(str.codePointAt(i + 1));
i++;
}
}
sb.append((char) Integer.parseInt(code, 8));
sb.append((char) Integer.parseInt(code.toString(), 8));
continue;
}
switch (nextChar) {
@ -299,22 +299,45 @@ public final class Util {
case '\'':
ch = '\'';
break;
// Hex Unicode: u????
// Hex Unicode Char: u????
// Hex Unicode Codepoint: u{??????}
case 'u':
if (i >= str.length() - 5) {
try {
if (i >= str.length() - 4) throw new IllegalStateException();
StringBuilder escape = new StringBuilder();
int offset = 2;
if (str.codePointAt(i + 2) != '{') {
if (i >= str.length() - 5) throw new IllegalStateException();
while (offset <= 5) {
Integer.toString(str.codePointAt(i + offset), 16);
escape.appendCodePoint(str.codePointAt(i + offset));
offset++;
}
offset--;
} else {
offset++;
while (str.codePointAt(i + offset) != '}') {
Integer.toString(str.codePointAt(i + offset), 16);
escape.appendCodePoint(str.codePointAt(i + offset));
offset++;
}
}
sb.append(new String(new int[]{
Integer.parseInt(escape.toString(), 16)
}, 0, 1));
i += offset;
continue;
} catch (Throwable e){
sb.append('\\');
ch = 'u';
break;
}
int code = Integer.parseInt(
"" + str.charAt(i + 2) + str.charAt(i + 3)
+ str.charAt(i + 4) + str.charAt(i + 5), 16);
sb.append(Character.toChars(code));
i += 5;
continue;
}
i++;
}
sb.append(ch);
sb.appendCodePoint(ch);
}
return sb.toString();
}

View File

@ -249,29 +249,29 @@ public final class Util {
* @return Unescaped String
*/
public static String unescapeJavaString(String str) {
StringBuilder sb = new StringBuilder(str.length());
for (int i = 0; i < str.length(); i++) {
char ch = str.charAt(i);
int ch = str.codePointAt(i);
if (ch == '\\') {
char nextChar = (i == str.length() - 1) ? '\\' : str
.charAt(i + 1);
int nextChar = (i == str.length() - 1) ? '\\' : str
.codePointAt(i + 1);
// Octal escape?
if (nextChar >= '0' && nextChar <= '7') {
String code = "" + nextChar;
StringBuilder code = new StringBuilder();
code.appendCodePoint(nextChar);
i++;
if ((i < str.length() - 1) && str.charAt(i + 1) >= '0'
&& str.charAt(i + 1) <= '7') {
code += str.charAt(i + 1);
if ((i < str.length() - 1) && str.codePointAt(i + 1) >= '0'
&& str.codePointAt(i + 1) <= '7') {
code.appendCodePoint(str.codePointAt(i + 1));
i++;
if ((i < str.length() - 1) && str.charAt(i + 1) >= '0'
&& str.charAt(i + 1) <= '7') {
code += str.charAt(i + 1);
if ((i < str.length() - 1) && str.codePointAt(i + 1) >= '0'
&& str.codePointAt(i + 1) <= '7') {
code.appendCodePoint(str.codePointAt(i + 1));
i++;
}
}
sb.append((char) Integer.parseInt(code, 8));
sb.append((char) Integer.parseInt(code.toString(), 8));
continue;
}
switch (nextChar) {
@ -299,22 +299,45 @@ public final class Util {
case '\'':
ch = '\'';
break;
// Hex Unicode: u????
// Hex Unicode Char: u????
// Hex Unicode Codepoint: u{??????}
case 'u':
if (i >= str.length() - 5) {
try {
if (i >= str.length() - 4) throw new IllegalStateException();
StringBuilder escape = new StringBuilder();
int offset = 2;
if (str.codePointAt(i + 2) != '{') {
if (i >= str.length() - 5) throw new IllegalStateException();
while (offset <= 5) {
Integer.toString(str.codePointAt(i + offset), 16);
escape.appendCodePoint(str.codePointAt(i + offset));
offset++;
}
offset--;
} else {
offset++;
while (str.codePointAt(i + offset) != '}') {
Integer.toString(str.codePointAt(i + offset), 16);
escape.appendCodePoint(str.codePointAt(i + offset));
offset++;
}
}
sb.append(new String(new int[]{
Integer.parseInt(escape.toString(), 16)
}, 0, 1));
i += offset;
continue;
} catch (Throwable e){
sb.append('\\');
ch = 'u';
break;
}
int code = Integer.parseInt(
"" + str.charAt(i + 2) + str.charAt(i + 3)
+ str.charAt(i + 4) + str.charAt(i + 5), 16);
sb.append(Character.toChars(code));
i += 5;
continue;
}
i++;
}
sb.append(ch);
sb.appendCodePoint(ch);
}
return sb.toString();
}

View File

@ -6,17 +6,19 @@ import java.io.IOException;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
public class AnsiHTMLColorStream extends AnsiOutputStream {
private boolean concealOn = false;
private static final String[] ANSI_COLOR_MAP = new String[]{"000000", "cd0000", "25bc24", "e1e100", "0000ee", "cd00cd", "00e1e1", "ffffff"};
private static final byte[] BYTES_NBSP = "&nbsp;".getBytes();
private static final byte[] BYTES_QUOT = "&quot;".getBytes();
private static final byte[] BYTES_AMP = "&amp;".getBytes();
private static final byte[] BYTES_LT = "&lt;".getBytes();
private static final byte[] BYTES_GT = "&gt;".getBytes();
private List<String> closingAttributes = new ArrayList();
private LinkedList<String> closingAttributes = new LinkedList<String>();
private boolean underline = false;
private boolean strikethrough = false;
public void close() throws IOException {
this.closeAttributes();
@ -33,22 +35,45 @@ public class AnsiHTMLColorStream extends AnsiOutputStream {
private void writeAttribute(String s) throws IOException {
this.write("<" + s + ">");
this.closingAttributes.add(0, s.split(" ", 2)[0]);
this.closingAttributes.add(0, s);
}
private void closeAttribute(String s) throws IOException {
LinkedList<String> closedAttributes = new LinkedList<String>();
LinkedList<String> closingAttributes = new LinkedList<String>();
LinkedList<String> unclosedAttributes = new LinkedList<String>();
closingAttributes.addAll(this.closingAttributes);
for (String attr : closingAttributes) {
if (attr.toLowerCase().startsWith(s.toLowerCase())) {
for (String a : unclosedAttributes) {
closedAttributes.add(0, a);
this.write("</" + a.split(" ", 2)[0] + ">");
}
this.closingAttributes.removeFirstOccurrence(attr);
unclosedAttributes.clear();
this.write("</" + attr.split(" ", 2)[0] + ">");
} else {
unclosedAttributes.add(attr);
}
}
for (String attr : closedAttributes) {
this.write("<" + attr + ">");
}
}
private void closeAttributes() throws IOException {
Iterator i$ = this.closingAttributes.iterator();
while(i$.hasNext()) {
String attr = (String)i$.next();
this.write("</" + attr + ">");
for (String attr : closingAttributes) {
this.write("</" + attr.split(" ", 2)[0] + ">");
}
this.underline = false;
this.strikethrough = false;
this.closingAttributes.clear();
}
private boolean nbsp = true;
public void write(int data) throws IOException {
@Override public void write(int data) throws IOException {
if (data == 32) {
if (nbsp) this.out.write(BYTES_NBSP);
else super.write(data);
@ -79,43 +104,66 @@ public class AnsiHTMLColorStream extends AnsiOutputStream {
this.closeAttributes();
}
private String parseTextDecoration() {
String dec = "";
if (underline) dec += " underline";
if (strikethrough) dec += " line-through";
if (dec.length() <= 0) dec += " none";
return dec.substring(1);
}
@Override
protected void processSetAttribute(int attribute) throws IOException {
switch(attribute) {
case 1:
this.writeAttribute("b");
break;
case 4:
this.writeAttribute("u");
case 7:
case 27:
default:
case 3:
this.writeAttribute("i");
break;
case 8:
this.write("\u001b[8m");
this.concealOn = true;
case 4:
this.closeAttribute("span class=\"ansi-decoration");
this.underline = true;
this.writeAttribute("span class=\"ansi-decoration\" style=\"text-decoration: " + parseTextDecoration() + ";\"");
break;
case 9:
this.closeAttribute("span class=\"ansi-decoration");
this.strikethrough = true;
this.writeAttribute("span class=\"ansi-decoration\" style=\"text-decoration: " + parseTextDecoration() + ";\"");
break;
case 22:
this.closeAttributes();
this.closeAttribute("b");
break;
case 23:
this.closeAttribute("i");
break;
case 24:
this.closeAttributes();
this.closeAttribute("span class=\"ansi-decoration");
this.underline = false;
this.writeAttribute("span class=\"ansi-decoration\" style=\"text-decoration: " + parseTextDecoration() + ";\"");
break;
case 29:
this.closeAttribute("span class=\"ansi-decoration");
this.strikethrough = false;
this.writeAttribute("span class=\"ansi-decoration\" style=\"text-decoration: " + parseTextDecoration() + ";\"");
break;
default:
break;
}
}
@Override
protected void processAttributeRest() throws IOException {
if (this.concealOn) {
this.write("\u001b[0m");
this.concealOn = false;
}
this.closeAttributes();
}
@Override
protected void processSetForegroundColor(int color) throws IOException {
this.writeAttribute("span class=\"ansi\" style=\"color: #" + ANSI_COLOR_MAP[color] + ";\"");
this.writeAttribute("span class=\"ansi-foreground\" style=\"color: #" + ANSI_COLOR_MAP[color] + ";\"");
}
@Override
protected void processSetBackgroundColor(int color) throws IOException {
this.writeAttribute("span class=\"ansi-background\" style=\"background-color: #" + ANSI_COLOR_MAP[color] + ";\"");
}

View File

@ -20,7 +20,7 @@
<dependency>
<groupId>net.ME1312.Galaxi</groupId>
<artifactId>GalaxiEngine</artifactId>
<version>18w43g</version>
<version>18w44a</version>
<scope>compile</scope>
</dependency>
<dependency>

View File

@ -249,29 +249,29 @@ public final class Util {
* @return Unescaped String
*/
public static String unescapeJavaString(String str) {
StringBuilder sb = new StringBuilder(str.length());
for (int i = 0; i < str.length(); i++) {
char ch = str.charAt(i);
int ch = str.codePointAt(i);
if (ch == '\\') {
char nextChar = (i == str.length() - 1) ? '\\' : str
.charAt(i + 1);
int nextChar = (i == str.length() - 1) ? '\\' : str
.codePointAt(i + 1);
// Octal escape?
if (nextChar >= '0' && nextChar <= '7') {
String code = "" + nextChar;
StringBuilder code = new StringBuilder();
code.appendCodePoint(nextChar);
i++;
if ((i < str.length() - 1) && str.charAt(i + 1) >= '0'
&& str.charAt(i + 1) <= '7') {
code += str.charAt(i + 1);
if ((i < str.length() - 1) && str.codePointAt(i + 1) >= '0'
&& str.codePointAt(i + 1) <= '7') {
code.appendCodePoint(str.codePointAt(i + 1));
i++;
if ((i < str.length() - 1) && str.charAt(i + 1) >= '0'
&& str.charAt(i + 1) <= '7') {
code += str.charAt(i + 1);
if ((i < str.length() - 1) && str.codePointAt(i + 1) >= '0'
&& str.codePointAt(i + 1) <= '7') {
code.appendCodePoint(str.codePointAt(i + 1));
i++;
}
}
sb.append((char) Integer.parseInt(code, 8));
sb.append((char) Integer.parseInt(code.toString(), 8));
continue;
}
switch (nextChar) {
@ -299,22 +299,45 @@ public final class Util {
case '\'':
ch = '\'';
break;
// Hex Unicode: u????
// Hex Unicode Char: u????
// Hex Unicode Codepoint: u{??????}
case 'u':
if (i >= str.length() - 5) {
try {
if (i >= str.length() - 4) throw new IllegalStateException();
StringBuilder escape = new StringBuilder();
int offset = 2;
if (str.codePointAt(i + 2) != '{') {
if (i >= str.length() - 5) throw new IllegalStateException();
while (offset <= 5) {
Integer.toString(str.codePointAt(i + offset), 16);
escape.appendCodePoint(str.codePointAt(i + offset));
offset++;
}
offset--;
} else {
offset++;
while (str.codePointAt(i + offset) != '}') {
Integer.toString(str.codePointAt(i + offset), 16);
escape.appendCodePoint(str.codePointAt(i + offset));
offset++;
}
}
sb.append(new String(new int[]{
Integer.parseInt(escape.toString(), 16)
}, 0, 1));
i += offset;
continue;
} catch (Throwable e){
sb.append('\\');
ch = 'u';
break;
}
int code = Integer.parseInt(
"" + str.charAt(i + 2) + str.charAt(i + 3)
+ str.charAt(i + 4) + str.charAt(i + 5), 16);
sb.append(Character.toChars(code));
i += 5;
continue;
}
i++;
}
sb.append(ch);
sb.appendCodePoint(ch);
}
return sb.toString();
}