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

/* Copyright (C) 1999, 2002, 2006  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;
}

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

jlong
java::util::zip::Deflater::getBytesWritten ()
{
  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;
}
