123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468 |
- /*
- * Copyright (c) Contributors to the Open 3D Engine Project.
- * For complete copyright and license terms please see the LICENSE at the root of this distribution.
- *
- * SPDX-License-Identifier: Apache-2.0 OR MIT
- *
- */
- #include "CrySystem_precompiled.h"
- #include <IXml.h>
- #include "xml.h"
- #include "XmlUtils.h"
- #include "../SimpleStringPool.h"
- #include "SerializeXMLReader.h"
- #include "SerializeXMLWriter.h"
- #include <AzCore/Serialization/Locale.h>
- #include "XMLBinaryReader.h"
- //////////////////////////////////////////////////////////////////////////
- #ifdef CRY_COLLECT_XML_NODE_STATS
- SXmlNodeStats* g_pCXmlNode_Stats = 0;
- #endif
- //////////////////////////////////////////////////////////////////////////
- CXmlUtils::CXmlUtils(ISystem* pSystem)
- {
- m_pSystem = pSystem;
- #ifdef CRY_COLLECT_XML_NODE_STATS
- g_pCXmlNode_Stats = new SXmlNodeStats();
- #endif
- }
- //////////////////////////////////////////////////////////////////////////
- CXmlUtils::~CXmlUtils()
- {
- #ifdef CRY_COLLECT_XML_NODE_STATS
- delete g_pCXmlNode_Stats;
- #endif
- }
- //////////////////////////////////////////////////////////////////////////
- IXmlParser* CXmlUtils::CreateXmlParser()
- {
- const bool bReuseStrings = false; //TODO: do we ever want to reuse strings here?
- return new XmlParser(bReuseStrings);
- }
- //////////////////////////////////////////////////////////////////////////
- XmlNodeRef CXmlUtils::LoadXmlFromFile(const char* sFilename, bool bReuseStrings)
- {
- // when saving and loading data files to disk, use the invariant locale
- AZ::Locale::ScopedSerializationLocale scopedLocale;
- // XmlParser is supposed to log warnings and errors (if any),
- // so we don't need to call parser.getErrorString(),
- // CryLog() etc here.
-
- XmlParser parser(bReuseStrings);
- return parser.ParseFile(sFilename, true);
- }
- //////////////////////////////////////////////////////////////////////////
- XmlNodeRef CXmlUtils::LoadXmlFromBuffer(const char* buffer, size_t size, bool bReuseStrings, bool bSuppressWarnings)
- {
- // when saving and loading data files to disk, use the invariant locale
- AZ::Locale::ScopedSerializationLocale scopedLocale;
- XmlParser parser(bReuseStrings);
- XmlNodeRef node = parser.ParseBuffer(buffer, static_cast<int>(size), true, bSuppressWarnings);
- return node;
- }
- //////////////////////////////////////////////////////////////////////////
- class CXmlSerializer final : public IXmlSerializer
- {
- public:
- CXmlSerializer() = default;
- ~CXmlSerializer()
- {
- ClearAll();
- }
- void ClearAll()
- {
- SAFE_DELETE(m_pReaderSer);
- SAFE_DELETE(m_pReaderImpl);
- SAFE_DELETE(m_pWriterSer);
- SAFE_DELETE(m_pWriterImpl);
- }
- //////////////////////////////////////////////////////////////////////////
- void AddRef() override
- {
- ++m_nRefCount;
- }
- void Release() override
- {
- if (--m_nRefCount <= 0)
- {
- delete this;
- }
- }
- ISerialize* GetWriter(XmlNodeRef& node) override
- {
- ClearAll();
- m_pWriterImpl = new CSerializeXMLWriterImpl(node);
- m_pWriterSer = new CSimpleSerializeWithDefaults<CSerializeXMLWriterImpl>(*m_pWriterImpl);
- return m_pWriterSer;
- }
- ISerialize* GetReader(XmlNodeRef& node) override
- {
- ClearAll();
- m_pReaderImpl = new CSerializeXMLReaderImpl(node);
- m_pReaderSer = new CSimpleSerializeWithDefaults<CSerializeXMLReaderImpl>(*m_pReaderImpl);
- return m_pReaderSer;
- }
- //////////////////////////////////////////////////////////////////////////
- private:
- int m_nRefCount = 0;
- CSerializeXMLReaderImpl* m_pReaderImpl = nullptr;
- CSimpleSerializeWithDefaults<CSerializeXMLReaderImpl>* m_pReaderSer = nullptr;
- CSerializeXMLWriterImpl* m_pWriterImpl = nullptr;
- CSimpleSerializeWithDefaults<CSerializeXMLWriterImpl>* m_pWriterSer = nullptr;
- };
- //////////////////////////////////////////////////////////////////////////
- IXmlSerializer* CXmlUtils::CreateXmlSerializer()
- {
- return new CXmlSerializer;
- }
- //////////////////////////////////////////////////////////////////////////
- class CXmlBinaryDataWriterFile final : public XMLBinary::IDataWriter
- {
- public:
- CXmlBinaryDataWriterFile(const char* file)
- {
- m_fileHandle = gEnv->pCryPak->FOpen(file, "wb");
- }
- ~CXmlBinaryDataWriterFile()
- {
- if (m_fileHandle != AZ::IO::InvalidHandle)
- {
- gEnv->pCryPak->FClose(m_fileHandle);
- }
- };
- virtual bool IsOk()
- {
- return m_fileHandle != AZ::IO::InvalidHandle;
- }
- ;
- void Write(const void* pData, size_t size) override
- {
- if (m_fileHandle != AZ::IO::InvalidHandle)
- {
- gEnv->pCryPak->FWrite(pData, size, m_fileHandle);
- }
- }
- private:
- AZ::IO::HandleType m_fileHandle;
- };
- //////////////////////////////////////////////////////////////////////////
- class CXmlTableReader final : public IXmlTableReader
- {
- public:
- CXmlTableReader();
- ~CXmlTableReader() override;
- void Release() override;
- bool Begin(XmlNodeRef rootNode) override;
- int GetEstimatedRowCount() override;
- bool ReadRow(int& rowIndex) override;
- bool ReadCell(int& columnIndex, const char*& pContent, size_t& contentSize) override;
- private:
- bool m_bExcel;
- XmlNodeRef m_tableNode;
- XmlNodeRef m_rowNode;
- int m_rowNodeIndex;
- int m_row;
- int m_columnNodeIndex; // used if m_bExcel == true
- int m_column;
- size_t m_rowTextSize; // used if m_bExcel == false
- size_t m_rowTextPos; // used if m_bExcel == false
- };
- //////////////////////////////////////////////////////////////////////////
- CXmlTableReader::CXmlTableReader()
- {
- }
- //////////////////////////////////////////////////////////////////////////
- CXmlTableReader::~CXmlTableReader()
- {
- }
- //////////////////////////////////////////////////////////////////////////
- void CXmlTableReader::Release()
- {
- delete this;
- }
- //////////////////////////////////////////////////////////////////////////
- bool CXmlTableReader::Begin(XmlNodeRef rootNode)
- {
- m_tableNode = nullptr;
- if (!rootNode)
- {
- return false;
- }
- XmlNodeRef worksheetNode = rootNode->findChild("Worksheet");
- if (worksheetNode)
- {
- m_bExcel = true;
- m_tableNode = worksheetNode->findChild("Table");
- }
- else
- {
- m_bExcel = false;
- m_tableNode = rootNode->findChild("Table");
- }
- m_rowNode = nullptr;
- m_rowNodeIndex = -1;
- m_row = -1;
- return (m_tableNode != nullptr);
- }
- //////////////////////////////////////////////////////////////////////////
- int CXmlTableReader::GetEstimatedRowCount()
- {
- if (!m_tableNode)
- {
- return -1;
- }
- return m_tableNode->getChildCount();
- }
- //////////////////////////////////////////////////////////////////////////
- bool CXmlTableReader::ReadRow(int& rowIndex)
- {
- if (!m_tableNode)
- {
- return false;
- }
- m_columnNodeIndex = -1;
- m_column = -1;
- const int rowNodeCount = m_tableNode->getChildCount();
- if (m_bExcel)
- {
- for (;; )
- {
- if (++m_rowNodeIndex >= rowNodeCount)
- {
- m_rowNodeIndex = rowNodeCount;
- return false;
- }
- m_rowNode = m_tableNode->getChild(m_rowNodeIndex);
- if (!m_rowNode)
- {
- m_rowNodeIndex = rowNodeCount;
- return false;
- }
- if (!m_rowNode->isTag("Row"))
- {
- m_rowNode = nullptr;
- continue;
- }
- ++m_row;
- int index = 0;
- if (m_rowNode->getAttr("ss:Index", index))
- {
- --index; // one-based -> zero-based
- if (index < m_row)
- {
- m_rowNodeIndex = rowNodeCount;
- m_rowNode = nullptr;
- return false;
- }
- m_row = index;
- }
- rowIndex = m_row;
- return true;
- }
- }
- {
- m_rowTextSize = 0;
- m_rowTextPos = 0;
- if (++m_rowNodeIndex >= rowNodeCount)
- {
- m_rowNodeIndex = rowNodeCount;
- return false;
- }
- m_rowNode = m_tableNode->getChild(m_rowNodeIndex);
- if (!m_rowNode)
- {
- m_rowNodeIndex = rowNodeCount;
- return false;
- }
- const char* const pContent = m_rowNode->getContent();
- if (pContent)
- {
- m_rowTextSize = strlen(pContent);
- }
- m_row = m_rowNodeIndex;
- rowIndex = m_rowNodeIndex;
- return true;
- }
- }
- //////////////////////////////////////////////////////////////////////////
- bool CXmlTableReader::ReadCell(int& columnIndex, const char*& pContent, size_t& contentSize)
- {
- pContent = nullptr;
- contentSize = 0;
- if (!m_tableNode)
- {
- return false;
- }
- if (!m_rowNode)
- {
- return false;
- }
- if (m_bExcel)
- {
- const int columnNodeCount = m_rowNode->getChildCount();
- for (;; )
- {
- if (++m_columnNodeIndex >= columnNodeCount)
- {
- m_columnNodeIndex = columnNodeCount;
- return false;
- }
- XmlNodeRef columnNode = m_rowNode->getChild(m_columnNodeIndex);
- if (!columnNode)
- {
- m_columnNodeIndex = columnNodeCount;
- return false;
- }
- if (!columnNode->isTag("Cell"))
- {
- continue;
- }
- ++m_column;
- int index = 0;
- if (columnNode->getAttr("ss:Index", index))
- {
- --index; // one-based -> zero-based
- if (index < m_column)
- {
- m_columnNodeIndex = columnNodeCount;
- return false;
- }
- m_column = index;
- }
- columnIndex = m_column;
- XmlNodeRef dataNode = columnNode->findChild("Data");
- if (dataNode)
- {
- pContent = dataNode->getContent();
- if (pContent)
- {
- contentSize = strlen(pContent);
- }
- }
- return true;
- }
- }
- {
- if (m_rowTextPos >= m_rowTextSize)
- {
- return false;
- }
- const char* const pRowContent = m_rowNode->getContent();
- if (!pRowContent)
- {
- m_rowTextPos = m_rowTextSize;
- return false;
- }
- pContent = &pRowContent[m_rowTextPos];
- columnIndex = ++m_column;
- for (;; )
- {
- char c = pRowContent[m_rowTextPos++];
- if ((c == '\n') || (c == '\0'))
- {
- return true;
- }
- if (c == '\r')
- {
- // ignore all '\r' chars
- for (;; )
- {
- c = pRowContent[m_rowTextPos++];
- if ((c == '\n') || (c == '\0'))
- {
- return true;
- }
- if (c != '\r')
- {
- // broken data. '\r' expected to be followed by '\n' or '\0'.
- contentSize = 0;
- m_rowTextPos = m_rowTextSize;
- return false;
- }
- }
- }
- ++contentSize;
- }
- }
- }
- //////////////////////////////////////////////////////////////////////////
- IXmlTableReader* CXmlUtils::CreateXmlTableReader()
- {
- return new CXmlTableReader;
- }
|