/
UKDirectoryEnumerator.h
225 lines (174 loc) · 11.2 KB
/
UKDirectoryEnumerator.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
//
// UKDirectoryEnumerator.h
// Filie
//
// Created by Uli Kusterer on 2004-04-15
// Copyright 2004 Uli Kusterer.
//
// This software is provided 'as-is', without any express or implied
// warranty. In no event will the authors be held liable for any damages
// arising from the use of this software.
//
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it
// freely, subject to the following restrictions:
//
// 1. The origin of this software must not be misrepresented; you must not
// claim that you wrote the original software. If you use this software
// in a product, an acknowledgment in the product documentation would be
// appreciated but is not required.
//
// 2. Altered source versions must be plainly marked as such, and must not be
// misrepresented as being the original software.
//
// 3. This notice may not be removed or altered from any source
// distribution.
//
/*
As of MacOS X 10.3, NSDirectoryEnumerator is dog-slow.
So, this is my take on it, which uses Carbon's FSGetCatalogInfoBulk() to
quickly list files. And to allow for more control over where this spends
its cycles, you can even specify what kinds of information you want. By
default, this will collect *no* info about the object at all. I.e. no
file attributes, no info whether it's a file or folder etc.
By explicitly requesting certain info, you can avoid a lot of work that
NSDirectoryEnumerator would do needlessly.
Also, this fetches files in batches of 16, which improves access locality
and stuff.
This doesn't yet support listing subfolders implicitly. You have to do that
manually. Apart from that it should be a drop-in replacement.
*/
// -----------------------------------------------------------------------------
// Headers:
// -----------------------------------------------------------------------------
#import <Foundation/Foundation.h>
#import <Carbon/Carbon.h>
// -----------------------------------------------------------------------------
// Constants:
// -----------------------------------------------------------------------------
#define UKDirectoryEnumeratorCacheSize 16 // Default size for cache.
#define UKDE_CACHE_SIZE UKDirectoryEnumeratorCacheSize // old name for UKDirectoryEnumeratorCacheSize.
#ifndef UKDE_ALLOW_SETWHICHINFO
#define UKDE_ALLOW_SETWHICHINFO 1 // Allow using old name setWhichInfo: instead of setDesiredInfo: and whichInfo instead of desiredInfo. Deprecated.
#endif
#ifndef UKDE_ALLOW_ENUMERATORWITHPATH
#define UKDE_ALLOW_ENUMERATORWITHPATH 1 // Allow using old name enumeratorWithPath: instead of enumeratorAtPath:. Deprecated.
#endif
// -----------------------------------------------------------------------------
// UKDirectoryEnumerator:
// -----------------------------------------------------------------------------
@interface UKDirectoryEnumerator : NSEnumerator
{
FSIterator iterator; // Carbon iterator corresponding to this enumerator.
FSRef* cache; // Carbon file refs to the found files. We get them in batches for performance reasons.
FSCatalogInfo* infoCache; // Cache for info about file. May be NULL if whichInfo is kFSCatInfoNone.
ItemCount cacheSize; // Number of files the cache can hold.
ItemCount foundItems; // Number of entries in cache that are used.
ItemCount currIndex; // Index into cache for next item to get. If this is >= foundItems, we need to re-cache.
FSCatalogInfoBitmap whichInfo; // Additional info to get for files (setDesiredInfo:/desiredInfo).
int prefixlen; // The number of characters to remove from files' pathnames to make them relative to the folder's path.
}
#if UKDE_ALLOW_ENUMERATORWITHPATH
+(id) enumeratorWithPath: (NSString*)fpath;
+(id) enumeratorWithPath: (NSString*)fpath cacheSize: (ItemCount)n;
#endif
+(id) enumeratorAtPath: (NSString*)fpath;
+(id) enumeratorAtPath: (NSString*)fpath cacheSize: (ItemCount)n;
-(id) initWithPath: (NSString*)fpath;
-(id) initWithPath: (NSString*)fpath cacheSize: (ItemCount)n;
-(id) initWithFSRef: (FSRef)theFile cacheSize: (ItemCount)n
desiredInfo: (FSCatalogInfoBitmap)desInfo; // Designated initialiser.
-(id) nextObject; // NSDirectoryEnumerator-compatible variant.
-(id) nextObjectFullPath; // Variant that returns an absolute path.
// Advanced users:
-(void) setDesiredInfo: (FSCatalogInfoBitmap)n; // Flags what additional info you want.
-(FSCatalogInfoBitmap) desiredInfo;
-(NSDictionary*) fileAttributes; // You must set up whichInfo to get something in here. Note that this is an expensive call. If you can use isDirectory() or isInvisible(), then do that instead.
-(BOOL) isInvisible; // You must set whichInfo to include kFSCatInfoFinderInfo to get something except NO here.
-(BOOL) shouldBeDisplayed; // This checks isInvisible *and* the file name to determine whether this file should be shown in file listings.
-(BOOL) isDirectory; // You must set whichInfo to include kFSCatInfoNodeFlags to get something except NO here.
-(void) setCacheSize: (ItemCount)c; // How many files to cache. Defaults to UKDirectoryEnumeratorCacheSize
-(ItemCount) cacheSize;
-(BOOL) cacheExhausted; // Not really needed. I like to use this to pick a convenient point in time at which to send a reloadData message to my view.
-(FSIterator) iterator; // Carbon FSIterator behind this.
#if UKDE_ALLOW_SETWHICHINFO
// Old name for setDesiredInfo: *DEPRECATED*
-(void) setWhichInfo: (FSCatalogInfoBitmap)n; // Flags what additional info you want.
-(FSCatalogInfoBitmap) whichInfo;
#endif
@end
// -----------------------------------------------------------------------------
// Constants:
// -----------------------------------------------------------------------------
/*
desiredInfo values and what values they add to the fileAttributes dictionary:
(Note: By default, desiredInfo is kFSCatInfoNone, which means you get an
empty fileAttributes dictionary)
UKNSWorkspaceAttributeFlags:
Gives you all the NSxxx keys that you'd get from NSWorkspace's NSDirectoryEnumerator.
kFSCatInfoNodeFlags:
NSFileType - either NSFileTypeDirectory or NSFileTypeRegular (or NSFileTypeSymbolicLink if kFSCatInfoFinderInfo is requested)
UKItemIsLocked - NSNumber containing boolean.
kFSCatInfoFinderInfo: NSNumbers containing booleans if not specified differently.
UKItemIsInvisible
UKItemIsAlias
UKItemHasBNDL
UKItemNameIsLocked
UKItemIsStationery
UKItemHasCustomIcon
UKLabelNumber - NSNumber containing number (0...7) indicating label of this file.
NSFileHFSTypeCode - NSNumber containing HFS type code.
NSFileHFSCreatorCode - NSNumber containing HFS creator code.
kFSCatInfoFinderXInfo:
UKItemHasCustomBadge - NSNumber containing boolean.
UKItemHasRoutingInfo - NSNumber containing boolean.
kFSCatInfoDataSizes:
NSFileSize - NSNumber containing logical size of data fork.
UKPhysicalFileSize - NSNumber containing physical size of data fork.
kFSCatInfoRsrcSizes:
UKLogicalResFileSize - NSNumber containing logical size of resource fork.
UKPhysicalResFileSize - NSNumber containing physical size of resource fork.
kFSCatInfoPermissions:
NSFileOwnerAccountID - NSNumber containing owner ID.
NSFileGroupOwnerAccountID - NSNumber containing owning group's ID.
NSFilePosixPermissions - NSNumber containing unix permissions for file.
kFSCatInfoCreateDate:
NSFileCreationDate - NSDate containing the date and time the file was created at.
kFSCatInfoContentMod:
NSFileModificationDate - NSDate containing the date and time the file's contents were last modified.
kFSCatInfoAttrMod:
UKFileAttrModificationDate - NSDate containing the date and time the file's attributes were last modified.
kFSCatInfoAccessDate:
UKFileAccessDate - NSDate containing the date and time the filewas last accessed.
kFSCatInfoBackupDate:
UKFileBackupDate - NSDate containing the date and time the file was last backed up.
*/
#define UKNSWorkspaceAttributeFlags (kFSCatInfoNodeFlags | kFSCatInfoFinderInfo | kFSCatInfoDataSizes \
| kFSCatInfoPermissions | kFSCatInfoCreateDate | kFSCatInfoContentMod)
// UKDirectoryEnumerator-specific keys in fileAttributes dictionary:
#define UKItemIsInvisible @"UKItemIsInvisible" // This is the HFS Finder flag. You still have to hide files starting with a period.
#define UKItemIsAlias @"UKItemIsAlias" // HFS Finder flag. Different from Symlinks.
#define UKItemHasBNDL @"UKItemHasBNDL" // HFS Finder flag. File has BNDL resource with type/creator -> icon mappings.
#define UKItemNameIsLocked @"UKItemNameIsLocked" // HFS Finder flag. Name and icon can't be edited in Finder.
#define UKItemIsLocked @"UKItemIsLocked" // HFS Finder flag.
#define UKItemIsStationery @"UKItemIsStationery" // HFS Finder flag. File is stationery that will be copied when opened.
#define UKItemHasCustomIcon @"UKItemHasCustomIcon" // HFS Finder flag. File/folder has a user-specified icon.
#define UKPhysicalFileSize @"UKPhysicalFileSize" // Physical size of data fork (may be larger than actual used logical file size).
#define UKLogicalResFileSize @"UKLogicalResFileSize" // Logical size of resource fork.
#define UKPhysicalResFileSize @"UKPhysicalResFileSize" // Physical size of resource fork (may be larger than actual used logical size).
#define UKItemHasCustomBadge @"UKItemHasCustomBadge" // HFS Finder flag. File has an icon badge (specified using resources).
#define UKItemHasRoutingInfo @"UKItemHasRoutingInfo" // HFS Finder flag. File has routing info resource telling where in system folder it goes.
#define UKLabelNumber @"UKLabelNumber" // HFS Finder info. This is the number of the label that's been applied to the icon.
#define UKFileAttrModificationDate @"UKFileAttrModificationDate" // When file attributes (as opposed to contents) were last changed.
#define UKFileAccessDate @"UKFileAccessDate" // When the file was last accessed.
#define UKFileBackupDate @"UKFileBackupDate" // When the file was last backed up.
// -----------------------------------------------------------------------------
// NSFileManager category:
// Allows to only get user-visible files, and to set UKDirectoryEnumerator-
// style file attributes and get them.
// -----------------------------------------------------------------------------
@interface NSFileManager (UKDirectoryEnumeratorVisibleDirectoryContents)
-(NSArray*) visibleDirectoryContentsAtPath: (NSString*)path;
-(BOOL) changeCarbonFileAttributes: (NSDictionary*)attrs atPath: (NSString*)path; // Doesn't yet support all attributes! Check source code!
-(NSDictionary*) carbonFileAttributesAtPath: (NSString*)path whichInfo: (FSCatalogInfoBitmap)whichInfo;
@end