blob: 982bc0842f2af6592edc5fe71244a6ea4e5450dc [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));
reed@android.com6f252972009-01-14 16:46:16 +000034 for (size_t i = 0; i < len; i++)
35 fStr[i] = src[i];
36 fStr[i] = 0;
reed@android.com8a1c16f2008-12-17 15:59:43 +000037}
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{
reed@android.com6f252972009-01-14 16:46:16 +000047 this->reset(path, suffix);
reed@android.com8a1c16f2008-12-17 15:59:43 +000048}
49
50SkOSFile::Iter::~Iter()
51{
reed@android.com6f252972009-01-14 16:46:16 +000052 sk_free(fPath16);
53 if (fHandle)
54 ::FindClose(fHandle);
reed@android.com8a1c16f2008-12-17 15:59:43 +000055}
56
57void SkOSFile::Iter::reset(const char path[], const char suffix[])
58{
reed@android.com6f252972009-01-14 16:46:16 +000059 if (fHandle)
60 {
61 ::FindClose(fHandle);
62 fHandle = 0;
63 }
64 if (path == nil)
65 path = "";
reed@android.com8a1c16f2008-12-17 15:59:43 +000066
reed@android.com6f252972009-01-14 16:46:16 +000067 sk_free(fPath16);
68 fPath16 = concat_to_16(path, suffix);
reed@android.com8a1c16f2008-12-17 15:59:43 +000069}
70
reed@android.comb50a60c2009-01-14 17:51:08 +000071static bool is_magic_dir(const uint16_t dir[])
reed@android.com8a1c16f2008-12-17 15:59:43 +000072{
reed@android.com6f252972009-01-14 16:46:16 +000073 // return true for "." and ".."
74 return dir[0] == '.' && (dir[1] == 0 || dir[1] == '.' && dir[2] == 0);
reed@android.com8a1c16f2008-12-17 15:59:43 +000075}
76
77static bool get_the_file(HANDLE handle, SkString* name, WIN32_FIND_DATAW* dataPtr, bool getDir)
78{
reed@android.com6f252972009-01-14 16:46:16 +000079 WIN32_FIND_DATAW data;
reed@android.com8a1c16f2008-12-17 15:59:43 +000080
reed@android.com6f252972009-01-14 16:46:16 +000081 if (dataPtr == nil)
82 {
83 if (::FindNextFileW(handle, &data))
84 dataPtr = &data;
85 else
86 return false;
87 }
reed@android.com8a1c16f2008-12-17 15:59:43 +000088
reed@android.com6f252972009-01-14 16:46:16 +000089 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;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000108}
109
110bool SkOSFile::Iter::next(SkString* name, bool getDir)
111{
reed@android.com6f252972009-01-14 16:46:16 +0000112 WIN32_FIND_DATAW data;
113 WIN32_FIND_DATAW* dataPtr = nil;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000114
reed@android.com6f252972009-01-14 16:46:16 +0000115 if (fHandle == 0) // our first time
116 {
117 if (fPath16 == nil || *fPath16 == 0) // check for no path
118 return false;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000119
reed@android.com6f252972009-01-14 16:46:16 +0000120 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);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000125}
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{
reed@android.com6f252972009-01-14 16:46:16 +0000143 this->reset(path, suffix);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000144}
145
146SkOSFile::Iter::~Iter()
147{
reed@android.com6f252972009-01-14 16:46:16 +0000148 if (fDIR)
149 ::closedir(fDIR);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000150}
151
152void SkOSFile::Iter::reset(const char path[], const char suffix[])
153{
reed@android.com6f252972009-01-14 16:46:16 +0000154 if (fDIR)
155 {
156 ::closedir(fDIR);
157 fDIR = 0;
158 }
reed@android.com8a1c16f2008-12-17 15:59:43 +0000159
reed@android.com6f252972009-01-14 16:46:16 +0000160 fPath.set(path);
161 if (path)
162 {
163 fDIR = ::opendir(path);
164 fSuffix.set(suffix);
165 }
166 else
167 fSuffix.reset();
reed@android.com8a1c16f2008-12-17 15:59:43 +0000168}
169
170// returns true if suffix is empty, or if str ends with suffix
171static bool issuffixfor(const SkString& suffix, const char str[])
172{
reed@android.com6f252972009-01-14 16:46:16 +0000173 size_t suffixLen = suffix.size();
174 size_t strLen = strlen(str);
agl@chromium.org0afaf9b2010-07-28 17:10:28 +0000175
reed@android.com6f252972009-01-14 16:46:16 +0000176 return strLen >= suffixLen &&
reed@android.com6f252972009-01-14 16:46:16 +0000177 memcmp(suffix.c_str(), str + strLen - suffixLen, suffixLen) == 0;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000178}
179
180#include <sys/stat.h>
181
182bool SkOSFile::Iter::next(SkString* name, bool getDir)
183{
reed@android.com6f252972009-01-14 16:46:16 +0000184 if (fDIR)
185 {
186 dirent* entry;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000187
reed@android.com6f252972009-01-14 16:46:16 +0000188 while ((entry = ::readdir(fDIR)) != NULL)
189 {
190 struct stat s;
191 SkString str(fPath);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000192
reed@android.com6f252972009-01-14 16:46:16 +0000193 if (!str.endsWith("/") && !str.endsWith("\\"))
194 str.append("/");
195 str.append(entry->d_name);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000196
reed@android.com6f252972009-01-14 16:46:16 +0000197 if (0 == stat(str.c_str(), &s))
198 {
199 if (getDir)
200 {
201 if (s.st_mode & S_IFDIR)
202 break;
203 }
204 else
205 {
206 if (!(s.st_mode & S_IFDIR) && issuffixfor(fSuffix, entry->d_name))
207 break;
208 }
209 }
210 }
211 if (entry) // we broke out with a file
212 {
213 if (name)
214 name->set(entry->d_name);
215 return true;
216 }
217 }
218 return false;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000219}
220
221#endif
222