mirror of
https://github.com/Eaglercraft-Archive/Eaglercraftx-1.8.8-src.git
synced 2025-06-27 18:38:14 -05:00
Update #48 - Added some features from OptiFine
This commit is contained in:
@ -0,0 +1,326 @@
|
||||
/*
|
||||
* Copyright (c) 1995, 2013, Oracle and/or its affiliates. All rights reserved.
|
||||
* ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
|
||||
*/
|
||||
|
||||
package net.lax1dude.eaglercraft.v1_8;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.Reader;
|
||||
import java.util.Properties;
|
||||
|
||||
public class EaglerProperties extends Properties {
|
||||
|
||||
public void load(Reader reader) throws IOException {
|
||||
load0(new LineReader(reader));
|
||||
}
|
||||
|
||||
public void load(InputStream inStream) throws IOException {
|
||||
load0(new LineReader(inStream));
|
||||
}
|
||||
|
||||
private void load0(LineReader lr) throws IOException {
|
||||
StringBuilder outBuffer = new StringBuilder();
|
||||
int limit;
|
||||
int keyLen;
|
||||
int valueStart;
|
||||
boolean hasSep;
|
||||
boolean precedingBackslash;
|
||||
boolean first = true;
|
||||
|
||||
while ((limit = lr.readLine()) >= 0) {
|
||||
keyLen = 0;
|
||||
valueStart = limit;
|
||||
hasSep = false;
|
||||
if(first && limit > 0) {
|
||||
if(lr.lineBuf[0] == 65279) {
|
||||
keyLen = 1;
|
||||
}
|
||||
}
|
||||
first = false;
|
||||
|
||||
// System.out.println("line=<" + new String(lineBuf, 0, limit) + ">");
|
||||
precedingBackslash = false;
|
||||
while (keyLen < limit) {
|
||||
char c = lr.lineBuf[keyLen];
|
||||
// need check if escaped.
|
||||
if ((c == '=' || c == ':') && !precedingBackslash) {
|
||||
valueStart = keyLen + 1;
|
||||
hasSep = true;
|
||||
break;
|
||||
} else if ((c == ' ' || c == '\t' || c == '\f') && !precedingBackslash) {
|
||||
valueStart = keyLen + 1;
|
||||
break;
|
||||
}
|
||||
if (c == '\\') {
|
||||
precedingBackslash = !precedingBackslash;
|
||||
} else {
|
||||
precedingBackslash = false;
|
||||
}
|
||||
keyLen++;
|
||||
}
|
||||
while (valueStart < limit) {
|
||||
char c = lr.lineBuf[valueStart];
|
||||
if (c != ' ' && c != '\t' && c != '\f') {
|
||||
if (!hasSep && (c == '=' || c == ':')) {
|
||||
hasSep = true;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
valueStart++;
|
||||
}
|
||||
String key = loadConvert(lr.lineBuf, 0, keyLen, outBuffer);
|
||||
String value = loadConvert(lr.lineBuf, valueStart, limit - valueStart, outBuffer);
|
||||
put(key, value);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Read in a "logical line" from an InputStream/Reader, skip all comment and
|
||||
* blank lines and filter out those leading whitespace characters (\u0020,
|
||||
* \u0009 and \u000c) from the beginning of a "natural line". Method returns the
|
||||
* char length of the "logical line" and stores the line in "lineBuf".
|
||||
*/
|
||||
private static class LineReader {
|
||||
LineReader(InputStream inStream) {
|
||||
this.inStream = inStream;
|
||||
inByteBuf = new byte[8192];
|
||||
}
|
||||
|
||||
LineReader(Reader reader) {
|
||||
this.reader = reader;
|
||||
inCharBuf = new char[8192];
|
||||
}
|
||||
|
||||
char[] lineBuf = new char[1024];
|
||||
private byte[] inByteBuf;
|
||||
private char[] inCharBuf;
|
||||
private int inLimit = 0;
|
||||
private int inOff = 0;
|
||||
private InputStream inStream;
|
||||
private Reader reader;
|
||||
|
||||
int readLine() throws IOException {
|
||||
// use locals to optimize for interpreted performance
|
||||
int len = 0;
|
||||
int off = inOff;
|
||||
int limit = inLimit;
|
||||
|
||||
boolean skipWhiteSpace = true;
|
||||
boolean appendedLineBegin = false;
|
||||
boolean precedingBackslash = false;
|
||||
boolean fromStream = inStream != null;
|
||||
byte[] byteBuf = inByteBuf;
|
||||
char[] charBuf = inCharBuf;
|
||||
char[] lineBuf = this.lineBuf;
|
||||
char c;
|
||||
|
||||
while (true) {
|
||||
if (off >= limit) {
|
||||
inLimit = limit = fromStream ? inStream.read(byteBuf) : reader.read(charBuf);
|
||||
if (limit <= 0) {
|
||||
if (len == 0) {
|
||||
return -1;
|
||||
}
|
||||
return precedingBackslash ? len - 1 : len;
|
||||
}
|
||||
off = 0;
|
||||
}
|
||||
|
||||
// (char)(byte & 0xFF) is equivalent to calling a ISO8859-1 decoder.
|
||||
c = (fromStream) ? (char) (byteBuf[off++] & 0xFF) : charBuf[off++];
|
||||
|
||||
if (skipWhiteSpace) {
|
||||
if (c == ' ' || c == '\t' || c == '\f') {
|
||||
continue;
|
||||
}
|
||||
if (!appendedLineBegin && (c == '\r' || c == '\n')) {
|
||||
continue;
|
||||
}
|
||||
skipWhiteSpace = false;
|
||||
appendedLineBegin = false;
|
||||
|
||||
}
|
||||
if (len == 0) { // Still on a new logical line
|
||||
if (c == '#' || c == '!') {
|
||||
// Comment, quickly consume the rest of the line
|
||||
|
||||
// When checking for new line characters a range check,
|
||||
// starting with the higher bound ('\r') means one less
|
||||
// branch in the common case.
|
||||
commentLoop: while (true) {
|
||||
if (fromStream) {
|
||||
byte b;
|
||||
while (off < limit) {
|
||||
b = byteBuf[off++];
|
||||
if (b <= '\r' && (b == '\r' || b == '\n'))
|
||||
break commentLoop;
|
||||
}
|
||||
if (off == limit) {
|
||||
inLimit = limit = inStream.read(byteBuf);
|
||||
if (limit <= 0) { // EOF
|
||||
return -1;
|
||||
}
|
||||
off = 0;
|
||||
}
|
||||
} else {
|
||||
while (off < limit) {
|
||||
c = charBuf[off++];
|
||||
if (c <= '\r' && (c == '\r' || c == '\n'))
|
||||
break commentLoop;
|
||||
}
|
||||
if (off == limit) {
|
||||
inLimit = limit = reader.read(charBuf);
|
||||
if (limit <= 0) { // EOF
|
||||
return -1;
|
||||
}
|
||||
off = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
skipWhiteSpace = true;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (c != '\n' && c != '\r') {
|
||||
lineBuf[len++] = c;
|
||||
if (len == lineBuf.length) {
|
||||
lineBuf = new char[len + (len << 1)];
|
||||
System.arraycopy(this.lineBuf, 0, lineBuf, 0, len);
|
||||
this.lineBuf = lineBuf;
|
||||
}
|
||||
// flip the preceding backslash flag
|
||||
precedingBackslash = (c == '\\') ? !precedingBackslash : false;
|
||||
} else {
|
||||
// reached EOL
|
||||
if (len == 0) {
|
||||
skipWhiteSpace = true;
|
||||
continue;
|
||||
}
|
||||
if (off >= limit) {
|
||||
inLimit = limit = fromStream ? inStream.read(byteBuf) : reader.read(charBuf);
|
||||
off = 0;
|
||||
if (limit <= 0) { // EOF
|
||||
return precedingBackslash ? len - 1 : len;
|
||||
}
|
||||
}
|
||||
if (precedingBackslash) {
|
||||
// backslash at EOL is not part of the line
|
||||
len -= 1;
|
||||
// skip leading whitespace characters in the following line
|
||||
skipWhiteSpace = true;
|
||||
appendedLineBegin = true;
|
||||
precedingBackslash = false;
|
||||
// take care not to include any subsequent \n
|
||||
if (c == '\r') {
|
||||
if (fromStream) {
|
||||
if (byteBuf[off] == '\n') {
|
||||
off++;
|
||||
}
|
||||
} else {
|
||||
if (charBuf[off] == '\n') {
|
||||
off++;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
inOff = off;
|
||||
return len;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Converts encoded \uxxxx to unicode chars and changes special saved chars
|
||||
* to their original forms
|
||||
*/
|
||||
private String loadConvert(char[] in, int off, int len, StringBuilder out) {
|
||||
char aChar;
|
||||
int end = off + len;
|
||||
int start = off;
|
||||
while (off < end) {
|
||||
aChar = in[off++];
|
||||
if (aChar == '\\') {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (off == end) { // No backslash
|
||||
return new String(in, start, len);
|
||||
}
|
||||
|
||||
// backslash found at off - 1, reset the shared buffer, rewind offset
|
||||
out.setLength(0);
|
||||
off--;
|
||||
out.append(in, start, off - start);
|
||||
|
||||
while (off < end) {
|
||||
aChar = in[off++];
|
||||
if (aChar == '\\') {
|
||||
// No need to bounds check since LineReader::readLine excludes
|
||||
// unescaped \s at the end of the line
|
||||
aChar = in[off++];
|
||||
if (aChar == 'u') {
|
||||
// Read the xxxx
|
||||
if (off > end - 4)
|
||||
throw new IllegalArgumentException("Malformed \\uxxxx encoding.");
|
||||
int value = 0;
|
||||
for (int i = 0; i < 4; i++) {
|
||||
aChar = in[off++];
|
||||
switch (aChar) {
|
||||
case '0':
|
||||
case '1':
|
||||
case '2':
|
||||
case '3':
|
||||
case '4':
|
||||
case '5':
|
||||
case '6':
|
||||
case '7':
|
||||
case '8':
|
||||
case '9':
|
||||
value = (value << 4) + aChar - '0';
|
||||
break;
|
||||
case 'a':
|
||||
case 'b':
|
||||
case 'c':
|
||||
case 'd':
|
||||
case 'e':
|
||||
case 'f':
|
||||
value = (value << 4) + 10 + aChar - 'a';
|
||||
break;
|
||||
case 'A':
|
||||
case 'B':
|
||||
case 'C':
|
||||
case 'D':
|
||||
case 'E':
|
||||
case 'F':
|
||||
value = (value << 4) + 10 + aChar - 'A';
|
||||
break;
|
||||
default:
|
||||
throw new IllegalArgumentException("Malformed \\uxxxx encoding.");
|
||||
};
|
||||
}
|
||||
out.append((char) value);
|
||||
} else {
|
||||
if (aChar == 't')
|
||||
aChar = '\t';
|
||||
else if (aChar == 'r')
|
||||
aChar = '\r';
|
||||
else if (aChar == 'n')
|
||||
aChar = '\n';
|
||||
else if (aChar == 'f')
|
||||
aChar = '\f';
|
||||
out.append(aChar);
|
||||
}
|
||||
} else {
|
||||
out.append(aChar);
|
||||
}
|
||||
}
|
||||
return out.toString();
|
||||
}
|
||||
|
||||
}
|
Reference in New Issue
Block a user