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 "dictionary/utils/format_utils.h"
18 
19 #include "dictionary/utils/byte_array_utils.h"
20 
21 namespace latinime {
22 
23 const uint32_t FormatUtils::MAGIC_NUMBER = 0x9BC13AFE;
24 
25 // Magic number (4 bytes), version (2 bytes), flags (2 bytes), header size (4 bytes) = 12
26 const size_t FormatUtils::DICTIONARY_MINIMUM_SIZE = 12;
27 
getFormatVersion(const int formatVersion)28 /* static */ FormatUtils::FORMAT_VERSION FormatUtils::getFormatVersion(const int formatVersion) {
29     switch (formatVersion) {
30         case VERSION_2:
31         case VERSION_201:
32             AKLOGE("Dictionary versions 2 and 201 are incompatible with this version");
33             return UNKNOWN_VERSION;
34         case VERSION_202:
35             return VERSION_202;
36         case VERSION_4_ONLY_FOR_TESTING:
37             return VERSION_4_ONLY_FOR_TESTING;
38         case VERSION_402:
39             return VERSION_402;
40         case VERSION_403:
41             return VERSION_403;
42         default:
43             return UNKNOWN_VERSION;
44     }
45 }
detectFormatVersion(const ReadOnlyByteArrayView dictBuffer)46 /* static */ FormatUtils::FORMAT_VERSION FormatUtils::detectFormatVersion(
47         const ReadOnlyByteArrayView dictBuffer) {
48     // The magic number is stored big-endian.
49     // If the dictionary is less than 4 bytes, we can't even read the magic number, so we don't
50     // understand this format.
51     if (dictBuffer.size() < DICTIONARY_MINIMUM_SIZE) {
52         return UNKNOWN_VERSION;
53     }
54     const uint32_t magicNumber = ByteArrayUtils::readUint32(dictBuffer.data(), 0);
55     switch (magicNumber) {
56         case MAGIC_NUMBER:
57             // The layout of the header is as follows:
58             // Magic number (4 bytes) 0x9B 0xC1 0x3A 0xFE
59             // Dictionary format version number (2 bytes)
60             // Options (2 bytes)
61             // Header size (4 bytes) : integer, big endian
62             // Conceptually this converts the hardcoded value of the bytes in the file into
63             // the symbolic value we use in the code. But we want the constants to be the
64             // same so we use them for both here.
65             return getFormatVersion(ByteArrayUtils::readUint16(dictBuffer.data(), 4));
66         default:
67             return UNKNOWN_VERSION;
68     }
69 }
70 
71 } // namespace latinime
72