#include "ExcelFormat.h"
#ifdef _MSC_VER
#include <malloc.h> // for alloca()
#endif
#ifdef _WIN32
namespace WinCompFiles
{
CompoundFile::CompoundFile()
{
_pStg = NULL;
}
CompoundFile::~CompoundFile()
{
Close();
}
// Compound File functions
bool CompoundFile::Create(const wchar_t* filename)
{
HRESULT hr = StgCreateDocfile(filename, STGM_READWRITE|STGM_CREATE|STGM_SHARE_EXCLUSIVE, 0, &_pStg);
return SUCCEEDED(hr);
}
bool CompoundFile::Open(const wchar_t* filename, ios_base::openmode mode/*=ios_base::in|ios_base::out*/)
{
int stgm_mode;
if ((mode & (ios_base::in|ios_base::out)) == (ios_base::in|ios_base::out))
stgm_mode = STGM_READWRITE | STGM_SHARE_EXCLUSIVE;
else if (mode & ios_base::out)
stgm_mode = STGM_WRITE | STGM_SHARE_EXCLUSIVE;
else
stgm_mode = STGM_READ | STGM_SHARE_EXCLUSIVE;
HRESULT hr = StgOpenStorage(filename, NULL, stgm_mode, NULL, 0, &_pStg);
return SUCCEEDED(hr);
}
bool CompoundFile::Close()
{
if (_pStg) {
_pStg->Release();
_pStg = NULL;
return true;
} else
return false;
}
bool CompoundFile::IsOpen()
{
return _pStg != NULL;
}
// File functions
CF_RESULT CompoundFile::MakeFile(const wchar_t* path)
{
IStream* pStream = NULL;
HRESULT hr = _pStg->CreateStream(path, STGM_READWRITE|STGM_CREATE|STGM_SHARE_EXCLUSIVE, 0, 0, &pStream);
if (pStream)
pStream->Release();
return SUCCEEDED(hr)? SUCCESS: INVALID_PATH;
}
CF_RESULT CompoundFile::FileSize(const wchar_t* path, ULONGLONG& size)
{
IStream* pStream = NULL;
// needs STGM_READWRITE in the StgCreateDocfile() call
if (FAILED(_pStg->OpenStream(path, NULL, STGM_READ|STGM_SHARE_EXCLUSIVE, 0, &pStream)))
return INVALID_PATH;
STATSTG stat;
HRESULT hr = pStream->Stat(&stat, STATFLAG_NONAME);
if (pStream)
pStream->Release();
if (SUCCEEDED(hr)) {
size = stat.cbSize.QuadPart;
return SUCCESS;
} else
return INVALID_PATH;
}
CF_RESULT CompoundFile::ReadFile(const wchar_t* path, char* data, ULONG size)
{
IStream* pStream = NULL;
if (FAILED(_pStg->OpenStream(path, NULL, STGM_READ|STGM_SHARE_EXCLUSIVE, 0, &pStream)))
return INVALID_PATH;
ULONG read;
HRESULT hr = pStream->Read(data, size, &read);
if (pStream)
pStream->Release();
return SUCCEEDED(hr)? SUCCESS: INVALID_PATH;
}
CF_RESULT CompoundFile::ReadFile(const wchar_t* path, vector<char>&data)
{
data.clear();
ULONGLONG dataSize;
CF_RESULT ret = FileSize(path, dataSize);
if (ret == SUCCESS) {
if (dataSize) {
if (dataSize == (ULONG)dataSize) {
data.resize((size_t)dataSize);
ret = ReadFile(path, &*(data.begin()), (ULONG)dataSize);
} else
ret = INVALID_SIZE;
} else
ret = SUCCESS;
}
return ret;
}
CF_RESULT CompoundFile::WriteFile(const wchar_t* path, const char* data, ULONG size)
{
IStream* pStream = NULL;
if (FAILED(_pStg->OpenStream(path, NULL, STGM_READWRITE|STGM_SHARE_EXCLUSIVE, 0, &pStream)))
return INVALID_PATH;
ULONG written;
HRESULT hr = pStream->Write(data, size, &written);
if (pStream)
pStream->Release();
return SUCCEEDED(hr)? SUCCESS: INVALID_PATH;
}
CF_RESULT CompoundFile::WriteFile(const wchar_t* path, const vector<char>&data, ULONG size)
{
IStream* pStream = NULL;
if (FAILED(_pStg->OpenStream(path, NULL, STGM_READWRITE|STGM_SHARE_EXCLUSIVE, 0, &pStream)))
return INVALID_PATH;
ULONG written;
HRESULT hr = pStream->Write(&*(data.begin()), size, &written);
if (pStream)
pStream->Release();
return SUCCEEDED(hr)? SUCCESS: INVALID_PATH;
}
// ANSI char functions
bool CompoundFile::Create(const char* filename)
{
return Create(widen_string(filename).c_str());
}
bool CompoundFile::Open(const char* filename, ios_base::openmode mode/*=ios_base::in|ios_base::out*/)
{
return Open(widen_string(filename).c_str(), mode);
}
CF_RESULT CompoundFile::MakeFile(const char* path)
{
return MakeFile(widen_string(path).c_str());
}
CF_RESULT CompoundFile::FileSize(const char* path, ULONGLONG& size)
{
return FileSize(widen_string(path).c_str(), size);
}
CF_RESULT CompoundFile::ReadFile(const char* path, char* data, ULONG size)
{
return ReadFile(widen_string(path).c_str(), data, size);
}
CF_RESULT CompoundFile::ReadFile(const char* path, vector<char>& data)
{
return ReadFile(widen_string(path).c_str(), data);
}
CF_RESULT CompoundFile::WriteFile(const char* path, const char* data, ULONG size)
{
return WriteFile(widen_string(path).c_str(), data, size);
}
CF_RESULT CompoundFile::WriteFile(const char* path, const vector<char>& data, ULONG size)
{
return WriteFile(widen_string(path).c_str(), data, size);
}
} // namespace WinCompFiles
#else // _WIN32
#if _MSC_VER>=1400 // VS 2005
#include <share.h> // _SH_DENYRW
#endif
namespace YCompoundFiles
{
/********************************** Start of Class Block *************************************/
// PURPOSE: Manage a file by treating it as blocks of data of a certain size.
Block::Block() :
blockSize_(512), fileSize_(0), indexEnd_(0),
filename_(0) {}
bool Block::Create(const wchar_t* filename)
// PURPOSE: Create a new block file and open it.
// PURPOSE: If file is present, truncate it and then open it.
// PROMISE: Return true if file is successfully created and opened, false if otherwise.
{
// Create new file
size_t filenameLength = wcslen(filename);
char* name = new char[filenameLength+1];
wcstombs(name, filename, filenameLength);
name[filenameLength] = 0;
// Open the file while truncating any existing file
bool ret = this->Open(filename, ios_base::in | ios_base::out | ios_base::trunc);
delete[] name;
return ret;
}
bool Block::Open(const wchar_t* filename, ios_base::openmode mode)
// PURPOSE: Open an existing block file.
// PROMISE: Return true if file is successfully opened, false if otherwise.
{
// Open existing file for reading or writing or both
size_t filenameLength = wcslen(filename);
filename_.resize(filenameLength+1, 0);
wcstombs(&*(filename_.begin()), filename, filenameLength);
#if _MSC_VER>=1400 // VS 2005
file_.open(&*(filename_.begin()), mode | ios_base::binary, _SH_DENYRW);
#else
file_.open(&*(filename_.begin()), mode | ios_base::binary);
#endif
if (!file_.is_open())
return false;
mode_ = mode;
// Calculate filesize
if (mode & ios_base::in) {
file_.seekg(0, ios_base::end);
fileSize_ = (ULONG) file_.tellg();
} else if (mode & ios_base::out) {
file_.seekp(0, ios_base::end);
fileSize_ = (ULONG) file_.tellp();
} else {
this->Close();
return false;
}
// Calculate last index + 1
indexEnd_ = fileSize_/blockSize_ + (fileSize_ % blockSize_ ? 1 : 0);
return true;
}
bool Block::Close()
// PURPOSE: Close the opened block file.
// PROMISE: Return true if file is successfully closed, false if otherwise.
{
file_.close();
file_.clear();
filename_.clear();
fileSize_ = 0;
indexEnd_ = 0;
blockSize_ = 512;
return !file_.is_open();
}
bool Block::IsOpen()
// PURPOSE: Check if the block file is still opened.
// PROMISE: Return true if file is still opened, false if otherwise.
{
return file_.is_open();
}
bool Block::Read(SECT index, char* block)
// PURPOSE: Read a block of data from the opened file at the index position.
// EXPLAIN: index is from [0..].
// PROMISE: Return true if data are successfully read, false if otherwise.
{
if (!(mode_ & ios_base::in))
return false;
if (index < indexEnd_) {
file_.seekg(index * blockSize_);
file_.read(block, blockSize_);
return !file_.fail();
} else
return false;
}
bool Block::Write(SECT index, const char* block)
// PURPOSE: Write a block of data to the opened file at the index position.
// EXPLAIN: index is from [0..].
// PROMISE: Return true if data are successfully written, false if otherwise.
{
if (!(mode_ & ios_base::out))
return false;
- 1
- 2
前往页