1 /*-----------------------------------------------------------------------------------------------
2 The MIT License (MIT)
3
4 Copyright (c) 2014-2015 Kim Kulling
5
6 Permission is hereby granted, free of charge, to any person obtaining a copy of
7 this software and associated documentation files (the "Software"), to deal in
8 the Software without restriction, including without limitation the rights to
9 use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
10 the Software, and to permit persons to whom the Software is furnished to do so,
11 subject to the following conditions:
12
13 The above copyright notice and this permission notice shall be included in all
14 copies or substantial portions of the Software.
15
16 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
18 FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
19 COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
20 IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
21 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22 -----------------------------------------------------------------------------------------------*/
23 #include <openddlparser/OpenDDLExport.h>
24 #include <openddlparser/DDLNode.h>
25 #include <openddlparser/Value.h>
26 #include <openddlparser/OpenDDLParser.h>
27
28 #include <sstream>
29
30 BEGIN_ODDLPARSER_NS
31
StreamFormatterBase()32 StreamFormatterBase::StreamFormatterBase() {
33
34 }
35
~StreamFormatterBase()36 StreamFormatterBase::~StreamFormatterBase() {
37
38 }
39
format(const std::string & statement)40 std::string StreamFormatterBase::format( const std::string &statement ) {
41 std::string tmp( statement );
42 return tmp;
43 }
44
IOStreamBase(StreamFormatterBase * formatter)45 IOStreamBase::IOStreamBase( StreamFormatterBase *formatter )
46 : m_formatter( formatter )
47 , m_file( ddl_nullptr ) {
48 if (ddl_nullptr == m_formatter) {
49 m_formatter = new StreamFormatterBase;
50 }
51 }
52
~IOStreamBase()53 IOStreamBase::~IOStreamBase() {
54 delete m_formatter;
55 m_formatter = ddl_nullptr;
56 }
57
open(const std::string & name)58 bool IOStreamBase::open( const std::string &name ) {
59 m_file = ::fopen( name.c_str(), "a" );
60 if (m_file == ddl_nullptr) {
61 return false;
62 }
63
64 return true;
65 }
66
close()67 bool IOStreamBase::close() {
68 if (ddl_nullptr == m_file) {
69 return false;
70 }
71
72 ::fclose( m_file );
73 m_file = ddl_nullptr;
74
75 return true;
76 }
77
write(const std::string & statement)78 size_t IOStreamBase::write( const std::string &statement ) {
79 if (ddl_nullptr == m_file) {
80 return 0;
81 }
82 std::string formatStatement = m_formatter->format( statement );
83 return ::fwrite( formatStatement.c_str(), sizeof( char ), formatStatement.size(), m_file );
84 }
85
86 struct DDLNodeIterator {
87 const DDLNode::DllNodeList &m_childs;
88 size_t m_idx;
89
DDLNodeIteratorDDLNodeIterator90 DDLNodeIterator( const DDLNode::DllNodeList &childs )
91 : m_childs( childs )
92 , m_idx( 0 ) {
93 // empty
94 }
95
~DDLNodeIteratorDDLNodeIterator96 ~DDLNodeIterator() {
97 // empty
98 }
99
getNextDDLNodeIterator100 bool getNext( DDLNode **node ) {
101 if( m_childs.size() > (m_idx+1) ) {
102 m_idx++;
103 *node = m_childs[ m_idx ];
104 return true;
105 }
106
107 return false;
108 }
109
110 private:
111 DDLNodeIterator() ddl_no_copy;
112 DDLNodeIterator &operator = ( const DDLNodeIterator & ) ddl_no_copy;
113 };
114
writeLineEnd(std::string & statement)115 static void writeLineEnd( std::string &statement ) {
116 statement += "\n";
117 }
118
OpenDDLExport(IOStreamBase * stream)119 OpenDDLExport::OpenDDLExport( IOStreamBase *stream )
120 : m_stream( stream ) {
121 if (ddl_nullptr == m_stream) {
122 m_stream = new IOStreamBase();
123 }
124 }
125
~OpenDDLExport()126 OpenDDLExport::~OpenDDLExport() {
127 if (ddl_nullptr != m_stream) {
128 m_stream->close();
129 }
130 delete m_stream;
131 }
132
exportContext(Context * ctx,const std::string & filename)133 bool OpenDDLExport::exportContext( Context *ctx, const std::string &filename ) {
134 if( ddl_nullptr == ctx ) {
135 return false;
136 }
137
138 DDLNode *root( ctx->m_root );
139 if ( ddl_nullptr == root ) {
140 return true;
141 }
142
143 if (!filename.empty()) {
144 if (!m_stream->open( filename )) {
145 return false;
146 }
147 }
148
149 const bool retValue( handleNode( root ) );
150
151 return retValue;
152 }
153
handleNode(DDLNode * node)154 bool OpenDDLExport::handleNode( DDLNode *node ) {
155 if( ddl_nullptr == node ) {
156 return true;
157 }
158
159 const DDLNode::DllNodeList &childs = node->getChildNodeList();
160 if( childs.empty() ) {
161 return true;
162 }
163 DDLNode *current( ddl_nullptr );
164 DDLNodeIterator it( childs );
165 std::string statement;
166 bool success( true );
167 while( it.getNext( ¤t ) ) {
168 if( ddl_nullptr != current ) {
169 success |= writeNode( current, statement );
170 if( !handleNode( current ) ) {
171 success = false;
172 }
173 }
174 }
175
176 return success;
177 }
178
writeToStream(const std::string & statement)179 bool OpenDDLExport::writeToStream( const std::string &statement ) {
180 if (ddl_nullptr == m_stream ) {
181 return false;
182 }
183
184 if ( !statement.empty()) {
185 m_stream->write( statement );
186 }
187
188 return true;
189 }
190
writeNode(DDLNode * node,std::string & statement)191 bool OpenDDLExport::writeNode( DDLNode *node, std::string &statement ) {
192 bool success( true );
193 writeNodeHeader( node, statement );
194 if (node->hasProperties()) {
195 success |= writeProperties( node, statement );
196 }
197 writeLineEnd( statement );
198
199 statement = "}";
200 DataArrayList *al( node->getDataArrayList() );
201 if ( ddl_nullptr != al ) {
202 writeValueType( al->m_dataList->m_type, al->m_numItems, statement );
203 writeValueArray( al, statement );
204 }
205 Value *v( node->getValue() );
206 if (ddl_nullptr != v ) {
207 writeValueType( v->m_type, 1, statement );
208 statement = "{";
209 writeLineEnd( statement );
210 writeValue( v, statement );
211 statement = "}";
212 writeLineEnd( statement );
213 }
214 statement = "}";
215 writeLineEnd( statement );
216
217 writeToStream( statement );
218
219 return true;
220 }
221
writeNodeHeader(DDLNode * node,std::string & statement)222 bool OpenDDLExport::writeNodeHeader( DDLNode *node, std::string &statement ) {
223 if (ddl_nullptr == node) {
224 return false;
225 }
226
227 statement += node->getType();
228 const std::string &name( node->getName() );
229 if ( !name.empty() ) {
230 statement += " ";
231 statement += "$";
232 statement += name;
233 }
234
235 return true;
236 }
237
writeProperties(DDLNode * node,std::string & statement)238 bool OpenDDLExport::writeProperties( DDLNode *node, std::string &statement ) {
239 if ( ddl_nullptr == node ) {
240 return false;
241 }
242
243 Property *prop( node->getProperties() );
244 // if no properties are there, return
245 if ( ddl_nullptr == prop ) {
246 return true;
247 }
248
249 if ( ddl_nullptr != prop ) {
250 // for instance (attrib = "position", bla=2)
251 statement += "(";
252 bool first( true );
253 while ( ddl_nullptr != prop ) {
254 if (!first) {
255 statement += ", ";
256 } else {
257 first = false;
258 }
259 statement += std::string( prop->m_key->m_buffer );
260 statement += " = ";
261 writeValue( prop->m_value, statement );
262 prop = prop->m_next;
263 }
264
265 statement += ")";
266 }
267
268 return true;
269 }
270
writeValueType(Value::ValueType type,size_t numItems,std::string & statement)271 bool OpenDDLExport::writeValueType( Value::ValueType type, size_t numItems, std::string &statement ) {
272 if ( Value::ddl_types_max == type) {
273 return false;
274 }
275
276 const std::string typeStr( getTypeToken( type ) );
277 statement += typeStr;
278 // if we have an array to write
279 if ( numItems > 1 ) {
280 statement += "[";
281 char buffer[ 256 ];
282 ::memset( buffer, '\0', 256 * sizeof( char ) );
283 sprintf( buffer, "%d", numItems );
284 statement += buffer;
285 statement += "]";
286 }
287
288 return true;
289 }
290
writeValue(Value * val,std::string & statement)291 bool OpenDDLExport::writeValue( Value *val, std::string &statement ) {
292 if (ddl_nullptr == val) {
293 return false;
294 }
295
296 switch ( val->m_type ) {
297 case Value::ddl_bool:
298 if ( true == val->getBool() ) {
299 statement += "true";
300 } else {
301 statement += "false";
302 }
303 break;
304 case Value::ddl_int8:
305 {
306 std::stringstream stream;
307 const int i = static_cast<int>( val->getInt8() );
308 stream << i;
309 statement += stream.str();
310 }
311 break;
312 case Value::ddl_int16:
313 {
314 std::stringstream stream;
315 char buffer[ 256 ];
316 ::memset( buffer, '\0', 256 * sizeof( char ) );
317 sprintf( buffer, "%d", val->getInt16() );
318 statement += buffer;
319 }
320 break;
321 case Value::ddl_int32:
322 {
323 std::stringstream stream;
324 char buffer[ 256 ];
325 ::memset( buffer, '\0', 256 * sizeof( char ) );
326 const int i = static_cast< int >( val->getInt32() );
327 sprintf( buffer, "%d", i );
328 statement += buffer;
329 }
330 break;
331 case Value::ddl_int64:
332 {
333 std::stringstream stream;
334 const int i = static_cast< int >( val->getInt64() );
335 stream << i;
336 statement += stream.str();
337 }
338 break;
339 case Value::ddl_unsigned_int8:
340 {
341 std::stringstream stream;
342 const int i = static_cast< unsigned int >( val->getUnsignedInt8() );
343 stream << i;
344 statement += stream.str();
345 }
346 break;
347 case Value::ddl_unsigned_int16:
348 {
349 std::stringstream stream;
350 const int i = static_cast< unsigned int >( val->getUnsignedInt16() );
351 stream << i;
352 statement += stream.str();
353 }
354 break;
355 case Value::ddl_unsigned_int32:
356 {
357 std::stringstream stream;
358 const int i = static_cast< unsigned int >( val->getUnsignedInt32() );
359 stream << i;
360 statement += stream.str();
361 }
362 break;
363 case Value::ddl_unsigned_int64:
364 {
365 std::stringstream stream;
366 const int i = static_cast< unsigned int >( val->getUnsignedInt64() );
367 stream << i;
368 statement += stream.str();
369 }
370 break;
371 case Value::ddl_half:
372 break;
373 case Value::ddl_float:
374 {
375 std::stringstream stream;
376 stream << val->getFloat();
377 statement += stream.str();
378 }
379 break;
380 case Value::ddl_double:
381 {
382 std::stringstream stream;
383 stream << val->getDouble();
384 statement += stream.str();
385 }
386 break;
387 case Value::ddl_string:
388 {
389 std::stringstream stream;
390 stream << val->getString();
391 statement += "\"";
392 statement += stream.str();
393 statement += "\"";
394 }
395 break;
396 case Value::ddl_ref:
397 break;
398 case Value::ddl_none:
399 case Value::ddl_types_max:
400 default:
401 break;
402 }
403
404 return true;
405 }
406
writeValueArray(DataArrayList * al,std::string & statement)407 bool OpenDDLExport::writeValueArray( DataArrayList *al, std::string &statement ) {
408 if (ddl_nullptr == al) {
409 return false;
410 }
411
412 if (0 == al->m_numItems) {
413 return true;
414 }
415
416 DataArrayList *nextDataArrayList = al ;
417 Value *nextValue( nextDataArrayList->m_dataList );
418 while (ddl_nullptr != nextDataArrayList) {
419 if (ddl_nullptr != nextDataArrayList) {
420 statement += "{ ";
421 nextValue = nextDataArrayList->m_dataList;
422 size_t idx( 0 );
423 while (ddl_nullptr != nextValue) {
424 if (idx > 0) {
425 statement += ", ";
426 }
427 writeValue( nextValue, statement );
428 nextValue = nextValue->m_next;
429 idx++;
430 }
431 statement += " }";
432 }
433 nextDataArrayList = nextDataArrayList->m_next;
434 }
435
436 return true;
437 }
438
439 END_ODDLPARSER_NS
440
441