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