#ifndef ASSIMP_BUILD_NO_X3D_IMPORTER
#ifdef __ANDROID__
#define _GLIBCXX_USE_C99 1
#endif
#include "FIReader.hpp"
#include "Exceptional.h"
#include <assimp/IOStream.hpp>
#include <assimp/types.h>
#include "MemoryIOWrapper.h"
#include "irrXMLWrapper.h"
#include "../contrib/utf8cpp/source/utf8.h"
#include <stack>
#include <map>
#include <iostream>
#include <sstream>
#include <iomanip>
namespace Assimp {
static const std::string parseErrorMessage = "Fast Infoset parse error";
static const char *xmlDeclarations[] = {
"<?xml encoding='finf'?>",
"<?xml encoding='finf' standalone='yes'?>",
"<?xml encoding='finf' standalone='no'?>",
"<?xml version='1.0' encoding='finf'?>",
"<?xml version='1.0' encoding='finf' standalone='yes'?>",
"<?xml version='1.0' encoding='finf' standalone='no'?>",
"<?xml version='1.1' encoding='finf'?>",
"<?xml version='1.1' encoding='finf' standalone='yes'?>",
"<?xml version='1.1' encoding='finf' standalone='no'?>"
};
static size_t parseMagic(const uint8_t *data, const uint8_t *dataEnd) {
if (dataEnd - data < 4) {
return 0;
}
uint32_t magic = (data[0] << 24) | (data[1] << 16) | (data[2] << 8) | data[3];
switch (magic) {
case 0xe0000001:
return 4;
case 0x3c3f786d: {
size_t xmlDeclarationsLength = sizeof(xmlDeclarations) / sizeof(xmlDeclarations[0]);
for (size_t i = 0; i < xmlDeclarationsLength; ++i) {
auto xmlDeclaration = xmlDeclarations[i];
ptrdiff_t xmlDeclarationLength = strlen(xmlDeclaration);
if ((dataEnd - data >= xmlDeclarationLength) && (memcmp(xmlDeclaration, data, xmlDeclarationLength) == 0)) {
data += xmlDeclarationLength;
if (dataEnd - data < 4) {
return 0;
}
magic = (data[0] << 24) | (data[1] << 16) | (data[2] << 8) | data[3];
return magic == 0xe0000001 ? xmlDeclarationLength + 4 : 0;
}
}
return 0;
}
default:
return 0;
}
}
static std::string parseUTF8String(const uint8_t *data, size_t len) {
return std::string((char*)data, len);
}
static std::string parseUTF16String(const uint8_t *data, size_t len) {
if (len & 1) {
throw DeadlyImportError(parseErrorMessage);
}
size_t numShorts = len / 2;
std::vector<short> utf16;
utf16.reserve(numShorts);
for (size_t i = 0; i < numShorts; ++i) {
short v = (data[0] << 8) | data[1];
utf16.push_back(v);
data += 2;
}
std::string result;
utf8::utf16to8(utf16.begin(), utf16.end(), back_inserter(result));
return result;
}
struct FIStringValueImpl: public FIStringValue {
inline FIStringValueImpl(std::string &&value_) { value = std::move(value_); }
virtual const std::string &toString() const { return value; }
};
std::shared_ptr<FIStringValue> FIStringValue::create(std::string &&value) {
return std::make_shared<FIStringValueImpl>(std::move(value));
}
struct FIHexValueImpl: public FIHexValue {
mutable std::string strValue;
mutable bool strValueValid;
inline FIHexValueImpl(std::vector<uint8_t> &&value_): strValueValid(false) { value = std::move(value_); }
virtual const std::string &toString() const {
if (!strValueValid) {
strValueValid = true;
std::ostringstream os;
os << std::hex << std::uppercase << std::setfill('0');
std::for_each(value.begin(), value.end(), [&](uint8_t c) { os << std::setw(2) << static_cast<int>(c); });
strValue = os.str();
}
return strValue;
};
};
std::shared_ptr<FIHexValue> FIHexValue::create(std::vector<uint8_t> &&value) {
return std::make_shared<FIHexValueImpl>(std::move(value));
}
struct FIBase64ValueImpl: public FIBase64Value {
mutable std::string strValue;
mutable bool strValueValid;
inline FIBase64ValueImpl(std::vector<uint8_t> &&value_): strValueValid(false) { value = std::move(value_); }
virtual const std::string &toString() const {
if (!strValueValid) {
strValueValid = true;
std::ostringstream os;
uint8_t c1, c2;
int imod3 = 0;
std::vector<uint8_t>::size_type valueSize = value.size();
for (std::vector<uint8_t>::size_type i = 0; i < valueSize; ++i) {
c2 = value[i];
switch (imod3) {
case 0:
os << basis_64[c2 >> 2];
imod3 = 1;
break;
case 1:
os << basis_64[((c1 & 0x03) << 4) | ((c2 & 0xf0) >> 4)];
imod3 = 2;
break;
case 2:
os << basis_64[((c1 & 0x0f) << 2) | ((c2 & 0xc0) >> 6)] << basis_64[c2 & 0x3f];
imod3 = 0;
break;
}
c1 = c2;
}
switch (imod3) {
case 1:
os << basis_64[(c1 & 0x03) << 4] << "==";
break;
case 2:
os << basis_64[(c1 & 0x0f) << 2] << '=';
break;
}
strValue = os.str();
}
return strValue;
};
static const char basis_64[];
};
const char FIBase64ValueImpl::basis_64[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
std::shared_ptr<FIBase64Value> FIBase64Value::create(std::vector<uint8_t> &&value) {
return std::make_shared<FIBase64ValueImpl>(std::move(value));
}
struct FIShortValueImpl: public FIShortValue {
mutable std::string strValue;
mutable bool strValueValid;
inline FIShortValueImpl(std::vector<int16_t> &&value_): strValueValid(false) { value = std::move(value_); }
virtual const std::string &toString() const {
if (!strValueValid) {
strValueValid = true;
std::ostringstream os;
int n = 0;
std::for_each(value.begin(), value.end(), [&](int16_t s) { if (++n > 1) os << ' '; os << s; });
strValue = os.str();
}
return strValue;
}
};
std::shared_ptr<FIShortValue> FIShortValue::create(std::vector<int16_t> &&value) {
return std::make_shared<FIShortValueImpl>(std::move(value));
}
struct FIIntValueImpl: public FIIntValue {
mutable std::string strValue;
mutable bool strValueValid;
inline FIIntValueImpl(std::vector<int32_t> &&value_): strValueValid(false) { value = std::move(value_); }
virtual const std::string &toString() const {
if (!strValueValid) {
strValueValid = true;
std::ostringstream os;
int n = 0;
std::for_each(value.begin(), value.end(), [&](int32_t i) { if (++n > 1) os << ' '; os << i; });
strValue = os.str();
}
return strValue;
};
};
std::shared_ptr<FIIntValue> FIIntValue::create(std::vector<int32_t> &&value) {
return std::make_shared<FIIntValueImpl>(std::move(value));
}
struct FILongValueImpl: public FILongValue {
mutable std::string strValue;
mutable bool strValueValid;
inline FILongValueImpl(std::vector<int64_t> &&value_): strValueValid(false) { value = std::move(value_); }
virtual const std::string &toString() const {
if (!strValueValid) {
strValueValid = true;
std::ostringstream os;
int n = 0;
std::for_each(value.begin(), value.end(), [&](int64_t l) { if (++n > 1) os << ' '; os << l; });
strValue = os.str();
}
return strValue;
};
};
std::shared_ptr<FILongValue> FILongValue::create(std::vector<int64_t> &&value) {
return std::make_shared<FILongValueImpl>(std::move(value));
}
struct FIBoolValueImpl: public FIBoolValue {
mutable std::string strValue;
mutable bool strValueValid;
inline FIBoolValueImpl(std::vector<bool> &&value_): strValueValid(false) { value = std::move(value_); }
virtual const std::string &toString() const {
if (!strValueValid) {
strValueValid = true;
std::ostringstream os;
os << std::boolalpha;
int n = 0;
std::for_each(value.begin(), value.end(), [&](bool b) { if (++n > 1) os << ' '; os << b; });
strValue = os.str();
}
return strValue;
};
};
std::shared_ptr<FIBoolValue> FIBoolValue::create(std::vector<bool> &&value) {
return std::make_shared<FIBoolValueImpl>(std::move(value));
}
struct FIFloatValueImpl: public FIFloatValue {
mutable std::string strValue;
mutable bool strValueValid;
inline FIFloatValueImpl(std::vector<float> &&value_): strValueValid(false) { value = std::move(value_); }
virtual const std::string &toString() const {
if (!strValueValid) {
strValueValid = true;
std::ostringstream os;
int n = 0;
std::for_each(value.begin(), value.end(), [&](float f) { if (++n > 1) os << ' '; os << f; });
strValue = os.str();
}
return strValue;
}
};
std::shared_ptr<FIFloatValue> FIFloatValue::create(std::vector<float> &&value) {
return std::make_shared<FIFloatValueImpl>(std::move(value));
}
struct FIDoubleValueImpl: public FIDoubleValue {
mutable std::string strValue;
mutable bool strValueValid;
inline FIDoubleValueImpl(std::vector<double> &&value_): strValueValid(false) { value = std::move(value_); }
virtual const std::string &toString() const {
if (!strValueValid) {
strValueValid = true;
std::ostringstream os;
int n = 0;
std::for_each(value.begin(), value.end(), [&](double d) { if (++n > 1) os << ' '; os << d; });
strValue = os.str();
}
return strValue;
}
};
std::shared_ptr<FIDoubleValue> FIDoubleValue::create(std::vector<double> &&value) {
return std::make_shared<FIDoubleValueImpl>(std::move(value));
}
struct FIUUIDValueImpl: public FIUUIDValue {
mutable std::string strValue;
mutable bool strValueValid;
inline FIUUIDValueImpl(std::vector<uint8_t> &&value_): strValueValid(false) { value = std::move(value_); }
virtual const std::string &toString() const {
if (!strValueValid) {
strValueValid = true;
std::ostringstream os;
os << std::hex << std::uppercase << std::setfill('0');
std::vector<uint8_t>::size_type valueSize = value.size();
for (std::vector<uint8_t>::size_type i = 0; i < valueSize; ++i) {
switch (i & 15) {
case 0:
if (i > 0) {
os << ' ';
}
os << std::setw(2) << static_cast<int>(value[i]);
break;
case 4:
case 6:
case 8:
case 10:
os << '-';
case 1:
case 2:
case 3:
case 5:
case 7:
case 9:
case 11:
case 12:
case 13:
case 14:
case 15:
os << std::setw(2) << static_cast<int>(value[i]);
break;
}
}
strValue = os.str();
}
return strValue;
};
};
std::shared_ptr<FIUUIDValue> FIUUIDValue::create(std::vector<uint8_t> &&value) {
return std::make_shared<FIUUIDValueImpl>(std::move(value));
}
struct FICDATAValueImpl: public FICDATAValue {
inline FICDATAValueImpl(std::string &&value_) { value = std::move(value_); }
virtual const std::string &toString() const { return value; }
};
std::shared_ptr<FICDATAValue> FICDATAValue::create(std::string &&value) {
return std::make_shared<FICDATAValueImpl>(std::move(value));
}
struct FIHexDecoder: public FIDecoder {
virtual std::shared_ptr<const FIValue> decode(const uint8_t *data, size_t len) {
return FIHexValue::create(std::vector<uint8_t>(data, data + len));
}
};
struct FIBase64Decoder: public FIDecoder {
virtual std::shared_ptr<const FIValue> decode(const uint8_t *data, size_t len) {
return FIBase64Value::create(std::vector<uint8_t>(data, data + len));
}
};
struct FIShortDecoder: public FIDecoder {
virtual std::shared_ptr<const FIValue> decode(const uint8_t *data, size_t len) {
if (len & 1) {
throw DeadlyImportError(parseErrorMessage);
}
std::vector<int16_t> value;
size_t numShorts = len / 2;
value.reserve(numShorts);
for (size_t i = 0; i < numShorts; ++i) {
int16_t v = (data[0] << 8) | data[1];
value.push_back(v);
data += 2;
}
return FIShortValue::create(std::move(value));
}
};
struct FIIntDecoder: public FIDecoder {
virtual std::shared_ptr<const FIValue> decode(const uint8_t *data, size_t len) {
if (len & 3) {
throw DeadlyImportError(parseErrorMessage);
}
std::vector<int32_t> value;
size_t numInts = len / 4;
value.reserve(numInts);
for (size_t i = 0; i < numInts; ++i) {
int32_t v = (data[0] << 24) | (data[1] << 16) | (data[2] << 8) | data[3];
value.push_back(v);
data += 4;
}
return FIIntValue::create(std::move(value));
}
};
struct FILongDecoder: public FIDecoder {
virtual std::shared_ptr<const FIValue> decode(const uint8_t *data, size_t len) {
if (len & 7) {
throw DeadlyImportError(parseErrorMessage);
}
std::vector<int64_t> value;
size_t numLongs = len / 8;
value.reserve(numLongs);
for (size_t i = 0; i < numLongs; ++i) {
int64_t b0 = data[0], b1 = data[1], b2 = data[2], b3 = data[3], b4 = data[4], b5 = data[5], b6 = data[6], b7 = data[7];
int64_t v = (b0 << 56) | (b1 << 48) | (b2 << 40) | (b3 << 32) | (b4 << 24) | (b5 << 16) | (b6 << 8) | b7;
value.push_back(v);
data += 8;
}
return FILongValue::create(std::move(value));
}
};
struct FIBoolDecoder: public FIDecoder {
virtual std::shared_ptr<const FIValue> decode(const uint8_t *data, size_t len) {
if (len < 1) {
throw DeadlyImportError(parseErrorMessage);
}
std::vector<bool> value;
uint8_t b = *data++;
size_t unusedBits = b >> 4;
size_t numBools = (len * 8) - 4 - unusedBits;
value.reserve(numBools);
uint8_t mask = 1 << 3;
for (size_t i = 0; i < numBools; ++i) {
if (!mask) {
mask = 1 << 7;
b = *data++;
}
value.push_back((b & mask) != 0);
}
return FIBoolValue::create(std::move(value));
}
};
struct FIFloatDecoder: public FIDecoder {
virtual std::shared_ptr<const FIValue> decode(const uint8_t *data, size_t len) {
if (len & 3) {
throw DeadlyImportError(parseErrorMessage);
}
std::vector<float> value;
size_t numFloats = len / 4;
value.reserve(numFloats);
for (size_t i = 0; i < numFloats; ++i) {
int v = (data[0] << 24) | (data[1] << 16) | (data[2] << 8) | data[3];
value.push_back(*(float*)&v);
data += 4;
}
return FIFloatValue::create(std::move(value));
}
};
struct FIDoubleDecoder: public FIDecoder {
virtual std::shared_ptr<const FIValue> decode(const uint8_t *data, size_t len) {
if (len & 7) {
throw DeadlyImportError(parseErrorMessage);
}
std::vector<double> value;
size_t numDoubles = len / 8;
value.reserve(numDoubles);
for (size_t i = 0; i < numDoubles; ++i) {
long long b0 = data[0], b1 = data[1], b2 = data[2], b3 = data[3], b4 = data[4], b5 = data[5], b6 = data[6], b7 = data[7];
long long v = (b0 << 56) | (b1 << 48) | (b2 << 40) | (b3 << 32) | (b4 << 24) | (b5 << 16) | (b6 << 8) | b7;
value.push_back(*(double*)&v);
data += 8;
}
return FIDoubleValue::create(std::move(value));
}
};
struct FIUUIDDecoder: public FIDecoder {
virtual std::shared_ptr<const FIValue> decode(const uint8_t *data, size_t len) {
if (len & 15) {
throw DeadlyImportError(parseErrorMessage);
}
return FIUUIDValue::create(std::vector<uint8_t>(data, data + len));
}
};
struct FICDATADecoder: public FIDecoder {
virtual std::shared_ptr<const FIValue> decode(const uint8_t *data, size_t len) {
return FICDATAValue::create(parseUTF8String(data, len));
}
};
class CFIReaderImpl: public FIReader {
public:
CFIReaderImpl(std::unique_ptr<uint8_t[]> data_, size_t size):
data(std::move(data_)), dataP(data.get()), dataEnd(data.get() + size), currentNodeType(irr::io::EXN_NONE),
emptyElement(false), headerPending(true), terminatorPending(false)
{}
virtual ~CFIReaderImpl() {}
virtual bool read() {
if (headerPending) {
headerPending = false;
parseHeader();
}
if (terminatorPending) {
terminatorPending = false;
if (elementStack.empty()) {
return false;
}
else {
nodeName = elementStack.top();
elementStack.pop();
currentNodeType = nodeName.empty() ? irr::io::EXN_UNKNOWN : irr::io::EXN_ELEMENT_END;
return true;
}
}
if (dataP >= dataEnd) {
return false;
}
uint8_t b = *dataP;
if (b < 0x80) { parseElement();
return true;
}
else if (b < 0xc0) { auto chars = parseNonIdentifyingStringOrIndex3(vocabulary.charactersTable);
nodeName = chars->toString();
currentNodeType = irr::io::EXN_TEXT;
return true;
}
else if (b < 0xe0) {
if ((b & 0xfc) == 0xc4) { ++dataP;
if (b & 0x02) {
parseIdentifyingStringOrIndex(vocabulary.otherURITable);
}
if (b & 0x01) {
parseIdentifyingStringOrIndex(vocabulary.otherURITable);
}
elementStack.push(EmptyString);
currentNodeType = irr::io::EXN_UNKNOWN;
return true;
}
else if ((b & 0xfc) == 0xc8) { ++dataP;
parseIdentifyingStringOrIndex(vocabulary.otherNCNameTable);
if (b & 0x02) {
parseIdentifyingStringOrIndex(vocabulary.otherURITable);
}
if (b & 0x01) {
parseIdentifyingStringOrIndex(vocabulary.otherURITable);
}
currentNodeType = irr::io::EXN_UNKNOWN;
return true;
}
}
else if (b < 0xf0) {
if (b == 0xe1) { ++dataP;
parseIdentifyingStringOrIndex(vocabulary.otherNCNameTable);
if (dataEnd - dataP < 1) {
throw DeadlyImportError(parseErrorMessage);
}
parseNonIdentifyingStringOrIndex1(vocabulary.otherStringTable);
currentNodeType = irr::io::EXN_UNKNOWN;
return true;
}
else if (b == 0xe2) { ++dataP;
if (dataEnd - dataP < 1) {
throw DeadlyImportError(parseErrorMessage);
}
std::shared_ptr<const FIValue> comment = parseNonIdentifyingStringOrIndex1(vocabulary.otherStringTable);
nodeName = comment->toString();
currentNodeType = irr::io::EXN_COMMENT;
return true;
}
}
else { ++dataP;
if (b == 0xff) {
terminatorPending = true;
}
if (elementStack.empty()) {
return false;
}
else {
nodeName = elementStack.top();
elementStack.pop();
currentNodeType = nodeName.empty() ? irr::io::EXN_UNKNOWN : irr::io::EXN_ELEMENT_END;
return true;
}
}
throw DeadlyImportError(parseErrorMessage);
}
virtual irr::io::EXML_NODE getNodeType() const {
return currentNodeType;
}
virtual int getAttributeCount() const {
return static_cast<int>(attributes.size());
}
virtual const char* getAttributeName(int idx) const {
if (idx < 0 || idx >= (int)attributes.size()) {
return nullptr;
}
return attributes[idx].name.c_str();
}
virtual const char* getAttributeValue(int idx) const {
if (idx < 0 || idx >= (int)attributes.size()) {
return nullptr;
}
return attributes[idx].value->toString().c_str();
}
virtual const char* getAttributeValue(const char* name) const {
const Attribute* attr = getAttributeByName(name);
if (!attr) {
return nullptr;
}
return attr->value->toString().c_str();
}
virtual const char* getAttributeValueSafe(const char* name) const {
const Attribute* attr = getAttributeByName(name);
if (!attr) {
return EmptyString.c_str();
}
return attr->value->toString().c_str();
}
virtual int getAttributeValueAsInt(const char* name) const {
const Attribute* attr = getAttributeByName(name);
if (!attr) {
return 0;
}
std::shared_ptr<const FIIntValue> intValue = std::dynamic_pointer_cast<const FIIntValue>(attr->value);
if (intValue) {
return intValue->value.size() == 1 ? intValue->value.front() : 0;
}
return stoi(attr->value->toString());
}
virtual int getAttributeValueAsInt(int idx) const {
if (idx < 0 || idx >= (int)attributes.size()) {
return 0;
}
std::shared_ptr<const FIIntValue> intValue = std::dynamic_pointer_cast<const FIIntValue>(attributes[idx].value);
if (intValue) {
return intValue->value.size() == 1 ? intValue->value.front() : 0;
}
return stoi(attributes[idx].value->toString());
}
virtual float getAttributeValueAsFloat(const char* name) const {
const Attribute* attr = getAttributeByName(name);
if (!attr) {
return 0;
}
std::shared_ptr<const FIFloatValue> floatValue = std::dynamic_pointer_cast<const FIFloatValue>(attr->value);
if (floatValue) {
return floatValue->value.size() == 1 ? floatValue->value.front() : 0;
}
return stof(attr->value->toString());
}
virtual float getAttributeValueAsFloat(int idx) const {
if (idx < 0 || idx >= (int)attributes.size()) {
return 0;
}
std::shared_ptr<const FIFloatValue> floatValue = std::dynamic_pointer_cast<const FIFloatValue>(attributes[idx].value);
if (floatValue) {
return floatValue->value.size() == 1 ? floatValue->value.front() : 0;
}
return stof(attributes[idx].value->toString());
}
virtual const char* getNodeName() const {
return nodeName.c_str();
}
virtual const char* getNodeData() const {
return nodeName.c_str();
}
virtual bool isEmptyElement() const {
return emptyElement;
}
virtual irr::io::ETEXT_FORMAT getSourceFormat() const {
return irr::io::ETF_UTF8;
}
virtual irr::io::ETEXT_FORMAT getParserFormat() const {
return irr::io::ETF_UTF8;
}
virtual std::shared_ptr<const FIValue> getAttributeEncodedValue(int idx) const {
if (idx < 0 || idx >= (int)attributes.size()) {
return nullptr;
}
return attributes[idx].value;
}
virtual std::shared_ptr<const FIValue> getAttributeEncodedValue(const char* name) const {
const Attribute* attr = getAttributeByName(name);
if (!attr) {
return nullptr;
}
return attr->value;
}
virtual void registerDecoder(const std::string &algorithmUri, std::unique_ptr<FIDecoder> decoder) {
decoderMap[algorithmUri] = std::move(decoder);
}
virtual void registerVocabulary(const std::string &vocabularyUri, const FIVocabulary *vocabulary) {
vocabularyMap[vocabularyUri] = vocabulary;
}
private:
struct QName {
std::string prefix;
std::string uri;
std::string name;
inline QName() {}
inline QName(const FIQName &qname): prefix(qname.prefix ? qname.prefix : ""), uri(qname.uri ? qname.uri : ""), name(qname.name) {}
};
struct Attribute {
QName qname;
std::string name;
std::shared_ptr<const FIValue> value;
};
struct Vocabulary {
std::vector<std::string> restrictedAlphabetTable;
std::vector<std::string> encodingAlgorithmTable;
std::vector<std::string> prefixTable;
std::vector<std::string> namespaceNameTable;
std::vector<std::string> localNameTable;
std::vector<std::string> otherNCNameTable;
std::vector<std::string> otherURITable;
std::vector<std::shared_ptr<const FIValue>> attributeValueTable;
std::vector<std::shared_ptr<const FIValue>> charactersTable;
std::vector<std::shared_ptr<const FIValue>> otherStringTable;
std::vector<QName> elementNameTable;
std::vector<QName> attributeNameTable;
Vocabulary() {
prefixTable.push_back("xml");
namespaceNameTable.push_back("http://www.w3.org/XML/1998/namespace");
}
};
const Attribute* getAttributeByName(const char* name) const {
if (!name) {
return 0;
}
std::string n = name;
for (int i=0; i<(int)attributes.size(); ++i) {
if (attributes[i].name == n) {
return &attributes[i];
}
}
return 0;
}
size_t parseInt2() { uint8_t b = *dataP++;
if (!(b & 0x40)) { return b & 0x3f;
}
else if ((b & 0x60) == 0x40) { if (dataEnd - dataP > 0) {
return (((b & 0x1f) << 8) | *dataP++) + 0x40;
}
}
else if ((b & 0x70) == 0x60) { if (dataEnd - dataP > 1) {
size_t result = (((b & 0x0f) << 16) | (dataP[0] << 8) | dataP[1]) + 0x2040;
dataP += 2;
return result;
}
}
throw DeadlyImportError(parseErrorMessage);
}
size_t parseInt3() { uint8_t b = *dataP++;
if (!(b & 0x20)) { return b & 0x1f;
}
else if ((b & 0x38) == 0x20) { if (dataEnd - dataP > 0) {
return (((b & 0x07) << 8) | *dataP++) + 0x20;
}
}
else if ((b & 0x38) == 0x28) { if (dataEnd - dataP > 1) {
size_t result = (((b & 0x07) << 16) | (dataP[0] << 8) | dataP[1]) + 0x820;
dataP += 2;
return result;
}
}
else if ((b & 0x3f) == 0x30) { if ((dataEnd - dataP > 2) && !(dataP[0] & 0xf0)) {
size_t result = (((dataP[0] & 0x0f) << 16) | (dataP[1] << 8) | dataP[2]) + 0x80820;
dataP += 3;
return result;
}
}
throw DeadlyImportError(parseErrorMessage);
}
size_t parseInt4() { uint8_t b = *dataP++;
if (!(b & 0x10)) { return b & 0x0f;
}
else if ((b & 0x1c) == 0x10) { if (dataEnd - dataP > 0) {
return (((b & 0x03) << 8) | *dataP++) + 0x10;
}
}
else if ((b & 0x1c) == 0x14) { if (dataEnd - dataP > 1) {
size_t result = (((b & 0x03) << 16) | (dataP[0] << 8) | dataP[1]) + 0x410;
dataP += 2;
return result;
}
}
else if ((b & 0x1f) == 0x18) { if ((dataEnd - dataP > 2) && !(dataP[0] & 0xf0)) {
size_t result = (((dataP[0] & 0x0f) << 16) | (dataP[1] << 8) | dataP[2]) + 0x40410;
dataP += 3;
return result;
}
}
throw DeadlyImportError(parseErrorMessage);
}
size_t parseSequenceLen() { if (dataEnd - dataP > 0) {
uint8_t b = *dataP++;
if (b < 0x80) { return b;
}
else if ((b & 0xf0) == 0x80) { if (dataEnd - dataP > 1) {
size_t result = (((b & 0x0f) << 16) | (dataP[0] << 8) | dataP[1]) + 0x80;
dataP += 2;
return result;
}
}
}
throw DeadlyImportError(parseErrorMessage);
}
std::string parseNonEmptyOctetString2() { uint8_t b = *dataP++ & 0x7f;
size_t len;
if (!(b & 0x40)) { len = b + 1;
}
else if (b == 0x40) { if (dataEnd - dataP < 1) {
throw DeadlyImportError(parseErrorMessage);
}
len = *dataP++ + 0x41;
}
else if (b == 0x60) { if (dataEnd - dataP < 4) {
throw DeadlyImportError(parseErrorMessage);
}
len = ((dataP[0] << 24) | (dataP[1] << 16) | (dataP[2] << 8) | dataP[3]) + 0x141;
dataP += 4;
}
else {
throw DeadlyImportError(parseErrorMessage);
}
if (dataEnd - dataP < static_cast<ptrdiff_t>(len)) {
throw DeadlyImportError(parseErrorMessage);
}
std::string s = parseUTF8String(dataP, len);
dataP += len;
return s;
}
size_t parseNonEmptyOctetString5Length() { size_t b = *dataP++ & 0x0f;
if (!(b & 0x08)) { return b + 1;
}
else if (b == 0x08) { if (dataEnd - dataP > 0) {
return *dataP++ + 0x09;
}
}
else if (b == 0x0c) { if (dataEnd - dataP > 3) {
size_t result = ((dataP[0] << 24) | (dataP[1] << 16) | (dataP[2] << 8) | dataP[3]) + 0x109;
dataP += 4;
return result;
}
}
throw DeadlyImportError(parseErrorMessage);
}
size_t parseNonEmptyOctetString7Length() { size_t b = *dataP++ & 0x03;
if (!(b & 0x02)) { return b + 1;
}
else if (b == 0x02) { if (dataEnd - dataP > 0) {
return *dataP++ + 0x3;
}
}
else if (b == 0x03) { if (dataEnd - dataP > 3) {
size_t result = ((dataP[0] << 24) | (dataP[1] << 16) | (dataP[2] << 8) | dataP[3]) + 0x103;
dataP += 4;
return result;
}
}
throw DeadlyImportError(parseErrorMessage);
}
std::shared_ptr<const FIValue> parseEncodedData(size_t index, size_t len) {
if (index < 32) {
FIDecoder *decoder = defaultDecoder[index];
if (!decoder) {
throw DeadlyImportError("Invalid encoding algorithm index " + std::to_string(index));
}
return decoder->decode(dataP, len);
}
else {
if (index - 32 >= vocabulary.encodingAlgorithmTable.size()) {
throw DeadlyImportError("Invalid encoding algorithm index " + std::to_string(index));
}
std::string uri = vocabulary.encodingAlgorithmTable[index - 32];
auto it = decoderMap.find(uri);
if (it == decoderMap.end()) {
throw DeadlyImportError("Unsupported encoding algorithm " + uri);
}
else {
return it->second->decode(dataP, len);
}
}
}
std::shared_ptr<const FIValue> parseRestrictedAlphabet(size_t index, size_t len) {
std::string alphabet;
if (index < 16) {
switch (index) {
case 0: alphabet = "0123456789-+.e ";
break;
case 1: alphabet = "0123456789-:TZ ";
break;
default:
throw DeadlyImportError("Invalid restricted alphabet index " + std::to_string(index));
}
}
else {
if (index - 16 >= vocabulary.restrictedAlphabetTable.size()) {
throw DeadlyImportError("Invalid restricted alphabet index " + std::to_string(index));
}
alphabet = vocabulary.restrictedAlphabetTable[index - 16];
}
std::vector<uint32_t> alphabetUTF32;
utf8::utf8to32(alphabet.begin(), alphabet.end(), back_inserter(alphabetUTF32));
std::string::size_type alphabetLength = alphabetUTF32.size();
if (alphabetLength < 2) {
throw DeadlyImportError("Invalid restricted alphabet length " + std::to_string(alphabetLength));
}
std::string::size_type bitsPerCharacter = 1;
while ((1ull << bitsPerCharacter) <= alphabetLength) {
++bitsPerCharacter;
}
size_t bitsAvail = 0;
uint8_t mask = (1 << bitsPerCharacter) - 1;
uint32_t bits = 0;
std::string s;
for (size_t i = 0; i < len; ++i) {
bits = (bits << 8) | dataP[i];
bitsAvail += 8;
while (bitsAvail >= bitsPerCharacter) {
bitsAvail -= bitsPerCharacter;
size_t charIndex = (bits >> bitsAvail) & mask;
if (charIndex < alphabetLength) {
s.push_back(alphabetUTF32[charIndex]);
}
else if (charIndex != mask) {
throw DeadlyImportError(parseErrorMessage);
}
}
}
return FIStringValue::create(std::move(s));
}
std::shared_ptr<const FIValue> parseEncodedCharacterString3() { std::shared_ptr<const FIValue> result;
size_t len;
uint8_t b = *dataP;
if (b & 0x20) {
++dataP;
if (dataEnd - dataP < 1) {
throw DeadlyImportError(parseErrorMessage);
}
size_t index = ((b & 0x0f) << 4) | ((*dataP & 0xf0) >> 4); len = parseNonEmptyOctetString5Length();
if (dataEnd - dataP < static_cast<ptrdiff_t>(len)) {
throw DeadlyImportError(parseErrorMessage);
}
if (b & 0x10) {
result = parseEncodedData(index, len);
}
else {
result = parseRestrictedAlphabet(index, len);
}
}
else {
len = parseNonEmptyOctetString5Length();
if (dataEnd - dataP < static_cast<ptrdiff_t>(len)) {
throw DeadlyImportError(parseErrorMessage);
}
if (b & 0x10) {
if (len & 1) {
throw DeadlyImportError(parseErrorMessage);
}
result = FIStringValue::create(parseUTF16String(dataP, len));
}
else {
result = FIStringValue::create(parseUTF8String(dataP, len));
}
}
dataP += len;
return result;
}
std::shared_ptr<const FIValue> parseEncodedCharacterString5() { std::shared_ptr<const FIValue> result;
size_t len;
uint8_t b = *dataP;
if (b & 0x08) {
++dataP;
if (dataEnd - dataP < 1) {
throw DeadlyImportError(parseErrorMessage);
}
size_t index = ((b & 0x03) << 6) | ((*dataP & 0xfc) >> 2);
len = parseNonEmptyOctetString7Length();
if (dataEnd - dataP < static_cast<ptrdiff_t>(len)) {
throw DeadlyImportError(parseErrorMessage);
}
if (b & 0x04) {
result = parseEncodedData(index, len);
}
else {
result = parseRestrictedAlphabet(index, len);
}
}
else {
len = parseNonEmptyOctetString7Length();
if (dataEnd - dataP < static_cast<ptrdiff_t>(len)) {
throw DeadlyImportError(parseErrorMessage);
}
if (b & 0x04) {
if (len & 1) {
throw DeadlyImportError(parseErrorMessage);
}
result = FIStringValue::create(parseUTF16String(dataP, len));
}
else {
result = FIStringValue::create(parseUTF8String(dataP, len));
}
}
dataP += len;
return result;
}
const std::string &parseIdentifyingStringOrIndex(std::vector<std::string> &stringTable) { if (dataEnd - dataP < 1) {
throw DeadlyImportError(parseErrorMessage);
}
uint8_t b = *dataP;
if (b & 0x80) {
size_t index = parseInt2();
if (index >= stringTable.size()) {
throw DeadlyImportError(parseErrorMessage);
}
return stringTable[index];
}
else {
stringTable.push_back(parseNonEmptyOctetString2());
return stringTable.back();
}
}
QName parseNameSurrogate() { if (dataEnd - dataP < 1) {
throw DeadlyImportError(parseErrorMessage);
}
uint8_t b = *dataP++;
if (b & 0xfc) { throw DeadlyImportError(parseErrorMessage);
}
QName result;
size_t index;
if (b & 0x02) { if ((dataEnd - dataP < 1) || (*dataP & 0x80)) {
throw DeadlyImportError(parseErrorMessage);
}
index = parseInt2();
if (index >= vocabulary.prefixTable.size()) {
throw DeadlyImportError(parseErrorMessage);
}
result.prefix = vocabulary.prefixTable[index];
}
if (b & 0x01) { if ((dataEnd - dataP < 1) || (*dataP & 0x80)) {
throw DeadlyImportError(parseErrorMessage);
}
index = parseInt2();
if (index >= vocabulary.namespaceNameTable.size()) {
throw DeadlyImportError(parseErrorMessage);
}
result.uri = vocabulary.namespaceNameTable[index];
}
if ((dataEnd - dataP < 1) || (*dataP & 0x80)) {
throw DeadlyImportError(parseErrorMessage);
}
index = parseInt2();
if (index >= vocabulary.localNameTable.size()) {
throw DeadlyImportError(parseErrorMessage);
}
result.name = vocabulary.localNameTable[index];
return result;
}
const QName &parseQualifiedNameOrIndex2(std::vector<QName> &qNameTable) { uint8_t b = *dataP;
if ((b & 0x7c) == 0x78) { ++dataP;
QName result;
result.prefix = b & 0x02 ? parseIdentifyingStringOrIndex(vocabulary.prefixTable) : std::string();
result.uri = b & 0x01 ? parseIdentifyingStringOrIndex(vocabulary.namespaceNameTable) : std::string();
result.name = parseIdentifyingStringOrIndex(vocabulary.localNameTable);
qNameTable.push_back(result);
return qNameTable.back();
}
else {
size_t index = parseInt2();
if (index >= qNameTable.size()) {
throw DeadlyImportError(parseErrorMessage);
}
return qNameTable[index];
}
}
const QName &parseQualifiedNameOrIndex3(std::vector<QName> &qNameTable) { uint8_t b = *dataP;
if ((b & 0x3c) == 0x3c) { ++dataP;
QName result;
result.prefix = b & 0x02 ? parseIdentifyingStringOrIndex(vocabulary.prefixTable) : std::string();
result.uri = b & 0x01 ? parseIdentifyingStringOrIndex(vocabulary.namespaceNameTable) : std::string();
result.name = parseIdentifyingStringOrIndex(vocabulary.localNameTable);
qNameTable.push_back(result);
return qNameTable.back();
}
else {
size_t index = parseInt3();
if (index >= qNameTable.size()) {
throw DeadlyImportError(parseErrorMessage);
}
return qNameTable[index];
}
}
std::shared_ptr<const FIValue> parseNonIdentifyingStringOrIndex1(std::vector<std::shared_ptr<const FIValue>> &valueTable) { uint8_t b = *dataP;
if (b == 0xff) { ++dataP;
return EmptyFIString;
}
else if (b & 0x80) { size_t index = parseInt2();
if (index >= valueTable.size()) {
throw DeadlyImportError(parseErrorMessage);
}
return valueTable[index];
}
else { std::shared_ptr<const FIValue> result = parseEncodedCharacterString3();
if (b & 0x40) { valueTable.push_back(result);
}
return result;
}
}
std::shared_ptr<const FIValue> parseNonIdentifyingStringOrIndex3(std::vector<std::shared_ptr<const FIValue>> &valueTable) { uint8_t b = *dataP;
if (b & 0x20) { size_t index = parseInt4();
if (index >= valueTable.size()) {
throw DeadlyImportError(parseErrorMessage);
}
return valueTable[index];
}
else { std::shared_ptr<const FIValue> result = parseEncodedCharacterString5();
if (b & 0x10) { valueTable.push_back(result);
}
return result;
}
}
void parseElement() {
attributes.clear();
uint8_t b = *dataP;
bool hasAttributes = (b & 0x40) != 0; if ((b & 0x3f) == 0x38) { ++dataP;
for (;;) {
if (dataEnd - dataP < 1) {
throw DeadlyImportError(parseErrorMessage);
}
b = *dataP++;
if (b == 0xf0) { break;
}
if ((b & 0xfc) != 0xcc) { throw DeadlyImportError(parseErrorMessage);
}
Attribute attr;
attr.qname.prefix = "xmlns";
attr.qname.name = b & 0x02 ? parseIdentifyingStringOrIndex(vocabulary.prefixTable) : std::string();
attr.qname.uri = b & 0x01 ? parseIdentifyingStringOrIndex(vocabulary.namespaceNameTable) : std::string();
attr.name = attr.qname.name.empty() ? "xmlns" : "xmlns:" + attr.qname.name;
attr.value = FIStringValue::create(std::string(attr.qname.uri));
attributes.push_back(attr);
}
if ((dataEnd - dataP < 1) || (*dataP & 0xc0)) {
throw DeadlyImportError(parseErrorMessage);
}
}
const QName &elemName = parseQualifiedNameOrIndex3(vocabulary.elementNameTable);
nodeName = elemName.prefix.empty() ? elemName.name : elemName.prefix + ':' + elemName.name;
if (hasAttributes) {
for (;;) {
if (dataEnd - dataP < 1) {
throw DeadlyImportError(parseErrorMessage);
}
b = *dataP;
if (b < 0x80) { Attribute attr;
attr.qname = parseQualifiedNameOrIndex2(vocabulary.attributeNameTable);
attr.name = attr.qname.prefix.empty() ? attr.qname.name : attr.qname.prefix + ':' + attr.qname.name;
if (dataEnd - dataP < 1) {
throw DeadlyImportError(parseErrorMessage);
}
attr.value = parseNonIdentifyingStringOrIndex1(vocabulary.attributeValueTable);
attributes.push_back(attr);
}
else {
if ((b & 0xf0) != 0xf0) { throw DeadlyImportError(parseErrorMessage);
}
emptyElement = b == 0xff; ++dataP;
break;
}
}
}
else {
if (dataEnd - dataP < 1) {
throw DeadlyImportError(parseErrorMessage);
}
b = *dataP;
switch (b) {
case 0xff:
terminatorPending = true;
case 0xf0:
emptyElement = true;
++dataP;
break;
default:
emptyElement = false;
}
}
if (!emptyElement) {
elementStack.push(nodeName);
}
currentNodeType = irr::io::EXN_ELEMENT;
}
void parseHeader() {
size_t magicSize = parseMagic(dataP, dataEnd);
if (!magicSize) {
throw DeadlyImportError(parseErrorMessage);
}
dataP += magicSize;
if (dataEnd - dataP < 1) {
throw DeadlyImportError(parseErrorMessage);
}
uint8_t b = *dataP++;
if (b & 0x40) {
size_t len = parseSequenceLen();
for (size_t i = 0; i < len; ++i) {
if (dataEnd - dataP < 1) {
throw DeadlyImportError(parseErrorMessage);
}
parseNonEmptyOctetString2();
if (dataEnd - dataP < 1) {
throw DeadlyImportError(parseErrorMessage);
}
parseNonEmptyOctetString2();
}
}
if (b & 0x20) {
if (dataEnd - dataP < 2) {
throw DeadlyImportError(parseErrorMessage);
}
uint16_t b1 = (dataP[0] << 8) | dataP[1];
dataP += 2;
if (b1 & 0x1000) {
if (dataEnd - dataP < 1) {
throw DeadlyImportError(parseErrorMessage);
}
std::string uri = parseNonEmptyOctetString2();
auto it = vocabularyMap.find(uri);
if (it == vocabularyMap.end()) {
throw DeadlyImportError("Unknown vocabulary " + uri);
}
const FIVocabulary *externalVocabulary = it->second;
if (externalVocabulary->restrictedAlphabetTable) {
std::copy(externalVocabulary->restrictedAlphabetTable, externalVocabulary->restrictedAlphabetTable + externalVocabulary->restrictedAlphabetTableSize, std::back_inserter(vocabulary.restrictedAlphabetTable));
}
if (externalVocabulary->encodingAlgorithmTable) {
std::copy(externalVocabulary->encodingAlgorithmTable, externalVocabulary->encodingAlgorithmTable + externalVocabulary->encodingAlgorithmTableSize, std::back_inserter(vocabulary.encodingAlgorithmTable));
}
if (externalVocabulary->prefixTable) {
std::copy(externalVocabulary->prefixTable, externalVocabulary->prefixTable + externalVocabulary->prefixTableSize, std::back_inserter(vocabulary.prefixTable));
}
if (externalVocabulary->namespaceNameTable) {
std::copy(externalVocabulary->namespaceNameTable, externalVocabulary->namespaceNameTable + externalVocabulary->namespaceNameTableSize, std::back_inserter(vocabulary.namespaceNameTable));
}
if (externalVocabulary->localNameTable) {
std::copy(externalVocabulary->localNameTable, externalVocabulary->localNameTable + externalVocabulary->localNameTableSize, std::back_inserter(vocabulary.localNameTable));
}
if (externalVocabulary->otherNCNameTable) {
std::copy(externalVocabulary->otherNCNameTable, externalVocabulary->otherNCNameTable + externalVocabulary->otherNCNameTableSize, std::back_inserter(vocabulary.otherNCNameTable));
}
if (externalVocabulary->otherURITable) {
std::copy(externalVocabulary->otherURITable, externalVocabulary->otherURITable + externalVocabulary->otherURITableSize, std::back_inserter(vocabulary.otherURITable));
}
if (externalVocabulary->attributeValueTable) {
std::copy(externalVocabulary->attributeValueTable, externalVocabulary->attributeValueTable + externalVocabulary->attributeValueTableSize, std::back_inserter(vocabulary.attributeValueTable));
}
if (externalVocabulary->charactersTable) {
std::copy(externalVocabulary->charactersTable, externalVocabulary->charactersTable + externalVocabulary->charactersTableSize, std::back_inserter(vocabulary.charactersTable));
}
if (externalVocabulary->otherStringTable) {
std::copy(externalVocabulary->otherStringTable, externalVocabulary->otherStringTable + externalVocabulary->otherStringTableSize, std::back_inserter(vocabulary.otherStringTable));
}
if (externalVocabulary->elementNameTable) {
std::copy(externalVocabulary->elementNameTable, externalVocabulary->elementNameTable + externalVocabulary->elementNameTableSize, std::back_inserter(vocabulary.elementNameTable));
}
if (externalVocabulary->attributeNameTable) {
std::copy(externalVocabulary->attributeNameTable, externalVocabulary->attributeNameTable + externalVocabulary->attributeNameTableSize, std::back_inserter(vocabulary.attributeNameTable));
}
}
if (b1 & 0x0800) {
for (size_t len = parseSequenceLen(); len > 0; --len) {
if (dataEnd - dataP < 1) {
throw DeadlyImportError(parseErrorMessage);
}
vocabulary.restrictedAlphabetTable.push_back(parseNonEmptyOctetString2());
}
}
if (b1 & 0x0400) {
for (size_t len = parseSequenceLen(); len > 0; --len) {
if (dataEnd - dataP < 1) {
throw DeadlyImportError(parseErrorMessage);
}
vocabulary.encodingAlgorithmTable.push_back(parseNonEmptyOctetString2());
}
}
if (b1 & 0x0200) {
for (size_t len = parseSequenceLen(); len > 0; --len) {
if (dataEnd - dataP < 1) {
throw DeadlyImportError(parseErrorMessage);
}
vocabulary.prefixTable.push_back(parseNonEmptyOctetString2());
}
}
if (b1 & 0x0100) {
for (size_t len = parseSequenceLen(); len > 0; --len) {
if (dataEnd - dataP < 1) {
throw DeadlyImportError(parseErrorMessage);
}
vocabulary.namespaceNameTable.push_back(parseNonEmptyOctetString2());
}
}
if (b1 & 0x0080) {
for (size_t len = parseSequenceLen(); len > 0; --len) {
if (dataEnd - dataP < 1) {
throw DeadlyImportError(parseErrorMessage);
}
vocabulary.localNameTable.push_back(parseNonEmptyOctetString2());
}
}
if (b1 & 0x0040) {
for (size_t len = parseSequenceLen(); len > 0; --len) {
if (dataEnd - dataP < 1) {
throw DeadlyImportError(parseErrorMessage);
}
vocabulary.otherNCNameTable.push_back(parseNonEmptyOctetString2());
}
}
if (b1 & 0x0020) {
for (size_t len = parseSequenceLen(); len > 0; --len) {
if (dataEnd - dataP < 1) {
throw DeadlyImportError(parseErrorMessage);
}
vocabulary.otherURITable.push_back(parseNonEmptyOctetString2());
}
}
if (b1 & 0x0010) {
for (size_t len = parseSequenceLen(); len > 0; --len) {
if (dataEnd - dataP < 1) {
throw DeadlyImportError(parseErrorMessage);
}
vocabulary.attributeValueTable.push_back(parseEncodedCharacterString3());
}
}
if (b1 & 0x0008) {
for (size_t len = parseSequenceLen(); len > 0; --len) {
if (dataEnd - dataP < 1) {
throw DeadlyImportError(parseErrorMessage);
}
vocabulary.charactersTable.push_back(parseEncodedCharacterString3());
}
}
if (b1 & 0x0004) {
for (size_t len = parseSequenceLen(); len > 0; --len) {
if (dataEnd - dataP < 1) {
throw DeadlyImportError(parseErrorMessage);
}
vocabulary.otherStringTable.push_back(parseEncodedCharacterString3());
}
}
if (b1 & 0x0002) {
for (size_t len = parseSequenceLen(); len > 0; --len) {
vocabulary.elementNameTable.push_back(parseNameSurrogate());
}
}
if (b1 & 0x0001) {
for (size_t len = parseSequenceLen(); len > 0; --len) {
vocabulary.attributeNameTable.push_back(parseNameSurrogate());
}
}
}
if (b & 0x10) {
for (;;) {
if (dataEnd - dataP < 1) {
throw DeadlyImportError(parseErrorMessage);
}
uint8_t b1 = *dataP++;
if (b1 == 0xf0) {
break;
}
if ((b1 & 0xfc) != 0xc0) {
throw DeadlyImportError(parseErrorMessage);
}
parseIdentifyingStringOrIndex(vocabulary.otherNCNameTable);
if (b1 & 0x02) {
parseIdentifyingStringOrIndex(vocabulary.otherURITable);
}
if (b1 & 0x01) {
parseIdentifyingStringOrIndex(vocabulary.otherURITable);
}
}
}
if (b & 0x08) {
for (;;) {
if (dataEnd - dataP < 1) {
throw DeadlyImportError(parseErrorMessage);
}
uint8_t b1 = *dataP++;
if (b1 == 0xf0) {
break;
}
if ((b1 & 0xfe) != 0xd0) {
throw DeadlyImportError(parseErrorMessage);
}
parseIdentifyingStringOrIndex(vocabulary.otherNCNameTable);
parseIdentifyingStringOrIndex(vocabulary.otherURITable);
if (b1 & 0x01) {
parseIdentifyingStringOrIndex(vocabulary.otherURITable);
}
parseIdentifyingStringOrIndex(vocabulary.otherNCNameTable);
}
}
if (b & 0x04) {
if (dataEnd - dataP < 1) {
throw DeadlyImportError(parseErrorMessage);
}
parseNonEmptyOctetString2();
}
if (b & 0x02) {
if (dataEnd - dataP < 1) {
throw DeadlyImportError(parseErrorMessage);
}
uint8_t b1 = *dataP++;
if (b1 & 0xfe) {
throw DeadlyImportError(parseErrorMessage);
}
}
if (b & 0x01) {
if (dataEnd - dataP < 1) {
throw DeadlyImportError(parseErrorMessage);
}
parseNonIdentifyingStringOrIndex1(vocabulary.otherStringTable);
}
}
std::unique_ptr<uint8_t[]> data;
uint8_t *dataP, *dataEnd;
irr::io::EXML_NODE currentNodeType;
bool emptyElement;
bool headerPending;
bool terminatorPending;
Vocabulary vocabulary;
std::vector<Attribute> attributes;
std::stack<std::string> elementStack;
std::string nodeName;
std::map<std::string, std::unique_ptr<FIDecoder>> decoderMap;
std::map<std::string, const FIVocabulary*> vocabularyMap;
static const std::string EmptyString;
static std::shared_ptr<const FIValue> EmptyFIString;
static FIHexDecoder hexDecoder;
static FIBase64Decoder base64Decoder;
static FIShortDecoder shortDecoder;
static FIIntDecoder intDecoder;
static FILongDecoder longDecoder;
static FIBoolDecoder boolDecoder;
static FIFloatDecoder floatDecoder;
static FIDoubleDecoder doubleDecoder;
static FIUUIDDecoder uuidDecoder;
static FICDATADecoder cdataDecoder;
static FIDecoder *defaultDecoder[32];
};
const std::string CFIReaderImpl::EmptyString;
std::shared_ptr<const FIValue> CFIReaderImpl::EmptyFIString = FIStringValue::create(std::string());
FIHexDecoder CFIReaderImpl::hexDecoder;
FIBase64Decoder CFIReaderImpl::base64Decoder;
FIShortDecoder CFIReaderImpl::shortDecoder;
FIIntDecoder CFIReaderImpl::intDecoder;
FILongDecoder CFIReaderImpl::longDecoder;
FIBoolDecoder CFIReaderImpl::boolDecoder;
FIFloatDecoder CFIReaderImpl::floatDecoder;
FIDoubleDecoder CFIReaderImpl::doubleDecoder;
FIUUIDDecoder CFIReaderImpl::uuidDecoder;
FICDATADecoder CFIReaderImpl::cdataDecoder;
FIDecoder *CFIReaderImpl::defaultDecoder[32] = {
&hexDecoder,
&base64Decoder,
&shortDecoder,
&intDecoder,
&longDecoder,
&boolDecoder,
&floatDecoder,
&doubleDecoder,
&uuidDecoder,
&cdataDecoder
};
class CXMLReaderImpl : public FIReader
{
public:
CXMLReaderImpl(std::unique_ptr<irr::io::IIrrXMLReader<char, irr::io::IXMLBase>> reader_)
: reader(std::move(reader_))
{}
virtual ~CXMLReaderImpl() {}
virtual bool read() {
return reader->read();
}
virtual irr::io::EXML_NODE getNodeType() const {
return reader->getNodeType();
}
virtual int getAttributeCount() const {
return reader->getAttributeCount();
}
virtual const char* getAttributeName(int idx) const {
return reader->getAttributeName(idx);
}
virtual const char* getAttributeValue(int idx) const {
return reader->getAttributeValue(idx);
}
virtual const char* getAttributeValue(const char* name) const {
return reader->getAttributeValue(name);
}
virtual const char* getAttributeValueSafe(const char* name) const {
return reader->getAttributeValueSafe(name);
}
virtual int getAttributeValueAsInt(const char* name) const {
return reader->getAttributeValueAsInt(name);
}
virtual int getAttributeValueAsInt(int idx) const {
return reader->getAttributeValueAsInt(idx);
}
virtual float getAttributeValueAsFloat(const char* name) const {
return reader->getAttributeValueAsFloat(name);
}
virtual float getAttributeValueAsFloat(int idx) const {
return reader->getAttributeValueAsFloat(idx);
}
virtual const char* getNodeName() const {
return reader->getNodeName();
}
virtual const char* getNodeData() const {
return reader->getNodeData();
}
virtual bool isEmptyElement() const {
return reader->isEmptyElement();
}
virtual irr::io::ETEXT_FORMAT getSourceFormat() const {
return reader->getSourceFormat();
}
virtual irr::io::ETEXT_FORMAT getParserFormat() const {
return reader->getParserFormat();
}
virtual std::shared_ptr<const FIValue> getAttributeEncodedValue(int idx) const {
return nullptr;
}
virtual std::shared_ptr<const FIValue> getAttributeEncodedValue(const char* name) const {
return nullptr;
}
virtual void registerDecoder(const std::string &algorithmUri, std::unique_ptr<FIDecoder> decoder) {}
virtual void registerVocabulary(const std::string &vocabularyUri, const FIVocabulary *vocabulary) {}
private:
std::unique_ptr<irr::io::IIrrXMLReader<char, irr::io::IXMLBase>> reader;
};
static std::unique_ptr<uint8_t[]> readFile(IOStream *stream, size_t &size, bool &isFI) {
size = stream->FileSize();
std::unique_ptr<uint8_t[]> data = std::unique_ptr<uint8_t[]>(new uint8_t[size]);
if (stream->Read(data.get(), size, 1) != 1) {
size = 0;
data.reset();
}
isFI = parseMagic(data.get(), data.get() + size) > 0;
return data;
}
std::unique_ptr<FIReader> FIReader::create(IOStream *stream)
{
size_t size;
bool isFI;
auto data = readFile(stream, size, isFI);
if (isFI) {
return std::unique_ptr<FIReader>(new CFIReaderImpl(std::move(data), size));
}
else {
auto memios = std::unique_ptr<MemoryIOStream>(new MemoryIOStream(data.release(), size, true));
auto callback = std::unique_ptr<CIrrXML_IOStreamReader>(new CIrrXML_IOStreamReader(memios.get()));
return std::unique_ptr<FIReader>(new CXMLReaderImpl(std::unique_ptr<irr::io::IIrrXMLReader<char, irr::io::IXMLBase>>(createIrrXMLReader(callback.get()))));
}
}
}
#endif