diff options
Diffstat (limited to 'libs/assimp/contrib/openddlparser/code/OpenDDLParser.cpp')
-rw-r--r-- | libs/assimp/contrib/openddlparser/code/OpenDDLParser.cpp | 1035 |
1 files changed, 1035 insertions, 0 deletions
diff --git a/libs/assimp/contrib/openddlparser/code/OpenDDLParser.cpp b/libs/assimp/contrib/openddlparser/code/OpenDDLParser.cpp new file mode 100644 index 0000000..e2bef97 --- /dev/null +++ b/libs/assimp/contrib/openddlparser/code/OpenDDLParser.cpp @@ -0,0 +1,1035 @@ +/*----------------------------------------------------------------------------------------------- +The MIT License (MIT) + +Copyright (c) 2014-2020 Kim Kulling + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software is furnished to do so, +subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +-----------------------------------------------------------------------------------------------*/ +#include <openddlparser/OpenDDLExport.h> +#include <openddlparser/OpenDDLParser.h> + +#include <math.h> +#include <algorithm> +#include <cassert> +#include <iostream> +#include <sstream> + +#ifdef _WIN32 +#include <windows.h> +#endif // _WIN32 + +BEGIN_ODDLPARSER_NS + +static const char *Version = "0.4.0"; + +namespace Grammar { + +static const char *OpenBracketToken = "{"; +static const char *CloseBracketToken = "}"; +static const char *OpenPropertyToken = "("; +static const char *ClosePropertyToken = ")"; +static const char *OpenArrayToken = "["; +static const char *CloseArrayToken = "]"; +static const char *BoolTrue = "true"; +static const char *BoolFalse = "false"; +static const char *CommaSeparator = ","; + +static const char *PrimitiveTypeToken[(size_t)Value::ValueType::ddl_types_max] = { + "bool", + "int8", + "int16", + "int32", + "int64", + "unsigned_int8", + "unsigned_int16", + "unsigned_int32", + "unsigned_int64", + "half", + "float", + "double", + "string", + "ref" +}; +} // Namespace Grammar + +const char *getTypeToken(Value::ValueType type) { + return Grammar::PrimitiveTypeToken[(size_t)type]; +} + +static void logInvalidTokenError(char *in, const std::string &exp, OpenDDLParser::logCallback callback) { + if (callback) { + std::string full(in); + std::string part(full.substr(0, 50)); + std::stringstream stream; + stream << "Invalid token \"" << *in << "\" " + << "(expected \"" << exp << "\") " + << "in: \"" << part << "\""; + callback(ddl_error_msg, stream.str()); + } +} + +static bool isIntegerType(Value::ValueType integerType) { + if (integerType != Value::ValueType::ddl_int8 && integerType != Value::ValueType::ddl_int16 && + integerType != Value::ValueType::ddl_int32 && integerType != Value::ValueType::ddl_int64) { + return false; + } + + return true; +} + +static bool isUnsignedIntegerType(Value::ValueType integerType) { + if (integerType != Value::ValueType::ddl_unsigned_int8 && integerType != Value::ValueType::ddl_unsigned_int16 && + integerType != Value::ValueType::ddl_unsigned_int32 && integerType != Value::ValueType::ddl_unsigned_int64) { + return false; + } + + return true; +} + +static DDLNode *createDDLNode(Text *id, OpenDDLParser *parser) { + if (nullptr == id || nullptr == parser || id->m_buffer == nullptr) { + return nullptr; + } + + const std::string type(id->m_buffer); + DDLNode *parent(parser->top()); + DDLNode *node = DDLNode::create(type, "", parent); + + return node; +} + +OpenDDLParser::OpenDDLParser() : + m_logCallback(nullptr), + m_buffer(), + m_stack(), + m_context(nullptr) { + // empty +} + +OpenDDLParser::OpenDDLParser(const char *buffer, size_t len) : + m_logCallback(nullptr), m_buffer(), m_context(nullptr) { + if (0 != len) { + setBuffer(buffer, len); + } +} + +OpenDDLParser::~OpenDDLParser() { + clear(); +} + +void OpenDDLParser::logToStream(FILE *f, LogSeverity severity, const std::string &message) { + if (f) { + const char *tag = "none"; + switch (severity) { + case ddl_debug_msg: tag = "debug"; break; + case ddl_info_msg: tag = "info"; break; + case ddl_warn_msg: tag = "warn"; break; + case ddl_error_msg: tag = "error"; break; + } + fprintf(f, "OpenDDLParser: (%5s) %s\n", tag, message.c_str()); + } +} + +OpenDDLParser::logCallback OpenDDLParser::StdLogCallback (FILE *destination) { + using namespace std::placeholders; + return std::bind(logToStream, destination ? destination : stderr, _1, _2); +} + +void OpenDDLParser::setLogCallback(logCallback callback) { + // install user-specific log callback; null = no log callback + m_logCallback = callback; +} + +OpenDDLParser::logCallback OpenDDLParser::getLogCallback() const { + return m_logCallback; +} + +void OpenDDLParser::setBuffer(const char *buffer, size_t len) { + clear(); + if (0 == len) { + return; + } + + m_buffer.resize(len); + ::memcpy(&m_buffer[0], buffer, len); +} + +void OpenDDLParser::setBuffer(const std::vector<char> &buffer) { + clear(); + m_buffer.resize(buffer.size()); + std::copy(buffer.begin(), buffer.end(), m_buffer.begin()); +} + +const char *OpenDDLParser::getBuffer() const { + if (m_buffer.empty()) { + return nullptr; + } + + return &m_buffer[0]; +} + +size_t OpenDDLParser::getBufferSize() const { + return m_buffer.size(); +} + +void OpenDDLParser::clear() { + m_buffer.resize(0); + delete m_context; + m_context = nullptr; +} + +bool OpenDDLParser::validate() { + if (m_buffer.empty()) { + return true; + } + + if (!isCharacter(m_buffer[0]) && !isNumeric(m_buffer[0])) { + return false; + } + + return true; +} + +bool OpenDDLParser::parse() { + if (m_buffer.empty()) { + return false; + } + + normalizeBuffer(m_buffer); + if (!validate()) { + return false; + } + + m_context = new Context; + m_context->m_root = DDLNode::create("root", "", nullptr); + pushNode(m_context->m_root); + + // do the main parsing + char *current(&m_buffer[0]); + char *end(&m_buffer[m_buffer.size() - 1] + 1); + size_t pos(current - &m_buffer[0]); + while (pos < m_buffer.size()) { + current = parseNextNode(current, end); + if (current == nullptr) { + return false; + } + pos = current - &m_buffer[0]; + } + return true; +} + +bool OpenDDLParser::exportContext(Context *ctx, const std::string &filename) { + if (nullptr == ctx) { + return false; + } + + OpenDDLExport myExporter; + return myExporter.exportContext(ctx, filename); +} + +char *OpenDDLParser::parseNextNode(char *in, char *end) { + in = parseHeader(in, end); + in = parseStructure(in, end); + + return in; +} + +#ifdef DEBUG_HEADER_NAME +static void dumpId(Identifier *id) { + if (nullptr != id) { + if (nullptr != id->m_text.m_buffer) { + std::cout << id->m_text.m_buffer << std::endl; + } + } +} +#endif + +char *OpenDDLParser::parseHeader(char *in, char *end) { + if (nullptr == in || in == end) { + return in; + } + + Text *id(nullptr); + in = OpenDDLParser::parseIdentifier(in, end, &id); + +#ifdef DEBUG_HEADER_NAME + dumpId(id); +#endif // DEBUG_HEADER_NAME + + in = lookForNextToken(in, end); + if (nullptr != id) { + // store the node + DDLNode *node(createDDLNode(id, this)); + if (nullptr != node) { + pushNode(node); + } else { + std::cerr << "nullptr returned by creating DDLNode." << std::endl; + } + delete id; + + Name *name(nullptr); + in = OpenDDLParser::parseName(in, end, &name); + if (nullptr != name && nullptr != node && nullptr != name->m_id->m_buffer) { + const std::string nodeName(name->m_id->m_buffer); + node->setName(nodeName); + delete name; + } + + Property *first(nullptr); + in = lookForNextToken(in, end); + if (in != end && *in == Grammar::OpenPropertyToken[0]) { + in++; + Property *prop(nullptr), *prev(nullptr); + while (in != end && *in != Grammar::ClosePropertyToken[0]) { + in = OpenDDLParser::parseProperty(in, end, &prop); + in = lookForNextToken(in, end); + if(in == end) { + break; + } + + if (*in != Grammar::CommaSeparator[0] && *in != Grammar::ClosePropertyToken[0]) { + logInvalidTokenError(in, Grammar::ClosePropertyToken, m_logCallback); + return nullptr; + } + + if (nullptr != prop && *in != Grammar::CommaSeparator[0]) { + if (nullptr == first) { + first = prop; + } + if (nullptr != prev) { + prev->m_next = prop; + } + prev = prop; + } + } + if(in != end) { + ++in; + } + } + + // set the properties + if (nullptr != first && nullptr != node) { + node->setProperties(first); + } + } + + return in; +} + +char *OpenDDLParser::parseStructure(char *in, char *end) { + if (nullptr == in || in == end) { + return in; + } + + bool error(false); + in = lookForNextToken(in, end); + if (*in == *Grammar::OpenBracketToken) { + // loop over all children ( data and nodes ) + do { + in = parseStructureBody(in, end, error); + if (in == nullptr) { + return nullptr; + } + } while (*in != *Grammar::CloseBracketToken); + ++in; + } else { + ++in; + logInvalidTokenError(in, std::string(Grammar::OpenBracketToken), m_logCallback); + error = true; + return nullptr; + } + in = lookForNextToken(in, end); + + // pop node from stack after successful parsing + if (!error) { + popNode(); + } + + return in; +} + +static void setNodeValues(DDLNode *currentNode, Value *values) { + if (nullptr != values) { + if (nullptr != currentNode) { + currentNode->setValue(values); + } + } +} + +static void setNodeReferences(DDLNode *currentNode, Reference *refs) { + if (nullptr != refs) { + if (nullptr != currentNode) { + currentNode->setReferences(refs); + } + } +} + +static void setNodeDataArrayList(DDLNode *currentNode, DataArrayList *dtArrayList) { + if (nullptr != dtArrayList) { + if (nullptr != currentNode) { + currentNode->setDataArrayList(dtArrayList); + } + } +} + +char *OpenDDLParser::parseStructureBody(char *in, char *end, bool &error) { + if (!isNumeric(*in) && !isCharacter(*in)) { + ++in; + } + + in = lookForNextToken(in, end); + Value::ValueType type(Value::ValueType::ddl_none); + size_t arrayLen(0); + in = OpenDDLParser::parsePrimitiveDataType(in, end, type, arrayLen); + if (Value::ValueType::ddl_none != type) { + // parse a primitive data type + in = lookForNextToken(in, end); + if (*in == Grammar::OpenBracketToken[0]) { + Reference *refs(nullptr); + DataArrayList *dtArrayList(nullptr); + Value *values(nullptr); + if (1 == arrayLen) { + size_t numRefs(0), numValues(0); + in = parseDataList(in, end, type, &values, numValues, &refs, numRefs); + setNodeValues(top(), values); + setNodeReferences(top(), refs); + } else if (arrayLen > 1) { + in = parseDataArrayList(in, end, type, &dtArrayList); + setNodeDataArrayList(top(), dtArrayList); + } else { + std::cerr << "0 for array is invalid." << std::endl; + error = true; + } + } + + in = lookForNextToken(in, end); + if (*in != '}') { + logInvalidTokenError(in, std::string(Grammar::CloseBracketToken), m_logCallback); + return nullptr; + } else { + //in++; + } + } else { + // parse a complex data type + in = parseNextNode(in, end); + } + + return in; +} + +void OpenDDLParser::pushNode(DDLNode *node) { + if (nullptr == node) { + return; + } + + m_stack.push_back(node); +} + +DDLNode *OpenDDLParser::popNode() { + if (m_stack.empty()) { + return nullptr; + } + + DDLNode *topNode(top()); + m_stack.pop_back(); + return topNode; +} + +DDLNode *OpenDDLParser::top() { + if (m_stack.empty()) { + return nullptr; + } + + DDLNode *top(m_stack.back()); + return top; +} + +DDLNode *OpenDDLParser::getRoot() const { + if (nullptr == m_context) { + return nullptr; + } + + return m_context->m_root; +} + +Context *OpenDDLParser::getContext() const { + return m_context; +} + +void OpenDDLParser::normalizeBuffer(std::vector<char> &buffer) { + if (buffer.empty()) { + return; + } + + std::vector<char> newBuffer; + const size_t len(buffer.size()); + char *end(&buffer[len - 1] + 1); + for (size_t readIdx = 0; readIdx < len; ++readIdx) { + char *c(&buffer[readIdx]); + // check for a comment + if (isCommentOpenTag(c, end)) { + ++readIdx; + while (readIdx < len && !isCommentCloseTag(&buffer[readIdx], end)) { + ++readIdx; + } + ++readIdx; + } else if (!isComment<char>(c, end) && !isNewLine(*c)) { + newBuffer.push_back(buffer[readIdx]); + } else { + if (isComment<char>(c, end)) { + ++readIdx; + // skip the comment and the rest of the line + while (readIdx < len && !isEndofLine(buffer[readIdx])) { + ++readIdx; + } + } + } + } + buffer = newBuffer; +} + +char *OpenDDLParser::parseName(char *in, char *end, Name **name) { + *name = nullptr; + if (nullptr == in || in == end) { + return in; + } + + // ignore blanks + in = lookForNextToken(in, end); + if (*in != '$' && *in != '%') { + return in; + } + + NameType ntype(GlobalName); + if (*in == '%') { + ntype = LocalName; + } + in++; + Name *currentName(nullptr); + Text *id(nullptr); + in = parseIdentifier(in, end, &id); + if (id) { + currentName = new Name(ntype, id); + if (currentName) { + *name = currentName; + } + } + + return in; +} + +char *OpenDDLParser::parseIdentifier(char *in, char *end, Text **id) { + *id = nullptr; + if (nullptr == in || in == end) { + return in; + } + + // ignore blanks + in = lookForNextToken(in, end); + if (in == end) { + return in; + } + + // staring with a number is forbidden + if (isNumeric<const char>(*in)) { + return in; + } + + // get size of id + size_t idLen(0); + char *start(in); + while ((in != end) && !isSeparator(*in) && !isNewLine(*in) && + *in != Grammar::OpenPropertyToken[0] && + *in != Grammar::ClosePropertyToken[0] && + *in != '$') { + ++in; + ++idLen; + } + + const size_t len(idLen); + *id = new Text(start, len); + + return in; +} + +char *OpenDDLParser::parsePrimitiveDataType(char *in, char *end, Value::ValueType &type, size_t &len) { + type = Value::ValueType::ddl_none; + len = 0; + if (nullptr == in || in == end) { + return in; + } + + size_t prim_len(0); + for (size_t i = 0; i < (size_t) Value::ValueType::ddl_types_max; i++) { + prim_len = strlen(Grammar::PrimitiveTypeToken[i]); + if (0 == strncmp(in, Grammar::PrimitiveTypeToken[i], prim_len)) { + type = static_cast<Value::ValueType>(i); + break; + } + } + + if (Value::ValueType::ddl_none == type) { + in = lookForNextToken(in, end); + return in; + } else { + in += prim_len; + } + + bool ok(true); + if (*in == Grammar::OpenArrayToken[0]) { + ok = false; + ++in; + char *start(in); + while (in != end) { + ++in; + if (*in == Grammar::CloseArrayToken[0]) { + len = ::atoi(start); + ok = true; + ++in; + break; + } + } + } else { + len = 1; + } + if (!ok) { + type = Value::ValueType::ddl_none; + } + + return in; +} + +char *OpenDDLParser::parseReference(char *in, char *end, std::vector<Name *> &names) { + if (nullptr == in || in == end) { + return in; + } + + Name *nextName(nullptr); + in = parseName(in, end, &nextName); + if (nextName) { + names.push_back(nextName); + } + while (Grammar::CommaSeparator[0] == *in) { + in = getNextSeparator(in, end); + if (Grammar::CommaSeparator[0] == *in) { + in = parseName(in, end, &nextName); + if (nextName) { + names.push_back(nextName); + } + } else { + break; + } + } + + return in; +} + +char *OpenDDLParser::parseBooleanLiteral(char *in, char *end, Value **boolean) { + *boolean = nullptr; + if (nullptr == in || in == end) { + return in; + } + + in = lookForNextToken(in, end); + char *start(in); + size_t len(0); + while (!isSeparator(*in) && in != end) { + ++in; + ++len; + } + ++len; + int res = ::strncmp(Grammar::BoolTrue, start, strlen(Grammar::BoolTrue)); + if (0 != res) { + res = ::strncmp(Grammar::BoolFalse, start, strlen(Grammar::BoolFalse)); + if (0 != res) { + *boolean = nullptr; + return in; + } + *boolean = ValueAllocator::allocPrimData(Value::ValueType::ddl_bool); + (*boolean)->setBool(false); + } else { + *boolean = ValueAllocator::allocPrimData(Value::ValueType::ddl_bool); + (*boolean)->setBool(true); + } + + return in; +} + +char *OpenDDLParser::parseIntegerLiteral(char *in, char *end, Value **integer, Value::ValueType integerType) { + *integer = nullptr; + if (nullptr == in || in == end) { + return in; + } + + if (!(isIntegerType(integerType) || isUnsignedIntegerType(integerType))) { + return in; + } + + in = lookForNextToken(in, end); + char *start(in); + while (!isSeparator(*in) && in != end) { + ++in; + } + + if (isNumeric(*start)) { +#ifdef OPENDDL_NO_USE_CPP11 + const int64 value(atol(start)); // maybe not really 64bit as atoll is but exists without c++11 + const uint64 uvalue(strtoul(start, nullptr, 10)); +#else + const int64 value(atoll(start)); + const uint64 uvalue(strtoull(start, nullptr, 10)); +#endif + *integer = ValueAllocator::allocPrimData(integerType); + switch (integerType) { + case Value::ValueType::ddl_int8: + (*integer)->setInt8((int8)value); + break; + case Value::ValueType::ddl_int16: + (*integer)->setInt16((int16)value); + break; + case Value::ValueType::ddl_int32: + (*integer)->setInt32((int32)value); + break; + case Value::ValueType::ddl_int64: + (*integer)->setInt64((int64)value); + break; + case Value::ValueType::ddl_unsigned_int8: + (*integer)->setUnsignedInt8((uint8)uvalue); + break; + case Value::ValueType::ddl_unsigned_int16: + (*integer)->setUnsignedInt16((uint16)uvalue); + break; + case Value::ValueType::ddl_unsigned_int32: + (*integer)->setUnsignedInt32((uint32)uvalue); + break; + case Value::ValueType::ddl_unsigned_int64: + (*integer)->setUnsignedInt64((uint64)uvalue); + break; + default: + break; + } + } + + return in; +} + +char *OpenDDLParser::parseFloatingLiteral(char *in, char *end, Value **floating, Value::ValueType floatType) { + *floating = nullptr; + if (nullptr == in || in == end) { + return in; + } + + in = lookForNextToken(in, end); + char *start(in); + while (!isSeparator(*in) && in != end) { + ++in; + } + + // parse the float value + bool ok(false); + if (isHexLiteral(start, end)) { + parseHexaLiteral(start, end, floating); + return in; + } + + if (isNumeric(*start)) { + ok = true; + } else { + if (*start == '-') { + if (isNumeric(*(start + 1))) { + ok = true; + } + } + } + + if (ok) { + if (floatType == Value::ValueType::ddl_double) { + const double value(atof(start)); + *floating = ValueAllocator::allocPrimData(Value::ValueType::ddl_double); + (*floating)->setDouble(value); + } else { + const float value((float)atof(start)); + *floating = ValueAllocator::allocPrimData(Value::ValueType::ddl_float); + (*floating)->setFloat(value); + } + } + + return in; +} + +char *OpenDDLParser::parseStringLiteral(char *in, char *end, Value **stringData) { + *stringData = nullptr; + if (nullptr == in || in == end) { + return in; + } + + in = lookForNextToken(in, end); + size_t len(0); + char *start(in); + if (*start == '\"') { + ++start; + ++in; + while (*in != '\"' && in != end) { + ++in; + ++len; + } + + *stringData = ValueAllocator::allocPrimData(Value::ValueType::ddl_string, len); + ::strncpy((char *)(*stringData)->m_data, start, len); + (*stringData)->m_data[len] = '\0'; + ++in; + } + + return in; +} + +static void createPropertyWithData(Text *id, Value *primData, Property **prop) { + if (nullptr != primData) { + (*prop) = new Property(id); + (*prop)->m_value = primData; + } +} + +char *OpenDDLParser::parseHexaLiteral(char *in, char *end, Value **data) { + *data = nullptr; + if (nullptr == in || in == end) { + return in; + } + + in = lookForNextToken(in, end); + if (*in != '0') { + return in; + } + + ++in; + if (*in != 'x' && *in != 'X') { + return in; + } + + ++in; + bool ok(true); + char *start(in); + int pos(0); + while (!isSeparator(*in) && in != end) { + if ((*in < '0' && *in > '9') || (*in < 'a' && *in > 'f') || (*in < 'A' && *in > 'F')) { + ok = false; + break; + } + ++pos; + ++in; + } + + if (!ok) { + return in; + } + + int value(0); + while (pos > 0) { + int v = hex2Decimal(*start); + --pos; + value = (value << 4) | v; + ++start; + } + + *data = ValueAllocator::allocPrimData(Value::ValueType::ddl_unsigned_int64); + if (nullptr != *data) { + (*data)->setUnsignedInt64(value); + } + + return in; +} + +char *OpenDDLParser::parseProperty(char *in, char *end, Property **prop) { + *prop = nullptr; + if (nullptr == in || in == end) { + return in; + } + + in = lookForNextToken(in, end); + Text *id = nullptr; + in = parseIdentifier(in, end, &id); + if (nullptr != id) { + in = lookForNextToken(in, end); + if (in != end && *in == '=') { + ++in; + in = getNextToken(in, end); + Value *primData(nullptr); + if (isInteger(in, end)) { + in = parseIntegerLiteral(in, end, &primData); + createPropertyWithData(id, primData, prop); + } else if (isFloat(in, end)) { + in = parseFloatingLiteral(in, end, &primData); + createPropertyWithData(id, primData, prop); + } else if (isStringLiteral(*in)) { // string data + in = parseStringLiteral(in, end, &primData); + createPropertyWithData(id, primData, prop); + } else { // reference data + std::vector<Name *> names; + in = parseReference(in, end, names); + if (!names.empty()) { + Reference *ref = new Reference(names.size(), &names[0]); + (*prop) = new Property(id); + (*prop)->m_ref = ref; + } + } + } else { + delete id; + } + } + + return in; +} + +char *OpenDDLParser::parseDataList(char *in, char *end, Value::ValueType type, Value **data, + size_t &numValues, Reference **refs, size_t &numRefs) { + *data = nullptr; + numValues = numRefs = 0; + if (nullptr == in || in == end) { + return in; + } + + in = lookForNextToken(in, end); + if (*in == '{') { + ++in; + Value *current(nullptr), *prev(nullptr); + while ('}' != *in) { + current = nullptr; + in = lookForNextToken(in, end); + if (Value::ValueType::ddl_ref == type) { + std::vector<Name *> names; + in = parseReference(in, end, names); + if (!names.empty()) { + Reference *ref = new Reference(names.size(), &names[0]); + *refs = ref; + numRefs = names.size(); + } + } else if (Value::ValueType::ddl_none == type) { + if (isInteger(in, end)) { + in = parseIntegerLiteral(in, end, ¤t); + } else if (isFloat(in, end)) { + in = parseFloatingLiteral(in, end, ¤t); + } else if (isStringLiteral(*in)) { + in = parseStringLiteral(in, end, ¤t); + } else if (isHexLiteral(in, end)) { + in = parseHexaLiteral(in, end, ¤t); + } + } else { + switch (type) { + case Value::ValueType::ddl_int8: + case Value::ValueType::ddl_int16: + case Value::ValueType::ddl_int32: + case Value::ValueType::ddl_int64: + case Value::ValueType::ddl_unsigned_int8: + case Value::ValueType::ddl_unsigned_int16: + case Value::ValueType::ddl_unsigned_int32: + case Value::ValueType::ddl_unsigned_int64: + in = parseIntegerLiteral(in, end, ¤t, type); + break; + case Value::ValueType::ddl_half: + case Value::ValueType::ddl_float: + case Value::ValueType::ddl_double: + in = parseFloatingLiteral(in, end, ¤t, type); + break; + case Value::ValueType::ddl_string: + in = parseStringLiteral(in, end, ¤t); + break; + default: + break; + } + } + + if (nullptr != current) { + if (nullptr == *data) { + *data = current; + prev = current; + } else { + prev->setNext(current); + prev = current; + } + ++numValues; + } + + in = getNextSeparator(in, end); + if (',' != *in && Grammar::CloseBracketToken[0] != *in && !isSpace(*in)) { + break; + } + } + ++in; + } + + return in; +} + +static DataArrayList *createDataArrayList(Value *currentValue, size_t numValues, + Reference *refs, size_t numRefs) { + DataArrayList *dataList(new DataArrayList); + dataList->m_dataList = currentValue; + dataList->m_numItems = numValues; + dataList->m_refs = refs; + dataList->m_numRefs = numRefs; + + return dataList; +} + +char *OpenDDLParser::parseDataArrayList(char *in, char *end, Value::ValueType type, + DataArrayList **dataArrayList) { + if (nullptr == dataArrayList) { + return in; + } + + *dataArrayList = nullptr; + if (nullptr == in || in == end) { + return in; + } + + in = lookForNextToken(in, end); + if (*in == Grammar::OpenBracketToken[0]) { + ++in; + Value *currentValue(nullptr); + Reference *refs(nullptr); + DataArrayList *prev(nullptr), *currentDataList(nullptr); + do { + size_t numRefs(0), numValues(0); + currentValue = nullptr; + + in = parseDataList(in, end, type, ¤tValue, numValues, &refs, numRefs); + if (nullptr != currentValue || 0 != numRefs) { + if (nullptr == prev) { + *dataArrayList = createDataArrayList(currentValue, numValues, refs, numRefs); + prev = *dataArrayList; + } else { + currentDataList = createDataArrayList(currentValue, numValues, refs, numRefs); + if (nullptr != prev) { + prev->m_next = currentDataList; + prev = currentDataList; + } + } + } + } while (Grammar::CommaSeparator[0] == *in && in != end); + in = lookForNextToken(in, end); + ++in; + } + + return in; +} + +const char *OpenDDLParser::getVersion() { + return Version; +} + +END_ODDLPARSER_NS |