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: */
|