/*
|
* Copyright 2011 Google Inc. All Rights Reserved.
|
*
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
* you may not use this file except in compliance with the License.
|
* You may obtain a copy of the License at
|
*
|
* http://www.apache.org/licenses/LICENSE-2.0
|
*
|
* Unless required by applicable law or agreed to in writing, software
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
* See the License for the specific language governing permissions and
|
* limitations under the License.
|
*/
|
|
#if defined (WIN32)
|
#include <windows.h>
|
#endif
|
|
#include <algorithm>
|
|
#include "sfntly/port/file_input_stream.h"
|
#include "sfntly/port/exception_type.h"
|
|
namespace sfntly {
|
|
FileInputStream::FileInputStream()
|
: file_(NULL),
|
position_(0),
|
length_(0) {
|
}
|
|
FileInputStream::~FileInputStream() {
|
Close();
|
}
|
|
int32_t FileInputStream::Available() {
|
return length_ - position_;
|
}
|
|
void FileInputStream::Close() {
|
if (file_) {
|
fclose(file_);
|
length_ = 0;
|
position_ = 0;
|
file_ = NULL;
|
}
|
}
|
|
void FileInputStream::Mark(int32_t readlimit) {
|
// NOP
|
UNREFERENCED_PARAMETER(readlimit);
|
}
|
|
bool FileInputStream::MarkSupported() {
|
return false;
|
}
|
|
int32_t FileInputStream::Read() {
|
if (!file_) {
|
#if !defined (SFNTLY_NO_EXCEPTION)
|
throw IOException("no opened file");
|
#endif
|
return 0;
|
}
|
if (feof(file_)) {
|
#if !defined (SFNTLY_NO_EXCEPTION)
|
throw IOException("eof reached");
|
#endif
|
return 0;
|
}
|
byte_t value = 0;
|
size_t length = fread(&value, 1, 1, file_);
|
position_ += length;
|
return value;
|
}
|
|
int32_t FileInputStream::Read(ByteVector* b) {
|
return Read(b, 0, b->size());
|
}
|
|
int32_t FileInputStream::Read(ByteVector* b, int32_t offset, int32_t length) {
|
assert(b);
|
if (!file_) {
|
#if !defined (SFNTLY_NO_EXCEPTION)
|
throw IOException("no opened file");
|
#endif
|
return 0;
|
}
|
if (feof(file_)) {
|
#if !defined (SFNTLY_NO_EXCEPTION)
|
throw IOException("eof reached");
|
#endif
|
return 0;
|
}
|
size_t read_count = std::min<size_t>(length_ - position_, length);
|
if (b->size() < (size_t)(offset + read_count)) {
|
b->resize((size_t)(offset + read_count));
|
}
|
int32_t actual_read = fread(&((*b)[offset]), 1, read_count, file_);
|
position_ += actual_read;
|
return actual_read;
|
}
|
|
void FileInputStream::Reset() {
|
// NOP
|
}
|
|
int64_t FileInputStream::Skip(int64_t n) {
|
if (!file_) {
|
#if !defined (SFNTLY_NO_EXCEPTION)
|
throw IOException("no opened file");
|
#endif
|
return 0;
|
}
|
int64_t skip_count = 0;
|
if (n < 0) { // move backwards
|
skip_count = std::max<int64_t>(0 - (int64_t)position_, n);
|
position_ -= (size_t)(0 - skip_count);
|
fseek(file_, position_, SEEK_SET);
|
} else {
|
skip_count = std::min<size_t>(length_ - position_, (size_t)n);
|
position_ += (size_t)skip_count;
|
fseek(file_, (size_t)skip_count, SEEK_CUR);
|
}
|
return skip_count;
|
}
|
|
void FileInputStream::Unread(ByteVector* b) {
|
Unread(b, 0, b->size());
|
}
|
|
void FileInputStream::Unread(ByteVector* b, int32_t offset, int32_t length) {
|
assert(b);
|
assert(b->size() >= size_t(offset + length));
|
if (!file_) {
|
#if !defined (SFNTLY_NO_EXCEPTION)
|
throw IOException("no opened file");
|
#endif
|
return;
|
}
|
size_t unread_count = std::min<size_t>(position_, length);
|
fseek(file_, position_ - unread_count, SEEK_SET);
|
position_ -= unread_count;
|
Read(b, offset, length);
|
fseek(file_, position_ - unread_count, SEEK_SET);
|
position_ -= unread_count;
|
}
|
|
bool FileInputStream::Open(const char* file_path) {
|
assert(file_path);
|
if (file_) {
|
Close();
|
}
|
#if defined (WIN32)
|
fopen_s(&file_, file_path, "rb");
|
#else
|
file_ = fopen(file_path, "rb");
|
#endif
|
if (file_ == NULL) {
|
return false;
|
}
|
|
fseek(file_, 0, SEEK_END);
|
length_ = ftell(file_);
|
fseek(file_, 0, SEEK_SET);
|
return true;
|
}
|
|
} // namespace sfntly
|