#include <stdio.h>

#include "index.h"
#include "misc.h"

#ifdef __GNUC__
#define INLINE __inline__
#else
#define INLINE
#endif

typedef unsigned short Bn;

typedef struct {
  unsigned u;
  char c[1];
} W;

typedef struct {
  void *d;
  const char *n;
} Hash;

typedef struct {
  const void *v;
  unsigned w;
} Gen;

typedef struct {
  unsigned value:27;
  unsigned bits:5;
} Code;

typedef struct {
  unsigned bit:5;
  unsigned byte:10;
  unsigned h:1;
  unsigned bn:16;
} Offset;

typedef struct {
  Bn last,total;
} Bnl;

typedef union {
  Bnl l;
  Offset o;
  Code c;
  unsigned u;
} Data;
  
typedef struct {
  Data code,off;
} Datum;

typedef struct {
  unsigned nw,nc,nt,ms,mm;
} Hash_totals;

/* typedef struct { */
/*   float w; */
/*   char l[2]; */
/*   void *n[2]; */
/* } Huff; */

typedef struct {
  unsigned v[2];
} Huff;

typedef struct {
  Hash   d;      /* word -> code and b offset */
  Map    b;      /* z Block index for words */
  Map    h;      /* Huffman tree, code -> word */
  void *he;
/*   Huff *h1,*he;   */
/*   char *w1,*we;   */
} Words;  

typedef struct {
  Data off;  /* z offset */
  char *n;   /* file name */
} File;

typedef struct {
  Hash d;     /* Name -> z Offset */
  Map  n;     /* Name list */
  Map  p;     /* Sorted File structure list, offset -> name */
} Files; 

typedef struct {
  Map   z; /* Compressed text */
  Words w; /* Word lookup */
  Files f; /* File lookup */
} Dict;

/* hash.c */

extern INLINE int
hash_open(Hash *,const char *,int);

extern INLINE Datum *
hash_get(Hash *,const Gen *);

extern INLINE Datum *
hash_seq(Hash *,Gen *);

extern INLINE int
hash_put(Hash *,const Gen *,Datum *);

extern INLINE int
hash_close(Hash *);

extern INLINE int
hash_sync(Hash *);

extern INLINE int
hash_perf(Hash *,unsigned);

extern INLINE Hash_totals *
hash_get_totals(Hash *);

extern INLINE int
hash_put_totals(Hash *,Hash_totals *);

extern INLINE int
hash_opt(Hash *);

/* huff.c */

extern INLINE int
huff_build_from_freq(Words *);

extern INLINE int
huff_build_from_codes(Words *);

extern INLINE int
huff_load_codes(Words *);

extern INLINE int
huff_test(Words *);

extern INLINE W *
huff_decode(Huff *,Huff *,unsigned **,unsigned *,unsigned *,unsigned);

/* parse.c */

extern INLINE int
str_to_token(Map *,Gen *);

extern INLINE void
token_to_str(const W *,Map *);

/* dict.c */

extern INLINE int
dict_close(Dict *);

extern INLINE int
dict_open(Dict *,const char *,int);

/* z.c */

extern INLINE int
z_open(Map *,const char *,int);

extern INLINE int
z_close(Map *);

extern INLINE int
z_encode_files(Dict *);

extern INLINE int
z_file_decode(Dict *,Bn,unsigned,Map *,Map *);

/* files.c */

extern INLINE int
files_open(Files *,const char *,const char *,int);

extern INLINE int
files_close(Files *);

extern INLINE const File *
files_get_by_offset(Files *,Offset);

/* words.c */

extern INLINE int
words_close(Words *);

extern INLINE int
words_open(Words *,const char *,int);

extern INLINE int
words_build_wordlist(Files *,Words *);

/* util.c */

extern INLINE void *
bsearch1(const void *,const void *,size_t,size_t,
	 int (*)(const void *,const void *),int *);

/*  #define err ierr */

/*  int  */
/*  ierr(const char *,...); */
