From 276f6b975d92bcfdb72f302121890c5efbf056d2 Mon Sep 17 00:00:00 2001 From: Mikhail Kurinnoi Date: Fri, 19 Oct 2018 21:02:58 +0300 Subject: [PATCH] Revise 'vfs' code. Switch from struct to class, add encapsulation. Fix cFILE::fseek() logic. Fix #14 --- src/core/audio/buffer.cpp | 14 +++---- src/core/font/font.cpp | 2 +- src/core/graphics/gl_glsl.cpp | 12 +++--- src/core/model3d/model3d.cpp | 2 +- src/core/text/text.cpp | 14 +++---- src/core/texture/texture.cpp | 4 +- src/core/texture/texture_tga.cpp | 2 +- src/core/texture/texture_tga.h | 2 +- src/core/vfs/vfs.cpp | 71 ++++++++++++++++---------------- src/core/vfs/vfs.h | 41 +++++++++++------- src/core/xml/xml.cpp | 6 +-- 11 files changed, 90 insertions(+), 80 deletions(-) mode change 100755 => 100644 src/core/vfs/vfs.cpp diff --git a/src/core/audio/buffer.cpp b/src/core/audio/buffer.cpp index af0c055a..ef51e93b 100755 --- a/src/core/audio/buffer.cpp +++ b/src/core/audio/buffer.cpp @@ -46,7 +46,7 @@ constexpr unsigned DYNBUF_SIZE{16384}; // (stream) buffer size struct sStreamBuffer { std::array Buffers{}; - std::unique_ptr File{}; + std::unique_ptr File{}; OggVorbis_File mVF{}; vorbis_info *mInfo{nullptr}; }; @@ -64,12 +64,12 @@ std::unordered_map StreamBuffersMap; */ static size_t VorbisRead(void *ptr, size_t byteSize, size_t sizeToRead, void *datasource) { - sFILE *vorbisData = static_cast(datasource); + cFILE *vorbisData = static_cast(datasource); return vorbisData->fread(ptr, byteSize, sizeToRead); } static int VorbisSeek(void *datasource, ogg_int64_t offset, int whence) { - sFILE *vorbisData = static_cast(datasource); + cFILE *vorbisData = static_cast(datasource); return vorbisData->fseek(offset, whence); } static int VorbisClose(void *UNUSED(datasource)) @@ -78,7 +78,7 @@ static int VorbisClose(void *UNUSED(datasource)) } static long VorbisTell(void *datasource) { - sFILE *vorbisData = static_cast(datasource); + cFILE *vorbisData = static_cast(datasource); return vorbisData->ftell(); } @@ -372,7 +372,7 @@ ALuint vw_CreateSoundBufferFromOGG(const std::string &Name) if (Buffer) return Buffer; - std::unique_ptr file = vw_fopen(Name); + std::unique_ptr file = vw_fopen(Name); if (!file) return 0; @@ -438,11 +438,11 @@ ALuint vw_CreateSoundBufferFromWAV(const std::string &Name) if (Buffer) return Buffer; - std::unique_ptr file = vw_fopen(Name); + std::unique_ptr file = vw_fopen(Name); if (!file) return 0; - Buffer = alutCreateBufferFromFileImage(file->Data.get(), file->Size); + Buffer = alutCreateBufferFromFileImage(file->GetData(), static_cast(file->GetSize())); if (!CheckALUTError(__func__)) return 0; diff --git a/src/core/font/font.cpp b/src/core/font/font.cpp index 7d389d57..2ddf44a6 100755 --- a/src/core/font/font.cpp +++ b/src/core/font/font.cpp @@ -153,7 +153,7 @@ int vw_InitFont(const std::string &FontName) if (InternalFontBuffer.get()) InternalFontBuffer.reset(); - std::unique_ptr FontFile = vw_fopen(FontName); + std::unique_ptr FontFile = vw_fopen(FontName); if (!FontFile) { std::cerr << __func__ << "(): " << "Can't open font file: " << FontName << "\n"; return ERR_FILE_NOT_FOUND; diff --git a/src/core/graphics/gl_glsl.cpp b/src/core/graphics/gl_glsl.cpp index b364cf76..d3b1191b 100755 --- a/src/core/graphics/gl_glsl.cpp +++ b/src/core/graphics/gl_glsl.cpp @@ -236,7 +236,7 @@ std::weak_ptr vw_CreateShader(const std::string &ShaderName, // create empty object ShadersMap[ShaderName]->VertexShader = pfn_glCreateShader(GL_VERTEX_SHADER); - std::unique_ptr VertexFile = vw_fopen(VertexShaderFileName); + std::unique_ptr VertexFile = vw_fopen(VertexShaderFileName); if (!VertexFile) { ShadersMap.erase(ShaderName); @@ -244,8 +244,8 @@ std::weak_ptr vw_CreateShader(const std::string &ShaderName, return std::weak_ptr{}; } - const GLchar *TmpGLchar = (const GLchar *)VertexFile->Data.get(); - GLint TmpGLint = (GLint)VertexFile->Size; + const GLchar *TmpGLchar = (const GLchar *)VertexFile->GetData(); + GLint TmpGLint = (GLint)VertexFile->GetSize(); pfn_glShaderSource(ShadersMap[ShaderName]->VertexShader, 1, &TmpGLchar, &TmpGLint); vw_fclose(VertexFile); } @@ -254,7 +254,7 @@ std::weak_ptr vw_CreateShader(const std::string &ShaderName, // create empty object ShadersMap[ShaderName]->FragmentShader = pfn_glCreateShader(GL_FRAGMENT_SHADER); - std::unique_ptr FragmentFile = vw_fopen(FragmentShaderFileName); + std::unique_ptr FragmentFile = vw_fopen(FragmentShaderFileName); if (!FragmentFile) { ShadersMap.erase(ShaderName); @@ -262,8 +262,8 @@ std::weak_ptr vw_CreateShader(const std::string &ShaderName, return std::weak_ptr{}; } - const GLchar *TmpGLchar = (const GLchar *)FragmentFile->Data.get(); - GLint TmpGLint = (GLint)FragmentFile->Size; + const GLchar *TmpGLchar = (const GLchar *)FragmentFile->GetData(); + GLint TmpGLint = (GLint)FragmentFile->GetSize(); pfn_glShaderSource(ShadersMap[ShaderName]->FragmentShader, 1, &TmpGLchar, &TmpGLint); vw_fclose(FragmentFile); } diff --git a/src/core/model3d/model3d.cpp b/src/core/model3d/model3d.cpp index 0593835e..37c593a6 100755 --- a/src/core/model3d/model3d.cpp +++ b/src/core/model3d/model3d.cpp @@ -565,7 +565,7 @@ bool cModel3DWrapper::LoadVW3D(const std::string &FileName) if (FileName.empty()) return false; - std::unique_ptr File = vw_fopen(FileName); + std::unique_ptr File = vw_fopen(FileName); if (!File) return false; diff --git a/src/core/text/text.cpp b/src/core/text/text.cpp index d58ba3cb..7ef94c21 100755 --- a/src/core/text/text.cpp +++ b/src/core/text/text.cpp @@ -115,7 +115,7 @@ static void CreateTextTableUTF32() /* * Parse each row's block, separated by 1.SymbolSeparator, 2.SymbolEndOfLine, 3.EOF */ -static int GetRowTextBlock(std::string &CurrentTextBlock, uint8_t *Data, unsigned DataSize, unsigned &i, +static int GetRowTextBlock(std::string &CurrentTextBlock, uint8_t *Data, long DataSize, long &i, const char SymbolSeparator, const char SymbolEndOfLine) { constexpr char SymbolQuotes{'\"'}; @@ -159,7 +159,7 @@ int vw_InitText(const char *FileName, const char SymbolSeparator, const char Sym vw_ReleaseText(); // open and don't call vw_fclose(), use tmpFile->Data directly - std::unique_ptr tmpFile = vw_fopen(FileName); + std::unique_ptr tmpFile = vw_fopen(FileName); if (!tmpFile) return ERR_FILE_NOT_FOUND; std::cout << "Load and parse .csv file " << FileName << "\n"; @@ -171,15 +171,15 @@ int vw_InitText(const char *FileName, const char SymbolSeparator, const char Sym std::string CurrentRowCode; unsigned int CurrentColumnNumber{0}; unsigned int LineNumber{1}; // line number for error message - for (unsigned int i = 0; i < tmpFile->Size; i++) { + for (long i = 0; i < tmpFile->GetSize(); i++) { // parse each row - for (; (tmpFile->Data[i] != SymbolEndOfLine) && (i < tmpFile->Size); i++) { + for (; (tmpFile->GetData()[i] != SymbolEndOfLine) && (i < tmpFile->GetSize()); i++) { // read text block in line, .csv line looks like: // text_block;text_block;...;text_blockSymbolEndOfLine // if text braced by quotes: // "text_block";"text_block";...;"text_block"SymbolEndOfLine std::string CurrentRowTextBlock{}; - if (GetRowTextBlock(CurrentRowTextBlock, tmpFile->Data.get(), tmpFile->Size, i, + if (GetRowTextBlock(CurrentRowTextBlock, tmpFile->GetData(), tmpFile->GetSize(), i, SymbolSeparator, SymbolEndOfLine)) { std::cerr << __func__ << "(): " << "file corrupted."; vw_ReleaseText(); @@ -198,10 +198,10 @@ int vw_InitText(const char *FileName, const char SymbolSeparator, const char Sym if (isElementPresentInTable(TextTable, CurrentColumnNumber, CurrentRowCode)) { std::cerr << __func__ << "(): " << "* Duplicate line detected, line number " << LineNumber << "\n"; - for (; (tmpFile->Data[i] != SymbolEndOfLine) && (i < tmpFile->Size); i++) {} + for (; (tmpFile->GetData()[i] != SymbolEndOfLine) && (i < tmpFile->GetSize()); i++) {} } // we found SymbolEndOfLine in previous cycle, in order to prevent "i" changes, break cycle - if (tmpFile->Data[i] == SymbolEndOfLine) + if (tmpFile->GetData()[i] == SymbolEndOfLine) break; } // move to next row diff --git a/src/core/texture/texture.cpp b/src/core/texture/texture.cpp index f103942d..427c187a 100755 --- a/src/core/texture/texture.cpp +++ b/src/core/texture/texture.cpp @@ -335,7 +335,7 @@ void vw_ConvertImageToVW2D(const std::string &SrcName, const std::string &DestNa std::unique_ptr tmpPixelsArray{}; eLoadTextureAs LoadAs{eLoadTextureAs::TGA}; - std::unique_ptr pFile = vw_fopen(SrcName); + std::unique_ptr pFile = vw_fopen(SrcName); if (pFile == nullptr) { std::cerr << __func__ << "(): " << "Unable to found " << SrcName << "\n"; return; @@ -396,7 +396,7 @@ GLtexture vw_LoadTexture(const std::string &TextureName, eTextureCompressionType // don't use std::vector here, since it allocates AND value-initializes std::unique_ptr tmpPixelsArray{}; - std::unique_ptr pFile = vw_fopen(TextureName); + std::unique_ptr pFile = vw_fopen(TextureName); if (!pFile) { std::cerr << __func__ << "(): " << "Unable to found " << TextureName << "\n"; return 0; diff --git a/src/core/texture/texture_tga.cpp b/src/core/texture/texture_tga.cpp index 3a5da513..e5cf236f 100755 --- a/src/core/texture/texture_tga.cpp +++ b/src/core/texture/texture_tga.cpp @@ -31,7 +31,7 @@ namespace viewizard { -int ReadTGA(std::unique_ptr &PixelsArray, sFILE *pFile, int &DWidth, int &DHeight, int &DChanels) +int ReadTGA(std::unique_ptr &PixelsArray, cFILE *pFile, int &DWidth, int &DHeight, int &DChanels) { constexpr uint8_t TGA_RGB{2}; // normal RGB (BGR) file constexpr uint8_t TGA_RLE{10}; // RLE file diff --git a/src/core/texture/texture_tga.h b/src/core/texture/texture_tga.h index fc01a270..ca622ea9 100755 --- a/src/core/texture/texture_tga.h +++ b/src/core/texture/texture_tga.h @@ -32,7 +32,7 @@ namespace viewizard { -int ReadTGA(std::unique_ptr &PixelsArray, sFILE *pFile, int &DWidth, int &DHeight, int &DChanels); +int ReadTGA(std::unique_ptr &PixelsArray, cFILE *pFile, int &DWidth, int &DHeight, int &DChanels); } // viewizard namespace diff --git a/src/core/vfs/vfs.cpp b/src/core/vfs/vfs.cpp old mode 100755 new mode 100644 index 62c8540f..f4b7f4d7 --- a/src/core/vfs/vfs.cpp +++ b/src/core/vfs/vfs.cpp @@ -36,13 +36,13 @@ On VFS file open, VFS entries list generated with all available in this VFS files data. Could be opened multiple VFS files, in this case VFS entries list will contain all available in all opened VFS files data. - On sFILE open, all requested data will be copied into memory buffer (sFILE->Data). - Opened sFILE is not connected to VFS file or VFS entries list in any way. + On cFILE open, all requested data will be copied into memory buffer (cFILE->Data_). + Opened cFILE is not connected to VFS file or VFS entries list in any way. - Caller should hold sFILE open as long, as it need memory buffer (sFILE->Data). - In order to code simplicity, read and write direct access to sFILE data allowed. - Caller could reset() memory buffer with different size (sFILE->Data), but should - care about sFILE->Size and sFILE->Pos field (access by fseek()). + Caller should hold cFILE open as long, as it need memory buffer (cFILE->Data_). + In order to code simplicity, read and write direct access to cFILE data allowed. + Caller could reset() memory buffer with different size (cFILE->Data), but should + care about cFILE->Size_ and cFILE->Pos_ field (access by fseek()). Game data VFS v1.6 structure. @@ -85,7 +85,7 @@ struct sVFS { struct sVFS_Entry { uint32_t Offset{0}; - uint32_t Size{0}; + uint32_t Size{0}; // NOTE cFILE::Size_ is long (32/64 depending from platform) std::weak_ptr Parent{}; }; @@ -225,11 +225,12 @@ int vw_CreateVFS(const std::string &Name, unsigned int BuildNumber, // copy all files from pack into new VFS for (const auto &tmpVFSEntry : VFSEntriesMap) { - std::unique_ptr tmpFile = vw_fopen(tmpVFSEntry.first); + std::unique_ptr tmpFile = vw_fopen(tmpVFSEntry.first); if (!tmpFile) return ERR_FILE_NOT_FOUND; - err = WriteIntoVFSfromMemory(TempVFS, tmpVFSEntry.first, tmpFile->Data.get(), - tmpFile->Size, FileTableOffset, WritableVFSEntriesMap); + err = WriteIntoVFSfromMemory(TempVFS, tmpVFSEntry.first, tmpFile->GetData(), + static_cast(tmpFile->GetSize()), + FileTableOffset, WritableVFSEntriesMap); if (err) { std::cerr << __func__ << "(): " << "VFS compilation process aborted!\n"; return err; @@ -364,7 +365,7 @@ void vw_ShutdownVFS() * Open the sFILE. * Return std::unique_ptr, provide smart pointer connected to caller's scope. */ -std::unique_ptr vw_fopen(const std::string &FileName) +std::unique_ptr vw_fopen(const std::string &FileName) { if (FileName.empty()) return nullptr; @@ -377,12 +378,12 @@ std::unique_ptr vw_fopen(const std::string &FileName) return nullptr; } - std::unique_ptr File(new sFILE(0, 0)); + std::unique_ptr File(new cFILE(0, 0)); - File->Size = FileInVFS->second.Size; + File->Size_ = static_cast(FileInVFS->second.Size); sharedParent->File.seekg(FileInVFS->second.Offset, std::ios::beg); - File->Data.reset(new uint8_t[File->Size]); - sharedParent->File.read(reinterpret_cast(File->Data.get()), File->Size); + File->Data_.reset(new uint8_t[File->Size_]); + sharedParent->File.read(reinterpret_cast(File->Data_.get()), File->Size_); return File; } @@ -395,11 +396,11 @@ std::unique_ptr vw_fopen(const std::string &FileName) return nullptr; fsFile.seekg(0, std::ios::beg); - std::unique_ptr File(new sFILE(0, 0)); + std::unique_ptr File(new cFILE(0, 0)); - File->Size = static_cast(tmpSize); - File->Data.reset(new uint8_t[File->Size]); - fsFile.read(reinterpret_cast(File->Data.get()), File->Size); + File->Size_ = static_cast(tmpSize); + File->Data_.reset(new uint8_t[File->Size_]); + fsFile.read(reinterpret_cast(File->Data_.get()), File->Size_); return File; } @@ -411,7 +412,7 @@ std::unique_ptr vw_fopen(const std::string &FileName) * You could call vw fclose() if you should release memory in particular * part of code. Otherwise, it will be released automatically (see. unique_ptr). */ -int vw_fclose(std::unique_ptr &stream) +int vw_fclose(std::unique_ptr &stream) { if (!stream.get()) return ERR_PARAMETERS; @@ -426,15 +427,15 @@ int vw_fclose(std::unique_ptr &stream) * Reads an array of 'count' elements, each one with a size of 'size' bytes, * from the stream and stores them in the block of memory specified by 'buffer'. */ -size_t sFILE::fread(void *buffer, size_t size, size_t count) +size_t cFILE::fread(void *buffer, size_t size, size_t count) { - if (!buffer || !Data) + if (!buffer || !Data_) return ERR_PARAMETERS; size_t CopyCount{0}; - for (; (CopyCount < count) && (Size >= static_cast(Pos + size)); CopyCount++) { - memcpy(static_cast(buffer) + CopyCount * size, Data.get() + Pos, size); - Pos += size; + for (; (CopyCount < count) && (Size_ >= static_cast(Pos_ + size)); CopyCount++) { + memcpy(static_cast(buffer) + CopyCount * size, Data_.get() + Pos_, size); + Pos_ += size; } return CopyCount; @@ -443,27 +444,25 @@ size_t sFILE::fread(void *buffer, size_t size, size_t count) /* * Sets the position indicator associated with the stream to a new position. */ -int sFILE::fseek(long offset, int origin) +int cFILE::fseek(long offset, int origin) { - // FIXME offset could be positive or negative, fix logic and use proper types (don't allow signed/unsigned comparison) - switch (origin) { case SEEK_CUR: - if ((Pos + offset) > Size) + if ((Pos_ + offset > Size_) || (Pos_ + offset < 0)) return ERR_PARAMETERS; - Pos += offset; + Pos_ += offset; break; case SEEK_END: - if (offset > Size) + if ((offset > 0) || (Size_ + offset < 0)) return ERR_PARAMETERS; - Pos = Size - offset; + Pos_ = Size_ + offset; break; case SEEK_SET: - if ((offset < 0) || (offset > Size)) + if ((offset < 0) || (offset > Size_)) return ERR_PARAMETERS; - Pos = offset; + Pos_ = offset; break; default: @@ -477,9 +476,9 @@ int sFILE::fseek(long offset, int origin) /* * Returns the current value of the position indicator of the stream. */ -long sFILE::ftell() +long cFILE::ftell() { - return Pos; + return Pos_; } } // viewizard namespace diff --git a/src/core/vfs/vfs.h b/src/core/vfs/vfs.h index 83eaaf29..65bbe656 100755 --- a/src/core/vfs/vfs.h +++ b/src/core/vfs/vfs.h @@ -25,8 +25,6 @@ *************************************************************************************/ -// TODO struct sFILE should use encapsulation (switch to class) - #ifndef CORE_VFS_VFS_H #define CORE_VFS_VFS_H @@ -45,30 +43,43 @@ int vw_OpenVFS(const std::string &Name, unsigned int BuildNumber); // Shutdown VFS. void vw_ShutdownVFS(); -struct sFILE { - uint32_t Size{0}; - // std::unique_ptr, we need only memory allocation without container's features - // don't use std::vector here, since it allocates AND value-initializes - std::unique_ptr Data{}; +class cFILE { + friend std::unique_ptr vw_fopen(const std::string &FileName); + +public: + explicit cFILE(long Size, long Pos) : + Size_{Size}, + Pos_{Pos} + {} + + long GetSize() + { + return Size_; + } + + uint8_t *GetData() + { + return Data_.get(); + } size_t fread(void *buffer, size_t size, size_t count); int fseek(long offset, int origin); long ftell(); - explicit sFILE(unsigned int _Size, long _Pos) : - Size{_Size}, - Pos{_Pos} - {} - private: - long Pos{0}; + long Size_{0}; + long Pos_{0}; + + // std::unique_ptr, we need only memory allocation without container's features + // don't use std::vector here, since it allocates AND value-initializes + std::unique_ptr Data_{}; }; // Return std::unique_ptr, provide smart pointer connected to caller's scope. -std::unique_ptr vw_fopen(const std::string &FileName); +std::unique_ptr vw_fopen(const std::string &FileName); // You could call vw_fclose() if you should release memory in particular // part of code. Otherwise, it will be released automatically (see. unique_ptr). -int vw_fclose(std::unique_ptr &stream); +int vw_fclose(std::unique_ptr &stream); } // viewizard namespace diff --git a/src/core/xml/xml.cpp b/src/core/xml/xml.cpp index e28bd036..fbd22ecd 100755 --- a/src/core/xml/xml.cpp +++ b/src/core/xml/xml.cpp @@ -263,14 +263,14 @@ cXMLDocument::cXMLDocument(const std::string &XMLFileName, bool Hash) RootXMLEntry.reset(); // read all data into buffer - std::unique_ptr File = vw_fopen(XMLFileName); + std::unique_ptr File = vw_fopen(XMLFileName); if (!File) { std::cerr << __func__ << "(): " << "XML file not found: " << XMLFileName << "\n"; return; } std::string Buffer{}; - Buffer.resize(File->Size + 1, '\0'); - Buffer.assign(reinterpret_cast(File->Data.get()), File->Size); + Buffer.resize(File->GetSize() + 1, '\0'); + Buffer.assign(reinterpret_cast(File->GetData()), File->GetSize()); vw_fclose(File); // check header