faststringbuffer.java

来自「JAVA 所有包」· Java 代码 · 共 1,295 行 · 第 1/3 页

JAVA
1,295
字号
    if (startColumn + length < m_chunkMask && m_innerFSB == null) {      return getOneChunkString(startChunk, startColumn, length);    }    return getString(new StringBuffer(length), startChunk, startColumn,                     length).toString();  }  protected String getOneChunkString(int startChunk, int startColumn,                                     int length) {    return new String(m_array[startChunk], startColumn, length);  }  /**   * @param sb StringBuffer to be appended to   * @param start Offset of first character in the range.   * @param length Number of characters to send.   * @return sb with the requested text appended to it   */  StringBuffer getString(StringBuffer sb, int start, int length)  {    return getString(sb, start >>> m_chunkBits, start & m_chunkMask, length);  }  /**   * Internal support for toString() and getString().   * PLEASE NOTE SIGNATURE CHANGE from earlier versions; it now appends into   * and returns a StringBuffer supplied by the caller. This simplifies   * m_innerFSB support.   * <p>   * Note that this operation has been somewhat deoptimized by the shift to a   * chunked array, as there is no factory method to produce a String object   * directly from an array of arrays and hence a double copy is needed.   * By presetting length we hope to minimize the heap overhead of building   * the intermediate StringBuffer.   * <p>   * (It really is a pity that Java didn't design String as a final subclass   * of MutableString, rather than having StringBuffer be a separate hierarchy.   * We'd avoid a <strong>lot</strong> of double-buffering.)   *   *   * @param sb   * @param startChunk   * @param startColumn   * @param length   *    * @return the contents of the FastStringBuffer as a standard Java string.   */  StringBuffer getString(StringBuffer sb, int startChunk, int startColumn,                         int length)  {    int stop = (startChunk << m_chunkBits) + startColumn + length;    int stopChunk = stop >>> m_chunkBits;    int stopColumn = stop & m_chunkMask;    // Factored out    //StringBuffer sb=new StringBuffer(length);    for (int i = startChunk; i < stopChunk; ++i)    {      if (i == 0 && m_innerFSB != null)        m_innerFSB.getString(sb, startColumn, m_chunkSize - startColumn);      else        sb.append(m_array[i], startColumn, m_chunkSize - startColumn);      startColumn = 0;  // after first chunk    }    if (stopChunk == 0 && m_innerFSB != null)      m_innerFSB.getString(sb, startColumn, stopColumn - startColumn);    else if (stopColumn > startColumn)      sb.append(m_array[stopChunk], startColumn, stopColumn - startColumn);    return sb;  }  /**   * Get a single character from the string buffer.   *   *   * @param pos character position requested.   * @return A character from the requested position.   */  public char charAt(int pos)  {    int startChunk = pos >>> m_chunkBits;    if (startChunk == 0 && m_innerFSB != null)      return m_innerFSB.charAt(pos & m_chunkMask);    else      return m_array[startChunk][pos & m_chunkMask];  }  /**   * Sends the specified range of characters as one or more SAX characters()   * events.   * Note that the buffer reference passed to the ContentHandler may be   * invalidated if the FastStringBuffer is edited; it's the user's   * responsibility to manage access to the FastStringBuffer to prevent this   * problem from arising.   * <p>   * Note too that there is no promise that the output will be sent as a   * single call. As is always true in SAX, one logical string may be split   * across multiple blocks of memory and hence delivered as several   * successive events.   *   * @param ch SAX ContentHandler object to receive the event.   * @param start Offset of first character in the range.   * @param length Number of characters to send.   * @exception org.xml.sax.SAXException may be thrown by handler's   * characters() method.   */  public void sendSAXcharacters(          org.xml.sax.ContentHandler ch, int start, int length)            throws org.xml.sax.SAXException  {    int startChunk = start >>> m_chunkBits;    int startColumn = start & m_chunkMask;    if (startColumn + length < m_chunkMask && m_innerFSB == null) {        ch.characters(m_array[startChunk], startColumn, length);        return;    }        int stop = start + length;    int stopChunk = stop >>> m_chunkBits;    int stopColumn = stop & m_chunkMask;    for (int i = startChunk; i < stopChunk; ++i)    {      if (i == 0 && m_innerFSB != null)        m_innerFSB.sendSAXcharacters(ch, startColumn,                                     m_chunkSize - startColumn);      else        ch.characters(m_array[i], startColumn, m_chunkSize - startColumn);      startColumn = 0;  // after first chunk    }    // Last, or only, chunk    if (stopChunk == 0 && m_innerFSB != null)      m_innerFSB.sendSAXcharacters(ch, startColumn, stopColumn - startColumn);    else if (stopColumn > startColumn)    {      ch.characters(m_array[stopChunk], startColumn,                    stopColumn - startColumn);    }  }    /**   * Sends the specified range of characters as one or more SAX characters()   * events, normalizing the characters according to XSLT rules.   *   * @param ch SAX ContentHandler object to receive the event.   * @param start Offset of first character in the range.   * @param length Number of characters to send.   * @return normalization status to apply to next chunk (because we may   * have been called recursively to process an inner FSB):   * <dl>   * <dt>0</dt>   * <dd>if this output did not end in retained whitespace, and thus whitespace   * at the start of the following chunk (if any) should be converted to a   * single space.   * <dt>SUPPRESS_LEADING_WS</dt>   * <dd>if this output ended in retained whitespace, and thus whitespace   * at the start of the following chunk (if any) should be completely   * suppressed.</dd>   * </dd>   * </dl>   * @exception org.xml.sax.SAXException may be thrown by handler's   * characters() method.   */  public int sendNormalizedSAXcharacters(          org.xml.sax.ContentHandler ch, int start, int length)            throws org.xml.sax.SAXException  {	// This call always starts at the beginning of the     // string being written out, either because it was called directly or    // because it was an m_innerFSB recursion. This is important since	// it gives us a well-known initial state for this flag:	int stateForNextChunk=SUPPRESS_LEADING_WS;    int stop = start + length;    int startChunk = start >>> m_chunkBits;    int startColumn = start & m_chunkMask;    int stopChunk = stop >>> m_chunkBits;    int stopColumn = stop & m_chunkMask;    for (int i = startChunk; i < stopChunk; ++i)    {      if (i == 0 && m_innerFSB != null)				stateForNextChunk=        m_innerFSB.sendNormalizedSAXcharacters(ch, startColumn,                                     m_chunkSize - startColumn);      else				stateForNextChunk=        sendNormalizedSAXcharacters(m_array[i], startColumn,                                     m_chunkSize - startColumn, 																		ch,stateForNextChunk);      startColumn = 0;  // after first chunk    }    // Last, or only, chunk    if (stopChunk == 0 && m_innerFSB != null)			stateForNextChunk= // %REVIEW% Is this update really needed?      m_innerFSB.sendNormalizedSAXcharacters(ch, startColumn, stopColumn - startColumn);    else if (stopColumn > startColumn)    {			stateForNextChunk= // %REVIEW% Is this update really needed?      sendNormalizedSAXcharacters(m_array[stopChunk], 																	startColumn, stopColumn - startColumn,																	ch, stateForNextChunk | SUPPRESS_TRAILING_WS);    }		return stateForNextChunk;  }    static final char[] SINGLE_SPACE = {' '};	    /**   * Internal method to directly normalize and dispatch the character array.   * This version is aware of the fact that it may be called several times   * in succession if the data is made up of multiple "chunks", and thus   * must actively manage the handling of leading and trailing whitespace.   *    * Note: The recursion is due to the possible recursion of inner FSBs.   *   * @param ch The characters from the XML document.   * @param start The start position in the array.   * @param length The number of characters to read from the array.   * @param handler SAX ContentHandler object to receive the event.   * @param edgeTreatmentFlags How leading/trailing spaces should be handled.    * This is a bitfield contining two flags, bitwise-ORed together:   * <dl>   * <dt>SUPPRESS_LEADING_WS</dt>   * <dd>When false, causes leading whitespace to be converted to a single   * space; when true, causes it to be discarded entirely.   * Should be set TRUE for the first chunk, and (in multi-chunk output)   * whenever the previous chunk ended in retained whitespace.</dd>   * <dt>SUPPRESS_TRAILING_WS</dt>   * <dd>When false, causes trailing whitespace to be converted to a single   * space; when true, causes it to be discarded entirely.   * Should be set TRUE for the last or only chunk.   * </dd>   * </dl>   * @return normalization status, as in the edgeTreatmentFlags parameter:   * <dl>   * <dt>0</dt>   * <dd>if this output did not end in retained whitespace, and thus whitespace   * at the start of the following chunk (if any) should be converted to a   * single space.   * <dt>SUPPRESS_LEADING_WS</dt>   * <dd>if this output ended in retained whitespace, and thus whitespace   * at the start of the following chunk (if any) should be completely   * suppressed.</dd>   * </dd>   * </dl>   *   *    * @exception org.xml.sax.SAXException Any SAX exception, possibly   *            wrapping another exception.   */  static int sendNormalizedSAXcharacters(char ch[],              int start, int length,              org.xml.sax.ContentHandler handler,						 int edgeTreatmentFlags)          throws org.xml.sax.SAXException  {     boolean processingLeadingWhitespace =                       ((edgeTreatmentFlags & SUPPRESS_LEADING_WS) != 0);     boolean seenWhitespace = ((edgeTreatmentFlags & CARRY_WS) != 0);     boolean suppressTrailingWhitespace =                       ((edgeTreatmentFlags & SUPPRESS_TRAILING_WS) != 0);     int currPos = start;     int limit = start+length;     // Strip any leading spaces first, if required     if (processingLeadingWhitespace) {         for (; currPos < limit                && XMLCharacterRecognizer.isWhiteSpace(ch[currPos]);              currPos++) { }         // If we've only encountered leading spaces, the         // current state remains unchanged         if (currPos == limit) {             return edgeTreatmentFlags;         }     }     // If we get here, there are no more leading spaces to strip     while (currPos < limit) {         int startNonWhitespace = currPos;         // Grab a chunk of non-whitespace characters         for (; currPos < limit                && !XMLCharacterRecognizer.isWhiteSpace(ch[currPos]);              currPos++) { }         // Non-whitespace seen - emit them, along with a single         // space for any preceding whitespace characters         if (startNonWhitespace != currPos) {             if (seenWhitespace) {                 handler.characters(SINGLE_SPACE, 0, 1);                 seenWhitespace = false;             }             handler.characters(ch, startNonWhitespace,                                currPos - startNonWhitespace);         }         int startWhitespace = currPos;         // Consume any whitespace characters         for (; currPos < limit                && XMLCharacterRecognizer.isWhiteSpace(ch[currPos]);              currPos++) { }         if (startWhitespace != currPos) {             seenWhitespace = true;         }     }     return (seenWhitespace ? CARRY_WS : 0)            | (edgeTreatmentFlags & SUPPRESS_TRAILING_WS);  }  /**   * Directly normalize and dispatch the character array.   *   * @param ch The characters from the XML document.   * @param start The start position in the array.   * @param length The number of characters to read from the array.   * @param handler SAX ContentHandler object to receive the event.   * @exception org.xml.sax.SAXException Any SAX exception, possibly   *            wrapping another exception.   */  public static void sendNormalizedSAXcharacters(char ch[],              int start, int length,              org.xml.sax.ContentHandler handler)          throws org.xml.sax.SAXException  {		sendNormalizedSAXcharacters(ch, start, length,              handler, SUPPRESS_BOTH);	}			/**   * Sends the specified range of characters as sax Comment.   * <p>   * Note that, unlike sendSAXcharacters, this has to be done as a single    * call to LexicalHandler#comment.   *   * @param ch SAX LexicalHandler object to receive the event.   * @param start Offset of first character in the range.   * @param length Number of characters to send.   * @exception org.xml.sax.SAXException may be thrown by handler's   * characters() method.   */  public void sendSAXComment(          org.xml.sax.ext.LexicalHandler ch, int start, int length)            throws org.xml.sax.SAXException  {    // %OPT% Do it this way for now...    String comment = getString(start, length);    ch.comment(comment.toCharArray(), 0, length);  }  /**   * Copies characters from this string into the destination character   * array.   *   * @param      srcBegin   index of the first character in the string   *                        to copy.   * @param      srcEnd     index after the last character in the string   *                        to copy.   * @param      dst        the destination array.   * @param      dstBegin   the start offset in the destination array.   * @exception IndexOutOfBoundsException If any of the following   *            is true:   *            <ul><li><code>srcBegin</code> is negative.   *            <li><code>srcBegin</code> is greater than <code>srcEnd</code>   *            <li><code>srcEnd</code> is greater than the length of this   *                string   *            <li><code>dstBegin</code> is negative   *            <li><code>dstBegin+(srcEnd-srcBegin)</code> is larger than   *                <code>dst.length</code></ul>   * @exception NullPointerException if <code>dst</code> is <code>null</code>   */  private void getChars(int srcBegin, int srcEnd, char dst[], int dstBegin)  {    // %TBD% Joe needs to write this function.  Make public when implemented.  }  /**   * Encapsulation c'tor. After this is called, the source FastStringBuffer   * will be reset to use the new object as its m_innerFSB, and will have   * had its chunk size reset appropriately. IT SHOULD NEVER BE CALLED   * EXCEPT WHEN source.length()==1<<(source.m_chunkBits+source.m_rebundleBits)   *   * NEEDSDOC @param source   */  private FastStringBuffer(FastStringBuffer source)  {    // Copy existing information into new encapsulation    m_chunkBits = source.m_chunkBits;    m_maxChunkBits = source.m_maxChunkBits;    m_rebundleBits = source.m_rebundleBits;    m_chunkSize = source.m_chunkSize;    m_chunkMask = source.m_chunkMask;    m_array = source.m_array;    m_innerFSB = source.m_innerFSB;    // These have to be adjusted because we're calling just at the time    // when we would be about to allocate another chunk    m_lastChunk = source.m_lastChunk - 1;    m_firstFree = source.m_chunkSize;    // Establish capsule as the Inner FSB, reset chunk sizes/addressing    source.m_array = new char[16][];    source.m_innerFSB = this;    // Since we encapsulated just as we were about to append another    // chunk, return ready to create the chunk after the innerFSB    // -- 1, not 0.    source.m_lastChunk = 1;    source.m_firstFree = 0;    source.m_chunkBits += m_rebundleBits;    source.m_chunkSize = 1 << (source.m_chunkBits);    source.m_chunkMask = source.m_chunkSize - 1;  }}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?