add openddl-parser to contrib.
Signed-off-by: Kim Kulling <kim.kulling@googlemail.com>pull/502/head
parent
62225f61e4
commit
1ee4c06e4b
|
@ -10,7 +10,7 @@ build
|
||||||
# Output
|
# Output
|
||||||
bin/
|
bin/
|
||||||
lib/
|
lib/
|
||||||
contrib/
|
|
||||||
|
|
||||||
# Generated
|
# Generated
|
||||||
assimp.pc
|
assimp.pc
|
||||||
|
|
|
@ -154,6 +154,7 @@ else(NOT ZLIB_FOUND)
|
||||||
endif(NOT ZLIB_FOUND)
|
endif(NOT ZLIB_FOUND)
|
||||||
INCLUDE_DIRECTORIES(${ZLIB_INCLUDE_DIR})
|
INCLUDE_DIRECTORIES(${ZLIB_INCLUDE_DIR})
|
||||||
|
|
||||||
|
add_subdirectory( contrib/openddlparser )
|
||||||
# Search for unzip
|
# Search for unzip
|
||||||
if (PKG_CONFIG_FOUND)
|
if (PKG_CONFIG_FOUND)
|
||||||
PKG_CHECK_MODULES(UNZIP minizip)
|
PKG_CHECK_MODULES(UNZIP minizip)
|
||||||
|
|
|
@ -634,7 +634,6 @@ SET( unzip_SRCS
|
||||||
)
|
)
|
||||||
SOURCE_GROUP( unzip FILES ${unzip_SRCS})
|
SOURCE_GROUP( unzip FILES ${unzip_SRCS})
|
||||||
|
|
||||||
|
|
||||||
# VC2010 fixes
|
# VC2010 fixes
|
||||||
if(MSVC10)
|
if(MSVC10)
|
||||||
option( VC10_STDINT_FIX "Fix for VC10 Compiler regarding pstdint.h redefinition errors" OFF )
|
option( VC10_STDINT_FIX "Fix for VC10 Compiler regarding pstdint.h redefinition errors" OFF )
|
||||||
|
|
|
@ -0,0 +1,63 @@
|
||||||
|
CMAKE_MINIMUM_REQUIRED( VERSION 2.6 )
|
||||||
|
PROJECT( OpenDDL-Parser )
|
||||||
|
SET ( OPENDDL_PARSER_VERSION_MAJOR 0 )
|
||||||
|
SET ( OPENDDL_PARSER_VERSION_MINOR 1 )
|
||||||
|
SET ( OPENDDL_PARSER_VERSION_PATCH 0 )
|
||||||
|
SET ( OPENDDL_PARSER_VERSION ${CPPCORE_VERSION_MAJOR}.${CPPCORE_VERSION_MINOR}.${CPPCORE_VERSION_PATCH} )
|
||||||
|
SET ( PROJECT_VERSION "${OPENDDL_PARSER_VERSION}" )
|
||||||
|
|
||||||
|
if( CMAKE_COMPILER_IS_GNUCC OR CMAKE_COMPILER_IS_GNUCXX )
|
||||||
|
find_package(Threads)
|
||||||
|
else()
|
||||||
|
add_definitions( -D_CRT_SECURE_NO_WARNINGS )
|
||||||
|
endif()
|
||||||
|
|
||||||
|
add_definitions( -DOPENDDLPARSER_BUILD )
|
||||||
|
add_definitions( -D_VARIADIC_MAX=10 )
|
||||||
|
|
||||||
|
INCLUDE_DIRECTORIES(
|
||||||
|
./
|
||||||
|
include/
|
||||||
|
contrib/gtest-1.7.0/include
|
||||||
|
contrib/gtest-1.7.0/
|
||||||
|
)
|
||||||
|
|
||||||
|
link_directories(
|
||||||
|
./
|
||||||
|
)
|
||||||
|
|
||||||
|
SET( CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_HOME_DIRECTORY}/lib )
|
||||||
|
SET( CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_HOME_DIRECTORY}/lib )
|
||||||
|
SET( CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_HOME_DIRECTORY}/bin )
|
||||||
|
|
||||||
|
if( WIN32 AND NOT CYGWIN )
|
||||||
|
set( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /EHsc" ) # Force to always compile with W4
|
||||||
|
if( CMAKE_CXX_FLAGS MATCHES "/W[0-4]" )
|
||||||
|
string( REGEX REPLACE "/W[0-4]" "/W4" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}" )
|
||||||
|
else()
|
||||||
|
set( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /W4" )
|
||||||
|
endif()
|
||||||
|
elseif( CMAKE_COMPILER_IS_GNUCC OR CMAKE_COMPILER_IS_GNUCXX )
|
||||||
|
# Update if necessary
|
||||||
|
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wno-long-long -pedantic -std=c++0x")
|
||||||
|
elseif ( "${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang" )
|
||||||
|
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wno-long-long -pedantic -std=c++11")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
SET ( openddl_parser_src
|
||||||
|
code/OpenDDLParser.cpp
|
||||||
|
code/DDLNode.cpp
|
||||||
|
code/Value.cpp
|
||||||
|
include/openddlparser/OpenDDLParser.h
|
||||||
|
include/openddlparser/OpenDDLParserUtils.h
|
||||||
|
include/openddlparser/OpenDDLCommon.h
|
||||||
|
include/openddlparser/DDLNode.h
|
||||||
|
include/openddlparser/Value.h
|
||||||
|
README.md
|
||||||
|
)
|
||||||
|
|
||||||
|
SOURCE_GROUP( code FILES ${openddl_parser_src} )
|
||||||
|
|
||||||
|
ADD_LIBRARY( openddl_parser SHARED
|
||||||
|
${openddl_parser_src}
|
||||||
|
)
|
|
@ -0,0 +1,111 @@
|
||||||
|
The OpenDDL-Parser
|
||||||
|
==================
|
||||||
|
|
||||||
|
A simple and fast OpenDDL Parser
|
||||||
|
Current build status: [![Build Status](https://travis-ci.org/kimkulling/openddl-parser.png)](https://travis-ci.org/kimkulling/openddl-parser)
|
||||||
|
|
||||||
|
Get the source code
|
||||||
|
===================
|
||||||
|
You can get the code from our git repository, which is located at GitHub. You can clone the repository like:
|
||||||
|
|
||||||
|
> git clone https://github.com/kimkulling/openddl-parser.git
|
||||||
|
|
||||||
|
Build from repo
|
||||||
|
===============
|
||||||
|
To build the library you need to install cmake first ( see http://www.cmake.org/ for more information ). Make also sure that a compiler toolchain is installed on your machine.
|
||||||
|
After installing it you can open a console and type:
|
||||||
|
|
||||||
|
> cmake CMakeLists.txt
|
||||||
|
|
||||||
|
This command will generate a build environment for your installed build enrironment ( for Visual Studio the project files will be generated, for gcc the makefiles will be generated ).
|
||||||
|
When using an IDE open the IDE and run the build. When using GNU-make type in your console:
|
||||||
|
|
||||||
|
> make
|
||||||
|
|
||||||
|
and that's all.
|
||||||
|
|
||||||
|
Use the library
|
||||||
|
===============
|
||||||
|
To use the OpenDDL-parser you need to build the lib first. Now add the
|
||||||
|
> <Repo-folder>/include
|
||||||
|
|
||||||
|
to your include-path and the
|
||||||
|
|
||||||
|
> <Repo-folder>/lib
|
||||||
|
|
||||||
|
to your lib-folder. Link the openddl.lib to your application.
|
||||||
|
|
||||||
|
Here is a small example how to use the lib:
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
#include <cassert>
|
||||||
|
#include <openddlparser/OpenDDLParser.h>
|
||||||
|
|
||||||
|
USE_ODDLPARSER_NS;
|
||||||
|
|
||||||
|
int main( int argc, char *argv[] ) {
|
||||||
|
if( argc < 3 ) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
char *filename( nullptr );
|
||||||
|
if( 0 == strncmp( FileOption, argv[ 1 ], strlen( FileOption ) ) ) {
|
||||||
|
filename = argv[ 2 ];
|
||||||
|
}
|
||||||
|
std::cout << "file to import: " << filename << std::endl;
|
||||||
|
if( nullptr == filename ) {
|
||||||
|
std::cerr << "Invalid filename." << std::endl;
|
||||||
|
return Error;
|
||||||
|
}
|
||||||
|
|
||||||
|
FILE *fileStream = fopen( filename, "r+" );
|
||||||
|
if( NULL == filename ) {
|
||||||
|
std::cerr << "Cannot open file " << filename << std::endl;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// obtain file size:
|
||||||
|
fseek( fileStream, 0, SEEK_END );
|
||||||
|
const size_t size( ftell( fileStream ) );
|
||||||
|
rewind( fileStream );
|
||||||
|
if( size > 0 ) {
|
||||||
|
char *buffer = new char[ size ];
|
||||||
|
const size_t readSize( fread( buffer, sizeof( char ), size, fileStream ) );
|
||||||
|
assert( readSize == size );
|
||||||
|
OpenDDLParser theParser;
|
||||||
|
theParser.setBuffer( buffer, size );
|
||||||
|
const bool result( theParser.parse() );
|
||||||
|
if( !result ) {
|
||||||
|
std::cerr << "Error while parsing file " << filename << "." << std::endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
How to access the imported data
|
||||||
|
===============================
|
||||||
|
The data is organized as a tree. You can get the root tree with the following code:
|
||||||
|
|
||||||
|
```
|
||||||
|
OpenDDLParser theParser;
|
||||||
|
theParser.setBuffer( buffer, size );
|
||||||
|
const bool result( theParser.parse() );
|
||||||
|
if ( result ) {
|
||||||
|
DDLNode *root = theParser.getRoot();
|
||||||
|
|
||||||
|
DDLNode::DllNodeList childs = root->getChildNodeList();
|
||||||
|
for ( size_t i=0; i<childs.size(); i++ ) {
|
||||||
|
DDLNode *child = childs[ i ];
|
||||||
|
Property *prop = child->getProperty(); // to get properties
|
||||||
|
std:.string type = child->getType(); // to get the node type
|
||||||
|
Value *values = child->getValue(); // to get the data;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
The instance called root contains the data.
|
|
@ -0,0 +1,162 @@
|
||||||
|
/*-----------------------------------------------------------------------------------------------
|
||||||
|
The MIT License (MIT)
|
||||||
|
|
||||||
|
Copyright (c) 2014 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 <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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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_idx( idx )
|
||||||
|
, m_dtArrayList( nullptr ) {
|
||||||
|
if( m_parent ) {
|
||||||
|
m_parent->m_children.push_back( this );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
DDLNode::~DDLNode() {
|
||||||
|
releaseDataType<Property>( m_properties );
|
||||||
|
releaseDataType<Value>( m_value );
|
||||||
|
|
||||||
|
delete m_dtArrayList;
|
||||||
|
m_dtArrayList = nullptr;
|
||||||
|
if( s_allocatedNodes[ m_idx ] == this ) {
|
||||||
|
s_allocatedNodes[ m_idx ] = nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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( m_parent ) {
|
||||||
|
std::vector<DDLNode*>::iterator it;
|
||||||
|
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 *first ) {
|
||||||
|
m_properties = first;
|
||||||
|
}
|
||||||
|
|
||||||
|
Property *DDLNode::getProperties() const {
|
||||||
|
return m_properties;
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
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( DllNodeList::iterator it = s_allocatedNodes.begin(); it != s_allocatedNodes.end(); it++ ) {
|
||||||
|
if( *it ) {
|
||||||
|
delete *it;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
s_allocatedNodes.clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
END_ODDLPARSER_NS
|
|
@ -0,0 +1,852 @@
|
||||||
|
/*-----------------------------------------------------------------------------------------------
|
||||||
|
The MIT License (MIT)
|
||||||
|
|
||||||
|
Copyright (c) 2014 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/OpenDDLParser.h>
|
||||||
|
|
||||||
|
#include <cassert>
|
||||||
|
#include <iostream>
|
||||||
|
#include <sstream>
|
||||||
|
#include <algorithm>
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
# include <windows.h>
|
||||||
|
#endif // _WIN32
|
||||||
|
|
||||||
|
#define DEBUG_HEADER_NAME
|
||||||
|
|
||||||
|
BEGIN_ODDLPARSER_NS
|
||||||
|
|
||||||
|
static const char *Version = "0.1.0";
|
||||||
|
|
||||||
|
static const char* PrimitiveTypeToken[ Value::ddl_types_max ] = {
|
||||||
|
"bool",
|
||||||
|
"int8",
|
||||||
|
"int16",
|
||||||
|
"int32",
|
||||||
|
"int64",
|
||||||
|
"unsigned_int8",
|
||||||
|
"unsigned_int16",
|
||||||
|
"unsigned_int32",
|
||||||
|
"unsigned_int64",
|
||||||
|
"half",
|
||||||
|
"float",
|
||||||
|
"double",
|
||||||
|
"string",
|
||||||
|
"ref"
|
||||||
|
};
|
||||||
|
|
||||||
|
static const char *BoolTrue = "true";
|
||||||
|
static const char *BoolFalse = "false";
|
||||||
|
static const char *RefToken = "ref";
|
||||||
|
|
||||||
|
static void logInvalidTokenError( char *in, char *exp, OpenDDLParser::logCallback callback ) {
|
||||||
|
std::stringstream stream;
|
||||||
|
stream << "Invalid token " << *in << ", " << exp << " expected." << std::endl;
|
||||||
|
callback( ddl_error_msg, stream.str() );
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool isIntegerType( Value::ValueType integerType ) {
|
||||||
|
if( integerType != Value::ddl_int8 && integerType != Value::ddl_int16 && integerType != Value::ddl_int32 && integerType != Value::ddl_int64 ) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static DDLNode *createDDLNode( Identifier *id, Property *first, OpenDDLParser *parser ) {
|
||||||
|
if( nullptr == id || nullptr == parser ) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::string type( id->m_buffer );
|
||||||
|
DDLNode *parent( parser->top() );
|
||||||
|
DDLNode *node = DDLNode::create( type, "", parent );
|
||||||
|
if( nullptr != first ) {
|
||||||
|
node->setProperties( first );
|
||||||
|
}
|
||||||
|
|
||||||
|
return node;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void logMessage( LogSeverity severity, const std::string &msg ) {
|
||||||
|
std::string log;
|
||||||
|
if( ddl_debug_msg == severity ) {
|
||||||
|
log += "Debug:";
|
||||||
|
} else if( ddl_info_msg == severity ) {
|
||||||
|
log += "Info :";
|
||||||
|
} else if( ddl_warn_msg == severity ) {
|
||||||
|
log += "Warn :";
|
||||||
|
} else if( ddl_error_msg == severity ) {
|
||||||
|
log += "Error:";
|
||||||
|
} else {
|
||||||
|
log += "None :";
|
||||||
|
}
|
||||||
|
|
||||||
|
log += msg;
|
||||||
|
std::cout << log;
|
||||||
|
}
|
||||||
|
|
||||||
|
OpenDDLParser::OpenDDLParser()
|
||||||
|
: m_logCallback( logMessage )
|
||||||
|
, m_ownsBuffer( false )
|
||||||
|
,m_buffer( nullptr )
|
||||||
|
, m_len( 0 )
|
||||||
|
, m_stack()
|
||||||
|
, m_context( nullptr ) {
|
||||||
|
// empty
|
||||||
|
}
|
||||||
|
|
||||||
|
OpenDDLParser::OpenDDLParser( char *buffer, size_t len, bool ownsIt )
|
||||||
|
: m_logCallback( &logMessage )
|
||||||
|
, m_ownsBuffer( false )
|
||||||
|
, m_buffer( nullptr )
|
||||||
|
, m_len( 0 )
|
||||||
|
, m_context( nullptr ) {
|
||||||
|
if( 0 != m_len ) {
|
||||||
|
setBuffer( buffer, len, ownsIt );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
OpenDDLParser::~OpenDDLParser() {
|
||||||
|
clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
void OpenDDLParser::setLogCallback( logCallback callback ) {
|
||||||
|
if( nullptr != callback ) {
|
||||||
|
// install user-specific log callback
|
||||||
|
m_logCallback = callback;
|
||||||
|
} else {
|
||||||
|
// install default log callback
|
||||||
|
m_logCallback = &logMessage;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
OpenDDLParser::logCallback OpenDDLParser::getLogCallback() const {
|
||||||
|
return m_logCallback;
|
||||||
|
}
|
||||||
|
|
||||||
|
void OpenDDLParser::setBuffer( char *buffer, size_t len, bool ownsIt ) {
|
||||||
|
if( m_buffer && m_ownsBuffer ) {
|
||||||
|
delete[] m_buffer;
|
||||||
|
m_buffer = nullptr;
|
||||||
|
m_len = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_ownsBuffer = ownsIt;
|
||||||
|
if( m_ownsBuffer ) {
|
||||||
|
// when we are owning the buffer we will do a deep copy
|
||||||
|
m_buffer = new char[ len ];
|
||||||
|
m_len = len;
|
||||||
|
::memcpy( m_buffer, buffer, len );
|
||||||
|
} else {
|
||||||
|
// when we are not owning the buffer, we just do a shallow copy
|
||||||
|
m_buffer = buffer;
|
||||||
|
m_len = len;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
char *OpenDDLParser::getBuffer() const {
|
||||||
|
return m_buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t OpenDDLParser::getBufferSize() const {
|
||||||
|
return m_len;
|
||||||
|
}
|
||||||
|
|
||||||
|
void OpenDDLParser::clear() {
|
||||||
|
if( m_ownsBuffer ) {
|
||||||
|
delete [] m_buffer;
|
||||||
|
}
|
||||||
|
m_buffer = nullptr;
|
||||||
|
m_len = 0;
|
||||||
|
|
||||||
|
if( m_context ) {
|
||||||
|
m_context->m_root = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
DDLNode::releaseNodes();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool OpenDDLParser::parse() {
|
||||||
|
if( 0 == m_len ) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
normalizeBuffer( m_buffer, m_len );
|
||||||
|
|
||||||
|
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_len - 1 ] + 1 );
|
||||||
|
while( current != end ) {
|
||||||
|
current = parseNextNode( current, end );
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
char *OpenDDLParser::parseNextNode( char *in, char *end ) {
|
||||||
|
in = parseHeader( in, end );
|
||||||
|
in = parseStructure( in, end );
|
||||||
|
|
||||||
|
return in;
|
||||||
|
}
|
||||||
|
|
||||||
|
char *OpenDDLParser::parseHeader( char *in, char *end ) {
|
||||||
|
if( nullptr == in || in == end ) {
|
||||||
|
return in;
|
||||||
|
}
|
||||||
|
|
||||||
|
Identifier *id( nullptr );
|
||||||
|
in = OpenDDLParser::parseIdentifier( in, end, &id );
|
||||||
|
|
||||||
|
#ifdef DEBUG_HEADER_NAME
|
||||||
|
if( id ) {
|
||||||
|
std::cout << id->m_buffer << std::endl;
|
||||||
|
}
|
||||||
|
#endif // DEBUG_HEADER_NAME
|
||||||
|
|
||||||
|
in = getNextToken( in, end );
|
||||||
|
Property *first( nullptr );
|
||||||
|
if( nullptr != id ) {
|
||||||
|
if( *in == '(' ) {
|
||||||
|
in++;
|
||||||
|
Property *prop( nullptr ), *prev( nullptr );
|
||||||
|
while( *in != ')' && in != end ) {
|
||||||
|
in = parseProperty( in, end, &prop );
|
||||||
|
in = getNextToken( in, end );
|
||||||
|
|
||||||
|
if( *in != ',' && *in != ')' ) {
|
||||||
|
logInvalidTokenError( in, ")", m_logCallback );
|
||||||
|
return in;
|
||||||
|
}
|
||||||
|
if( nullptr != prop && *in != ',' ) {
|
||||||
|
if( nullptr == first ) {
|
||||||
|
first = prop;
|
||||||
|
}
|
||||||
|
if( nullptr != prev ) {
|
||||||
|
prev->m_next = prop;
|
||||||
|
}
|
||||||
|
prev = prop;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
in++;
|
||||||
|
}
|
||||||
|
|
||||||
|
// store the node
|
||||||
|
DDLNode *node( createDDLNode( id, first, this ) );
|
||||||
|
if( nullptr != node ) {
|
||||||
|
pushNode( node );
|
||||||
|
} else {
|
||||||
|
std::cerr << "nullptr returned by creating DDLNode." << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
Name *name( nullptr );
|
||||||
|
in = OpenDDLParser::parseName( in, end, &name );
|
||||||
|
if( nullptr != name ) {
|
||||||
|
const std::string nodeName( name->m_id->m_buffer );
|
||||||
|
node->setName( nodeName );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return in;
|
||||||
|
}
|
||||||
|
|
||||||
|
char *OpenDDLParser::parseStructure( char *in, char *end ) {
|
||||||
|
if( nullptr == in || in == end ) {
|
||||||
|
return in;
|
||||||
|
}
|
||||||
|
|
||||||
|
in = getNextToken( in, end );
|
||||||
|
if( *in == '{' ) {
|
||||||
|
in++;
|
||||||
|
in = getNextToken( in, end );
|
||||||
|
Value::ValueType type( Value::ddl_none );
|
||||||
|
size_t arrayLen( 0 );
|
||||||
|
in = OpenDDLParser::parsePrimitiveDataType( in, end, type, arrayLen );
|
||||||
|
if( Value::ddl_none != type ) {
|
||||||
|
in = getNextToken( in, end );
|
||||||
|
if( *in == '{' ) {
|
||||||
|
DataArrayList *dtArrayList( nullptr );
|
||||||
|
Value *values( nullptr );
|
||||||
|
if( 1 == arrayLen ) {
|
||||||
|
in = parseDataList( in, end, &values );
|
||||||
|
if( nullptr != values ){
|
||||||
|
DDLNode *currentNode( top() );
|
||||||
|
if( nullptr != currentNode ) {
|
||||||
|
currentNode->setValue( values );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if( arrayLen > 1 ) {
|
||||||
|
in = parseDataArrayList( in, end, &dtArrayList );
|
||||||
|
if( nullptr != dtArrayList ) {
|
||||||
|
DDLNode *currentNode( top() );
|
||||||
|
if( nullptr != currentNode ) {
|
||||||
|
currentNode->setDataArrayList( dtArrayList );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
std::cerr << "0 for array is invalid." << std::endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
in = getNextToken( in, end );
|
||||||
|
if( *in != '}' ) {
|
||||||
|
logInvalidTokenError( in, "}", m_logCallback );
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
in = parseHeader( in, end );
|
||||||
|
in = parseStructure( in, end );
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
in++;
|
||||||
|
logInvalidTokenError( in, "{", m_logCallback );
|
||||||
|
return in;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
in++;
|
||||||
|
|
||||||
|
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( char *buffer, size_t len ) {
|
||||||
|
if( nullptr == buffer || 0 == len ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t writeIdx( 0 );
|
||||||
|
char *end( &buffer[ len ] + 1 );
|
||||||
|
for( size_t readIdx = 0; readIdx<len; ++readIdx ) {
|
||||||
|
char *c( &buffer[readIdx] );
|
||||||
|
// check for a comment
|
||||||
|
if( !isComment<char>( c, end ) ) {
|
||||||
|
buffer[ writeIdx ] = buffer[ readIdx ];
|
||||||
|
writeIdx++;
|
||||||
|
} else {
|
||||||
|
readIdx++;
|
||||||
|
// skip the comment and the rest of the line
|
||||||
|
while( !isEndofLine( buffer[ readIdx ] ) ) {
|
||||||
|
readIdx++;
|
||||||
|
}
|
||||||
|
buffer[writeIdx] = '\n';
|
||||||
|
writeIdx++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if( writeIdx < len ) {
|
||||||
|
buffer[ writeIdx ] = '\0';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
char *OpenDDLParser::parseName( char *in, char *end, Name **name ) {
|
||||||
|
*name = nullptr;
|
||||||
|
if( nullptr == in || in == end ) {
|
||||||
|
return in;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ignore blanks
|
||||||
|
in = getNextToken( in, end );
|
||||||
|
if( *in != '$' && *in != '%' ) {
|
||||||
|
return in;
|
||||||
|
}
|
||||||
|
|
||||||
|
NameType ntype( GlobalName );
|
||||||
|
if( *in == '%' ) {
|
||||||
|
ntype = LocalName;
|
||||||
|
}
|
||||||
|
|
||||||
|
Name *currentName( nullptr );
|
||||||
|
Identifier *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, Identifier **id ) {
|
||||||
|
*id = nullptr;
|
||||||
|
if( nullptr == in || in == end ) {
|
||||||
|
return in;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ignore blanks
|
||||||
|
in = getNextToken( in, end );
|
||||||
|
|
||||||
|
// 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( !isSeparator( *in ) && ( in != end ) && *in != '(' && *in != ')' ) {
|
||||||
|
in++;
|
||||||
|
idLen++;
|
||||||
|
}
|
||||||
|
|
||||||
|
const size_t len( idLen + 1 );
|
||||||
|
Identifier *newId = new Identifier( len, new char[ len ] );
|
||||||
|
::strncpy( newId->m_buffer, start, newId->m_len-1 );
|
||||||
|
newId->m_buffer[ newId->m_len - 1 ] = '\0';
|
||||||
|
*id = newId;
|
||||||
|
|
||||||
|
return in;
|
||||||
|
}
|
||||||
|
|
||||||
|
char *OpenDDLParser::parsePrimitiveDataType( char *in, char *end, Value::ValueType &type, size_t &len ) {
|
||||||
|
type = Value::ddl_none;
|
||||||
|
len = 0;
|
||||||
|
if( nullptr == in || in == end ) {
|
||||||
|
return in;
|
||||||
|
}
|
||||||
|
|
||||||
|
for( unsigned int i = 0; i < Value::ddl_types_max; i++ ) {
|
||||||
|
const size_t prim_len( strlen( PrimitiveTypeToken[ i ] ) );
|
||||||
|
if( 0 == strncmp( in, PrimitiveTypeToken[ i ], prim_len ) ) {
|
||||||
|
type = ( Value::ValueType ) i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if( Value::ddl_none == type ) {
|
||||||
|
in = getNextToken( in, end );
|
||||||
|
return in;
|
||||||
|
} else {
|
||||||
|
in += strlen( PrimitiveTypeToken[ type ] );
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ok( true );
|
||||||
|
if( *in == '[' ) {
|
||||||
|
ok = false;
|
||||||
|
in++;
|
||||||
|
char *start( in );
|
||||||
|
while ( in != end ) {
|
||||||
|
in++;
|
||||||
|
if( *in == ']' ) {
|
||||||
|
len = atoi( start );
|
||||||
|
ok = true;
|
||||||
|
in++;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
len = 1;
|
||||||
|
}
|
||||||
|
if( !ok ) {
|
||||||
|
type = Value::ddl_none;
|
||||||
|
}
|
||||||
|
|
||||||
|
return in;
|
||||||
|
}
|
||||||
|
|
||||||
|
char *OpenDDLParser::parseReference( char *in, char *end, std::vector<Name*> &names ) {
|
||||||
|
if( nullptr == in || in == end ) {
|
||||||
|
return in;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( 0 != strncmp( in, RefToken, strlen( RefToken ) ) ) {
|
||||||
|
return false;
|
||||||
|
} else {
|
||||||
|
const size_t refTokenLen( strlen( RefToken ) );
|
||||||
|
in += refTokenLen;
|
||||||
|
}
|
||||||
|
|
||||||
|
in = getNextToken( in, end );
|
||||||
|
if( '{' != *in ) {
|
||||||
|
return in;
|
||||||
|
} else {
|
||||||
|
in++;
|
||||||
|
}
|
||||||
|
|
||||||
|
in = getNextToken( in, end );
|
||||||
|
Name *nextName( nullptr );
|
||||||
|
in = parseName( in, end, &nextName );
|
||||||
|
if( nextName ) {
|
||||||
|
names.push_back( nextName );
|
||||||
|
}
|
||||||
|
while( '}' != *in ) {
|
||||||
|
in = getNextSeparator( in, end );
|
||||||
|
if( ',' == *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 = getNextToken( in, end );
|
||||||
|
char *start( in );
|
||||||
|
size_t len( 0 );
|
||||||
|
while( !isSeparator( *in ) && in != end ) {
|
||||||
|
in++;
|
||||||
|
len++;
|
||||||
|
}
|
||||||
|
len++;
|
||||||
|
int res = ::strncmp( BoolTrue, start, strlen( BoolTrue ) );
|
||||||
|
if( 0 != res ) {
|
||||||
|
res = ::strncmp( BoolFalse, start, strlen( BoolFalse ) );
|
||||||
|
if( 0 != res ) {
|
||||||
|
*boolean = nullptr;
|
||||||
|
return in;
|
||||||
|
}
|
||||||
|
*boolean = ValueAllocator::allocPrimData( Value::ddl_bool );
|
||||||
|
(*boolean)->setBool( false );
|
||||||
|
} else {
|
||||||
|
*boolean = ValueAllocator::allocPrimData( Value::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 ) ) {
|
||||||
|
return in;
|
||||||
|
}
|
||||||
|
|
||||||
|
in = getNextToken( in, end );
|
||||||
|
char *start( in );
|
||||||
|
while( !isSeparator( *in ) && in != end ) {
|
||||||
|
in++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( isNumeric( *start ) ) {
|
||||||
|
const int value( atoi( start ) );
|
||||||
|
*integer = ValueAllocator::allocPrimData( integerType );
|
||||||
|
switch( integerType ) {
|
||||||
|
case Value::ddl_int8:
|
||||||
|
( *integer )->setInt8( (int8) value );
|
||||||
|
break;
|
||||||
|
case Value::ddl_int16:
|
||||||
|
( *integer )->setInt16( ( int16 ) value );
|
||||||
|
break;
|
||||||
|
case Value::ddl_int32:
|
||||||
|
( *integer )->setInt32( ( int32 ) value );
|
||||||
|
break;
|
||||||
|
case Value::ddl_int64:
|
||||||
|
( *integer )->setInt64( ( int64 ) value );
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return in;
|
||||||
|
}
|
||||||
|
|
||||||
|
char *OpenDDLParser::parseFloatingLiteral( char *in, char *end, Value **floating ) {
|
||||||
|
*floating = nullptr;
|
||||||
|
if( nullptr == in || in == end ) {
|
||||||
|
return in;
|
||||||
|
}
|
||||||
|
|
||||||
|
in = getNextToken( in, end );
|
||||||
|
char *start( in );
|
||||||
|
while( !isSeparator( *in ) && in != end ) {
|
||||||
|
in++;
|
||||||
|
}
|
||||||
|
|
||||||
|
// parse the float value
|
||||||
|
bool ok( false );
|
||||||
|
if( isNumeric( *start ) ) {
|
||||||
|
ok = true;
|
||||||
|
} else {
|
||||||
|
if( *start == '-' ) {
|
||||||
|
if( isNumeric( *(start+1) ) ) {
|
||||||
|
ok = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if( ok ) {
|
||||||
|
const float value( ( float ) atof( start ) );
|
||||||
|
*floating = ValueAllocator::allocPrimData( Value::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 = getNextToken( in, end );
|
||||||
|
size_t len( 0 );
|
||||||
|
char *start( in );
|
||||||
|
if( *start == '\"' ) {
|
||||||
|
start++;
|
||||||
|
in++;
|
||||||
|
while( *in != '\"' && in != end ) {
|
||||||
|
in++;
|
||||||
|
len++;
|
||||||
|
}
|
||||||
|
|
||||||
|
*stringData = ValueAllocator::allocPrimData( Value::ddl_string, len + 1 );
|
||||||
|
::strncpy( ( char* ) ( *stringData )->m_data, start, len );
|
||||||
|
( *stringData )->m_data[len] = '\0';
|
||||||
|
in++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return in;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void createPropertyWithData( Identifier *id, Value *primData, Property **prop ) {
|
||||||
|
if( nullptr != primData ) {
|
||||||
|
( *prop ) = new Property( id );
|
||||||
|
( *prop )->m_primData = primData;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
char *OpenDDLParser::parseHexaLiteral( char *in, char *end, Value **data ) {
|
||||||
|
*data = nullptr;
|
||||||
|
if( nullptr == in || in == end ) {
|
||||||
|
return in;
|
||||||
|
}
|
||||||
|
|
||||||
|
in = getNextToken( 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 ) {
|
||||||
|
pos--;
|
||||||
|
value += hex2Decimal( *start ) * static_cast<int>( pow( 16.0, pos ) );
|
||||||
|
start++;
|
||||||
|
}
|
||||||
|
|
||||||
|
*data = ValueAllocator::allocPrimData( Value::ddl_int32 );
|
||||||
|
(*data)->setInt32( value );
|
||||||
|
|
||||||
|
return in;
|
||||||
|
}
|
||||||
|
|
||||||
|
char *OpenDDLParser::parseProperty( char *in, char *end, Property **prop ) {
|
||||||
|
*prop = nullptr;
|
||||||
|
if( nullptr == in || in == end ) {
|
||||||
|
return in;
|
||||||
|
}
|
||||||
|
|
||||||
|
in = getNextToken( in, end );
|
||||||
|
Identifier *id( nullptr );
|
||||||
|
in = parseIdentifier( in, end, &id );
|
||||||
|
if( nullptr != id ) {
|
||||||
|
in = getNextToken( in, end );
|
||||||
|
if( *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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return in;
|
||||||
|
}
|
||||||
|
|
||||||
|
char *OpenDDLParser::parseDataList( char *in, char *end, Value **data ) {
|
||||||
|
*data = nullptr;
|
||||||
|
if( nullptr == in || in == end ) {
|
||||||
|
return in;
|
||||||
|
}
|
||||||
|
|
||||||
|
in = getNextToken( in, end );
|
||||||
|
if( *in == '{' ) {
|
||||||
|
in++;
|
||||||
|
Value *current( nullptr ), *prev( nullptr );
|
||||||
|
while( '}' != *in ) {
|
||||||
|
current = nullptr;
|
||||||
|
in = getNextToken( in, end );
|
||||||
|
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 );
|
||||||
|
}
|
||||||
|
|
||||||
|
if( nullptr != current ) {
|
||||||
|
if( nullptr == *data ) {
|
||||||
|
*data = current;
|
||||||
|
prev = current;
|
||||||
|
} else {
|
||||||
|
prev->setNext( current );
|
||||||
|
prev = current;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
in = getNextSeparator( in, end );
|
||||||
|
if( ',' != *in && '}' != *in && !isSpace( *in ) ) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
in++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return in;
|
||||||
|
}
|
||||||
|
|
||||||
|
char *OpenDDLParser::parseDataArrayList( char *in, char *end, DataArrayList **dataList ) {
|
||||||
|
*dataList = nullptr;
|
||||||
|
if( nullptr == in || in == end ) {
|
||||||
|
return in;
|
||||||
|
}
|
||||||
|
|
||||||
|
in = getNextToken( in, end );
|
||||||
|
if( *in == '{' ) {
|
||||||
|
in++;
|
||||||
|
Value *current( nullptr );
|
||||||
|
DataArrayList *prev( nullptr ), *currentDataList( nullptr );
|
||||||
|
do {
|
||||||
|
in = parseDataList( in, end, ¤t );
|
||||||
|
if( nullptr != current ) {
|
||||||
|
if( nullptr == prev ) {
|
||||||
|
*dataList = new DataArrayList;
|
||||||
|
(*dataList)->m_dataList = current;
|
||||||
|
prev = *dataList;
|
||||||
|
} else {
|
||||||
|
currentDataList = new DataArrayList;
|
||||||
|
if( nullptr != prev ) {
|
||||||
|
prev->m_next = currentDataList;
|
||||||
|
prev = currentDataList;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} while( ',' == *in && in != end );
|
||||||
|
}
|
||||||
|
|
||||||
|
return in;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *OpenDDLParser::getVersion() {
|
||||||
|
return Version;
|
||||||
|
}
|
||||||
|
|
||||||
|
END_ODDLPARSER_NS
|
|
@ -0,0 +1,243 @@
|
||||||
|
/*-----------------------------------------------------------------------------------------------
|
||||||
|
The MIT License (MIT)
|
||||||
|
|
||||||
|
Copyright (c) 2014 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/Value.h>
|
||||||
|
#include <iostream>
|
||||||
|
#include <cassert>
|
||||||
|
|
||||||
|
BEGIN_ODDLPARSER_NS
|
||||||
|
|
||||||
|
Value::Value()
|
||||||
|
: m_type( ddl_none )
|
||||||
|
, m_size( 0 )
|
||||||
|
, m_data( nullptr )
|
||||||
|
, m_next( nullptr ) {
|
||||||
|
// empty
|
||||||
|
}
|
||||||
|
|
||||||
|
Value::~Value() {
|
||||||
|
// empty
|
||||||
|
}
|
||||||
|
|
||||||
|
void Value::setBool( bool value ) {
|
||||||
|
assert( ddl_bool == m_type );
|
||||||
|
::memcpy( m_data, &value, m_size );
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Value::getBool() {
|
||||||
|
assert( ddl_bool == m_type );
|
||||||
|
return ( bool ) ( *m_data );
|
||||||
|
}
|
||||||
|
|
||||||
|
void Value::setInt8( int8 value ) {
|
||||||
|
assert( ddl_int8 == m_type );
|
||||||
|
::memcpy( m_data, &value, m_size );
|
||||||
|
}
|
||||||
|
|
||||||
|
int8 Value::getInt8() {
|
||||||
|
assert( ddl_int8 == m_type );
|
||||||
|
return ( int8 ) ( *m_data );
|
||||||
|
}
|
||||||
|
|
||||||
|
void Value::setInt16( int16 value ) {
|
||||||
|
assert( ddl_int16 == m_type );
|
||||||
|
::memcpy( m_data, &value, m_size );
|
||||||
|
}
|
||||||
|
|
||||||
|
int16 Value::getInt16() {
|
||||||
|
assert( ddl_int16 == m_type );
|
||||||
|
return ( int16 ) ( *m_data );
|
||||||
|
}
|
||||||
|
|
||||||
|
void Value::setInt32( int32 value ) {
|
||||||
|
assert( ddl_int32 == m_type );
|
||||||
|
::memcpy( m_data, &value, m_size );
|
||||||
|
}
|
||||||
|
|
||||||
|
int32 Value::getInt32() {
|
||||||
|
assert( ddl_int32 == m_type );
|
||||||
|
return ( int32 ) ( *m_data );
|
||||||
|
}
|
||||||
|
|
||||||
|
void Value::setInt64( int64 value ) {
|
||||||
|
assert( ddl_int32 == m_type );
|
||||||
|
::memcpy( m_data, &value, m_size );
|
||||||
|
}
|
||||||
|
|
||||||
|
int64 Value::getInt64() {
|
||||||
|
return ( int64 ) ( *m_data );
|
||||||
|
}
|
||||||
|
|
||||||
|
void Value::setFloat( float value ) {
|
||||||
|
assert( ddl_float == m_type );
|
||||||
|
::memcpy( m_data, &value, m_size );
|
||||||
|
}
|
||||||
|
|
||||||
|
float Value::getFloat() const {
|
||||||
|
float v;
|
||||||
|
::memcpy( &v, m_data, m_size );
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Value::setDouble( double value ) {
|
||||||
|
assert( ddl_double == m_type );
|
||||||
|
::memcpy( m_data, &value, m_size );
|
||||||
|
}
|
||||||
|
|
||||||
|
double Value::getDouble() const {
|
||||||
|
double v;
|
||||||
|
::memcpy( &v, m_data, m_size );
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Value::dump() {
|
||||||
|
switch( m_type ) {
|
||||||
|
case ddl_none:
|
||||||
|
std::cout << "None" << std::endl;
|
||||||
|
break;
|
||||||
|
case ddl_bool:
|
||||||
|
std::cout << getBool() << std::endl;
|
||||||
|
break;
|
||||||
|
case ddl_int8:
|
||||||
|
std::cout << getInt8() << std::endl;
|
||||||
|
break;
|
||||||
|
case ddl_int16:
|
||||||
|
std::cout << getInt16() << std::endl;
|
||||||
|
break;
|
||||||
|
case ddl_int32:
|
||||||
|
std::cout << getInt32() << std::endl;
|
||||||
|
break;
|
||||||
|
case ddl_int64:
|
||||||
|
std::cout << getInt64() << std::endl;
|
||||||
|
break;
|
||||||
|
case ddl_unsigned_int8:
|
||||||
|
std::cout << "Not supported" << std::endl;
|
||||||
|
break;
|
||||||
|
case ddl_unsigned_int16:
|
||||||
|
std::cout << "Not supported" << std::endl;
|
||||||
|
break;
|
||||||
|
case ddl_unsigned_int32:
|
||||||
|
std::cout << "Not supported" << std::endl;
|
||||||
|
break;
|
||||||
|
case ddl_unsigned_int64:
|
||||||
|
std::cout << "Not supported" << std::endl;
|
||||||
|
break;
|
||||||
|
case ddl_half:
|
||||||
|
std::cout << "Not supported" << std::endl;
|
||||||
|
break;
|
||||||
|
case ddl_float:
|
||||||
|
std::cout << getFloat() << std::endl;
|
||||||
|
break;
|
||||||
|
case ddl_double:
|
||||||
|
std::cout << getDouble() << std::endl;
|
||||||
|
break;
|
||||||
|
case ddl_string:
|
||||||
|
std::cout << "Not supported" << std::endl;
|
||||||
|
break;
|
||||||
|
case ddl_ref:
|
||||||
|
std::cout << "Not supported" << std::endl;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Value::setNext( Value *next ) {
|
||||||
|
m_next = next;
|
||||||
|
}
|
||||||
|
|
||||||
|
Value *Value::getNext() const {
|
||||||
|
return m_next;
|
||||||
|
}
|
||||||
|
|
||||||
|
Value *ValueAllocator::allocPrimData( Value::ValueType type, size_t len ) {
|
||||||
|
if( type == Value::ddl_none || Value::ddl_types_max == type ) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
Value *data = new Value;
|
||||||
|
data->m_type = type;
|
||||||
|
switch( type ) {
|
||||||
|
case Value::ddl_bool:
|
||||||
|
data->m_size = sizeof( bool );
|
||||||
|
break;
|
||||||
|
case Value::ddl_int8:
|
||||||
|
data->m_size = sizeof( char );
|
||||||
|
break;
|
||||||
|
case Value::ddl_int16:
|
||||||
|
data->m_size = sizeof( short );
|
||||||
|
break;
|
||||||
|
case Value::ddl_int32:
|
||||||
|
data->m_size = sizeof( int );
|
||||||
|
break;
|
||||||
|
case Value::ddl_int64:
|
||||||
|
data->m_size = sizeof( long );
|
||||||
|
break;
|
||||||
|
case Value::ddl_unsigned_int8:
|
||||||
|
data->m_size = sizeof( unsigned char );
|
||||||
|
break;
|
||||||
|
case Value::ddl_unsigned_int32:
|
||||||
|
data->m_size = sizeof( unsigned int );
|
||||||
|
break;
|
||||||
|
case Value::ddl_unsigned_int64:
|
||||||
|
data->m_size = sizeof( unsigned long );
|
||||||
|
break;
|
||||||
|
case Value::ddl_half:
|
||||||
|
data->m_size = sizeof( short );
|
||||||
|
break;
|
||||||
|
case Value::ddl_float:
|
||||||
|
data->m_size = sizeof( float );
|
||||||
|
break;
|
||||||
|
case Value::ddl_double:
|
||||||
|
data->m_size = sizeof( double );
|
||||||
|
break;
|
||||||
|
case Value::ddl_string:
|
||||||
|
data->m_size = sizeof( char );
|
||||||
|
break;
|
||||||
|
case Value::ddl_ref:
|
||||||
|
data->m_size = sizeof( char );
|
||||||
|
break;
|
||||||
|
case Value::ddl_none:
|
||||||
|
case Value::ddl_types_max:
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( data->m_size ) {
|
||||||
|
data->m_size *= len;
|
||||||
|
data->m_data = new unsigned char[ data->m_size ];
|
||||||
|
}
|
||||||
|
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ValueAllocator::releasePrimData( Value **data ) {
|
||||||
|
if( !data ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
delete *data;
|
||||||
|
*data = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
END_ODDLPARSER_NS
|
|
@ -0,0 +1,87 @@
|
||||||
|
/*-----------------------------------------------------------------------------------------------
|
||||||
|
The MIT License (MIT)
|
||||||
|
|
||||||
|
Copyright (c) 2014 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.
|
||||||
|
-----------------------------------------------------------------------------------------------*/
|
||||||
|
#pragma once
|
||||||
|
#ifndef OPENDDLPARSER_DDLNODE_H_INC
|
||||||
|
#define OPENDDLPARSER_DDLNODE_H_INC
|
||||||
|
|
||||||
|
#include <openddlparser/OpenDDLCommon.h>
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
BEGIN_ODDLPARSER_NS
|
||||||
|
|
||||||
|
class Value;
|
||||||
|
class OpenDDLParser;
|
||||||
|
|
||||||
|
struct Identifier;
|
||||||
|
struct Reference;
|
||||||
|
struct Property;
|
||||||
|
struct DataArrayList;
|
||||||
|
|
||||||
|
class DLL_ODDLPARSER_EXPORT DDLNode {
|
||||||
|
public:
|
||||||
|
friend class OpenDDLParser;
|
||||||
|
|
||||||
|
typedef std::vector<DDLNode*> DllNodeList;
|
||||||
|
|
||||||
|
public:
|
||||||
|
~DDLNode();
|
||||||
|
void attachParent( DDLNode *parent );
|
||||||
|
void detachParent();
|
||||||
|
DDLNode *getParent() const;
|
||||||
|
const DllNodeList &getChildNodeList() const;
|
||||||
|
void setType( const std::string &name );
|
||||||
|
const std::string &getType() const;
|
||||||
|
void setName( const std::string &name );
|
||||||
|
const std::string &getName() const;
|
||||||
|
void setProperties( Property *first );
|
||||||
|
Property *getProperties() const;
|
||||||
|
void setValue( Value *val );
|
||||||
|
Value *getValue() const;
|
||||||
|
void setDataArrayList( DataArrayList *dtArrayList );
|
||||||
|
DataArrayList *getDataArrayList() const;
|
||||||
|
static DDLNode *create( const std::string &type, const std::string &name, DDLNode *parent = nullptr );
|
||||||
|
|
||||||
|
private:
|
||||||
|
DDLNode( const std::string &type, const std::string &name, size_t idx, DDLNode *parent = nullptr );
|
||||||
|
DDLNode();
|
||||||
|
DDLNode( const DDLNode & );
|
||||||
|
DDLNode &operator = ( const DDLNode & );
|
||||||
|
static void releaseNodes();
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::string m_type;
|
||||||
|
std::string m_name;
|
||||||
|
DDLNode *m_parent;
|
||||||
|
std::vector<DDLNode*> m_children;
|
||||||
|
Property *m_properties;
|
||||||
|
Value *m_value;
|
||||||
|
DataArrayList *m_dtArrayList;
|
||||||
|
size_t m_idx;
|
||||||
|
static DllNodeList s_allocatedNodes;
|
||||||
|
};
|
||||||
|
|
||||||
|
END_ODDLPARSER_NS
|
||||||
|
|
||||||
|
#endif // OPENDDLPARSER_DDLNODE_H_INC
|
|
@ -0,0 +1,148 @@
|
||||||
|
/*-----------------------------------------------------------------------------------------------
|
||||||
|
The MIT License (MIT)
|
||||||
|
|
||||||
|
Copyright (c) 2014 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.
|
||||||
|
-----------------------------------------------------------------------------------------------*/
|
||||||
|
#pragma once
|
||||||
|
#ifndef OPENDDLPARSER_OPENDDLPARSERCOMMON_H_INC
|
||||||
|
#define OPENDDLPARSER_OPENDDLPARSERCOMMON_H_INC
|
||||||
|
|
||||||
|
#include <cstddef>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
# define TAG_DLL_EXPORT __declspec(dllexport)
|
||||||
|
# define TAG_DLL_IMPORT __declspec(dllimport )
|
||||||
|
# ifdef OPENDDLPARSER_BUILD
|
||||||
|
# define DLL_ODDLPARSER_EXPORT TAG_DLL_EXPORT
|
||||||
|
# else
|
||||||
|
# define DLL_ODDLPARSER_EXPORT TAG_DLL_IMPORT
|
||||||
|
# endif // OPENDDLPARSER_BUILD
|
||||||
|
# pragma warning( disable : 4251 )
|
||||||
|
#else
|
||||||
|
# define DLL_ODDLPARSER_EXPORT
|
||||||
|
#endif // _WIN32
|
||||||
|
|
||||||
|
#define BEGIN_ODDLPARSER_NS namespace ODDLParser {
|
||||||
|
#define END_ODDLPARSER_NS }
|
||||||
|
#define USE_ODDLPARSER_NS using namespace ODDLParser;
|
||||||
|
|
||||||
|
BEGIN_ODDLPARSER_NS
|
||||||
|
|
||||||
|
class DDLNode;
|
||||||
|
class Value;
|
||||||
|
|
||||||
|
struct Name;
|
||||||
|
struct Identifier;
|
||||||
|
struct Reference;
|
||||||
|
struct Property;
|
||||||
|
struct DataArrayList;
|
||||||
|
|
||||||
|
typedef char int8;
|
||||||
|
typedef short int16;
|
||||||
|
typedef int int32;
|
||||||
|
typedef long int64;
|
||||||
|
|
||||||
|
enum NameType {
|
||||||
|
GlobalName,
|
||||||
|
LocalName
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Name {
|
||||||
|
NameType m_type;
|
||||||
|
Identifier *m_id;
|
||||||
|
|
||||||
|
Name( NameType type, Identifier *id )
|
||||||
|
: m_type( type )
|
||||||
|
, m_id( id ) {
|
||||||
|
// empty
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Reference {
|
||||||
|
size_t m_numRefs;
|
||||||
|
Name **m_referencedName;
|
||||||
|
|
||||||
|
Reference( size_t numrefs, Name **names )
|
||||||
|
: m_numRefs( numrefs )
|
||||||
|
, m_referencedName( names ) {
|
||||||
|
// empty
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Identifier {
|
||||||
|
size_t m_len;
|
||||||
|
char *m_buffer;
|
||||||
|
|
||||||
|
Identifier( size_t len, char *buffer )
|
||||||
|
: m_len( len )
|
||||||
|
, m_buffer( buffer ) {
|
||||||
|
// empty
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Property {
|
||||||
|
Identifier *m_id;
|
||||||
|
Value *m_primData;
|
||||||
|
Reference *m_ref;
|
||||||
|
Property *m_next;
|
||||||
|
|
||||||
|
Property( Identifier *id )
|
||||||
|
: m_id( id )
|
||||||
|
, m_primData( nullptr )
|
||||||
|
, m_ref( nullptr )
|
||||||
|
, m_next( nullptr ) {
|
||||||
|
// empty
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct DataArrayList {
|
||||||
|
size_t m_numItems;
|
||||||
|
Value *m_dataList;
|
||||||
|
DataArrayList *m_next;
|
||||||
|
|
||||||
|
DataArrayList()
|
||||||
|
: m_numItems( 0 )
|
||||||
|
, m_dataList( nullptr )
|
||||||
|
, m_next( nullptr ) {
|
||||||
|
// empty
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Context {
|
||||||
|
Property *m_properties;
|
||||||
|
DDLNode *m_root;
|
||||||
|
|
||||||
|
Context()
|
||||||
|
: m_properties( nullptr )
|
||||||
|
, m_root( nullptr ) {
|
||||||
|
// empty
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
END_ODDLPARSER_NS
|
||||||
|
|
||||||
|
#define ODDL_NO_COPYING( classname ) \
|
||||||
|
private: \
|
||||||
|
classname( const classname & ); \
|
||||||
|
classname &operator = ( const classname & );
|
||||||
|
|
||||||
|
#endif // OPENDDLPARSER_OPENDDLPARSERCOMMON_H_INC
|
||||||
|
|
|
@ -0,0 +1,233 @@
|
||||||
|
/*-----------------------------------------------------------------------------------------------
|
||||||
|
The MIT License (MIT)
|
||||||
|
|
||||||
|
Copyright (c) 2014 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.
|
||||||
|
-----------------------------------------------------------------------------------------------*/
|
||||||
|
#pragma once
|
||||||
|
#ifndef OPENDDLPARSER_OPENDDLPARSERUTILS_H_INC
|
||||||
|
#define OPENDDLPARSER_OPENDDLPARSERUTILS_H_INC
|
||||||
|
|
||||||
|
#include <openddlparser/OpenDDLCommon.h>
|
||||||
|
|
||||||
|
BEGIN_ODDLPARSER_NS
|
||||||
|
|
||||||
|
template<class T>
|
||||||
|
inline
|
||||||
|
bool isComment( T *in, T *end ) {
|
||||||
|
if( *in == '/' ) {
|
||||||
|
if( in + 1 != end ) {
|
||||||
|
if( *( in + 1 ) == '/' ) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class T>
|
||||||
|
inline
|
||||||
|
bool isUpperCase( T in ) {
|
||||||
|
return ( in >= 'A' && in <= 'Z' );
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class T>
|
||||||
|
inline
|
||||||
|
bool isLowerCase( T in ) {
|
||||||
|
return ( in >= 'a' && in <= 'z' );
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class T>
|
||||||
|
inline
|
||||||
|
bool isSpace( const T in ) {
|
||||||
|
return ( ' ' == in || '\t' == in );
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class T>
|
||||||
|
inline
|
||||||
|
bool isNewLine( const T in ) {
|
||||||
|
return ( '\n' == in );
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class T>
|
||||||
|
inline
|
||||||
|
bool isSeparator( T in ) {
|
||||||
|
if( isSpace( in ) || ',' == in || '{' == in || '}' == in || '[' == in ) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const unsigned char chartype_table[ 256 ] = {
|
||||||
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0-15
|
||||||
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 16-31
|
||||||
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 32-47
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, // 48-63
|
||||||
|
|
||||||
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 64-79
|
||||||
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 80-95
|
||||||
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 96-111
|
||||||
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 112-127
|
||||||
|
|
||||||
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // > 127
|
||||||
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
|
|
||||||
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
|
};
|
||||||
|
|
||||||
|
template<class T>
|
||||||
|
inline
|
||||||
|
bool isNumeric( const T in ) {
|
||||||
|
return ( in >= '0' && in <= '9' );
|
||||||
|
//return ( chartype_table[in] );
|
||||||
|
/*if (in >= '0' && in <= '9' )
|
||||||
|
return true;
|
||||||
|
|
||||||
|
return false;*/
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class T>
|
||||||
|
inline
|
||||||
|
bool isInteger( T *in, T *end ) {
|
||||||
|
if( in != end ) {
|
||||||
|
if( *in == '-' ) {
|
||||||
|
in++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool result( false );
|
||||||
|
while( '}' != *in && ',' != *in && !isSpace( *in ) && in != end ) {
|
||||||
|
result = isNumeric( *in );
|
||||||
|
if( !result ) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
in++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class T>
|
||||||
|
inline
|
||||||
|
bool isFloat( T *in, T *end ) {
|
||||||
|
if( in != end ) {
|
||||||
|
if( *in == '-' ) {
|
||||||
|
in++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// check for <1>.0f
|
||||||
|
bool result( false );
|
||||||
|
while( !isSpace( *in ) && in != end ) {
|
||||||
|
if( *in == '.' ) {
|
||||||
|
result = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
result = isNumeric( *in );
|
||||||
|
if( !result ) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
in++;
|
||||||
|
}
|
||||||
|
|
||||||
|
// check for 1<.>0f
|
||||||
|
if( *in == '.' ) {
|
||||||
|
in++;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// check for 1.<0>f
|
||||||
|
while( !isSpace( *in ) && in != end && *in != ',' ) {
|
||||||
|
result = isNumeric( *in );
|
||||||
|
if( !result ) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
in++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class T>
|
||||||
|
inline
|
||||||
|
bool isCharacter( const T in ) {
|
||||||
|
return ( in >= 'a' && in <= 'z' || in >= 'A' && in <= 'Z' );
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class T>
|
||||||
|
inline
|
||||||
|
bool isStringLiteral( const T in ) {
|
||||||
|
return ( in == '\"' );
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class T>
|
||||||
|
inline
|
||||||
|
bool isHexLiteral( T *in, T *end ) {
|
||||||
|
if( *in == '0' ) {
|
||||||
|
if( in + 1 != end ) {
|
||||||
|
if( *( in + 1 ) == 'x' || *( in + 1 ) == 'X' ) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class T>
|
||||||
|
inline
|
||||||
|
bool isEndofLine( const T in ) {
|
||||||
|
return ( '\n' == in );
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class T>
|
||||||
|
inline
|
||||||
|
static T *getNextSeparator( T *in, T *end ) {
|
||||||
|
while( !isSeparator( *in ) || in == end ) {
|
||||||
|
in++;
|
||||||
|
}
|
||||||
|
return in;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const int ErrorHex2Decimal = 9999;
|
||||||
|
|
||||||
|
inline
|
||||||
|
int hex2Decimal( char in ) {
|
||||||
|
if( isNumeric( in ) ) {
|
||||||
|
return (int) in-48;
|
||||||
|
}
|
||||||
|
char hexCodeLower( 'a' ), hexCodeUpper( 'A' );
|
||||||
|
for( int i = 0; i<16; i++ ) {
|
||||||
|
if( in == hexCodeLower + i || in == hexCodeUpper + i ) {
|
||||||
|
return i+10;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ErrorHex2Decimal;
|
||||||
|
}
|
||||||
|
|
||||||
|
END_ODDLPARSER_NS
|
||||||
|
|
||||||
|
#endif // OPENDDLPARSER_OPENDDLPARSERUTILS_H_INC
|
|
@ -0,0 +1,85 @@
|
||||||
|
/*-----------------------------------------------------------------------------------------------
|
||||||
|
The MIT License (MIT)
|
||||||
|
|
||||||
|
Copyright (c) 2014 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.
|
||||||
|
-----------------------------------------------------------------------------------------------*/
|
||||||
|
#pragma once
|
||||||
|
#ifndef OPENDDLPARSER_VALUE_H_INC
|
||||||
|
#define OPENDDLPARSER_VALUE_H_INC
|
||||||
|
|
||||||
|
#include <openddlparser/OpenDDLCommon.h>
|
||||||
|
|
||||||
|
BEGIN_ODDLPARSER_NS
|
||||||
|
|
||||||
|
class DLL_ODDLPARSER_EXPORT Value {
|
||||||
|
public:
|
||||||
|
enum ValueType {
|
||||||
|
ddl_none = -1,
|
||||||
|
ddl_bool = 0,
|
||||||
|
ddl_int8,
|
||||||
|
ddl_int16,
|
||||||
|
ddl_int32,
|
||||||
|
ddl_int64,
|
||||||
|
ddl_unsigned_int8,
|
||||||
|
ddl_unsigned_int16,
|
||||||
|
ddl_unsigned_int32,
|
||||||
|
ddl_unsigned_int64,
|
||||||
|
ddl_half,
|
||||||
|
ddl_float,
|
||||||
|
ddl_double,
|
||||||
|
ddl_string,
|
||||||
|
ddl_ref,
|
||||||
|
ddl_types_max
|
||||||
|
};
|
||||||
|
|
||||||
|
Value();
|
||||||
|
~Value();
|
||||||
|
void setBool( bool value );
|
||||||
|
bool getBool();
|
||||||
|
void setInt8( int8 value );
|
||||||
|
int8 getInt8();
|
||||||
|
void setInt16( int16 value );
|
||||||
|
int16 getInt16();
|
||||||
|
void setInt32( int32 value );
|
||||||
|
int32 getInt32();
|
||||||
|
void setInt64( int64 value );
|
||||||
|
int64 getInt64();
|
||||||
|
void setFloat( float value );
|
||||||
|
float getFloat() const;
|
||||||
|
void setDouble( double value );
|
||||||
|
double getDouble() const;
|
||||||
|
void dump();
|
||||||
|
void setNext( Value *next );
|
||||||
|
Value *getNext() const;
|
||||||
|
|
||||||
|
ValueType m_type;
|
||||||
|
size_t m_size;
|
||||||
|
unsigned char *m_data;
|
||||||
|
Value *m_next;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct DLL_ODDLPARSER_EXPORT ValueAllocator {
|
||||||
|
static Value *allocPrimData( Value::ValueType type, size_t len = 1 );
|
||||||
|
static void releasePrimData( Value **data );
|
||||||
|
};
|
||||||
|
|
||||||
|
END_ODDLPARSER_NS
|
||||||
|
|
||||||
|
#endif // OPENDDLPARSER_VALUE_H_INC
|
Loading…
Reference in New Issue