3 * libneuro, a light weight abstraction of high or lower libraries
4 * and toolkit for applications.
5 * Copyright (C) 2005-2006 Nicholas Niro, Robert Lemay
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
24 * interface to the EBUF header.
25 * EBUF is used in a same manner as we use linked lists;
26 * It is an easy way to have a growing structure array.
27 * The EBUF header elements are hidden to external programs.
30 /*-------------------- Extern Headers Including --------------------*/
33 /*-------------------- Local Headers Including ---------------------*/
36 /*-------------------- Main Module Header --------------------------*/
39 /*-------------------- Other ----------------------------*/
41 NEURO_MODULE_CHANNEL("ebuf");
43 /* take note that the typedef is in the ebuf.h header!!
45 * this is the core EBUF header. It is
46 * 16 bytes in size and handles structures
47 * so their use is memory leak less, safe and
48 * easy. There is only one of this header
49 * structure per EBUF iteration. The actual
50 * data we hold is in the **buffer variable!
54 /* this pointer will point to the structures
55 * the external programs give us. This is where the
56 * data is kept and grows.
60 /* how many overhead memory inside the **buffer we have
61 * allocated in advance.
65 /* the current total number of elements inside **buffer */
68 /* callback that is not necessarily needed. This callback
69 * is used if the input structure itself has allocated elements
70 * that needs to be freed for every iteration.
72 void (*callback
)(void *src
);
75 /* doesn't seem to be ISO C ANSI compliant.
76 * I'm leaving the code here for future
80 #define GIVEEBUF(__eng, __elem) \
82 register void ***__buf; \
84 if (__elem > __eng->total) \
86 __buf = (void***)&__eng->buffer; \
87 if ((*__buf)[__elem]) \
88 __result = (*__buf)[__elem]; \
94 /*-------------------- Global Variables ----------------------------*/
96 /*-------------------- Static Variables ----------------------------*/
98 /*-------------------- Static Prototypes ---------------------------*/
100 /*-------------------- Static Functions ----------------------------*/
102 /*-------------------- Global Functions ----------------------------*/
105 Neuro_CreateEBuf(EBUF
**eng
)
108 /* we allocate only the header EBUF structure */
109 *eng
= (EBUF
*)calloc(1, sizeof(EBUF
));
111 /* set ALL the elements in the header EBUF structure
112 * to their default NULL or 0 values.
116 (*eng
)->buffer
= NULL
;
117 (*eng
)->callback
= NULL
;
122 Neuro_SetcallbEBuf(EBUF
*eng
, void (*callback
)(void *src
))
124 eng
->callback
= callback
;
127 /* sptp stands for : size of the pointer type of the structure
128 * the external program will pass to EBUF. example :
129 * sizeof(struct foo *) or sizeof(foo *)
131 * sobj stands for : size of the actual structure the external
132 * program will pass to EBUF. example : sizeof(struct foo)
136 Neuro_AllocEBuf(EBUF
*eng
, size_t sptp
, size_t sobj
)
150 Debug_Val(0, "debug : %d\n", sptp);
151 Debug_Val(0, "before mem %d\n", mem);
156 NEURO_ERROR("Tried to allocate in a NULL buffer", NULL
);
160 /* we will allocate or reallocate the **
161 * which is what points to the * elements
165 /* we allocate extra amount of elements to speed up
166 * allocation time. MEMORY_ALLOC_OVERH is set in the
169 *buf
= calloc(MEMORY_ALLOC_OVERH
, sptp
);
172 /* we set the mem EBUF element to how many overhead
173 * times we could add data without the need to reallocate.
175 *mem
= MEMORY_ALLOC_OVERH
- 1;
177 else if ((*mem
* sptp
) < sptp
)
181 /* theres a big problem */
182 NEURO_ERROR("Memory buffer unknown error", NULL
);
186 /* we again allocate more memory than needed */
187 *buf
= realloc(*buf
, sptp
* (*total
+ MEMORY_ALLOC_OVERH
));
189 /* keep track of how many times we don't need to reallocate */
190 *mem
= MEMORY_ALLOC_OVERH
- 1;
194 /* We now will use an emplacement that was allocated in advance.
195 * Since we will use an element, we decrement the overhead EBUF
196 * mem variable value.
201 /* Debug_Val(0, "EBUF -- after mem %d\n", *mem); */
203 /* in addition to allocating the **buffer pointer, we also
204 * need to allocate the actual structure it will point to.
206 * in technical terms, we now allocate the * .
208 (*buf
)[*total
] = calloc(1, sobj
);
215 Neuro_MultiAllocEBuf(EBUF
*eng
, u32 amount
, size_t sptp
, size_t sobj
)
229 Neuro_AllocEBuf(eng, sptp, sobj);
237 Neuro_AllocEBuf(eng
, sptp
, sobj
);
241 /* we only do anything if the buffer doesn't contain anything
242 * to avoid memory leaks.
246 *buf
= calloc(amount
, sptp
);
253 /* we need to allocate every * elements in the ** */
256 (*buf
)[i
] = calloc(1, sobj
);
263 Neuro_SCleanEBuf(EBUF
*eng
, void *object
)
271 NEURO_WARN("Element eng or object is NULL", NULL
);
275 total
= Neuro_GiveEBufCount(eng
);
277 /* normally, EBUF functions input integers which are
278 * corresponding to the ** array. But in this function
279 * we input the actual pointer to the element.
281 * This puts the actual integer corresponding to the
282 * pointer object from the ** array and puts it in elem.
284 if (Neuro_GiveEBufElem(eng
, object
, &elem
))
286 NEURO_WARN("Element wasn't found in the buffer", NULL
);
290 /* we call the callback that will clean
291 * allocated pointers in the structure if
294 if (eng
->callback
!= NULL
)
295 eng
->callback(object
);
297 NEURO_TRACE("There's no cleaning callback for this buffer (this could be normal)", NULL
);
302 /* now that the object is freed, we will attempt to fill its
303 * emplacement with the last one.
306 /* check to see if the one we want to remove is the last one */
309 /* get the last one */
310 buf
= Neuro_GiveEBuf(eng
, total
);
312 /* make the one we just deleted point to the last one */
313 Neuro_SetEBuf(eng
, Neuro_GiveEBufAddr(eng
, elem
), buf
);
316 /* make the last element point to NULL so it can be reused*/
317 Neuro_SetEBuf(eng
, Neuro_GiveEBufAddr(eng
, total
), NULL
);
319 eng
->mem
++; /* add an extra mem because we now have an extra slot free */
325 Neuro_CleanEBuf(EBUF
**engi
)
332 * this is to avoid very big and puzzling call to the **engi element like
333 * (*engi)->mem or engi[0]->mem. This is for cleaner code.
343 /* loop all the elements in the EBUF **, call the
344 * callback(if theres one!) with the actual element
345 * as the argument and finally free the element.
347 * in short : free every * in the ** array.
352 buf
= Neuro_GiveEBuf(eng
, i
);
362 /* Debug_Val(0, "#%d -- cleaned\n", i); */
365 /* free the actual ** array */
366 if (eng
->buffer
!= NULL
)
372 /* Debug_Val(0, "cleaned %d elements\n", eng->total); */
376 /* free the actual EBUF structure */
385 Neuro_GiveEBufCount(EBUF
*eng
)
390 return (eng
->total
> 0 ? eng
->total
-1 : 0);
394 Neuro_GiveEBuf(EBUF
*eng
, u32 elem
)
399 if (Neuro_EBufIsEmpty(eng
))
402 if (elem
> eng
->total
)
406 if (eng
->buffer
[elem
])
407 return eng
->buffer
[elem
];
413 Neuro_GiveCurEBuf(EBUF
*eng
)
418 if (Neuro_EBufIsEmpty(eng
))
422 if (eng
->buffer
[eng
->total
- 1])
423 return (eng
->buffer
[eng
->total
- 1]);
429 Neuro_GiveEBufCore(EBUF
*eng
)
437 /* returns 1 on error and 0 if all is ok
439 * for a certain pointer, we return its corresponding array
443 Neuro_GiveEBufElem(EBUF
*eng
, void *object
, u32
*elem
)
459 buf
= Neuro_GiveEBuf(eng
, i
);
471 /* give the address of an EBUF * element */
473 Neuro_GiveEBufAddr(EBUF
*eng
, u32 elem
)
481 buf
= (void***)&eng
->buffer
;
484 return &(*buf
)[elem
];
489 /* to move EBUF elements from a position to another
490 * watch out for memory leaks!
493 Neuro_SetEBuf(EBUF
*eng
, void **to
, void *from
)
495 if (!eng
|| !to
|| !from
)
503 /* copy an EBUF header to another */
505 Neuro_CopyEBuf(EBUF
*to
, EBUF
*from
)
510 to
->buffer
= from
->buffer
;
512 to
->total
= from
->total
;
515 /* reset the EBUF element
517 * NOTE : should only be called if the EBUF address
518 * was passed to another EBUF or it was copied to another
519 * using the Neuro_CopyEBuf function!!!
520 * Else, there will be a big memory leak.
523 Neuro_ResetEBuf(EBUF
*eng
)
533 /* returns 1 if the EBUF is empty, 0 if its NOT empty and
534 * 2 if the EBUF passed does not exist. */
536 Neuro_EBufIsEmpty(EBUF
*eng
)
541 return (eng
->total
== 0 ? 1 : 0);