130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun/* 230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun * Copyright 2011 Google Inc. All Rights Reserved. 330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun * 430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun * Licensed under the Apache License, Version 2.0 (the "License"); 530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun * you may not use this file except in compliance with the License. 630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun * You may obtain a copy of the License at 730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun * 830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun * http://www.apache.org/licenses/LICENSE-2.0 930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun * 1030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun * Unless required by applicable law or agreed to in writing, software 1130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun * distributed under the License is distributed on an "AS IS" BASIS, 1230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun * See the License for the specific language governing permissions and 1430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun * limitations under the License. 1530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun */ 1630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun 1730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun#if defined (WIN32) 1830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun#include <windows.h> 1930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun#endif 2030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun 2130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun#include "sfntly/port/file_input_stream.h" 2230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun#include "sfntly/port/exception_type.h" 2330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun 2430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurunnamespace sfntly { 2530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun 2630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim GurunFileInputStream::FileInputStream() 2730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun : file_(NULL), 2830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun position_(0), 2930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun length_(0) { 3030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun} 3130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun 3230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim GurunFileInputStream::~FileInputStream() { 3330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun Close(); 3430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun} 3530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun 3630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurunint32_t FileInputStream::Available() { 3730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun return length_ - position_; 3830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun} 3930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun 4030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurunvoid FileInputStream::Close() { 4130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun if (file_) { 4230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun fclose(file_); 4330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun length_ = 0; 4430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun position_ = 0; 4530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun file_ = NULL; 4630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun } 4730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun} 4830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun 4930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurunvoid FileInputStream::Mark(int32_t readlimit) { 5030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun // NOP 5130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun UNREFERENCED_PARAMETER(readlimit); 5230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun} 5330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun 5430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurunbool FileInputStream::MarkSupported() { 5530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun return false; 5630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun} 5730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun 5830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurunint32_t FileInputStream::Read() { 5930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun if (!file_) { 6030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun#if !defined (SFNTLY_NO_EXCEPTION) 6130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun throw IOException("no opened file"); 6230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun#endif 6330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun return 0; 6430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun } 6530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun if (feof(file_)) { 6630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun#if !defined (SFNTLY_NO_EXCEPTION) 6730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun throw IOException("eof reached"); 6830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun#endif 6930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun return 0; 7030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun } 7130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun byte_t value; 7230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun size_t length = fread(&value, 1, 1, file_); 7330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun position_ += length; 7430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun return value; 7530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun} 7630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun 7730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurunint32_t FileInputStream::Read(ByteVector* b) { 7830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun return Read(b, 0, b->size()); 7930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun} 8030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun 8130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurunint32_t FileInputStream::Read(ByteVector* b, int32_t offset, int32_t length) { 8230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun assert(b); 8330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun if (!file_) { 8430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun#if !defined (SFNTLY_NO_EXCEPTION) 8530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun throw IOException("no opened file"); 8630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun#endif 8730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun return 0; 8830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun } 8930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun if (feof(file_)) { 9030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun#if !defined (SFNTLY_NO_EXCEPTION) 9130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun throw IOException("eof reached"); 9230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun#endif 9330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun return 0; 9430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun } 9530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun size_t read_count = std::min<size_t>(length_ - position_, length); 9630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun if (b->size() < (size_t)(offset + read_count)) { 9730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun b->resize((size_t)(offset + read_count)); 9830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun } 9930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun int32_t actual_read = fread(&((*b)[offset]), 1, read_count, file_); 10030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun position_ += actual_read; 10130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun return actual_read; 10230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun} 10330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun 10430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurunvoid FileInputStream::Reset() { 10530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun // NOP 10630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun} 10730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun 10830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurunint64_t FileInputStream::Skip(int64_t n) { 10930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun if (!file_) { 11030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun#if !defined (SFNTLY_NO_EXCEPTION) 11130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun throw IOException("no opened file"); 11230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun#endif 11330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun return 0; 11430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun } 11530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun int64_t skip_count = 0; 11630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun if (n < 0) { // move backwards 11730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun skip_count = std::max<int64_t>(0 - (int64_t)position_, n); 11830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun position_ -= (size_t)(0 - skip_count); 11930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun fseek(file_, position_, SEEK_SET); 12030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun } else { 12130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun skip_count = std::min<size_t>(length_ - position_, (size_t)n); 12230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun position_ += (size_t)skip_count; 12330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun fseek(file_, (size_t)skip_count, SEEK_CUR); 12430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun } 12530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun return skip_count; 12630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun} 12730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun 12830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurunvoid FileInputStream::Unread(ByteVector* b) { 12930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun Unread(b, 0, b->size()); 13030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun} 13130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun 13230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurunvoid FileInputStream::Unread(ByteVector* b, int32_t offset, int32_t length) { 13330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun assert(b); 13430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun assert(b->size() >= size_t(offset + length)); 13530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun if (!file_) { 13630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun#if !defined (SFNTLY_NO_EXCEPTION) 13730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun throw IOException("no opened file"); 13830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun#endif 13930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun return; 14030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun } 14130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun size_t unread_count = std::min<size_t>(position_, length); 14230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun fseek(file_, position_ - unread_count, SEEK_SET); 14330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun position_ -= unread_count; 14430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun Read(b, offset, length); 14530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun fseek(file_, position_ - unread_count, SEEK_SET); 14630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun position_ -= unread_count; 14730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun} 14830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun 14930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurunbool FileInputStream::Open(const char* file_path) { 15030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun assert(file_path); 15130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun if (file_) { 15230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun Close(); 15330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun } 15430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun#if defined (WIN32) 15530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun fopen_s(&file_, file_path, "rb"); 15630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun#else 15730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun file_ = fopen(file_path, "rb"); 15830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun#endif 15930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun if (file_ == NULL) { 16030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun return false; 16130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun } 16230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun 16330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun fseek(file_, 0, SEEK_END); 16430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun length_ = ftell(file_); 16530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun fseek(file_, 0, SEEK_SET); 16630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun return true; 16730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun} 16830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun 16930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun} // namespace sfntly 170