1 /**************************************************************************** 2 * Copyright (C) 2012 by Matteo Franchin * 3 * * 4 * This file is part of Box. * 5 * * 6 * Box is free software: you can redistribute it and/or modify it * 7 * under the terms of the GNU Lesser General Public License as published * 8 * by the Free Software Foundation, either version 3 of the License, or * 9 * (at your option) any later version. * 10 * * 11 * Box is distributed in the hope that it will be useful, * 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of * 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * 14 * GNU Lesser General Public License for more details. * 15 * * 16 * You should have received a copy of the GNU Lesser General Public * 17 * License along with Box. If not, see <http://www.gnu.org/licenses/>. * 18 ****************************************************************************/ 19 20 /** 21 * @file obj.h 22 * @brief Definition of object allocation and managig functions. 23 * 24 * This module defines basic functions to allocate Box objects and manage 25 * them. 26 */ 27 28 #ifndef _BOX_OBJ_H 29 # define _BOX_OBJ_H 30 31 #include <box/types.h> 32 #include <box/exception.h> 33 34 /** 35 * @brief Initialize a subtype. 36 * 37 * @param st Pointer to a region of memory ready to contain a #BoxSubtype 38 * object. 39 */ 40 BOXEXPORT void 41 BoxSubtype_Init(BoxSubtype *st); 42 43 /** 44 * @brief Finalize a subtype. 45 * 46 * @param Pointer to the subtype. 47 */ 48 BOXEXPORT void 49 BoxSubtype_Finish(BoxSubtype *st); 50 51 /** 52 * A pointer to a target object decorated with the type of the target. 53 * This is using for boxing/unboxing objects. 54 */ 55 typedef struct { 56 BoxType *type; 57 BoxPtr ptr; 58 } BoxAny; 59 60 # define BoxAny_Init(obj) \ 61 do {(obj)->type = NULL; BoxPtr_Init(& (obj)->ptr);} while(0) 62 63 /** 64 * @brief Get the type of the object stored inside the #BoxAny object. 65 */ 66 # define BoxAny_Get_Type(obj) \ 67 ((obj)->type) 68 69 /** 70 * @brief Get the pointer to the object stored inside the #BoxAny object. 71 */ 72 # define BoxAny_Get_Obj(obj) \ 73 (& (obj)->ptr) 74 75 /** 76 * Finalize an Any object. 77 */ 78 BOXEXPORT void 79 BoxAny_Finish(BoxAny *any); 80 81 /** 82 * @brief Copy an #Any object. 83 * 84 * @param dst An uninitialized region of memory which can contain a #BoxAny 85 * object. 86 * @param src The initialized #BoxAny object to copy. 87 */ 88 BOXEXPORT void 89 BoxAny_Copy(BoxAny *dst, BoxAny *src); 90 91 /** 92 * @brief Change the boxed object stored inside the given any object. 93 * 94 * @param any The ANY object which should be changed to reference @p obj. 95 * @param obj The object which should be put inside @p any. 96 * @param t The type of @p obj. 97 * @param safe If this is @c BOXBOOL_TRUE, then the object in @p obj is copied 98 * whenever it is a NULL-block pointer. Otherwise, the object is not copied 99 * which is unsafe as the Any object may survive even after @p obj is 100 * deallocated. 101 * @return Whether the boxing operation was successful. 102 */ 103 BOXEXPORT BoxBool 104 BoxAny_Box(BoxPtr *any, BoxPtr *obj, BoxType *t, BoxBool weak); 105 106 /** 107 * @brief Retrieve the boxed object stored inside the given any object. 108 * 109 * @param obj An unitialised pointer which will be set with a fresh reference 110 * to the object contained inside @p any. 111 * @param any The @c ANY object containing the boxed object. 112 * @param t The type of the boxed object. 113 * @return Whether the unboxing operation was successful. Unboxing @p any can 114 * be done only if the contained object has a type which matches @p t. 115 */ 116 BOXEXPORT BoxBool 117 BoxAny_Unbox(BOXOUT BoxPtr *obj, BoxPtr *any, BoxType *t); 118 119 /** 120 * @brief C counterpart of the Box Set type, used to set items in containers. 121 */ 122 typedef struct { 123 BoxAny index, /**< Index for the set operation. */ 124 value; /**< Value for the set operation. */ 125 } BoxSet; 126 127 /** 128 * Object header. Every object allocation includes some extra space to contain 129 * This structure, which contains the type of the object and the number of 130 * references that other objects make to it. 131 */ 132 typedef struct BoxObjHeader_struct { 133 size_t num_refs; 134 BoxType *type; 135 } BoxObjHeader; 136 137 /** 138 * Single Pointer to a Box object. 139 */ 140 typedef void *BoxSPtr; 141 142 /** 143 * @brief Allocate space for an object of the given type. 144 * 145 * This is an internal function which is not meant to be used externally. 146 */ 147 BOXEXPORT BoxSPtr 148 BoxSPtr_Alloc(BoxType *t); 149 150 /** 151 * @brief Raw allocation function. 152 * 153 * This is an internal function which is not meant to be used externally. 154 */ 155 BOXEXPORT BoxSPtr 156 BoxSPtr_Raw_Alloc(BoxType *t, size_t obj_size); 157 158 /** 159 * @brief Add a reference to an object and return it. 160 * 161 * @param src The object to reference. 162 * @return Return its argument, src. 163 */ 164 BOXEXPORT BoxSPtr 165 BoxSPtr_Link(BoxSPtr src); 166 167 /** 168 * This function, which should be used in conjunction with BoxSPtr_Unlink_End, 169 * allows unlinking an object and performing some extra operations before 170 * object destruction. It should be used in the following way: 171 * @code 172 * if (BoxSPtr_Unlink_Begin(src)) { 173 * // do something 174 * BoxSPtr_Unlink_End(src); 175 * } 176 * @endcode 177 * The function BoxSPtr_Unlink_Begin checks the reference counts of src. If 178 * this is greater than one, then the reference count is decreased and 179 * BOXBOOL_FALSE is returned. If the reference count is one, then the function 180 * does not change the reference count, but rather returns BOXBOOL_TRUE. 181 * The function BoxSPtr_Unlink_End does finally increase the reference count 182 * and destroy the object. 183 * @param src Object to unlink. 184 * @return BOXBOOL_TRUE if the object has just one reference, otherwise return 185 * BOXBOOL_FALSE. 186 * @see BoxSPtr_Unlink 187 */ 188 BOXEXPORT BoxBool 189 BoxSPtr_Unlink_Begin(BoxSPtr src); 190 191 /** 192 * @brief Function to be used in conjunction with BoxSPtr_Unlink_Begin. 193 * 194 * @see BoxSPtr_Unlink_Begin 195 */ 196 BOXEXPORT void 197 BoxSPtr_Unlink_End(BoxSPtr src); 198 199 /** 200 * @brief Remove a reference to an object, destroying it, if unreferenced. 201 * 202 * @param src Object to unreference. 203 * @return src if the object was unreferenced but not destroyed, NULL if the 204 * object was unreferenced and destroyed. 205 */ 206 BOXEXPORT BoxSPtr 207 BoxSPtr_Unlink(BoxSPtr src); 208 209 /** 210 * @brief Get the type of the allocated object. 211 * 212 * @param obj An object allocated with BoxSPtr_Alloc() or BoxSPtr_Raw_Alloc(). 213 * @return The type of @p obj. 214 */ 215 BOXEXPORT BoxType * 216 BoxSPtr_Get_Type(BoxSPtr obj); 217 218 /** 219 * @brief Reference the given object. 220 * 221 * @param src Object to reference. 222 * @return @p src is returned. 223 */ 224 BOXEXPORT BoxPtr * 225 BoxPtr_Link(BoxPtr *src); 226 227 /** 228 * @brief Remove a reference to an object, destroying it, if unreferenced. 229 * 230 * @param src Object to unreference. 231 * @return @c BOXBOOL_TRUE if the object was unreferenced but not destroyed, 232 * @c BOXBOOL_FALSE if the object was unreferenced and also destroyed. 233 */ 234 BOXEXPORT BoxBool 235 BoxPtr_Unlink(BoxPtr *src); 236 237 /** 238 * @brief Create a new object of the given type and return a pointer to it. 239 * 240 * @param ptr Location where to put the pointer to the object. 241 * @param t The type descriptor. 242 * @return Whether the operation was successful. 243 */ 244 BOXEXPORT BoxBool 245 BoxPtr_Create_Obj(BOXOUT BoxPtr *ptr, BoxType *t); 246 247 /** 248 * @brief Copy an object of the given type. 249 * 250 * @param dst Pointer to the destination. 251 * @param src Pointer to the source. 252 * @param t The type descriptor. 253 * @return Whether the operation was successful. 254 */ 255 BOXEXPORT BoxBool 256 BoxPtr_Copy_Obj(BoxPtr *dst, BoxPtr *src, BoxType *t); 257 258 /** 259 * @brief Try to convert a BoxPtr object to a simple single pointer. 260 * 261 * This function returns the a pointer @c sptr, if a pointer @c src exists such 262 * that @p src can be obtained from <tt>BoxPtr_Init_From_SPtr(src, sptr)</tt>. 263 * 264 * @param src The input double pointer. 265 * @return The single pointer corresponding to @p src, or @c NULL if such 266 * @c src cannot be expressed by using a single pointer. 267 */ 268 BOXEXPORT void * 269 BoxPtr_Get_SPtr(const BoxPtr *src); 270 271 /** 272 * @brief Combine two objects from their types and pointers. 273 * 274 * @see Box_Combine_Any 275 */ 276 BOXEXPORT BoxBool 277 Box_Combine(BoxType *t_parent, BoxPtr *parent, 278 BoxType *t_child, BoxPtr *child, BoxException **except); 279 280 /** 281 * @brief Combine two objects boxed as #BoxAny objects. 282 * 283 * @param parent A #BoxAny object containing the parent. 284 * @param child A #BoxAny object containing the child. 285 * @param except Pointer where to store a #BoxException, in case the 286 * combination is found and returns with failure. 287 * @return @c BOXBOOL_TRUE if the combination was found, else @c BOXBOOL_FALSE. 288 * 289 * @note <tt>*except</tt> is set only when the function returns @c BOXBOOL_TRUE. 290 * @see Box_Combine 291 */ 292 BOXEXPORT BoxBool 293 Box_Combine_Any(BoxAny *parent, BoxAny *child, BoxException **except); 294 295 #endif /* _BOX_OBJ_H */ 296