Merge "Prepare dictionary file creating in native code."
This commit is contained in:
commit
10b56df486
7 changed files with 173 additions and 70 deletions
|
@ -85,6 +85,7 @@ LATIN_IME_CORE_SRC_FILES := \
|
|||
$(addprefix suggest/policyimpl/dictionary/utils/, \
|
||||
buffer_with_extendable_buffer.cpp \
|
||||
byte_array_utils.cpp \
|
||||
dict_file_writing_utils.cpp \
|
||||
format_utils.cpp) \
|
||||
suggest/policyimpl/gesture/gesture_suggest_policy_factory.cpp \
|
||||
$(addprefix suggest/policyimpl/typing/, \
|
||||
|
|
|
@ -16,9 +16,6 @@
|
|||
|
||||
#include "suggest/policyimpl/dictionary/dynamic_patricia_trie_writing_helper.h"
|
||||
|
||||
#include <cstdio>
|
||||
#include <cstring>
|
||||
|
||||
#include "suggest/policyimpl/dictionary/bigram/dynamic_bigram_list_policy.h"
|
||||
#include "suggest/policyimpl/dictionary/dynamic_patricia_trie_gc_event_listeners.h"
|
||||
#include "suggest/policyimpl/dictionary/dynamic_patricia_trie_node_reader.h"
|
||||
|
@ -28,13 +25,12 @@
|
|||
#include "suggest/policyimpl/dictionary/header/header_policy.h"
|
||||
#include "suggest/policyimpl/dictionary/patricia_trie_reading_utils.h"
|
||||
#include "suggest/policyimpl/dictionary/shortcut/dynamic_shortcut_list_policy.h"
|
||||
#include "suggest/policyimpl/dictionary/utils/dict_file_writing_utils.h"
|
||||
#include "utils/hash_map_compat.h"
|
||||
|
||||
namespace latinime {
|
||||
|
||||
const int DynamicPatriciaTrieWritingHelper::CHILDREN_POSITION_FIELD_SIZE = 3;
|
||||
const char *const DynamicPatriciaTrieWritingHelper::TEMP_FILE_SUFFIX_FOR_WRITING_DICT_FILE =
|
||||
".tmp";
|
||||
// TODO: Make MAX_DICTIONARY_SIZE 8MB.
|
||||
const size_t DynamicPatriciaTrieWritingHelper::MAX_DICTIONARY_SIZE = 2 * 1024 * 1024;
|
||||
|
||||
|
@ -147,7 +143,7 @@ void DynamicPatriciaTrieWritingHelper::writeToDictFile(const char *const fileNam
|
|||
if (!headerPolicy->writeHeaderToBuffer(&headerBuffer, false /* updatesLastUpdatedTime */)) {
|
||||
return;
|
||||
}
|
||||
flushAllToFile(fileName, &headerBuffer, mBuffer);
|
||||
DictFileWritingUtils::flushAllHeaderAndBodyToFile(fileName, &headerBuffer, mBuffer);
|
||||
}
|
||||
|
||||
void DynamicPatriciaTrieWritingHelper::writeToDictFileWithGC(const int rootPtNodeArrayPos,
|
||||
|
@ -161,7 +157,7 @@ void DynamicPatriciaTrieWritingHelper::writeToDictFileWithGC(const int rootPtNod
|
|||
if (!runGC(rootPtNodeArrayPos, &newDictBuffer)) {
|
||||
return;
|
||||
}
|
||||
flushAllToFile(fileName, &headerBuffer, &newDictBuffer);
|
||||
DictFileWritingUtils::flushAllHeaderAndBodyToFile(fileName, &headerBuffer, &newDictBuffer);
|
||||
}
|
||||
|
||||
bool DynamicPatriciaTrieWritingHelper::markNodeAsDeleted(
|
||||
|
@ -463,60 +459,6 @@ bool DynamicPatriciaTrieWritingHelper::reallocatePtNodeAndAddNewPtNodes(
|
|||
return true;
|
||||
}
|
||||
|
||||
// TODO: Create a struct which contains header, body and etc... and use here as an argument.
|
||||
void DynamicPatriciaTrieWritingHelper::flushAllToFile(const char *const fileName,
|
||||
BufferWithExtendableBuffer *const dictHeader,
|
||||
BufferWithExtendableBuffer *const dictBody) const {
|
||||
const int tmpFileNameBufSize = strlen(fileName)
|
||||
+ strlen(TEMP_FILE_SUFFIX_FOR_WRITING_DICT_FILE) + 1 /* terminator */;
|
||||
// Name of a temporary file used for writing that is a connected string of original name and
|
||||
// TEMP_FILE_SUFFIX_FOR_WRITING_DICT_FILE.
|
||||
char tmpFileName[tmpFileNameBufSize];
|
||||
snprintf(tmpFileName, tmpFileNameBufSize, "%s%s", fileName,
|
||||
TEMP_FILE_SUFFIX_FOR_WRITING_DICT_FILE);
|
||||
FILE *const file = fopen(tmpFileName, "wb");
|
||||
if (!file) {
|
||||
AKLOGI("Dictionary file %s cannnot be opened.", tmpFileName);
|
||||
ASSERT(false);
|
||||
return;
|
||||
}
|
||||
// Write the dictionary header.
|
||||
if (!writeBufferToFilePointer(file, dictHeader)) {
|
||||
remove(tmpFileName);
|
||||
AKLOGI("Dictionary header cannnot be written. size: %d", dictHeader->getTailPosition());
|
||||
ASSERT(false);
|
||||
return;
|
||||
}
|
||||
// Write the dictionary body.
|
||||
if (!writeBufferToFilePointer(file, dictBody)) {
|
||||
remove(tmpFileName);
|
||||
AKLOGI("Dictionary body cannnot be written. size: %d", dictBody->getTailPosition());
|
||||
ASSERT(false);
|
||||
return;
|
||||
}
|
||||
fclose(file);
|
||||
rename(tmpFileName, fileName);
|
||||
}
|
||||
|
||||
// This closes file pointer when an error is caused and returns whether the writing was succeeded
|
||||
// or not.
|
||||
bool DynamicPatriciaTrieWritingHelper::writeBufferToFilePointer(FILE *const file,
|
||||
const BufferWithExtendableBuffer *const buffer) const {
|
||||
const int originalBufSize = buffer->getOriginalBufferSize();
|
||||
if (originalBufSize > 0 && fwrite(buffer->getBuffer(false /* usesAdditionalBuffer */),
|
||||
originalBufSize, 1, file) < 1) {
|
||||
fclose(file);
|
||||
return false;
|
||||
}
|
||||
const int additionalBufSize = buffer->getTailPosition() - buffer->getOriginalBufferSize();
|
||||
if (additionalBufSize > 0 && fwrite(buffer->getBuffer(true /* usesAdditionalBuffer */),
|
||||
additionalBufSize, 1, file) < 1) {
|
||||
fclose(file);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool DynamicPatriciaTrieWritingHelper::runGC(const int rootPtNodeArrayPos,
|
||||
BufferWithExtendableBuffer *const bufferToWrite) {
|
||||
DynamicPatriciaTrieReadingHelper readingHelper(mBuffer, mBigramPolicy, mShortcutPolicy);
|
||||
|
|
|
@ -17,7 +17,6 @@
|
|||
#ifndef LATINIME_DYNAMIC_PATRICIA_TRIE_WRITING_HELPER_H
|
||||
#define LATINIME_DYNAMIC_PATRICIA_TRIE_WRITING_HELPER_H
|
||||
|
||||
#include <cstdio>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "defines.h"
|
||||
|
@ -85,7 +84,6 @@ class DynamicPatriciaTrieWritingHelper {
|
|||
DISALLOW_IMPLICIT_CONSTRUCTORS(DynamicPatriciaTrieWritingHelper);
|
||||
|
||||
static const int CHILDREN_POSITION_FIELD_SIZE;
|
||||
static const char *const TEMP_FILE_SUFFIX_FOR_WRITING_DICT_FILE;
|
||||
static const size_t MAX_DICTIONARY_SIZE;
|
||||
|
||||
BufferWithExtendableBuffer *const mBuffer;
|
||||
|
@ -124,13 +122,6 @@ class DynamicPatriciaTrieWritingHelper {
|
|||
const int probabilityOfNewPtNode, const int *const newNodeCodePoints,
|
||||
const int newNodeCodePointCount);
|
||||
|
||||
void flushAllToFile(const char *const fileName,
|
||||
BufferWithExtendableBuffer *const dictHeader,
|
||||
BufferWithExtendableBuffer *const dictBody) const;
|
||||
|
||||
bool writeBufferToFilePointer(FILE *const file,
|
||||
const BufferWithExtendableBuffer *const buffer) const;
|
||||
|
||||
bool runGC(const int rootPtNodeArrayPos, BufferWithExtendableBuffer *const bufferToWrite);
|
||||
};
|
||||
} // namespace latinime
|
||||
|
|
|
@ -36,6 +36,16 @@ const int DynamicPatriciaTrieWritingUtils::DICT_OFFSET_NEGATIVE_FLAG = 0x800000;
|
|||
const int DynamicPatriciaTrieWritingUtils::PROBABILITY_FIELD_SIZE = 1;
|
||||
const int DynamicPatriciaTrieWritingUtils::NODE_FLAG_FIELD_SIZE = 1;
|
||||
|
||||
/* static */ bool DynamicPatriciaTrieWritingUtils::writeEmptyDictionary(
|
||||
BufferWithExtendableBuffer *const buffer, const int rootPos) {
|
||||
int writingPos = rootPos;
|
||||
if (!writePtNodeArraySizeAndAdvancePosition(buffer, 0 /* arraySize */, &writingPos)) {
|
||||
return false;
|
||||
}
|
||||
return writeForwardLinkPositionAndAdvancePosition(buffer, NOT_A_DICT_POS /* forwardLinkPos */,
|
||||
&writingPos);
|
||||
}
|
||||
|
||||
/* static */ bool DynamicPatriciaTrieWritingUtils::writeForwardLinkPositionAndAdvancePosition(
|
||||
BufferWithExtendableBuffer *const buffer, const int forwardLinkPos,
|
||||
int *const forwardLinkFieldPos) {
|
||||
|
|
|
@ -30,6 +30,8 @@ class DynamicPatriciaTrieWritingUtils {
|
|||
public:
|
||||
static const int NODE_FLAG_FIELD_SIZE;
|
||||
|
||||
static bool writeEmptyDictionary(BufferWithExtendableBuffer *const buffer, const int rootPos);
|
||||
|
||||
static bool writeForwardLinkPositionAndAdvancePosition(
|
||||
BufferWithExtendableBuffer *const buffer, const int forwardLinkPos,
|
||||
int *const forwardLinkFieldPos);
|
||||
|
|
|
@ -0,0 +1,107 @@
|
|||
/*
|
||||
* Copyright (C) 2013, The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "suggest/policyimpl/dictionary/utils/dict_file_writing_utils.h"
|
||||
|
||||
#include <cstdio>
|
||||
#include <cstring>
|
||||
|
||||
#include "suggest/policyimpl/dictionary/header/header_policy.h"
|
||||
#include "suggest/policyimpl/dictionary/dynamic_patricia_trie_writing_utils.h"
|
||||
#include "suggest/policyimpl/dictionary/utils/buffer_with_extendable_buffer.h"
|
||||
#include "suggest/policyimpl/dictionary/utils/format_utils.h"
|
||||
|
||||
namespace latinime {
|
||||
|
||||
const char *const DictFileWritingUtils::TEMP_FILE_SUFFIX_FOR_WRITING_DICT_FILE = ".tmp";
|
||||
|
||||
/* static */ bool DictFileWritingUtils::createEmptyDictFile(const char *const filePath,
|
||||
const int dictVersion, const HeaderReadWriteUtils::AttributeMap *const attributeMap) {
|
||||
switch (dictVersion) {
|
||||
case 3:
|
||||
return createEmptyV3DictFile(filePath, attributeMap);
|
||||
default:
|
||||
// Only version 3 dictionary is supported for now.
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/* static */ bool DictFileWritingUtils::createEmptyV3DictFile(const char *const filePath,
|
||||
const HeaderReadWriteUtils::AttributeMap *const attributeMap) {
|
||||
BufferWithExtendableBuffer headerBuffer(0 /* originalBuffer */, 0 /* originalBufferSize */);
|
||||
HeaderPolicy headerPolicy(FormatUtils::VERSION_3, attributeMap);
|
||||
headerPolicy.writeHeaderToBuffer(&headerBuffer, true /* updatesLastUpdatedTime */);
|
||||
BufferWithExtendableBuffer bodyBuffer(0 /* originalBuffer */, 0 /* originalBufferSize */);
|
||||
if (!DynamicPatriciaTrieWritingUtils::writeEmptyDictionary(&bodyBuffer, 0 /* rootPos */)) {
|
||||
return false;
|
||||
}
|
||||
return flushAllHeaderAndBodyToFile(filePath, &headerBuffer, &bodyBuffer);
|
||||
}
|
||||
|
||||
/* static */ bool DictFileWritingUtils::flushAllHeaderAndBodyToFile(const char *const filePath,
|
||||
BufferWithExtendableBuffer *const dictHeader, BufferWithExtendableBuffer *const dictBody) {
|
||||
const int tmpFileNameBufSize = strlen(filePath)
|
||||
+ strlen(TEMP_FILE_SUFFIX_FOR_WRITING_DICT_FILE) + 1 /* terminator */;
|
||||
// Name of a temporary file used for writing that is a connected string of original name and
|
||||
// TEMP_FILE_SUFFIX_FOR_WRITING_DICT_FILE.
|
||||
char tmpFileName[tmpFileNameBufSize];
|
||||
snprintf(tmpFileName, tmpFileNameBufSize, "%s%s", filePath,
|
||||
TEMP_FILE_SUFFIX_FOR_WRITING_DICT_FILE);
|
||||
FILE *const file = fopen(tmpFileName, "wb");
|
||||
if (!file) {
|
||||
AKLOGE("Dictionary file %s cannnot be opened.", tmpFileName);
|
||||
ASSERT(false);
|
||||
return false;
|
||||
}
|
||||
// Write the dictionary header.
|
||||
if (!writeBufferToFile(file, dictHeader)) {
|
||||
remove(tmpFileName);
|
||||
AKLOGE("Dictionary header cannnot be written. size: %d", dictHeader->getTailPosition());
|
||||
ASSERT(false);
|
||||
return false;
|
||||
}
|
||||
// Write the dictionary body.
|
||||
if (!writeBufferToFile(file, dictBody)) {
|
||||
remove(tmpFileName);
|
||||
AKLOGE("Dictionary body cannnot be written. size: %d", dictBody->getTailPosition());
|
||||
ASSERT(false);
|
||||
return false;
|
||||
}
|
||||
fclose(file);
|
||||
rename(tmpFileName, filePath);
|
||||
return true;
|
||||
}
|
||||
|
||||
// This closes file pointer when an error is caused and returns whether the writing was succeeded
|
||||
// or not.
|
||||
/* static */ bool DictFileWritingUtils::writeBufferToFile(FILE *const file,
|
||||
const BufferWithExtendableBuffer *const buffer) {
|
||||
const int originalBufSize = buffer->getOriginalBufferSize();
|
||||
if (originalBufSize > 0 && fwrite(buffer->getBuffer(false /* usesAdditionalBuffer */),
|
||||
originalBufSize, 1, file) < 1) {
|
||||
fclose(file);
|
||||
return false;
|
||||
}
|
||||
const int additionalBufSize = buffer->getTailPosition() - buffer->getOriginalBufferSize();
|
||||
if (additionalBufSize > 0 && fwrite(buffer->getBuffer(true /* usesAdditionalBuffer */),
|
||||
additionalBufSize, 1, file) < 1) {
|
||||
fclose(file);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace latinime
|
|
@ -0,0 +1,50 @@
|
|||
/*
|
||||
* Copyright (C) 2013, The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef LATINIME_DICT_FILE_WRITING_UTILS_H
|
||||
#define LATINIME_DICT_FILE_WRITING_UTILS_H
|
||||
|
||||
#include <cstdio>
|
||||
|
||||
#include "defines.h"
|
||||
#include "suggest/policyimpl/dictionary/header/header_read_write_utils.h"
|
||||
|
||||
namespace latinime {
|
||||
|
||||
class BufferWithExtendableBuffer;
|
||||
|
||||
class DictFileWritingUtils {
|
||||
public:
|
||||
static bool createEmptyDictFile(const char *const filePath, const int dictVersion,
|
||||
const HeaderReadWriteUtils::AttributeMap *const attributeMap);
|
||||
|
||||
static bool flushAllHeaderAndBodyToFile(const char *const filePath,
|
||||
BufferWithExtendableBuffer *const dictHeader,
|
||||
BufferWithExtendableBuffer *const dictBody);
|
||||
|
||||
private:
|
||||
DISALLOW_IMPLICIT_CONSTRUCTORS(DictFileWritingUtils);
|
||||
|
||||
static const char *const TEMP_FILE_SUFFIX_FOR_WRITING_DICT_FILE;
|
||||
|
||||
static bool createEmptyV3DictFile(const char *const filePath,
|
||||
const HeaderReadWriteUtils::AttributeMap *const attributeMap);
|
||||
|
||||
static bool writeBufferToFile(FILE *const file,
|
||||
const BufferWithExtendableBuffer *const buffer);
|
||||
};
|
||||
} // namespace latinime
|
||||
#endif /* LATINIME_DICT_FILE_WRITING_UTILS_H */
|
Loading…
Reference in a new issue