/*
 * This file is part of the Poliqarp suite.
 * 
 * Copyright (C) 2004-2009 by Instytut Podstaw Informatyki Polskiej
 * Akademii Nauk (IPI PAN; Institute of Computer Science, Polish
 * Academy of Sciences; cf. www.ipipan.waw.pl).  All rights reserved.
 * 
 * This file may be distributed and/or modified under the terms of the
 * GNU General Public License version 2 as published by the Free Software
 * Foundation and appearing in the file gpl.txt included in the packaging
 * of this file.  (See http://www.gnu.org/licenses/translations.html for
 * unofficial translations.)
 * 
 * A commercial license is available from IPI PAN (contact
 * Michal.Ciesiolka@ipipan.waw.pl or ipi@ipipan.waw.pl for more
 * information).  Licensees holding a valid commercial license from IPI
 * PAN may use this file in accordance with that license.
 * 
 * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING
 * THE WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE.
 */

#ifndef BPNG_BINARY_POOL_H
#define BPNG_BINARY_POOL_H 1

#include <poliqarp-config.h>

#include <stdlib.h>
#include <stdint.h>
#include <stdio.h>

typedef int (*binary_pool_node_cmp_fn)(const void *, const void *);

struct binary_pool_node {
   size_t id; /**< unique identifier */
   uint32_t count; /**< frequency count */
   uint32_t length; /**< data length */
   void *data; /**< data pointer */
};

struct binary_pool_chain {
   struct binary_pool_node node;
   struct binary_pool_chain *next;
};

struct binary_pool {
   struct binary_pool_chain *hash_array; /**< chained hash array */
   size_t array_size; /**< array size */
   size_t count; /**< number of unique items */
   struct binary_pool_node *dense_array; /**< dense array */
   uint32_t *index; /**< little-endian array of indices */
   uint32_t *offset; /**< little-endian array of offsets */
   /* data + offset[index[key]] == object */
   struct binary_pool_chain *last; /**< cached last object */
   struct marena arena; /**< memory source */
};

/** Compare nodes by their reversed frequency. */
int binary_pool_compare_freq(const void *, const void *);

/** Compare text nodes. */
int binary_pool_compare_alpha(const void *, const void *);

/** Compare text nodes, case insensitively. */
int binary_pool_compare_ialpha(const void *, const void *);

/** Compare text nodes, atergo. */
int binary_pool_compare_atergo(const void *, const void *);

/** Compare text nodes, case-insensitively, atergo. */
int binary_pool_compare_iatergo(const void *, const void *);

/** Initialize pool structures. */
void binary_pool_create(struct binary_pool *, size_t size);

/** Free pool structures. */
void binary_pool_destroy(struct binary_pool *);

/** Add all items from the dictionary to the pool. */
void binary_pool_add_dict(struct binary_pool *, const char *image_path,
   const char *offset_path);

/** Add the binary object to the pool. */
struct binary_pool_node *binary_pool_add(struct binary_pool *,
   const void *buffer, size_t length);

/** Add the binary object to the pool. */
struct binary_pool_node *binary_pool_add_freq(struct binary_pool *,
   const void *buffer, size_t length, size_t freq);

/** Add the string to the pool. */
struct binary_pool_node *binary_pool_add_string_n(struct binary_pool *,
   const char *, size_t length);

/** Add the null-terminated string to the pool. */
struct binary_pool_node *binary_pool_add_string(struct binary_pool *,
   const char *);

/** Find the object in the pool. */
struct binary_pool_node *binary_pool_lookup(struct binary_pool *,
   const void *buffer, size_t length);

/** Find the string in the pool. */
struct binary_pool_node *binary_pool_lookup_string_n(struct binary_pool *,
   const char *buffer, size_t length);

/** Find the null-terminated string in the pool. */
struct binary_pool_node *binary_pool_lookup_string(struct binary_pool *,
   const char *string);

/** Create a dense array of the pool nodes. */
void binary_pool_make_dense_array(struct binary_pool *);

/** Sort the pool data according to th given comparator. */
void binary_pool_sort_data(struct binary_pool *, binary_pool_node_cmp_fn cmp);

/** Sort the pool index according to the given comparator. */
void binary_pool_sort_index(struct binary_pool *, binary_pool_node_cmp_fn cmp);

/** Write the pool index to the stream. */
void binary_pool_write_index(struct binary_pool *, FILE *stream);

/** Write the pool data/offsets to the stream. */
void binary_pool_write_data(struct binary_pool *, FILE *stream);

/** Write the pool offsets to the stream. */
void binary_pool_write_offsets(struct binary_pool *, FILE *stream);

#endif /* BPNG_BINARY_POOL_H */
