diff options
author | sanine <sanine.not@pm.me> | 2022-04-16 11:55:09 -0500 |
---|---|---|
committer | sanine <sanine.not@pm.me> | 2022-04-16 11:55:09 -0500 |
commit | db81b925d776103326128bf629cbdda576a223e7 (patch) | |
tree | 58bea8155c686733310009f6bed7363f91fbeb9d /libs/assimp/contrib/openddlparser/code | |
parent | 55860037b14fb3893ba21cf2654c83d349cc1082 (diff) |
move 3rd-party librarys into libs/ and add built-in honeysuckle
Diffstat (limited to 'libs/assimp/contrib/openddlparser/code')
-rw-r--r-- | libs/assimp/contrib/openddlparser/code/DDLNode.cpp | 227 | ||||
-rw-r--r-- | libs/assimp/contrib/openddlparser/code/OpenDDLCommon.cpp | 200 | ||||
-rw-r--r-- | libs/assimp/contrib/openddlparser/code/OpenDDLExport.cpp | 361 | ||||
-rw-r--r-- | libs/assimp/contrib/openddlparser/code/OpenDDLParser.cpp | 1035 | ||||
-rw-r--r-- | libs/assimp/contrib/openddlparser/code/OpenDDLStream.cpp | 96 | ||||
-rw-r--r-- | libs/assimp/contrib/openddlparser/code/Value.cpp | 438 |
6 files changed, 2357 insertions, 0 deletions
diff --git a/libs/assimp/contrib/openddlparser/code/DDLNode.cpp b/libs/assimp/contrib/openddlparser/code/DDLNode.cpp new file mode 100644 index 0000000..724c5d6 --- /dev/null +++ b/libs/assimp/contrib/openddlparser/code/DDLNode.cpp @@ -0,0 +1,227 @@ +/*----------------------------------------------------------------------------------------------- +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/DDLNode.h> +#include <openddlparser/OpenDDLParser.h> +#include <openddlparser/OpenDDLStream.h> + +#include <algorithm> + +BEGIN_ODDLPARSER_NS + +DDLNode::DllNodeList DDLNode::s_allocatedNodes; + +template <class T> +inline static void releaseDataType(T *ptr) { + if (nullptr == ptr) { + return; + } + + T *current(nullptr); + while (ptr) { + current = ptr; + ptr = ptr->m_next; + delete current; + } +} + +static void releaseReferencedNames(Reference *ref) { + if (nullptr == ref) { + return; + } + + delete ref; +} + +DDLNode::DDLNode(const std::string &type, const std::string &name, size_t idx, DDLNode *parent) : + m_type(type), + m_name(name), + m_parent(parent), + m_children(), + m_properties(nullptr), + m_value(nullptr), + m_dtArrayList(nullptr), + m_references(nullptr), + m_idx(idx) { + if (m_parent) { + m_parent->m_children.push_back(this); + } +} + +DDLNode::~DDLNode() { + delete m_properties; + delete m_value; + releaseReferencedNames(m_references); + + delete m_dtArrayList; + m_dtArrayList = nullptr; + if (s_allocatedNodes[m_idx] == this) { + s_allocatedNodes[m_idx] = nullptr; + } + for (size_t i = 0; i < m_children.size(); i++) { + delete m_children[i]; + } +} + +void DDLNode::attachParent(DDLNode *parent) { + if (m_parent == parent) { + return; + } + + m_parent = parent; + if (nullptr != m_parent) { + m_parent->m_children.push_back(this); + } +} + +void DDLNode::detachParent() { + if (nullptr != m_parent) { + DDLNodeIt it = std::find(m_parent->m_children.begin(), m_parent->m_children.end(), this); + if (m_parent->m_children.end() != it) { + m_parent->m_children.erase(it); + } + m_parent = nullptr; + } +} + +DDLNode *DDLNode::getParent() const { + return m_parent; +} + +const DDLNode::DllNodeList &DDLNode::getChildNodeList() const { + return m_children; +} + +void DDLNode::setType(const std::string &type) { + m_type = type; +} + +const std::string &DDLNode::getType() const { + return m_type; +} + +void DDLNode::setName(const std::string &name) { + m_name = name; +} + +const std::string &DDLNode::getName() const { + return m_name; +} + +void DDLNode::setProperties(Property *prop) { + if (m_properties != nullptr) + delete m_properties; + m_properties = prop; +} + +Property *DDLNode::getProperties() const { + return m_properties; +} + +bool DDLNode::hasProperty(const std::string &name) { + const Property *prop(findPropertyByName(name)); + return (nullptr != prop); +} + +bool DDLNode::hasProperties() const { + return (nullptr != m_properties); +} + +Property *DDLNode::findPropertyByName(const std::string &name) { + if (name.empty()) { + return nullptr; + } + + if (nullptr == m_properties) { + return nullptr; + } + + Property *current(m_properties); + while (nullptr != current) { + int res = strncmp(current->m_key->m_buffer, name.c_str(), name.size()); + if (0 == res) { + return current; + } + current = current->m_next; + } + + return nullptr; +} + +void DDLNode::setValue(Value *val) { + m_value = val; +} + +Value *DDLNode::getValue() const { + return m_value; +} + +void DDLNode::setDataArrayList(DataArrayList *dtArrayList) { + m_dtArrayList = dtArrayList; +} + +DataArrayList *DDLNode::getDataArrayList() const { + return m_dtArrayList; +} + +void DDLNode::setReferences(Reference *refs) { + m_references = refs; +} + +Reference *DDLNode::getReferences() const { + return m_references; +} + +void DDLNode::dump(IOStreamBase &stream) { + if (!stream.isOpen()) { + return; + } + + const std::string &type = this->getType(); + stream.write("type = " + type); + Value::Iterator it(getValue()); + while (it.hasNext()) { + Value *v = it.getNext(); + v->dump(stream); + } +} + +DDLNode *DDLNode::create(const std::string &type, const std::string &name, DDLNode *parent) { + const size_t idx(s_allocatedNodes.size()); + DDLNode *node = new DDLNode(type, name, idx, parent); + s_allocatedNodes.push_back(node); + + return node; +} + +void DDLNode::releaseNodes() { + if (s_allocatedNodes.size() > 0) { + for (DDLNodeIt it = s_allocatedNodes.begin(); it != s_allocatedNodes.end(); it++) { + if (*it) { + delete *it; + } + } + s_allocatedNodes.clear(); + } +} + +END_ODDLPARSER_NS diff --git a/libs/assimp/contrib/openddlparser/code/OpenDDLCommon.cpp b/libs/assimp/contrib/openddlparser/code/OpenDDLCommon.cpp new file mode 100644 index 0000000..d853efa --- /dev/null +++ b/libs/assimp/contrib/openddlparser/code/OpenDDLCommon.cpp @@ -0,0 +1,200 @@ +/*----------------------------------------------------------------------------------------------- +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/DDLNode.h> +#include <openddlparser/OpenDDLCommon.h> +#include <openddlparser/Value.h> + +BEGIN_ODDLPARSER_NS + +Text::Text(const char *buffer, size_t numChars) : + m_capacity(0), + m_len(0), + m_buffer(nullptr) { + set(buffer, numChars); +} + +Text::~Text() { + clear(); +} + +void Text::clear() { + delete[] m_buffer; + m_buffer = nullptr; + m_capacity = 0; + m_len = 0; +} + +void Text::set(const char *buffer, size_t numChars) { + clear(); + if (numChars > 0) { + m_len = numChars; + m_capacity = m_len + 1; + m_buffer = new char[m_capacity]; + strncpy(m_buffer, buffer, numChars); + m_buffer[numChars] = '\0'; + } +} + +bool Text::operator==(const std::string &name) const { + if (m_len != name.size()) { + return false; + } + const int res(strncmp(m_buffer, name.c_str(), name.size())); + + return (0 == res); +} + +bool Text::operator==(const Text &rhs) const { + if (m_len != rhs.m_len) { + return false; + } + + const int res(strncmp(m_buffer, rhs.m_buffer, m_len)); + + return (0 == res); +} + +Name::Name(NameType type, Text *id) : + m_type(type), m_id(id) { + // empty +} + +Name::~Name() { + delete m_id; + m_id = nullptr; +} + +Name::Name(const Name &name) { + m_type = name.m_type; + m_id = new Text(name.m_id->m_buffer, name.m_id->m_len); +} + +Reference::Reference() : + m_numRefs(0), m_referencedName(nullptr) { + // empty +} + +Reference::Reference(size_t numrefs, Name **names) : + m_numRefs(numrefs), m_referencedName(nullptr) { + if (numrefs > 0) { + m_referencedName = new Name *[numrefs]; + for (size_t i = 0; i < numrefs; i++) { + m_referencedName[i] = names[i]; + } + } +} +Reference::Reference(const Reference &ref) { + m_numRefs = ref.m_numRefs; + if (m_numRefs != 0) { + m_referencedName = new Name *[m_numRefs]; + for (size_t i = 0; i < m_numRefs; i++) { + m_referencedName[i] = new Name(*ref.m_referencedName[i]); + } + } +} + +Reference::~Reference() { + for (size_t i = 0; i < m_numRefs; i++) { + delete m_referencedName[i]; + } + m_numRefs = 0; + delete[] m_referencedName; + m_referencedName = nullptr; +} + +size_t Reference::sizeInBytes() { + if (0 == m_numRefs) { + return 0; + } + + size_t size(0); + for (size_t i = 0; i < m_numRefs; i++) { + Name *name(m_referencedName[i]); + if (nullptr != name) { + size += name->m_id->m_len; + } + } + + return size; +} + +Property::Property(Text *id) : + m_key(id), m_value(nullptr), m_ref(nullptr), m_next(nullptr) { + // empty +} + +Property::~Property() { + delete m_key; + if (m_value != nullptr) + delete m_value; + if (m_ref != nullptr) + delete (m_ref); + if (m_next != nullptr) + delete m_next; +} + +DataArrayList::DataArrayList() : + m_numItems(0), m_dataList(nullptr), m_next(nullptr), m_refs(nullptr), m_numRefs(0) { + // empty +} + +DataArrayList::~DataArrayList() { + delete m_dataList; + if (m_next != nullptr) + delete m_next; + if (m_refs != nullptr) + delete m_refs; +} + +size_t DataArrayList::size() { + size_t result(0); + if (nullptr == m_next) { + if (m_dataList != nullptr) { + result = 1; + } + return result; + } + + DataArrayList *n(m_next); + while (nullptr != n) { + result++; + n = n->m_next; + } + return result; +} + +Context::Context() : + m_root(nullptr) { + // empty +} + +Context::~Context() { + clear(); +} + +void Context::clear() { + delete m_root; + m_root = nullptr; +} + +END_ODDLPARSER_NS diff --git a/libs/assimp/contrib/openddlparser/code/OpenDDLExport.cpp b/libs/assimp/contrib/openddlparser/code/OpenDDLExport.cpp new file mode 100644 index 0000000..d235b55 --- /dev/null +++ b/libs/assimp/contrib/openddlparser/code/OpenDDLExport.cpp @@ -0,0 +1,361 @@ +/*----------------------------------------------------------------------------------------------- +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/DDLNode.h> +#include <openddlparser/OpenDDLExport.h> +#include <openddlparser/OpenDDLParser.h> +#include <openddlparser/Value.h> + +#include <sstream> + +BEGIN_ODDLPARSER_NS + +struct DDLNodeIterator { + const DDLNode::DllNodeList &m_childs; + size_t m_idx; + + DDLNodeIterator(const DDLNode::DllNodeList &childs) : + m_childs(childs), m_idx(0) { + // empty + } + + ~DDLNodeIterator() { + // empty + } + + bool getNext(DDLNode **node) { + if (m_childs.size() > (m_idx + 1)) { + m_idx++; + *node = m_childs[m_idx]; + return true; + } + + return false; + } + +private: + DDLNodeIterator() ddl_no_copy; + DDLNodeIterator &operator=(const DDLNodeIterator &) ddl_no_copy; +}; + +static void writeLineEnd(std::string &statement) { + statement += "\n"; +} + +OpenDDLExport::OpenDDLExport(IOStreamBase *stream) : + m_stream(stream) { + if (nullptr == m_stream) { + m_stream = new IOStreamBase(); + } +} + +OpenDDLExport::~OpenDDLExport() { + if (nullptr != m_stream) { + m_stream->close(); + } + delete m_stream; +} + +bool OpenDDLExport::exportContext(Context *ctx, const std::string &filename) { + if (nullptr == ctx) { + return false; + } + + DDLNode *root(ctx->m_root); + if (nullptr == root) { + return true; + } + + if (!filename.empty()) { + if (!m_stream->open(filename)) { + return false; + } + } + + const bool retValue(handleNode(root)); + + return retValue; +} + +bool OpenDDLExport::handleNode(DDLNode *node) { + if (nullptr == node) { + return true; + } + + const DDLNode::DllNodeList &childs = node->getChildNodeList(); + if (childs.empty()) { + return true; + } + DDLNode *current(nullptr); + DDLNodeIterator it(childs); + std::string statement; + bool success(true); + while (it.getNext(¤t)) { + if (nullptr != current) { + success |= writeNode(current, statement); + if (!handleNode(current)) { + success = false; + } + } + } + + return success; +} + +bool OpenDDLExport::writeToStream(const std::string &statement) { + if (nullptr == m_stream) { + return false; + } + + if (!statement.empty()) { + m_stream->write(statement); + } + + return true; +} + +bool OpenDDLExport::writeNode(DDLNode *node, std::string &statement) { + writeNodeHeader(node, statement); + if (node->hasProperties()) { + writeProperties(node, statement); + } + writeLineEnd(statement); + + statement = "}"; + DataArrayList *al(node->getDataArrayList()); + if (nullptr != al) { + writeValueType(al->m_dataList->m_type, al->m_numItems, statement); + writeValueArray(al, statement); + } + Value *v(node->getValue()); + if (nullptr != v) { + writeValueType(v->m_type, 1, statement); + statement = "{"; + writeLineEnd(statement); + writeValue(v, statement); + statement = "}"; + writeLineEnd(statement); + } + statement = "}"; + writeLineEnd(statement); + + writeToStream(statement); + + return true; +} + +bool OpenDDLExport::writeNodeHeader(DDLNode *node, std::string &statement) { + if (nullptr == node) { + return false; + } + + statement += node->getType(); + const std::string &name(node->getName()); + if (!name.empty()) { + statement += " "; + statement += "$"; + statement += name; + } + + return true; +} + +bool OpenDDLExport::writeProperties(DDLNode *node, std::string &statement) { + if (nullptr == node) { + return false; + } + + Property *prop(node->getProperties()); + // if no properties are there, return + if (nullptr == prop) { + return true; + } + + if (nullptr != prop) { + // for instance (attrib = "position", bla=2) + statement += "("; + bool first(true); + while (nullptr != prop) { + if (!first) { + statement += ", "; + } else { + first = false; + } + statement += std::string(prop->m_key->m_buffer); + statement += " = "; + writeValue(prop->m_value, statement); + prop = prop->m_next; + } + + statement += ")"; + } + + return true; +} + +bool OpenDDLExport::writeValueType(Value::ValueType type, size_t numItems, std::string &statement) { + if (Value::ValueType::ddl_types_max == type) { + return false; + } + + const std::string typeStr(getTypeToken(type)); + statement += typeStr; + // if we have an array to write + if (numItems > 1) { + statement += "["; + char buffer[256]; + ::memset(buffer, '\0', 256 * sizeof(char)); + sprintf(buffer, "%d", static_cast<int>(numItems)); + statement += buffer; + statement += "]"; + } + + return true; +} + +bool OpenDDLExport::writeValue(Value *val, std::string &statement) { + if (nullptr == val) { + return false; + } + + switch (val->m_type) { + case Value::ValueType::ddl_bool: + if (true == val->getBool()) { + statement += "true"; + } else { + statement += "false"; + } + break; + case Value::ValueType::ddl_int8 : { + std::stringstream stream; + const int i = static_cast<int>(val->getInt8()); + stream << i; + statement += stream.str(); + } break; + case Value::ValueType::ddl_int16: { + std::stringstream stream; + char buffer[256]; + ::memset(buffer, '\0', 256 * sizeof(char)); + sprintf(buffer, "%d", val->getInt16()); + statement += buffer; + } break; + case Value::ValueType::ddl_int32: { + std::stringstream stream; + char buffer[256]; + ::memset(buffer, '\0', 256 * sizeof(char)); + const int i = static_cast<int>(val->getInt32()); + sprintf(buffer, "%d", i); + statement += buffer; + } break; + case Value::ValueType::ddl_int64: { + std::stringstream stream; + const int i = static_cast<int>(val->getInt64()); + stream << i; + statement += stream.str(); + } break; + case Value::ValueType::ddl_unsigned_int8: { + std::stringstream stream; + const int i = static_cast<unsigned int>(val->getUnsignedInt8()); + stream << i; + statement += stream.str(); + } break; + case Value::ValueType::ddl_unsigned_int16: { + std::stringstream stream; + const int i = static_cast<unsigned int>(val->getUnsignedInt16()); + stream << i; + statement += stream.str(); + } break; + case Value::ValueType::ddl_unsigned_int32: { + std::stringstream stream; + const int i = static_cast<unsigned int>(val->getUnsignedInt32()); + stream << i; + statement += stream.str(); + } break; + case Value::ValueType::ddl_unsigned_int64: { + std::stringstream stream; + const int i = static_cast<unsigned int>(val->getUnsignedInt64()); + stream << i; + statement += stream.str(); + } break; + case Value::ValueType::ddl_half: + break; + case Value::ValueType::ddl_float: { + std::stringstream stream; + stream << val->getFloat(); + statement += stream.str(); + } break; + case Value::ValueType::ddl_double: { + std::stringstream stream; + stream << val->getDouble(); + statement += stream.str(); + } break; + case Value::ValueType::ddl_string: { + std::stringstream stream; + stream << val->getString(); + statement += "\""; + statement += stream.str(); + statement += "\""; + } break; + case Value::ValueType::ddl_ref: + break; + case Value::ValueType::ddl_none: + case Value::ValueType::ddl_types_max: + default: + break; + } + + return true; +} + +bool OpenDDLExport::writeValueArray(DataArrayList *al, std::string &statement) { + if (nullptr == al) { + return false; + } + + if (0 == al->m_numItems) { + return true; + } + + DataArrayList *nextDataArrayList = al; + Value *nextValue(nextDataArrayList->m_dataList); + while (nullptr != nextDataArrayList) { + if (nullptr != nextDataArrayList) { + statement += "{ "; + nextValue = nextDataArrayList->m_dataList; + size_t idx(0); + while (nullptr != nextValue) { + if (idx > 0) { + statement += ", "; + } + writeValue(nextValue, statement); + nextValue = nextValue->m_next; + idx++; + } + statement += " }"; + } + nextDataArrayList = nextDataArrayList->m_next; + } + + return true; +} + +END_ODDLPARSER_NS 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 diff --git a/libs/assimp/contrib/openddlparser/code/OpenDDLStream.cpp b/libs/assimp/contrib/openddlparser/code/OpenDDLStream.cpp new file mode 100644 index 0000000..1a38dfa --- /dev/null +++ b/libs/assimp/contrib/openddlparser/code/OpenDDLStream.cpp @@ -0,0 +1,96 @@ +/*----------------------------------------------------------------------------------------------- +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/OpenDDLStream.h> + +BEGIN_ODDLPARSER_NS + +StreamFormatterBase::StreamFormatterBase() { + // empty +} + +StreamFormatterBase::~StreamFormatterBase() { + // empty +} + +std::string StreamFormatterBase::format(const std::string &statement) { + std::string tmp(statement); + return tmp; +} + +IOStreamBase::IOStreamBase(StreamFormatterBase *formatter) : + m_formatter(formatter), + m_file(nullptr) { + if (nullptr == m_formatter) { + m_formatter = new StreamFormatterBase; + } +} + +IOStreamBase::~IOStreamBase() { + delete m_formatter; + m_formatter = nullptr; +} + +bool IOStreamBase::open(const std::string &name) { + m_file = ::fopen(name.c_str(), "a"); + if (m_file == nullptr) { + return false; + } + + return true; +} + +bool IOStreamBase::close() { + if (nullptr == m_file) { + return false; + } + + ::fclose(m_file); + m_file = nullptr; + + return true; +} + +bool IOStreamBase::isOpen() const { + return (nullptr != m_file); +} + +size_t IOStreamBase::read(size_t sizeToRead, std::string &statement) { + if (nullptr == m_file) { + return 0; + } + + statement.resize(sizeToRead); + const size_t readBytes = ::fread(&statement[0], 1, sizeToRead, m_file); + + return readBytes; +} + +size_t IOStreamBase::write(const std::string &statement) { + if (nullptr == m_file) { + return 0; + } + std::string formatStatement = m_formatter->format(statement); + return ::fwrite(formatStatement.c_str(), sizeof(char), formatStatement.size(), m_file); +} + +END_ODDLPARSER_NS diff --git a/libs/assimp/contrib/openddlparser/code/Value.cpp b/libs/assimp/contrib/openddlparser/code/Value.cpp new file mode 100644 index 0000000..5a8aa39 --- /dev/null +++ b/libs/assimp/contrib/openddlparser/code/Value.cpp @@ -0,0 +1,438 @@ +/*----------------------------------------------------------------------------------------------- +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/OpenDDLStream.h> +#include <openddlparser/Value.h> + +#include <cassert> + +BEGIN_ODDLPARSER_NS + +static Value::Iterator end(nullptr); + +Value::Iterator::Iterator() : + m_start(nullptr), + m_current(nullptr) { + // empty +} + +Value::Iterator::Iterator(Value *start) : + m_start(start), + m_current(start) { + // empty +} + +Value::Iterator::Iterator(const Iterator &rhs) : + m_start(rhs.m_start), + m_current(rhs.m_current) { + // empty +} + +Value::Iterator::~Iterator() { + // empty +} + +bool Value::Iterator::hasNext() const { + if (nullptr == m_current) { + return false; + } + return (nullptr != m_current->getNext()); +} + +Value *Value::Iterator::getNext() { + if (!hasNext()) { + return nullptr; + } + + Value *v(m_current->getNext()); + m_current = v; + + return v; +} + +const Value::Iterator Value::Iterator::operator++(int) { + if (nullptr == m_current) { + return end; + } + + m_current = m_current->getNext(); + Iterator inst(m_current); + + return inst; +} + +Value::Iterator &Value::Iterator::operator++() { + if (nullptr == m_current) { + return end; + } + + m_current = m_current->getNext(); + + return *this; +} + +bool Value::Iterator::operator==(const Iterator &rhs) const { + return (m_current == rhs.m_current); +} + +Value *Value::Iterator::operator->() const { + if (nullptr == m_current) { + return nullptr; + } + return m_current; +} + +Value::Value(ValueType type) : + m_type(type), + m_size(0), + m_data(nullptr), + m_next(nullptr) { + // empty +} + +Value::~Value() { + if (m_data != nullptr) { + if (m_type == ValueType::ddl_ref) { + Reference *tmp = (Reference *)m_data; + if (tmp != nullptr) { + delete tmp; + } + } else { + delete[] m_data; + } + } + delete m_next; +} + +void Value::setBool(bool value) { + assert(ValueType::ddl_bool == m_type); + ::memcpy(m_data, &value, m_size); +} + +bool Value::getBool() { + assert(ValueType::ddl_bool == m_type); + return (*m_data == 1); +} + +void Value::setInt8(int8 value) { + assert(ValueType::ddl_int8 == m_type); + ::memcpy(m_data, &value, m_size); +} + +int8 Value::getInt8() { + assert(ValueType::ddl_int8 == m_type); + return (int8)(*m_data); +} + +void Value::setInt16(int16 value) { + assert(ValueType::ddl_int16 == m_type); + ::memcpy(m_data, &value, m_size); +} + +int16 Value::getInt16() { + assert(ValueType::ddl_int16 == m_type); + int16 i; + ::memcpy(&i, m_data, m_size); + return i; +} + +void Value::setInt32(int32 value) { + assert(ValueType::ddl_int32 == m_type); + ::memcpy(m_data, &value, m_size); +} + +int32 Value::getInt32() { + assert(ValueType::ddl_int32 == m_type); + int32 i; + ::memcpy(&i, m_data, m_size); + return i; +} + +void Value::setInt64(int64 value) { + assert(ValueType::ddl_int64 == m_type); + ::memcpy(m_data, &value, m_size); +} + +int64 Value::getInt64() { + assert(ValueType::ddl_int64 == m_type); + int64 i; + ::memcpy(&i, m_data, m_size); + return i; +} + +void Value::setUnsignedInt8(uint8 value) { + assert(ValueType::ddl_unsigned_int8 == m_type); + ::memcpy(m_data, &value, m_size); +} + +uint8 Value::getUnsignedInt8() const { + assert(ValueType::ddl_unsigned_int8 == m_type); + uint8 i; + ::memcpy(&i, m_data, m_size); + return i; +} + +void Value::setUnsignedInt16(uint16 value) { + assert(ValueType::ddl_unsigned_int16 == m_type); + ::memcpy(m_data, &value, m_size); +} + +uint16 Value::getUnsignedInt16() const { + assert(ValueType::ddl_unsigned_int16 == m_type); + uint16 i; + ::memcpy(&i, m_data, m_size); + return i; +} + +void Value::setUnsignedInt32(uint32 value) { + assert(ValueType::ddl_unsigned_int32 == m_type); + ::memcpy(m_data, &value, m_size); +} + +uint32 Value::getUnsignedInt32() const { + assert(ValueType::ddl_unsigned_int32 == m_type); + uint32 i; + ::memcpy(&i, m_data, m_size); + return i; +} + +void Value::setUnsignedInt64(uint64 value) { + assert(ValueType::ddl_unsigned_int64 == m_type); + ::memcpy(m_data, &value, m_size); +} + +uint64 Value::getUnsignedInt64() const { + assert(ValueType::ddl_unsigned_int64 == m_type); + uint64 i; + ::memcpy(&i, m_data, m_size); + return i; +} + +void Value::setFloat(float value) { + assert(ValueType::ddl_float == m_type); + ::memcpy(m_data, &value, m_size); +} + +float Value::getFloat() const { + if (m_type == ValueType::ddl_float) { + float v; + ::memcpy(&v, m_data, m_size); + return (float)v; + } else { + float tmp; + ::memcpy(&tmp, m_data, 4); + return (float)tmp; + } +} + +void Value::setDouble(double value) { + assert(ValueType::ddl_double == m_type); + ::memcpy(m_data, &value, m_size); +} + +double Value::getDouble() const { + if (m_type == ValueType::ddl_double) { + double v; + ::memcpy(&v, m_data, m_size); + return (float)v; + } else { + double tmp; + ::memcpy(&tmp, m_data, 4); + return (double)tmp; + } +} + +void Value::setString(const std::string &str) { + assert(ValueType::ddl_string == m_type); + ::memcpy(m_data, str.c_str(), str.size()); + m_data[str.size()] = '\0'; +} + +const char *Value::getString() const { + assert(ValueType::ddl_string == m_type); + return (const char *)m_data; +} + +void Value::setRef(Reference *ref) { + assert(ValueType::ddl_ref == m_type); + + if (nullptr != ref) { + const size_t sizeInBytes(ref->sizeInBytes()); + if (sizeInBytes > 0) { + if (nullptr != m_data) { + delete[] m_data; + } + + m_data = (unsigned char *)new Reference(*ref); + } + } +} + +Reference *Value::getRef() const { + assert(ValueType::ddl_ref == m_type); + + return (Reference *)m_data; +} + +void Value::dump(IOStreamBase &stream) { + switch (m_type) { + case ValueType::ddl_none: + stream.write("None\n"); + break; + case ValueType::ddl_bool: + stream.write(std::to_string(getBool()) + "\n"); + break; + case ValueType::ddl_int8: + stream.write(std::to_string(getInt8()) + "\n"); + break; + case ValueType::ddl_int16: + stream.write(std::to_string(getInt16()) + "\n"); + break; + case ValueType::ddl_int32: + stream.write(std::to_string(getInt32()) + "\n"); + break; + case ValueType::ddl_int64: + stream.write(std::to_string(getInt64()) + "\n"); + break; + case ValueType::ddl_unsigned_int8: + stream.write("Not supported\n"); + break; + case ValueType::ddl_unsigned_int16: + stream.write("Not supported\n"); + break; + case ValueType::ddl_unsigned_int32: + stream.write("Not supported\n"); + break; + case ValueType::ddl_unsigned_int64: + stream.write("Not supported\n"); + break; + case ValueType::ddl_half: + stream.write("Not supported\n"); + break; + case ValueType::ddl_float: + stream.write(std::to_string(getFloat()) + "\n"); + break; + case ValueType::ddl_double: + stream.write(std::to_string(getDouble()) + "\n"); + break; + case ValueType::ddl_string: + stream.write(std::string(getString()) + "\n"); + break; + case ValueType::ddl_ref: + stream.write("Not supported\n"); + break; + default: + break; + } +} + +void Value::setNext(Value *next) { + m_next = next; +} + +Value *Value::getNext() const { + return m_next; +} + +size_t Value::size() const { + size_t result = 1; + Value *n = m_next; + while (n != nullptr) { + result++; + n = n->m_next; + } + return result; +} + +Value *ValueAllocator::allocPrimData(Value::ValueType type, size_t len) { + if (type == Value::ValueType::ddl_none || Value::ValueType::ddl_types_max == type) { + return nullptr; + } + + Value *data = new Value(type); + switch (type) { + case Value::ValueType::ddl_bool: + data->m_size = sizeof(bool); + break; + case Value::ValueType::ddl_int8: + data->m_size = sizeof(int8); + break; + case Value::ValueType::ddl_int16: + data->m_size = sizeof(int16); + break; + case Value::ValueType::ddl_int32: + data->m_size = sizeof(int32); + break; + case Value::ValueType::ddl_int64: + data->m_size = sizeof(int64); + break; + case Value::ValueType::ddl_unsigned_int8: + data->m_size = sizeof(uint8); + break; + case Value::ValueType::ddl_unsigned_int16: + data->m_size = sizeof(uint16); + break; + case Value::ValueType::ddl_unsigned_int32: + data->m_size = sizeof(uint32); + break; + case Value::ValueType::ddl_unsigned_int64: + data->m_size = sizeof(uint64); + break; + case Value::ValueType::ddl_half: + data->m_size = sizeof(short); + break; + case Value::ValueType::ddl_float: + data->m_size = sizeof(float); + break; + case Value::ValueType::ddl_double: + data->m_size = sizeof(double); + break; + case Value::ValueType::ddl_string: + data->m_size = sizeof(char) * (len + 1); + break; + case Value::ValueType::ddl_ref: + data->m_size = 0; + break; + case Value::ValueType::ddl_none: + case Value::ValueType::ddl_types_max: + default: + break; + } + + if (data->m_size) { + data->m_data = new unsigned char[data->m_size]; + ::memset(data->m_data, 0, data->m_size); + } + + return data; +} + +void ValueAllocator::releasePrimData(Value **data) { + if (!data) { + return; + } + + delete *data; + *data = nullptr; +} + +END_ODDLPARSER_NS |