mirror of
https://github.com/vcmi/vcmi.git
synced 2025-11-23 22:37:55 +02:00
FileStream files
This commit is contained in:
149
lib/filesystem/FileStream.cpp
Normal file
149
lib/filesystem/FileStream.cpp
Normal file
@@ -0,0 +1,149 @@
|
|||||||
|
#include "StdInc.h"
|
||||||
|
#define INC_FROM_FILESTREAM_CPP
|
||||||
|
#include "FileStream.h"
|
||||||
|
#include "../minizip/unzip.h"
|
||||||
|
|
||||||
|
#include <cstdio>
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
#ifndef _CRT_SECURE_NO_WARNINGS
|
||||||
|
#define _CRT_SECURE_NO_WARNINGS
|
||||||
|
#endif
|
||||||
|
#include <cwchar>
|
||||||
|
#define CHAR_LITERAL(s) L##s
|
||||||
|
#define DO_OPEN(name, mode) _wfopen(name, mode)
|
||||||
|
using CharType = wchar_t;
|
||||||
|
#else
|
||||||
|
#define CHAR_LITERAL(s) s
|
||||||
|
#define DO_OPEN(name, mode) fopen(name, mode)
|
||||||
|
using CharType = char;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define GETFILE static_cast<std::FILE*>(filePtr)
|
||||||
|
|
||||||
|
voidpf ZCALLBACK MinizipOpenFunc(voidpf opaque, const void* filename, int mode)
|
||||||
|
{
|
||||||
|
const CharType* mode_fopen = [mode]() -> const CharType*
|
||||||
|
{
|
||||||
|
if ((mode & ZLIB_FILEFUNC_MODE_READWRITEFILTER) == ZLIB_FILEFUNC_MODE_READ)
|
||||||
|
return CHAR_LITERAL("rb");
|
||||||
|
else if (mode & ZLIB_FILEFUNC_MODE_EXISTING)
|
||||||
|
return CHAR_LITERAL("r+b");
|
||||||
|
else if (mode & ZLIB_FILEFUNC_MODE_CREATE)
|
||||||
|
return CHAR_LITERAL("wb");
|
||||||
|
return nullptr;
|
||||||
|
}();
|
||||||
|
|
||||||
|
if (filename != nullptr && mode_fopen != nullptr)
|
||||||
|
return DO_OPEN(static_cast<const CharType*>(filename), mode_fopen);
|
||||||
|
else
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
zlib_filefunc64_def* FileStream::GetMinizipFilefunc()
|
||||||
|
{
|
||||||
|
static zlib_filefunc64_def MinizipFilefunc;
|
||||||
|
static bool initialized = false;
|
||||||
|
if (!initialized) {
|
||||||
|
fill_fopen64_filefunc((&MinizipFilefunc));
|
||||||
|
MinizipFilefunc.zopen64_file = &MinizipOpenFunc;
|
||||||
|
initialized = true;
|
||||||
|
}
|
||||||
|
return &MinizipFilefunc;
|
||||||
|
}
|
||||||
|
|
||||||
|
template class DLL_LINKAGE boost::iostreams::stream<FileBuf>;
|
||||||
|
|
||||||
|
/*static*/
|
||||||
|
bool FileStream::CreateFile(const boost::filesystem::path& filename)
|
||||||
|
{
|
||||||
|
FILE* f = DO_OPEN(filename.c_str(), CHAR_LITERAL("wb"));
|
||||||
|
bool result = (f != nullptr);
|
||||||
|
fclose(f);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
FileBuf::FileBuf(const boost::filesystem::path& filename, std::ios_base::openmode mode)
|
||||||
|
{
|
||||||
|
std::string openmode = [mode]() -> std::string
|
||||||
|
{
|
||||||
|
using namespace std;
|
||||||
|
switch (mode & (~ios_base::ate & ~ios_base::binary))
|
||||||
|
{
|
||||||
|
case (ios_base::in):
|
||||||
|
return "r";
|
||||||
|
case (ios_base::out):
|
||||||
|
case (ios_base::out | ios_base::trunc):
|
||||||
|
return "w";
|
||||||
|
case (ios_base::app):
|
||||||
|
case (ios_base::out | ios_base::app):
|
||||||
|
return "a";
|
||||||
|
case (ios_base::out | ios_base::in):
|
||||||
|
return "r+";
|
||||||
|
case (ios_base::out | ios_base::in | ios_base::trunc):
|
||||||
|
return "w+";
|
||||||
|
case (ios_base::out | ios_base::in | ios_base::app):
|
||||||
|
case (ios_base::in | ios_base::app):
|
||||||
|
return "a+";
|
||||||
|
default:
|
||||||
|
throw std::ios_base::failure("invalid open mode");
|
||||||
|
}
|
||||||
|
}();
|
||||||
|
|
||||||
|
if (mode & std::ios_base::binary)
|
||||||
|
openmode += 'b';
|
||||||
|
|
||||||
|
#if defined(_WIN32)
|
||||||
|
filePtr = _wfopen(filename.c_str(), std::wstring(openmode.begin(), openmode.end()).c_str());
|
||||||
|
#else
|
||||||
|
filePtr = std::open(filename.c_str(), openmode);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (filePtr == nullptr)
|
||||||
|
throw std::ios_base::failure("could not open file");
|
||||||
|
|
||||||
|
if (mode & std::ios_base::ate) {
|
||||||
|
if (std::fseek(GETFILE, 0, SEEK_END)) {
|
||||||
|
fclose(GETFILE);
|
||||||
|
throw std::ios_base::failure("could not open file");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void FileBuf::close()
|
||||||
|
{
|
||||||
|
std::fclose(GETFILE);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::streamsize FileBuf::read(char* s, std::streamsize n)
|
||||||
|
{
|
||||||
|
return static_cast<std::streamsize>(std::fread(s, 1, n, GETFILE));
|
||||||
|
}
|
||||||
|
|
||||||
|
std::streamsize FileBuf::write(const char* s, std::streamsize n)
|
||||||
|
{
|
||||||
|
return static_cast<std::streamsize>(std::fwrite(s, 1, n, GETFILE));
|
||||||
|
}
|
||||||
|
|
||||||
|
std::streamoff FileBuf::seek(std::streamoff off, std::ios_base::seekdir way)
|
||||||
|
{
|
||||||
|
auto src = [way]() -> int
|
||||||
|
{
|
||||||
|
switch(way)
|
||||||
|
{
|
||||||
|
case std::ios_base::beg:
|
||||||
|
return SEEK_SET;
|
||||||
|
case std::ios_base::cur:
|
||||||
|
return SEEK_CUR;
|
||||||
|
case std::ios_base::end:
|
||||||
|
return SEEK_END;
|
||||||
|
default:
|
||||||
|
throw std::ios_base::failure("bad seek direction");
|
||||||
|
}
|
||||||
|
}();
|
||||||
|
if(std::fseek(GETFILE, off, src))
|
||||||
|
throw std::ios_base::failure("bad seek offset");
|
||||||
|
|
||||||
|
return static_cast<std::streamsize>(std::ftell(GETFILE));
|
||||||
|
}
|
||||||
43
lib/filesystem/FileStream.h
Normal file
43
lib/filesystem/FileStream.h
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <iosfwd>
|
||||||
|
#include <boost/iostreams/categories.hpp>
|
||||||
|
#include <boost/iostreams/stream.hpp>
|
||||||
|
|
||||||
|
class DLL_LINKAGE FileBuf {
|
||||||
|
public:
|
||||||
|
typedef char char_type;
|
||||||
|
typedef struct category_ :
|
||||||
|
boost::iostreams::seekable_device_tag,
|
||||||
|
boost::iostreams::closable_tag
|
||||||
|
{} category;
|
||||||
|
|
||||||
|
FileBuf(const boost::filesystem::path& filename, std::ios_base::openmode mode = (std::ios_base::in | std::ios_base::out));
|
||||||
|
|
||||||
|
std::streamsize read(char* s, std::streamsize n);
|
||||||
|
std::streamsize write(const char* s, std::streamsize n);
|
||||||
|
std::streamoff seek(std::streamoff off, std::ios_base::seekdir way);
|
||||||
|
|
||||||
|
void close();
|
||||||
|
private:
|
||||||
|
void* filePtr;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct zlib_filefunc64_def_s;
|
||||||
|
typedef zlib_filefunc64_def_s zlib_filefunc64_def;
|
||||||
|
|
||||||
|
#ifdef VCMI_DLL
|
||||||
|
extern template class DLL_LINKAGE boost::iostreams::stream<FileBuf>;
|
||||||
|
#else
|
||||||
|
template class DLL_LINKAGE boost::iostreams::stream<FileBuf>;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
class DLL_LINKAGE FileStream : public boost::iostreams::stream<FileBuf>
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
using boost::iostreams::stream<FileBuf>::stream;
|
||||||
|
|
||||||
|
static bool CreateFile(const boost::filesystem::path& filename);
|
||||||
|
|
||||||
|
static zlib_filefunc64_def* GetMinizipFilefunc();
|
||||||
|
};
|
||||||
Reference in New Issue
Block a user