2015-10-01 22:38:50 +00:00
|
|
|
/*-----------------------------------------------------------------------------------------------
|
|
|
|
The MIT License (MIT)
|
|
|
|
|
|
|
|
Copyright (c) 2014-2015 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/DDLNode.h>
|
2015-10-31 08:43:34 +00:00
|
|
|
#include <openddlparser/Value.h>
|
|
|
|
#include <openddlparser/OpenDDLParser.h>
|
|
|
|
|
|
|
|
#include <sstream>
|
2015-10-01 22:38:50 +00:00
|
|
|
|
|
|
|
BEGIN_ODDLPARSER_NS
|
|
|
|
|
2016-01-08 15:46:13 +00:00
|
|
|
StreamFormatterBase::StreamFormatterBase() {
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
StreamFormatterBase::~StreamFormatterBase() {
|
|
|
|
|
2015-10-31 08:43:34 +00:00
|
|
|
}
|
2016-01-08 15:46:13 +00:00
|
|
|
|
|
|
|
std::string StreamFormatterBase::format( const std::string &statement ) {
|
|
|
|
std::string tmp( statement );
|
|
|
|
return tmp;
|
|
|
|
}
|
|
|
|
|
|
|
|
IOStreamBase::IOStreamBase( StreamFormatterBase *formatter )
|
|
|
|
: m_formatter( formatter )
|
|
|
|
, m_file( ddl_nullptr ) {
|
|
|
|
if (ddl_nullptr == m_formatter) {
|
|
|
|
m_formatter = new StreamFormatterBase;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-10-31 08:43:34 +00:00
|
|
|
IOStreamBase::~IOStreamBase() {
|
2016-01-08 15:46:13 +00:00
|
|
|
delete m_formatter;
|
|
|
|
m_formatter = ddl_nullptr;
|
2015-10-31 08:43:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
bool IOStreamBase::open( const std::string &name ) {
|
|
|
|
m_file = ::fopen( name.c_str(), "a" );
|
|
|
|
if (m_file == ddl_nullptr) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool IOStreamBase::close() {
|
|
|
|
if (ddl_nullptr == m_file) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
::fclose( m_file );
|
|
|
|
m_file = ddl_nullptr;
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2016-01-08 15:46:13 +00:00
|
|
|
size_t IOStreamBase::write( const std::string &statement ) {
|
2015-10-31 08:43:34 +00:00
|
|
|
if (ddl_nullptr == m_file) {
|
2016-01-08 15:46:13 +00:00
|
|
|
return 0;
|
2015-10-31 08:43:34 +00:00
|
|
|
}
|
2016-01-08 15:46:13 +00:00
|
|
|
std::string formatStatement = m_formatter->format( statement );
|
|
|
|
return ::fwrite( formatStatement.c_str(), sizeof( char ), formatStatement.size(), m_file );
|
2015-10-31 08:43:34 +00:00
|
|
|
}
|
|
|
|
|
2015-10-01 22:38:50 +00:00
|
|
|
struct DDLNodeIterator {
|
|
|
|
const DDLNode::DllNodeList &m_childs;
|
|
|
|
size_t m_idx;
|
2015-10-31 08:43:34 +00:00
|
|
|
|
2015-10-01 22:38:50 +00:00
|
|
|
DDLNodeIterator( const DDLNode::DllNodeList &childs )
|
2015-10-31 08:43:34 +00:00
|
|
|
: m_childs( childs )
|
|
|
|
, m_idx( 0 ) {
|
|
|
|
// empty
|
|
|
|
}
|
2015-10-01 22:38:50 +00:00
|
|
|
|
2015-10-31 08:43:34 +00:00
|
|
|
~DDLNodeIterator() {
|
|
|
|
// empty
|
2015-10-01 22:38:50 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
bool getNext( DDLNode **node ) {
|
|
|
|
if( m_childs.size() > (m_idx+1) ) {
|
|
|
|
m_idx++;
|
|
|
|
*node = m_childs[ m_idx ];
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
2016-01-08 15:46:13 +00:00
|
|
|
|
|
|
|
private:
|
|
|
|
DDLNodeIterator() ddl_no_copy;
|
|
|
|
DDLNodeIterator &operator = ( const DDLNodeIterator & ) ddl_no_copy;
|
2015-10-01 22:38:50 +00:00
|
|
|
};
|
|
|
|
|
2015-10-31 08:43:34 +00:00
|
|
|
static void writeLineEnd( std::string &statement ) {
|
|
|
|
statement += "\n";
|
|
|
|
}
|
2015-10-01 22:38:50 +00:00
|
|
|
|
2015-10-31 08:43:34 +00:00
|
|
|
OpenDDLExport::OpenDDLExport( IOStreamBase *stream )
|
|
|
|
: m_stream( stream ) {
|
|
|
|
if (ddl_nullptr == m_stream) {
|
|
|
|
m_stream = new IOStreamBase();
|
|
|
|
}
|
2015-10-01 22:38:50 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
OpenDDLExport::~OpenDDLExport() {
|
2015-10-31 08:43:34 +00:00
|
|
|
if (ddl_nullptr != m_stream) {
|
|
|
|
m_stream->close();
|
2015-10-01 22:38:50 +00:00
|
|
|
}
|
2015-10-31 08:43:34 +00:00
|
|
|
delete m_stream;
|
2015-10-01 22:38:50 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
bool OpenDDLExport::exportContext( Context *ctx, const std::string &filename ) {
|
|
|
|
if( ddl_nullptr == ctx ) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
DDLNode *root( ctx->m_root );
|
2015-10-31 08:43:34 +00:00
|
|
|
if ( ddl_nullptr == root ) {
|
2015-10-01 22:38:50 +00:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2015-10-31 08:43:34 +00:00
|
|
|
if (!filename.empty()) {
|
|
|
|
if (!m_stream->open( filename )) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
const bool retValue( handleNode( root ) );
|
|
|
|
|
|
|
|
return retValue;
|
2015-10-01 22:38:50 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
bool OpenDDLExport::handleNode( DDLNode *node ) {
|
|
|
|
if( ddl_nullptr == node ) {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
const DDLNode::DllNodeList &childs = node->getChildNodeList();
|
|
|
|
if( childs.empty() ) {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
DDLNode *current( ddl_nullptr );
|
|
|
|
DDLNodeIterator it( childs );
|
2015-10-31 08:43:34 +00:00
|
|
|
std::string statement;
|
2015-10-01 22:38:50 +00:00
|
|
|
bool success( true );
|
|
|
|
while( it.getNext( ¤t ) ) {
|
|
|
|
if( ddl_nullptr != current ) {
|
2015-10-31 08:43:34 +00:00
|
|
|
success |= writeNode( current, statement );
|
2015-10-01 22:38:50 +00:00
|
|
|
if( !handleNode( current ) ) {
|
2015-10-31 08:43:34 +00:00
|
|
|
success = false;
|
2015-10-01 22:38:50 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return success;
|
|
|
|
}
|
|
|
|
|
2015-10-31 08:43:34 +00:00
|
|
|
bool OpenDDLExport::writeToStream( const std::string &statement ) {
|
|
|
|
if (ddl_nullptr == m_stream ) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ( !statement.empty()) {
|
|
|
|
m_stream->write( statement );
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool OpenDDLExport::writeNode( DDLNode *node, std::string &statement ) {
|
2015-10-01 22:38:50 +00:00
|
|
|
bool success( true );
|
2015-10-31 08:43:34 +00:00
|
|
|
writeNodeHeader( node, statement );
|
|
|
|
if (node->hasProperties()) {
|
|
|
|
success |= writeProperties( node, statement );
|
|
|
|
}
|
|
|
|
writeLineEnd( statement );
|
|
|
|
|
|
|
|
statement = "}";
|
|
|
|
DataArrayList *al( node->getDataArrayList() );
|
|
|
|
if ( ddl_nullptr != al ) {
|
|
|
|
writeValueType( al->m_dataList->m_type, al->m_numItems, statement );
|
|
|
|
writeValueArray( al, statement );
|
|
|
|
}
|
|
|
|
Value *v( node->getValue() );
|
|
|
|
if (ddl_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 (ddl_nullptr == node) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
statement += node->getType();
|
|
|
|
const std::string &name( node->getName() );
|
|
|
|
if ( !name.empty() ) {
|
|
|
|
statement += " ";
|
|
|
|
statement += "$";
|
|
|
|
statement += name;
|
2015-10-01 22:38:50 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2015-10-31 08:43:34 +00:00
|
|
|
bool OpenDDLExport::writeProperties( DDLNode *node, std::string &statement ) {
|
|
|
|
if ( ddl_nullptr == node ) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2015-10-01 22:38:50 +00:00
|
|
|
Property *prop( node->getProperties() );
|
2015-10-31 08:43:34 +00:00
|
|
|
// if no properties are there, return
|
|
|
|
if ( ddl_nullptr == prop ) {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ( ddl_nullptr != prop ) {
|
|
|
|
// for instance (attrib = "position", bla=2)
|
|
|
|
statement += "(";
|
|
|
|
bool first( true );
|
|
|
|
while ( ddl_nullptr != prop ) {
|
|
|
|
if (!first) {
|
|
|
|
statement += ", ";
|
|
|
|
} else {
|
|
|
|
first = false;
|
|
|
|
}
|
|
|
|
statement += std::string( prop->m_key->m_text.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::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", numItems );
|
|
|
|
statement += buffer;
|
|
|
|
statement += "]";
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool OpenDDLExport::writeValue( Value *val, std::string &statement ) {
|
|
|
|
if (ddl_nullptr == val) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
switch ( val->m_type ) {
|
|
|
|
case Value::ddl_bool:
|
|
|
|
if ( true == val->getBool() ) {
|
|
|
|
statement += "true";
|
|
|
|
} else {
|
|
|
|
statement += "false";
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case Value::ddl_int8:
|
|
|
|
{
|
|
|
|
std::stringstream stream;
|
|
|
|
const int i = static_cast<int>( val->getInt8() );
|
|
|
|
stream << i;
|
|
|
|
statement += stream.str();
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case Value::ddl_int16:
|
|
|
|
{
|
|
|
|
std::stringstream stream;
|
|
|
|
char buffer[ 256 ];
|
|
|
|
::memset( buffer, '\0', 256 * sizeof( char ) );
|
|
|
|
sprintf( buffer, "%d", val->getInt16() );
|
|
|
|
statement += buffer;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case Value::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::ddl_int64:
|
|
|
|
{
|
|
|
|
std::stringstream stream;
|
|
|
|
const int i = static_cast< int >( val->getInt64() );
|
|
|
|
stream << i;
|
|
|
|
statement += stream.str();
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case Value::ddl_unsigned_int8:
|
|
|
|
{
|
|
|
|
std::stringstream stream;
|
|
|
|
const int i = static_cast< unsigned int >( val->getUnsignedInt8() );
|
|
|
|
stream << i;
|
|
|
|
statement += stream.str();
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case Value::ddl_unsigned_int16:
|
|
|
|
{
|
|
|
|
std::stringstream stream;
|
|
|
|
const int i = static_cast< unsigned int >( val->getUnsignedInt16() );
|
|
|
|
stream << i;
|
|
|
|
statement += stream.str();
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case Value::ddl_unsigned_int32:
|
|
|
|
{
|
|
|
|
std::stringstream stream;
|
|
|
|
const int i = static_cast< unsigned int >( val->getUnsignedInt32() );
|
|
|
|
stream << i;
|
|
|
|
statement += stream.str();
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case Value::ddl_unsigned_int64:
|
|
|
|
{
|
|
|
|
std::stringstream stream;
|
|
|
|
const int i = static_cast< unsigned int >( val->getUnsignedInt64() );
|
|
|
|
stream << i;
|
|
|
|
statement += stream.str();
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case Value::ddl_half:
|
|
|
|
break;
|
|
|
|
case Value::ddl_float:
|
|
|
|
{
|
|
|
|
std::stringstream stream;
|
|
|
|
stream << val->getFloat();
|
|
|
|
statement += stream.str();
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case Value::ddl_double:
|
|
|
|
break;
|
|
|
|
case Value::ddl_string:
|
|
|
|
{
|
|
|
|
std::stringstream stream;
|
|
|
|
stream << val->getString();
|
|
|
|
statement += "\"";
|
|
|
|
statement += stream.str();
|
|
|
|
statement += "\"";
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case Value::ddl_ref:
|
|
|
|
break;
|
|
|
|
case Value::ddl_none:
|
|
|
|
case Value::ddl_types_max:
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool OpenDDLExport::writeValueArray( DataArrayList *al, std::string &statement ) {
|
|
|
|
if (ddl_nullptr == al) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (0 == al->m_numItems) {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
DataArrayList *nextDataArrayList = al ;
|
|
|
|
Value *nextValue( nextDataArrayList->m_dataList );
|
|
|
|
while (ddl_nullptr != nextDataArrayList) {
|
|
|
|
if (ddl_nullptr != nextDataArrayList) {
|
|
|
|
statement += "{ ";
|
|
|
|
nextValue = nextDataArrayList->m_dataList;
|
|
|
|
size_t idx( 0 );
|
|
|
|
while (ddl_nullptr != nextValue) {
|
|
|
|
if (idx > 0) {
|
|
|
|
statement += ", ";
|
|
|
|
}
|
|
|
|
writeValue( nextValue, statement );
|
|
|
|
nextValue = nextValue->m_next;
|
|
|
|
idx++;
|
|
|
|
}
|
|
|
|
statement += " }";
|
|
|
|
}
|
|
|
|
nextDataArrayList = nextDataArrayList->m_next;
|
|
|
|
}
|
2015-10-01 22:38:50 +00:00
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
END_ODDLPARSER_NS
|
2016-01-08 15:46:13 +00:00
|
|
|
|