Home | History | Annotate | Download | only in port
      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 
     28 FileInputStream::FileInputStream()
     29     : file_(NULL),
     30       position_(0),
     31       length_(0) {
     32 }
     33 
     34 FileInputStream::~FileInputStream() {
     35   Close();
     36 }
     37 
     38 int32_t FileInputStream::Available() {
     39   return length_ - position_;
     40 }
     41 
     42 void FileInputStream::Close() {
     43   if (file_) {
     44     fclose(file_);
     45     length_ = 0;
     46     position_ = 0;
     47     file_ = NULL;
     48   }
     49 }
     50 
     51 void FileInputStream::Mark(int32_t readlimit) {
     52   // NOP
     53   UNREFERENCED_PARAMETER(readlimit);
     54 }
     55 
     56 bool FileInputStream::MarkSupported() {
     57   return false;
     58 }
     59 
     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 
     79 int32_t FileInputStream::Read(ByteVector* b) {
     80   return Read(b, 0, b->size());
     81 }
     82 
     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 
    106 void FileInputStream::Reset() {
    107   // NOP
    108 }
    109 
    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 
    130 void FileInputStream::Unread(ByteVector* b) {
    131   Unread(b, 0, b->size());
    132 }
    133 
    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 
    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