Utility method to overlay the input bytes into the parse buffers,
starting at the input index and moving forward as needed.

@param data
@param inOffset
@param inLength
@param inIndex
@return index of last buffer updated
18209
private int overlayBytes(byte[] data, int inOffset, int inLength, int inIndex) {
        int length = inLength;
        int offset = inOffset;
        int index = inIndex;
        WsByteBuffer buffer = this.parseBuffers[index];
        if (-1 == length) {
            length = data.length;
        }
        while (index <= this.parseIndex) {
            int remaining = buffer.remaining();
            if (remaining >= length) {
                // it all fits now
                buffer.put(data, offset, length);
                return index;
            }
            // put what we can, loop through the next buffer
            buffer.put(data, offset, remaining);
            offset += remaining;
            length -= remaining;
            buffer = this.parseBuffers[++index];
            buffer.position(0);
        }
        return index;
    }
1080896
public boolean containsInstructionWithOffset(int offset) {
        Iterator<InstructionHandle> i = instructionIterator();
        while (i.hasNext()) {
            if (i.next().getPosition() == offset) {
                return true;
            }
        }
        return false;
    }
23913
public static final long getLong(byte[] data, int offset)
   {
      long result = 0;
      int i = offset;
      for (int shiftBy = 0; shiftBy < 64; shiftBy += 8)
      {
         result |= ((long) (data[i] & 0xff)) << shiftBy;
         ++i;
      }
      return result;
   }
1313298
static int putVarInt32AndGetOffset(final int value,
            final byte[] buffer, final int variableOffset)
    {
        switch (ProtobufOutput.computeRawVarint32Size(value))
        {
            case 1:
                buffer[variableOffset + 4] = (byte) value;
                return variableOffset + 4;

            case 2:
                buffer[variableOffset + 3] = (byte) ((value & 0x7F) | 0x80);
                buffer[variableOffset + 4] = (byte) (value >>> 7);
                return variableOffset + 3;

            case 3:
                buffer[variableOffset + 2] = (byte) ((value & 0x7F) | 0x80);
                buffer[variableOffset + 3] = (byte) ((value >>> 7 & 0x7F) | 0x80);
                buffer[variableOffset + 4] = (byte) (value >>> 14);
                return variableOffset + 2;

            case 4:
                buffer[variableOffset + 1] = (byte) ((value & 0x7F) | 0x80);
                buffer[variableOffset + 2] = (byte) ((value >>> 7 & 0x7F) | 0x80);
                buffer[variableOffset + 3] = (byte) ((value >>> 14 & 0x7F) | 0x80);
                buffer[variableOffset + 4] = (byte) (value >>> 21);
                return variableOffset + 1;

            default:
                buffer[variableOffset] = (byte) ((value & 0x7F) | 0x80);
                buffer[variableOffset + 1] = (byte) ((value >>> 7 & 0x7F) | 0x80);
                buffer[variableOffset + 2] = (byte) ((value >>> 14 & 0x7F) | 0x80);
                buffer[variableOffset + 3] = (byte) ((value >>> 21 & 0x7F) | 0x80);
                buffer[variableOffset + 4] = (byte) (value >>> 28);
                return variableOffset;
        }

    }
594966
public INode getLastCompleteNodeByOffset(INode node, int offsetPosition, int completionOffset) {
		return internalGetLastCompleteNodeByOffset(node.getRootNode(), offsetPosition);
	}
1112314
@Override public long indexOf(byte b, long fromIndex) {
    if (fromIndex < 0) throw new IllegalArgumentException("fromIndex < 0");

    Segment s = head;
    if (s == null) return -1L;
    long offset = 0L;
    do {
      int segmentByteCount = s.limit - s.pos;
      if (fromIndex >= segmentByteCount) {
        fromIndex -= segmentByteCount;
      } else {
        byte[] data = s.data;
        for (int pos = (int) (s.pos + fromIndex), limit = s.limit; pos < limit; pos++) {
          if (data[pos] == b) return offset + pos - s.pos;
        }
        fromIndex = 0;
      }
      offset += segmentByteCount;
      s = s.next;
    } while (s != head);
    return -1L;
  }
838127
private static long getNextPageOffset(final int offset, final int limit, final long total) {
        return hasFullNextPage(offset, limit, total) ? getNextFullPageOffset(offset, limit) : getLastPageOffset(total, limit);
    }
673177
private boolean checkBuffer(long offset) throws IOException {
    if (offset - bufferOffset < 0 || offset - bufferOffset >= currentBufferSize) {
      // the given offset is not contained in the buffer
      bufferOffset = offset;
      int index = 0;
      input.seek(offset);
      try {
        //input.read(buffer, 0, maxBufferSize);
        for (long pos = offset; pos < offset + maxBufferSize; pos++) {
          int ch = input.read();
          if (ch > -1) {
            buffer[index] = (byte)ch;
            index++;
          }
        }
      } catch (IOException ex) {
        // not possible
        ex.printStackTrace();
      }
      currentBufferSize = index;
      return true;
    }
    return false;
  }
314459
private static final int gatherPartialIntLE(final byte[] data, final int index, final int available) {
        int i = data[index] & 0xFF;

        if(available > 1) {
            i |= (data[index + 1] & 0xFF) << 8;
            if(available > 2) {
                i |= (data[index + 2] & 0xFF) << 16;
            }
        }

        return i;
    }
315077
static final byte[] inflate(final byte[] in, final int offset, final int length)
			throws DataFormatException {
		byte[] infBuf = new byte[length << 1];
		int payloadLength;
		synchronized (inflater) {
			inflater.reset();
			inflater.setInput(in, offset, length);
			payloadLength = inflater.inflate(infBuf);
		}
		return resizeBuffer(infBuf, payloadLength);
	}
504712
public void setBytes(long memoryOffset, ByteBuffer buffer)
    {
        if (buffer == null)
            throw new NullPointerException();
        else if (buffer.remaining() == 0)
            return;

        int bufferOffset = buffer.position();

        checkPosition(memoryOffset);
        long end = memoryOffset + buffer.remaining();
        checkPosition(end - 1);
        while (memoryOffset < end)
        {
            unsafe.putByte(peer + memoryOffset, buffer.get(bufferOffset));
            memoryOffset++;
            bufferOffset++;
        }
    }
759211
protected boolean computeOffset(final int dataIndex, CacheDataSet cache) {
        float layoutOffset = getLayoutOffset();
        int pos = cache.getPos(dataIndex);
        float startDataOffset = Float.NaN;
        float endDataOffset = Float.NaN;
        if (pos > 0) {
            int id = cache.getId(pos - 1);
            if (id != -1) {
                startDataOffset = cache.getEndDataOffset(id);
                if (!Float.isNaN(startDataOffset)) {
                    endDataOffset = cache.setDataAfter(dataIndex, startDataOffset);
                }
            }
        } else if (pos == 0) {
            int id = cache.getId(pos + 1);
            if (id != -1) {
                endDataOffset = cache.getStartDataOffset(id);
                if (!Float.isNaN(endDataOffset)) {
                    startDataOffset = cache.setDataBefore(dataIndex, endDataOffset);
                }
            } else {
                startDataOffset = getStartingOffset((cache.getTotalSizeWithPadding()));
                endDataOffset = cache.setDataAfter(dataIndex, startDataOffset);
            }
        }

        Log.d(LAYOUT, TAG, "computeOffset [%d, %d]: startDataOffset = %f endDataOffset = %f",
                dataIndex, pos, startDataOffset, endDataOffset);

        boolean inBounds = !Float.isNaN(cache.getDataOffset(dataIndex)) &&
                endDataOffset > layoutOffset &&
                startDataOffset < -layoutOffset;

        return inBounds;
    }
903462
public static LinkedBuffer sencode(final byte[] input, int inOffset, int inLen,
            final WriteSession session,
            final LinkedBuffer lb) throws IOException
    {
        int outputSize = ((inLen + 2) / 3) * 4;
        session.size += outputSize;

        int available = lb.buffer.length - lb.offset;
        if (outputSize > available)
        {
            final byte[] buffer = lb.buffer;
            int offset = lb.offset, remaining = inLen % 3, chunks = available / 4;
            byte b0, b1, b2;

            for (int stop = inOffset + (inLen - remaining); inOffset < stop; chunks--)
            {
                if (chunks == 0)
                {
                    // available size is less than 4
                    // flush and reset
                    offset = session.flush(buffer, lb.start, offset - lb.start);
                    // available = buffer.length - offset;
                    chunks = (buffer.length - offset) / 4;
                }

                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];
            }

            switch (remaining)
            {
                case 0:
                    break;
                case 1:
                    if (chunks == 0)
                        offset = session.flush(buffer, lb.start, offset - lb.start);

                    b0 = input[inOffset++];
                    buffer[offset++] = nibble2code[(b0 >>> 2) & 0x3f];
                    buffer[offset++] = nibble2code[(b0 << 4) & 0x3f];
                    buffer[offset++] = pad;
                    buffer[offset++] = pad;
                    break;
                case 2:
                    if (chunks == 0)
                        offset = session.flush(buffer, lb.start, offset - lb.start);

                    b0 = input[inOffset++];
                    b1 = input[inOffset++];
                    buffer[offset++] = nibble2code[(b0 >>> 2) & 0x3f];
                    buffer[offset++] = nibble2code[(b0 << 4) & 0x3f | (b1 >>> 4) & 0x0f];
                    buffer[offset++] = nibble2code[(b1 << 2) & 0x3f];
                    buffer[offset++] = pad;
                    break;

                default:
                    throw new IllegalStateException("should not happen");
            }

            lb.offset = offset;
            return lb;
        }

        encode(input, inOffset, inLen, lb.buffer, lb.offset);
        lb.offset += outputSize;

        return lb;
    }
909697
@Override
    public int lastIndexOf(Object o) {
        if (displacement != null) {
            return super.lastIndexOf(o) + displacement;
        }
        return super.lastIndexOf(o);
    }
224569
private boolean fillBuffer(int offset) throws IOException {
		int maxReadLength = this.readBuffer.length - offset;
		// special case for reading the whole split.
		if (this.splitLength == FileInputFormat.READ_WHOLE_SPLIT_FLAG) {
			int read = this.stream.read(this.readBuffer, offset, maxReadLength);
			if (read == -1) {
				this.stream.close();
				this.stream = null;
				return false;
			} else {
				this.readPos = offset;
				this.limit = read;
				return true;
			}
		}
		
		// else ..
		int toRead;
		if (this.splitLength > 0) {
			// if we have more data, read that
			toRead = this.splitLength > maxReadLength ? maxReadLength : (int) this.splitLength;
		}
		else {
			// if we have exhausted our split, we need to complete the current record, or read one
			// more across the next split.
			// the reason is that the next split will skip over the beginning until it finds the first
			// delimiter, discarding it as an incomplete chunk of data that belongs to the last record in the
			// previous split.
			toRead = maxReadLength;
			this.overLimit = true;
		}

		int read = this.stream.read(this.readBuffer, offset, toRead);

		if (read == -1) {
			this.stream.close();
			this.stream = null;
			return false;
		} else {
			this.splitLength -= read;
			this.readPos = offset; // position from where to start reading
			this.limit = read + offset; // number of valid bytes in the read buffer
			return true;
		}
	}
1122691
public byte[] readLine(int offset) throws IOException {
		int lastIndex = -1;
		int localOffset = offset;
		int read;
		do {
			read = ensureBuffer(localOffset, BUFFER_SIZE);
			if (read <= 0) {
				// EOF
				this.pos = this.buffer.length;
				return null;
			}

			// NOT EOF, search for end of line
			final int end = localOffset + read;
			for (int idx = localOffset; (lastIndex == -1) && (idx < this.buffer.length) && (idx < end); ++idx) {
				if ((this.buffer[idx] == '\n') || (this.buffer[idx] == '\r')) {
					lastIndex = idx;
				}
			}
			localOffset += read;
		}
		while (lastIndex == -1);
		this.pos = lastIndex;
		return Arrays.copyOfRange(this.buffer, offset, lastIndex);
	}
1348718
public long lastIndex() {
    assertSegmentOpen();
    return !isEmpty() ? offsetIndex.lastOffset() + descriptor.index() + skip : descriptor.index() - 1;
  }