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 #include "sfntly/data/byte_array.h"
18 
19 #include <algorithm>
20 
21 #include "sfntly/port/exception_type.h"
22 
23 namespace sfntly {
24 
25 const int32_t ByteArray::COPY_BUFFER_SIZE = 8192;
26 
~ByteArray()27 ByteArray::~ByteArray() {}
28 
SetFilledLength(int32_t filled_length)29 int32_t ByteArray::SetFilledLength(int32_t filled_length) {
30   filled_length_ = std::min<int32_t>(filled_length, storage_length_);
31   return filled_length_;
32 }
33 
Get(int32_t index)34 int32_t ByteArray::Get(int32_t index) {
35   if (index < 0 || index >= Length())
36     return -1;
37   return InternalGet(index) & 0xff;
38 }
39 
Get(int32_t index,std::vector<uint8_t> * b)40 int32_t ByteArray::Get(int32_t index, std::vector<uint8_t>* b) {
41   assert(b);
42   return Get(index, &((*b)[0]), 0, b->size());
43 }
44 
Get(int32_t index,uint8_t * b,int32_t offset,int32_t length)45 int32_t ByteArray::Get(int32_t index,
46                        uint8_t* b,
47                        int32_t offset,
48                        int32_t length) {
49   assert(b);
50   if (index < 0 || index >= filled_length_)
51     return 0;
52 
53   if (length <= 0)
54     return 0;
55 
56   int32_t actual_length = std::min<int32_t>(length, filled_length_ - index);
57   return InternalGet(index, b, offset, actual_length);
58 }
59 
Put(int32_t index,uint8_t b)60 void ByteArray::Put(int32_t index, uint8_t b) {
61   if (index < 0 || index >= Size()) {
62 #if defined (SFNTLY_NO_EXCEPTION)
63     return;
64 #else
65     throw IndexOutOfBoundException(
66         "Attempt to write outside the bounds of the data");
67 #endif
68   }
69   InternalPut(index, b);
70   filled_length_ = std::max<int32_t>(filled_length_, index + 1);
71 }
72 
Put(int index,std::vector<uint8_t> * b)73 int32_t ByteArray::Put(int index, std::vector<uint8_t>* b) {
74   assert(b);
75   return Put(index, &((*b)[0]), 0, b->size());
76 }
77 
Put(int32_t index,uint8_t * b,int32_t offset,int32_t length)78 int32_t ByteArray::Put(int32_t index,
79                        uint8_t* b,
80                        int32_t offset,
81                        int32_t length) {
82   assert(b);
83   if (index < 0 || index >= Size()) {
84 #if defined (SFNTLY_NO_EXCEPTION)
85     return 0;
86 #else
87     throw IndexOutOfBoundException(
88         "Attempt to write outside the bounds of the data");
89 #endif
90   }
91   int32_t actual_length = std::min<int32_t>(length, Size() - index);
92   int32_t bytes_written = InternalPut(index, b, offset, actual_length);
93   filled_length_ = std::max<int32_t>(filled_length_, index + bytes_written);
94   return bytes_written;
95 }
96 
CopyTo(ByteArray * array)97 int32_t ByteArray::CopyTo(ByteArray* array) {
98   return CopyTo(array, 0, Length());
99 }
100 
CopyTo(ByteArray * array,int32_t offset,int32_t length)101 int32_t ByteArray::CopyTo(ByteArray* array, int32_t offset, int32_t length) {
102   return CopyTo(0, array, offset, length);
103 }
104 
CopyTo(int32_t dst_offset,ByteArray * array,int32_t src_offset,int32_t length)105 int32_t ByteArray::CopyTo(int32_t dst_offset, ByteArray* array,
106                           int32_t src_offset, int32_t length) {
107   assert(array);
108   if (array->Size() < dst_offset + length) {  // insufficient space
109     return -1;
110   }
111 
112   std::vector<uint8_t> b(COPY_BUFFER_SIZE);
113   int32_t bytes_read = 0;
114   int32_t index = 0;
115   int32_t remaining_length = length;
116   int32_t buffer_length = std::min<int32_t>(COPY_BUFFER_SIZE, length);
117   while ((bytes_read =
118               Get(index + src_offset, &(b[0]), 0, buffer_length)) > 0) {
119     int bytes_written = array->Put(index + dst_offset, &(b[0]), 0, bytes_read);
120     UNREFERENCED_PARAMETER(bytes_written);
121     index += bytes_read;
122     remaining_length -= bytes_read;
123     buffer_length = std::min<int32_t>(b.size(), remaining_length);
124   }
125   return index;
126 }
127 
CopyTo(OutputStream * os)128 int32_t ByteArray::CopyTo(OutputStream* os) {
129     return CopyTo(os, 0, Length());
130 }
131 
CopyTo(OutputStream * os,int32_t offset,int32_t length)132 int32_t ByteArray::CopyTo(OutputStream* os, int32_t offset, int32_t length) {
133   std::vector<uint8_t> b(COPY_BUFFER_SIZE);
134   int32_t bytes_read = 0;
135   int32_t index = 0;
136   int32_t buffer_length = std::min<int32_t>(COPY_BUFFER_SIZE, length);
137   while ((bytes_read = Get(index + offset, &(b[0]), 0, buffer_length)) > 0) {
138     os->Write(&b, 0, bytes_read);
139     index += bytes_read;
140     buffer_length = std::min<int32_t>(b.size(), length - index);
141   }
142   return index;
143 }
144 
CopyFrom(InputStream * is,int32_t length)145 bool ByteArray::CopyFrom(InputStream* is, int32_t length) {
146   std::vector<uint8_t> b(COPY_BUFFER_SIZE);
147   int32_t bytes_read = 0;
148   int32_t index = 0;
149   int32_t buffer_length = std::min<int32_t>(COPY_BUFFER_SIZE, length);
150   while ((bytes_read = is->Read(&b, 0, buffer_length)) > 0) {
151     if (Put(index, &(b[0]), 0, bytes_read) != bytes_read) {
152 #if defined (SFNTLY_NO_EXCEPTION)
153       return 0;
154 #else
155       throw IOException("Error writing bytes.");
156 #endif
157     }
158     index += bytes_read;
159     length -= bytes_read;
160     buffer_length = std::min<int32_t>(b.size(), length);
161   }
162   return true;
163 }
164 
CopyFrom(InputStream * is)165 bool ByteArray::CopyFrom(InputStream* is) {
166   std::vector<uint8_t> b(COPY_BUFFER_SIZE);
167   int32_t bytes_read = 0;
168   int32_t index = 0;
169   int32_t buffer_length = COPY_BUFFER_SIZE;
170   while ((bytes_read = is->Read(&b, 0, buffer_length)) > 0) {
171     if (Put(index, &b[0], 0, bytes_read) != bytes_read) {
172 #if defined (SFNTLY_NO_EXCEPTION)
173       return 0;
174 #else
175       throw IOException("Error writing bytes.");
176 #endif
177     }
178     index += bytes_read;
179   }
180   return true;
181 }
182 
ByteArray(int32_t filled_length,int32_t storage_length,bool growable)183 ByteArray::ByteArray(int32_t filled_length,
184                      int32_t storage_length,
185                      bool growable) {
186   Init(filled_length, storage_length, growable);
187 }
188 
ByteArray(int32_t filled_length,int32_t storage_length)189 ByteArray::ByteArray(int32_t filled_length, int32_t storage_length) {
190   Init(filled_length, storage_length, false);
191 }
192 
Init(int32_t filled_length,int32_t storage_length,bool growable)193 void ByteArray::Init(int32_t filled_length,
194                      int32_t storage_length,
195                      bool growable) {
196   storage_length_ = storage_length;
197   growable_ = growable;
198   SetFilledLength(filled_length);
199 }
200 
201 }  // namespace sfntly
202