You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
o3de/Code/CryEngine/Cry3DEngine/CGF/ChunkFileWriters.h

342 lines
9.2 KiB
C++

/*
* 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 CRYINCLUDE_CRY3DENGINE_CGF_CHUNKFILEWRITERS_H
#define CRYINCLUDE_CRY3DENGINE_CGF_CHUNKFILEWRITERS_H
#pragma once
#include "ChunkFileComponents.h"
// RESOURCE_COMPIELR is defined by max plugin, too, and the max plugin MAY NOT include any of azcore
// or anything else which uses modern C++
#if !defined(RESOURCE_COMPILER)
#include <AzCore/IO/FileIO.h>
#endif
namespace AZ::IO
{
struct IArchive;
}
namespace ChunkFile
{
struct IWriter
{
virtual ~IWriter()
{
}
virtual void Erase() = 0;
virtual void Close() = 0; // if Close() is not called then the file should be deleted in destructor
virtual int32 GetPos() const = 0;
virtual bool Write(const void* buffer, size_t size) = 0;
// non-virtual helper function
bool WriteZeros(size_t size);
};
class OsFileWriter
: public IWriter
{
public:
OsFileWriter();
virtual ~OsFileWriter();
bool Create(const char* filename);
//-------------------------------------------------------
// IWriter interface
virtual void Erase();
virtual void Close();
virtual int32 GetPos() const;
virtual bool Write(const void* buffer, size_t size);
//-------------------------------------------------------
private:
string m_filename;
FILE* m_f;
int32 m_offset;
};
#if !defined(RESOURCE_COMPILER)
class CryPakFileWriter
: public IWriter
{
public:
CryPakFileWriter();
virtual ~CryPakFileWriter();
bool Create(AZ::IO::IArchive* pPak, const char* filename);
//-------------------------------------------------------
// IWriter interface
virtual void Erase();
virtual void Close();
virtual int32 GetPos() const;
virtual bool Write(const void* buffer, size_t size);
//-------------------------------------------------------
private:
string m_filename;
AZ::IO::IArchive* m_pPak;
AZ::IO::HandleType m_fileHandle;
int32 m_offset;
};
#endif
// Doesn't write any data, just computes the size
class SizeWriter
: public IWriter
{
public:
SizeWriter()
{
}
virtual ~SizeWriter()
{
}
void Start()
{
m_offset = 0;
}
//-------------------------------------------------------
// IWriter interface
virtual void Erase()
{
}
virtual void Close()
{
}
virtual int32 GetPos() const
{
return m_offset;
}
virtual bool Write([[maybe_unused]] const void* buffer, size_t size)
{
m_offset += size;
return true;
}
//-------------------------------------------------------
private:
int32 m_offset;
};
class MemoryWriter
: public IWriter
{
public:
MemoryWriter();
virtual ~MemoryWriter();
bool Start(void* ptr, int32 size);
//-------------------------------------------------------
// IWriter interface
virtual void Erase();
virtual void Close();
virtual int32 GetPos() const;
virtual bool Write(const void* buffer, size_t size);
//-------------------------------------------------------
private:
char* m_ptr;
int32 m_size;
int32 m_offset;
};
// Memoryless chunk file writer
//
// Usage example:
//
// OsFileWriter writer;
// if (!writer.Create(filename))
// {
// showAnErrorMessage();
// }
// else
// {
// MemorylessChunkFileWriter wr(eChunFileFormat, writer);
// while (wr.StartPass())
// {
// // default alignment of chunk data in file is 4, but you may change it by calling wr.SetAlignment(xxx)
//
// wr.StartChunk(eEndianness_Native, chunkA_type, chunkA_version, chunkA_id);
// wr.AddChunkData(data_ptr0, data_size0); // make sure that data have endianness specified by bLittleEdndian
// wr.AddChunkData(data_ptr1, data_size1);
// ...
// wr.StartChunk(eEndianness_Native, chunkB_type, chunkB_version, chunkB_id);
// wr.AddChunkData(data_ptrN, data_sizeN);
// ...
// }
// if (!wr.HasWrittenSuccessfully())
// {
// showAnErrorMessage();
// }
// }
//
// Usage example (interface way): see
//
// OsFileWriter writer;
// if (!writer.Create(filename))
// {
// showAnErrorMessage();
// }
// else
// {
// MemorylessChunkFileWriter wr(eChunFileFormat, writer);
// while (wr.StartPass())
// {
// // default alignment of chunk data in file is 4, but you may change it by calling wr.SetAlignment(xxx)
//
// wr.StartChunk(eEndianness_Native, chunkA_type, chunkA_version, chunkA_id);
// wr.AddChunkData(data_ptr0, data_size0); // make sure that data have endianness specified by bLittleEdndian
// wr.AddChunkData(data_ptr1, data_size1);
// ...
// wr.StartChunk(eEndianness_Native, chunkB_type, chunkB_version, chunkB_id);
// wr.AddChunkData(data_ptrN, data_sizeN);
// ...
// }
// if (!wr.HasWrittenSuccessfully())
// {
// showAnErrorMessage();
// }
// }
//
struct IChunkFileWriter
{
virtual ~IChunkFileWriter()
{
}
// Sets alignment for *beginning* of chunk data.
// Allowed to be called at any time, influences all future
// StartChunk() calls (until a new SetAlignment() call).
virtual void SetAlignment(size_t alignment) = 0;
// Returns false when there is no more passes left.
virtual bool StartPass() = 0;
// eEndianness specifies endianness of the data user is
// going to provide via AddChunkData*(). The data will be
// sent to the low-level writer as is, without any re-coding.
virtual void StartChunk(EEndianness eEndianness, uint32 type, uint32 version, uint32 id) = 0;
virtual void AddChunkData(void* ptr, size_t size) = 0;
virtual void AddChunkDataZeros(size_t size) = 0;
virtual void AddChunkDataAlignment(size_t alignment) = 0;
virtual bool HasWrittenSuccessfully() const = 0;
virtual IWriter* GetWriter() const = 0;
};
class MemorylessChunkFileWriter
: public IChunkFileWriter
{
public:
enum EChunkFileFormat
{
eChunkFileFormat_0x745,
eChunkFileFormat_0x746,
};
MemorylessChunkFileWriter(EChunkFileFormat eFormat, IWriter* pWriter);
//-------------------------------------------------------
// IChunkFileWriter interface
virtual ~MemorylessChunkFileWriter();
virtual void SetAlignment(size_t alignment);
virtual bool StartPass();
virtual void StartChunk(EEndianness eEndianness, uint32 type, uint32 version, uint32 id);
virtual void AddChunkData(void* ptr, size_t size);
virtual void AddChunkDataZeros(size_t size);
virtual void AddChunkDataAlignment(size_t alignment);
virtual bool HasWrittenSuccessfully() const;
virtual IWriter* GetWriter() const;
//-------------------------------------------------------
private:
void Fail();
static size_t ComputeSizeOfAlignmentArea(size_t pos, size_t alignment);
size_t GetSizeOfHeader() const;
void WriteFileHeader(int32 chunkCount, uint32 chunkTableOffsetInFile);
size_t GetSizeOfChunkTable(int32 chunkCount) const;
void WriteChunkTableHeader(int32 chunkCount);
void WriteChunkEntry();
private:
IWriter* const m_pWriter;
EChunkFileFormat m_eChunkFileFormat;
size_t m_alignment;
int32 m_chunkCount;
int32 m_chunkIndex;
uint16 m_chunkType;
uint16 m_chunkVersion;
uint32 m_chunkId;
uint32 m_chunkSize;
uint32 m_chunkOffsetInFile;
EEndianness m_chunkEndianness;
uint32 m_dataOffsetInFile;
enum EState
{
eState_Init,
eState_CountingChunks,
eState_WritingChunkTable,
eState_WritingData,
eState_Success,
eState_Fail,
};
EState m_eState;
};
} // namespace ChunkFile
#endif // CRYINCLUDE_CRY3DENGINE_CGF_CHUNKFILEWRITERS_H