Home | History | Annotate | Download | only in structure
      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/structure/dictionary_structure_with_buffer_policy_factory.h"
     18 
     19 #include <climits>
     20 
     21 #include "defines.h"
     22 #include "dictionary/structure/backward/v402/ver4_dict_buffers.h"
     23 #include "dictionary/structure/backward/v402/ver4_dict_constants.h"
     24 #include "dictionary/structure/backward/v402/ver4_patricia_trie_policy.h"
     25 #include "dictionary/structure/pt_common/dynamic_pt_writing_utils.h"
     26 #include "dictionary/structure/v2/patricia_trie_policy.h"
     27 #include "dictionary/structure/v4/ver4_dict_buffers.h"
     28 #include "dictionary/structure/v4/ver4_dict_constants.h"
     29 #include "dictionary/structure/v4/ver4_patricia_trie_policy.h"
     30 #include "dictionary/utils/dict_file_writing_utils.h"
     31 #include "dictionary/utils/file_utils.h"
     32 #include "dictionary/utils/format_utils.h"
     33 #include "dictionary/utils/mmapped_buffer.h"
     34 #include "utils/byte_array_view.h"
     35 
     36 namespace latinime {
     37 
     38 /* static */ DictionaryStructureWithBufferPolicy::StructurePolicyPtr
     39         DictionaryStructureWithBufferPolicyFactory::newPolicyForExistingDictFile(
     40                 const char *const path, const int bufOffset, const int size,
     41                 const bool isUpdatable) {
     42     if (FileUtils::existsDir(path)) {
     43         // Given path represents a directory.
     44         return newPolicyForDirectoryDict(path, isUpdatable);
     45     } else {
     46         if (isUpdatable) {
     47             AKLOGE("One file dictionaries don't support updating. path: %s", path);
     48             ASSERT(false);
     49             return nullptr;
     50         }
     51         return newPolicyForFileDict(path, bufOffset, size);
     52     }
     53 }
     54 
     55 /* static */ DictionaryStructureWithBufferPolicy::StructurePolicyPtr
     56         DictionaryStructureWithBufferPolicyFactory:: newPolicyForOnMemoryDict(
     57                 const int formatVersion, const std::vector<int> &locale,
     58                 const DictionaryHeaderStructurePolicy::AttributeMap *const attributeMap) {
     59     FormatUtils::FORMAT_VERSION dictFormatVersion = FormatUtils::getFormatVersion(formatVersion);
     60     switch (dictFormatVersion) {
     61         case FormatUtils::VERSION_402: {
     62             return newPolicyForOnMemoryV4Dict<backward::v402::Ver4DictConstants,
     63                     backward::v402::Ver4DictBuffers,
     64                     backward::v402::Ver4DictBuffers::Ver4DictBuffersPtr,
     65                     backward::v402::Ver4PatriciaTriePolicy>(
     66                             dictFormatVersion, locale, attributeMap);
     67         }
     68         case FormatUtils::VERSION_4_ONLY_FOR_TESTING:
     69         case FormatUtils::VERSION_403: {
     70             return newPolicyForOnMemoryV4Dict<Ver4DictConstants, Ver4DictBuffers,
     71                     Ver4DictBuffers::Ver4DictBuffersPtr, Ver4PatriciaTriePolicy>(
     72                             dictFormatVersion, locale, attributeMap);
     73         }
     74         default:
     75             AKLOGE("DICT: dictionary format %d is not supported for on memory dictionary",
     76                     formatVersion);
     77             break;
     78     }
     79     return nullptr;
     80 }
     81 
     82 template<class DictConstants, class DictBuffers, class DictBuffersPtr, class StructurePolicy>
     83 /* static */ DictionaryStructureWithBufferPolicy::StructurePolicyPtr
     84         DictionaryStructureWithBufferPolicyFactory::newPolicyForOnMemoryV4Dict(
     85                 const FormatUtils::FORMAT_VERSION formatVersion,
     86                 const std::vector<int> &locale,
     87                 const DictionaryHeaderStructurePolicy::AttributeMap *const attributeMap) {
     88     HeaderPolicy headerPolicy(formatVersion, locale, attributeMap);
     89     DictBuffersPtr dictBuffers = DictBuffers::createVer4DictBuffers(&headerPolicy,
     90             DictConstants::MAX_DICT_EXTENDED_REGION_SIZE);
     91     if (!DynamicPtWritingUtils::writeEmptyDictionary(
     92             dictBuffers->getWritableTrieBuffer(), 0 /* rootPos */)) {
     93         AKLOGE("Empty ver4 dictionary structure cannot be created on memory.");
     94         return nullptr;
     95     }
     96     return DictionaryStructureWithBufferPolicy::StructurePolicyPtr(
     97             new StructurePolicy(std::move(dictBuffers)));
     98 }
     99 
    100 /* static */ DictionaryStructureWithBufferPolicy::StructurePolicyPtr
    101         DictionaryStructureWithBufferPolicyFactory::newPolicyForDirectoryDict(
    102                 const char *const path, const bool isUpdatable) {
    103     const int headerFilePathBufSize = PATH_MAX + 1 /* terminator */;
    104     char headerFilePath[headerFilePathBufSize];
    105     getHeaderFilePathInDictDir(path, headerFilePathBufSize, headerFilePath);
    106     // Allocated buffer in MmapedBuffer::openBuffer() will be freed in the destructor of
    107     // MmappedBufferPtr if the instance has the responsibility.
    108     MmappedBuffer::MmappedBufferPtr mmappedBuffer =
    109             MmappedBuffer::openBuffer(headerFilePath, isUpdatable);
    110     if (!mmappedBuffer) {
    111         return nullptr;
    112     }
    113     const FormatUtils::FORMAT_VERSION formatVersion = FormatUtils::detectFormatVersion(
    114             mmappedBuffer->getReadOnlyByteArrayView());
    115     switch (formatVersion) {
    116         case FormatUtils::VERSION_2:
    117         case FormatUtils::VERSION_201:
    118         case FormatUtils::VERSION_202:
    119             AKLOGE("Given path is a directory but the format is version 2xx. path: %s", path);
    120             break;
    121         case FormatUtils::VERSION_402: {
    122             return newPolicyForV4Dict<backward::v402::Ver4DictConstants,
    123                     backward::v402::Ver4DictBuffers,
    124                     backward::v402::Ver4DictBuffers::Ver4DictBuffersPtr,
    125                     backward::v402::Ver4PatriciaTriePolicy>(
    126                             headerFilePath, formatVersion, std::move(mmappedBuffer));
    127         }
    128         case FormatUtils::VERSION_4_ONLY_FOR_TESTING:
    129         case FormatUtils::VERSION_403: {
    130             return newPolicyForV4Dict<Ver4DictConstants, Ver4DictBuffers,
    131                     Ver4DictBuffers::Ver4DictBuffersPtr, Ver4PatriciaTriePolicy>(
    132                             headerFilePath, formatVersion, std::move(mmappedBuffer));
    133         }
    134         default:
    135             AKLOGE("DICT: dictionary format is unknown, bad magic number. path: %s", path);
    136             break;
    137     }
    138     ASSERT(false);
    139     return nullptr;
    140 }
    141 
    142 template<class DictConstants, class DictBuffers, class DictBuffersPtr, class StructurePolicy>
    143 /* static */ DictionaryStructureWithBufferPolicy::StructurePolicyPtr
    144         DictionaryStructureWithBufferPolicyFactory::newPolicyForV4Dict(
    145                 const char *const headerFilePath, const FormatUtils::FORMAT_VERSION formatVersion,
    146                 MmappedBuffer::MmappedBufferPtr &&mmappedBuffer) {
    147     const int dictDirPathBufSize = strlen(headerFilePath) + 1 /* terminator */;
    148     char dictPath[dictDirPathBufSize];
    149     if (!FileUtils::getFilePathWithoutSuffix(headerFilePath,
    150             DictConstants::HEADER_FILE_EXTENSION, dictDirPathBufSize, dictPath)) {
    151         AKLOGE("Dictionary file name is not valid as a ver4 dictionary. header path: %s",
    152                 headerFilePath);
    153         ASSERT(false);
    154         return nullptr;
    155     }
    156     DictBuffersPtr dictBuffers =
    157             DictBuffers::openVer4DictBuffers(dictPath, std::move(mmappedBuffer), formatVersion);
    158     if (!dictBuffers || !dictBuffers->isValid()) {
    159         AKLOGE("DICT: The dictionary doesn't satisfy ver4 format requirements. path: %s",
    160                 dictPath);
    161         ASSERT(false);
    162         return nullptr;
    163     }
    164     return DictionaryStructureWithBufferPolicy::StructurePolicyPtr(
    165             new StructurePolicy(std::move(dictBuffers)));
    166 }
    167 
    168 /* static */ DictionaryStructureWithBufferPolicy::StructurePolicyPtr
    169         DictionaryStructureWithBufferPolicyFactory::newPolicyForFileDict(
    170                 const char *const path, const int bufOffset, const int size) {
    171     // Allocated buffer in MmapedBuffer::openBuffer() will be freed in the destructor of
    172     // MmappedBufferPtr if the instance has the responsibility.
    173     MmappedBuffer::MmappedBufferPtr mmappedBuffer(
    174             MmappedBuffer::openBuffer(path, bufOffset, size, false /* isUpdatable */));
    175     if (!mmappedBuffer) {
    176         return nullptr;
    177     }
    178     switch (FormatUtils::detectFormatVersion(mmappedBuffer->getReadOnlyByteArrayView())) {
    179         case FormatUtils::VERSION_2:
    180         case FormatUtils::VERSION_201:
    181             AKLOGE("Dictionary versions 2 and 201 are incompatible with this version");
    182             break;
    183         case FormatUtils::VERSION_202:
    184             return DictionaryStructureWithBufferPolicy::StructurePolicyPtr(
    185                     new PatriciaTriePolicy(std::move(mmappedBuffer)));
    186         case FormatUtils::VERSION_4_ONLY_FOR_TESTING:
    187         case FormatUtils::VERSION_402:
    188         case FormatUtils::VERSION_403:
    189             AKLOGE("Given path is a file but the format is version 4. path: %s", path);
    190             break;
    191         default:
    192             AKLOGE("DICT: dictionary format is unknown, bad magic number. path: %s", path);
    193             break;
    194     }
    195     ASSERT(false);
    196     return nullptr;
    197 }
    198 
    199 /* static */ void DictionaryStructureWithBufferPolicyFactory::getHeaderFilePathInDictDir(
    200         const char *const dictDirPath, const int outHeaderFileBufSize,
    201         char *const outHeaderFilePath) {
    202     const int dictNameBufSize = strlen(dictDirPath) + 1 /* terminator */;
    203     char dictName[dictNameBufSize];
    204     FileUtils::getBasename(dictDirPath, dictNameBufSize, dictName);
    205     snprintf(outHeaderFilePath, outHeaderFileBufSize, "%s/%s%s", dictDirPath,
    206             dictName, Ver4DictConstants::HEADER_FILE_EXTENSION);
    207 }
    208 
    209 } // namespace latinime
    210