blob: 0ee0deab6c1061edb3f475d44a3ff9b7e6f7f51d [file] [log] [blame]
/*
* Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#include "webrtc/system_wrappers/source/file_impl.h"
#include <assert.h>
#ifdef _WIN32
#include <Windows.h>
#else
#include <stdarg.h>
#include <string.h>
#endif
#include "webrtc/base/checks.h"
#include "webrtc/system_wrappers/include/rw_lock_wrapper.h"
namespace webrtc {
FileWrapper* FileWrapper::Create() {
return new FileWrapperImpl();
}
FileWrapperImpl::FileWrapperImpl()
: rw_lock_(RWLockWrapper::CreateRWLock()),
id_(NULL),
managed_file_handle_(true),
open_(false),
looping_(false),
read_only_(false),
max_size_in_bytes_(0),
size_in_bytes_(0) {
memset(file_name_utf8_, 0, kMaxFileNameSize);
}
FileWrapperImpl::~FileWrapperImpl() {
if (id_ != NULL && managed_file_handle_) {
fclose(id_);
}
}
int FileWrapperImpl::CloseFile() {
WriteLockScoped write(*rw_lock_);
return CloseFileImpl();
}
int FileWrapperImpl::Rewind() {
WriteLockScoped write(*rw_lock_);
if (looping_ || !read_only_) {
if (id_ != NULL) {
size_in_bytes_ = 0;
return fseek(id_, 0, SEEK_SET);
}
}
return -1;
}
int FileWrapperImpl::SetMaxFileSize(size_t bytes) {
WriteLockScoped write(*rw_lock_);
max_size_in_bytes_ = bytes;
return 0;
}
int FileWrapperImpl::Flush() {
WriteLockScoped write(*rw_lock_);
return FlushImpl();
}
int FileWrapperImpl::FileName(char* file_name_utf8, size_t size) const {
ReadLockScoped read(*rw_lock_);
size_t length = strlen(file_name_utf8_);
if (length > kMaxFileNameSize) {
assert(false);
return -1;
}
if (length < 1) {
return -1;
}
// Make sure to NULL terminate
if (size < length) {
length = size - 1;
}
memcpy(file_name_utf8, file_name_utf8_, length);
file_name_utf8[length] = 0;
return 0;
}
bool FileWrapperImpl::Open() const {
ReadLockScoped read(*rw_lock_);
return open_;
}
int FileWrapperImpl::OpenFile(const char* file_name_utf8, bool read_only,
bool loop, bool text) {
WriteLockScoped write(*rw_lock_);
if (id_ != NULL && !managed_file_handle_)
return -1;
size_t length = strlen(file_name_utf8);
if (length > kMaxFileNameSize - 1) {
return -1;
}
read_only_ = read_only;
FILE* tmp_id = NULL;
#if defined _WIN32
wchar_t wide_file_name[kMaxFileNameSize];
wide_file_name[0] = 0;
MultiByteToWideChar(CP_UTF8,
0, // UTF8 flag
file_name_utf8,
-1, // Null terminated string
wide_file_name,
kMaxFileNameSize);
if (text) {
if (read_only) {
tmp_id = _wfopen(wide_file_name, L"rt");
} else {
tmp_id = _wfopen(wide_file_name, L"wt");
}
} else {
if (read_only) {
tmp_id = _wfopen(wide_file_name, L"rb");
} else {
tmp_id = _wfopen(wide_file_name, L"wb");
}
}
#else
if (text) {
if (read_only) {
tmp_id = fopen(file_name_utf8, "rt");
} else {
tmp_id = fopen(file_name_utf8, "wt");
}
} else {
if (read_only) {
tmp_id = fopen(file_name_utf8, "rb");
} else {
tmp_id = fopen(file_name_utf8, "wb");
}
}
#endif
if (tmp_id != NULL) {
// +1 comes from copying the NULL termination character.
memcpy(file_name_utf8_, file_name_utf8, length + 1);
if (id_ != NULL) {
fclose(id_);
}
id_ = tmp_id;
managed_file_handle_ = true;
looping_ = loop;
open_ = true;
return 0;
}
return -1;
}
int FileWrapperImpl::OpenFromFileHandle(FILE* handle,
bool manage_file,
bool read_only,
bool loop) {
WriteLockScoped write(*rw_lock_);
if (!handle)
return -1;
if (id_ != NULL) {
if (managed_file_handle_)
fclose(id_);
else
return -1;
}
id_ = handle;
managed_file_handle_ = manage_file;
read_only_ = read_only;
looping_ = loop;
open_ = true;
return 0;
}
int FileWrapperImpl::Read(void* buf, size_t length) {
WriteLockScoped write(*rw_lock_);
if (id_ == NULL)
return -1;
size_t bytes_read = fread(buf, 1, length, id_);
if (bytes_read != length && !looping_) {
CloseFileImpl();
}
return static_cast<int>(bytes_read);
}
int FileWrapperImpl::WriteText(const char* format, ...) {
WriteLockScoped write(*rw_lock_);
if (format == NULL)
return -1;
if (read_only_)
return -1;
if (id_ == NULL)
return -1;
va_list args;
va_start(args, format);
int num_chars = vfprintf(id_, format, args);
va_end(args);
if (num_chars >= 0) {
return num_chars;
} else {
CloseFileImpl();
return -1;
}
}
bool FileWrapperImpl::Write(const void* buf, size_t length) {
WriteLockScoped write(*rw_lock_);
if (buf == NULL)
return false;
if (read_only_)
return false;
if (id_ == NULL)
return false;
// Check if it's time to stop writing.
if (max_size_in_bytes_ > 0 &&
(size_in_bytes_ + length) > max_size_in_bytes_) {
FlushImpl();
return false;
}
size_t num_bytes = fwrite(buf, 1, length, id_);
if (num_bytes > 0) {
size_in_bytes_ += num_bytes;
return true;
}
CloseFileImpl();
return false;
}
int FileWrapperImpl::CloseFileImpl() {
if (id_ != NULL) {
if (managed_file_handle_)
fclose(id_);
id_ = NULL;
}
memset(file_name_utf8_, 0, kMaxFileNameSize);
open_ = false;
return 0;
}
int FileWrapperImpl::FlushImpl() {
if (id_ != NULL) {
return fflush(id_);
}
return -1;
}
int FileWrapper::Rewind() {
RTC_DCHECK(false);
return -1;
}
} // namespace webrtc