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 22namespace webrtc { 23 24FileWrapper* FileWrapper::Create() 25{ 26 return new FileWrapperImpl(); 27} 28 29FileWrapperImpl::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 40FileWrapperImpl::~FileWrapperImpl() 41{ 42 if (_id != NULL) 43 { 44 fclose(_id); 45 } 46} 47 48int 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 60int 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 73int FileWrapperImpl::SetMaxFileSize(size_t bytes) 74{ 75 _maxSizeInBytes = bytes; 76 return 0; 77} 78 79int FileWrapperImpl::Flush() 80{ 81 if (_id != NULL) 82 { 83 return fflush(_id); 84 } 85 return -1; 86} 87 88int 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 112bool FileWrapperImpl::Open() const 113{ 114 return _open; 115} 116 117int 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 190int 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 206int 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 233bool 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