1bd0d1afdb28a28e2ddac1409208c59ba64350399Keisuke Kuroynagi/*
2bd0d1afdb28a28e2ddac1409208c59ba64350399Keisuke Kuroynagi * Copyright (C) 2013, The Android Open Source Project
3bd0d1afdb28a28e2ddac1409208c59ba64350399Keisuke Kuroynagi *
4bd0d1afdb28a28e2ddac1409208c59ba64350399Keisuke Kuroynagi * Licensed under the Apache License, Version 2.0 (the "License");
5bd0d1afdb28a28e2ddac1409208c59ba64350399Keisuke Kuroynagi * you may not use this file except in compliance with the License.
6bd0d1afdb28a28e2ddac1409208c59ba64350399Keisuke Kuroynagi * You may obtain a copy of the License at
7bd0d1afdb28a28e2ddac1409208c59ba64350399Keisuke Kuroynagi *
8bd0d1afdb28a28e2ddac1409208c59ba64350399Keisuke Kuroynagi *     http://www.apache.org/licenses/LICENSE-2.0
9bd0d1afdb28a28e2ddac1409208c59ba64350399Keisuke Kuroynagi *
10bd0d1afdb28a28e2ddac1409208c59ba64350399Keisuke Kuroynagi * Unless required by applicable law or agreed to in writing, software
11bd0d1afdb28a28e2ddac1409208c59ba64350399Keisuke Kuroynagi * distributed under the License is distributed on an "AS IS" BASIS,
12bd0d1afdb28a28e2ddac1409208c59ba64350399Keisuke Kuroynagi * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13bd0d1afdb28a28e2ddac1409208c59ba64350399Keisuke Kuroynagi * See the License for the specific language governing permissions and
14bd0d1afdb28a28e2ddac1409208c59ba64350399Keisuke Kuroynagi * limitations under the License.
15bd0d1afdb28a28e2ddac1409208c59ba64350399Keisuke Kuroynagi */
16bd0d1afdb28a28e2ddac1409208c59ba64350399Keisuke Kuroynagi
1788bc312ad34321fb3e81be2dc939a889d065f4a7Keisuke Kuroyanagi#include "dictionary/header/header_read_write_utils.h"
18bd0d1afdb28a28e2ddac1409208c59ba64350399Keisuke Kuroynagi
19989596844e05b551d8fc6bb64c343677da0e4f7fKeisuke Kuroyanagi#include <cctype>
20989596844e05b551d8fc6bb64c343677da0e4f7fKeisuke Kuroyanagi#include <cstdio>
21fb2bde5a688d93aa946e3dd923aa1e99588777fcAkifumi Yoshimoto#include <memory>
225754817a5e2e804f5ced54e601d4c08087d75b44Keisuke Kuroyanagi#include <vector>
23bd0d1afdb28a28e2ddac1409208c59ba64350399Keisuke Kuroynagi
24bd0d1afdb28a28e2ddac1409208c59ba64350399Keisuke Kuroynagi#include "defines.h"
2588bc312ad34321fb3e81be2dc939a889d065f4a7Keisuke Kuroyanagi#include "dictionary/utils/buffer_with_extendable_buffer.h"
2688bc312ad34321fb3e81be2dc939a889d065f4a7Keisuke Kuroyanagi#include "dictionary/utils/byte_array_utils.h"
27bd0d1afdb28a28e2ddac1409208c59ba64350399Keisuke Kuroynagi
28bd0d1afdb28a28e2ddac1409208c59ba64350399Keisuke Kuroynaginamespace latinime {
29bd0d1afdb28a28e2ddac1409208c59ba64350399Keisuke Kuroynagi
30fc2858c55bf64ef96b1b60f19db23de4b0c62c9cKen Wakasa// Number of base-10 digits in the largest integer + 1 to leave room for a zero terminator.
31fc2858c55bf64ef96b1b60f19db23de4b0c62c9cKen Wakasa// As such, this is the maximum number of characters will be needed to represent an int as a
32fc2858c55bf64ef96b1b60f19db23de4b0c62c9cKen Wakasa// string, including the terminator; this is used as the size of a string buffer large enough to
33fc2858c55bf64ef96b1b60f19db23de4b0c62c9cKen Wakasa// hold any value that is intended to fit in an integer, e.g. in the code that reads the header
34fc2858c55bf64ef96b1b60f19db23de4b0c62c9cKen Wakasa// of the binary dictionary where a {key,value} string pair scheme is used.
35fc2858c55bf64ef96b1b60f19db23de4b0c62c9cKen Wakasaconst int HeaderReadWriteUtils::LARGEST_INT_DIGIT_COUNT = 11;
36fc2858c55bf64ef96b1b60f19db23de4b0c62c9cKen Wakasa
37484fa7b59cb0659ac18fa68da5c7b641d9255be8Keisuke Kuroyanagiconst int HeaderReadWriteUtils::MAX_ATTRIBUTE_KEY_LENGTH = 256;
38fb2bde5a688d93aa946e3dd923aa1e99588777fcAkifumi Yoshimotoconst int HeaderReadWriteUtils::MAX_ATTRIBUTE_VALUE_LENGTH = 2048;
39bd0d1afdb28a28e2ddac1409208c59ba64350399Keisuke Kuroynagi
40484fa7b59cb0659ac18fa68da5c7b641d9255be8Keisuke Kuroyanagiconst int HeaderReadWriteUtils::HEADER_MAGIC_NUMBER_SIZE = 4;
41484fa7b59cb0659ac18fa68da5c7b641d9255be8Keisuke Kuroyanagiconst int HeaderReadWriteUtils::HEADER_DICTIONARY_VERSION_SIZE = 2;
42484fa7b59cb0659ac18fa68da5c7b641d9255be8Keisuke Kuroyanagiconst int HeaderReadWriteUtils::HEADER_FLAG_SIZE = 2;
43484fa7b59cb0659ac18fa68da5c7b641d9255be8Keisuke Kuroyanagiconst int HeaderReadWriteUtils::HEADER_SIZE_FIELD_SIZE = 4;
44fb2bde5a688d93aa946e3dd923aa1e99588777fcAkifumi Yoshimotoconst char *const HeaderReadWriteUtils::CODE_POINT_TABLE_KEY = "codePointTable";
4576e579c7caf2ef04f440be21c27377fe0b4150ffKeisuke Kuroyanagi
46484fa7b59cb0659ac18fa68da5c7b641d9255be8Keisuke Kuroyanagiconst HeaderReadWriteUtils::DictionaryFlags HeaderReadWriteUtils::NO_FLAGS = 0;
47989596844e05b551d8fc6bb64c343677da0e4f7fKeisuke Kuroyanagi
48fc9ca59cc1dccc8353528c42a7eb710ad6d90e14Keisuke Kuroyanagitypedef DictionaryHeaderStructurePolicy::AttributeMap AttributeMap;
49fc9ca59cc1dccc8353528c42a7eb710ad6d90e14Keisuke Kuroyanagi
50484fa7b59cb0659ac18fa68da5c7b641d9255be8Keisuke Kuroyanagi/* static */ int HeaderReadWriteUtils::getHeaderSize(const uint8_t *const dictBuf) {
5199007de979e006b6b08bf381f2d394377264de85Keisuke Kuroyanagi    // See the format of the header in the comment in
5299007de979e006b6b08bf381f2d394377264de85Keisuke Kuroyanagi    // BinaryDictionaryFormatUtils::detectFormatVersion()
5376e579c7caf2ef04f440be21c27377fe0b4150ffKeisuke Kuroyanagi    return ByteArrayUtils::readUint32(dictBuf, HEADER_MAGIC_NUMBER_SIZE
5476e579c7caf2ef04f440be21c27377fe0b4150ffKeisuke Kuroyanagi            + HEADER_DICTIONARY_VERSION_SIZE + HEADER_FLAG_SIZE);
55bd0d1afdb28a28e2ddac1409208c59ba64350399Keisuke Kuroynagi}
56bd0d1afdb28a28e2ddac1409208c59ba64350399Keisuke Kuroynagi
57484fa7b59cb0659ac18fa68da5c7b641d9255be8Keisuke Kuroyanagi/* static */ HeaderReadWriteUtils::DictionaryFlags
58484fa7b59cb0659ac18fa68da5c7b641d9255be8Keisuke Kuroyanagi        HeaderReadWriteUtils::getFlags(const uint8_t *const dictBuf) {
5976e579c7caf2ef04f440be21c27377fe0b4150ffKeisuke Kuroyanagi    return ByteArrayUtils::readUint16(dictBuf,
6076e579c7caf2ef04f440be21c27377fe0b4150ffKeisuke Kuroyanagi            HEADER_MAGIC_NUMBER_SIZE + HEADER_DICTIONARY_VERSION_SIZE);
61bd0d1afdb28a28e2ddac1409208c59ba64350399Keisuke Kuroynagi}
62bd0d1afdb28a28e2ddac1409208c59ba64350399Keisuke Kuroynagi
63989596844e05b551d8fc6bb64c343677da0e4f7fKeisuke Kuroyanagi/* static */ HeaderReadWriteUtils::DictionaryFlags
64989596844e05b551d8fc6bb64c343677da0e4f7fKeisuke Kuroyanagi        HeaderReadWriteUtils::createAndGetDictionaryFlagsUsingAttributeMap(
65fc9ca59cc1dccc8353528c42a7eb710ad6d90e14Keisuke Kuroyanagi                const AttributeMap *const attributeMap) {
662fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa    return NO_FLAGS;
67989596844e05b551d8fc6bb64c343677da0e4f7fKeisuke Kuroyanagi}
68989596844e05b551d8fc6bb64c343677da0e4f7fKeisuke Kuroyanagi
69484fa7b59cb0659ac18fa68da5c7b641d9255be8Keisuke Kuroyanagi/* static */ void HeaderReadWriteUtils::fetchAllHeaderAttributes(const uint8_t *const dictBuf,
705754817a5e2e804f5ced54e601d4c08087d75b44Keisuke Kuroyanagi        AttributeMap *const headerAttributes) {
7199007de979e006b6b08bf381f2d394377264de85Keisuke Kuroyanagi    const int headerSize = getHeaderSize(dictBuf);
7299007de979e006b6b08bf381f2d394377264de85Keisuke Kuroyanagi    int pos = getHeaderOptionsPosition();
735ae8722bd52b0f70ab7cd3bd888585422bef9563Keisuke Kuroynagi    if (pos == NOT_A_DICT_POS) {
745ae8722bd52b0f70ab7cd3bd888585422bef9563Keisuke Kuroynagi        // The header doesn't have header options.
755754817a5e2e804f5ced54e601d4c08087d75b44Keisuke Kuroyanagi        return;
765ae8722bd52b0f70ab7cd3bd888585422bef9563Keisuke Kuroynagi    }
775754817a5e2e804f5ced54e601d4c08087d75b44Keisuke Kuroyanagi    int keyBuffer[MAX_ATTRIBUTE_KEY_LENGTH];
78fb2bde5a688d93aa946e3dd923aa1e99588777fcAkifumi Yoshimoto    std::unique_ptr<int[]> valueBuffer(new int[MAX_ATTRIBUTE_VALUE_LENGTH]);
79bd0d1afdb28a28e2ddac1409208c59ba64350399Keisuke Kuroynagi    while (pos < headerSize) {
80fb2bde5a688d93aa946e3dd923aa1e99588777fcAkifumi Yoshimoto        // The values in the header don't use the code point table for their encoding.
815754817a5e2e804f5ced54e601d4c08087d75b44Keisuke Kuroyanagi        const int keyLength = ByteArrayUtils::readStringAndAdvancePosition(dictBuf,
82fb2bde5a688d93aa946e3dd923aa1e99588777fcAkifumi Yoshimoto                MAX_ATTRIBUTE_KEY_LENGTH, nullptr /* codePointTable */, keyBuffer, &pos);
835754817a5e2e804f5ced54e601d4c08087d75b44Keisuke Kuroyanagi        std::vector<int> key;
845754817a5e2e804f5ced54e601d4c08087d75b44Keisuke Kuroyanagi        key.insert(key.end(), keyBuffer, keyBuffer + keyLength);
855754817a5e2e804f5ced54e601d4c08087d75b44Keisuke Kuroyanagi        const int valueLength = ByteArrayUtils::readStringAndAdvancePosition(dictBuf,
86fb2bde5a688d93aa946e3dd923aa1e99588777fcAkifumi Yoshimoto                MAX_ATTRIBUTE_VALUE_LENGTH, nullptr /* codePointTable */, valueBuffer.get(), &pos);
875754817a5e2e804f5ced54e601d4c08087d75b44Keisuke Kuroyanagi        std::vector<int> value;
88fb2bde5a688d93aa946e3dd923aa1e99588777fcAkifumi Yoshimoto        value.insert(value.end(), valueBuffer.get(), valueBuffer.get() + valueLength);
895754817a5e2e804f5ced54e601d4c08087d75b44Keisuke Kuroyanagi        headerAttributes->insert(AttributeMap::value_type(key, value));
90bd0d1afdb28a28e2ddac1409208c59ba64350399Keisuke Kuroynagi    }
91bd0d1afdb28a28e2ddac1409208c59ba64350399Keisuke Kuroynagi}
92bd0d1afdb28a28e2ddac1409208c59ba64350399Keisuke Kuroynagi
93fb2bde5a688d93aa946e3dd923aa1e99588777fcAkifumi Yoshimoto/* static */ const int *HeaderReadWriteUtils::readCodePointTable(
94fb2bde5a688d93aa946e3dd923aa1e99588777fcAkifumi Yoshimoto        AttributeMap *const headerAttributes) {
95fb2bde5a688d93aa946e3dd923aa1e99588777fcAkifumi Yoshimoto    AttributeMap::key_type keyVector;
96fb2bde5a688d93aa946e3dd923aa1e99588777fcAkifumi Yoshimoto    insertCharactersIntoVector(CODE_POINT_TABLE_KEY, &keyVector);
97fb2bde5a688d93aa946e3dd923aa1e99588777fcAkifumi Yoshimoto    AttributeMap::const_iterator it = headerAttributes->find(keyVector);
98fb2bde5a688d93aa946e3dd923aa1e99588777fcAkifumi Yoshimoto    if (it == headerAttributes->end()) {
99fb2bde5a688d93aa946e3dd923aa1e99588777fcAkifumi Yoshimoto        return nullptr;
100fb2bde5a688d93aa946e3dd923aa1e99588777fcAkifumi Yoshimoto    }
101fb2bde5a688d93aa946e3dd923aa1e99588777fcAkifumi Yoshimoto    return it->second.data();
102fb2bde5a688d93aa946e3dd923aa1e99588777fcAkifumi Yoshimoto}
103fb2bde5a688d93aa946e3dd923aa1e99588777fcAkifumi Yoshimoto
104484fa7b59cb0659ac18fa68da5c7b641d9255be8Keisuke Kuroyanagi/* static */ bool HeaderReadWriteUtils::writeDictionaryVersion(
105484fa7b59cb0659ac18fa68da5c7b641d9255be8Keisuke Kuroyanagi        BufferWithExtendableBuffer *const buffer, const FormatUtils::FORMAT_VERSION version,
106484fa7b59cb0659ac18fa68da5c7b641d9255be8Keisuke Kuroyanagi        int *const writingPos) {
107484fa7b59cb0659ac18fa68da5c7b641d9255be8Keisuke Kuroyanagi    if (!buffer->writeUintAndAdvancePosition(FormatUtils::MAGIC_NUMBER, HEADER_MAGIC_NUMBER_SIZE,
108484fa7b59cb0659ac18fa68da5c7b641d9255be8Keisuke Kuroyanagi            writingPos)) {
109484fa7b59cb0659ac18fa68da5c7b641d9255be8Keisuke Kuroyanagi        return false;
110484fa7b59cb0659ac18fa68da5c7b641d9255be8Keisuke Kuroyanagi    }
111484fa7b59cb0659ac18fa68da5c7b641d9255be8Keisuke Kuroyanagi    switch (version) {
112484fa7b59cb0659ac18fa68da5c7b641d9255be8Keisuke Kuroyanagi        case FormatUtils::VERSION_2:
113fb2bde5a688d93aa946e3dd923aa1e99588777fcAkifumi Yoshimoto        case FormatUtils::VERSION_201:
1147c87859d4c16c9cf19b095b865d7000ebc3cdaa9Adrian Velicu        case FormatUtils::VERSION_202:
1157c87859d4c16c9cf19b095b865d7000ebc3cdaa9Adrian Velicu            // None of the static dictionaries (v2x) support writing
116484fa7b59cb0659ac18fa68da5c7b641d9255be8Keisuke Kuroyanagi            return false;
117455dc84cf2c6526329b535f30000ea45b7d4d4d7Keisuke Kuroyanagi        case FormatUtils::VERSION_4_ONLY_FOR_TESTING:
118ea468cc9de468b6574f98b3a7614decfcb7e456eKeisuke Kuroyanagi        case FormatUtils::VERSION_402:
119ea468cc9de468b6574f98b3a7614decfcb7e456eKeisuke Kuroyanagi        case FormatUtils::VERSION_403:
120455dc84cf2c6526329b535f30000ea45b7d4d4d7Keisuke Kuroyanagi            return buffer->writeUintAndAdvancePosition(version /* data */,
121484fa7b59cb0659ac18fa68da5c7b641d9255be8Keisuke Kuroyanagi                    HEADER_DICTIONARY_VERSION_SIZE, writingPos);
122484fa7b59cb0659ac18fa68da5c7b641d9255be8Keisuke Kuroyanagi        default:
123484fa7b59cb0659ac18fa68da5c7b641d9255be8Keisuke Kuroyanagi            return false;
124484fa7b59cb0659ac18fa68da5c7b641d9255be8Keisuke Kuroyanagi    }
125484fa7b59cb0659ac18fa68da5c7b641d9255be8Keisuke Kuroyanagi}
126484fa7b59cb0659ac18fa68da5c7b641d9255be8Keisuke Kuroyanagi
127484fa7b59cb0659ac18fa68da5c7b641d9255be8Keisuke Kuroyanagi/* static */ bool HeaderReadWriteUtils::writeDictionaryFlags(
128484fa7b59cb0659ac18fa68da5c7b641d9255be8Keisuke Kuroyanagi        BufferWithExtendableBuffer *const buffer, const DictionaryFlags flags,
129484fa7b59cb0659ac18fa68da5c7b641d9255be8Keisuke Kuroyanagi        int *const writingPos) {
130484fa7b59cb0659ac18fa68da5c7b641d9255be8Keisuke Kuroyanagi    return buffer->writeUintAndAdvancePosition(flags, HEADER_FLAG_SIZE, writingPos);
131484fa7b59cb0659ac18fa68da5c7b641d9255be8Keisuke Kuroyanagi}
132484fa7b59cb0659ac18fa68da5c7b641d9255be8Keisuke Kuroyanagi
133484fa7b59cb0659ac18fa68da5c7b641d9255be8Keisuke Kuroyanagi/* static */ bool HeaderReadWriteUtils::writeDictionaryHeaderSize(
134484fa7b59cb0659ac18fa68da5c7b641d9255be8Keisuke Kuroyanagi        BufferWithExtendableBuffer *const buffer, const int size, int *const writingPos) {
135484fa7b59cb0659ac18fa68da5c7b641d9255be8Keisuke Kuroyanagi    return buffer->writeUintAndAdvancePosition(size, HEADER_SIZE_FIELD_SIZE, writingPos);
136484fa7b59cb0659ac18fa68da5c7b641d9255be8Keisuke Kuroyanagi}
137484fa7b59cb0659ac18fa68da5c7b641d9255be8Keisuke Kuroyanagi
138484fa7b59cb0659ac18fa68da5c7b641d9255be8Keisuke Kuroyanagi/* static */ bool HeaderReadWriteUtils::writeHeaderAttributes(
139484fa7b59cb0659ac18fa68da5c7b641d9255be8Keisuke Kuroyanagi        BufferWithExtendableBuffer *const buffer, const AttributeMap *const headerAttributes,
140484fa7b59cb0659ac18fa68da5c7b641d9255be8Keisuke Kuroyanagi        int *const writingPos) {
141484fa7b59cb0659ac18fa68da5c7b641d9255be8Keisuke Kuroyanagi    for (AttributeMap::const_iterator it = headerAttributes->begin();
142484fa7b59cb0659ac18fa68da5c7b641d9255be8Keisuke Kuroyanagi            it != headerAttributes->end(); ++it) {
1439cb1e78a44f4136d05df8368816e12725cbf5861Keisuke Kuroyanagi        if (it->first.empty() || it->second.empty()) {
1449cb1e78a44f4136d05df8368816e12725cbf5861Keisuke Kuroyanagi            continue;
1459cb1e78a44f4136d05df8368816e12725cbf5861Keisuke Kuroyanagi        }
146484fa7b59cb0659ac18fa68da5c7b641d9255be8Keisuke Kuroyanagi        // Write a key.
147484fa7b59cb0659ac18fa68da5c7b641d9255be8Keisuke Kuroyanagi        if (!buffer->writeCodePointsAndAdvancePosition(&(it->first.at(0)), it->first.size(),
148484fa7b59cb0659ac18fa68da5c7b641d9255be8Keisuke Kuroyanagi                true /* writesTerminator */, writingPos)) {
149484fa7b59cb0659ac18fa68da5c7b641d9255be8Keisuke Kuroyanagi            return false;
150484fa7b59cb0659ac18fa68da5c7b641d9255be8Keisuke Kuroyanagi        }
151484fa7b59cb0659ac18fa68da5c7b641d9255be8Keisuke Kuroyanagi        // Write a value.
152484fa7b59cb0659ac18fa68da5c7b641d9255be8Keisuke Kuroyanagi        if (!buffer->writeCodePointsAndAdvancePosition(&(it->second.at(0)), it->second.size(),
153484fa7b59cb0659ac18fa68da5c7b641d9255be8Keisuke Kuroyanagi                true /* writesTerminator */, writingPos)) {
154484fa7b59cb0659ac18fa68da5c7b641d9255be8Keisuke Kuroyanagi            return false;
155484fa7b59cb0659ac18fa68da5c7b641d9255be8Keisuke Kuroyanagi        }
156484fa7b59cb0659ac18fa68da5c7b641d9255be8Keisuke Kuroyanagi    }
157484fa7b59cb0659ac18fa68da5c7b641d9255be8Keisuke Kuroyanagi    return true;
158484fa7b59cb0659ac18fa68da5c7b641d9255be8Keisuke Kuroyanagi}
159484fa7b59cb0659ac18fa68da5c7b641d9255be8Keisuke Kuroyanagi
16043cf9076b2d053c554941e55f6073b8f586c510bJean Chalard/* static */ void HeaderReadWriteUtils::setCodePointVectorAttribute(
161fbddeedff617d101b7617995bdf7c9c7ce7eaf24Keisuke Kuroyanagi        AttributeMap *const headerAttributes, const char *const key,
162fbddeedff617d101b7617995bdf7c9c7ce7eaf24Keisuke Kuroyanagi        const std::vector<int> &value) {
16343cf9076b2d053c554941e55f6073b8f586c510bJean Chalard    AttributeMap::key_type keyVector;
16443cf9076b2d053c554941e55f6073b8f586c510bJean Chalard    insertCharactersIntoVector(key, &keyVector);
16543cf9076b2d053c554941e55f6073b8f586c510bJean Chalard    (*headerAttributes)[keyVector] = value;
16643cf9076b2d053c554941e55f6073b8f586c510bJean Chalard}
16743cf9076b2d053c554941e55f6073b8f586c510bJean Chalard
168989596844e05b551d8fc6bb64c343677da0e4f7fKeisuke Kuroyanagi/* static */ void HeaderReadWriteUtils::setBoolAttribute(AttributeMap *const headerAttributes,
16931097a57cc6f8022abc0ea56f27147399f41b630Keisuke Kuroyanagi        const char *const key, const bool value) {
170989596844e05b551d8fc6bb64c343677da0e4f7fKeisuke Kuroyanagi    setIntAttribute(headerAttributes, key, value ? 1 : 0);
171989596844e05b551d8fc6bb64c343677da0e4f7fKeisuke Kuroyanagi}
172989596844e05b551d8fc6bb64c343677da0e4f7fKeisuke Kuroyanagi
173989596844e05b551d8fc6bb64c343677da0e4f7fKeisuke Kuroyanagi/* static */ void HeaderReadWriteUtils::setIntAttribute(AttributeMap *const headerAttributes,
17431097a57cc6f8022abc0ea56f27147399f41b630Keisuke Kuroyanagi        const char *const key, const int value) {
17531097a57cc6f8022abc0ea56f27147399f41b630Keisuke Kuroyanagi    AttributeMap::key_type keyVector;
17631097a57cc6f8022abc0ea56f27147399f41b630Keisuke Kuroyanagi    insertCharactersIntoVector(key, &keyVector);
17731097a57cc6f8022abc0ea56f27147399f41b630Keisuke Kuroyanagi    setIntAttributeInner(headerAttributes, &keyVector, value);
17831097a57cc6f8022abc0ea56f27147399f41b630Keisuke Kuroyanagi}
17931097a57cc6f8022abc0ea56f27147399f41b630Keisuke Kuroyanagi
18031097a57cc6f8022abc0ea56f27147399f41b630Keisuke Kuroyanagi/* static */ void HeaderReadWriteUtils::setIntAttributeInner(AttributeMap *const headerAttributes,
181989596844e05b551d8fc6bb64c343677da0e4f7fKeisuke Kuroyanagi        const AttributeMap::key_type *const key, const int value) {
182989596844e05b551d8fc6bb64c343677da0e4f7fKeisuke Kuroyanagi    AttributeMap::mapped_type valueVector;
183fc2858c55bf64ef96b1b60f19db23de4b0c62c9cKen Wakasa    char charBuf[LARGEST_INT_DIGIT_COUNT];
184fc2858c55bf64ef96b1b60f19db23de4b0c62c9cKen Wakasa    snprintf(charBuf, sizeof(charBuf), "%d", value);
185989596844e05b551d8fc6bb64c343677da0e4f7fKeisuke Kuroyanagi    insertCharactersIntoVector(charBuf, &valueVector);
186989596844e05b551d8fc6bb64c343677da0e4f7fKeisuke Kuroyanagi    (*headerAttributes)[*key] = valueVector;
187989596844e05b551d8fc6bb64c343677da0e4f7fKeisuke Kuroyanagi}
188989596844e05b551d8fc6bb64c343677da0e4f7fKeisuke Kuroyanagi
18943cf9076b2d053c554941e55f6073b8f586c510bJean Chalard/* static */ const std::vector<int> HeaderReadWriteUtils::readCodePointVectorAttributeValue(
19043cf9076b2d053c554941e55f6073b8f586c510bJean Chalard        const AttributeMap *const headerAttributes, const char *const key) {
19143cf9076b2d053c554941e55f6073b8f586c510bJean Chalard    AttributeMap::key_type keyVector;
19243cf9076b2d053c554941e55f6073b8f586c510bJean Chalard    insertCharactersIntoVector(key, &keyVector);
19343cf9076b2d053c554941e55f6073b8f586c510bJean Chalard    AttributeMap::const_iterator it = headerAttributes->find(keyVector);
19443cf9076b2d053c554941e55f6073b8f586c510bJean Chalard    if (it == headerAttributes->end()) {
19543cf9076b2d053c554941e55f6073b8f586c510bJean Chalard        return std::vector<int>();
19643cf9076b2d053c554941e55f6073b8f586c510bJean Chalard    } else {
19743cf9076b2d053c554941e55f6073b8f586c510bJean Chalard        return it->second;
19843cf9076b2d053c554941e55f6073b8f586c510bJean Chalard    }
19943cf9076b2d053c554941e55f6073b8f586c510bJean Chalard}
20043cf9076b2d053c554941e55f6073b8f586c510bJean Chalard
201989596844e05b551d8fc6bb64c343677da0e4f7fKeisuke Kuroyanagi/* static */ bool HeaderReadWriteUtils::readBoolAttributeValue(
20231097a57cc6f8022abc0ea56f27147399f41b630Keisuke Kuroyanagi        const AttributeMap *const headerAttributes, const char *const key,
203989596844e05b551d8fc6bb64c343677da0e4f7fKeisuke Kuroyanagi        const bool defaultValue) {
204989596844e05b551d8fc6bb64c343677da0e4f7fKeisuke Kuroyanagi    const int intDefaultValue = defaultValue ? 1 : 0;
205989596844e05b551d8fc6bb64c343677da0e4f7fKeisuke Kuroyanagi    const int intValue = readIntAttributeValue(headerAttributes, key, intDefaultValue);
206989596844e05b551d8fc6bb64c343677da0e4f7fKeisuke Kuroyanagi    return intValue != 0;
207989596844e05b551d8fc6bb64c343677da0e4f7fKeisuke Kuroyanagi}
208989596844e05b551d8fc6bb64c343677da0e4f7fKeisuke Kuroyanagi
209989596844e05b551d8fc6bb64c343677da0e4f7fKeisuke Kuroyanagi/* static */ int HeaderReadWriteUtils::readIntAttributeValue(
21031097a57cc6f8022abc0ea56f27147399f41b630Keisuke Kuroyanagi        const AttributeMap *const headerAttributes, const char *const key,
21131097a57cc6f8022abc0ea56f27147399f41b630Keisuke Kuroyanagi        const int defaultValue) {
21231097a57cc6f8022abc0ea56f27147399f41b630Keisuke Kuroyanagi    AttributeMap::key_type keyVector;
21331097a57cc6f8022abc0ea56f27147399f41b630Keisuke Kuroyanagi    insertCharactersIntoVector(key, &keyVector);
21431097a57cc6f8022abc0ea56f27147399f41b630Keisuke Kuroyanagi    return readIntAttributeValueInner(headerAttributes, &keyVector, defaultValue);
21531097a57cc6f8022abc0ea56f27147399f41b630Keisuke Kuroyanagi}
21631097a57cc6f8022abc0ea56f27147399f41b630Keisuke Kuroyanagi
21731097a57cc6f8022abc0ea56f27147399f41b630Keisuke Kuroyanagi/* static */ int HeaderReadWriteUtils::readIntAttributeValueInner(
218989596844e05b551d8fc6bb64c343677da0e4f7fKeisuke Kuroyanagi        const AttributeMap *const headerAttributes, const AttributeMap::key_type *const key,
219989596844e05b551d8fc6bb64c343677da0e4f7fKeisuke Kuroyanagi        const int defaultValue) {
220989596844e05b551d8fc6bb64c343677da0e4f7fKeisuke Kuroyanagi    AttributeMap::const_iterator it = headerAttributes->find(*key);
221989596844e05b551d8fc6bb64c343677da0e4f7fKeisuke Kuroyanagi    if (it != headerAttributes->end()) {
222989596844e05b551d8fc6bb64c343677da0e4f7fKeisuke Kuroyanagi        int value = 0;
223989596844e05b551d8fc6bb64c343677da0e4f7fKeisuke Kuroyanagi        bool isNegative = false;
224989596844e05b551d8fc6bb64c343677da0e4f7fKeisuke Kuroyanagi        for (size_t i = 0; i < it->second.size(); ++i) {
225989596844e05b551d8fc6bb64c343677da0e4f7fKeisuke Kuroyanagi            if (i == 0 && it->second.at(i) == '-') {
226989596844e05b551d8fc6bb64c343677da0e4f7fKeisuke Kuroyanagi                isNegative = true;
227989596844e05b551d8fc6bb64c343677da0e4f7fKeisuke Kuroyanagi            } else {
228989596844e05b551d8fc6bb64c343677da0e4f7fKeisuke Kuroyanagi                if (!isdigit(it->second.at(i))) {
229989596844e05b551d8fc6bb64c343677da0e4f7fKeisuke Kuroyanagi                    // If not a number.
230989596844e05b551d8fc6bb64c343677da0e4f7fKeisuke Kuroyanagi                    return defaultValue;
231989596844e05b551d8fc6bb64c343677da0e4f7fKeisuke Kuroyanagi                }
232989596844e05b551d8fc6bb64c343677da0e4f7fKeisuke Kuroyanagi                value *= 10;
233989596844e05b551d8fc6bb64c343677da0e4f7fKeisuke Kuroyanagi                value += it->second.at(i) - '0';
234989596844e05b551d8fc6bb64c343677da0e4f7fKeisuke Kuroyanagi            }
235989596844e05b551d8fc6bb64c343677da0e4f7fKeisuke Kuroyanagi        }
236989596844e05b551d8fc6bb64c343677da0e4f7fKeisuke Kuroyanagi        return isNegative ? -value : value;
237989596844e05b551d8fc6bb64c343677da0e4f7fKeisuke Kuroyanagi    }
238989596844e05b551d8fc6bb64c343677da0e4f7fKeisuke Kuroyanagi    return defaultValue;
239989596844e05b551d8fc6bb64c343677da0e4f7fKeisuke Kuroyanagi}
240989596844e05b551d8fc6bb64c343677da0e4f7fKeisuke Kuroyanagi
241989596844e05b551d8fc6bb64c343677da0e4f7fKeisuke Kuroyanagi/* static */ void HeaderReadWriteUtils::insertCharactersIntoVector(const char *const characters,
242989596844e05b551d8fc6bb64c343677da0e4f7fKeisuke Kuroyanagi        std::vector<int> *const vector) {
243989596844e05b551d8fc6bb64c343677da0e4f7fKeisuke Kuroyanagi    for (int i = 0; characters[i]; ++i) {
244989596844e05b551d8fc6bb64c343677da0e4f7fKeisuke Kuroyanagi        vector->push_back(characters[i]);
245989596844e05b551d8fc6bb64c343677da0e4f7fKeisuke Kuroyanagi    }
246989596844e05b551d8fc6bb64c343677da0e4f7fKeisuke Kuroyanagi}
247989596844e05b551d8fc6bb64c343677da0e4f7fKeisuke Kuroyanagi
248bd0d1afdb28a28e2ddac1409208c59ba64350399Keisuke Kuroynagi} // namespace latinime
249