header_read_write_utils.cpp revision 5ae8722bd52b0f70ab7cd3bd888585422bef9563
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
17bd0d1afdb28a28e2ddac1409208c59ba64350399Keisuke Kuroynagi#include "suggest/core/dictionary/binary_dictionary_header_reading_utils.h"
18bd0d1afdb28a28e2ddac1409208c59ba64350399Keisuke Kuroynagi
19bd0d1afdb28a28e2ddac1409208c59ba64350399Keisuke Kuroynagi#include <cctype>
20bd0d1afdb28a28e2ddac1409208c59ba64350399Keisuke Kuroynagi#include <cstdlib>
21bd0d1afdb28a28e2ddac1409208c59ba64350399Keisuke Kuroynagi
22bd0d1afdb28a28e2ddac1409208c59ba64350399Keisuke Kuroynagi#include "defines.h"
23bd0d1afdb28a28e2ddac1409208c59ba64350399Keisuke Kuroynagi#include "suggest/core/dictionary/binary_dictionary_info.h"
24bd0d1afdb28a28e2ddac1409208c59ba64350399Keisuke Kuroynagi
25bd0d1afdb28a28e2ddac1409208c59ba64350399Keisuke Kuroynaginamespace latinime {
26bd0d1afdb28a28e2ddac1409208c59ba64350399Keisuke Kuroynagi
27c44536973208bebf1fdd2e4d13e947eb541678d7Ken Wakasaconst int BinaryDictionaryHeaderReadingUtils::MAX_OPTION_KEY_LENGTH = 256;
28bd0d1afdb28a28e2ddac1409208c59ba64350399Keisuke Kuroynagi
295ae8722bd52b0f70ab7cd3bd888585422bef9563Keisuke Kuroynagiconst int BinaryDictionaryHeaderReadingUtils::VERSION_2_HEADER_MAGIC_NUMBER_SIZE = 4;
305ae8722bd52b0f70ab7cd3bd888585422bef9563Keisuke Kuroynagiconst int BinaryDictionaryHeaderReadingUtils::VERSION_2_HEADER_DICTIONARY_VERSION_SIZE = 2;
315ae8722bd52b0f70ab7cd3bd888585422bef9563Keisuke Kuroynagiconst int BinaryDictionaryHeaderReadingUtils::VERSION_2_HEADER_FLAG_SIZE = 2;
325ae8722bd52b0f70ab7cd3bd888585422bef9563Keisuke Kuroynagiconst int BinaryDictionaryHeaderReadingUtils::VERSION_2_HEADER_SIZE_FIELD_SIZE = 4;
33bd0d1afdb28a28e2ddac1409208c59ba64350399Keisuke Kuroynagi
34c44536973208bebf1fdd2e4d13e947eb541678d7Ken Wakasaconst BinaryDictionaryHeaderReadingUtils::DictionaryFlags
35c44536973208bebf1fdd2e4d13e947eb541678d7Ken Wakasa        BinaryDictionaryHeaderReadingUtils::NO_FLAGS = 0;
36bd0d1afdb28a28e2ddac1409208c59ba64350399Keisuke Kuroynagi// Flags for special processing
37bd0d1afdb28a28e2ddac1409208c59ba64350399Keisuke Kuroynagi// Those *must* match the flags in makedict (BinaryDictInputOutput#*_PROCESSING_FLAG) or
38bd0d1afdb28a28e2ddac1409208c59ba64350399Keisuke Kuroynagi// something very bad (like, the apocalypse) will happen. Please update both at the same time.
39c44536973208bebf1fdd2e4d13e947eb541678d7Ken Wakasaconst BinaryDictionaryHeaderReadingUtils::DictionaryFlags
40c44536973208bebf1fdd2e4d13e947eb541678d7Ken Wakasa        BinaryDictionaryHeaderReadingUtils::GERMAN_UMLAUT_PROCESSING_FLAG = 0x1;
41c44536973208bebf1fdd2e4d13e947eb541678d7Ken Wakasaconst BinaryDictionaryHeaderReadingUtils::DictionaryFlags
42c44536973208bebf1fdd2e4d13e947eb541678d7Ken Wakasa        BinaryDictionaryHeaderReadingUtils::SUPPORTS_DYNAMIC_UPDATE_FLAG = 0x2;
43c44536973208bebf1fdd2e4d13e947eb541678d7Ken Wakasaconst BinaryDictionaryHeaderReadingUtils::DictionaryFlags
44c44536973208bebf1fdd2e4d13e947eb541678d7Ken Wakasa        BinaryDictionaryHeaderReadingUtils::FRENCH_LIGATURE_PROCESSING_FLAG = 0x4;
45bd0d1afdb28a28e2ddac1409208c59ba64350399Keisuke Kuroynagi
46c44536973208bebf1fdd2e4d13e947eb541678d7Ken Wakasa/* static */ int BinaryDictionaryHeaderReadingUtils::getHeaderSize(
47bd0d1afdb28a28e2ddac1409208c59ba64350399Keisuke Kuroynagi        const BinaryDictionaryInfo *const binaryDictionaryInfo) {
485ae8722bd52b0f70ab7cd3bd888585422bef9563Keisuke Kuroynagi    switch (getHeaderVersion(binaryDictionaryInfo->getFormat())) {
495ae8722bd52b0f70ab7cd3bd888585422bef9563Keisuke Kuroynagi        case HEADER_VERSION_2:
50bd0d1afdb28a28e2ddac1409208c59ba64350399Keisuke Kuroynagi            // See the format of the header in the comment in
51bd0d1afdb28a28e2ddac1409208c59ba64350399Keisuke Kuroynagi            // BinaryDictionaryFormatUtils::detectFormatVersion()
52bd0d1afdb28a28e2ddac1409208c59ba64350399Keisuke Kuroynagi            return ByteArrayUtils::readUint32(binaryDictionaryInfo->getDictBuf(),
535ae8722bd52b0f70ab7cd3bd888585422bef9563Keisuke Kuroynagi                    VERSION_2_HEADER_MAGIC_NUMBER_SIZE + VERSION_2_HEADER_DICTIONARY_VERSION_SIZE
545ae8722bd52b0f70ab7cd3bd888585422bef9563Keisuke Kuroynagi                            + VERSION_2_HEADER_FLAG_SIZE);
55bd0d1afdb28a28e2ddac1409208c59ba64350399Keisuke Kuroynagi        default:
56bd0d1afdb28a28e2ddac1409208c59ba64350399Keisuke Kuroynagi            return S_INT_MAX;
57bd0d1afdb28a28e2ddac1409208c59ba64350399Keisuke Kuroynagi    }
58bd0d1afdb28a28e2ddac1409208c59ba64350399Keisuke Kuroynagi}
59bd0d1afdb28a28e2ddac1409208c59ba64350399Keisuke Kuroynagi
60c44536973208bebf1fdd2e4d13e947eb541678d7Ken Wakasa/* static */ BinaryDictionaryHeaderReadingUtils::DictionaryFlags
61c44536973208bebf1fdd2e4d13e947eb541678d7Ken Wakasa        BinaryDictionaryHeaderReadingUtils::getFlags(
62c44536973208bebf1fdd2e4d13e947eb541678d7Ken Wakasa                const BinaryDictionaryInfo *const binaryDictionaryInfo) {
635ae8722bd52b0f70ab7cd3bd888585422bef9563Keisuke Kuroynagi    switch (getHeaderVersion(binaryDictionaryInfo->getFormat())) {
645ae8722bd52b0f70ab7cd3bd888585422bef9563Keisuke Kuroynagi        case HEADER_VERSION_2:
65bd0d1afdb28a28e2ddac1409208c59ba64350399Keisuke Kuroynagi            return ByteArrayUtils::readUint16(binaryDictionaryInfo->getDictBuf(),
665ae8722bd52b0f70ab7cd3bd888585422bef9563Keisuke Kuroynagi                    VERSION_2_HEADER_MAGIC_NUMBER_SIZE + VERSION_2_HEADER_DICTIONARY_VERSION_SIZE);
67bd0d1afdb28a28e2ddac1409208c59ba64350399Keisuke Kuroynagi        default:
68bd0d1afdb28a28e2ddac1409208c59ba64350399Keisuke Kuroynagi            return NO_FLAGS;
69bd0d1afdb28a28e2ddac1409208c59ba64350399Keisuke Kuroynagi    }
70bd0d1afdb28a28e2ddac1409208c59ba64350399Keisuke Kuroynagi}
71bd0d1afdb28a28e2ddac1409208c59ba64350399Keisuke Kuroynagi
72bd0d1afdb28a28e2ddac1409208c59ba64350399Keisuke Kuroynagi// Returns if the key is found or not and reads the found value into outValue.
73c44536973208bebf1fdd2e4d13e947eb541678d7Ken Wakasa/* static */ bool BinaryDictionaryHeaderReadingUtils::readHeaderValue(
74bd0d1afdb28a28e2ddac1409208c59ba64350399Keisuke Kuroynagi        const BinaryDictionaryInfo *const binaryDictionaryInfo,
75bd0d1afdb28a28e2ddac1409208c59ba64350399Keisuke Kuroynagi        const char *const key, int *outValue, const int outValueSize) {
765ae8722bd52b0f70ab7cd3bd888585422bef9563Keisuke Kuroynagi    if (outValueSize <= 0) {
77bd0d1afdb28a28e2ddac1409208c59ba64350399Keisuke Kuroynagi        return false;
78bd0d1afdb28a28e2ddac1409208c59ba64350399Keisuke Kuroynagi    }
79bd0d1afdb28a28e2ddac1409208c59ba64350399Keisuke Kuroynagi    const int headerSize = getHeaderSize(binaryDictionaryInfo);
80bd0d1afdb28a28e2ddac1409208c59ba64350399Keisuke Kuroynagi    int pos = getHeaderOptionsPosition(binaryDictionaryInfo->getFormat());
815ae8722bd52b0f70ab7cd3bd888585422bef9563Keisuke Kuroynagi    if (pos == NOT_A_DICT_POS) {
825ae8722bd52b0f70ab7cd3bd888585422bef9563Keisuke Kuroynagi        // The header doesn't have header options.
835ae8722bd52b0f70ab7cd3bd888585422bef9563Keisuke Kuroynagi        return false;
845ae8722bd52b0f70ab7cd3bd888585422bef9563Keisuke Kuroynagi    }
85bd0d1afdb28a28e2ddac1409208c59ba64350399Keisuke Kuroynagi    while (pos < headerSize) {
86bd0d1afdb28a28e2ddac1409208c59ba64350399Keisuke Kuroynagi        if(ByteArrayUtils::compareStringInBufferWithCharArray(
87bd0d1afdb28a28e2ddac1409208c59ba64350399Keisuke Kuroynagi                binaryDictionaryInfo->getDictBuf(), key, headerSize - pos, &pos) == 0) {
88bd0d1afdb28a28e2ddac1409208c59ba64350399Keisuke Kuroynagi            // The key was found.
89bd0d1afdb28a28e2ddac1409208c59ba64350399Keisuke Kuroynagi            ByteArrayUtils::readStringAndAdvancePosition(
90bd0d1afdb28a28e2ddac1409208c59ba64350399Keisuke Kuroynagi                    binaryDictionaryInfo->getDictBuf(), outValueSize, outValue, &pos);
91bd0d1afdb28a28e2ddac1409208c59ba64350399Keisuke Kuroynagi            return true;
92bd0d1afdb28a28e2ddac1409208c59ba64350399Keisuke Kuroynagi        }
93bd0d1afdb28a28e2ddac1409208c59ba64350399Keisuke Kuroynagi        ByteArrayUtils::advancePositionToBehindString(
94bd0d1afdb28a28e2ddac1409208c59ba64350399Keisuke Kuroynagi                binaryDictionaryInfo->getDictBuf(), headerSize - pos, &pos);
95bd0d1afdb28a28e2ddac1409208c59ba64350399Keisuke Kuroynagi    }
96bd0d1afdb28a28e2ddac1409208c59ba64350399Keisuke Kuroynagi    // The key was not found.
97bd0d1afdb28a28e2ddac1409208c59ba64350399Keisuke Kuroynagi    return false;
98bd0d1afdb28a28e2ddac1409208c59ba64350399Keisuke Kuroynagi}
99bd0d1afdb28a28e2ddac1409208c59ba64350399Keisuke Kuroynagi
100c44536973208bebf1fdd2e4d13e947eb541678d7Ken Wakasa/* static */ int BinaryDictionaryHeaderReadingUtils::readHeaderValueInt(
101bd0d1afdb28a28e2ddac1409208c59ba64350399Keisuke Kuroynagi        const BinaryDictionaryInfo *const binaryDictionaryInfo, const char *const key) {
102bd0d1afdb28a28e2ddac1409208c59ba64350399Keisuke Kuroynagi    const int bufferSize = LARGEST_INT_DIGIT_COUNT;
103bd0d1afdb28a28e2ddac1409208c59ba64350399Keisuke Kuroynagi    int intBuffer[bufferSize];
104bd0d1afdb28a28e2ddac1409208c59ba64350399Keisuke Kuroynagi    char charBuffer[bufferSize];
105bd0d1afdb28a28e2ddac1409208c59ba64350399Keisuke Kuroynagi    if (!readHeaderValue(binaryDictionaryInfo, key, intBuffer, bufferSize)) {
106bd0d1afdb28a28e2ddac1409208c59ba64350399Keisuke Kuroynagi        return S_INT_MIN;
107bd0d1afdb28a28e2ddac1409208c59ba64350399Keisuke Kuroynagi    }
108bd0d1afdb28a28e2ddac1409208c59ba64350399Keisuke Kuroynagi    for (int i = 0; i < bufferSize; ++i) {
109bd0d1afdb28a28e2ddac1409208c59ba64350399Keisuke Kuroynagi        charBuffer[i] = intBuffer[i];
110bd0d1afdb28a28e2ddac1409208c59ba64350399Keisuke Kuroynagi        if (charBuffer[i] == '0') {
111bd0d1afdb28a28e2ddac1409208c59ba64350399Keisuke Kuroynagi            break;
112bd0d1afdb28a28e2ddac1409208c59ba64350399Keisuke Kuroynagi        }
113bd0d1afdb28a28e2ddac1409208c59ba64350399Keisuke Kuroynagi        if (!isdigit(charBuffer[i])) {
114bd0d1afdb28a28e2ddac1409208c59ba64350399Keisuke Kuroynagi            // If not a number, return S_INT_MIN
115bd0d1afdb28a28e2ddac1409208c59ba64350399Keisuke Kuroynagi            return S_INT_MIN;
116bd0d1afdb28a28e2ddac1409208c59ba64350399Keisuke Kuroynagi        }
117bd0d1afdb28a28e2ddac1409208c59ba64350399Keisuke Kuroynagi    }
118bd0d1afdb28a28e2ddac1409208c59ba64350399Keisuke Kuroynagi    return atoi(charBuffer);
119bd0d1afdb28a28e2ddac1409208c59ba64350399Keisuke Kuroynagi}
120bd0d1afdb28a28e2ddac1409208c59ba64350399Keisuke Kuroynagi
121bd0d1afdb28a28e2ddac1409208c59ba64350399Keisuke Kuroynagi} // namespace latinime
122