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 */
35 * \\fIEBuf\\fR stands for Engine Buffer.
36 * Its primary use is to make structures
37 * \\fIallocation\\fR and \\fIreallocation\\fR quick
38 * and easy; It provides \\fIsecure\\fR and easy ways to
39 * dynamically \\fIadd\\fR, \\fIremove\\fR and \\fImodify\\fR entries
44 * INTRODUCTION : \n \n
46 * This \\fImanual\\fR presents the way the module has
47 * to be used (which \\fIfunctions\\fR to call and in what order)
49 * without going into too much details. The goal of this \\fImanual\\fR
50 * is to give a general insight as to which functions are
51 * needed to attain a result. \n \n \n
56 * To make use of even the slightest of this module, the first
57 * requirement is to create a \\fIpointer\\fR to an EBUF type. \n \n
59 * \\fIhere's an example\\fR : EBUF *abuffer; \n \n
61 * You cannot use a direct variable like : EBUF abuffer --
62 * for parity reasons(safegard of the data integrity),
63 * the content of the structure is to remain hidden
64 * from external programs. \n
66 * The EBuf module is completely reentrant, meaning it does
67 * not contain global data in the module, making it
68 * thread safe. \n \n \n
71 * INITIALISING AND FREEING : \n \n
73 * Now that the EBUF pointer is created, the next step is to
74 * initialize it by using Neuro_CreateEBuf(3). Among other,
75 * it allocated enough memory for its own internal data and
76 * then resets them to default initial values. \n
78 * When no longer needed, the pointer should be freed by using
79 * Neuro_CleanEBuf(3). It frees the EBUF's internal buffer
80 * completely. In the case that the use of the EBUF pointer
81 * is needed after it is freed, the call of Neuro_CreateEBuf(3)
82 * is required again. In the case that just one element
83 * in the buffer needs to be freed, the use of
84 * Neuro_SCleanEBuf(3) is required. \n
86 * In addition to normal freeing, you can also set a callback
87 * right after the initialization using Neuro_SetcallbEBuf(3).
88 * The callback will be called for every elements that the
89 * EBUF contains right before they are freed (by either calling
90 * Neuro_CleanEBuf(3) or Neuro_SCleanEBuf(3)), permitting
91 * the manual freeing of allocated pointers inside the structure.
92 * Among other, this permits EBUF pointers to contain other
93 * EBUF pointers and/or manually allocated pointers and the
94 * hability to free them cleanly.\n \n \n
96 * ALLOCATING NEW DATA : \n \n
98 * by now, we have initalised and possibly set a callback to the
99 * instance, but we are still missing an important step :
100 * creating a structure template which the instance EBUF will
101 * contain. Theres only two ways to allocate : Neuro_AllocEBuf(3)
102 * and Neuro_MultiAllocEBuf(3)
103 * A basic structure template was used in the example in
104 * the man page for the function Neuro_AllocEBuf(3) which is
105 * exactly the function we need to use to allocate a new element.
108 * READ AND WRITE : \n \n
109 * reading from an ebuf element is quite easy, it works kind of
110 * the same as when you call malloc(). After calling Neuro_AllocEBuf(3)
111 * or Neuro_MultiAllocEBuf(3), you can use either Neuro_GiveEBuf(3)
112 * or Neuro_GiveCurEBuf(3). Those two functions return a void pointer
113 * which you simply put into the correct variable. You can then read
114 * or write from the structure directly. \n \n \n
116 * MOVING DATA : \n \n
118 * on certain occasions, you might want to change the order by which
119 * the data in the EBUF buffer is organised. This is needed when you
120 * want to sort the elements. For this effect, we actually need to use
121 * the function Neuro_SetEBuf(3) to copy a certain element to a
122 * precise address on the buffer. This can't be used directly, we
123 * actually need to get the address of the element we want to change.
124 * To get the address of a certain element, we need to use the function
125 * Neuro_GiveEBufAddr(3). \n
126 * Here's how we do it : \n \n
128 * -- in this code example, we will transfer the last element into -- \n
129 * -- a certain position in the buffer and transfer that certain -- \n
130 * -- position into the last place. -- \n \n
132 * -- ST is a structure we use throughout the EBUF man pages -- \n
133 * -- if you have no idea whats it for, check a few man paged -- \n
134 * -- on EBUF, especially the Neuro_SetcallbEBuf(3) one. -- \n
135 * -- we assume this pointer already points to an EBUF element -- \n
137 * u32 elem_value; \n \n
141 * -- we need the array number of the element to call the next -- \n
143 * if (Neuro_GiveEBufElem(myeng, element, &elem_value)) \n
144 * return; -- an error occured so we bail out -- \n
146 * -- we then copy the last element into that certain's element address -- \n
147 * Neuro_SetEBuf(myeng, Neuro_GiveEBufAddr(myeng, elem_value), Neuro_GiveCurEBuf(myeng)); \n \n
149 * -- now that we copied the address of the last element into -- \n
150 * -- our certain element. we need to copy our certain element into -- \n
151 * -- the last position. -- \n \n
153 * Neuro_SetEBuf(myeng, Neuro_GiveEBufAddr(myeng, Neuro_GiveEBufCount(myeng)), element); \n \n
155 * And thats it folks! Now, next time we loop the buffer, the order will have
156 * a certain element at the end and the last element in what ever position our
157 * certain element was.
160 * PLEASE NOTE : you CAN'T use the returned value of the function
161 * Neuro_GiveEBufCount(3) to FIGURE if the EBUF is empty (ie it
162 * doesn't contain any elements or isn't allocated by Neuro_CreateEBuf(3)).
163 * FOR THIS, you have to use the function Neuro_EBufIsEmpty(3) which returns
164 * 1 if the buffer can NOT be used and 0 if it CAN. Any use of an EBUF
165 * which returns 1 when you call Neuro_EBufIsEmpty(3) can create VERY
166 * unwanted results and VERY likely cause a segmentation fault.
169 * Neuro_CreateEBuf(3), Neuro_SetcallbEBuf(3),
170 * Neuro_AllocEBuf(3), Neuro_MultiAllocEBuf(3),
171 * Neuro_CleanEBuf(3), Neuro_SCleanEBuf(3),
172 * Neuro_GiveEBufCount(3), Neuro_GiveEBufElem(3),
173 * Neuro_GiveCurEBuf(3), Neuro_GiveEBufAddr(3),
174 * Neuro_GiveEBuf(3), Neuro_GiveEBufCore(3),
175 * Neuro_SetEBuf(3), Neuro_CopyEBuf(3),
176 * Neuro_ResetEBuf(3), Neuro_EBufIsEmpty(3)
180 * This macro is to set the number of extra instances
181 * of memory needs to be allocated per allocations.
182 * In theory, this is absolutely not needed but since
183 * the allocation proccess is slow, the less we do it,
184 * the better. 10 is a good default.
186 #define MEMORY_ALLOC_OVERH 10
193 * the Engine Buffer object. A pointer variable
194 * of this type is required.
195 * Example : EBUF *myeng;
197 * -- this is the struct we want to have buffered,
198 * -- meaning EBUF will keep and create instances of this struct.
205 typedef struct EBUF EBUF
;
209 * sole constructor of an EBUF element.
212 * This function initializes and makes operationnal
216 * the address of an EBUF pointer.
220 * static EBUF *myeng; \n \n
224 * Neuro_CreateEBuf(&myeng);
227 * Neuro_CleanEBuf(3), Neuro_AllocEBuf(3), Neuro_SetcallbEBuf(3),
228 * Neuro_EBufIsEmpty(3)
231 extern void Neuro_CreateEBuf(EBUF
**eng
);
233 /** Neuro_SetcallbEBuf
235 * Set a callback that will be called for each array elements
236 * when the EBUF element is cleaning itself after a call to Neuro_CleanEBuf
237 * or Neuro_SCleanEBuf.
240 * This function is used to set a callback function to the EBUF element.
241 * This callback function will be called (during the cleaning
242 * time) for every arrays right before they are each freed.
243 * This is so you can free custom stuff that you allocated in the
244 * struct you put in EBUF. The callback function will need a single
245 * argument which will be a void pointer. This will point to the
246 * array(single element of the big array) which is being freed.
253 * a callback which itself contain an argument to a void pointer.
257 * typedef struct ST \n
259 * char *someString; \n
263 * static EBUF *myeng; \n \n
266 * callbackclean(void *src) \n
270 * temp = (ST*)src; \n \n
274 * if (temp->someString) \n
275 * free(temp->someString); \n
281 * Neuro_CreateEBuf(&myeng); \n \n
282 * Neuro_SetcallbEBuf(myeng, callbackclean); \n \n
288 * Neuro_AllocEBuf(myeng, sizeof(ST*), sizeof(ST)); \n \n
290 * foo = Neuro_GiveCurEBuf(myeng); \n \n
292 * foo->someString = (char*)malloc(50); \n \n
296 * Neuro_CleanEBuf(&myeng);
299 * Neuro_CreateEBuf(3), Neuro_CleanEBuf(3)
302 extern void Neuro_SetcallbEBuf(EBUF
*eng
, void (*callback
)(void *src
));
306 * Simple Allocation and reallocation of an EBuf element.
309 * This function is pretty much the most useful function in the lot,
310 * it actually creates a new "slot" which can then be used to add
311 * data to an EBUF element. This function and Neuro_MultiAllocEBuf
312 * are the two only functions which allocate/reallocate memory in
315 * Take good note that an EBUF element can buffer
316 * any kinds of structure (so it can dynamically grow easily and avoid memory
317 * leaks). To support this, this function needs only 2 informations
318 * about the structure :
319 * the size of its pointer form and the size of its normal form. It might
320 * also be possible to work with other variable types than structures, although
321 * it is not really recommended unless you know what you are doing.
327 * the size of the pointer form of the structure (usually sizeof can be used to find it).
330 * the size of the normal form of the structure (usually sizeof can be used to find it).
333 * typedef struct ST \n
339 * static EBUF *myeng; \n \n
344 * Neuro_CreateEBuf(&myeng); \n \n
348 * Neuro_AllocEBuf(myeng, sizeof(ST*), sizeof(ST)); \n \n
352 * Neuro_CleanEBuf(&myeng);
355 * Neuro_GiveEBufCount(3), Neuro_GiveEBuf(3), Neuro_GiveCurEBuf(3),
356 * Neuro_MultiAllocEBuf(3)
358 extern void Neuro_AllocEBuf(EBUF
*eng
, size_t sptp
, size_t sobj
);
361 /** Neuro_MultiAllocEBuf
363 * initial allocation of a bigger amount of slots than one.
366 * This function works exactly the same as Neuro_AllocEBuf except
367 * for one single thing : It can allocate more than one slot at once.
368 * Take very good note that this will only work if the EBUF object hasn't
369 * been allocated before, ie only if it is empty. For security purpose, this
370 * function won't work if theres already allocated slots in the EBUF.
376 * the amount of slots to allocate.
379 * the size of the pointer form of the structure (usually sizeof can be used to find it).
382 * the size of the normal form of the structure (usually sizeof can be used to find it).*
385 * see the example in Neuro_AllocEBuf(3)
388 * Neuro_GiveEBufCount(3), Neuro_GiveEBuf(3), Neuro_GiveCurEBuf(3),
391 extern void Neuro_MultiAllocEBuf(EBUF
*eng
, u32 amount
, size_t sptp
, size_t sobj
);
395 * Standard destructor of an EBUF element.
401 * the address of an EBUF pointer.
405 * static EBUF *myeng; \n \n
409 * Neuro_CreateEBuf(&myeng);
413 * Neuro_CleanEBuf(&myeng);
416 * Neuro_CreateEBuf(3), Neuro_AllocEBuf(3), Neuro_SetcallbEBuf(3),
417 * Neuro_SCleanEBuf(3)
420 extern void Neuro_CleanEBuf(EBUF
**eng
);
424 * cleans/frees one element.
427 * This function's purpose is to clean elements in a similar
428 * manner as Neuro_CleanEBuf(3) but it only
429 * cleans one element. Take note that the callback
430 * which can be set using the function Neuro_SetcallbEBuf(3) is also called with this function.
436 * the pointer to an element contained in the EBUF buffer which needs to be cleaned.
440 * typedef struct ST \n
442 * char *someString; \n
445 * static EBUF *myeng; \n \n
449 * Neuro_CreateEBuf(&myeng); \n \n
455 * Neuro_AllocEBuf(myeng, sizeof(ST*), sizeof(ST)); \n \n
457 * buf = Neuro_GetCurEBuf(myeng); \n \n
459 * buf->someString = "hello"; \n \n
461 * -- lets say we no longer need the variable -- \n
462 * -- we can clean it using this function -- \n
463 * Neuro_SCleanEBuf(myeng, buf); \n \n
467 * Neuro_CleanEBuf(&myeng); \n \n
470 * Neuro_CreateEBuf(3), Neuro_AllocEBuf(3), Neuro_SetcallbEBuf(3), Neuro_CleanEBuf(3), Neuro_GiveEBuf(3), Neuro_GiveCurEBuf(3)
473 extern void Neuro_SCleanEBuf(EBUF
*eng
, void *object
);
475 /** Neuro_GiveEBufCount
478 * give the count of elements in the array
481 * This function returns the number of elements contained
482 * in the core buffer. Each elements in the buffer are ordered
483 * in the order they were "pushed" into the buffer thus this
484 * value can be used to loop the buffer for all the elements
485 * one after the other. NOTE This function returns 0 when theres only
486 * one element and it can't return negative values so it cannot
487 * be used to know if the buffer is empty or not! Use the function
488 * Neuro_EBufIsEmpty(3) to check if its empty or not.
494 * the amount of elements in the EBUF element.
498 * -- in this example, I ommited the initial creation of the buffer, -- \n
499 * -- the final cleaning of the buffer, -- \n
500 * -- the cleaning callback function, -- \n
501 * -- the allocation of the buffer and -- \n
502 * -- the struct ST and its typedef. -- \n
503 * -- SEE the man page for the function Neuro_AllocEBuf(3) for those -- \n
504 * -- and SEE the man page for Neuro_SetcallbEBuf(3) for the callback -- \n \n
507 * unsigned int total = 0; \n \n
509 * -- we check if the buffer is empty -- \n
510 * if (Neuro_EBufIsEmpty(myeng)) \n
513 * -- we get the total number of elements in myeng -- \n
514 * -- and also increment it by one because we will -- \n
515 * -- loop the elements from finish to start -- \n
516 * total = Neuro_GiveEBufCount(myeng) + 1; \n \n
518 * while (total-- > 0) \n
520 * buf = Neuro_GiveEBuf(myeng, total); \n \n
527 * Neuro_AllocEBuf(3), Neuro_GiveEBuf(3),
528 * Neuro_GiveCurEBuf(3), Neuro_EBufIsEmpty(3)
530 extern u32
Neuro_GiveEBufCount(EBUF
*eng
);
532 /** Neuro_GiveEBufElem
534 * output the array number of the element object
537 * This function is used to get the array number
538 * of a structure pointer which is inside
539 * the buffer eng. If the element is not
540 * contained inside the buffer, this will
541 * return 1 and 0 on success. Make sure to
542 * put either a real integer or an allocated
543 * one's address for the *elem argument.
549 * a void pointer of an element
550 * of which the array number will be put
551 * in the output integer.
554 * the array number of the element in the
558 * either 0 or 1. 1 on error (when the pointer object is not
559 * found in the buffer eng or when the buffer eng is NULL).
564 * typedef struct ST \n
566 * char *someString; \n
569 * -- we create a struct element -- \n
570 * -- called an_element into which -- \n
571 * -- we will put the address of an ebuf allocated element -- \n
572 * -- this method can be used to track certain key elements inside the buffer. -- \n
574 * static ST *an_element; \n \n
576 * static EBUF *myeng; \n \n
579 * callbackclean(void *src) \n
583 * temp = (ST*)src; \n \n
587 * if (temp->someString) \n
588 * free(temp->someString); \n
594 * Neuro_CreateEBuf(&myeng); \n \n
595 * Neuro_SetcallbEBuf(myeng, callbackclean); \n \n
601 * Neuro_AllocEBuf(myeng, sizeof(ST*), sizeof(ST)); \n \n
603 * foo = Neuro_GiveCurEBuf(myeng); \n \n
606 * foo->someString = (char*)malloc(50); \n \n
608 * -- we set our variable to the address that the pointer foo points to -- \n
609 * -- this makes it behave the exact same as if it was actually -- \n
610 * -- the pointer foo... we can then access the data from it -- \n
611 * -- for any purpose and fast. -- \n
612 * an_element = foo; \n \n
616 * -- in a certain function, we use the content of the pointer an_element -- \n
617 * -- but for certain cases we also need to get its array number. -- \n
618 * -- This only works if this particular pointer was allocated in an EBUF. -- \n \n
620 * u32 elem_value = 0; \n \n
622 * if (Neuro_GiveEBufElem(myeng, an_element, &elem_value)) \n
624 * printf("an error happened, the element (an_element) wasn't found in the buffer (myeng)\\\\n"); \n
628 * -- now, if there wasn't any errors, the variable an_element -- \n
629 * -- contains the array number for the pointer an_element. -- \n
630 * -- this number can be used with the function Neuro_GiveEBuf(3) or Neuro_GiveEBufAddr(3). \n \n
634 * Neuro_CleanEBuf(&myeng);
639 * Neuro_GiveEBufAddr(3), Neuro_GiveEBuf
641 extern int Neuro_GiveEBufElem(EBUF
*eng
, void *object
, u32
*elem
);
643 /** Neuro_GiveCurEBuf
645 * outputs the last element of the buffer.
648 * before this function, we had to get the number of
649 * elements from the buffer using Neuro_GiveEBufCount(3)
650 * and then call Neuro_GiveEBuf(3) to get the element.
651 * Now, this function can be used to have the exact same
652 * result but in just one call.
658 * the pointer of the element. It returns NULL on error.
661 * -- see the man page for Neuro_GiveEBuf(3) for how this -- \n
662 * -- function can be used. Also, almost all the functions -- \n
663 * -- use this function in their examples so just check how --\n
664 * -- they use it... usually, this function is called right -- \n
665 * -- after you allocate the buffer using Neuro_AllocEBuf(3), -- \n
666 * -- because we need to get the pointer so we can populate it. -- \n
669 * Neuro_AllocEBuf(3), Neuro_MultiAllocEBuf(3),
672 extern void *Neuro_GiveCurEBuf(EBUF
*eng
);
674 /** Neuro_GiveEBufAddr
677 * gives the real address of the element of the array number elem.
680 * this function is essential in the event that you want
681 * to change the order into which the EBUF buffer is.
687 * the array number of the element you want the pointer address.
690 * the pointer to a pointer which contains the address of the
694 * see the Neuro_EBuf(3) man page on section MOVING DATA for
695 * an example on how to use this function.
698 * Neuro_GiveEBufElem(3), Neuro_SetEBuf(3),
700 extern void **Neuro_GiveEBufAddr(EBUF
*eng
, u32 elem
);
705 * gives the element corresponding to the number input in
709 * This function is the default way of getting the
710 * pointer of an allocated element. The pointer can
711 * be used to access the data and read/write to it.
717 * this argument corresponds to the element number
718 * that you want to fetch from the buffer.
721 * the pointer to the element from the EBUF. As a void pointer
722 * so it is possible to "morph" it into any other pointer type.
726 * typedef struct ST \n
728 * char *someString; \n
732 * static EBUF *myeng; \n \n
735 * callbackclean(void *src) \n
739 * temp = (ST*)src; \n \n
743 * if (temp->someString) \n
744 * free(temp->someString); \n
750 * Neuro_CreateEBuf(&myeng); \n \n
751 * Neuro_SetcallbEBuf(myeng, callbackclean); \n \n
757 * Neuro_AllocEBuf(myeng, sizeof(ST*), sizeof(ST)); \n \n
759 * foo = Neuro_GiveCurEBuf(myeng); \n \n
761 * foo->someString = (char*)malloc(50); \n \n
765 * -- this code outputs to the default output channel -- \n
766 * -- the content of every elements of the buffer -- \n
768 * ST *temp = NULL; \n \n
770 * if (Neuro_EBufIsEmpty(myeng)) \n
773 * total = Neuro_GiveEBufCount(myeng) + 1; \n \n
775 * while (total-- > 0) \n
777 * temp = Neuro_GiveEBuf(myeng, total); \n \n
779 * printf("some value : %s\\\\n", temp->someString); \n
784 * Neuro_CleanEBuf(&myeng); \n
787 * Neuro_AllocEBuf(3), Neuro_MultiAllocEBuf(3),
788 * Neuro_GiveEBufCount(3)
790 extern void *Neuro_GiveEBuf(EBUF
*eng
, u32 elem
);
792 /** Neuro_GiveEBufCore
794 * give the core buffer of the EBuf element
797 * this function should never be used, it returns
798 * the actual pointer of the CORE of an EBUF element.
799 * The need of this function is very close to Nill
800 * and it is strongly advised to avoid the use of this
801 * function at all cost.
807 * the CORE of the EBUF's main (and only) buffer.
810 * this function was initially made for bitmap loading
811 * in neuro extlib, it permitted to input simple string
812 * elements and then the ability to give this core
813 * to the pixmap library so it would load the bitmap
814 * from it. This use was considered a BIG HACK. The neuro
815 * bitmap loading code stopped using this function quite
816 * a long time ago so it is unused anywhere.
818 * Neuro_SCleanEBuf(3) Neuro_GiveEBufAddr(3)
819 * Neuro_GiveEBufAddr(3), Neuro_SetEBuf(3),
820 * Neuro_CopyEBuf(3), Neuro_ResetEBuf(3)
822 extern void **Neuro_GiveEBufCore(EBUF
*eng
);
828 * copy the actual content to another position in the
832 * this function is a key element for the task of sorting
833 * elements among the other elements in the buffer.
839 * the actual address of the pointer of an element from the EBUF.
840 * This informations can ONLY be given by the function
841 * Neuro_GiveEBufAddr(3).
844 * the pointer of the element to copy to the address to.
847 * see the Neuro_EBuf(3) man page on section MOVING DATA for
848 * an example on how to use this function. *
851 * Neuro_GiveEBufAddr(3), Neuro_GiveEBufElem(3)
853 extern void Neuro_SetEBuf(EBUF
*eng
, void **to
, void *from
);
857 * copy the content of an EBUF variable to another EBUF variable.
860 * nothing unusual with this function, it simply cleanly copies the
861 * content of an already created EBUF element to another one
862 * that wasn't created yet. If copy an EBUF to another that
863 * already contains data, you'll create a big memory leak.
864 * Note : this function is very fast because it is only copies addresses.
865 * Note2 : Also note that only one of the two needs to be cleaned;
866 * they both contain the same addresses.
872 * an EBUF pointer which gets copied into the EBUF to.
875 * static EBUF *myeng; \n \n
879 * Neuro_CreateEBuf(&myeng); \n \n
885 * Neuro_CopyEBuf(clone, myeng);
889 * Neuro_CleanEBuf(&myeng);
895 extern void Neuro_CopyEBuf(EBUF
*to
, EBUF
*from
);
899 * resets the EBUF variable WITHOUT FREEING IT -- Warning this
900 * is a mem leak if you didn't copy the content to another one
903 * use the function Neuro_CopyEBuf(3) to backup the addresses for
904 * the cleaning process prior to using this function please.
912 extern void Neuro_ResetEBuf(EBUF
*eng
);
914 /** Neuro_EBufIsEmpty
916 * this is a simple boolean returning function that returns
917 * 1 if [eng] is empty and 0 if it holds stuff.
920 * this function is the only way to know if an EBUF is empty
921 * or not, you CAN'T use the function Neuro_GiveEBufCount(3)
928 * 1 if the EBUF is empty and should not be used and 0 if it
929 * was created and populated.
932 * Neuro_GiveEBufCount(3)
934 extern u8
Neuro_EBufIsEmpty(EBUF
*eng
);
940 #endif /* not __EBUF_H */