From 76e579c7caf2ef04f440be21c27377fe0b4150ff Mon Sep 17 00:00:00 2001
From: Keisuke Kuroyanagi <ksk@google.com>
Date: Tue, 13 Aug 2013 20:22:40 +0900
Subject: [PATCH] Move header reading methods to policyimpl.

Bug: 6669677
Change-Id: I24cb32f28cf355485b431cc56d877000e3f946d4
---
 .../dictionary/binary_dictionary_header.cpp   | 18 ++-----
 .../dictionary/binary_dictionary_header.h     | 35 +++++++------
 ...binary_dictionary_header_reading_utils.cpp | 49 +++++++++---------
 .../binary_dictionary_header_reading_utils.h  | 24 ++++-----
 .../core/dictionary/binary_dictionary_info.h  | 40 +--------------
 .../suggest/core/dictionary/dictionary.cpp    | 35 ++++++++++++-
 .../src/suggest/core/dictionary/dictionary.h  |  2 +
 .../suggest/core/dictionary/digraph_utils.cpp | 13 ++---
 .../suggest/core/dictionary/digraph_utils.h   |  9 ++--
 .../dictionary_header_structure_policy.h      | 50 +++++++++++++++++++
 .../dictionary_structure_with_buffer_policy.h |  5 +-
 .../core/session/dic_traverse_session.cpp     |  5 +-
 native/jni/src/suggest/core/suggest.cpp       |  3 +-
 .../dictionary/dynamic_patricia_trie_policy.h |  9 ++--
 .../dictionary/patricia_trie_policy.h         |  9 ++--
 15 files changed, 174 insertions(+), 132 deletions(-)
 create mode 100644 native/jni/src/suggest/core/policy/dictionary_header_structure_policy.h

diff --git a/native/jni/src/suggest/core/dictionary/binary_dictionary_header.cpp b/native/jni/src/suggest/core/dictionary/binary_dictionary_header.cpp
index 16f534c214..a39ffedd5c 100644
--- a/native/jni/src/suggest/core/dictionary/binary_dictionary_header.cpp
+++ b/native/jni/src/suggest/core/dictionary/binary_dictionary_header.cpp
@@ -16,23 +16,15 @@
 
 #include "suggest/core/dictionary/binary_dictionary_header.h"
 
-#include "defines.h"
-
 namespace latinime {
 
-const char *const BinaryDictionaryHeader::MULTIPLE_WORDS_DEMOTION_RATE_KEY =
+const char *const HeaderPolicy::MULTIPLE_WORDS_DEMOTION_RATE_KEY =
         "MULTIPLE_WORDS_DEMOTION_RATE";
-const float BinaryDictionaryHeader::DEFAULT_MULTI_WORD_COST_MULTIPLIER = 1.0f;
-const float BinaryDictionaryHeader::MULTI_WORD_COST_MULTIPLIER_SCALE = 100.0f;
-
-BinaryDictionaryHeader::BinaryDictionaryHeader(const uint8_t *const dictBuf)
-        : mDictBuf(dictBuf),
-          mDictionaryFlags(BinaryDictionaryHeaderReadingUtils::getFlags(mDictBuf)),
-          mSize(BinaryDictionaryHeaderReadingUtils::getHeaderSize(mDictBuf)),
-          mMultiWordCostMultiplier(readMultiWordCostMultiplier()) {}
+const float HeaderPolicy::DEFAULT_MULTI_WORD_COST_MULTIPLIER = 1.0f;
+const float HeaderPolicy::MULTI_WORD_COST_MULTIPLIER_SCALE = 100.0f;
 
-float BinaryDictionaryHeader::readMultiWordCostMultiplier() const {
-    const int headerValue = BinaryDictionaryHeaderReadingUtils::readHeaderValueInt(
+float HeaderPolicy::readMultiWordCostMultiplier() const {
+    const int headerValue = HeaderReadingUtils::readHeaderValueInt(
             mDictBuf, MULTIPLE_WORDS_DEMOTION_RATE_KEY);
     if (headerValue == S_INT_MIN) {
         // not found
diff --git a/native/jni/src/suggest/core/dictionary/binary_dictionary_header.h b/native/jni/src/suggest/core/dictionary/binary_dictionary_header.h
index 6b51c326d1..0e1337291e 100644
--- a/native/jni/src/suggest/core/dictionary/binary_dictionary_header.h
+++ b/native/jni/src/suggest/core/dictionary/binary_dictionary_header.h
@@ -14,39 +14,41 @@
  * limitations under the License.
  */
 
-#ifndef LATINIME_BINARY_DICTIONARY_HEADER_H
-#define LATINIME_BINARY_DICTIONARY_HEADER_H
+#ifndef LATINIME_HEADER_POLICY_H
+#define LATINIME_HEADER_POLICY_H
 
 #include <stdint.h>
 
 #include "defines.h"
+#include "suggest/core/policy/dictionary_header_structure_policy.h"
 #include "suggest/core/dictionary/binary_dictionary_header_reading_utils.h"
 
 namespace latinime {
 
-/**
- * This class abstracts dictionary header structures and provide interface to access dictionary
- * header information.
- */
-// TODO:: Move header classes to policyimpl.
-class BinaryDictionaryHeader {
+// TODO: Move to policyimpl.
+class HeaderPolicy : public DictionaryHeaderStructurePolicy {
  public:
-    explicit BinaryDictionaryHeader(const uint8_t *const dictBuf);
+    explicit HeaderPolicy(const uint8_t *const dictBuf)
+            : mDictBuf(dictBuf), mDictionaryFlags(HeaderReadingUtils::getFlags(dictBuf)),
+              mSize(HeaderReadingUtils::getHeaderSize(dictBuf)),
+              mMultiWordCostMultiplier(readMultiWordCostMultiplier()) {}
+
+    ~HeaderPolicy() {}
 
     AK_FORCE_INLINE int getSize() const {
         return mSize;
     }
 
     AK_FORCE_INLINE bool supportsDynamicUpdate() const {
-        return BinaryDictionaryHeaderReadingUtils::supportsDynamicUpdate(mDictionaryFlags);
+        return HeaderReadingUtils::supportsDynamicUpdate(mDictionaryFlags);
     }
 
     AK_FORCE_INLINE bool requiresGermanUmlautProcessing() const {
-        return BinaryDictionaryHeaderReadingUtils::requiresGermanUmlautProcessing(mDictionaryFlags);
+        return HeaderReadingUtils::requiresGermanUmlautProcessing(mDictionaryFlags);
     }
 
     AK_FORCE_INLINE bool requiresFrenchLigatureProcessing() const {
-        return BinaryDictionaryHeaderReadingUtils::requiresFrenchLigatureProcessing(
+        return HeaderReadingUtils::requiresFrenchLigatureProcessing(
                 mDictionaryFlags);
     }
 
@@ -61,7 +63,7 @@ class BinaryDictionaryHeader {
             outValue[0] = '\0';
             return;
         }
-        if (!BinaryDictionaryHeaderReadingUtils::readHeaderValue(mDictBuf,
+        if (!HeaderReadingUtils::readHeaderValue(mDictBuf,
                 key, outValue, outValueSize)) {
             outValue[0] = '?';
             outValue[1] = '\0';
@@ -69,18 +71,19 @@ class BinaryDictionaryHeader {
     }
 
  private:
-    DISALLOW_COPY_AND_ASSIGN(BinaryDictionaryHeader);
+    DISALLOW_IMPLICIT_CONSTRUCTORS(HeaderPolicy);
 
     static const char *const MULTIPLE_WORDS_DEMOTION_RATE_KEY;
     static const float DEFAULT_MULTI_WORD_COST_MULTIPLIER;
     static const float MULTI_WORD_COST_MULTIPLIER_SCALE;
 
     const uint8_t *const mDictBuf;
-    const BinaryDictionaryHeaderReadingUtils::DictionaryFlags mDictionaryFlags;
+    const HeaderReadingUtils::DictionaryFlags mDictionaryFlags;
     const int mSize;
     const float mMultiWordCostMultiplier;
 
     float readMultiWordCostMultiplier() const;
 };
+
 } // namespace latinime
-#endif // LATINIME_BINARY_DICTIONARY_HEADER_H
+#endif /* LATINIME_HEADER_POLICY_H */
diff --git a/native/jni/src/suggest/core/dictionary/binary_dictionary_header_reading_utils.cpp b/native/jni/src/suggest/core/dictionary/binary_dictionary_header_reading_utils.cpp
index dbcad9d664..2ea35bd551 100644
--- a/native/jni/src/suggest/core/dictionary/binary_dictionary_header_reading_utils.cpp
+++ b/native/jni/src/suggest/core/dictionary/binary_dictionary_header_reading_utils.cpp
@@ -24,39 +24,40 @@
 
 namespace latinime {
 
-const int BinaryDictionaryHeaderReadingUtils::MAX_OPTION_KEY_LENGTH = 256;
-const int BinaryDictionaryHeaderReadingUtils::VERSION_2_HEADER_MAGIC_NUMBER_SIZE = 4;
-const int BinaryDictionaryHeaderReadingUtils::VERSION_2_HEADER_DICTIONARY_VERSION_SIZE = 2;
-const int BinaryDictionaryHeaderReadingUtils::VERSION_2_HEADER_FLAG_SIZE = 2;
-const int BinaryDictionaryHeaderReadingUtils::VERSION_2_HEADER_SIZE_FIELD_SIZE = 4;
+const int HeaderReadingUtils::MAX_OPTION_KEY_LENGTH = 256;
 
-const BinaryDictionaryHeaderReadingUtils::DictionaryFlags
-        BinaryDictionaryHeaderReadingUtils::NO_FLAGS = 0;
+const int HeaderReadingUtils::HEADER_MAGIC_NUMBER_SIZE = 4;
+const int HeaderReadingUtils::HEADER_DICTIONARY_VERSION_SIZE = 2;
+const int HeaderReadingUtils::HEADER_FLAG_SIZE = 2;
+const int HeaderReadingUtils::HEADER_SIZE_FIELD_SIZE = 4;
+
+const HeaderReadingUtils::DictionaryFlags
+        HeaderReadingUtils::NO_FLAGS = 0;
 // Flags for special processing
 // Those *must* match the flags in makedict (BinaryDictInputOutput#*_PROCESSING_FLAG) or
 // something very bad (like, the apocalypse) will happen. Please update both at the same time.
-const BinaryDictionaryHeaderReadingUtils::DictionaryFlags
-        BinaryDictionaryHeaderReadingUtils::GERMAN_UMLAUT_PROCESSING_FLAG = 0x1;
-const BinaryDictionaryHeaderReadingUtils::DictionaryFlags
-        BinaryDictionaryHeaderReadingUtils::SUPPORTS_DYNAMIC_UPDATE_FLAG = 0x2;
-const BinaryDictionaryHeaderReadingUtils::DictionaryFlags
-        BinaryDictionaryHeaderReadingUtils::FRENCH_LIGATURE_PROCESSING_FLAG = 0x4;
+const HeaderReadingUtils::DictionaryFlags
+        HeaderReadingUtils::GERMAN_UMLAUT_PROCESSING_FLAG = 0x1;
+const HeaderReadingUtils::DictionaryFlags
+        HeaderReadingUtils::SUPPORTS_DYNAMIC_UPDATE_FLAG = 0x2;
+const HeaderReadingUtils::DictionaryFlags
+        HeaderReadingUtils::FRENCH_LIGATURE_PROCESSING_FLAG = 0x4;
 
-/* static */ int BinaryDictionaryHeaderReadingUtils::getHeaderSize(const uint8_t *const dictBuf) {
+/* static */ int HeaderReadingUtils::getHeaderSize(const uint8_t *const dictBuf) {
     // See the format of the header in the comment in
     // BinaryDictionaryFormatUtils::detectFormatVersion()
-    return ByteArrayUtils::readUint32(dictBuf, VERSION_2_HEADER_MAGIC_NUMBER_SIZE
-            + VERSION_2_HEADER_DICTIONARY_VERSION_SIZE + VERSION_2_HEADER_FLAG_SIZE);
+    return ByteArrayUtils::readUint32(dictBuf, HEADER_MAGIC_NUMBER_SIZE
+            + HEADER_DICTIONARY_VERSION_SIZE + HEADER_FLAG_SIZE);
 }
 
-/* static */ BinaryDictionaryHeaderReadingUtils::DictionaryFlags
-        BinaryDictionaryHeaderReadingUtils::getFlags(const uint8_t *const dictBuf) {
-    return ByteArrayUtils::readUint16(dictBuf, VERSION_2_HEADER_MAGIC_NUMBER_SIZE
-            + VERSION_2_HEADER_DICTIONARY_VERSION_SIZE);
+/* static */ HeaderReadingUtils::DictionaryFlags
+        HeaderReadingUtils::getFlags(const uint8_t *const dictBuf) {
+    return ByteArrayUtils::readUint16(dictBuf,
+            HEADER_MAGIC_NUMBER_SIZE + HEADER_DICTIONARY_VERSION_SIZE);
 }
 
 // Returns if the key is found or not and reads the found value into outValue.
-/* static */ bool BinaryDictionaryHeaderReadingUtils::readHeaderValue(const uint8_t *const dictBuf,
+/* static */ bool HeaderReadingUtils::readHeaderValue(const uint8_t *const dictBuf,
         const char *const key, int *outValue, const int outValueSize) {
     if (outValueSize <= 0) {
         return false;
@@ -71,8 +72,8 @@ const BinaryDictionaryHeaderReadingUtils::DictionaryFlags
         if(ByteArrayUtils::compareStringInBufferWithCharArray(
                 dictBuf, key, headerSize - pos, &pos) == 0) {
             // The key was found.
-            const int length = ByteArrayUtils::readStringAndAdvancePosition(
-                    dictBuf, outValueSize, outValue, &pos);
+            const int length = ByteArrayUtils::readStringAndAdvancePosition(dictBuf, outValueSize,
+                    outValue, &pos);
             // Add a 0 terminator to the string.
             outValue[length < outValueSize ? length : outValueSize - 1] = '\0';
             return true;
@@ -83,7 +84,7 @@ const BinaryDictionaryHeaderReadingUtils::DictionaryFlags
     return false;
 }
 
-/* static */ int BinaryDictionaryHeaderReadingUtils::readHeaderValueInt(
+/* static */ int HeaderReadingUtils::readHeaderValueInt(
         const uint8_t *const dictBuf, const char *const key) {
     const int bufferSize = LARGEST_INT_DIGIT_COUNT;
     int intBuffer[bufferSize];
diff --git a/native/jni/src/suggest/core/dictionary/binary_dictionary_header_reading_utils.h b/native/jni/src/suggest/core/dictionary/binary_dictionary_header_reading_utils.h
index deae9be271..eed8a041e1 100644
--- a/native/jni/src/suggest/core/dictionary/binary_dictionary_header_reading_utils.h
+++ b/native/jni/src/suggest/core/dictionary/binary_dictionary_header_reading_utils.h
@@ -14,8 +14,8 @@
  * limitations under the License.
  */
 
-#ifndef LATINIME_DICTIONARY_HEADER_READING_UTILS_H
-#define LATINIME_DICTIONARY_HEADER_READING_UTILS_H
+#ifndef LATINIME_HEADER_READING_UTILS_H
+#define LATINIME_HEADER_READING_UTILS_H
 
 #include <stdint.h>
 
@@ -23,8 +23,8 @@
 
 namespace latinime {
 
-// TODO:: Move header classes to policyimpl.
-class BinaryDictionaryHeaderReadingUtils {
+// TODO: Move to policyimpl.
+class HeaderReadingUtils {
  public:
     typedef uint16_t DictionaryFlags;
 
@@ -47,8 +47,8 @@ class BinaryDictionaryHeaderReadingUtils {
     }
 
     static AK_FORCE_INLINE int getHeaderOptionsPosition() {
-        return VERSION_2_HEADER_MAGIC_NUMBER_SIZE + VERSION_2_HEADER_DICTIONARY_VERSION_SIZE
-                + VERSION_2_HEADER_FLAG_SIZE + VERSION_2_HEADER_SIZE_FIELD_SIZE;
+        return HEADER_MAGIC_NUMBER_SIZE + HEADER_DICTIONARY_VERSION_SIZE + HEADER_FLAG_SIZE
+                + HEADER_SIZE_FIELD_SIZE;
     }
 
     static bool readHeaderValue(const uint8_t *const dictBuf,
@@ -57,12 +57,12 @@ class BinaryDictionaryHeaderReadingUtils {
     static int readHeaderValueInt(const uint8_t *const dictBuf, const char *const key);
 
  private:
-    DISALLOW_IMPLICIT_CONSTRUCTORS(BinaryDictionaryHeaderReadingUtils);
+    DISALLOW_IMPLICIT_CONSTRUCTORS(HeaderReadingUtils);
 
-    static const int VERSION_2_HEADER_MAGIC_NUMBER_SIZE;
-    static const int VERSION_2_HEADER_DICTIONARY_VERSION_SIZE;
-    static const int VERSION_2_HEADER_FLAG_SIZE;
-    static const int VERSION_2_HEADER_SIZE_FIELD_SIZE;
+    static const int HEADER_MAGIC_NUMBER_SIZE;
+    static const int HEADER_DICTIONARY_VERSION_SIZE;
+    static const int HEADER_FLAG_SIZE;
+    static const int HEADER_SIZE_FIELD_SIZE;
 
     static const DictionaryFlags NO_FLAGS;
     // Flags for special processing
@@ -74,4 +74,4 @@ class BinaryDictionaryHeaderReadingUtils {
     static const DictionaryFlags CONTAINS_BIGRAMS_FLAG;
 };
 }
-#endif /* LATINIME_DICTIONARY_HEADER_READING_UTILS_H */
+#endif /* LATINIME_HEADER_READING_UTILS_H */
diff --git a/native/jni/src/suggest/core/dictionary/binary_dictionary_info.h b/native/jni/src/suggest/core/dictionary/binary_dictionary_info.h
index da6b0da8c7..e50baae0b7 100644
--- a/native/jni/src/suggest/core/dictionary/binary_dictionary_info.h
+++ b/native/jni/src/suggest/core/dictionary/binary_dictionary_info.h
@@ -20,21 +20,15 @@
 #include <stdint.h>
 
 #include "defines.h"
-#include "jni.h"
-#include "suggest/core/dictionary/binary_dictionary_header.h"
-#include "utils/log_utils.h"
 
 namespace latinime {
 
 class BinaryDictionaryInfo {
  public:
-     AK_FORCE_INLINE BinaryDictionaryInfo(JNIEnv *env, const uint8_t *const dictBuf,
+     AK_FORCE_INLINE BinaryDictionaryInfo(const uint8_t *const dictBuf,
             const int dictSize, const int mmapFd, const int dictBufOffset, const bool isUpdatable)
             : mDictBuf(dictBuf), mDictSize(dictSize), mMmapFd(mmapFd),
-              mDictBufOffset(dictBufOffset), mIsUpdatable(isUpdatable),
-              mDictionaryHeader(dictBuf) {
-        logDictionaryInfo(env);
-    }
+              mDictBufOffset(dictBufOffset), mIsUpdatable(isUpdatable) {}
 
     ~BinaryDictionaryInfo() {}
 
@@ -68,36 +62,6 @@ class BinaryDictionaryInfo {
     const int mMmapFd;
     const int mDictBufOffset;
     const bool mIsUpdatable;
-    // TODO: Move BinaryDictionaryHeader to policyimpl and introduce dedicated API to the
-    // DictionaryStructureWithBufferPolicy.
-    const BinaryDictionaryHeader mDictionaryHeader;
-
-    AK_FORCE_INLINE void logDictionaryInfo(JNIEnv *const env) const {
-        const int BUFFER_SIZE = 16;
-        int dictionaryIdCodePointBuffer[BUFFER_SIZE];
-        int versionStringCodePointBuffer[BUFFER_SIZE];
-        int dateStringCodePointBuffer[BUFFER_SIZE];
-        mDictionaryHeader.readHeaderValueOrQuestionMark("dictionary",
-                dictionaryIdCodePointBuffer, BUFFER_SIZE);
-        mDictionaryHeader.readHeaderValueOrQuestionMark("version",
-                versionStringCodePointBuffer, BUFFER_SIZE);
-        mDictionaryHeader.readHeaderValueOrQuestionMark("date",
-                dateStringCodePointBuffer, BUFFER_SIZE);
-
-        char dictionaryIdCharBuffer[BUFFER_SIZE];
-        char versionStringCharBuffer[BUFFER_SIZE];
-        char dateStringCharBuffer[BUFFER_SIZE];
-        intArrayToCharArray(dictionaryIdCodePointBuffer, BUFFER_SIZE,
-                dictionaryIdCharBuffer, BUFFER_SIZE);
-        intArrayToCharArray(versionStringCodePointBuffer, BUFFER_SIZE,
-                versionStringCharBuffer, BUFFER_SIZE);
-        intArrayToCharArray(dateStringCodePointBuffer, BUFFER_SIZE,
-                dateStringCharBuffer, BUFFER_SIZE);
-
-        LogUtils::logToJava(env,
-                "Dictionary info: dictionary = %s ; version = %s ; date = %s ; filesize = %i",
-                dictionaryIdCharBuffer, versionStringCharBuffer, dateStringCharBuffer, mDictSize);
-    }
 };
 }
 #endif /* LATINIME_BINARY_DICTIONARY_INFO_H */
diff --git a/native/jni/src/suggest/core/dictionary/dictionary.cpp b/native/jni/src/suggest/core/dictionary/dictionary.cpp
index 55ad8611e8..af00e9927c 100644
--- a/native/jni/src/suggest/core/dictionary/dictionary.cpp
+++ b/native/jni/src/suggest/core/dictionary/dictionary.cpp
@@ -21,20 +21,21 @@
 #include <stdint.h>
 
 #include "defines.h"
-#include "jni.h"
 #include "suggest/core/dictionary/bigram_dictionary.h"
+#include "suggest/core/policy/dictionary_header_structure_policy.h"
 #include "suggest/core/session/dic_traverse_session.h"
 #include "suggest/core/suggest.h"
 #include "suggest/core/suggest_options.h"
 #include "suggest/policyimpl/dictionary/dictionary_structure_with_buffer_policy_factory.h"
 #include "suggest/policyimpl/gesture/gesture_suggest_policy_factory.h"
 #include "suggest/policyimpl/typing/typing_suggest_policy_factory.h"
+#include "utils/log_utils.h"
 
 namespace latinime {
 
 Dictionary::Dictionary(JNIEnv *env, void *dict, int dictSize, int mmapFd,
         int dictBufOffset, bool isUpdatable)
-        : mBinaryDictionaryInfo(env, static_cast<const uint8_t *>(dict), dictSize, mmapFd,
+        : mBinaryDictionaryInfo(static_cast<const uint8_t *>(dict), dictSize, mmapFd,
                 dictBufOffset, isUpdatable),
           mDictionaryStructureWithBufferPolicy(DictionaryStructureWithBufferPolicyFactory
                   ::newDictionaryStructureWithBufferPolicy(
@@ -42,6 +43,7 @@ Dictionary::Dictionary(JNIEnv *env, void *dict, int dictSize, int mmapFd,
           mBigramDictionary(new BigramDictionary(mDictionaryStructureWithBufferPolicy)),
           mGestureSuggest(new Suggest(GestureSuggestPolicyFactory::getGestureSuggestPolicy())),
           mTypingSuggest(new Suggest(TypingSuggestPolicyFactory::getTypingSuggestPolicy())) {
+    logDictionaryInfo(env);
 }
 
 Dictionary::~Dictionary() {
@@ -128,4 +130,33 @@ void Dictionary::removeBigramWords(const int *const word0, const int length0,
     // TODO: Support dynamic update
 }
 
+void Dictionary::logDictionaryInfo(JNIEnv *const env) const {
+    const int BUFFER_SIZE = 16;
+    int dictionaryIdCodePointBuffer[BUFFER_SIZE];
+    int versionStringCodePointBuffer[BUFFER_SIZE];
+    int dateStringCodePointBuffer[BUFFER_SIZE];
+    const DictionaryHeaderStructurePolicy *const headerPolicy =
+            getDictionaryStructurePolicy()->getHeaderStructurePolicy();
+    headerPolicy->readHeaderValueOrQuestionMark("dictionary", dictionaryIdCodePointBuffer,
+            BUFFER_SIZE);
+    headerPolicy->readHeaderValueOrQuestionMark("version", versionStringCodePointBuffer,
+            BUFFER_SIZE);
+    headerPolicy->readHeaderValueOrQuestionMark("date", dateStringCodePointBuffer, BUFFER_SIZE);
+
+    char dictionaryIdCharBuffer[BUFFER_SIZE];
+    char versionStringCharBuffer[BUFFER_SIZE];
+    char dateStringCharBuffer[BUFFER_SIZE];
+    intArrayToCharArray(dictionaryIdCodePointBuffer, BUFFER_SIZE,
+            dictionaryIdCharBuffer, BUFFER_SIZE);
+    intArrayToCharArray(versionStringCodePointBuffer, BUFFER_SIZE,
+            versionStringCharBuffer, BUFFER_SIZE);
+    intArrayToCharArray(dateStringCodePointBuffer, BUFFER_SIZE,
+            dateStringCharBuffer, BUFFER_SIZE);
+
+    LogUtils::logToJava(env,
+            "Dictionary info: dictionary = %s ; version = %s ; date = %s ; filesize = %i",
+            dictionaryIdCharBuffer, versionStringCharBuffer, dateStringCharBuffer,
+            mBinaryDictionaryInfo.getDictSize());
+}
+
 } // namespace latinime
diff --git a/native/jni/src/suggest/core/dictionary/dictionary.h b/native/jni/src/suggest/core/dictionary/dictionary.h
index dc07efb0a8..17ce479749 100644
--- a/native/jni/src/suggest/core/dictionary/dictionary.h
+++ b/native/jni/src/suggest/core/dictionary/dictionary.h
@@ -97,6 +97,8 @@ class Dictionary {
     const BigramDictionary *mBigramDictionary;
     SuggestInterface *mGestureSuggest;
     SuggestInterface *mTypingSuggest;
+
+    void logDictionaryInfo(JNIEnv *const env) const;
 };
 } // namespace latinime
 #endif // LATINIME_DICTIONARY_H
diff --git a/native/jni/src/suggest/core/dictionary/digraph_utils.cpp b/native/jni/src/suggest/core/dictionary/digraph_utils.cpp
index af378b1b7b..3271c1bfb7 100644
--- a/native/jni/src/suggest/core/dictionary/digraph_utils.cpp
+++ b/native/jni/src/suggest/core/dictionary/digraph_utils.cpp
@@ -19,7 +19,7 @@
 #include <cstdlib>
 
 #include "defines.h"
-#include "suggest/core/dictionary/binary_dictionary_header.h"
+#include "suggest/core/policy/dictionary_header_structure_policy.h"
 #include "utils/char_utils.h"
 
 namespace latinime {
@@ -35,8 +35,9 @@ const DigraphUtils::DigraphType DigraphUtils::USED_DIGRAPH_TYPES[] =
         { DIGRAPH_TYPE_GERMAN_UMLAUT, DIGRAPH_TYPE_FRENCH_LIGATURES };
 
 /* static */ bool DigraphUtils::hasDigraphForCodePoint(
-        const BinaryDictionaryHeader *const header, const int compositeGlyphCodePoint) {
-    const DigraphUtils::DigraphType digraphType = getDigraphTypeForDictionary(header);
+        const DictionaryHeaderStructurePolicy *const headerPolicy,
+        const int compositeGlyphCodePoint) {
+    const DigraphUtils::DigraphType digraphType = getDigraphTypeForDictionary(headerPolicy);
     if (DigraphUtils::getDigraphForDigraphTypeAndCodePoint(digraphType, compositeGlyphCodePoint)) {
         return true;
     }
@@ -45,11 +46,11 @@ const DigraphUtils::DigraphType DigraphUtils::USED_DIGRAPH_TYPES[] =
 
 // Returns the digraph type associated with the given dictionary.
 /* static */ DigraphUtils::DigraphType DigraphUtils::getDigraphTypeForDictionary(
-        const BinaryDictionaryHeader *const header) {
-    if (header->requiresGermanUmlautProcessing()) {
+        const DictionaryHeaderStructurePolicy *const headerPolicy) {
+    if (headerPolicy->requiresGermanUmlautProcessing()) {
         return DIGRAPH_TYPE_GERMAN_UMLAUT;
     }
-    if (header->requiresFrenchLigatureProcessing()) {
+    if (headerPolicy->requiresFrenchLigatureProcessing()) {
         return DIGRAPH_TYPE_FRENCH_LIGATURES;
     }
     return DIGRAPH_TYPE_NONE;
diff --git a/native/jni/src/suggest/core/dictionary/digraph_utils.h b/native/jni/src/suggest/core/dictionary/digraph_utils.h
index 9d74fe3a61..6ae16e3909 100644
--- a/native/jni/src/suggest/core/dictionary/digraph_utils.h
+++ b/native/jni/src/suggest/core/dictionary/digraph_utils.h
@@ -21,7 +21,7 @@
 
 namespace latinime {
 
-class BinaryDictionaryHeader;
+class DictionaryHeaderStructurePolicy;
 
 class DigraphUtils {
  public:
@@ -39,14 +39,15 @@ class DigraphUtils {
 
     typedef struct { int first; int second; int compositeGlyph; } digraph_t;
 
-    static bool hasDigraphForCodePoint(
-            const BinaryDictionaryHeader *const header, const int compositeGlyphCodePoint);
+    static bool hasDigraphForCodePoint(const DictionaryHeaderStructurePolicy *const headerPolicy,
+            const int compositeGlyphCodePoint);
     static int getDigraphCodePointForIndex(const int compositeGlyphCodePoint,
             const DigraphCodePointIndex digraphCodePointIndex);
 
  private:
     DISALLOW_IMPLICIT_CONSTRUCTORS(DigraphUtils);
-    static DigraphType getDigraphTypeForDictionary(const BinaryDictionaryHeader *const header);
+    static DigraphType getDigraphTypeForDictionary(
+            const DictionaryHeaderStructurePolicy *const headerPolicy);
     static int getAllDigraphsForDigraphTypeAndReturnSize(
             const DigraphType digraphType, const digraph_t **const digraphs);
     static const digraph_t *getDigraphForCodePoint(const int compositeGlyphCodePoint);
diff --git a/native/jni/src/suggest/core/policy/dictionary_header_structure_policy.h b/native/jni/src/suggest/core/policy/dictionary_header_structure_policy.h
new file mode 100644
index 0000000000..a6829b476c
--- /dev/null
+++ b/native/jni/src/suggest/core/policy/dictionary_header_structure_policy.h
@@ -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_DICTIONARY_HEADER_STRUCTURE_POLICY_H
+#define LATINIME_DICTIONARY_HEADER_STRUCTURE_POLICY_H
+
+#include "defines.h"
+
+namespace latinime {
+
+/*
+ * This class abstracts structure of dictionaries.
+ * Implement this policy to support additional dictionaries.
+ */
+class DictionaryHeaderStructurePolicy {
+ public:
+    virtual ~DictionaryHeaderStructurePolicy() {}
+
+    virtual bool supportsDynamicUpdate() const = 0;
+
+    virtual bool requiresGermanUmlautProcessing() const = 0;
+
+    virtual bool requiresFrenchLigatureProcessing() const = 0;
+
+    virtual float getMultiWordCostMultiplier() const = 0;
+
+    virtual void readHeaderValueOrQuestionMark(const char *const key, int *outValue,
+            int outValueSize) const = 0;
+
+ protected:
+    DictionaryHeaderStructurePolicy() {}
+
+ private:
+    DISALLOW_COPY_AND_ASSIGN(DictionaryHeaderStructurePolicy);
+};
+} // namespace latinime
+#endif /* LATINIME_DICTIONARY_HEADER_STRUCTURE_POLICY_H */
diff --git a/native/jni/src/suggest/core/policy/dictionary_structure_with_buffer_policy.h b/native/jni/src/suggest/core/policy/dictionary_structure_with_buffer_policy.h
index a8a8b26071..1b34f03f07 100644
--- a/native/jni/src/suggest/core/policy/dictionary_structure_with_buffer_policy.h
+++ b/native/jni/src/suggest/core/policy/dictionary_structure_with_buffer_policy.h
@@ -21,10 +21,10 @@
 
 namespace latinime {
 
-class BinaryDictionaryHeader;
 class DicNode;
 class DicNodeVector;
 class DictionaryBigramsStructurePolicy;
+class DictionaryHeaderStructurePolicy;
 class DictionaryShortcutsStructurePolicy;
 
 /*
@@ -66,8 +66,7 @@ class DictionaryStructureWithBufferPolicy {
 
     virtual int getBigramsPositionOfNode(const int nodePos) const = 0;
 
-    // TODO: Use policy to access header information.
-    virtual const BinaryDictionaryHeader *getHeader() const = 0;
+    virtual const DictionaryHeaderStructurePolicy *getHeaderStructurePolicy() const = 0;
 
     virtual const DictionaryBigramsStructurePolicy *getBigramsStructurePolicy() const = 0;
 
diff --git a/native/jni/src/suggest/core/session/dic_traverse_session.cpp b/native/jni/src/suggest/core/session/dic_traverse_session.cpp
index 30a41f0eab..0ca583f900 100644
--- a/native/jni/src/suggest/core/session/dic_traverse_session.cpp
+++ b/native/jni/src/suggest/core/session/dic_traverse_session.cpp
@@ -17,9 +17,8 @@
 #include "suggest/core/session/dic_traverse_session.h"
 
 #include "defines.h"
-#include "jni.h"
-#include "suggest/core/dictionary/binary_dictionary_header.h"
 #include "suggest/core/dictionary/dictionary.h"
+#include "suggest/core/policy/dictionary_header_structure_policy.h"
 #include "suggest/core/policy/dictionary_structure_with_buffer_policy.h"
 
 namespace latinime {
@@ -27,7 +26,7 @@ namespace latinime {
 void DicTraverseSession::init(const Dictionary *const dictionary, const int *prevWord,
         int prevWordLength, const SuggestOptions *const suggestOptions) {
     mDictionary = dictionary;
-    mMultiWordCostMultiplier = getDictionaryStructurePolicy()->getHeader()
+    mMultiWordCostMultiplier = getDictionaryStructurePolicy()->getHeaderStructurePolicy()
             ->getMultiWordCostMultiplier();
     mSuggestOptions = suggestOptions;
     if (!prevWord) {
diff --git a/native/jni/src/suggest/core/suggest.cpp b/native/jni/src/suggest/core/suggest.cpp
index 5ebf79bfe5..3b77227a00 100644
--- a/native/jni/src/suggest/core/suggest.cpp
+++ b/native/jni/src/suggest/core/suggest.cpp
@@ -308,7 +308,8 @@ void Suggest::expandCurrentDicNodes(DicTraverseSession *traverseSession) const {
                     continue;
                 }
                 if (DigraphUtils::hasDigraphForCodePoint(
-                        traverseSession->getDictionaryStructurePolicy()->getHeader(),
+                        traverseSession->getDictionaryStructurePolicy()
+                                ->getHeaderStructurePolicy(),
                         childDicNode->getNodeCodePoint())) {
                     correctionDicNode.initByCopy(childDicNode);
                     correctionDicNode.advanceDigraphIndex();
diff --git a/native/jni/src/suggest/policyimpl/dictionary/dynamic_patricia_trie_policy.h b/native/jni/src/suggest/policyimpl/dictionary/dynamic_patricia_trie_policy.h
index 490c62f918..80ccbdc0fe 100644
--- a/native/jni/src/suggest/policyimpl/dictionary/dynamic_patricia_trie_policy.h
+++ b/native/jni/src/suggest/policyimpl/dictionary/dynamic_patricia_trie_policy.h
@@ -33,7 +33,7 @@ class DicNodeVector;
 class DynamicPatriciaTriePolicy : public DictionaryStructureWithBufferPolicy {
  public:
     DynamicPatriciaTriePolicy(const uint8_t *const dictBuf)
-            : mHeader(dictBuf), mDictRoot(dictBuf + mHeader.getSize()),
+            : mHeaderPolicy(dictBuf), mDictRoot(dictBuf + mHeaderPolicy.getSize()),
               mBigramListPolicy(mDictRoot), mShortcutListPolicy(mDictRoot) {}
 
     ~DynamicPatriciaTriePolicy() {}
@@ -58,9 +58,8 @@ class DynamicPatriciaTriePolicy : public DictionaryStructureWithBufferPolicy {
 
     int getBigramsPositionOfNode(const int nodePos) const;
 
-    // TODO: Remove and use policy to access header information.
-    const BinaryDictionaryHeader *getHeader() const {
-        return &mHeader;
+    const DictionaryHeaderStructurePolicy *getHeaderStructurePolicy() const {
+        return &mHeaderPolicy;
     }
 
     const DictionaryBigramsStructurePolicy *getBigramsStructurePolicy() const {
@@ -75,7 +74,7 @@ class DynamicPatriciaTriePolicy : public DictionaryStructureWithBufferPolicy {
     DISALLOW_IMPLICIT_CONSTRUCTORS(DynamicPatriciaTriePolicy);
     static const int MAX_CHILD_COUNT_TO_AVOID_INFINITE_LOOP;
 
-    const BinaryDictionaryHeader mHeader;
+    const HeaderPolicy mHeaderPolicy;
     // TODO: Consolidate mDictRoot.
     const uint8_t *const mDictRoot;
     const BigramListPolicy mBigramListPolicy;
diff --git a/native/jni/src/suggest/policyimpl/dictionary/patricia_trie_policy.h b/native/jni/src/suggest/policyimpl/dictionary/patricia_trie_policy.h
index ee51a7e055..20c08b1393 100644
--- a/native/jni/src/suggest/policyimpl/dictionary/patricia_trie_policy.h
+++ b/native/jni/src/suggest/policyimpl/dictionary/patricia_trie_policy.h
@@ -33,7 +33,7 @@ class DicNodeVector;
 class PatriciaTriePolicy : public DictionaryStructureWithBufferPolicy {
  public:
     PatriciaTriePolicy(const uint8_t *const dictBuf)
-            : mHeader(dictBuf), mDictRoot(dictBuf + mHeader.getSize()),
+            : mHeaderPolicy(dictBuf), mDictRoot(dictBuf + mHeaderPolicy.getSize()),
               mBigramListPolicy(mDictRoot), mShortcutListPolicy(mDictRoot) {}
 
     ~PatriciaTriePolicy() {}
@@ -58,9 +58,8 @@ class PatriciaTriePolicy : public DictionaryStructureWithBufferPolicy {
 
     int getBigramsPositionOfNode(const int nodePos) const;
 
-    // TODO: Remove and use policy to access header information.
-    const BinaryDictionaryHeader *getHeader() const {
-        return &mHeader;
+    const DictionaryHeaderStructurePolicy *getHeaderStructurePolicy() const {
+        return &mHeaderPolicy;
     }
 
     const DictionaryBigramsStructurePolicy *getBigramsStructurePolicy() const {
@@ -74,7 +73,7 @@ class PatriciaTriePolicy : public DictionaryStructureWithBufferPolicy {
  private:
     DISALLOW_IMPLICIT_CONSTRUCTORS(PatriciaTriePolicy);
 
-    const BinaryDictionaryHeader mHeader;
+    const HeaderPolicy mHeaderPolicy;
     const uint8_t *const mDictRoot;
     const BigramListPolicy mBigramListPolicy;
     const ShortcutListPolicy mShortcutListPolicy;
-- 
GitLab