diff options
| author | Bryan Galdrikian <[email protected]> | 2018-05-31 11:36:08 -0700 |
|---|---|---|
| committer | Bryan Galdrikian <[email protected]> | 2018-05-31 11:36:08 -0700 |
| commit | 7115f60b91b5717d90f643fd692010905c7004db (patch) | |
| tree | effd68c6978751c517d54c2f2bb5bb6e7dc93e18 /sdk/extensions/import/apexmodules/NvParameterized/src/XmlDeserializer.cpp | |
| parent | Updating BlastTool zip (diff) | |
| download | blast-7115f60b91b5717d90f643fd692010905c7004db.tar.xz blast-7115f60b91b5717d90f643fd692010905c7004db.zip | |
Blast 1.1.3. See docs/release_notes.txt.v1.1.3_rc1
Diffstat (limited to 'sdk/extensions/import/apexmodules/NvParameterized/src/XmlDeserializer.cpp')
| -rwxr-xr-x[-rw-r--r--] | sdk/extensions/import/apexmodules/NvParameterized/src/XmlDeserializer.cpp | 1518 |
1 files changed, 759 insertions, 759 deletions
diff --git a/sdk/extensions/import/apexmodules/NvParameterized/src/XmlDeserializer.cpp b/sdk/extensions/import/apexmodules/NvParameterized/src/XmlDeserializer.cpp index 69253e6..cf1eaad 100644..100755 --- a/sdk/extensions/import/apexmodules/NvParameterized/src/XmlDeserializer.cpp +++ b/sdk/extensions/import/apexmodules/NvParameterized/src/XmlDeserializer.cpp @@ -1,759 +1,759 @@ -// This code contains NVIDIA Confidential Information and is disclosed to you -// under a form of NVIDIA software license agreement provided separately to you. -// -// Notice -// NVIDIA Corporation and its licensors retain all intellectual property and -// proprietary rights in and to this software and related documentation and -// any modifications thereto. Any use, reproduction, disclosure, or -// distribution of this software and related documentation without an express -// license agreement from NVIDIA Corporation is strictly prohibited. -// -// ALL NVIDIA DESIGN SPECIFICATIONS, CODE ARE PROVIDED "AS IS.". NVIDIA MAKES -// NO WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO -// THE MATERIALS, AND EXPRESSLY DISCLAIMS ALL IMPLIED WARRANTIES OF NONINFRINGEMENT, -// MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE. -// -// Information and code furnished is believed to be accurate and reliable. -// However, NVIDIA Corporation assumes no responsibility for the consequences of use of such -// information or for any infringement of patents or other rights of third parties that may -// result from its use. No license is granted by implication or otherwise under any patent -// or patent rights of NVIDIA Corporation. Details are subject to change without notice. -// This code supersedes and replaces all information previously supplied. -// NVIDIA Corporation products are not authorized for use as critical -// components in life support devices or systems without express written approval of -// NVIDIA Corporation. -// -// Copyright (c) 2008-2013 NVIDIA Corporation. All rights reserved. - -#include "PxSimpleTypes.h" -#include "NvParameters.h" -#include "nvparameterized/NvParameterizedTraits.h" - -#include "NvTraitsInternal.h" - -#include "XmlDeserializer.h" - -#define XML_WARNING(_format, ...) \ - NV_PARAM_TRAITS_WARNING(mTraits, "XML serializer: " _format, ##__VA_ARGS__) - - - -namespace NvParameterized -{ - -/*! -Get number of elements in array -*/ -template <typename T, size_t N> -char (&ArraySizeHelper(T (&array)[N]))[N]; -#define PX_ARRAY_SIZE(_array) (sizeof(ArraySizeHelper(_array))) - - static uint32_t ReadVersion(const physx::shdfnd::FastXml::AttributePairs& attr) - { - const char *versionText = attr.get("version"); - - // If there's no version, assume version is 0.0 - if( !versionText ) - return 0; - - //XML stores versions in "x.y"-format - //FIXME: strtoul is unsafe - - const char *dot = strchr(versionText, '.'); - uint32_t minor = dot ? strtoul(dot + 1, 0, 10) : 0; - - uint32_t major = strtoul(versionText, 0, 10); - - return (major << 16) + minor; - } - - static PX_INLINE bool isWhiteSpace(char c) - { - return c == ' ' || c == '\t' || c == '\r' || c == '\n' || c == ','; - } - - static PX_INLINE const char * skipWhiteSpace(const char *scan) - { - while ( isWhiteSpace(*scan) && *scan ) scan++; - return *scan ? scan : 0; - } - - static PX_FORCE_INLINE const char * skipNonWhiteSpace(const char* scan) - { - while ( !isWhiteSpace(*scan) && *scan ) scan++; - return *scan ? scan : 0; - } - - bool XmlDeserializer::verifyObject(Interface *obj, const physx::shdfnd::FastXml::AttributePairs& attr) - { - if( ReadVersion(attr) != obj->version() ) - { - XML_WARNING("unknown error"); - DEBUG_ALWAYS_ASSERT(); - mError = Serializer::ERROR_UNKNOWN; - return false; - } - - char *checksum = (char *)attr.get("checksum"); - if( checksum && !DoIgnoreChecksum(*obj) ) - { - uint32_t objBits; - const uint32_t *objChecksum = obj->checksum(objBits); - - uint32_t bits = 0; - - char *cur = checksum, *next = 0; - bool sameBits = true; - for(uint32_t i = 0; ; ++i, cur = next) - { - uint32_t val = (uint32_t)strtoul(cur, &next, 0); //FIXME: strtoul is not safe - if( cur == next ) - break; - - bits += 32; - if( bits > objBits || val != objChecksum[i] ) - { - NV_PARAM_TRAITS_WARNING( - mTraits, - "Schema checksum is different for object of class %s and version %u, " - "asset may be corrupted", - obj->className(), - (unsigned)obj->version() - ); - sameBits = false; - break; - } - } - - if( objBits != bits && sameBits ) - { - NV_PARAM_TRAITS_WARNING( - mTraits, - "Schema checksum is different for object of class %s and version %u, " - "asset may be corrupted", - obj->className(), - (unsigned)obj->version() - ); - } - } //if( checksum ) - - return true; - } - - bool XmlDeserializer::initAddressString(char *dest, uint32_t len, const char *name) - { - char *end = dest + len; - - for (uint32_t i = 0; i < tos().getIndex(); i++) - { - FieldInfo &field = tos().getFieldInfo(i); - - const char *n = field.name; - FieldType type = field.type; - - if( SKIP == type ) - continue; - - while ( n && *n && dest < end ) - *dest++ = *n++; - - if ( ARRAY == type ) - { - char temp[512]; - physx::shdfnd::snprintf(temp, 512, "[%d]", field.idx); - - if( dest + ::strlen(temp) >= end ) - { - XML_WARNING("buffer overflow"); - DEBUG_ALWAYS_ASSERT(); - mError = Serializer::ERROR_INTERNAL_BUFFER_OVERFLOW; - return false; - } - - const char *scan = temp; - while ( *scan && dest < end ) - { - *dest++ = *scan++; - } - } - else - { - if( dest + 1 >= end ) - { - XML_WARNING("buffer overflow"); - DEBUG_ALWAYS_ASSERT(); - mError = Serializer::ERROR_INTERNAL_BUFFER_OVERFLOW; - return false; - } - - *dest++ = '.'; - } - } - - while ( name && *name && dest < end ) - { - *dest++ = *name++; - } - - *dest = 0; - //printf("Fully qualified name: %s\n", scratch ); - - return true; - } - - bool XmlDeserializer::processClose(const char *tag,uint32_t depth,bool &isError) - { - isError = true; //By default if we return with false it's due to error - - if( strcmp(tag, "NxParameters") == 0 || - strcmp(tag, "NvParameters") == 0) - { - mInRootElement = false; - - // in xml there's only 1 root element allowed, - // so we want to stop after the first NvParameters - isError = false; - return false; - } - - static const char *validTags[] = { - "struct", - "value", - "array" - }; - - for(uint32_t i = 0; i < PX_ARRAY_SIZE(validTags); ++i) - { - if( 0 != ::strcmp(validTags[i], tag) ) - continue; - -# ifndef NDEBUG - uint32_t idx = tos().getIndex(); - DEBUG_ASSERT( idx > 0 ); - - static FieldType validTypes[] = { - STRUCT, - VALUE, - ARRAY - }; - - // Make gcc happy - const FieldType* tmp = &validTypes[0]; - PX_UNUSED(tmp); - - FieldType type = tos().getFieldInfo(idx - 1).type; - PX_UNUSED(type); - DEBUG_ASSERT( type == SKIP || type == validTypes[i] ); -# endif - - if( !popField() ) - return false; - - if (depth == 1 && mRootIndex > MAX_ROOT_OBJ) - { - DEBUG_ASSERT(i == 1); - mObjects[0].getObject()->destroy(); - } - - return tos().getIndex() ? depth != 0 : popObj(); - } - - return false; - } - - bool XmlDeserializer::processElement( - const char *elementName, - const char *elementData, - const physx::shdfnd::FastXml::AttributePairs& attr, - int32_t /*lineno*/) - { - //Force DOCTYPE - if( !mHasDoctype ) - { - XML_WARNING("DOCTYPE is missing"); - DEBUG_ALWAYS_ASSERT(); - mError = Serializer::ERROR_MISSING_DOCTYPE; - return false; - } - - if( strcmp(elementName, "NxParameters") == 0 || - strcmp(elementName, "NvParameters") == 0) - { - if( mObjIndex ) - { - XML_WARNING("NvParameters must be root element"); - DEBUG_ALWAYS_ASSERT(); - mError = Serializer::ERROR_MISSING_ROOT_ELEMENT; - return false; - } - - if( mInRootElement ) - { - XML_WARNING("More than one root element encountered"); - DEBUG_ALWAYS_ASSERT(); - mError = Serializer::ERROR_INVALID_NESTING; - return false; - } - - uint32_t ver = ReadVersion(attr); - if( ver != mVer ) - { - XML_WARNING("unknown version of APX file format: %u", (unsigned)ver); - DEBUG_ALWAYS_ASSERT(); - mError = Serializer::ERROR_INVALID_FILE_VERSION; - return false; - } - - const char* numObjects = attr.get("numObjects"); - if (numObjects != NULL) - { - PX_ASSERT(atoi(numObjects) >= 0); - const uint32_t num = static_cast<uint32_t>(atoi(numObjects)); - if (num > MAX_ROOT_OBJ) - { - XML_WARNING("APX file has more than %d root objects, only %d will be read", num, MAX_ROOT_OBJ); - } - } - - - ++mRootTags; - mInRootElement = true; - - return true; - } - - if( mRootTags > 0 && !mInRootElement ) - { - XML_WARNING("element %s not under root element", elementName); - DEBUG_ALWAYS_ASSERT(); - mError = Serializer::ERROR_MISSING_ROOT_ELEMENT; - return false; - } - - if ( strcmp(elementName, "struct") == 0 ) - { - const char *name = attr.get("name"); - - if( !mObjIndex ) - { - XML_WARNING("struct-element %s not under value-element", name); - DEBUG_ALWAYS_ASSERT(); - mError = Serializer::ERROR_INVALID_NESTING; - return false; - } - - pushField(name, STRUCT); - } - else if ( strcmp(elementName, "value") == 0 ) - { - if( !mObjIndex ) //Root object? - { - const char *className = attr.get("className"); - - uint32_t version = ReadVersion(attr); - - Interface *obj = mTraits->createNvParameterized(className, version); - if( !obj ) - { - XML_WARNING("failed to create object of type %s and version %u", className, (unsigned)version); - DEBUG_ALWAYS_ASSERT(); - mError = Serializer::ERROR_OBJECT_CREATION_FAILED; - return false; - } - - const char *objectName = attr.get("objectName"); - if( objectName ) - obj->setName(objectName); - - if (mRootIndex < MAX_ROOT_OBJ) - { - mRootObjs[mRootIndex] = obj; - } - mRootIndex++; - - pushObj(obj); - pushField("", SKIP); //Root <value> should not be used in initAddressString - - return true; - } - - const char *name = attr.get("name"); - - char scratch[2048]; - if( !initAddressString(scratch, sizeof(scratch), name) ) - { - return false; - } - - pushField(name, VALUE); - - Interface *obj = tos().getObject(); - if( !obj ) - { - XML_WARNING("unknown error"); - DEBUG_ALWAYS_ASSERT(); - mError = Serializer::ERROR_UNKNOWN; - return false; - } - - Handle handle(*obj, scratch); - if( !handle.isValid() ) - { - XML_WARNING("%s: invalid path", scratch); - DEBUG_ALWAYS_ASSERT(); -// mError = Serializer::ERROR_INVALID_PARAM_HANDLE; - return true; - } - - const char *type = attr.get("type"); - const char *expectedType = typeToStr(handle.parameterDefinition()->type()); - if ( type && 0 != physx::shdfnd::stricmp(type, expectedType) ) - { - XML_WARNING("%s: invalid type %s (expected %s)", scratch, type, expectedType); - DEBUG_ALWAYS_ASSERT(); - mError = Serializer::ERROR_INVALID_ATTR; - return false; - } - - const char *included = attr.get("included"); - if ( included ) - { - bool isIncludedRef = 0 != atoi(included); - if( isIncludedRef != handle.parameterDefinition()->isIncludedRef() ) - { - XML_WARNING("%s: unexpected included-attribute", scratch); - DEBUG_ALWAYS_ASSERT(); - mError = Serializer::ERROR_INVALID_ATTR; - return false; - } - - const char *className = attr.get("className"); - if( !className ) - { - if( attr.get("classNames") ) - { - // Ref is NULL - - Interface *oldObj = 0; - if( NvParameterized::ERROR_NONE != handle.getParamRef(oldObj) ) - return false; - if( oldObj ) - oldObj->destroy(); - - handle.setParamRef(0); - - return true; - } - else - { - XML_WARNING("%s: missing both className and classNames attribute", scratch); - DEBUG_ALWAYS_ASSERT(); - mError = Serializer::ERROR_INVALID_ATTR; - return false; - } - } - - uint32_t version = ReadVersion(attr); - - Interface *refObj = 0; - if( isIncludedRef ) - refObj = mTraits->createNvParameterized(className, version); - else - { - void *buf = mTraits->alloc(sizeof(NvParameters)); - refObj = PX_PLACEMENT_NEW(buf, NvParameters)(mTraits); - - refObj->setClassName(className); - } - - if( !refObj ) - { - XML_WARNING("%s: failed to create object of type %s and version %u", scratch, className, (unsigned)version); - DEBUG_ALWAYS_ASSERT(); - mError = Serializer::ERROR_OBJECT_CREATION_FAILED; - return false; - } - - if( refObj && (-1 == handle.parameterDefinition()->refVariantValIndex(refObj->className())) ) - { - char longName[256]; - handle.getLongName(longName, sizeof(longName)); - NV_PARAM_TRAITS_WARNING( - mTraits, - "%s: setting reference of invalid class %s", - longName, - refObj->className() - ); - } - - if( NvParameterized::ERROR_NONE != handle.setParamRef(refObj) ) - { - XML_WARNING("%s: failed to set reference of type %s", scratch, className); - DEBUG_ALWAYS_ASSERT(); - mError = Serializer::ERROR_INVALID_REFERENCE; - return false; - } - - const char *objectName = attr.get("objectName"); - if( objectName && refObj ) - refObj->setName(objectName); - - if( isIncludedRef ) - pushObj(refObj); - else if ( elementData && refObj ) - refObj->setName(elementData); - } - else - { - if ( elementData == 0 ) - elementData = ""; - - const char *isNull = attr.get("null"); - if( isNull && 0 != atoi(isNull) ) - { - //Only strings and enums may be NULL so it's safe to call setParamString - - DataType t = handle.parameterDefinition()->type(); - PX_UNUSED(t); - DEBUG_ASSERT( TYPE_STRING == t || TYPE_ENUM == t ); - - handle.setParamString(0); - } - else - { - if( NvParameterized::ERROR_NONE != handle.strToValue(elementData, 0) ) - { - XML_WARNING("%s: failed to convert string to value: %10s", scratch, elementData); - DEBUG_ALWAYS_ASSERT(); - mError = Serializer::ERROR_STRING2VAL_FAILED; - return false; - } - } - } //if ( included ) - } - else if ( strcmp(elementName, "array") == 0 ) - { - const char *name = attr.get("name"); - - if( !mObjIndex ) - { - XML_WARNING("array-element %s not under value-element", name); - DEBUG_ALWAYS_ASSERT(); - mError = Serializer::ERROR_INVALID_NESTING; - return false; - } - - int32_t arraySize = 0; - if ( const char *sz = attr.get("size") ) - { - PX_ASSERT(atoi(sz) >= 0); - arraySize = (int32_t)atoi(sz); - } - - if ( arraySize > 0 ) - { - Interface *obj = tos().getObject(); - if( !obj ) - { - XML_WARNING("unknown error"); - DEBUG_ALWAYS_ASSERT(); - mError = Serializer::ERROR_UNKNOWN; - return false; - } - - char scratch[2048]; - if( !initAddressString(scratch, sizeof(scratch), name) ) - { - return false; - } - - Handle handle(*obj, scratch); - if( !handle.isValid() ) - { - - mError = Serializer::ERROR_INVALID_PARAM_HANDLE; - XML_WARNING("%s: invalid path", scratch); - DEBUG_ALWAYS_ASSERT(); - - return false; - } - - if( !handle.parameterDefinition()->arraySizeIsFixed() ) - if( NvParameterized::ERROR_NONE != handle.resizeArray(arraySize) ) - { - XML_WARNING("%s: failed to resize array", scratch); - DEBUG_ALWAYS_ASSERT(); - mError = Serializer::ERROR_INVALID_ARRAY; - return false; - } - if ( elementData ) - { - const char *scan = elementData; - - handle.set(0); - const Definition *paramDef = handle.parameterDefinition(); - handle.popIndex(); - - - if ( paramDef->type() == TYPE_STRUCT ) - { - // read the structElements field - const char* structElements = attr.get("structElements"); - - int32_t* simpleStructRedirect = getSimpleStructRedirect(static_cast<uint32_t>(paramDef->numChildren())); - uint32_t numRedirects = 0; - while (structElements && *structElements) - { - char fieldName[64]; - char type[16]; - - size_t count = 0; - while(*structElements != 0 && *structElements != ',' && *structElements != '(') - fieldName[count++] = *structElements++; - if( count >= sizeof(fieldName) ) - { - DEBUG_ALWAYS_ASSERT(); - mError = Serializer::ERROR_INTERNAL_BUFFER_OVERFLOW; - return false; - } - fieldName[count] = 0; - - if (*structElements == '(') - { - structElements++; - count = 0; - while(*structElements != 0 && *structElements != ',' && *structElements != ')') - type[count++] = *structElements++; - if( count >= sizeof(type) ) - { - DEBUG_ALWAYS_ASSERT(); - mError = Serializer::ERROR_INTERNAL_BUFFER_OVERFLOW; - return false; - } - type[count] = 0; - - } - if (*structElements == ')') - structElements++; - if (*structElements == ',') - structElements++; - - const Definition* childDef = paramDef->child(fieldName, simpleStructRedirect[numRedirects]); - const char* trueType = childDef ? typeToStr(childDef->type()) : 0; - if (childDef && ::strcmp(trueType, type) != 0) - { - XML_WARNING( - "%s[].%s: unexpected type: %s (must be %s)", - scratch, fieldName, type, trueType ? trueType : ""); - DEBUG_ALWAYS_ASSERT(); - mError = Serializer::ERROR_INVALID_DATA_TYPE; - return false; - } - - // -2 means to reed the data but not storing it - // -1 means to not read the data as it was not serialized' - // i = [0 .. n] means to read the data and store it in child i - if (childDef == NULL) - { - simpleStructRedirect[numRedirects] = -2; - - // Fail fast - XML_WARNING("%s[]: unexpected structure field: %s", scratch, fieldName); - DEBUG_ALWAYS_ASSERT(); - mError = Serializer::ERROR_INVALID_PARAM_HANDLE; - return false; - } - - numRedirects++; - } - - const int32_t numChildren = paramDef->numChildren(); - for(int32_t i = 0; i < arraySize; ++i) - { - handle.set(i); - for( int32_t j=0; j<numChildren; j++ ) - { - if (simpleStructRedirect[j] < 0) - { - if (simpleStructRedirect[j] < -1) - { - // read the data anyways - scan = skipWhiteSpace(scan); - if (scan != NULL) - scan = skipNonWhiteSpace(scan); - } - continue; - } - - scan = skipWhiteSpace(scan); - if ( !scan ) break; - - handle.set(simpleStructRedirect[j]); - - if( NvParameterized::ERROR_NONE != handle.strToValue(scan, &scan) ) - { - XML_WARNING("%s: failed to convert string to value: %10s...", scan); - DEBUG_ALWAYS_ASSERT(); - mError = Serializer::ERROR_STRING2VAL_FAILED; - return false; - } - - handle.popIndex(); - if ( !scan ) break; - } - handle.popIndex(); - if ( !scan ) break; - } - } - else - { - // LRR: wall clock time is the same for this simple loop as the previous - // "unrolled" version - for (int32_t i = 0; i<arraySize; i++) - { - handle.set(i); - if( NvParameterized::ERROR_NONE != handle.strToValue(scan, &scan) ) - { - XML_WARNING("%s: failed to convert string to value: %10s", scratch, scan); - DEBUG_ALWAYS_ASSERT(); - mError = Serializer::ERROR_STRING2VAL_FAILED; - return false; - } - handle.popIndex(); - } - } - } //if( elementData ) - } //if ( arraySize > 0 ) - - pushField(name, ARRAY); - } - else - { - XML_WARNING("unknown element %s", elementName); - DEBUG_ALWAYS_ASSERT(); - mError = Serializer::ERROR_UNKNOWN_XML_TAG; - return false; - } - - return true; - } - - int32_t* XmlDeserializer::getSimpleStructRedirect(uint32_t size) - { - if (mSimpleStructRedirectSize < size) - { - if (mSimpleStructRedirect != NULL) - mTraits->free(mSimpleStructRedirect); - - if (size < 16) - size = 16; // just to not allocate all these small things more than once - - mSimpleStructRedirect = (int32_t*)mTraits->alloc(sizeof(int32_t) * size); - mSimpleStructRedirectSize = size; - } - - memset(mSimpleStructRedirect, -1, sizeof(int32_t) * size); - return mSimpleStructRedirect; - } - -} +// This code contains NVIDIA Confidential Information and is disclosed to you
+// under a form of NVIDIA software license agreement provided separately to you.
+//
+// Notice
+// NVIDIA Corporation and its licensors retain all intellectual property and
+// proprietary rights in and to this software and related documentation and
+// any modifications thereto. Any use, reproduction, disclosure, or
+// distribution of this software and related documentation without an express
+// license agreement from NVIDIA Corporation is strictly prohibited.
+//
+// ALL NVIDIA DESIGN SPECIFICATIONS, CODE ARE PROVIDED "AS IS.". NVIDIA MAKES
+// NO WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO
+// THE MATERIALS, AND EXPRESSLY DISCLAIMS ALL IMPLIED WARRANTIES OF NONINFRINGEMENT,
+// MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE.
+//
+// Information and code furnished is believed to be accurate and reliable.
+// However, NVIDIA Corporation assumes no responsibility for the consequences of use of such
+// information or for any infringement of patents or other rights of third parties that may
+// result from its use. No license is granted by implication or otherwise under any patent
+// or patent rights of NVIDIA Corporation. Details are subject to change without notice.
+// This code supersedes and replaces all information previously supplied.
+// NVIDIA Corporation products are not authorized for use as critical
+// components in life support devices or systems without express written approval of
+// NVIDIA Corporation.
+//
+// Copyright (c) 2008-2013 NVIDIA Corporation. All rights reserved.
+
+#include "PxSimpleTypes.h"
+#include "NvParameters.h"
+#include "nvparameterized/NvParameterizedTraits.h"
+
+#include "NvTraitsInternal.h"
+
+#include "XmlDeserializer.h"
+
+#define XML_WARNING(_format, ...) \
+ NV_PARAM_TRAITS_WARNING(mTraits, "XML serializer: " _format, ##__VA_ARGS__)
+
+
+
+namespace NvParameterized
+{
+
+/*!
+Get number of elements in array
+*/
+template <typename T, size_t N>
+char (&ArraySizeHelper(T (&array)[N]))[N];
+#define PX_ARRAY_SIZE(_array) (sizeof(ArraySizeHelper(_array)))
+
+ static uint32_t ReadVersion(const physx::shdfnd::FastXml::AttributePairs& attr)
+ {
+ const char *versionText = attr.get("version");
+
+ // If there's no version, assume version is 0.0
+ if( !versionText )
+ return 0;
+
+ //XML stores versions in "x.y"-format
+ //FIXME: strtoul is unsafe
+
+ const char *dot = strchr(versionText, '.');
+ uint32_t minor = dot ? strtoul(dot + 1, 0, 10) : 0;
+
+ uint32_t major = strtoul(versionText, 0, 10);
+
+ return (major << 16) + minor;
+ }
+
+ static PX_INLINE bool isWhiteSpace(char c)
+ {
+ return c == ' ' || c == '\t' || c == '\r' || c == '\n' || c == ',';
+ }
+
+ static PX_INLINE const char * skipWhiteSpace(const char *scan)
+ {
+ while ( isWhiteSpace(*scan) && *scan ) scan++;
+ return *scan ? scan : 0;
+ }
+
+ static PX_FORCE_INLINE const char * skipNonWhiteSpace(const char* scan)
+ {
+ while ( !isWhiteSpace(*scan) && *scan ) scan++;
+ return *scan ? scan : 0;
+ }
+
+ bool XmlDeserializer::verifyObject(Interface *obj, const physx::shdfnd::FastXml::AttributePairs& attr)
+ {
+ if( ReadVersion(attr) != obj->version() )
+ {
+ XML_WARNING("unknown error");
+ DEBUG_ALWAYS_ASSERT();
+ mError = Serializer::ERROR_UNKNOWN;
+ return false;
+ }
+
+ char *checksum = (char *)attr.get("checksum");
+ if( checksum && !DoIgnoreChecksum(*obj) )
+ {
+ uint32_t objBits;
+ const uint32_t *objChecksum = obj->checksum(objBits);
+
+ uint32_t bits = 0;
+
+ char *cur = checksum, *next = 0;
+ bool sameBits = true;
+ for(uint32_t i = 0; ; ++i, cur = next)
+ {
+ uint32_t val = (uint32_t)strtoul(cur, &next, 0); //FIXME: strtoul is not safe
+ if( cur == next )
+ break;
+
+ bits += 32;
+ if( bits > objBits || val != objChecksum[i] )
+ {
+ NV_PARAM_TRAITS_WARNING(
+ mTraits,
+ "Schema checksum is different for object of class %s and version %u, "
+ "asset may be corrupted",
+ obj->className(),
+ (unsigned)obj->version()
+ );
+ sameBits = false;
+ break;
+ }
+ }
+
+ if( objBits != bits && sameBits )
+ {
+ NV_PARAM_TRAITS_WARNING(
+ mTraits,
+ "Schema checksum is different for object of class %s and version %u, "
+ "asset may be corrupted",
+ obj->className(),
+ (unsigned)obj->version()
+ );
+ }
+ } //if( checksum )
+
+ return true;
+ }
+
+ bool XmlDeserializer::initAddressString(char *dest, uint32_t len, const char *name)
+ {
+ char *end = dest + len;
+
+ for (uint32_t i = 0; i < tos().getIndex(); i++)
+ {
+ FieldInfo &field = tos().getFieldInfo(i);
+
+ const char *n = field.name;
+ FieldType type = field.type;
+
+ if( SKIP == type )
+ continue;
+
+ while ( n && *n && dest < end )
+ *dest++ = *n++;
+
+ if ( ARRAY == type )
+ {
+ char temp[512];
+ physx::shdfnd::snprintf(temp, 512, "[%d]", field.idx);
+
+ if( dest + ::strlen(temp) >= end )
+ {
+ XML_WARNING("buffer overflow");
+ DEBUG_ALWAYS_ASSERT();
+ mError = Serializer::ERROR_INTERNAL_BUFFER_OVERFLOW;
+ return false;
+ }
+
+ const char *scan = temp;
+ while ( *scan && dest < end )
+ {
+ *dest++ = *scan++;
+ }
+ }
+ else
+ {
+ if( dest + 1 >= end )
+ {
+ XML_WARNING("buffer overflow");
+ DEBUG_ALWAYS_ASSERT();
+ mError = Serializer::ERROR_INTERNAL_BUFFER_OVERFLOW;
+ return false;
+ }
+
+ *dest++ = '.';
+ }
+ }
+
+ while ( name && *name && dest < end )
+ {
+ *dest++ = *name++;
+ }
+
+ *dest = 0;
+ //printf("Fully qualified name: %s\n", scratch );
+
+ return true;
+ }
+
+ bool XmlDeserializer::processClose(const char *tag,uint32_t depth,bool &isError)
+ {
+ isError = true; //By default if we return with false it's due to error
+
+ if( strcmp(tag, "NxParameters") == 0 ||
+ strcmp(tag, "NvParameters") == 0)
+ {
+ mInRootElement = false;
+
+ // in xml there's only 1 root element allowed,
+ // so we want to stop after the first NvParameters
+ isError = false;
+ return false;
+ }
+
+ static const char *validTags[] = {
+ "struct",
+ "value",
+ "array"
+ };
+
+ for(uint32_t i = 0; i < PX_ARRAY_SIZE(validTags); ++i)
+ {
+ if( 0 != ::strcmp(validTags[i], tag) )
+ continue;
+
+# ifndef NDEBUG
+ uint32_t idx = tos().getIndex();
+ DEBUG_ASSERT( idx > 0 );
+
+ static FieldType validTypes[] = {
+ STRUCT,
+ VALUE,
+ ARRAY
+ };
+
+ // Make gcc happy
+ const FieldType* tmp = &validTypes[0];
+ PX_UNUSED(tmp);
+
+ FieldType type = tos().getFieldInfo(idx - 1).type;
+ PX_UNUSED(type);
+ DEBUG_ASSERT( type == SKIP || type == validTypes[i] );
+# endif
+
+ if( !popField() )
+ return false;
+
+ if (depth == 1 && mRootIndex > MAX_ROOT_OBJ)
+ {
+ DEBUG_ASSERT(i == 1);
+ mObjects[0].getObject()->destroy();
+ }
+
+ return tos().getIndex() ? depth != 0 : popObj();
+ }
+
+ return false;
+ }
+
+ bool XmlDeserializer::processElement(
+ const char *elementName,
+ const char *elementData,
+ const physx::shdfnd::FastXml::AttributePairs& attr,
+ int32_t /*lineno*/)
+ {
+ //Force DOCTYPE
+ if( !mHasDoctype )
+ {
+ XML_WARNING("DOCTYPE is missing");
+ DEBUG_ALWAYS_ASSERT();
+ mError = Serializer::ERROR_MISSING_DOCTYPE;
+ return false;
+ }
+
+ if( strcmp(elementName, "NxParameters") == 0 ||
+ strcmp(elementName, "NvParameters") == 0)
+ {
+ if( mObjIndex )
+ {
+ XML_WARNING("NvParameters must be root element");
+ DEBUG_ALWAYS_ASSERT();
+ mError = Serializer::ERROR_MISSING_ROOT_ELEMENT;
+ return false;
+ }
+
+ if( mInRootElement )
+ {
+ XML_WARNING("More than one root element encountered");
+ DEBUG_ALWAYS_ASSERT();
+ mError = Serializer::ERROR_INVALID_NESTING;
+ return false;
+ }
+
+ uint32_t ver = ReadVersion(attr);
+ if( ver != mVer )
+ {
+ XML_WARNING("unknown version of APX file format: %u", (unsigned)ver);
+ DEBUG_ALWAYS_ASSERT();
+ mError = Serializer::ERROR_INVALID_FILE_VERSION;
+ return false;
+ }
+
+ const char* numObjects = attr.get("numObjects");
+ if (numObjects != NULL)
+ {
+ PX_ASSERT(atoi(numObjects) >= 0);
+ const uint32_t num = static_cast<uint32_t>(atoi(numObjects));
+ if (num > MAX_ROOT_OBJ)
+ {
+ XML_WARNING("APX file has more than %d root objects, only %d will be read", num, MAX_ROOT_OBJ);
+ }
+ }
+
+
+ ++mRootTags;
+ mInRootElement = true;
+
+ return true;
+ }
+
+ if( mRootTags > 0 && !mInRootElement )
+ {
+ XML_WARNING("element %s not under root element", elementName);
+ DEBUG_ALWAYS_ASSERT();
+ mError = Serializer::ERROR_MISSING_ROOT_ELEMENT;
+ return false;
+ }
+
+ if ( strcmp(elementName, "struct") == 0 )
+ {
+ const char *name = attr.get("name");
+
+ if( !mObjIndex )
+ {
+ XML_WARNING("struct-element %s not under value-element", name);
+ DEBUG_ALWAYS_ASSERT();
+ mError = Serializer::ERROR_INVALID_NESTING;
+ return false;
+ }
+
+ pushField(name, STRUCT);
+ }
+ else if ( strcmp(elementName, "value") == 0 )
+ {
+ if( !mObjIndex ) //Root object?
+ {
+ const char *className = attr.get("className");
+
+ uint32_t version = ReadVersion(attr);
+
+ Interface *obj = mTraits->createNvParameterized(className, version);
+ if( !obj )
+ {
+ XML_WARNING("failed to create object of type %s and version %u", className, (unsigned)version);
+ DEBUG_ALWAYS_ASSERT();
+ mError = Serializer::ERROR_OBJECT_CREATION_FAILED;
+ return false;
+ }
+
+ const char *objectName = attr.get("objectName");
+ if( objectName )
+ obj->setName(objectName);
+
+ if (mRootIndex < MAX_ROOT_OBJ)
+ {
+ mRootObjs[mRootIndex] = obj;
+ }
+ mRootIndex++;
+
+ pushObj(obj);
+ pushField("", SKIP); //Root <value> should not be used in initAddressString
+
+ return true;
+ }
+
+ const char *name = attr.get("name");
+
+ char scratch[2048];
+ if( !initAddressString(scratch, sizeof(scratch), name) )
+ {
+ return false;
+ }
+
+ pushField(name, VALUE);
+
+ Interface *obj = tos().getObject();
+ if( !obj )
+ {
+ XML_WARNING("unknown error");
+ DEBUG_ALWAYS_ASSERT();
+ mError = Serializer::ERROR_UNKNOWN;
+ return false;
+ }
+
+ Handle handle(*obj, scratch);
+ if( !handle.isValid() )
+ {
+ XML_WARNING("%s: invalid path", scratch);
+ DEBUG_ALWAYS_ASSERT();
+// mError = Serializer::ERROR_INVALID_PARAM_HANDLE;
+ return true;
+ }
+
+ const char *type = attr.get("type");
+ const char *expectedType = typeToStr(handle.parameterDefinition()->type());
+ if ( type && 0 != physx::shdfnd::stricmp(type, expectedType) )
+ {
+ XML_WARNING("%s: invalid type %s (expected %s)", scratch, type, expectedType);
+ DEBUG_ALWAYS_ASSERT();
+ mError = Serializer::ERROR_INVALID_ATTR;
+ return false;
+ }
+
+ const char *included = attr.get("included");
+ if ( included )
+ {
+ bool isIncludedRef = 0 != atoi(included);
+ if( isIncludedRef != handle.parameterDefinition()->isIncludedRef() )
+ {
+ XML_WARNING("%s: unexpected included-attribute", scratch);
+ DEBUG_ALWAYS_ASSERT();
+ mError = Serializer::ERROR_INVALID_ATTR;
+ return false;
+ }
+
+ const char *className = attr.get("className");
+ if( !className )
+ {
+ if( attr.get("classNames") )
+ {
+ // Ref is NULL
+
+ Interface *oldObj = 0;
+ if( NvParameterized::ERROR_NONE != handle.getParamRef(oldObj) )
+ return false;
+ if( oldObj )
+ oldObj->destroy();
+
+ handle.setParamRef(0);
+
+ return true;
+ }
+ else
+ {
+ XML_WARNING("%s: missing both className and classNames attribute", scratch);
+ DEBUG_ALWAYS_ASSERT();
+ mError = Serializer::ERROR_INVALID_ATTR;
+ return false;
+ }
+ }
+
+ uint32_t version = ReadVersion(attr);
+
+ Interface *refObj = 0;
+ if( isIncludedRef )
+ refObj = mTraits->createNvParameterized(className, version);
+ else
+ {
+ void *buf = mTraits->alloc(sizeof(NvParameters));
+ refObj = PX_PLACEMENT_NEW(buf, NvParameters)(mTraits);
+
+ refObj->setClassName(className);
+ }
+
+ if( !refObj )
+ {
+ XML_WARNING("%s: failed to create object of type %s and version %u", scratch, className, (unsigned)version);
+ DEBUG_ALWAYS_ASSERT();
+ mError = Serializer::ERROR_OBJECT_CREATION_FAILED;
+ return false;
+ }
+
+ if( refObj && (-1 == handle.parameterDefinition()->refVariantValIndex(refObj->className())) )
+ {
+ char longName[256];
+ handle.getLongName(longName, sizeof(longName));
+ NV_PARAM_TRAITS_WARNING(
+ mTraits,
+ "%s: setting reference of invalid class %s",
+ longName,
+ refObj->className()
+ );
+ }
+
+ if( NvParameterized::ERROR_NONE != handle.setParamRef(refObj) )
+ {
+ XML_WARNING("%s: failed to set reference of type %s", scratch, className);
+ DEBUG_ALWAYS_ASSERT();
+ mError = Serializer::ERROR_INVALID_REFERENCE;
+ return false;
+ }
+
+ const char *objectName = attr.get("objectName");
+ if( objectName && refObj )
+ refObj->setName(objectName);
+
+ if( isIncludedRef )
+ pushObj(refObj);
+ else if ( elementData && refObj )
+ refObj->setName(elementData);
+ }
+ else
+ {
+ if ( elementData == 0 )
+ elementData = "";
+
+ const char *isNull = attr.get("null");
+ if( isNull && 0 != atoi(isNull) )
+ {
+ //Only strings and enums may be NULL so it's safe to call setParamString
+
+ DataType t = handle.parameterDefinition()->type();
+ PX_UNUSED(t);
+ DEBUG_ASSERT( TYPE_STRING == t || TYPE_ENUM == t );
+
+ handle.setParamString(0);
+ }
+ else
+ {
+ if( NvParameterized::ERROR_NONE != handle.strToValue(elementData, 0) )
+ {
+ XML_WARNING("%s: failed to convert string to value: %10s", scratch, elementData);
+ DEBUG_ALWAYS_ASSERT();
+ mError = Serializer::ERROR_STRING2VAL_FAILED;
+ return false;
+ }
+ }
+ } //if ( included )
+ }
+ else if ( strcmp(elementName, "array") == 0 )
+ {
+ const char *name = attr.get("name");
+
+ if( !mObjIndex )
+ {
+ XML_WARNING("array-element %s not under value-element", name);
+ DEBUG_ALWAYS_ASSERT();
+ mError = Serializer::ERROR_INVALID_NESTING;
+ return false;
+ }
+
+ int32_t arraySize = 0;
+ if ( const char *sz = attr.get("size") )
+ {
+ PX_ASSERT(atoi(sz) >= 0);
+ arraySize = (int32_t)atoi(sz);
+ }
+
+ if ( arraySize > 0 )
+ {
+ Interface *obj = tos().getObject();
+ if( !obj )
+ {
+ XML_WARNING("unknown error");
+ DEBUG_ALWAYS_ASSERT();
+ mError = Serializer::ERROR_UNKNOWN;
+ return false;
+ }
+
+ char scratch[2048];
+ if( !initAddressString(scratch, sizeof(scratch), name) )
+ {
+ return false;
+ }
+
+ Handle handle(*obj, scratch);
+ if( !handle.isValid() )
+ {
+
+ mError = Serializer::ERROR_INVALID_PARAM_HANDLE;
+ XML_WARNING("%s: invalid path", scratch);
+ DEBUG_ALWAYS_ASSERT();
+
+ return false;
+ }
+
+ if( !handle.parameterDefinition()->arraySizeIsFixed() )
+ if( NvParameterized::ERROR_NONE != handle.resizeArray(arraySize) )
+ {
+ XML_WARNING("%s: failed to resize array", scratch);
+ DEBUG_ALWAYS_ASSERT();
+ mError = Serializer::ERROR_INVALID_ARRAY;
+ return false;
+ }
+ if ( elementData )
+ {
+ const char *scan = elementData;
+
+ handle.set(0);
+ const Definition *paramDef = handle.parameterDefinition();
+ handle.popIndex();
+
+
+ if ( paramDef->type() == TYPE_STRUCT )
+ {
+ // read the structElements field
+ const char* structElements = attr.get("structElements");
+
+ int32_t* simpleStructRedirect = getSimpleStructRedirect(static_cast<uint32_t>(paramDef->numChildren()));
+ uint32_t numRedirects = 0;
+ while (structElements && *structElements)
+ {
+ char fieldName[64];
+ char type[16];
+
+ size_t count = 0;
+ while(*structElements != 0 && *structElements != ',' && *structElements != '(')
+ fieldName[count++] = *structElements++;
+ if( count >= sizeof(fieldName) )
+ {
+ DEBUG_ALWAYS_ASSERT();
+ mError = Serializer::ERROR_INTERNAL_BUFFER_OVERFLOW;
+ return false;
+ }
+ fieldName[count] = 0;
+
+ if (*structElements == '(')
+ {
+ structElements++;
+ count = 0;
+ while(*structElements != 0 && *structElements != ',' && *structElements != ')')
+ type[count++] = *structElements++;
+ if( count >= sizeof(type) )
+ {
+ DEBUG_ALWAYS_ASSERT();
+ mError = Serializer::ERROR_INTERNAL_BUFFER_OVERFLOW;
+ return false;
+ }
+ type[count] = 0;
+
+ }
+ if (*structElements == ')')
+ structElements++;
+ if (*structElements == ',')
+ structElements++;
+
+ const Definition* childDef = paramDef->child(fieldName, simpleStructRedirect[numRedirects]);
+ const char* trueType = childDef ? typeToStr(childDef->type()) : 0;
+ if (childDef && ::strcmp(trueType, type) != 0)
+ {
+ XML_WARNING(
+ "%s[].%s: unexpected type: %s (must be %s)",
+ scratch, fieldName, type, trueType ? trueType : "");
+ DEBUG_ALWAYS_ASSERT();
+ mError = Serializer::ERROR_INVALID_DATA_TYPE;
+ return false;
+ }
+
+ // -2 means to reed the data but not storing it
+ // -1 means to not read the data as it was not serialized'
+ // i = [0 .. n] means to read the data and store it in child i
+ if (childDef == NULL)
+ {
+ simpleStructRedirect[numRedirects] = -2;
+
+ // Fail fast
+ XML_WARNING("%s[]: unexpected structure field: %s", scratch, fieldName);
+ DEBUG_ALWAYS_ASSERT();
+ mError = Serializer::ERROR_INVALID_PARAM_HANDLE;
+ return false;
+ }
+
+ numRedirects++;
+ }
+
+ const int32_t numChildren = paramDef->numChildren();
+ for(int32_t i = 0; i < arraySize; ++i)
+ {
+ handle.set(i);
+ for( int32_t j=0; j<numChildren; j++ )
+ {
+ if (simpleStructRedirect[j] < 0)
+ {
+ if (simpleStructRedirect[j] < -1)
+ {
+ // read the data anyways
+ scan = skipWhiteSpace(scan);
+ if (scan != NULL)
+ scan = skipNonWhiteSpace(scan);
+ }
+ continue;
+ }
+
+ scan = skipWhiteSpace(scan);
+ if ( !scan ) break;
+
+ handle.set(simpleStructRedirect[j]);
+
+ if( NvParameterized::ERROR_NONE != handle.strToValue(scan, &scan) )
+ {
+ XML_WARNING("%s: failed to convert string to value: %10s...", scan);
+ DEBUG_ALWAYS_ASSERT();
+ mError = Serializer::ERROR_STRING2VAL_FAILED;
+ return false;
+ }
+
+ handle.popIndex();
+ if ( !scan ) break;
+ }
+ handle.popIndex();
+ if ( !scan ) break;
+ }
+ }
+ else
+ {
+ // LRR: wall clock time is the same for this simple loop as the previous
+ // "unrolled" version
+ for (int32_t i = 0; i<arraySize; i++)
+ {
+ handle.set(i);
+ if( NvParameterized::ERROR_NONE != handle.strToValue(scan, &scan) )
+ {
+ XML_WARNING("%s: failed to convert string to value: %10s", scratch, scan);
+ DEBUG_ALWAYS_ASSERT();
+ mError = Serializer::ERROR_STRING2VAL_FAILED;
+ return false;
+ }
+ handle.popIndex();
+ }
+ }
+ } //if( elementData )
+ } //if ( arraySize > 0 )
+
+ pushField(name, ARRAY);
+ }
+ else
+ {
+ XML_WARNING("unknown element %s", elementName);
+ DEBUG_ALWAYS_ASSERT();
+ mError = Serializer::ERROR_UNKNOWN_XML_TAG;
+ return false;
+ }
+
+ return true;
+ }
+
+ int32_t* XmlDeserializer::getSimpleStructRedirect(uint32_t size)
+ {
+ if (mSimpleStructRedirectSize < size)
+ {
+ if (mSimpleStructRedirect != NULL)
+ mTraits->free(mSimpleStructRedirect);
+
+ if (size < 16)
+ size = 16; // just to not allocate all these small things more than once
+
+ mSimpleStructRedirect = (int32_t*)mTraits->alloc(sizeof(int32_t) * size);
+ mSimpleStructRedirectSize = size;
+ }
+
+ memset(mSimpleStructRedirect, -1, sizeof(int32_t) * size);
+ return mSimpleStructRedirect;
+ }
+
+}
|