dictionary_structure_with_buffer_policy_factory.cpp revision 455dc84cf2c6526329b535f30000ea45b7d4d4d7
12fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa/*
22fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa * Copyright (C) 2013 The Android Open Source Project
32fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa *
42fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa * Licensed under the Apache License, Version 2.0 (the "License");
52fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa * you may not use this file except in compliance with the License.
62fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa * You may obtain a copy of the License at
72fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa *
82fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa *      http://www.apache.org/licenses/LICENSE-2.0
92fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa *
102fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa * Unless required by applicable law or agreed to in writing, software
112fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa * distributed under the License is distributed on an "AS IS" BASIS,
122fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
132fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa * See the License for the specific language governing permissions and
142fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa * limitations under the License.
152fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa */
162fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa
172fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa#include "suggest/policyimpl/dictionary/structure/dictionary_structure_with_buffer_policy_factory.h"
182fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa
192fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa#include <climits>
202fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa
212fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa#include "defines.h"
223b7984752c88bff157016a09158dc92d94ed401dKeisuke Kuroyanagi#include "suggest/policyimpl/dictionary/structure/pt_common/dynamic_pt_writing_utils.h"
232fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa#include "suggest/policyimpl/dictionary/structure/v2/patricia_trie_policy.h"
242fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa#include "suggest/policyimpl/dictionary/structure/v4/ver4_dict_buffers.h"
252fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa#include "suggest/policyimpl/dictionary/structure/v4/ver4_dict_constants.h"
262fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa#include "suggest/policyimpl/dictionary/structure/v4/ver4_patricia_trie_policy.h"
273b7984752c88bff157016a09158dc92d94ed401dKeisuke Kuroyanagi#include "suggest/policyimpl/dictionary/utils/dict_file_writing_utils.h"
282fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa#include "suggest/policyimpl/dictionary/utils/file_utils.h"
292fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa#include "suggest/policyimpl/dictionary/utils/format_utils.h"
302fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa#include "suggest/policyimpl/dictionary/utils/mmapped_buffer.h"
312fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa
322fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasanamespace latinime {
332fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa
342fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa/* static */ DictionaryStructureWithBufferPolicy::StructurePolicyPtr
35903be5bbd33b664c7e691d8bee0dd4d6376947bcKeisuke Kuroyanagi        DictionaryStructureWithBufferPolicyFactory::newPolicyForExistingDictFile(
36903be5bbd33b664c7e691d8bee0dd4d6376947bcKeisuke Kuroyanagi                const char *const path, const int bufOffset, const int size,
37903be5bbd33b664c7e691d8bee0dd4d6376947bcKeisuke Kuroyanagi                const bool isUpdatable) {
382fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa    if (FileUtils::existsDir(path)) {
392fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa        // Given path represents a directory.
40903be5bbd33b664c7e691d8bee0dd4d6376947bcKeisuke Kuroyanagi        return newPolicyForDirectoryDict(path, isUpdatable);
412fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa    } else {
422fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa        if (isUpdatable) {
432fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa            AKLOGE("One file dictionaries don't support updating. path: %s", path);
442fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa            ASSERT(false);
454ce480d5ce2d47f607448ce439aaf2cefba1bdd8Keisuke Kuroyanagi            return DictionaryStructureWithBufferPolicy::StructurePolicyPtr(nullptr);
462fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa        }
47903be5bbd33b664c7e691d8bee0dd4d6376947bcKeisuke Kuroyanagi        return newPolicyForFileDict(path, bufOffset, size);
482fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa    }
492fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa}
502fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa
512fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa/* static */ DictionaryStructureWithBufferPolicy::StructurePolicyPtr
52903be5bbd33b664c7e691d8bee0dd4d6376947bcKeisuke Kuroyanagi        DictionaryStructureWithBufferPolicyFactory:: newPolicyForOnMemoryDict(
53903be5bbd33b664c7e691d8bee0dd4d6376947bcKeisuke Kuroyanagi                const int formatVersion, const std::vector<int> &locale,
54903be5bbd33b664c7e691d8bee0dd4d6376947bcKeisuke Kuroyanagi                const DictionaryHeaderStructurePolicy::AttributeMap *const attributeMap) {
55455dc84cf2c6526329b535f30000ea45b7d4d4d7Keisuke Kuroyanagi    FormatUtils::FORMAT_VERSION dictFormatVersion = FormatUtils::getFormatVersion(formatVersion);
56455dc84cf2c6526329b535f30000ea45b7d4d4d7Keisuke Kuroyanagi    switch (dictFormatVersion) {
57455dc84cf2c6526329b535f30000ea45b7d4d4d7Keisuke Kuroyanagi        case FormatUtils::VERSION_4_ONLY_FOR_TESTING:
58903be5bbd33b664c7e691d8bee0dd4d6376947bcKeisuke Kuroyanagi        case FormatUtils::VERSION_4: {
59455dc84cf2c6526329b535f30000ea45b7d4d4d7Keisuke Kuroyanagi            HeaderPolicy headerPolicy(dictFormatVersion, locale, attributeMap);
60903be5bbd33b664c7e691d8bee0dd4d6376947bcKeisuke Kuroyanagi            Ver4DictBuffers::Ver4DictBuffersPtr dictBuffers =
61903be5bbd33b664c7e691d8bee0dd4d6376947bcKeisuke Kuroyanagi                    Ver4DictBuffers::createVer4DictBuffers(&headerPolicy,
62903be5bbd33b664c7e691d8bee0dd4d6376947bcKeisuke Kuroyanagi                            Ver4DictConstants::MAX_DICT_EXTENDED_REGION_SIZE);
633b7984752c88bff157016a09158dc92d94ed401dKeisuke Kuroyanagi            if (!DynamicPtWritingUtils::writeEmptyDictionary(
643b7984752c88bff157016a09158dc92d94ed401dKeisuke Kuroyanagi                    dictBuffers->getWritableTrieBuffer(), 0 /* rootPos */)) {
653b7984752c88bff157016a09158dc92d94ed401dKeisuke Kuroyanagi                AKLOGE("Empty ver4 dictionary structure cannot be created on memory.");
663b7984752c88bff157016a09158dc92d94ed401dKeisuke Kuroyanagi                return DictionaryStructureWithBufferPolicy::StructurePolicyPtr(nullptr);
673b7984752c88bff157016a09158dc92d94ed401dKeisuke Kuroyanagi            }
68903be5bbd33b664c7e691d8bee0dd4d6376947bcKeisuke Kuroyanagi            return DictionaryStructureWithBufferPolicy::StructurePolicyPtr(
69903be5bbd33b664c7e691d8bee0dd4d6376947bcKeisuke Kuroyanagi                    new Ver4PatriciaTriePolicy(std::move(dictBuffers)));
70903be5bbd33b664c7e691d8bee0dd4d6376947bcKeisuke Kuroyanagi        }
71903be5bbd33b664c7e691d8bee0dd4d6376947bcKeisuke Kuroyanagi        default:
72903be5bbd33b664c7e691d8bee0dd4d6376947bcKeisuke Kuroyanagi            AKLOGE("DICT: dictionary format %d is not supported for on memory dictionary",
73903be5bbd33b664c7e691d8bee0dd4d6376947bcKeisuke Kuroyanagi                    formatVersion);
74903be5bbd33b664c7e691d8bee0dd4d6376947bcKeisuke Kuroyanagi            break;
75903be5bbd33b664c7e691d8bee0dd4d6376947bcKeisuke Kuroyanagi    }
76903be5bbd33b664c7e691d8bee0dd4d6376947bcKeisuke Kuroyanagi    return DictionaryStructureWithBufferPolicy::StructurePolicyPtr(nullptr);
77903be5bbd33b664c7e691d8bee0dd4d6376947bcKeisuke Kuroyanagi}
78903be5bbd33b664c7e691d8bee0dd4d6376947bcKeisuke Kuroyanagi
79903be5bbd33b664c7e691d8bee0dd4d6376947bcKeisuke Kuroyanagi/* static */ DictionaryStructureWithBufferPolicy::StructurePolicyPtr
80903be5bbd33b664c7e691d8bee0dd4d6376947bcKeisuke Kuroyanagi        DictionaryStructureWithBufferPolicyFactory::newPolicyForDirectoryDict(
812fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa                const char *const path, const bool isUpdatable) {
822fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa    const int headerFilePathBufSize = PATH_MAX + 1 /* terminator */;
832fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa    char headerFilePath[headerFilePathBufSize];
842fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa    getHeaderFilePathInDictDir(path, headerFilePathBufSize, headerFilePath);
852fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa    // Allocated buffer in MmapedBuffer::openBuffer() will be freed in the destructor of
862fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa    // MmappedBufferPtr if the instance has the responsibility.
874ce480d5ce2d47f607448ce439aaf2cefba1bdd8Keisuke Kuroyanagi    MmappedBuffer::MmappedBufferPtr mmappedBuffer(
884ce480d5ce2d47f607448ce439aaf2cefba1bdd8Keisuke Kuroyanagi            MmappedBuffer::openBuffer(headerFilePath, isUpdatable));
894ce480d5ce2d47f607448ce439aaf2cefba1bdd8Keisuke Kuroyanagi    if (!mmappedBuffer) {
904ce480d5ce2d47f607448ce439aaf2cefba1bdd8Keisuke Kuroyanagi        return DictionaryStructureWithBufferPolicy::StructurePolicyPtr(nullptr);
912fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa    }
92455dc84cf2c6526329b535f30000ea45b7d4d4d7Keisuke Kuroyanagi    const FormatUtils::FORMAT_VERSION formatVersion = FormatUtils::detectFormatVersion(
93455dc84cf2c6526329b535f30000ea45b7d4d4d7Keisuke Kuroyanagi            mmappedBuffer->getBuffer(), mmappedBuffer->getBufferSize());
94455dc84cf2c6526329b535f30000ea45b7d4d4d7Keisuke Kuroyanagi    switch (formatVersion) {
952fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa        case FormatUtils::VERSION_2:
962fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa            AKLOGE("Given path is a directory but the format is version 2. path: %s", path);
972fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa            break;
98455dc84cf2c6526329b535f30000ea45b7d4d4d7Keisuke Kuroyanagi        case FormatUtils::VERSION_4_ONLY_FOR_TESTING:
992fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa        case FormatUtils::VERSION_4: {
1002fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa            const int dictDirPathBufSize = strlen(headerFilePath) + 1 /* terminator */;
1012fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa            char dictPath[dictDirPathBufSize];
1022fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa            if (!FileUtils::getFilePathWithoutSuffix(headerFilePath,
1032fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa                    Ver4DictConstants::HEADER_FILE_EXTENSION, dictDirPathBufSize, dictPath)) {
1042fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa                AKLOGE("Dictionary file name is not valid as a ver4 dictionary. path: %s", path);
1052fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa                ASSERT(false);
1064ce480d5ce2d47f607448ce439aaf2cefba1bdd8Keisuke Kuroyanagi                return DictionaryStructureWithBufferPolicy::StructurePolicyPtr(nullptr);
1072fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa            }
1084ce480d5ce2d47f607448ce439aaf2cefba1bdd8Keisuke Kuroyanagi            Ver4DictBuffers::Ver4DictBuffersPtr dictBuffers(
109455dc84cf2c6526329b535f30000ea45b7d4d4d7Keisuke Kuroyanagi                    Ver4DictBuffers::openVer4DictBuffers(dictPath, std::move(mmappedBuffer),
110455dc84cf2c6526329b535f30000ea45b7d4d4d7Keisuke Kuroyanagi                            formatVersion));
1114ce480d5ce2d47f607448ce439aaf2cefba1bdd8Keisuke Kuroyanagi            if (!dictBuffers || !dictBuffers->isValid()) {
1122fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa                AKLOGE("DICT: The dictionary doesn't satisfy ver4 format requirements. path: %s",
1132fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa                        path);
1142fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa                ASSERT(false);
1154ce480d5ce2d47f607448ce439aaf2cefba1bdd8Keisuke Kuroyanagi                return DictionaryStructureWithBufferPolicy::StructurePolicyPtr(nullptr);
1162fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa            }
1172fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa            return DictionaryStructureWithBufferPolicy::StructurePolicyPtr(
1184ce480d5ce2d47f607448ce439aaf2cefba1bdd8Keisuke Kuroyanagi                    new Ver4PatriciaTriePolicy(std::move(dictBuffers)));
1192fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa        }
1202fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa        default:
1212fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa            AKLOGE("DICT: dictionary format is unknown, bad magic number. path: %s", path);
1222fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa            break;
1232fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa    }
1242fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa    ASSERT(false);
1254ce480d5ce2d47f607448ce439aaf2cefba1bdd8Keisuke Kuroyanagi    return DictionaryStructureWithBufferPolicy::StructurePolicyPtr(nullptr);
1262fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa}
1272fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa
1282fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa/* static */ DictionaryStructureWithBufferPolicy::StructurePolicyPtr
129903be5bbd33b664c7e691d8bee0dd4d6376947bcKeisuke Kuroyanagi        DictionaryStructureWithBufferPolicyFactory::newPolicyForFileDict(
1302fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa                const char *const path, const int bufOffset, const int size) {
1312fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa    // Allocated buffer in MmapedBuffer::openBuffer() will be freed in the destructor of
1322fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa    // MmappedBufferPtr if the instance has the responsibility.
1334ce480d5ce2d47f607448ce439aaf2cefba1bdd8Keisuke Kuroyanagi    MmappedBuffer::MmappedBufferPtr mmappedBuffer(
1344ce480d5ce2d47f607448ce439aaf2cefba1bdd8Keisuke Kuroyanagi            MmappedBuffer::openBuffer(path, bufOffset, size, false /* isUpdatable */));
1354ce480d5ce2d47f607448ce439aaf2cefba1bdd8Keisuke Kuroyanagi    if (!mmappedBuffer) {
1364ce480d5ce2d47f607448ce439aaf2cefba1bdd8Keisuke Kuroyanagi        return DictionaryStructureWithBufferPolicy::StructurePolicyPtr(nullptr);
1372fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa    }
1384ce480d5ce2d47f607448ce439aaf2cefba1bdd8Keisuke Kuroyanagi    switch (FormatUtils::detectFormatVersion(mmappedBuffer->getBuffer(),
1394ce480d5ce2d47f607448ce439aaf2cefba1bdd8Keisuke Kuroyanagi            mmappedBuffer->getBufferSize())) {
1402fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa        case FormatUtils::VERSION_2:
1412fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa            return DictionaryStructureWithBufferPolicy::StructurePolicyPtr(
1424ce480d5ce2d47f607448ce439aaf2cefba1bdd8Keisuke Kuroyanagi                    new PatriciaTriePolicy(std::move(mmappedBuffer)));
143455dc84cf2c6526329b535f30000ea45b7d4d4d7Keisuke Kuroyanagi        case FormatUtils::VERSION_4_ONLY_FOR_TESTING:
1442fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa        case FormatUtils::VERSION_4:
1452fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa            AKLOGE("Given path is a file but the format is version 4. path: %s", path);
1462fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa            break;
1472fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa        default:
1482fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa            AKLOGE("DICT: dictionary format is unknown, bad magic number. path: %s", path);
1492fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa            break;
1502fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa    }
1512fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa    ASSERT(false);
1524ce480d5ce2d47f607448ce439aaf2cefba1bdd8Keisuke Kuroyanagi    return DictionaryStructureWithBufferPolicy::StructurePolicyPtr(nullptr);
1532fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa}
1542fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa
1552fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa/* static */ void DictionaryStructureWithBufferPolicyFactory::getHeaderFilePathInDictDir(
1562fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa        const char *const dictDirPath, const int outHeaderFileBufSize,
1572fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa        char *const outHeaderFilePath) {
1582fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa    const int dictNameBufSize = strlen(dictDirPath) + 1 /* terminator */;
1592fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa    char dictName[dictNameBufSize];
1602fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa    FileUtils::getBasename(dictDirPath, dictNameBufSize, dictName);
1612fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa    snprintf(outHeaderFilePath, outHeaderFileBufSize, "%s/%s%s", dictDirPath,
1622fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa            dictName, Ver4DictConstants::HEADER_FILE_EXTENSION);
1632fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa}
1642fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa
1652fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa} // namespace latinime
166