| Index: third_party/prediction/suggest/policyimpl/dictionary/header/header_read_write_utils.cpp
|
| diff --git a/third_party/prediction/suggest/policyimpl/dictionary/header/header_read_write_utils.cpp b/third_party/prediction/suggest/policyimpl/dictionary/header/header_read_write_utils.cpp
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..e00899d6b39ae9143be1baf66d984e7a276774fe
|
| --- /dev/null
|
| +++ b/third_party/prediction/suggest/policyimpl/dictionary/header/header_read_write_utils.cpp
|
| @@ -0,0 +1,262 @@
|
| +/*
|
| + * Copyright (C) 2013, The Android Open Source Project
|
| + *
|
| + * Licensed under the Apache License, Version 2.0 (the "License");
|
| + * you may not use this file except in compliance with the License.
|
| + * You may obtain a copy of the License at
|
| + *
|
| + * http://www.apache.org/licenses/LICENSE-2.0
|
| + *
|
| + * Unless required by applicable law or agreed to in writing, software
|
| + * distributed under the License is distributed on an "AS IS" BASIS,
|
| + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
| + * See the License for the specific language governing permissions and
|
| + * limitations under the License.
|
| + */
|
| +
|
| +#include "third_party/prediction/suggest/policyimpl/dictionary/header/header_read_write_utils.h"
|
| +
|
| +#include <cctype>
|
| +#include <cstdio>
|
| +#include <vector>
|
| +
|
| +#include "third_party/prediction/defines.h"
|
| +#include "third_party/prediction/suggest/policyimpl/dictionary/utils/buffer_with_extendable_buffer.h"
|
| +#include "third_party/prediction/suggest/policyimpl/dictionary/utils/byte_array_utils.h"
|
| +
|
| +namespace latinime {
|
| +
|
| +// Number of base-10 digits in the largest integer + 1 to leave room for a zero
|
| +// terminator.
|
| +// As such, this is the maximum number of characters will be needed to represent
|
| +// an int as a
|
| +// string, including the terminator; this is used as the size of a string buffer
|
| +// large enough to
|
| +// hold any value that is intended to fit in an integer, e.g. in the code that
|
| +// reads the header
|
| +// of the binary dictionary where a {key,value} string pair scheme is used.
|
| +const int HeaderReadWriteUtils::LARGEST_INT_DIGIT_COUNT = 11;
|
| +
|
| +const int HeaderReadWriteUtils::MAX_ATTRIBUTE_KEY_LENGTH = 256;
|
| +const int HeaderReadWriteUtils::MAX_ATTRIBUTE_VALUE_LENGTH = 256;
|
| +
|
| +const int HeaderReadWriteUtils::HEADER_MAGIC_NUMBER_SIZE = 4;
|
| +const int HeaderReadWriteUtils::HEADER_DICTIONARY_VERSION_SIZE = 2;
|
| +const int HeaderReadWriteUtils::HEADER_FLAG_SIZE = 2;
|
| +const int HeaderReadWriteUtils::HEADER_SIZE_FIELD_SIZE = 4;
|
| +
|
| +const HeaderReadWriteUtils::DictionaryFlags HeaderReadWriteUtils::NO_FLAGS = 0;
|
| +
|
| +typedef DictionaryHeaderStructurePolicy::AttributeMap AttributeMap;
|
| +
|
| +/* static */ int HeaderReadWriteUtils::getHeaderSize(
|
| + const uint8_t* const dictBuf) {
|
| + // See the format of the header in the comment in
|
| + // BinaryDictionaryFormatUtils::detectFormatVersion()
|
| + return ByteArrayUtils::readUint32(
|
| + dictBuf, HEADER_MAGIC_NUMBER_SIZE + HEADER_DICTIONARY_VERSION_SIZE +
|
| + HEADER_FLAG_SIZE);
|
| +}
|
| +
|
| +/* static */ HeaderReadWriteUtils::DictionaryFlags
|
| +HeaderReadWriteUtils::getFlags(const uint8_t* const dictBuf) {
|
| + return ByteArrayUtils::readUint16(
|
| + dictBuf, HEADER_MAGIC_NUMBER_SIZE + HEADER_DICTIONARY_VERSION_SIZE);
|
| +}
|
| +
|
| +/* static */ HeaderReadWriteUtils::DictionaryFlags
|
| +HeaderReadWriteUtils::createAndGetDictionaryFlagsUsingAttributeMap(
|
| + const AttributeMap* const attributeMap) {
|
| + return NO_FLAGS;
|
| +}
|
| +
|
| +/* static */ void HeaderReadWriteUtils::fetchAllHeaderAttributes(
|
| + const uint8_t* const dictBuf,
|
| + AttributeMap* const headerAttributes) {
|
| + const int headerSize = getHeaderSize(dictBuf);
|
| + int pos = getHeaderOptionsPosition();
|
| + if (pos == NOT_A_DICT_POS) {
|
| + // The header doesn't have header options.
|
| + return;
|
| + }
|
| + int keyBuffer[MAX_ATTRIBUTE_KEY_LENGTH];
|
| + int valueBuffer[MAX_ATTRIBUTE_VALUE_LENGTH];
|
| + while (pos < headerSize) {
|
| + const int keyLength = ByteArrayUtils::readStringAndAdvancePosition(
|
| + dictBuf, MAX_ATTRIBUTE_KEY_LENGTH, keyBuffer, &pos);
|
| + std::vector<int> key;
|
| + key.insert(key.end(), keyBuffer, keyBuffer + keyLength);
|
| + const int valueLength = ByteArrayUtils::readStringAndAdvancePosition(
|
| + dictBuf, MAX_ATTRIBUTE_VALUE_LENGTH, valueBuffer, &pos);
|
| + std::vector<int> value;
|
| + value.insert(value.end(), valueBuffer, valueBuffer + valueLength);
|
| + headerAttributes->insert(AttributeMap::value_type(key, value));
|
| + }
|
| +}
|
| +
|
| +/* static */ bool HeaderReadWriteUtils::writeDictionaryVersion(
|
| + BufferWithExtendableBuffer* const buffer,
|
| + const FormatUtils::FORMAT_VERSION version,
|
| + int* const writingPos) {
|
| + if (!buffer->writeUintAndAdvancePosition(
|
| + FormatUtils::MAGIC_NUMBER, HEADER_MAGIC_NUMBER_SIZE, writingPos)) {
|
| + return false;
|
| + }
|
| + switch (version) {
|
| + case FormatUtils::VERSION_2:
|
| + // Version 2 dictionary writing is not supported.
|
| + return false;
|
| + case FormatUtils::VERSION_4_ONLY_FOR_TESTING:
|
| + case FormatUtils::VERSION_4:
|
| + case FormatUtils::VERSION_4_DEV:
|
| + return buffer->writeUintAndAdvancePosition(
|
| + version /* data */, HEADER_DICTIONARY_VERSION_SIZE, writingPos);
|
| + default:
|
| + return false;
|
| + }
|
| +}
|
| +
|
| +/* static */ bool HeaderReadWriteUtils::writeDictionaryFlags(
|
| + BufferWithExtendableBuffer* const buffer,
|
| + const DictionaryFlags flags,
|
| + int* const writingPos) {
|
| + return buffer->writeUintAndAdvancePosition(flags, HEADER_FLAG_SIZE,
|
| + writingPos);
|
| +}
|
| +
|
| +/* static */ bool HeaderReadWriteUtils::writeDictionaryHeaderSize(
|
| + BufferWithExtendableBuffer* const buffer,
|
| + const int size,
|
| + int* const writingPos) {
|
| + return buffer->writeUintAndAdvancePosition(size, HEADER_SIZE_FIELD_SIZE,
|
| + writingPos);
|
| +}
|
| +
|
| +/* static */ bool HeaderReadWriteUtils::writeHeaderAttributes(
|
| + BufferWithExtendableBuffer* const buffer,
|
| + const AttributeMap* const headerAttributes,
|
| + int* const writingPos) {
|
| + for (AttributeMap::const_iterator it = headerAttributes->begin();
|
| + it != headerAttributes->end(); ++it) {
|
| + if (it->first.empty() || it->second.empty()) {
|
| + continue;
|
| + }
|
| + // Write a key.
|
| + if (!buffer->writeCodePointsAndAdvancePosition(
|
| + &(it->first.at(0)), it->first.size(), true /* writesTerminator */,
|
| + writingPos)) {
|
| + return false;
|
| + }
|
| + // Write a value.
|
| + if (!buffer->writeCodePointsAndAdvancePosition(
|
| + &(it->second.at(0)), it->second.size(), true /* writesTerminator */,
|
| + writingPos)) {
|
| + return false;
|
| + }
|
| + }
|
| + return true;
|
| +}
|
| +
|
| +/* static */ void HeaderReadWriteUtils::setCodePointVectorAttribute(
|
| + AttributeMap* const headerAttributes,
|
| + const char* const key,
|
| + const std::vector<int> value) {
|
| + AttributeMap::key_type keyVector;
|
| + insertCharactersIntoVector(key, &keyVector);
|
| + (*headerAttributes)[keyVector] = value;
|
| +}
|
| +
|
| +/* static */ void HeaderReadWriteUtils::setBoolAttribute(
|
| + AttributeMap* const headerAttributes,
|
| + const char* const key,
|
| + const bool value) {
|
| + setIntAttribute(headerAttributes, key, value ? 1 : 0);
|
| +}
|
| +
|
| +/* static */ void HeaderReadWriteUtils::setIntAttribute(
|
| + AttributeMap* const headerAttributes,
|
| + const char* const key,
|
| + const int value) {
|
| + AttributeMap::key_type keyVector;
|
| + insertCharactersIntoVector(key, &keyVector);
|
| + setIntAttributeInner(headerAttributes, &keyVector, value);
|
| +}
|
| +
|
| +/* static */ void HeaderReadWriteUtils::setIntAttributeInner(
|
| + AttributeMap* const headerAttributes,
|
| + const AttributeMap::key_type* const key,
|
| + const int value) {
|
| + AttributeMap::mapped_type valueVector;
|
| + char charBuf[LARGEST_INT_DIGIT_COUNT];
|
| + snprintf(charBuf, sizeof(charBuf), "%d", value);
|
| + insertCharactersIntoVector(charBuf, &valueVector);
|
| + (*headerAttributes)[*key] = valueVector;
|
| +}
|
| +
|
| +/* static */ const std::vector<int>
|
| +HeaderReadWriteUtils::readCodePointVectorAttributeValue(
|
| + const AttributeMap* const headerAttributes,
|
| + const char* const key) {
|
| + AttributeMap::key_type keyVector;
|
| + insertCharactersIntoVector(key, &keyVector);
|
| + AttributeMap::const_iterator it = headerAttributes->find(keyVector);
|
| + if (it == headerAttributes->end()) {
|
| + return std::vector<int>();
|
| + } else {
|
| + return it->second;
|
| + }
|
| +}
|
| +
|
| +/* static */ bool HeaderReadWriteUtils::readBoolAttributeValue(
|
| + const AttributeMap* const headerAttributes,
|
| + const char* const key,
|
| + const bool defaultValue) {
|
| + const int intDefaultValue = defaultValue ? 1 : 0;
|
| + const int intValue =
|
| + readIntAttributeValue(headerAttributes, key, intDefaultValue);
|
| + return intValue != 0;
|
| +}
|
| +
|
| +/* static */ int HeaderReadWriteUtils::readIntAttributeValue(
|
| + const AttributeMap* const headerAttributes,
|
| + const char* const key,
|
| + const int defaultValue) {
|
| + AttributeMap::key_type keyVector;
|
| + insertCharactersIntoVector(key, &keyVector);
|
| + return readIntAttributeValueInner(headerAttributes, &keyVector, defaultValue);
|
| +}
|
| +
|
| +/* static */ int HeaderReadWriteUtils::readIntAttributeValueInner(
|
| + const AttributeMap* const headerAttributes,
|
| + const AttributeMap::key_type* const key,
|
| + const int defaultValue) {
|
| + AttributeMap::const_iterator it = headerAttributes->find(*key);
|
| + if (it != headerAttributes->end()) {
|
| + int value = 0;
|
| + bool isNegative = false;
|
| + for (size_t i = 0; i < it->second.size(); ++i) {
|
| + if (i == 0 && it->second.at(i) == '-') {
|
| + isNegative = true;
|
| + } else {
|
| + if (!isdigit(it->second.at(i))) {
|
| + // If not a number.
|
| + return defaultValue;
|
| + }
|
| + value *= 10;
|
| + value += it->second.at(i) - '0';
|
| + }
|
| + }
|
| + return isNegative ? -value : value;
|
| + }
|
| + return defaultValue;
|
| +}
|
| +
|
| +/* static */ void HeaderReadWriteUtils::insertCharactersIntoVector(
|
| + const char* const characters,
|
| + std::vector<int>* const vector) {
|
| + for (int i = 0; characters[i]; ++i) {
|
| + vector->push_back(characters[i]);
|
| + }
|
| +}
|
| +
|
| +} // namespace latinime
|
|
|