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