root/trunk/orca/gl/res.c

Revision 43, 6.3 kB (checked in by krobillard, 3 years ago)

Added copyright info to gl/ files.

Line 
1/*============================================================================
2    ORCA Interpreter
3    Copyright (C) 2005-2006  Karl Robillard
4
5    This library is free software; you can redistribute it and/or
6    modify it under the terms of the GNU Lesser General Public
7    License as published by the Free Software Foundation; either
8    version 2.1 of the License, or (at your option) any later version.
9
10    This library is distributed in the hope that it will be useful,
11    but WITHOUT ANY WARRANTY; without even the implied warranty of
12    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13    Lesser General Public License for more details.
14
15    You should have received a copy of the GNU Lesser General Public
16    License along with this library; if not, write to the Free Software
17    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
18===========================================================================*/
19
20
21#include <assert.h>
22#include "os.h"
23#include "res.h"
24
25
26static uint16_t _currentGroup = 0;
27
28
29ResourceClass* _resClass[ MAX_RES_TYPES ] =
30{
31    0, 0, 0, 0, 0, 0, 0, 0,
32    0, 0, 0, 0, 0, 0, 0, 0
33};
34
35
36void resd_register( ResourceClass* rc )
37{
38    int i = rc->type;
39    _resClass[ i ] = rc;
40}
41
42
43void resd_destroy( Resource* res )
44{
45    ResourceClass* rc;
46    assert( res->resType < MAX_RES_TYPES );
47    rc = _resClass[ res->resType ];
48    assert( rc );
49    if( rc->destroy )
50        rc->destroy( res );
51}
52
53
54uint16_t resd_currentGroup()
55{
56    return _currentGroup;
57}
58
59
60/**
61  Resources added with resd_add() will be assigned to the current group.
62  The default group is zero.
63*/
64void resd_setCurrentGroup( uint16_t group )
65{
66    _currentGroup = group;
67}
68
69
70/*--------------------------------------------------------------------------*/
71
72
73/**
74  Allocates the memory for the hash table and prepares it for use.
75  tableLen must be a power of 2.
76*/
77void resd_init( ResourceDict* dict, int tableLen )
78{
79    Resource** it;
80    Resource** end;
81
82    dict->table = memAlloc( sizeof(Resource*) * tableLen );
83    assert( dict->table );
84    dict->tableLen = tableLen;
85
86    it  = dict->table;
87    end = it + tableLen;
88    while( it != end )
89        *it++ = 0;
90}
91
92
93void resd_free( ResourceDict* dict )
94{
95    if( dict->table )
96    {
97        Resource* bi;
98        Resource* next;
99        Resource** it  = dict->table;
100        Resource** end = it + dict->tableLen;
101
102        while( it != end )
103        {
104            bi = *it;
105            while( bi )
106            {
107                next = bi->resLink;
108                resd_destroy( bi );
109                bi = next;
110            }
111
112            ++it;
113        }
114
115        memFree( dict->table );
116        dict->table    = 0;
117        dict->tableLen = 0;
118    }
119}
120
121
122/**
123  Free all the resources in a dictionary which belong to a particular group.
124*/
125void resd_freeGroup( ResourceDict* dict, uint16_t group )
126{
127    if( dict->table )
128    {
129        Resource* bi;
130        Resource* next;
131        Resource* prev;
132        Resource** it  = dict->table;
133        Resource** end = it + dict->tableLen;
134
135        while( it != end )
136        {
137            prev = 0;
138            bi = *it;
139            while( bi )
140            {
141                next = bi->resLink;
142                if( bi->resGroup == group )
143                {
144                    if( prev )
145                        prev->resLink = bi->resLink;
146                    else
147                        *it = bi->resLink;
148
149                    resd_destroy( bi );
150                }
151                else
152                {
153                    prev = bi;
154                }
155                bi = next;
156            }
157
158            ++it;
159        }
160    }
161}
162
163
164uint32_t resd_hash( const char* buf, int len )
165{
166    // Justin Zobel's bitwise hash function.
167    //  http://goanna.cs.rmit.edu.au/~hugh/zhw-ipl.html
168
169    uint32_t hashval;
170    const char* end = buf + len;
171
172    hashval = 1159241;
173    for( ; buf != end; ++buf )
174        hashval ^= ((hashval << 5) + *buf + (hashval >> 2));
175
176    return (hashval & 0x7fffffff);
177}
178
179
180/**
181  Returns zero if not found.
182*/
183Resource* resd_lookup( const ResourceDict* dict, uint32_t key )
184{
185    Resource* it;
186    Resource* prev = 0;
187    Resource** table = dict->table + (key & (dict->tableLen - 1));
188
189    for( it = *table; it; prev = it, it = it->resLink )
190    {
191        if( it->resKey == key )
192        {
193            if( prev )
194            {
195                // Move to front on access so commonly used words are
196                // found more quickly.
197                prev->resLink = it->resLink;
198                it->resLink = *table;
199                *table = it;
200            }
201
202            return it;
203        }
204    }
205    return 0;
206}
207
208
209/**
210  Add a Resource to the dictionary.
211  A Resource can only be in a single dictionary.
212*/
213void resd_add( ResourceDict* dict, Resource* res, uint32_t key )
214{
215    Resource** table = dict->table + (key & (dict->tableLen - 1));
216    res->resKey   = key;
217    res->resLink  = *table;
218    res->resGroup = _currentGroup;
219    *table = res;
220}
221
222
223/**
224  Returns pointer to Resource or zero if key is not found.
225*/
226Resource* resd_remove( ResourceDict* dict, uint32_t key )
227{
228    Resource* it;
229    Resource* prev = 0;
230    Resource** table = dict->table + (key & (dict->tableLen - 1));
231
232    for( it = *table; it; prev = it, it = it->resLink )
233    {
234        if( it->resKey == key )
235        {
236            if( prev )
237                prev->resLink = it->resLink;
238            else
239                *table = it->resLink;
240
241            it->resLink = 0;
242            return it;
243        }
244    }
245    return 0;
246}
247
248
249/**
250  Prints information about dictionary.
251*/
252void resd_statistics( ResourceDict* dict, const char* msg )
253{
254#ifndef NDEBUG
255    int totalNodes = 0;
256    int maxDepth = 0;
257    int i;
258    for( i = 0; i < dict->tableLen; ++i )
259    {
260        int count = 0;
261        Resource* res = dict->table[ i ];
262        while( res )
263        {
264            ++count;
265            res = res->resLink;
266        }
267
268        if( count > maxDepth )
269            maxDepth = count;
270        totalNodes += count;
271    }
272
273    dprint( "%s [\n"
274            "  table-size: %d\n"
275            "  population: %d\n"
276            "  average-depth: %d\n"
277            "  maximum-depth: %d\n"
278            "]\n",
279            msg ? msg : "ResourceDict",
280            dict->tableLen,
281            totalNodes,
282            totalNodes / dict->tableLen,
283            maxDepth );
284#endif
285}
286
287
288/*EOF*/
Note: See TracBrowser for help on using the browser.