Home | History | Annotate | Download | only in source
      1 /*
      2  *  Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
      3  *
      4  *  Use of this source code is governed by a BSD-style license
      5  *  that can be found in the LICENSE file in the root of the source
      6  *  tree. An additional intellectual property rights grant can be found
      7  *  in the file PATENTS.  All contributing project authors may
      8  *  be found in the AUTHORS file in the root of the source tree.
      9  */
     10 
     11 #include "file_impl.h"
     12 
     13 #include <assert.h>
     14 
     15 #ifdef _WIN32
     16 #include <Windows.h>
     17 #else
     18 #include <stdarg.h>
     19 #include <string.h>
     20 #endif
     21 
     22 namespace webrtc {
     23 
     24 FileWrapper* FileWrapper::Create()
     25 {
     26     return new FileWrapperImpl();
     27 }
     28 
     29 FileWrapperImpl::FileWrapperImpl()
     30     : _id(NULL),
     31       _open(false),
     32       _looping(false),
     33       _readOnly(false),
     34       _maxSizeInBytes(0),
     35       _sizeInBytes(0)
     36 {
     37     memset(_fileNameUTF8, 0, kMaxFileNameSize);
     38 }
     39 
     40 FileWrapperImpl::~FileWrapperImpl()
     41 {
     42     if (_id != NULL)
     43     {
     44         fclose(_id);
     45     }
     46 }
     47 
     48 int FileWrapperImpl::CloseFile()
     49 {
     50     if (_id != NULL)
     51     {
     52         fclose(_id);
     53         _id = NULL;
     54     }
     55     memset(_fileNameUTF8, 0, kMaxFileNameSize);
     56     _open = false;
     57     return 0;
     58 }
     59 
     60 int FileWrapperImpl::Rewind()
     61 {
     62     if(_looping || !_readOnly)
     63     {
     64         if (_id != NULL)
     65         {
     66             _sizeInBytes = 0;
     67             return fseek(_id, 0, SEEK_SET);
     68         }
     69     }
     70     return -1;
     71 }
     72 
     73 int FileWrapperImpl::SetMaxFileSize(size_t bytes)
     74 {
     75     _maxSizeInBytes = bytes;
     76     return 0;
     77 }
     78 
     79 int FileWrapperImpl::Flush()
     80 {
     81     if (_id != NULL)
     82     {
     83         return fflush(_id);
     84     }
     85     return -1;
     86 }
     87 
     88 int FileWrapperImpl::FileName(char* fileNameUTF8,
     89                               size_t size) const
     90 {
     91     size_t length = strlen(_fileNameUTF8);
     92     if(length > kMaxFileNameSize)
     93     {
     94         assert(false);
     95         return -1;
     96     }
     97     if(length < 1)
     98     {
     99         return -1;
    100     }
    101 
    102     // Make sure to NULL terminate
    103     if(size < length)
    104     {
    105         length = size - 1;
    106     }
    107     memcpy(fileNameUTF8, _fileNameUTF8, length);
    108     fileNameUTF8[length] = 0;
    109     return 0;
    110 }
    111 
    112 bool FileWrapperImpl::Open() const
    113 {
    114     return _open;
    115 }
    116 
    117 int FileWrapperImpl::OpenFile(const char *fileNameUTF8, bool readOnly,
    118                               bool loop, bool text)
    119 {
    120     size_t length = strlen(fileNameUTF8);
    121     if (length > kMaxFileNameSize)
    122     {
    123         return -1;
    124     }
    125 
    126     _readOnly = readOnly;
    127 
    128     FILE *tmpId = NULL;
    129 #if defined _WIN32
    130     wchar_t wideFileName[kMaxFileNameSize];
    131     wideFileName[0] = 0;
    132 
    133     MultiByteToWideChar(CP_UTF8,
    134                         0 /*UTF8 flag*/,
    135                         fileNameUTF8,
    136                         -1 /*Null terminated string*/,
    137                         wideFileName,
    138                         kMaxFileNameSize);
    139     if(text)
    140     {
    141         if(readOnly)
    142         {
    143             tmpId = _wfopen(wideFileName, L"rt");
    144         } else {
    145             tmpId = _wfopen(wideFileName, L"wt");
    146         }
    147     } else {
    148         if(readOnly)
    149         {
    150             tmpId = _wfopen(wideFileName, L"rb");
    151         } else {
    152             tmpId = _wfopen(wideFileName, L"wb");
    153         }
    154     }
    155 #else
    156     if(text)
    157     {
    158         if(readOnly)
    159         {
    160             tmpId = fopen(fileNameUTF8, "rt");
    161         } else {
    162             tmpId = fopen(fileNameUTF8, "wt");
    163         }
    164     } else {
    165         if(readOnly)
    166         {
    167             tmpId = fopen(fileNameUTF8, "rb");
    168         } else {
    169             tmpId = fopen(fileNameUTF8, "wb");
    170         }
    171     }
    172 #endif
    173 
    174     if (tmpId != NULL)
    175     {
    176         // +1 comes from copying the NULL termination character.
    177         memcpy(_fileNameUTF8, fileNameUTF8, length + 1);
    178         if (_id != NULL)
    179         {
    180             fclose(_id);
    181         }
    182         _id = tmpId;
    183         _looping = loop;
    184         _open = true;
    185         return 0;
    186     }
    187     return -1;
    188 }
    189 
    190 int FileWrapperImpl::Read(void* buf, int length)
    191 {
    192     if (length < 0)
    193         return -1;
    194 
    195     if (_id == NULL)
    196         return -1;
    197 
    198     int bytes_read = static_cast<int>(fread(buf, 1, length, _id));
    199     if (bytes_read != length && !_looping)
    200     {
    201         CloseFile();
    202     }
    203     return bytes_read;
    204 }
    205 
    206 int FileWrapperImpl::WriteText(const char* format, ...)
    207 {
    208     if (format == NULL)
    209         return -1;
    210 
    211     if (_readOnly)
    212         return -1;
    213 
    214     if (_id == NULL)
    215         return -1;
    216 
    217     va_list args;
    218     va_start(args, format);
    219     int num_chars = vfprintf(_id, format, args);
    220     va_end(args);
    221 
    222     if (num_chars >= 0)
    223     {
    224         return num_chars;
    225     }
    226     else
    227     {
    228         CloseFile();
    229         return -1;
    230     }
    231 }
    232 
    233 bool FileWrapperImpl::Write(const void* buf, int length)
    234 {
    235     if (buf == NULL)
    236         return false;
    237 
    238     if (length < 0)
    239         return false;
    240 
    241     if (_readOnly)
    242         return false;
    243 
    244     if (_id == NULL)
    245         return false;
    246 
    247     // Check if it's time to stop writing.
    248     if (_maxSizeInBytes > 0 && (_sizeInBytes + length) > _maxSizeInBytes)
    249     {
    250         Flush();
    251         return false;
    252     }
    253 
    254     size_t num_bytes = fwrite(buf, 1, length, _id);
    255     if (num_bytes > 0)
    256     {
    257         _sizeInBytes += num_bytes;
    258         return true;
    259     }
    260 
    261     CloseFile();
    262     return false;
    263 }
    264 
    265 } // namespace webrtc
    266