/* * Mesa 3-D graphics library * Version: 6.6 * * Copyright (C) 2005-2006 Brian Paul All Rights Reserved. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included * in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /** * \file slang_utility.c * slang utilities * \author Michal Krol */ #include "imports.h" #include "slang_utility.h" char * slang_string_concat (char *dst, const char *src) { return _mesa_strcpy (dst + _mesa_strlen (dst), src); } /* slang_string */ GLvoid slang_string_init (slang_string *self) { self->data = NULL; self->capacity = 0; self->length = 0; self->fail = GL_FALSE; } GLvoid slang_string_free (slang_string *self) { if (self->data != NULL) _mesa_free (self->data); } GLvoid slang_string_reset (slang_string *self) { self->length = 0; self->fail = GL_FALSE; } static GLboolean grow (slang_string *self, GLuint size) { if (self->fail) return GL_FALSE; if (size > self->capacity) { /* do not overflow 32-bit range */ assert (size < 0x80000000); self->data = (char *) (_mesa_realloc (self->data, self->capacity, size * 2)); self->capacity = size * 2; if (self->data == NULL) { self->capacity = 0; self->fail = GL_TRUE; return GL_FALSE; } } return GL_TRUE; } GLvoid slang_string_push (slang_string *self, const slang_string *str) { if (str->fail) { self->fail = GL_TRUE; return; } if (grow (self, self->length + str->length)) { _mesa_memcpy (&self->data[self->length], str->data, str->length); self->length += str->length; } } GLvoid slang_string_pushc (slang_string *self, const char c) { if (grow (self, self->length + 1)) { self->data[self->length] = c; self->length++; } } GLvoid slang_string_pushs (slang_string *self, const char *cstr, GLuint len) { if (grow (self, self->length + len)) { _mesa_memcpy (&self->data[self->length], cstr, len); self->length += len; } } GLvoid slang_string_pushi (slang_string *self, GLint i) { char buffer[12]; _mesa_sprintf (buffer, "%d", i); slang_string_pushs (self, buffer, strlen (buffer)); } const char * slang_string_cstr (slang_string *self) { if (grow (self, self->length + 1)) self->data[self->length] = '\0'; return self->data; } /* slang_atom_pool */ void slang_atom_pool_construct(slang_atom_pool * pool) { GLuint i; for (i = 0; i < SLANG_ATOM_POOL_SIZE; i++) pool->entries[i] = NULL; } void slang_atom_pool_destruct (slang_atom_pool * pool) { GLuint i; for (i = 0; i < SLANG_ATOM_POOL_SIZE; i++) { slang_atom_entry * entry; entry = pool->entries[i]; while (entry != NULL) { slang_atom_entry *next; next = entry->next; slang_alloc_free(entry->id); slang_alloc_free(entry); entry = next; } } } /* * Search the atom pool for an atom with a given name. * If atom is not found, create and add it to the pool. * Returns ATOM_NULL if the atom was not found and the function failed to create a new atom. */ slang_atom slang_atom_pool_atom(slang_atom_pool * pool, const char * id) { GLuint hash; const char * p = id; slang_atom_entry ** entry; /* Hash a given string to a number in the range [0, ATOM_POOL_SIZE). */ hash = 0; while (*p != '\0') { GLuint g; hash = (hash << 4) + (GLuint) (*p++); g = hash & 0xf0000000; if (g != 0) hash ^= g >> 24; hash &= ~g; } hash %= SLANG_ATOM_POOL_SIZE; /* Now the hash points to a linked list of atoms with names that have the same hash value. * Search the linked list for a given name. */ entry = &pool->entries[hash]; while (*entry != NULL) { /* If the same, return the associated atom. */ if (slang_string_compare((**entry).id, id) == 0) return (slang_atom) (**entry).id; /* Grab the next atom in the linked list. */ entry = &(**entry).next; } /* Okay, we have not found an atom. Create a new entry for it. * Note that the points to the last entry's field. */ *entry = (slang_atom_entry *) (slang_alloc_malloc(sizeof(slang_atom_entry))); if (*entry == NULL) return SLANG_ATOM_NULL; /* Initialize a new entry. Because we'll need the actual name of the atom, we use the pointer * to this string as an actual atom's value. */ (**entry).next = NULL; (**entry).id = slang_string_duplicate(id); if ((**entry).id == NULL) return SLANG_ATOM_NULL; return (slang_atom) (**entry).id; } /** * Return the name of a given atom. */ const char * slang_atom_pool_id(slang_atom_pool * pool, slang_atom atom) { return (const char *) (atom); }