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
25 #include "neuro_engine.h"
26 #include <stdlib.h> /* for the size_t type */
34 * The EBUF module. Stands for Engine Buffer.
35 * Its primary use is to make the allocation and
36 * reallocation of structures quick and easy;
37 * It provides secure and easy ways to
38 * dynamically add, remove and modify entries
43 * INTRODUCTION : \n \n
44 * This manual presents the way the module has
45 * to be used (which functions to call and in what order) briefly,
46 * without however, going into too much details. The goal is to
47 * give a general insight as to which functions are needed to
48 * attain a result. \n \n \n
52 * To make use of even the slightest of this module, the first
53 * requirement is to create a pointer to an EBUF type. \n \n
55 * here's an example : EBUF *abuffer; \n \n
57 * You cannot use a direct variable like : EBUF abuffer --
58 * for parity reasons(safegard of the data integrity),
59 * the content of the structure is to remain hidden
60 * from external programs. \n
62 * The EBuf module is completely reentrant, meaning it does
63 * not contain global data in the module, making it
64 * thread safe. \n \n \n
67 * INITIALISING AND FREEING : \n \n
68 * Now that the EBUF pointer is created, the next step is to
69 * initialize it by using Neuro_CreateEBuf(3). Among other,
70 * it allocated enough memory for its own internal data and
71 * then resets them to default initial values. \n
73 * When no longer needed, the pointer should be freed by using
74 * Neuro_CleanEBuf(3). It frees the EBUF's internal buffer
75 * completely. In the case that the use of the EBUF pointer
76 * is needed after it is freed, the call of Neuro_CreateEBuf(3)
77 * is required again. In the case that just one element
78 * in the buffer needs to be freed, the use of
79 * Neuro_SCleanEBuf(3) is required. \n
81 * In addition to normal freeing, you can also set a callback
82 * right after the initialization using Neuro_SetcallbEBuf(3).
83 * The callback will be called for every elements that the
84 * EBUF contains right before they are freed (by either calling
85 * Neuro_CleanEBuf(3) or Neuro_SCleanEBuf(3)), permitting
86 * the manual freeing of allocated pointers inside the structure.
87 * Among other, this permits EBUF pointers to contain other
88 * EBUF pointers and/or manually allocated pointers and the
89 * hability to free them cleanly.\n \n \n
91 * ALLOCATING NEW DATA : \n \n
92 * by now, we have initalised and possibly set a callback to the
93 * instance, but we are still missing an important step :
94 * creating a structure template which the instance EBUF will
95 * contain. Theres only two ways to allocate : Neuro_AllocEBuf(3)
96 * and Neuro_MultiAllocEBuf(3)
97 * A basic structure template was used in the example in
98 * the man page for the function Neuro_AllocEBuf(3) which is
99 * exactly the function we need to use to allocate a new element.
102 * READ AND WRITE : \n \n
103 * reading from an ebuf element is quite easy, it works kind of
104 * the same as when you call malloc(). After calling Neuro_AllocEBuf(3)
105 * or Neuro_MultiAllocEBuf(3), you can use either Neuro_GiveEBuf(3)
106 * or Neuro_GiveCurEBuf(3). Those two functions return a void pointer
107 * which you simply put into the correct variable. You can then read
108 * or write from the structure directly. \n \n \n
110 * MOVING DATA : \n \n
111 * on certain occasions, you might want to change the order by which
112 * the data in the EBUF buffer is organised. This is needed when you
113 * want to sort the elements. For this effect, we actually need to use
114 * the function Neuro_SetEBuf(3) to copy a certain element to a
115 * precise address on the buffer. This can't be used directly, we
116 * actually need to get the address of the element we want to change.
117 * To get the address of a certain element, we need to use the function
118 * Neuro_GiveEBufAddr(3). \n
119 * Here's how we do it : \n \n
121 * -- in this code example, we will transfer the last element into -- \n
122 * -- a certain position in the buffer and transfer that certain -- \n
123 * -- position into the last place. -- \n \n
125 * -- ST is a structure we use throughout the EBUF man pages -- \n
126 * -- if you have no idea whats it for, check a few man paged -- \n
127 * -- on EBUF, especially the Neuro_SetcallbEBuf(3) one. -- \n
128 * -- we assume this pointer already points to an EBUF element -- \n
130 * u32 elem_value; \n \n
134 * -- we need the array number of the element to call the next -- \n
136 * if (Neuro_GiveEBufElem(myeng, element, &elem_value)) \n
137 * return; -- an error occured so we bail out -- \n
139 * -- we then copy the last element into that certain's element address -- \n
140 * Neuro_SetEBuf(myeng, Neuro_GiveEBufAddr(myeng, elem_value), Neuro_GiveCurEBuf(myeng)); \n \n
142 * -- now that we copied the address of the last element into -- \n
143 * -- our certain element. we need to copy our certain element into -- \n
144 * -- the last position. -- \n \n
146 * Neuro_SetEBuf(myeng, Neuro_GiveEBufAddr(myeng, Neuro_GiveEBufCount(myeng)), element); \n \n
148 * And thats it folks! Now, next time we loop the buffer, the order will have
149 * a certain element at the end and the last element in what ever position our
150 * certain element was.
153 * PLEASE NOTE : you CAN'T use the returned value of the function
154 * Neuro_GiveEBufCount(3) to FIGURE if the EBUF is empty (ie it
155 * doesn't contain any elements or isn't allocated by Neuro_CreateEBuf(3)).
156 * FOR THIS, you have to use the function Neuro_EBufIsEmpty(3) which returns
157 * 1 if the buffer can NOT be used and 0 if it CAN. Any use of an EBUF
158 * which returns 1 when you call Neuro_EBufIsEmpty(3) can create VERY
159 * unwanted results and VERY likely cause a segmentation fault.
162 * Neuro_CreateEBuf(3), Neuro_SetcallbEBuf(3),
163 * Neuro_AllocEBuf(3), Neuro_MultiAllocEBuf(3),
164 * Neuro_CleanEBuf(3), Neuro_SCleanEBuf(3),
165 * Neuro_GiveEBufCount(3), Neuro_GiveEBufElem(3),
166 * Neuro_GiveCurEBuf(3), Neuro_GiveEBufAddr(3),
167 * Neuro_GiveEBuf(3), Neuro_GiveEBufCore(3),
168 * Neuro_SetEBuf(3), Neuro_CopyEBuf(3),
169 * Neuro_ResetEBuf(3), Neuro_EBufIsEmpty(3)
173 * This macro is to set the number of extra instances
174 * of memory needs to be allocated per allocations.
175 * In theory, this is absolutely not needed but since
176 * the allocation proccess is slow, the less we do it,
177 * the better. 10 is a good default.
179 #define MEMORY_ALLOC_OVERH 10
186 * the Engine Buffer object. A pointer variable
187 * of this type is required.
188 * Example : EBUF *myeng;
190 * -- this is the struct we want to have buffered,
191 * -- meaning EBUF will keep and create instances of this struct.
198 typedef struct EBUF EBUF
;
202 * sole constructor of an EBUF element.
205 * This function initializes and makes operationnal
209 * the address of an EBUF pointer.
213 * static EBUF *myeng; \n \n
217 * Neuro_CreateEBuf(&myeng);
220 * Neuro_CleanEBuf(3), Neuro_AllocEBuf(3), Neuro_SetcallbEBuf(3),
221 * Neuro_EBufIsEmpty(3)
224 extern void Neuro_CreateEBuf(EBUF
**eng
);
226 /** Neuro_SetcallbEBuf
228 * Set a callback that will be called for each array elements
229 * when the EBUF element is cleaning itself after a call to Neuro_CleanEBuf
230 * or Neuro_SCleanEBuf.
233 * This function is used to set a callback function to the EBUF element.
234 * This callback function will be called (during the cleaning
235 * time) for every arrays right before they are each freed.
236 * This is so you can free custom stuff that you allocated in the
237 * struct you put in EBUF. The callback function will need a single
238 * argument which will be a void pointer. This will point to the
239 * array(single element of the big array) which is being freed.
246 * a callback which itself contain an argument to a void pointer.
250 * typedef struct ST \n
252 * char *someString; \n
256 * static EBUF *myeng; \n \n
259 * callbackclean(void *src) \n
263 * temp = (ST*)src; \n \n
267 * if (temp->someString) \n
268 * free(temp->someString); \n
274 * Neuro_CreateEBuf(&myeng); \n \n
275 * Neuro_SetcallbEBuf(myeng, callbackclean); \n \n
281 * Neuro_AllocEBuf(myeng, sizeof(ST*), sizeof(ST)); \n \n
283 * foo = Neuro_GiveCurEBuf(myeng); \n \n
285 * foo->someString = (char*)malloc(50); \n \n
289 * Neuro_CleanEBuf(&myeng);
292 * Neuro_CreateEBuf(3), Neuro_CleanEBuf(3)
295 extern void Neuro_SetcallbEBuf(EBUF
*eng
, void (*callback
)(void *src
));
299 * Simple Allocation and reallocation of an EBuf element.
302 * This function is pretty much the most useful function in the lot,
303 * it actually creates a new "slot" which can then be used to add
304 * data to an EBUF element. This function and Neuro_MultiAllocEBuf
305 * are the two only functions which allocate/reallocate memory in
308 * Take good note that an EBUF element can buffer
309 * any kinds of structure (so it can dynamically grow easily and avoid memory
310 * leaks). To support this, this function needs only 2 informations
311 * about the structure :
312 * the size of its pointer form and the size of its normal form. It might
313 * also be possible to work with other variable types than structures, although
314 * it is not really recommended unless you know what you are doing.
320 * the size of the pointer form of the structure (usually sizeof can be used to find it).
323 * the size of the normal form of the structure (usually sizeof can be used to find it).
326 * typedef struct ST \n
332 * static EBUF *myeng; \n \n
337 * Neuro_CreateEBuf(&myeng); \n \n
341 * Neuro_AllocEBuf(myeng, sizeof(ST*), sizeof(ST)); \n \n
345 * Neuro_CleanEBuf(&myeng);
348 * Neuro_GiveEBufCount(3), Neuro_GiveEBuf(3), Neuro_GiveCurEBuf(3),
349 * Neuro_MultiAllocEBuf(3)
351 extern void Neuro_AllocEBuf(EBUF
*eng
, size_t sptp
, size_t sobj
);
354 /** Neuro_MultiAllocEBuf
356 * initial allocation of a bigger amount of slots than one.
359 * This function works exactly the same as Neuro_AllocEBuf except
360 * for one single thing : It can allocate more than one slot at once.
361 * Take very good note that this will only work if the EBUF object hasn't
362 * been allocated before, ie only if it is empty. For security purpose, this
363 * function won't work if theres already allocated slots in the EBUF.
369 * the amount of slots to allocate.
372 * the size of the pointer form of the structure (usually sizeof can be used to find it).
375 * the size of the normal form of the structure (usually sizeof can be used to find it).*
378 * see the example in Neuro_AllocEBuf(3)
381 * Neuro_GiveEBufCount(3), Neuro_GiveEBuf(3), Neuro_GiveCurEBuf(3),
384 extern void Neuro_MultiAllocEBuf(EBUF
*eng
, u32 amount
, size_t sptp
, size_t sobj
);
388 * Standard destructor of an EBUF element.
394 * the address of an EBUF pointer.
398 * static EBUF *myeng; \n \n
402 * Neuro_CreateEBuf(&myeng);
406 * Neuro_CleanEBuf(&myeng);
409 * Neuro_CreateEBuf(3), Neuro_AllocEBuf(3), Neuro_SetcallbEBuf(3),
410 * Neuro_SCleanEBuf(3)
413 extern void Neuro_CleanEBuf(EBUF
**eng
);
417 * cleans/frees one element.
420 * This function's purpose is to clean elements in a similar
421 * manner as Neuro_CleanEBuf(3) but it only
422 * cleans one element. Take note that the callback
423 * which can be set using the function Neuro_SetcallbEBuf(3) is also called with this function.
429 * the pointer to an element contained in the EBUF buffer which needs to be cleaned.
433 * typedef struct ST \n
435 * char *someString; \n
438 * static EBUF *myeng; \n \n
442 * Neuro_CreateEBuf(&myeng); \n \n
448 * Neuro_AllocEBuf(myeng, sizeof(ST*), sizeof(ST)); \n \n
450 * buf = Neuro_GetCurEBuf(myeng); \n \n
452 * buf->someString = "hello"; \n \n
454 * -- lets say we no longer need the variable -- \n
455 * -- we can clean it using this function -- \n
456 * Neuro_SCleanEBuf(myeng, buf); \n \n
460 * Neuro_CleanEBuf(&myeng); \n \n
463 * Neuro_CreateEBuf(3), Neuro_AllocEBuf(3), Neuro_SetcallbEBuf(3), Neuro_CleanEBuf(3), Neuro_GiveEBuf(3), Neuro_GiveCurEBuf(3)
466 extern void Neuro_SCleanEBuf(EBUF
*eng
, void *object
);
468 /** Neuro_GiveEBufCount
471 * give the count of elements in the array
474 * This function returns the number of elements contained
475 * in the core buffer. Each elements in the buffer are ordered
476 * in the order they were "pushed" into the buffer thus this
477 * value can be used to loop the buffer for all the elements
478 * one after the other. NOTE This function returns 0 when theres only
479 * one element and it can't return negative values so it cannot
480 * be used to know if the buffer is empty or not! Use the function
481 * Neuro_EBufIsEmpty(3) to check if its empty or not.
487 * the amount of elements in the EBUF element.
491 * -- in this example, I ommited the initial creation of the buffer, -- \n
492 * -- the final cleaning of the buffer, -- \n
493 * -- the cleaning callback function, -- \n
494 * -- the allocation of the buffer and -- \n
495 * -- the struct ST and its typedef. -- \n
496 * -- SEE the man page for the function Neuro_AllocEBuf(3) for those -- \n
497 * -- and SEE the man page for Neuro_SetcallbEBuf(3) for the callback -- \n \n
500 * unsigned int total = 0; \n \n
502 * -- we check if the buffer is empty -- \n
503 * if (Neuro_EBufIsEmpty(myeng)) \n
506 * -- we get the total number of elements in myeng -- \n
507 * -- and also increment it by one because we will -- \n
508 * -- loop the elements from finish to start -- \n
509 * total = Neuro_GiveEBufCount(myeng) + 1; \n \n
511 * while (total-- > 0) \n
513 * buf = Neuro_GiveEBuf(myeng, total); \n \n
520 * Neuro_AllocEBuf(3), Neuro_GiveEBuf(3),
521 * Neuro_GiveCurEBuf(3), Neuro_EBufIsEmpty(3)
523 extern u32
Neuro_GiveEBufCount(EBUF
*eng
);
525 /** Neuro_GiveEBufElem
527 * output the array number of the element object
530 * This function is used to get the array number
531 * of a structure pointer which is inside
532 * the buffer eng. If the element is not
533 * contained inside the buffer, this will
534 * return 1 and 0 on success. Make sure to
535 * put either a real integer or an allocated
536 * one's address for the *elem argument.
542 * a void pointer of an element
543 * of which the array number will be put
544 * in the output integer.
547 * the array number of the element in the
551 * either 0 or 1. 1 on error (when the pointer object is not
552 * found in the buffer eng or when the buffer eng is NULL).
557 * typedef struct ST \n
559 * char *someString; \n
562 * -- we create a struct element -- \n
563 * -- called an_element into which -- \n
564 * -- we will put the address of an ebuf allocated element -- \n
565 * -- this method can be used to track certain key elements inside the buffer. -- \n
567 * static ST *an_element; \n \n
569 * static EBUF *myeng; \n \n
572 * callbackclean(void *src) \n
576 * temp = (ST*)src; \n \n
580 * if (temp->someString) \n
581 * free(temp->someString); \n
587 * Neuro_CreateEBuf(&myeng); \n \n
588 * Neuro_SetcallbEBuf(myeng, callbackclean); \n \n
594 * Neuro_AllocEBuf(myeng, sizeof(ST*), sizeof(ST)); \n \n
596 * foo = Neuro_GiveCurEBuf(myeng); \n \n
599 * foo->someString = (char*)malloc(50); \n \n
601 * -- we set our variable to the address that the pointer foo points to -- \n
602 * -- this makes it behave the exact same as if it was actually -- \n
603 * -- the pointer foo... we can then access the data from it -- \n
604 * -- for any purpose and fast. -- \n
605 * an_element = foo; \n \n
609 * -- in a certain function, we use the content of the pointer an_element -- \n
610 * -- but for certain cases we also need to get its array number. -- \n
611 * -- This only works if this particular pointer was allocated in an EBUF. -- \n \n
613 * u32 elem_value = 0; \n \n
615 * if (Neuro_GiveEBufElem(myeng, an_element, &elem_value)) \n
617 * printf("an error happened, the element (an_element) wasn't found in the buffer (myeng)\n"); \n
621 * -- now, if there wasn't any errors, the variable an_element -- \n
622 * -- contains the array number for the pointer an_element. -- \n
623 * -- this number can be used with the function Neuro_GiveEBuf(3) or Neuro_GiveEBufAddr(3). \n \n
627 * Neuro_CleanEBuf(&myeng);
632 * Neuro_GiveEBufAddr(3), Neuro_GiveEBuf
634 extern int Neuro_GiveEBufElem(EBUF
*eng
, void *object
, u32
*elem
);
636 /** Neuro_GiveCurEBuf
638 * outputs the last element of the buffer.
641 * before this function, we had to get the number of
642 * elements from the buffer using Neuro_GiveEBufCount(3)
643 * and then call Neuro_GiveEBuf(3) to get the element.
644 * Now, this function can be used to have the exact same
645 * result but in just one call.
651 * the pointer of the element. It returns NULL on error.
654 * -- see the man page for Neuro_GiveEBuf(3) for how this -- \n
655 * -- function can be used. Also, almost all the functions -- \n
656 * -- use this function in their examples so just check how --\n
657 * -- they use it... usually, this function is called right -- \n
658 * -- after you allocate the buffer using Neuro_AllocEBuf(3), -- \n
659 * -- because we need to get the pointer so we can populate it. -- \n
662 * Neuro_AllocEBuf(3), Neuro_MultiAllocEBuf(3),
665 extern void *Neuro_GiveCurEBuf(EBUF
*eng
);
667 /** Neuro_GiveEBufAddr
670 * gives the real address of the element of the array number elem.
673 * this function is essential in the event that you want
674 * to change the order into which the EBUF buffer is.
680 * the array number of the element you want the pointer address.
683 * the pointer to a pointer which contains the address of the
687 * see the Neuro_EBuf(3) man page on section MOVING DATA for
688 * an example on how to use this function.
691 * Neuro_GiveEBufElem(3), Neuro_SetEBuf(3),
693 extern void **Neuro_GiveEBufAddr(EBUF
*eng
, u32 elem
);
698 * gives the element corresponding to the number input in
702 * This function is the default way of getting the
703 * pointer of an allocated element. The pointer can
704 * be used to access the data and read/write to it.
710 * this argument corresponds to the element number
711 * that you want to fetch from the buffer.
714 * the pointer to the element from the EBUF. As a void pointer
715 * so it is possible to "morph" it into any other pointer type.
719 * typedef struct ST \n
721 * char *someString; \n
724 * static EBUF *myeng; \n \n
727 * callbackclean(void *src) \n
731 * temp = (ST*)src; \n \n
735 * if (temp->someString) \n
736 * free(temp->someString); \n
742 * Neuro_CreateEBuf(&myeng); \n \n
743 * Neuro_SetcallbEBuf(myeng, callbackclean); \n \n
749 * Neuro_AllocEBuf(myeng, sizeof(ST*), sizeof(ST)); \n \n
751 * foo = Neuro_GiveCurEBuf(myeng); \n \n
754 * foo->someString = (char*)malloc(50); \n \n
758 * -- this code outputs to the default output channel -- \n
759 * -- the content of every elements of the buffer -- \n
763 * if (Neuro_EBufIsEmpty(myeng))
766 * total = Neuro_GiveEBufCount(myeng) + 1;
768 * while (total-- > 0)
770 * temp = Neuro_GiveEBuf(myeng, total);
772 * printf("some value : %s\n", temp->someString);
777 * Neuro_CleanEBuf(&myeng); \n
781 * Neuro_AllocEBuf(3), Neuro_MultiAllocEBuf(3),
782 * Neuro_GiveEBufCount(3)
784 extern void *Neuro_GiveEBuf(EBUF
*eng
, u32 elem
);
786 /** Neuro_GiveEBufCore
788 * give the core buffer of the EBuf element
791 * this function should never be used, it returns
792 * the actual pointer of the CORE of an EBUF element.
793 * The need of this function is very close to Nill
794 * and it is strongly advised to avoid the use of this
795 * function at all cost.
801 * the CORE of the EBUF's main (and only) buffer.
804 * this function was initially made for bitmap loading
805 * in neuro extlib, it permitted to input simple string
806 * elements and then the ability to give this core
807 * to the pixmap library so it would load the bitmap
808 * from it. This use was considered a BIG HACK. The neuro
809 * bitmap loading code stopped using this function quite
810 * a long time ago so it is unused anywhere.
812 * Neuro_SCleanEBuf(3) Neuro_GiveEBufAddr(3)
813 * Neuro_GiveEBufAddr(3), Neuro_SetEBuf(3),
814 * Neuro_CopyEBuf(3), Neuro_ResetEBuf(3)
816 extern void **Neuro_GiveEBufCore(EBUF
*eng
);
822 * copy the actual content to another position in the
826 * this function is a key element for the task of sorting
827 * elements among the other elements in the buffer.
833 * the actual address of the pointer of an element from the EBUF.
834 * This informations can ONLY be given by the function
835 * Neuro_GiveEBufAddr(3).
838 * the pointer of the element to copy to the address to.
841 * see the Neuro_EBuf(3) man page on section MOVING DATA for
842 * an example on how to use this function. *
845 * Neuro_GiveEBufAddr(3), Neuro_GiveEBufElem(3)
847 extern void Neuro_SetEBuf(EBUF
*eng
, void **to
, void *from
);
851 * copy the content of an EBUF variable to another EBUF variable.
854 * nothing unusual with this function, it simply cleanly copies the
855 * content of an already created EBUF element to another one
856 * that wasn't created yet. If copy an EBUF to another that
857 * already contains data, you'll create a big memory leak.
858 * Note : this function is very fast because it is only copies addresses.
859 * Note2 : Also note that only one of the two needs to be cleaned;
860 * they both contain the same addresses.
866 * an EBUF pointer which gets copied into the EBUF to.
869 * static EBUF *myeng; \n \n
873 * Neuro_CreateEBuf(&myeng); \n \n
879 * Neuro_CopyEBuf(clone, myeng);
883 * Neuro_CleanEBuf(&myeng);
889 extern void Neuro_CopyEBuf(EBUF
*to
, EBUF
*from
);
893 * resets the EBUF variable WITHOUT FREEING IT -- Warning this
894 * is a mem leak if you didn't copy the content to another one
897 * use the function Neuro_CopyEBuf(3) to backup the addresses for
898 * the cleaning process prior to using this function please.
906 extern void Neuro_ResetEBuf(EBUF
*eng
);
910 * this is a simple boolean returning function that returns
911 * 1 if [eng] is empty and 0 if it holds stuff.
914 * this function is the only way to know if an EBUF is empty
915 * or not, you CAN'T use the function Neuro_GiveEBufCount(3)
922 * 1 if the EBUF is empty and should not be used and 0 if it
923 * was created and populated.
926 * Neuro_GiveEBufCount(3)
928 extern u8
Neuro_EBufIsEmpty(EBUF
*eng
);
934 #endif /* not __EBUF_H */