1 /*
2 * Copyright (c) 2012 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
Create()24 FileWrapper* FileWrapper::Create()
25 {
26 return new FileWrapperImpl();
27 }
28
FileWrapperImpl()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
~FileWrapperImpl()40 FileWrapperImpl::~FileWrapperImpl()
41 {
42 if (_id != NULL)
43 {
44 fclose(_id);
45 }
46 }
47
CloseFile()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
Rewind()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
SetMaxFileSize(size_t bytes)73 int FileWrapperImpl::SetMaxFileSize(size_t bytes)
74 {
75 _maxSizeInBytes = bytes;
76 return 0;
77 }
78
Flush()79 int FileWrapperImpl::Flush()
80 {
81 if (_id != NULL)
82 {
83 return fflush(_id);
84 }
85 return -1;
86 }
87
FileName(char * fileNameUTF8,size_t size) const88 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
Open() const112 bool FileWrapperImpl::Open() const
113 {
114 return _open;
115 }
116
OpenFile(const char * fileNameUTF8,bool readOnly,bool loop,bool text)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 - 1)
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
Read(void * buf,int length)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
WriteText(const char * format,...)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
Write(const void * buf,int length)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