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 <string.h>
22 
23 #include <algorithm>
24 
25 #include "sfntly/port/memory_input_stream.h"
26 #include "sfntly/port/exception_type.h"
27 
28 namespace sfntly {
29 
MemoryInputStream()30 MemoryInputStream::MemoryInputStream()
31     : buffer_(NULL),
32       position_(0),
33       length_(0) {
34 }
35 
~MemoryInputStream()36 MemoryInputStream::~MemoryInputStream() {
37   Close();
38 }
39 
Length()40 int32_t MemoryInputStream::Length() {
41   return length_;
42 }
43 
Available()44 int32_t MemoryInputStream::Available() {
45   return length_ - position_;
46 }
47 
Close()48 void MemoryInputStream::Close() {
49 }
50 
Mark(int32_t readlimit)51 void MemoryInputStream::Mark(int32_t readlimit) {
52   // NOP
53   UNREFERENCED_PARAMETER(readlimit);
54 }
55 
MarkSupported()56 bool MemoryInputStream::MarkSupported() {
57   return false;
58 }
59 
Read()60 int32_t MemoryInputStream::Read() {
61   if (!buffer_) {
62 #if !defined (SFNTLY_NO_EXCEPTION)
63     throw IOException("no memory attached");
64 #endif
65     return 0;
66   }
67   if (position_ >= length_) {
68 #if !defined (SFNTLY_NO_EXCEPTION)
69     throw IOException("eof reached");
70 #endif
71     return 0;
72   }
73   uint8_t value = buffer_[position_++];
74   return value;
75 }
76 
Read(std::vector<uint8_t> * b)77 int32_t MemoryInputStream::Read(std::vector<uint8_t>* b) {
78   return Read(b, 0, b->size());
79 }
80 
Read(std::vector<uint8_t> * b,int32_t offset,int32_t length)81 int32_t MemoryInputStream::Read(std::vector<uint8_t>* b, int32_t offset, int32_t length) {
82   assert(b);
83   if (!buffer_) {
84 #if !defined (SFNTLY_NO_EXCEPTION)
85     throw IOException("no memory attached");
86 #endif
87     return 0;
88   }
89   if (position_ >= length_) {
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   memcpy(&((*b)[offset]), buffer_ + position_, read_count);
100   position_ += read_count;
101   return read_count;
102 }
103 
Reset()104 void MemoryInputStream::Reset() {
105   // NOP
106 }
107 
Skip(int64_t n)108 int64_t MemoryInputStream::Skip(int64_t n) {
109   if (!buffer_) {
110 #if !defined (SFNTLY_NO_EXCEPTION)
111     throw IOException("no memory attached");
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   } else {
120     skip_count = std::min<size_t>(length_ - position_, (size_t)n);
121     position_ += (size_t)skip_count;
122   }
123   return skip_count;
124 }
125 
Unread(std::vector<uint8_t> * b)126 void MemoryInputStream::Unread(std::vector<uint8_t>* b) {
127   Unread(b, 0, b->size());
128 }
129 
Unread(std::vector<uint8_t> * b,int32_t offset,int32_t length)130 void MemoryInputStream::Unread(std::vector<uint8_t>* b, int32_t offset, int32_t length) {
131   assert(b);
132   assert(b->size() >= size_t(offset + length));
133   if (!buffer_) {
134 #if !defined (SFNTLY_NO_EXCEPTION)
135     throw IOException("no memory attached");
136 #endif
137     return;
138   }
139   size_t unread_count = std::min<size_t>(position_, length);
140   position_ -= unread_count;
141   Read(b, offset, length);
142   position_ -= unread_count;
143 }
144 
Attach(const uint8_t * buffer,size_t length)145 bool MemoryInputStream::Attach(const uint8_t* buffer, size_t length) {
146   assert(buffer);
147   assert(length);
148   buffer_ = buffer;
149   length_ = length;
150   return true;
151 }
152 
153 }  // namespace sfntly
154