📄 basicexcel.cpp
字号:
/********************************** End of Class PropertyTree ************************************/
/********************************** Start of Class CompoundFile ******************************/
// PURPOSE: Manage a compound file.
CompoundFile::CompoundFile() :
block_(512), properties_(0), propertyTrees_(0),
blocksIndices_(0), sblocksIndices_(0) {};
CompoundFile::~CompoundFile() {this->Close();}
/************************* Compound File Functions ***************************/
bool CompoundFile::Create(const wchar_t* filename)
// PURPOSE: Create a new compound 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.
{
Close();
file_.Create(filename);
// Write compound file header
header_ = Header();
SaveHeader();
// Save BAT
blocksIndices_.clear();
blocksIndices_.resize(128, -1);
blocksIndices_[0] = -3;
blocksIndices_[1] = -2;
SaveBAT();
// Save properties
Property* root = new Property;
wcscpy(root->name_, L"Root Entry");
root->propertyType_ = 5;
properties_.push_back(root);
SaveProperties();
// Set property tree
propertyTrees_ = new PropertyTree;
propertyTrees_->parent_ = 0;
propertyTrees_->self_ = properties_[0];
propertyTrees_->index_ = 0;
currentDirectory_ = propertyTrees_;
return true;
}
bool CompoundFile::Open(const wchar_t* filename, ios_base::openmode mode)
// PURPOSE: Open an existing compound file.
// PROMISE: Return true if file is successfully opened, false if otherwise.
{
Close();
if (!file_.Open(filename, mode)) return false;
// Load header
if (!LoadHeader()) return false;
// Load BAT information
LoadBAT();
// Load properties
propertyTrees_ = new PropertyTree;
LoadProperties();
currentDirectory_ = propertyTrees_;
return true;
}
bool CompoundFile::Close()
// PURPOSE: Close the opened compound file.
// PURPOSE: Reset BAT indices, SBAT indices, properties and properties tree information.
// PROMISE: Return true if file is successfully closed, false if otherwise.
{
blocksIndices_.clear();
sblocksIndices_.clear();
int maxProperties = properties_.size();
for (int i=0; i<maxProperties; ++i)
{
if (properties_[i]) delete properties_[i];
}
properties_.clear();
if (propertyTrees_)
{
delete propertyTrees_;
propertyTrees_ = 0;
}
previousDirectories_.clear();
currentDirectory_ = 0;
return file_.Close();
}
bool CompoundFile::IsOpen()
// PURPOSE: Check if the compound file is still opened.
// PROMISE: Return true if file is still opened, false if otherwise.
{
return file_.IsOpen();
}
/************************* Directory Functions ***************************/
int CompoundFile::ChangeDirectory(const wchar_t* path)
// PURPOSE: Change to a different directory in the compound file.
// PROMISE: Current directory will not be changed if directory is not present.
{
previousDirectories_.push_back(currentDirectory_);
// Handle special cases
if (wcscmp(path, L".") == 0)
{
// Current directory
previousDirectories_.pop_back();
return SUCCESS;
}
if (wcscmp(path, L"..") == 0)
{
// Go up 1 directory
if (currentDirectory_->parent_ != 0)
{
currentDirectory_ = currentDirectory_->parent_;
}
previousDirectories_.pop_back();
return SUCCESS;
}
if (wcscmp(path, L"\\") == 0)
{
// Go to root directory
currentDirectory_ = propertyTrees_;
previousDirectories_.pop_back();
return SUCCESS;
}
// Handle normal cases
int ipos = 0;
int npos = 0;
int pathLength = wcslen(path);
if (pathLength > 0 && path[0] == L'\\')
{
// Start from root directory
currentDirectory_ = propertyTrees_;
++ipos;
++npos;
}
do
{
for (; npos<pathLength; ++npos)
{
if (path[npos] == L'\\') break;
}
wchar_t* directory = new wchar_t[npos-ipos+1];
//copy (path+ipos, path+npos, directory);
wmemcpy(directory, path+ipos, npos-ipos);
directory[npos-ipos] = 0;
currentDirectory_ = FindProperty(currentDirectory_, directory);
delete[] directory;
ipos = npos + 1;
npos = ipos;
if (currentDirectory_ == 0)
{
// Directory not found
currentDirectory_ = previousDirectories_.back();
previousDirectories_.pop_back();
return DIRECTORY_NOT_FOUND;
}
} while (npos < pathLength);
previousDirectories_.pop_back();
return SUCCESS;
}
int CompoundFile::MakeDirectory(const wchar_t* path)
// PURPOSE: Create a new directory in the compound file.
// PROMISE: Directory will not be created if it is already present or
// PROMISE: a file with the same name is present.
{
previousDirectories_.push_back(currentDirectory_);
Property* property = new Property;
property->propertyType_ = 1;
int ret = MakeProperty(path, property);
currentDirectory_ = previousDirectories_.back();
previousDirectories_.pop_back();
SaveHeader();
SaveBAT();
SaveProperties();
return ret;
}
int CompoundFile::PresentWorkingDirectory(wchar_t* path)
// PURPOSE: Get the full path of the current directory in the compound file.
// REQUIRE: path must be large enough to receive the full path information.
{
previousDirectories_.push_back(currentDirectory_);
vector<wchar_t> fullpath;
do
{
int directoryLength = wcslen(currentDirectory_->self_->name_);
vector<wchar_t> directory(directoryLength+1);
directory[0] = L'\\';
copy (currentDirectory_->self_->name_,
currentDirectory_->self_->name_+directoryLength,
directory.begin()+1);
fullpath.insert(fullpath.begin(), directory.begin(), directory.end());
} while (currentDirectory_ = currentDirectory_->parent_);
fullpath.erase(fullpath.begin(), fullpath.begin()+11);
if (fullpath.empty())
fullpath.push_back(L'\\');
//copy (fullpath.begin(), fullpath.end(), path);
if( fullpath.size() > 0 )
wmemcpy( path, &fullpath[0], fullpath.size());
path[fullpath.size()] = 0;
currentDirectory_ = previousDirectories_.back();
previousDirectories_.pop_back();
return SUCCESS;
}
int CompoundFile::PresentWorkingDirectory(vector<wchar_t>& path)
// PURPOSE: Get the full path of the current directory in the compound file.
{
previousDirectories_.push_back(currentDirectory_);
path.clear();
do
{
int directoryLength = wcslen(currentDirectory_->self_->name_);
vector<wchar_t> directory(directoryLength+1);
directory[0] = L'\\';
copy (currentDirectory_->self_->name_,
currentDirectory_->self_->name_+directoryLength,
directory.begin()+1);
path.insert(path.begin(), directory.begin(), directory.end());
} while (currentDirectory_ = currentDirectory_->parent_);
path.erase(path.begin(), path.begin()+11);
if (path.empty()) path.push_back(L'\\');
currentDirectory_ = previousDirectories_.back();
previousDirectories_.pop_back();
return SUCCESS;
}
int CompoundFile::RemoveDirectory(const wchar_t* path)
// PURPOSE: Remove a directory in the compound file.
// PROMISE: Directory will not be removed if it has subdirectories or files under it.
{
PropertyTree* directory = FindProperty(path);
if (directory == 0) return DIRECTORY_NOT_FOUND;
if (directory->self_->childProp_ != -1) return DIRECTORY_NOT_EMPTY;
DeletePropertyTree(directory);
SaveHeader();
SaveBAT();
SaveProperties();
return SUCCESS;
}
int CompoundFile::DelTree(const wchar_t* path)
// PURPOSE: Remove everything in the path in the compound file, including
// PURPOSE: any files and subdirectories.
{
previousDirectories_.push_back(currentDirectory_);
PropertyTree* directory = FindProperty(path);
if (directory == 0) return DIRECTORY_NOT_FOUND;
if (directory->self_->childProp_ != -1)
{
int maxChildren = directory->children_.size();
wchar_t* curpath = new wchar_t[65535];
for (int i=0; i<maxChildren; ++i)
{
currentDirectory_ = directory->children_[i];
PresentWorkingDirectory(curpath);
if (directory->children_[i]->self_->propertyType_ == 1)
{
// Directory
DelTree(curpath);
}
else if (directory->children_[i]->self_->propertyType_ == 2)
{
// File
RemoveFile(curpath);
}
}
directory->self_->childProp_ = -1;
delete[] curpath;
}
if (directory->self_->propertyType_ == 1)
{
// Directory
RemoveDirectory(path);
}
else if (directory->self_->propertyType_ == 2)
{
// File
RemoveFile(path);
}
currentDirectory_ = previousDirectories_.back();
previousDirectories_.pop_back();
return SUCCESS;
}
int CompoundFile::DirectoryList(vector<vector<wchar_t> >& list, const wchar_t* path)
{
previousDirectories_.push_back(currentDirectory_);
if (path != 0)
{
int ret = ChangeDirectory(path);
if (ret != SUCCESS) return ret;
}
list.clear();
int maxChildren = currentDirectory_->children_.size();
vector<wchar_t> name(32);
for (int i=0; i<maxChildren; ++i)
{
wcscpy(&*(name.begin()), currentDirectory_->children_[i]->self_->name_);
list.push_back(name);
}
currentDirectory_ = previousDirectories_.back();
previousDirectories_.pop_back();
return SUCCESS;
}
/************************* File Functions ***************************/
int CompoundFile::MakeFile(const wchar_t* path)
// PURPOSE: Create a new file in the compound file.
// PROMISE: File will not be created if it is already present or
// PROMISE: a directory with the same name is present.
{
previousDirectories_.push_back(currentDirectory_);
Property* property = new Property;
property->propertyType_ = 2;
int ret = MakeProperty(path, property);
currentDirectory_ = previousDirectories_.back();
previousDirectories_.pop_back();
SaveHeader();
SaveBAT();
SaveProperties();
return ret;
}
int CompoundFile::RemoveFile(const wchar_t* path)
// PURPOSE: Remove a file in the compound file.
{
int ret = WriteFile(path, 0, 0);
if (ret == SUCCESS)
{
DeletePropertyTree(FindProperty(path));
SaveHeader();
SaveBAT();
SaveProperties();
return SUCCESS;
}
else return ret;
}
int CompoundFile::FileSize(const wchar_t* path, int& size)
// PURPOSE: Get the size of a file in the compound file.
// PROMISE: Return the data size stored in the Root Entry if path = "\".
// PROMISE: size will not be set if file is not present in the compound file.
{
// Special case of reading root entry
if (wcscmp(path, L"\\") == 0)
{
size = propertyTrees_->self_->size_;
return SUCCESS;
}
// Check to see if file is present in the specified directory.
PropertyTree* property = FindProperty(path);
if (property == 0) return FILE_NOT_FOUND;
else
{
size = property->self_->size_;
return SUCCESS;
}
}
int CompoundFile::ReadFile(const wchar_t* path, char* data)
// PURPOSE: Read a file's data in the compound file.
// REQUIRE: data must be large enough to receive the file's data.
// REQUIRE: The required data size can be obtained by using FileSize().
// PROMISE: Returns the small blocks of data stored by the Root Entry if path = "\".
// PROMISE: data will not be set if file is not present in the compound file.
{
// Special case of reading root entry
char* buffer;
if (wcscmp(path, L"\\") == 0)
{
buffer = new char[DataSize(propertyTrees_->self_->startBlock_, true)];
ReadData(propertyTrees_->self_->startBlock_, buffer, true);
//copy (buffer, buffer+propertyTrees_->self_->size_, data);
memcpy(data, buffer, propertyTrees_->self_->size_);
delete[] buffer;
return SUCCESS;
}
// Check to see if file is present in the specified directory.
PropertyTree* property = FindProperty(path);
if (property == 0) return FILE_NOT_FOUND;
if (property->self_->size_ >= 4096)
{
// Data stored in normal big blocks
buffer = new char[DataSize(property->self_->startBlock_, true)];
ReadData(property->self_->startBlock_, buffer, true);
}
else
{
// Data stored in small blocks
buffer = new char[DataSize(property->self_->startBlock_, false)];
ReadData(property->self_->startBlock_, buffer, false);
}
// Truncated the retrieved data to the actual file size.
//copy (buffer, buffer+property->self_->size_, data);
memcpy(data, buffer, property->self_->size_);
delete[] buffer;
return SUCCESS;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -