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
24 namespace sfntly {
25
FileInputStream()26 FileInputStream::FileInputStream()
27 : file_(NULL),
28 position_(0),
29 length_(0) {
30 }
31
~FileInputStream()32 FileInputStream::~FileInputStream() {
33 Close();
34 }
35
Available()36 int32_t FileInputStream::Available() {
37 return length_ - position_;
38 }
39
Close()40 void FileInputStream::Close() {
41 if (file_) {
42 fclose(file_);
43 length_ = 0;
44 position_ = 0;
45 file_ = NULL;
46 }
47 }
48
Mark(int32_t readlimit)49 void FileInputStream::Mark(int32_t readlimit) {
50 // NOP
51 UNREFERENCED_PARAMETER(readlimit);
52 }
53
MarkSupported()54 bool FileInputStream::MarkSupported() {
55 return false;
56 }
57
Read()58 int32_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
Read(ByteVector * b)77 int32_t FileInputStream::Read(ByteVector* b) {
78 return Read(b, 0, b->size());
79 }
80
Read(ByteVector * b,int32_t offset,int32_t length)81 int32_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
Reset()104 void FileInputStream::Reset() {
105 // NOP
106 }
107
Skip(int64_t n)108 int64_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
Unread(ByteVector * b)128 void FileInputStream::Unread(ByteVector* b) {
129 Unread(b, 0, b->size());
130 }
131
Unread(ByteVector * b,int32_t offset,int32_t length)132 void 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
Open(const char * file_path)149 bool 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