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
17246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com#include "sfntly/data/byte_array.h"
18246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com
19464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com#include <algorithm>
20464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com
21464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com#include "sfntly/port/exception_type.h"
22464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com
23464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.comnamespace sfntly {
24464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com
25464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.comconst int32_t ByteArray::COPY_BUFFER_SIZE = 8192;
26464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com
27464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.comByteArray::~ByteArray() {}
28464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com
29246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.comint32_t ByteArray::Length() { return filled_length_; }
30246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.comint32_t ByteArray::Size() { return storage_length_; }
31464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com
32246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.comint32_t ByteArray::SetFilledLength(int32_t filled_length) {
33464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com  filled_length_ = std::min<int32_t>(filled_length, storage_length_);
34464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com  return filled_length_;
35464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com}
36464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com
3732a01c7c6e7be46dda9bfc78de9ce32d99e4c8b7arthurhsu@google.comint32_t ByteArray::Get(int32_t index) {
3832a01c7c6e7be46dda9bfc78de9ce32d99e4c8b7arthurhsu@google.com  return InternalGet(index) & 0xff;
39464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com}
40464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com
41246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.comint32_t ByteArray::Get(int32_t index, ByteVector* b) {
42464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com  assert(b);
4332a01c7c6e7be46dda9bfc78de9ce32d99e4c8b7arthurhsu@google.com  return Get(index, &((*b)[0]), 0, b->size());
44464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com}
45464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com
46246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.comint32_t ByteArray::Get(int32_t index,
4732a01c7c6e7be46dda9bfc78de9ce32d99e4c8b7arthurhsu@google.com                       byte_t* b,
48246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com                       int32_t offset,
49464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com                       int32_t length) {
50464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com  assert(b);
51464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com  if (index < 0 || index >= filled_length_) {
5232a01c7c6e7be46dda9bfc78de9ce32d99e4c8b7arthurhsu@google.com    return 0;
53464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com  }
54464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com  int32_t actual_length = std::min<int32_t>(length, filled_length_ - index);
55246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com  return InternalGet(index, b, offset, actual_length);
56464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com}
57464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com
5832a01c7c6e7be46dda9bfc78de9ce32d99e4c8b7arthurhsu@google.comvoid ByteArray::Put(int32_t index, byte_t b) {
59246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com  if (index < 0 || index >= Size()) {
6032a01c7c6e7be46dda9bfc78de9ce32d99e4c8b7arthurhsu@google.com#if defined (SFNTLY_NO_EXCEPTION)
6132a01c7c6e7be46dda9bfc78de9ce32d99e4c8b7arthurhsu@google.com    return;
6232a01c7c6e7be46dda9bfc78de9ce32d99e4c8b7arthurhsu@google.com#else
6332a01c7c6e7be46dda9bfc78de9ce32d99e4c8b7arthurhsu@google.com    throw IndexOutOfBoundException(
6432a01c7c6e7be46dda9bfc78de9ce32d99e4c8b7arthurhsu@google.com        "Attempt to write outside the bounds of the data");
6532a01c7c6e7be46dda9bfc78de9ce32d99e4c8b7arthurhsu@google.com#endif
66464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com  }
6732a01c7c6e7be46dda9bfc78de9ce32d99e4c8b7arthurhsu@google.com  InternalPut(index, b);
68464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com  filled_length_ = std::max<int32_t>(filled_length_, index + 1);
69464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com}
70464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com
71246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.comint32_t ByteArray::Put(int index, ByteVector* b) {
72464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com  assert(b);
7332a01c7c6e7be46dda9bfc78de9ce32d99e4c8b7arthurhsu@google.com  return Put(index, &((*b)[0]), 0, b->size());
74464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com}
75464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com
76246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.comint32_t ByteArray::Put(int32_t index,
7732a01c7c6e7be46dda9bfc78de9ce32d99e4c8b7arthurhsu@google.com                       byte_t* b,
78246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com                       int32_t offset,
79464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com                       int32_t length) {
80464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com  assert(b);
81246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com  if (index < 0 || index >= Size()) {
8232a01c7c6e7be46dda9bfc78de9ce32d99e4c8b7arthurhsu@google.com#if defined (SFNTLY_NO_EXCEPTION)
83464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com    return 0;
8432a01c7c6e7be46dda9bfc78de9ce32d99e4c8b7arthurhsu@google.com#else
8532a01c7c6e7be46dda9bfc78de9ce32d99e4c8b7arthurhsu@google.com    throw IndexOutOfBoundException(
8632a01c7c6e7be46dda9bfc78de9ce32d99e4c8b7arthurhsu@google.com        "Attempt to write outside the bounds of the data");
8732a01c7c6e7be46dda9bfc78de9ce32d99e4c8b7arthurhsu@google.com#endif
88464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com  }
89246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com  int32_t actual_length = std::min<int32_t>(length, Size() - index);
90246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com  int32_t bytes_written = InternalPut(index, b, offset, actual_length);
91464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com  filled_length_ = std::max<int32_t>(filled_length_, index + bytes_written);
92464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com  return bytes_written;
93464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com}
94464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com
95246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.comint32_t ByteArray::CopyTo(ByteArray* array) {
96246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com  return CopyTo(array, 0, Length());
97464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com}
98464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com
99246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.comint32_t ByteArray::CopyTo(ByteArray* array, int32_t offset, int32_t length) {
100246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com  return CopyTo(0, array, offset, length);
101464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com}
102464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com
103246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.comint32_t ByteArray::CopyTo(int32_t dst_offset, ByteArray* array,
104464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com                          int32_t src_offset, int32_t length) {
105464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com  assert(array);
106246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com  if (array->Size() < dst_offset + length) {  // insufficient space
107464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com    return -1;
108464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com  }
109464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com
110464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com  ByteVector b(COPY_BUFFER_SIZE);
111464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com  int32_t bytes_read = 0;
112464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com  int32_t index = 0;
113464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com  int32_t remaining_length = length;
114464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com  int32_t buffer_length = std::min<int32_t>(COPY_BUFFER_SIZE, length);
11532a01c7c6e7be46dda9bfc78de9ce32d99e4c8b7arthurhsu@google.com  while ((bytes_read =
11632a01c7c6e7be46dda9bfc78de9ce32d99e4c8b7arthurhsu@google.com              Get(index + src_offset, &(b[0]), 0, buffer_length)) > 0) {
11732a01c7c6e7be46dda9bfc78de9ce32d99e4c8b7arthurhsu@google.com    int bytes_written = array->Put(index + dst_offset, &(b[0]), 0, bytes_read);
118333edd91cb32d6acfd0307ba2ae8f60baed75ff4arthurhsu@google.com    UNREFERENCED_PARAMETER(bytes_written);
119464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com    index += bytes_read;
120464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com    remaining_length -= bytes_read;
121464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com    buffer_length = std::min<int32_t>(b.size(), remaining_length);
122464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com  }
123464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com  return index;
124464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com}
125464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com
126246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.comint32_t ByteArray::CopyTo(OutputStream* os) {
127246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com    return CopyTo(os, 0, Length());
128464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com}
129464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com
130246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.comint32_t ByteArray::CopyTo(OutputStream* os, int32_t offset, int32_t length) {
131464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com  ByteVector b(COPY_BUFFER_SIZE);
132464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com  int32_t bytes_read = 0;
133ed8406cf320973d04bbe348c681090b1feba3d68arthurhsu@google.com  int32_t index = 0;
134464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com  int32_t buffer_length = std::min<int32_t>(COPY_BUFFER_SIZE, length);
13532a01c7c6e7be46dda9bfc78de9ce32d99e4c8b7arthurhsu@google.com  while ((bytes_read = Get(index + offset, &(b[0]), 0, buffer_length)) > 0) {
136246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com    os->Write(&b, 0, bytes_read);
137464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com    index += bytes_read;
138464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com    buffer_length = std::min<int32_t>(b.size(), length - index);
139464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com  }
140464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com  return index;
141464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com}
142464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com
143246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.combool ByteArray::CopyFrom(InputStream* is, int32_t length) {
144464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com  ByteVector b(COPY_BUFFER_SIZE);
145464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com  int32_t bytes_read = 0;
146464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com  int32_t index = 0;
147464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com  int32_t buffer_length = std::min<int32_t>(COPY_BUFFER_SIZE, length);
148246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com  while ((bytes_read = is->Read(&b, 0, buffer_length)) > 0) {
14932a01c7c6e7be46dda9bfc78de9ce32d99e4c8b7arthurhsu@google.com    if (Put(index, &(b[0]), 0, bytes_read) != bytes_read) {
1500e411afcef9fc211b3f8f70d31bc1dfa4c0f85d3arthurhsu@google.com#if defined (SFNTLY_NO_EXCEPTION)
1510e411afcef9fc211b3f8f70d31bc1dfa4c0f85d3arthurhsu@google.com      return 0;
1520e411afcef9fc211b3f8f70d31bc1dfa4c0f85d3arthurhsu@google.com#else
153464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com      throw IOException("Error writing bytes.");
1540e411afcef9fc211b3f8f70d31bc1dfa4c0f85d3arthurhsu@google.com#endif
155464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com    }
156464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com    index += bytes_read;
157464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com    length -= bytes_read;
158464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com    buffer_length = std::min<int32_t>(b.size(), length);
159464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com  }
160464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com  return true;
161464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com}
162464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com
163246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.combool ByteArray::CopyFrom(InputStream* is) {
164464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com  ByteVector b(COPY_BUFFER_SIZE);
165464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com  int32_t bytes_read = 0;
166464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com  int32_t index = 0;
167464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com  int32_t buffer_length = COPY_BUFFER_SIZE;
168246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com  while ((bytes_read = is->Read(&b, 0, buffer_length)) > 0) {
16932a01c7c6e7be46dda9bfc78de9ce32d99e4c8b7arthurhsu@google.com    if (Put(index, &b[0], 0, bytes_read) != bytes_read) {
1700e411afcef9fc211b3f8f70d31bc1dfa4c0f85d3arthurhsu@google.com#if defined (SFNTLY_NO_EXCEPTION)
1710e411afcef9fc211b3f8f70d31bc1dfa4c0f85d3arthurhsu@google.com      return 0;
1720e411afcef9fc211b3f8f70d31bc1dfa4c0f85d3arthurhsu@google.com#else
173464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com      throw IOException("Error writing bytes.");
1740e411afcef9fc211b3f8f70d31bc1dfa4c0f85d3arthurhsu@google.com#endif
175464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com    }
176464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com    index += bytes_read;
177464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com  }
178464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com  return true;
179464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com}
180464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com
181246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.comByteArray::ByteArray(int32_t filled_length,
182246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com                     int32_t storage_length,
183246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com                     bool growable) {
184246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com  Init(filled_length, storage_length, growable);
185246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com}
186246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com
187246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.comByteArray::ByteArray(int32_t filled_length, int32_t storage_length) {
188246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com  Init(filled_length, storage_length, false);
189246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com}
190246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com
191246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.comvoid ByteArray::Init(int32_t filled_length,
192246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com                     int32_t storage_length,
193246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com                     bool growable) {
194246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com  storage_length_ = storage_length;
195246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com  growable_ = growable;
196246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com  SetFilledLength(filled_length);
197246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com}
198246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com
199464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com}  // namespace sfntly
200