#ifndef _JAMJAR_H
#define _JAMJAR_H

/*
** $Id: jamjar.h,v 1.7 2003/01/21 08:39:00 gray Exp $
*/

/*
** The version number used for this jamjar.
*/

#define VERSION "0.7.1"

/*
** Doubly linked list manipulation functions. They require a sentinel
** element to be available, but reduce the checking and special cases
** that need to be handled.
*/

#define list_remove(x) {                               \
  (x)->previous->next = (x)->next;                     \
  (x)->next->previous = (x)->previous;                 \
}

#define list_insert(f, x) {                            \
  (x)->next = (f);                                     \
  (x)->previous = (f)->previous;                       \
  (f)->previous->next = (x);                           \
  (f)->previous = (x);                                 \
}

#define list_init(f) {                                 \
  (f)->next = (f);                                     \
  (f)->previous = (f);                                 \
}

#define list_break(l, f) {                             \
  (f) = (l)->next;                                     \
  (l)->next->previous = NULL;                          \
  (l)->previous->next = NULL;                          \
}

/*
** Macros for flag manipulation.
*/

#define isSet(x, flag)              ((x) & (flag))
#define isNotSet(x, flag)           (!isSet((x), (flag)))
#define setFlag(x, flag)            ((x) |= (flag))
#define unsetFlag(x, flag)          ((x) &= ~(flag))

/*
** jamjar structure references.
*/

typedef struct j_Res * j_res;
typedef struct j_Entry * j_entry;
typedef struct j_Zip * j_zip;
typedef struct j_Class * j_class;
typedef struct j_Arg * j_arg;

typedef unsigned int j_flags;
typedef unsigned char j_byte;
typedef unsigned int j_crc;
typedef unsigned int j_size;
typedef unsigned short j_dosdate;
typedef unsigned short j_dostime;
typedef struct j_Options * j_options;
typedef struct j_Out * j_out;

/*
** Ancillary structure for writing zip files.
*/

typedef struct j_Out {
  size_t offset;
  size_t dir_size;
  size_t count;
} j_Out;

typedef struct j_Options {
  j_arg jar;                    // The argument of the output jarfile, is NULL for stdout output
  int out;                      // Output file descriptor
  j_arg manifest;               // The manifest file of the argument line, can be NULL
  size_t verbosity;             // Level of verbosity
  j_flags flags;                // Flags, see OPT_xxxxxx flags below
  j_arg args;                   // Expanded list of processed command line files
  char * version;               // Version of jamjar
} j_Options;

extern j_options options;

#define OPT_INDEX     0x00000001 // An index must be made
#define OPT_LIST      0x00000002 // A list must be produced
#define OPT_CREATE    0x00000004 // Jarfile must be created
#define OPT_UPDATE    0x00000008 // Jarfile must be updated
#define OPT_EXTRACT   0x00000010 // All jarfile components must be extracted
#define OPT_NO_MAN    0x00000020 // Don't create a manifest file
#define OPT_STORE     0x00000040 // Don't compress, store only
#define OPT_CU        0x00000080 // Update when jarfile exists, otherwise create, like the 'ar cu' options
#define OPT_ARG_MAN   0x00000100 // Manifest file is passed as argument
#define OPT_STDOUT    0x00000200 // Output is standard output
#define OPT_STOREJARS 0x00000400 // When a jar that is to be taken in the output is allready compressed, don't recompress

/*
** The mode flags for reading a jar file.
*/

#define OUTPUT_JAR   1
#define LIST_JAR     2

#ifdef DEBUG
#define jj_calloc(n, s) _jj_calloc(__FILE__, __LINE__, n, s)
void * _jj_calloc(const char *f, size_t l ,size_t num, size_t size);
#define jj_realloc(b, s) _jj_realloc(__FILE__, __LINE__, b, s)
void * _jj_realloc(const char *f, size_t l, void * block, size_t size);
#define jj_free(b) _jj_free(__FILE__, __LINE__, b)
void _jj_free(const char *f, size_t l, void * block);
void jj_check(void);
#else
#define jj_calloc(n, s)      calloc(n, s)
#define jj_realloc(b, s)     realloc(b, s)
#define jj_free(b)           free(b)
inline static void jj_check(void) { }
#endif

void * z_calloc(void * x, size_t num, size_t size);
void z_free(void * x, void * block);

void logmsg(int level, const char * format, ...);

#endif /* _JAMJAR_H */
