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