blob: 37d2d410fd95da830f32b9e582ec214722454ced [file] [log] [blame]
niklase@google.com470e71d2011-07-07 08:21:25 +00001/*
henrike@webrtc.org143abd92012-02-08 19:39:38 +00002 * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
niklase@google.com470e71d2011-07-07 08:21:25 +00003 *
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
henrike@webrtc.org9a6dac42012-09-27 22:20:34 +000011#include "system_wrappers/source/file_impl.h"
niklase@google.com470e71d2011-07-07 08:21:25 +000012
andrew@webrtc.org114c7902011-12-10 02:33:33 +000013#include <assert.h>
niklase@google.com470e71d2011-07-07 08:21:25 +000014
15#ifdef _WIN32
andrew@webrtc.org114c7902011-12-10 02:33:33 +000016#include <Windows.h>
niklase@google.com470e71d2011-07-07 08:21:25 +000017#else
andrew@webrtc.org114c7902011-12-10 02:33:33 +000018#include <stdarg.h>
19#include <string.h>
niklase@google.com470e71d2011-07-07 08:21:25 +000020#endif
21
henrike@webrtc.org9a6dac42012-09-27 22:20:34 +000022#include "system_wrappers/interface/rw_lock_wrapper.h"
23
niklase@google.com470e71d2011-07-07 08:21:25 +000024namespace webrtc {
andrew@webrtc.org5ae19de2011-12-13 22:59:33 +000025
niklase@google.com470e71d2011-07-07 08:21:25 +000026FileWrapper* FileWrapper::Create()
27{
28 return new FileWrapperImpl();
29}
30
31FileWrapperImpl::FileWrapperImpl()
henrike@webrtc.org9a6dac42012-09-27 22:20:34 +000032 : _rwLock(RWLockWrapper::CreateRWLock()),
33 _id(NULL),
niklase@google.com470e71d2011-07-07 08:21:25 +000034 _open(false),
35 _looping(false),
36 _readOnly(false),
andrew@webrtc.org5ae19de2011-12-13 22:59:33 +000037 _maxSizeInBytes(0),
niklase@google.com470e71d2011-07-07 08:21:25 +000038 _sizeInBytes(0)
39{
40 memset(_fileNameUTF8, 0, kMaxFileNameSize);
41}
42
43FileWrapperImpl::~FileWrapperImpl()
44{
45 if (_id != NULL)
46 {
47 fclose(_id);
48 }
49}
50
andrew@webrtc.org5ae19de2011-12-13 22:59:33 +000051int FileWrapperImpl::CloseFile()
niklase@google.com470e71d2011-07-07 08:21:25 +000052{
henrike@webrtc.org9a6dac42012-09-27 22:20:34 +000053 WriteLockScoped write(*_rwLock);
54 return CloseFileImpl();
niklase@google.com470e71d2011-07-07 08:21:25 +000055}
56
57int FileWrapperImpl::Rewind()
58{
henrike@webrtc.org9a6dac42012-09-27 22:20:34 +000059 WriteLockScoped write(*_rwLock);
niklase@google.com470e71d2011-07-07 08:21:25 +000060 if(_looping || !_readOnly)
61 {
62 if (_id != NULL)
63 {
64 _sizeInBytes = 0;
65 return fseek(_id, 0, SEEK_SET);
66 }
67 }
68 return -1;
69}
70
andrew@webrtc.org5ae19de2011-12-13 22:59:33 +000071int FileWrapperImpl::SetMaxFileSize(size_t bytes)
niklase@google.com470e71d2011-07-07 08:21:25 +000072{
henrike@webrtc.org9a6dac42012-09-27 22:20:34 +000073 WriteLockScoped write(*_rwLock);
niklase@google.com470e71d2011-07-07 08:21:25 +000074 _maxSizeInBytes = bytes;
75 return 0;
76}
77
andrew@webrtc.org5ae19de2011-12-13 22:59:33 +000078int FileWrapperImpl::Flush()
niklase@google.com470e71d2011-07-07 08:21:25 +000079{
henrike@webrtc.org9a6dac42012-09-27 22:20:34 +000080 WriteLockScoped write(*_rwLock);
81 return FlushImpl();
niklase@google.com470e71d2011-07-07 08:21:25 +000082}
83
andrew@webrtc.org5ae19de2011-12-13 22:59:33 +000084int FileWrapperImpl::FileName(char* fileNameUTF8,
85 size_t size) const
niklase@google.com470e71d2011-07-07 08:21:25 +000086{
henrike@webrtc.org9a6dac42012-09-27 22:20:34 +000087 ReadLockScoped read(*_rwLock);
andrew@webrtc.org986fab12011-12-15 19:11:41 +000088 size_t length = strlen(_fileNameUTF8);
89 if(length > kMaxFileNameSize)
niklase@google.com470e71d2011-07-07 08:21:25 +000090 {
91 assert(false);
92 return -1;
93 }
andrew@webrtc.org986fab12011-12-15 19:11:41 +000094 if(length < 1)
niklase@google.com470e71d2011-07-07 08:21:25 +000095 {
96 return -1;
97 }
andrew@webrtc.org986fab12011-12-15 19:11:41 +000098
niklase@google.com470e71d2011-07-07 08:21:25 +000099 // Make sure to NULL terminate
andrew@webrtc.org986fab12011-12-15 19:11:41 +0000100 if(size < length)
niklase@google.com470e71d2011-07-07 08:21:25 +0000101 {
andrew@webrtc.org986fab12011-12-15 19:11:41 +0000102 length = size - 1;
niklase@google.com470e71d2011-07-07 08:21:25 +0000103 }
andrew@webrtc.org986fab12011-12-15 19:11:41 +0000104 memcpy(fileNameUTF8, _fileNameUTF8, length);
105 fileNameUTF8[length] = 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000106 return 0;
107}
108
andrew@webrtc.org5ae19de2011-12-13 22:59:33 +0000109bool FileWrapperImpl::Open() const
niklase@google.com470e71d2011-07-07 08:21:25 +0000110{
henrike@webrtc.org9a6dac42012-09-27 22:20:34 +0000111 ReadLockScoped read(*_rwLock);
niklase@google.com470e71d2011-07-07 08:21:25 +0000112 return _open;
113}
114
andrew@webrtc.org5ae19de2011-12-13 22:59:33 +0000115int FileWrapperImpl::OpenFile(const char *fileNameUTF8, bool readOnly,
116 bool loop, bool text)
niklase@google.com470e71d2011-07-07 08:21:25 +0000117{
henrike@webrtc.org9a6dac42012-09-27 22:20:34 +0000118 WriteLockScoped write(*_rwLock);
andrew@webrtc.org5ae19de2011-12-13 22:59:33 +0000119 size_t length = strlen(fileNameUTF8);
henrike@webrtc.org143abd92012-02-08 19:39:38 +0000120 if (length > kMaxFileNameSize - 1)
niklase@google.com470e71d2011-07-07 08:21:25 +0000121 {
122 return -1;
123 }
124
125 _readOnly = readOnly;
126
127 FILE *tmpId = NULL;
128#if defined _WIN32
129 wchar_t wideFileName[kMaxFileNameSize];
130 wideFileName[0] = 0;
131
132 MultiByteToWideChar(CP_UTF8,
133 0 /*UTF8 flag*/,
134 fileNameUTF8,
135 -1 /*Null terminated string*/,
136 wideFileName,
137 kMaxFileNameSize);
138 if(text)
139 {
140 if(readOnly)
141 {
142 tmpId = _wfopen(wideFileName, L"rt");
143 } else {
144 tmpId = _wfopen(wideFileName, L"wt");
145 }
146 } else {
147 if(readOnly)
148 {
149 tmpId = _wfopen(wideFileName, L"rb");
150 } else {
151 tmpId = _wfopen(wideFileName, L"wb");
152 }
153 }
154#else
155 if(text)
156 {
157 if(readOnly)
158 {
159 tmpId = fopen(fileNameUTF8, "rt");
160 } else {
161 tmpId = fopen(fileNameUTF8, "wt");
162 }
163 } else {
164 if(readOnly)
165 {
166 tmpId = fopen(fileNameUTF8, "rb");
167 } else {
168 tmpId = fopen(fileNameUTF8, "wb");
169 }
170 }
171#endif
172
173 if (tmpId != NULL)
174 {
andrew@webrtc.org114c7902011-12-10 02:33:33 +0000175 // +1 comes from copying the NULL termination character.
niklase@google.com470e71d2011-07-07 08:21:25 +0000176 memcpy(_fileNameUTF8, fileNameUTF8, length + 1);
177 if (_id != NULL)
178 {
179 fclose(_id);
180 }
181 _id = tmpId;
182 _looping = loop;
183 _open = true;
184 return 0;
185 }
186 return -1;
187}
188
andrew@webrtc.org986fab12011-12-15 19:11:41 +0000189int FileWrapperImpl::Read(void* buf, int length)
niklase@google.com470e71d2011-07-07 08:21:25 +0000190{
henrike@webrtc.org9a6dac42012-09-27 22:20:34 +0000191 WriteLockScoped write(*_rwLock);
andrew@webrtc.org986fab12011-12-15 19:11:41 +0000192 if (length < 0)
andrew@webrtc.org114c7902011-12-10 02:33:33 +0000193 return -1;
194
niklase@google.com470e71d2011-07-07 08:21:25 +0000195 if (_id == NULL)
andrew@webrtc.org114c7902011-12-10 02:33:33 +0000196 return -1;
197
andrew@webrtc.org986fab12011-12-15 19:11:41 +0000198 int bytes_read = static_cast<int>(fread(buf, 1, length, _id));
199 if (bytes_read != length && !_looping)
200 {
henrike@webrtc.org9a6dac42012-09-27 22:20:34 +0000201 CloseFileImpl();
andrew@webrtc.org986fab12011-12-15 19:11:41 +0000202 }
203 return bytes_read;
204}
205
206int FileWrapperImpl::WriteText(const char* format, ...)
207{
henrike@webrtc.org9a6dac42012-09-27 22:20:34 +0000208 WriteLockScoped write(*_rwLock);
andrew@webrtc.org114c7902011-12-10 02:33:33 +0000209 if (format == NULL)
210 return -1;
211
andrew@webrtc.org986fab12011-12-15 19:11:41 +0000212 if (_readOnly)
213 return -1;
214
215 if (_id == NULL)
216 return -1;
217
andrew@webrtc.org114c7902011-12-10 02:33:33 +0000218 va_list args;
219 va_start(args, format);
andrew@webrtc.org5ae19de2011-12-13 22:59:33 +0000220 int num_chars = vfprintf(_id, format, args);
andrew@webrtc.org114c7902011-12-10 02:33:33 +0000221 va_end(args);
222
andrew@webrtc.org7e5ddf52011-12-14 18:02:02 +0000223 if (num_chars >= 0)
niklase@google.com470e71d2011-07-07 08:21:25 +0000224 {
andrew@webrtc.org7e5ddf52011-12-14 18:02:02 +0000225 return num_chars;
andrew@webrtc.org114c7902011-12-10 02:33:33 +0000226 }
227 else
228 {
henrike@webrtc.org9a6dac42012-09-27 22:20:34 +0000229 CloseFileImpl();
niklase@google.com470e71d2011-07-07 08:21:25 +0000230 return -1;
231 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000232}
233
andrew@webrtc.org986fab12011-12-15 19:11:41 +0000234bool FileWrapperImpl::Write(const void* buf, int length)
niklase@google.com470e71d2011-07-07 08:21:25 +0000235{
henrike@webrtc.org9a6dac42012-09-27 22:20:34 +0000236 WriteLockScoped write(*_rwLock);
andrew@webrtc.org986fab12011-12-15 19:11:41 +0000237 if (buf == NULL)
238 return false;
239
240 if (length < 0)
241 return false;
242
andrew@webrtc.org5a9c6f22011-12-14 00:53:30 +0000243 if (_readOnly)
andrew@webrtc.org986fab12011-12-15 19:11:41 +0000244 return false;
245
246 if (_id == NULL)
247 return false;
248
249 // Check if it's time to stop writing.
250 if (_maxSizeInBytes > 0 && (_sizeInBytes + length) > _maxSizeInBytes)
andrew@webrtc.org114c7902011-12-10 02:33:33 +0000251 {
henrike@webrtc.org9a6dac42012-09-27 22:20:34 +0000252 FlushImpl();
andrew@webrtc.org114c7902011-12-10 02:33:33 +0000253 return false;
254 }
255
andrew@webrtc.org986fab12011-12-15 19:11:41 +0000256 size_t num_bytes = fwrite(buf, 1, length, _id);
257 if (num_bytes > 0)
niklase@google.com470e71d2011-07-07 08:21:25 +0000258 {
andrew@webrtc.org986fab12011-12-15 19:11:41 +0000259 _sizeInBytes += num_bytes;
260 return true;
niklase@google.com470e71d2011-07-07 08:21:25 +0000261 }
andrew@webrtc.org986fab12011-12-15 19:11:41 +0000262
henrike@webrtc.org9a6dac42012-09-27 22:20:34 +0000263 CloseFileImpl();
niklase@google.com470e71d2011-07-07 08:21:25 +0000264 return false;
265}
andrew@webrtc.org5ae19de2011-12-13 22:59:33 +0000266
henrike@webrtc.org9a6dac42012-09-27 22:20:34 +0000267int FileWrapperImpl::CloseFileImpl() {
268 if (_id != NULL)
269 {
270 fclose(_id);
271 _id = NULL;
272 }
273 memset(_fileNameUTF8, 0, kMaxFileNameSize);
274 _open = false;
275 return 0;
276}
277
278int FileWrapperImpl::FlushImpl() {
279 if (_id != NULL)
280 {
281 return fflush(_id);
282 }
283 return -1;
284}
285
286
niklase@google.com470e71d2011-07-07 08:21:25 +0000287} // namespace webrtc