/**
   * read 1.5 compression stream ref table
   *
   * @throws PdfException
   */
  private PdfObject readCompressedStream(
      PdfObject rootObj,
      int pointer,
      final PdfFileReader currentPdfFile,
      final ObjectReader objectReader,
      final PdfObject linearObj)
      throws PdfException {

    while (pointer != -1) {

      /** get values to read stream ref */
      movePointer(pointer);

      final byte[] raw = objectReader.readObjectData(-1, null);

      /** read the object name from the start */
      final StringBuilder objectName = new StringBuilder();
      char current1, last = ' ';
      int matched = 0, i1 = 0;
      while (i1 < raw.length) {
        current1 = (char) raw[i1];

        // treat returns same as spaces
        if (current1 == 10 || current1 == 13) {
          current1 = ' ';
        }

        if (current1 == ' ' && last == ' ') { // lose duplicate or spaces
          matched = 0;
        } else if (current1 == pattern.charAt(matched)) { // looking for obj at end
          matched++;
        } else {
          matched = 0;
          objectName.append(current1);
        }
        if (matched == 3) {
          break;
        }
        last = current1;
        i1++;
      }

      // add end and put into Map
      objectName.append('R');

      final PdfObject pdfObject = new CompressedObject(objectName.toString());
      pdfObject.setCompressedStream(true);
      final ObjectDecoder objectDecoder = new ObjectDecoder(currentPdfFile);
      objectDecoder.readDictionaryAsObject(pdfObject, 0, raw);

      // read the field sizes
      final int[] fieldSizes = pdfObject.getIntArray(PdfDictionary.W);

      // read the xrefs stream
      byte[] xrefs = pdfObject.getDecodedStream();

      // if encr
      if (xrefs == null) {
        xrefs = currentPdfFile.readStream(pdfObject, true, true, false, false, true, null);
      }

      final int[] Index = pdfObject.getIntArray(PdfDictionary.Index);
      if (Index == null) { // single set of values

        // System.out.println("-------------1.Offsets-------------"+current+" "+numbEntries);
        CompressedObjects.readCompressedOffsets(
            0, 0, pdfObject.getInt(PdfDictionary.Size), fieldSizes, xrefs, offset, pdf_datafile);

      } else { // pairs of values in Index[] array
        final int count = Index.length;
        int pntr = 0;

        for (int aa = 0; aa < count; aa += 2) {

          // System.out.println("-------------2.Offsets-------------"+Index[aa]+" "+Index[aa+1]);

          pntr =
              CompressedObjects.readCompressedOffsets(
                  pntr, Index[aa], Index[aa + 1], fieldSizes, xrefs, offset, pdf_datafile);
        }
      }

      /**
       * now process trailer values - only first set of table values for root, encryption and info
       */
      if (rootObj == null) {

        rootObj = pdfObject.getDictionary(PdfDictionary.Root);

        /** handle encryption */
        encryptObj = pdfObject.getDictionary(PdfDictionary.Encrypt);

        if (encryptObj != null) {

          final byte[][] IDs = pdfObject.getStringArray(PdfDictionary.ID);
          if (IDs != null && this.ID == null) {
            // only the first encountered ID should be used as a fileID for decryption
            this.ID = IDs[0];
          }
        }

        infoObject = pdfObject.getDictionary(PdfDictionary.Info);
      }

      // make sure first values used if several tables and code for prev so long as not linearized
      // may need adjusting as more examples turn up
      if (linearObj != null) {
        pointer = -1;
      } else {
        pointer = pdfObject.getInt(PdfDictionary.Prev);

        // a non-compressed object table can follow a compressed one so we need to allow for this
        if (!isCompressedStream(pointer, (int) eof)) {
          return readLegacyReferenceTable(rootObj, pointer, (int) eof, currentPdfFile);
        }
      }
    }

    return rootObj;
  }