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