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