/*
Реализация спецификаций CLDC версии 1.1 (JSR-139), MIDP версии 2.1 (JSR-118)
и других спецификаций для функционирования компактных приложений на языке
Java (мидлетов) в среде программного обеспечения Малик Эмулятор.
Copyright © 2016–2017, 2019–2023 Малик Разработчик
Это свободная программа: вы можете перераспространять ее и/или изменять
ее на условиях Меньшей Стандартной общественной лицензии GNU в том виде,
в каком она была опубликована Фондом свободного программного обеспечения;
либо версии 3 лицензии, либо (по вашему выбору) любой более поздней версии.
Эта программа распространяется в надежде, что она будет полезной,
но БЕЗО ВСЯКИХ ГАРАНТИЙ; даже без неявной гарантии ТОВАРНОГО ВИДА
или ПРИГОДНОСТИ ДЛЯ ОПРЕДЕЛЕННЫХ ЦЕЛЕЙ. Подробнее см. в Меньшей Стандартной
общественной лицензии GNU.
Вы должны были получить копию Меньшей Стандартной общественной лицензии GNU
вместе с этой программой. Если это не так, см.
<https://www.gnu.org/licenses/>.
*/
package malik.emulator.fileformats.text.mapped;
import java.io.*;
import malik.emulator.fileformats.*;
public final class ManifestDecoder extends CustomKeyValueList implements AttributedTextDecoder
{
private static int skipLineEndings(byte[] stream, int offset) {
int i = offset;
for(int c; (c = stream[i]) == '\n' || c == '\r'; i += c == '\r' && stream[i + 1] == '\n' ? 2 : 1);
return i;
}
private String parsed;
private final Object monitor;
public ManifestDecoder() {
this.monitor = new Object();
}
public void loadFromInputStream(InputStream stream) throws IOException {
int size;
byte[] s;
stream.read(s = new byte[(size = stream.available()) + 1], 0, size);
synchronized(monitor)
{
clear();
try
{
String key;
String value;
for(int i = size >= 3 && s[0] == (byte) 0xef && s[1] == (byte) 0xbb && s[2] == (byte) 0xbf ? 3 : 0; s[i = skipLineEndings(s, i)] != 0 && i < size; set(key, value))
{
if(s[i = parseKey(s, i)] != ':')
{
throw new InvalidManifestFileFormatException("ManifestDecoder.loadFromInputStream: неправильный формат файла MANIFEST.MF.");
}
key = parsed.intern();
i = parseValue(s, i + 1);
value = parsed.intern();
}
}
finally
{
parsed = null;
}
}
}
public void loadFromInputStream(InputStream stream, String encoding) throws IOException {
loadFromInputStream(stream);
}
public void loadFromDataStream(ExtendedDataInputStream stream) throws IOException {
loadFromInputStream(stream);
}
public void loadFromDataStream(ExtendedDataInputStream stream, String encoding) throws IOException {
loadFromInputStream(stream);
}
public String[] getAttributes(String key) {
int i;
int j;
int len;
int index;
String[] result;
String value;
if((value = get(key)) == null) return null;
if((value = value.trim()).length() <= 0) return new String[0];
for(len = 1, j = 0; (j = value.indexOf(',', j)) >= 0; j++) len++;
for(result = new String[len], i = j = index = 0; (j = value.indexOf(',', j)) >= 0; i = ++j) result[index++] = value.substring(i, j).trim().intern();
result[index] = value.substring(i).trim().intern();
return result;
}
private int parseKey(byte[] stream, int offset) throws InvalidManifestFileFormatException {
int c;
int i = offset;
if(((c = stream[i++]) < '0' || c > '9') && (c < 'A' || c > 'Z') && (c < 'a' || c > 'z'))
{
throw new InvalidManifestFileFormatException("ManifestFile.loadFromInputStream: неправильный формат файла MANIFEST.MF.");
}
for(; ((c = stream[i]) >= '0' && c <= '9') || (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z') || c == '-' || c == '_'; i++);
parsed = new String(stream, offset, i - offset);
return i;
}
private int parseValue(byte[] stream, int offset) {
int c;
int i = offset;
ByteArrayOutputStream result = new ByteArrayOutputStream();
if(stream[i] == ' ') offset = ++i;
for(; ; )
{
for(; (c = stream[i]) != 0 && c != '\r' && c != '\n'; i++);
result.write(stream, offset, i - offset);
if(c == 0) break;
i += c == '\r' && stream[i + 1] == '\n' ? 2 : 1;
if((c = stream[i]) != ' ') break;
offset = ++i;
}
parsed = result.toString();
return i;
}
}