/*
 * Copyright (C) 2020-2021 Aloysius Indrayanto
 *
 * This file is part of the eCxx library, see LICENSE file for the license details.
 */


#ifndef ECXX_CTL_TYPES_H
#define ECXX_CTL_TYPES_H


#include <limits.h>
#include <stddef.h>
#include <string.h>

#include <eCxx/Config.h>


namespace eCxx {


//
// Integer typedefs
//
    typedef unsigned char  uchar;
    typedef unsigned short ushort;
    typedef unsigned int   uint;
    typedef unsigned long  ulong;

    typedef ::size_t     size_t;
    typedef ::ptrdiff_t ssize_t;

    typedef signed   char  int8_t;
    typedef unsigned char uint8_t;

#ifdef __AVR_ARCH__

#if UINT_MAX == 0xFFFF

    typedef int           int16_t;
    typedef unsigned int uint16_t;

#elif USHRT_MAX == 0xFFFF

    typedef short           int16_t;
    typedef unsigned short uint16_t;

#endif

#else

#if USHRT_MAX == 0xFFFF

    typedef short           int16_t;
    typedef unsigned short uint16_t;

#elif UINT_MAX == 0xFFFF

    typedef int           int16_t;
    typedef unsigned int uint16_t;

#endif

#endif

#if UINT_MAX == 0xFFFFFFFFUL

    typedef int           int32_t;
    typedef unsigned int uint32_t;

#elif ULONG_MAX == 0xFFFFFFFFUL

    typedef long           int32_t;
    typedef unsigned long uint32_t;

#endif

#if ULONG_MAX == 0xFFFFFFFFFFFFFFFFULL

    #define ECXX_WITH_I64
    typedef long           int64_t;
    typedef unsigned long uint64_t;

#elif ULLONG_MAX == 0xFFFFFFFFFFFFFFFFULL

    #define ECXX_WITH_I64
    typedef long long           int64_t;
    typedef unsigned long long uint64_t;

#elif defined(__GNUC__)

    #define ECXX_WITH_I64
    typedef long long           int64_t;
    typedef unsigned long long uint64_t;

    #define LLONG_MAX  9223372036854775807LL
    #define LLONG_MIN  (-LLONG_MAX - 1LL)
    #define ULLONG_MAX 18446744073709551615ULL

#endif


//
// Wrapper for bool; to prevent implicit conversion to bool whenever necessary
//
class Bool {
    private:
        const bool b;
    public:
        constexpr explicit Bool(bool b_) : b(b_) {}
        constexpr explicit operator bool() const { return b; }
};


//
// Active state
//
enum class ActiveState : uint8_t {
    Low     = 0,
    High    = 1,
    Invalid = 0xFF
};


//
// Active clock edge
//
enum class ActiveClockEdge : uint8_t {
    Rising  = 0,
    Falling = 1,
    Invalid = 0xFF
};


//
// Bit order
//
enum class BitOrder : uint8_t {
    LSBFirst = 0,
    MSBFirst = 1
};


//
// Common callback types
//
using BoolCallback                     = bool(*)(      void             );

using VoidCallback                     = void(*)(      void             );
using VoidCallback_Bool                = void(*)(      bool             );
using VoidCallback_Size                = void(*)(                size_t );
using VoidCallback_UInt8               = void(*)(                uint8_t);

using VoidCallback_Size_Size           = void(*)(      size_t,   size_t );
using VoidCallback_UInt8_UInt8         = void(*)(      uint8_t,  uint8_t);

using VoidCallback_VoidPtr             = void(*)(      void*            );
using VoidCallback_VoidPtr_Size        = void(*)(      void*,    size_t );
using VoidCallback_VoidPtr_UInt8       = void(*)(      void*,    uint8_t);
using VoidCallback_ConstVoidPtr        = void(*)(const void*            );
using VoidCallback_ConstVoidPtr_Size   = void(*)(const void*,    size_t );
using VoidCallback_ConstVoidPtr_UInt8  = void(*)(const void*,    uint8_t);

using VoidCallback_UInt8Ptr            = void(*)(      uint8_t*         );
using VoidCallback_UInt8Ptr_Size       = void(*)(      uint8_t*, size_t );
using VoidCallback_UInt8Ptr_UInt8      = void(*)(      uint8_t*, uint8_t);
using VoidCallback_ConstUInt8Ptr       = void(*)(const uint8_t*         );
using VoidCallback_ConstUInt8Ptr_Size  = void(*)(const uint8_t*, size_t );
using VoidCallback_ConstUInt8Ptr_UInt8 = void(*)(const uint8_t*, uint8_t);


} // namespace eCxx


#endif
