📄 unicodestring.java
字号:
/** * set the option flags which among other things return if this is a 16-bit or * 8 bit string * * @param of optionflags bitmask * */ public void setOptionFlags(byte of) { field_2_optionflags = of; } /** * get the actual string this contains as a java String object * * * @return String * */ public String getString() { return field_3_string; } /** * set the actual string this contains * @param string the text */ public void setString(String string) { field_3_string = string; setCharCount((short)field_3_string.length()); // scan for characters greater than 255 ... if any are // present, we have to use 16-bit encoding. Otherwise, we // can use 8-bit encoding boolean useUTF16 = false; int strlen = string.length(); for ( int j = 0; j < strlen; j++ ) { if ( string.charAt( j ) > 255 ) { useUTF16 = true; break; } } if (useUTF16) //Set the uncomressed bit field_2_optionflags = highByte.setByte(field_2_optionflags); else field_2_optionflags = highByte.clearByte(field_2_optionflags); } public int getFormatRunCount() { if (field_4_format_runs == null) return 0; return field_4_format_runs.size(); } public FormatRun getFormatRun(int index) { if (field_4_format_runs == null) return null; if ((index < 0) || (index >= field_4_format_runs.size())) return null; return (FormatRun)field_4_format_runs.get(index); } private int findFormatRunAt(int characterPos) { int size = field_4_format_runs.size(); for (int i=0;i<size;i++) { FormatRun r = (FormatRun)field_4_format_runs.get(i); if (r.character == characterPos) return i; else if (r.character > characterPos) return -1; } return -1; } /** Adds a font run to the formatted string. * * If a font run exists at the current charcter location, then it is * replaced with the font run to be added. */ public void addFormatRun(FormatRun r) { if (field_4_format_runs == null) field_4_format_runs = new ArrayList(); int index = findFormatRunAt(r.character); if (index != -1) field_4_format_runs.remove(index); field_4_format_runs.add(r); //Need to sort the font runs to ensure that the font runs appear in //character order Collections.sort(field_4_format_runs); //Make sure that we now say that we are a rich string field_2_optionflags = richText.setByte(field_2_optionflags); } public Iterator formatIterator() { if (field_4_format_runs != null) return field_4_format_runs.iterator(); return null; } public void removeFormatRun(FormatRun r) { field_4_format_runs.remove(r); if (field_4_format_runs.size() == 0) { field_4_format_runs = null; field_2_optionflags = richText.clearByte(field_2_optionflags); } } public void clearFormatting() { field_4_format_runs = null; field_2_optionflags = richText.clearByte(field_2_optionflags); } public byte[] getExtendedRst() { return this.field_5_ext_rst; } public void setExtendedRst(byte[] ext_rst) { if (ext_rst != null) field_2_optionflags = extBit.setByte(field_2_optionflags); else field_2_optionflags = extBit.clearByte(field_2_optionflags); this.field_5_ext_rst = ext_rst; } /** * unlike the real records we return the same as "getString()" rather than debug info * @see #getDebugInfo() * @return String value of the record */ public String toString() { return getString(); } /** * return a character representation of the fields of this record * * * @return String of output for biffviewer etc. * */ public String getDebugInfo() { StringBuffer buffer = new StringBuffer(); buffer.append("[UNICODESTRING]\n"); buffer.append(" .charcount = ") .append(Integer.toHexString(getCharCount())).append("\n"); buffer.append(" .optionflags = ") .append(Integer.toHexString(getOptionFlags())).append("\n"); buffer.append(" .string = ").append(getString()).append("\n"); if (field_4_format_runs != null) { for (int i = 0; i < field_4_format_runs.size();i++) { FormatRun r = (FormatRun)field_4_format_runs.get(i); buffer.append(" .format_run"+i+" = ").append(r.toString()).append("\n"); } } if (field_5_ext_rst != null) { buffer.append(" .field_5_ext_rst = ").append("\n").append(HexDump.toHex(field_5_ext_rst)).append("\n"); } buffer.append("[/UNICODESTRING]\n"); return buffer.toString(); } private int writeContinueIfRequired(UnicodeRecordStats stats, final int requiredSize, int offset, byte[] data) { //Basic string overhead if (stats.remainingSize < requiredSize) { //Check if be are already in a continue record, if so make sure that //we go back and write out our length if (stats.lastLengthPos != -1) { short lastRecordLength = (short)(offset - stats.lastLengthPos - 2); if (lastRecordLength > 8224) throw new InternalError(); LittleEndian.putShort(data, stats.lastLengthPos, lastRecordLength); } LittleEndian.putShort(data, offset, ContinueRecord.sid); offset+=2; //Record the location of the last continue legnth position, but dont write //anything there yet (since we dont know what it will be!) stats.lastLengthPos = offset; offset += 2; stats.recordSize += 4; stats.remainingSize = SSTRecord.MAX_RECORD_SIZE-4; } return offset; } public int serialize(UnicodeRecordStats stats, final int offset, byte [] data) { int pos = offset; //Basic string overhead pos = writeContinueIfRequired(stats, 3, pos, data); // byte[] retval = new byte[ 3 + (getString().length() * charsize)]; LittleEndian.putShort(data, pos, getCharCount()); pos += 2; data[ pos ] = getOptionFlags(); pos += 1; stats.recordSize += 3; stats.remainingSize-= 3; if (isRichText()) { if (field_4_format_runs != null) { pos = writeContinueIfRequired(stats, 2, pos, data); LittleEndian.putShort(data, pos, (short) field_4_format_runs.size()); pos += 2; stats.recordSize += 2; stats.remainingSize -= 2; } } if ( isExtendedText() ) { if (this.field_5_ext_rst != null) { pos = writeContinueIfRequired(stats, 4, pos, data); LittleEndian.putInt(data, pos, field_5_ext_rst.length); pos += 4; stats.recordSize += 4; stats.remainingSize -= 4; } } int charsize = isUncompressedUnicode() ? 2 : 1; int strSize = (getString().length() * charsize); byte[] strBytes = null; try { String unicodeString = getString(); if (!isUncompressedUnicode()) { strBytes = unicodeString.getBytes("ISO-8859-1"); } else { strBytes = unicodeString.getBytes("UTF-16LE"); } } catch (Exception e) { throw new InternalError(); } if (strSize != strBytes.length) throw new InternalError("That shouldnt have happened!"); //Check to see if the offset occurs mid string, if so then we need to add //the byte to start with that represents the first byte of the continue record. if (strSize > stats.remainingSize) { //Ok the offset occurs half way through the string, that means that //we need an extra byte after the continue record ie we didnt finish //writing out the string the 1st time through //But hang on, how many continue records did we span? What if this is //a REALLY long string. We need to work this all out. int ammountThatCantFit = strSize; int strPos = 0; while (ammountThatCantFit > 0) { int ammountWritten = Math.min(stats.remainingSize, ammountThatCantFit); //Make sure that the ammount that cant fit takes into account //whether we are writing double byte unicode if (isUncompressedUnicode()) { //We have the '-1' here because whether this is the first record or //subsequent continue records, there is always the case that the //number of bytes in a string on doube byte boundaries is actually odd. if ( ( (ammountWritten ) % 2) == 1) ammountWritten--; } System.arraycopy(strBytes, strPos, data, pos, ammountWritten); pos += ammountWritten; strPos += ammountWritten; stats.recordSize += ammountWritten; stats.remainingSize -= ammountWritten; //Ok lets subtract what we can write ammountThatCantFit -= ammountWritten; //Each iteration of this while loop is another continue record, unless //everything now fits. if (ammountThatCantFit > 0) { //We know that a continue WILL be requied, but use this common method pos = writeContinueIfRequired(stats, ammountThatCantFit, pos, data); //The first byte after a continue mid string is the extra byte to //indicate if this run is compressed or not. data[pos] = (byte) (isUncompressedUnicode() ? 0x1 : 0x0); pos++; stats.recordSize++; stats.remainingSize --; } } } else { if (strSize > (data.length-pos)) System.out.println("Hmm shouldnt happen"); //Ok the string fits nicely in the remaining size System.arraycopy(strBytes, 0, data, pos, strSize); pos += strSize; stats.recordSize += strSize; stats.remainingSize -= strSize; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -