This code example implements the shape, circle and rectangle classes as discussed in the Generic Object System topic. It can also be found in the speect/engine/examples/base/objsystem/ directory, and be compiled with the WANT_EXAMPLES build option.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 | #ifndef _SPCT_SHAPE_EXAMPLE_H__
#define _SPCT_SHAPE_EXAMPLE_H__
/**
* @file shape.h
* 2d shape class as an example of Speect's object-oriented
* programming support.
*/
/************************************************************************************/
/* */
/* Modules used */
/* */
/************************************************************************************/
#include "speect.h"
/************************************************************************************/
/* */
/* Begin external c declaration */
/* */
/************************************************************************************/
S_BEGIN_C_DECLS
/************************************************************************************/
/* */
/* Macros */
/* */
/************************************************************************************/
/**
* @name Utility Macros
* @{
*/
/**
* @hideinitializer
* Return the given #SShape child class object as a shape
* object.
*
* @param SELF The given object.
*
* @return Given object as #SShape* type.
*
* @note This casting is not safety checked.
*/
#define S_SHAPE(SELF) ((SShape *)(SELF))
/**
* @}
*/
/************************************************************************************/
/* */
/* SShape definition */
/* */
/************************************************************************************/
/**
* @ingroup SShape
* A 2d shape class as an example of Speect's
* object-oriented programming support.
* @extends SObject
*/
typedef struct
{
/**
* @protected Inherit from #SObject.
*/
SObject obj;
/**
* @protected x-coordinate of rectangle top left hand position.
*/
int x;
/**
* @protected y-coordinate of rectangle top left hand position.
*/
int y;
} SShape;
/************************************************************************************/
/* */
/* SShapeClass definition */
/* */
/************************************************************************************/
/**
* The abstract shape class structure.
* @extends SObjectClass
*/
typedef struct
{
/* Class members */
/**
* @protected Inherit from #SObjectClass.
*/
SObjectClass _inherit;
/* Class methods */
/**
* @protected Move function pointer.
* Move the given shape to the given coordinates.
*
* @param self The shape to move.
* @param newx The new x coordinate.
* @param newy The new y coordinate.
* @param error Error code.
*/
void (* const move) (SShape *self, int newx, int newy, s_erc *error);
/**
* @protected Area function pointer.
* Calculate and return the given shape's area.
*
* @param self The shape to calculate the area of.
* @param error Error code.
*
* @return The given shape's area.
*/
float (* const area) (const SShape *self, s_erc *error);
} SShapeClass;
/************************************************************************************/
/* */
/* Function prototypes */
/* */
/************************************************************************************/
/**
* Move the given shape to the given coordinates.
* @public @memberof SShape
*
* @param self The shape to move.
* @param newx The new x coordinate.
* @param newy The new y coordinate.
* @param error Error code.
*/
S_API void SShapeMove(SShape *self, int newx, int newy, s_erc *error);
/**
* Calculate and return the given shape's area.
* @public @memberof SShape
*
* @param self The shape to calculate the area of.
* @param error Error code.
*
* @return The given shape's area.
*/
S_API float SShapeArea(const SShape *self, s_erc *error);
/**
* Register the SShape class to the object system.
* @private @memberof SShape
*
* @param error Error code.
*/
S_LOCAL void _s_shape_class_reg(s_erc *error);
/**
* Free the SShape class from the object system.
* @private @memberof SShape
*
* @param error Error code.
*/
S_LOCAL void _s_shape_class_free(s_erc *error);
/************************************************************************************/
/* */
/* End external c declaration */
/* */
/************************************************************************************/
S_END_C_DECLS
/**
* @}
* end documentation
*/
#endif /* _SPCT_SHAPE_EXAMPLE_H__ */
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 | /************************************************************************************/
/* */
/* Modules used */
/* */
/************************************************************************************/
#include "shape.h"
/************************************************************************************/
/* */
/* Macros */
/* */
/************************************************************************************/
/**
* @hideinitializer
* Call the given function method of the given #SShape,
* see full description #S_SHAPE_CALL for usage.
*
* @param SELF The given #SShape*.
* @param FUNC The function method of the given object to call.
*
* @note This casting is not safety checked.
* @note Example usage:
@verbatim
S_SHAPE_CALL(self, func)(param1, param2, ..., paramN);
@endverbatim
* where @c param1, @c param2, ..., @c paramN are the parameters
* passed to the object function @c func.
*/
#define S_SHAPE_CALL(SELF, FUNC) \
((SShapeClass *)S_OBJECT_CLS(SELF))->FUNC
/**
* @hideinitializer
* Test if the given function method of the given #SShape
* can be called.
*
* @param SELF The given #SShape*.
* @param FUNC The function method of the given object to check.
*
* @return #TRUE if function can be called, otherwise #FALSE.
*
* @note This casting is not safety checked.
*/
#define S_SHAPE_METH_VALID(SELF, FUNC) \
S_SHAPE_CALL(SELF, FUNC) ? TRUE : FALSE
/************************************************************************************/
/* */
/* Static variables */
/* */
/************************************************************************************/
static SShapeClass ShapeClass; /* Shape class declaration. */
/************************************************************************************/
/* */
/* Function implementations */
/* */
/************************************************************************************/
S_API void SShapeMove(SShape *self, int newx, int newy, s_erc *error)
{
S_CLR_ERR(error);
if (self == NULL)
{
S_CTX_ERR(error, S_ARGERROR,
"SShapeMove",
"Argument \"self\" is NULL");
return;
}
if (!S_SHAPE_METH_VALID(self, move))
{
S_CTX_ERR(error, S_METHINVLD,
"SShapeMove",
"Shape method \"move\" not implemented");
return;
}
S_SHAPE_CALL(self, move)(self, newx, newy, error);
S_CHK_ERR(error, S_CONTERR,
"SShapeMove",
"Call to class method \"move\" failed");
}
S_API float SShapeArea(const SShape *self, s_erc *error)
{
float area;
S_CLR_ERR(error);
if (self == NULL)
{
S_CTX_ERR(error, S_ARGERROR,
"SShapeArea",
"Argument \"self\" is NULL");
return 0.0;
}
if (!S_SHAPE_METH_VALID(self, area))
{
S_CTX_ERR(error, S_METHINVLD,
"SShapeArea",
"Shape method \"area\" not implemented");
return 0.0;
}
area = S_SHAPE_CALL(self, area)(self, error);
if (S_CHK_ERR(error, S_CONTERR,
"SShapeArea",
"Call to class method \"area\" failed"))
return 0.0;
return area;
}
/************************************************************************************/
/* */
/* Class registration */
/* */
/************************************************************************************/
S_LOCAL void _s_shape_class_reg(s_erc *error)
{
S_CLR_ERR(error);
s_class_reg(S_OBJECTCLASS(&ShapeClass), error);
S_CHK_ERR(error, S_CONTERR,
"_s_shape_class_reg",
"Failed to register SShapeClass");
}
S_LOCAL void _s_shape_class_free(s_erc *error)
{
S_CLR_ERR(error);
s_class_free(S_OBJECTCLASS(&ShapeClass), error);
S_CHK_ERR(error, S_CONTERR,
"_s_shape_class_free",
"Failed to free SShapeClass");
}
/************************************************************************************/
/* */
/* Static class function implementations */
/* */
/************************************************************************************/
static void InitShape(void *obj, s_erc *error)
{
SShape *self = obj;
S_CLR_ERR(error);
self->x = 0;
self->y = 0;
}
static void DisposeShape(void *obj, s_erc *error)
{
S_CLR_ERR(error);
SObjectDecRef(obj);
}
static void MoveShape(SShape *self, int newx, int newy, s_erc *error)
{
S_CLR_ERR(error);
self->x = newx;
self->y = newy;
}
/************************************************************************************/
/* */
/* Class initialization */
/* */
/************************************************************************************/
static SShapeClass ShapeClass =
{
/* SObjectClass */
{
"SShape",
sizeof(SShape),
{ 0, 1},
InitShape, /* init */
NULL, /* destroy */
DisposeShape, /* dispose */
NULL, /* compare */
NULL, /* print */
NULL, /* copy */
},
/* SShapeClass */
MoveShape, /* move */
NULL /* area */
};
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 | #ifndef _SPCT_RECTANGLE_EXAMPLE_H__
#define _SPCT_RECTANGLE_EXAMPLE_H__
/**
* @file rectangle.h
* 2d rectangle class as an example of Speect's object-oriented
* programming support.
*/
/************************************************************************************/
/* */
/* Modules used */
/* */
/************************************************************************************/
#include "shape.h"
/************************************************************************************/
/* */
/* Begin external c declaration */
/* */
/************************************************************************************/
S_BEGIN_C_DECLS
/************************************************************************************/
/* */
/* Macros */
/* */
/************************************************************************************/
/**
* @name Utility Macros
* @{
*/
/**
* @hideinitializer
* Return the given #SRectangle child class object as a rectangle
* object.
*
* @param SELF The given object.
*
* @return Given object as #SRectangle* type.
*
* @note This casting is not safety checked.
*/
#define S_RECTANGLE(SELF) ((SRectangle *)(SELF))
/**
* @}
*/
/************************************************************************************/
/* */
/* SRectangle definition */
/* */
/************************************************************************************/
/**
* @ingroup SRectangle
* A 2d rectangle class as an example of Speect's object-oriented programming support.
* @extends SShape
*/
typedef struct
{
/**
* @protected Inherit from #SShape.
*/
SShape obj;
/**
* @protected Rectangle width.
*/
int width;
/**
* @protected Rectangle height.
*/
int height;
} SRectangle;
/************************************************************************************/
/* */
/* SRectangleClass definition */
/* */
/************************************************************************************/
/**
* The rectangle class structure.
* @extends SShapeClass
*/
typedef struct
{
/* Class members */
/**
* @protected Inherit from #SShapeClass.
*/
SShapeClass _inherit;
/* Class methods */
/**
* @protected SetWidth function pointer.
* Set the width of the given rectangle.
*
* @param self The rectangle to set the width of.
* @param new_width The new width of the rectangle.
* @param error Error code.
*/
void (* const set_width) (SRectangle *self, int new_width, s_erc *error);
/**
* @protected SetHeight function pointer.
* Set the height of the given rectangle.
*
* @param self The rectangle to set the height of.
* @param new_height The new height of the rectangle.
* @param error Error code.
*/
void (* const set_height) (SRectangle *self, int new_height, s_erc *error);
} SRectangleClass;
/************************************************************************************/
/* */
/* Function prototypes */
/* */
/************************************************************************************/
/**
* Create a new rectangle from the given parameters.
* @public @memberof SRectangle
*
* @param x x-coordinate of rectangle top left hand position.
* @param y y-coordinate of rectangle top left hand position.
* @param width Rectangle width.
* @param height Rectangle height.
* @param error error Error code.
*
* @return Pointer to newly created rectangle.
*/
S_API SRectangle *SRectangleNew(int x, int y, int width, int height, s_erc *error);
/**
* Set the width of the given rectangle.
* @public @memberof SRectangle
*
* @param self The rectangle to set the width of.
* @param new_width The new width of the rectangle.
* @param error Error code.
*/
S_API void SRectangleSetWidth(SRectangle *self, int new_width, s_erc *error);
/**
* Set the height of the given rectangle.
* @public @memberof SRectangle
*
* @param self The rectangle to set the height of.
* @param new_height The new height of the rectangle.
* @param error Error code.
*/
S_API void SRectangleSetHeight(SRectangle *self, int new_height, s_erc *error);
/**
* Register the SRectangle class to the object system.
* @private @memberof SRectangle
*
* @param error Error code.
*/
S_LOCAL void _s_rectangle_class_reg(s_erc *error);
/**
* Free the SRectangle class from the object system.
* @private @memberof SRectangle
*
* @param error Error code.
*/
S_LOCAL void _s_rectangle_class_free(s_erc *error);
/************************************************************************************/
/* */
/* End external c declaration */
/* */
/************************************************************************************/
S_END_C_DECLS
/**
* @}
* end documentation
*/
#endif /* _SPCT_RECTANGLE_EXAMPLE_H__ */
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 | /************************************************************************************/
/* */
/* Modules used */
/* */
/************************************************************************************/
#include "rectangle.h"
/************************************************************************************/
/* */
/* Macros */
/* */
/************************************************************************************/
/**
* @hideinitializer
* Call the given function method of the given #SRectangle,
* see full description #S_RECTANGLE_CALL for usage.
*
* @param SELF The given #SRectangle*.
* @param FUNC The function method of the given object to call.
*
* @note This casting is not safety checked.
* @note Example usage:
@verbatim
S_RECTANGLE_CALL(self, func)(param1, param2, ..., paramN);
@endverbatim
* where @c param1, @c param2, ..., @c paramN are the parameters
* passed to the object function @c func.
*/
#define S_RECTANGLE_CALL(SELF, FUNC) \
((SRectangleClass *)S_OBJECT_CLS(SELF))->FUNC
/**
* @hideinitializer
* Test if the given function method of the given #SRectangle
* can be called.
*
* @param SELF The given #SRectangle*.
* @param FUNC The function method of the given object to check.
*
* @return #TRUE if function can be called, otherwise #FALSE.
*
* @note This casting is not safety checked.
*/
#define S_RECTANGLE_METH_VALID(SELF, FUNC) \
S_RECTANGLE_CALL(SELF, FUNC) ? TRUE : FALSE
/************************************************************************************/
/* */
/* Static variables */
/* */
/************************************************************************************/
static SRectangleClass RectangleClass; /* Rectangle class declaration. */
/************************************************************************************/
/* */
/* Function implementations */
/* */
/************************************************************************************/
S_API SRectangle *SRectangleNew(int x, int y, int width, int height, s_erc *error)
{
SRectangle *self;
S_CLR_ERR(error);
self = S_NEW(SRectangle, error);
if (S_CHK_ERR(error, S_CONTERR,
"SRectangleNew",
"Failed to create new object"))
{
return NULL;
}
S_SHAPE(self)->x = x;
S_SHAPE(self)->y = y;
self->width = width;
self->height = height;
return self;
}
S_API void SRectangleSetWidth(SRectangle *self, int new_width, s_erc *error)
{
S_CLR_ERR(error);
if (self == NULL)
{
S_CTX_ERR(error, S_ARGERROR,
"SRectangleSetWidth",
"Argument \"self\" is NULL");
return;
}
if (!S_RECTANGLE_METH_VALID(self, set_width))
{
S_CTX_ERR(error, S_METHINVLD,
"SRectangleSetWidth",
"Rectangle method \"set_width\" not implemented");
return;
}
S_RECTANGLE_CALL(self, set_width)(self, new_width, error);
S_CHK_ERR(error, S_CONTERR,
"SRectangleSetWidth",
"Call to class method \"set_width\" failed");
}
S_API void SRectangleSetHeight(SRectangle *self, int new_height, s_erc *error)
{
S_CLR_ERR(error);
if (self == NULL)
{
S_CTX_ERR(error, S_ARGERROR,
"SRectangleSetHeight",
"Argument \"self\" is NULL");
return;
}
if (!S_RECTANGLE_METH_VALID(self, set_height))
{
S_CTX_ERR(error, S_METHINVLD,
"SRectangleSetHeight",
"Rectangle method \"set_height\" not implemented");
return;
}
S_RECTANGLE_CALL(self, set_height)(self, new_height, error);
S_CHK_ERR(error, S_CONTERR,
"SRectangleSetHeight",
"Call to class method \"set_height\" failed");
}
/************************************************************************************/
/* */
/* Class registration */
/* */
/************************************************************************************/
S_LOCAL void _s_rectangle_class_reg(s_erc *error)
{
S_CLR_ERR(error);
s_class_reg(S_OBJECTCLASS(&RectangleClass), error);
S_CHK_ERR(error, S_CONTERR,
"_s_rectangle_class_reg",
"Failed to register SRectangleClass");
}
S_LOCAL void _s_rectangle_class_free(s_erc *error)
{
S_CLR_ERR(error);
s_class_free(S_OBJECTCLASS(&RectangleClass), error);
S_CHK_ERR(error, S_CONTERR,
"_s_rectangle_class_free",
"Failed to free SRectangleClass");
}
/************************************************************************************/
/* */
/* Static class function implementations */
/* */
/************************************************************************************/
static void InitRectangle(void *obj, s_erc *error)
{
SRectangle *self = obj;
S_CLR_ERR(error);
self->width = 0;
self->height = 0;
}
static void DisposeRectangle(void *obj, s_erc *error)
{
S_CLR_ERR(error);
SObjectDecRef(obj);
}
static char *PrintRectangle(const SObject *self, s_erc *error)
{
SRectangle *rec = S_RECTANGLE(self);
const char *type = "[SRectangle] at (%d,%d), width %d, height %d";
char *buf;
S_CLR_ERR(error);
s_asprintf(&buf, error, type, S_SHAPE(rec)->x, S_SHAPE(rec)->y, rec->width, rec->height);
if (S_CHK_ERR(error, S_CONTERR,
"PrintRectangle",
"Call to \"s_asprintf\" failed"))
{
if (buf != NULL)
S_FREE(buf);
return NULL;
}
return buf;
}
static void MoveRectangle(SShape *self, int newx, int newy, s_erc *error)
{
S_CLR_ERR(error);
self->x = newx;
self->y = newy;
}
static float AreaRectangle(const SShape *self, s_erc *error)
{
SRectangle *rec = S_RECTANGLE(self);
float area;
S_CLR_ERR(error);
area = rec->width * rec->height;
return area;
}
static void SetWidthRectangle(SRectangle *self, int new_width, s_erc *error)
{
S_CLR_ERR(error);
self->width = new_width;
}
static void SetHeightRectangle(SRectangle *self, int new_heigth, s_erc *error)
{
S_CLR_ERR(error);
self->height = new_heigth;
}
/************************************************************************************/
/* */
/* Class initialization */
/* */
/************************************************************************************/
static SRectangleClass RectangleClass =
{
{
/* SObjectClass */
{
"SShape:SRectangle",
sizeof(SRectangle),
{ 0, 1},
InitRectangle, /* init */
NULL, /* destroy */
DisposeRectangle, /* dispose */
NULL, /* compare */
PrintRectangle, /* print */
NULL, /* copy */
},
/* SShapeClass */
MoveRectangle, /* move */
AreaRectangle, /* area */
},
/* SRectangleClass */
SetWidthRectangle, /* set_width */
SetHeightRectangle /* set_height */
};
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 | #ifndef _SPCT_CIRCLE_EXAMPLE_H__
#define _SPCT_CIRCLE_EXAMPLE_H__
/**
* @file circle.h
* 2d circle class as an example of Speect's object-oriented
* programming support.
*/
/************************************************************************************/
/* */
/* Modules used */
/* */
/************************************************************************************/
#include "shape.h"
/************************************************************************************/
/* */
/* Begin external c declaration */
/* */
/************************************************************************************/
S_BEGIN_C_DECLS
/************************************************************************************/
/* */
/* Macros */
/* */
/************************************************************************************/
/**
* @name Utility Macros
* @{
*/
/**
* @hideinitializer
* Return the given #SCircle child class object as a circle
* object.
*
* @param SELF The given object.
*
* @return Given object as #SCircle* type.
*
* @note This casting is not safety checked.
*/
#define S_CIRCLE(SELF) ((SCircle *)(SELF))
/**
* @}
*/
/************************************************************************************/
/* */
/* SCircle definition */
/* */
/************************************************************************************/
/**
* @ingroup SCircle
* A 2d circle class as an example of Speect's object-oriented programming support.
* @extends SShape
*/
typedef struct
{
/**
* @protected Inherit from #SShape.
*/
SShape obj;
/**
* @protected Circle radius.
*/
int radius;
/**
* @protected Circle colour.
*/
char *colour;
} SCircle;
/************************************************************************************/
/* */
/* SCircleClass definition */
/* */
/************************************************************************************/
/**
* The circle class structure.
* @extends SShapeClass
*/
typedef struct
{
/* Class members */
/**
* @protected Inherit from #SShapeClass.
*/
SShapeClass _inherit;
/* Class methods */
/**
* @protected SetRadius function pointer.
* Set the radius of the given circle.
*
* @param self The circle to set the radius of.
* @param new_radius The new radius of the circle.
* @param error Error code.
*/
void (* const set_radius) (SCircle *self, int new_radius, s_erc *error);
/**
* @protected SetColour function pointer.
* Set the colour of the given circle.
*
* @param self The circle to set the colour of.
* @param new_colour The new colour of the circle.
* @param error Error code.
*/
void (* const set_colour) (SCircle *self, const char *new_colour, s_erc *error);
} SCircleClass;
/************************************************************************************/
/* */
/* Function prototypes */
/* */
/************************************************************************************/
/**
* Create a new circle from the given parameters.
* @public @memberof SCircle
*
* @param x x-coordinate of circle top left hand position.
* @param y y-coordinate of circle top left hand position.
* @param radius Circle radius.
* @param colour Circle colour.
* @param error error Error code.
*
* @return Pointer to newly created circle.
*/
S_API SCircle *SCircleNew(int x, int y, int radius, const char *colour, s_erc *error);
/**
* Set the radius of the given circle.
* @public @memberof SCircle
*
* @param self The circle to set the radius of.
* @param new_radius The new radius of the circle.
* @param error Error code.
*/
S_API void SCircleSetRadius(SCircle *self, int new_radius, s_erc *error);
/**
* Set the colour of the given circle.
* @public @memberof SCircle
*
* @param self The circle to set the colour of.
* @param new_colour The new colour of the circle.
* @param error Error code.
*/
S_API void SCircleSetColour(SCircle *self, const char *new_colour, s_erc *error);
/**
* Register the SCircle class to the object system.
* @private @memberof SCircle
*
* @param error Error code.
*/
S_LOCAL void _s_circle_class_reg(s_erc *error);
/**
* Free the SCircle class from the object system.
* @private @memberof SCircle
*
* @param error Error code.
*/
S_LOCAL void _s_circle_class_free(s_erc *error);
/************************************************************************************/
/* */
/* End external c declaration */
/* */
/************************************************************************************/
S_END_C_DECLS
/**
* @}
* end documentation
*/
#endif /* _SPCT_CIRCLE_EXAMPLE_H__ */
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 | /************************************************************************************/
/* */
/* Modules used */
/* */
/************************************************************************************/
#include "circle.h"
/************************************************************************************/
/* */
/* Macros */
/* */
/************************************************************************************/
/**
* @hideinitializer
* Call the given function method of the given #SCircle,
* see full description #S_CIRCLE_CALL for usage.
*
* @param SELF The given #SCircle*.
* @param FUNC The function method of the given object to call.
*
* @note This casting is not safety checked.
* @note Example usage:
@verbatim
S_CIRCLE_CALL(self, func)(param1, param2, ..., paramN);
@endverbatim
* where @c param1, @c param2, ..., @c paramN are the parameters
* passed to the object function @c func.
*/
#define S_CIRCLE_CALL(SELF, FUNC) \
((SCircleClass *)S_OBJECT_CLS(SELF))->FUNC
/**
* @hideinitializer
* Test if the given function method of the given #SCircle
* can be called.
*
* @param SELF The given #SCircle*.
* @param FUNC The function method of the given object to check.
*
* @return #TRUE if function can be called, otherwise #FALSE.
*
* @note This casting is not safety checked.
*/
#define S_CIRCLE_METH_VALID(SELF, FUNC) \
S_CIRCLE_CALL(SELF, FUNC) ? TRUE : FALSE
/************************************************************************************/
/* */
/* Static variables */
/* */
/************************************************************************************/
static SCircleClass CircleClass; /* Circle class declaration. */
/************************************************************************************/
/* */
/* Function implementations */
/* */
/************************************************************************************/
S_API SCircle *SCircleNew(int x, int y, int radius, const char *colour, s_erc *error)
{
SCircle *self;
S_CLR_ERR(error);
self = S_NEW(SCircle, error);
if (S_CHK_ERR(error, S_CONTERR,
"SCircleNew",
"Failed to create new object"))
{
return NULL;
}
S_SHAPE(self)->x = x;
S_SHAPE(self)->y = y;
self->radius = radius;
self->colour = s_strdup(colour, error);
if (S_CHK_ERR(error, S_CONTERR,
"SCircleNew",
"Call to \"s_strdup\" failed"))
{
S_DELETE(self, "SCircleNew", error);
return NULL;
}
return self;
}
S_API void SCircleSetRadius(SCircle *self, int new_radius, s_erc *error)
{
S_CLR_ERR(error);
if (self == NULL)
{
S_CTX_ERR(error, S_ARGERROR,
"SCircleSetRadius",
"Argument \"self\" is NULL");
return;
}
if (!S_CIRCLE_METH_VALID(self, set_radius))
{
S_CTX_ERR(error, S_METHINVLD,
"SCircleSetRadius",
"Circle method \"set_radius\" not implemented");
return;
}
S_CIRCLE_CALL(self, set_radius)(self, new_radius, error);
S_CHK_ERR(error, S_CONTERR,
"SCircleSetRadius",
"Call to class method \"set_radius\" failed");
}
S_API void SCircleSetColour(SCircle *self, const char *new_colour, s_erc *error)
{
S_CLR_ERR(error);
if (self == NULL)
{
S_CTX_ERR(error, S_ARGERROR,
"SCircleSetColour",
"Argument \"self\" is NULL");
return;
}
if (new_colour == NULL)
{
S_CTX_ERR(error, S_ARGERROR,
"SCircleSetColour",
"Argument \"new_colour\" is NULL");
return;
}
if (!S_CIRCLE_METH_VALID(self, set_colour))
{
S_CTX_ERR(error, S_METHINVLD,
"SCircleSetColour",
"Circle method \"set_colour\" not implemented");
return;
}
S_CIRCLE_CALL(self, set_colour)(self, new_colour, error);
S_CHK_ERR(error, S_CONTERR,
"SCircleSetColour",
"Call to class method \"set_colour\" failed");
}
/************************************************************************************/
/* */
/* Class registration */
/* */
/************************************************************************************/
S_LOCAL void _s_circle_class_reg(s_erc *error)
{
S_CLR_ERR(error);
s_class_reg(S_OBJECTCLASS(&CircleClass), error);
S_CHK_ERR(error, S_CONTERR,
"_s_circle_class_reg",
"Failed to register SCircleClass");
}
S_LOCAL void _s_circle_class_free(s_erc *error)
{
S_CLR_ERR(error);
s_class_free(S_OBJECTCLASS(&CircleClass), error);
S_CHK_ERR(error, S_CONTERR,
"_s_circle_class_free",
"Failed to free SCircleClass");
}
/************************************************************************************/
/* */
/* Static class function implementations */
/* */
/************************************************************************************/
static void InitCircle(void *obj, s_erc *error)
{
SCircle *self = obj;
S_CLR_ERR(error);
self->radius = 0;
self->colour = NULL;
}
static void DestroyCircle(void *obj, s_erc *error)
{
SCircle *self = obj;
S_CLR_ERR(error);
if (self->colour != NULL)
{
S_FREE(self->colour);
}
}
static void DisposeCircle(void *obj, s_erc *error)
{
S_CLR_ERR(error);
SObjectDecRef(obj);
}
static char *PrintCircle(const SObject *self, s_erc *error)
{
SCircle *cir = S_CIRCLE(self);
const char *type = "[SCircle] at (%d,%d), radius %d, colour %s";
char *buf;
S_CLR_ERR(error);
if (cir->colour == NULL)
{
s_asprintf(&buf, error, type, S_SHAPE(cir)->x, S_SHAPE(cir)->y, cir->radius, "None");
}
else
{
s_asprintf(&buf, error, type, S_SHAPE(cir)->x, S_SHAPE(cir)->y, cir->radius, cir->colour);
}
if (S_CHK_ERR(error, S_CONTERR,
"PrintCircle",
"Call to \"s_asprintf\" failed"))
{
if (buf != NULL)
S_FREE(buf);
return NULL;
}
return buf;
}
static void MoveCircle(SShape *self, int newx, int newy, s_erc *error)
{
SShapeClass *shapeClass = NULL;
S_CLR_ERR(error);
shapeClass = S_FIND_CLASS(SShape, error);
if (S_CHK_ERR(error, S_CONTERR,
"MoveCircle",
"Call to \"S_FIND_CLASS\" failed"))
return;
shapeClass->move(self, newx, newy, error);
}
static float AreaCircle(const SShape *self, s_erc *error)
{
SCircle *cir = S_CIRCLE(self);
float area;
S_CLR_ERR(error);
area = S_PI * cir->radius * cir->radius;
return area;
}
static void SetRadiusCircle(SCircle *self, int new_radius, s_erc *error)
{
S_CLR_ERR(error);
self->radius = new_radius;
}
static void SetColourCircle(SCircle *self, const char *new_colour, s_erc *error)
{
S_CLR_ERR(error);
if (self->colour != NULL)
S_FREE(self->colour);
self->colour = s_strdup(new_colour, error);
S_CHK_ERR(error, S_CONTERR,
"SetColourCircle",
"Call to \"s_strdup\" failed");
}
/************************************************************************************/
/* */
/* Class initialization */
/* */
/************************************************************************************/
static SCircleClass CircleClass =
{
{
/* SObjectClass */
{
"SShape:SCircle",
sizeof(SCircle),
{ 0, 1},
InitCircle, /* init */
DestroyCircle, /* destroy */
DisposeCircle, /* dispose */
NULL, /* compare */
PrintCircle, /* print */
NULL, /* copy */
},
/* SShapeClass */
MoveCircle, /* move */
AreaCircle, /* area */
},
/* SCircleClass */
SetRadiusCircle, /* set_radius */
SetColourCircle /* set_colour */
};
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 | #include <stdio.h>
#include "speect.h"
#include "shape.h"
#include "rectangle.h"
#include "circle.h"
/*
* register shape, rectangle and circle objects with the Speect object
* system.
*/
void register_objects(s_erc *error)
{
s_erc local_err = S_SUCCESS;
S_CLR_ERR(error);
_s_shape_class_reg(error);
if (S_CHK_ERR(error, S_CONTERR,
"register_objects",
"Call to \"_s_shape_class_reg\" failed"))
return;
_s_rectangle_class_reg(error);
if (S_CHK_ERR(error, S_CONTERR,
"register_objects",
"Call to \"_s_rectangle_class_reg\" failed"))
{
_s_shape_class_free(&local_err);
return;
}
_s_circle_class_reg(error);
if (S_CHK_ERR(error, S_CONTERR,
"register_objects",
"Call to \"_s_circle_class_reg\" failed"))
{
_s_rectangle_class_free(&local_err);
_s_shape_class_free(&local_err);
return;
}
}
/*
* free shape, rectangle and circle objects from the Speect object
* system.
*/
void free_objects(s_erc *error)
{
s_erc local_err = S_SUCCESS;
S_CLR_ERR(error);
_s_circle_class_free(&local_err);
if (S_CHK_ERR(&local_err, S_CONTERR,
"register_objects",
"Call to \"_s_circle_class_free\" failed"))
S_NEW_ERR(error, local_err);
_s_rectangle_class_free(&local_err);
if (S_CHK_ERR(&local_err, S_CONTERR,
"register_objects",
"Call to \"_s_rectangle_class_free\" failed"))
S_NEW_ERR(error, local_err);
_s_shape_class_free(&local_err);
if (S_CHK_ERR(&local_err, S_CONTERR,
"register_objects",
"Call to \"_s_shape_class_free\" failed"))
S_NEW_ERR(error, local_err);
}
int main()
{
s_erc error = S_SUCCESS;
SCircle *circleShape = NULL;
SRectangle *rectangleShape = NULL;
int rv = 0;
char *buf = NULL;
int registered = 0;
float area = 0.0;
/*
* initialize speect
*/
error = speect_init(NULL);
if (error != S_SUCCESS)
{
printf("Failed to initialize Speect\n");
return 1;
}
/*
* register SShape, SRectangle and SCircle classes with the Speect
* object system.
*/
register_objects(&error);
if (S_CHK_ERR(&error, S_CONTERR,
"main",
"Call to \"SRectangleNew\" failed"))
{
rv = 1;
goto quit;
}
else
{
registered = 1;
}
/*
* create new rectangle
*/
rectangleShape = SRectangleNew(10, 15, 100, 140, &error);
if (S_CHK_ERR(&error, S_CONTERR,
"main",
"Call to \"SRectangleNew\" failed"))
{
rv = 1;
goto quit;
}
/*
* Print the SRectangle object as an SObject
*/
buf = SObjectPrint(S_OBJECT(rectangleShape), &error);
if (S_CHK_ERR(&error, S_CONTERR,
"main",
"Call to \"SObjectPrint\" failed"))
{
rv = 1;
goto quit;
}
printf("%s\n", buf);
S_FREE(buf);
/* get the rectangle's area */
area = SShapeArea(S_SHAPE(rectangleShape), &error);
if (S_CHK_ERR(&error, S_CONTERR,
"main",
"Call to \"SShapeArea\" failed"))
{
rv = 1;
goto quit;
}
printf("rectangle area = %f\n\n", area);
/*
* create new circle
*/
circleShape = SCircleNew(20, 62, 70, "green", &error);
if (S_CHK_ERR(&error, S_CONTERR,
"main",
"Call to \"SCircleNew\" failed"))
{
rv = 1;
goto quit;
}
/*
* Print the SCircle object as an SObject
*/
buf = SObjectPrint(S_OBJECT(circleShape), &error);
if (S_CHK_ERR(&error, S_CONTERR,
"main",
"Call to \"SObjectPrint\" failed"))
{
rv = 1;
goto quit;
}
printf("%s\n", buf);
S_FREE(buf);
/* get the circle's area */
area = SShapeArea(S_SHAPE(circleShape), &error);
if (S_CHK_ERR(&error, S_CONTERR,
"main",
"Call to \"SShapeArea\" failed"))
{
rv = 1;
goto quit;
}
printf("circle area = %f\n\n", area);
/* move the rectangle to new coordinates */
SShapeMove(S_SHAPE(rectangleShape), 631, 103, &error);
if (S_CHK_ERR(&error, S_CONTERR,
"main",
"Call to \"SShapeMove\" failed"))
{
rv = 1;
goto quit;
}
/* move the circle to new coordinates */
SShapeMove(S_SHAPE(circleShape), 311, 67, &error);
if (S_CHK_ERR(&error, S_CONTERR,
"main",
"Call to \"SShapeMove\" failed"))
{
rv = 1;
goto quit;
}
/* set the width and height of the rectangle */
SRectangleSetWidth(rectangleShape, 32, &error);
if (S_CHK_ERR(&error, S_CONTERR,
"main",
"Call to \"SRectangleSetWidth\" failed"))
{
rv = 1;
goto quit;
}
SRectangleSetHeight(rectangleShape, 102, &error);
if (S_CHK_ERR(&error, S_CONTERR,
"main",
"Call to \"SRectangleSetHeight\" failed"))
{
rv = 1;
goto quit;
}
/* set the radius and colour of the circle */
SCircleSetRadius(circleShape, 34, &error);
if (S_CHK_ERR(&error, S_CONTERR,
"main",
"Call to \"SCircleSetRadius\" failed"))
{
rv = 1;
goto quit;
}
SCircleSetColour(circleShape, "red", &error);
if (S_CHK_ERR(&error, S_CONTERR,
"main",
"Call to \"SCircleSetColour\" failed"))
{
rv = 1;
goto quit;
}
/* print rectangle and circle attributes after all changes */
printf("attributes after changes\n");
/*
* Print the SRectangle object as an SObject
*/
buf = SObjectPrint(S_OBJECT(rectangleShape), &error);
if (S_CHK_ERR(&error, S_CONTERR,
"main",
"Call to \"SObjectPrint\" failed"))
{
rv = 1;
goto quit;
}
printf("%s\n", buf);
S_FREE(buf);
/* get the rectangle's area */
area = SShapeArea(S_SHAPE(rectangleShape), &error);
if (S_CHK_ERR(&error, S_CONTERR,
"main",
"Call to \"SShapeArea\" failed"))
{
rv = 1;
goto quit;
}
printf("rectangle area = %f\n\n", area);
/*
* Print the SCircle object as an SObject
*/
buf = SObjectPrint(S_OBJECT(circleShape), &error);
if (S_CHK_ERR(&error, S_CONTERR,
"main",
"Call to \"SObjectPrint\" failed"))
{
rv = 1;
goto quit;
}
printf("%s\n", buf);
S_FREE(buf);
/* get the circle's area */
area = SShapeArea(S_SHAPE(circleShape), &error);
if (S_CHK_ERR(&error, S_CONTERR,
"main",
"Call to \"SShapeArea\" failed"))
{
rv = 1;
goto quit;
}
printf("circle area = %f\n\n", area);
quit:
if (circleShape != NULL)
S_DELETE(circleShape, "main", &error);
if (rectangleShape != NULL)
S_DELETE(rectangleShape, "main", &error);
if (registered)
free_objects(&error);
/*
* quit speect
*/
error = speect_quit();
if (error != S_SUCCESS)
{
printf("Call to 'speect_quit' failed\n");
return 1;
}
return rv;
}
|