-
Notifications
You must be signed in to change notification settings - Fork 0
/
xfl.cpp
executable file
·251 lines (228 loc) · 8.28 KB
/
xfl.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
/////////////////////////////////////////////////
// Find-File-Descriptor
#ifdef GLib_WIN
TFFileDesc::TFFileDesc(): FFileH(INVALID_HANDLE_VALUE) {}
bool TFFileDesc::IsDir() const {
return (FDesc.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)!=0;
}
TStr TFFileDesc::GetFBase() const {
return TStr(FDesc.cFileName);
}
TFFileDesc::~TFFileDesc() {}
#elif defined(GLib_UNIX)
TFFileDesc::TFFileDesc(): FDesc(NULL), DirEnt(NULL) {}
bool TFFileDesc::IsDir() const {
Fail; // !bn: function not needed; besides we do not have full path to the entry
return false;
}
TStr TFFileDesc::GetFBase() const {
Assert(DirEnt != NULL);
return TStr(DirEnt->d_name);
}
TFFileDesc::~TFFileDesc() {
if (FDesc) closedir(FDesc);
}
#endif
/////////////////////////////////////////////////
// Find-File
TFFile::TFFile(const TStr& FNmWc, const bool& _RecurseP):
FPathV(), FExtV(), FBaseWc(),
CsImpP(false), RecurseP(_RecurseP), FPathN(0-1),
FFileDesc(TFFileDesc::New()), SubFFile(), CurFNm(), CurFNmN(0-1){
// prepare file-base-name wild-card
FBaseWc=FNmWc.GetFBase(); if (!CsImpP){FBaseWc.ToUc();}
// get & assign file-name
TStr FPath=FNmWc.GetFPath();
FPathV.Add(TStr::GetNrFPath(FPath));
}
TFFile::TFFile(const TStr& _FPath, const TStr& _FExt, const bool& _RecurseP):
FPathV(), FExtV(), FBaseWc(),
CsImpP(false), RecurseP(_RecurseP), FPathN(0-1),
FFileDesc(TFFileDesc::New()), SubFFile(), CurFNm(), CurFNmN(0-1){
FPathV.Add(TStr::GetNrFPath(_FPath));
if (!_FExt.Empty()){
FExtV.Add(TStr::GetNrFExt(_FExt));
if (!CsImpP){FExtV.Last().ToUc();}
}
}
TFFile::TFFile(const TStrV& _FPathV, const TStrV& _FExtV, const TStr& _FBaseWc,
const bool& _RecurseP):
FPathV(_FPathV), FExtV(_FExtV), FBaseWc(_FBaseWc),
CsImpP(false), RecurseP(_RecurseP), FPathN(0-1),
FFileDesc(TFFileDesc::New()), SubFFile(), CurFNm(), CurFNmN(0-1){
// prepare file-paths
for (int FPathN=0; FPathN<FPathV.Len(); FPathN++){
FPathV[FPathN]=TStr::GetNrFPath(FPathV[FPathN]);}
// prepare file-extensions
for (int FExtN=0; FExtN<FExtV.Len(); FExtN++){
FExtV[FExtN]=TStr::GetNrFExt(FExtV[FExtN]);
if (!CsImpP){FExtV[FExtN].ToUc();}
}
// prepare file-base wild-card
if (!CsImpP){FBaseWc.ToUc();}
}
#ifdef GLib_WIN
TFFile::~TFFile(){
if (FFileDesc->FFileH!=INVALID_HANDLE_VALUE){
IAssert(FindClose(FFileDesc->FFileH));}
}
bool TFFile::Next(TStr& FNm){
// if need to recurse
if (!SubFFile.Empty()){
if (SubFFile->Next(FNm)){CurFNm=FNm; CurFNmN++; return true;}
else {SubFFile=NULL;}
}
// for all required file-paths
while (FPathN<FPathV.Len()){
if ((FPathN!=-1)&&(FindNextFile(FFileDesc->FFileH, &FFileDesc->FDesc))){
// next file-name available on the current file-path
TStr FBase=FFileDesc->GetFBase();
if ((RecurseP)&&(FFileDesc->IsDir())){
// file-name is directory and recursion is required
if ((FBase!=".")&&(FBase!="..")){
// directory is non-trivial - prepare sub-file-find for recursion
TStr SubFPath=FPathV[FPathN]+FBase;
TStrV SubFPathV; SubFPathV.Add(SubFPath);
SubFFile=New(SubFPathV, FExtV, FBaseWc, RecurseP);
if (SubFFile->Next(FNm)){CurFNm=FNm; CurFNmN++; return true;}
else {SubFFile=NULL;}
}
} else {
// return file-name if fits
if ((FBase!=".")&&(FBase!="..")){
FNm=FPathV[FPathN]+FBase;
TStr FExt=FNm.GetFExt(); if (!CsImpP){FExt.ToUc(); FBase.ToUc();}
if (((FExtV.Empty())||(FExtV.SearchForw(FExt)!=-1))&&
((FBaseWc.Empty())||(FBase.IsWcMatch(FBaseWc)))){
CurFNm=FNm; CurFNmN++; return true;}
}
}
} else {
// close file-find descriptor if needed
if (FPathN!=-1){
IAssert(FindClose(FFileDesc->FFileH));
FFileDesc->FFileH=INVALID_HANDLE_VALUE;
}
// find next file existing path from the input list
while ((++FPathN<FPathV.Len())&&
((FFileDesc->FFileH=FindFirstFile((FPathV[FPathN]+"*.*").CStr(),
&FFileDesc->FDesc))==INVALID_HANDLE_VALUE)){}
if ((FPathN<FPathV.Len())&&(RecurseP)&&(FFileDesc->IsDir())){
// file-path found, file-name is directory and recursion is required
TStr FBase=FFileDesc->GetFBase();
if ((FBase!=".")&&(FBase!="..")){
TStr SubFPath=FPathV[FPathN]+FBase;
TStrV SubFPathV; SubFPathV.Add(SubFPath);
SubFFile=New(SubFPathV, FExtV, FBaseWc, RecurseP);
if (SubFFile->Next(FNm)){CurFNm=FNm; CurFNmN++; return true;}
else {SubFFile=NULL;}
}
} else {
// return file-name if fits
if (FPathN<FPathV.Len()){
TStr FBase=FFileDesc->GetFBase();
if ((FBase!=".")&&(FBase!="..")){
FNm=FPathV[FPathN]+FBase;
TStr FExt=FNm.GetFExt(); if (!CsImpP){FExt.ToUc(); FBase.ToUc();}
if (((FExtV.Empty())||(FExtV.SearchForw(FExt)!=-1))&&
((FBaseWc.Empty())||(FBase.IsWcMatch(FBaseWc)))){
CurFNm=FNm; CurFNmN++; return true;
}
}
}
}
}
}
// not found
CurFNm=""; CurFNmN=-1; return false;
}
#elif defined(GLib_UNIX)
TFFile::~TFFile(){}
bool TFFile::Next(TStr& FNm){
// if need to recurse
if (!SubFFile.Empty()){
if (SubFFile->Next(FNm)){CurFNm=FNm; CurFNmN++; return true;}
else {SubFFile=NULL;}
}
// for all required file-paths
while (FPathN<FPathV.Len()){
// try to find anything within FPathV[FPathN] directory
while (true) {
// if directory not open -> open next first
if (!FFileDesc->FDesc) {
if ((++FPathN)<FPathV.Len()) {
FFileDesc->FDesc = opendir(FPathV[FPathN].CStr());
} else break;
if (!FFileDesc->FDesc) break; // failed to open this one; pass control to outer loop
}
FFileDesc->DirEnt = readdir(FFileDesc->FDesc);
if (FFileDesc->DirEnt) {
// found something
TStr FBase = FFileDesc->GetFBase();
FNm = FPathV[FPathN]+FBase;
struct stat Stat;
int ErrCd = stat(FNm.CStr(), &Stat);
Assert(ErrCd==0); // !bn: assert-with-exception [pa se drugje po tej funkciji]
if (S_ISREG(Stat.st_mode)) {
if ((FBase!=".")&&(FBase!="..")){
TStr FExt=FNm.GetFExt(); if (!CsImpP){FExt.ToUc(); FBase.ToUc();}
if (((FExtV.Empty())||(FExtV.SearchForw(FExt)!=-1))&&
((FBaseWc.Empty())||(FBase.IsWcMatch(FBaseWc)))){
CurFNm=FNm; CurFNmN++; return true;}
}
} else if (S_ISDIR(Stat.st_mode) && RecurseP) {
if ((FBase!=".")&&(FBase!="..")){
TStr SubFPath=FPathV[FPathN]+FBase;
TStrV SubFPathV; SubFPathV.Add(SubFPath);
SubFFile=New(SubFPathV, FExtV, FBaseWc, RecurseP);
if (SubFFile->Next(FNm)){CurFNm=FNm; CurFNmN++; return true;}
else {SubFFile=NULL;}
}
}
} else {
// end of directory; clean up (ignore DirEnt, it's allocated within FDesc), pass control to outer loop
FFileDesc->DirEnt = NULL;
int ErrCd = closedir(FFileDesc->FDesc);
FFileDesc->FDesc = NULL;
Assert(ErrCd==0);
break;
}
}
}
// not found
CurFNm=""; CurFNmN=-1; return false;
}
#endif
void TFFile::GetFNmV(
const TStr& FPath, const TStrV& FExtV, const bool& RecurseP, TStrV& FNmV){
// prepare file-directory traversal
TStrV FPathV; FPathV.Add(FPath);
TFFile FFile(FPathV, FExtV, "", RecurseP); TStr FNm;
// traverse directory
FNmV.Clr();
while (FFile.Next(FNm)){
FNmV.Add(FNm);
}
}
/////////////////////////////////////////////////
// Directories
TStr TDir::GetCurDir(){
const int MxBfL=1000;
char Bf[MxBfL];
int BfL=GetCurrentDirectory(MxBfL, Bf);
IAssert((BfL!=0)&&(BfL<MxBfL));
return TStr::GetNrFPath(TStr(Bf));
}
TStr TDir::GetExeDir(){
const int MxBfL=1000;
char Bf[MxBfL];
int BfL=GetModuleFileName(NULL, Bf, MxBfL);
IAssert((BfL!=0)&&(BfL<MxBfL));
return TStr::GetNrFPath(TStr(Bf).GetFPath());
}
bool TDir::GenDir(const TStr& FPathFNm){
return CreateDirectory(FPathFNm.CStr(), NULL)!=0;
}
bool TDir::DelDir(const TStr& FPathFNm){
return RemoveDirectory(FPathFNm.CStr())!=0;
}