| OLD | NEW |
| (Empty) | |
| 1 /* |
| 2 * Copyright (C) 2013 The Android Open Source Project |
| 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 "third_party/prediction/suggest/policyimpl/dictionary/utils/buffer_with
_extendable_buffer.h" |
| 18 |
| 19 namespace latinime { |
| 20 |
| 21 const size_t BufferWithExtendableBuffer::DEFAULT_MAX_ADDITIONAL_BUFFER_SIZE = |
| 22 1024 * 1024; |
| 23 const int BufferWithExtendableBuffer::NEAR_BUFFER_LIMIT_THRESHOLD_PERCENTILE = |
| 24 90; |
| 25 // TODO: Needs to allocate larger memory corresponding to the current vector |
| 26 // size. |
| 27 const size_t BufferWithExtendableBuffer::EXTEND_ADDITIONAL_BUFFER_SIZE_STEP = |
| 28 128 * 1024; |
| 29 |
| 30 uint32_t BufferWithExtendableBuffer::readUint(const int size, |
| 31 const int pos) const { |
| 32 const bool readingPosIsInAdditionalBuffer = isInAdditionalBuffer(pos); |
| 33 const int posInBuffer = |
| 34 readingPosIsInAdditionalBuffer ? pos - mOriginalBuffer.size() : pos; |
| 35 return ByteArrayUtils::readUint(getBuffer(readingPosIsInAdditionalBuffer), |
| 36 size, posInBuffer); |
| 37 } |
| 38 |
| 39 uint32_t BufferWithExtendableBuffer::readUintAndAdvancePosition( |
| 40 const int size, |
| 41 int* const pos) const { |
| 42 const int value = readUint(size, *pos); |
| 43 *pos += size; |
| 44 return value; |
| 45 } |
| 46 |
| 47 void BufferWithExtendableBuffer::readCodePointsAndAdvancePosition( |
| 48 const int maxCodePointCount, |
| 49 int* const outCodePoints, |
| 50 int* outCodePointCount, |
| 51 int* const pos) const { |
| 52 const bool readingPosIsInAdditionalBuffer = isInAdditionalBuffer(*pos); |
| 53 if (readingPosIsInAdditionalBuffer) { |
| 54 *pos -= mOriginalBuffer.size(); |
| 55 } |
| 56 *outCodePointCount = ByteArrayUtils::readStringAndAdvancePosition( |
| 57 getBuffer(readingPosIsInAdditionalBuffer), maxCodePointCount, |
| 58 outCodePoints, pos); |
| 59 if (readingPosIsInAdditionalBuffer) { |
| 60 *pos += mOriginalBuffer.size(); |
| 61 } |
| 62 } |
| 63 |
| 64 bool BufferWithExtendableBuffer::extend(const int size) { |
| 65 return checkAndPrepareWriting(getTailPosition(), size); |
| 66 } |
| 67 |
| 68 bool BufferWithExtendableBuffer::writeUint(const uint32_t data, |
| 69 const int size, |
| 70 const int pos) { |
| 71 int writingPos = pos; |
| 72 return writeUintAndAdvancePosition(data, size, &writingPos); |
| 73 } |
| 74 |
| 75 bool BufferWithExtendableBuffer::writeUintAndAdvancePosition( |
| 76 const uint32_t data, |
| 77 const int size, |
| 78 int* const pos) { |
| 79 if (!(size >= 1 && size <= 4)) { |
| 80 AKLOGI("writeUintAndAdvancePosition() is called with invalid size: %d", |
| 81 size); |
| 82 ASSERT(false); |
| 83 return false; |
| 84 } |
| 85 if (!checkAndPrepareWriting(*pos, size)) { |
| 86 return false; |
| 87 } |
| 88 const bool usesAdditionalBuffer = isInAdditionalBuffer(*pos); |
| 89 uint8_t* const buffer = |
| 90 usesAdditionalBuffer ? mAdditionalBuffer.data() : mOriginalBuffer.data(); |
| 91 if (usesAdditionalBuffer) { |
| 92 *pos -= mOriginalBuffer.size(); |
| 93 } |
| 94 ByteArrayUtils::writeUintAndAdvancePosition(buffer, data, size, pos); |
| 95 if (usesAdditionalBuffer) { |
| 96 *pos += mOriginalBuffer.size(); |
| 97 } |
| 98 return true; |
| 99 } |
| 100 |
| 101 bool BufferWithExtendableBuffer::writeCodePointsAndAdvancePosition( |
| 102 const int* const codePoints, |
| 103 const int codePointCount, |
| 104 const bool writesTerminator, |
| 105 int* const pos) { |
| 106 const size_t size = |
| 107 ByteArrayUtils::calculateRequiredByteCountToStoreCodePoints( |
| 108 codePoints, codePointCount, writesTerminator); |
| 109 if (!checkAndPrepareWriting(*pos, size)) { |
| 110 return false; |
| 111 } |
| 112 const bool usesAdditionalBuffer = isInAdditionalBuffer(*pos); |
| 113 uint8_t* const buffer = |
| 114 usesAdditionalBuffer ? mAdditionalBuffer.data() : mOriginalBuffer.data(); |
| 115 if (usesAdditionalBuffer) { |
| 116 *pos -= mOriginalBuffer.size(); |
| 117 } |
| 118 ByteArrayUtils::writeCodePointsAndAdvancePosition( |
| 119 buffer, codePoints, codePointCount, writesTerminator, pos); |
| 120 if (usesAdditionalBuffer) { |
| 121 *pos += mOriginalBuffer.size(); |
| 122 } |
| 123 return true; |
| 124 } |
| 125 |
| 126 bool BufferWithExtendableBuffer::extendBuffer(const size_t size) { |
| 127 const size_t extendSize = std::max(EXTEND_ADDITIONAL_BUFFER_SIZE_STEP, size); |
| 128 const size_t sizeAfterExtending = |
| 129 std::min(mAdditionalBuffer.size() + extendSize, mMaxAdditionalBufferSize); |
| 130 if (sizeAfterExtending < mAdditionalBuffer.size() + size) { |
| 131 return false; |
| 132 } |
| 133 mAdditionalBuffer.resize(sizeAfterExtending); |
| 134 return true; |
| 135 } |
| 136 |
| 137 bool BufferWithExtendableBuffer::checkAndPrepareWriting(const int pos, |
| 138 const int size) { |
| 139 if (pos < 0 || size < 0) { |
| 140 // Invalid position or size. |
| 141 return false; |
| 142 } |
| 143 const size_t totalRequiredSize = static_cast<size_t>(pos + size); |
| 144 if (!isInAdditionalBuffer(pos)) { |
| 145 // Here don't need to care about the additional buffer. |
| 146 if (mOriginalBuffer.size() < totalRequiredSize) { |
| 147 // Violate the boundary. |
| 148 return false; |
| 149 } |
| 150 // The buffer has sufficient capacity. |
| 151 return true; |
| 152 } |
| 153 // Hereafter, pos is in the additional buffer. |
| 154 const size_t tailPosition = static_cast<size_t>(getTailPosition()); |
| 155 if (totalRequiredSize <= tailPosition) { |
| 156 // The buffer has sufficient capacity. |
| 157 return true; |
| 158 } |
| 159 if (static_cast<size_t>(pos) != tailPosition) { |
| 160 // The additional buffer must be extended from the tail position. |
| 161 return false; |
| 162 } |
| 163 const size_t extendSize = |
| 164 totalRequiredSize - |
| 165 std::min(mAdditionalBuffer.size() + mOriginalBuffer.size(), |
| 166 totalRequiredSize); |
| 167 if (extendSize > 0 && !extendBuffer(extendSize)) { |
| 168 // Failed to extend the buffer. |
| 169 return false; |
| 170 } |
| 171 mUsedAdditionalBufferSize += size; |
| 172 return true; |
| 173 } |
| 174 |
| 175 bool BufferWithExtendableBuffer::copy( |
| 176 const BufferWithExtendableBuffer* const sourceBuffer) { |
| 177 int copyingPos = 0; |
| 178 const int tailPos = sourceBuffer->getTailPosition(); |
| 179 const int maxDataChunkSize = sizeof(uint32_t); |
| 180 while (copyingPos < tailPos) { |
| 181 const int remainingSize = tailPos - copyingPos; |
| 182 const int copyingSize = |
| 183 (remainingSize >= maxDataChunkSize) ? maxDataChunkSize : remainingSize; |
| 184 const uint32_t data = sourceBuffer->readUint(copyingSize, copyingPos); |
| 185 if (!writeUint(data, copyingSize, copyingPos)) { |
| 186 return false; |
| 187 } |
| 188 copyingPos += copyingSize; |
| 189 } |
| 190 return true; |
| 191 } |
| 192 } |
| OLD | NEW |