int insert ( Object caller , int version , bbBlock curr , int pos , int len ) { assert mutation_in_progress ( caller , version ) ; // DEBUG: int amountMoved = 0; // DEBUG: int before = this._buf_limit; // DEBUG: assert _validate(); // if there's room in the current block - just // move the "trailing" bytes down and we're done int neededSpace = len - curr . unusedBlockCapacity ( ) ; if ( neededSpace <= 0 ) { // we have all the space we need in the current block // DEBUG: amountMoved = insertInCurrOnly ( caller , version , curr , pos , len ) ; } else { // we'll need at least some additional space beyond the curr // block, see if there's room in the // next one, otherwise we'll make more (blocks) bbBlock next = null ; if ( curr . _idx < this . _next_block_position - 1 ) { // if there is another block next = this . _blocks . get ( curr . _idx + 1 ) ; } if ( next != null && ( neededSpace <= next . unusedBlockCapacity ( ) ) ) { // with the addition of the free space in the following block we have enough // DEBUG: amountMoved = insertInCurrAndNext ( caller , version , curr , pos , len , next ) ; } else { // we'll have to make one or more new blocks // first figure out much will be in the first // and last blocks (i.e. ignoring the whole // blocks int lenNeededInLastAddedBlock = neededSpace % _blockSizeUpperLimit ; int tailLen = curr . bytesAvailableToRead ( pos ) ; if ( lenNeededInLastAddedBlock < tailLen ) lenNeededInLastAddedBlock = tailLen ; if ( lenNeededInLastAddedBlock < neededSpace && neededSpace < this . _blockSizeUpperLimit ) { // if we need less than the largest block then we should // make *one* block with all of the needed space lenNeededInLastAddedBlock = neededSpace ; } bbBlock newblock = insertMakeNewTailBlock ( caller , version , curr , lenNeededInLastAddedBlock ) ; // now see if the curr block and this newblock have enough // available space to do the job, and if there's some trailing // data from curr that will end up staying in curr if ( len <= ( curr . unusedBlockCapacity ( ) + newblock . unusedBlockCapacity ( ) ) ) { // insert this as a zero length block immediately after _curr // insertBlock also adjusts the trailing blocks idx values insertBlock ( newblock ) ; // now pretend we just have the "push into the next block" case // DEBUG: amountMoved = insertInCurrAndNext ( caller , version , curr , pos , len , newblock ) ; } else { // and last we have the case of having to insert more than 1 block // which means all of the trailing bytes in _curr move into the last // block // DEBUG: amountMoved = insertAsManyBlocksAsNeeded ( caller , version , curr , pos , len , newblock ) ; } } } // DEBUG: if (this._buf_limit - before != len // DEBUG: || amountMoved != len) { // DEBUG: throw new BlockedBufferException("insert went wrong #1 !!!"); // DEBUG: } assert _validate ( ) ; return len ; }
dispatcher for the various forms of insert we encounter calls one of the four helpers depending on the case that is needed to inser here