finish CKStateChunk refactor
This commit is contained in:
parent
50784e719c
commit
81d1e80d14
|
@ -30,16 +30,18 @@ namespace LibCmo::CK2 {
|
||||||
chk->ReadStruct(imgbytesize);
|
chk->ReadStruct(imgbytesize);
|
||||||
if (imgbytesize != 0) {
|
if (imgbytesize != 0) {
|
||||||
// get image data ptr
|
// get image data ptr
|
||||||
const void* imgdata = nullptr;
|
auto imgdata = chk->LockReadBufferWrapper(imgbytesize);
|
||||||
if (!chk->ReadDryBuffer(&imgdata, imgbytesize)) {
|
if (imgdata == nullptr) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// parse image
|
// parse image
|
||||||
VxMath::VxImageDescEx cache;
|
VxMath::VxImageDescEx cache;
|
||||||
if (!reader->ReadMemory(imgdata, imgbytesize, &cache)) {
|
if (!reader->ReadMemory(imgdata.get(), imgbytesize, &cache)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
// unlock buffer
|
||||||
|
imgdata.reset();
|
||||||
|
|
||||||
// post proc image (copy to slot)
|
// post proc image (copy to slot)
|
||||||
VxMath::VxDoBlit(&cache, slot);
|
VxMath::VxDoBlit(&cache, slot);
|
||||||
|
@ -53,9 +55,7 @@ namespace LibCmo::CK2 {
|
||||||
chk->ReadStruct(globalalpha);
|
chk->ReadStruct(globalalpha);
|
||||||
VxMath::VxDoAlphaBlit(slot, static_cast<CKBYTE>(globalalpha));
|
VxMath::VxDoAlphaBlit(slot, static_cast<CKBYTE>(globalalpha));
|
||||||
} else {
|
} else {
|
||||||
CKStateChunk::TBuffer alphabuf;
|
auto alphabuf = chk->ReadBufferWrapper();
|
||||||
CKDWORD buflen;
|
|
||||||
chk->ReadBufferWrapper(&alphabuf, &buflen);
|
|
||||||
VxMath::VxDoAlphaBlit(slot, reinterpret_cast<CKBYTE*>(alphabuf.get()));
|
VxMath::VxDoAlphaBlit(slot, reinterpret_cast<CKBYTE*>(alphabuf.get()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -78,7 +78,7 @@ namespace LibCmo::CK2 {
|
||||||
chk->ReadStruct(blueMask);
|
chk->ReadStruct(blueMask);
|
||||||
|
|
||||||
// read RGBA buffer
|
// read RGBA buffer
|
||||||
CKStateChunk::TBuffer redBuffer, greenBuffer, blueBuffer, alphaBuffer;
|
CKStateChunk::Buffer_t redBuffer, greenBuffer, blueBuffer, alphaBuffer;
|
||||||
CKDWORD bufsize;
|
CKDWORD bufsize;
|
||||||
CKDWORD bufopt;
|
CKDWORD bufopt;
|
||||||
chk->ReadStruct(bufopt);
|
chk->ReadStruct(bufopt);
|
||||||
|
@ -90,11 +90,11 @@ namespace LibCmo::CK2 {
|
||||||
// so return false simply
|
// so return false simply
|
||||||
return false;
|
return false;
|
||||||
} else {
|
} else {
|
||||||
chk->ReadBufferWrapper(&blueBuffer, &bufsize);
|
blueBuffer = chk->ReadBufferWrapper();
|
||||||
chk->ReadBufferWrapper(&greenBuffer, &bufsize);
|
greenBuffer = chk->ReadBufferWrapper();
|
||||||
chk->ReadBufferWrapper(&redBuffer, &bufsize);
|
redBuffer = chk->ReadBufferWrapper();
|
||||||
}
|
}
|
||||||
chk->ReadBufferWrapper(&alphaBuffer, &bufsize);
|
alphaBuffer = chk->ReadBufferWrapper();
|
||||||
|
|
||||||
// write into file
|
// write into file
|
||||||
if (redBuffer != nullptr && greenBuffer != nullptr && blueBuffer != nullptr) {
|
if (redBuffer != nullptr && greenBuffer != nullptr && blueBuffer != nullptr) {
|
||||||
|
|
|
@ -99,6 +99,37 @@ namespace LibCmo::CK2 {
|
||||||
|
|
||||||
#pragma endregion
|
#pragma endregion
|
||||||
|
|
||||||
|
#pragma region Self Used Data Struct
|
||||||
|
|
||||||
|
void CKStateChunk::LockedReadBufferDeleter::operator()(LIBCMO_UNUSED const void* buf) {
|
||||||
|
if (m_Host == nullptr) return;
|
||||||
|
m_Host->UnLockReadBuffer(m_ConsumedSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CKStateChunk::LockedReadBufferDeleter::SetConsumedSize(CKDWORD newsize) {
|
||||||
|
m_ConsumedSize = newsize;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CKStateChunk::LockedWriteBufferDeleter::operator()(LIBCMO_UNUSED const void* buf) {
|
||||||
|
if (m_Host == nullptr) return;
|
||||||
|
m_Host->UnLockWriteBuffer(m_ConsumedSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CKStateChunk::LockedWriteBufferDeleter::SetConsumedSize(CKDWORD newsize) {
|
||||||
|
m_ConsumedSize = newsize;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CKStateChunk::BufferDeleter::operator()(const void* buf) {
|
||||||
|
if (m_Host == nullptr) return;
|
||||||
|
m_Host->DeleteBuffer(buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
CKDWORD CKStateChunk::BufferDeleter::GetBufferSize() const {
|
||||||
|
return m_BufSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
#pragma endregion
|
||||||
|
|
||||||
#pragma region Misc Funcs
|
#pragma region Misc Funcs
|
||||||
|
|
||||||
// ========== Public Funcs ==========
|
// ========== Public Funcs ==========
|
||||||
|
@ -525,24 +556,66 @@ namespace LibCmo::CK2 {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool CKStateChunk::LockReadBuffer(const void** ppData, CKDWORD size_in_byte) {
|
||||||
/* ========== Basic Data Read Functions ==========*/
|
// check arguments
|
||||||
|
if (*ppData == nullptr) return false;
|
||||||
bool CKStateChunk::ReadByteData(void* data_ptr, CKDWORD size_in_byte) {
|
*ppData = nullptr;
|
||||||
|
// check self status
|
||||||
if (this->m_Parser.m_Status != CKStateChunkStatus::READ) return false;
|
if (this->m_Parser.m_Status != CKStateChunkStatus::READ) return false;
|
||||||
|
|
||||||
|
// get corresponding size
|
||||||
CKDWORD size_in_dword = this->GetCeilDwordSize(size_in_byte);
|
CKDWORD size_in_dword = this->GetCeilDwordSize(size_in_byte);
|
||||||
|
// ensure space
|
||||||
|
if (this->EnsureReadSpace(size_in_dword)) {
|
||||||
|
*ppData = this->m_pData + this->m_Parser.m_CurrentPos;
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
// failed, report to context
|
||||||
|
m_BindContext->OutputToConsoleEx("CKStateChunk::LockReadBuffer at buffer pos %" PRIuCKDWORD ".", this->m_Parser.m_CurrentPos);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CKStateChunk::UnLockReadBuffer(CKDWORD size_in_byte) {
|
||||||
|
// check self status
|
||||||
|
if (this->m_Parser.m_Status != CKStateChunkStatus::READ) return false;
|
||||||
|
|
||||||
|
// get corresponding size
|
||||||
|
CKDWORD size_in_dword = this->GetCeilDwordSize(size_in_byte);
|
||||||
|
// ensure space
|
||||||
if (this->EnsureReadSpace(size_in_dword)) {
|
if (this->EnsureReadSpace(size_in_dword)) {
|
||||||
// only copy when data_ptr is not nullptr
|
|
||||||
// do dry run if there are no dest to copy for.
|
|
||||||
if (data_ptr != nullptr) {
|
|
||||||
std::memcpy(data_ptr, this->m_pData + this->m_Parser.m_CurrentPos, size_in_byte);
|
|
||||||
}
|
|
||||||
this->m_Parser.m_CurrentPos += size_in_dword;
|
this->m_Parser.m_CurrentPos += size_in_dword;
|
||||||
return true;
|
return true;
|
||||||
} else {
|
} else {
|
||||||
// failed, report to context
|
// failed, report to context
|
||||||
m_BindContext->OutputToConsoleEx("CKStateChunk read length error at %" PRIuCKDWORD ".", this->m_Parser.m_CurrentPos);
|
m_BindContext->OutputToConsoleEx("CKStateChunk::UnLockReadBuffer at buffer pos %" PRIuCKDWORD ".", this->m_Parser.m_CurrentPos);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
CKStateChunk::LockedReadBuffer_t CKStateChunk::LockReadBufferWrapper(CKDWORD size_in_byte) {
|
||||||
|
const void* pData;
|
||||||
|
bool ret = LockReadBuffer(&pData, size_in_byte);
|
||||||
|
if (ret) {
|
||||||
|
return LockedReadBuffer_t(pData, LockedReadBufferDeleter(this, size_in_byte));
|
||||||
|
} else {
|
||||||
|
return LockedReadBuffer_t();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ========== Basic Data Read Functions ==========*/
|
||||||
|
|
||||||
|
|
||||||
|
bool CKStateChunk::ReadByteData(void* data_ptr, CKDWORD size_in_byte) {
|
||||||
|
if (data_ptr == nullptr) return false;
|
||||||
|
|
||||||
|
const void* pData;
|
||||||
|
bool ret = LockReadBuffer(&pData, size_in_byte);
|
||||||
|
if (ret) {
|
||||||
|
std::memcpy(data_ptr, pData, size_in_byte);
|
||||||
|
UnLockReadBuffer(size_in_byte);
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -753,38 +826,22 @@ namespace LibCmo::CK2 {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CKStateChunk::ReadBufferWrapper(TBuffer* uptr, CKDWORD* len_in_byte) {
|
|
||||||
if (uptr == nullptr || len_in_byte == nullptr) return false;
|
|
||||||
|
|
||||||
void* bufcache = nullptr;
|
|
||||||
bool ret = ReadBuffer(&bufcache, len_in_byte);
|
|
||||||
uptr->reset(bufcache);
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool CKStateChunk::ReadDryBuffer(const void** buf, CKDWORD ordered_size) {
|
|
||||||
if (buf == nullptr) return false;
|
|
||||||
|
|
||||||
// backup current pos
|
|
||||||
*buf = GetCurrentPointer();
|
|
||||||
if (!this->ReadByteData(nullptr, ordered_size)) {
|
|
||||||
*buf = nullptr;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void CKStateChunk::BufferDeleter::operator()(void* buf) {
|
|
||||||
if (buf == nullptr) return;
|
|
||||||
delete[] reinterpret_cast<const CKBYTE*>(buf);
|
|
||||||
}
|
|
||||||
|
|
||||||
void CKStateChunk::DeleteBuffer(const void* buf) {
|
void CKStateChunk::DeleteBuffer(const void* buf) {
|
||||||
if (buf == nullptr) return;
|
if (buf == nullptr) return;
|
||||||
delete[] reinterpret_cast<const CKBYTE*>(buf);
|
delete[] reinterpret_cast<const CKBYTE*>(buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CKStateChunk::Buffer_t CKStateChunk::ReadBufferWrapper() {
|
||||||
|
void* bufcache = nullptr;
|
||||||
|
CKDWORD len_in_byte;
|
||||||
|
bool ret = ReadBuffer(&bufcache, &len_in_byte);
|
||||||
|
if (ret) {
|
||||||
|
return Buffer_t(bufcache, BufferDeleter(this, len_in_byte));
|
||||||
|
} else {
|
||||||
|
return Buffer_t();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* ========== Sequence Functions ==========*/
|
/* ========== Sequence Functions ==========*/
|
||||||
|
|
||||||
bool CKStateChunk::ReadObjectIDSequence(XContainer::XArray<CK_ID>* ls) {
|
bool CKStateChunk::ReadObjectIDSequence(XContainer::XArray<CK_ID>* ls) {
|
||||||
|
@ -966,6 +1023,18 @@ namespace LibCmo::CK2 {
|
||||||
this->m_Parser.m_Status = CKStateChunkStatus::IDLE;
|
this->m_Parser.m_Status = CKStateChunkStatus::IDLE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool CKStateChunk::LockWriteBuffer(const void** ppData, CKDWORD size_in_byte) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CKStateChunk::UnLockWriteBuffer(CKDWORD size_in_byte) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
CKStateChunk::LockedWriteBuffer_t CKStateChunk::LockWriteBufferWrapper(CKDWORD size_in_byte) {
|
||||||
|
return LockedWriteBuffer_t();
|
||||||
|
}
|
||||||
|
|
||||||
#pragma endregion
|
#pragma endregion
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -37,69 +37,52 @@ namespace LibCmo::CK2 {
|
||||||
void* m_DataPtr;
|
void* m_DataPtr;
|
||||||
CKDWORD m_AreaSize;
|
CKDWORD m_AreaSize;
|
||||||
};
|
};
|
||||||
template<bool _TCanWrite>
|
|
||||||
class LockedBuffer_t {
|
class LockedReadBufferDeleter {
|
||||||
public:
|
public:
|
||||||
/**
|
LockedReadBufferDeleter() : m_Host(nullptr), m_ConsumedSize(0) {}
|
||||||
* @brief The type of free function called by this class.
|
LockedReadBufferDeleter(CKStateChunk* host, CKDWORD init_size) :
|
||||||
* It must have 2 argument, first one is buffer need to be free, second is consumed size.
|
m_Host(host), m_ConsumedSize(init_size) {}
|
||||||
*/
|
LIBCMO_DEFAULT_COPY_MOVE(LockedReadBufferDeleter);
|
||||||
using FreeFct = std::function<void(const void*,CKDWORD)>;
|
|
||||||
|
|
||||||
LockedBuffer_t() : m_Ptr(nullptr), m_ConsumedByteSize(0), m_FreeFct(nullptr) {}
|
void operator()(LIBCMO_UNUSED const void* buf);
|
||||||
LockedBuffer_t(const void* ptr, CKDWORD expectedByteSize, FreeFct fct) :
|
void SetConsumedSize(CKDWORD newsize);
|
||||||
m_Ptr(const_cast<CKBYTE*>(static_cast<const CKBYTE*>(ptr))), m_ConsumedByteSize(expectedByteSize), m_FreeFct(fct) {}
|
|
||||||
LockedBuffer_t(const LockedBuffer_t&) = delete;
|
|
||||||
LockedBuffer_t& operator=(const LockedBuffer_t&) = delete;
|
|
||||||
LockedBuffer_t(LockedBuffer_t&& rhs) :
|
|
||||||
m_Ptr(rhs.m_Ptr), m_ConsumedByteSize(rhs.m_ConsumedByteSize), m_FreeFct(rhs.m_FreeFct) {
|
|
||||||
rhs.m_Ptr = nullptr;
|
|
||||||
rhs.m_ConsumedByteSize = 0;
|
|
||||||
rhs.m_FreeFct = nullptr;
|
|
||||||
}
|
|
||||||
LockedBuffer_t& operator=(LockedBuffer_t&& rhs) {
|
|
||||||
// reset self
|
|
||||||
Reset();
|
|
||||||
// copy data
|
|
||||||
m_Ptr = rhs.m_Ptr;
|
|
||||||
m_ConsumedByteSize = rhs.m_ConsumedByteSize;
|
|
||||||
m_FreeFct = rhs.m_FreeFct;
|
|
||||||
// remove rhs data.
|
|
||||||
rhs.m_Ptr = nullptr;
|
|
||||||
rhs.m_ConsumedByteSize = 0;
|
|
||||||
rhs.m_FreeFct = nullptr;
|
|
||||||
}
|
|
||||||
~LockedBuffer_t() {
|
|
||||||
Reset();
|
|
||||||
}
|
|
||||||
|
|
||||||
const void* GetPtr() const {
|
|
||||||
return m_Ptr;
|
|
||||||
}
|
|
||||||
// References:
|
|
||||||
// https://stackoverflow.com/questions/43051882/how-to-disable-a-class-member-function-for-certain-template-types
|
|
||||||
// https://stackoverflow.com/questions/13964447/why-compile-error-with-enable-if
|
|
||||||
template<bool _UCanWrite = _TCanWrite, std::enable_if_t<sizeof(_UCanWrite) && _TCanWrite, int> = 0>
|
|
||||||
void* GetMutablePtr() {
|
|
||||||
return m_Ptr;
|
|
||||||
}
|
|
||||||
void SetRealConsumedSize(CKDWORD sizeInByte) {
|
|
||||||
m_ConsumedByteSize = sizeInByte;
|
|
||||||
}
|
|
||||||
void Reset() {
|
|
||||||
if (m_Ptr == nullptr) return;
|
|
||||||
if (m_FreeFct == nullptr) return;
|
|
||||||
m_FreeFct(m_Ptr, m_ConsumedByteSize);
|
|
||||||
|
|
||||||
m_Ptr = nullptr;
|
|
||||||
m_ConsumedByteSize = 0;
|
|
||||||
m_FreeFct = nullptr;
|
|
||||||
}
|
|
||||||
private:
|
private:
|
||||||
CKBYTE* m_Ptr;
|
CKStateChunk* m_Host;
|
||||||
CKDWORD m_ConsumedByteSize;
|
CKDWORD m_ConsumedSize;
|
||||||
FreeFct m_FreeFct;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class LockedWriteBufferDeleter {
|
||||||
|
public:
|
||||||
|
LockedWriteBufferDeleter() : m_Host(nullptr), m_ConsumedSize(0) {}
|
||||||
|
LockedWriteBufferDeleter(CKStateChunk* host, CKDWORD init_size) :
|
||||||
|
m_Host(host), m_ConsumedSize(init_size) {}
|
||||||
|
LIBCMO_DEFAULT_COPY_MOVE(LockedWriteBufferDeleter);
|
||||||
|
|
||||||
|
void operator()(LIBCMO_UNUSED const void* buf);
|
||||||
|
void SetConsumedSize(CKDWORD newsize);
|
||||||
|
private:
|
||||||
|
CKStateChunk* m_Host;
|
||||||
|
CKDWORD m_ConsumedSize;
|
||||||
|
};
|
||||||
|
|
||||||
|
class BufferDeleter {
|
||||||
|
public:
|
||||||
|
BufferDeleter() : m_Host(nullptr), m_BufSize(0) {}
|
||||||
|
BufferDeleter(CKStateChunk* host, CKDWORD bufsize) :
|
||||||
|
m_Host(host), m_BufSize(bufsize) {}
|
||||||
|
LIBCMO_DEFAULT_COPY_MOVE(BufferDeleter);
|
||||||
|
|
||||||
|
void operator()(const void* buf);
|
||||||
|
CKDWORD GetBufferSize() const;
|
||||||
|
private:
|
||||||
|
CKStateChunk* m_Host;
|
||||||
|
CKDWORD m_BufSize;
|
||||||
|
};
|
||||||
|
|
||||||
|
using LockedReadBuffer_t = std::unique_ptr<const void, LockedReadBufferDeleter>;
|
||||||
|
using LockedWriteBuffer_t = std::unique_ptr<void, LockedWriteBufferDeleter>;
|
||||||
|
using Buffer_t = std::unique_ptr<void, BufferDeleter>;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
enum class CKStateChunkStatus : CKDWORD {
|
enum class CKStateChunkStatus : CKDWORD {
|
||||||
|
@ -226,44 +209,91 @@ namespace LibCmo::CK2 {
|
||||||
return SeekIdentifierDwordAndReturnSize(static_cast<CKDWORD>(enum_v), out_size);
|
return SeekIdentifierDwordAndReturnSize(static_cast<CKDWORD>(enum_v), out_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* ========== Read Buffer Controller ==========*/
|
||||||
|
|
||||||
|
public:
|
||||||
|
/**
|
||||||
|
* @brief Lock read buffer and make sure it has at least some bytes to read.
|
||||||
|
* @param ppData[out] The pointer to pointer receiving data address.
|
||||||
|
* @param size_in_byte[in] The number of bytes present in the read buffer needs to be ensured.
|
||||||
|
* @return Treu if success (can read)
|
||||||
|
* @remark
|
||||||
|
* + It actually not lock the buffer, just make sure that the read area is okey.
|
||||||
|
* + Do not forget calling UnLockReadBuffer after all read work done.
|
||||||
|
* @see UnLockReadBuffer, ReadBufferLocker
|
||||||
|
*/
|
||||||
|
bool LockReadBuffer(const void** ppData, CKDWORD size_in_byte);
|
||||||
|
/**
|
||||||
|
* @brief Unlock read buffer and move forward with specified bytes.
|
||||||
|
* @param size_in_byte[in] The number of bytes you wish to move forward.
|
||||||
|
* This value can be different with the value passed to LockReadBuffer but should not greater than it.
|
||||||
|
* @return True if success (have enough space to move forward)
|
||||||
|
* @remark
|
||||||
|
* + It actually not unlock the buffer, just move forward reading pointer.
|
||||||
|
* + Used together with LockReadBuffer.
|
||||||
|
* @see LockReadBuffer
|
||||||
|
*/
|
||||||
|
bool UnLockReadBuffer(CKDWORD size_in_byte);
|
||||||
|
/**
|
||||||
|
* @brief A RAII wrapper for LockReadBuffer and UnLockReadBuffer.
|
||||||
|
* @param size_in_byte[in] The value passed to LockReadBuffer.
|
||||||
|
* @return A read-only buffer with RAII feature (more like std::unique_ptr).
|
||||||
|
* @remark
|
||||||
|
* + The return value is more like std::unique_ptr but it have more features.
|
||||||
|
* + If GeneralBuffer_t::GetPtr return nullptr, it mean this function is failed.
|
||||||
|
* + If you only use the pointer-getter provided by the return value, the final moving forward byte count is the value passed in this function.
|
||||||
|
* + You also can use GeneralBuffer_t::SetSize to set the final moving forward byte count before the return value free itself.
|
||||||
|
* + The value passed to GeneralBuffer_t::SetSize will finally be passed to UnLockReadBuffer.
|
||||||
|
* + You can use GeneralBuffer_t::Reset to force free the return value.
|
||||||
|
* @example
|
||||||
|
* ```
|
||||||
|
* LockedReadBuffer_t buf = ReadBufferLocker(1919810);
|
||||||
|
* if (buf.GetPtr() == nullptr) {
|
||||||
|
* // failed
|
||||||
|
* } else {
|
||||||
|
* stuff(buf); // do some operation...
|
||||||
|
* buf.SetSize(114514); // i only consume these bytes.
|
||||||
|
* buf.Reset(); // immediately free it.
|
||||||
|
* }
|
||||||
|
* ```
|
||||||
|
* @see LockReadBuffer, UnLockReadBuffer, LockedReadBuffer_t
|
||||||
|
*/
|
||||||
|
LockedReadBuffer_t LockReadBufferWrapper(CKDWORD size_in_byte);
|
||||||
|
|
||||||
/* ========== Basic Data Read Functions ==========*/
|
/* ========== Basic Data Read Functions ==========*/
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
bool LockReadBuffer(void** ppData, CKDWORD expectedByteSize);
|
|
||||||
bool UnLockReadBuffer(CKDWORD realConsumedByteSize);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief The base read function for all data.
|
* @brief A struct-read-friendly wrapper for LockReadBuffer and UnLockReadBuffer.
|
||||||
* This function will check all read requirements.
|
* All following struct reading function use this function as a underlaying calling.
|
||||||
* If you have use this function or functions calling this function. You do not need check any reading requirements anymore.
|
|
||||||
* @param data_ptr[out] the pointer to data. must be allocated first.
|
* @param data_ptr[out] the pointer to data. must be allocated first.
|
||||||
* @param size_in_byte[in] the size of data in byte.
|
* @param size_in_byte[in] the size of data in byte.
|
||||||
* @return True if success.
|
* @return True if success.
|
||||||
*/
|
*/
|
||||||
bool ReadByteData(void* data_ptr, CKDWORD size_in_byte);
|
bool ReadByteData(void* data_ptr, CKDWORD size_in_byte);
|
||||||
public:
|
public:
|
||||||
/// <summary>
|
/**
|
||||||
/// Read Struct
|
* @brief Read Struct
|
||||||
/// <para>Primitive type: ReadInt, ReadByte, ReadWord, ReadDword, ReadFloat, etc...</para>
|
* @tparam T The reading type.
|
||||||
/// <para>Struct type: ReadGuid, ReadVector, ReadMatrix, etc...</para>
|
* @param data Data pointer for reading. Can not be bullptr
|
||||||
/// <para>Both of them are redirected to this.</para>
|
* @return True if reading success.
|
||||||
/// </summary>
|
* @remark
|
||||||
/// <typeparam name="T"></typeparam>
|
* + This function is a reinterpter of a bunch of original Virtools SDK reading functions, including:
|
||||||
/// <param name="data"></param>
|
* - Primitive type: ReadInt, ReadByte, ReadWord, ReadDword, ReadFloat, etc...
|
||||||
/// <returns></returns>
|
* - Struct type: ReadGuid, ReadVector, ReadMatrix, etc...
|
||||||
|
* @see ReadStruct(T&)
|
||||||
|
*/
|
||||||
template<typename T>
|
template<typename T>
|
||||||
bool ReadStruct(T* data) {
|
bool ReadStruct(T* data) {
|
||||||
return ReadByteData(data, CKSizeof(T));
|
return ReadByteData(data, CKSizeof(T));
|
||||||
}
|
}
|
||||||
/// <summary>
|
/**
|
||||||
/// Read Struct
|
* @brief Read Struct (Reference Type)
|
||||||
/// <para>A wrapper for ReadStructPtr.</para>
|
* @tparam T The reading type.
|
||||||
/// <para>Use reference, not pointer.</para>
|
* @param data Data reference for reading.
|
||||||
/// </summary>
|
* @return True if reading success.
|
||||||
/// <typeparam name="T"></typeparam>
|
* @see ReadStruct(T*)
|
||||||
/// <param name="data"></param>
|
*/
|
||||||
/// <returns></returns>
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
inline bool ReadStruct(T& data) {
|
inline bool ReadStruct(T& data) {
|
||||||
return ReadByteData(&data, CKSizeof(T));
|
return ReadByteData(&data, CKSizeof(T));
|
||||||
|
@ -291,14 +321,12 @@ namespace LibCmo::CK2 {
|
||||||
return ReadManagerInt(&guid, &intval);
|
return ReadManagerInt(&guid, &intval);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/**
|
||||||
/// Read sub chunk
|
* @brief Read sub chunk
|
||||||
/// <para>Return nullptr if failed.</para>
|
* @return Returned a new created of CKStateChunk if success, otherwise nullptr.
|
||||||
/// <para>Returned CKStateChunk should be manually released!</para>
|
* Returned CKStateChunk should be manually released!
|
||||||
/// </summary>
|
*/
|
||||||
/// <param name=""></param>
|
CKStateChunk* ReadSubChunk();
|
||||||
/// <returns></returns>
|
|
||||||
CKStateChunk* ReadSubChunk(void);
|
|
||||||
|
|
||||||
/* ========== Buffer Functions ==========*/
|
/* ========== Buffer Functions ==========*/
|
||||||
|
|
||||||
|
@ -315,61 +343,63 @@ namespace LibCmo::CK2 {
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief The deleter for std::unique_ptr of CKStateChunk created buffer.
|
* @brief Read a buffer with unknow size (order user specific it).
|
||||||
|
* @param size_in_byte[in] The size of buffer.
|
||||||
|
* @param allocatedBuf[out] Buffer for filling.
|
||||||
|
* @return true if success.
|
||||||
|
* @remark
|
||||||
|
* + Following original Virtools functions can use this function to implement:
|
||||||
|
* - ReadAndFillBuffer(int, void*)
|
||||||
|
* - ReadAndFillBuffer_LEndian(int, void*)
|
||||||
|
* - ReadAndFillBuffer_LEndian16(int, void*)
|
||||||
*/
|
*/
|
||||||
struct BufferDeleter {
|
|
||||||
BufferDeleter() = default;
|
|
||||||
BufferDeleter(const BufferDeleter&) noexcept {}
|
|
||||||
void operator()(void* buf);
|
|
||||||
};
|
|
||||||
/**
|
|
||||||
* @brief The type of CKStateChunk auto free buffer.
|
|
||||||
*/
|
|
||||||
using TBuffer = std::unique_ptr<void, BufferDeleter>;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Read a buffer with unknow size (order user specific it).
|
|
||||||
/// <para>ReadAndFillBuffer(int, void*), ReadAndFillBuffer_LEndian(int, void*), ReadAndFillBuffer_LEndian16(int, void*) are redirected to this.</para>
|
|
||||||
/// <para>The buffer should be allocated by caller first.</para>
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="size"></param>
|
|
||||||
/// <param name="allocatedBuf"></param>
|
|
||||||
/// <returns></returns>
|
|
||||||
bool ReadNoSizeBuffer(CKDWORD size_in_byte, void* allocatedBuf);
|
bool ReadNoSizeBuffer(CKDWORD size_in_byte, void* allocatedBuf);
|
||||||
/// <summary>
|
|
||||||
/// Read a buffer with knowen size stored in chunk.
|
|
||||||
/// <para>ReadBuffer(void**), ReadAndFillBuffer(void*), ReadAndFillBuffer_LEndian(void*), ReadAndFillBuffer_LEndian16(void*) are redirected to this.</para>
|
|
||||||
/// <para>The buffer will be allocated by function.</para>
|
|
||||||
/// <para>Use CKStateChunk::DeleteBuffer() to delete it.</para>
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="buf">a pointer to the pointer receiving data start address.</param>
|
|
||||||
/// <param name="len">a pointer to the variable receiving the length of gotten buffer.</param>
|
|
||||||
/// <returns></returns>
|
|
||||||
bool ReadBuffer(void** buf, CKDWORD* len_in_byte);
|
|
||||||
/**
|
/**
|
||||||
* @brief A auto free wrapper for ReadBuffer
|
* @brief Read a buffer with knowen size stored in chunk.
|
||||||
* @param uptr The pointer to unique_ptr receiving data.
|
|
||||||
* @param len_in_byte The size of gotten buffer.
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
bool ReadBufferWrapper(TBuffer* uptr, CKDWORD* len_in_byte);
|
|
||||||
/**
|
|
||||||
* @brief Perform a dry buffer reading.
|
|
||||||
* This function will only make sure there is enough space for your reading.
|
|
||||||
* And return the start memory address to you.
|
|
||||||
* And will not create any extra memory like ReadBuffer.
|
|
||||||
* @param buf[out] a pointer to the pointer receiving data start address.
|
* @param buf[out] a pointer to the pointer receiving data start address.
|
||||||
* @param ordered_sizepin] your expected length of this buffer.
|
* @param len_in_byte[out] a pointer to the variable receiving the length of gotten buffer.
|
||||||
* @return
|
* @return true if success.
|
||||||
|
* @remark
|
||||||
|
* + Following original Virtools functions can use this function to implement:
|
||||||
|
* - ReadBuffer(void**)
|
||||||
|
* - ReadAndFillBuffer(void*)
|
||||||
|
* - ReadAndFillBuffer_LEndian(void*)
|
||||||
|
* - ReadAndFillBuffer_LEndian16(void*)
|
||||||
|
* + The created buffer should be freed by DeleteBuffer().
|
||||||
*/
|
*/
|
||||||
bool ReadDryBuffer(const void** buf, CKDWORD ordered_size);
|
bool ReadBuffer(void** buf, CKDWORD* len_in_byte);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Free the buffer allocated by CKStateChunk reading functions.
|
* @brief Free the buffer allocated by CKStateChunk reading functions.
|
||||||
* @param buf The buffer need to be free.
|
* @param buf[in] The buffer need to be free.
|
||||||
|
* @see ReadBuffer
|
||||||
*/
|
*/
|
||||||
void DeleteBuffer(const void* buf);
|
void DeleteBuffer(const void* buf);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief A RAII wrapper for ReadBuffer and DeleteBuffer
|
||||||
|
* @param uptr The pointer to unique_ptr receiving data.
|
||||||
|
* @param len_in_byte The size of gotten buffer.
|
||||||
|
* @return A buffer with RAII feature (more like std::unique_ptr).
|
||||||
|
* @remark
|
||||||
|
* + The return value is more like std::unique_ptr but it have more features.
|
||||||
|
* + If Buffer_t::GetPtr return nullptr, it mean this function is failed.
|
||||||
|
* + Use Buffer_t::GetSize to get the size of buffer.
|
||||||
|
* + You can use Buffer_t::Reset to force free the return value.
|
||||||
|
* @example
|
||||||
|
* ```
|
||||||
|
* Buffer_t buf = ReadBufferWrapper(1919810);
|
||||||
|
* if (buf.GetPtr() == nullptr) {
|
||||||
|
* // failed
|
||||||
|
* } else {
|
||||||
|
* stuff(buf); // do some operation...
|
||||||
|
* buf.SetSize(114514); // i only consume these bytes.
|
||||||
|
* buf.Reset(); // immediately free it.
|
||||||
|
* }
|
||||||
|
* ```
|
||||||
|
*/
|
||||||
|
Buffer_t ReadBufferWrapper();
|
||||||
|
|
||||||
/* ========== Sequence Functions ==========*/
|
/* ========== Sequence Functions ==========*/
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -476,6 +506,10 @@ namespace LibCmo::CK2 {
|
||||||
*/
|
*/
|
||||||
void StopWrite(void);
|
void StopWrite(void);
|
||||||
|
|
||||||
|
bool LockWriteBuffer(const void** ppData, CKDWORD size_in_byte);
|
||||||
|
bool UnLockWriteBuffer(CKDWORD size_in_byte);
|
||||||
|
LockedWriteBuffer_t LockWriteBufferWrapper(CKDWORD size_in_byte);
|
||||||
|
|
||||||
#pragma endregion
|
#pragma endregion
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -168,9 +168,7 @@ namespace LibCmo::CK2::ObjImpls {
|
||||||
|
|
||||||
// save properties
|
// save properties
|
||||||
if (chunk->SeekIdentifier(CK_STATESAVEFLAGS_TEXTURE::CK_STATESAVE_TEXSAVEFORMAT)) {
|
if (chunk->SeekIdentifier(CK_STATESAVEFLAGS_TEXTURE::CK_STATESAVE_TEXSAVEFORMAT)) {
|
||||||
CKDWORD bufsize;
|
auto buf = chunk->ReadBufferWrapper();
|
||||||
CKStateChunk::TBuffer buf;
|
|
||||||
chunk->ReadBufferWrapper(&buf, &bufsize);
|
|
||||||
if (buf != nullptr) {
|
if (buf != nullptr) {
|
||||||
FakeBitmapProperties* props = reinterpret_cast<FakeBitmapProperties*>(buf.get());
|
FakeBitmapProperties* props = reinterpret_cast<FakeBitmapProperties*>(buf.get());
|
||||||
|
|
||||||
|
|
|
@ -222,7 +222,7 @@ namespace Unvirt::StructFormatter {
|
||||||
|
|
||||||
// write identifiers
|
// write identifiers
|
||||||
operchunk->StartRead();
|
operchunk->StartRead();
|
||||||
const auto collection = operchunk->GetIdentifierProfile();
|
const auto collection = operchunk->GetIdentifiersProfile();
|
||||||
operchunk->StopRead();
|
operchunk->StopRead();
|
||||||
fputs(UNVIRT_TERMCOL_LIGHT_YELLOW(("Identifiers\n")), stdout);
|
fputs(UNVIRT_TERMCOL_LIGHT_YELLOW(("Identifiers\n")), stdout);
|
||||||
fputs("Identifier\tData Pointer\tData Size\n", stdout);
|
fputs("Identifier\tData Pointer\tData Size\n", stdout);
|
||||||
|
|
Loading…
Reference in New Issue
Block a user