Merge "Start to support adding shortcuts."
diff --git a/native/jni/src/defines.h b/native/jni/src/defines.h
index 5648115..9a26fe0 100644
--- a/native/jni/src/defines.h
+++ b/native/jni/src/defines.h
@@ -298,6 +298,7 @@
 #define NOT_AN_INDEX (-1)
 #define NOT_A_PROBABILITY (-1)
 #define NOT_A_DICT_POS (S_INT_MIN)
+#define NOT_A_TIMESTAMP (-1)
 
 // A special value to mean the first word confidence makes no sense in this case,
 // e.g. this is not a multi-word suggestion.
diff --git a/native/jni/src/suggest/policyimpl/dictionary/structure/v4/content/bigram_dict_content.cpp b/native/jni/src/suggest/policyimpl/dictionary/structure/v4/content/bigram_dict_content.cpp
index 04c80a7..cb9d450 100644
--- a/native/jni/src/suggest/policyimpl/dictionary/structure/v4/content/bigram_dict_content.cpp
+++ b/native/jni/src/suggest/policyimpl/dictionary/structure/v4/content/bigram_dict_content.cpp
@@ -27,7 +27,7 @@
             Ver4DictConstants::BIGRAM_FLAGS_FIELD_SIZE, bigramEntryPos);
     const bool hasNext = (bigramFlags & Ver4DictConstants::BIGRAM_HAS_NEXT_MASK) != 0;
     int probability = NOT_A_PROBABILITY;
-    int timestamp = Ver4DictConstants::NOT_A_TIME_STAMP;
+    int timestamp = NOT_A_TIMESTAMP;
     int level = 0;
     int count = 0;
     if (mHasHistoricalInfo) {
@@ -48,7 +48,8 @@
             (encodedTargetTerminalId == Ver4DictConstants::INVALID_BIGRAM_TARGET_TERMINAL_ID) ?
                     Ver4DictConstants::NOT_A_TERMINAL_ID : encodedTargetTerminalId;
     if (mHasHistoricalInfo) {
-        return BigramEntry(hasNext, probability, timestamp, level, count, targetTerminalId);
+        const HistoricalInfo historicalInfo(timestamp, level, count);
+        return BigramEntry(hasNext, probability, &historicalInfo, targetTerminalId);
     } else {
         return BigramEntry(hasNext, probability, targetTerminalId);
     }
@@ -72,22 +73,23 @@
                     bigramEntryToWrite->getProbability());
             return false;
         }
-        if (!bigramListBuffer->writeUintAndAdvancePosition(bigramEntryToWrite->getTimeStamp(),
+        const HistoricalInfo *const historicalInfo = bigramEntryToWrite->getHistoricalInfo();
+        if (!bigramListBuffer->writeUintAndAdvancePosition(historicalInfo->getTimeStamp(),
                 Ver4DictConstants::TIME_STAMP_FIELD_SIZE, entryWritingPos)) {
             AKLOGE("Cannot write bigram timestamps. pos: %d, timestamp: %d", *entryWritingPos,
-                    bigramEntryToWrite->getTimeStamp());
+                    historicalInfo->getTimeStamp());
             return false;
         }
-        if (!bigramListBuffer->writeUintAndAdvancePosition(bigramEntryToWrite->getLevel(),
+        if (!bigramListBuffer->writeUintAndAdvancePosition(historicalInfo->getLevel(),
                 Ver4DictConstants::WORD_LEVEL_FIELD_SIZE, entryWritingPos)) {
             AKLOGE("Cannot write bigram level. pos: %d, level: %d", *entryWritingPos,
-                    bigramEntryToWrite->getLevel());
+                    historicalInfo->getLevel());
             return false;
         }
-        if (!bigramListBuffer->writeUintAndAdvancePosition(bigramEntryToWrite->getCount(),
+        if (!bigramListBuffer->writeUintAndAdvancePosition(historicalInfo->getCount(),
                 Ver4DictConstants::WORD_COUNT_FIELD_SIZE, entryWritingPos)) {
             AKLOGE("Cannot write bigram count. pos: %d, count: %d", *entryWritingPos,
-                    bigramEntryToWrite->getCount());
+                    historicalInfo->getCount());
             return false;
         }
     }
diff --git a/native/jni/src/suggest/policyimpl/dictionary/structure/v4/content/bigram_entry.h b/native/jni/src/suggest/policyimpl/dictionary/structure/v4/content/bigram_entry.h
index 10b3ec8..8050145 100644
--- a/native/jni/src/suggest/policyimpl/dictionary/structure/v4/content/bigram_entry.h
+++ b/native/jni/src/suggest/policyimpl/dictionary/structure/v4/content/bigram_entry.h
@@ -19,6 +19,7 @@
 
 #include "defines.h"
 #include "suggest/policyimpl/dictionary/structure/v4/ver4_dict_constants.h"
+#include "suggest/policyimpl/dictionary/utils/historical_info.h"
 
 namespace latinime {
 
@@ -26,38 +27,38 @@
  public:
     BigramEntry(const BigramEntry& bigramEntry)
             : mHasNext(bigramEntry.mHasNext), mProbability(bigramEntry.mProbability),
-              mTimestamp(bigramEntry.mTimestamp), mLevel(bigramEntry.mLevel),
-              mCount(bigramEntry.mCount), mTargetTerminalId(bigramEntry.mTargetTerminalId) {}
+              mHistoricalInfo(), mTargetTerminalId(bigramEntry.mTargetTerminalId) {}
 
     // Entry with historical information.
     BigramEntry(const bool hasNext, const int probability, const int targetTerminalId)
-            : mHasNext(hasNext), mProbability(probability),
-              mTimestamp(Ver4DictConstants::NOT_A_TIME_STAMP), mLevel(0), mCount(0),
+            : mHasNext(hasNext), mProbability(probability), mHistoricalInfo(),
               mTargetTerminalId(targetTerminalId) {}
 
     // Entry with historical information.
-    BigramEntry(const bool hasNext, const int probability, const int timestamp, const int level,
-            const int count, const int targetTerminalId)
-            : mHasNext(hasNext), mProbability(probability), mTimestamp(timestamp),
-              mLevel(level), mCount(count), mTargetTerminalId(targetTerminalId) {}
+    BigramEntry(const bool hasNext, const int probability,
+            const HistoricalInfo *const historicalInfo, const int targetTerminalId)
+            : mHasNext(hasNext), mProbability(probability), mHistoricalInfo(*historicalInfo),
+              mTargetTerminalId(targetTerminalId) {}
 
     const BigramEntry getInvalidatedEntry() const {
         return updateTargetTerminalIdAndGetEntry(Ver4DictConstants::NOT_A_TERMINAL_ID);
     }
 
     const BigramEntry updateHasNextAndGetEntry(const bool hasNext) const {
-        return BigramEntry(hasNext, mProbability, mTimestamp, mLevel, mCount,
-                mTargetTerminalId);
+        return BigramEntry(hasNext, mProbability, &mHistoricalInfo, mTargetTerminalId);
     }
 
     const BigramEntry updateTargetTerminalIdAndGetEntry(const int newTargetTerminalId) const {
-        return BigramEntry(mHasNext, mProbability, mTimestamp, mLevel, mCount,
-                newTargetTerminalId);
+        return BigramEntry(mHasNext, mProbability, &mHistoricalInfo, newTargetTerminalId);
     }
 
     const BigramEntry updateProbabilityAndGetEntry(const int probability) const {
-        return BigramEntry(mHasNext, probability, mTimestamp, mLevel, mCount,
-                mTargetTerminalId);
+        return BigramEntry(mHasNext, probability, &mHistoricalInfo, mTargetTerminalId);
+    }
+
+    const BigramEntry updateHistoricalInfoAndGetEntry(
+            const HistoricalInfo *const historicalInfo) const {
+        return BigramEntry(mHasNext, mProbability, historicalInfo, mTargetTerminalId);
     }
 
     bool isValid() const {
@@ -72,16 +73,8 @@
         return mProbability;
     }
 
-    int getTimeStamp() const {
-        return mTimestamp;
-    }
-
-    int getLevel() const {
-        return mLevel;
-    }
-
-    int getCount() const {
-        return mCount;
+    const HistoricalInfo *getHistoricalInfo() const {
+        return &mHistoricalInfo;
     }
 
     int getTargetTerminalId() const {
@@ -95,9 +88,7 @@
 
     const bool mHasNext;
     const int mProbability;
-    const int mTimestamp;
-    const int mLevel;
-    const int mCount;
+    const HistoricalInfo mHistoricalInfo;
     const int mTargetTerminalId;
 };
 } // namespace latinime
diff --git a/native/jni/src/suggest/policyimpl/dictionary/structure/v4/content/probability_dict_content.cpp b/native/jni/src/suggest/policyimpl/dictionary/structure/v4/content/probability_dict_content.cpp
index 7a75499..01e406b 100644
--- a/native/jni/src/suggest/policyimpl/dictionary/structure/v4/content/probability_dict_content.cpp
+++ b/native/jni/src/suggest/policyimpl/dictionary/structure/v4/content/probability_dict_content.cpp
@@ -41,7 +41,8 @@
                 Ver4DictConstants::WORD_LEVEL_FIELD_SIZE, &entryPos);
         const int count = buffer->readUintAndAdvancePosition(
                 Ver4DictConstants::WORD_COUNT_FIELD_SIZE, &entryPos);
-        return ProbabilityEntry(flags, probability, timestamp, level, count);
+        const HistoricalInfo historicalInfo(timestamp, level, count);
+        return ProbabilityEntry(flags, probability, &historicalInfo);
     } else {
         return ProbabilityEntry(flags, probability);
     }
@@ -136,17 +137,18 @@
         return false;
     }
     if (mHasHistoricalInfo) {
-        if (!bufferToWrite->writeUintAndAdvancePosition(probabilityEntry->getTimeStamp(),
+        const HistoricalInfo *const historicalInfo = probabilityEntry->getHistoricalInfo();
+        if (!bufferToWrite->writeUintAndAdvancePosition(historicalInfo->getTimeStamp(),
                 Ver4DictConstants::TIME_STAMP_FIELD_SIZE, &writingPos)) {
             AKLOGE("Cannot write timestamp in probability dict content. pos: %d", writingPos);
             return false;
         }
-        if (!bufferToWrite->writeUintAndAdvancePosition(probabilityEntry->getLevel(),
+        if (!bufferToWrite->writeUintAndAdvancePosition(historicalInfo->getLevel(),
                 Ver4DictConstants::WORD_LEVEL_FIELD_SIZE, &writingPos)) {
             AKLOGE("Cannot write level in probability dict content. pos: %d", writingPos);
             return false;
         }
-        if (!bufferToWrite->writeUintAndAdvancePosition(probabilityEntry->getCount(),
+        if (!bufferToWrite->writeUintAndAdvancePosition(historicalInfo->getCount(),
                 Ver4DictConstants::WORD_COUNT_FIELD_SIZE, &writingPos)) {
             AKLOGE("Cannot write count in probability dict content. pos: %d", writingPos);
             return false;
diff --git a/native/jni/src/suggest/policyimpl/dictionary/structure/v4/content/probability_entry.h b/native/jni/src/suggest/policyimpl/dictionary/structure/v4/content/probability_entry.h
index 274c465..d1b28cc 100644
--- a/native/jni/src/suggest/policyimpl/dictionary/structure/v4/content/probability_entry.h
+++ b/native/jni/src/suggest/policyimpl/dictionary/structure/v4/content/probability_entry.h
@@ -19,6 +19,7 @@
 
 #include "defines.h"
 #include "suggest/policyimpl/dictionary/structure/v4/ver4_dict_constants.h"
+#include "suggest/policyimpl/dictionary/utils/historical_info.h"
 
 namespace latinime {
 
@@ -26,27 +27,28 @@
  public:
     ProbabilityEntry(const ProbabilityEntry &probabilityEntry)
             : mFlags(probabilityEntry.mFlags), mProbability(probabilityEntry.mProbability),
-              mTimestamp(probabilityEntry.mTimestamp), mLevel(probabilityEntry.mLevel),
-              mCount(probabilityEntry.mCount) {}
+              mHistoricalInfo(probabilityEntry.mHistoricalInfo) {}
 
     // Dummy entry
     ProbabilityEntry()
-            : mFlags(0), mProbability(NOT_A_PROBABILITY),
-              mTimestamp(Ver4DictConstants::NOT_A_TIME_STAMP), mLevel(0), mCount(0) {}
+            : mFlags(0), mProbability(NOT_A_PROBABILITY), mHistoricalInfo() {}
 
     // Entry without historical information
     ProbabilityEntry(const int flags, const int probability)
-            : mFlags(flags), mProbability(probability),
-              mTimestamp(Ver4DictConstants::NOT_A_TIME_STAMP), mLevel(0), mCount(0) {}
+            : mFlags(flags), mProbability(probability), mHistoricalInfo() {}
 
     // Entry with historical information.
-    ProbabilityEntry(const int flags, const int probability, const int timestamp,
-            const int level, const int count)
-            : mFlags(flags), mProbability(probability), mTimestamp(timestamp), mLevel(level),
-              mCount(count) {}
+    ProbabilityEntry(const int flags, const int probability,
+            const HistoricalInfo *const historicalInfo)
+            : mFlags(flags), mProbability(probability), mHistoricalInfo(*historicalInfo) {}
 
     const ProbabilityEntry createEntryWithUpdatedProbability(const int probability) const {
-        return ProbabilityEntry(mFlags, probability, mTimestamp, mLevel, mCount);
+        return ProbabilityEntry(mFlags, probability, &mHistoricalInfo);
+    }
+
+    const ProbabilityEntry createEntryWithUpdatedHistoricalInfo(
+            const HistoricalInfo *const historicalInfo) const {
+        return ProbabilityEntry(mFlags, mProbability, historicalInfo);
     }
 
     int getFlags() const {
@@ -57,16 +59,8 @@
         return mProbability;
     }
 
-    int getTimeStamp() const {
-        return mTimestamp;
-    }
-
-    int getLevel() const {
-        return mLevel;
-    }
-
-    int getCount() const {
-        return mCount;
+    const HistoricalInfo *getHistoricalInfo() const {
+        return &mHistoricalInfo;
     }
 
  private:
@@ -75,9 +69,7 @@
 
     const int mFlags;
     const int mProbability;
-    const int mTimestamp;
-    const int mLevel;
-    const int mCount;
+    const HistoricalInfo mHistoricalInfo;
 };
 } // namespace latinime
 #endif /* LATINIME_PROBABILITY_ENTRY_H */
diff --git a/native/jni/src/suggest/policyimpl/dictionary/structure/v4/ver4_dict_constants.cpp b/native/jni/src/suggest/policyimpl/dictionary/structure/v4/ver4_dict_constants.cpp
index d359caa..066d6ed 100644
--- a/native/jni/src/suggest/policyimpl/dictionary/structure/v4/ver4_dict_constants.cpp
+++ b/native/jni/src/suggest/policyimpl/dictionary/structure/v4/ver4_dict_constants.cpp
@@ -38,7 +38,6 @@
 const int Ver4DictConstants::MAX_DICT_EXTENDED_REGION_SIZE = 1 * 1024 * 1024;
 
 const int Ver4DictConstants::NOT_A_TERMINAL_ID = -1;
-const int Ver4DictConstants::NOT_A_TIME_STAMP = -1;
 const int Ver4DictConstants::PROBABILITY_SIZE = 1;
 const int Ver4DictConstants::FLAGS_IN_PROBABILITY_FILE_SIZE = 1;
 const int Ver4DictConstants::TERMINAL_ADDRESS_TABLE_ADDRESS_SIZE = 3;
diff --git a/native/jni/src/suggest/policyimpl/dictionary/structure/v4/ver4_dict_constants.h b/native/jni/src/suggest/policyimpl/dictionary/structure/v4/ver4_dict_constants.h
index 5764bed..7afdc86 100644
--- a/native/jni/src/suggest/policyimpl/dictionary/structure/v4/ver4_dict_constants.h
+++ b/native/jni/src/suggest/policyimpl/dictionary/structure/v4/ver4_dict_constants.h
@@ -38,7 +38,6 @@
     static const int MAX_DICT_EXTENDED_REGION_SIZE;
 
     static const int NOT_A_TERMINAL_ID;
-    static const int NOT_A_TIME_STAMP;
     static const int PROBABILITY_SIZE;
     static const int FLAGS_IN_PROBABILITY_FILE_SIZE;
     static const int TERMINAL_ADDRESS_TABLE_ADDRESS_SIZE;
diff --git a/native/jni/src/suggest/policyimpl/dictionary/structure/v4/ver4_patricia_trie_policy.cpp b/native/jni/src/suggest/policyimpl/dictionary/structure/v4/ver4_patricia_trie_policy.cpp
index 9c8db3b..82cd95e 100644
--- a/native/jni/src/suggest/policyimpl/dictionary/structure/v4/ver4_patricia_trie_policy.cpp
+++ b/native/jni/src/suggest/policyimpl/dictionary/structure/v4/ver4_patricia_trie_policy.cpp
@@ -319,6 +319,7 @@
     const ProbabilityEntry probabilityEntry =
             mBuffers.get()->getProbabilityDictContent()->getProbabilityEntry(
                     ptNodeParams.getTerminalId());
+    const HistoricalInfo *const historicalInfo = probabilityEntry.getHistoricalInfo();
     // Fetch shortcut information.
     std::vector<std::vector<int> > shortcutTargets;
     std::vector<int> shortcutProbabilities;
@@ -341,8 +342,8 @@
     return UnigramProperty(ptNodeParams.getCodePoints(), ptNodeParams.getCodePointCount(),
             ptNodeParams.isNotAWord(), ptNodeParams.isBlacklisted(), ptNodeParams.hasBigrams(),
             ptNodeParams.hasShortcutTargets(), ptNodeParams.getProbability(),
-            probabilityEntry.getTimeStamp(), probabilityEntry.getLevel(),
-            probabilityEntry.getCount(), &shortcutTargets, &shortcutProbabilities);
+            historicalInfo->getTimeStamp(), historicalInfo->getLevel(),
+            historicalInfo->getCount(), &shortcutTargets, &shortcutProbabilities);
 }
 
 } // namespace latinime
diff --git a/native/jni/src/suggest/policyimpl/dictionary/utils/historical_info.h b/native/jni/src/suggest/policyimpl/dictionary/utils/historical_info.h
new file mode 100644
index 0000000..64c0136
--- /dev/null
+++ b/native/jni/src/suggest/policyimpl/dictionary/utils/historical_info.h
@@ -0,0 +1,54 @@
+/*
+ * 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_HISTORICAL_INFO_H
+#define LATINIME_HISTORICAL_INFO_H
+
+#include "defines.h"
+
+namespace latinime {
+
+class HistoricalInfo {
+ public:
+    // Invalid historical info.
+    HistoricalInfo()
+            : mTimestamp(NOT_A_TIMESTAMP), mLevel(0), mCount(0) {}
+
+    HistoricalInfo(const int timestamp, const int level, const int count)
+            : mTimestamp(timestamp), mLevel(level), mCount(count) {}
+
+    int getTimeStamp() const {
+        return mTimestamp;
+    }
+
+    int getLevel() const {
+        return mLevel;
+    }
+
+    int getCount() const {
+        return mCount;
+    }
+
+ private:
+    // Copy constructor is public to use this class as a type of return value.
+    DISALLOW_ASSIGNMENT_OPERATOR(HistoricalInfo);
+
+    const int mTimestamp;
+    const int mLevel;
+    const int mCount;
+};
+} // namespace latinime
+#endif /* LATINIME_HISTORICAL_INFO_H */