- Added new dir for the library
[textus:php-language-detection.git] / textcat / memory.c
1 /*
2    +----------------------------------------------------------------------+
3    | Copyright (c) 2010 The PHP Group                                     |
4    +----------------------------------------------------------------------+
5    | This source file is subject to version 3.01 of the PHP license,      |
6    | that is bundled with this package in the file LICENSE, and is        |
7    | available through the world-wide-web at the following url:           |
8    | http://www.php.net/license/3_01.txt                                  |
9    | If you did not receive a copy of the PHP license and are unable to   |
10    | obtain it through the world-wide-web, please send a note to          |
11    | license@php.net so we can mail you a copy immediately.               |
12    +----------------------------------------------------------------------+
13    | Author:  C├ęsar Rodas <crodas@member.fsf.org>                         |
14    +----------------------------------------------------------------------+
15  */
16
17 #include "textcat.h"
18 #include "textcat_internal.h"
19
20 typedef struct memblock {
21     void * memory;
22     size_t size;
23     size_t offset;
24     short int free;
25     struct memblock * next;
26 } memblock;
27
28 typedef struct mempool {
29     memblock * first;
30     memblock * last;
31     size_t size;
32     size_t usage;
33     size_t blocks;
34     /* callback */
35     void * (*malloc)(size_t);
36     void (*free)(void *);
37     size_t block_size;
38 } mempool;
39
40 static Bool mempool_add_memblock (mempool * pool, size_t rsize);
41
42 /* mempool_init(void ** memory, void * (*xmalloc)(size_t), void * (*xfree)(void *), size_t block_size) {{{ */
43 extern Bool mempool_init(void ** memory, void * (*xmalloc)(size_t), void (*xfree)(void *), size_t block_size)
44 {
45     mempool * mem;
46     mem = xmalloc(sizeof(mempool));
47     if (mem == NULL) {
48         *memory = NULL;
49         return TC_FALSE;
50     }
51     mem->first      = NULL;
52     mem->last       = NULL;
53     mem->blocks     = 0;
54     mem->usage      = 0;
55     mem->size       = 0;
56     mem->free       = xfree;
57     mem->malloc     = xmalloc;
58     mem->block_size = block_size;
59     *memory  = (void *)mem;
60     return TC_TRUE;
61 }
62 /* }}} */
63
64 /* mempool_done(void * memory) {{{ */
65 void mempool_done(void ** memory)
66 {
67     mempool * mem;
68     mem = *memory;
69     void  (*xfree)(size_t);
70     xfree = mem->free;
71     if (mem->size > 0) {
72         memblock * mem1, * mem2;
73         mem1 = mem->first;
74         while (mem1) {
75             mem2 = mem1->next;
76             if (mem1->size > 0) {
77                 xfree(mem1->memory);
78             }
79             mem1 = mem2;
80         }
81     }
82     xfree(*memory);
83     *memory = 0;
84 }
85 /* }}} */
86
87 /* mempool_reset(void * memory) {{{ */
88 void mempool_reset(void * memory)
89 {
90     mempool  * pool;
91     memblock * block, * next, *aux;
92     pool = (mempool *) memory;
93     aux  = NULL;
94     if (pool->first == NULL) {
95         return;
96     }
97     for (block = pool->first; block; block = block->next) {
98         block->offset = sizeof(memblock);
99         block->free   = 1;
100         if (aux && block->size > pool->block_size) {
101             pool->blocks--;
102             pool->size -=  block->size;
103             aux->next   = block->next;
104             pool->free(block->memory);
105             block = aux;
106         } 
107         aux = block;
108     }
109     pool->usage = 0;
110     pool->last  = aux;
111 }
112 /* }}} */ 
113
114 /* mempool _malloc(void * memory, size_t size) {{{ */
115 void * mempool_malloc(void * memory, size_t size)
116 {
117     mempool * pool;
118     memblock * mem;
119     void * mmem;
120     size_t free; 
121     short ask_mem;
122
123     pool    = (mempool *) memory;
124     ask_mem = 1; 
125
126     for (mem=pool->first; mem; mem = mem->next) {
127         if (mem->free == 1) {
128             free = mem->size > mem->offset ? mem->size - mem->offset : 0;
129             if (free > 0 && free > size) {
130                 /* found a free block */
131                 ask_mem = 0;
132                 break;
133             }
134         }
135     }
136
137     if (ask_mem) {
138         if (mempool_add_memblock(pool, size) == TC_FALSE) {
139             return NULL;
140         }
141         mem = pool->last;
142     }
143     mmem         = mem->memory + mem->offset;
144     pool->usage += size;
145     mem->offset += size;
146     mem->free    = mem->offset == mem->size ? 0 : 1; 
147
148     return mmem;
149 }
150 /* }}} */
151
152 /* mempool_calloc(void * memory, size_t nmemb, size_t size) {{{ */
153 void * mempool_calloc(void * memory, size_t nmemb, size_t size)
154 {
155     void * mem;
156     mem = mempool_malloc(memory, nmemb * size);
157     if (mem != NULL) {
158         memset(mem, 0, nmemb * size);
159     }
160     return mem;
161 }
162 /* }}} */
163
164 /* mempool_strndup(void * memory, uchar * key, size_t len) {{{ */
165 uchar * mempool_strndup(void * memory, uchar * key, size_t len)
166 {
167     uchar * mem;
168     mem = mempool_malloc(memory, len + 1);
169     if (mem == NULL) {
170         return NULL;
171     }
172     memcpy(mem, key, len);
173     *(mem+len) = '\0';
174     return mem;
175 }
176 /* }}} */
177
178 /* mempool_add_memblock (mempool * pool, size_t rsize) {{{ */
179 static Bool mempool_add_memblock (mempool * pool, size_t rsize)
180 {
181     size_t size;
182     void  * _memblock;
183     memblock * mem;
184     size       = pool->block_size > rsize ? pool->block_size : rsize;
185     _memblock  = (void *) pool->malloc( size + sizeof(memblock) );
186     if (_memblock == NULL) {
187         return TC_FALSE;
188     }
189     mem = (memblock *) _memblock;
190     mem->size   = size;
191     mem->free   = 1;
192     mem->offset = sizeof(memblock); 
193     mem->next   = NULL;
194     mem->memory = _memblock;
195     if (pool->first == NULL) {
196         pool->first = mem;
197     }
198     if (pool->last != NULL) {
199         pool->last->next = mem;
200     }
201     pool->last   = mem;
202     pool->size  += size;
203     pool->blocks++;
204     return TC_TRUE;
205 }
206 /* }}} */
207
208 /*
209  * Local variables:
210  * tab-width: 4
211  * c-basic-offset: 4
212  * End:
213  * vim600: sw=4 ts=4 fdm=marker
214  * vim<600: sw=4 ts=4
215  */