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) || defined(SK_BUILD_FOR_IOS) 136 137 #if 0 138 OSStatus FSPathMakeRef ( 139 const UInt8 * path, 140 FSRef * ref, 141 Boolean * isDirectory 142 ); 143 #endif 144 145 SkOSFile::Iter::Iter() : fDIR(0) 146 { 147 } 148 149 SkOSFile::Iter::Iter(const char path[], const char suffix[]) : fDIR(0) 150 { 151 this->reset(path, suffix); 152 } 153 154 SkOSFile::Iter::~Iter() 155 { 156 if (fDIR) 157 ::closedir(fDIR); 158 } 159 160 void SkOSFile::Iter::reset(const char path[], const char suffix[]) 161 { 162 if (fDIR) 163 { 164 ::closedir(fDIR); 165 fDIR = 0; 166 } 167 168 fPath.set(path); 169 if (path) 170 { 171 fDIR = ::opendir(path); 172 fSuffix.set(suffix); 173 } 174 else 175 fSuffix.reset(); 176 } 177 178 // returns true if suffix is empty, or if str ends with suffix 179 static bool issuffixfor(const SkString& suffix, const char str[]) 180 { 181 size_t suffixLen = suffix.size(); 182 size_t strLen = strlen(str); 183 184 return strLen >= suffixLen && 185 memcmp(suffix.c_str(), str + strLen - suffixLen, suffixLen) == 0; 186 } 187 188 #include <sys/stat.h> 189 190 bool SkOSFile::Iter::next(SkString* name, bool getDir) 191 { 192 if (fDIR) 193 { 194 dirent* entry; 195 196 while ((entry = ::readdir(fDIR)) != NULL) 197 { 198 struct stat s; 199 SkString str(fPath); 200 201 if (!str.endsWith("/") && !str.endsWith("\\")) 202 str.append("/"); 203 str.append(entry->d_name); 204 205 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; 227 } 228 229 #endif 230