private CacheChunk prepareRangesForCompressedRead(long cOffset, long endCOffset,
      long streamOffset, long unlockUntilCOffset, DiskRangeList current,
      ColumnStreamData columnStreamData, IdentityHashMap<ByteBuffer, Boolean> toRelease,
      List<ByteBuffer> toReleaseCopies, List<ProcCacheChunk> toDecompress,
      List<IncompleteCb> badEstimates) throws IOException {
    if (cOffset > current.getOffset()) {
      // Target compression block is in the middle of the range; slice the range in two.
      current = current.split(cOffset).next;
    }
    long currentOffset = cOffset;
    CacheChunk lastUncompressed = null;
    while (true) {
      DiskRangeList next = null;
      if (current instanceof CacheChunk) {
        // 2a. This is a decoded compression buffer, add as is.
        CacheChunk cc = (CacheChunk)current;
        if (isTracingEnabled) {
          LOG.trace("Locking " + cc.getBuffer() + " due to reuse");
        }
        cacheWrapper.reuseBuffer(cc.getBuffer());
        columnStreamData.getCacheBuffers().add(cc.getBuffer());
        currentOffset = cc.getEnd();
        if (isTracingEnabled) {
          LOG.trace("Adding an already-uncompressed buffer " + cc.getBuffer());
        }
        ponderReleaseInitialRefcount(unlockUntilCOffset, streamOffset, cc);
        lastUncompressed = cc;
        next = current.next;
        if (next != null && (endCOffset >= 0 && currentOffset < endCOffset)
            && next.getOffset() >= endCOffset) {
          throw new IOException("Expected data at " + currentOffset + " (reading until "
            + endCOffset + "), but the next buffer starts at " + next.getOffset());
        }
      } else if (current instanceof IncompleteCb)  {
        // 2b. This is a known incomplete CB caused by ORC CB end boundaries being estimates.
        if (isTracingEnabled) {
          LOG.trace("Cannot read " + current);
        }
        next = null;
        currentOffset = -1;
      } else {
        // 2c. This is a compressed buffer. We need to uncompress it; the buffer can comprise
        // several disk ranges, so we might need to combine them.
        if (!(current instanceof BufferChunk)) {
          String msg = "Found an unexpected " + current.getClass().getSimpleName() + ": "
              + current + " while looking at " + currentOffset;
          LOG.error(msg);
          throw new RuntimeException(msg);
        }
        BufferChunk bc = (BufferChunk)current;
        ProcCacheChunk newCached = addOneCompressionBuffer(bc, columnStreamData.getCacheBuffers(),
            toDecompress, toRelease, toReleaseCopies, badEstimates);
        lastUncompressed = (newCached == null) ? lastUncompressed : newCached;
        next = (newCached != null) ? newCached.next : null;
        currentOffset = (next != null) ? next.getOffset() : -1;
      }

      if (next == null || (endCOffset >= 0 && currentOffset >= endCOffset)) {
        break;
      }
      current = next;
    }
    return lastUncompressed;
  }
Subset of readEncodedStream specific to compressed streams, separate to avoid long methods.
ql/src/java/org/apache/hadoop/hive/ql/io/orc/encoded/EncodedReaderImpl.java