Home | History | Annotate | Download | only in utils
      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)
    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 
    231