object: Move OO programming helper macros to a separate header file
This commit is contained in:
@@ -111,7 +111,7 @@ utils/parser_helper.h utils/test.h utils/integrity_checker.h utils/process.h \
|
|||||||
utils/utils/strerror.h utils/compat/windows.h utils/compat/apple.h \
|
utils/utils/strerror.h utils/compat/windows.h utils/compat/apple.h \
|
||||||
utils/utils/atomics.h utils/utils/types.h utils/utils/byteorder.h \
|
utils/utils/atomics.h utils/utils/types.h utils/utils/byteorder.h \
|
||||||
utils/utils/string.h utils/utils/memory.h utils/utils/tty.h utils/utils/path.h \
|
utils/utils/string.h utils/utils/memory.h utils/utils/tty.h utils/utils/path.h \
|
||||||
utils/utils/status.h
|
utils/utils/status.h utils/utils/object.h
|
||||||
endif
|
endif
|
||||||
|
|
||||||
library.lo : $(top_builddir)/config.status
|
library.lo : $(top_builddir)/config.status
|
||||||
|
|||||||
@@ -82,6 +82,7 @@
|
|||||||
#include "utils/memory.h"
|
#include "utils/memory.h"
|
||||||
#include "utils/strerror.h"
|
#include "utils/strerror.h"
|
||||||
#include "utils/status.h"
|
#include "utils/status.h"
|
||||||
|
#include "utils/object.h"
|
||||||
#include "utils/path.h"
|
#include "utils/path.h"
|
||||||
#include "utils/tty.h"
|
#include "utils/tty.h"
|
||||||
#ifdef __APPLE__
|
#ifdef __APPLE__
|
||||||
@@ -114,112 +115,11 @@ void utils_deinit();
|
|||||||
typeof(y) _y = (y); \
|
typeof(y) _y = (y); \
|
||||||
_x < _y ? _x : _y; })
|
_x < _y ? _x : _y; })
|
||||||
|
|
||||||
/**
|
|
||||||
* Call destructor of an object, if object != NULL
|
|
||||||
*/
|
|
||||||
#define DESTROY_IF(obj) if (obj) (obj)->destroy(obj)
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Call offset destructor of an object, if object != NULL
|
|
||||||
*/
|
|
||||||
#define DESTROY_OFFSET_IF(obj, offset) if (obj) obj->destroy_offset(obj, offset);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Call function destructor of an object, if object != NULL
|
|
||||||
*/
|
|
||||||
#define DESTROY_FUNCTION_IF(obj, fn) if (obj) obj->destroy_function(obj, fn);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Debug macro to follow control flow
|
* Debug macro to follow control flow
|
||||||
*/
|
*/
|
||||||
#define POS printf("%s, line %d\n", __FILE__, __LINE__)
|
#define POS printf("%s, line %d\n", __FILE__, __LINE__)
|
||||||
|
|
||||||
/**
|
|
||||||
* Object allocation/initialization macro, using designated initializer.
|
|
||||||
*/
|
|
||||||
#define INIT(this, ...) { (this) = malloc(sizeof(*(this))); \
|
|
||||||
*(this) = (typeof(*(this))){ __VA_ARGS__ }; }
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Aligning version of INIT().
|
|
||||||
*
|
|
||||||
* The returned pointer must be freed using free_align(), not free().
|
|
||||||
*
|
|
||||||
* @param this object to allocate/initialize
|
|
||||||
* @param align alignment for allocation, in bytes
|
|
||||||
* @param ... initializer
|
|
||||||
*/
|
|
||||||
#define INIT_ALIGN(this, align, ...) { \
|
|
||||||
(this) = malloc_align(sizeof(*(this)), align); \
|
|
||||||
*(this) = (typeof(*(this))){ __VA_ARGS__ }; }
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Object allocation/initialization macro, with extra allocated bytes at tail.
|
|
||||||
*
|
|
||||||
* The extra space gets zero-initialized.
|
|
||||||
*
|
|
||||||
* @param this pointer to object to allocate memory for
|
|
||||||
* @param extra number of bytes to allocate at end of this
|
|
||||||
* @param ... initializer
|
|
||||||
*/
|
|
||||||
#define INIT_EXTRA(this, extra, ...) { \
|
|
||||||
typeof(extra) _extra = (extra); \
|
|
||||||
(this) = malloc(sizeof(*(this)) + _extra); \
|
|
||||||
*(this) = (typeof(*(this))){ __VA_ARGS__ }; \
|
|
||||||
memset((this) + 1, 0, _extra); }
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Aligning version of INIT_EXTRA().
|
|
||||||
*
|
|
||||||
* The returned pointer must be freed using free_align(), not free().
|
|
||||||
*
|
|
||||||
* @param this object to allocate/initialize
|
|
||||||
* @param extra number of bytes to allocate at end of this
|
|
||||||
* @param align alignment for allocation, in bytes
|
|
||||||
* @param ... initializer
|
|
||||||
*/
|
|
||||||
#define INIT_EXTRA_ALIGN(this, extra, align, ...) { \
|
|
||||||
typeof(extra) _extra = (extra); \
|
|
||||||
(this) = malloc_align(sizeof(*(this)) + _extra, align); \
|
|
||||||
*(this) = (typeof(*(this))){ __VA_ARGS__ }; \
|
|
||||||
memset((this) + 1, 0, _extra); }
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Method declaration/definition macro, providing private and public interface.
|
|
||||||
*
|
|
||||||
* Defines a method name with this as first parameter and a return value ret,
|
|
||||||
* and an alias for this method with a _ prefix, having the this argument
|
|
||||||
* safely casted to the public interface iface.
|
|
||||||
* _name is provided a function pointer, but will get optimized out by GCC.
|
|
||||||
*/
|
|
||||||
#define METHOD(iface, name, ret, this, ...) \
|
|
||||||
static ret name(union {iface *_public; this;} \
|
|
||||||
__attribute__((transparent_union)), ##__VA_ARGS__); \
|
|
||||||
static typeof(name) *_##name = (typeof(name)*)name; \
|
|
||||||
static ret name(this, ##__VA_ARGS__)
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Same as METHOD(), but is defined for two public interfaces.
|
|
||||||
*/
|
|
||||||
#define METHOD2(iface1, iface2, name, ret, this, ...) \
|
|
||||||
static ret name(union {iface1 *_public1; iface2 *_public2; this;} \
|
|
||||||
__attribute__((transparent_union)), ##__VA_ARGS__); \
|
|
||||||
static typeof(name) *_##name = (typeof(name)*)name; \
|
|
||||||
static ret name(this, ##__VA_ARGS__)
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Callback declaration/definition macro, allowing casted first parameter.
|
|
||||||
*
|
|
||||||
* This is very similar to METHOD, but instead of casting the first parameter
|
|
||||||
* to a public interface, it uses a void*. This allows type safe definition
|
|
||||||
* of a callback function, while using the real type for the first parameter.
|
|
||||||
*/
|
|
||||||
#define CALLBACK(name, ret, param1, ...) \
|
|
||||||
static ret _cb_##name(union {void *_generic; param1;} \
|
|
||||||
__attribute__((transparent_union)), ##__VA_ARGS__); \
|
|
||||||
static typeof(_cb_##name) *name = (typeof(_cb_##name)*)_cb_##name; \
|
|
||||||
static ret _cb_##name(param1, ##__VA_ARGS__)
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This macro allows counting the number of arguments passed to a macro.
|
* This macro allows counting the number of arguments passed to a macro.
|
||||||
* Combined with the VA_ARGS_DISPATCH() macro this can be used to implement
|
* Combined with the VA_ARGS_DISPATCH() macro this can be used to implement
|
||||||
@@ -262,11 +162,6 @@ void utils_deinit();
|
|||||||
*/
|
*/
|
||||||
#define ignore_result(call) { if(call){}; }
|
#define ignore_result(call) { if(call){}; }
|
||||||
|
|
||||||
/**
|
|
||||||
* Assign a function as a class method
|
|
||||||
*/
|
|
||||||
#define ASSIGN(method, function) (method = (typeof(method))function)
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* time_t not defined
|
* time_t not defined
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -0,0 +1,126 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2008-2014 Tobias Brunner
|
||||||
|
* Copyright (C) 2008 Martin Willi
|
||||||
|
* Hochschule fuer Technik Rapperswil
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms of the GNU General Public License as published by the
|
||||||
|
* Free Software Foundation; either version 2 of the License, or (at your
|
||||||
|
* option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful, but
|
||||||
|
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||||
|
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||||
|
* for more details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @defgroup object_i object
|
||||||
|
* @{ @ingroup utils_i
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef OBJECT_H_
|
||||||
|
#define OBJECT_H_
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Call destructor of an object, if object != NULL
|
||||||
|
*/
|
||||||
|
#define DESTROY_IF(obj) if (obj) (obj)->destroy(obj)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Call offset destructor of an object, if object != NULL
|
||||||
|
*/
|
||||||
|
#define DESTROY_OFFSET_IF(obj, offset) if (obj) obj->destroy_offset(obj, offset);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Call function destructor of an object, if object != NULL
|
||||||
|
*/
|
||||||
|
#define DESTROY_FUNCTION_IF(obj, fn) if (obj) obj->destroy_function(obj, fn);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Object allocation/initialization macro, using designated initializer.
|
||||||
|
*/
|
||||||
|
#define INIT(this, ...) { (this) = malloc(sizeof(*(this))); \
|
||||||
|
*(this) = (typeof(*(this))){ __VA_ARGS__ }; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Aligning version of INIT().
|
||||||
|
*
|
||||||
|
* The returned pointer must be freed using free_align(), not free().
|
||||||
|
*
|
||||||
|
* @param this object to allocate/initialize
|
||||||
|
* @param align alignment for allocation, in bytes
|
||||||
|
* @param ... initializer
|
||||||
|
*/
|
||||||
|
#define INIT_ALIGN(this, align, ...) { \
|
||||||
|
(this) = malloc_align(sizeof(*(this)), align); \
|
||||||
|
*(this) = (typeof(*(this))){ __VA_ARGS__ }; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Object allocation/initialization macro, with extra allocated bytes at tail.
|
||||||
|
*
|
||||||
|
* The extra space gets zero-initialized.
|
||||||
|
*
|
||||||
|
* @param this pointer to object to allocate memory for
|
||||||
|
* @param extra number of bytes to allocate at end of this
|
||||||
|
* @param ... initializer
|
||||||
|
*/
|
||||||
|
#define INIT_EXTRA(this, extra, ...) { \
|
||||||
|
typeof(extra) _extra = (extra); \
|
||||||
|
(this) = malloc(sizeof(*(this)) + _extra); \
|
||||||
|
*(this) = (typeof(*(this))){ __VA_ARGS__ }; \
|
||||||
|
memset((this) + 1, 0, _extra); }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Aligning version of INIT_EXTRA().
|
||||||
|
*
|
||||||
|
* The returned pointer must be freed using free_align(), not free().
|
||||||
|
*
|
||||||
|
* @param this object to allocate/initialize
|
||||||
|
* @param extra number of bytes to allocate at end of this
|
||||||
|
* @param align alignment for allocation, in bytes
|
||||||
|
* @param ... initializer
|
||||||
|
*/
|
||||||
|
#define INIT_EXTRA_ALIGN(this, extra, align, ...) { \
|
||||||
|
typeof(extra) _extra = (extra); \
|
||||||
|
(this) = malloc_align(sizeof(*(this)) + _extra, align); \
|
||||||
|
*(this) = (typeof(*(this))){ __VA_ARGS__ }; \
|
||||||
|
memset((this) + 1, 0, _extra); }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Method declaration/definition macro, providing private and public interface.
|
||||||
|
*
|
||||||
|
* Defines a method name with this as first parameter and a return value ret,
|
||||||
|
* and an alias for this method with a _ prefix, having the this argument
|
||||||
|
* safely casted to the public interface iface.
|
||||||
|
* _name is provided a function pointer, but will get optimized out by GCC.
|
||||||
|
*/
|
||||||
|
#define METHOD(iface, name, ret, this, ...) \
|
||||||
|
static ret name(union {iface *_public; this;} \
|
||||||
|
__attribute__((transparent_union)), ##__VA_ARGS__); \
|
||||||
|
static typeof(name) *_##name = (typeof(name)*)name; \
|
||||||
|
static ret name(this, ##__VA_ARGS__)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Same as METHOD(), but is defined for two public interfaces.
|
||||||
|
*/
|
||||||
|
#define METHOD2(iface1, iface2, name, ret, this, ...) \
|
||||||
|
static ret name(union {iface1 *_public1; iface2 *_public2; this;} \
|
||||||
|
__attribute__((transparent_union)), ##__VA_ARGS__); \
|
||||||
|
static typeof(name) *_##name = (typeof(name)*)name; \
|
||||||
|
static ret name(this, ##__VA_ARGS__)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Callback declaration/definition macro, allowing casted first parameter.
|
||||||
|
*
|
||||||
|
* This is very similar to METHOD, but instead of casting the first parameter
|
||||||
|
* to a public interface, it uses a void*. This allows type safe definition
|
||||||
|
* of a callback function, while using the real type for the first parameter.
|
||||||
|
*/
|
||||||
|
#define CALLBACK(name, ret, param1, ...) \
|
||||||
|
static ret _cb_##name(union {void *_generic; param1;} \
|
||||||
|
__attribute__((transparent_union)), ##__VA_ARGS__); \
|
||||||
|
static typeof(_cb_##name) *name = (typeof(_cb_##name)*)_cb_##name; \
|
||||||
|
static ret _cb_##name(param1, ##__VA_ARGS__)
|
||||||
|
|
||||||
|
#endif /** OBJECT_H_ @} */
|
||||||
Reference in New Issue
Block a user