FlateStream.cc 3.19 KB
Newer Older
1 2 3 4
//========================================================================
//
// FlateStream.cc
//
5
// Copyright (C) 2005, Jeff Muizelaar <jeff@infidigm.net>
6
// Copyright (C) 2010, Albert Astals Cid <aacid@kde.org>
Albert Astals Cid's avatar
Albert Astals Cid committed
7
// Copyright (C) 2016, William Bader <williambader@hotmail.com>
8
// Copyright (C) 2017, Adrian Johnson <ajohnson@redneon.com>
9
//
10 11
// This file is under the GPLv2 or later license
//
12
//========================================================================
13 14 15 16 17 18 19 20 21

#include <config.h>

#ifdef USE_GCC_PRAGMAS
#pragma implementation
#endif

#include "poppler-config.h"

22
#ifdef ENABLE_ZLIB_UNCOMPRESS
23

24
#include "FlateStream.h"
25

26 27 28 29 30 31 32 33 34 35
FlateStream::FlateStream(Stream *strA, int predictor, int columns, int colors, int bits) :
  FilterStream(strA)
{
  if (predictor != 1) {
    pred = new StreamPredictor(this, predictor, columns, colors, bits);
  } else {
    pred = NULL;
  }
  out_pos = 0;
  memset(&d_stream, 0, sizeof(d_stream));
36
  inflateInit(&d_stream);
37 38 39 40
}

FlateStream::~FlateStream() {
  inflateEnd(&d_stream);
41
  delete pred;
42 43 44 45 46 47
  delete str;
}

void FlateStream::reset() {
  //FIXME: what are the semantics of reset?
  //i.e. how much intialization has to happen in the constructor?
48 49 50

  /* reinitialize zlib */
  inflateEnd(&d_stream);
51 52
  memset(&d_stream, 0, sizeof(d_stream));
  inflateInit(&d_stream);
53 54

  str->reset();
55 56 57 58 59 60 61
  d_stream.avail_in = 0;
  status = Z_OK;
  out_pos = 0;
  out_buf_len = 0;
}

int FlateStream::getRawChar() {
62 63
  return doGetRawChar();
}
64

65 66 67
void FlateStream::getRawChars(int nChars, int *buffer) {
  for (int i = 0; i < nChars; ++i)
    buffer[i] = doGetRawChar();
68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87
}

int FlateStream::getChar() {
  if (pred)
    return pred->getChar();
  else
    return getRawChar();
}

int FlateStream::lookChar() {
  if (pred)
    return pred->lookChar();

  if (fill_buffer())
    return EOF;

  return out_buf[out_pos];
}

int FlateStream::fill_buffer() {
88
  /* only fill the buffer if it has all been used */
89
  if (out_pos >= out_buf_len) {
90
    /* check if the flatestream has been exhausted */
91 92 93
    if (status == Z_STREAM_END) {
      return -1;
    }
94 95

    /* set to the begining of out_buf */
96 97 98
    d_stream.avail_out = sizeof(out_buf);
    d_stream.next_out = out_buf;
    out_pos = 0;
99 100 101 102 103 104 105 106 107 108

    while (1) {
      /* buffer is empty so we need to fill it */
      if (d_stream.avail_in == 0) {
	int c;
	/* read from the source stream */
	while (d_stream.avail_in < sizeof(in_buf) && (c = str->getChar()) != EOF) {
	  in_buf[d_stream.avail_in++] = c;
	}
	d_stream.next_in = in_buf;
109
      }
110 111 112 113

      /* keep decompressing until we can't anymore */
      if (d_stream.avail_out == 0 || d_stream.avail_in == 0 || (status != Z_OK && status != Z_BUF_ERROR))
	break;
114 115
      status = inflate(&d_stream, Z_SYNC_FLUSH);
    }
116

117 118 119 120 121 122 123 124 125 126
    out_buf_len = sizeof(out_buf) - d_stream.avail_out;
    if (status != Z_OK && status != Z_STREAM_END)
      return -1;
    if (!out_buf_len)
      return -1;
  }

  return 0;
}

127
GooString *FlateStream::getPSFilter(int psLevel, const char *indent) {
128 129 130 131 132 133 134 135 136 137 138 139 140 141 142
  GooString *s;

  if (psLevel < 3 || pred) {
    return NULL;
  }
  if (!(s = str->getPSFilter(psLevel, indent))) {
    return NULL;
  }
  s->append(indent)->append("<< >> /FlateDecode filter\n");
  return s;
}

GBool FlateStream::isBinary(GBool last) {
  return str->isBinary(gTrue);
}
143 144

#endif