michael@0: /* michael@0: * Copyright 2011 Google Inc. michael@0: * michael@0: * Use of this source code is governed by a BSD-style license that can be michael@0: * found in the LICENSE file. michael@0: */ michael@0: #include "SkOSFile.h" michael@0: michael@0: SkString SkOSPath::SkPathJoin(const char *rootPath, const char *relativePath) { michael@0: SkString result(rootPath); michael@0: if (!result.endsWith(SkPATH_SEPARATOR)) { michael@0: result.appendUnichar(SkPATH_SEPARATOR); michael@0: } michael@0: result.append(relativePath); michael@0: return result; michael@0: } michael@0: michael@0: SkString SkOSPath::SkBasename(const char* fullPath) { michael@0: if (!fullPath) { michael@0: return SkString(); michael@0: } michael@0: const char* filename = strrchr(fullPath, SkPATH_SEPARATOR); michael@0: if (NULL == filename) { michael@0: filename = fullPath; michael@0: } else { michael@0: ++filename; michael@0: } michael@0: return SkString(filename); michael@0: } michael@0: michael@0: #ifdef SK_BUILD_FOR_WIN michael@0: michael@0: static uint16_t* concat_to_16(const char src[], const char suffix[]) michael@0: { michael@0: size_t i, len = strlen(src); michael@0: size_t len2 = 3 + (suffix ? strlen(suffix) : 0); michael@0: uint16_t* dst = (uint16_t*)sk_malloc_throw((len + len2) * sizeof(uint16_t)); michael@0: michael@0: for (i = 0; i < len; i++) michael@0: dst[i] = src[i]; michael@0: michael@0: if (i > 0 && dst[i-1] != '/') michael@0: dst[i++] = '/'; michael@0: dst[i++] = '*'; michael@0: michael@0: if (suffix) michael@0: { michael@0: while (*suffix) michael@0: dst[i++] = *suffix++; michael@0: } michael@0: dst[i] = 0; michael@0: SkASSERT(i + 1 <= len + len2); michael@0: michael@0: return dst; michael@0: } michael@0: michael@0: SkUTF16_Str::SkUTF16_Str(const char src[]) michael@0: { michael@0: size_t len = strlen(src); michael@0: michael@0: fStr = (uint16_t*)sk_malloc_throw((len + 1) * sizeof(uint16_t)); michael@0: size_t i; michael@0: for (i = 0; i < len; i++) michael@0: fStr[i] = src[i]; michael@0: fStr[i] = 0; michael@0: } michael@0: michael@0: //////////////////////////////////////////////////////////////////////////// michael@0: michael@0: SkOSFile::Iter::Iter() : fHandle(0), fPath16(NULL) michael@0: { michael@0: } michael@0: michael@0: SkOSFile::Iter::Iter(const char path[], const char suffix[]) : fHandle(0), fPath16(NULL) michael@0: { michael@0: this->reset(path, suffix); michael@0: } michael@0: michael@0: SkOSFile::Iter::~Iter() michael@0: { michael@0: sk_free(fPath16); michael@0: if (fHandle) michael@0: ::FindClose(fHandle); michael@0: } michael@0: michael@0: void SkOSFile::Iter::reset(const char path[], const char suffix[]) michael@0: { michael@0: if (fHandle) michael@0: { michael@0: ::FindClose(fHandle); michael@0: fHandle = 0; michael@0: } michael@0: if (NULL == path) michael@0: path = ""; michael@0: michael@0: sk_free(fPath16); michael@0: fPath16 = concat_to_16(path, suffix); michael@0: } michael@0: michael@0: static bool is_magic_dir(const uint16_t dir[]) michael@0: { michael@0: // return true for "." and ".." michael@0: return dir[0] == '.' && (dir[1] == 0 || dir[1] == '.' && dir[2] == 0); michael@0: } michael@0: michael@0: static bool get_the_file(HANDLE handle, SkString* name, WIN32_FIND_DATAW* dataPtr, bool getDir) michael@0: { michael@0: WIN32_FIND_DATAW data; michael@0: michael@0: if (NULL == dataPtr) michael@0: { michael@0: if (::FindNextFileW(handle, &data)) michael@0: dataPtr = &data; michael@0: else michael@0: return false; michael@0: } michael@0: michael@0: for (;;) michael@0: { michael@0: if (getDir) michael@0: { michael@0: if ((dataPtr->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) && !is_magic_dir((uint16_t*)dataPtr->cFileName)) michael@0: break; michael@0: } michael@0: else michael@0: { michael@0: if (!(dataPtr->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) michael@0: break; michael@0: } michael@0: if (!::FindNextFileW(handle, dataPtr)) michael@0: return false; michael@0: } michael@0: // if we get here, we've found a file/dir michael@0: if (name) michael@0: name->setUTF16((uint16_t*)dataPtr->cFileName); michael@0: return true; michael@0: } michael@0: michael@0: bool SkOSFile::Iter::next(SkString* name, bool getDir) michael@0: { michael@0: WIN32_FIND_DATAW data; michael@0: WIN32_FIND_DATAW* dataPtr = NULL; michael@0: michael@0: if (fHandle == 0) // our first time michael@0: { michael@0: if (fPath16 == NULL || *fPath16 == 0) // check for no path michael@0: return false; michael@0: michael@0: fHandle = ::FindFirstFileW((LPCWSTR)fPath16, &data); michael@0: if (fHandle != 0 && fHandle != (HANDLE)~0) michael@0: dataPtr = &data; michael@0: } michael@0: return fHandle != (HANDLE)~0 && get_the_file(fHandle, name, dataPtr, getDir); michael@0: } michael@0: michael@0: #elif defined(SK_BUILD_FOR_MAC) || defined(SK_BUILD_FOR_UNIX) || defined(SK_BUILD_FOR_ANDROID) || defined(SK_BUILD_FOR_IOS) michael@0: michael@0: #if 0 michael@0: OSStatus FSPathMakeRef ( michael@0: const UInt8 * path, michael@0: FSRef * ref, michael@0: Boolean * isDirectory michael@0: ); michael@0: #endif michael@0: michael@0: SkOSFile::Iter::Iter() : fDIR(0) michael@0: { michael@0: } michael@0: michael@0: SkOSFile::Iter::Iter(const char path[], const char suffix[]) : fDIR(0) michael@0: { michael@0: this->reset(path, suffix); michael@0: } michael@0: michael@0: SkOSFile::Iter::~Iter() michael@0: { michael@0: if (fDIR) michael@0: ::closedir(fDIR); michael@0: } michael@0: michael@0: void SkOSFile::Iter::reset(const char path[], const char suffix[]) michael@0: { michael@0: if (fDIR) michael@0: { michael@0: ::closedir(fDIR); michael@0: fDIR = 0; michael@0: } michael@0: michael@0: fPath.set(path); michael@0: if (path) michael@0: { michael@0: fDIR = ::opendir(path); michael@0: fSuffix.set(suffix); michael@0: } michael@0: else michael@0: fSuffix.reset(); michael@0: } michael@0: michael@0: // returns true if suffix is empty, or if str ends with suffix michael@0: static bool issuffixfor(const SkString& suffix, const char str[]) michael@0: { michael@0: size_t suffixLen = suffix.size(); michael@0: size_t strLen = strlen(str); michael@0: michael@0: return strLen >= suffixLen && michael@0: memcmp(suffix.c_str(), str + strLen - suffixLen, suffixLen) == 0; michael@0: } michael@0: michael@0: #include michael@0: michael@0: bool SkOSFile::Iter::next(SkString* name, bool getDir) michael@0: { michael@0: if (fDIR) michael@0: { michael@0: dirent* entry; michael@0: michael@0: while ((entry = ::readdir(fDIR)) != NULL) michael@0: { michael@0: struct stat s; michael@0: SkString str(fPath); michael@0: michael@0: if (!str.endsWith("/") && !str.endsWith("\\")) michael@0: str.append("/"); michael@0: str.append(entry->d_name); michael@0: michael@0: if (0 == stat(str.c_str(), &s)) michael@0: { michael@0: if (getDir) michael@0: { michael@0: if (s.st_mode & S_IFDIR) michael@0: break; michael@0: } michael@0: else michael@0: { michael@0: if (!(s.st_mode & S_IFDIR) && issuffixfor(fSuffix, entry->d_name)) michael@0: break; michael@0: } michael@0: } michael@0: } michael@0: if (entry) // we broke out with a file michael@0: { michael@0: if (name) michael@0: name->set(entry->d_name); michael@0: return true; michael@0: } michael@0: } michael@0: return false; michael@0: } michael@0: #endif // if one of:SK_BUILD_FOR_MAC, SK_BUILD_FOR_UNIX, SK_BUILD_FOR_ANDROID,SK_BUILD_FOR_IOS