#include "FEnums"
#include <config.h>
#include <string.h>

using namespace Futile;

extern "C" {
void FC_FUNC_(bind_f90_f_enumerator_copy_constructor, BIND_F90_F_ENUMERATOR_COPY_CONSTRUCTOR)(FEnumerator::f90_f_enumerator_pointer*,
  const FEnumerator::f90_f_enumerator*);
void FC_FUNC_(bind_f90_f_enumerator_type_new, BIND_F90_F_ENUMERATOR_TYPE_NEW)(FEnumerator::f90_f_enumerator_pointer*,
  FEnumerator::f90_f_enumerator_pointer*,
  const int*,
  const char*,
  size_t);
void FC_FUNC_(bind_f90_f_enumerator_free, BIND_F90_F_ENUMERATOR_FREE)(FEnumerator::f90_f_enumerator_pointer*);
void FC_FUNC_(bind_f_enumerator_null, BIND_F_ENUMERATOR_NULL)(FEnumerator::f90_f_enumerator_pointer*);
void FC_FUNC_(bind_nullify_f_enum, BIND_NULLIFY_F_ENUM)(FEnumerator::f90_f_enumerator*);
void FC_FUNC_(bind_f_enum_attr, BIND_F_ENUM_ATTR)(FEnumerator::f90_f_enumerator*,
  FEnumerator::f90_f_enumerator*);
void FC_FUNC_(bind_f_enum_update, BIND_F_ENUM_UPDATE)(FEnumerator::f90_f_enumerator*,
  const FEnumerator::f90_f_enumerator*);
void FC_FUNC_(bind_enum_is_enum, BIND_ENUM_IS_ENUM)(int*,
  const FEnumerator::f90_f_enumerator*,
  const FEnumerator::f90_f_enumerator*);
void FC_FUNC_(bind_enum_is_int, BIND_ENUM_IS_INT)(int*,
  const FEnumerator::f90_f_enumerator*,
  const int*);
void FC_FUNC_(bind_int_is_enum, BIND_INT_IS_ENUM)(int*,
  const int*,
  const FEnumerator::f90_f_enumerator*);
void FC_FUNC_(bind_enum_is_char, BIND_ENUM_IS_CHAR)(int*,
  const FEnumerator::f90_f_enumerator*,
  const char*,
  const size_t*,
  size_t);
void FC_FUNC_(bind_enum_is_not_enum, BIND_ENUM_IS_NOT_ENUM)(int*,
  const FEnumerator::f90_f_enumerator*,
  const FEnumerator::f90_f_enumerator*);
void FC_FUNC_(bind_enum_is_not_int, BIND_ENUM_IS_NOT_INT)(int*,
  const FEnumerator::f90_f_enumerator*,
  const int*);
void FC_FUNC_(bind_enum_is_not_char, BIND_ENUM_IS_NOT_CHAR)(int*,
  const FEnumerator::f90_f_enumerator*,
  const char*,
  const size_t*,
  size_t);
void FC_FUNC_(bind_enum_has_attribute, BIND_ENUM_HAS_ATTRIBUTE)(int*,
  const FEnumerator::f90_f_enumerator*,
  const FEnumerator::f90_f_enumerator*);
void FC_FUNC_(bind_enum_has_char, BIND_ENUM_HAS_CHAR)(int*,
  const FEnumerator::f90_f_enumerator*,
  const char*,
  const size_t*,
  size_t);
void FC_FUNC_(bind_enum_has_int, BIND_ENUM_HAS_INT)(int*,
  const FEnumerator::f90_f_enumerator*,
  const int*);
void FC_FUNC_(bind_enum_get_from_int, BIND_ENUM_GET_FROM_INT)(FEnumerator::f90_f_enumerator_pointer*,
  const FEnumerator::f90_f_enumerator*,
  const int*);
void FC_FUNC_(bind_enum_get_from_char, BIND_ENUM_GET_FROM_CHAR)(FEnumerator::f90_f_enumerator_pointer*,
  const FEnumerator::f90_f_enumerator*,
  const char*,
  const size_t*,
  size_t);
void FC_FUNC_(bind_enum_get_from_enum, BIND_ENUM_GET_FROM_ENUM)(FEnumerator::f90_f_enumerator_pointer*,
  const FEnumerator::f90_f_enumerator*,
  const FEnumerator::f90_f_enumerator*);
void FC_FUNC_(bind_int_enum, BIND_INT_ENUM)(int*,
  const FEnumerator::f90_f_enumerator*);
}

bool Futile::operator ==(int int_bn,
    const FEnumerator& en)
{
  int out_ok;
  FC_FUNC_(bind_int_is_enum, BIND_INT_IS_ENUM)
    (&out_ok, &int_bn, en);
  return out_ok;
}

FEnumerator::FEnumerator(const FEnumerator& other)
{
  FC_FUNC_(bind_f90_f_enumerator_copy_constructor, BIND_F90_F_ENUMERATOR_COPY_CONSTRUCTOR)
    (*this, other);
}

FEnumerator::FEnumerator(FEnumerator (*family),
    const int (*id),
    const char (*name)[64])
{
  size_t name_len = 64, name_chk_len = 64;
  FC_FUNC_(bind_f90_f_enumerator_type_new, BIND_F90_F_ENUMERATOR_TYPE_NEW)
    (*this, family ? (FEnumerator::f90_f_enumerator_pointer*)*family : NULL, id, name ? *name : NULL, name_chk_len);
}

FEnumerator::~FEnumerator(void)
{
  FC_FUNC_(bind_f90_f_enumerator_free, BIND_F90_F_ENUMERATOR_FREE)
    (*this);
}

void FEnumerator::nullify_f_enum(void)
{
  FC_FUNC_(bind_nullify_f_enum, BIND_NULLIFY_F_ENUM)
    (*this);
}

void FEnumerator::f_enum_attr(FEnumerator& attr)
{
  FC_FUNC_(bind_f_enum_attr, BIND_F_ENUM_ATTR)
    (*this, attr);
}

void FEnumerator::f_enum_update(const FEnumerator& src)
{
  FC_FUNC_(bind_f_enum_update, BIND_F_ENUM_UPDATE)
    (*this, src);
}

bool FEnumerator::operator ==(const FEnumerator& en1) const
{
  int out_ok;
  FC_FUNC_(bind_enum_is_enum, BIND_ENUM_IS_ENUM)
    (&out_ok, *this, en1);
  return out_ok;
}

bool FEnumerator::operator ==(int int_bn) const
{
  int out_ok;
  FC_FUNC_(bind_enum_is_int, BIND_ENUM_IS_INT)
    (&out_ok, *this, &int_bn);
  return out_ok;
}

bool FEnumerator::operator ==(const char* char_bn) const
{
  int out_ok;
  size_t char_bn_chk_len, char_bn_len = char_bn_chk_len = char_bn ? strlen(char_bn) : 0;
  FC_FUNC_(bind_enum_is_char, BIND_ENUM_IS_CHAR)
    (&out_ok, *this, char_bn, &char_bn_len, char_bn_chk_len);
  return out_ok;
}

bool FEnumerator::operator !=(const FEnumerator& en1) const
{
  int out_ok;
  FC_FUNC_(bind_enum_is_not_enum, BIND_ENUM_IS_NOT_ENUM)
    (&out_ok, *this, en1);
  return out_ok;
}

bool FEnumerator::operator !=(int int_bn) const
{
  int out_ok;
  FC_FUNC_(bind_enum_is_not_int, BIND_ENUM_IS_NOT_INT)
    (&out_ok, *this, &int_bn);
  return out_ok;
}

bool FEnumerator::operator !=(const char* char_bn) const
{
  int out_ok;
  size_t char_bn_chk_len, char_bn_len = char_bn_chk_len = char_bn ? strlen(char_bn) : 0;
  FC_FUNC_(bind_enum_is_not_char, BIND_ENUM_IS_NOT_CHAR)
    (&out_ok, *this, char_bn, &char_bn_len, char_bn_chk_len);
  return out_ok;
}

bool FEnumerator::enum_has_attribute(const FEnumerator& family) const
{
  int out_ok;
  FC_FUNC_(bind_enum_has_attribute, BIND_ENUM_HAS_ATTRIBUTE)
    (&out_ok, *this, family);
  return out_ok;
}

bool FEnumerator::enum_has_char(const char* family) const
{
  int out_ok;
  size_t family_chk_len, family_len = family_chk_len = family ? strlen(family) : 0;
  FC_FUNC_(bind_enum_has_char, BIND_ENUM_HAS_CHAR)
    (&out_ok, *this, family, &family_len, family_chk_len);
  return out_ok;
}

bool FEnumerator::enum_has_int(int family) const
{
  int out_ok;
  FC_FUNC_(bind_enum_has_int, BIND_ENUM_HAS_INT)
    (&out_ok, *this, &family);
  return out_ok;
}

FEnumerator FEnumerator::enum_get_from_int(int family) const
{
  FEnumerator::f90_f_enumerator_pointer out_iter;
  FC_FUNC_(bind_enum_get_from_int, BIND_ENUM_GET_FROM_INT)
    (&out_iter, *this, &family);
  return FEnumerator(out_iter);
}

FEnumerator FEnumerator::enum_get_from_char(const char* family) const
{
  FEnumerator::f90_f_enumerator_pointer out_iter;
  size_t family_chk_len, family_len = family_chk_len = family ? strlen(family) : 0;
  FC_FUNC_(bind_enum_get_from_char, BIND_ENUM_GET_FROM_CHAR)
    (&out_iter, *this, family, &family_len, family_chk_len);
  return FEnumerator(out_iter);
}

FEnumerator FEnumerator::enum_get_from_enum(const FEnumerator& family) const
{
  FEnumerator::f90_f_enumerator_pointer out_iter;
  FC_FUNC_(bind_enum_get_from_enum, BIND_ENUM_GET_FROM_ENUM)
    (&out_iter, *this, family);
  return FEnumerator(out_iter);
}

int FEnumerator::toi(void) const
{
  int out_int_enum;
  FC_FUNC_(bind_int_enum, BIND_INT_ENUM)
    (&out_int_enum, *this);
  return out_int_enum;
}

