| OLD | NEW |
| (Empty) | |
| 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 "third_party/prediction/suggest/policyimpl/dictionary/utils/dict_file_w
riting_utils.h" |
| 18 |
| 19 #include <cstdio> |
| 20 #include <errno.h> |
| 21 #include <fcntl.h> |
| 22 #include <sys/stat.h> |
| 23 #include <sys/types.h> |
| 24 |
| 25 #include "third_party/prediction/suggest/policyimpl/dictionary/header/header_pol
icy.h" |
| 26 #include "third_party/prediction/suggest/policyimpl/dictionary/structure/backwar
d/v402/ver4_dict_buffers.h" |
| 27 #include "third_party/prediction/suggest/policyimpl/dictionary/structure/pt_comm
on/dynamic_pt_writing_utils.h" |
| 28 #include "third_party/prediction/suggest/policyimpl/dictionary/structure/v4/ver4
_dict_buffers.h" |
| 29 #include "third_party/prediction/suggest/policyimpl/dictionary/utils/buffer_with
_extendable_buffer.h" |
| 30 #include "third_party/prediction/suggest/policyimpl/dictionary/utils/file_utils.
h" |
| 31 #include "third_party/prediction/suggest/policyimpl/dictionary/utils/format_util
s.h" |
| 32 #include "third_party/prediction/utils/time_keeper.h" |
| 33 |
| 34 namespace latinime { |
| 35 |
| 36 const char* const DictFileWritingUtils::TEMP_FILE_SUFFIX_FOR_WRITING_DICT_FILE = |
| 37 ".tmp"; |
| 38 // Enough size to describe buffer size. |
| 39 const int DictFileWritingUtils::SIZE_OF_BUFFER_SIZE_FIELD = 4; |
| 40 |
| 41 /* static */ bool DictFileWritingUtils::createEmptyDictFile( |
| 42 const char* const filePath, |
| 43 const int dictVersion, |
| 44 const std::vector<int> localeAsCodePointVector, |
| 45 const DictionaryHeaderStructurePolicy::AttributeMap* const attributeMap) { |
| 46 TimeKeeper::setCurrentTime(); |
| 47 const FormatUtils::FORMAT_VERSION formatVersion = |
| 48 FormatUtils::getFormatVersion(dictVersion); |
| 49 switch (formatVersion) { |
| 50 case FormatUtils::VERSION_4: |
| 51 return createEmptyV4DictFile< |
| 52 backward::v402::Ver4DictConstants, backward::v402::Ver4DictBuffers, |
| 53 backward::v402::Ver4DictBuffers::Ver4DictBuffersPtr>( |
| 54 filePath, localeAsCodePointVector, attributeMap, formatVersion); |
| 55 case FormatUtils::VERSION_4_ONLY_FOR_TESTING: |
| 56 case FormatUtils::VERSION_4_DEV: |
| 57 return createEmptyV4DictFile<Ver4DictConstants, Ver4DictBuffers, |
| 58 Ver4DictBuffers::Ver4DictBuffersPtr>( |
| 59 filePath, localeAsCodePointVector, attributeMap, formatVersion); |
| 60 default: |
| 61 AKLOGE( |
| 62 "Cannot create dictionary %s because format version %d is not " |
| 63 "supported.", |
| 64 filePath, dictVersion); |
| 65 return false; |
| 66 } |
| 67 } |
| 68 |
| 69 template <class DictConstants, class DictBuffers, class DictBuffersPtr> |
| 70 /* static */ bool DictFileWritingUtils::createEmptyV4DictFile( |
| 71 const char* const dirPath, |
| 72 const std::vector<int> localeAsCodePointVector, |
| 73 const DictionaryHeaderStructurePolicy::AttributeMap* const attributeMap, |
| 74 const FormatUtils::FORMAT_VERSION formatVersion) { |
| 75 HeaderPolicy headerPolicy(formatVersion, localeAsCodePointVector, |
| 76 attributeMap); |
| 77 DictBuffersPtr dictBuffers = DictBuffers::createVer4DictBuffers( |
| 78 &headerPolicy, DictConstants::MAX_DICT_EXTENDED_REGION_SIZE); |
| 79 headerPolicy.fillInAndWriteHeaderToBuffer( |
| 80 true /* updatesLastDecayedTime */, 0 /* unigramCount */, |
| 81 0 /* bigramCount */, 0 /* extendedRegionSize */, |
| 82 dictBuffers->getWritableHeaderBuffer()); |
| 83 if (!DynamicPtWritingUtils::writeEmptyDictionary( |
| 84 dictBuffers->getWritableTrieBuffer(), 0 /* rootPos */)) { |
| 85 AKLOGE("Empty ver4 dictionary structure cannot be created on memory."); |
| 86 return false; |
| 87 } |
| 88 return dictBuffers->flush(dirPath); |
| 89 } |
| 90 |
| 91 /* static */ bool DictFileWritingUtils::flushBufferToFileWithSuffix( |
| 92 const char* const basePath, |
| 93 const char* const suffix, |
| 94 const BufferWithExtendableBuffer* const buffer) { |
| 95 const int filePathBufSize = |
| 96 FileUtils::getFilePathWithSuffixBufSize(basePath, suffix); |
| 97 char filePath[filePathBufSize]; |
| 98 FileUtils::getFilePathWithSuffix(basePath, suffix, filePathBufSize, filePath); |
| 99 return flushBufferToFile(filePath, buffer); |
| 100 } |
| 101 |
| 102 /* static */ bool DictFileWritingUtils::writeBufferToFileTail( |
| 103 FILE* const file, |
| 104 const BufferWithExtendableBuffer* const buffer) { |
| 105 uint8_t bufferSize[SIZE_OF_BUFFER_SIZE_FIELD]; |
| 106 int writingPos = 0; |
| 107 ByteArrayUtils::writeUintAndAdvancePosition( |
| 108 bufferSize, buffer->getTailPosition(), SIZE_OF_BUFFER_SIZE_FIELD, |
| 109 &writingPos); |
| 110 if (fwrite(bufferSize, SIZE_OF_BUFFER_SIZE_FIELD, 1 /* count */, file) < 1) { |
| 111 return false; |
| 112 } |
| 113 return writeBufferToFile(file, buffer); |
| 114 } |
| 115 |
| 116 /* static */ bool DictFileWritingUtils::flushBufferToFile( |
| 117 const char* const filePath, |
| 118 const BufferWithExtendableBuffer* const buffer) { |
| 119 const int fd = open(filePath, O_WRONLY | O_CREAT | O_EXCL, S_IRUSR | S_IWUSR); |
| 120 if (fd == -1) { |
| 121 AKLOGE("File %s cannot be opened. errno: %d", filePath, errno); |
| 122 ASSERT(false); |
| 123 return false; |
| 124 } |
| 125 FILE* const file = fdopen(fd, "wb"); |
| 126 if (!file) { |
| 127 AKLOGE("fdopen failed for the file %s. errno: %d", filePath, errno); |
| 128 ASSERT(false); |
| 129 return false; |
| 130 } |
| 131 if (!writeBufferToFile(file, buffer)) { |
| 132 fclose(file); |
| 133 remove(filePath); |
| 134 AKLOGE("Buffer cannot be written to the file %s. size: %d", filePath, |
| 135 buffer->getTailPosition()); |
| 136 ASSERT(false); |
| 137 return false; |
| 138 } |
| 139 fclose(file); |
| 140 return true; |
| 141 } |
| 142 |
| 143 // Returns whether the writing was succeeded or not. |
| 144 /* static */ bool DictFileWritingUtils::writeBufferToFile( |
| 145 FILE* const file, |
| 146 const BufferWithExtendableBuffer* const buffer) { |
| 147 const int originalBufSize = buffer->getOriginalBufferSize(); |
| 148 if (originalBufSize > 0 && |
| 149 fwrite(buffer->getBuffer(false /* usesAdditionalBuffer */), |
| 150 originalBufSize, 1, file) < 1) { |
| 151 return false; |
| 152 } |
| 153 const int additionalBufSize = buffer->getUsedAdditionalBufferSize(); |
| 154 if (additionalBufSize > 0 && |
| 155 fwrite(buffer->getBuffer(true /* usesAdditionalBuffer */), |
| 156 additionalBufSize, 1, file) < 1) { |
| 157 return false; |
| 158 } |
| 159 return true; |
| 160 } |
| 161 |
| 162 } // namespace latinime |
| OLD | NEW |