blob: 7c2b02439a3dd290a950e23d0c3b69343290053b [file] [log] [blame]
epoger@google.comec3ed6a2011-07-28 14:26:00 +00001
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 */
reed@android.com8a1c16f2008-12-17 15:59:43 +00008#include "SkOSFile.h"
9
10#ifdef SK_BUILD_FOR_WIN
11
reed@android.comb50a60c2009-01-14 17:51:08 +000012static uint16_t* concat_to_16(const char src[], const char suffix[])
reed@android.com8a1c16f2008-12-17 15:59:43 +000013{
reed@android.com6f252972009-01-14 16:46:16 +000014 size_t i, len = strlen(src);
15 size_t len2 = 3 + (suffix ? strlen(suffix) : 0);
reed@android.comb50a60c2009-01-14 17:51:08 +000016 uint16_t* dst = (uint16_t*)sk_malloc_throw((len + len2) * sizeof(uint16_t));
reed@android.com8a1c16f2008-12-17 15:59:43 +000017
reed@android.com6f252972009-01-14 16:46:16 +000018 for (i = 0; i < len; i++)
19 dst[i] = src[i];
reed@android.com8a1c16f2008-12-17 15:59:43 +000020
reed@android.com6f252972009-01-14 16:46:16 +000021 if (i > 0 && dst[i-1] != '/')
22 dst[i++] = '/';
23 dst[i++] = '*';
reed@android.com8a1c16f2008-12-17 15:59:43 +000024
reed@android.com6f252972009-01-14 16:46:16 +000025 if (suffix)
26 {
27 while (*suffix)
28 dst[i++] = *suffix++;
29 }
30 dst[i] = 0;
31 SkASSERT(i + 1 <= len + len2);
reed@android.com8a1c16f2008-12-17 15:59:43 +000032
reed@android.com6f252972009-01-14 16:46:16 +000033 return dst;
reed@android.com8a1c16f2008-12-17 15:59:43 +000034}
35
36SkUTF16_Str::SkUTF16_Str(const char src[])
37{
reed@android.com6f252972009-01-14 16:46:16 +000038 size_t len = strlen(src);
reed@android.com8a1c16f2008-12-17 15:59:43 +000039
reed@android.comb50a60c2009-01-14 17:51:08 +000040 fStr = (uint16_t*)sk_malloc_throw((len + 1) * sizeof(uint16_t));
bsalomon@google.comc8ad63e2011-03-18 14:29:44 +000041 size_t i;
42 for (i = 0; i < len; i++)
reed@android.com6f252972009-01-14 16:46:16 +000043 fStr[i] = src[i];
44 fStr[i] = 0;
reed@android.com8a1c16f2008-12-17 15:59:43 +000045}
46
47////////////////////////////////////////////////////////////////////////////
48
bsalomon@google.comc8ad63e2011-03-18 14:29:44 +000049SkOSFile::Iter::Iter() : fHandle(0), fPath16(NULL)
reed@android.com8a1c16f2008-12-17 15:59:43 +000050{
51}
52
bsalomon@google.comc8ad63e2011-03-18 14:29:44 +000053SkOSFile::Iter::Iter(const char path[], const char suffix[]) : fHandle(0), fPath16(NULL)
reed@android.com8a1c16f2008-12-17 15:59:43 +000054{
reed@android.com6f252972009-01-14 16:46:16 +000055 this->reset(path, suffix);
reed@android.com8a1c16f2008-12-17 15:59:43 +000056}
57
58SkOSFile::Iter::~Iter()
59{
reed@android.com6f252972009-01-14 16:46:16 +000060 sk_free(fPath16);
61 if (fHandle)
62 ::FindClose(fHandle);
reed@android.com8a1c16f2008-12-17 15:59:43 +000063}
64
65void SkOSFile::Iter::reset(const char path[], const char suffix[])
66{
reed@android.com6f252972009-01-14 16:46:16 +000067 if (fHandle)
68 {
69 ::FindClose(fHandle);
70 fHandle = 0;
71 }
bsalomon@google.comc8ad63e2011-03-18 14:29:44 +000072 if (NULL == path)
reed@android.com6f252972009-01-14 16:46:16 +000073 path = "";
reed@android.com8a1c16f2008-12-17 15:59:43 +000074
reed@android.com6f252972009-01-14 16:46:16 +000075 sk_free(fPath16);
76 fPath16 = concat_to_16(path, suffix);
reed@android.com8a1c16f2008-12-17 15:59:43 +000077}
78
reed@android.comb50a60c2009-01-14 17:51:08 +000079static bool is_magic_dir(const uint16_t dir[])
reed@android.com8a1c16f2008-12-17 15:59:43 +000080{
reed@android.com6f252972009-01-14 16:46:16 +000081 // return true for "." and ".."
82 return dir[0] == '.' && (dir[1] == 0 || dir[1] == '.' && dir[2] == 0);
reed@android.com8a1c16f2008-12-17 15:59:43 +000083}
84
85static bool get_the_file(HANDLE handle, SkString* name, WIN32_FIND_DATAW* dataPtr, bool getDir)
86{
reed@android.com6f252972009-01-14 16:46:16 +000087 WIN32_FIND_DATAW data;
reed@android.com8a1c16f2008-12-17 15:59:43 +000088
bsalomon@google.comc8ad63e2011-03-18 14:29:44 +000089 if (NULL == dataPtr)
reed@android.com6f252972009-01-14 16:46:16 +000090 {
91 if (::FindNextFileW(handle, &data))
92 dataPtr = &data;
93 else
94 return false;
95 }
reed@android.com8a1c16f2008-12-17 15:59:43 +000096
reed@android.com6f252972009-01-14 16:46:16 +000097 for (;;)
98 {
99 if (getDir)
100 {
bsalomon@google.comc8ad63e2011-03-18 14:29:44 +0000101 if ((dataPtr->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) && !is_magic_dir((uint16_t*)dataPtr->cFileName))
reed@android.com6f252972009-01-14 16:46:16 +0000102 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)
bsalomon@google.comc8ad63e2011-03-18 14:29:44 +0000114 name->setUTF16((uint16_t*)dataPtr->cFileName);
reed@android.com6f252972009-01-14 16:46:16 +0000115 return true;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000116}
117
118bool SkOSFile::Iter::next(SkString* name, bool getDir)
119{
reed@android.com6f252972009-01-14 16:46:16 +0000120 WIN32_FIND_DATAW data;
bsalomon@google.comc8ad63e2011-03-18 14:29:44 +0000121 WIN32_FIND_DATAW* dataPtr = NULL;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000122
reed@android.com6f252972009-01-14 16:46:16 +0000123 if (fHandle == 0) // our first time
124 {
bsalomon@google.comc8ad63e2011-03-18 14:29:44 +0000125 if (fPath16 == NULL || *fPath16 == 0) // check for no path
reed@android.com6f252972009-01-14 16:46:16 +0000126 return false;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000127
bsalomon@google.comc8ad63e2011-03-18 14:29:44 +0000128 fHandle = ::FindFirstFileW((LPCWSTR)fPath16, &data);
reed@android.com6f252972009-01-14 16:46:16 +0000129 if (fHandle != 0 && fHandle != (HANDLE)~0)
130 dataPtr = &data;
131 }
132 return fHandle != (HANDLE)~0 && get_the_file(fHandle, name, dataPtr, getDir);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000133}
134
djsollen@google.com58629292011-11-03 13:08:29 +0000135#elif defined(SK_BUILD_FOR_MAC) || defined(SK_BUILD_FOR_UNIX) || defined(SK_BUILD_FOR_ANDROID)
reed@android.com8a1c16f2008-12-17 15:59:43 +0000136
137#if 0
138OSStatus FSPathMakeRef (
139 const UInt8 * path,
140 FSRef * ref,
141 Boolean * isDirectory
142);
143#endif
144
145SkOSFile::Iter::Iter() : fDIR(0)
146{
147}
148
149SkOSFile::Iter::Iter(const char path[], const char suffix[]) : fDIR(0)
150{
reed@android.com6f252972009-01-14 16:46:16 +0000151 this->reset(path, suffix);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000152}
153
154SkOSFile::Iter::~Iter()
155{
reed@android.com6f252972009-01-14 16:46:16 +0000156 if (fDIR)
157 ::closedir(fDIR);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000158}
159
160void SkOSFile::Iter::reset(const char path[], const char suffix[])
161{
reed@android.com6f252972009-01-14 16:46:16 +0000162 if (fDIR)
163 {
164 ::closedir(fDIR);
165 fDIR = 0;
166 }
reed@android.com8a1c16f2008-12-17 15:59:43 +0000167
reed@android.com6f252972009-01-14 16:46:16 +0000168 fPath.set(path);
169 if (path)
170 {
171 fDIR = ::opendir(path);
172 fSuffix.set(suffix);
173 }
174 else
175 fSuffix.reset();
reed@android.com8a1c16f2008-12-17 15:59:43 +0000176}
177
178// returns true if suffix is empty, or if str ends with suffix
179static bool issuffixfor(const SkString& suffix, const char str[])
180{
reed@android.com6f252972009-01-14 16:46:16 +0000181 size_t suffixLen = suffix.size();
182 size_t strLen = strlen(str);
agl@chromium.org0afaf9b2010-07-28 17:10:28 +0000183
reed@android.com6f252972009-01-14 16:46:16 +0000184 return strLen >= suffixLen &&
reed@android.com6f252972009-01-14 16:46:16 +0000185 memcmp(suffix.c_str(), str + strLen - suffixLen, suffixLen) == 0;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000186}
187
188#include <sys/stat.h>
189
190bool SkOSFile::Iter::next(SkString* name, bool getDir)
191{
reed@android.com6f252972009-01-14 16:46:16 +0000192 if (fDIR)
193 {
194 dirent* entry;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000195
reed@android.com6f252972009-01-14 16:46:16 +0000196 while ((entry = ::readdir(fDIR)) != NULL)
197 {
198 struct stat s;
199 SkString str(fPath);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000200
reed@android.com6f252972009-01-14 16:46:16 +0000201 if (!str.endsWith("/") && !str.endsWith("\\"))
202 str.append("/");
203 str.append(entry->d_name);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000204
reed@android.com6f252972009-01-14 16:46:16 +0000205 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;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000227}
228
229#endif
230