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