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