faststringbuffer.java

来自「java jdk 1.4的源码」· Java 代码 · 共 1,377 行 · 第 1/4 页

JAVA
1,377
字号
    int copyfrom = start;    char[] chunk = m_array[m_lastChunk];    int available = m_chunkSize - m_firstFree;    // Repeat while data remains to be copied    while (strlen > 0)    {      // Copy what fits      if (available > strlen)        available = strlen;      System.arraycopy(chars, copyfrom, m_array[m_lastChunk], m_firstFree,                       available);      strlen -= available;      copyfrom += available;      // If there's more left, allocate another chunk and continue      if (strlen > 0)      {        // Extend array?        int i = m_array.length;        if (m_lastChunk + 1 == i)        {          char[][] newarray = new char[i + 16][];          System.arraycopy(m_array, 0, newarray, 0, i);          m_array = newarray;        }        // Advance one chunk        chunk = m_array[++m_lastChunk];        if (chunk == null)        {          // Hierarchical encapsulation          if (m_lastChunk == 1 << m_rebundleBits                  && m_chunkBits < m_maxChunkBits)          {            // Should do all the work of both encapsulating            // existing data and establishing new sizes/offsets            m_innerFSB = new FastStringBuffer(this);          }          // Add a chunk.          chunk = m_array[m_lastChunk] = new char[m_chunkSize];        }        available = m_chunkSize;        m_firstFree = 0;      }    }    // Adjust the insert point in the last chunk, when we've reached it.    m_firstFree += available;  }  /**   * Append the contents of another FastStringBuffer onto   * this FastStringBuffer, growing the storage if necessary.   * <p>   * NOTE THAT after calling append(), previously obtained   * references to m_array[] may no longer be valid.   *   * @param value FastStringBuffer whose contents are   * to be appended.   */  public final void append(FastStringBuffer value)  {    // Complicating factor here is that the two buffers may use    // different chunk sizes, and even if they're the same we're    // probably on a different alignment due to previously appended    // data. We have to work through the source in bite-sized chunks.    if (value == null)       return;    int strlen = value.length();    if (0 == strlen)      return;    int copyfrom = 0;    char[] chunk = m_array[m_lastChunk];    int available = m_chunkSize - m_firstFree;    // Repeat while data remains to be copied    while (strlen > 0)    {      // Copy what fits      if (available > strlen)        available = strlen;      int sourcechunk = (copyfrom + value.m_chunkSize - 1)                        >>> value.m_chunkBits;      int sourcecolumn = copyfrom & value.m_chunkMask;      int runlength = value.m_chunkSize - sourcecolumn;      if (runlength > available)        runlength = available;      System.arraycopy(value.m_array[sourcechunk], sourcecolumn,                       m_array[m_lastChunk], m_firstFree, runlength);      if (runlength != available)        System.arraycopy(value.m_array[sourcechunk + 1], 0,                         m_array[m_lastChunk], m_firstFree + runlength,                         available - runlength);      strlen -= available;      copyfrom += available;      // If there's more left, allocate another chunk and continue      if (strlen > 0)      {        // Extend array?        int i = m_array.length;        if (m_lastChunk + 1 == i)        {          char[][] newarray = new char[i + 16][];          System.arraycopy(m_array, 0, newarray, 0, i);          m_array = newarray;        }        // Advance one chunk        chunk = m_array[++m_lastChunk];        if (chunk == null)        {          // Hierarchical encapsulation          if (m_lastChunk == 1 << m_rebundleBits                  && m_chunkBits < m_maxChunkBits)          {            // Should do all the work of both encapsulating            // existing data and establishing new sizes/offsets            m_innerFSB = new FastStringBuffer(this);          }          // Add a chunk.           chunk = m_array[m_lastChunk] = new char[m_chunkSize];        }        available = m_chunkSize;        m_firstFree = 0;      }    }    // Adjust the insert point in the last chunk, when we've reached it.    m_firstFree += available;  }  /**   * @return true if the specified range of characters are all whitespace,   * as defined by XMLCharacterRecognizer.   * <p>   * CURRENTLY DOES NOT CHECK FOR OUT-OF-RANGE.   *   * @param start Offset of first character in the range.   * @param length Number of characters to send.   */  public boolean isWhitespace(int start, int length)  {    int sourcechunk = start >>> m_chunkBits;    int sourcecolumn = start & m_chunkMask;    int available = m_chunkSize - sourcecolumn;    boolean chunkOK;    while (length > 0)    {      int runlength = (length <= available) ? length : available;      if (sourcechunk == 0 && m_innerFSB != null)        chunkOK = m_innerFSB.isWhitespace(sourcecolumn, runlength);      else        chunkOK = org.apache.xml.utils.XMLCharacterRecognizer.isWhiteSpace(          m_array[sourcechunk], sourcecolumn, runlength);      if (!chunkOK)        return false;      length -= runlength;      ++sourcechunk;      sourcecolumn = 0;      available = m_chunkSize;    }    return true;  }  /**   * @param start Offset of first character in the range.   * @param length Number of characters to send.   * @return a new String object initialized from the specified range of   * characters.   */  public String getString(int start, int length)  {    return getString(new StringBuffer(length), start >>> m_chunkBits,                     start & m_chunkMask, length).toString();  }  /**   * @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 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)        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);    }

⌨️ 快捷键说明

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