Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/elfmz/far2l.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorelfmz <fenix1905@tut.by>2022-09-06 23:53:52 +0300
committerelfmz <fenix1905@tut.by>2022-09-07 00:41:19 +0300
commit6203953dd76218dcdd9fdf39dcfcc17397d733c5 (patch)
treef944be06b46cfb0bb27ff2a2c7fa3f90a136d0cd
parent398b4dc626aa9f00c02941afae2e588e50871b19 (diff)
multiarc - yet more refactoring and optimizations
-rw-r--r--multiarc/src/ArcMix.cpp2
-rw-r--r--multiarc/src/ArcProc.cpp6
-rw-r--r--multiarc/src/MultiArc.cpp8
-rw-r--r--multiarc/src/MultiArc.hpp7
-rw-r--r--multiarc/src/arccmd.cpp45
-rw-r--r--multiarc/src/arcget.cpp6
-rw-r--r--multiarc/src/arcput.cpp9
-rw-r--r--multiarc/src/arcread.cpp372
-rw-r--r--multiarc/src/fmt.hpp9
-rw-r--r--multiarc/src/formats/libarch/libarch_cmd_read.cpp20
-rw-r--r--multiarc/src/formats/libarch/libarch_cmd_write.cpp30
-rw-r--r--multiarc/src/formats/libarch/libarch_utils.cpp49
-rw-r--r--multiarc/src/formats/libarch/libarch_utils.h4
-rw-r--r--utils/CMakeLists.txt1
-rw-r--r--utils/include/PathParts.h51
-rw-r--r--utils/include/utils.h11
-rw-r--r--utils/src/PathParts.cpp51
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;
+}