/* UPE library
 * (c)2000 Stepan Roh
 * see license.txt for copying
 */
 
#ifndef UPE_H
#define UPE_H

#include "upe_config.h"

#ifdef UPE_BYTE_SIZE_AS_VAR
extern upe_u32_t upe_byte_size;
#else
#ifndef upe_byte_size
#define upe_byte_size 8
#endif
#endif

/* sign types - unused */
typedef enum {
  UPE_NO_SIGN,
  UPE_COMPLEMENT_2,
  UPE_SIGN_BIT,
} upe_sign_type;

/* variable-size (max. 2^32 bits) integer
 * variable-sized means variable at creation not after it */
typedef struct upe_number_t {
  upe_u32_t size;		/* number of bits */
  upe_u32_t *val_ptr;		/* allocated space in upe_bytes (upe_u32_t) */
  int sign;			/* signed ? - unused */
  upe_sign_type sign_type;	/* sign type - unused */
} upe_number_t;

/* byte order mapping for loading/storing from/to memory */
extern upe_u32_t **upe_byte_order;

/* byte order mapping length */
extern int upe_byte_order_len;

/* number of bytes to store given number of bits */
#define UPE_NUM_OF_BYTES(bits,bits_in_byte)	(((bits)/(bits_in_byte))+(((bits)%(bits_in_byte)) ? 1 : 0))

upe_number_t *upe_initnum (upe_u32_t bits, int sign, upe_sign_type sign_type);
void upe_donenum (upe_number_t *num);
upe_number_t *upe_setnum (upe_number_t *num, int inum);
int upe_getnum (upe_number_t *num);
upe_number_t *upe_strtonum (upe_number_t *num, char *str);
upe_number_t *upe_zeronum (upe_number_t *num);
upe_number_t *upe_addnum (upe_number_t *dest, upe_number_t *src, int *overflow);
upe_number_t *upe_subnum (upe_number_t *dest, upe_number_t *src, int *underflow);
upe_number_t *upe_copynum (upe_number_t *dest, upe_number_t *src);
upe_number_t *upe_dupnum (upe_number_t *src);
upe_number_t *upe_dupnum_range (upe_number_t *src, upe_u32_t bit_from, upe_u32_t bit_to);
int upe_ltnum (upe_number_t *n1, upe_number_t *n2);
int upe_lenum (upe_number_t *n1, upe_number_t *n2);
int upe_eqnum (upe_number_t *n1, upe_number_t *n2);
#define upe_gtnum(n1,n2)\
	(!upe_lenum ((n1), (n2)))
#define upe_genum(n1,n2)\
	(!upe_ltnum ((n1), (n2)))
#define upe_nenum(n1,n2)\
	(!upe_eqnum ((n1), (n2)))
int upe_iszero (upe_number_t *num);
#define upe_isnonzero(num)\
	(!upe_iszero ((num)))
upe_number_t *upe_negnum (upe_number_t *num);
upe_number_t *upe_andnum (upe_number_t *dest, upe_number_t *src);
upe_number_t *upe_ornum (upe_number_t *dest, upe_number_t *src);
upe_number_t *upe_bitnegnum (upe_number_t *num);
upe_number_t *upe_bitandnum (upe_number_t *dest, upe_number_t *src);
upe_number_t *upe_bitornum (upe_number_t *dest, upe_number_t *src);
upe_number_t *upe_bitxornum (upe_number_t *dest, upe_number_t *src);
upe_number_t *upe_shlnum (upe_number_t *dest, upe_u32_t num);
upe_number_t *upe_shrnum (upe_number_t *dest, upe_u32_t num);
upe_number_t *upe_incnum (upe_number_t *num, int *overflow);
upe_number_t *upe_decnum (upe_number_t *num, int *underflow);

int upe_add_byte_order (char *order);

typedef struct upe_mem_t upe_mem_t;
typedef int (*upe_read_mem_fn) (upe_mem_t *, int, upe_number_t *, upe_u32_t, upe_number_t **);
typedef int (*upe_write_mem_fn) (upe_mem_t *, int, upe_number_t *, upe_number_t *);

upe_mem_t *upe_create_mem (int pools);
void upe_destroy_mem (upe_mem_t *mem);
int upe_map_mem (upe_mem_t *mem, int pool, upe_number_t *from, upe_number_t *to, unsigned char *adr, int read_access, upe_read_mem_fn read_fn, int write_access, upe_write_mem_fn write_fn);
int upe_read_mem (upe_mem_t *mem, int pool, upe_number_t *adr, upe_u32_t bytes, upe_number_t **val);
int upe_write_mem (upe_mem_t *mem, int pool, upe_number_t *adr, upe_number_t *val);

#endif	/* UPE_H */