1/* 2 * Copyright 2011 Google Inc. All Rights Reserved. 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17#if defined (WIN32) 18#include <windows.h> 19#endif 20 21#include <algorithm> 22 23#include "sfntly/port/file_input_stream.h" 24#include "sfntly/port/exception_type.h" 25 26namespace sfntly { 27 28FileInputStream::FileInputStream() 29 : file_(NULL), 30 position_(0), 31 length_(0) { 32} 33 34FileInputStream::~FileInputStream() { 35 Close(); 36} 37 38int32_t FileInputStream::Available() { 39 return length_ - position_; 40} 41 42void FileInputStream::Close() { 43 if (file_) { 44 fclose(file_); 45 length_ = 0; 46 position_ = 0; 47 file_ = NULL; 48 } 49} 50 51void FileInputStream::Mark(int32_t readlimit) { 52 // NOP 53 UNREFERENCED_PARAMETER(readlimit); 54} 55 56bool FileInputStream::MarkSupported() { 57 return false; 58} 59 60int32_t FileInputStream::Read() { 61 if (!file_) { 62#if !defined (SFNTLY_NO_EXCEPTION) 63 throw IOException("no opened file"); 64#endif 65 return 0; 66 } 67 if (feof(file_)) { 68#if !defined (SFNTLY_NO_EXCEPTION) 69 throw IOException("eof reached"); 70#endif 71 return 0; 72 } 73 byte_t value; 74 size_t length = fread(&value, 1, 1, file_); 75 position_ += length; 76 return value; 77} 78 79int32_t FileInputStream::Read(ByteVector* b) { 80 return Read(b, 0, b->size()); 81} 82 83int32_t FileInputStream::Read(ByteVector* b, int32_t offset, int32_t length) { 84 assert(b); 85 if (!file_) { 86#if !defined (SFNTLY_NO_EXCEPTION) 87 throw IOException("no opened file"); 88#endif 89 return 0; 90 } 91 if (feof(file_)) { 92#if !defined (SFNTLY_NO_EXCEPTION) 93 throw IOException("eof reached"); 94#endif 95 return 0; 96 } 97 size_t read_count = std::min<size_t>(length_ - position_, length); 98 if (b->size() < (size_t)(offset + read_count)) { 99 b->resize((size_t)(offset + read_count)); 100 } 101 int32_t actual_read = fread(&((*b)[offset]), 1, read_count, file_); 102 position_ += actual_read; 103 return actual_read; 104} 105 106void FileInputStream::Reset() { 107 // NOP 108} 109 110int64_t FileInputStream::Skip(int64_t n) { 111 if (!file_) { 112#if !defined (SFNTLY_NO_EXCEPTION) 113 throw IOException("no opened file"); 114#endif 115 return 0; 116 } 117 int64_t skip_count = 0; 118 if (n < 0) { // move backwards 119 skip_count = std::max<int64_t>(0 - (int64_t)position_, n); 120 position_ -= (size_t)(0 - skip_count); 121 fseek(file_, position_, SEEK_SET); 122 } else { 123 skip_count = std::min<size_t>(length_ - position_, (size_t)n); 124 position_ += (size_t)skip_count; 125 fseek(file_, (size_t)skip_count, SEEK_CUR); 126 } 127 return skip_count; 128} 129 130void FileInputStream::Unread(ByteVector* b) { 131 Unread(b, 0, b->size()); 132} 133 134void FileInputStream::Unread(ByteVector* b, int32_t offset, int32_t length) { 135 assert(b); 136 assert(b->size() >= size_t(offset + length)); 137 if (!file_) { 138#if !defined (SFNTLY_NO_EXCEPTION) 139 throw IOException("no opened file"); 140#endif 141 return; 142 } 143 size_t unread_count = std::min<size_t>(position_, length); 144 fseek(file_, position_ - unread_count, SEEK_SET); 145 position_ -= unread_count; 146 Read(b, offset, length); 147 fseek(file_, position_ - unread_count, SEEK_SET); 148 position_ -= unread_count; 149} 150 151bool FileInputStream::Open(const char* file_path) { 152 assert(file_path); 153 if (file_) { 154 Close(); 155 } 156#if defined (WIN32) 157 fopen_s(&file_, file_path, "rb"); 158#else 159 file_ = fopen(file_path, "rb"); 160#endif 161 if (file_ == NULL) { 162 return false; 163 } 164 165 fseek(file_, 0, SEEK_END); 166 length_ = ftell(file_); 167 fseek(file_, 0, SEEK_SET); 168 return true; 169} 170 171} // namespace sfntly 172