Save This Page
Home » xmlbeans-2.5.0-src » org.apache.xmlbeans.impl » store » [javadoc | source]
    1   /*   Copyright 2004 The Apache Software Foundation
    2    *
    3    *   Licensed under the Apache License, Version 2.0 (the "License");
    4    *   you may not use this file except in compliance with the License.
    5    *   You may obtain a copy of the License at
    6    *
    7    *       http://www.apache.org/licenses/LICENSE-2.0
    8    *
    9    *   Unless required by applicable law or agreed to in writing, software
   10    *   distributed under the License is distributed on an "AS IS" BASIS,
   11    *   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   12    *   See the License for the specific language governing permissions and
   13    *  limitations under the License.
   14    */
   15   package org.apache.xmlbeans.impl.store;
   16   
   17   import java.io.PrintStream;
   18   import java.lang.ref.SoftReference;
   19   
   20   public final class CharUtil
   21   {
   22       public CharUtil ( int charBufSize )
   23       {
   24           _charBufSize = charBufSize;
   25       }
   26   
   27       public CharIterator getCharIterator ( Object src, int off, int cch )
   28       {
   29           _charIter.init( src, off, cch );
   30           return _charIter;
   31       }
   32       
   33       public CharIterator getCharIterator ( Object src, int off, int cch, int start )
   34       {
   35           _charIter.init( src, off, cch, start );
   36           return _charIter;
   37       }
   38   
   39       public static CharUtil getThreadLocalCharUtil ( )
   40       {
   41           SoftReference softRef = (SoftReference)tl_charUtil.get();
   42           CharUtil charUtil = (CharUtil) softRef.get();
   43           if (charUtil==null)
   44           {
   45               charUtil = new CharUtil( CHARUTIL_INITIAL_BUFSIZE );
   46               tl_charUtil.set(new SoftReference(charUtil));
   47           }
   48           return charUtil;
   49       }
   50   
   51       public static void getString ( StringBuffer sb, Object src, int off, int cch )
   52       {
   53           assert isValid( src, off, cch );
   54   
   55           if (cch == 0)
   56               return;
   57   
   58           if (src instanceof char[])
   59               sb.append( (char[]) src, off, cch );
   60           else if (src instanceof String)
   61           {
   62               String s = (String) src;
   63               
   64               if (off == 0 && cch == s.length())
   65                   sb.append( (String) src );
   66               else
   67                   sb.append( s.substring( off, off + cch ) );
   68           }
   69           else
   70               ((CharJoin) src).getString( sb, off, cch );
   71       }
   72       
   73       public static void getChars ( char[] chars, int start, Object src, int off, int cch )
   74       {
   75           assert isValid( src, off, cch );
   76           assert chars != null && start >= 0 && start <= chars.length;
   77   
   78           if (cch == 0)
   79               return;
   80   
   81           if (src instanceof char[])
   82               System.arraycopy( (char[]) src, off, chars, start, cch );
   83           else if (src instanceof String)
   84               ((String) src).getChars( off, off + cch, chars, start );
   85           else
   86               ((CharJoin) src).getChars( chars, start, off, cch );
   87       }
   88       
   89       public static String getString ( Object src, int off, int cch )
   90       {
   91           assert isValid( src, off, cch );
   92   
   93           if (cch == 0)
   94               return "";
   95   
   96           if (src instanceof char[])
   97               return new String( (char[]) src, off, cch );
   98   
   99           if (src instanceof String)
  100           {
  101               String s = (String) src;
  102   
  103               if (off == 0 && cch == s.length())
  104                   return s;
  105   
  106               return s.substring( off, off + cch );
  107           }
  108   
  109           StringBuffer sb = new StringBuffer();
  110           
  111           ((CharJoin) src).getString( sb, off, cch );
  112           
  113           return sb.toString();
  114       }
  115   
  116       public static final boolean isWhiteSpace ( char ch )
  117       {
  118           switch ( ch )
  119           {
  120               case ' ': case '\t': case '\n': case '\r': return true;
  121               default                                  : return false;
  122           }
  123       }
  124   
  125       public final boolean isWhiteSpace ( Object src, int off, int cch )
  126       {
  127           assert isValid( src, off, cch );
  128   
  129           if (cch <= 0)
  130               return true;
  131           
  132           if (src instanceof char[])
  133           {
  134               for ( char[] chars = (char[]) src ; cch > 0 ; cch-- )
  135                   if (!isWhiteSpace( chars[ off++ ] ))
  136                       return false;
  137   
  138               return true;
  139           }
  140               
  141           if (src instanceof String)
  142           {
  143               for ( String s = (String) src ; cch > 0 ; cch-- )
  144                   if (!isWhiteSpace( s.charAt( off++ ) ))
  145                       return false;
  146   
  147               return true;
  148           }
  149               
  150           boolean isWhite = true;
  151   
  152           for ( _charIter.init( src, off, cch ) ; _charIter.hasNext() ; )
  153           {
  154               if (!isWhiteSpace( _charIter.next() ))
  155               {
  156                   isWhite = false;
  157                   break;
  158               }
  159           }
  160   
  161           _charIter.release();
  162   
  163           return isWhite;
  164       }
  165   
  166       public Object stripLeft ( Object src, int off, int cch )
  167       {
  168           assert isValid( src, off, cch );
  169   
  170           if (cch > 0)
  171           {
  172               if (src instanceof char[])
  173               {
  174                   char[] chars = (char[]) src;
  175   
  176                   while ( cch > 0 && isWhiteSpace( chars[ off ] ) )
  177                       { cch--; off++; }
  178               }
  179               else if (src instanceof String)
  180               {
  181                   String s = (String) src;
  182   
  183                   while ( cch > 0 && isWhiteSpace( s.charAt( off ) ) )
  184                       { cch--; off++; }
  185               }
  186               else
  187               {
  188                   int count = 0;
  189                   
  190                   for ( _charIter.init( src, off, cch ) ; _charIter.hasNext() ; count++ )
  191                       if (!isWhiteSpace( _charIter.next() ))
  192                           break;
  193                   
  194                   _charIter.release();
  195   
  196                   off += count;
  197               }
  198           }
  199   
  200           if (cch == 0)
  201           {
  202               _offSrc = 0;
  203               _cchSrc = 0;
  204               
  205               return null;
  206           }
  207   
  208           _offSrc = off;
  209           _cchSrc = cch;
  210   
  211           return src;
  212       }
  213   
  214       public Object stripRight ( Object src, int off, int cch )
  215       {
  216           assert isValid( src, off, cch );
  217           
  218           if (cch > 0)
  219           {
  220               for ( _charIter.init( src, off, cch, cch ) ; _charIter.hasPrev() ; cch-- )
  221                   if (!isWhiteSpace( _charIter.prev() ))
  222                       break;
  223   
  224               _charIter.release();
  225           }
  226           
  227           if (cch == 0)
  228           {
  229               _offSrc = 0;
  230               _cchSrc = 0;
  231               
  232               return null;
  233           }
  234   
  235           _offSrc = off;
  236           _cchSrc = cch;
  237   
  238           return src;
  239       }
  240       
  241       public Object insertChars (
  242           int posInsert,
  243           Object src, int off, int cch,
  244           Object srcInsert, int offInsert, int cchInsert )
  245       {
  246           assert isValid( src, off, cch );
  247           assert isValid( srcInsert, offInsert, cchInsert );
  248           assert posInsert >= 0 && posInsert <= cch;
  249   
  250           // TODO - at some point, instead of creating joins, I should
  251           // normalize all the text into a single buffer to stop large
  252           // tree's from being built when many modifications happen...
  253   
  254           // TODO - actually, I should see if the size of the new char
  255           // sequence is small enough to simply allocate a new contigous
  256           // sequence, either in a common char[] managed by the master,
  257           // or just create a new string ... this goes for remove chars
  258           // as well.
  259   
  260           if (cchInsert == 0)
  261           {
  262               _cchSrc = cch;
  263               _offSrc = off;
  264               return src;
  265           }
  266   
  267           if (cch == 0)
  268           {
  269               _cchSrc = cchInsert;
  270               _offSrc = offInsert;
  271               return srcInsert;
  272           }
  273   
  274           _cchSrc = cch + cchInsert;
  275   
  276           Object newSrc;
  277   
  278           if (_cchSrc <= MAX_COPY && canAllocate( _cchSrc ))
  279           {
  280               char[] c = allocate( _cchSrc );
  281   
  282               getChars( c, _offSrc, src, off, posInsert );
  283               getChars( c, _offSrc + posInsert, srcInsert, offInsert, cchInsert );
  284               getChars( c, _offSrc + posInsert + cchInsert, src, off + posInsert, cch - posInsert );
  285   
  286               newSrc = c;
  287           }
  288           else
  289           {
  290               _offSrc = 0;
  291   
  292               CharJoin newJoin;
  293   
  294               if (posInsert == 0)
  295                   newJoin = new CharJoin( srcInsert, offInsert, cchInsert, src, off );
  296               else if (posInsert == cch)
  297                   newJoin = new CharJoin( src, off, cch, srcInsert, offInsert );
  298               else
  299               {
  300                   CharJoin j = new CharJoin( src, off, posInsert, srcInsert, offInsert );
  301                   newJoin = new CharJoin( j, 0, posInsert + cchInsert, src, off + posInsert );
  302               }
  303               
  304               if (newJoin._depth > CharJoin.MAX_DEPTH)
  305                   newSrc = saveChars( newJoin, _offSrc, _cchSrc );
  306               else
  307                   newSrc = newJoin;
  308           }
  309   
  310           assert isValid( newSrc, _offSrc, _cchSrc );
  311   
  312           return newSrc;
  313       }
  314   
  315       public Object removeChars ( int posRemove, int cchRemove, Object src, int off, int cch )
  316       {
  317           assert isValid( src, off, cch );
  318           assert posRemove >= 0 && posRemove <= cch;
  319           assert cchRemove >= 0 && posRemove + cchRemove <= cch;
  320   
  321           Object newSrc;
  322   
  323           _cchSrc = cch - cchRemove;
  324           
  325           if (_cchSrc == 0)
  326           {
  327               newSrc = null;
  328               _offSrc = 0;
  329           }
  330           else if (posRemove == 0)
  331           {
  332               newSrc = src;
  333               _offSrc = off + cchRemove;
  334           }
  335           else if (posRemove + cchRemove == cch)
  336           {
  337               newSrc = src;
  338               _offSrc = off;
  339           }
  340           else
  341           {
  342               int cchAfter = cch - cchRemove;
  343               
  344               if (cchAfter <= MAX_COPY && canAllocate( cchAfter ))
  345               {
  346                   char[] chars = allocate( cchAfter );
  347   
  348                   getChars( chars, _offSrc, src, off, posRemove );
  349   
  350                   getChars(
  351                       chars, _offSrc + posRemove,
  352                       src, off + posRemove + cchRemove, cch - posRemove - cchRemove );
  353   
  354                   newSrc = chars;
  355                   _offSrc = _offSrc;
  356               }
  357               else
  358               {
  359                   CharJoin j = new CharJoin( src, off, posRemove, src, off + posRemove + cchRemove );
  360   
  361                   if (j._depth > CharJoin.MAX_DEPTH)
  362                       newSrc = saveChars( j, 0, _cchSrc );
  363                   else
  364                   {
  365                       newSrc = j;
  366                       _offSrc = 0;
  367                   }
  368               }
  369           }
  370           
  371           assert isValid( newSrc, _offSrc, _cchSrc );
  372           
  373           return newSrc;
  374       }
  375   
  376       private static int sizeof ( Object src )
  377       {
  378           assert src == null || src instanceof String || src instanceof char[];
  379           
  380           if (src instanceof char[])
  381               return ((char[]) src).length;
  382   
  383           return src == null ? 0 : ((String) src).length();
  384       }
  385   
  386       private boolean canAllocate ( int cch )
  387       {
  388           return _currentBuffer == null || _currentBuffer.length - _currentOffset >= cch;
  389       }
  390       
  391       private char[] allocate ( int cch )
  392       {
  393           assert _currentBuffer == null || _currentBuffer.length - _currentOffset > 0;
  394           
  395           if (_currentBuffer == null)
  396           {
  397               _currentBuffer = new char [ Math.max( cch, _charBufSize ) ];
  398               _currentOffset = 0;
  399           }
  400   
  401           _offSrc = _currentOffset;
  402           _cchSrc = Math.min( _currentBuffer.length - _currentOffset, cch );
  403   
  404           char[] retBuf = _currentBuffer;
  405   
  406           assert _currentOffset + _cchSrc <= _currentBuffer.length;
  407   
  408           if ((_currentOffset += _cchSrc) == _currentBuffer.length)
  409           {
  410               _currentBuffer = null;
  411               _currentOffset = 0;
  412           }
  413   
  414           return retBuf;
  415       }
  416   
  417       public Object saveChars ( Object srcSave, int offSave, int cchSave )
  418       {
  419           return saveChars( srcSave, offSave, cchSave, null, 0, 0 );
  420       }
  421               
  422       public Object saveChars (
  423           Object srcSave, int offSave, int cchSave,
  424           Object srcPrev, int offPrev, int cchPrev )
  425       {
  426           // BUGBUG (ericvas)
  427           //
  428           // There is a severe degenerate situation which can deveol here.  The cases is where
  429           // there is a long strings of calls to saveChars, where the caller passes in prev text
  430           // to be prepended.  In this cases, the buffer breaks and a join is made, but because the
  431           // join is created, subsequent calls willproduce additional joins.  I need to figure
  432           // out a way that a whole bunch of joins are not created.  I really only want to create
  433           // joins in situations where large amount of text is manipulated.
  434   
  435           assert isValid( srcSave, offSave, cchSave );
  436           assert isValid( srcPrev, offPrev, cchPrev );
  437   
  438           // Allocate some space to save the text and copy it there.  This may not allocate all
  439           // the space I need.  This happens when I run out of buffer space.  Deal with this later.
  440           
  441           char[] srcAlloc = allocate( cchSave );
  442           int offAlloc = _offSrc;
  443           int cchAlloc = _cchSrc;
  444   
  445           assert cchAlloc <= cchSave;
  446   
  447           getChars( srcAlloc, offAlloc, srcSave, offSave, cchAlloc );
  448   
  449           Object srcNew;
  450           int offNew;
  451   
  452           int cchNew = cchAlloc + cchPrev;
  453           
  454           // The prev arguments specify a chunk of text which the caller wants prepended to the
  455           // text to be saved.  The optimization here is to detect the case where the prev text
  456           // and the newly allcoated and saved text are adjacent, so that I can avoid copying
  457           // or joining the two pieces.  The situation where this happens most is when a parser
  458           // reports a big piece of text in chunks, perhaps because there are entities in the
  459           // big chunk of text.
  460   
  461           CharJoin j;
  462   
  463           if (cchPrev == 0)
  464           {
  465               srcNew = srcAlloc;
  466               offNew = offAlloc;
  467           }
  468           else if (srcPrev == srcAlloc && offPrev + cchPrev == offAlloc)
  469           {
  470               assert srcPrev instanceof char[];
  471               
  472               srcNew = srcPrev;
  473               offNew = offPrev;
  474           }
  475           else if (srcPrev instanceof CharJoin && (j = (CharJoin) srcPrev)._srcRight == srcAlloc &&
  476                       offPrev + cchPrev - j._cchLeft + j._offRight == offAlloc)
  477           {
  478               assert j._srcRight instanceof char[];
  479   
  480               srcNew = srcPrev;
  481               offNew = offPrev;
  482           }
  483           else
  484           {
  485               j = new CharJoin( srcPrev, offPrev, cchPrev, srcAlloc, offAlloc );
  486   
  487               srcNew = j;
  488               offNew = 0;
  489               srcNew = j._depth > CharJoin.MAX_DEPTH ? saveChars( j, 0, cchNew ) : j;
  490           }
  491   
  492           // Now, srcNew and offNew specify the two parts of the triple which has the prev text and
  493           // part of the text to save (if not all of it).  Here I compute cchMore which is any
  494           // remaining text which was not allocated for earlier.  Effectively, this code deals with
  495           // the case where the text to save was greater than the remaining space in the buffer and
  496           // I need to allocate another buffer to save away the second part and then join the two.
  497           
  498           int cchMore = cchSave - cchAlloc;
  499           
  500           if (cchMore > 0)
  501           {
  502               // If we're here the the buffer got consumed.  So, this time it must allocate a new
  503               // buffer capable of containing all of the remaining text (no matter how large) and
  504               // return the beginning part of it.
  505               
  506               srcAlloc = allocate( cchMore );
  507               offAlloc = _offSrc;
  508               cchAlloc = _cchSrc;
  509   
  510               assert cchAlloc == cchMore;
  511               assert offAlloc == 0;
  512   
  513               getChars( srcAlloc, offAlloc, srcSave, offSave + (cchSave - cchMore), cchMore );
  514   
  515               j = new CharJoin( srcNew, offNew, cchNew, srcAlloc, offAlloc );
  516               
  517               offNew = 0;
  518               cchNew += cchMore;
  519               srcNew = j._depth > CharJoin.MAX_DEPTH ? saveChars( j, 0, cchNew ) : j;
  520           }
  521   
  522           _offSrc = offNew;
  523           _cchSrc = cchNew;
  524           
  525           assert isValid( srcNew, _offSrc, _cchSrc );
  526           
  527           return srcNew;
  528       }
  529   
  530       private static void dumpText ( PrintStream o, String s )
  531       {
  532           o.print( "\"" );
  533   
  534           for ( int i = 0 ; i < s.length() ; i++ )
  535           {
  536               char ch = s.charAt( i );
  537   
  538               if (i == 36)
  539               {
  540                   o.print( "..." );
  541                   break;
  542               }
  543   
  544               if      (ch == '\n') o.print( "\\n" );
  545               else if (ch == '\r') o.print( "\\r" );
  546               else if (ch == '\t') o.print( "\\t" );
  547               else if (ch == '\f') o.print( "\\f" );
  548               else if (ch == '\f') o.print( "\\f" );
  549               else if (ch == '"' ) o.print( "\\\"" );
  550               else                 o.print( ch );
  551           }
  552   
  553           o.print( "\"" );
  554       }
  555   
  556       public static void dump ( Object src, int off, int cch )
  557       {
  558           dumpChars( System.out, src, off, cch );
  559           System.out.println();
  560       }
  561       
  562       public static void dumpChars ( PrintStream p, Object src, int off, int cch )
  563       {
  564           p.print( "off=" + off + ", cch=" + cch + ", " );
  565           
  566           if (src == null)
  567               p.print( "<null-src>" );
  568           else if (src instanceof String)
  569           {
  570               String s = (String) src;
  571   
  572               p.print( "String" );
  573   
  574               if (off != 0 || cch != s.length())
  575               {
  576                   if (off < 0 || off > s.length() || off + cch < 0 || off + cch > s.length())
  577                   {
  578                       p.print( " (Error)" );
  579                       return;
  580                   }
  581               }
  582   
  583               //p.print( ": " );
  584               dumpText( p, s.substring( off, off + cch ) );
  585           }
  586           else if (src instanceof char[])
  587           {
  588               char[] chars = (char[]) src;
  589   
  590               p.print( "char[]" );
  591   
  592               if (off != 0 || cch != chars.length)
  593               {
  594                   if (off < 0 || off > chars.length || off + cch < 0 || off + cch > chars.length)
  595                   {
  596                       p.print( " (Error)" );
  597                       return;
  598                   }
  599               }
  600   
  601               //p.print( ": " );
  602               dumpText( p, new String( chars, off, cch ) );
  603           }
  604           else if (src instanceof CharJoin)
  605           {
  606               p.print( "CharJoin" );
  607   
  608               ((CharJoin) src).dumpChars( p, off, cch );
  609           }
  610           else
  611           {
  612               p.print( "Unknown text source" );
  613           }
  614       }
  615   
  616       public static boolean isValid ( Object src, int off, int cch )
  617       {
  618           if (cch < 0 || off < 0)
  619               return false;
  620   
  621           if (src == null)
  622               return off == 0 && cch == 0;
  623   
  624           if (src instanceof char[])
  625           {
  626               char[] c = (char[]) src;
  627               return off <= c.length && off + cch <= c.length;
  628           }
  629   
  630           if (src instanceof String)
  631           {
  632               String s = (String) src;
  633               return off <= s.length() && off + cch <= s.length();
  634           }
  635   
  636           if (src instanceof CharJoin)
  637               return ((CharJoin) src).isValid( off, cch );
  638   
  639           return false;
  640       }
  641   
  642       //
  643       // Private stuff
  644       //
  645       
  646       public static final class CharJoin
  647       {
  648           public CharJoin (
  649               Object srcLeft, int offLeft, int cchLeft, Object srcRight, int offRight )
  650           {
  651               _srcLeft  = srcLeft;  _offLeft  = offLeft;  _cchLeft = cchLeft;
  652               _srcRight = srcRight; _offRight = offRight;
  653   
  654               int depth = 0;
  655               
  656               if (srcLeft instanceof CharJoin)
  657                   depth = ((CharJoin) srcLeft)._depth;
  658               
  659               if (srcRight instanceof CharJoin)
  660               {
  661                   int rightDepth = ((CharJoin) srcRight)._depth;
  662                   
  663                   if (rightDepth > depth)
  664                       depth = rightDepth;
  665               }
  666               
  667               _depth = depth + 1;
  668   
  669               assert _depth <= MAX_DEPTH + 2;
  670           }
  671           
  672           private int cchRight ( int off, int cch )
  673           {
  674               return Math.max( 0, cch - _cchLeft - off );
  675           }
  676   
  677           public int depth ( )
  678           {
  679               int depth = 0;
  680               
  681               if (_srcLeft instanceof CharJoin)
  682                   depth = ((CharJoin) _srcLeft).depth();
  683               
  684               if (_srcRight instanceof CharJoin)
  685                   depth = Math.max( ((CharJoin)_srcRight).depth(), depth );
  686   
  687               return depth + 1;
  688           }
  689           
  690           public boolean isValid ( int off, int cch )
  691           {
  692               // Deep trees cause this to take forever
  693               
  694               if (_depth > 2)
  695                   return true;
  696   
  697               assert _depth == depth();
  698               
  699               if (off < 0 || cch < 0)
  700                   return false;
  701   
  702               if (!CharUtil.isValid( _srcLeft, _offLeft, _cchLeft ))
  703                   return false;
  704   
  705               if (!CharUtil.isValid( _srcRight, _offRight, cchRight( off, cch ) ))
  706                   return false;
  707   
  708               return true;
  709           }
  710   
  711           private void getString ( StringBuffer sb, int off, int cch )
  712           {
  713               assert cch > 0;
  714               
  715               if (off < _cchLeft)
  716               {
  717                   int cchL = Math.min( _cchLeft - off, cch );
  718   
  719                   CharUtil.getString( sb, _srcLeft, _offLeft + off, cchL );
  720   
  721                   if (cch > cchL)
  722                       CharUtil.getString( sb, _srcRight, _offRight, cch - cchL );
  723               }
  724               else
  725                   CharUtil.getString( sb, _srcRight, _offRight + off - _cchLeft, cch );
  726           }
  727   
  728           private void getChars ( char[] chars, int start, int off, int cch )
  729           {
  730               assert cch > 0;
  731   
  732               if (off < _cchLeft)
  733               {
  734                   int cchL = Math.min( _cchLeft - off, cch );
  735                              
  736                   CharUtil.getChars( chars, start, _srcLeft, _offLeft + off, cchL );
  737   
  738                   if (cch > cchL)
  739                       CharUtil.getChars( chars, start + cchL, _srcRight, _offRight, cch - cchL );
  740               }
  741               else
  742                   CharUtil.getChars( chars, start, _srcRight, _offRight + off - _cchLeft, cch );
  743           }
  744   
  745           private void dumpChars( int off, int cch )
  746           {
  747               dumpChars( System.out, off, cch );
  748           }
  749           
  750           private void dumpChars( PrintStream p, int off, int cch )
  751           {
  752               p.print( "( " );
  753               CharUtil.dumpChars( p, _srcLeft, _offLeft, _cchLeft );
  754               p.print( ", " );
  755               CharUtil.dumpChars( p, _srcRight, _offRight, cchRight( off, cch ) );
  756               p.print( " )" );
  757           }
  758           
  759           //
  760           //
  761           //
  762           
  763           public final Object _srcLeft;
  764           public final int    _offLeft;
  765           public final int    _cchLeft;
  766   
  767           public final Object _srcRight;
  768           public final int    _offRight;
  769   
  770           public final int _depth;
  771   
  772           static final int MAX_DEPTH = 64;
  773       }
  774   
  775       //
  776       //
  777       //
  778       
  779       public final static class CharIterator
  780       {
  781           public void init ( Object src, int off, int cch )
  782           {
  783               init( src, off, cch, 0 );
  784           }
  785           
  786           public void init ( Object src, int off, int cch, int startPos )
  787           {
  788               assert isValid( src, off, cch );
  789   
  790               release();
  791               
  792               _srcRoot = src;
  793               _offRoot = off;
  794               _cchRoot = cch;
  795   
  796               _minPos = _maxPos = -1;
  797               
  798               movePos( startPos );
  799           }
  800   
  801           public void release ( )
  802           {
  803               _srcRoot = null;
  804               _srcLeafString = null;
  805               _srcLeafChars = null;
  806           }
  807   
  808           public boolean hasNext ( ) { return _pos < _cchRoot; }
  809           public boolean hasPrev ( ) { return _pos > 0;       }
  810           
  811           public char next ( )
  812           {
  813               assert hasNext() ;
  814   
  815               char ch = currentChar();
  816   
  817               movePos( _pos + 1 );
  818   
  819               return ch;
  820           }
  821               
  822           public char prev ( )
  823           {
  824               assert hasPrev() ;
  825               
  826               movePos( _pos - 1 );
  827               
  828               return currentChar();
  829           }
  830   
  831           public void movePos ( int newPos )
  832           {
  833               assert newPos >= 0 && newPos <= _cchRoot;
  834   
  835               if (newPos < _minPos || newPos > _maxPos)
  836               {
  837                   // if newPos out of cached leaf, recache new leaf
  838                   Object  src    = _srcRoot;
  839                   int     off    = _offRoot + newPos;
  840                   int     cch    = _cchRoot;
  841   
  842                   for ( _offLeaf = _offRoot ; src instanceof CharJoin ; )
  843                   {
  844                       CharJoin j = (CharJoin) src;
  845   
  846                       if (off < j._cchLeft)
  847                       {
  848                           src = j._srcLeft;
  849                           _offLeaf = j._offLeft;
  850                           off = off + j._offLeft;
  851                           cch = j._cchLeft;
  852                       }
  853                       else
  854                       {
  855                           src = j._srcRight;
  856                           _offLeaf = j._offRight;
  857                           off = off - (j._cchLeft - j._offRight);
  858                           cch = cch - j._cchLeft;
  859                       }
  860                   }
  861   
  862   //                _offLeaf = off - Math.min( off - _offLeaf, newPos );
  863                   _minPos = newPos - (off - _offLeaf);
  864   //                _maxPos = newPos + Math.min( _cchRoot - newPos, sizeof( src ) - off );
  865                   _maxPos = _minPos + cch;
  866   
  867                   if (newPos < _cchRoot)
  868                       _maxPos--;
  869   
  870                   // Cache the leaf src to avoid instanceof for every char
  871                   
  872                   _srcLeafChars = null;
  873                   _srcLeafString = null;
  874   
  875                   if (src instanceof char[])
  876                       _srcLeafChars = (char[]) src;
  877                   else
  878                       _srcLeafString = (String) src;
  879                   
  880                   assert newPos >= _minPos && newPos <= _maxPos;
  881               }
  882   
  883               _pos = newPos;
  884           }
  885   
  886           private char currentChar ( )
  887           {
  888               int i = _offLeaf + _pos - _minPos;
  889               
  890               return _srcLeafChars == null ? _srcLeafString.charAt( i ) : _srcLeafChars[ i ];
  891           }
  892   
  893           private Object _srcRoot; // Original triple
  894           private int    _offRoot;
  895           private int    _cchRoot;
  896   
  897           private int    _pos;     // Current position
  898   
  899           private int    _minPos;  // Min/max poses for current cached leaf
  900           private int    _maxPos;
  901   
  902           private int    _offLeaf;
  903           
  904           private String _srcLeafString;  // Cached leaf - either a char[] or a string
  905           private char[] _srcLeafChars;
  906       }
  907   
  908       private static int CHARUTIL_INITIAL_BUFSIZE = 1024 * 32;
  909       private static ThreadLocal tl_charUtil =
  910           new ThreadLocal() { protected Object initialValue() { return new SoftReference(new CharUtil( CHARUTIL_INITIAL_BUFSIZE )); } };
  911   
  912       private CharIterator _charIter = new CharIterator();
  913   
  914       // TODO - 64 is kinda arbitrary.  Perhaps it should be configurable.
  915       private static final int MAX_COPY = 64;
  916   
  917       // Current char buffer we're allcoating new chars to
  918   
  919       private int    _charBufSize;
  920       private int    _currentOffset;
  921       private char[] _currentBuffer;
  922       
  923       // These members are used to communicate offset and character count
  924       // information back to a caller of various methods on CharUtil.
  925       // Usually, the methods returns the src Object, and these two hold
  926       // the offset and the char count.
  927       
  928       public int _offSrc;
  929       public int _cchSrc;
  930   } 

Save This Page
Home » xmlbeans-2.5.0-src » org.apache.xmlbeans.impl » store » [javadoc | source]