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 "sfntly/port/file_input_stream.h" 22#include "sfntly/port/exception_type.h" 23 24namespace sfntly { 25 26FileInputStream::FileInputStream() 27 : file_(NULL), 28 position_(0), 29 length_(0) { 30} 31 32FileInputStream::~FileInputStream() { 33 Close(); 34} 35 36int32_t FileInputStream::Available() { 37 return length_ - position_; 38} 39 40void FileInputStream::Close() { 41 if (file_) { 42 fclose(file_); 43 length_ = 0; 44 position_ = 0; 45 file_ = NULL; 46 } 47} 48 49void FileInputStream::Mark(int32_t readlimit) { 50 // NOP 51 UNREFERENCED_PARAMETER(readlimit); 52} 53 54bool FileInputStream::MarkSupported() { 55 return false; 56} 57 58int32_t FileInputStream::Read() { 59 if (!file_) { 60#if !defined (SFNTLY_NO_EXCEPTION) 61 throw IOException("no opened file"); 62#endif 63 return 0; 64 } 65 if (feof(file_)) { 66#if !defined (SFNTLY_NO_EXCEPTION) 67 throw IOException("eof reached"); 68#endif 69 return 0; 70 } 71 byte_t value; 72 size_t length = fread(&value, 1, 1, file_); 73 position_ += length; 74 return value; 75} 76 77int32_t FileInputStream::Read(ByteVector* b) { 78 return Read(b, 0, b->size()); 79} 80 81int32_t FileInputStream::Read(ByteVector* b, int32_t offset, int32_t length) { 82 assert(b); 83 if (!file_) { 84#if !defined (SFNTLY_NO_EXCEPTION) 85 throw IOException("no opened file"); 86#endif 87 return 0; 88 } 89 if (feof(file_)) { 90#if !defined (SFNTLY_NO_EXCEPTION) 91 throw IOException("eof reached"); 92#endif 93 return 0; 94 } 95 size_t read_count = std::min<size_t>(length_ - position_, length); 96 if (b->size() < (size_t)(offset + read_count)) { 97 b->resize((size_t)(offset + read_count)); 98 } 99 int32_t actual_read = fread(&((*b)[offset]), 1, read_count, file_); 100 position_ += actual_read; 101 return actual_read; 102} 103 104void FileInputStream::Reset() { 105 // NOP 106} 107 108int64_t FileInputStream::Skip(int64_t n) { 109 if (!file_) { 110#if !defined (SFNTLY_NO_EXCEPTION) 111 throw IOException("no opened file"); 112#endif 113 return 0; 114 } 115 int64_t skip_count = 0; 116 if (n < 0) { // move backwards 117 skip_count = std::max<int64_t>(0 - (int64_t)position_, n); 118 position_ -= (size_t)(0 - skip_count); 119 fseek(file_, position_, SEEK_SET); 120 } else { 121 skip_count = std::min<size_t>(length_ - position_, (size_t)n); 122 position_ += (size_t)skip_count; 123 fseek(file_, (size_t)skip_count, SEEK_CUR); 124 } 125 return skip_count; 126} 127 128void FileInputStream::Unread(ByteVector* b) { 129 Unread(b, 0, b->size()); 130} 131 132void FileInputStream::Unread(ByteVector* b, int32_t offset, int32_t length) { 133 assert(b); 134 assert(b->size() >= size_t(offset + length)); 135 if (!file_) { 136#if !defined (SFNTLY_NO_EXCEPTION) 137 throw IOException("no opened file"); 138#endif 139 return; 140 } 141 size_t unread_count = std::min<size_t>(position_, length); 142 fseek(file_, position_ - unread_count, SEEK_SET); 143 position_ -= unread_count; 144 Read(b, offset, length); 145 fseek(file_, position_ - unread_count, SEEK_SET); 146 position_ -= unread_count; 147} 148 149bool FileInputStream::Open(const char* file_path) { 150 assert(file_path); 151 if (file_) { 152 Close(); 153 } 154#if defined (WIN32) 155 fopen_s(&file_, file_path, "rb"); 156#else 157 file_ = fopen(file_path, "rb"); 158#endif 159 if (file_ == NULL) { 160 return false; 161 } 162 163 fseek(file_, 0, SEEK_END); 164 length_ = ftell(file_); 165 fseek(file_, 0, SEEK_SET); 166 return true; 167} 168 169} // namespace sfntly 170