docs: public static LinkedBuffer encode(final byte[] input, int inOffset, int inLen,
              final WriteSession session, final OutputStream out, 
              final LinkedBuffer lb) throws IOException
      {
          int outputSize = ((inLen+2)/3)*4;
          session.size += outputSize;
          
          final int available = lb.buffer.length - lb.offset;
          if(outputSize > available)
          {
              final int bufSize = lb.buffer.length - lb.start;
              if(outputSize > bufSize)
              {
                  // still larger than buffer size.
                  int chunks = available/4;
                  if(chunks == 0)
                  {
                      // available size is less than 4
                      // flush and reset
                      out.write(lb.buffer, lb.start, lb.offset-lb.start);
                      lb.offset = lb.start;
                      
                      final int loops = bufSize/4, inProcessLen = loops*3, outProcessLen = loops*4;
                      do
                      {
                          inOffset = encodeExplicit(input, inOffset, 0, lb.buffer, 
                                  lb.offset, loops);
                          
                          out.write(lb.buffer, lb.offset, outProcessLen);
                          inLen -= inProcessLen;
                          outputSize -= outProcessLen;
                      }
                      while(inLen > inProcessLen);
                      
                      // write remaining
                      encode(input, inOffset, inLen, lb.buffer, lb.offset);
                      lb.offset += outputSize;
                      
                      return lb;
                  }
                  
                  int inBefore = inOffset;
                  byte[] buffer = lb.buffer;
                  int offset = lb.offset;
                  byte b0, b1, b2;
                  
                  // process available
                  while(chunks-->0)
                  {
                      b0=input[inOffset++];
                      b1=input[inOffset++];
                      b2=input[inOffset++];
                      buffer[offset++]=nibble2code[(b0>>>2)&0x3f];
                      buffer[offset++]=nibble2code[(b0<<4)&0x3f|(b1>>>4)&0x0f];
                      buffer[offset++]=nibble2code[(b1<<2)&0x3f|(b2>>>6)&0x03];
                      buffer[offset++]=nibble2code[b2&077];
                  }
                  
                  inLen -= (inOffset - inBefore);
                  
                  outputSize -= (offset - lb.offset);
                  
                  // flush available
                  out.write(buffer, lb.start, offset-lb.start);
                  // reset
                  lb.offset = lb.start;
                  
                  if(outputSize > bufSize)
                  {
                      // still larger than buffer size.
                      final int loops = bufSize/4, inProcessLen = loops*3, outProcessLen = loops*4;
                      do
                      {
                          inOffset = encodeExplicit(input, inOffset, 0, lb.buffer, 
                                  lb.offset, loops);
                          
                          out.write(lb.buffer, lb.offset, outProcessLen);
                          inLen -= inProcessLen;
                          outputSize -= outProcessLen;
                      }
                      while(inLen > inProcessLen);
                      
                      // write remaining
                      encode(input, inOffset, inLen, lb.buffer, lb.offset);
                      lb.offset += outputSize;
                      
                      return lb;
                  }
                  
                  encode(input, inOffset, inLen, lb.buffer, lb.offset);
                  lb.offset += outputSize;
  
                  return lb;
              }
              
              // flush and reset
              out.write(lb.buffer, lb.start, lb.offset-lb.start);
              lb.offset = lb.start;
          }
          
          encode(input, inOffset, inLen, lb.buffer, lb.offset);
          lb.offset += outputSize;
  
          return lb;
      }