2012-09-11 01:28:15 +00:00
|
|
|
/*
|
|
|
|
* Copyright (C) 2012 The Android Open Source Project
|
|
|
|
*
|
2013-01-21 12:52:57 +00:00
|
|
|
* 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
|
2012-09-11 01:28:15 +00:00
|
|
|
*
|
2013-01-21 12:52:57 +00:00
|
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
2012-09-11 01:28:15 +00:00
|
|
|
*
|
|
|
|
* Unless required by applicable law or agreed to in writing, software
|
2013-01-21 12:52:57 +00:00
|
|
|
* 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.
|
2012-09-11 01:28:15 +00:00
|
|
|
*/
|
|
|
|
|
|
|
|
package com.android.inputmethod.latin.makedict;
|
|
|
|
|
2013-08-08 10:09:26 +00:00
|
|
|
import com.android.inputmethod.annotations.UsedForTesting;
|
2012-09-11 01:28:15 +00:00
|
|
|
import com.android.inputmethod.latin.Constants;
|
2013-09-12 08:46:09 +00:00
|
|
|
import com.android.inputmethod.latin.makedict.DictDecoder.DictionaryBufferFactory;
|
2012-09-12 09:53:33 +00:00
|
|
|
import com.android.inputmethod.latin.makedict.FusionDictionary.DictionaryOptions;
|
2012-09-11 01:28:15 +00:00
|
|
|
|
2013-09-12 08:46:09 +00:00
|
|
|
import java.io.File;
|
|
|
|
|
2012-09-11 01:28:15 +00:00
|
|
|
/**
|
|
|
|
* Dictionary File Format Specification.
|
|
|
|
*/
|
|
|
|
public final class FormatSpec {
|
|
|
|
|
2013-08-08 05:16:50 +00:00
|
|
|
/*
|
|
|
|
* File header layout is as follows:
|
|
|
|
*
|
|
|
|
* v |
|
|
|
|
* e | MAGIC_NUMBER + version of the file format, 2 bytes.
|
|
|
|
* r |
|
|
|
|
* sion
|
|
|
|
*
|
|
|
|
* o |
|
|
|
|
* p | not used 4 bits
|
|
|
|
* t | has bigrams ? 1 bit, 1 = yes, 0 = no : CONTAINS_BIGRAMS_FLAG
|
|
|
|
* i | FRENCH_LIGATURE_PROCESSING_FLAG
|
|
|
|
* o | supports dynamic updates ? 1 bit, 1 = yes, 0 = no : SUPPORTS_DYNAMIC_UPDATE
|
|
|
|
* n | GERMAN_UMLAUT_PROCESSING_FLAG
|
|
|
|
* f |
|
|
|
|
* lags
|
|
|
|
*
|
|
|
|
* h |
|
|
|
|
* e | size of the file header, 4bytes
|
|
|
|
* a | including the size of the magic number, the option flags and the header size
|
|
|
|
* d |
|
|
|
|
* ersize
|
|
|
|
*
|
|
|
|
* | attributes list
|
|
|
|
*
|
|
|
|
* attributes list is:
|
|
|
|
* <key> = | string of characters at the char format described below, with the terminator used
|
|
|
|
* | to signal the end of the string.
|
|
|
|
* <value> = | string of characters at the char format described below, with the terminator used
|
|
|
|
* | to signal the end of the string.
|
|
|
|
* if the size of already read < headersize, goto key.
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
2012-09-11 01:28:15 +00:00
|
|
|
/*
|
2013-08-16 05:51:37 +00:00
|
|
|
* Node array (FusionDictionary.PtNodeArray) layout is as follows:
|
2012-09-11 01:28:15 +00:00
|
|
|
*
|
2013-08-22 02:07:52 +00:00
|
|
|
* n |
|
|
|
|
* o | the number of PtNodes, 1 or 2 bytes.
|
|
|
|
* d | 1 byte = bbbbbbbb match
|
|
|
|
* e | case 1xxxxxxx => xxxxxxx << 8 + next byte
|
|
|
|
* c | otherwise => bbbbbbbb
|
|
|
|
* o |
|
|
|
|
* unt
|
2012-09-11 01:28:15 +00:00
|
|
|
*
|
2013-08-22 02:07:52 +00:00
|
|
|
* n |
|
|
|
|
* o | sequence of PtNodes,
|
|
|
|
* d | the layout of each PtNode is described below.
|
|
|
|
* e |
|
|
|
|
* s
|
2012-09-11 01:28:15 +00:00
|
|
|
*
|
2012-09-14 03:38:47 +00:00
|
|
|
* f |
|
2012-09-20 07:21:40 +00:00
|
|
|
* o | IF SUPPORTS_DYNAMIC_UPDATE (defined in the file header)
|
2012-09-14 03:38:47 +00:00
|
|
|
* r | forward link address, 3byte
|
2012-09-20 07:21:40 +00:00
|
|
|
* w | 1 byte = bbbbbbbb match
|
|
|
|
* a | case 1xxxxxxx => -((xxxxxxx << 16) + (next byte << 8) + next byte)
|
|
|
|
* r | otherwise => (xxxxxxx << 16) + (next byte << 8) + next byte
|
|
|
|
* d |
|
|
|
|
* linkaddress
|
2012-09-11 01:28:15 +00:00
|
|
|
*/
|
|
|
|
|
2013-08-22 02:07:52 +00:00
|
|
|
/* Node (FusionDictionary.PtNode) layout is as follows:
|
2012-09-25 11:48:25 +00:00
|
|
|
* | IF !SUPPORTS_DYNAMIC_UPDATE
|
2013-08-22 02:07:52 +00:00
|
|
|
* | addressType xx : mask with MASK_CHILDREN_ADDRESS_TYPE
|
|
|
|
* | 2 bits, 00 = no children : FLAG_CHILDREN_ADDRESS_TYPE_NOADDRESS
|
|
|
|
* f | 01 = 1 byte : FLAG_CHILDREN_ADDRESS_TYPE_ONEBYTE
|
|
|
|
* l | 10 = 2 bytes : FLAG_CHILDREN_ADDRESS_TYPE_TWOBYTES
|
|
|
|
* a | 11 = 3 bytes : FLAG_CHILDREN_ADDRESS_TYPE_THREEBYTES
|
2012-09-25 11:48:25 +00:00
|
|
|
* g | ELSE
|
2013-08-22 02:07:52 +00:00
|
|
|
* s | is moved ? 2 bits, 11 = no : FLAG_IS_NOT_MOVED
|
|
|
|
* | This must be the same as FLAG_CHILDREN_ADDRESS_TYPE_THREEBYTES
|
|
|
|
* | 01 = yes : FLAG_IS_MOVED
|
2012-09-25 11:48:25 +00:00
|
|
|
* | the new address is stored in the same place as the parent address
|
2013-08-22 02:07:52 +00:00
|
|
|
* | is deleted? 10 = yes : FLAG_IS_DELETED
|
2012-09-25 11:48:25 +00:00
|
|
|
* | has several chars ? 1 bit, 1 = yes, 0 = no : FLAG_HAS_MULTIPLE_CHARS
|
|
|
|
* | has a terminal ? 1 bit, 1 = yes, 0 = no : FLAG_IS_TERMINAL
|
2012-09-11 01:28:15 +00:00
|
|
|
* | has shortcut targets ? 1 bit, 1 = yes, 0 = no : FLAG_HAS_SHORTCUT_TARGETS
|
|
|
|
* | has bigrams ? 1 bit, 1 = yes, 0 = no : FLAG_HAS_BIGRAMS
|
|
|
|
* | is not a word ? 1 bit, 1 = yes, 0 = no : FLAG_IS_NOT_A_WORD
|
|
|
|
* | is blacklisted ? 1 bit, 1 = yes, 0 = no : FLAG_IS_BLACKLISTED
|
|
|
|
*
|
|
|
|
* p |
|
2012-09-20 07:21:40 +00:00
|
|
|
* a | IF SUPPORTS_DYNAMIC_UPDATE (defined in the file header)
|
2012-09-11 01:28:15 +00:00
|
|
|
* r | parent address, 3byte
|
2012-09-20 07:21:40 +00:00
|
|
|
* e | 1 byte = bbbbbbbb match
|
|
|
|
* n | case 1xxxxxxx => -((0xxxxxxx << 16) + (next byte << 8) + next byte)
|
|
|
|
* t | otherwise => (bbbbbbbb << 16) + (next byte << 8) + next byte
|
2013-09-05 02:50:13 +00:00
|
|
|
* a | This address is relative to the head of the PtNode.
|
|
|
|
* d | If the node doesn't have a parent, this field is set to 0.
|
|
|
|
* d |
|
|
|
|
* ress
|
2012-09-11 01:28:15 +00:00
|
|
|
*
|
|
|
|
* c | IF FLAG_HAS_MULTIPLE_CHARS
|
2013-08-22 02:07:52 +00:00
|
|
|
* h | char, char, char, char n * (1 or 3 bytes) : use PtNodeInfo for i/o helpers
|
2012-09-11 01:28:15 +00:00
|
|
|
* a | end 1 byte, = 0
|
|
|
|
* r | ELSE
|
|
|
|
* s | char 1 or 3 bytes
|
|
|
|
* | END
|
|
|
|
*
|
|
|
|
* f |
|
|
|
|
* r | IF FLAG_IS_TERMINAL
|
|
|
|
* e | frequency 1 byte
|
|
|
|
* q |
|
|
|
|
*
|
2013-08-22 02:07:52 +00:00
|
|
|
* c | IF SUPPORTS_DYNAMIC_UPDATE
|
|
|
|
* h | children address, 3 bytes
|
|
|
|
* i | 1 byte = bbbbbbbb match
|
|
|
|
* l | case 1xxxxxxx => -((0xxxxxxx << 16) + (next byte << 8) + next byte)
|
|
|
|
* d | otherwise => (bbbbbbbb<<16) + (next byte << 8) + next byte
|
2013-09-05 02:50:13 +00:00
|
|
|
* r | if this node doesn't have children, this field is set to 0.
|
|
|
|
* e | (see BinaryDictEncoderUtils#writeVariableSignedAddress)
|
|
|
|
* n | ELSIF 00 = FLAG_CHILDREN_ADDRESS_TYPE_NOADDRESS == addressType
|
|
|
|
* a | // nothing
|
|
|
|
* d | ELSIF 01 = FLAG_CHILDREN_ADDRESS_TYPE_ONEBYTE == addressType
|
|
|
|
* d | children address, 1 byte
|
|
|
|
* r | ELSIF 10 = FLAG_CHILDREN_ADDRESS_TYPE_TWOBYTES == addressType
|
|
|
|
* e | children address, 2 bytes
|
|
|
|
* s | ELSE // 11 = FLAG_CHILDREN_ADDRESS_TYPE_THREEBYTES = addressType
|
|
|
|
* s | children address, 3 bytes
|
|
|
|
* | END
|
|
|
|
* | This address is relative to the position of this field.
|
2012-09-11 01:28:15 +00:00
|
|
|
*
|
|
|
|
* | IF FLAG_IS_TERMINAL && FLAG_HAS_SHORTCUT_TARGETS
|
|
|
|
* | shortcut string list
|
|
|
|
* | IF FLAG_IS_TERMINAL && FLAG_HAS_BIGRAMS
|
|
|
|
* | bigrams address list
|
|
|
|
*
|
|
|
|
* Char format is:
|
|
|
|
* 1 byte = bbbbbbbb match
|
|
|
|
* case 000xxxxx: xxxxx << 16 + next byte << 8 + next byte
|
|
|
|
* else: if 00011111 (= 0x1F) : this is the terminator. This is a relevant choice because
|
|
|
|
* unicode code points range from 0 to 0x10FFFF, so any 3-byte value starting with
|
|
|
|
* 00011111 would be outside unicode.
|
|
|
|
* else: iso-latin-1 code
|
|
|
|
* This allows for the whole unicode range to be encoded, including chars outside of
|
|
|
|
* the BMP. Also everything in the iso-latin-1 charset is only 1 byte, except control
|
|
|
|
* characters which should never happen anyway (and still work, but take 3 bytes).
|
|
|
|
*
|
|
|
|
* bigram address list is:
|
2013-08-22 02:07:52 +00:00
|
|
|
* <flags> = | hasNext = 1 bit, 1 = yes, 0 = no : FLAG_BIGRAM_SHORTCUT_ATTR_HAS_NEXT
|
|
|
|
* | addressSign = 1 bit, : FLAG_BIGRAM_ATTR_OFFSET_NEGATIVE
|
2012-09-11 01:28:15 +00:00
|
|
|
* | 1 = must take -address, 0 = must take +address
|
2013-08-22 02:07:52 +00:00
|
|
|
* | xx : mask with MASK_BIGRAM_ATTR_ADDRESS_TYPE
|
|
|
|
* | addressFormat = 2 bits, 00 = unused : FLAG_BIGRAM_ATTR_ADDRESS_TYPE_ONEBYTE
|
|
|
|
* | 01 = 1 byte : FLAG_BIGRAM_ATTR_ADDRESS_TYPE_ONEBYTE
|
|
|
|
* | 10 = 2 bytes : FLAG_BIGRAM_ATTR_ADDRESS_TYPE_TWOBYTES
|
|
|
|
* | 11 = 3 bytes : FLAG_BIGRAM_ATTR_ADDRESS_TYPE_THREEBYTES
|
|
|
|
* | 4 bits : frequency : mask with FLAG_BIGRAM_SHORTCUT_ATTR_FREQUENCY
|
|
|
|
* <address> | IF (01 == FLAG_BIGRAM_ATTR_ADDRESS_TYPE_ONEBYTE == addressFormat)
|
2012-09-11 01:28:15 +00:00
|
|
|
* | read 1 byte, add top 4 bits
|
2013-08-22 02:07:52 +00:00
|
|
|
* | ELSIF (10 == FLAG_BIGRAM_ATTR_ADDRESS_TYPE_TWOBYTES == addressFormat)
|
2012-09-11 01:28:15 +00:00
|
|
|
* | read 2 bytes, add top 4 bits
|
2013-08-22 02:07:52 +00:00
|
|
|
* | ELSE // 11 == FLAG_BIGRAM_ATTR_ADDRESS_TYPE_THREEBYTES == addressFormat
|
2012-09-11 01:28:15 +00:00
|
|
|
* | read 3 bytes, add top 4 bits
|
|
|
|
* | END
|
2013-08-22 02:07:52 +00:00
|
|
|
* | if (FLAG_BIGRAM_ATTR_OFFSET_NEGATIVE) then address = -address
|
|
|
|
* if (FLAG_BIGRAM_SHORTCUT_ATTR_HAS_NEXT) goto bigram_and_shortcut_address_list_is
|
2012-09-11 01:28:15 +00:00
|
|
|
*
|
|
|
|
* shortcut string list is:
|
2013-08-22 02:07:52 +00:00
|
|
|
* <byte size> = PTNODE_SHORTCUT_LIST_SIZE_SIZE bytes, big-endian: size of the list, in bytes.
|
|
|
|
* <flags> = | hasNext = 1 bit, 1 = yes, 0 = no : FLAG_BIGRAM_SHORTCUT_ATTR_HAS_NEXT
|
2012-09-11 01:28:15 +00:00
|
|
|
* | reserved = 3 bits, must be 0
|
2013-08-22 02:07:52 +00:00
|
|
|
* | 4 bits : frequency : mask with FLAG_BIGRAM_SHORTCUT_ATTR_FREQUENCY
|
2012-09-11 01:28:15 +00:00
|
|
|
* <shortcut> = | string of characters at the char format described above, with the terminator
|
|
|
|
* | used to signal the end of the string.
|
2013-08-22 02:07:52 +00:00
|
|
|
* if (FLAG_BIGRAM_SHORTCUT_ATTR_HAS_NEXT goto flags
|
2012-09-11 01:28:15 +00:00
|
|
|
*/
|
|
|
|
|
2013-08-08 05:16:50 +00:00
|
|
|
public static final int MAGIC_NUMBER = 0x9BC13AFE;
|
|
|
|
static final int MINIMUM_SUPPORTED_VERSION = 2;
|
2013-09-10 08:16:32 +00:00
|
|
|
static final int MAXIMUM_SUPPORTED_VERSION = 4;
|
2012-09-11 01:28:15 +00:00
|
|
|
static final int NOT_A_VERSION_NUMBER = -1;
|
2012-09-21 12:21:58 +00:00
|
|
|
static final int FIRST_VERSION_WITH_DYNAMIC_UPDATE = 3;
|
2013-09-10 08:16:32 +00:00
|
|
|
static final int FIRST_VERSION_WITH_TERMINAL_ID = 4;
|
|
|
|
static final int VERSION3 = 3;
|
|
|
|
static final int VERSION4 = 4;
|
2012-09-11 01:28:15 +00:00
|
|
|
|
|
|
|
// These options need to be the same numeric values as the one in the native reading code.
|
|
|
|
static final int GERMAN_UMLAUT_PROCESSING_FLAG = 0x1;
|
2012-09-18 12:29:59 +00:00
|
|
|
// TODO: Make the native reading code read this variable.
|
2012-09-21 12:21:58 +00:00
|
|
|
static final int SUPPORTS_DYNAMIC_UPDATE = 0x2;
|
2012-09-11 01:28:15 +00:00
|
|
|
static final int FRENCH_LIGATURE_PROCESSING_FLAG = 0x4;
|
|
|
|
static final int CONTAINS_BIGRAMS_FLAG = 0x8;
|
|
|
|
|
|
|
|
// TODO: Make this value adaptative to content data, store it in the header, and
|
|
|
|
// use it in the reading code.
|
2013-07-26 03:35:11 +00:00
|
|
|
static final int MAX_WORD_LENGTH = Constants.DICTIONARY_MAX_WORD_LENGTH;
|
2012-09-11 01:28:15 +00:00
|
|
|
|
|
|
|
static final int PARENT_ADDRESS_SIZE = 3;
|
2012-09-14 03:38:47 +00:00
|
|
|
static final int FORWARD_LINK_ADDRESS_SIZE = 3;
|
2012-09-11 01:28:15 +00:00
|
|
|
|
2012-10-03 03:34:52 +00:00
|
|
|
// These flags are used only in the static dictionary.
|
2013-08-22 02:07:52 +00:00
|
|
|
static final int MASK_CHILDREN_ADDRESS_TYPE = 0xC0;
|
|
|
|
static final int FLAG_CHILDREN_ADDRESS_TYPE_NOADDRESS = 0x00;
|
|
|
|
static final int FLAG_CHILDREN_ADDRESS_TYPE_ONEBYTE = 0x40;
|
|
|
|
static final int FLAG_CHILDREN_ADDRESS_TYPE_TWOBYTES = 0x80;
|
|
|
|
static final int FLAG_CHILDREN_ADDRESS_TYPE_THREEBYTES = 0xC0;
|
2012-09-11 01:28:15 +00:00
|
|
|
|
|
|
|
static final int FLAG_HAS_MULTIPLE_CHARS = 0x20;
|
|
|
|
|
|
|
|
static final int FLAG_IS_TERMINAL = 0x10;
|
|
|
|
static final int FLAG_HAS_SHORTCUT_TARGETS = 0x08;
|
|
|
|
static final int FLAG_HAS_BIGRAMS = 0x04;
|
|
|
|
static final int FLAG_IS_NOT_A_WORD = 0x02;
|
|
|
|
static final int FLAG_IS_BLACKLISTED = 0x01;
|
2012-10-03 03:34:52 +00:00
|
|
|
|
|
|
|
// These flags are used only in the dynamic dictionary.
|
2012-10-03 08:58:22 +00:00
|
|
|
static final int MASK_MOVE_AND_DELETE_FLAG = 0xC0;
|
2012-10-03 03:34:52 +00:00
|
|
|
static final int FIXED_BIT_OF_DYNAMIC_UPDATE_MOVE = 0x40;
|
|
|
|
static final int FLAG_IS_MOVED = 0x00 | FIXED_BIT_OF_DYNAMIC_UPDATE_MOVE;
|
|
|
|
static final int FLAG_IS_NOT_MOVED = 0x80 | FIXED_BIT_OF_DYNAMIC_UPDATE_MOVE;
|
2012-10-03 08:23:39 +00:00
|
|
|
static final int FLAG_IS_DELETED = 0x80;
|
2012-09-11 01:28:15 +00:00
|
|
|
|
2013-08-22 02:07:52 +00:00
|
|
|
static final int FLAG_BIGRAM_SHORTCUT_ATTR_HAS_NEXT = 0x80;
|
|
|
|
static final int FLAG_BIGRAM_ATTR_OFFSET_NEGATIVE = 0x40;
|
|
|
|
static final int MASK_BIGRAM_ATTR_ADDRESS_TYPE = 0x30;
|
|
|
|
static final int FLAG_BIGRAM_ATTR_ADDRESS_TYPE_ONEBYTE = 0x10;
|
|
|
|
static final int FLAG_BIGRAM_ATTR_ADDRESS_TYPE_TWOBYTES = 0x20;
|
|
|
|
static final int FLAG_BIGRAM_ATTR_ADDRESS_TYPE_THREEBYTES = 0x30;
|
|
|
|
static final int FLAG_BIGRAM_SHORTCUT_ATTR_FREQUENCY = 0x0F;
|
2012-09-11 01:28:15 +00:00
|
|
|
|
2013-08-22 02:07:52 +00:00
|
|
|
static final int PTNODE_CHARACTERS_TERMINATOR = 0x1F;
|
2012-09-11 01:28:15 +00:00
|
|
|
|
2013-08-22 02:07:52 +00:00
|
|
|
static final int PTNODE_TERMINATOR_SIZE = 1;
|
|
|
|
static final int PTNODE_FLAGS_SIZE = 1;
|
|
|
|
static final int PTNODE_FREQUENCY_SIZE = 1;
|
2013-09-10 08:16:32 +00:00
|
|
|
static final int PTNODE_TERMINAL_ID_SIZE = 4;
|
2013-08-22 02:07:52 +00:00
|
|
|
static final int PTNODE_MAX_ADDRESS_SIZE = 3;
|
|
|
|
static final int PTNODE_ATTRIBUTE_FLAGS_SIZE = 1;
|
|
|
|
static final int PTNODE_ATTRIBUTE_MAX_ADDRESS_SIZE = 3;
|
|
|
|
static final int PTNODE_SHORTCUT_LIST_SIZE_SIZE = 2;
|
2012-09-11 01:28:15 +00:00
|
|
|
|
2013-09-10 08:16:32 +00:00
|
|
|
// These values are used only by version 4 or later.
|
|
|
|
static final String TRIE_FILE_EXTENSION = ".trie";
|
|
|
|
static final String FREQ_FILE_EXTENSION = ".freq";
|
2013-09-12 11:53:44 +00:00
|
|
|
// tat = Terminal Address Table
|
|
|
|
static final String TERMINAL_ADDRESS_TABLE_FILE_EXTENSION = ".tat";
|
2013-09-19 12:09:34 +00:00
|
|
|
static final String BIGRAM_FILE_EXTENSION = ".bigram";
|
2013-10-02 05:45:22 +00:00
|
|
|
static final String SHORTCUT_FILE_EXTENSION = ".shortcut";
|
2013-10-01 14:08:27 +00:00
|
|
|
static final String LOOKUP_TABLE_FILE_SUFFIX = "_lookup";
|
|
|
|
static final String CONTENT_TABLE_FILE_SUFFIX = "_index";
|
2013-09-10 08:16:32 +00:00
|
|
|
static final int FREQUENCY_AND_FLAGS_SIZE = 2;
|
2013-09-12 11:53:44 +00:00
|
|
|
static final int TERMINAL_ADDRESS_TABLE_ADDRESS_SIZE = 3;
|
2013-10-02 05:45:22 +00:00
|
|
|
|
|
|
|
// With the English main dictionary as of October 2013, the size of bigram address table is
|
|
|
|
// is 584KB with the block size being 4.
|
|
|
|
// This is 91% of that of full address table.
|
2013-09-19 12:09:34 +00:00
|
|
|
static final int BIGRAM_ADDRESS_TABLE_BLOCK_SIZE = 4;
|
2013-10-01 14:08:27 +00:00
|
|
|
static final int BIGRAM_CONTENT_COUNT = 1;
|
|
|
|
static final int BIGRAM_FREQ_CONTENT_INDEX = 0;
|
|
|
|
static final String BIGRAM_FREQ_CONTENT_ID = "_freq";
|
2013-09-10 08:16:32 +00:00
|
|
|
|
2013-10-02 05:45:22 +00:00
|
|
|
static final int SHORTCUT_CONTENT_COUNT = 1;
|
|
|
|
static final int SHORTCUT_CONTENT_INDEX = 0;
|
|
|
|
// With the English main dictionary as of October 2013, the size of shortcut address table is
|
|
|
|
// 29KB with the block size being 64.
|
|
|
|
// This is only 4.4% of that of full address table.
|
|
|
|
static final int SHORTCUT_ADDRESS_TABLE_BLOCK_SIZE = 64;
|
|
|
|
static final String SHORTCUT_CONTENT_ID = "_shortcut";
|
|
|
|
|
2012-09-11 01:28:15 +00:00
|
|
|
static final int NO_CHILDREN_ADDRESS = Integer.MIN_VALUE;
|
|
|
|
static final int NO_PARENT_ADDRESS = 0;
|
2012-09-14 03:38:47 +00:00
|
|
|
static final int NO_FORWARD_LINK_ADDRESS = 0;
|
2012-09-11 01:28:15 +00:00
|
|
|
static final int INVALID_CHARACTER = -1;
|
|
|
|
|
2013-08-22 02:07:52 +00:00
|
|
|
static final int MAX_PTNODES_FOR_ONE_BYTE_PTNODE_COUNT = 0x7F; // 127
|
|
|
|
static final int MAX_PTNODES_IN_A_PT_NODE_ARRAY = 0x7FFF; // 32767
|
|
|
|
static final int MAX_BIGRAMS_IN_A_PTNODE = 10000;
|
2013-09-10 08:16:32 +00:00
|
|
|
static final int MAX_SHORTCUT_LIST_SIZE_IN_A_PTNODE = 0xFFFF;
|
2012-09-11 01:28:15 +00:00
|
|
|
|
|
|
|
static final int MAX_TERMINAL_FREQUENCY = 255;
|
|
|
|
static final int MAX_BIGRAM_FREQUENCY = 15;
|
|
|
|
|
2012-10-25 09:15:42 +00:00
|
|
|
public static final int SHORTCUT_WHITELIST_FREQUENCY = 15;
|
|
|
|
|
2012-09-19 05:38:17 +00:00
|
|
|
// This option needs to be the same numeric value as the one in binary_format.h.
|
|
|
|
static final int NOT_VALID_WORD = -99;
|
2012-09-20 07:21:40 +00:00
|
|
|
static final int SIGNED_CHILDREN_ADDRESS_SIZE = 3;
|
2012-09-19 05:38:17 +00:00
|
|
|
|
2013-08-14 09:39:14 +00:00
|
|
|
static final int UINT8_MAX = 0xFF;
|
|
|
|
static final int UINT16_MAX = 0xFFFF;
|
|
|
|
static final int UINT24_MAX = 0xFFFFFF;
|
|
|
|
static final int SINT24_MAX = 0x7FFFFF;
|
|
|
|
static final int MSB8 = 0x80;
|
|
|
|
static final int MSB24 = 0x800000;
|
|
|
|
|
2012-09-12 09:53:33 +00:00
|
|
|
/**
|
|
|
|
* Options about file format.
|
|
|
|
*/
|
2012-09-27 09:16:16 +00:00
|
|
|
public static final class FormatOptions {
|
2012-09-12 09:53:33 +00:00
|
|
|
public final int mVersion;
|
2012-09-21 12:21:58 +00:00
|
|
|
public final boolean mSupportsDynamicUpdate;
|
2013-09-10 08:16:32 +00:00
|
|
|
public final boolean mHasTerminalId;
|
2013-08-08 10:09:26 +00:00
|
|
|
@UsedForTesting
|
2012-09-12 09:53:33 +00:00
|
|
|
public FormatOptions(final int version) {
|
|
|
|
this(version, false);
|
|
|
|
}
|
2013-08-08 10:09:26 +00:00
|
|
|
|
|
|
|
@UsedForTesting
|
2012-09-21 12:21:58 +00:00
|
|
|
public FormatOptions(final int version, final boolean supportsDynamicUpdate) {
|
2012-09-12 09:53:33 +00:00
|
|
|
mVersion = version;
|
2012-09-21 12:21:58 +00:00
|
|
|
if (version < FIRST_VERSION_WITH_DYNAMIC_UPDATE && supportsDynamicUpdate) {
|
|
|
|
throw new RuntimeException("Dynamic updates are only supported with versions "
|
|
|
|
+ FIRST_VERSION_WITH_DYNAMIC_UPDATE + " and ulterior.");
|
2012-09-14 03:38:47 +00:00
|
|
|
}
|
2012-09-21 12:21:58 +00:00
|
|
|
mSupportsDynamicUpdate = supportsDynamicUpdate;
|
2013-09-10 08:16:32 +00:00
|
|
|
mHasTerminalId = (version >= FIRST_VERSION_WITH_TERMINAL_ID);
|
2012-09-12 09:53:33 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Class representing file header.
|
|
|
|
*/
|
2013-01-18 09:55:40 +00:00
|
|
|
public static final class FileHeader {
|
2012-09-12 09:53:33 +00:00
|
|
|
public final int mHeaderSize;
|
|
|
|
public final DictionaryOptions mDictionaryOptions;
|
|
|
|
public final FormatOptions mFormatOptions;
|
2013-09-26 03:59:02 +00:00
|
|
|
// Note that these are corresponding definitions in native code in latinime::HeaderPolicy
|
|
|
|
// and latinime::HeaderReadWriteUtils.
|
|
|
|
public static final String SUPPORTS_DYNAMIC_UPDATE_ATTRIBUTE = "SUPPORTS_DYNAMIC_UPDATE";
|
|
|
|
public static final String USES_FORGETTING_CURVE_ATTRIBUTE = "USES_FORGETTING_CURVE";
|
|
|
|
public static final String ATTRIBUTE_VALUE_TRUE = "1";
|
|
|
|
|
2013-09-28 03:50:09 +00:00
|
|
|
public static final String DICTIONARY_VERSION_ATTRIBUTE = "version";
|
|
|
|
public static final String DICTIONARY_LOCALE_ATTRIBUTE = "locale";
|
|
|
|
public static final String DICTIONARY_ID_ATTRIBUTE = "dictionary";
|
2013-02-23 09:35:21 +00:00
|
|
|
private static final String DICTIONARY_DESCRIPTION_ATTRIBUTE = "description";
|
2012-09-12 09:53:33 +00:00
|
|
|
public FileHeader(final int headerSize, final DictionaryOptions dictionaryOptions,
|
|
|
|
final FormatOptions formatOptions) {
|
|
|
|
mHeaderSize = headerSize;
|
|
|
|
mDictionaryOptions = dictionaryOptions;
|
|
|
|
mFormatOptions = formatOptions;
|
|
|
|
}
|
2013-01-29 07:34:14 +00:00
|
|
|
|
|
|
|
// Helper method to get the locale as a String
|
|
|
|
public String getLocaleString() {
|
|
|
|
return mDictionaryOptions.mAttributes.get(FileHeader.DICTIONARY_LOCALE_ATTRIBUTE);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Helper method to get the version String
|
|
|
|
public String getVersion() {
|
|
|
|
return mDictionaryOptions.mAttributes.get(FileHeader.DICTIONARY_VERSION_ATTRIBUTE);
|
|
|
|
}
|
2013-02-23 04:49:48 +00:00
|
|
|
|
|
|
|
// Helper method to get the dictionary ID as a String
|
|
|
|
public String getId() {
|
|
|
|
return mDictionaryOptions.mAttributes.get(FileHeader.DICTIONARY_ID_ATTRIBUTE);
|
|
|
|
}
|
2013-02-23 09:35:21 +00:00
|
|
|
|
|
|
|
// Helper method to get the description
|
|
|
|
public String getDescription() {
|
|
|
|
// TODO: Right now each dictionary file comes with a description in its own language.
|
|
|
|
// It will display as is no matter the device's locale. It should be internationalized.
|
|
|
|
return mDictionaryOptions.mAttributes.get(FileHeader.DICTIONARY_DESCRIPTION_ATTRIBUTE);
|
|
|
|
}
|
2012-09-12 09:53:33 +00:00
|
|
|
}
|
|
|
|
|
2013-09-12 08:46:09 +00:00
|
|
|
/**
|
|
|
|
* Returns new dictionary decoder.
|
|
|
|
*
|
|
|
|
* @param dictFile the dictionary file.
|
2013-08-20 12:05:05 +00:00
|
|
|
* @param bufferType The type of buffer, as one of USE_* in DictDecoder.
|
2013-09-12 08:46:09 +00:00
|
|
|
* @return new dictionary decoder if the dictionary file exists, otherwise null.
|
|
|
|
*/
|
|
|
|
public static DictDecoder getDictDecoder(final File dictFile, final int bufferType) {
|
2013-08-20 12:05:05 +00:00
|
|
|
if (dictFile.isDirectory()) {
|
|
|
|
return new Ver4DictDecoder(dictFile, bufferType);
|
|
|
|
} else if (dictFile.isFile()) {
|
|
|
|
return new Ver3DictDecoder(dictFile, bufferType);
|
|
|
|
}
|
|
|
|
return null;
|
2013-09-12 08:46:09 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
public static DictDecoder getDictDecoder(final File dictFile,
|
|
|
|
final DictionaryBufferFactory factory) {
|
2013-08-20 12:05:05 +00:00
|
|
|
if (dictFile.isDirectory()) {
|
|
|
|
return new Ver4DictDecoder(dictFile, factory);
|
|
|
|
} else if (dictFile.isFile()) {
|
|
|
|
return new Ver3DictDecoder(dictFile, factory);
|
|
|
|
}
|
|
|
|
return null;
|
2013-09-12 08:46:09 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
public static DictDecoder getDictDecoder(final File dictFile) {
|
|
|
|
return getDictDecoder(dictFile, DictDecoder.USE_READONLY_BYTEBUFFER);
|
|
|
|
}
|
|
|
|
|
2012-09-11 01:28:15 +00:00
|
|
|
private FormatSpec() {
|
|
|
|
// This utility class is not publicly instantiable.
|
|
|
|
}
|
|
|
|
}
|