Exemplo n.º 1
0
void commands_ns::AddToFile(FileSystem *fs, int argc, char *argv[], std::ostream& out)
{
	size_t size = 0;
	if (argc != 2)
	{
		out << "Неправильное количество параметров" << std::endl;
		return;
	}
	char *nt[2];
	nt[0] = strtok(argv[0], ".");
	nt[1] = strtok(NULL, "");
	char *s = strtok(NULL, ".,-!");
	if ((!nt[0]) || (!nt[1]) || (s))
	{
		out << "Введены некорректные данные" << std::endl;
		return;
	}

	if (fs->names_types(nt[0])||fs->names_types(nt[1]))
	{
		out << "Введены некорректные данные" << std::endl;
		return;
	}
	if (fs->GetFilesCount() <= 0)
	{
		out << "Файл не найден" << std::endl;
		return;
	}
	if ((!argv[1]) || (strlen(argv[1]) <= 0))
	{
		out << "Информация для добавления не введена" << std::endl;
		return;
	}
	int addSize = strlen(argv[1]);
	int fileIndx = -1;
	//формируем список блоков из дескрипторов по возрастанию смещения======
	std::list < MemList> List;
	std::list<MemList>::iterator iter;
	std::list<MemList>::iterator fileToAdd;
	FileIterator *fi = fs->GetIterator();
	FileDescriptor *fd;
	MemList ml;
	unsigned int indx = 0, max_indx;
	while (fi->HasNext())
	{
		fi->Next();
		fd = fi->GetFileDescriptor();
		if ((strcmpi(fd->GetName(), nt[0]) == 0) && (strcmpi(fd->GetType(), nt[1]) == 0))
		{
			fileIndx = indx;
		}
		ml.FDescrPtr = fd;
		ml.offset = fd->GetOffset();
		ml.sz = fd->GetSize();
		ml.index = indx;
		if (List.empty())
		{
			List.push_back(ml);
			if (indx == fileIndx) {fileToAdd = List.begin();}
		}
		else
		{
			for (iter = List.begin(); iter != List.end(); iter++)
			{
				if ((ml.offset < (*iter).offset) || ((ml.offset == (*iter).offset) && (ml.sz < (*iter).sz)))
				{
					List.insert(iter, ml);
					if (indx == fileIndx) { fileToAdd = std::prev(iter); }
					break;
				}
			}
			if (iter == List.end())
			{
				List.push_back(ml);
				if (indx == fileIndx) { fileToAdd = std::prev(List.end()); }
			}
		}
		++indx;
	}
	max_indx = indx - 1;
	if (fileIndx==-1)
	{
		out << "Файл с указанным именем не существует" << std::endl;
		return;
	}
	//вставляем пустой блок в начало, если нужно
	size_t FD_END = 0;
	if ((*(List.begin())).offset > FD_END)
	{
		ml.offset = FD_END;
		ml.sz = (*(List.begin())).offset - FD_END;
		ml.FDescrPtr = NULL;
		List.insert(List.begin(), ml);
	}
	//вставляем пустые блоки в список
	for (iter = List.begin(); iter != List.end(); iter++)
	{
		if (std::next(iter) != List.end())
		{
			if ((*(std::next(iter))).offset != ((*iter).offset + (*iter).sz))
			{
				ml.offset = (*iter).offset + (*iter).sz;
				ml.sz = (*(std::next(iter))).offset - ml.offset;
				ml.FDescrPtr = NULL;
				List.insert(std::next(iter), ml);
				++iter;
			}
		}
	}
	//проверяем размер
	size_t MaxSz = fs->GetMaxSize();
	if (((*(std::prev(List.end()))).offset + (*(std::prev(List.end()))).sz+addSize) > MaxSz)
	{
		out << "Недостаточно места для добавления введенной информации" << std::endl;
		return;
	}
	//меняем размер файла, в который добавляется информация
	(*fileToAdd).sz += addSize;
	(*fileToAdd).FDescrPtr->SetSize((*fileToAdd).sz);
	if (std::next(fileToAdd) == List.end())//если файл последний в памяти - просто добавляем в размер
	{
		fi = fs->GetIterator();
		int i = 0;
		while (fi->HasNext())
		{
			fi->Next();
			if (i == (*fileToAdd).index)
			{
				fi->SetFileDescriptor((*fileToAdd).FDescrPtr);
				break;
			}
		}
		out << "Информация добавлена" << std::endl;
		return;
	}
	//если не последний - ищем подходящую "дырку"
	bool isMoved = false;
	for (iter = List.begin(); iter != List.end(); iter++)
	{
		if (((*iter).FDescrPtr == NULL) && ((*iter).sz >= (*fileToAdd).sz))
		{
			MemList ml = (*fileToAdd);
			List.erase(fileToAdd);
			ml.offset = (*iter).offset;
			(*iter).sz -= ml.sz;
			(*iter).offset += ml.sz;
			std::list<MemList>::iterator movedFile = List.insert(iter, ml);
			(*movedFile).FDescrPtr->SetOffset((*movedFile).offset);
			if ((*iter).sz <= 0)
			{
				List.erase(iter);
			}
			fileToAdd = movedFile;
			isMoved = true;
			break;
		}
	}
	//если нет подходящей дырки - сдвигаем все следующие блоки
	if (!isMoved)
	{
		for (iter = std::next(fileToAdd); iter != List.end(); iter++)
		{
			(*iter).offset += addSize;
		}
	}
	//меняем дескрипторы и записываем их в файл в нужном порядке
	fi = fs->GetIterator();
	for (indx = 0; indx <= max_indx; indx++)
	{
		for (iter = List.begin(); ((iter != List.end()) && ((*iter).index != indx)); iter++) {}
		fi->Next();
		(*iter).FDescrPtr->SetOffset((*iter).offset);
		fi->SetFileDescriptor((*iter).FDescrPtr);
	}
	fi->Close();
	out << "Информация добавлена" << std::endl;
	return;
}
Exemplo n.º 2
0
void commands_ns::Cmprs(FileSystem *fs, int argc, char *argv[], std::ostream& out)
{
	if (argc > 0) { out << "This command must be used without argumnents" << std::endl; return; }
	if (fs->GetFilesCount() <= 0) { out << "no files" << std::endl; return; }//проверяем наличие файлов
	//формируем список блоков из дескрипторов по возрастанию смещения======
	std::list < MemList> List;
	std::list<MemList>::iterator iter;
	FileIterator *fi = fs->GetIterator();
	FileDescriptor *fd;
	MemList ml;
	unsigned int indx = 0, max_indx;
	while (fi->HasNext())
	{
		fi->Next();
		fd = fi->GetFileDescriptor();
		ml.FDescrPtr = fd;
		ml.offset = fd->GetOffset();
		ml.sz = fd->GetSize();
		ml.index = indx;
		if (List.empty())
		{
			List.push_front(ml);
		}
		else
		{
			for (iter = List.begin(); iter != List.end(); iter++)
			{
				if ( (ml.offset < (*iter).offset) || ((ml.offset == (*iter).offset) && (ml.sz < (*iter).sz)) )
				{
					List.insert(iter, ml);
					break;
				}
			}
			if (iter == List.end())
			{
				List.push_back(ml);
			}
		}
		++indx;
	}
	max_indx = indx - 1;
	//вставляем пустой блок в начало, если нужно
	size_t FD_END = 0;//START_OF_FILE_SPACE;
	if ((*(List.begin())).offset > FD_END)
	{
		ml.offset = FD_END;
		ml.sz = (*(List.begin())).offset - FD_END;
		ml.FDescrPtr = NULL;
		//List.insert(List.begin(), ml);
		List.push_front(ml);
	}
	//вставляем пустые блоки в список
	for (iter = List.begin(); iter != List.end(); iter++)
	{
		if (std::next(iter) != List.end())
		{
			if ((*(std::next(iter))).offset != ((*iter).offset + (*iter).sz))
			{
				ml.offset = (*iter).offset + (*iter).sz;
				ml.sz = (*(std::next(iter))).offset - ml.offset;
				ml.FDescrPtr = NULL;
				List.insert(std::next(iter), ml);
				++iter;
			}
		}
	}
	//=========================================================*/
	out << "The whole data size before compressing: " << ((*(std::prev(List.end()))).offset + (*(std::prev(List.end()))).sz - (*(List.begin())).offset) << std::endl;
	//сжатие===================================================
	for (iter = List.begin(); iter != List.end(); iter++)
	{
		if (!((*iter).FDescrPtr))//если текущий блок пустой
		{
			if (std::next(iter) != List.end())//если не последний
			{
				//ищем наибольший влезающий в текущий пустой блок с конца
				std::list<MemList>::iterator MaxAppr = List.end();
				for (std::list<MemList>::iterator insIter = std::prev(List.end()); insIter != iter; insIter--)
				{
					if ((*insIter).FDescrPtr)
					{
						if ( ( (MaxAppr == List.end()) || ((*insIter).sz > (*MaxAppr).sz) ) && ((*insIter).sz <= (*iter).sz) && ((*insIter).sz > 0) )
						{
							MaxAppr = insIter;
						}
					}
				}
				if (MaxAppr != List.end())//если нашёлся
				{
					MemList mlCopy = (*MaxAppr);//копируем
					//делаем перемещаемый блок пустым
					(*MaxAppr).FDescrPtr = NULL;
					if ( (std::next(MaxAppr) != List.end()) && ((*(std::next(MaxAppr))).FDescrPtr == NULL) )//если следующий пустой - объединяем
					{
						size_t rmv_size = (*(std::next(MaxAppr))).sz;
						List.erase(std::next(MaxAppr));
						(*MaxAppr).sz += rmv_size;
					}
					if ((*(std::prev(MaxAppr))).FDescrPtr == NULL)//аналогично с предыдущим
					{
						size_t rmv_size = (*MaxAppr).sz;
						std::list<MemList>::iterator li = std::prev(MaxAppr);
						(*li).sz += rmv_size;
						List.erase(MaxAppr);
					}
					//вставляем копию перед текущим пустым блоком
					mlCopy.offset = (*iter).offset;
					List.insert(iter, mlCopy);
					//корректируем смещение и размер пустого блока после вставки
					(*iter).sz -= mlCopy.sz;
					(*iter).offset += mlCopy.sz;
					//если перемещаемый блок полностью заполнил пустой блок - удаляем текущий пустой блок
					if ((*iter).sz == 0)
					{
						std::list<MemList>::iterator li = std::prev(iter);
						List.erase(iter);
						iter = li;//ставим указатель на предыдущий
					}
					else//если пустое место осталось
					{
						if ( (std::next(iter) != List.end()) && ((*(std::next(iter))).FDescrPtr == NULL) )//если следущий пуст - объединяем
						{
							size_t rmv_size = (*(std::next(iter))).sz;
							List.erase(std::next(iter));
							(*iter).sz += rmv_size;
						}
						--iter;//ставим указатель на предыдущий (он существует, так как только что вставили)
					}
				}
				else//если не нашёлся блок для вставки
				{
					//удаляем текущий пустой блок
					size_t rmv_size = (*iter).sz;
					std::list<MemList>::iterator insIter = List.erase(iter);
					//уменьшаем смещение всех последующих до пустого блока
					for (; ((*insIter).FDescrPtr && (insIter != List.end())); insIter++)
					{
						(*insIter).offset -= rmv_size;
					}
					//если встретился пустой блок
					if (insIter != List.end())
					{
						(*insIter).offset -= rmv_size;//уменьшаем смещение
						(*insIter).sz += rmv_size;//увеличиваем размер
						iter = insIter;//ставим указатель на предыдущий блок
						--iter;
					}
					else//если нет больше пустых блоков - завершаем цикл
					{
						break;
					}
				}
			}
			else//если последний
			{
				List.erase(iter);//удаляем
				break;//выходим из цикла
			}
		}
	}
	//записываем изменения в файл================
	for (iter = List.begin(); iter != List.end(); iter++) { (*iter).FDescrPtr->SetOffset((*iter).offset); }//меняем смещение в дескрипторах
	fi = fs->GetIterator();
	for (indx = 0; indx <= max_indx; indx++)
	{
		for (iter = List.begin(); ( (iter != List.end()) && ((*iter).index != indx) ); iter++) {}
		fi->Next();
		fi->SetFileDescriptor((*iter).FDescrPtr);
	}
	fi->Close();
	//выводим результат
	out << "The whole data size after compressing: " << ( (*(std::prev(List.end()))).offset + (*(std::prev(List.end()))).sz - (*(List.begin())).offset) << std::endl;
}