Torque3D Documentation / _generateds / tamlJSONParser.cpp

tamlJSONParser.cpp

Engine/source/persistence/taml/json/tamlJSONParser.cpp

More...

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/json/tamlJSONParser.h"
 25#include "persistence/taml/tamlVisitor.h"
 26#include "console/console.h"
 27#include "core/stream/fileStream.h"
 28#include "core/frameAllocator.h"
 29
 30// Debug Profiling.
 31#include "platform/profiler.h"
 32
 33//-----------------------------------------------------------------------------
 34
 35bool TamlJSONParser::accept( const char* pFilename, TamlVisitor& visitor )
 36{
 37    // Debug Profiling.
 38    PROFILE_SCOPE(TamlJSONParser_Accept);
 39
 40    // Sanity!
 41    AssertFatal( pFilename != NULL, "Cannot parse a NULL filename." );
 42
 43    // Expand the file-path.
 44    char filenameBuffer[1024];
 45    Con::expandToolScriptFilename( filenameBuffer, sizeof(filenameBuffer), pFilename );
 46
 47    FileStream stream;
 48
 49    // File open for read?
 50    if ( !stream.open( filenameBuffer, Torque::FS::File::Write ) )
 51    {
 52        // No, so warn.
 53        Con::warnf("TamlJSONParser::parse() - Could not open filename '%s' for parse.", filenameBuffer );
 54        return false;
 55    }
 56
 57    // Read JSON file.
 58    const U32 streamSize = stream.getStreamSize();
 59    FrameTemp<char> jsonText( streamSize + 1 );
 60    if ( !stream.read( streamSize, jsonText ) )
 61    {
 62        // Warn!
 63        Con::warnf("TamlJSONParser::parse() - Could not load Taml JSON file from stream.");
 64        return false;
 65    }
 66
 67    // Create JSON document.
 68    rapidjson::Document inputDocument;
 69    inputDocument.Parse<0>( jsonText );
 70
 71    // Close the stream.
 72    stream.close();
 73
 74    // Check the document is valid.
 75    if ( inputDocument.GetType() != rapidjson::kObjectType )
 76    {
 77        // Warn!
 78        Con::warnf("TamlJSONParser::parse() - Load Taml JSON file from stream but was invalid.");
 79        return false;
 80    }
 81
 82    // Set parsing filename.
 83    setParsingFilename( filenameBuffer );
 84
 85    // Flag document as not dirty.
 86    mDocumentDirty = false;
 87
 88    // Fetch the root.
 89    rapidjson::Value::MemberIterator rootItr = inputDocument.MemberBegin();
 90
 91    // Parse root value.
 92    parseType( rootItr, visitor, true );
 93
 94    // Reset parsing filename.
 95    setParsingFilename( StringTable->EmptyString() );
 96
 97    // Finish if the document is not dirty.
 98    if ( !mDocumentDirty )
 99        return true;
100
101    // Open for write?
102
103    if ( !stream.open( filenameBuffer, Torque::FS::File::Write ) )
104    {
105        // No, so warn.
106        Con::warnf("TamlJSONParser::parse() - Could not open filename '%s' for write.", filenameBuffer );
107        return false;
108    }
109
110    // Create output document.
111    rapidjson::Document outputDocument;
112    outputDocument.AddMember( rootItr->name, rootItr->value, outputDocument.GetAllocator() );
113
114    // Write document to stream.
115    rapidjson::PrettyWriter<FileStream> jsonStreamWriter( stream );
116    outputDocument.Accept( jsonStreamWriter );
117
118    // Close the stream.
119    stream.close();
120
121    return true;
122}
123
124//-----------------------------------------------------------------------------
125
126inline bool TamlJSONParser::parseType( rapidjson::Value::MemberIterator& memberItr, TamlVisitor& visitor, const bool isRoot )
127{
128    // Debug Profiling.
129    PROFILE_SCOPE(TamlJSONParser_ParseType);
130
131    // Fetch name and value.
132    const rapidjson::Value& typeName = memberItr->name;
133    rapidjson::Value& typeValue = memberItr->value;
134
135    // Create a visitor property state.
136    TamlVisitor::PropertyState propertyState;
137    propertyState.setObjectName( typeName.GetString(), isRoot );
138
139    // Parse field members.
140    for( rapidjson::Value::MemberIterator fieldMemberItr = typeValue.MemberBegin(); fieldMemberItr != typeValue.MemberEnd(); ++fieldMemberItr )
141    {
142        // Fetch value.
143        const rapidjson::Value& fieldName = fieldMemberItr->name;
144        rapidjson::Value& fieldValue = fieldMemberItr->value;
145        
146        // Skip if not a field.
147        if ( fieldValue.IsObject() )
148            continue;
149
150        char valueBuffer[4096];
151        if ( !parseStringValue( valueBuffer, sizeof(valueBuffer), fieldValue, fieldName.GetString() ) )
152        {
153            // Warn.
154            Con::warnf( "TamlJSONParser::parseTyoe() - Could not interpret value for field '%s'", fieldName.GetString() );
155            continue;
156        }
157
158        // Configure property state.
159        propertyState.setProperty( fieldName.GetString(), valueBuffer );
160
161        // Visit this attribute.
162        const bool visitStatus = visitor.visit( *this, propertyState );
163
164        // Was the property value changed?
165        if ( propertyState.getPropertyValueDirty() )
166        {
167            // Yes, so update the attribute.
168            fieldValue.SetString(rapidjson::GenericStringRef<UTF8>(propertyState.getPropertyValue()) );
169
170            // Flag the document as dirty.
171            mDocumentDirty = true;
172        }
173
174        // Finish if requested.
175        if ( !visitStatus )
176            return false;
177    }
178
179    // Finish if only the root is needed.
180    if ( visitor.wantsRootOnly() )
181        return false;
182
183    // Parse children and custom node members.
184    for( rapidjson::Value::MemberIterator objectMemberItr = typeValue.MemberBegin(); objectMemberItr != typeValue.MemberEnd(); ++objectMemberItr )
185    {
186        // Fetch name and value.
187        const rapidjson::Value& objectValue = objectMemberItr->value;
188        
189        // Skip if not an object.
190        if ( !objectValue.IsObject() )
191            continue;
192
193        // Parse the type.
194        if ( !parseType( objectMemberItr, visitor, false ) )
195            return false;
196    }
197
198    return true;
199}
200
201//-----------------------------------------------------------------------------
202
203inline bool TamlJSONParser::parseStringValue( char* pBuffer, const S32 bufferSize, const rapidjson::Value& value, const char* pName )
204{
205    // Debug Profiling.
206    PROFILE_SCOPE(TamlJSONParser_ParseStringValue);
207
208    // Handle field value appropriately.
209
210    if ( value.IsString() )
211    {
212        dSprintf( pBuffer, bufferSize, "%s", value.GetString() );
213        return true;
214    }
215
216    if ( value.IsNumber() )
217    {
218        if ( value.IsInt() )
219        {
220            dSprintf( pBuffer, bufferSize, "%d", value.GetInt() );
221            return true;
222        }
223
224        if ( value.IsUint() )
225        {
226            dSprintf( pBuffer, bufferSize, "%d", value.GetUint() );
227            return true;
228        }
229
230        if ( value.IsInt64() )
231        {
232            dSprintf( pBuffer, bufferSize, "%d", value.GetInt64() );
233            return true;
234        }
235
236        if ( value.IsUint64() )
237        {
238            dSprintf( pBuffer, bufferSize, "%d", value.GetUint64() );
239            return true;
240        }
241
242        if ( value.IsDouble() )
243        {
244            dSprintf( pBuffer, bufferSize, "%f", value.GetDouble() );
245            return true;
246        }
247    }
248
249    if ( value.IsBool() )
250    {
251        dSprintf( pBuffer, bufferSize, "%d", value.GetBool() );
252        return true;
253    }
254
255    // Failed to get value type.
256    Con::warnf( "Taml: Encountered a field '%s' but its value is an unknown type.", pName );
257    return false;
258}
259
260