common/inc/c_pal/thandle_ptr.h (79 lines of code) (raw):

// Copyright (c) Microsoft. All rights reserved. // Licensed under the MIT license. See LICENSE file in the project root for full license information. #ifndef THANDLE_PTR_H #define THANDLE_PTR_H #include "c_pal/thandle.h" #include "c_pal/thandle_ll.h" // for THANDLE #include "macro_utils/macro_utils.h" // for MU_COUNT_ARG_0, MU_DISPATCH_EMP... /*all the macros in this file depend on "T". T is "a pointer to a type", so it looks like "COORD_STRUCT*". */ /*this introduces a new *name* for a type that is a typedef of struct THANDLE_PTR_STRUCT_TAG_NAME {...}*/ #define PTR(T) MU_C2(PTR_STRUCT_, T) /*this introduces a new *name* for a structure type that contains "T pointer"*/ #define PTR_STRUCT_TAG_TYPE_NAME(T) MU_C2(PTR(T), _TAG) /*this introduces a new *name* for a function pointer type that takes a T and frees it*/ #define THANDLE_PTR_FREE_FUNC_TYPE_NAME(T) MU_C2(THANDLE_PTR_FREE_FUNC_, T) /*this introduces a new *type* which is a pointer to the free type for T*/ #define THANDLE_PTR_FREE_FUNC_TYPE(T) typedef void (*THANDLE_PTR_FREE_FUNC_TYPE_NAME(T))(T arg); /*this introduces a new *type* which is a structure with a field of type T"*/ #define PTR_STRUCT_TYPE_TYPEDEF(T) \ typedef struct PTR_STRUCT_TAG_TYPE_NAME(T) \ { \ T pointer; /*original pointer passed to THANDLE_PTR_CREATE_WITH_MOVE*/ \ THANDLE_PTR_FREE_FUNC_TYPE_NAME(T) dispose; /*original dispose passed to THANDLE_PTR_CREATE_WITH_MOVE*/ \ } PTR(T); #define PRI_T_PTR "p" #define T_PTR_VALUE(t_ptr) ((t_ptr)->pointer) #define T_PTR_VALUE_OR_NULL(t_ptr) ((t_ptr) == NULL ? NULL : (t_ptr)->pointer) /*this introduces one new *name* for a function which is used to capture a T ptr and move it under the THANDLE(PTR(T))*/ #define THANDLE_PTR_CREATE_WITH_MOVE(T) MU_C2(THANDLE_PTR_CREATE_WITH_MOVE_, T) /*this introduces one new *name* for the function type of THANDLE_PTR_CREATE_WITH_MOVE*/ #define THANDLE_PTR_CREATE_WITH_MOVE_FUNCTION_TYPE(T) MU_C2(THANDLE_PTR_CREATE_WITH_MOVE_TYPE_, T) /*this introduces one new *type* for the function type of THANDLE_PTR_CREATE_WITH_MOVE*/ #define THANDLE_PTR_CREATE_WITH_MOVE_TYPE(T) typedef THANDLE(PTR(T))(*THANDLE_PTR_CREATE_WITH_MOVE_FUNCTION_TYPE(T))(T* pointer, THANDLE_PTR_FREE_FUNC_TYPE_NAME(T) dispose); /*this introduces a new *name* for a function that calls the dispose as passed to THANDLE_PTR_CREATE_WITH_MOVE*/ #define THANDLE_PTR_DISPOSE(T) MU_C2(THANDLE_PTR_DISPOSE_, T) #include "umock_c/umock_c_prod.h" /*this introduces the declarations needed in a .h file for THANDLE(PTR(T))*/ #define THANDLE_PTR_DECLARE(T) \ THANDLE_PTR_FREE_FUNC_TYPE(T); \ PTR_STRUCT_TYPE_TYPEDEF(T); \ THANDLE_TYPE_DECLARE(PTR(T)); \ THANDLE_PTR_CREATE_WITH_MOVE_TYPE(T); \ MOCKABLE_FUNCTION(,THANDLE(PTR(T)), THANDLE_PTR_CREATE_WITH_MOVE(T), T*, pointer, THANDLE_PTR_FREE_FUNC_TYPE_NAME(T), dispose ); \ /*this introduces the definitions for the declarations above to be used in a .c file*/ #define THANDLE_PTR_DEFINE(T) \ THANDLE_TYPE_DEFINE(PTR(T)); \ static void THANDLE_PTR_DISPOSE(T)(PTR(T)* ptr) \ { \ /*Codes_SRS_THANDLE_PTR_02_002: [ If the original dispose is non-NULL then THANDLE_PTR_DISPOSE(T) shall call dispose. ]*/ \ if(ptr->dispose!=NULL) \ { \ ptr->dispose(ptr->pointer); \ } \ else \ { \ /*Codes_SRS_THANDLE_PTR_02_003: [ THANDLE_PTR_DISPOSE(T) shall return. ]*/ \ /*do nothing*/ \ } \ } \ THANDLE(PTR(T)) THANDLE_PTR_CREATE_WITH_MOVE(T)(T* pointer, THANDLE_PTR_FREE_FUNC_TYPE_NAME(T) dispose ) \ { \ THANDLE(PTR(T)) result = NULL; \ /*Codes_SRS_THANDLE_PTR_02_004: [ If pointer is NULL then THANDLE_PTR_CREATE_WITH_MOVE(T) shall fail and return NULL. ]*/ \ if(pointer == NULL) \ { \ LogError("invalid arguments T* pointer=%p, THANDLE_PTR_FREE_FUNC_TYPE_NAME(" MU_TOSTRING(T) ") dispose=%p", pointer, dispose); \ /*return as set to NULL already*/; \ } \ else \ { \ PTR(T) temp = \ { \ .pointer = *pointer, /* this is "move" */ \ .dispose = dispose \ }; \ /*Codes_SRS_THANDLE_PTR_02_005: [ THANDLE_PTR_CREATE_WITH_MOVE(T) shall call THANDLE_CREATE_FROM_CONTENT(PTR(T))(THANDLE_PTR_DISPOSE(T)). ]*/ \ THANDLE_INITIALIZE_MOVE(PTR(T))(&result, &(THANDLE(PTR(T))){THANDLE_CREATE_FROM_CONTENT(PTR(T))(&temp, THANDLE_PTR_DISPOSE(T), NULL)}); \ if(result == NULL) \ { \ /*Codes_SRS_THANDLE_PTR_02_006: [ If THANDLE_CREATE_FROM_CONTENT(PTR(T))(THANDLE_PTR_DISPOSE(T)) fails then THANDLE_PTR_CREATE_WITH_MOVE(T) shall return NULL. ]*/ \ LogError("failure in THANDLE_CREATE_FROM_CONTENT(PTR(" MU_TOSTRING(T) "))(&temp=%p, THANDLE_PTR_DISPOSE(T=" MU_TOSTRING(T) ")=%p, NULL)", \ &temp, THANDLE_PTR_DISPOSE(T)); \ /*return as is*/ \ } \ else \ { \ /*Codes_SRS_THANDLE_PTR_02_007: [ Otherwise THANDLE_CREATE_FROM_CONTENT(PTR(T))(THANDLE_PTR_DISPOSE(T)) shall succeed, set pointer to NULL and return what THANDLE_CREATE_FROM_CONTENT(PTR(T))(THANDLE_PTR_DISPOSE(T)) returned. ]*/ \ *pointer = NULL; \ /*return as is (non-NULL)*/ \ } \ } \ return result; \ } #endif /*THANDLE_PTR_H*/