blob: c8eeeea405c581b9853c9b2217b291065ee3b97d [file] [log] [blame]
reed@android.com8a1c16f2008-12-17 15:59:43 +00001#include "SkOSFile.h"
2
3#ifdef SK_BUILD_FOR_WIN
4
5static U16* concat_to_16(const char src[], const char suffix[])
6{
7 size_t i, len = strlen(src);
8 size_t len2 = 3 + (suffix ? strlen(suffix) : 0);
9 U16* dst = (U16*)sk_malloc_throw((len + len2) * sizeof(U16));
10
11 for (i = 0; i < len; i++)
12 dst[i] = src[i];
13
14 if (i > 0 && dst[i-1] != '/')
15 dst[i++] = '/';
16 dst[i++] = '*';
17
18 if (suffix)
19 {
20 while (*suffix)
21 dst[i++] = *suffix++;
22 }
23 dst[i] = 0;
24 SkASSERT(i + 1 <= len + len2);
25
26 return dst;
27}
28
29SkUTF16_Str::SkUTF16_Str(const char src[])
30{
31 size_t len = strlen(src);
32
33 fStr = (U16*)sk_malloc_throw((len + 1) * sizeof(U16));
34 for (size_t i = 0; i < len; i++)
35 fStr[i] = src[i];
36 fStr[i] = 0;
37}
38
39////////////////////////////////////////////////////////////////////////////
40
41SkOSFile::Iter::Iter() : fHandle(0), fPath16(nil)
42{
43}
44
45SkOSFile::Iter::Iter(const char path[], const char suffix[]) : fHandle(0), fPath16(nil)
46{
47 this->reset(path, suffix);
48}
49
50SkOSFile::Iter::~Iter()
51{
52 sk_free(fPath16);
53 if (fHandle)
54 ::FindClose(fHandle);
55}
56
57void SkOSFile::Iter::reset(const char path[], const char suffix[])
58{
59 if (fHandle)
60 {
61 ::FindClose(fHandle);
62 fHandle = 0;
63 }
64 if (path == nil)
65 path = "";
66
67 sk_free(fPath16);
68 fPath16 = concat_to_16(path, suffix);
69}
70
71static bool is_magic_dir(const U16 dir[])
72{
73 // return true for "." and ".."
74 return dir[0] == '.' && (dir[1] == 0 || dir[1] == '.' && dir[2] == 0);
75}
76
77static bool get_the_file(HANDLE handle, SkString* name, WIN32_FIND_DATAW* dataPtr, bool getDir)
78{
79 WIN32_FIND_DATAW data;
80
81 if (dataPtr == nil)
82 {
83 if (::FindNextFileW(handle, &data))
84 dataPtr = &data;
85 else
86 return false;
87 }
88
89 for (;;)
90 {
91 if (getDir)
92 {
93 if ((dataPtr->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) && !is_magic_dir(dataPtr->cFileName))
94 break;
95 }
96 else
97 {
98 if (!(dataPtr->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY))
99 break;
100 }
101 if (!::FindNextFileW(handle, dataPtr))
102 return false;
103 }
104 // if we get here, we've found a file/dir
105 if (name)
106 name->setUTF16(dataPtr->cFileName);
107 return true;
108}
109
110bool SkOSFile::Iter::next(SkString* name, bool getDir)
111{
112 WIN32_FIND_DATAW data;
113 WIN32_FIND_DATAW* dataPtr = nil;
114
115 if (fHandle == 0) // our first time
116 {
117 if (fPath16 == nil || *fPath16 == 0) // check for no path
118 return false;
119
120 fHandle = ::FindFirstFileW(fPath16, &data);
121 if (fHandle != 0 && fHandle != (HANDLE)~0)
122 dataPtr = &data;
123 }
124 return fHandle != (HANDLE)~0 && get_the_file(fHandle, name, dataPtr, getDir);
125}
126
127#elif defined(SK_BUILD_FOR_MAC) || defined(SK_BUILD_FOR_UNIX)
128
129#if 0
130OSStatus FSPathMakeRef (
131 const UInt8 * path,
132 FSRef * ref,
133 Boolean * isDirectory
134);
135#endif
136
137SkOSFile::Iter::Iter() : fDIR(0)
138{
139}
140
141SkOSFile::Iter::Iter(const char path[], const char suffix[]) : fDIR(0)
142{
143 this->reset(path, suffix);
144}
145
146SkOSFile::Iter::~Iter()
147{
148 if (fDIR)
149 ::closedir(fDIR);
150}
151
152void SkOSFile::Iter::reset(const char path[], const char suffix[])
153{
154 if (fDIR)
155 {
156 ::closedir(fDIR);
157 fDIR = 0;
158 }
159
160 fPath.set(path);
161 if (path)
162 {
163 fDIR = ::opendir(path);
164 fSuffix.set(suffix);
165 }
166 else
167 fSuffix.reset();
168}
169
170// returns true if suffix is empty, or if str ends with suffix
171static bool issuffixfor(const SkString& suffix, const char str[])
172{
173 size_t suffixLen = suffix.size();
174 size_t strLen = strlen(str);
175
176 return strLen >= suffixLen &&
177 suffixLen == 0 ||
178 memcmp(suffix.c_str(), str + strLen - suffixLen, suffixLen) == 0;
179}
180
181#include <sys/stat.h>
182
183bool SkOSFile::Iter::next(SkString* name, bool getDir)
184{
185 if (fDIR)
186 {
187 dirent* entry;
188
189 while ((entry = ::readdir(fDIR)) != NULL)
190 {
191 struct stat s;
192 SkString str(fPath);
193
194 if (!str.endsWith("/") && !str.endsWith("\\"))
195 str.append("/");
196 str.append(entry->d_name);
197
198 if (0 == stat(str.c_str(), &s))
199 {
200 if (getDir)
201 {
202 if (s.st_mode & S_IFDIR)
203 break;
204 }
205 else
206 {
207 if (!(s.st_mode & S_IFDIR) && issuffixfor(fSuffix, entry->d_name))
208 break;
209 }
210 }
211 }
212 if (entry) // we broke out with a file
213 {
214 if (name)
215 name->set(entry->d_name);
216 return true;
217 }
218 }
219 return false;
220}
221
222#endif
223