tamlBinaryWriter.cpp
Engine/source/persistence/taml/binary/tamlBinaryWriter.cpp
Detailed Description
1 2//----------------------------------------------------------------------------- 3// Copyright (c) 2013 GarageGames, LLC 4// 5// Permission is hereby granted, free of charge, to any person obtaining a copy 6// of this software and associated documentation files (the "Software"), to 7// deal in the Software without restriction, including without limitation the 8// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 9// sell copies of the Software, and to permit persons to whom the Software is 10// furnished to do so, subject to the following conditions: 11// 12// The above copyright notice and this permission notice shall be included in 13// all copies or substantial portions of the Software. 14// 15// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 21// IN THE SOFTWARE. 22//----------------------------------------------------------------------------- 23 24#include "persistence/taml/binary/tamlBinaryWriter.h" 25 26#ifndef _ZIPSUBSTREAM_H_ 27#include "core/util/zip/zipSubStream.h" 28#endif 29 30// Debug Profiling. 31#include "platform/profiler.h" 32 33//----------------------------------------------------------------------------- 34 35bool TamlBinaryWriter::write( FileStream& stream, const TamlWriteNode* pTamlWriteNode, const bool compressed ) 36{ 37 // Debug Profiling. 38 PROFILE_SCOPE(TamlBinaryWriter_Write); 39 40 // Write Taml signature. 41 stream.writeString( StringTable->insert( TAML_SIGNATURE ) ); 42 43 // Write version Id. 44 stream.write( mVersionId ); 45 46 // Write compressed flag. 47 stream.write( compressed ); 48 49 // Are we compressed? 50 if ( compressed ) 51 { 52 // yes, so attach zip stream. 53 ZipSubWStream zipStream; 54 zipStream.attachStream( &stream ); 55 56 // Write element. 57 writeElement( zipStream, pTamlWriteNode ); 58 59 // Detach zip stream. 60 zipStream.detachStream(); 61 } 62 else 63 { 64 // No, so write element. 65 writeElement( stream, pTamlWriteNode ); 66 } 67 68 return true; 69} 70 71//----------------------------------------------------------------------------- 72 73void TamlBinaryWriter::writeElement( Stream& stream, const TamlWriteNode* pTamlWriteNode ) 74{ 75 // Debug Profiling. 76 PROFILE_SCOPE(TamlBinaryWriter_WriteElement); 77 78 // Fetch object. 79 SimObject* pSimObject = pTamlWriteNode->mpSimObject; 80 81 // Fetch element name. 82 const char* pElementName = pSimObject->getClassName(); 83 84 // Write element name. 85 stream.writeString( pElementName ); 86 87 // Fetch object name. 88 const char* pObjectName = pTamlWriteNode->mpObjectName; 89 90 // Write object name. 91 stream.writeString( pObjectName != NULL ? pObjectName : StringTable->EmptyString() ); 92 93 // Fetch reference Id. 94 const U32 tamlRefId = pTamlWriteNode->mRefId; 95 96 // Write reference Id. 97 stream.write( tamlRefId ); 98 99 // Do we have a reference to node? 100 if ( pTamlWriteNode->mRefToNode != NULL ) 101 { 102 // Yes, so fetch reference to Id. 103 const U32 tamlRefToId = pTamlWriteNode->mRefToNode->mRefId; 104 105 // Sanity! 106 AssertFatal( tamlRefToId != 0, "Taml: Invalid reference to Id." ); 107 108 // Write reference to Id. 109 stream.write( tamlRefToId ); 110 111 // Finished. 112 return; 113 } 114 115 // No, so write no reference to Id. 116 stream.write( 0 ); 117 118 // Write attributes. 119 writeAttributes( stream, pTamlWriteNode ); 120 121 // Write children. 122 writeChildren( stream, pTamlWriteNode ); 123 124 // Write custom elements. 125 writeCustomElements( stream, pTamlWriteNode ); 126} 127 128//----------------------------------------------------------------------------- 129 130void TamlBinaryWriter::writeAttributes( Stream& stream, const TamlWriteNode* pTamlWriteNode ) 131{ 132 // Debug Profiling. 133 PROFILE_SCOPE(TamlBinaryWriter_WriteAttributes); 134 135 // Fetch fields. 136 const Vector<TamlWriteNode::FieldValuePair*>& fields = pTamlWriteNode->mFields; 137 138 // Write placeholder attribute count. 139 stream.write( (U32)fields.size() ); 140 141 // Finish if no fields. 142 if ( fields.size() == 0 ) 143 return; 144 145 // Iterate fields. 146 for( Vector<TamlWriteNode::FieldValuePair*>::const_iterator itr = fields.begin(); itr != fields.end(); ++itr ) 147 { 148 // Fetch field/value pair. 149 TamlWriteNode::FieldValuePair* pFieldValue = (*itr); 150 151 // Write attribute. 152 stream.writeString( pFieldValue->mName ); 153 stream.writeLongString( 4096, pFieldValue->mpValue ); 154 } 155} 156 157void TamlBinaryWriter::writeChildren( Stream& stream, const TamlWriteNode* pTamlWriteNode ) 158{ 159 // Debug Profiling. 160 PROFILE_SCOPE(TamlBinaryWriter_WriteChildren); 161 162 // Fetch children. 163 Vector<TamlWriteNode*>* pChildren = pTamlWriteNode->mChildren; 164 165 // Do we have any children? 166 if ( pChildren == NULL ) 167 { 168 // No, so write no children. 169 stream.write( (U32)0 ); 170 return; 171 } 172 173 // Write children count. 174 stream.write( (U32)pChildren->size() ); 175 176 // Iterate children. 177 for( Vector<TamlWriteNode*>::iterator itr = pChildren->begin(); itr != pChildren->end(); ++itr ) 178 { 179 // Write child. 180 writeElement( stream, (*itr) ); 181 } 182} 183 184//----------------------------------------------------------------------------- 185 186void TamlBinaryWriter::writeCustomElements( Stream& stream, const TamlWriteNode* pTamlWriteNode ) 187{ 188 // Debug Profiling. 189 PROFILE_SCOPE(TamlBinaryWriter_WriteCustomElements); 190 191 // Fetch custom nodes. 192 const TamlCustomNodes& customNodes = pTamlWriteNode->mCustomNodes; 193 194 // Fetch custom nodes. 195 const TamlCustomNodeVector& nodes = customNodes.getNodes(); 196 197 // Write custom node count. 198 stream.write( (U32)nodes.size() ); 199 200 // Finish if there are no nodes. 201 if ( nodes.size() == 0 ) 202 return; 203 204 // Iterate custom nodes. 205 for( TamlCustomNodeVector::const_iterator customNodesItr = nodes.begin(); customNodesItr != nodes.end(); ++customNodesItr ) 206 { 207 // Fetch the custom node. 208 TamlCustomNode* pCustomNode = *customNodesItr; 209 210 // Write custom node name. 211 stream.writeString( pCustomNode->getNodeName() ); 212 213 // Fetch node children. 214 const TamlCustomNodeVector& nodeChildren = pCustomNode->getChildren(); 215 216 // Iterate children nodes. 217 for( TamlCustomNodeVector::const_iterator childNodeItr = nodeChildren.begin(); childNodeItr != nodeChildren.end(); ++childNodeItr ) 218 { 219 // Fetch child node. 220 const TamlCustomNode* pChildNode = *childNodeItr; 221 222 // Write the custom node. 223 writeCustomNode( stream, pChildNode ); 224 } 225 } 226} 227 228//----------------------------------------------------------------------------- 229 230void TamlBinaryWriter::writeCustomNode( Stream& stream, const TamlCustomNode* pCustomNode ) 231{ 232 // Is the node a proxy object? 233 if ( pCustomNode->isProxyObject() ) 234 { 235 // Yes, so flag as proxy object. 236 stream.write( true ); 237 238 // Write the element. 239 writeElement( stream, pCustomNode->getProxyWriteNode() ); 240 return; 241 } 242 243 // No, so flag as custom node. 244 stream.write( false ); 245 246 // Write custom node name. 247 stream.writeString( pCustomNode->getNodeName() ); 248 249 // Write custom node text. 250 stream.writeLongString(MAX_TAML_NODE_FIELDVALUE_LENGTH, pCustomNode->getNodeTextField().getFieldValue()); 251 252 // Fetch node children. 253 const TamlCustomNodeVector& nodeChildren = pCustomNode->getChildren(); 254 255 // Fetch child node count. 256 const U32 childNodeCount = (U32)nodeChildren.size(); 257 258 // Write custom node count. 259 stream.write( childNodeCount ); 260 261 // Do we have any children nodes. 262 if ( childNodeCount > 0 ) 263 { 264 // Yes, so iterate children nodes. 265 for( TamlCustomNodeVector::const_iterator childNodeItr = nodeChildren.begin(); childNodeItr != nodeChildren.end(); ++childNodeItr ) 266 { 267 // Fetch child node. 268 const TamlCustomNode* pChildNode = *childNodeItr; 269 270 // Write the custom node. 271 writeCustomNode( stream, pChildNode ); 272 } 273 } 274 275 // Fetch fields. 276 const TamlCustomFieldVector& fields = pCustomNode->getFields(); 277 278 // Fetch child field count. 279 const U32 childFieldCount = (U32)fields.size(); 280 281 // Write custom field count. 282 stream.write( childFieldCount ); 283 284 // Do we have any child fields? 285 if ( childFieldCount > 0 ) 286 { 287 // Yes, so iterate fields. 288 for ( TamlCustomFieldVector::const_iterator fieldItr = fields.begin(); fieldItr != fields.end(); ++fieldItr ) 289 { 290 // Fetch node field. 291 const TamlCustomField* pField = *fieldItr; 292 293 // Write the node field. 294 stream.writeString( pField->getFieldName() ); 295 stream.writeLongString( MAX_TAML_NODE_FIELDVALUE_LENGTH, pField->getFieldValue() ); 296 } 297 } 298} 299