package org.apache.poi.hssf.record; import org.apache.poi.util.BitField; import org.apache.poi.util.LittleEndian; import org.apache.poi.util.StringUtil; /** * @author qiuyiping * * General String Record which length is a 16bit integer. */ public class StringValue2{ protected int field_1_string_length; protected byte field_2_flag; protected String field_3_string; protected long field_4_fareast_info_length; protected byte field_4_fareast_info[]; protected int field_5_richtext_info_length; protected short field_5_richtext_info[]; static private BitField Charater_16 = new BitField(0x01); static private BitField Far_East_Info = new BitField(0x04); static private BitField Rich_Text_Info = new BitField(0x08); /** * Constructor for StringValue2. */ public StringValue2() { } /** * Constructor for StringValue2. * @param id * @param size * @param data */ public StringValue2(short size, byte[] data) { fillFields(data, size, 0); } /** * Constructor for StringValue2. * @param id * @param size * @param data * @param offset */ public StringValue2(short size, byte[] data, int offset) { fillFields(data, size, offset); } public void fillFields(byte [] data, short size) { fillFields(data, size, 0); } /** * @see org.apache.poi.hssf.record.Record#fillFields(byte, short, int) */ public void fillFields(byte[] data, short size, int offset) { field_1_string_length = LittleEndian.getUShort(data, 0 + offset); field_2_flag = data[ 2 + offset ]; offset+=3; if(field_1_string_length==0){ field_3_string=null; return; } if (isRichtext()){ field_5_richtext_info_length= LittleEndian.getUShort(data, 0 + offset); offset+=2; } if (isFareast()){ field_4_fareast_info_length = LittleEndian.getUInt(data, 0 + offset); offset+=4; } if (isCharacterOf16Bit()){ field_3_string = StringUtil.getFromUnicode(data, offset, field_1_string_length ); } else { field_3_string = new String(data, 3 + offset, field_1_string_length); } } public void setStringLength(short length) { field_1_string_length=length; } public int getStringLength() { return field_1_string_length; } public int getStringByteLength() { return isCharacterOf16Bit() ? field_1_string_length * 2 : field_1_string_length; } /** * gives the current serialized size of the record. Should include the sid and reclength (4 bytes). */ public int getRecordSize() { int length = 2 + 1 + getStringByteLength(); if(isRichtext()){ length += 2 + field_5_richtext_info_length*4; } if(isFareast()){ length += 4 + field_4_fareast_info_length; } return length; } /** * called by the class that is responsible for writing this sucker. * Subclasses should implement this so that their data is passed back in a * byte array. * * @param offset to begin writing at * @param data byte array containing instance data * @return number of bytes written */ public int serialize(int offset, byte[] data ) { setFarEast(false); setRichtext(false); LittleEndian.putUShort(data, 0 + offset, field_1_string_length); data[2 + offset] = field_2_flag; if(field_1_string_length!=0){ if (isCharacterOf16Bit()){ StringUtil.putUncompressedUnicode(field_3_string, data, 3 + offset); }else{ StringUtil.putCompressedUnicode(field_3_string, data, 3 + offset); } } return getRecordSize(); } /** * @return The string represented by this record. */ public String getString() { return field_3_string; } /** * Sets the string represented by this record. */ public void setString(String string ) { if(string==null){ this.field_1_string_length = 0; this.field_2_flag = 0; this.field_3_string = null; return; } this.field_1_string_length = string.length(); for(int i =0; i255 || string.charAt(i)<255){ setCharacterOf16Bit(true); break; } } this.field_3_string = string; } /** * Sets the string represented by this record. */ public void setString(String string, boolean isCharacter16) { if(string==null){ this.field_1_string_length = 0; this.field_2_flag = 0; this.field_3_string = null; return; } setCharacterOf16Bit(isCharacter16); this.field_1_string_length = string.length(); this.field_3_string = string; } /** * is this uncompressed unicode (16bit)? Or just 8-bit compressed? * @return isUnicode - True for 16bit- false for 8bit */ public boolean isCharacterOf16Bit() { return Charater_16.isSet(field_2_flag); } /** * Sets whether the string is 16bit or 8bit * @param flag true = 16bit, false = 8bit */ public void setCharacterOf16Bit(boolean flag) { this.field_2_flag = Charater_16.setByteBoolean(this.field_2_flag,flag); } /** * is this has fareast extended data about phonetic, keyboard, etc.? * @return isFareast - True for extended data - false for no */ public boolean isFareast() { return Far_East_Info.isSet(field_2_flag); } /** * Sets whether the string is Rich Text Format * @param flag true = fareast data, false = no */ public void setRichtext(boolean flag) { this.field_2_flag = Rich_Text_Info.setByteBoolean(this.field_2_flag,flag); } /** * is this Rich Text Format? * @return isRichtext - True for Rich Text Format - false for no */ public boolean isRichtext() { return Rich_Text_Info.isSet(field_2_flag); } /** * Sets whether the string has Fareast extended data * @param flag true = fareast data, false = no */ public void setFarEast(boolean flag) { this.field_2_flag = Far_East_Info.setByteBoolean(this.field_2_flag,flag); } public String toString() { return field_3_string; } public Object clone() { StringValue2 rec = new StringValue2(); rec.field_1_string_length = field_1_string_length; rec.field_2_flag = (byte)(isCharacterOf16Bit()?1:0); rec.field_3_string = field_3_string; return rec; } }