// natDeflater.cc - Implementation of Deflater native methods.

/* Copyright (C) 1999, 2002  Free Software Foundation

   This file is part of libgcj.

This software is copyrighted work licensed under the terms of the
Libgcj License.  Please consult the file "LIBGCJ_LICENSE" for
details.  */

// Written by Tom Tromey <tromey@cygnus.com>

#include <config.h>

#include <zlib.h>
#include <stdlib.h>

#include <gcj/cni.h>
#include <jvm.h>

#include <java/util/zip/Deflater.h>
#include <java/util/zip/DataFormatException.h>

#include <java/lang/InternalError.h>
#include <java/lang/NullPointerException.h>
#include <java/lang/ArrayIndexOutOfBoundsException.h>

extern void *_Jv_ZMalloc (void *, uInt nitems, uInt size);
extern void _Jv_ZFree (void *, void *addr);



jint
java::util::zip::Deflater::deflate (jbyteArray buf, jint off, jint len)
{
  JvSynchronize sync (this);
  z_streamp s = (z_streamp) zstream;

  if (! buf)
    throw new java::lang::NullPointerException;
  if (off < 0 || len < 0 || off + len > buf->length)
    throw new java::lang::ArrayIndexOutOfBoundsException;

  if (len == 0)
    return 0;

  s->next_out = (Bytef *) (elements (buf) + off);
  s->avail_out = len;

  switch (::deflate (s, flush_flag))
    {
    case Z_STREAM_END:
      is_finished = true;
      if (s->avail_out == (unsigned int) len)
	return -1;
      break;

    case Z_STREAM_ERROR:
    case Z_BUF_ERROR:
      // FIXME?
      throw new java::lang::InternalError;
      break;

    case Z_OK:
      break;
    }

  return len - s->avail_out;
}

void
java::util::zip::Deflater::end ()
{
  JvSynchronize sync (this);
  // Just ignore errors.
  deflateEnd ((z_streamp) zstream);
  _Jv_Free (zstream);
  zstream = NULL;
}

void
java::util::zip::Deflater::finish ()
{
  JvSynchronize sync (this);
  flush_flag = Z_FINISH;
}

jint
java::util::zip::Deflater::getAdler ()
{
  JvSynchronize sync (this);
  z_streamp s = (z_streamp) zstream;
  return s->adler;
}

jint
java::util::zip::Deflater::getTotalIn ()
{
  JvSynchronize sync (this);
  z_streamp s = (z_streamp) zstream;
  return s->total_in;
}

jint
java::util::zip::Deflater::getTotalOut ()
{
  JvSynchronize sync (this);
  z_streamp s = (z_streamp) zstream;
  return s->total_out;
}

jboolean
java::util::zip::Deflater::needsInput ()
{
  JvSynchronize sync (this);
  z_streamp s = (z_streamp) zstream;
  return s->avail_in == 0;
}

void
java::util::zip::Deflater::reset ()
{
  JvSynchronize sync (this);
  z_streamp s = (z_streamp) zstream;
  // Just ignore errors.
  deflateReset (s);
  s->avail_in = 0;
  flush_flag = 0;
  is_finished = false;
}

void
java::util::zip::Deflater::setDictionary (jbyteArray buf, jint off, jint len)
{
  JvSynchronize sync (this);
  z_streamp s = (z_streamp) zstream;

  if (! buf)
    throw new java::lang::NullPointerException;
  if (off < 0 || len < 0 || off + len > buf->length)
    throw new java::lang::ArrayIndexOutOfBoundsException;

  // Ignore errors.
  deflateSetDictionary (s, (Bytef *) (elements (buf) + off), len);
}

void
java::util::zip::Deflater::setInput (jbyteArray buf, jint off, jint len)
{
  JvSynchronize sync (this);
  z_streamp s = (z_streamp) zstream;

  if (! buf)
    throw new java::lang::NullPointerException;
  if (off < 0 || len < 0 || off + len > buf->length)
    throw new java::lang::ArrayIndexOutOfBoundsException;

  s->next_in = (Bytef *) (elements (buf) + off);
  s->avail_in = len;
}

void
java::util::zip::Deflater::update ()
{
  JvSynchronize sync (this);
  z_streamp s = (z_streamp) zstream;

  int strat = Z_DEFAULT_STRATEGY;
  switch (strategy)
    {
    case DEFAULT_STRATEGY:
      strat = Z_DEFAULT_STRATEGY;
      break;
    case FILTERED:
      strat = Z_FILTERED;
      break;
    case HUFFMAN_ONLY:
      strat = Z_HUFFMAN_ONLY;
      break;
    default:
      JvFail ("unexpected strategy");
    }

  // Ignore errors.
  deflateParams (s, level, strat);
}

void
java::util::zip::Deflater::init (jint level, jboolean no_header)
{
  z_stream_s *stream = (z_stream_s *) _Jv_Malloc (sizeof (z_stream_s));
  stream->next_in = Z_NULL;
  stream->avail_in = 0;
  stream->zalloc = _Jv_ZMalloc;
  stream->zfree = _Jv_ZFree;
  stream->opaque = NULL;

  // Handle NO_HEADER using undocumented zlib feature.
  int wbits = MAX_WBITS;
  if (no_header)
    wbits = - wbits;

#define DEFAULT_MEM_LEVEL 8
  if (deflateInit2 (stream, level, Z_DEFLATED, wbits,
		    DEFAULT_MEM_LEVEL, Z_DEFAULT_STRATEGY) != Z_OK)
    {
      jstring msg = NULL;
      if (stream->msg != NULL)
	msg = JvNewStringLatin1 (stream->msg);
      throw new java::lang::InternalError (msg);
    }

  zstream = reinterpret_cast<gnu::gcj::RawData *> (stream);
  is_finished = false;
  flush_flag = 0;
}
