Initial commit

This commit is contained in:
alexpete
2021-03-05 11:26:34 -08:00
commit a10351f38d
27091 changed files with 5521199 additions and 0 deletions
@@ -0,0 +1,239 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
// Original file Copyright Crytek GMBH or its affiliates, used under license.
#include "CrySystem_precompiled.h"
#include <Serialization/IArchiveHost.h>
#include "JSONIArchive.h"
#include "JSONOArchive.h"
#include "BinArchive.h"
#include "XmlIArchive.h"
#include "XmlOArchive.h"
#include <Serialization/ClassFactoryImpl.h>
namespace Serialization
{
bool LoadFile(std::vector<char>& content, const char* filename)
{
AZ::IO::HandleType fileHandle = gEnv->pCryPak->FOpen(filename, "rb");
if (!fileHandle)
{
return false;
}
gEnv->pCryPak->FSeek(fileHandle, 0, SEEK_END);
size_t size = gEnv->pCryPak->FTell(fileHandle);
gEnv->pCryPak->FSeek(fileHandle, 0, SEEK_SET);
content.resize(size);
bool result = true;
if (size != 0)
{
result = gEnv->pCryPak->FRead(&content[0], size, fileHandle) == size;
}
gEnv->pCryPak->FClose(fileHandle);
return result;
}
class CArchiveHost
: public IArchiveHost
{
public:
bool LoadJsonFile(const SStruct& obj, const char* filename) override
{
std::vector<char> content;
if (!LoadFile(content, filename))
{
return false;
}
JSONIArchive ia;
if (!ia.open(content.data(), content.size()))
{
return false;
}
return ia(obj);
}
bool SaveJsonFile(const char* gameFilename, const SStruct& obj) override
{
char buffer[AZ::IO::IArchive::MaxPath];
const char* filename = gEnv->pCryPak->AdjustFileName(gameFilename, buffer, AZ_ARRAY_SIZE(buffer), AZ::IO::IArchive::FLAGS_FOR_WRITING);
JSONOArchive oa;
if (!oa(obj))
{
return false;
}
return oa.save(filename);
}
bool LoadJsonBuffer(const SStruct& obj, const char* buffer, size_t bufferLength) override
{
if (bufferLength == 0)
{
return false;
}
JSONIArchive ia;
if (!ia.open(buffer, bufferLength))
{
return false;
}
return ia(obj);
}
bool SaveJsonBuffer(DynArray<char>& buffer, const SStruct& obj) override
{
JSONOArchive oa;
if (!oa(obj))
{
return false;
}
buffer.assign(oa.buffer(), oa.buffer() + oa.length());
return true;
}
bool LoadBinaryFile(const SStruct& obj, const char* filename) override
{
std::vector<char> content;
if (!LoadFile(content, filename))
{
return false;
}
BinIArchive ia;
if (!ia.open(content.data(), content.size()))
{
return false;
}
return ia(obj);
}
bool SaveBinaryFile(const char* gameFilename, const SStruct& obj) override
{
char buffer[AZ::IO::IArchive::MaxPath];
const char* filename = gEnv->pCryPak->AdjustFileName(gameFilename, buffer, AZ_ARRAY_SIZE(buffer), AZ::IO::IArchive::FLAGS_FOR_WRITING);
BinOArchive oa;
obj(oa);
return oa.save(filename);
}
bool LoadBinaryBuffer(const SStruct& obj, const char* buffer, size_t bufferLength) override
{
if (bufferLength == 0)
{
return false;
}
BinIArchive ia;
if (!ia.open(buffer, bufferLength))
{
return false;
}
return ia(obj);
}
bool SaveBinaryBuffer(DynArray<char>& buffer, const SStruct& obj) override
{
BinOArchive oa;
obj(oa);
buffer.assign(oa.buffer(), oa.buffer() + oa.length());
return true;
}
bool CloneBinary(const SStruct& dest, const SStruct& src) override
{
BinOArchive oa;
src(oa);
BinIArchive ia;
if (!ia.open(oa.buffer(), oa.length()))
{
return false;
}
dest(ia);
return true;
}
bool CompareBinary(const SStruct& lhs, const SStruct& rhs) override
{
BinOArchive oa1;
lhs(oa1);
BinOArchive oa2;
rhs(oa2);
if (oa1.length() != oa2.length())
{
return false;
}
return memcmp(oa1.buffer(), oa2.buffer(), oa1.length()) == 0;
}
bool SaveXmlFile(const char* filename, const SStruct& obj, const char* rootNodeName) override
{
XmlNodeRef node = SaveXmlNode(obj, rootNodeName);
if (!node)
{
return false;
}
return node->saveToFile(filename);
}
bool LoadXmlFile(const SStruct& obj, const char* filename) override
{
XmlNodeRef node = gEnv->pSystem->LoadXmlFromFile(filename);
if (!node)
{
return false;
}
return LoadXmlNode(obj, node);
}
XmlNodeRef SaveXmlNode(const SStruct& obj, const char* nodeName) override
{
CXmlOArchive oa;
XmlNodeRef node = gEnv->pSystem->CreateXmlNode(nodeName);
if (!node)
{
return XmlNodeRef();
}
oa.SetXmlNode(node);
if (!obj(oa))
{
return XmlNodeRef();
}
return oa.GetXmlNode();
}
bool SaveXmlNode(XmlNodeRef& node, const SStruct& obj) override
{
if (!node)
{
return false;
}
CXmlOArchive oa;
oa.SetXmlNode(node);
return obj(oa);
}
bool LoadXmlNode(const SStruct& obj, const XmlNodeRef& node) override
{
CXmlIArchive ia;
ia.SetXmlNode(node);
if (!obj(ia))
{
return false;
}
return true;
}
};
IArchiveHost* CreateArchiveHost()
{
return new CArchiveHost;
}
}
@@ -0,0 +1,21 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
// Original file Copyright Crytek GMBH or its affiliates, used under license.
#pragma once
#include <Serialization/IArchiveHost.h>
namespace Serialization
{
IArchiveHost* CreateArchiveHost();
}
@@ -0,0 +1,839 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
// Original file Copyright Crytek GMBH or its affiliates, used under license.
#include "CrySystem_precompiled.h"
#include "BinArchive.h"
#include <map>
#include "Serialization/ClassFactory.h"
namespace Serialization {
static const unsigned char SIZE16 = 254;
static const unsigned char SIZE32 = 255;
static const unsigned int BIN_MAGIC = 0xb1a4c17f;
//#ifdef _DEBUG
//typedef std::map<unsigned short, string> HashMap;
//static HashMap hashMap;
//#endif
BinOArchive::BinOArchive()
: IArchive(OUTPUT | BINARY)
{
clear();
}
void BinOArchive::clear()
{
stream_.clear();
stream_.write((const char*)&BIN_MAGIC, sizeof(BIN_MAGIC));
}
size_t BinOArchive::length() const
{
return stream_.position();
}
bool BinOArchive::save(const char* filename)
{
FILE* f = nullptr;
azfopen(&f, filename, "wb");
if (!f)
{
return false;
}
if (fwrite(buffer(), 1, length(), f) != length())
{
fclose(f);
return false;
}
fclose(f);
return true;
}
inline void BinOArchive::openNode(const char* name, bool size8)
{
if (!strlen(name))
{
return;
}
unsigned short hash = calcHash(name);
stream_.write(hash);
blockSizeOffsets_.push_back(int(stream_.position()));
stream_.write((unsigned char)0);
if (!size8)
{
stream_.write((unsigned short)0);
}
#ifdef _DEBUG
// HashMap::iterator i = hashMap.find(hash);
// if(i != hashMap.end() && i->second != name)
// ASSERT_STR(0, name);
// hashMap[hash] = name;
#endif
}
inline void BinOArchive::closeNode(const char* name, bool size8)
{
if (!strlen(name))
{
return;
}
unsigned int offset = blockSizeOffsets_.back();
unsigned int size = (unsigned int)(stream_.position() - offset - sizeof(unsigned char) - (size8 ? 0 : sizeof(unsigned short)));
blockSizeOffsets_.pop_back();
unsigned char* sizePtr = (unsigned char*)(stream_.buffer() + offset);
if (size < SIZE16)
{
*sizePtr = size;
if (!size8)
{
unsigned char* buffer = sizePtr + 3;
memmove(buffer - 2, buffer, size);
stream_.setPosition(stream_.position() - 2);
}
}
else
{
YASLI_ASSERT(!size8);
if (size < 0x10000)
{
*sizePtr = SIZE16;
*((unsigned short*)(sizePtr + 1)) = size;
}
else
{
unsigned char* buffer = sizePtr + 3;
stream_.write((unsigned short)0);
*sizePtr = SIZE32;
memmove(buffer + 2, buffer, size);
*((unsigned int*)(sizePtr + 1)) = size;
}
}
}
bool BinOArchive::operator()(bool& value, const char* name, [[maybe_unused]] const char* label)
{
openNode(name);
stream_.write(value);
closeNode(name);
return true;
}
bool BinOArchive::operator()(IString& value, const char* name, [[maybe_unused]] const char* label)
{
bool size8 = strlen(value.get()) + 1 < SIZE16;
openNode(name, size8);
stream_ << value.get();
stream_.write(char(0));
closeNode(name, size8);
return true;
}
bool BinOArchive::operator()(IWString& value, const char* name, [[maybe_unused]] const char* label)
{
bool size8 = (wcslen(value.get()) + 1) * 2 < SIZE16;
openNode(name, size8);
stream_ << value.get();
stream_.write(short(0));
closeNode(name, size8);
return true;
}
bool BinOArchive::operator()(float& value, const char* name, [[maybe_unused]] const char* label)
{
openNode(name);
stream_.write(value);
closeNode(name);
return true;
}
bool BinOArchive::operator()(double& value, const char* name, [[maybe_unused]] const char* label)
{
openNode(name);
stream_.write(value);
closeNode(name);
return true;
}
bool BinOArchive::operator()(int16& value, const char* name, [[maybe_unused]] const char* label)
{
openNode(name);
stream_.write(value);
closeNode(name);
return true;
}
bool BinOArchive::operator()(int8& value, const char* name, [[maybe_unused]] const char* label)
{
openNode(name);
stream_.write(value);
closeNode(name);
return true;
}
bool BinOArchive::operator()(uint8& value, const char* name, [[maybe_unused]] const char* label)
{
openNode(name);
stream_.write(value);
closeNode(name);
return true;
}
bool BinOArchive::operator()(char& value, const char* name, [[maybe_unused]] const char* label)
{
openNode(name);
stream_.write(value);
closeNode(name);
return true;
}
bool BinOArchive::operator()(uint16& value, const char* name, [[maybe_unused]] const char* label)
{
openNode(name);
stream_.write(value);
closeNode(name);
return true;
}
bool BinOArchive::operator()(int32& value, const char* name, [[maybe_unused]] const char* label)
{
openNode(name);
stream_.write(value);
closeNode(name);
return true;
}
bool BinOArchive::operator()(uint32& value, const char* name, [[maybe_unused]] const char* label)
{
openNode(name);
stream_.write(value);
closeNode(name);
return true;
}
bool BinOArchive::operator()(int64& value, const char* name, [[maybe_unused]] const char* label)
{
openNode(name);
stream_.write(value);
closeNode(name);
return true;
}
bool BinOArchive::operator()(uint64& value, const char* name, [[maybe_unused]] const char* label)
{
openNode(name);
stream_.write(value);
closeNode(name);
return true;
}
bool BinOArchive::operator()(const SStruct& ser, const char* name, [[maybe_unused]] const char* label)
{
openNode(name, false);
ser(*this);
closeNode(name, false);
return true;
}
bool BinOArchive::operator()(IContainer& ser, const char* name, [[maybe_unused]] const char* label)
{
openNode(name, false);
unsigned int size = (unsigned int)ser.size();
if (size < SIZE16)
{
stream_.write((unsigned char)size);
}
else if (size < 0x10000)
{
stream_.write(SIZE16);
stream_.write((unsigned short)size);
}
else
{
stream_.write(SIZE32);
stream_.write(size);
}
if (strlen(name))
{
if (size > 0)
{
int i = 0;
do
{
char elementName[16];
azitoa(i++, elementName, AZ_ARRAY_SIZE(elementName), 10);
ser(*this, elementName, "");
} while (ser.next());
}
closeNode(name, false);
}
else
{
if (size > 0)
{
do
{
ser(*this, "", "");
}
while (ser.next());
}
}
return true;
}
bool BinOArchive::operator()(IPointer& ptr, const char* name, [[maybe_unused]] const char* label)
{
openNode(name, false);
const char* typeName = ptr.registeredTypeName();
if (!typeName)
{
typeName = "";
}
if (typeName[0] == '\0' && ptr.get())
{
CRY_ASSERT_MESSAGE(0, "Writing unregistered class. Use SERIALIZATION_CLASS_NAME macro for registration.");
}
TypeID baseType = ptr.baseType();
if (ptr.get())
{
stream_ << typeName;
stream_.write(char(0));
ptr.serializer()(*this);
}
else
{
stream_.write(char(0));
}
closeNode(name, false);
return true;
}
//////////////////////////////////////////////////////////////////////////
BinIArchive::BinIArchive()
: IArchive(INPUT | BINARY)
, loadedData_(0)
{
}
BinIArchive::~BinIArchive()
{
close();
}
bool BinIArchive::load(const char* filename)
{
close();
FILE* f = nullptr;
azfopen(&f, filename, "rb");
if (!f)
{
return false;
}
fseek(f, 0, SEEK_END);
size_t length = ftell(f);
fseek(f, 0, SEEK_SET);
if (length == 0)
{
fclose(f);
return false;
}
loadedData_ = new char[length];
if (fread((void*)loadedData_, 1, length, f) != length || !open(loadedData_, length))
{
close();
fclose(f);
return false;
}
fclose(f);
return true;
}
bool BinIArchive::open(const char* buffer, size_t size)
{
if (size < sizeof(int))
{
return false;
}
if (*(unsigned*)(buffer) != BIN_MAGIC)
{
return false;
}
buffer += sizeof(unsigned int);
size -= sizeof(unsigned int);
blocks_.push_back(Block(buffer, (unsigned int)size));
return true;
}
void BinIArchive::close()
{
if (loadedData_)
{
delete[] loadedData_;
}
loadedData_ = 0;
}
bool BinIArchive::openNode(const char* name)
{
Block block(0, 0);
if (currentBlock().get(name, block))
{
blocks_.push_back(block);
return true;
}
return false;
}
void BinIArchive::closeNode([[maybe_unused]] const char* name, [[maybe_unused]] bool check)
{
YASLI_ASSERT(!check || currentBlock().validToClose());
blocks_.pop_back();
}
bool BinIArchive::operator()(bool& value, const char* name, [[maybe_unused]] const char* label)
{
if (!strlen(name))
{
read(value);
return true;
}
if (!openNode(name))
{
return false;
}
read(value);
closeNode(name);
return true;
}
bool BinIArchive::operator()(IString& value, const char* name, [[maybe_unused]] const char* label)
{
if (!strlen(name))
{
string str;
read(str);
value.set(str.c_str());
return true;
}
if (!openNode(name))
{
return false;
}
string str;
read(str);
value.set(str.c_str());
closeNode(name);
return true;
}
bool BinIArchive::operator()(IWString& value, const char* name, [[maybe_unused]] const char* label)
{
if (!strlen(name))
{
wstring str;
read(str);
value.set(str.c_str());
return true;
}
if (!openNode(name))
{
return false;
}
wstring str;
read(str);
value.set(str.c_str());
closeNode(name);
return true;
}
bool BinIArchive::operator()(float& value, const char* name, [[maybe_unused]] const char* label)
{
if (!strlen(name))
{
read(value);
return true;
}
if (!openNode(name))
{
return false;
}
read(value);
closeNode(name);
return true;
}
bool BinIArchive::operator()(double& value, const char* name, [[maybe_unused]] const char* label)
{
if (!strlen(name))
{
read(value);
return true;
}
if (!openNode(name))
{
return false;
}
read(value);
closeNode(name);
return true;
}
bool BinIArchive::operator()(int16& value, const char* name, [[maybe_unused]] const char* label)
{
if (!strlen(name))
{
read(value);
return true;
}
if (!openNode(name))
{
return false;
}
read(value);
closeNode(name);
return true;
}
bool BinIArchive::operator()(uint16& value, const char* name, [[maybe_unused]] const char* label)
{
if (!strlen(name))
{
read(value);
return true;
}
if (!openNode(name))
{
return false;
}
read(value);
closeNode(name);
return true;
}
bool BinIArchive::operator()(int32& value, const char* name, [[maybe_unused]] const char* label)
{
if (!strlen(name))
{
read(value);
return true;
}
if (!openNode(name))
{
return false;
}
read(value);
closeNode(name);
return true;
}
bool BinIArchive::operator()(uint32& value, const char* name, [[maybe_unused]] const char* label)
{
if (!strlen(name))
{
read(value);
return true;
}
if (!openNode(name))
{
return false;
}
read(value);
closeNode(name);
return true;
}
bool BinIArchive::operator()(int64& value, const char* name, [[maybe_unused]] const char* label)
{
if (!strlen(name))
{
read(value);
return true;
}
if (!openNode(name))
{
return false;
}
read(value);
closeNode(name);
return true;
}
bool BinIArchive::operator()(uint64& value, const char* name, [[maybe_unused]] const char* label)
{
if (!strlen(name))
{
read(value);
return true;
}
if (!openNode(name))
{
return false;
}
read(value);
closeNode(name);
return true;
}
bool BinIArchive::operator()(int8& value, const char* name, [[maybe_unused]] const char* label)
{
if (!strlen(name))
{
read(value);
return true;
}
if (!openNode(name))
{
return false;
}
read(value);
closeNode(name);
return true;
}
bool BinIArchive::operator()(uint8& value, const char* name, [[maybe_unused]] const char* label)
{
if (!strlen(name))
{
read(value);
return true;
}
if (!openNode(name))
{
return false;
}
read(value);
closeNode(name);
return true;
}
bool BinIArchive::operator()(char& value, const char* name, [[maybe_unused]] const char* label)
{
if (!strlen(name))
{
read(value);
return true;
}
if (!openNode(name))
{
return false;
}
read(value);
closeNode(name);
return true;
}
bool BinIArchive::operator()(const SStruct& ser, const char* name, [[maybe_unused]] const char* label)
{
if (!strlen(name))
{
ser(*this);
return true;
}
if (!openNode(name))
{
return false;
}
ser(*this);
closeNode(name, false);
return true;
}
bool BinIArchive::operator()(IContainer& ser, const char* name, [[maybe_unused]] const char* label)
{
if (strlen(name))
{
if (!openNode(name))
{
return false;
}
size_t size = currentBlock().readPackedSize();
ser.resize(size);
if (size > 0)
{
int i = 0;
do
{
char elementName[16];
azitoa(i++, elementName, AZ_ARRAY_SIZE(elementName), 10);
ser(*this, elementName, "");
}
while (ser.next());
}
closeNode(name);
return true;
}
else
{
size_t size = currentBlock().readPackedSize();
ser.resize(size);
if (size > 0)
{
do
{
ser(*this, "", "");
}
while (ser.next());
}
return true;
}
}
bool BinIArchive::operator()(IPointer& ptr, const char* name, [[maybe_unused]] const char* label)
{
if (strlen(name) && !openNode(name))
{
return false;
}
string typeName;
read(typeName);
if (ptr.get() && (typeName.empty() || strcmp(typeName.c_str(), ptr.registeredTypeName()) != 0))
{
ptr.create(""); // 0
}
if (!typeName.empty() && !ptr.get())
{
ptr.create(typeName.c_str());
}
if (SStruct ser = ptr.serializer())
{
ser(*this);
}
if (strlen(name))
{
closeNode(name);
}
return true;
}
unsigned int BinIArchive::Block::readPackedSize()
{
unsigned char size8;
read(size8);
if (size8 < SIZE16)
{
return size8;
}
if (size8 == SIZE16)
{
unsigned short size16;
read(size16);
return size16;
}
unsigned int size32;
read(size32);
return size32;
}
bool BinIArchive::Block::get(const char* name, Block& block)
{
if (begin_ == end_)
{
return false;
}
complex_ = true;
unsigned short hashName = calcHash(name);
const char* currInitial = curr_;
bool restarted = false;
for (;; )
{
if (curr_ >= end_)
{
return false;
}
unsigned short hash;
read(hash);
unsigned int size = readPackedSize();
const char* currPrev = curr_;
if ((curr_ += size) == end_)
{
if (restarted)
{
return false;
}
curr_ = begin_;
restarted = true;
}
//ASSERT(curr_ < end_);
if (hash == hashName)
{
block = Block(currPrev, size);
return true;
}
if (curr_ == currInitial)
{
return false;
}
}
}
}
@@ -0,0 +1,180 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
// Original file Copyright Crytek GMBH or its affiliates, used under license.
#pragma once
// For tags 16-bit xor-hash is used, with check for uniquness in debug
// Block size is automatic: 8, 16 or 32 bits
#include "Serialization/IArchive.h"
#include "MemoryWriter.h"
namespace Serialization {
inline unsigned short calcHash(const char* str)
{
unsigned short hash = 0;
const unsigned short* p = (const unsigned short*)(str);
for (;; )
{
unsigned short w = *p++;
if (!(w & 0xff))
{
break;
}
hash ^= w;
if (!(w & 0xff00))
{
break;
}
}
return hash;
}
class BinOArchive
: public IArchive
{
public:
BinOArchive();
~BinOArchive() {}
void clear();
size_t length() const;
const char* buffer() const { return stream_.buffer(); }
bool save(const char* fileName);
bool operator()(bool& value, const char* name, const char* label);
bool operator()(IString& value, const char* name, const char* label);
bool operator()(IWString& value, const char* name, const char* label);
bool operator()(float& value, const char* name, const char* label);
bool operator()(double& value, const char* name, const char* label);
bool operator()(int32& value, const char* name, const char* label);
bool operator()(uint32& value, const char* name, const char* label);
bool operator()(int16& value, const char* name, const char* label);
bool operator()(uint16& value, const char* name, const char* label);
bool operator()(int64& value, const char* name, const char* label);
bool operator()(uint64& value, const char* name, const char* label);
bool operator()(int8& value, const char* name, const char* label);
bool operator()(uint8& value, const char* name, const char* label);
bool operator()(char& value, const char* name, const char* label);
bool operator()(const SStruct& ser, const char* name, const char* label);
bool operator()(IContainer& ser, const char* name, const char* label);
bool operator()(IPointer& ptr, const char* name, const char* label);
using IArchive::operator();
private:
void openContainer(const char* name, int size, const char* typeName);
void openNode(const char* name, bool size8 = true);
void closeNode(const char* name, bool size8 = true);
std::vector<unsigned int> blockSizeOffsets_;
MemoryWriter stream_;
};
//////////////////////////////////////////////////////////////////////////
class BinIArchive
: public IArchive
{
public:
BinIArchive();
~BinIArchive();
bool load(const char* fileName);
bool open(const char* buffer, size_t length); // doesn't copy the buffer
bool open(const BinOArchive& ar) { return open(ar.buffer(), ar.length()); }
void close();
bool operator()(bool& value, const char* name, const char* label);
bool operator()(IString& value, const char* name, const char* label);
bool operator()(IWString& value, const char* name, const char* label);
bool operator()(float& value, const char* name, const char* label);
bool operator()(double& value, const char* name, const char* label);
bool operator()(int16& value, const char* name, const char* label);
bool operator()(uint16& value, const char* name, const char* label);
bool operator()(int32& value, const char* name, const char* label);
bool operator()(uint32& value, const char* name, const char* label);
bool operator()(int64& value, const char* name, const char* label);
bool operator()(uint64& value, const char* name, const char* label);
bool operator()(int8& value, const char* name, const char* label);
bool operator()(uint8& value, const char* name, const char* label);
bool operator()(char& value, const char* name, const char* label);
bool operator()(const SStruct& ser, const char* name, const char* label);
bool operator()(IContainer& ser, const char* name, const char* label);
bool operator()(IPointer& ptr, const char* name, const char* label);
using IArchive::operator();
private:
class Block
{
public:
Block(const char* data, int size)
: begin_(data)
, end_(data + size)
, curr_(data)
, complex_(false) {}
bool get(const char* name, Block& block);
void read(void* data, int size)
{
YASLI_ASSERT(curr_ + size <= end_);
memcpy(data, curr_, size);
curr_ += size;
}
template<class T>
void read(T& x){ read(&x, sizeof(x)); }
void read(string& s)
{
YASLI_ASSERT(curr_ + strlen(curr_) < end_);
s = curr_;
curr_ += strlen(curr_) + 1;
}
void read(wstring& s)
{
YASLI_ASSERT(curr_ + sizeof(wchar_t) * wcslen((wchar_t*)curr_) < end_);
s = (wchar_t*)curr_;
curr_ += (wcslen((wchar_t*)curr_) + 1) * sizeof(wchar_t);
}
unsigned int readPackedSize();
bool validToClose() const { return complex_ || curr_ == end_; }
private:
const char* begin_;
const char* end_;
const char* curr_;
bool complex_;
};
typedef std::vector<Block> Blocks;
Blocks blocks_;
const char* loadedData_;
bool openNode(const char* name);
void closeNode(const char* name, bool check = true);
Block& currentBlock() { return blocks_.back(); }
template<class T>
void read(T& t) { currentBlock().read(t); }
};
}
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,95 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
// Original file Copyright Crytek GMBH or its affiliates, used under license.
#pragma once
#include "Serialization/IArchive.h"
#include "MemoryReader.h"
#include "Token.h"
#include <memory>
namespace Serialization {
class MemoryReader;
class JSONIArchive
: public IArchive
{
public:
JSONIArchive();
~JSONIArchive();
bool load(const char* filename);
bool open(const char* buffer, size_t length, bool free = false);
// virtuals:
bool operator()(bool& value, const char* name = "", const char* label = 0);
bool operator()(IString& value, const char* name = "", const char* label = 0);
bool operator()(IWString& value, const char* name = "", const char* label = 0);
bool operator()(float& value, const char* name = "", const char* label = 0);
bool operator()(double& value, const char* name = "", const char* label = 0);
bool operator()(int16& value, const char* name = "", const char* label = 0);
bool operator()(uint16& value, const char* name = "", const char* label = 0);
bool operator()(int32& value, const char* name = "", const char* label = 0);
bool operator()(uint32& value, const char* name = "", const char* label = 0);
bool operator()(int64& value, const char* name = "", const char* label = 0);
bool operator()(uint64& value, const char* name = "", const char* label = 0);
bool operator()(int8& value, const char* name = "", const char* label = 0);
bool operator()(uint8& value, const char* name = "", const char* label = 0);
bool operator()(char& value, const char* name = "", const char* label = 0);
bool operator()(const SStruct& ser, const char* name = "", const char* label = 0);
bool operator()(const SBlackBox& ser, const char* name = "", const char* label = 0);
bool operator()(IContainer& ser, const char* name = "", const char* label = 0);
bool operator()(IKeyValue& ser, const char* name = "", const char* label = 0);
bool operator()(IPointer& ser, const char* name = "", const char* label = 0);
using IArchive::operator();
private:
bool findName(const char* name, Token* outName = 0);
bool openBracket();
bool closeBracket();
bool openContainerBracket();
bool closeContainerBracket();
void checkValueToken();
bool checkStringValueToken();
void readToken();
void putToken();
int line(const char* position) const;
bool isName(Token token) const;
bool expect(char token);
void skipBlock();
struct Level
{
const char* start;
const char* firstToken;
bool isContainer;
bool isKeyValue;
Level()
: isContainer(false)
, isKeyValue(false) {}
};
typedef std::vector<Level> Stack;
Stack stack_;
std::unique_ptr<MemoryReader> reader_;
Token token_;
std::vector<char> unescapeBuffer_;
string filename_;
void* buffer_;
};
}
@@ -0,0 +1,828 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
// Original file Copyright Crytek GMBH or its affiliates, used under license.
#include "CrySystem_precompiled.h"
#include "JSONOArchive.h"
#include "MemoryWriter.h"
#include "Serialization/KeyValue.h"
#include "Serialization/ClassFactory.h"
#include "Serialization/BlackBox.h"
#include <float.h>
namespace Serialization {
// Some of non-latin1 characters here are not escaped to
// keep compatibility with 8-bit local encoding (e.g. windows-1251)
static const char* escapeTable[256] = {
"\\0" /* 0x00: */,
"\\x01" /* 0x01: */,
"\\x02" /* 0x02: */,
"\\x03" /* 0x03: */,
"\\x04" /* 0x04: */,
"\\x05" /* 0x05: */,
"\\x06" /* 0x06: */,
"\\x07" /* 0x07: */,
"\\x08" /* 0x08: */,
"\\t" /* 0x09: \t */,
"\\n" /* 0x0A: \n */,
"\\x0B" /* 0x0B: */,
"\\x0C" /* 0x0C: */,
"\\r" /* 0x0D: */,
"\\x0E" /* 0x0E: */,
"\\x0F" /* 0x0F: */,
"\\x10" /* 0x10: */,
"\\x11" /* 0x11: */,
"\\x12" /* 0x12: */,
"\\x13" /* 0x13: */,
"\\x14" /* 0x14: */,
"\\x15" /* 0x15: */,
"\\x16" /* 0x16: */,
"\\x17" /* 0x17: */,
"\\x18" /* 0x18: */,
"\\x19" /* 0x19: */,
"\\x1A" /* 0x1A: */,
"\\x1B" /* 0x1B: */,
"\\x1C" /* 0x1C: */,
"\\x1D" /* 0x1D: */,
"\\x1E" /* 0x1E: */,
"\\x1F" /* 0x1F: */,
" " /* 0x20: */,
"!" /* 0x21: ! */,
"\\\"" /* 0x22: " */,
"#" /* 0x23: # */,
"$" /* 0x24: $ */,
"%" /* 0x25: % */,
"&" /* 0x26: & */,
"'" /* 0x27: ' */,
"(" /* 0x28: ( */,
")" /* 0x29: ) */,
"*" /* 0x2A: * */,
"+" /* 0x2B: + */,
"," /* 0x2C: , */,
"-" /* 0x2D: - */,
"." /* 0x2E: . */,
"/" /* 0x2F: / */,
"0" /* 0x30: 0 */,
"1" /* 0x31: 1 */,
"2" /* 0x32: 2 */,
"3" /* 0x33: 3 */,
"4" /* 0x34: 4 */,
"5" /* 0x35: 5 */,
"6" /* 0x36: 6 */,
"7" /* 0x37: 7 */,
"8" /* 0x38: 8 */,
"9" /* 0x39: 9 */,
":" /* 0x3A: : */,
";" /* 0x3B: ; */,
"<" /* 0x3C: < */,
"=" /* 0x3D: = */,
">" /* 0x3E: > */,
"?" /* 0x3F: ? */,
"@" /* 0x40: @ */,
"A" /* 0x41: A */,
"B" /* 0x42: B */,
"C" /* 0x43: C */,
"D" /* 0x44: D */,
"E" /* 0x45: E */,
"F" /* 0x46: F */,
"G" /* 0x47: G */,
"H" /* 0x48: H */,
"I" /* 0x49: I */,
"J" /* 0x4A: J */,
"K" /* 0x4B: K */,
"L" /* 0x4C: L */,
"M" /* 0x4D: M */,
"N" /* 0x4E: N */,
"O" /* 0x4F: O */,
"P" /* 0x50: P */,
"Q" /* 0x51: Q */,
"R" /* 0x52: R */,
"S" /* 0x53: S */,
"T" /* 0x54: T */,
"U" /* 0x55: U */,
"V" /* 0x56: V */,
"W" /* 0x57: W */,
"X" /* 0x58: X */,
"Y" /* 0x59: Y */,
"Z" /* 0x5A: Z */,
"[" /* 0x5B: [ */,
"\\\\" /* 0x5C: \ */,
"]" /* 0x5D: ] */,
"^" /* 0x5E: ^ */,
"_" /* 0x5F: _ */,
"`" /* 0x60: ` */,
"a" /* 0x61: a */,
"b" /* 0x62: b */,
"c" /* 0x63: c */,
"d" /* 0x64: d */,
"e" /* 0x65: e */,
"f" /* 0x66: f */,
"g" /* 0x67: g */,
"h" /* 0x68: h */,
"i" /* 0x69: i */,
"j" /* 0x6A: j */,
"k" /* 0x6B: k */,
"l" /* 0x6C: l */,
"m" /* 0x6D: m */,
"n" /* 0x6E: n */,
"o" /* 0x6F: o */,
"p" /* 0x70: p */,
"q" /* 0x71: q */,
"r" /* 0x72: r */,
"s" /* 0x73: s */,
"t" /* 0x74: t */,
"u" /* 0x75: u */,
"v" /* 0x76: v */,
"w" /* 0x77: w */,
"x" /* 0x78: x */,
"y" /* 0x79: y */,
"z" /* 0x7A: z */,
"{" /* 0x7B: { */,
"|" /* 0x7C: | */,
"}" /* 0x7D: } */,
"~" /* 0x7E: ~ */,
"\x7F" /* 0x7F: */, // for utf-8
"\x80" /* 0x80: */,
"\x81" /* 0x81: */,
"\x82" /* 0x82: */,
"\x83" /* 0x83: */,
"\x84" /* 0x84: */,
"\x85" /* 0x85: */,
"\x86" /* 0x86: */,
"\x87" /* 0x87: */,
"\x88" /* 0x88: */,
"\x89" /* 0x89: */,
"\x8A" /* 0x8A: */,
"\x8B" /* 0x8B: */,
"\x8C" /* 0x8C: */,
"\x8D" /* 0x8D: */,
"\x8E" /* 0x8E: */,
"\x8F" /* 0x8F: */,
"\x90" /* 0x90: */,
"\x91" /* 0x91: */,
"\x92" /* 0x92: */,
"\x93" /* 0x93: */,
"\x94" /* 0x94: */,
"\x95" /* 0x95: */,
"\x96" /* 0x96: */,
"\x97" /* 0x97: */,
"\x98" /* 0x98: */,
"\x99" /* 0x99: */,
"\x9A" /* 0x9A: */,
"\x9B" /* 0x9B: */,
"\x9C" /* 0x9C: */,
"\x9D" /* 0x9D: */,
"\x9E" /* 0x9E: */,
"\x9F" /* 0x9F: */,
"\xA0" /* 0xA0: */,
"\xA1" /* 0xA1: */,
"\xA2" /* 0xA2: */,
"\xA3" /* 0xA3: */,
"\xA4" /* 0xA4: */,
"\xA5" /* 0xA5: */,
"\xA6" /* 0xA6: */,
"\xA7" /* 0xA7: */,
"\xA8" /* 0xA8: */,
"\xA9" /* 0xA9: */,
"\xAA" /* 0xAA: */,
"\xAB" /* 0xAB: */,
"\xAC" /* 0xAC: */,
"\xAD" /* 0xAD: */,
"\xAE" /* 0xAE: */,
"\xAF" /* 0xAF: */,
"\xB0" /* 0xB0: */,
"\xB1" /* 0xB1: */,
"\xB2" /* 0xB2: */,
"\xB3" /* 0xB3: */,
"\xB4" /* 0xB4: */,
"\xB5" /* 0xB5: */,
"\xB6" /* 0xB6: */,
"\xB7" /* 0xB7: */,
"\xB8" /* 0xB8: */,
"\xB9" /* 0xB9: */,
"\xBA" /* 0xBA: */,
"\xBB" /* 0xBB: */,
"\xBC" /* 0xBC: */,
"\xBD" /* 0xBD: */,
"\xBE" /* 0xBE: */,
"\xBF" /* 0xBF: */,
"\xC0" /* 0xC0: */,
"\xC1" /* 0xC1: */,
"\xC2" /* 0xC2: */,
"\xC3" /* 0xC3: */,
"\xC4" /* 0xC4: */,
"\xC5" /* 0xC5: */,
"\xC6" /* 0xC6: */,
"\xC7" /* 0xC7: */,
"\xC8" /* 0xC8: */,
"\xC9" /* 0xC9: */,
"\xCA" /* 0xCA: */,
"\xCB" /* 0xCB: */,
"\xCC" /* 0xCC: */,
"\xCD" /* 0xCD: */,
"\xCE" /* 0xCE: */,
"\xCF" /* 0xCF: */,
"\xD0" /* 0xD0: */,
"\xD1" /* 0xD1: */,
"\xD2" /* 0xD2: */,
"\xD3" /* 0xD3: */,
"\xD4" /* 0xD4: */,
"\xD5" /* 0xD5: */,
"\xD6" /* 0xD6: */,
"\xD7" /* 0xD7: */,
"\xD8" /* 0xD8: */,
"\xD9" /* 0xD9: */,
"\xDA" /* 0xDA: */,
"\xDB" /* 0xDB: */,
"\xDC" /* 0xDC: */,
"\xDD" /* 0xDD: */,
"\xDE" /* 0xDE: */,
"\xDF" /* 0xDF: */,
"\xE0" /* 0xE0: */,
"\xE1" /* 0xE1: */,
"\xE2" /* 0xE2: */,
"\xE3" /* 0xE3: */,
"\xE4" /* 0xE4: */,
"\xE5" /* 0xE5: */,
"\xE6" /* 0xE6: */,
"\xE7" /* 0xE7: */,
"\xE8" /* 0xE8: */,
"\xE9" /* 0xE9: */,
"\xEA" /* 0xEA: */,
"\xEB" /* 0xEB: */,
"\xEC" /* 0xEC: */,
"\xED" /* 0xED: */,
"\xEE" /* 0xEE: */,
"\xEF" /* 0xEF: */,
"\xF0" /* 0xF0: */,
"\xF1" /* 0xF1: */,
"\xF2" /* 0xF2: */,
"\xF3" /* 0xF3: */,
"\xF4" /* 0xF4: */,
"\xF5" /* 0xF5: */,
"\xF6" /* 0xF6: */,
"\xF7" /* 0xF7: */,
"\xF8" /* 0xF8: */,
"\xF9" /* 0xF9: */,
"\xFA" /* 0xFA: */,
"\xFB" /* 0xFB: */,
"\xFC" /* 0xFC: */,
"\xFD" /* 0xFD: */,
"\xFE" /* 0xFE: */,
"\xFF" /* 0xFF: */
};
static void escapeString(MemoryWriter& dest, const char* begin, const char* end)
{
while (begin != end)
{
const char* str = escapeTable[(unsigned char)(*begin)];
dest.write(str);
++begin;
}
}
// ---------------------------------------------------------------------------
static const int TAB_WIDTH = 2;
JSONOArchive::JSONOArchive(int textWidth, const char* header)
: IArchive(OUTPUT | TEXT)
, header_(header)
, textWidth_(textWidth)
, compactOffset_(0)
{
buffer_.reset(new MemoryWriter(1024, true));
if (header_)
{
(*buffer_) << header_;
}
YASLI_ASSERT(stack_.empty());
stack_.push_back(Level(false, 0, 0));
}
JSONOArchive::~JSONOArchive()
{
}
bool JSONOArchive::save(const char* fileName)
{
YASLI_ESCAPE(fileName && strlen(fileName) > 0, return false);
YASLI_ESCAPE(stack_.size() == 1, return false);
YASLI_ESCAPE(buffer_.get() != 0, return false);
YASLI_ESCAPE(buffer_->position() <= buffer_->size(), return false);
stack_.pop_back();
FILE* file = nullptr;
azfopen(&file, fileName, "wb");
if (file)
{
if (fwrite(buffer_->c_str(), 1, buffer_->position(), file) != buffer_->position())
{
fclose(file);
return false;
}
fclose(file);
return true;
}
else
{
return false;
}
}
const char* JSONOArchive::c_str() const
{
return buffer_->c_str();
}
size_t JSONOArchive::length() const
{
return buffer_->position();
}
void JSONOArchive::openBracket()
{
*buffer_ << "{";
}
void JSONOArchive::closeBracket()
{
*buffer_ << "}";
}
void JSONOArchive::openContainerBracket()
{
*buffer_ << "[";
}
void JSONOArchive::closeContainerBracket()
{
*buffer_ << "]";
}
void JSONOArchive::placeName(const char* name)
{
if (stack_.back().isKeyValue)
{
return;
}
if ((name[0] != '\0' || !stack_.back().isContainer) && stack_.size() > 1)
{
*buffer_ << "\"";
*buffer_ << name;
*buffer_ << "\": ";
stack_.back().nameIndex += 1;
}
}
void JSONOArchive::placeIndent(bool putComma)
{
if (stack_.back().isKeyValue)
{
return;
}
if (putComma && stack_.back().elementIndex > 0)
{
*buffer_ << ",";
}
if (buffer_->position() > 0)
{
*buffer_ << "\n";
}
int count = int(stack_.size() - 1);
stack_.back().indentCount += count;
stack_.back().elementIndex += 1;
for (int i = 0; i < count; ++i)
{
*buffer_ << "\t";
}
compactOffset_ = 0;
}
void JSONOArchive::placeIndentCompact(bool putComma)
{
if (stack_.back().isKeyValue)
{
return;
}
if (putComma && stack_.back().elementIndex > 0)
{
*buffer_ << ",";
}
if ((compactOffset_ % 32) != 0 && stack_.back().isContainer)
{
*buffer_ << " ";
compactOffset_ += 1;
stack_.back().elementIndex += 1;
}
else if (buffer_->size())
{
*buffer_ << "\n";
int count = int(stack_.size() - 1);
stack_.back().indentCount += count /* * TAB_WIDTH*/;
stack_.back().elementIndex += 1;
for (int i = 0; i < count; ++i)
{
*buffer_ << "\t";
}
compactOffset_ = 1;
}
}
bool JSONOArchive::operator()(bool& value, const char* name, [[maybe_unused]] const char* label)
{
placeIndent();
placeName(name);
*buffer_ << (value ? "true" : "false");
return true;
}
bool JSONOArchive::operator()(IString& value, const char* name, [[maybe_unused]] const char* label)
{
placeIndent();
placeName(name);
(*buffer_) << "\"";
const char* str = value.get();
escapeString(*buffer_, str, str + strlen(value.get()));
(*buffer_) << "\"";
return true;
}
inline char* writeUtf16ToUtf8(char* s, unsigned int ch)
{
const unsigned char byteMark = 0x80;
const unsigned char byteMask = 0xBF;
size_t len;
if (ch < 0x80)
{
len = 1;
}
else if (ch < 0x800)
{
len = 2;
}
else if (ch < 0x10000)
{
len = 3;
}
else if (ch < 0x200000)
{
len = 4;
}
else
{
return s;
}
s += len;
const unsigned char firstByteMark[7] = { 0x00, 0x00, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC };
switch (len)
{
case 4:
*--s = (char)((ch | byteMark) & byteMask);
ch >>= 6;
case 3:
*--s = (char)((ch | byteMark) & byteMask);
ch >>= 6;
case 2:
*--s = (char)((ch | byteMark) & byteMask);
ch >>= 6;
case 1:
*--s = (char)(ch | firstByteMark[len]);
}
return s + len;
}
bool JSONOArchive::operator()(IWString& value, const char* name, [[maybe_unused]] const char* label)
{
placeIndent();
placeName(name);
(*buffer_) << "\"";
const wchar_t* in = value.get();
for (; *in; ++in)
{
char buf[6];
escapeString(*buffer_, buf, writeUtf16ToUtf8(buf, *in));
}
(*buffer_) << "\"";
return true;
}
bool JSONOArchive::operator()(float& value, const char* name, [[maybe_unused]] const char* label)
{
placeIndentCompact();
placeName(name);
(*buffer_) << value;
return true;
}
bool JSONOArchive::operator()(double& value, const char* name, [[maybe_unused]] const char* label)
{
placeIndentCompact();
placeName(name);
(*buffer_) << value;
return true;
}
bool JSONOArchive::operator()(int32& value, const char* name, [[maybe_unused]] const char* label)
{
placeIndentCompact();
placeName(name);
(*buffer_) << value;
return true;
}
bool JSONOArchive::operator()(uint32& value, const char* name, [[maybe_unused]] const char* label)
{
placeIndentCompact();
placeName(name);
(*buffer_) << value;
return true;
}
bool JSONOArchive::operator()(int16& value, const char* name, [[maybe_unused]] const char* label)
{
placeIndentCompact();
placeName(name);
(*buffer_) << value;
return true;
}
bool JSONOArchive::operator()(uint16& value, const char* name, [[maybe_unused]] const char* label)
{
placeIndentCompact();
placeName(name);
(*buffer_) << value;
return true;
}
bool JSONOArchive::operator()(int64& value, const char* name, [[maybe_unused]] const char* label)
{
placeIndentCompact();
placeName(name);
(*buffer_) << value;
return true;
}
bool JSONOArchive::operator()(uint64& value, const char* name, [[maybe_unused]] const char* label)
{
placeIndentCompact();
placeName(name);
(*buffer_) << value;
return true;
}
bool JSONOArchive::operator()(uint8& value, const char* name, [[maybe_unused]] const char* label)
{
placeIndentCompact();
placeName(name);
(*buffer_) << value;
return true;
}
bool JSONOArchive::operator()(int8& value, const char* name, [[maybe_unused]] const char* label)
{
placeIndentCompact();
placeName(name);
(*buffer_) << value;
return true;
}
bool JSONOArchive::operator()(char& value, const char* name, [[maybe_unused]] const char* label)
{
placeIndentCompact();
placeName(name);
(*buffer_) << value;
return true;
}
bool JSONOArchive::operator()(const SStruct& ser, const char* name, [[maybe_unused]] const char* label)
{
placeIndent();
placeName(name);
std::size_t position = buffer_->position();
openBracket();
stack_.push_back(Level(false, position, int(strlen(name) + 2 * (name[0] & 1) + (stack_.size() - 1) * TAB_WIDTH + 2)));
YASLI_ASSERT(ser);
ser(*this);
bool joined = joinLinesIfPossible();
bool noNames = stack_.back().nameIndex == 0;
if (noNames)
{
if (stack_.size() != 2)
{
buffer_->buffer()[stack_.back().startPosition] = '[';
}
}
stack_.pop_back();
if (!joined)
{
placeIndent(false);
}
else
{
*buffer_ << " ";
}
if (noNames)
{
closeContainerBracket();
}
else
{
closeBracket();
}
return true;
}
bool JSONOArchive::operator()(const SBlackBox& box, const char* name, [[maybe_unused]] const char* label)
{
if (strcmp(box.format, "json") != 0)
{
return false;
}
if (box.size == 0)
{
return false;
}
placeIndent();
placeName(name);
return buffer_->write(box.data, box.size);
}
bool JSONOArchive::operator()(IKeyValue& keyValue, [[maybe_unused]] const char* name, [[maybe_unused]] const char* label)
{
placeIndent();
*buffer_ << "\"";
*buffer_ << keyValue.get();
*buffer_ << "\": ";
stack_.back().nameIndex += 1;
stack_.back().isKeyValue = true;
keyValue.serializeValue(*this, "", 0);
stack_.back().isKeyValue = false;
if (stack_.back().isContainer)
{
stack_.back().isDictionary = true;
}
return true;
}
bool JSONOArchive::operator()(IPointer& ser, const char* name, [[maybe_unused]] const char* label)
{
placeIndent();
placeName(name);
openBracket();
const char* registeredTypeName = ser.registeredTypeName();
if (registeredTypeName && registeredTypeName[0] != '\0')
{
*buffer_ << " ";
placeName(registeredTypeName);
stack_.back().isKeyValue = true;
operator()(ser.serializer(), "");
stack_.back().isKeyValue = false;
*buffer_ << " ";
}
closeBracket();
return true;
}
bool JSONOArchive::operator()(IContainer& ser, const char* name, [[maybe_unused]] const char* label)
{
placeIndent();
placeName(name);
std::size_t position = buffer_->position();
openContainerBracket();
stack_.push_back(Level(true, position, int(strlen(name) + 2 * (name[0] & 1) + stack_.size() - 1 * TAB_WIDTH + 2)));
std::size_t size = ser.size();
if (size > 0)
{
do
{
ser(*this, "", "");
} while (ser.next());
}
bool joined = joinLinesIfPossible();
bool isDictionary = stack_.back().isDictionary;
if (isDictionary)
{
buffer_->buffer()[stack_.back().startPosition] = '{';
}
stack_.pop_back();
if (!joined)
{
placeIndent(false);
}
else
{
*buffer_ << " ";
}
if (isDictionary)
{
closeBracket();
}
else
{
closeContainerBracket();
}
return true;
}
static char* joinLines(char* start, char* end)
{
YASLI_ASSERT(start <= end);
char* next = start;
while (next != end)
{
if (*next != '\t' && *next != '\r')
{
if (*next != '\n')
{
*start = *next;
}
else
{
*start = ' ';
}
++start;
}
++next;
}
return start;
}
bool JSONOArchive::joinLinesIfPossible()
{
YASLI_ASSERT(!stack_.empty());
std::size_t startPosition = stack_.back().startPosition;
YASLI_ASSERT(startPosition < buffer_->size());
int indentCount = stack_.back().indentCount;
//YASLI_ASSERT(startPosition >= indentCount);
if (buffer_->position() - startPosition - indentCount < std::size_t(textWidth_))
{
char* buffer = buffer_->buffer();
char* start = buffer + startPosition;
char* end = buffer + buffer_->position();
end = joinLines(start, end);
std::size_t newPosition = end - buffer;
YASLI_ASSERT(newPosition <= buffer_->position());
buffer_->setPosition(newPosition);
return true;
}
return false;
}
}
// vim:ts=4 sw=4:
@@ -0,0 +1,102 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
// Original file Copyright Crytek GMBH or its affiliates, used under license.
#pragma once
#include <memory>
#include "Serialization/IArchive.h"
#include "Serialization/MemoryWriter.h"
namespace Serialization {
class MemoryWriter;
class JSONOArchive
: public IArchive
{
public:
// header = 0 - default header, use "" to omit
JSONOArchive(int textWidth = 80, const char* header = 0);
~JSONOArchive();
bool save(const char* fileName);
const char* c_str() const;
const char* buffer() const { return c_str(); }
size_t length() const;
// from Archive:
bool operator()(bool& value, const char* name = "", const char* label = 0);
bool operator()(IString& value, const char* name = "", const char* label = 0);
bool operator()(IWString& value, const char* name = "", const char* label = 0);
bool operator()(float& value, const char* name = "", const char* label = 0);
bool operator()(double& value, const char* name = "", const char* label = 0);
bool operator()(int16& value, const char* name = "", const char* label = 0);
bool operator()(uint16& value, const char* name = "", const char* label = 0);
bool operator()(int32& value, const char* name = "", const char* label = 0);
bool operator()(uint32& value, const char* name = "", const char* label = 0);
bool operator()(int64& value, const char* name = "", const char* label = 0);
bool operator()(uint64& value, const char* name = "", const char* label = 0);
bool operator()(char& value, const char* name = "", const char* label = 0);
bool operator()(int8& value, const char* name = "", const char* label = 0);
bool operator()(uint8& value, const char* name = "", const char* label = 0);
bool operator()(const SStruct& ser, const char* name = "", const char* label = 0);
bool operator()(const SBlackBox& box, const char* name = "", const char* label = 0);
bool operator()(IContainer& ser, const char* name = "", const char* label = 0);
bool operator()(IKeyValue& keyValue, const char* name = "", const char* label = 0);
bool operator()(IPointer& ser, const char* name = "", const char* label = 0);
// ^^^
using IArchive::operator();
private:
void openBracket();
void closeBracket();
void openContainerBracket();
void closeContainerBracket();
void placeName(const char* name);
void placeIndent(bool putComma = true);
void placeIndentCompact(bool putComma = true);
bool joinLinesIfPossible();
struct Level
{
Level(bool _isContainer, std::size_t position, int column)
: isKeyValue(false)
, isContainer(_isContainer)
, isDictionary(false)
, startPosition(position)
, nameIndex(0)
, elementIndex(0)
, indentCount(-column)
{}
bool isKeyValue;
bool isContainer;
bool isDictionary;
std::size_t startPosition;
int nameIndex;
int elementIndex;
int indentCount;
};
typedef std::vector<Level> Stack;
Stack stack_;
std::unique_ptr<MemoryWriter> buffer_;
const char* header_;
int textWidth_;
string fileName_;
int compactOffset_;
bool isKeyValue_;
};
}
@@ -0,0 +1,92 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
// Original file Copyright Crytek GMBH or its affiliates, used under license.
#include "CrySystem_precompiled.h"
#include <platform.h>
#include "Serialization/Assert.h"
#include "MemoryReader.h"
#include <stdlib.h>
#include <memory.h>
namespace Serialization {
MemoryReader::MemoryReader()
: size_(0)
, position_(0)
, memory_(0)
, ownedMemory_(false)
{
}
MemoryReader::MemoryReader(const void* memory, std::size_t size, bool ownAndFree)
: size_(size)
, position_((const char*)(memory))
, memory_((const char*)(memory))
, ownedMemory_(ownAndFree)
{
}
MemoryReader::~MemoryReader()
{
if (ownedMemory_)
{
free(const_cast<char*>(memory_));
memory_ = 0;
size_ = 0;
}
}
void MemoryReader::setPosition(const char* position)
{
position_ = position;
}
void MemoryReader::read(void* data, std::size_t size)
{
YASLI_ASSERT(memory_ && position_);
YASLI_ASSERT(position_ - memory_ + size <= size_);
memcpy(data, position_, size);
position_ += size;
}
bool MemoryReader::checkedRead(void* data, std::size_t size)
{
if (!memory_ || !position_)
{
return false;
}
if (position_ - memory_ + size > size_)
{
return false;
}
memcpy(data, position_, size);
position_ += size;
return true;
}
bool MemoryReader::checkedSkip(std::size_t size)
{
if (!memory_ || !position_)
{
return false;
}
if (position_ - memory_ + size > size_)
{
return false;
}
position_ += size;
return true;
}
}
@@ -0,0 +1,56 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
// Original file Copyright Crytek GMBH or its affiliates, used under license.
#pragma once
#include <cstddef>
namespace Serialization {
class MemoryReader
{
public:
MemoryReader();
MemoryReader(const void* memory, size_t size, bool ownAndFree = false);
~MemoryReader();
void setPosition(const char* position);
const char* position(){ return position_; }
template<class T>
void read(T& value)
{
read(reinterpret_cast<void*>(&value), sizoef(value));
}
void read(void* data, size_t size);
bool checkedSkip(size_t size);
bool checkedRead(void* data, size_t size);
template<class T>
bool checkedRead(T& t)
{
return checkedRead((void*)&t, sizeof(t));
}
const char* buffer() const{ return memory_; }
size_t size() const{ return size_; }
const char* begin() const{ return memory_; }
const char* end() const{ return memory_ + size_; }
private:
size_t size_;
const char* position_;
const char* memory_;
bool ownedMemory_;
};
}
// vim:ts=4 sw=4:
@@ -0,0 +1,236 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
// Original file Copyright Crytek GMBH or its affiliates, used under license.
#include "CrySystem_precompiled.h"
#include <platform.h>
#include "Serialization/Assert.h"
#include <stdio.h>
#include <stdlib.h>
#include <cstring>
#include <math.h>
#ifdef _MSC_VER
# include <float.h>
# define isnan _isnan
#endif
#include "MemoryWriter.h"
#undef YASLI_ASSERT
#define YASLI_ASSERT(x)
namespace Serialization {
MemoryWriter::MemoryWriter(std::size_t size, bool reallocate)
: size_(size)
, reallocate_(reallocate)
, digits_(5)
{
allocate(size);
}
MemoryWriter::~MemoryWriter()
{
position_ = 0;
CryModuleFree(memory_);
}
void MemoryWriter::allocate(std::size_t initialSize)
{
memory_ = (char*)CryModuleMalloc(initialSize + 1);
position_ = memory_;
}
void MemoryWriter::reallocate(std::size_t newSize)
{
YASLI_ASSERT(newSize > size_);
std::size_t pos = position();
// Supressing the warning as we generally don't handle malloc errors.
// cppcheck-suppress memleakOnRealloc
memory_ = (char*)CryModuleRealloc(memory_, newSize + 1);
YASLI_ASSERT(memory_ != 0);
position_ = memory_ + pos;
size_ = newSize;
}
MemoryWriter& MemoryWriter::operator<<(int value)
{
// TODO: optimize
char buffer[12];
sprintf_s(buffer, "%i", value);
return operator<<((const char*)buffer);
}
MemoryWriter& MemoryWriter::operator<<(long value)
{
// TODO: optimize
char buffer[12];
#ifdef _MSC_VER
sprintf_s(buffer, "%i", value);
#else
sprintf_s(buffer, "%li", value);
#endif
return operator<<((const char*)buffer);
}
MemoryWriter& MemoryWriter::operator<<(unsigned long value)
{
// TODO: optimize
char buffer[12];
#ifdef _MSC_VER
sprintf_s(buffer, "%u", value);
#else
sprintf_s(buffer, "%lu", value);
#endif
return operator<<((const char*)buffer);
}
MemoryWriter& MemoryWriter::operator<<(long long value)
{
// TODO: optimize
char buffer[24];
#ifdef _MSC_VER
sprintf_s(buffer, "%I64i", value);
#else
sprintf_s(buffer, "%lli", value);
#endif
return operator<<((const char*)buffer);
}
MemoryWriter& MemoryWriter::operator<<(unsigned long long value)
{
// TODO: optimize
char buffer[24];
sprintf_s(buffer, "%llu", value);
return operator<<((const char*)buffer);
}
MemoryWriter& MemoryWriter::operator<<(unsigned int value)
{
// TODO: optimize
char buffer[12];
sprintf_s(buffer, "%u", value);
return operator<<((const char*)buffer);
}
MemoryWriter& MemoryWriter::operator<<(char value)
{
char buffer[12];
sprintf_s(buffer, "%i", int(value));
return operator<<((const char*)buffer);
}
MemoryWriter& MemoryWriter::operator<<(unsigned char value)
{
char buffer[12];
sprintf_s(buffer, "%i", int(value));
return operator<<((const char*)buffer);
}
MemoryWriter& MemoryWriter::operator<<(signed char value)
{
char buffer[12];
sprintf_s(buffer, "%i", int(value));
return operator<<((const char*)buffer);
}
inline void cutRightZeros(const char* str)
{
for (char* p = (char*)str + strlen(str) - 1; p >= str; --p)
{
if (*p == '0')
{
*p = 0;
}
else
{
return;
}
}
}
MemoryWriter& MemoryWriter::operator<<(double value)
{
YASLI_ASSERT(!isnan(value));
char buf[64] = { 0 };
sprintf_s(buf, "%f", value);
operator<<(buf);
return *this;
}
MemoryWriter& MemoryWriter::operator<<(const char* value)
{
write((void*)value, strlen(value));
YASLI_ASSERT(position() < size());
*position_ = '\0';
return *this;
}
MemoryWriter& MemoryWriter::operator<<(const wchar_t* value)
{
write((void*)value, wcslen(value) * sizeof(wchar_t));
YASLI_ASSERT(position() < size());
*position_ = '\0';
return *this;
}
void MemoryWriter::setPosition(std::size_t pos)
{
YASLI_ASSERT(pos < size_);
YASLI_ASSERT(memory_ + pos <= position_);
position_ = memory_ + pos;
}
void MemoryWriter::write(const char* value)
{
write((void*)value, strlen(value));
}
bool MemoryWriter::write(const void* data, std::size_t size)
{
YASLI_ASSERT(memory_ <= position_);
YASLI_ASSERT(position() < this->size());
if (size_ - position() > size)
{
memcpy(position_, data, size);
position_ += size;
}
else
{
if (!reallocate_)
{
return false;
}
reallocate(size_ * 2);
write(data, size);
}
YASLI_ASSERT(position() < this->size());
return true;
}
void MemoryWriter::write(char c)
{
if (size_ - position() > 1)
{
*(char*)(position_) = c;
++position_;
}
else
{
YASLI_ESCAPE(reallocate_, return );
reallocate(size_ * 2);
write(c);
}
YASLI_ASSERT(position() < this->size());
}
}
@@ -0,0 +1,72 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
// Original file Copyright Crytek GMBH or its affiliates, used under license.
#pragma once
#include <cstddef>
namespace Serialization {
class MemoryWriter
{
public:
MemoryWriter(std::size_t size = 128, bool reallocate = true);
~MemoryWriter();
const char* c_str() { return memory_; };
const wchar_t* w_str() { return (wchar_t*)memory_; };
char* buffer() { return memory_; }
const char* buffer() const { return memory_; }
std::size_t size() const{ return size_; }
void clear() { position_ = memory_; }
// String interface (after this calls '\0' is always written)
MemoryWriter& operator<<(int value);
MemoryWriter& operator<<(long value);
MemoryWriter& operator<<(unsigned long value);
MemoryWriter& operator<<(unsigned int value);
MemoryWriter& operator<<(long long value);
MemoryWriter& operator<<(unsigned long long value);
MemoryWriter& operator<<(float value) { return (*this) << double(value); }
MemoryWriter& operator<<(double value);
MemoryWriter& operator<<(signed char value);
MemoryWriter& operator<<(unsigned char value);
MemoryWriter& operator<<(char value);
MemoryWriter& operator<<(const char* value);
MemoryWriter& operator<<(const wchar_t* value);
// Binary interface (does not writes trailing '\0')
template<class T>
void write(const T& value)
{
write(reinterpret_cast<const T*>(&value), sizeof(value));
}
void write(char c);
void write(const char* str);
bool write(const void* data, std::size_t size);
std::size_t position() const{ return position_ - memory_; }
void setPosition(std::size_t pos);
MemoryWriter& setDigits(int digits) { digits_ = (unsigned char)digits; return *this; }
private:
void allocate(std::size_t initialSize);
void reallocate(std::size_t newSize);
std::size_t size_;
char* position_;
char* memory_;
bool reallocate_;
unsigned char digits_;
};
}
@@ -0,0 +1,492 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
// Original file Copyright Crytek GMBH or its affiliates, used under license.
#include "CrySystem_precompiled.h"
#include <AzTest/AzTest.h>
#include <AzCore/UnitTest/TestTypes.h>
#include "ArchiveHost.h"
#include <Serialization/STL.h>
#include <Serialization/IArchive.h>
#include <Serialization/StringList.h>
#include <Serialization/SmartPtr.h>
#include <memory>
namespace Serialization
{
struct SMember
{
string name;
float weight;
SMember()
: weight(0.0f)
{}
void CheckEquality(const SMember& copy) const
{
EXPECT_TRUE(name == copy.name);
EXPECT_TRUE(weight == copy.weight);
}
void Change(int index)
{
name = "Changed name ";
name += (index % 10) + '0';
weight = float(index);
}
void Serialize(IArchive& ar)
{
ar(name, "name");
ar(weight, "weight");
}
};
class CPolyBase
: public _i_reference_target_t
{
public:
CPolyBase()
{
baseMember = "Regular base member";
}
virtual void Change()
{
baseMember = "Changed base member";
}
virtual void Serialize(IArchive& ar)
{
ar(baseMember, "baseMember");
}
virtual void CheckEquality(const CPolyBase* copy) const
{
EXPECT_TRUE(baseMember == copy->baseMember);
}
virtual bool IsDerivedA() const
{
return false;
}
virtual bool IsDerivedB() const
{
return false;
}
protected:
string baseMember;
};
class CPolyDerivedA
: public CPolyBase
{
public:
void Serialize(IArchive& ar)
{
CPolyBase::Serialize(ar);
ar(derivedMember, "derivedMember");
}
bool IsDerivedA() const override
{
return true;
}
void CheckEquality(const CPolyBase* copyBase) const
{
EXPECT_TRUE(copyBase->IsDerivedA());
const CPolyDerivedA* copy = (CPolyDerivedA*)copyBase;
EXPECT_TRUE(derivedMember == copy->derivedMember);
CPolyBase::CheckEquality(copyBase);
}
protected:
string derivedMember;
};
class CPolyDerivedB
: public CPolyBase
{
public:
CPolyDerivedB()
: derivedMember("B Derived")
{}
bool IsDerivedB() const override
{
return true;
}
void Serialize(IArchive& ar)
{
CPolyBase::Serialize(ar);
ar(derivedMember, "derivedMember");
}
void CheckEquality(const CPolyBase* copyBase) const
{
EXPECT_TRUE(copyBase->IsDerivedB());
const CPolyDerivedB* copy = (const CPolyDerivedB*)copyBase;
EXPECT_TRUE(derivedMember == copy->derivedMember);
CPolyBase::CheckEquality(copyBase);
}
protected:
string derivedMember;
};
struct SNumericTypes
{
SNumericTypes()
: m_bool(false)
, m_char(0)
, m_int8(0)
, m_uint8(0)
, m_int16(0)
, m_uint16(0)
, m_int32(0)
, m_uint32(0)
, m_int64(0)
, m_uint64(0)
, m_float(0.0f)
, m_double(0.0)
{}
void Change()
{
m_bool = true;
m_char = -1;
m_int8 = -2;
m_uint8 = 0xff - 3;
m_int16 = -6;
m_uint16 = 0xff - 7;
m_int32 = -4;
m_uint32 = -5;
m_int64 = -8ll;
m_uint64 = 9ull;
m_float = -10.0f;
m_double = -11.0;
}
void Serialize(IArchive& ar)
{
ar(m_bool, "bool");
ar(m_char, "char");
ar(m_int8, "int8");
ar(m_uint8, "uint8");
ar(m_int16, "int16");
ar(m_uint16, "uint16");
ar(m_int32, "int32");
ar(m_uint32, "uint32");
ar(m_int64, "int64");
ar(m_uint64, "uint64");
ar(m_float, "float");
ar(m_double, "double");
}
void CheckEquality(const SNumericTypes& rhs) const
{
EXPECT_TRUE(m_bool == rhs.m_bool);
EXPECT_TRUE(m_char == rhs.m_char);
EXPECT_TRUE(m_int8 == rhs.m_int8);
EXPECT_TRUE(m_uint8 == rhs.m_uint8);
EXPECT_TRUE(m_int16 == rhs.m_int16);
EXPECT_TRUE(m_uint16 == rhs.m_uint16);
EXPECT_TRUE(m_int32 == rhs.m_int32);
EXPECT_TRUE(m_uint32 == rhs.m_uint32);
EXPECT_TRUE(m_int64 == rhs.m_int64);
EXPECT_TRUE(m_uint64 == rhs.m_uint64);
EXPECT_TRUE(m_float == rhs.m_float);
EXPECT_TRUE(m_double == rhs.m_double);
}
bool m_bool;
char m_char;
int8 m_int8;
uint8 m_uint8;
int16 m_int16;
uint16 m_uint16;
int32 m_int32;
uint32 m_uint32;
int64 m_int64;
uint64 m_uint64;
float m_float;
double m_double;
};
class CComplexClass
{
public:
CComplexClass()
: index(0)
{
name = "Foo";
stringList.push_back("Choice 1");
stringList.push_back("Choice 2");
stringList.push_back("Choice 3");
polyPtr.reset(new CPolyDerivedA());
polyVector.push_back(new CPolyDerivedB);
polyVector.push_back(new CPolyBase);
SMember& a = stringToStructMap["a"];
a.name = "A";
SMember& b = stringToStructMap["b"];
b.name = "B";
members.resize(13);
intToString.push_back(std::make_pair(1, "one"));
intToString.push_back(std::make_pair(2, "two"));
intToString.push_back(std::make_pair(3, "three"));
stringToInt.push_back(std::make_pair("one", 1));
stringToInt.push_back(std::make_pair("two", 2));
stringToInt.push_back(std::make_pair("three", 3));
}
void Change()
{
name = "Slightly changed name";
index = 2;
polyPtr.reset(new CPolyDerivedB());
polyPtr->Change();
for (size_t i = 0; i < members.size(); ++i)
{
members[i].Change(int(i));
}
members.erase(members.begin());
for (size_t i = 0; i < polyVector.size(); ++i)
{
polyVector[i]->Change();
}
polyVector.resize(4);
polyVector.push_back(new CPolyBase());
polyVector[4]->Change();
const size_t arrayLen = sizeof(array) / sizeof(array[0]);
for (size_t i = 0; i < arrayLen; ++i)
{
array[i].Change(int(arrayLen - i));
}
numericTypes.Change();
vectorOfStrings.push_back("str1");
vectorOfStrings.push_back("2str");
vectorOfStrings.push_back("thirdstr");
stringToStructMap.erase("a");
SMember& c = stringToStructMap["c"];
c.name = "C";
intToString.push_back(std::make_pair(4, "four"));
stringToInt.push_back(std::make_pair("four", 4));
}
void Serialize(IArchive& ar)
{
ar(name, "name");
ar(polyPtr, "polyPtr");
ar(polyVector, "polyVector");
ar(members, "members");
{
StringListValue value(stringList, stringList[index]);
ar(value, "stringList");
index = value.index();
if (index == -1)
{
index = 0;
}
}
ar(array, "array");
ar(numericTypes, "numericTypes");
ar(vectorOfStrings, "vectorOfStrings");
ar(stringToInt, "stringToInt");
}
void CheckEquality(const CComplexClass& copy) const
{
EXPECT_TRUE(name == copy.name);
EXPECT_TRUE(index == copy.index);
EXPECT_TRUE(polyPtr != 0);
EXPECT_TRUE(copy.polyPtr != 0);
polyPtr->CheckEquality(copy.polyPtr);
EXPECT_TRUE(members.size() == copy.members.size());
for (size_t i = 0; i < members.size(); ++i)
{
members[i].CheckEquality(copy.members[i]);
}
EXPECT_TRUE(polyVector.size() == copy.polyVector.size());
for (size_t i = 0; i < polyVector.size(); ++i)
{
if (polyVector[i] == 0)
{
EXPECT_TRUE(copy.polyVector[i] == 0);
continue;
}
EXPECT_TRUE(copy.polyVector[i] != 0);
polyVector[i]->CheckEquality(copy.polyVector[i]);
}
const size_t arrayLen = sizeof(array) / sizeof(array[0]);
for (size_t i = 0; i < arrayLen; ++i)
{
array[i].CheckEquality(copy.array[i]);
}
numericTypes.CheckEquality(copy.numericTypes);
EXPECT_TRUE(stringToInt.size() == copy.stringToInt.size());
for (size_t i = 0; i < stringToInt.size(); ++i)
{
EXPECT_TRUE(stringToInt[i] == copy.stringToInt[i]);
}
}
protected:
string name;
typedef std::vector<SMember> Members;
std::vector<string> vectorOfStrings;
std::vector<std::pair<int, string> > intToString;
std::vector<std::pair<string, int> > stringToInt;
Members members;
int32 index;
SNumericTypes numericTypes;
StringListStatic stringList;
std::vector< _smart_ptr<CPolyBase> > polyVector;
_smart_ptr<CPolyBase> polyPtr;
std::map<string, SMember> stringToStructMap;
SMember array[5];
};
struct ArchiveHostTests
: ::testing::Test
{
public:
void SetUp() override
{
AZ::AllocatorInstance<AZ::LegacyAllocator>::Create();
AZ::AllocatorInstance<CryStringAllocator>::Create();
m_classFactoryRTTI = AZStd::make_unique<ClassFactoryRTTI>();
}
void TearDown()
{
m_classFactoryRTTI.reset();
AZ::AllocatorInstance<CryStringAllocator>::Destroy();
AZ::AllocatorInstance<AZ::LegacyAllocator>::Destroy();
}
struct ClassFactoryRTTI
{
ClassFactoryRTTI()
: CPolyBaseCPolyBase_DerivedDescription("base", "Base")
, CPolyBaseCPolyBase_Creator(&CPolyBaseCPolyBase_DerivedDescription)
, TypeCPolyBase_DerivedDescription("derived_a", "Derived A")
, TypeCPolyBase_Creator(&TypeCPolyBase_DerivedDescription)
, CPolyDerivedBCPolyBase_DerivedDescription("derived_b", "Derived B")
, CPolyDerivedBCPolyBase_Creator(&CPolyDerivedBCPolyBase_DerivedDescription)
{}
~ClassFactoryRTTI()
{
Serialization::ClassFactory<CPolyBase>::destroy();
}
const Serialization::TypeDescription CPolyBaseCPolyBase_DerivedDescription;
Serialization::ClassFactory<CPolyBase>::Creator<CPolyBase> CPolyBaseCPolyBase_Creator;
const Serialization::TypeDescription TypeCPolyBase_DerivedDescription;
Serialization::ClassFactory<CPolyBase>::Creator<CPolyDerivedA> TypeCPolyBase_Creator;
const Serialization::TypeDescription CPolyDerivedBCPolyBase_DerivedDescription;
Serialization::ClassFactory<CPolyBase>::Creator<CPolyDerivedB> CPolyDerivedBCPolyBase_Creator;
};
AZStd::unique_ptr<ClassFactoryRTTI> m_classFactoryRTTI;
};
TEST_F(ArchiveHostTests, JsonBasicTypes)
{
std::unique_ptr<IArchiveHost> host(CreateArchiveHost());
DynArray<char> bufChanged;
CComplexClass objChanged;
objChanged.Change();
host->SaveJsonBuffer(bufChanged, SStruct(objChanged));
EXPECT_TRUE(!bufChanged.empty());
DynArray<char> bufResaved;
{
CComplexClass obj;
EXPECT_TRUE(host->LoadJsonBuffer(SStruct(obj), bufChanged.data(), bufChanged.size()));
EXPECT_TRUE(host->SaveJsonBuffer(bufResaved, SStruct(obj)));
EXPECT_TRUE(!bufResaved.empty());
obj.CheckEquality(objChanged);
}
EXPECT_TRUE(bufChanged.size() == bufResaved.size());
for (size_t i = 0; i < bufChanged.size(); ++i)
{
EXPECT_TRUE(bufChanged[i] == bufResaved[i]);
}
}
TEST_F(ArchiveHostTests, BinBasicTypes)
{
std::unique_ptr<IArchiveHost> host(CreateArchiveHost());
DynArray<char> bufChanged;
CComplexClass objChanged;
objChanged.Change();
host->SaveBinaryBuffer(bufChanged, SStruct(objChanged));
EXPECT_TRUE(!bufChanged.empty());
DynArray<char> bufResaved;
{
CComplexClass obj;
EXPECT_TRUE(host->LoadBinaryBuffer(SStruct(obj), bufChanged.data(), bufChanged.size()));
EXPECT_TRUE(host->SaveBinaryBuffer(bufResaved, SStruct(obj)));
EXPECT_TRUE(!bufResaved.empty());
obj.CheckEquality(objChanged);
}
EXPECT_TRUE(bufChanged.size() == bufResaved.size());
for (size_t i = 0; i < bufChanged.size(); ++i)
{
EXPECT_TRUE(bufChanged[i] == bufResaved[i]);
}
}
}
@@ -0,0 +1,89 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
// Original file Copyright Crytek GMBH or its affiliates, used under license.
#pragma once
#include <string.h>
#include "Serialization/Strings.h"
namespace Serialization {
struct Token
{
Token(const char* _str = 0)
: start(_str)
, end(_str ? _str + strlen(_str) : 0)
{
}
Token(const char* _str, size_t _len)
: start(_str)
, end(_str + _len) {}
Token(const char* _start, const char* _end)
: start(_start)
, end(_end) {}
void set(const char* _start, const char* _end) { start = _start; end = _end; }
std::size_t length() const{ return end - start; }
bool operator==(const Token& rhs) const
{
if (length() != rhs.length())
{
return false;
}
return memcmp(start, rhs.start, length()) == 0;
}
bool operator==(const string& rhs) const
{
if (length() != rhs.size())
{
return false;
}
return memcmp(start, rhs.c_str(), length()) == 0;
}
bool operator==(const char* text) const
{
if (strncmp(text, start, length()) == 0)
{
return text[length()] == '\0';
}
return false;
}
bool operator!=(const char* text) const
{
if (strncmp(text, start, length()) == 0)
{
return text[length()] != '\0';
}
return true;
}
bool operator==(char c) const
{
return length() == 1 && *start == c;
}
bool operator!=(char c) const
{
return length() != 1 || *start != c;
}
operator bool() const{
return start != end;
}
string str() const{ return string(start, end); }
const char* start;
const char* end;
};
}
@@ -0,0 +1,297 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
// Original file Copyright Crytek GMBH or its affiliates, used under license.
#include "CrySystem_precompiled.h"
#include "CryExtension/Impl/ClassWeaver.h"
#include <Serialization/STL.h>
#include <Serialization/ClassFactory.h>
#include "XmlIArchive.h"
#include <Serialization/STLImpl.h>
#include <Serialization/ClassFactoryImpl.h>
namespace XmlUtil
{
int g_hintSuccess = 0;
int g_hintFail = 0;
XmlNodeRef FindChildNode(XmlNodeRef pParent, const int childIndexOverride, int& childIndexHint, const char* const name)
{
CRY_ASSERT(pParent);
if (0 <= childIndexOverride)
{
CRY_ASSERT(childIndexOverride < pParent->getChildCount());
return pParent->getChild(childIndexOverride);
}
else
{
CRY_ASSERT(name);
CRY_ASSERT(name[ 0 ]);
CRY_ASSERT(0 <= childIndexHint);
const int childCount = pParent->getChildCount();
const bool hasValidChildHint = (childIndexHint < childCount);
if (hasValidChildHint)
{
XmlNodeRef pChildNode = pParent->getChild(childIndexHint);
if (pChildNode->isTag(name))
{
g_hintSuccess++;
const int nextChildIndexHint = childIndexHint + 1;
childIndexHint = (nextChildIndexHint < childCount) ? nextChildIndexHint : 0;
return pChildNode;
}
else
{
g_hintFail++;
}
}
for (int i = 0; i < childCount; ++i)
{
XmlNodeRef pChildNode = pParent->getChild(i);
if (pChildNode->isTag(name))
{
const int nextChildIndexHint = i + 1;
childIndexHint = (nextChildIndexHint < childCount) ? nextChildIndexHint : 0;
return pChildNode;
}
}
}
return XmlNodeRef();
}
template< typename T, typename TOut >
bool ReadChildNodeAs(XmlNodeRef pParent, const int childIndexOverride, int& childIndexHint, const char* const name, TOut& valueOut)
{
XmlNodeRef pChild = FindChildNode(pParent, childIndexOverride, childIndexHint, name);
if (pChild)
{
T tmp;
const bool readValueSuccess = pChild->getAttr("value", tmp);
if (readValueSuccess)
{
valueOut = tmp;
}
return readValueSuccess;
}
return false;
}
template< typename T >
bool ReadChildNode(XmlNodeRef pParent, const int childIndexOverride, int& childIndexHint, const char* const name, T& valueOut)
{
return ReadChildNodeAs< T >(pParent, childIndexOverride, childIndexHint, name, valueOut);
}
}
Serialization::CXmlIArchive::CXmlIArchive()
: IArchive(INPUT | NO_EMPTY_NAMES)
, m_childIndexOverride(-1)
, m_childIndexHint(0)
{
}
Serialization::CXmlIArchive::CXmlIArchive(XmlNodeRef pRootNode)
: IArchive(INPUT | NO_EMPTY_NAMES)
, m_pRootNode(pRootNode)
, m_childIndexOverride(-1)
, m_childIndexHint(0)
{
CRY_ASSERT(m_pRootNode);
}
Serialization::CXmlIArchive::~CXmlIArchive()
{
}
void Serialization::CXmlIArchive::SetXmlNode(XmlNodeRef pNode)
{
m_pRootNode = pNode;
}
XmlNodeRef Serialization::CXmlIArchive::GetXmlNode() const
{
return m_pRootNode;
}
bool Serialization::CXmlIArchive::operator()(bool& value, const char* name, [[maybe_unused]] const char* label)
{
XmlNodeRef pChild = XmlUtil::FindChildNode(m_pRootNode, m_childIndexOverride, m_childIndexHint, name);
if (pChild)
{
const char* const stringValue = pChild->getAttr("value");
if (stringValue)
{
value = (strcmp("true", stringValue) == 0);
value = value || (strcmp("1", stringValue) == 0);
return true;
}
return false;
}
return false;
}
bool Serialization::CXmlIArchive::operator()(IString& value, const char* name, [[maybe_unused]] const char* label)
{
XmlNodeRef pChild = XmlUtil::FindChildNode(m_pRootNode, m_childIndexOverride, m_childIndexHint, name);
if (pChild)
{
const char* const stringValue = pChild->getAttr("value");
if (stringValue)
{
value.set(stringValue);
return true;
}
return false;
}
return false;
}
bool Serialization::CXmlIArchive::operator()([[maybe_unused]] IWString& value, [[maybe_unused]] const char* name, [[maybe_unused]] const char* label)
{
CryFatalError("CXmlIArchive::operator() with IWString is not implemented");
return false;
}
bool Serialization::CXmlIArchive::operator()(float& value, const char* name, [[maybe_unused]] const char* label)
{
return XmlUtil::ReadChildNode(m_pRootNode, m_childIndexOverride, m_childIndexHint, name, value);
}
bool Serialization::CXmlIArchive::operator()(double& value, const char* name, [[maybe_unused]] const char* label)
{
return XmlUtil::ReadChildNode(m_pRootNode, m_childIndexOverride, m_childIndexHint, name, value);
}
bool Serialization::CXmlIArchive::operator()(int16& value, const char* name, [[maybe_unused]] const char* label)
{
return XmlUtil::ReadChildNodeAs< int >(m_pRootNode, m_childIndexOverride, m_childIndexHint, name, value);
}
bool Serialization::CXmlIArchive::operator()(uint16& value, const char* name, [[maybe_unused]] const char* label)
{
return XmlUtil::ReadChildNodeAs< uint >(m_pRootNode, m_childIndexOverride, m_childIndexHint, name, value);
}
bool Serialization::CXmlIArchive::operator()(int32& value, const char* name, [[maybe_unused]] const char* label)
{
return XmlUtil::ReadChildNode(m_pRootNode, m_childIndexOverride, m_childIndexHint, name, value);
}
bool Serialization::CXmlIArchive::operator()(uint32& value, const char* name, [[maybe_unused]] const char* label)
{
return XmlUtil::ReadChildNode(m_pRootNode, m_childIndexOverride, m_childIndexHint, name, value);
}
bool Serialization::CXmlIArchive::operator()(int64& value, const char* name, [[maybe_unused]] const char* label)
{
return XmlUtil::ReadChildNode(m_pRootNode, m_childIndexOverride, m_childIndexHint, name, value);
}
bool Serialization::CXmlIArchive::operator()(uint64& value, const char* name, [[maybe_unused]] const char* label)
{
return XmlUtil::ReadChildNode(m_pRootNode, m_childIndexOverride, m_childIndexHint, name, value);
}
bool Serialization::CXmlIArchive::operator()(int8& value, const char* name, [[maybe_unused]] const char* label)
{
return XmlUtil::ReadChildNodeAs< int >(m_pRootNode, m_childIndexOverride, m_childIndexHint, name, value);
}
bool Serialization::CXmlIArchive::operator()(uint8& value, const char* name, [[maybe_unused]] const char* label)
{
return XmlUtil::ReadChildNodeAs< uint >(m_pRootNode, m_childIndexOverride, m_childIndexHint, name, value);
}
bool Serialization::CXmlIArchive::operator()(char& value, const char* name, [[maybe_unused]] const char* label)
{
return XmlUtil::ReadChildNodeAs< int >(m_pRootNode, m_childIndexOverride, m_childIndexHint, name, value);
}
bool Serialization::CXmlIArchive::operator()(const SStruct& ser, const char* name, [[maybe_unused]] const char* label)
{
CRY_ASSERT(name);
CRY_ASSERT(name[ 0 ]);
XmlNodeRef pChild = XmlUtil::FindChildNode(m_pRootNode, m_childIndexOverride, m_childIndexHint, name);
if (pChild)
{
CXmlIArchive childArchive(pChild);
childArchive.SetFilter(GetFilter());
childArchive.SetInnerContext(GetInnerContext());
const bool serializeSuccess = ser(childArchive);
return serializeSuccess;
}
return false;
}
bool Serialization::CXmlIArchive::operator()(IContainer& ser, const char* name, [[maybe_unused]] const char* label)
{
CRY_ASSERT(name);
CRY_ASSERT(name[ 0 ]);
bool serializeSuccess = true;
XmlNodeRef pChild = XmlUtil::FindChildNode(m_pRootNode, m_childIndexOverride, m_childIndexHint, name);
if (pChild)
{
const int elementCount = pChild->getChildCount();
ser.resize(elementCount);
if (0 < elementCount)
{
CXmlIArchive childArchive(pChild);
childArchive.SetFilter(GetFilter());
childArchive.SetInnerContext(GetInnerContext());
for (int i = 0; i < elementCount; ++i)
{
childArchive.m_childIndexOverride = i;
serializeSuccess &= ser(childArchive, "Element", "Element");
ser.next();
}
}
}
return serializeSuccess;
}
@@ -0,0 +1,62 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
// Original file Copyright Crytek GMBH or its affiliates, used under license.
#ifndef __XML_I_ARCHIVE__H__
#define __XML_I_ARCHIVE__H__
#include <Serialization/IArchive.h>
namespace Serialization
{
class CXmlIArchive
: public IArchive
{
public:
CXmlIArchive();
CXmlIArchive(XmlNodeRef pRootNode);
~CXmlIArchive();
void SetXmlNode(XmlNodeRef pNode);
XmlNodeRef GetXmlNode() const;
// IArchive
bool operator()(bool& value, const char* name = "", const char* label = 0) override;
bool operator()(IString& value, const char* name = "", const char* label = 0) override;
bool operator()(IWString& value, const char* name = "", const char* label = 0) override;
bool operator()(float& value, const char* name = "", const char* label = 0) override;
bool operator()(double& value, const char* name = "", const char* label = 0) override;
bool operator()(int16& value, const char* name = "", const char* label = 0) override;
bool operator()(uint16& value, const char* name = "", const char* label = 0) override;
bool operator()(int32& value, const char* name = "", const char* label = 0) override;
bool operator()(uint32& value, const char* name = "", const char* label = 0) override;
bool operator()(int64& value, const char* name = "", const char* label = 0) override;
bool operator()(uint64& value, const char* name = "", const char* label = 0) override;
bool operator()(int8& value, const char* name = "", const char* label = 0) override;
bool operator()(uint8& value, const char* name = "", const char* label = 0) override;
bool operator()(char& value, const char* name = "", const char* label = 0) override;
bool operator()(const SStruct& ser, const char* name = "", const char* label = 0) override;
bool operator()(IContainer& ser, const char* name = "", const char* label = 0) override;
// ~IArchive
using IArchive::operator();
private:
XmlNodeRef m_pRootNode;
int m_childIndexOverride;
int m_childIndexHint;
};
}
#endif
@@ -0,0 +1,213 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
// Original file Copyright Crytek GMBH or its affiliates, used under license.
#include "CrySystem_precompiled.h"
#include "CryExtension/Impl/ClassWeaver.h"
#include <Serialization/STL.h>
#include <Serialization/IClassFactory.h>
#include "XmlOArchive.h"
#include <Serialization/STLImpl.h>
#include <Serialization/ClassFactory.h>
namespace XmlUtil
{
XmlNodeRef CreateChildNode(XmlNodeRef pParent, const char* const name)
{
CRY_ASSERT(pParent);
CRY_ASSERT(name);
CRY_ASSERT(name[ 0 ]);
XmlNodeRef pChild = pParent->createNode(name);
CRY_ASSERT(pChild);
pParent->addChild(pChild);
return pChild;
}
template < typename T, typename TIn >
bool WriteChildNodeAs(XmlNodeRef pParent, const char* const name, const TIn& value)
{
XmlNodeRef pChild = XmlUtil::CreateChildNode(pParent, name);
CRY_ASSERT(pChild);
pChild->setAttr("value", static_cast< T >(value));
return true;
}
template < typename T >
bool WriteChildNode(XmlNodeRef pParent, const char* const name, const T& value)
{
return WriteChildNodeAs< T >(pParent, name, value);
}
}
Serialization::CXmlOArchive::CXmlOArchive()
: IArchive(OUTPUT | NO_EMPTY_NAMES)
{
}
Serialization::CXmlOArchive::CXmlOArchive(XmlNodeRef pRootNode)
: IArchive(OUTPUT | NO_EMPTY_NAMES)
, m_pRootNode(pRootNode)
{
CRY_ASSERT(m_pRootNode);
}
Serialization::CXmlOArchive::~CXmlOArchive()
{
}
void Serialization::CXmlOArchive::SetXmlNode(XmlNodeRef pNode)
{
m_pRootNode = pNode;
}
XmlNodeRef Serialization::CXmlOArchive::GetXmlNode() const
{
return m_pRootNode;
}
bool Serialization::CXmlOArchive::operator()(bool& value, const char* name, [[maybe_unused]] const char* label)
{
const char* const stringValue = value ? "true" : "false";
return XmlUtil::WriteChildNode(m_pRootNode, name, stringValue);
}
bool Serialization::CXmlOArchive::operator()(IString& value, const char* name, [[maybe_unused]] const char* label)
{
const char* const stringValue = value.get();
return XmlUtil::WriteChildNode(m_pRootNode, name, stringValue);
}
bool Serialization::CXmlOArchive::operator()([[maybe_unused]] IWString& value, [[maybe_unused]] const char* name, [[maybe_unused]] const char* label)
{
CryFatalError("CXmlOArchive::operator() with IWString is not implemented");
return false;
}
bool Serialization::CXmlOArchive::operator()(float& value, const char* name, [[maybe_unused]] const char* label)
{
return XmlUtil::WriteChildNode(m_pRootNode, name, value);
}
bool Serialization::CXmlOArchive::operator()(double& value, const char* name, [[maybe_unused]] const char* label)
{
return XmlUtil::WriteChildNode(m_pRootNode, name, value);
}
bool Serialization::CXmlOArchive::operator()(int16& value, const char* name, [[maybe_unused]] const char* label)
{
return XmlUtil::WriteChildNodeAs< int >(m_pRootNode, name, value);
}
bool Serialization::CXmlOArchive::operator()(uint16& value, const char* name, [[maybe_unused]] const char* label)
{
return XmlUtil::WriteChildNodeAs< uint >(m_pRootNode, name, value);
}
bool Serialization::CXmlOArchive::operator()(int32& value, const char* name, [[maybe_unused]] const char* label)
{
return XmlUtil::WriteChildNode(m_pRootNode, name, value);
}
bool Serialization::CXmlOArchive::operator()(uint32& value, const char* name, [[maybe_unused]] const char* label)
{
return XmlUtil::WriteChildNode(m_pRootNode, name, value);
}
bool Serialization::CXmlOArchive::operator()(int64& value, const char* name, [[maybe_unused]] const char* label)
{
return XmlUtil::WriteChildNode(m_pRootNode, name, value);
}
bool Serialization::CXmlOArchive::operator()(uint64& value, const char* name, [[maybe_unused]] const char* label)
{
return XmlUtil::WriteChildNode(m_pRootNode, name, value);
}
bool Serialization::CXmlOArchive::operator()(int8& value, const char* name, [[maybe_unused]] const char* label)
{
return XmlUtil::WriteChildNodeAs< int >(m_pRootNode, name, value);
}
bool Serialization::CXmlOArchive::operator()(uint8& value, const char* name, [[maybe_unused]] const char* label)
{
return XmlUtil::WriteChildNodeAs< uint >(m_pRootNode, name, value);
}
bool Serialization::CXmlOArchive::operator()(char& value, const char* name, [[maybe_unused]] const char* label)
{
return XmlUtil::WriteChildNodeAs< int >(m_pRootNode, name, value);
}
bool Serialization::CXmlOArchive::operator()(const SStruct& ser, const char* name, [[maybe_unused]] const char* label)
{
CRY_ASSERT(name);
CRY_ASSERT(name[ 0 ]);
XmlNodeRef pChild = XmlUtil::CreateChildNode(m_pRootNode, name);
CXmlOArchive childArchive(pChild);
childArchive.SetFilter(GetFilter());
childArchive.SetInnerContext(GetInnerContext());
const bool serializeSuccess = ser(childArchive);
return serializeSuccess;
}
bool Serialization::CXmlOArchive::operator()(IContainer& ser, const char* name, [[maybe_unused]] const char* label)
{
CRY_ASSERT(name);
CRY_ASSERT(name[ 0 ]);
bool serializeSuccess = true;
XmlNodeRef pChild = XmlUtil::CreateChildNode(m_pRootNode, name);
CXmlOArchive childArchive(pChild);
childArchive.SetFilter(GetFilter());
childArchive.SetInnerContext(GetInnerContext());
const size_t containerSize = ser.size();
if (0 < containerSize)
{
do
{
serializeSuccess &= ser(childArchive, "Element", "Element");
} while (ser.next());
}
return serializeSuccess;
}
@@ -0,0 +1,60 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
// Original file Copyright Crytek GMBH or its affiliates, used under license.
#ifndef __XML_O_ARCHIVE__H__
#define __XML_O_ARCHIVE__H__
#include <Serialization/IArchive.h>
namespace Serialization
{
class CXmlOArchive
: public IArchive
{
public:
CXmlOArchive();
CXmlOArchive(XmlNodeRef pRootNode);
~CXmlOArchive();
void SetXmlNode(XmlNodeRef pNode);
XmlNodeRef GetXmlNode() const;
// IArchive
bool operator()(bool& value, const char* name = "", const char* label = 0) override;
bool operator()(IString& value, const char* name = "", const char* label = 0) override;
bool operator()(IWString& value, const char* name = "", const char* label = 0) override;
bool operator()(float& value, const char* name = "", const char* label = 0) override;
bool operator()(double& value, const char* name = "", const char* label = 0) override;
bool operator()(int16& value, const char* name = "", const char* label = 0) override;
bool operator()(uint16& value, const char* name = "", const char* label = 0) override;
bool operator()(int32& value, const char* name = "", const char* label = 0) override;
bool operator()(uint32& value, const char* name = "", const char* label = 0) override;
bool operator()(int64& value, const char* name = "", const char* label = 0) override;
bool operator()(uint64& value, const char* name = "", const char* label = 0) override;
bool operator()(int8& value, const char* name = "", const char* label = 0) override;
bool operator()(uint8& value, const char* name = "", const char* label = 0) override;
bool operator()(char& value, const char* name = "", const char* label = 0) override;
bool operator()(const SStruct& ser, const char* name = "", const char* label = 0) override;
bool operator()(IContainer& ser, const char* name = "", const char* label = 0) override;
// ~IArchive
using IArchive::operator();
private:
XmlNodeRef m_pRootNode;
};
}
#endif