source: XMLIO_V2/external/src/POCO/Foundation/Glob.cpp @ 80

Last change on this file since 80 was 80, checked in by ymipsl, 14 years ago

ajout lib externe

  • Property svn:eol-style set to native
File size: 6.6 KB
Line 
1//
2// Glob.cpp
3//
4// $Id: //poco/1.3/Foundation/src/Glob.cpp#4 $
5//
6// Library: Foundation
7// Package: Filesystem
8// Module:  Glob
9//
10// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH.
11// and Contributors.
12//
13// Permission is hereby granted, free of charge, to any person or organization
14// obtaining a copy of the software and accompanying documentation covered by
15// this license (the "Software") to use, reproduce, display, distribute,
16// execute, and transmit the Software, and to prepare derivative works of the
17// Software, and to permit third-parties to whom the Software is furnished to
18// do so, all subject to the following:
19//
20// The copyright notices in the Software and this entire statement, including
21// the above license grant, this restriction and the following disclaimer,
22// must be included in all copies of the Software, in whole or in part, and
23// all derivative works of the Software, unless such copies or derivative
24// works are solely in the form of machine-executable object code generated by
25// a source language processor.
26//
27// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
28// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
29// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
30// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
31// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
32// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
33// DEALINGS IN THE SOFTWARE.
34//
35
36
37#include <Poco/Glob.h>
38#include <Poco/Path.h>
39#include <Poco/Exception.h>
40#include <Poco/DirectoryIterator.h>
41#include <Poco/File.h>
42#include <Poco/UTF8Encoding.h>
43#include <Poco/Unicode.h>
44
45
46namespace Poco {
47
48
49Glob::Glob(const std::string& pattern, int options): 
50        _pattern(pattern),
51        _options(options)
52{
53        poco_assert (!_pattern.empty());
54}
55
56
57Glob::~Glob()
58{
59}
60
61
62bool Glob::match(const std::string& subject)
63{
64        UTF8Encoding utf8;
65        TextIterator itp(_pattern, utf8);
66        TextIterator endp(_pattern);
67        TextIterator its(subject, utf8);
68        TextIterator ends(subject);
69       
70        if ((_options & GLOB_DOT_SPECIAL) && its != ends && *its == '.' && (*itp == '?' || *itp == '*'))
71                return false;
72        else
73                return match(itp, endp, its, ends);
74}
75
76
77void Glob::glob(const std::string& pathPattern, std::set<std::string>& files, int options)
78{
79        glob(Path(Path::expand(pathPattern), Path::PATH_GUESS), files, options);
80}
81
82
83void Glob::glob(const char* pathPattern, std::set<std::string>& files, int options)
84{
85        glob(Path(Path::expand(pathPattern), Path::PATH_GUESS), files, options);
86}
87
88
89void Glob::glob(const Path& pathPattern, std::set<std::string>& files, int options)
90{
91        Path pattern(pathPattern);
92        pattern.makeDirectory(); // to simplify pattern handling later on
93        Path base(pattern);
94        Path absBase(base);
95        absBase.makeAbsolute();
96        while (base.depth() > 0 && base[base.depth() - 1] != "..") 
97        {
98                base.popDirectory();
99                absBase.popDirectory();
100        }
101        if (pathPattern.isDirectory()) options |= GLOB_DIRS_ONLY;
102        collect(pattern, absBase, base, pathPattern[base.depth()], files, options);             
103}
104
105
106bool Glob::match(TextIterator& itp, const TextIterator& endp, TextIterator& its, const TextIterator& ends)
107{
108        while (itp != endp)
109        {
110                if (its == ends)
111                {
112                        while (itp != endp && *itp == '*') ++itp;
113                        break;
114                }
115                switch (*itp)
116                {
117                case '?':
118                        ++itp; ++its;
119                        break;
120                case '*':
121                        if (++itp != endp)
122                        {
123                                while (its != ends && !matchAfterAsterisk(itp, endp, its, ends)) ++its;
124                                return its != ends;
125                        }
126                        return true;
127                case '[':
128                        if (++itp != endp) 
129                        {
130                                bool invert = *itp == '!';
131                                if (invert) ++itp;
132                                if (itp != endp)
133                                {
134                                        bool mtch = matchSet(itp, endp, *its++);
135                                        if ((invert && mtch) || (!invert && !mtch)) return false;
136                                        break;
137                                }
138                        }
139                        throw SyntaxException("bad range syntax in glob pattern");
140                case '\\':
141                        if (++itp == endp) throw SyntaxException("backslash must be followed by character in glob pattern");
142                        // fallthrough
143                default:
144                        if (_options & GLOB_CASELESS)
145                        {
146                                if (Unicode::toLower(*itp) != Unicode::toLower(*its)) return false;
147                        }
148                        else
149                        {
150                                if (*itp != *its) return false;
151                        }
152                        ++itp; ++its;
153                }
154        }
155        return itp == endp && its == ends;
156}
157
158
159bool Glob::matchAfterAsterisk(TextIterator itp, const TextIterator& endp, TextIterator its, const TextIterator& ends)
160{
161        return match(itp, endp, its, ends);
162}
163
164
165bool Glob::matchSet(TextIterator& itp, const TextIterator& endp, int c)
166{
167        if (_options & GLOB_CASELESS)
168                c = Unicode::toLower(c);
169
170        while (itp != endp)
171        {
172                switch (*itp)
173                {
174                case ']':
175                        ++itp; 
176                        return false;
177                case '\\':
178                        if (++itp == endp) throw SyntaxException("backslash must be followed by character in glob pattern");
179                }
180                int first = *itp;
181                int last  = first;
182                if (++itp != endp && *itp == '-')
183                {
184                        if (++itp != endp)
185                                last = *itp++;
186                        else
187                                throw SyntaxException("bad range syntax in glob pattern");
188                }
189                if (_options & GLOB_CASELESS)
190                {
191                        first = Unicode::toLower(first);
192                        last  = Unicode::toLower(last);
193                }
194                if (first <= c && c <= last)
195                {
196                        while (itp != endp)
197                        {
198                                switch (*itp)
199                                {
200                                case ']':
201                                        ++itp;
202                                        return true;
203                                case '\\':
204                                        if (++itp == endp) break;
205                                default:
206                                        ++itp;
207                                }
208                        }
209                        throw SyntaxException("range must be terminated by closing bracket in glob pattern");
210                }
211        }
212        return false;
213}
214
215
216void Glob::collect(const Path& pathPattern, const Path& base, const Path& current, const std::string& pattern, std::set<std::string>& files, int options)
217{
218        try
219        {
220                std::string pp = pathPattern.toString();
221                std::string basep = base.toString();
222                std::string curp  = current.toString();
223                Glob g(pattern, options);
224                DirectoryIterator it(base);
225                DirectoryIterator end;
226                while (it != end)
227                {
228                        const std::string& name = it.name();
229                        if (g.match(name))
230                        {
231                                Path p(current);
232                                if (p.depth() < pathPattern.depth() - 1)
233                                {
234                                        p.pushDirectory(name);
235                                        collect(pathPattern, it.path(), p, pathPattern[p.depth()], files, options);
236                                }
237                                else
238                                {
239                                        p.setFileName(name);
240                                        if (isDirectory(p, (options & GLOB_FOLLOW_SYMLINKS) != 0))
241                                        {
242                                                p.makeDirectory();
243                                                files.insert(p.toString());
244                                        }
245                                        else if (!(options & GLOB_DIRS_ONLY))
246                                        {
247                                                files.insert(p.toString());
248                                        }
249                                }
250                        }
251                        ++it;
252                }
253        }
254        catch (Exception&)
255        {
256        }
257}
258
259
260bool Glob::isDirectory(const Path& path, bool followSymlink)
261{
262        File f(path);
263        if (f.isDirectory())
264        {
265                return true;
266        }
267        else if (followSymlink && f.isLink())
268        {
269                try
270                {
271                        // Test if link resolves to a directory.
272                        DirectoryIterator it(f);
273                        return true;
274                }
275                catch (Exception&)
276                {
277                }
278        }
279        return false;
280}
281
282
283} // namespace Poco
Note: See TracBrowser for help on using the repository browser.