/* Copyright (C) 2019-2020  Philipp "ph3-der-loewe" Schafft <lion@lion.leolix.org>
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Library General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Library General Public License for more details.
 *
 * You should have received a copy of the GNU Library General Public
 * License along with this library; if not, write to the
 * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
 * Boston, MA  02110-1301, USA.
 */

#ifndef _LIBIGLOO__PRIVATE_H_
#define _LIBIGLOO__PRIVATE_H_

#ifdef __cplusplus
extern "C" {
#endif

#include <stdbool.h>
#include <pthread.h>

#include <igloo/types.h>
#include <igloo/rwlock.h>

typedef struct {
    const char *start;
    const char *end;
    size_t minlen;
    size_t maxlen;
    size_t objects;
    bool clean;
} igloo_sp_area_t;
typedef struct {
    uint32_t refc;
    char str[16]; // should be a multiple of sizeof(refc)
} igloo_sp_state_buffer_small_t;
typedef struct {
    igloo_rwlock_t lock;
    igloo_sp_state_buffer_small_t small_strings[256];
    igloo_sp_area_t const_area;
    igloo_sp_area_t small_area;
    igloo_sp_area_t fallback_area;
    igloo_sp_area_t *areas[3];
} igloo_sp_state_t;

typedef char igloo_digest_512_t[512/8];
typedef struct {
    uint64_t state;
    uint64_t flags;
    size_t bits;
    size_t overcommitment;
    size_t callcount;
    pthread_mutex_t lock;
    igloo_digest_512_t initial;
    igloo_digest_512_t auto_seed0;
    igloo_digest_512_t auto_seed1;
    igloo_digest_512_t manual_seed0;
    igloo_digest_512_t manual_seed1;
    igloo_digest_512_t last_result;
} igloo_prng_state_t;

extern const igloo_ro_type_t * igloo_instance_type;

igloo_error_t igloo_ro_bootstrap(igloo_ro_t *instance, const igloo_ro_type_t *type);
igloo_ro_t igloo_ro_get_instance_unsafe(igloo_ro_t self, const igloo_ro_type_t *type);
igloo_sp_state_t *igloo_instance_get_stringpool_state(igloo_ro_t self);
igloo_prng_state_t *igloo_instance_get_prng_state(igloo_ro_t self, size_t *instancelen);

igloo_error_t   igloo_instance_sp_init(igloo_sp_state_t *state);
void            igloo_instance_sp_destroy(igloo_sp_state_t *state);
igloo_error_t   igloo_instance_sp_stringify(igloo_sp_state_t *state, char *buf, size_t len);

igloo_error_t   igloo_instance_prng_init(igloo_prng_state_t *state);
void            igloo_instance_prng_destroy(igloo_prng_state_t *state);
igloo_error_t   igloo_instance_prng_stringify(igloo_prng_state_t *state, char *buf, size_t len);

#ifdef __cplusplus
}
#endif

#endif /* ! _LIBIGLOO__PRIVATE_H_ */
