Home | History | Annotate | Download | only in utils
      1 /*
      2  * Copyright 2011 Google Inc.
      3  *
      4  * Use of this source code is governed by a BSD-style license that can be
      5  * found in the LICENSE file.
      6  */
      7 #include "SkOSFile.h"
      8 
      9 SkString SkOSPath::SkPathJoin(const char *rootPath, const char *relativePath) {
     10     SkString result(rootPath);
     11     if (!result.endsWith(SkPATH_SEPARATOR)) {
     12         result.appendUnichar(SkPATH_SEPARATOR);
     13     }
     14     result.append(relativePath);
     15     return result;
     16 }
     17 
     18 SkString SkOSPath::SkBasename(const char* fullPath) {
     19     if (!fullPath) {
     20         return SkString();
     21     }
     22     const char* filename = strrchr(fullPath, SkPATH_SEPARATOR);
     23     if (NULL == filename) {
     24         filename = fullPath;
     25     } else {
     26         ++filename;
     27     }
     28     return SkString(filename);
     29 }
     30 
     31 #ifdef SK_BUILD_FOR_WIN
     32 
     33 static uint16_t* concat_to_16(const char src[], const char suffix[])
     34 {
     35     size_t  i, len = strlen(src);
     36     size_t  len2 = 3 + (suffix ? strlen(suffix) : 0);
     37     uint16_t* dst = (uint16_t*)sk_malloc_throw((len + len2) * sizeof(uint16_t));
     38 
     39     for (i = 0; i < len; i++)
     40         dst[i] = src[i];
     41 
     42     if (i > 0 && dst[i-1] != '/')
     43         dst[i++] = '/';
     44     dst[i++] = '*';
     45 
     46     if (suffix)
     47     {
     48         while (*suffix)
     49             dst[i++] = *suffix++;
     50     }
     51     dst[i] = 0;
     52     SkASSERT(i + 1 <= len + len2);
     53 
     54     return dst;
     55 }
     56 
     57 SkUTF16_Str::SkUTF16_Str(const char src[])
     58 {
     59     size_t  len = strlen(src);
     60 
     61     fStr = (uint16_t*)sk_malloc_throw((len + 1) * sizeof(uint16_t));
     62     size_t i;
     63     for (i = 0; i < len; i++)
     64         fStr[i] = src[i];
     65     fStr[i] = 0;
     66 }
     67 
     68 ////////////////////////////////////////////////////////////////////////////
     69 
     70 SkOSFile::Iter::Iter() : fHandle(0), fPath16(NULL)
     71 {
     72 }
     73 
     74 SkOSFile::Iter::Iter(const char path[], const char suffix[]) : fHandle(0), fPath16(NULL)
     75 {
     76     this->reset(path, suffix);
     77 }
     78 
     79 SkOSFile::Iter::~Iter()
     80 {
     81     sk_free(fPath16);
     82     if (fHandle)
     83         ::FindClose(fHandle);
     84 }
     85 
     86 void SkOSFile::Iter::reset(const char path[], const char suffix[])
     87 {
     88     if (fHandle)
     89     {
     90         ::FindClose(fHandle);
     91         fHandle = 0;
     92     }
     93     if (NULL == path)
     94         path = "";
     95 
     96     sk_free(fPath16);
     97     fPath16 = concat_to_16(path, suffix);
     98 }
     99 
    100 static bool is_magic_dir(const uint16_t dir[])
    101 {
    102     // return true for "." and ".."
    103     return dir[0] == '.' && (dir[1] == 0 || dir[1] == '.' && dir[2] == 0);
    104 }
    105 
    106 static bool get_the_file(HANDLE handle, SkString* name, WIN32_FIND_DATAW* dataPtr, bool getDir)
    107 {
    108     WIN32_FIND_DATAW    data;
    109 
    110     if (NULL == dataPtr)
    111     {
    112         if (::FindNextFileW(handle, &data))
    113             dataPtr = &data;
    114         else
    115             return false;
    116     }
    117 
    118     for (;;)
    119     {
    120         if (getDir)
    121         {
    122             if ((dataPtr->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) && !is_magic_dir((uint16_t*)dataPtr->cFileName))
    123                 break;
    124         }
    125         else
    126         {
    127             if (!(dataPtr->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY))
    128                 break;
    129         }
    130         if (!::FindNextFileW(handle, dataPtr))
    131             return false;
    132     }
    133     // if we get here, we've found a file/dir
    134     if (name)
    135         name->setUTF16((uint16_t*)dataPtr->cFileName);
    136     return true;
    137 }
    138 
    139 bool SkOSFile::Iter::next(SkString* name, bool getDir)
    140 {
    141     WIN32_FIND_DATAW    data;
    142     WIN32_FIND_DATAW*   dataPtr = NULL;
    143 
    144     if (fHandle == 0)   // our first time
    145     {
    146         if (fPath16 == NULL || *fPath16 == 0)    // check for no path
    147             return false;
    148 
    149         fHandle = ::FindFirstFileW((LPCWSTR)fPath16, &data);
    150         if (fHandle != 0 && fHandle != (HANDLE)~0)
    151             dataPtr = &data;
    152     }
    153     return fHandle != (HANDLE)~0 && get_the_file(fHandle, name, dataPtr, getDir);
    154 }
    155 
    156 #elif defined(SK_BUILD_FOR_MAC) || defined(SK_BUILD_FOR_UNIX) || defined(SK_BUILD_FOR_ANDROID) || defined(SK_BUILD_FOR_IOS)
    157 
    158 #if 0
    159 OSStatus FSPathMakeRef (
    160    const UInt8 * path,
    161    FSRef * ref,
    162    Boolean * isDirectory
    163 );
    164 #endif
    165 
    166 SkOSFile::Iter::Iter() : fDIR(0)
    167 {
    168 }
    169 
    170 SkOSFile::Iter::Iter(const char path[], const char suffix[]) : fDIR(0)
    171 {
    172     this->reset(path, suffix);
    173 }
    174 
    175 SkOSFile::Iter::~Iter()
    176 {
    177     if (fDIR)
    178         ::closedir(fDIR);
    179 }
    180 
    181 void SkOSFile::Iter::reset(const char path[], const char suffix[])
    182 {
    183     if (fDIR)
    184     {
    185         ::closedir(fDIR);
    186         fDIR = 0;
    187     }
    188 
    189     fPath.set(path);
    190     if (path)
    191     {
    192         fDIR = ::opendir(path);
    193         fSuffix.set(suffix);
    194     }
    195     else
    196         fSuffix.reset();
    197 }
    198 
    199 // returns true if suffix is empty, or if str ends with suffix
    200 static bool issuffixfor(const SkString& suffix, const char str[])
    201 {
    202     size_t  suffixLen = suffix.size();
    203     size_t  strLen = strlen(str);
    204 
    205     return  strLen >= suffixLen &&
    206             memcmp(suffix.c_str(), str + strLen - suffixLen, suffixLen) == 0;
    207 }
    208 
    209 #include <sys/stat.h>
    210 
    211 bool SkOSFile::Iter::next(SkString* name, bool getDir)
    212 {
    213     if (fDIR)
    214     {
    215         dirent* entry;
    216 
    217         while ((entry = ::readdir(fDIR)) != NULL)
    218         {
    219             struct stat s;
    220             SkString    str(fPath);
    221 
    222             if (!str.endsWith("/") && !str.endsWith("\\"))
    223                 str.append("/");
    224             str.append(entry->d_name);
    225 
    226             if (0 == stat(str.c_str(), &s))
    227             {
    228                 if (getDir)
    229                 {
    230                     if (s.st_mode & S_IFDIR)
    231                         break;
    232                 }
    233                 else
    234                 {
    235                     if (!(s.st_mode & S_IFDIR) && issuffixfor(fSuffix, entry->d_name))
    236                         break;
    237                 }
    238             }
    239         }
    240         if (entry)  // we broke out with a file
    241         {
    242             if (name)
    243                 name->set(entry->d_name);
    244             return true;
    245         }
    246     }
    247     return false;
    248 }
    249 #endif // if one of:SK_BUILD_FOR_MAC, SK_BUILD_FOR_UNIX, SK_BUILD_FOR_ANDROID,SK_BUILD_FOR_IOS
    250