Use new memory pool allocator. Lots of debug code still in place...
[mesa.git] / src / mesa / shader / slang / slang_utility.c
1 /*
2 * Mesa 3-D graphics library
3 * Version: 6.5.3
4 *
5 * Copyright (C) 2005-2007 Brian Paul All Rights Reserved.
6 *
7 * Permission is hereby granted, free of charge, to any person obtaining a
8 * copy of this software and associated documentation files (the "Software"),
9 * to deal in the Software without restriction, including without limitation
10 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
11 * and/or sell copies of the Software, and to permit persons to whom the
12 * Software is furnished to do so, subject to the following conditions:
13 *
14 * The above copyright notice and this permission notice shall be included
15 * in all copies or substantial portions of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
18 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
21 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
22 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23 */
24
25 /**
26 * \file slang_utility.c
27 * slang utilities
28 * \author Michal Krol
29 */
30
31 #include "imports.h"
32 #include "slang_utility.h"
33 #include "slang_mem.h"
34
35 char *
36 slang_string_concat (char *dst, const char *src)
37 {
38 return _mesa_strcpy (dst + _mesa_strlen (dst), src);
39 }
40
41
42 /* slang_string */
43
44 GLvoid
45 slang_string_init (slang_string *self)
46 {
47 self->data = NULL;
48 self->capacity = 0;
49 self->length = 0;
50 self->fail = GL_FALSE;
51 }
52
53 GLvoid
54 slang_string_free (slang_string *self)
55 {
56 if (self->data != NULL)
57 _mesa_free (self->data);
58 }
59
60 GLvoid
61 slang_string_reset (slang_string *self)
62 {
63 self->length = 0;
64 self->fail = GL_FALSE;
65 }
66
67 static GLboolean
68 grow (slang_string *self, GLuint size)
69 {
70 if (self->fail)
71 return GL_FALSE;
72 if (size > self->capacity) {
73 /* do not overflow 32-bit range */
74 assert (size < 0x80000000);
75
76 self->data = (char *) (_mesa_realloc (self->data, self->capacity, size * 2));
77 self->capacity = size * 2;
78 if (self->data == NULL) {
79 self->capacity = 0;
80 self->fail = GL_TRUE;
81 return GL_FALSE;
82 }
83 }
84 return GL_TRUE;
85 }
86
87 GLvoid
88 slang_string_push (slang_string *self, const slang_string *str)
89 {
90 if (str->fail) {
91 self->fail = GL_TRUE;
92 return;
93 }
94 if (grow (self, self->length + str->length)) {
95 _mesa_memcpy (&self->data[self->length], str->data, str->length);
96 self->length += str->length;
97 }
98 }
99
100 GLvoid
101 slang_string_pushc (slang_string *self, const char c)
102 {
103 if (grow (self, self->length + 1)) {
104 self->data[self->length] = c;
105 self->length++;
106 }
107 }
108
109 GLvoid
110 slang_string_pushs (slang_string *self, const char *cstr, GLuint len)
111 {
112 if (grow (self, self->length + len)) {
113 _mesa_memcpy (&self->data[self->length], cstr, len);
114 self->length += len;
115 }
116 }
117
118 GLvoid
119 slang_string_pushi (slang_string *self, GLint i)
120 {
121 char buffer[12];
122
123 _mesa_sprintf (buffer, "%d", i);
124 slang_string_pushs (self, buffer, strlen (buffer));
125 }
126
127 const char *
128 slang_string_cstr (slang_string *self)
129 {
130 if (grow (self, self->length + 1))
131 self->data[self->length] = '\0';
132 return self->data;
133 }
134
135 /* slang_atom_pool */
136
137 void
138 slang_atom_pool_construct(slang_atom_pool * pool)
139 {
140 GLuint i;
141
142 for (i = 0; i < SLANG_ATOM_POOL_SIZE; i++)
143 pool->entries[i] = NULL;
144 }
145
146 void
147 slang_atom_pool_destruct (slang_atom_pool * pool)
148 {
149 GLuint i;
150
151 for (i = 0; i < SLANG_ATOM_POOL_SIZE; i++) {
152 slang_atom_entry * entry;
153
154 entry = pool->entries[i];
155 while (entry != NULL) {
156 slang_atom_entry *next;
157
158 next = entry->next;
159 #if USE_MEMPOOL
160 _slang_free(entry->id);
161 _slang_free(entry);
162 #else
163 slang_alloc_free(entry->id);
164 slang_alloc_free(entry);
165 #endif
166 entry = next;
167 }
168 }
169 }
170
171 /*
172 * Search the atom pool for an atom with a given name.
173 * If atom is not found, create and add it to the pool.
174 * Returns ATOM_NULL if the atom was not found and the function failed
175 * to create a new atom.
176 */
177 slang_atom
178 slang_atom_pool_atom(slang_atom_pool * pool, const char * id)
179 {
180 GLuint hash;
181 const char * p = id;
182 slang_atom_entry ** entry;
183
184 /* Hash a given string to a number in the range [0, ATOM_POOL_SIZE). */
185 hash = 0;
186 while (*p != '\0') {
187 GLuint g;
188
189 hash = (hash << 4) + (GLuint) (*p++);
190 g = hash & 0xf0000000;
191 if (g != 0)
192 hash ^= g >> 24;
193 hash &= ~g;
194 }
195 hash %= SLANG_ATOM_POOL_SIZE;
196
197 /* Now the hash points to a linked list of atoms with names that
198 * have the same hash value. Search the linked list for a given
199 * name.
200 */
201 entry = &pool->entries[hash];
202 while (*entry != NULL) {
203 /* If the same, return the associated atom. */
204 if (slang_string_compare((**entry).id, id) == 0)
205 return (slang_atom) (**entry).id;
206 /* Grab the next atom in the linked list. */
207 entry = &(**entry).next;
208 }
209
210 /* Okay, we have not found an atom. Create a new entry for it.
211 * Note that the <entry> points to the last entry's <next> field.
212 */
213 #if USE_MEMPOOL
214 *entry = (slang_atom_entry *) (_slang_alloc(sizeof(slang_atom_entry)));
215 #else
216 *entry = (slang_atom_entry *) (slang_alloc_malloc(sizeof(slang_atom_entry)));
217 #endif
218 if (*entry == NULL)
219 return SLANG_ATOM_NULL;
220
221 /* Initialize a new entry. Because we'll need the actual name of
222 * the atom, we use the pointer to this string as an actual atom's
223 * value.
224 */
225 (**entry).next = NULL;
226 #if USE_MEMPOOL
227 (**entry).id = _slang_strdup(id);
228 #else
229 (**entry).id = slang_string_duplicate(id);
230 #endif
231 if ((**entry).id == NULL)
232 return SLANG_ATOM_NULL;
233 return (slang_atom) (**entry).id;
234 }
235
236 /**
237 * Return the name of a given atom.
238 */
239 const char *
240 slang_atom_pool_id(slang_atom_pool * pool, slang_atom atom)
241 {
242 return (const char *) (atom);
243 }