1464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com/*
2464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com * Copyright 2011 Google Inc. All Rights Reserved.
3464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com *
4464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com * Licensed under the Apache License, Version 2.0 (the "License");
5464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com * you may not use this file except in compliance with the License.
6464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com * You may obtain a copy of the License at
7464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com *
8464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com *      http://www.apache.org/licenses/LICENSE-2.0
9464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com *
10464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com * Unless required by applicable law or agreed to in writing, software
11464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com * distributed under the License is distributed on an "AS IS" BASIS,
12464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com * See the License for the specific language governing permissions and
14464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com * limitations under the License.
15464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com */
16464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com
17464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com#if defined (WIN32)
18464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com#include <windows.h>
19464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com#endif
20464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com
218f090032dd4f8f8908f338cc73bb840b788377f2stuartg@google.com#include <algorithm>
228f090032dd4f8f8908f338cc73bb840b788377f2stuartg@google.com
23464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com#include "sfntly/port/file_input_stream.h"
24464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com#include "sfntly/port/exception_type.h"
25464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com
26464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.comnamespace sfntly {
27464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com
28246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.comFileInputStream::FileInputStream()
29246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com    : file_(NULL),
30246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com      position_(0),
31246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com      length_(0) {
32464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com}
33464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com
34464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.comFileInputStream::~FileInputStream() {
35246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com  Close();
36464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com}
37464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com
38246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.comint32_t FileInputStream::Available() {
39464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com  return length_ - position_;
40464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com}
41464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com
42246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.comvoid FileInputStream::Close() {
43464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com  if (file_) {
44464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com    fclose(file_);
45464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com    length_ = 0;
46464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com    position_ = 0;
472aa6d0f9873471e25e471f778153eec1001e42e0arthurhsu@google.com    file_ = NULL;
48464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com  }
49464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com}
50464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com
51246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.comvoid FileInputStream::Mark(int32_t readlimit) {
52464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com  // NOP
53464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com  UNREFERENCED_PARAMETER(readlimit);
54464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com}
55464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com
56246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.combool FileInputStream::MarkSupported() {
57464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com  return false;
58464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com}
59464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com
60246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.comint32_t FileInputStream::Read() {
61464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com  if (!file_) {
62b54cce09c1fc2b09e2adae43d7eb017b47b0cccfarthurhsu@google.com#if !defined (SFNTLY_NO_EXCEPTION)
63464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com    throw IOException("no opened file");
640e411afcef9fc211b3f8f70d31bc1dfa4c0f85d3arthurhsu@google.com#endif
65b54cce09c1fc2b09e2adae43d7eb017b47b0cccfarthurhsu@google.com    return 0;
66464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com  }
67464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com  if (feof(file_)) {
68b54cce09c1fc2b09e2adae43d7eb017b47b0cccfarthurhsu@google.com#if !defined (SFNTLY_NO_EXCEPTION)
69464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com    throw IOException("eof reached");
700e411afcef9fc211b3f8f70d31bc1dfa4c0f85d3arthurhsu@google.com#endif
71b54cce09c1fc2b09e2adae43d7eb017b47b0cccfarthurhsu@google.com    return 0;
72464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com  }
73464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com  byte_t value;
7435a9bf28a889295528bfe46ab51902a460be5407arthurhsu@google.com  size_t length = fread(&value, 1, 1, file_);
7535a9bf28a889295528bfe46ab51902a460be5407arthurhsu@google.com  position_ += length;
76464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com  return value;
77464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com}
78464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com
79246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.comint32_t FileInputStream::Read(ByteVector* b) {
80b54cce09c1fc2b09e2adae43d7eb017b47b0cccfarthurhsu@google.com  return Read(b, 0, b->size());
81464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com}
82464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com
83246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.comint32_t FileInputStream::Read(ByteVector* b, int32_t offset, int32_t length) {
84464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com  assert(b);
85464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com  if (!file_) {
86b54cce09c1fc2b09e2adae43d7eb017b47b0cccfarthurhsu@google.com#if !defined (SFNTLY_NO_EXCEPTION)
87464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com    throw IOException("no opened file");
880e411afcef9fc211b3f8f70d31bc1dfa4c0f85d3arthurhsu@google.com#endif
89b54cce09c1fc2b09e2adae43d7eb017b47b0cccfarthurhsu@google.com    return 0;
90464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com  }
91464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com  if (feof(file_)) {
92b54cce09c1fc2b09e2adae43d7eb017b47b0cccfarthurhsu@google.com#if !defined (SFNTLY_NO_EXCEPTION)
93464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com    throw IOException("eof reached");
940e411afcef9fc211b3f8f70d31bc1dfa4c0f85d3arthurhsu@google.com#endif
95b54cce09c1fc2b09e2adae43d7eb017b47b0cccfarthurhsu@google.com    return 0;
96464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com  }
97464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com  size_t read_count = std::min<size_t>(length_ - position_, length);
982aa6d0f9873471e25e471f778153eec1001e42e0arthurhsu@google.com  if (b->size() < (size_t)(offset + read_count)) {
992aa6d0f9873471e25e471f778153eec1001e42e0arthurhsu@google.com    b->resize((size_t)(offset + read_count));
1002aa6d0f9873471e25e471f778153eec1001e42e0arthurhsu@google.com  }
101464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com  int32_t actual_read = fread(&((*b)[offset]), 1, read_count, file_);
102464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com  position_ += actual_read;
103464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com  return actual_read;
104464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com}
105464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com
106246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.comvoid FileInputStream::Reset() {
107464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com  // NOP
108464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com}
109464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com
110246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.comint64_t FileInputStream::Skip(int64_t n) {
111464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com  if (!file_) {
112b54cce09c1fc2b09e2adae43d7eb017b47b0cccfarthurhsu@google.com#if !defined (SFNTLY_NO_EXCEPTION)
113464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com    throw IOException("no opened file");
1140e411afcef9fc211b3f8f70d31bc1dfa4c0f85d3arthurhsu@google.com#endif
115b54cce09c1fc2b09e2adae43d7eb017b47b0cccfarthurhsu@google.com    return 0;
116464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com  }
1172aa6d0f9873471e25e471f778153eec1001e42e0arthurhsu@google.com  int64_t skip_count = 0;
1182aa6d0f9873471e25e471f778153eec1001e42e0arthurhsu@google.com  if (n < 0) {  // move backwards
1192aa6d0f9873471e25e471f778153eec1001e42e0arthurhsu@google.com    skip_count = std::max<int64_t>(0 - (int64_t)position_, n);
1202aa6d0f9873471e25e471f778153eec1001e42e0arthurhsu@google.com    position_ -= (size_t)(0 - skip_count);
1212aa6d0f9873471e25e471f778153eec1001e42e0arthurhsu@google.com    fseek(file_, position_, SEEK_SET);
1222aa6d0f9873471e25e471f778153eec1001e42e0arthurhsu@google.com  } else {
1232aa6d0f9873471e25e471f778153eec1001e42e0arthurhsu@google.com    skip_count = std::min<size_t>(length_ - position_, (size_t)n);
1242aa6d0f9873471e25e471f778153eec1001e42e0arthurhsu@google.com    position_ += (size_t)skip_count;
1252aa6d0f9873471e25e471f778153eec1001e42e0arthurhsu@google.com    fseek(file_, (size_t)skip_count, SEEK_CUR);
126464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com  }
127464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com  return skip_count;
128464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com}
129464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com
130246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.comvoid FileInputStream::Unread(ByteVector* b) {
131b54cce09c1fc2b09e2adae43d7eb017b47b0cccfarthurhsu@google.com  Unread(b, 0, b->size());
132464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com}
133464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com
134246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.comvoid FileInputStream::Unread(ByteVector* b, int32_t offset, int32_t length) {
135464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com  assert(b);
136464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com  assert(b->size() >= size_t(offset + length));
137464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com  if (!file_) {
138b54cce09c1fc2b09e2adae43d7eb017b47b0cccfarthurhsu@google.com#if !defined (SFNTLY_NO_EXCEPTION)
139464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com    throw IOException("no opened file");
1400e411afcef9fc211b3f8f70d31bc1dfa4c0f85d3arthurhsu@google.com#endif
141b54cce09c1fc2b09e2adae43d7eb017b47b0cccfarthurhsu@google.com    return;
142464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com  }
143464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com  size_t unread_count = std::min<size_t>(position_, length);
144464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com  fseek(file_, position_ - unread_count, SEEK_SET);
1452aa6d0f9873471e25e471f778153eec1001e42e0arthurhsu@google.com  position_ -= unread_count;
146246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com  Read(b, offset, length);
147464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com  fseek(file_, position_ - unread_count, SEEK_SET);
1482aa6d0f9873471e25e471f778153eec1001e42e0arthurhsu@google.com  position_ -= unread_count;
149464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com}
150464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com
151246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.combool FileInputStream::Open(const char* file_path) {
152246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com  assert(file_path);
153246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com  if (file_) {
154246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com    Close();
155246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com  }
156246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com#if defined (WIN32)
157246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com  fopen_s(&file_, file_path, "rb");
158246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com#else
159246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com  file_ = fopen(file_path, "rb");
160246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com#endif
161246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com  if (file_ == NULL) {
162246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com    return false;
163246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com  }
164246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com
165246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com  fseek(file_, 0, SEEK_END);
166246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com  length_ = ftell(file_);
167246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com  fseek(file_, 0, SEEK_SET);
168246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com  return true;
169246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com}
170246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com
171464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com}  // namespace sfntly
172