00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011 #include <stdio.h>
00012 #include <stdlib.h>
00013 #include <string.h>
00014 #include <assert.h>
00015 #include "TSystem.h"
00016 #include "TObjArray.h"
00017 #include "TError.h"
00018
00019 #include "TDirIter.h"
00020
00021
00022
00023
00024 TDirIter::TDirIter(const char *path,Int_t maxlev):fRegx("",0)
00025 {
00026 fArr = new TObjArray;
00027 Reset(path,maxlev);
00028 }
00029
00030 TDirIter::~TDirIter()
00031 {
00032 fArr->Delete();
00033 delete fArr;
00034 fArr=0;
00035 }
00036
00037 void TDirIter::Reset(const char *path,Int_t maxlev)
00038 {
00039 fIter = -1;
00040 fArr->Delete();
00041 fFull = "";
00042 fMaxLev = maxlev;
00043 if (*path == '@') {
00044 FILE *in = fopen(path+1,"r");
00045 if (!in) {
00046 fprintf(stderr,"*** TDirIter::Reset failed to open %s ***\n",path+1);
00047 fSele = -2;
00048 return;
00049 }
00050
00051 char buf[1024];
00052 while ( fgets(buf,1024,in) ) {
00053 if (*buf == '!') continue;
00054 if (*buf == '#') continue;
00055
00056 char *c = strchr(buf,' ');
00057 if (c){
00058
00059 *c= '\0';
00060 fFull += buf;
00061 fFull += "\n";
00062 } else {
00063 fFull += buf;
00064 }
00065 }
00066 fclose(in);
00067
00068 } else {
00069 fFull = path;
00070
00071 }
00072
00073
00074 fSkip = strspn(fFull.Data()," \t\n");
00075 ResetQQ(fFull.Data()+fSkip);
00076 }
00077
00078 void TDirIter::ResetQQ(const char *path)
00079 {
00080 TString machine("root://");
00081 machine += gSystem->HostName();
00082 machine += "/";
00083 fLevel = 0; fState = 1; fSele=0; fTop = 0;
00084 fMaxLevQQ = fMaxLev;
00085 int n = strcspn(path," \t\n");
00086 TString myPath; myPath.Insert(0,path,n);
00087 gSystem->ExpandPathName(myPath);
00088
00089 fEntrStk[0]=0;
00090 const char *p = myPath.Data();
00091 if (*p == '^') p++;
00092 fFile = p;
00093 if (fFile.BeginsWith(machine)) {
00094 fFile.ReplaceAll(machine,"");
00095 } else {
00096 fFile.ReplaceAll(".gov//",".gov:1095//");
00097 }
00098 const char *c,*f=fFile.Data();
00099 c = strpbrk(f,"*#?[]\\");
00100 if (c) {
00101 fSele=1;fFile.Remove(c-f,9999);
00102 int s = fFile.Last('/');
00103 if (s>0) {fFile.Remove(s,9999);}
00104 else {fFile = "";}
00105 }
00106 if (fFile.Length()==0) f = ".";
00107 if (fSele==0) {
00108 Long_t flags = 0, id = 0, modtime = 0; Long64_t size=1;
00109 int noexi = 0;
00110 if (! strstr(f,"://"))
00111 noexi = gSystem->GetPathInfo(f,&id,&size,&flags,&modtime);
00112 if (noexi) {
00113 fSele = -2;
00114 Warning("TDirIter","*** File %s does not exist ***",f);}
00115 else if (size==0) {
00116 fSele = -2;
00117 Warning("TDirIter","*** File %s is empty ***",f);}
00118 else if ((flags&2)==0) {
00119 fSele = -1;
00120 Warning("TDirIter","*** File %s is special (like socket) ***",f);}
00121 }
00122
00123 fTop = fFile.Length();
00124 if (myPath[0]=='^') fTop = 0;
00125 TString QWE = MakeWild(myPath.Data()+fTop);
00126 fRegx=TRegexp(QWE);
00127
00128 p = myPath.Data();
00129 int lP = myPath.Length();
00130 if (lP && *p!='^' && strstr(p,"#")==0) {
00131 fMaxLevQQ=1;
00132 for(int i=fTop+1;i<lP;i++) { if (p[i]=='/') fMaxLevQQ++; } }
00133 }
00134
00135 const char *TDirIter::NextFile()
00136 {
00137 if (fIter == -1) {
00138 const char *name=0;
00139 while((name=NextFileQ())) {fArr->Add(new TNamed(name,""));}
00140 fArr->Sort();
00141 }
00142 fIter++;
00143 if (fIter > fArr->GetLast()) return 0;
00144 return fArr->At(fIter)->GetName();
00145 }
00146
00147
00148 const char *TDirIter::NextFileQ()
00149 {
00150
00151 const char *name = NextFileQQ();
00152 if (name) return name;
00153 const char *full = fFull.Data();
00154 if (full[fSkip]==0) return 0;
00155 fSkip += strcspn(full+fSkip," \t\n");
00156 if (full[fSkip]==0) return 0;
00157 fSkip += strspn(full+fSkip," \t\n");
00158 if (full[fSkip]==0) return 0;
00159
00160 ResetQQ(full+fSkip);
00161 return NextFileQ();
00162 }
00163
00164 const char *TDirIter::NextFileQQ()
00165 {
00166 if (fSele == -2) return 0;
00167 if (fSele == -1) {fSele = -2; return fFile.Data();}
00168 while(2002) {
00169 if (fState && fLevel < fMaxLevQQ) {
00170 fLevel++; fState=0;
00171 const char *f = fFile.Data();
00172 if (*f==0) f=".";
00173 fEntrStk[fLevel] = gSystem->OpenDirectory(f);
00174 fLengStk[fLevel] = fFile.Length();
00175 }
00176
00177 const char *name;
00178 while ((name = gSystem->GetDirEntry(fEntrStk[fLevel])))
00179 {
00180 if (strcmp("." ,name)==0) continue;
00181 if (strcmp("..",name)==0) continue;
00182 break;
00183 }
00184 if (name==0) {
00185 gSystem->FreeDirectory(fEntrStk[fLevel]);
00186 if (fLevel<=0) return 0;
00187 fLevel--; fState=0;
00188 return NextFileQ();
00189 }
00190
00191 fFile.Remove(fLengStk[fLevel],999);
00192 if (fFile.Length()) fFile += "/"; fFile += name;
00193 Long_t flags=0; fState=0;
00194 Long_t id = 0, modtime = 0;Long64_t size=0;
00195 if (strstr(fFile.Data(),"://")==0)
00196 gSystem->GetPathInfo(fFile.Data(),&id,&size,&flags,&modtime);
00197 if (flags & 2) fState=1;
00198 if (fSele==0) break;
00199 int len;
00200 TString qwe(fFile.Data()+fTop);
00201 if (fRegx.Index(qwe,&len) >=0) break;
00202
00203 }
00204 return fFile.Data();
00205 }
00206
00207 TString TDirIter::MakeWild(const char *re)
00208 {
00209 TString ts;
00210 if (re[0]=='^') { ts = re; return ts;}
00211
00212 for (int i=0;re[i];i++)
00213 {
00214 if (i == 0) {ts+="^" ;}
00215 if (re[i]=='*') {ts+="[a-zA-Z0-9_\\.,-= ]*"; continue;}
00216 if (re[i]=='#') {ts+=".*"; continue;}
00217 if (re[i] == '.') {ts+="\\."; continue;}
00218 ts += re[i];
00219 }
00220 ts += "$";
00221 return ts;
00222 }
00223
00224
00225
00226
00227
00228
00229