Branch data Line data Source code
1 : : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : : /*
3 : : * This file is part of the LibreOffice project.
4 : : *
5 : : * This Source Code Form is subject to the terms of the Mozilla Public
6 : : * License, v. 2.0. If a copy of the MPL was not distributed with this
7 : : * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 : : *
9 : : * This file incorporates work covered by the following license notice:
10 : : *
11 : : * Licensed to the Apache Software Foundation (ASF) under one or more
12 : : * contributor license agreements. See the NOTICE file distributed
13 : : * with this work for additional information regarding copyright
14 : : * ownership. The ASF licenses this file to you under the Apache
15 : : * License, Version 2.0 (the "License"); you may not use this file
16 : : * except in compliance with the License. You may obtain a copy of
17 : : * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 : : */
19 : : #define _DIR_CXX
20 : :
21 : : #include <stdlib.h>
22 : : #include <cstdarg>
23 : : #include <limits.h>
24 : : #include <tools/debug.hxx>
25 : :
26 : : #include "comdep.hxx"
27 : : #include <tools/fsys.hxx>
28 : :
29 : : DBG_NAME( Dir )
30 : :
31 : : /// determines whether insertion is required
32 : 0 : sal_Bool Dir::ImpInsertPointReached( const DirEntry& rNewEntry,
33 : : const FileStat& rNewStat,
34 : : size_t nCurPos, size_t nSortIndex ) const
35 : : {
36 : : #define VALUE( nKindFlags ) \
37 : : ( ( FSYS_KIND_FILE | FSYS_KIND_DIR | FSYS_KIND_DEV | \
38 : : FSYS_KIND_CHAR | FSYS_KIND_BLOCK ) & nKindFlags )
39 : :
40 [ # # ]: 0 : if ( pLst->empty() )
41 : 0 : return sal_True;
42 : :
43 : 0 : FSysSort nSort = (*pSortLst)[ nSortIndex ];
44 : 0 : FileStat *pOldStat = NULL;
45 : 0 : DirEntry *pCurLstObj = (*pLst)[ nCurPos ];
46 [ # # ]: 0 : if ( pStatLst )
47 : 0 : pOldStat = (*pStatLst)[ nCurPos ];
48 : :
49 [ # # # # : 0 : switch( nSort )
# # # # #
# # # # #
# ]
50 : : {
51 : : case FSYS_SORT_NAME:
52 : : case (FSYS_SORT_NAME | FSYS_SORT_ASCENDING):
53 [ # # ]: 0 : if ( pCurLstObj->aName > rNewEntry.aName )
54 : 0 : return sal_True;
55 [ # # ]: 0 : if ( !(pCurLstObj->aName == rNewEntry.aName) )
56 : 0 : return sal_False;
57 : 0 : break;
58 : : case (FSYS_SORT_NAME | FSYS_SORT_DESCENDING):
59 [ # # ]: 0 : if ( pCurLstObj->aName < rNewEntry.aName )
60 : 0 : return sal_True;
61 [ # # ]: 0 : if ( !(pCurLstObj->aName == rNewEntry.aName) )
62 : 0 : return sal_False;
63 : 0 : break;
64 : :
65 : : case FSYS_SORT_EXT:
66 : : case (FSYS_SORT_EXT | FSYS_SORT_ASCENDING):
67 : : {
68 [ # # ][ # # ]: 0 : if ( pCurLstObj->GetExtension() > rNewEntry.GetExtension() )
[ # # ][ # # ]
69 : 0 : return sal_True;
70 [ # # ][ # # ]: 0 : if ( !(pCurLstObj->GetExtension() == rNewEntry.GetExtension()) )
[ # # ][ # # ]
71 : 0 : return sal_False;
72 : 0 : break;
73 : : }
74 : : case (FSYS_SORT_EXT | FSYS_SORT_DESCENDING):
75 : : {
76 [ # # ][ # # ]: 0 : if ( pCurLstObj->GetExtension() < rNewEntry.GetExtension() )
[ # # ][ # # ]
77 : 0 : return sal_True;
78 [ # # ][ # # ]: 0 : if ( !(pCurLstObj->GetExtension() == rNewEntry.GetExtension()) )
[ # # ][ # # ]
79 : 0 : return sal_False;
80 : 0 : break;
81 : : }
82 : :
83 : : case FSYS_SORT_KIND:
84 : : case (FSYS_SORT_KIND | FSYS_SORT_ASCENDING ):
85 [ # # ]: 0 : if ( VALUE(pOldStat->nKindFlags) > VALUE(rNewStat.nKindFlags) )
86 : 0 : return sal_True;
87 [ # # ]: 0 : if ( !(VALUE(pOldStat->nKindFlags) == VALUE(rNewStat.nKindFlags)) )
88 : 0 : return sal_False;
89 : 0 : break;
90 : : case (FSYS_SORT_KIND | FSYS_SORT_DESCENDING):
91 [ # # ]: 0 : if ( VALUE(pOldStat->nKindFlags) < VALUE(rNewStat.nKindFlags) )
92 : 0 : return sal_True;
93 [ # # ]: 0 : if ( !(VALUE(pOldStat->nKindFlags) == VALUE(rNewStat.nKindFlags)) )
94 : 0 : return sal_False;
95 : 0 : break;
96 : :
97 : : case FSYS_SORT_SIZE:
98 : : case (FSYS_SORT_SIZE | FSYS_SORT_ASCENDING):
99 [ # # ]: 0 : if ( pOldStat->nSize > rNewStat.nSize )
100 : 0 : return sal_True;
101 [ # # ]: 0 : if ( !(pOldStat->nSize == rNewStat.nSize) )
102 : 0 : return sal_False;
103 : 0 : break;
104 : : case (FSYS_SORT_SIZE | FSYS_SORT_DESCENDING):
105 [ # # ]: 0 : if ( pOldStat->nSize < rNewStat.nSize )
106 : 0 : return sal_True;
107 [ # # ]: 0 : if ( !(pOldStat->nSize == rNewStat.nSize) )
108 : 0 : return sal_False;
109 : 0 : break;
110 : :
111 : : case FSYS_SORT_MODIFYED:
112 : : case (FSYS_SORT_MODIFYED | FSYS_SORT_ASCENDING):
113 [ # # # # ]: 0 : if ( (pOldStat->aDateModified >= rNewStat.aDateModified) &&
[ # # ]
114 : 0 : (pOldStat->aTimeModified > rNewStat.aTimeModified) )
115 : 0 : return sal_True;
116 [ # # ]: 0 : if ( !((pOldStat->aDateModified == rNewStat.aDateModified) &&
117 [ # # ][ # # ]: 0 : (pOldStat->aTimeModified == rNewStat.aTimeModified)) )
118 : 0 : return sal_False;
119 : 0 : break;
120 : : case (FSYS_SORT_MODIFYED | FSYS_SORT_DESCENDING):
121 [ # # # # ]: 0 : if ( (pOldStat->aDateModified <= rNewStat.aDateModified) &&
[ # # ]
122 : 0 : (pOldStat->aTimeModified < rNewStat.aTimeModified) )
123 : 0 : return sal_True;
124 [ # # ]: 0 : if ( !((pOldStat->aDateModified == rNewStat.aDateModified) &&
125 [ # # ][ # # ]: 0 : (pOldStat->aTimeModified == rNewStat.aTimeModified)) )
126 : 0 : return sal_False;
127 : 0 : break;
128 : :
129 : : case FSYS_SORT_CREATED:
130 : : case (FSYS_SORT_CREATED | FSYS_SORT_ASCENDING):
131 [ # # # # ]: 0 : if ( (pOldStat->aDateCreated >= rNewStat.aDateCreated) &&
[ # # ]
132 : 0 : (pOldStat->aTimeCreated > rNewStat.aTimeCreated) )
133 : 0 : return sal_True;
134 [ # # ]: 0 : if ( !((pOldStat->aDateCreated == rNewStat.aDateCreated) &&
135 [ # # ][ # # ]: 0 : (pOldStat->aTimeCreated == rNewStat.aTimeCreated)) )
136 : 0 : return sal_False;
137 : 0 : break;
138 : : case (FSYS_SORT_CREATED | FSYS_SORT_DESCENDING):
139 [ # # # # ]: 0 : if ( (pOldStat->aDateCreated <= rNewStat.aDateCreated) &&
[ # # ]
140 : 0 : (pOldStat->aTimeCreated < rNewStat.aTimeCreated) )
141 : 0 : return sal_True;
142 [ # # ]: 0 : if ( !((pOldStat->aDateCreated == rNewStat.aDateCreated) &&
143 [ # # ][ # # ]: 0 : (pOldStat->aTimeCreated == rNewStat.aTimeCreated)) )
144 : 0 : return sal_False;
145 : 0 : break;
146 : :
147 : : case FSYS_SORT_ACCESSED:
148 : : case (FSYS_SORT_ACCESSED | FSYS_SORT_ASCENDING):
149 [ # # # # ]: 0 : if ( (pOldStat->aDateAccessed >= rNewStat.aDateAccessed) &&
[ # # ]
150 : 0 : (pOldStat->aTimeAccessed > rNewStat.aTimeAccessed) )
151 : 0 : return sal_True;
152 [ # # ]: 0 : if ( !((pOldStat->aDateAccessed == rNewStat.aDateAccessed) &&
153 [ # # ][ # # ]: 0 : (pOldStat->aTimeAccessed == rNewStat.aTimeAccessed)) )
154 : 0 : return sal_False;
155 : 0 : break;
156 : : case (FSYS_SORT_ACCESSED | FSYS_SORT_DESCENDING):
157 [ # # # # ]: 0 : if ( (pOldStat->aDateAccessed <= rNewStat.aDateAccessed) &&
[ # # ]
158 : 0 : (pOldStat->aTimeAccessed < rNewStat.aTimeAccessed) )
159 : 0 : return sal_True;
160 [ # # ]: 0 : if ( !((pOldStat->aDateAccessed == rNewStat.aDateAccessed) &&
161 [ # # ][ # # ]: 0 : (pOldStat->aTimeAccessed == rNewStat.aTimeAccessed)) )
162 : 0 : return sal_False;
163 : 0 : break;
164 : : default: /* Kann nicht sein */;
165 : : }
166 : :
167 [ # # ]: 0 : if ( nSortIndex == ( pSortLst->size() - 1 ) )
168 : 0 : return sal_True;
169 : : else
170 : : return ImpInsertPointReached( rNewEntry, rNewStat,
171 : 0 : nCurPos, nSortIndex + 1 );
172 : : #undef VALUE
173 : : }
174 : :
175 : : /// Insert as sorted
176 : 0 : void Dir::ImpSortedInsert( const DirEntry *pNewEntry, const FileStat *pNewStat )
177 : : {
178 : : // special case: no sorting required
179 [ # # ]: 0 : if ( !pSortLst ) {
180 [ # # ]: 0 : pLst->push_back( (DirEntry*)pNewEntry );
181 : 0 : return;
182 : : }
183 : :
184 [ # # ]: 0 : for ( size_t i = 0, n = pLst->size(); i < n; ++i )
185 : : {
186 [ # # ]: 0 : if ( ImpInsertPointReached( *pNewEntry, *pNewStat, i, 0 ) )
187 : : {
188 [ # # ]: 0 : if ( pStatLst ) {
189 : 0 : FileStatList::iterator it = pStatLst->begin();
190 [ # # ]: 0 : ::std::advance( it, i );
191 [ # # ]: 0 : pStatLst->insert( it, (FileStat*)pNewStat );
192 : : }
193 : 0 : DirEntryList::iterator it = pLst->begin();
194 [ # # ]: 0 : ::std::advance( it, i );
195 [ # # ]: 0 : pLst->insert( it, (DirEntry*)pNewEntry );
196 : : return;
197 : : }
198 : : }
199 : :
200 [ # # ]: 0 : if ( pStatLst )
201 [ # # ]: 0 : pStatLst->push_back( (FileStat*)pNewStat );
202 [ # # ]: 0 : pLst->push_back( (DirEntry*)pNewEntry );
203 : : }
204 : :
205 : : /// shared implementation of CTORs
206 : 0 : void Dir::Construct( DirEntryKind nKindFlags )
207 : : {
208 : 0 : pLst = NULL;
209 : 0 : pSortLst = NULL;
210 : 0 : pStatLst = NULL;
211 : 0 : eAttrMask = nKindFlags;
212 [ # # ][ # # ]: 0 : rtl::OString aTempName(rtl::OUStringToOString(GetName(), osl_getThreadTextEncoding()));
[ # # ][ # # ]
[ # # ]
213 [ # # ][ # # ]: 0 : if (aTempName.indexOf('*') != -1 || aTempName.indexOf('?') != -1)
[ # # ]
214 : : {
215 : : #if defined( WNT )
216 : : rtl::OString aTStr(rtl::OUStringToOString(CutName(), osl_getThreadTextEncoding()));
217 : : char* pBuffer = new char[aTStr.getLength()+1];
218 : : strcpy( pBuffer, aTStr.getStr() );
219 : : CharLowerBuff( pBuffer, aTStr.getLength() );
220 : : aNameMask = WildCard( String(pBuffer, osl_getThreadTextEncoding()), ';' );
221 : : delete [] pBuffer;
222 : : #else
223 [ # # ][ # # ]: 0 : aNameMask = WildCard( CutName(), ';' );
[ # # ][ # # ]
[ # # ][ # # ]
224 : : #endif
225 : : }
226 : : else
227 [ # # ]: 0 : aNameMask.setGlob(rtl::OUString(static_cast<sal_Unicode>('*')));
228 : 0 : }
229 : :
230 : 0 : void Dir::Reset()
231 : : {
232 : : // remove old Reader if necessary
233 [ # # ][ # # ]: 0 : if ( pReader && pReader->bInUse )
234 [ # # ]: 0 : DELETEZ(pReader);
235 : :
236 : : // Remove all DirEntries from List and free memory
237 [ # # ]: 0 : if ( pLst )
238 : : {
239 [ # # ]: 0 : for ( size_t i = 0, n = pLst->size(); i < n; ++i ) {
240 [ # # ]: 0 : delete (*pLst)[ i ];
241 : : }
242 : 0 : pLst->clear();
243 : : }
244 : : else
245 [ # # ]: 0 : pLst = new DirEntryList();
246 : :
247 : : // Remove old File-Stats
248 [ # # ]: 0 : if ( pStatLst )
249 : : {
250 [ # # ]: 0 : for ( size_t i = 0, n = pStatLst->size(); i < n; ++i ) {
251 [ # # ]: 0 : delete (*pStatLst)[ i ];
252 : : }
253 : 0 : pStatLst->clear();
254 [ # # ]: 0 : delete pStatLst;
255 : 0 : pStatLst = NULL;
256 : : }
257 : :
258 : : // Does sorting require FileStats?
259 [ # # ]: 0 : if ( pSortLst )
260 : : {
261 [ # # ]: 0 : for ( size_t i = 0, n = pSortLst->size(); i < n; ++i ) {
262 [ # # ]: 0 : if ( (*pSortLst)[ i ]
263 : : & ( FSYS_SORT_KIND | FSYS_SORT_SIZE | FSYS_SORT_CREATED
264 : : | FSYS_SORT_MODIFYED | FSYS_SORT_ACCESSED
265 : : )
266 : : ) {
267 [ # # ]: 0 : pStatLst = new FileStatList();
268 : 0 : break;
269 : : }
270 : : }
271 : : }
272 : :
273 : : // Create new reader if necessary
274 [ # # ]: 0 : if ( !pReader )
275 [ # # ]: 0 : pReader = new DirReader_Impl( *this );
276 : :
277 : : // Does the directory exist at all?
278 : : #if !defined(UNX) //explanation: see DirReader_Impl::Read() in unx.cxx
279 : : if( !pReader->pDosDir )
280 : : {
281 : : nError = FSYS_ERR_NOTADIRECTORY;
282 : : DELETEZ( pReader );
283 : : return;
284 : : }
285 : : #endif
286 : 0 : }
287 : :
288 : 0 : sal_uInt16 Dir::Scan( sal_uInt16 nCount )
289 : : {
290 : :
291 : 0 : sal_uInt16 nRead = 0; // Number of read entries in this round
292 : : FSysFailOnErrorImpl();
293 : :
294 : : // did not complete
295 [ # # ]: 0 : if ( pReader )
296 : : {
297 : : // is this a new reader?
298 [ # # ]: 0 : if ( pLst->empty() )
299 : : {
300 : : // Scan directories
301 : 0 : pReader->bInUse = sal_True;
302 : 0 : nRead = pReader->Init();
303 : : }
304 : :
305 : : // continue reading
306 [ # # ][ # # ]: 0 : while ( nRead <= nCount && !pReader->bReady )
[ # # ]
307 : 0 : nRead = nRead + pReader->Read();
308 : :
309 : : // done?
310 [ # # ][ # # ]: 0 : if ( pReader && pReader->bReady )
311 [ # # ]: 0 : DELETEZ( pReader );
312 : : }
313 : :
314 : : // Return read entry count
315 : 0 : return nRead;
316 : : }
317 : :
318 : 0 : Dir::Dir( const DirEntry& rDirEntry, DirEntryKind nKindFlags ):
319 : : DirEntry( rDirEntry ),
320 : 0 : pReader( 0 )
321 : : {
322 : : DBG_CTOR( Dir, NULL );
323 : :
324 [ # # ]: 0 : Construct( nKindFlags );
325 [ # # ]: 0 : Reset();
326 : 0 : }
327 : :
328 [ # # ]: 0 : Dir::~Dir()
329 : : {
330 : : DBG_DTOR( Dir, NULL );
331 : :
332 : : // Remove all DirEntries and free memory
333 [ # # ]: 0 : if ( pLst )
334 : : {
335 [ # # ]: 0 : for ( size_t i = 0, n = pLst->size(); i < n; ++i ) {
336 [ # # ][ # # ]: 0 : delete (*pLst)[ i ];
[ # # ]
337 : : }
338 : 0 : pLst->clear();
339 [ # # ]: 0 : delete pLst;
340 : : }
341 : :
342 : : // Remove all Sorts from list and free memory
343 [ # # ]: 0 : if ( pSortLst )
344 : : {
345 : 0 : pSortLst->clear();
346 [ # # ]: 0 : delete pSortLst;
347 : : }
348 : :
349 : : // Remove all FileStats from list and free memory
350 [ # # ]: 0 : if ( pStatLst )
351 : : {
352 [ # # ]: 0 : for ( size_t i = 0, n = pStatLst->size(); i < n; ++i ) {
353 [ # # ][ # # ]: 0 : delete (*pStatLst)[ i ];
[ # # ]
354 : : }
355 : 0 : pStatLst->clear();
356 [ # # ]: 0 : delete pStatLst;
357 : : }
358 : :
359 [ # # ][ # # ]: 0 : delete pReader;
360 : 0 : }
361 : :
362 : 0 : DirEntry& Dir::operator[] ( size_t nIndex ) const
363 : : {
364 : : DBG_ASSERT( nIndex < Count(), "Dir::operator[] : nIndex > Count()" );
365 : :
366 : 0 : DirEntry *pEntry = (*pLst)[ nIndex ];
367 : 0 : return *pEntry;
368 : : }
369 : :
370 : 0 : Dir& Dir::operator+=( const Dir& rDir )
371 : : {
372 : : // Read the rest of the directory
373 [ # # ]: 0 : if ( pReader )
374 : 0 : Scan( USHRT_MAX );
375 : : DBG_ASSERT( !rDir.pReader, "Dir::+= with incomplete Dir" );
376 : :
377 [ # # ]: 0 : if ( !pLst )
378 [ # # ]: 0 : pLst = new DirEntryList();
379 : :
380 : : // FileStats required by sorting criteria?
381 : 0 : sal_Bool bStat = sal_False;
382 [ # # ]: 0 : if ( pSortLst ) {
383 [ # # ][ # # ]: 0 : for ( size_t i = 0, n = pSortLst->size(); i < n && !bStat; ++i ) {
[ # # ]
384 [ # # ]: 0 : if ( (*pSortLst)[ i ]
385 : : & ( FSYS_SORT_CREATED | FSYS_SORT_MODIFYED | FSYS_SORT_SIZE
386 : : | FSYS_SORT_ACCESSED | FSYS_SORT_KIND
387 : : )
388 : : ) {
389 : 0 : bStat = sal_True;
390 : : }
391 : : }
392 : : }
393 : 0 : FileStat* stat = NULL;
394 [ # # ]: 0 : for ( size_t nNr = 0; nNr < rDir.Count(); nNr++ )
395 : : {
396 [ # # ]: 0 : if ( bStat )
397 : : {
398 [ # # ]: 0 : if ( rDir.pStatLst )
399 [ # # ]: 0 : stat = new FileStat( *(*rDir.pStatLst)[ nNr ] );
400 : : else
401 [ # # ]: 0 : stat = new FileStat( rDir[nNr] );
402 : : }
403 [ # # ]: 0 : ImpSortedInsert( new DirEntry( rDir[nNr] ), stat );
404 : : }
405 : 0 : return *this;
406 : : }
407 : :
408 : 0 : size_t Dir::Count( sal_Bool bUpdated ) const
409 : : {
410 : : // Read the rest of the directory
411 [ # # ][ # # ]: 0 : if ( bUpdated && pReader )
412 : 0 : ((Dir*)this)->Scan( USHRT_MAX );
413 : :
414 [ # # ]: 0 : return pLst == NULL ? 0 : pLst->size();
415 : : }
416 : :
417 : : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|