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