Home | History | Annotate | Download | only in utils
      1 #include "SkOSFile.h"
      2 
      3 #ifdef SK_BUILD_FOR_WIN
      4 
      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 
     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     for (size_t i = 0; i < len; i++)
     35         fStr[i] = src[i];
     36     fStr[i] = 0;
     37 }
     38 
     39 ////////////////////////////////////////////////////////////////////////////
     40 
     41 SkOSFile::Iter::Iter() : fHandle(0), fPath16(nil)
     42 {
     43 }
     44 
     45 SkOSFile::Iter::Iter(const char path[], const char suffix[]) : fHandle(0), fPath16(nil)
     46 {
     47     this->reset(path, suffix);
     48 }
     49 
     50 SkOSFile::Iter::~Iter()
     51 {
     52     sk_free(fPath16);
     53     if (fHandle)
     54         ::FindClose(fHandle);
     55 }
     56 
     57 void SkOSFile::Iter::reset(const char path[], const char suffix[])
     58 {
     59     if (fHandle)
     60     {
     61         ::FindClose(fHandle);
     62         fHandle = 0;
     63     }
     64     if (path == nil)
     65         path = "";
     66 
     67     sk_free(fPath16);
     68     fPath16 = concat_to_16(path, suffix);
     69 }
     70 
     71 static bool is_magic_dir(const uint16_t dir[])
     72 {
     73     // return true for "." and ".."
     74     return dir[0] == '.' && (dir[1] == 0 || dir[1] == '.' && dir[2] == 0);
     75 }
     76 
     77 static bool get_the_file(HANDLE handle, SkString* name, WIN32_FIND_DATAW* dataPtr, bool getDir)
     78 {
     79     WIN32_FIND_DATAW    data;
     80 
     81     if (dataPtr == nil)
     82     {
     83         if (::FindNextFileW(handle, &data))
     84             dataPtr = &data;
     85         else
     86             return false;
     87     }
     88 
     89     for (;;)
     90     {
     91         if (getDir)
     92         {
     93             if ((dataPtr->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) && !is_magic_dir(dataPtr->cFileName))
     94                 break;
     95         }
     96         else
     97         {
     98             if (!(dataPtr->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY))
     99                 break;
    100         }
    101         if (!::FindNextFileW(handle, dataPtr))
    102             return false;
    103     }
    104     // if we get here, we've found a file/dir
    105     if (name)
    106         name->setUTF16(dataPtr->cFileName);
    107     return true;
    108 }
    109 
    110 bool SkOSFile::Iter::next(SkString* name, bool getDir)
    111 {
    112     WIN32_FIND_DATAW    data;
    113     WIN32_FIND_DATAW*   dataPtr = nil;
    114 
    115     if (fHandle == 0)   // our first time
    116     {
    117         if (fPath16 == nil || *fPath16 == 0)    // check for no path
    118             return false;
    119 
    120         fHandle = ::FindFirstFileW(fPath16, &data);
    121         if (fHandle != 0 && fHandle != (HANDLE)~0)
    122             dataPtr = &data;
    123     }
    124     return fHandle != (HANDLE)~0 && get_the_file(fHandle, name, dataPtr, getDir);
    125 }
    126 
    127 #elif defined(SK_BUILD_FOR_MAC) || defined(SK_BUILD_FOR_UNIX)
    128 
    129 #if 0
    130 OSStatus FSPathMakeRef (
    131    const UInt8 * path,
    132    FSRef * ref,
    133    Boolean * isDirectory
    134 );
    135 #endif
    136 
    137 SkOSFile::Iter::Iter() : fDIR(0)
    138 {
    139 }
    140 
    141 SkOSFile::Iter::Iter(const char path[], const char suffix[]) : fDIR(0)
    142 {
    143     this->reset(path, suffix);
    144 }
    145 
    146 SkOSFile::Iter::~Iter()
    147 {
    148     if (fDIR)
    149         ::closedir(fDIR);
    150 }
    151 
    152 void SkOSFile::Iter::reset(const char path[], const char suffix[])
    153 {
    154     if (fDIR)
    155     {
    156         ::closedir(fDIR);
    157         fDIR = 0;
    158     }
    159 
    160     fPath.set(path);
    161     if (path)
    162     {
    163         fDIR = ::opendir(path);
    164         fSuffix.set(suffix);
    165     }
    166     else
    167         fSuffix.reset();
    168 }
    169 
    170 // returns true if suffix is empty, or if str ends with suffix
    171 static bool issuffixfor(const SkString& suffix, const char str[])
    172 {
    173     size_t  suffixLen = suffix.size();
    174     size_t  strLen = strlen(str);
    175 
    176     return  strLen >= suffixLen &&
    177             suffixLen == 0 ||
    178             memcmp(suffix.c_str(), str + strLen - suffixLen, suffixLen) == 0;
    179 }
    180 
    181 #include <sys/stat.h>
    182 
    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