diff options
author | elfmz <fenix1905@tut.by> | 2022-09-06 23:53:52 +0300 |
---|---|---|
committer | elfmz <fenix1905@tut.by> | 2022-09-07 00:41:19 +0300 |
commit | 6203953dd76218dcdd9fdf39dcfcc17397d733c5 (patch) | |
tree | f944be06b46cfb0bb27ff2a2c7fa3f90a136d0cd | |
parent | 398b4dc626aa9f00c02941afae2e588e50871b19 (diff) |
multiarc - yet more refactoring and optimizations
-rw-r--r-- | multiarc/src/ArcMix.cpp | 2 | ||||
-rw-r--r-- | multiarc/src/ArcProc.cpp | 6 | ||||
-rw-r--r-- | multiarc/src/MultiArc.cpp | 8 | ||||
-rw-r--r-- | multiarc/src/MultiArc.hpp | 7 | ||||
-rw-r--r-- | multiarc/src/arccmd.cpp | 45 | ||||
-rw-r--r-- | multiarc/src/arcget.cpp | 6 | ||||
-rw-r--r-- | multiarc/src/arcput.cpp | 9 | ||||
-rw-r--r-- | multiarc/src/arcread.cpp | 372 | ||||
-rw-r--r-- | multiarc/src/fmt.hpp | 9 | ||||
-rw-r--r-- | multiarc/src/formats/libarch/libarch_cmd_read.cpp | 20 | ||||
-rw-r--r-- | multiarc/src/formats/libarch/libarch_cmd_write.cpp | 30 | ||||
-rw-r--r-- | multiarc/src/formats/libarch/libarch_utils.cpp | 49 | ||||
-rw-r--r-- | multiarc/src/formats/libarch/libarch_utils.h | 4 | ||||
-rw-r--r-- | utils/CMakeLists.txt | 1 | ||||
-rw-r--r-- | utils/include/PathParts.h | 51 | ||||
-rw-r--r-- | utils/include/utils.h | 11 | ||||
-rw-r--r-- | utils/src/PathParts.cpp | 51 |
17 files changed, 330 insertions, 351 deletions
diff --git a/multiarc/src/ArcMix.cpp b/multiarc/src/ArcMix.cpp index 5921739c..193ba994 100644 --- a/multiarc/src/ArcMix.cpp +++ b/multiarc/src/ArcMix.cpp @@ -38,7 +38,7 @@ BOOL GoToFile(const char *Target, BOOL AllowChangeDir) char Name[NM], Dir[NM*5]; int pathlen; - strcpy(Name,FSF.PointToName(const_cast<char*>(Target))); + ArrayCpyZ(Name,FSF.PointToName(const_cast<char*>(Target))); pathlen=(int)(FSF.PointToName(const_cast<char*>(Target))-Target); if(pathlen) memcpy(Dir,Target,pathlen); diff --git a/multiarc/src/ArcProc.cpp b/multiarc/src/ArcProc.cpp index c6b5de85..0397dff3 100644 --- a/multiarc/src/ArcProc.cpp +++ b/multiarc/src/ArcProc.cpp @@ -55,7 +55,7 @@ int PluginClass::DeleteFiles(struct PluginPanelItem *PanelItem,int ItemsNumber,i GetCommandFormat(CMD_DELETE,Command,sizeof(Command)); GetCommandFormat(CMD_ALLFILESMASK,AllFilesMask,sizeof(AllFilesMask)); int IgnoreErrors=(CurArcInfo.Flags & AF_IGNOREERRORS); - ArcCommand ArcCmd(PanelItem,ItemsNumber,ArcData,Command,ArcName,CurDir,"",AllFilesMask,IgnoreErrors,0,0,CurDir,ItemsInfo.Codepage); + ArcCommand ArcCmd(PanelItem,ItemsNumber,Command,ArcName,CurDir,"",AllFilesMask,IgnoreErrors,0,0,CurDir,ItemsInfo.Codepage); if (!IgnoreErrors && ArcCmd.GetExecCode()!=0) return FALSE; if (Opt.UpdateDescriptions) @@ -176,7 +176,7 @@ int PluginClass::ProcessHostFile(struct PluginPanelItem *PanelItem,int ItemsNumb break; } - ArcCommand ArcCmd(PanelItem,ItemsNumber,ArcData,Command,ArcName,CurDir,Password,AllFilesMask, + ArcCommand ArcCmd(PanelItem,ItemsNumber,Command,ArcName,CurDir,Password,AllFilesMask, IgnoreErrors,CommandType==CMD_COMMENT || CommandType==CMD_COMMENTFILES ? 2:0,0, CurDir,ItemsInfo.Codepage); return IgnoreErrors || ArcCmd.GetExecCode()==0; @@ -326,7 +326,7 @@ int PluginClass::ProcessKey(int Key,unsigned int ControlState) if(strstr(ArcName,/*"FarTmp"*/"FTMP")==NULL)//$AA какая-то бяка баловалась { char CurDir[NM]; - strcpy(CurDir,ArcName); + ArrayCpyZ(CurDir,ArcName); char *Slash=strrchr(CurDir, GOOD_SLASH); if (Slash!=NULL) { diff --git a/multiarc/src/MultiArc.cpp b/multiarc/src/MultiArc.cpp index aa6d1af7..b52c5536 100644 --- a/multiarc/src/MultiArc.cpp +++ b/multiarc/src/MultiArc.cpp @@ -258,7 +258,7 @@ SHAREDSYMBOL void WINAPI _export GetPluginInfo(struct PluginInfo *Info) Info->PluginConfigStrings=PluginCfgStrings; Info->PluginConfigStringsNumber=ARRAYSIZE(PluginCfgStrings); static char CommandPrefix[sizeof(Opt.CommandPrefix1)]; - strcpy(CommandPrefix,Opt.CommandPrefix1); + ArrayCpyZ(CommandPrefix,Opt.CommandPrefix1); Info->CommandPrefix=CommandPrefix; } @@ -287,9 +287,9 @@ SHAREDSYMBOL int WINAPI _export ProcessKey(HANDLE hPlugin,int Key,unsigned int C SHAREDSYMBOL int WINAPI _export Configure(int ItemNumber) { struct FarMenuItem MenuItems[2]; - memset(MenuItems,0,sizeof(MenuItems)); - strcpy(MenuItems[0].Text,GetMsg(MCfgLine1)); - strcpy(MenuItems[1].Text,GetMsg(MCfgLine2)); + ZeroFill(MenuItems); + ArrayCpyZ(MenuItems[0].Text,GetMsg(MCfgLine1)); + ArrayCpyZ(MenuItems[1].Text,GetMsg(MCfgLine2)); MenuItems[0].Selected=TRUE; do{ diff --git a/multiarc/src/MultiArc.hpp b/multiarc/src/MultiArc.hpp index 68be4f1b..cda5b9a7 100644 --- a/multiarc/src/MultiArc.hpp +++ b/multiarc/src/MultiArc.hpp @@ -10,6 +10,7 @@ #include <vector> #include <utils.h> #include <KeyFileHelper.h> +#include <PathParts.h> #include <farplug-mb.h> using namespace oldfar; #include "fmt.hpp" @@ -92,6 +93,7 @@ struct PluginItem PLUGINGETSFXPOS pGetSFXPos; }; +typedef PathNode<ArcItemAttributes> ArcItemNode; class ArcPlugins { @@ -132,7 +134,8 @@ class PluginClass private: char ArcName[NM + 2]; char CurDir[NM]; - std::vector<ArcItemInfo> ArcData; + ArcItemNode ArcData; + size_t ArcDataCount = 0; struct stat ArcStat {}; int ArcPluginNumber; int ArcPluginType; @@ -198,7 +201,6 @@ class ArcCommand bool NeedSudo; struct PluginPanelItem *PanelItem; int ItemsNumber; - const std::vector<ArcItemInfo> &ArcData; std::string ArcName; std::string ArcDir; std::string RealArcDir; @@ -228,7 +230,6 @@ class ArcCommand public: ArcCommand(struct PluginPanelItem *PanelItem,int ItemsNumber, - const std::vector<ArcItemInfo> &ArcData_, const char *FormatString,const char *ArcName,const char *ArcDir,const char *Password, const char *AllFilesMask,int IgnoreErrors,int CommandType, int Silent,const char *RealArcDir,int DefaultCodepage); diff --git a/multiarc/src/arccmd.cpp b/multiarc/src/arccmd.cpp index fde3efd9..285a7f86 100644 --- a/multiarc/src/arccmd.cpp +++ b/multiarc/src/arccmd.cpp @@ -5,11 +5,9 @@ #include <fcntl.h> ArcCommand::ArcCommand(struct PluginPanelItem *PanelItem,int ItemsNumber, - const std::vector<ArcItemInfo> &ArcData_, const char *FormatString,const char *ArcName,const char *ArcDir, const char *Password,const char *AllFilesMask,int IgnoreErrors, int CommandType,int ASilent,const char *RealArcDir,int DefaultCodepage) - : ArcData(ArcData_) { NeedSudo = false; Silent=ASilent; @@ -175,8 +173,8 @@ bool ArcCommand::ProcessCommand(std::string FormatString, int CommandType, int I char NameMsg[NM]; FSF.sprintf(ErrMsg,(char *)GetMsg(MArcNonZero),ExecCode); const char *MsgItems[]={GetMsg(MError),NameMsg,ErrMsg,GetMsg(MOk)}; - - FSF.TruncPathStr(strncpy(NameMsg,ArcName.c_str(),sizeof(NameMsg) - 1),MAX_WIDTH_MESSAGE); + ArrayCpyZ(NameMsg, ArcName.c_str()); + FSF.TruncPathStr(NameMsg, MAX_WIDTH_MESSAGE); Info.Message(Info.ModuleNumber,FMSG_WARNING,NULL,MsgItems,ARRAYSIZE(MsgItems),1); } return false; @@ -306,14 +304,11 @@ int ArcCommand::ReplaceVar(std::string &Command) Command.clear(); for (int N = 0; N < ItemsNumber; ++N) { - if ((PanelItem[N].UserData ^ USER_DATA_MAGIC) < DWORD64(ArcData.size())) + const ArcItemAttributes *Attrs = (const ArcItemAttributes *)PanelItem[N].UserData; + if (Attrs && Attrs->Codepage > 0) { - const auto Codepage = ArcData[PanelItem[N].UserData ^ USER_DATA_MAGIC].Codepage; - if (Codepage > 0) - { - Command = StrPrintf("CP%u", Codepage); - break; - } + Command = StrPrintf("CP%u", Attrs->Codepage); + break; } } if (Command.empty() && DefaultCodepage > 0) @@ -424,14 +419,13 @@ int ArcCommand::ReplaceVar(std::string &Command) *PrefixFileName=0; const char *cFileName = PanelItem[N].FindData.cFileName; - - if ((PanelItem[N].UserData ^ USER_DATA_MAGIC) < DWORD64(ArcData.size())) + const ArcItemAttributes *Attrs = (const ArcItemAttributes *)PanelItem[N].UserData; + if (Attrs) { - const auto &ArcItem = ArcData[PanelItem[N].UserData ^ USER_DATA_MAGIC]; - if (ArcItem.Prefix) - strncpy(PrefixFileName, ArcItem.Prefix->c_str(), sizeof(PrefixFileName) - 1); - if (ArcItem.LinkName) - cFileName = ArcItem.LinkName->c_str(); + if (Attrs->Prefix) + ArrayCpyZ(PrefixFileName, Attrs->Prefix->c_str()); + if (Attrs->LinkName) + cFileName = Attrs->LinkName->c_str(); } // CHECK for BUGS!! Name = PrefixFileName; @@ -526,7 +520,8 @@ int ArcCommand::MakeListFile(char *ListFileName, int QuoteName, { char NameMsg[NM]; const char *MsgItems[]={GetMsg(MError),GetMsg(MCannotCreateListFile),NameMsg,GetMsg(MOk)}; - FSF.TruncPathStr(strncpy(NameMsg,ListFileName,sizeof(NameMsg) - 1),MAX_WIDTH_MESSAGE); + ArrayCpyZ(NameMsg, ListFileName); + FSF.TruncPathStr(NameMsg, MAX_WIDTH_MESSAGE); Info.Message(Info.ModuleNumber,FMSG_WARNING,NULL,MsgItems,ARRAYSIZE(MsgItems),1); } /* $ 25.07.2001 AA @@ -559,13 +554,13 @@ int ArcCommand::MakeListFile(char *ListFileName, int QuoteName, int FileAttr=PanelItem[I].FindData.dwFileAttributes; *PrefixFileName=0; - if ((PanelItem[I].UserData ^ USER_DATA_MAGIC) < DWORD64(ArcData.size())) + const ArcItemAttributes *Attrs = (const ArcItemAttributes *)PanelItem[I].UserData; + if (Attrs) { - const auto &ArcItem = ArcData[PanelItem[I].UserData ^ USER_DATA_MAGIC]; - if (ArcItem.Prefix) - strncpy(PrefixFileName, ArcItem.Prefix->c_str(), sizeof(PrefixFileName) - 1); - if (ArcItem.LinkName) - FileName = *ArcItem.LinkName; + if (Attrs->Prefix) + ArrayCpyZ(PrefixFileName, Attrs->Prefix->c_str()); + if (Attrs->LinkName) + FileName = *Attrs->LinkName; } int Error=FALSE; diff --git a/multiarc/src/arcget.cpp b/multiarc/src/arcget.cpp index aa212003..07b2a1dd 100644 --- a/multiarc/src/arcget.cpp +++ b/multiarc/src/arcget.cpp @@ -158,8 +158,8 @@ int PluginClass::GetFiles(PluginPanelItem *PanelItem, int ItemsNumber, return -1; if (MsgCode==1) { - memset(&MaskPanelItem,0,sizeof(MaskPanelItem)); - strncpy(MaskPanelItem.FindData.cFileName, AllFilesMask, ARRAYSIZE(MaskPanelItem.FindData.cFileName)-1); + ZeroFill(MaskPanelItem); + ArrayCpyZ(MaskPanelItem.FindData.cFileName, AllFilesMask); if (ItemsInfo.Encrypted) MaskPanelItem.Flags=F_ENCRYPTED; PanelItem=&MaskPanelItem; @@ -186,7 +186,7 @@ int PluginClass::GetFiles(PluginPanelItem *PanelItem, int ItemsNumber, Opt.HideOutput=2; int IgnoreErrors=(CurArcInfo.Flags & AF_IGNOREERRORS); - ArcCommand ArcCmd(PanelItem,ItemsNumber,ArcData,Command,ArcName,CurDir, + ArcCommand ArcCmd(PanelItem,ItemsNumber,Command,ArcName,CurDir, DialogItems[5].Data,AllFilesMask,IgnoreErrors, (OpMode & OPM_VIEW)!=0,(OpMode & OPM_FIND),CurDir,ItemsInfo.Codepage); diff --git a/multiarc/src/arcput.cpp b/multiarc/src/arcput.cpp index 84a8ad74..7a1761e1 100644 --- a/multiarc/src/arcput.cpp +++ b/multiarc/src/arcput.cpp @@ -187,7 +187,7 @@ LONG_PTR WINAPI PluginClass::PutDlgProc(HANDLE hDlg,int Msg,int Param1,LONG_PTR }
else if(Param1 == PDI_SELARCCOMB)
{
- strcpy(pdd->ArcFormat, ((FarDialogItem *)Param2)->Data);
+ ArrayCpyZ(pdd->ArcFormat, ((FarDialogItem *)Param2)->Data);
Info.SendDlgMessage(hDlg, MAM_SELARC, 0, 0);
}
else if(Param1 == PDI_SWITCHESEDT)
@@ -428,7 +428,7 @@ int PluginClass::PutFiles(struct PluginPanelItem *PanelItem,int ItemsNumber, }
else
{
- strcpy(pdd.ArcFormat,DefaultFormat);
+ ArrayCpyZ(pdd.ArcFormat,DefaultFormat);
pdd.DefaultPluginNotFound=FALSE;
}
}
@@ -697,7 +697,7 @@ int PluginClass::PutFiles(struct PluginPanelItem *PanelItem,int ItemsNumber, int IgnoreErrors=(CurArcInfo.Flags & AF_IGNOREERRORS);
FSF.Unquote(DialogItems[PDI_ARCNAMEEDT].Data);
NewArchive=!FileExists(DialogItems[PDI_ARCNAMEEDT].Data);
- ArcCommand ArcCmd(PanelItem,ItemsNumber,ArcData,Command.c_str(),
+ ArcCommand ArcCmd(PanelItem,ItemsNumber,Command.c_str(),
DialogItems[PDI_ARCNAMEEDT].Data,"",pdd.Password1,
AllFilesMask.c_str(),IgnoreErrors,0,0,CurDir,ItemsInfo.Codepage);
@@ -715,7 +715,8 @@ int PluginClass::PutFiles(struct PluginPanelItem *PanelItem,int ItemsNumber, continue;
std::string fullname = MakeFullName(DialogItems[PDI_ARCNAMEEDT].Data);
- if (!fullname.empty()) strncpy(ArcName, fullname.c_str(), ARRAYSIZE(ArcName)-1);
+ if (!fullname.empty())
+ ArrayCpyZ(ArcName, fullname.c_str());
break;
}
diff --git a/multiarc/src/arcread.cpp b/multiarc/src/arcread.cpp index 7d7ceb69..0ec84186 100644 --- a/multiarc/src/arcread.cpp +++ b/multiarc/src/arcread.cpp @@ -5,12 +5,12 @@ PluginClass::PluginClass(int ArcPluginNumber) { - *ArcName=0; - *CurDir=0; - PluginClass::ArcPluginNumber=ArcPluginNumber; - DizPresent=FALSE; - bGOPIFirstCall=true; - *farlang=0; + *ArcName = 0; + *CurDir = 0; + PluginClass::ArcPluginNumber = ArcPluginNumber; + DizPresent = FALSE; + bGOPIFirstCall = true; + *farlang = 0; ZeroFill(CurArcInfo); } @@ -22,7 +22,8 @@ PluginClass::~PluginClass() void PluginClass::FreeArcData() { - ArcData.clear(); + ArcData.Clear(); + ArcDataCount = 0; } int PluginClass::PreReadArchive(const char *Name) @@ -31,13 +32,11 @@ int PluginClass::PreReadArchive(const char *Name) return FALSE; } - strncpy(ArcName, Name, ARRAYSIZE(ArcName) - 2); + ArrayCpyZ(ArcName, Name); if (strchr(FSF.PointToName(ArcName), '.') == NULL) strcat(ArcName, "."); - ArcName[ARRAYSIZE(ArcName) - 1] = 0; - return TRUE; } @@ -63,43 +62,34 @@ int PluginClass::ReadArchive(const char *Name,int OpMode) ItemsInfo = ArcItemInfo{}; ZeroFill(CurArcInfo); - TotalSize=PackedSize=0; + TotalSize = PackedSize = 0; + ArcDataCount = 0; HANDLE hScreen=Info.SaveScreen(0,0,-1,-1); DWORD UpdateTime = GetProcessUptimeMSec() + 1000; - int WaitMessage=FALSE; + bool MessageShown = false; int GetItemCode; + ArcItemInfo CurItemInfo; + PathParts CurPP; while (1) { - try { - ArcData.emplace_back(); - } catch (std::exception &e) { - fprintf(stderr, "%s: %s\n", __FUNCTION__, e.what()); + CurItemInfo = ArcItemInfo(); + GetItemCode = ArcPlugin->GetArcItem(ArcPluginNumber, &CurItemInfo); + if (GetItemCode != GETARC_SUCCESS) break; - } - auto &CurItemInfo = ArcData.back(); - GetItemCode=ArcPlugin->GetArcItem(ArcPluginNumber,&CurItemInfo); SanitizeString(CurItemInfo.PathName); if (CurItemInfo.Description) SanitizeString(*CurItemInfo.Description); if (CurItemInfo.LinkName) SanitizeString(*CurItemInfo.LinkName); - - if (GetItemCode!=GETARC_SUCCESS) - { - ArcData.pop_back(); - break; - } - - if ((ArcData.size() & 0x1f)==0) + if ((ArcDataCount & 0x1f) == 0) { if (CheckForEsc()) { - ArcData.pop_back(); FreeArcData(); ArcPlugin->CloseArchive(ArcPluginNumber,&CurArcInfo); Info.RestoreScreen(NULL); @@ -113,12 +103,13 @@ int PluginClass::ReadArchive(const char *Name,int OpMode) UpdateTime = Now + 100; char FilesMsg[100]; char NameMsg[NM]; - FSF.sprintf(FilesMsg,GetMsg(MArcReadFiles),(unsigned int)ArcData.size()); - const char *MsgItems[]={GetMsg(MArcReadTitle),GetMsg(MArcReading),NameMsg,FilesMsg}; - FSF.TruncPathStr(strncpy(NameMsg,Name,sizeof(NameMsg)-1),MAX_WIDTH_MESSAGE); - Info.Message(Info.ModuleNumber,WaitMessage ? FMSG_KEEPBACKGROUND:0,NULL,MsgItems, - ARRAYSIZE(MsgItems),0); - WaitMessage=TRUE; + FSF.sprintf(FilesMsg,GetMsg(MArcReadFiles),(unsigned int)ArcDataCount); + const char *MsgItems[]={GetMsg(MArcReadTitle), GetMsg(MArcReading), NameMsg, FilesMsg}; + ArrayCpyZ(NameMsg, Name); + FSF.TruncPathStr(NameMsg, MAX_WIDTH_MESSAGE); + Info.Message(Info.ModuleNumber, MessageShown ? FMSG_KEEPBACKGROUND : 0, + NULL, MsgItems, ARRAYSIZE(MsgItems),0); + MessageShown = true; } } @@ -129,58 +120,53 @@ int PluginClass::ReadArchive(const char *Name,int OpMode) ItemsInfo.HostOS = (ItemsInfo.HostOS ? CurItemInfo.HostOS : GetMsg(MSeveralOS)); if (ItemsInfo.Codepage <= 0) - ItemsInfo.Codepage=CurItemInfo.Codepage; + ItemsInfo.Codepage = CurItemInfo.Codepage; - ItemsInfo.Solid|=CurItemInfo.Solid; - ItemsInfo.Comment|=CurItemInfo.Comment; - ItemsInfo.Encrypted|=CurItemInfo.Encrypted; + ItemsInfo.Solid|= CurItemInfo.Solid; + ItemsInfo.Comment|= CurItemInfo.Comment; + ItemsInfo.Encrypted|= CurItemInfo.Encrypted; if (CurItemInfo.Encrypted) - CurItemInfo.Flags|=F_ENCRYPTED; + CurItemInfo.Flags|= F_ENCRYPTED; - if (CurItemInfo.DictSize>ItemsInfo.DictSize) - ItemsInfo.DictSize=CurItemInfo.DictSize; + if (CurItemInfo.DictSize > ItemsInfo.DictSize) + ItemsInfo.DictSize = CurItemInfo.DictSize; - if (CurItemInfo.UnpVer>ItemsInfo.UnpVer) - ItemsInfo.UnpVer=CurItemInfo.UnpVer; + if (CurItemInfo.UnpVer > ItemsInfo.UnpVer) + ItemsInfo.UnpVer = CurItemInfo.UnpVer; - CurItemInfo.NumberOfLinks=1; + CurItemInfo.NumberOfLinks = 1; - NormalizePath(CurItemInfo.PathName); - //fprintf(stderr, "PATH: %s\n", CurItemInfo.PathName.c_str()); + size_t PrefixSize = 0; + if (StrStartsFrom(CurItemInfo.PathName, "./")) + PrefixSize = 2; + else if (StrStartsFrom(CurItemInfo.PathName, "../")) + PrefixSize = 3; + while (PrefixSize < CurItemInfo.PathName.size() && CurItemInfo.PathName[PrefixSize] == '/') + PrefixSize++; - const char *NamePtr=CurItemInfo.PathName.c_str(); - const char *EndPos=NamePtr; - while (*EndPos == '.') EndPos++; - - if(*EndPos == '/') - while(*EndPos == '/') EndPos++; - else - EndPos = NamePtr; - - if(EndPos != NamePtr) - CurItemInfo.Prefix.reset(new std::string(NamePtr, EndPos-NamePtr)); - - if (EndPos!=NamePtr) + if (PrefixSize) { - assert(size_t(EndPos - NamePtr) <= CurItemInfo.PathName.size()); - CurItemInfo.PathName.erase(0, EndPos - NamePtr); + CurItemInfo.Prefix.reset(new std::string(CurItemInfo.PathName.substr(0, PrefixSize))); + CurItemInfo.PathName.erase(0, PrefixSize); } if (!CurItemInfo.PathName.empty() && CurItemInfo.PathName.back() == '/') - { - CurItemInfo.PathName.pop_back(); CurItemInfo.dwFileAttributes|=FILE_ATTRIBUTE_DIRECTORY; - } - TotalSize+=CurItemInfo.nFileSize; - PackedSize+=CurItemInfo.nPhysicalSize; + TotalSize+= CurItemInfo.nFileSize; + PackedSize+= CurItemInfo.nPhysicalSize; + + CurPP.clear(); + CurPP.Traverse(CurItemInfo.PathName); + ArcItemAttributes *CurAttrs = ArcData.Ensure(CurPP.begin(), CurPP.end()); + *CurAttrs = std::move(CurItemInfo); + ++ArcDataCount; } Info.RestoreScreen(NULL); Info.RestoreScreen(hScreen); - ArcData.shrink_to_fit(); ArcPlugin->CloseArchive(ArcPluginNumber,&CurArcInfo); if(GetItemCode != GETARC_EOF && GetItemCode != GETARC_SUCCESS) @@ -248,102 +234,62 @@ bool PluginClass::EnsureFindDataUpToDate(int OpMode) int PluginClass::GetFindData(PluginPanelItem **pPanelItem,int *pItemsNumber,int OpMode) { - if (!EnsureFindDataUpToDate(OpMode)) - return FALSE; - - const size_t CurDirLength = strlen(CurDir); *pPanelItem = NULL; *pItemsNumber = 0; - int AlocatedItemsNumber = 0; - std::string CurName; - for (size_t I = 0; I < ArcData.size(); ++I) - { - const auto &CurArcData = ArcData[I]; - const auto &CurPathName = CurArcData.PathName; - - // some dynamically adjusted stuff.. - CurName = CurArcData.PathName; - auto CurFileAttributes = CurArcData.dwFileAttributes; - auto CurFileSize = CurArcData.nFileSize; - auto CurPhysicalSize = CurArcData.nPhysicalSize; - - bool Append = (StrStartsFrom(CurPathName, '/') - || StrStartsFrom(CurPathName, "./") - || StrStartsFrom(CurPathName, "../")); - if (!Append && CurPathName.size() > CurDirLength - && (CurDirLength == 0 || (CurPathName[CurDirLength] == '/' && StrStartsFrom(CurPathName, CurDir))) ) - { - if (CurDirLength != 0) - CurName.erase(0, CurDirLength + 1); - - const size_t SlashPos = CurName.find('/'); - if (SlashPos != std::string::npos) - { - CurName.resize(SlashPos); - CurFileAttributes = FILE_ATTRIBUTE_DIRECTORY; - CurPhysicalSize = CurFileSize = 0; - } + PathParts CurDirPP; + CurDirPP.Traverse(CurDir); - Append = true; + if (!EnsureFindDataUpToDate(OpMode)) + { + fprintf(stderr, "MA::GetFindData: can't update at '%s'\n", CurDirPP.Join().c_str()); + return FALSE; + } - if (CurFileAttributes & FILE_ATTRIBUTE_DIRECTORY) - { - for (auto *ScanPPI = *pPanelItem + *pItemsNumber; ScanPPI != *pPanelItem; ) - { - --ScanPPI; - if ((ScanPPI->FindData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0 - && StrMatchArray(CurName, ScanPPI->FindData.cFileName)) - { - ScanPPI->FindData.dwFileAttributes |= CurFileAttributes; - Append = false; - break; - } - } - } - } + const auto *DirNode = ArcData.Find(CurDirPP.begin(), CurDirPP.end()); + if (!DirNode) + { + fprintf(stderr, "MA::GetFindData: no node at '%s'\n", CurDirPP.Join().c_str()); + return FALSE; + } - if (Append) - { - if (*pItemsNumber >= AlocatedItemsNumber) - { - AlocatedItemsNumber = AlocatedItemsNumber + 256 + AlocatedItemsNumber / 4; - PluginPanelItem *NewPanelItem = (PluginPanelItem *) - realloc(*pPanelItem, AlocatedItemsNumber * sizeof(PluginPanelItem)); - if (!NewPanelItem) - { - fprintf(stderr, "%s: can't allocate %d items\n", __FUNCTION__, AlocatedItemsNumber); - break; - } - *pPanelItem = NewPanelItem; - } + if (DirNode->empty()) + return TRUE; - auto &ppi = (*pPanelItem)[*pItemsNumber]; - ZeroFill(ppi); - ppi.FindData.ftCreationTime = CurArcData.ftCreationTime; - ppi.FindData.ftLastAccessTime = CurArcData.ftLastAccessTime; - ppi.FindData.ftLastWriteTime = CurArcData.ftLastWriteTime; - ppi.FindData.nPhysicalSize = CurPhysicalSize; - ppi.FindData.nFileSize = CurFileSize; - ppi.FindData.dwFileAttributes = CurFileAttributes; - ppi.FindData.dwUnixMode = CurArcData.dwUnixMode; - strncpy(ppi.FindData.cFileName, CurName.c_str(), ARRAYSIZE(ppi.FindData.cFileName)); - ppi.Flags = CurArcData.Flags; - ppi.NumberOfLinks = CurArcData.NumberOfLinks; - ppi.CRC32 = CurArcData.CRC32; - ppi.Description = CurArcData.Description ? (char *)CurArcData.Description->c_str() : nullptr; - ppi.UserData = I ^ USER_DATA_MAGIC; - - (*pItemsNumber)++; - } + PluginPanelItem *CurrentItem = *pPanelItem = (PluginPanelItem *) + calloc(DirNode->size(), sizeof(PluginPanelItem)); + if (!CurrentItem) + { + fprintf(stderr, "MA::GetFindData: can't alloc %lu items at '%s'\n", + (unsigned long)DirNode->size(), CurDirPP.Join().c_str()); + return FALSE; } - if (*pItemsNumber > 0) - { // shrink to fit - PluginPanelItem *NewPanelItem = (PluginPanelItem *) - realloc(*pPanelItem, *pItemsNumber * sizeof(PluginPanelItem)); - if (NewPanelItem) - *pPanelItem = NewPanelItem; + *pItemsNumber = (int)DirNode->size(); + + for (const auto &it : *DirNode) + { + CurrentItem->FindData.ftCreationTime = it.second.ftCreationTime; + CurrentItem->FindData.ftLastAccessTime = it.second.ftLastAccessTime; + CurrentItem->FindData.ftLastWriteTime = it.second.ftLastWriteTime; + CurrentItem->FindData.nPhysicalSize = it.second.nPhysicalSize; + CurrentItem->FindData.nFileSize = it.second.nFileSize; + CurrentItem->FindData.dwFileAttributes = it.second.dwFileAttributes; + CurrentItem->FindData.dwUnixMode = it.second.dwUnixMode; + ArrayCpyZ(CurrentItem->FindData.cFileName, it.first.c_str()); + CurrentItem->Flags = it.second.Flags; + CurrentItem->NumberOfLinks = it.second.NumberOfLinks; + CurrentItem->CRC32 = it.second.CRC32; + CurrentItem->Description = it.second.Description ? (char *)it.second.Description->c_str() : nullptr; + CurrentItem->UserData = (DWORD_PTR)&it.second; + + if (!it.second.empty()) + CurrentItem->FindData.dwFileAttributes|= FILE_ATTRIBUTE_DIRECTORY; + if (CurrentItem->FindData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) + CurrentItem->FindData.nPhysicalSize = CurrentItem->FindData.nFileSize = 0; + + ++CurrentItem; } + return TRUE; } @@ -353,62 +299,33 @@ void PluginClass::FreeFindData(PluginPanelItem *PanelItem,int ItemsNumber) if(PanelItem) free(PanelItem); } - int PluginClass::SetDirectory(const char *Dir,int OpMode) { if (*Dir=='/' && *(++Dir)==0) { - *CurDir=0; + *CurDir = 0; return TRUE; } - if (strcmp(Dir,"..")==0) - { - if (*CurDir==0) - return FALSE; + PathParts NewDirPP; + NewDirPP.Traverse(CurDir); + NewDirPP.Traverse(Dir); + const auto &NewDir = NewDirPP.Join(); - char *Slash=strrchr(CurDir,'/'); - if (Slash!=NULL) - *Slash=0; - else - *CurDir=0; - } - else + auto *DirNode = ArcData.Find(NewDirPP.begin(), NewDirPP.end()); + if (!DirNode) { - int Found=FALSE; - int CurDirLength=strlen(CurDir); - if (CurDirLength!=0) - CurDirLength++; - - size_t NewDirLength=strlen(Dir); - - for (const auto &I : ArcData) - { - const char *CurName=I.PathName.c_str(); - - if (strlen(CurName)>=CurDirLength+NewDirLength && strncmp(CurName+CurDirLength,Dir,NewDirLength)==0) - { - char Ch=CurName[CurDirLength+NewDirLength]; - if (Ch=='/' || Ch==0) - { - Found=TRUE; - break; - } - } - } - - if (!Found) - return FALSE; + fprintf(stderr, "MA::SetDirectory('%s', %d): no node for '%s'\n", Dir, OpMode, NewDir.c_str()); + return FALSE; + } - if (*CurDir==0 || *Dir==0 || strchr(Dir,'/')!=0) - strcpy(CurDir,Dir); - else - { - FSF.AddEndSlash(CurDir); - strcat(CurDir,Dir); - } + if (NewDir.size() >= ARRAYSIZE(CurDir)) + { + fprintf(stderr, "MA::SetDirectory('%s', %d): too long path '%s'\n", Dir, OpMode, NewDir.c_str()); + return FALSE; } + strcpy(CurDir, NewDir.c_str()); return TRUE; } @@ -422,7 +339,7 @@ bool PluginClass::FarLangChanged() if (!strcmp(tmplang, farlang)) return false; - strcpy(farlang, tmplang); + ArrayCpyZ(farlang, tmplang); return true; } @@ -436,8 +353,8 @@ static void AppendInfoData(std::string &Str, const char *Data) void PluginClass::SetInfoLineSZ(size_t Index, int TextID, const char *Data) { - strncpy(InfoLines[Index].Text, GetMsg(TextID), ARRAYSIZE(InfoLines[Index].Text)); - strncpy(InfoLines[Index].Data, Data, ARRAYSIZE(InfoLines[Index].Data)); + ArrayCpyZ(InfoLines[Index].Text, GetMsg(TextID)); + ArrayCpyZ(InfoLines[Index].Data, Data); } void PluginClass::SetInfoLine(size_t Index, int TextID, const std::string &Data) @@ -452,44 +369,42 @@ void PluginClass::SetInfoLine(size_t Index, int TextID, int DataID) void PluginClass::GetOpenPluginInfo(struct OpenPluginInfo *Info) { - Info->StructSize=sizeof(*Info); - Info->Flags=OPIF_USEFILTER|OPIF_USESORTGROUPS|OPIF_USEHIGHLIGHTING| - OPIF_ADDDOTS|OPIF_COMPAREFATTIME; - Info->HostFile=ArcName; - Info->CurDir=CurDir; + Info->StructSize = sizeof(*Info); + Info->Flags = OPIF_USEFILTER | OPIF_USESORTGROUPS | OPIF_USEHIGHLIGHTING | OPIF_ADDDOTS | OPIF_COMPAREFATTIME; + Info->HostFile = ArcName; + Info->CurDir = CurDir; if (bGOPIFirstCall) - ArcPlugin->GetFormatName(ArcPluginNumber,ArcPluginType,FormatName,DefExt); + ArcPlugin->GetFormatName(ArcPluginNumber, ArcPluginType, FormatName, DefExt); char NameTitle[NM]; - strncpy(NameTitle,FSF.PointToName(ArcName),sizeof(NameTitle)-1); + strncpy(NameTitle, FSF.PointToName(ArcName), sizeof(NameTitle) - 1); { struct PanelInfo PInfo; - if(::Info.Control((HANDLE)this,FCTL_GETPANELSHORTINFO,&PInfo)) + if (::Info.Control((HANDLE)this, FCTL_GETPANELSHORTINFO, &PInfo)) { //TruncStr - FSF.TruncPathStr(NameTitle,(PInfo.PanelRect.right-PInfo.PanelRect.left+1-(strlen(FormatName)+3+4))); + FSF.TruncPathStr(NameTitle, (PInfo.PanelRect.right - PInfo.PanelRect.left + 1 - (strlen(FormatName)+3+4))); } } - FSF.snprintf(Title,ARRAYSIZE(Title)-1," %s:%s%s%s ",FormatName,NameTitle, *CurDir ? "/" : "", *CurDir ? CurDir : ""); + FSF.snprintf(Title, ARRAYSIZE(Title) - 1, " %s:%s%s%s ", FormatName, NameTitle, *CurDir ? "/" : "", *CurDir ? CurDir : ""); Info->PanelTitle=Title; if (bGOPIFirstCall || FarLangChanged()) { - FSF.sprintf(Format,GetMsg(MArcFormat),FormatName); + FSF.snprintf(Format, ARRAYSIZE(Format) - 1, GetMsg(MArcFormat), FormatName); - memset(InfoLines,0,sizeof(InfoLines)); - FSF.snprintf(InfoLines[0].Text,ARRAYSIZE(InfoLines[0].Text),GetMsg(MInfoTitle),FSF.PointToName(ArcName)); - InfoLines[0].Separator=TRUE; + ZeroFill(InfoLines); + FSF.snprintf(InfoLines[0].Text, ARRAYSIZE(InfoLines[0].Text), GetMsg(MInfoTitle), FSF.PointToName(ArcName)); + InfoLines[0].Separator = TRUE; std::string TmpInfoData = FormatName; - if (ItemsInfo.UnpVer!=0) + if (ItemsInfo.UnpVer != 0) TmpInfoData+= StrPrintf(" %d.%d", ItemsInfo.UnpVer/256,ItemsInfo.UnpVer%256); if (ItemsInfo.HostOS) TmpInfoData+= StrPrintf("/%s", ItemsInfo.HostOS); - strncpy(InfoLines[1].Data,TmpInfoData.c_str(),ARRAYSIZE(InfoLines[1].Data)); SetInfoLine(1, MInfoArchive, TmpInfoData); TmpInfoData = ItemsInfo.Solid ? GetMsg(MInfoSolid) : ""; @@ -520,24 +435,25 @@ void PluginClass::GetOpenPluginInfo(struct OpenPluginInfo *Info) else SetInfoLine(10, MInfoChapters, MInfoAbsent); - SetInfoLine(11, MInfoTotalFiles, std::to_string(ArcData.size())); + SetInfoLine(11, MInfoTotalFiles, std::to_string(ArcDataCount)); SetInfoLine(12, MInfoTotalSize, NumberWithCommas(TotalSize)); SetInfoLine(13, MInfoPackedSize, NumberWithCommas(PackedSize)); SetInfoLine(14, MInfoRatio, StrPrintf("%d%%", MA_ToPercent(PackedSize, TotalSize))); - memset(&KeyBar,0,sizeof(KeyBar)); - KeyBar.ShiftTitles[1-1]=(char*)""; - KeyBar.AltTitles[6-1]=(char*)GetMsg(MAltF6); - KeyBar.AltShiftTitles[9-1]=(char*)GetMsg(MAltShiftF9); + ZeroFill(KeyBar); + KeyBar.ShiftTitles[1-1] = (char*)""; + KeyBar.AltTitles[6-1] = (char*)GetMsg(MAltF6); + KeyBar.AltShiftTitles[9-1] = (char*)GetMsg(MAltShiftF9); } - Info->Format=Format; - Info->KeyBar=&KeyBar; - Info->InfoLines=InfoLines; - Info->InfoLinesNumber=ARRAYSIZE(InfoLines); + Info->Format = Format; + Info->KeyBar = &KeyBar; + Info->InfoLines = InfoLines; + Info->InfoLinesNumber = ARRAYSIZE(InfoLines); + + ArrayCpyZ(DescrFilesString, Opt.DescriptionNames); - strcpy(DescrFilesString,Opt.DescriptionNames); - size_t DescrFilesNumber=0; + size_t DescrFilesNumber = 0; char *NamePtr=DescrFilesString; while (DescrFilesNumber<ARRAYSIZE(DescrFiles)) diff --git a/multiarc/src/fmt.hpp b/multiarc/src/fmt.hpp index 292a7418..e68cc25e 100644 --- a/multiarc/src/fmt.hpp +++ b/multiarc/src/fmt.hpp @@ -39,7 +39,7 @@ enum GETARC_CODE GETARC_READERROR =4, }; -struct ArcItemInfo +struct ArcItemAttributes { int Solid{}; int Comment{}; @@ -61,8 +61,6 @@ struct ArcItemInfo DWORD64 nPhysicalSize{}; DWORD64 nFileSize{}; - std::string PathName; - // NULL or ptr to statically alloc'ed literal - no need to free const char *HostOS{}; @@ -72,6 +70,11 @@ struct ArcItemInfo std::unique_ptr<std::string> Prefix; }; +struct ArcItemInfo : ArcItemAttributes +{ + std::string PathName; +}; + enum ARCINFO_FLAGS { AF_AVPRESENT =0x00000001, diff --git a/multiarc/src/formats/libarch/libarch_cmd_read.cpp b/multiarc/src/formats/libarch/libarch_cmd_read.cpp index 596d68e5..f29e7547 100644 --- a/multiarc/src/formats/libarch/libarch_cmd_read.cpp +++ b/multiarc/src/formats/libarch/libarch_cmd_read.cpp @@ -13,7 +13,7 @@ #include "libarch_utils.h" #include "libarch_cmd.h" -static bool PartsMatchesWanted(const std::vector<std::string> &wanted, const std::vector<std::string> &parts) +static bool PartsMatchesWanted(const PathParts &wanted, const PathParts &parts) { size_t i = 0; while (i != wanted.size() && i != parts.size() && (wanted[i] == parts[i] || wanted[i] == "*")) { @@ -23,7 +23,7 @@ static bool PartsMatchesWanted(const std::vector<std::string> &wanted, const std return (i == wanted.size()); } -static bool PartsMatchesAnyOfWanteds(const std::vector<std::vector<std::string> > &wanteds, const std::vector<std::string> &parts) +static bool PartsMatchesAnyOfWanteds(const std::vector<PathParts > &wanteds, const PathParts &parts) { for (const auto &w : wanteds) { if (PartsMatchesWanted(w, parts)) { @@ -35,10 +35,10 @@ static bool PartsMatchesAnyOfWanteds(const std::vector<std::vector<std::string> } static bool LIBARCH_CommandReadWanteds(const char *cmd, LibArchOpenRead &arc, - const size_t root_count, const std::vector<std::vector<std::string> > &wanteds) + const size_t root_count, const std::vector<PathParts > &wanteds) { std::string src_path, extract_path; - std::vector<std::string> parts; + PathParts parts; bool out = true; for (;;) { @@ -50,7 +50,7 @@ static bool LIBARCH_CommandReadWanteds(const char *cmd, LibArchOpenRead &arc, const char *pathname = LibArch_EntryPathname(entry); src_path = pathname ? pathname : ""; parts.clear(); - LibArch_ParsePathToParts(parts, src_path); + parts.Traverse(src_path); if (parts.empty()) { fprintf(stderr, "Empty path: '%s' '%ls'\n", @@ -116,21 +116,21 @@ static bool LIBARCH_CommandReadWanteds(const char *cmd, LibArchOpenRead &arc, bool LIBARCH_CommandRead(const char *cmd, const char *arc_path, const LibarchCommandOptions &arc_opts, int files_cnt, char *files[]) { - std::vector<std::vector<std::string> > wanteds; + std::vector<PathParts > wanteds; wanteds.reserve(files_cnt); - std::vector<std::string> root; + PathParts root; if (!arc_opts.root_path.empty()) { - LibArch_ParsePathToParts(root, arc_opts.root_path); + root.Traverse(arc_opts.root_path); } for (int i = 0; i < files_cnt; ++i) { wanteds.emplace_back(); if (files[i]) { if (*files[i]) { - LibArch_ParsePathToParts(wanteds.back(), std::string(files[i])); + wanteds.back().Traverse(std::string(files[i])); } - if (!root.empty() && !LibArch_PartsStartsBy(wanteds.back(), root)) { + if (!root.empty() && !wanteds.back().Starts(root)) { fprintf(stderr, "Fixup root for path: '%s'\n", files[i]); wanteds.back().insert(wanteds.back().begin(), root.begin(), root.end()); } diff --git a/multiarc/src/formats/libarch/libarch_cmd_write.cpp b/multiarc/src/formats/libarch/libarch_cmd_write.cpp index 33431c95..e2fd9223 100644 --- a/multiarc/src/formats/libarch/libarch_cmd_write.cpp +++ b/multiarc/src/formats/libarch/libarch_cmd_write.cpp @@ -27,7 +27,7 @@ protected: { } - virtual bool OnCopyEntry(const std::vector<std::string> &parts) + virtual bool OnCopyEntry(const PathParts &parts) { return true; } @@ -58,7 +58,7 @@ public: OnStart(arc_dst); - std::vector<std::string> parts; + PathParts parts; std::string str; for (;;) { @@ -71,7 +71,7 @@ public: if (pathname) { parts.clear(); str = pathname; - LibArch_ParsePathToParts(parts, str); + parts.Traverse(str); if (!OnCopyEntry(parts)) { arc_src.SkipData(); continue; @@ -129,9 +129,9 @@ public: class LIBARCH_Delete : public LIBARCH_Modify { - std::vector<std::vector<std::string> > _files_parts; + std::vector<PathParts > _files_parts; - virtual bool OnCopyEntry(const std::vector<std::string> &parts) + virtual bool OnCopyEntry(const PathParts &parts) { for (const auto &fp : _files_parts) if (parts.size() >= fp.size()) { size_t i = 0; @@ -139,7 +139,7 @@ class LIBARCH_Delete : public LIBARCH_Modify ++i; } if (i == fp.size()) { - printf("Deleted: %s\n", LibArch_PathFromParts(parts).c_str()); + printf("Deleted: %s\n", parts.Join().c_str()); return false; } } @@ -155,10 +155,10 @@ public: for (int i = 0; i < files_cnt; ++i) if (files[i]) { _files_parts.emplace_back(); if (!arc_opts.root_path.empty()) { - LibArch_ParsePathToParts(_files_parts.back(), arc_opts.root_path); + _files_parts.back().Traverse(arc_opts.root_path); } str = files[i]; - LibArch_ParsePathToParts(_files_parts.back(), str); + _files_parts.back().Traverse(str); } } }; @@ -171,8 +171,8 @@ class LIBARCH_Add static LIBARCH_Add *s_ftw_caller; const LibarchCommandOptions &_arc_opts; - std::vector<std::string> _add_pathes; - std::vector<std::string> _well_added_pathes; + PathParts _add_pathes; + PathParts _well_added_pathes; LibArchOpenWrite *_arc_dst = nullptr; @@ -246,8 +246,8 @@ class LIBARCH_Add } _added_parts.emplace_back(); - LibArch_ParsePathToParts(_added_parts.back(), _arc_opts.root_path); - LibArch_ParsePathToParts(_added_parts.back(), path); + _added_parts.back().Traverse(_arc_opts.root_path); + _added_parts.back().Traverse(path); if (data_len) { // once file entry header has been added it cannot be dismissed, @@ -325,7 +325,7 @@ class LIBARCH_Add protected: const char *_cmd; - std::vector< std::vector<std::string> > _added_parts, _illformed_parts; + std::vector< PathParts > _added_parts, _illformed_parts; bool _good; public: @@ -398,13 +398,13 @@ class LIBARCH_ReplacingAdd : public LIBARCH_Modify, public LIBARCH_Add AddInto(arc_dst); } - virtual bool OnCopyEntry(const std::vector<std::string> &parts) + virtual bool OnCopyEntry(const PathParts &parts) { if (std::binary_search(_added_parts.begin(), _added_parts.end(), parts)) { if (std::binary_search(_illformed_parts.begin(), _illformed_parts.end(), parts)) { throw std::runtime_error("tried to replace existing file by illformed one"); } - printf("Replaced: %s\n", LibArch_PathFromParts(parts).c_str()); + printf("Replaced: %s\n", parts.Join().c_str()); return false; } diff --git a/multiarc/src/formats/libarch/libarch_utils.cpp b/multiarc/src/formats/libarch/libarch_utils.cpp index 0026c27b..06baf244 100644 --- a/multiarc/src/formats/libarch/libarch_utils.cpp +++ b/multiarc/src/formats/libarch/libarch_utils.cpp @@ -68,55 +68,6 @@ bool LibArch_DetectedFormatHasCompression(struct archive *a) return false; } - -void LibArch_ParsePathToParts(std::vector<std::string> &parts, const std::string &path) -{ - size_t i = parts.size(); - StrExplode(parts, path, "/"); - while (i < parts.size()) { - if (parts[i] == ".") { - parts.erase(parts.begin() + i); - } else if (parts[i] == "..") { - parts.erase(parts.begin() + i); - if (i != 0) { - parts.erase(parts.begin() + i - 1); - --i; - } else { - fprintf(stderr, "LibArch_ParsePathToParts: impossible <..> in '%s'\n", path.c_str()); - } - } else { - ++i; - } - } -} - -bool LibArch_PartsStartsBy(std::vector<std::string> &parts, std::vector<std::string> &root) -{ - if (parts.size() < root.size()) { - return false; - } - - for (size_t i = 0; i != root.size(); ++i) { - if (parts[i] != root[i]) { - return false; - } - } - - return true; -} - -std::string LibArch_PathFromParts(const std::vector<std::string> &parts) -{ - std::string out; - for (const auto &p : parts) { - if (!out.empty()) { - out+= '/'; - } - out+= p; - } - return out; -} - LibArchOpenRead::LibArchOpenRead(const char *name, const char *cmd, const char *charset) { Open(name); diff --git a/multiarc/src/formats/libarch/libarch_utils.h b/multiarc/src/formats/libarch/libarch_utils.h index 41216f26..42c854eb 100644 --- a/multiarc/src/formats/libarch/libarch_utils.h +++ b/multiarc/src/formats/libarch/libarch_utils.h @@ -5,6 +5,7 @@ #include <archive.h> #include <archive_entry.h> +#include <PathParts.h> template <typename ... ARGS> static int LibArchCall(int (*pfn)(ARGS ... args), ARGS ... args) @@ -34,9 +35,6 @@ void LibArch_SetPassprhase(const char *passprhase); const char *LibArch_EntryPathname(struct archive_entry *e); bool LibArch_DetectedFormatHasCompression(struct archive *a); -void LibArch_ParsePathToParts(std::vector<std::string> &parts, const std::string &path); -bool LibArch_PartsStartsBy(std::vector<std::string> &parts, std::vector<std::string> &root); -std::string LibArch_PathFromParts(const std::vector<std::string> &parts); struct LibArchOpenRead { diff --git a/utils/CMakeLists.txt b/utils/CMakeLists.txt index 984efab8..44333da9 100644 --- a/utils/CMakeLists.txt +++ b/utils/CMakeLists.txt @@ -29,6 +29,7 @@ set(SOURCES src/FSNotify.cpp src/TestPath.cpp src/PipeIPC.cpp + src/PathParts.cpp ) add_library (utils ${SOURCES}) diff --git a/utils/include/PathParts.h b/utils/include/PathParts.h new file mode 100644 index 00000000..f5aeae5d --- /dev/null +++ b/utils/include/PathParts.h @@ -0,0 +1,51 @@ +#pragma once +#include <vector> +#include <string> +#include <map> + +struct PathParts : std::vector<std::string> +{ + void Traverse(const std::string &path); + + std::string Join() const; + bool Starts(PathParts &root) const; +}; + +/// + +template <class PathNodeAttributesT> struct PathNode; + +template <class PathNodeAttributesT> + struct PathNode : PathNodeAttributesT, std::map<std::string, PathNode<PathNodeAttributesT> > +{ + PathNode<PathNodeAttributesT> *Find(PathParts::const_iterator root, PathParts::const_iterator edge) + { + if (root == edge) + return this; + + auto it = std::map<std::string, PathNode<PathNodeAttributesT> >::find(*root); + if (it == std::map<std::string, PathNode<PathNodeAttributesT> >::end()) + return nullptr; + + ++root; + return it->second.Find(root, edge); + } + + PathNode<PathNodeAttributesT> *Ensure(PathParts::const_iterator root, PathParts::const_iterator edge) + { + if (root == edge) + return this; + + auto &subnode = std::map<std::string, PathNode<PathNodeAttributesT> >::operator[](*root); + + ++root; + return subnode.Ensure(root, edge); + } + + void Clear() + { + std::map<std::string, PathNode<PathNodeAttributesT> >::clear(); + PathNodeAttributesT::operator =(PathNodeAttributesT()); + } +}; + diff --git a/utils/include/utils.h b/utils/include/utils.h index edd1c68e..5e305730 100644 --- a/utils/include/utils.h +++ b/utils/include/utils.h @@ -317,4 +317,15 @@ template <class STRING_T, typename ARRAY_T> return s.size() == l && s.compare(0, std::string::npos, a, l) == 0; } +template <typename ARRAY_T, class CHAR_T> + void ArrayCpyZ(ARRAY_T &dst, const CHAR_T *src) +{ + static_assert ( sizeof(dst) != sizeof(void *), "ArrayCpyZ should be used with arrays but not pointers"); + size_t i; + for (i = 0; src[i] && i + 1 < ARRAYSIZE(dst); ++i) { + dst[i] = src[i]; + } + dst[i] = 0; +} + #define DBGLINE fprintf(stderr, "%d %d @%s\n", getpid(), __LINE__, __FILE__) diff --git a/utils/src/PathParts.cpp b/utils/src/PathParts.cpp new file mode 100644 index 00000000..94b834ee --- /dev/null +++ b/utils/src/PathParts.cpp @@ -0,0 +1,51 @@ +#include "PathParts.h" +#include "utils.h" + +void PathParts::Traverse(const std::string &path) +{ + size_t i = size(); + StrExplode(*this, path, "/"); + while (i < size()) { + if (operator[](i) == ".") { + erase(begin() + i); + + } else if (operator[](i) == "..") { + erase(begin() + i); + if (i != 0) { + erase(begin() + i - 1); + --i; + } else { + fprintf(stderr, "PathParts::Traverse: impossible <..> in '%s'\n", path.c_str()); + } + } else { + ++i; + } + } +} + +bool PathParts::Starts(PathParts &root) const +{ + if (size() < root.size()) { + return false; + } + + for (size_t i = 0; i != root.size(); ++i) { + if (operator[](i) != root[i]) { + return false; + } + } + + return true; +} + +std::string PathParts::Join() const +{ + std::string out; + for (const auto &p : *this) { + if (!out.empty()) { + out+= '/'; + } + out+= p; + } + return out; +} |