aboutsummaryrefslogtreecommitdiffstats
path: root/native/jni/src/suggest/policyimpl/dictionary/header/header_policy.cpp
blob: 47ace23a1aaff50a402acff5567c3fc6f4668343 (about) (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
/*
 * 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/header/header_policy.h"

#include <cstddef>
#include <cstdio>
#include <ctime>

namespace latinime {

const char *const HeaderPolicy::MULTIPLE_WORDS_DEMOTION_RATE_KEY = "MULTIPLE_WORDS_DEMOTION_RATE";
const char *const HeaderPolicy::USES_FORGETTING_CURVE_KEY = "USES_FORGETTING_CURVE";
const char *const HeaderPolicy::LAST_UPDATED_TIME_KEY = "date";
const float HeaderPolicy::DEFAULT_MULTIPLE_WORD_COST_MULTIPLIER = 1.0f;
const float HeaderPolicy::MULTIPLE_WORD_COST_MULTIPLIER_SCALE = 100.0f;

// Used for logging. Question mark is used to indicate that the key is not found.
void HeaderPolicy::readHeaderValueOrQuestionMark(const char *const key, int *outValue,
        int outValueSize) const {
    if (outValueSize <= 0) return;
    if (outValueSize == 1) {
        outValue[0] = '\0';
        return;
    }
    std::vector<int> keyCodePointVector;
    insertCharactersIntoVector(key, &keyCodePointVector);
    HeaderReadWriteUtils::AttributeMap::const_iterator it = mAttributeMap.find(keyCodePointVector);
    if (it == mAttributeMap.end()) {
        // The key was not found.
        outValue[0] = '?';
        outValue[1] = '\0';
        return;
    }
    const int terminalIndex = min(static_cast<int>(it->second.size()), outValueSize - 1);
    for (int i = 0; i < terminalIndex; ++i) {
        outValue[i] = it->second[i];
    }
    outValue[terminalIndex] = '\0';
}

float HeaderPolicy::readMultipleWordCostMultiplier() const {
    int attributeValue = 0;
    if (getAttributeValueAsInt(MULTIPLE_WORDS_DEMOTION_RATE_KEY, &attributeValue)) {
        if (attributeValue <= 0) {
            return static_cast<float>(MAX_VALUE_FOR_WEIGHTING);
        }
        return MULTIPLE_WORD_COST_MULTIPLIER_SCALE / static_cast<float>(attributeValue);
    } else {
        return DEFAULT_MULTIPLE_WORD_COST_MULTIPLIER;
    }
}

bool HeaderPolicy::readUsesForgettingCurveFlag() const {
    int attributeValue = 0;
    if (getAttributeValueAsInt(USES_FORGETTING_CURVE_KEY, &attributeValue)) {
        return attributeValue != 0;
    } else {
        return false;
    }
}

// Returns S_INT_MIN when the key is not found or the value is invalid.
int HeaderPolicy::readLastUpdatedTime() const {
    int attributeValue = 0;
    if (getAttributeValueAsInt(LAST_UPDATED_TIME_KEY, &attributeValue)) {
        return attributeValue;
    } else {
        return S_INT_MIN;
    }
}

// Returns whether the key is found or not and stores the found value into outValue.
bool HeaderPolicy::getAttributeValueAsInt(const char *const key, int *const outValue) const {
    std::vector<int> keyVector;
    insertCharactersIntoVector(key, &keyVector);
    HeaderReadWriteUtils::AttributeMap::const_iterator it = mAttributeMap.find(keyVector);
    if (it == mAttributeMap.end()) {
        // The key was not found.
        return false;
    }
    *outValue = parseIntAttributeValue(&(it->second));
    return true;
}

bool HeaderPolicy::writeHeaderToBuffer(BufferWithExtendableBuffer *const bufferToWrite,
        const bool updatesLastUpdatedTime) const {
    int writingPos = 0;
    if (!HeaderReadWriteUtils::writeDictionaryVersion(bufferToWrite, mDictFormatVersion,
            &writingPos)) {
        return false;
    }
    if (!HeaderReadWriteUtils::writeDictionaryFlags(bufferToWrite, mDictionaryFlags,
            &writingPos)) {
        return false;
    }
    // Temporarily writes a dummy header size.
    int headerSizeFieldPos = writingPos;
    if (!HeaderReadWriteUtils::writeDictionaryHeaderSize(bufferToWrite, 0 /* size */,
            &writingPos)) {
        return false;
    }
    if (updatesLastUpdatedTime) {
        // Set current time as a last updated time.
        HeaderReadWriteUtils::AttributeMap attributeMapTowrite(mAttributeMap);
        std::vector<int> updatedTimekey;
        insertCharactersIntoVector(LAST_UPDATED_TIME_KEY, &updatedTimekey);
        const time_t currentTime = time(NULL);
        std::vector<int> updatedTimeValue;
        char charBuf[LARGEST_INT_DIGIT_COUNT + 1];
        snprintf(charBuf, LARGEST_INT_DIGIT_COUNT + 1, "%ld", currentTime);
        insertCharactersIntoVector(charBuf, &updatedTimeValue);
        attributeMapTowrite[updatedTimekey] = updatedTimeValue;
        if (!HeaderReadWriteUtils::writeHeaderAttributes(bufferToWrite, &attributeMapTowrite,
                &writingPos)) {
            return false;
        }
    } else {
        if (!HeaderReadWriteUtils::writeHeaderAttributes(bufferToWrite, &mAttributeMap,
                &writingPos)) {
            return false;
        }
    }
    // Writes an actual header size.
    if (!HeaderReadWriteUtils::writeDictionaryHeaderSize(bufferToWrite, writingPos,
            &headerSizeFieldPos)) {
        return false;
    }
    return true;
}

/* static */ HeaderReadWriteUtils::AttributeMap
        HeaderPolicy::createAttributeMapAndReadAllAttributes(const uint8_t *const dictBuf) {
    HeaderReadWriteUtils::AttributeMap attributeMap;
    HeaderReadWriteUtils::fetchAllHeaderAttributes(dictBuf, &attributeMap);
    return attributeMap;
}

/* static */ int HeaderPolicy::parseIntAttributeValue(
        const std::vector<int> *const attributeValue) {
    int value = 0;
    bool isNegative = false;
    for (size_t i = 0; i < attributeValue->size(); ++i) {
        if (i == 0 && attributeValue->at(i) == '-') {
            isNegative = true;
        } else {
            if (!isdigit(attributeValue->at(i))) {
                // If not a number, return S_INT_MIN
                return S_INT_MIN;
            }
            value *= 10;
            value += attributeValue->at(i) - '0';
        }
    }
    return isNegative ? -value : value;
}

/* static */ void HeaderPolicy::insertCharactersIntoVector(const char *const characters,
        std::vector<int> *const vector) {
    for (int i = 0; characters[i]; ++i) {
        vector->push_back(characters[i]);
    }
}

} // namespace latinime