Home | History | Annotate | Download | only in header
      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 "suggest/policyimpl/dictionary/header/header_read_write_utils.h"
     18 
     19 #include <cctype>
     20 #include <cstdio>
     21 #include <vector>
     22 
     23 #include "defines.h"
     24 #include "suggest/policyimpl/dictionary/utils/buffer_with_extendable_buffer.h"
     25 #include "suggest/policyimpl/dictionary/utils/byte_array_utils.h"
     26 
     27 namespace latinime {
     28 
     29 // Number of base-10 digits in the largest integer + 1 to leave room for a zero terminator.
     30 // As such, this is the maximum number of characters will be needed to represent an int as a
     31 // string, including the terminator; this is used as the size of a string buffer large enough to
     32 // hold any value that is intended to fit in an integer, e.g. in the code that reads the header
     33 // of the binary dictionary where a {key,value} string pair scheme is used.
     34 const int HeaderReadWriteUtils::LARGEST_INT_DIGIT_COUNT = 11;
     35 
     36 const int HeaderReadWriteUtils::MAX_ATTRIBUTE_KEY_LENGTH = 256;
     37 const int HeaderReadWriteUtils::MAX_ATTRIBUTE_VALUE_LENGTH = 256;
     38 
     39 const int HeaderReadWriteUtils::HEADER_MAGIC_NUMBER_SIZE = 4;
     40 const int HeaderReadWriteUtils::HEADER_DICTIONARY_VERSION_SIZE = 2;
     41 const int HeaderReadWriteUtils::HEADER_FLAG_SIZE = 2;
     42 const int HeaderReadWriteUtils::HEADER_SIZE_FIELD_SIZE = 4;
     43 
     44 const HeaderReadWriteUtils::DictionaryFlags HeaderReadWriteUtils::NO_FLAGS = 0;
     45 
     46 typedef DictionaryHeaderStructurePolicy::AttributeMap AttributeMap;
     47 
     48 /* static */ int HeaderReadWriteUtils::getHeaderSize(const uint8_t *const dictBuf) {
     49     // See the format of the header in the comment in
     50     // BinaryDictionaryFormatUtils::detectFormatVersion()
     51     return ByteArrayUtils::readUint32(dictBuf, HEADER_MAGIC_NUMBER_SIZE
     52             + HEADER_DICTIONARY_VERSION_SIZE + HEADER_FLAG_SIZE);
     53 }
     54 
     55 /* static */ HeaderReadWriteUtils::DictionaryFlags
     56         HeaderReadWriteUtils::getFlags(const uint8_t *const dictBuf) {
     57     return ByteArrayUtils::readUint16(dictBuf,
     58             HEADER_MAGIC_NUMBER_SIZE + HEADER_DICTIONARY_VERSION_SIZE);
     59 }
     60 
     61 /* static */ HeaderReadWriteUtils::DictionaryFlags
     62         HeaderReadWriteUtils::createAndGetDictionaryFlagsUsingAttributeMap(
     63                 const AttributeMap *const attributeMap) {
     64     return NO_FLAGS;
     65 }
     66 
     67 /* static */ void HeaderReadWriteUtils::fetchAllHeaderAttributes(const uint8_t *const dictBuf,
     68         AttributeMap *const headerAttributes) {
     69     const int headerSize = getHeaderSize(dictBuf);
     70     int pos = getHeaderOptionsPosition();
     71     if (pos == NOT_A_DICT_POS) {
     72         // The header doesn't have header options.
     73         return;
     74     }
     75     int keyBuffer[MAX_ATTRIBUTE_KEY_LENGTH];
     76     int valueBuffer[MAX_ATTRIBUTE_VALUE_LENGTH];
     77     while (pos < headerSize) {
     78         const int keyLength = ByteArrayUtils::readStringAndAdvancePosition(dictBuf,
     79                 MAX_ATTRIBUTE_KEY_LENGTH, keyBuffer, &pos);
     80         std::vector<int> key;
     81         key.insert(key.end(), keyBuffer, keyBuffer + keyLength);
     82         const int valueLength = ByteArrayUtils::readStringAndAdvancePosition(dictBuf,
     83                 MAX_ATTRIBUTE_VALUE_LENGTH, valueBuffer, &pos);
     84         std::vector<int> value;
     85         value.insert(value.end(), valueBuffer, valueBuffer + valueLength);
     86         headerAttributes->insert(AttributeMap::value_type(key, value));
     87     }
     88 }
     89 
     90 /* static */ bool HeaderReadWriteUtils::writeDictionaryVersion(
     91         BufferWithExtendableBuffer *const buffer, const FormatUtils::FORMAT_VERSION version,
     92         int *const writingPos) {
     93     if (!buffer->writeUintAndAdvancePosition(FormatUtils::MAGIC_NUMBER, HEADER_MAGIC_NUMBER_SIZE,
     94             writingPos)) {
     95         return false;
     96     }
     97     switch (version) {
     98         case FormatUtils::VERSION_2:
     99             // Version 2 dictionary writing is not supported.
    100             return false;
    101         case FormatUtils::VERSION_4_ONLY_FOR_TESTING:
    102         case FormatUtils::VERSION_4:
    103         case FormatUtils::VERSION_4_DEV:
    104             return buffer->writeUintAndAdvancePosition(version /* data */,
    105                     HEADER_DICTIONARY_VERSION_SIZE, writingPos);
    106         default:
    107             return false;
    108     }
    109 }
    110 
    111 /* static */ bool HeaderReadWriteUtils::writeDictionaryFlags(
    112         BufferWithExtendableBuffer *const buffer, const DictionaryFlags flags,
    113         int *const writingPos) {
    114     return buffer->writeUintAndAdvancePosition(flags, HEADER_FLAG_SIZE, writingPos);
    115 }
    116 
    117 /* static */ bool HeaderReadWriteUtils::writeDictionaryHeaderSize(
    118         BufferWithExtendableBuffer *const buffer, const int size, int *const writingPos) {
    119     return buffer->writeUintAndAdvancePosition(size, HEADER_SIZE_FIELD_SIZE, writingPos);
    120 }
    121 
    122 /* static */ bool HeaderReadWriteUtils::writeHeaderAttributes(
    123         BufferWithExtendableBuffer *const buffer, const AttributeMap *const headerAttributes,
    124         int *const writingPos) {
    125     for (AttributeMap::const_iterator it = headerAttributes->begin();
    126             it != headerAttributes->end(); ++it) {
    127         if (it->first.empty() || it->second.empty()) {
    128             continue;
    129         }
    130         // Write a key.
    131         if (!buffer->writeCodePointsAndAdvancePosition(&(it->first.at(0)), it->first.size(),
    132                 true /* writesTerminator */, writingPos)) {
    133             return false;
    134         }
    135         // Write a value.
    136         if (!buffer->writeCodePointsAndAdvancePosition(&(it->second.at(0)), it->second.size(),
    137                 true /* writesTerminator */, writingPos)) {
    138             return false;
    139         }
    140     }
    141     return true;
    142 }
    143 
    144 /* static */ void HeaderReadWriteUtils::setCodePointVectorAttribute(
    145         AttributeMap *const headerAttributes, const char *const key, const std::vector<int> value) {
    146     AttributeMap::key_type keyVector;
    147     insertCharactersIntoVector(key, &keyVector);
    148     (*headerAttributes)[keyVector] = value;
    149 }
    150 
    151 /* static */ void HeaderReadWriteUtils::setBoolAttribute(AttributeMap *const headerAttributes,
    152         const char *const key, const bool value) {
    153     setIntAttribute(headerAttributes, key, value ? 1 : 0);
    154 }
    155 
    156 /* static */ void HeaderReadWriteUtils::setIntAttribute(AttributeMap *const headerAttributes,
    157         const char *const key, const int value) {
    158     AttributeMap::key_type keyVector;
    159     insertCharactersIntoVector(key, &keyVector);
    160     setIntAttributeInner(headerAttributes, &keyVector, value);
    161 }
    162 
    163 /* static */ void HeaderReadWriteUtils::setIntAttributeInner(AttributeMap *const headerAttributes,
    164         const AttributeMap::key_type *const key, const int value) {
    165     AttributeMap::mapped_type valueVector;
    166     char charBuf[LARGEST_INT_DIGIT_COUNT];
    167     snprintf(charBuf, sizeof(charBuf), "%d", value);
    168     insertCharactersIntoVector(charBuf, &valueVector);
    169     (*headerAttributes)[*key] = valueVector;
    170 }
    171 
    172 /* static */ const std::vector<int> HeaderReadWriteUtils::readCodePointVectorAttributeValue(
    173         const AttributeMap *const headerAttributes, const char *const key) {
    174     AttributeMap::key_type keyVector;
    175     insertCharactersIntoVector(key, &keyVector);
    176     AttributeMap::const_iterator it = headerAttributes->find(keyVector);
    177     if (it == headerAttributes->end()) {
    178         return std::vector<int>();
    179     } else {
    180         return it->second;
    181     }
    182 }
    183 
    184 /* static */ bool HeaderReadWriteUtils::readBoolAttributeValue(
    185         const AttributeMap *const headerAttributes, const char *const key,
    186         const bool defaultValue) {
    187     const int intDefaultValue = defaultValue ? 1 : 0;
    188     const int intValue = readIntAttributeValue(headerAttributes, key, intDefaultValue);
    189     return intValue != 0;
    190 }
    191 
    192 /* static */ int HeaderReadWriteUtils::readIntAttributeValue(
    193         const AttributeMap *const headerAttributes, const char *const key,
    194         const int defaultValue) {
    195     AttributeMap::key_type keyVector;
    196     insertCharactersIntoVector(key, &keyVector);
    197     return readIntAttributeValueInner(headerAttributes, &keyVector, defaultValue);
    198 }
    199 
    200 /* static */ int HeaderReadWriteUtils::readIntAttributeValueInner(
    201         const AttributeMap *const headerAttributes, const AttributeMap::key_type *const key,
    202         const int defaultValue) {
    203     AttributeMap::const_iterator it = headerAttributes->find(*key);
    204     if (it != headerAttributes->end()) {
    205         int value = 0;
    206         bool isNegative = false;
    207         for (size_t i = 0; i < it->second.size(); ++i) {
    208             if (i == 0 && it->second.at(i) == '-') {
    209                 isNegative = true;
    210             } else {
    211                 if (!isdigit(it->second.at(i))) {
    212                     // If not a number.
    213                     return defaultValue;
    214                 }
    215                 value *= 10;
    216                 value += it->second.at(i) - '0';
    217             }
    218         }
    219         return isNegative ? -value : value;
    220     }
    221     return defaultValue;
    222 }
    223 
    224 /* static */ void HeaderReadWriteUtils::insertCharactersIntoVector(const char *const characters,
    225         std::vector<int> *const vector) {
    226     for (int i = 0; characters[i]; ++i) {
    227         vector->push_back(characters[i]);
    228     }
    229 }
    230 
    231 } // namespace latinime
    232