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 :
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 :
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 :
49 : SkOSFile::Iter::Iter() : fHandle(0), fPath16(NULL)
50 : {
51 : }
52 :
53 : SkOSFile::Iter::Iter(const char path[], const char suffix[]) : fHandle(0), fPath16(NULL)
54 : {
55 : this->reset(path, suffix);
56 : }
57 :
58 : SkOSFile::Iter::~Iter()
59 : {
60 : sk_free(fPath16);
61 : if (fHandle)
62 : ::FindClose(fHandle);
63 : }
64 :
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 :
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 :
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 :
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 :
145 0 : SkOSFile::Iter::Iter() : fDIR(0)
146 : {
147 0 : }
148 :
149 0 : SkOSFile::Iter::Iter(const char path[], const char suffix[]) : fDIR(0)
150 : {
151 0 : this->reset(path, suffix);
152 0 : }
153 :
154 0 : SkOSFile::Iter::~Iter()
155 : {
156 0 : if (fDIR)
157 0 : ::closedir(fDIR);
158 0 : }
159 :
160 0 : void SkOSFile::Iter::reset(const char path[], const char suffix[])
161 : {
162 0 : if (fDIR)
163 : {
164 0 : ::closedir(fDIR);
165 0 : fDIR = 0;
166 : }
167 :
168 0 : fPath.set(path);
169 0 : if (path)
170 : {
171 0 : fDIR = ::opendir(path);
172 0 : fSuffix.set(suffix);
173 : }
174 : else
175 0 : fSuffix.reset();
176 0 : }
177 :
178 : // returns true if suffix is empty, or if str ends with suffix
179 0 : static bool issuffixfor(const SkString& suffix, const char str[])
180 : {
181 0 : size_t suffixLen = suffix.size();
182 0 : size_t strLen = strlen(str);
183 :
184 : return strLen >= suffixLen &&
185 0 : memcmp(suffix.c_str(), str + strLen - suffixLen, suffixLen) == 0;
186 : }
187 :
188 : #include <sys/stat.h>
189 :
190 0 : bool SkOSFile::Iter::next(SkString* name, bool getDir)
191 : {
192 0 : if (fDIR)
193 : {
194 : dirent* entry;
195 :
196 0 : while ((entry = ::readdir(fDIR)) != NULL)
197 : {
198 : struct stat s;
199 0 : SkString str(fPath);
200 :
201 0 : if (!str.endsWith("/") && !str.endsWith("\\"))
202 0 : str.append("/");
203 0 : str.append(entry->d_name);
204 :
205 0 : if (0 == stat(str.c_str(), &s))
206 : {
207 0 : if (getDir)
208 : {
209 0 : if (s.st_mode & S_IFDIR)
210 : break;
211 : }
212 : else
213 : {
214 0 : if (!(s.st_mode & S_IFDIR) && issuffixfor(fSuffix, entry->d_name))
215 : break;
216 : }
217 : }
218 : }
219 0 : if (entry) // we broke out with a file
220 : {
221 0 : if (name)
222 0 : name->set(entry->d_name);
223 0 : return true;
224 : }
225 : }
226 0 : return false;
227 : }
228 :
229 : #endif
230 :
|