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
32 struct DDLNodeIterator {
33 const DDLNode::DllNodeList &m_childs;
34 size_t m_idx;
35
DDLNodeIteratorDDLNodeIterator36 DDLNodeIterator( const DDLNode::DllNodeList &childs )
37 : m_childs( childs )
38 , m_idx( 0 ) {
39 // empty
40 }
41
~DDLNodeIteratorDDLNodeIterator42 ~DDLNodeIterator() {
43 // empty
44 }
45
getNextDDLNodeIterator46 bool getNext( DDLNode **node ) {
47 if( m_childs.size() > (m_idx+1) ) {
48 m_idx++;
49 *node = m_childs[ m_idx ];
50 return true;
51 }
52
53 return false;
54 }
55
56 private:
57 DDLNodeIterator() ddl_no_copy;
58 DDLNodeIterator &operator = ( const DDLNodeIterator & ) ddl_no_copy;
59 };
60
writeLineEnd(std::string & statement)61 static void writeLineEnd( std::string &statement ) {
62 statement += "\n";
63 }
64
OpenDDLExport(IOStreamBase * stream)65 OpenDDLExport::OpenDDLExport( IOStreamBase *stream )
66 : m_stream( stream ) {
67 if (ddl_nullptr == m_stream) {
68 m_stream = new IOStreamBase();
69 }
70 }
71
~OpenDDLExport()72 OpenDDLExport::~OpenDDLExport() {
73 if (ddl_nullptr != m_stream) {
74 m_stream->close();
75 }
76 delete m_stream;
77 }
78
exportContext(Context * ctx,const std::string & filename)79 bool OpenDDLExport::exportContext( Context *ctx, const std::string &filename ) {
80 if( ddl_nullptr == ctx ) {
81 return false;
82 }
83
84 DDLNode *root( ctx->m_root );
85 if ( ddl_nullptr == root ) {
86 return true;
87 }
88
89 if (!filename.empty()) {
90 if (!m_stream->open( filename )) {
91 return false;
92 }
93 }
94
95 const bool retValue( handleNode( root ) );
96
97 return retValue;
98 }
99
handleNode(DDLNode * node)100 bool OpenDDLExport::handleNode( DDLNode *node ) {
101 if( ddl_nullptr == node ) {
102 return true;
103 }
104
105 const DDLNode::DllNodeList &childs = node->getChildNodeList();
106 if( childs.empty() ) {
107 return true;
108 }
109 DDLNode *current( ddl_nullptr );
110 DDLNodeIterator it( childs );
111 std::string statement;
112 bool success( true );
113 while( it.getNext( ¤t ) ) {
114 if( ddl_nullptr != current ) {
115 success |= writeNode( current, statement );
116 if( !handleNode( current ) ) {
117 success = false;
118 }
119 }
120 }
121
122 return success;
123 }
124
writeToStream(const std::string & statement)125 bool OpenDDLExport::writeToStream( const std::string &statement ) {
126 if (ddl_nullptr == m_stream ) {
127 return false;
128 }
129
130 if ( !statement.empty()) {
131 m_stream->write( statement );
132 }
133
134 return true;
135 }
136
writeNode(DDLNode * node,std::string & statement)137 bool OpenDDLExport::writeNode( DDLNode *node, std::string &statement ) {
138 writeNodeHeader( node, statement );
139 if (node->hasProperties()) {
140 writeProperties( node, statement );
141 }
142 writeLineEnd( statement );
143
144 statement = "}";
145 DataArrayList *al( node->getDataArrayList() );
146 if ( ddl_nullptr != al ) {
147 writeValueType( al->m_dataList->m_type, al->m_numItems, statement );
148 writeValueArray( al, statement );
149 }
150 Value *v( node->getValue() );
151 if (ddl_nullptr != v ) {
152 writeValueType( v->m_type, 1, statement );
153 statement = "{";
154 writeLineEnd( statement );
155 writeValue( v, statement );
156 statement = "}";
157 writeLineEnd( statement );
158 }
159 statement = "}";
160 writeLineEnd( statement );
161
162 writeToStream( statement );
163
164 return true;
165 }
166
writeNodeHeader(DDLNode * node,std::string & statement)167 bool OpenDDLExport::writeNodeHeader( DDLNode *node, std::string &statement ) {
168 if (ddl_nullptr == node) {
169 return false;
170 }
171
172 statement += node->getType();
173 const std::string &name( node->getName() );
174 if ( !name.empty() ) {
175 statement += " ";
176 statement += "$";
177 statement += name;
178 }
179
180 return true;
181 }
182
writeProperties(DDLNode * node,std::string & statement)183 bool OpenDDLExport::writeProperties( DDLNode *node, std::string &statement ) {
184 if ( ddl_nullptr == node ) {
185 return false;
186 }
187
188 Property *prop( node->getProperties() );
189 // if no properties are there, return
190 if ( ddl_nullptr == prop ) {
191 return true;
192 }
193
194 if ( ddl_nullptr != prop ) {
195 // for instance (attrib = "position", bla=2)
196 statement += "(";
197 bool first( true );
198 while ( ddl_nullptr != prop ) {
199 if (!first) {
200 statement += ", ";
201 } else {
202 first = false;
203 }
204 statement += std::string( prop->m_key->m_buffer );
205 statement += " = ";
206 writeValue( prop->m_value, statement );
207 prop = prop->m_next;
208 }
209
210 statement += ")";
211 }
212
213 return true;
214 }
215
writeValueType(Value::ValueType type,size_t numItems,std::string & statement)216 bool OpenDDLExport::writeValueType( Value::ValueType type, size_t numItems, std::string &statement ) {
217 if ( Value::ddl_types_max == type) {
218 return false;
219 }
220
221 const std::string typeStr( getTypeToken( type ) );
222 statement += typeStr;
223 // if we have an array to write
224 if ( numItems > 1 ) {
225 statement += "[";
226 char buffer[ 256 ];
227 ::memset( buffer, '\0', 256 * sizeof( char ) );
228 sprintf( buffer, "%d", static_cast<int>( numItems ) );
229 statement += buffer;
230 statement += "]";
231 }
232
233 return true;
234 }
235
writeValue(Value * val,std::string & statement)236 bool OpenDDLExport::writeValue( Value *val, std::string &statement ) {
237 if (ddl_nullptr == val) {
238 return false;
239 }
240
241 switch ( val->m_type ) {
242 case Value::ddl_bool:
243 if ( true == val->getBool() ) {
244 statement += "true";
245 } else {
246 statement += "false";
247 }
248 break;
249 case Value::ddl_int8:
250 {
251 std::stringstream stream;
252 const int i = static_cast<int>( val->getInt8() );
253 stream << i;
254 statement += stream.str();
255 }
256 break;
257 case Value::ddl_int16:
258 {
259 std::stringstream stream;
260 char buffer[ 256 ];
261 ::memset( buffer, '\0', 256 * sizeof( char ) );
262 sprintf( buffer, "%d", val->getInt16() );
263 statement += buffer;
264 }
265 break;
266 case Value::ddl_int32:
267 {
268 std::stringstream stream;
269 char buffer[ 256 ];
270 ::memset( buffer, '\0', 256 * sizeof( char ) );
271 const int i = static_cast< int >( val->getInt32() );
272 sprintf( buffer, "%d", i );
273 statement += buffer;
274 }
275 break;
276 case Value::ddl_int64:
277 {
278 std::stringstream stream;
279 const int i = static_cast< int >( val->getInt64() );
280 stream << i;
281 statement += stream.str();
282 }
283 break;
284 case Value::ddl_unsigned_int8:
285 {
286 std::stringstream stream;
287 const int i = static_cast< unsigned int >( val->getUnsignedInt8() );
288 stream << i;
289 statement += stream.str();
290 }
291 break;
292 case Value::ddl_unsigned_int16:
293 {
294 std::stringstream stream;
295 const int i = static_cast< unsigned int >( val->getUnsignedInt16() );
296 stream << i;
297 statement += stream.str();
298 }
299 break;
300 case Value::ddl_unsigned_int32:
301 {
302 std::stringstream stream;
303 const int i = static_cast< unsigned int >( val->getUnsignedInt32() );
304 stream << i;
305 statement += stream.str();
306 }
307 break;
308 case Value::ddl_unsigned_int64:
309 {
310 std::stringstream stream;
311 const int i = static_cast< unsigned int >( val->getUnsignedInt64() );
312 stream << i;
313 statement += stream.str();
314 }
315 break;
316 case Value::ddl_half:
317 break;
318 case Value::ddl_float:
319 {
320 std::stringstream stream;
321 stream << val->getFloat();
322 statement += stream.str();
323 }
324 break;
325 case Value::ddl_double:
326 {
327 std::stringstream stream;
328 stream << val->getDouble();
329 statement += stream.str();
330 }
331 break;
332 case Value::ddl_string:
333 {
334 std::stringstream stream;
335 stream << val->getString();
336 statement += "\"";
337 statement += stream.str();
338 statement += "\"";
339 }
340 break;
341 case Value::ddl_ref:
342 break;
343 case Value::ddl_none:
344 case Value::ddl_types_max:
345 default:
346 break;
347 }
348
349 return true;
350 }
351
writeValueArray(DataArrayList * al,std::string & statement)352 bool OpenDDLExport::writeValueArray( DataArrayList *al, std::string &statement ) {
353 if (ddl_nullptr == al) {
354 return false;
355 }
356
357 if (0 == al->m_numItems) {
358 return true;
359 }
360
361 DataArrayList *nextDataArrayList = al ;
362 while (ddl_nullptr != nextDataArrayList) {
363 if (ddl_nullptr != nextDataArrayList) {
364 statement += "{ ";
365 Value *nextValue( nextDataArrayList->m_dataList );
366 size_t idx( 0 );
367 while (ddl_nullptr != nextValue) {
368 if (idx > 0) {
369 statement += ", ";
370 }
371 writeValue( nextValue, statement );
372 nextValue = nextValue->m_next;
373 idx++;
374 }
375 statement += " }";
376 }
377 nextDataArrayList = nextDataArrayList->m_next;
378 }
379
380 return true;
381 }
382
383 END_ODDLPARSER_NS
384
385