/*
* Copyright 2014 Takao Nakaguchi
*
* 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.
*/
package org.trie4j.io;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import org.trie4j.Trie;
import org.trie4j.bv.BitVector01Divider;
import org.trie4j.bv.BytesRank0OnlySuccinctBitVector;
import org.trie4j.bv.BytesRank1OnlySuccinctBitVector;
import org.trie4j.bv.BytesSuccinctBitVector;
import org.trie4j.bv.LongsSuccinctBitVector;
import org.trie4j.bv.SuccinctBitVector;
import org.trie4j.louds.TailLOUDSTrie;
import org.trie4j.louds.bvtree.BvTree;
import org.trie4j.louds.bvtree.LOUDSBvTree;
import org.trie4j.louds.bvtree.LOUDSPPBvTree;
import org.trie4j.tail.DefaultTailArray;
import org.trie4j.tail.TailArray;
import org.trie4j.tail.index.ArrayTailIndex;
import org.trie4j.tail.index.DenseArrayTailIndex;
import org.trie4j.tail.index.SBVTailIndex;
import org.trie4j.tail.index.TailIndex;
import org.trie4j.util.IntArray;
public class TrieWriter implements Constants{
public TrieWriter(OutputStream os) {
dos = new DataOutputStream(os);
}
public void flush() throws IOException{
dos.flush();
}
public void write(Trie trie) throws IOException{
if(trie instanceof TailLOUDSTrie){
dos.writeShort(TYPE_TRIE_LOUDS_TAIL);
writeTailLOUDSTrie((TailLOUDSTrie)trie);
} else{
throw new IOException("unknown trie: " + trie.getClass().getName());
}
}
public void writeTailLOUDSTrie(TailLOUDSTrie trie) throws IOException{
trie.trimToSize();
dos.writeInt(trie.size());
dos.writeInt(trie.nodeSize());
writeBvTree(trie.getBvTree());
writeChars(trie.getLabels());
writeTailArray(trie.getTailArray());
writeSuccinctBitVector(trie.getTerm());
}
public void writeBvTree(BvTree bvTree) throws IOException{
if(bvTree instanceof LOUDSBvTree){
dos.writeShort(TYPE_BVTREE_LOUDS);
writeLOUDSBvTree((LOUDSBvTree)bvTree);
} else if(bvTree instanceof LOUDSPPBvTree){
dos.writeShort(TYPE_BVTREE_LOUDSPP);
writeLOUDSPPBvTree((LOUDSPPBvTree)bvTree);
} else{
throw new IOException("unknown bv tree: " + bvTree.getClass().getName());
}
}
public void writeLOUDSBvTree(LOUDSBvTree bvTree) throws IOException{
bvTree.trimToSize();
writeSuccinctBitVector(bvTree.getSbv());
}
public void writeLOUDSPPBvTree(LOUDSPPBvTree bvTree) throws IOException{
bvTree.trimToSize();
writeBitVector01Divider(bvTree.getDivider());
writeSuccinctBitVector(bvTree.getR0());
writeSuccinctBitVector(bvTree.getR1());
}
public void writeTailArray(TailArray tailArray) throws IOException{
if(tailArray instanceof DefaultTailArray){
dos.writeShort(TYPE_TAILARRAY_DEFAULT);
writeDefaultTailArray((DefaultTailArray)tailArray);
} else{
throw new IOException("unknown tail array: " + tailArray.getClass().getName());
}
}
public void writeDefaultTailArray(DefaultTailArray tailArray) throws IOException{
writeChars(tailArray.getTail());
writeTailIndex(tailArray.getTailIndex());
}
public void writeTailIndex(TailIndex tailIndex) throws IOException{
if(tailIndex instanceof ArrayTailIndex){
dos.writeShort(TYPE_TAILINDEX_ARRAY);
writeArrayTailIndex((ArrayTailIndex)tailIndex);
} else if(tailIndex instanceof DenseArrayTailIndex){
dos.writeShort(TYPE_TAILINDEX_DENSEARRAY);
writeDenseArrayTailIndex((DenseArrayTailIndex)tailIndex);
} else if(tailIndex instanceof SBVTailIndex){
dos.writeShort(TYPE_TAILINDEX_SBV);
writeSBVTailIndex((SBVTailIndex)tailIndex);
} else{
throw new IOException("unknown tail index: " + tailIndex.getClass().getName());
}
}
public void writeArrayTailIndex(ArrayTailIndex tailIndex) throws IOException{
writeInts(tailIndex.getIndexes());
}
public void writeDenseArrayTailIndex(DenseArrayTailIndex tailIndex) throws IOException{
writeSuccinctBitVector(tailIndex.getSbv());
writeInts(tailIndex.getTail());
}
public void writeSBVTailIndex(SBVTailIndex tailIndex) throws IOException{
writeSuccinctBitVector(tailIndex.getSbv());
dos.writeInt(tailIndex.size());
}
/**
* Write BitVector01Divider to OutputStream. This method doesn't care about
* r0 and r1. Caller must write these bvs.
* @param divider
* @throws IOException
*/
public void writeBitVector01Divider(BitVector01Divider divider) throws IOException{
dos.writeBoolean(divider.isFirst());
dos.writeBoolean(divider.isZeroCounting());
}
public void writeSuccinctBitVector(SuccinctBitVector sbv) throws IOException{
if(sbv instanceof BytesSuccinctBitVector){
dos.writeShort(TYPE_SBV_BYTES);
writeBytesSuccinctBitVector((BytesSuccinctBitVector)sbv);
} else if(sbv instanceof BytesRank0OnlySuccinctBitVector){
dos.writeShort(TYPE_SBV_RANK0ONLY);
writeRank0OnlySuccinctBitVector((BytesRank0OnlySuccinctBitVector)sbv);
} else if(sbv instanceof BytesRank1OnlySuccinctBitVector){
dos.writeShort(TYPE_SBV_RANK1ONLY);
writeRank1OnlySuccinctBitVector((BytesRank1OnlySuccinctBitVector)sbv);
} else if(sbv instanceof BytesRank1OnlySuccinctBitVector){
dos.writeShort(TYPE_SBV_LONGS);
writeLongsSuccinctBitVector((LongsSuccinctBitVector)sbv);
} else {
throw new IOException("unknown sbv: " + sbv.getClass().getName());
}
}
public void writeRank0OnlySuccinctBitVector(BytesRank0OnlySuccinctBitVector sbv)
throws IOException{
sbv.trimToSize();
writeBytes(sbv.getVector());
dos.writeInt(sbv.size());
writeInts(sbv.getCountCache0());
}
public void writeRank1OnlySuccinctBitVector(BytesRank1OnlySuccinctBitVector sbv)
throws IOException{
sbv.trimToSize();
writeBytes(sbv.getBytes());
dos.writeInt(sbv.size());
writeInts(sbv.getCountCache1());
}
public void writeBytesSuccinctBitVector(BytesSuccinctBitVector sbv)
throws IOException{
sbv.trimToSize();
writeBytes(sbv.getBytes());
dos.writeInt(sbv.size());
dos.writeInt(sbv.getSize0());
dos.writeInt(sbv.getNode1pos());
dos.writeInt(sbv.getNode2pos());
dos.writeInt(sbv.getNode3pos());
writeInts(sbv.getCountCache0());
writeIntArray(sbv.getIndexCache0());
}
public void writeLongsSuccinctBitVector(LongsSuccinctBitVector sbv)
throws IOException{
sbv.trimToSize();
writeLongs(sbv.getLongs());
dos.writeInt(sbv.size());
dos.writeInt(sbv.getSize0());
dos.writeInt(sbv.getNode1pos());
dos.writeInt(sbv.getNode2pos());
dos.writeInt(sbv.getNode3pos());
writeInts(sbv.getCountCache0());
writeIntArray(sbv.getIndexCache0());
}
public void writeBytes(byte[] data)
throws IOException{
dos.writeInt(data.length);
dos.write(data);
}
public void writeChars(char[] data)
throws IOException{
dos.writeInt(data.length);
for(char d : data){
dos.writeChar(d);
}
}
public void writeChars(CharSequence data)
throws IOException{
if(data instanceof StringBuilder){
((StringBuilder) data).trimToSize();
}
int n = data.length();
dos.writeInt(data.length());
for(int i = 0; i < n; i++){
dos.writeChar(data.charAt(i));
}
}
public void writeInts(int[] data)
throws IOException{
dos.writeInt(data.length);
for(int d : data){
dos.writeInt(d);
}
}
public void writeLongs(long[] data)
throws IOException{
dos.writeInt(data.length);
for(long d : data){
dos.writeLong(d);
}
}
public void writeIntArray(IntArray data)
throws IOException{
writeInts(data.getElements());
}
private DataOutputStream dos;
}