1 #include "SkOSFile.h"
2
3 #ifdef SK_BUILD_FOR_WIN
4
concat_to_16(const char src[],const char suffix[])5 static uint16_t* 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 uint16_t* dst = (uint16_t*)sk_malloc_throw((len + len2) * sizeof(uint16_t));
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
SkUTF16_Str(const char src[])29 SkUTF16_Str::SkUTF16_Str(const char src[])
30 {
31 size_t len = strlen(src);
32
33 fStr = (uint16_t*)sk_malloc_throw((len + 1) * sizeof(uint16_t));
34 size_t i;
35 for (i = 0; i < len; i++)
36 fStr[i] = src[i];
37 fStr[i] = 0;
38 }
39
40 ////////////////////////////////////////////////////////////////////////////
41
Iter()42 SkOSFile::Iter::Iter() : fHandle(0), fPath16(NULL)
43 {
44 }
45
Iter(const char path[],const char suffix[])46 SkOSFile::Iter::Iter(const char path[], const char suffix[]) : fHandle(0), fPath16(NULL)
47 {
48 this->reset(path, suffix);
49 }
50
~Iter()51 SkOSFile::Iter::~Iter()
52 {
53 sk_free(fPath16);
54 if (fHandle)
55 ::FindClose(fHandle);
56 }
57
reset(const char path[],const char suffix[])58 void SkOSFile::Iter::reset(const char path[], const char suffix[])
59 {
60 if (fHandle)
61 {
62 ::FindClose(fHandle);
63 fHandle = 0;
64 }
65 if (NULL == path)
66 path = "";
67
68 sk_free(fPath16);
69 fPath16 = concat_to_16(path, suffix);
70 }
71
is_magic_dir(const uint16_t dir[])72 static bool is_magic_dir(const uint16_t dir[])
73 {
74 // return true for "." and ".."
75 return dir[0] == '.' && (dir[1] == 0 || dir[1] == '.' && dir[2] == 0);
76 }
77
get_the_file(HANDLE handle,SkString * name,WIN32_FIND_DATAW * dataPtr,bool getDir)78 static bool get_the_file(HANDLE handle, SkString* name, WIN32_FIND_DATAW* dataPtr, bool getDir)
79 {
80 WIN32_FIND_DATAW data;
81
82 if (NULL == dataPtr)
83 {
84 if (::FindNextFileW(handle, &data))
85 dataPtr = &data;
86 else
87 return false;
88 }
89
90 for (;;)
91 {
92 if (getDir)
93 {
94 if ((dataPtr->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) && !is_magic_dir((uint16_t*)dataPtr->cFileName))
95 break;
96 }
97 else
98 {
99 if (!(dataPtr->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY))
100 break;
101 }
102 if (!::FindNextFileW(handle, dataPtr))
103 return false;
104 }
105 // if we get here, we've found a file/dir
106 if (name)
107 name->setUTF16((uint16_t*)dataPtr->cFileName);
108 return true;
109 }
110
next(SkString * name,bool getDir)111 bool SkOSFile::Iter::next(SkString* name, bool getDir)
112 {
113 WIN32_FIND_DATAW data;
114 WIN32_FIND_DATAW* dataPtr = NULL;
115
116 if (fHandle == 0) // our first time
117 {
118 if (fPath16 == NULL || *fPath16 == 0) // check for no path
119 return false;
120
121 fHandle = ::FindFirstFileW((LPCWSTR)fPath16, &data);
122 if (fHandle != 0 && fHandle != (HANDLE)~0)
123 dataPtr = &data;
124 }
125 return fHandle != (HANDLE)~0 && get_the_file(fHandle, name, dataPtr, getDir);
126 }
127
128 #elif defined(SK_BUILD_FOR_MAC) || defined(SK_BUILD_FOR_UNIX)
129
130 #if 0
131 OSStatus FSPathMakeRef (
132 const UInt8 * path,
133 FSRef * ref,
134 Boolean * isDirectory
135 );
136 #endif
137
Iter()138 SkOSFile::Iter::Iter() : fDIR(0)
139 {
140 }
141
Iter(const char path[],const char suffix[])142 SkOSFile::Iter::Iter(const char path[], const char suffix[]) : fDIR(0)
143 {
144 this->reset(path, suffix);
145 }
146
~Iter()147 SkOSFile::Iter::~Iter()
148 {
149 if (fDIR)
150 ::closedir(fDIR);
151 }
152
reset(const char path[],const char suffix[])153 void SkOSFile::Iter::reset(const char path[], const char suffix[])
154 {
155 if (fDIR)
156 {
157 ::closedir(fDIR);
158 fDIR = 0;
159 }
160
161 fPath.set(path);
162 if (path)
163 {
164 fDIR = ::opendir(path);
165 fSuffix.set(suffix);
166 }
167 else
168 fSuffix.reset();
169 }
170
171 // returns true if suffix is empty, or if str ends with suffix
issuffixfor(const SkString & suffix,const char str[])172 static bool issuffixfor(const SkString& suffix, const char str[])
173 {
174 size_t suffixLen = suffix.size();
175 size_t strLen = strlen(str);
176
177 return strLen >= suffixLen &&
178 memcmp(suffix.c_str(), str + strLen - suffixLen, suffixLen) == 0;
179 }
180
181 #include <sys/stat.h>
182
next(SkString * name,bool getDir)183 bool 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
224