10ecfb9424754341d7ee41557fc1f913cb6ca79c2Keisuke Kuroyanagi/*
20ecfb9424754341d7ee41557fc1f913cb6ca79c2Keisuke Kuroyanagi * Copyright (C) 2013 The Android Open Source Project
30ecfb9424754341d7ee41557fc1f913cb6ca79c2Keisuke Kuroyanagi *
40ecfb9424754341d7ee41557fc1f913cb6ca79c2Keisuke Kuroyanagi * Licensed under the Apache License, Version 2.0 (the "License");
50ecfb9424754341d7ee41557fc1f913cb6ca79c2Keisuke Kuroyanagi * you may not use this file except in compliance with the License.
60ecfb9424754341d7ee41557fc1f913cb6ca79c2Keisuke Kuroyanagi * You may obtain a copy of the License at
70ecfb9424754341d7ee41557fc1f913cb6ca79c2Keisuke Kuroyanagi *
80ecfb9424754341d7ee41557fc1f913cb6ca79c2Keisuke Kuroyanagi *      http://www.apache.org/licenses/LICENSE-2.0
90ecfb9424754341d7ee41557fc1f913cb6ca79c2Keisuke Kuroyanagi *
100ecfb9424754341d7ee41557fc1f913cb6ca79c2Keisuke Kuroyanagi * Unless required by applicable law or agreed to in writing, software
110ecfb9424754341d7ee41557fc1f913cb6ca79c2Keisuke Kuroyanagi * distributed under the License is distributed on an "AS IS" BASIS,
120ecfb9424754341d7ee41557fc1f913cb6ca79c2Keisuke Kuroyanagi * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
130ecfb9424754341d7ee41557fc1f913cb6ca79c2Keisuke Kuroyanagi * See the License for the specific language governing permissions and
140ecfb9424754341d7ee41557fc1f913cb6ca79c2Keisuke Kuroyanagi * limitations under the License.
150ecfb9424754341d7ee41557fc1f913cb6ca79c2Keisuke Kuroyanagi */
160ecfb9424754341d7ee41557fc1f913cb6ca79c2Keisuke Kuroyanagi
1790619ae02b1861e644db6a0d72d0e5f9c195ef3eKeisuke Kuroyanagi#include "suggest/policyimpl/dictionary/utils/format_utils.h"
180ecfb9424754341d7ee41557fc1f913cb6ca79c2Keisuke Kuroyanagi
1990619ae02b1861e644db6a0d72d0e5f9c195ef3eKeisuke Kuroyanagi#include "suggest/policyimpl/dictionary/utils/byte_array_utils.h"
2099007de979e006b6b08bf381f2d394377264de85Keisuke Kuroyanagi
210ecfb9424754341d7ee41557fc1f913cb6ca79c2Keisuke Kuroyanaginamespace latinime {
220ecfb9424754341d7ee41557fc1f913cb6ca79c2Keisuke Kuroyanagi
23484fa7b59cb0659ac18fa68da5c7b641d9255be8Keisuke Kuroyanagiconst uint32_t FormatUtils::MAGIC_NUMBER = 0x9BC13AFE;
240ecfb9424754341d7ee41557fc1f913cb6ca79c2Keisuke Kuroyanagi
25484fa7b59cb0659ac18fa68da5c7b641d9255be8Keisuke Kuroyanagi// Magic number (4 bytes), version (2 bytes), flags (2 bytes), header size (4 bytes) = 12
26484fa7b59cb0659ac18fa68da5c7b641d9255be8Keisuke Kuroyanagiconst int FormatUtils::DICTIONARY_MINIMUM_SIZE = 12;
270ecfb9424754341d7ee41557fc1f913cb6ca79c2Keisuke Kuroyanagi
2890619ae02b1861e644db6a0d72d0e5f9c195ef3eKeisuke Kuroyanagi/* static */ FormatUtils::FORMAT_VERSION FormatUtils::detectFormatVersion(
2990619ae02b1861e644db6a0d72d0e5f9c195ef3eKeisuke Kuroyanagi        const uint8_t *const dict, const int dictSize) {
300ecfb9424754341d7ee41557fc1f913cb6ca79c2Keisuke Kuroyanagi    // The magic number is stored big-endian.
310ecfb9424754341d7ee41557fc1f913cb6ca79c2Keisuke Kuroyanagi    // If the dictionary is less than 4 bytes, we can't even read the magic number, so we don't
320ecfb9424754341d7ee41557fc1f913cb6ca79c2Keisuke Kuroyanagi    // understand this format.
330ecfb9424754341d7ee41557fc1f913cb6ca79c2Keisuke Kuroyanagi    if (dictSize < DICTIONARY_MINIMUM_SIZE) {
340ecfb9424754341d7ee41557fc1f913cb6ca79c2Keisuke Kuroyanagi        return UNKNOWN_VERSION;
350ecfb9424754341d7ee41557fc1f913cb6ca79c2Keisuke Kuroyanagi    }
360ecfb9424754341d7ee41557fc1f913cb6ca79c2Keisuke Kuroyanagi    const uint32_t magicNumber = ByteArrayUtils::readUint32(dict, 0);
370ecfb9424754341d7ee41557fc1f913cb6ca79c2Keisuke Kuroyanagi    switch (magicNumber) {
38484fa7b59cb0659ac18fa68da5c7b641d9255be8Keisuke Kuroyanagi        case MAGIC_NUMBER:
395ae8722bd52b0f70ab7cd3bd888585422bef9563Keisuke Kuroynagi            // Version 2 header is as follows:
405ae8722bd52b0f70ab7cd3bd888585422bef9563Keisuke Kuroynagi            // Magic number (4 bytes) 0x9B 0xC1 0x3A 0xFE
41484fa7b59cb0659ac18fa68da5c7b641d9255be8Keisuke Kuroyanagi            // Dictionary format version number (2 bytes)
425ae8722bd52b0f70ab7cd3bd888585422bef9563Keisuke Kuroynagi            // Options (2 bytes)
435ae8722bd52b0f70ab7cd3bd888585422bef9563Keisuke Kuroynagi            // Header size (4 bytes) : integer, big endian
445ae8722bd52b0f70ab7cd3bd888585422bef9563Keisuke Kuroynagi            if (ByteArrayUtils::readUint16(dict, 4) == 2) {
455ae8722bd52b0f70ab7cd3bd888585422bef9563Keisuke Kuroynagi                return VERSION_2;
465ae8722bd52b0f70ab7cd3bd888585422bef9563Keisuke Kuroynagi            } else if (ByteArrayUtils::readUint16(dict, 4) == 3) {
4760eb250194f05a944447e8bdee94c35a01911870Keisuke Kuroyanagi                return VERSION_3;
485ae8722bd52b0f70ab7cd3bd888585422bef9563Keisuke Kuroynagi            } else {
495ae8722bd52b0f70ab7cd3bd888585422bef9563Keisuke Kuroynagi                return UNKNOWN_VERSION;
505ae8722bd52b0f70ab7cd3bd888585422bef9563Keisuke Kuroynagi            }
515ae8722bd52b0f70ab7cd3bd888585422bef9563Keisuke Kuroynagi        default:
520ecfb9424754341d7ee41557fc1f913cb6ca79c2Keisuke Kuroyanagi            return UNKNOWN_VERSION;
530ecfb9424754341d7ee41557fc1f913cb6ca79c2Keisuke Kuroyanagi    }
540ecfb9424754341d7ee41557fc1f913cb6ca79c2Keisuke Kuroyanagi}
550ecfb9424754341d7ee41557fc1f913cb6ca79c2Keisuke Kuroyanagi
560ecfb9424754341d7ee41557fc1f913cb6ca79c2Keisuke Kuroyanagi} // namespace latinime
57