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; }
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; }