戻る 目次へ
§5.1.5 ezht_glob.cc
戻る 目次へ

  1: /******************************************************************************
  2:   ezht - Copyright (C) 2004 Tradcrafts
  3:   This file is part of the ezht.
  4:                                                                        
  5:   ezht is free software; you can redistribute it and/or modify
  6:   it under the terms of the GNU General Public License as published by the 
  7:   Free Software Foundation;   either version 2 of the License,  or (at your 
  8:   option) any later version.
  9: 
 10:   ezht is distributed in the hope that it will be useful, but 
 11:   WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
 12:   or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
 13:   more details.
 14: 
 15:   You should have received a copy of the GNU General Public License along with
 16:   this program; see the file COPYING.  If not, write to the Free Software 
 17:   Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
 18: ******************************************************************************/
 19: 
 20: #include <unistd.h>
 21: #include <string.h>
 22: #include <ctype.h>
 23: #include <list>
 24: #include <string>
 25: 
 26: 
 27: /* 最初に指定文字('?'を含んでよい)の現れるポインタ
 28: (見つからなければNULL)を返す。*/
 29: static const char * StrChr(const char *s,int c)
 30: {
 31:   if(c=='?')
 32:     return (*s)!='\0' ? s : 0;
 33:   return strchr(s,c);
 34: }
 35: 
 36: /* 文字列 d がワイルドカードを含む文字列 s に一致すれば真を返す */
 37: static int WildMatch(const char *d,const char *s)
 38: {
 39: 
 40:   for(;*s!='\0';s++)
 41:     switch(*s){
 42:     case '*':
 43:       while(*(++s)=='*')
 44:         ;
 45:       if(*s=='\0')
 46:         return 1; //matches
 47:       d=StrChr(d,*s);
 48:       if( !d )
 49:         return 0;//unmatched
 50:       do{
 51:         if(WildMatch(d,s))
 52:           return 1;
 53:       }while(NULL!=(d=StrChr(d+1,*s)));
 54:       return 0;
 55:     case '?':
 56:       if( *d++ == '\0' )
 57:         return 0;
 58:       break;
 59:     default:
 60:       if( *s != *d++ )
 61:         return 0;
 62:       break;
 63:     }
 64:   return *d=='\0';
 65: }
 66: 
 67: #include <string.h>
 68: #include <dirent.h>
 69: #include <sys/stat.h>
 70: 
 71: struct listdirstruc
 72: {
 73:   bool isdir;
 74:   bool iswild;
 75:   std::string name;
 76: };
 77:   
 78: static int __listdir(const char *dirnam, std::list<listdirstruc> patlist,
 79:                      int ind,std::list<std::string> &list);
 80: 
 81: static inline bool ischild(const char *fname)
 82: {
 83:   if( strcmp(fname,".")==0 || strcmp(fname,"..")==0 )
 84:     return false;
 85:   else
 86:     return true;
 87: }
 88: 
 89: #define TEMPBUF_SIZE 2048
 90: static char tempbuf[TEMPBUF_SIZE];
 91: 
 92: int ezht_glob(const char *pattern,std::list<std::string> &results)
 93: {
 94:   std::list<listdirstruc> patlist;
 95:   listdirstruc *p;
 96:   int i,j,len;
 97:   bool iswild;
 98:   char c;
 99: 
100:   len = strlen(pattern);
101: 
102:   if(len==0)
103:     return 0;
104: 
105:   
106:   if( pattern[0]=='/' ){
107:     listdirstruc s;
108:     s.name = "/";
109:     s.iswild = false;
110:     s.isdir  = true;
111:     patlist.push_back(s);
112:     i=1;
113:   }
114:   else
115:     i=0;
116: 
117:   for( ; i<len ;i++){
118:     iswild = false;
119:     j = i;
120:     while( (c=pattern[i])!='/' && c!='\0'){
121:       if( c=='*' || c=='?' )
122:         iswild = true;
123:       i++;
124:     }
125:     if(j!=i){
126:       listdirstruc s;
127:       s.iswild = iswild;
128:       s.isdir  = true;
129:       strncpy(tempbuf,pattern+j,i-j);
130:       tempbuf[i-j]='\0';
131:       s.name = tempbuf;
132:       patlist.push_back(s);
133:     }
134:   }
135:     
136:   std::list<listdirstruc>::iterator term=patlist.end();
137:   --term;
138:   for(std::list<listdirstruc>::iterator cur=patlist.begin(); cur!=term;){
139:     std::list<listdirstruc>::iterator next = cur;
140:     ++next;
141:     if( ! (*cur).iswild && ! (*next).iswild ){
142:       if( (*cur).name == "/" )
143:         (*cur).name += (*next).name;
144:       else
145:         (*cur).name += "/" + (*next).name;
146:       if( next == term )
147:         break;
148:       patlist.erase(next);
149:     }
150:     else
151:       cur++;
152:   }
153: 
154:   (*patlist.rbegin()).isdir = false;
155:   
156:   DIR *dirp;
157:   struct dirent *ent;
158:   
159:   int nmatched = 0;
160:   p = & (*patlist.begin());
161: 
162: 
163:   if( p->isdir ){
164:     if( p->iswild ){
165:       getcwd(tempbuf,TEMPBUF_SIZE);
166:       dirp = opendir(tempbuf);
167:       if( dirp ){
168:         while( (ent=readdir(dirp)) != NULL )
169:           if( ischild(ent->d_name) && WildMatch(ent->d_name,p->name.c_str()) )
170:             nmatched += __listdir(ent->d_name,patlist,1,results);
171:         closedir(dirp);
172:       }
173:     }
174:     else
175:       nmatched = __listdir(p->name.c_str(),patlist,1,results);
176:   }
177:   else{
178:     if( p->iswild ){
179:       getcwd(tempbuf,TEMPBUF_SIZE);
180:       dirp = opendir(tempbuf);
181:       if( dirp ){
182:         while( (ent=readdir(dirp))!=NULL )
183:           if( ischild(ent->d_name) && WildMatch(ent->d_name,p->name.c_str()) ){
184:             results.push_back(ent->d_name);
185:             nmatched ++;
186:           }
187:         closedir(dirp);
188:       }
189:     }
190:     else{
191:       if( access(p->name.c_str(),F_OK) == 0 ){
192:         results.push_back(p->name);
193:         nmatched = 1;
194:       }
195:     }
196:   }
197:     
198:   results.sort(); // 昇順にソート
199: 
200:   return nmatched;
201: }
202: 
203: 
204: static int __listdir(const char *dirnam, std::list<listdirstruc> patlist, int ind,
205:               std::list<std::string> &results)
206: {
207:   std::string  Name  = dirnam;
208:   DIR *dirp;
209:   struct dirent *ent;
210:   listdirstruc *p;
211:   int nmatched = 0;
212: 
213:   
214:   std::list<listdirstruc>::iterator itr=patlist.begin();
215:   for(int i=0; i<ind; i++)
216:     itr++;
217: 
218:   p = &(*itr);
219:   
220:   if( Name!="/" )
221:     Name = Name + "/";
222: 
223:   if( p->isdir ){
224:     dirp = opendir(dirnam);
225:     if( dirp ){
226:       if( p->iswild ){
227:         while( (ent=readdir(dirp))!=NULL )
228:           if( ischild(ent->d_name) && WildMatch(ent->d_name,p->name.c_str()) )
229:             nmatched += __listdir( (Name+ent->d_name).c_str() , 
230:                                   patlist , ind+1 ,results);
231:         closedir(dirp);
232:       }
233:       else{
234:         closedir(dirp);
235:         nmatched = __listdir( (Name+p->name).c_str() , patlist , ind+1 ,results);
236:       }
237:     }
238:   }
239:   else{
240:     if( p->iswild ){
241:       dirp = opendir(dirnam);
242:       if(dirp){
243:         while( (ent=readdir(dirp))!=NULL )
244:           if( ischild(ent->d_name) && WildMatch(ent->d_name,p->name.c_str()) ){
245:             std::string path = Name;
246:             path += ent->d_name;
247:             results.push_back(path);
248:             nmatched++;
249:           }
250:         closedir(dirp);
251:       }
252:     }
253:     else{
254:       std::string path = Name;
255:       path += p->name;
256:       if( access(path.c_str(),F_OK)==0 ){
257:         results.push_back(path);
258:         nmatched=1;
259:       }
260:     }
261:   }
262: 
263:   return nmatched;
264: }
265: 




Copyright 2004 Tradcrafts. ALL RIGHTS RESERVED.