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 27 ByteArray::~ByteArray() {} 28 29 int32_t ByteArray::Length() { return filled_length_; } 30 int32_t ByteArray::Size() { return storage_length_; } 31 32 int32_t ByteArray::SetFilledLength(int32_t filled_length) { 33 filled_length_ = std::min<int32_t>(filled_length, storage_length_); 34 return filled_length_; 35 } 36 37 int32_t ByteArray::Get(int32_t index) { 38 if (index < 0 || index >= Length()) 39 return -1; 40 return InternalGet(index) & 0xff; 41 } 42 43 int32_t ByteArray::Get(int32_t index, ByteVector* b) { 44 assert(b); 45 return Get(index, &((*b)[0]), 0, b->size()); 46 } 47 48 int32_t ByteArray::Get(int32_t index, 49 byte_t* b, 50 int32_t offset, 51 int32_t length) { 52 assert(b); 53 if (index < 0 || index >= filled_length_) { 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 60 void ByteArray::Put(int32_t index, byte_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 73 int32_t ByteArray::Put(int index, ByteVector* b) { 74 assert(b); 75 return Put(index, &((*b)[0]), 0, b->size()); 76 } 77 78 int32_t ByteArray::Put(int32_t index, 79 byte_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 97 int32_t ByteArray::CopyTo(ByteArray* array) { 98 return CopyTo(array, 0, Length()); 99 } 100 101 int32_t ByteArray::CopyTo(ByteArray* array, int32_t offset, int32_t length) { 102 return CopyTo(0, array, offset, length); 103 } 104 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 ByteVector 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 128 int32_t ByteArray::CopyTo(OutputStream* os) { 129 return CopyTo(os, 0, Length()); 130 } 131 132 int32_t ByteArray::CopyTo(OutputStream* os, int32_t offset, int32_t length) { 133 ByteVector 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 145 bool ByteArray::CopyFrom(InputStream* is, int32_t length) { 146 ByteVector 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 165 bool ByteArray::CopyFrom(InputStream* is) { 166 ByteVector 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 183 ByteArray::ByteArray(int32_t filled_length, 184 int32_t storage_length, 185 bool growable) { 186 Init(filled_length, storage_length, growable); 187 } 188 189 ByteArray::ByteArray(int32_t filled_length, int32_t storage_length) { 190 Init(filled_length, storage_length, false); 191 } 192 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