/*
 * Copyright (C) 1997-2002, Michael Jennings
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to
 * deal in the Software without restriction, including without limitation the
 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
 * sell copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies of the Software, its documentation and marketing & publicity
 * materials, and acknowledgment shall be given in the documentation, materials
 * and software packages that this Software was used.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
 * THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
 * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */

#ifndef _LIBAST_TYPES_H_
#define _LIBAST_TYPES_H_

/* Macros to construct object types from the basenames of the types (obj, str, etc.) */
#define SPIF_TYPE(type)                  spif_ ## type ## _t
#define SPIF_CONST_TYPE(type)            spif_const_ ## type ## _t

/* Macros to allocate and deallocate memory for an object.  For use only in
   object constructors/destructors, not in end-user programs. */
#define SPIF_ALLOC(type)                 SPIF_CAST(type) MALLOC(SPIF_SIZEOF_TYPE(type))
#define SPIF_DEALLOC(obj)                FREE(obj)

/* Macros for specifying the classname variables for each class type.  Each subclass of
   spif_obj_t must define this variable using these macros. */
#define SPIF_DECL_CLASSNAME(type)        "!spif_" #type "_t!"

/* Typecast macros */
#define SPIF_CAST_C(type)                (type)
#define SPIF_CONST_CAST_C(type)          (const type)
#define SPIF_CAST(type)                  (SPIF_TYPE(type))
#define SPIF_CONST_CAST(type)            (const SPIF_TYPE(type))
#define SPIF_CAST_PTR(type)              (SPIF_TYPE(type) *)
#define SPIF_CONST_CAST_PTR(type)        (const SPIF_TYPE(type) *)

/* Cast the NULL pointer to a particular object type. */
#define SPIF_NULL_TYPE(type)             (SPIF_CAST(type) (NULL))
#define SPIF_NULL_CTYPE(type)            (SPIF_CAST_C(type) (NULL))

/* Converts a type (such as "obj") to a string denoting a NULL object of that type. */
#define SPIF_NULLSTR_TYPE(type)          "{ ((spif_" #type "_t) NULL) }"
#define SPIF_NULLSTR_CTYPE(type)         "{ ((" #type ") NULL) }"

/* Our own version of the sizeof() operator since objects are actually pointers. */
#define SPIF_SIZEOF_TYPE(type)           (sizeof(SPIF_CONST_TYPE(type)))

/* Make typedef's easier. */
#define SPIF_DEFINE_TYPE(t, u) \
typedef u SPIF_CONST_TYPE(t); \
typedef SPIF_CONST_TYPE(t) * SPIF_TYPE(t)

/* Integer types that are guaranteed to be there and to work...more or less. :) */
typedef signed   char  spif_int8_t;
typedef unsigned char  spif_uint8_t;
typedef signed   short spif_int16_t;
typedef unsigned short spif_uint16_t;
typedef signed   int spif_int32_t;
typedef unsigned int spif_uint32_t;
typedef signed   long long spif_int64_t;
typedef unsigned long long spif_uint64_t;

typedef signed char spif_char_t;
typedef signed short spif_short_t;
typedef signed int spif_int_t;
typedef signed long spif_long_t;
typedef unsigned char spif_uchar_t;
typedef unsigned short spif_ushort_t;
typedef unsigned int spif_uint_t;
typedef unsigned long spif_ulong_t;

/* Char pointer that enforces signedness of char type */
typedef spif_char_t *spif_charptr_t;

/* Socket types */
SPIF_DEFINE_TYPE(sockaddr, struct sockaddr);
SPIF_DEFINE_TYPE(ipsockaddr, struct sockaddr_in);
SPIF_DEFINE_TYPE(unixsockaddr, struct sockaddr_un);
SPIF_DEFINE_TYPE(ipaddr, struct in_addr);
SPIF_DEFINE_TYPE(hostinfo, struct hostent);
SPIF_DEFINE_TYPE(protoinfo, struct protoent);
SPIF_DEFINE_TYPE(servinfo, struct servent);
typedef int spif_sockfd_t;
typedef int spif_sockfamily_t;
typedef int spif_socktype_t;
typedef int spif_sockproto_t;
typedef spif_uint16_t spif_sockport_t;
typedef socklen_t spif_sockaddr_len_t;

/* Type for object comparisons */
typedef enum {
  SPIF_CMP_LESS = -1,
  SPIF_CMP_EQUAL = 0,
  SPIF_CMP_GREATER = 1
} spif_cmp_t;
#define SPIF_CMP_FROM_INT(i)      (((i) < 0) ? (SPIF_CMP_LESS) : (((i) > 0) ? (SPIF_CMP_GREATER) : (SPIF_CMP_EQUAL)))
#define SPIF_CMP_IS_LESS(cmp)     ((cmp) == SPIF_CMP_LESS)
#define SPIF_CMP_IS_EQUAL(cmp)    ((cmp) == SPIF_CMP_EQUAL)
#define SPIF_CMP_IS_GREATER(cmp)  ((cmp) == SPIF_CMP_GREATER)

#undef false
#undef False
#undef FALSE
#undef true
#undef True
#undef TRUE

typedef enum {
#ifndef __cplusplus
  false = 0,
#endif
  False = 0,
  FALSE = 0,
#ifndef __cplusplus
  true = 1,
#endif
  True = 1,
  TRUE = 1
} spif_bool_t;

/* Generic pointer */
typedef void *spif_ptr_t;
/* Generic function pointer */
typedef spif_ptr_t (*spif_fptr_t)(spif_ptr_t, ...);
#endif /* _LIBAST_TYPES_H_ */
