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