Add writeNode.

Change-Id: I088bb6ea43ce0841d725e48b677d429e1155569d
main
Yuichiro Hanada 2012-10-03 17:58:22 +09:00
parent 48ce9e77ce
commit c3a98ca306
3 changed files with 124 additions and 9 deletions

View File

@ -33,6 +33,11 @@ import java.util.Stack;
public final class BinaryDictIOUtils {
private static final boolean DBG = false;
private static final int MAX_JUMPS = 10000;
private BinaryDictIOUtils() {
// This utility class is not publicly instantiable.
}
private static final class Position {
public static final int NOT_READ_GROUPCOUNT = -1;
@ -377,8 +382,8 @@ public final class BinaryDictIOUtils {
*
* @param buffer the buffer to be modified.
* @param nodeOriginAddress the address of a modified Node.
* @param newParentAddress the address to be written
* @param formatOptions file format options
* @param newParentAddress the address to be written.
* @param formatOptions file format options.
*/
public static void updateParentAddresses(final FusionDictionaryBufferInterface buffer,
final int nodeOriginAddress, final int newParentAddress,
@ -435,7 +440,7 @@ public final class BinaryDictIOUtils {
}
}
destination.write((byte)FormatSpec.GROUP_CHARACTERS_TERMINATOR);
size++;
size += FormatSpec.GROUP_TERMINATOR_SIZE;
return size;
}
@ -473,7 +478,7 @@ public final class BinaryDictIOUtils {
*/
public static int writeCharGroup(final OutputStream destination, final CharGroupInfo info)
throws IOException {
int size = 1;
int size = FormatSpec.GROUP_FLAGS_SIZE;
destination.write((byte)info.mFlags);
final int parentOffset = info.mParentAddress == FormatSpec.NO_PARENT_ADDRESS ?
FormatSpec.NO_PARENT_ADDRESS : info.mParentAddress - info.mOriginalAddress;
@ -497,9 +502,15 @@ public final class BinaryDictIOUtils {
size++;
}
if (DBG) {
MakedictLog.d("writeCharGroup origin=" + info.mOriginalAddress + ", size=" + size
+ ", child=" + info.mChildrenAddress + ", characters ="
+ new String(info.mCharacters, 0, info.mCharacters.length));
}
final int childrenOffset = info.mChildrenAddress == FormatSpec.NO_CHILDREN_ADDRESS ?
0 : info.mChildrenAddress - info.mOriginalAddress;
0 : info.mChildrenAddress - (info.mOriginalAddress + size);
writeSInt24ToStream(destination, childrenOffset);
size += FormatSpec.SIGNED_CHILDREN_ADDRESS_SIZE;
if (info.mShortcutTargets != null && info.mShortcutTargets.size() > 0) {
final int shortcutListSize =
@ -545,4 +556,94 @@ public final class BinaryDictIOUtils {
}
return size;
}
private static void updateForwardLink(final FusionDictionaryBufferInterface buffer,
final int nodeOriginAddress, final int newNodeAddress,
final FormatOptions formatOptions) {
buffer.position(nodeOriginAddress);
int jumpCount = 0;
while (jumpCount++ < MAX_JUMPS) {
final int count = BinaryDictInputOutput.readCharGroupCount(buffer);
for (int i = 0; i < count; ++i) skipCharGroup(buffer, formatOptions);
final int forwardLinkAddress = buffer.readUnsignedInt24();
if (forwardLinkAddress == FormatSpec.NO_FORWARD_LINK_ADDRESS) {
buffer.position(buffer.position() - FormatSpec.FORWARD_LINK_ADDRESS_SIZE);
writeSInt24ToBuffer(buffer, newNodeAddress);
return;
}
buffer.position(forwardLinkAddress);
}
if (DBG && jumpCount >= MAX_JUMPS) {
throw new RuntimeException("too many jumps, probably a bug.");
}
}
/**
* Helper method to move a char group to the tail of the file.
*/
private static int moveCharGroup(final OutputStream destination,
final FusionDictionaryBufferInterface buffer, final CharGroupInfo info,
final int nodeOriginAddress, final int oldGroupAddress,
final FormatOptions formatOptions) throws IOException {
updateParentAddress(buffer, oldGroupAddress, buffer.limit() + 1, formatOptions);
buffer.position(oldGroupAddress);
final int currentFlags = buffer.readUnsignedByte();
buffer.position(oldGroupAddress);
buffer.put((byte)(FormatSpec.FLAG_IS_MOVED | (currentFlags
& (~FormatSpec.MASK_MOVE_AND_DELETE_FLAG))));
int size = FormatSpec.GROUP_FLAGS_SIZE;
updateForwardLink(buffer, nodeOriginAddress, buffer.limit(), formatOptions);
size += writeNode(destination, new CharGroupInfo[] { info });
return size;
}
/**
* Compute the size of the char group.
*/
private static int computeGroupSize(final CharGroupInfo info,
final FormatOptions formatOptions) {
int size = FormatSpec.GROUP_FLAGS_SIZE + FormatSpec.PARENT_ADDRESS_SIZE
+ BinaryDictInputOutput.getGroupCharactersSize(info.mCharacters)
+ BinaryDictInputOutput.getChildrenAddressSize(info.mFlags, formatOptions);
if ((info.mFlags & FormatSpec.FLAG_IS_TERMINAL) != 0) {
size += FormatSpec.GROUP_FREQUENCY_SIZE;
}
if (info.mShortcutTargets != null && !info.mShortcutTargets.isEmpty()) {
size += BinaryDictInputOutput.getShortcutListSize(info.mShortcutTargets);
}
if (info.mBigrams != null) {
for (final PendingAttribute attr : info.mBigrams) {
size += FormatSpec.GROUP_FLAGS_SIZE;
size += BinaryDictInputOutput.getByteSize(attr.mAddress);
}
}
return size;
}
/**
* Write a node to the stream.
*
* @param destination the stream to write.
* @param infos groups to be written.
* @return the size written, in bytes.
* @throws IOException
*/
private static int writeNode(final OutputStream destination, final CharGroupInfo[] infos)
throws IOException {
int size = BinaryDictInputOutput.getGroupCountSize(infos.length);
switch (BinaryDictInputOutput.getGroupCountSize(infos.length)) {
case 1:
destination.write((byte)infos.length);
break;
case 2:
destination.write((byte)(infos.length >> 8));
destination.write((byte)(infos.length & 0xFF));
break;
default:
throw new RuntimeException("Invalid group count size.");
}
for (final CharGroupInfo info : infos) size += writeCharGroup(destination, info);
writeSInt24ToStream(destination, FormatSpec.NO_FORWARD_LINK_ADDRESS);
return size + FormatSpec.FORWARD_LINK_ADDRESS_SIZE;
}
}

View File

@ -275,6 +275,21 @@ public final class BinaryDictInputOutput {
}
}
/**
* Compute the binary size of the character array.
*
* If only one character, this is the size of this character. If many, it's the sum of their
* sizes + 1 byte for the terminator.
*
* @param characters the character array
* @return the size of the char array, including the terminator if any
*/
static int getGroupCharactersSize(final int[] characters) {
int size = CharEncoding.getCharArraySize(characters);
if (characters.length > 1) size += FormatSpec.GROUP_TERMINATOR_SIZE;
return size;
}
/**
* Compute the binary size of the character array in a group
*
@ -285,9 +300,7 @@ public final class BinaryDictInputOutput {
* @return the size of the char array, including the terminator if any
*/
private static int getGroupCharactersSize(final CharGroup group) {
int size = CharEncoding.getCharArraySize(group.mChars);
if (group.hasSeveralChars()) size += FormatSpec.GROUP_TERMINATOR_SIZE;
return size;
return getGroupCharactersSize(group.mChars);
}
/**
@ -1193,7 +1206,7 @@ public final class BinaryDictInputOutput {
// Input methods: Read a binary dictionary to memory.
// readDictionaryBinary is the public entry point for them.
private static int getChildrenAddressSize(final int optionFlags,
static int getChildrenAddressSize(final int optionFlags,
final FormatOptions formatOptions) {
if (formatOptions.mSupportsDynamicUpdate) return FormatSpec.SIGNED_CHILDREN_ADDRESS_SIZE;
switch (optionFlags & FormatSpec.MASK_GROUP_ADDRESS_TYPE) {

View File

@ -188,6 +188,7 @@ public final class FormatSpec {
static final int FLAG_IS_BLACKLISTED = 0x01;
// These flags are used only in the dynamic dictionary.
static final int MASK_MOVE_AND_DELETE_FLAG = 0xC0;
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;