/*****************************************************************************
 *   Copyright(C)2009-2025 by GorgonMeducer<embedded_zhuoran@hotmail.com>    *
 *                                                                           *
 *  Licensed under the Apache License, Version 2.0 (the "License");          *
 *  you may not use this file except in compliance with the License.         *
 *  You may obtain a copy of the License at                                  *
 *                                                                           *
 *     http://www.apache.org/licenses/LICENSE-2.0                            *
 *                                                                           *
 *  Unless required by applicable law or agreed to in writing, software      *
 *  distributed under the License is distributed on an "AS IS" BASIS,        *
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. *
 *  See the License for the specific language governing permissions and      *
 *  limitations under the License.                                           *
 *                                                                           *
 ****************************************************************************/

#ifndef __PROTECTED_LOW_OVERHEAD_OBJECT_ORIENTED_C_H__
#define __PROTECTED_LOW_OVERHEAD_OBJECT_ORIENTED_C_H__

/*============================ INCLUDES ======================================*/
#if (!defined(__STDC_VERSION__) || __STDC_VERSION__ < 199901L) && !defined(__cplusplus)
//! you have to define this by yourselves
#else
#include <stdint.h>
#include <stdbool.h>
#endif

/*! \NOTE the uint_fast8_t used in this header file is defined in stdint.h 
          if you don't have stdint.h supported in your toolchain, you should
          define uint_fast8_t all by yourself with following rule:
          a. if the target processor is 8 bits, define it as uint8_t
          b. if the target processor is 16 bits, define it as uint16_t 
          c. if the target processor is 32 bits, define it as uint32_t
          d. if the target processor is 64 bits, define it as either uint32_t or 
             uint64_t
 */

#if defined(__clang__)
#   pragma clang diagnostic push
#   pragma clang diagnostic ignored "-Wunknown-warning-option"
#   pragma clang diagnostic ignored "-Wreserved-identifier"
#   pragma clang diagnostic ignored "-Wtypedef-redefinition"
#   pragma clang diagnostic ignored "-Wmissing-declarations"
#   pragma clang diagnostic ignored "-Wempty-body"
#   pragma clang diagnostic ignored "-Wmicrosoft-anon-tag"
#   pragma clang diagnostic ignored "-Wmissing-field-initializers"
#   pragma clang diagnostic ignored "-Wmissing-declarations"
#   pragma clang diagnostic ignored "-Wmissing-braces"
#elif ((__ARMCC_VERSION >= 5000000) && (__ARMCC_VERSION < 6000000))
/*! arm compiler 5 */
#   pragma push
#   pragma diag_suppress 1,64,174,177,188,68,513,144,2525
#elif defined(__IAR_SYSTEMS_ICC__)
/*! IAR */
#elif defined(__GNUC__)
#   pragma GCC diagnostic push
#   pragma GCC diagnostic ignored "-Wmissing-declarations"
#   pragma GCC diagnostic ignored "-Wempty-body"
#   pragma GCC diagnostic ignored "-Wpragmas"
#   pragma GCC diagnostic ignored "-Wformat="
#   pragma GCC diagnostic ignored "-Wmissing-braces"
#   pragma GCC diagnostic ignored "-Wmissing-declarations"
#endif


 #ifdef __cplusplus
extern "C" {
#endif

/*============================ MACROS ========================================*/
#ifndef __cplusplus
#   ifndef plooc_private
#       define plooc_private    static
#   endif

#   ifndef plooc_public
#       define plooc_public      
#   endif
#endif

#ifndef plooc_malloc_align
#   define plooc_malloc_align(__size, __align)  malloc(__size)
#endif

#ifndef plooc_free
#   define plooc_free   free
#endif


/*============================ MACROFIED FUNCTIONS ===========================*/

/* helper macros */
#ifndef PLOOC_UNUSED_PARAM
#   define PLOOC_UNUSED_PARAM(__N)      (void)(__N)
#endif

#ifndef __PLOOC_ALIGN
#   define __PLOOC_ALIGN(__N)           __attribute__((aligned(__N)))
#endif
#ifndef PLOOC_ALIGN
#   define PLOOC_ALIGN(__N)             __PLOOC_ALIGN(__N)
#endif
/*
#ifndef PLOOC_DEFAULT_OBJ_ALIGN
#   define PLOOC_DEFAULT_OBJ_ALIGN      sizeof(uint_fast8_t)
#endif
*/
#ifndef PLOOC_PACKED
#   define PLOOC_PACKED                 __attribute__((packed))
#endif


#undef PLOOC_ALIGNOF_STRUCT
#undef PLOOC_SIZEOF_STRUCT

#if (!defined(__STDC_VERSION__) || __STDC_VERSION__ < 199901L) && !defined(__cplusplus) 

#   ifndef PLOOC_ALIGNOF
#       define PLOOC_ALIGNOF(__TYPE)           __alignof__(__TYPE)
#   endif

#   define PLOOC_ALIGNOF_STRUCT(__TYPE)       PLOOC_ALIGNOF(struct {__TYPE})
#   define PLOOC_SIZEOF_STRUCT(__TYPE)        sizeof(struct {__TYPE})

#else

#   ifndef PLOOC_ALIGNOF
#       define PLOOC_ALIGNOF(...)           __alignof__(__VA_ARGS__)
#   endif

#   define PLOOC_ALIGNOF_STRUCT(...)       PLOOC_ALIGNOF(struct {__VA_ARGS__})
#   define PLOOC_SIZEOF_STRUCT(...)        sizeof(struct {__VA_ARGS__})

#endif


/*! \note add which macro to support multiple inheriting and implementations
 *!
 *!       declare_interface( i_lv0_abc_t )
 *!       declare_interface( i_lv0_efg_t )
 *!       def_interface( i_lv0_abc_t )
 *!           ...
 *!       end_def_interface( i_lv0_abc_t )
 *!
 *!       def_interface( i_lv0_efg_t )
 *!           ...
 *!       end_def_interface( i_lv0_efg_t )
 *!     
 *!       declare_interface( i_lv1_t )
 *!       def_interface( i_lv1_t, which( inherit( i_lv0_abc_t ) 
 *!                                      inherit( i_lv0_efg_t ) ) )
 *!           ...
 *!       end_def_interface( i_lv1_t )
  */

#undef __declare_interface
#undef __declare_structure
#undef __def_interface
#undef __end_def_interface
#undef __def_structure
#undef __end_def_structure

#define __declare_interface(__name)   typedef struct __name __name;
#define __declare_structure(__name)   typedef struct __name __name;

#if (!defined(__STDC_VERSION__) || __STDC_VERSION__ < 199901L) && !defined(__cplusplus)

//! \name interface definition
//! @{
#define __def_interface(__name)                                                 \
            /*typedef struct __name __name;*/                                   \
            struct __name {

#define __end_def_interface(__name)                                             \
            };
//! @}

//! \name structure definition
//! @{
#define __def_structure(__name)                                                 \
            /*typedef struct __name __name; */                                  \
            struct __name {

#define __end_def_structure(__name)                                             \
            };
//! @}

#else
//! \name interface definition
//! @{
#define __def_interface(__name,...)                                             \
            typedef struct __name __name;                                       \
            __VA_ARGS__                                                         \
            struct __name {

#define __end_def_interface(__name)                                             \
            };
//! @}

//! \name structure definition
//! @{
#define __def_structure(__name,...)                                             \
            typedef struct __name __name;                                       \
            __VA_ARGS__                                                         \
            struct __name {

#define __end_def_structure(__name)                                             \
            };
//! @}
#endif

//! \brief macro for inheritance

#undef __IMPLEMENT_EX
#undef __INHERIT_EX
#undef __IMPLEMENT
#undef __INHERIT
#undef INHERIT
#undef INHERIT_EX
#undef IMPLEMENT
#undef IMPLEMENT_EX
#undef OBJ_CONVERT_AS
#undef __OBJ_CONVERT_AS
#undef __REF_OBJ_AS
#undef REF_OBJ_AS

#if !defined(__STDC_VERSION__) || __STDC_VERSION__ < 199901L
#define __IMPLEMENT_EX(__TYPE, __NAME)                                          \
            __TYPE  __NAME;                                                 
#else
#define __IMPLEMENT_EX(__TYPE, __NAME)                                          \
            union {                                                             \
                __TYPE  __NAME;                                                 \
                __TYPE;                                                         \
            };
#endif

#define __INHERIT_EX(__TYPE, __NAME)    __TYPE  __NAME;
#define INHERIT_EX(__TYPE, __NAME)      __INHERIT_EX(__TYPE, __NAME)

#define __INHERIT(__TYPE)              INHERIT_EX(__TYPE, use_as__##__TYPE)
#define INHERIT(__TYPE)                __INHERIT(__TYPE)



/*! \note You can only use IMPLEMENT when defining INTERFACE. For Implement 
 *        interface when defining class, you should use DEF_CLASS_IMPLEMENT 
 *        instead.
 */
#define __IMPLEMENT(__INTERFACE)        __IMPLEMENT_EX( __INTERFACE,            \
                                                        use_as__##__INTERFACE)
#define IMPLEMENT(__INTERFACE)          __IMPLEMENT(__INTERFACE)  

/*! \note if you have used INHERIT or IMPLEMENT to define a class / INTERFACE, 
          you can use OBJ_CONVERT_AS to extract the reference to the inherited 
          object. 
  \*/
#define __OBJ_CONVERT_AS(__OBJ, __INTERFACE)    (__OBJ.use_as__##__INTERFACE)
#define OBJ_CONVERT_AS(__OBJ, __INTERFACE)      __OBJ_CONVERT_AS(   (__OBJ),    \
                                                                    __INTERFACE)

#define __REF_OBJ_AS(__OBJ, __TYPE)             (&(__OBJ.use_as__##__TYPE))
#define REF_OBJ_AS(__OBJ, __TYPE)               __REF_OBJ_AS((__OBJ), __TYPE)


#if (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L) || defined(__cplusplus)
/*! \brief You can use __PLOOC_EVAL() to dynamically select the right API which
 *!        has the right number of parameters (no more than 8).
 */
//! @{
#undef __PLOOC_VA_NUM_ARGS_IMPL
#undef __PLOOC_VA_NUM_ARGS
#undef __16_PLOOC_EVAL
#undef __15_PLOOC_EVAL
#undef __14_PLOOC_EVAL
#undef __13_PLOOC_EVAL
#undef __12_PLOOC_EVAL
#undef __11_PLOOC_EVAL
#undef __10_PLOOC_EVAL
#undef __9_PLOOC_EVAL
#undef __8_PLOOC_EVAL
#undef __7_PLOOC_EVAL
#undef __6_PLOOC_EVAL
#undef __5_PLOOC_EVAL
#undef __4_PLOOC_EVAL
#undef __3_PLOOC_EVAL
#undef __2_PLOOC_EVAL
#undef __1_PLOOC_EVAL
#undef __0_PLOOC_EVAL
#undef __PLOOC_EVAL

#define __PLOOC_VA_NUM_ARGS_IMPL(   _0,_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12,  \
                                    _13,_14,_15,_16,__N,...)      __N
#define __PLOOC_VA_NUM_ARGS(...)                                                \
            __PLOOC_VA_NUM_ARGS_IMPL( 0,##__VA_ARGS__,16,15,14,13,12,11,10,9,   \
                                      8,7,6,5,4,3,2,1,0)

#define __16_PLOOC_EVAL(__FUNC, __NO_ARGS)  __FUNC##__NO_ARGS
#define __15_PLOOC_EVAL(__FUNC, __NO_ARGS)  __16_PLOOC_EVAL(__FUNC, __NO_ARGS)
#define __14_PLOOC_EVAL(__FUNC, __NO_ARGS)  __15_PLOOC_EVAL(__FUNC, __NO_ARGS)
#define __13_PLOOC_EVAL(__FUNC, __NO_ARGS)  __14_PLOOC_EVAL(__FUNC, __NO_ARGS)

#define __12_PLOOC_EVAL(__FUNC, __NO_ARGS)  __13_PLOOC_EVAL(__FUNC, __NO_ARGS)
#define __11_PLOOC_EVAL(__FUNC, __NO_ARGS)  __12_PLOOC_EVAL(__FUNC, __NO_ARGS)
#define __10_PLOOC_EVAL(__FUNC, __NO_ARGS)  __11_PLOOC_EVAL(__FUNC, __NO_ARGS)
#define __9_PLOOC_EVAL(__FUNC, __NO_ARGS)   __10_PLOOC_EVAL(__FUNC, __NO_ARGS)
#define __8_PLOOC_EVAL(__FUNC, __NO_ARGS)   __9_PLOOC_EVAL(__FUNC, __NO_ARGS)

#define __7_PLOOC_EVAL(__FUNC, __NO_ARGS)   __8_PLOOC_EVAL(__FUNC, __NO_ARGS)
#define __6_PLOOC_EVAL(__FUNC, __NO_ARGS)   __7_PLOOC_EVAL(__FUNC, __NO_ARGS)
#define __5_PLOOC_EVAL(__FUNC, __NO_ARGS)   __6_PLOOC_EVAL(__FUNC, __NO_ARGS)
#define __4_PLOOC_EVAL(__FUNC, __NO_ARGS)   __5_PLOOC_EVAL(__FUNC, __NO_ARGS)
#define __3_PLOOC_EVAL(__FUNC, __NO_ARGS)   __4_PLOOC_EVAL(__FUNC, __NO_ARGS)
#define __2_PLOOC_EVAL(__FUNC, __NO_ARGS)   __3_PLOOC_EVAL(__FUNC, __NO_ARGS)
#define __1_PLOOC_EVAL(__FUNC, __NO_ARGS)   __2_PLOOC_EVAL(__FUNC, __NO_ARGS)
#define __0_PLOOC_EVAL(__FUNC, __NO_ARGS)   __1_PLOOC_EVAL(__FUNC, __NO_ARGS)

#define __PLOOC_EVAL(__FUNC, ...)           __0_PLOOC_EVAL(                     \
                                                __FUNC,                         \
                                                __PLOOC_VA_NUM_ARGS(__VA_ARGS__))
//! @}   
#endif
           
/*----------------------------------------------------------------------------* 
 * new standard (lower case)                                                  *
 *----------------------------------------------------------------------------*/
#undef def_interface
#undef define_interface
#undef def_structure
#undef define_structure
#undef def_params
#undef define_params
#undef end_def_params
#undef end_define_params
#undef def_members
#undef define_members
#undef end_def_members
#undef end_define_members

#if !defined(__STDC_VERSION__) || __STDC_VERSION__ < 199901L
#   define def_interface(__name)            __def_interface(__name)
#   define define_interface(__name)         __def_interface(__name)
#   define def_structure(__name)            __def_structure(__name)
#   define define_structure(__name)         __def_structure(__name)
#   define def_params(__code)               __code
#   define define_params(__code)            __code
#   define end_def_params()
#   define end_define_params()
#   define def_members(__code)              __code
#   define define_members(__code)           __code
#   define end_def_members()
#   define end_define_members()
#else
#   define def_interface(__name, ...)       __def_interface(__name, __VA_ARGS__)
#   define define_interface(__name, ...)    __def_interface(__name, __VA_ARGS__)
#   define def_structure(__name, ...)       __def_structure(__name, __VA_ARGS__)
#   define define_structure(__name, ...)       __def_structure(__name, __VA_ARGS__)
#   define def_params(...)                  __VA_ARGS__
#   define define_params(...)               __VA_ARGS__
#   define end_def_params(...)
#   define end_define_params(...)
#   define def_members(...)                 __VA_ARGS__
#   define define_members(...)              __VA_ARGS__
#   define end_def_members(...)
#   define end_define_members(...)
#endif

#undef implement
#undef implement_ex
#undef inherit_ex
#undef inherit
#undef ref_interface
#undef convert_obj_as
#undef obj_convert_as
#undef ref_obj_as

#undef end_def_interface
#undef end_define_interface
#undef dcl_interface
#undef declare_interface
#undef end_def_structure
#undef end_define_structure
#undef dcl_structure
#undef declare_structure

#undef this_interface
#undef base_obj

#define implement(__type)                   IMPLEMENT(__type)
#define implement_ex(__type, __name)        __IMPLEMENT_EX(__type, __name)
#define inherit_ex(__type, __name)          INHERIT_EX(__type, __name)
#define inherit(__type)                     INHERIT(__type)
#define ref_interface(__INTERFACE)          const __INTERFACE *ptMethod;
#define convert_obj_as(__obj, __type)       OBJ_CONVERT_AS(__obj, __type)
#define obj_convert_as(__obj, __type)       OBJ_CONVERT_AS(__obj, __type)       /*  obsolete */
#define ref_obj_as(__obj, __type)           REF_OBJ_AS(__obj, __type)

#define end_def_interface(__name)           __end_def_interface(__name)
#define end_define_interface(__name)        __end_def_interface(__name)
#define dcl_interface(__name)               __declare_interface(__name)
#define declare_interface(__name)           __declare_interface(__name)
#define end_def_structure(__name)           __end_def_structure(__name)
#define end_define_structure(__name)        __end_def_structure(__name)
#define dcl_structure(__name)               __declare_structure(__name)
#define declare_structure(__name)           __declare_structure(__name)

#define this_interface(__INTERFACE)         convert_obj_as(this, __INTERFACE)
#define base_obj(__type)                    convert_obj_as(this, __type)

/*============================ TYPES =========================================*/

//! \name interface: u32_property_t
//! @{
dcl_interface(u32_property_t)
def_interface(u32_property_t)
    bool (*Set)(uint32_t wValue);
    uint32_t (*Get)(void);
end_def_interface(u32_property_t)
//! @}

//! \name interface: u16_property_t
//! @{
dcl_interface(u16_property_t)
def_interface(u16_property_t)
    bool (*Set)(uint_fast16_t wValue);
    uint_fast16_t (*Get)(void);
end_def_interface(u16_property_t)
//! @}

//! \name interface: u8_property_t
//! @{
dcl_interface(u8_property_t)
def_interface(u8_property_t)
    bool (*Set)(uint_fast8_t wValue);
    uint_fast8_t (*Get)(void);
end_def_interface(u8_property_t)
//! @}


//! \name interface: i32_property_t
//! @{
dcl_interface(i32_property_t)
def_interface(i32_property_t)
    bool (*Set)(int32_t wValue);
    int32_t (*Get)(void);
end_def_interface(i32_property_t)
//! @}

//! \name interface: i16_property_t
//! @{
dcl_interface(i16_property_t)
def_interface(i16_property_t)
    bool (*Set)(int_fast16_t wValue);
    int_fast16_t (*Get)(void);
end_def_interface(i16_property_t)
//! @}

//! \name interface: u8_property_t
//! @{
dcl_interface(i8_property_t)
def_interface(i8_property_t)
    bool (*Set)(int_fast8_t wValue);
    int_fast8_t (*Get)(void);
end_def_interface(i8_property_t)
//! @}

//! \name interface: bool_property_t
//! @{
dcl_interface(bool_property_t)
def_interface(bool_property_t)
    bool (*Set)(bool bValue);
    bool (*Get)(void);
end_def_interface(bool_property_t)
//! @}

//! \name interface: bool_property_t
//! @{
dcl_interface(en_property_t)
def_interface(en_property_t)
    bool (*Enable)(void);
    bool (*Disable)(void);
end_def_interface(en_property_t)
//! @}

/*============================ GLOBAL VARIABLES ==============================*/
/*============================ LOCAL VARIABLES ===============================*/
/*============================ PROTOTYPES ====================================*/

#ifdef __cplusplus
}
#endif

//#if defined(__clang__)
//#   pragma clang diagnostic pop
//#endif

#endif
/* EOF */
