diff options
Diffstat (limited to 'sfntly/port/file_input_stream.cc')
-rw-r--r-- | sfntly/port/file_input_stream.cc | 171 |
1 files changed, 171 insertions, 0 deletions
diff --git a/sfntly/port/file_input_stream.cc b/sfntly/port/file_input_stream.cc new file mode 100644 index 0000000..dfe9a7b --- /dev/null +++ b/sfntly/port/file_input_stream.cc @@ -0,0 +1,171 @@ +/* + * 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; + 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 |