blob: c1b69436f49b6267f7355d8d5fb3788736e9e7e8 [file] [log] [blame]
reed@android.com8a1c16f2008-12-17 15:59:43 +00001#include "SkOSFile.h"
2
3#ifdef SK_BUILD_FOR_WIN
4
reed@android.comb50a60c2009-01-14 17:51:08 +00005static uint16_t* concat_to_16(const char src[], const char suffix[])
reed@android.com8a1c16f2008-12-17 15:59:43 +00006{
reed@android.com6f252972009-01-14 16:46:16 +00007 size_t i, len = strlen(src);
8 size_t len2 = 3 + (suffix ? strlen(suffix) : 0);
reed@android.comb50a60c2009-01-14 17:51:08 +00009 uint16_t* dst = (uint16_t*)sk_malloc_throw((len + len2) * sizeof(uint16_t));
reed@android.com8a1c16f2008-12-17 15:59:43 +000010
reed@android.com6f252972009-01-14 16:46:16 +000011 for (i = 0; i < len; i++)
12 dst[i] = src[i];
reed@android.com8a1c16f2008-12-17 15:59:43 +000013
reed@android.com6f252972009-01-14 16:46:16 +000014 if (i > 0 && dst[i-1] != '/')
15 dst[i++] = '/';
16 dst[i++] = '*';
reed@android.com8a1c16f2008-12-17 15:59:43 +000017
reed@android.com6f252972009-01-14 16:46:16 +000018 if (suffix)
19 {
20 while (*suffix)
21 dst[i++] = *suffix++;
22 }
23 dst[i] = 0;
24 SkASSERT(i + 1 <= len + len2);
reed@android.com8a1c16f2008-12-17 15:59:43 +000025
reed@android.com6f252972009-01-14 16:46:16 +000026 return dst;
reed@android.com8a1c16f2008-12-17 15:59:43 +000027}
28
29SkUTF16_Str::SkUTF16_Str(const char src[])
30{
reed@android.com6f252972009-01-14 16:46:16 +000031 size_t len = strlen(src);
reed@android.com8a1c16f2008-12-17 15:59:43 +000032
reed@android.comb50a60c2009-01-14 17:51:08 +000033 fStr = (uint16_t*)sk_malloc_throw((len + 1) * sizeof(uint16_t));
bsalomon@google.comc8ad63e2011-03-18 14:29:44 +000034 size_t i;
35 for (i = 0; i < len; i++)
reed@android.com6f252972009-01-14 16:46:16 +000036 fStr[i] = src[i];
37 fStr[i] = 0;
reed@android.com8a1c16f2008-12-17 15:59:43 +000038}
39
40////////////////////////////////////////////////////////////////////////////
41
bsalomon@google.comc8ad63e2011-03-18 14:29:44 +000042SkOSFile::Iter::Iter() : fHandle(0), fPath16(NULL)
reed@android.com8a1c16f2008-12-17 15:59:43 +000043{
44}
45
bsalomon@google.comc8ad63e2011-03-18 14:29:44 +000046SkOSFile::Iter::Iter(const char path[], const char suffix[]) : fHandle(0), fPath16(NULL)
reed@android.com8a1c16f2008-12-17 15:59:43 +000047{
reed@android.com6f252972009-01-14 16:46:16 +000048 this->reset(path, suffix);
reed@android.com8a1c16f2008-12-17 15:59:43 +000049}
50
51SkOSFile::Iter::~Iter()
52{
reed@android.com6f252972009-01-14 16:46:16 +000053 sk_free(fPath16);
54 if (fHandle)
55 ::FindClose(fHandle);
reed@android.com8a1c16f2008-12-17 15:59:43 +000056}
57
58void SkOSFile::Iter::reset(const char path[], const char suffix[])
59{
reed@android.com6f252972009-01-14 16:46:16 +000060 if (fHandle)
61 {
62 ::FindClose(fHandle);
63 fHandle = 0;
64 }
bsalomon@google.comc8ad63e2011-03-18 14:29:44 +000065 if (NULL == path)
reed@android.com6f252972009-01-14 16:46:16 +000066 path = "";
reed@android.com8a1c16f2008-12-17 15:59:43 +000067
reed@android.com6f252972009-01-14 16:46:16 +000068 sk_free(fPath16);
69 fPath16 = concat_to_16(path, suffix);
reed@android.com8a1c16f2008-12-17 15:59:43 +000070}
71
reed@android.comb50a60c2009-01-14 17:51:08 +000072static bool is_magic_dir(const uint16_t dir[])
reed@android.com8a1c16f2008-12-17 15:59:43 +000073{
reed@android.com6f252972009-01-14 16:46:16 +000074 // return true for "." and ".."
75 return dir[0] == '.' && (dir[1] == 0 || dir[1] == '.' && dir[2] == 0);
reed@android.com8a1c16f2008-12-17 15:59:43 +000076}
77
78static bool get_the_file(HANDLE handle, SkString* name, WIN32_FIND_DATAW* dataPtr, bool getDir)
79{
reed@android.com6f252972009-01-14 16:46:16 +000080 WIN32_FIND_DATAW data;
reed@android.com8a1c16f2008-12-17 15:59:43 +000081
bsalomon@google.comc8ad63e2011-03-18 14:29:44 +000082 if (NULL == dataPtr)
reed@android.com6f252972009-01-14 16:46:16 +000083 {
84 if (::FindNextFileW(handle, &data))
85 dataPtr = &data;
86 else
87 return false;
88 }
reed@android.com8a1c16f2008-12-17 15:59:43 +000089
reed@android.com6f252972009-01-14 16:46:16 +000090 for (;;)
91 {
92 if (getDir)
93 {
bsalomon@google.comc8ad63e2011-03-18 14:29:44 +000094 if ((dataPtr->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) && !is_magic_dir((uint16_t*)dataPtr->cFileName))
reed@android.com6f252972009-01-14 16:46:16 +000095 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)
bsalomon@google.comc8ad63e2011-03-18 14:29:44 +0000107 name->setUTF16((uint16_t*)dataPtr->cFileName);
reed@android.com6f252972009-01-14 16:46:16 +0000108 return true;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000109}
110
111bool SkOSFile::Iter::next(SkString* name, bool getDir)
112{
reed@android.com6f252972009-01-14 16:46:16 +0000113 WIN32_FIND_DATAW data;
bsalomon@google.comc8ad63e2011-03-18 14:29:44 +0000114 WIN32_FIND_DATAW* dataPtr = NULL;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000115
reed@android.com6f252972009-01-14 16:46:16 +0000116 if (fHandle == 0) // our first time
117 {
bsalomon@google.comc8ad63e2011-03-18 14:29:44 +0000118 if (fPath16 == NULL || *fPath16 == 0) // check for no path
reed@android.com6f252972009-01-14 16:46:16 +0000119 return false;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000120
bsalomon@google.comc8ad63e2011-03-18 14:29:44 +0000121 fHandle = ::FindFirstFileW((LPCWSTR)fPath16, &data);
reed@android.com6f252972009-01-14 16:46:16 +0000122 if (fHandle != 0 && fHandle != (HANDLE)~0)
123 dataPtr = &data;
124 }
125 return fHandle != (HANDLE)~0 && get_the_file(fHandle, name, dataPtr, getDir);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000126}
127
128#elif defined(SK_BUILD_FOR_MAC) || defined(SK_BUILD_FOR_UNIX)
129
130#if 0
131OSStatus FSPathMakeRef (
132 const UInt8 * path,
133 FSRef * ref,
134 Boolean * isDirectory
135);
136#endif
137
138SkOSFile::Iter::Iter() : fDIR(0)
139{
140}
141
142SkOSFile::Iter::Iter(const char path[], const char suffix[]) : fDIR(0)
143{
reed@android.com6f252972009-01-14 16:46:16 +0000144 this->reset(path, suffix);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000145}
146
147SkOSFile::Iter::~Iter()
148{
reed@android.com6f252972009-01-14 16:46:16 +0000149 if (fDIR)
150 ::closedir(fDIR);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000151}
152
153void SkOSFile::Iter::reset(const char path[], const char suffix[])
154{
reed@android.com6f252972009-01-14 16:46:16 +0000155 if (fDIR)
156 {
157 ::closedir(fDIR);
158 fDIR = 0;
159 }
reed@android.com8a1c16f2008-12-17 15:59:43 +0000160
reed@android.com6f252972009-01-14 16:46:16 +0000161 fPath.set(path);
162 if (path)
163 {
164 fDIR = ::opendir(path);
165 fSuffix.set(suffix);
166 }
167 else
168 fSuffix.reset();
reed@android.com8a1c16f2008-12-17 15:59:43 +0000169}
170
171// returns true if suffix is empty, or if str ends with suffix
172static bool issuffixfor(const SkString& suffix, const char str[])
173{
reed@android.com6f252972009-01-14 16:46:16 +0000174 size_t suffixLen = suffix.size();
175 size_t strLen = strlen(str);
agl@chromium.org0afaf9b2010-07-28 17:10:28 +0000176
reed@android.com6f252972009-01-14 16:46:16 +0000177 return strLen >= suffixLen &&
reed@android.com6f252972009-01-14 16:46:16 +0000178 memcmp(suffix.c_str(), str + strLen - suffixLen, suffixLen) == 0;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000179}
180
181#include <sys/stat.h>
182
183bool SkOSFile::Iter::next(SkString* name, bool getDir)
184{
reed@android.com6f252972009-01-14 16:46:16 +0000185 if (fDIR)
186 {
187 dirent* entry;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000188
reed@android.com6f252972009-01-14 16:46:16 +0000189 while ((entry = ::readdir(fDIR)) != NULL)
190 {
191 struct stat s;
192 SkString str(fPath);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000193
reed@android.com6f252972009-01-14 16:46:16 +0000194 if (!str.endsWith("/") && !str.endsWith("\\"))
195 str.append("/");
196 str.append(entry->d_name);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000197
reed@android.com6f252972009-01-14 16:46:16 +0000198 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;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000220}
221
222#endif
223