⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 basicexcel.cpp

📁 Excel for add/delete item or sheet compile in VS2008/VC9 no error and no warnning
💻 CPP
📖 第 1 页 / 共 5 页
字号:

int CompoundFile::GetFreeBlockIndex(bool isBig)
// PURPOSE: Get the index of a new block where data can be stored.
// EXPLAIN: isBig is true if property uses big blocks, false if it uses small blocks.
// PROMISE: It does not physically create a new block in the compound file. 
// PROMISE: It only adjust BAT arrays and indices or SBAT arrays and indices so that
// PROMISE: it gives the index of a new block where data can be inserted.
{
	int index;
	if (isBig)
	{
		// Find first free location
		index = distance(blocksIndices_.begin(), 
						 find(blocksIndices_.begin(), 
							  blocksIndices_.end(), -1));
		if (index == blocksIndices_.size())
		{
			ExpandBATArray(true);
			index = distance(blocksIndices_.begin(), 
 							 find(blocksIndices_.begin(), 
								  blocksIndices_.end(), -1));
		}
		blocksIndices_[index] = -2;
	}
	else
	{
		// Find first free location
		index = distance(sblocksIndices_.begin(), 
						 find(sblocksIndices_.begin(), 
							  sblocksIndices_.end(), -1));
		if (index == sblocksIndices_.size())
		{
			ExpandBATArray(false);
			index = distance(sblocksIndices_.begin(), 
							 find(sblocksIndices_.begin(), 
							 	  sblocksIndices_.end(), -1));
		}
		sblocksIndices_[index] = -2;
	}
	return index;
}

void CompoundFile::ExpandBATArray(bool isBig)
// PURPOSE: Create a new block of BAT or SBAT indices.
// EXPLAIN: isBig is true if property uses big blocks, false if it uses small blocks.
{
	int newIndex;
	fill (block_.begin(), block_.end(), -1);

	if (isBig)
	{
		int BATindex = distance(&header_.BATArray_[0], 
								   find(header_.BATArray_, 
										header_.BATArray_+109, -1));
		if (BATindex < 109)
		{
			// Set new BAT index location
			newIndex = blocksIndices_.size(); // New index location
			file_.Insert(newIndex+1, &*(block_.begin()));
			IncreaseLocationReferences(vector<int>(1, newIndex));

			// Update BAT array
			header_.BATArray_[BATindex] = newIndex;
			++header_.BATCount_;
		}
		else
		{
			// No free BAT indices. Increment using XBAT
			// Set new XBAT index location
			if (header_.XBATCount_ != 0)
			{
				newIndex = header_.XBATStart_ + header_.XBATCount_;
				file_.Insert(newIndex, &*(block_.begin()));
				IncreaseLocationReferences(vector<int>(1, newIndex));
			}
			else
			{
				newIndex = blocksIndices_.size();
				file_.Insert(newIndex, &*(block_.begin()));
				IncreaseLocationReferences(vector<int>(1, newIndex));
				header_.XBATStart_ = newIndex;
			}
			++header_.XBATCount_;
		}
		blocksIndices_.insert(blocksIndices_.begin()+newIndex, -3);
		blocksIndices_.resize(blocksIndices_.size()+127, -1);
	}
	else
	{
		// Set new SBAT index location
		if (header_.SBATCount_ != 0)
		{
			newIndex = header_.SBATStart_ + header_.SBATCount_;
			file_.Insert(newIndex, &*(block_.begin()));
			IncreaseLocationReferences(vector<int>(1, newIndex));
		}
		else
		{
			newIndex = GetFreeBlockIndex(true);
			file_.Insert(newIndex, &*(block_.begin()));
			IncreaseLocationReferences(vector<int>(1, newIndex));
			header_.SBATStart_ = newIndex;
		}
		++header_.SBATCount_;
		sblocksIndices_.resize(sblocksIndices_.size()+128, -1);
	}
}

void CompoundFile::LinkBlocks(int from, int to, bool isBig)
// PURPOSE: Link one BAT index to another.
// EXPLAIN: isBig is true if property uses big blocks, false if it uses small blocks.
{
	if (isBig) blocksIndices_[from] = to;	
	else sblocksIndices_[from] = to;
}

void CompoundFile::FreeBlocks(vector<int>& indices, bool isBig)
// PURPOSE: Delete blocks of data from compound file.
// EXPLAIN: indices contains indices to blocks of data to be deleted. 
// EXPLAIN: isBig is true if property uses big blocks, false if it uses small blocks.
{
	if (isBig)
	{
		// Decrease all location references before deleting blocks from file.
		DecreaseLocationReferences(indices);
		int maxIndices = indices.size();
		{for (int i=0; i<maxIndices; ++i) ++indices[i];}	// Increase by 1 because Block index 1 corresponds to index 0 here
		file_.Erase(indices);

		// Shrink BAT indices if necessary
		vector<int> indicesToRemove;
		while (distance(find(blocksIndices_.begin(), 
						     blocksIndices_.end(),-1),
						     blocksIndices_.end()) >= 128)
		{			
			blocksIndices_.resize(blocksIndices_.size()-128);
			if (header_.XBATCount_ != 0)
			{
				// Shrink XBAT first
				--header_.XBATCount_;
				indicesToRemove.push_back(header_.XBATStart_+header_.XBATCount_+1); // Add 1 because Block index 1 corresponds to index 0 here
				if (header_.XBATCount_ == 0) header_.XBATStart_ = -2;
			}
			else
			{
				// No XBAT, delete last occupied BAT array element
				int BATindex = distance(&header_.BATArray_[0], 
										   find(header_.BATArray_, 
												header_.BATArray_+109, -1));
				if (BATindex != 109)
				{
					--header_.BATCount_;
					indicesToRemove.push_back(header_.BATArray_[BATindex-1]+1); // Add 1 because Block index 1 corresponds to index 0 here
					header_.BATArray_[BATindex-1] = -1;
				}
			}
		}
		// Erase extra BAT indices if present
		if (!indicesToRemove.empty()) file_.Erase(indicesToRemove);
	}
	else
	{
		// Erase block
		int maxIndices = indices.size();
		int maxBlocks = properties_[0]->size_ / header_.bigBlockSize_ +
						   (properties_[0]->size_ % header_.bigBlockSize_ ? 1 : 0);
		int size = maxBlocks * header_.bigBlockSize_;
		char* data = new char[size];
		ReadData(properties_[0]->startBlock_, data, true);
		int maxSmallBlocks = properties_[0]->size_ / header_.smallBlockSize_;
		char* newdata = new char[properties_[0]->size_-maxIndices*header_.smallBlockSize_];
		{for (int i=0, j=0; i<maxSmallBlocks; ++i)
		{
			if (find(indices.begin(), indices.end(), i) == indices.end()) 
			{
				/*copy (data+i*header_.smallBlockSize_, 
						data+i*header_.smallBlockSize_+header_.smallBlockSize_, 
						newdata+j*header_.smallBlockSize_);*/
				memcpy(	newdata+j*header_.smallBlockSize_, 
						data+i*header_.smallBlockSize_,
						header_.smallBlockSize_);
				++j;
			}
		}}
		properties_[0]->startBlock_ = WriteData(newdata, properties_[0]->size_-maxIndices*header_.smallBlockSize_,
											   properties_[0]->startBlock_, true);
		properties_[0]->size_ -= maxIndices*header_.smallBlockSize_;
		delete[] data;
		delete[] newdata;

		// Change SBAT indices
		int maxSBATindices = sblocksIndices_.size();
		{for (int i=0; i<maxIndices; ++i)
		{
			for (int j=0; j<maxSBATindices; ++j)
			{
				if (j == indices[i]) continue;
				if (sblocksIndices_[j] == indices[i]) sblocksIndices_[j] = sblocksIndices_[indices[i]];
				if (sblocksIndices_[j] > indices[i] &&
					sblocksIndices_[j] != -1 &&
					sblocksIndices_[j] != -2) --sblocksIndices_[j];
			}
		}}
		sort (indices.begin(), indices.end(), greater<int>());
		{for (int i=0; i<maxIndices; ++i)
		{
			sblocksIndices_.erase(sblocksIndices_.begin()+indices[i]);
			sblocksIndices_.push_back(-1);
		}}
		vector<int> indicesToRemove;
		while (distance(find(sblocksIndices_.begin(), 
						     sblocksIndices_.end(),-1),
						     sblocksIndices_.end()) >= 128)
		{
			// Shrink SBAT indices if necessary
			sblocksIndices_.resize(sblocksIndices_.size()-128);
			--header_.SBATCount_;
			indicesToRemove.push_back(header_.SBATStart_+header_.SBATCount_);
			if (header_.SBATCount_ == 0) header_.SBATStart_ = -2;
		}
		FreeBlocks(indicesToRemove, true);
	}
}

/*********************** Inaccessible Properties Functions ***************************/
void CompoundFile::LoadProperties()
// PURPOSE: Load properties information for compound file.
{
	// Read properties' data from compound file.
	int propertiesSize = DataSize(header_.propertiesStart_, true);
	char* buffer = new char[propertiesSize];
	ReadData(header_.propertiesStart_, buffer, true);

	// Split properties' data into individual property.
	int maxPropertiesBlock = propertiesSize / header_.bigBlockSize_;
	int propertiesPerBlock = header_.bigBlockSize_ / 128;
	int maxProperties = maxPropertiesBlock * propertiesPerBlock;
	int maxBlocks = maxProperties / propertiesPerBlock + 
					   (maxProperties % propertiesPerBlock ? 1 : 0);

	for (int i=0; i<maxBlocks; ++i)
	{
		for (int j=0; j<4; ++j)
		{
			// Read individual property
			Property* property = new Property;
			property->Read(buffer+i*512+j*128);
			if (wcslen(property->name_) == 0)
			{
				delete property;
				break;
			}
			properties_.push_back(property);
		}
	}
	delete[] buffer;

	// Generate property trees
	propertyTrees_->parent_ = 0;
	propertyTrees_->self_ = properties_[0];
	propertyTrees_->index_ = 0;

	InsertPropertyTree(propertyTrees_, 
					   properties_[properties_[0]->childProp_], 
					   properties_[0]->childProp_);
}

void CompoundFile::SaveProperties()
// PURPOSE: Save properties information for compound file.
{
	// Calculate total size required by properties
	int maxProperties = properties_.size();
	int propertiesPerBlock = header_.bigBlockSize_ / 128;
	int maxBlocks = maxProperties / propertiesPerBlock + 
					   (maxProperties % propertiesPerBlock ? 1 : 0);
	int propertiesSize = maxBlocks*header_.bigBlockSize_;
	char* buffer = new char[propertiesSize];
	{for (int i=0; i<propertiesSize; ++i) buffer[i] = 0;}
	{for (int i=0; i<maxProperties; ++i)
	{
		// Save individual property
		properties_[i]->Write(buffer+i*128);
	}}

	// Write properties' data to compound file.
	WriteData(buffer, propertiesSize, header_.propertiesStart_, true);
	delete[] buffer;
}

int CompoundFile::MakeProperty(const wchar_t* path, CompoundFile::Property* property)
// PURPOSE: Create a new property in the compound file.
// EXPLAIN: path is the full path name for the property.
// EXPLAIN: property contains information on the type of property to be created.
{
	wchar_t* parentpath = 0;
	wchar_t* propertyname = 0;
	
	// Change to the specified directory. If specified directory is not present,
	// create it.
	if (wcslen(path) != 0)
	{
		if (path[0] == L'\\') currentDirectory_ = propertyTrees_;
	}
	SplitPath(path, parentpath, propertyname);

	if (propertyname != 0)
	{
		if (parentpath != 0)
		{
			if (ChangeDirectory(parentpath) != SUCCESS)
			{
				int ret = MakeDirectory(parentpath);
				if (ret != SUCCESS) 
				{
					delete[] parentpath;
					delete[] propertyname;
					return ret;
				}
				else ChangeDirectory(parentpath);
			}
			delete[] parentpath;
		}

		// Insert property into specified directory
		int propertynameLength = wcslen(propertyname);
		if (propertynameLength >= 32) 
		{
			delete[] propertyname;
			return NAME_TOO_LONG;
		}
		wcscpy(property->name_, propertyname);
		delete[] propertyname;
		property->nameSize_ = propertynameLength*2+2;
		if (FindProperty(currentDirectory_, property->name_) == 0)
		{
			// Find location to insert property
			int maxProperties = properties_.size();
			int index;
			for (index=1; index<maxProperties; ++index)
			{
				if (*(properties_[index]) > *property) break;
			}
			if (index != maxProperties)
			{
				// Change references for all properties affected by the new property
				IncreasePropertyReferences(propertyTrees_, index);
			}
			properties_.insert(properties_.begin()+index, property);
			InsertPropertyTree(currentDirectory_, property, index);
			return SUCCESS;
		}
		else return DUPLICATE_PROPERTY;
	}
	else 
	{
		if (parentpath != 0) delete[] parentpath;
		return INVALID_PATH;	
	}
}

CompoundFile::PropertyTree* CompoundFile::FindProperty(int index)
// PURPOSE: Find property in the compound file, given the index of the property.
// PROMISE: Returns a pointer to the property tree of the property if property
// PROMISE: is present, 0 if otherwise.
{
	if (previousDirectories_.empty()) previousDirectories_.push_back(propertyTrees_);
	PropertyTree* currentTree = previousDirectories_.back();
	if (currentTree->index_ != index)
	{
		int maxChildren = currentTree->children_.size();
		for (int i=0; i<maxChildren; ++i)
		{
			previousDirectories_.push_back(currentTree->children_[i]);
			PropertyTree* child = FindProperty(index);
			if (child != 0) 
			{
				previousDirectories_.pop_back();
				return child;
			}
		}
	}
	else 
	{
		previousDirectories_.pop_back();
		return currentTree;
	}
	previousDirectories_.pop_back();
	return 0;
}

CompoundFile::PropertyTree* CompoundFile::FindProperty(const wchar_t* path)
// PURPOSE: Find property in the compound file, given the path of the property.
// PROMISE: Returns a pointer to the property tree of the property if property
// PROMISE: is present, 0 if otherwise.
{
	previousDirectories_.push_back(currentDirectory_);

	// Change to specified directory
	wchar_t* parentpath = 0;
	wchar_t* filename = 0;

	if (wcslen(path) != 0)
	{
		if (path[0] == L'\\') currentDirectory_ = propertyTrees_;
	}

	SplitPath(path, parentpath, filename);
	if (parentpath != 0)
	{
		int ret = ChangeDirectory(parentpath);
		delete[] parentpath;
		if (ret != SUCCESS)
		{
			// Cannot change to specified directory
			if (filename != 0) delete[] filen

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -