Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: orxonox.OLD/orxonox/branches/old.chris/src/data_tank.cc @ 3568

Last change on this file since 3568 was 2702, checked in by chris, 20 years ago

orxonox/branches/chris: corrected a bug in DataTank

File size: 10.1 KB
Line 
1/*
2   orxonox - the future of 3D-vertical-scrollers
3
4   Copyright (C) 2004 orx
5
6   This program is free software; you can redistribute it and/or modify
7   it under the terms of the GNU General Public License as published by
8   the Free Software Foundation; either version 2, or (at your option)
9   any later version.
10
11   This program is distributed in the hope that it will be useful,
12   but WITHOUT ANY WARRANTY; without even the implied warranty of
13   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14   GNU General Public License for more details.
15
16   You should have received a copy of the GNU General Public License
17   along with this program; if not, write to the Free Software Foundation,
18   Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 
19
20
21   ### File Specific:
22   main-programmer: Christian Meyer
23   co-programmer: ...
24*/
25
26#include "data_tank.h"
27
28using namespace std;
29
30//////////////////
31// DataTank
32//////////////////
33
34DataTank::DataTank()
35{
36        loader = new DataLoader;
37        tree = NULL;
38}
39
40DataTank::~DataTank()
41{
42        // free DataTree
43        tree_delete();
44        // free DataLoader
45        if( loader) delete loader;
46}
47
48void DataTank::tree_add( void* r, char* filename, int type)
49{
50        DataTree *act;
51       
52        if( tree == NULL)
53        {
54                tree = (DataTree*) malloc( sizeof( DataTree));
55                tree->type = type;
56                memset( tree->filename, 0, MAX_FILENAME_LENGHT);
57                strncpy( tree->filename, filename, MAX_FILENAME_LENGHT-1);
58                tree->parent = NULL;
59                tree->up = NULL;
60                tree->down = NULL;
61                tree->resource = r;
62                return;
63        }
64       
65        act = tree;
66        while( act != NULL)
67        {
68                if( strcmp( act->filename, filename) > 0)
69                {
70                        if( act->up != NULL) act = act->up;
71                        else
72                        {
73                                act->up = (DataTree*) malloc( sizeof( DataTree));
74                                act->up->type = type;
75                                memset( act->up->filename, 0, MAX_FILENAME_LENGHT);
76                                strncpy( act->up->filename, filename, MAX_FILENAME_LENGHT-1);
77                                act->up->parent = act;
78                                act->up->up = NULL;
79                                act->up->down = NULL;
80                                act->up->resource = r;
81                                break;
82                        }
83                }
84                else
85                {
86                        if( act->down != NULL) act = act->down;
87                        else
88                        {
89                                act->down = (DataTree*) malloc( sizeof( DataTree));
90                                act->down->type = type;
91                                memset( act->down->filename, 0, MAX_FILENAME_LENGHT);
92                                strncpy( act->down->filename, filename, MAX_FILENAME_LENGHT-1);
93                                act->down->parent = act;
94                                act->down->up = NULL;
95                                act->down->down = NULL;
96                                act->down->resource = r;
97                                break;
98                        }
99                }
100        }
101}
102
103DataTree* DataTank::tree_find( char* file)
104{
105        DataTree *act;
106       
107        if( tree == NULL) return NULL;
108       
109        act = tree;
110       
111        while( act != NULL)
112        {
113                if( strcmp( act->filename, file) == 0) break;
114                else if( strcmp( act->filename, file) > 0)
115                        act = act->up;
116                else
117                        act = act->down;
118        }
119       
120        return act;
121}
122
123DataTree* DataTank::tree_highest( DataTree* t)
124{
125        DataTree* act;
126       
127        if( t == NULL) return NULL;
128       
129        act = t;
130       
131        while( act != NULL)
132        {
133                if( act->up == NULL) break;
134                act = act->up;
135        }
136       
137        return act;
138}
139
140DataTree* DataTank::tree_lowest( DataTree* t)
141{
142        DataTree* act;
143       
144        if( t == NULL) return NULL;
145       
146        act = t;
147       
148        while( act != NULL)
149        {
150                if( act->down == NULL) break;
151                act = act->down;
152        }
153       
154        return act;
155}
156
157void DataTank::tree_remove( DataTree* rem)
158{
159        DataTree *rep;
160        void* tempv;
161        int tempi;
162        char tempn[MAX_FILENAME_LENGHT];
163       
164        if( rem != NULL)
165        {
166                if( rem->up == NULL && rem->down == NULL)
167                {
168                                // leaf
169                        if( rem->parent == NULL) tree = NULL;
170                        else
171                        {
172                                if( rem->parent->up == rem) rem->parent->up = NULL;
173                                else rem->parent->down = NULL;
174                        }
175                        loader->free_file( rem->resource, rem->type);
176                        free( rem);
177                }
178                else if( rem->up != NULL && rem->down == NULL)
179                {
180                                // branch up
181                        if( rem->parent == NULL)
182                        {
183                                tree = rem->up;
184                                rem->up->parent = NULL;
185                        }
186                        else
187                        {
188                                if( rem->parent->up == rem) rem->parent->up = rem->up;
189                                else rem->parent->down = rem->up;
190                                rem->up->parent = rem->parent;
191                        }
192                        loader->free_file( rem->resource, rem->type);
193                        free( rem);                     
194                }
195                else if( rem->up == NULL && rem->down != NULL)
196                {
197                                // branch down
198                        if( rem->parent == NULL)
199                        {
200                                tree = rem->down;
201                                rem->down->parent = NULL;
202                        }
203                        else
204                        {
205                                if( rem->parent->up == rem) rem->parent->up = rem->down;
206                                else rem->parent->down = rem->down;
207                                rem->down->parent = rem->parent;
208                        }
209                        loader->free_file( rem->resource, rem->type);
210                        free( rem);                     
211                }
212                else
213                {
214                                // fork
215                        // get highest from down tree
216                        rep = tree_highest( rem->down);
217                       
218                        // swap contents
219                        tempv = rep->resource;
220                        tempi = rep->type;
221                        strcpy( tempn, rep->filename);
222                       
223                        rep->resource = rem->resource;
224                        rep->type = rem->type;
225                        strcpy( rep->filename, rem->filename);
226                       
227                        rem->resource = tempv;
228                        rem->type = tempi;
229                        strcpy( rem->filename, tempn);
230                       
231                        // remove rep
232                        tree_remove( rep);
233                }
234        }
235}
236
237void DataTank::tree_delete()
238{
239        DataTree *act, *kil;
240       
241        if( tree != NULL)
242        {
243                act = tree;
244                while( act != NULL)
245                {
246                        if( act->up != NULL)
247                        {
248                                act = act->up;
249                                continue;
250                        }
251                        if( act->down != NULL)
252                        {
253                                act = act->down;
254                                continue;
255                        }
256                        kil = act;
257                        act = act->parent;
258                        if( act != NULL)
259                        {
260                                if( kil == act->up)     act->up = NULL;
261                                if( kil == act->down) act->down = NULL;
262                        }
263                        loader->free_file( kil->resource, kil->type);
264                        free( kil);
265                }
266        }
267}
268
269void* DataTank::get( char* file)
270{
271        DataTree* t;
272        void* new_res;
273        int type;
274       
275        t = tree_find( file);
276       
277        if( t == NULL)
278        {
279                type = loader->get_type( file);
280                if( type == -1) return NULL;
281                new_res = loader->load_file( file, type);
282                if( new_res == NULL)
283                {
284                        // return placeholder
285                        return loader->get_placeholder( type);
286                }
287                else
288                {
289                        tree_add( new_res, file, type);
290                        return new_res;
291                }
292        }
293        else
294        {
295                return t->resource;
296        }
297}
298
299void DataTank::unload( char* file)
300{
301        DataTree* rem;
302       
303        rem = tree_find( file);
304       
305        tree_remove( rem);
306}
307
308void DataTank::precache( char* resfile, void(*pfunc)(int, float, char*))
309{
310        FILE* source;
311        int total, done;
312        char file[256];
313        char* s;
314       
315        source = fopen( resfile, "r");
316        if( source == NULL) return;
317       
318        total = done = 0;
319       
320        while( !feof( source))
321        {
322                fgets( file, 256, source);
323                if( (s = strchr( file, '\n')) != NULL) *s = 0;
324                if( strlen( file) > 1) total++;
325        }
326       
327        rewind( source);
328       
329        while( !feof( source))
330        {
331                fgets( file, 256, source);
332                if( (s = strchr( file, '\n')) != NULL) *s = 0;
333                if( strlen( file) > 1)
334                {
335                        if( pfunc) pfunc( total, ((float)done)/((float)total), file);
336                        get( file);
337                        done++;
338                }
339        }
340       
341        fclose( source);
342}
343
344void DataTank::save_precache( char* filename)
345{
346        FILE* out;
347       
348        out = fopen( filename, "w");
349        if( out == NULL) return;
350       
351        if( tree != NULL) save_node( tree, out);
352       
353        fclose( out);
354}
355
356void DataTank::save_node( DataTree* act, FILE* out)
357{
358        fprintf(out, "%s\n", act->filename);
359       
360        if( act->down) save_node( act->down, out);
361        if( act->up) save_node( act->up, out);
362       
363        return;
364}
365
366int DataTank::add_filetype( char* postfix, void*(*lfunc)(char*), void(*ffunc)(void*), char* placeholderfile)
367{
368        return loader->add_filetype( postfix, lfunc, ffunc, placeholderfile);
369}
370
371////////////////
372// DataLoader
373////////////////
374
375DataLoader::DataLoader()
376{
377        ntypes = 0;
378        load_funcs = NULL;
379        free_funcs = NULL;
380        postfixes = NULL;
381        placeholders = NULL;
382}
383
384DataLoader::~DataLoader()
385{
386        int i;
387       
388        for( i = 0; i < ntypes; i++)
389        {
390                if( placeholders[i] != NULL) free_funcs[i]( placeholders[i]);
391                if( postfixes[i] != NULL) free( postfixes[i]);
392        }
393       
394        if( postfixes) free( postfixes);
395        if( placeholders) free( placeholders);
396        if( free_funcs) free( free_funcs);
397        if( load_funcs) free( load_funcs);
398}
399
400int DataLoader::add_filetype( char* postfix, void*(*lfunc)(char*), void(*ffunc)(void*), char* placeholderfile)
401{
402        int type = 0;
403        char testfile[MAX_FILENAME_LENGHT];
404
405        if( !postfix || !lfunc || !ffunc || !placeholderfile) return -1;
406
407        sprintf( testfile, "blabla.%s", postfix);
408        if( (type = get_type( testfile)) != -1)
409        {
410                load_funcs[type] = lfunc;
411                free_funcs[type] = ffunc;
412                placeholders[type] = lfunc( placeholderfile);
413                return type;
414        }
415       
416        // backup
417        void*(**old_load_funcs)(char*) = load_funcs;
418        void(**old_free_funcs)(void*) = free_funcs;
419        char** old_postfixes = postfixes;
420        void** old_placeholders = placeholders;
421
422        // realloc
423        load_funcs = (void*(**)(char*)) malloc( sizeof( void*(*)(char*)) * (ntypes + 1));
424        free_funcs = (void(**)(void*)) malloc( sizeof( void(*)(void*)) * (ntypes + 1));
425        postfixes = (char**) malloc( sizeof( char*) * (ntypes + 1));
426        placeholders = (void**) malloc( sizeof( void*) * (ntypes + 1));
427       
428        // copy
429        memcpy( load_funcs, old_load_funcs, sizeof( void*(*)(char*)) * ntypes);
430        memcpy( free_funcs, old_free_funcs, sizeof( void(*)(void*)) * ntypes);
431        memcpy( postfixes, old_postfixes, sizeof( char*) * ntypes);
432        memcpy( placeholders, old_placeholders, sizeof( void*) * ntypes);
433       
434        // free
435        free( old_load_funcs);
436        free( old_free_funcs);
437        free( old_postfixes);
438        free( old_placeholders);
439       
440        // add
441        type = ntypes;
442        ntypes++;
443       
444        load_funcs[type] = lfunc;
445        free_funcs[type] = ffunc;
446        postfixes[type] = (char*) malloc( sizeof( char) * POSTFIX_LENGHT);
447        memset( postfixes[type], 0, POSTFIX_LENGHT);
448        strncpy( postfixes[type], postfix, POSTFIX_LENGHT);
449        placeholders[type] = lfunc( placeholderfile);
450       
451        return type;
452}
453
454void* DataLoader::load_file( char* file, int type)
455{
456        if( type <= ntypes && type >= 0) return load_funcs[type]( file);
457        else return NULL;
458}
459
460int DataLoader::get_type( char* file)
461{
462        int i, n;
463        char* posterior;
464       
465        if( file == NULL) return -1;
466       
467        i = 0;
468        n = -1;
469        while( file[i] != 0)
470        {
471                if( file[i] == '.') n = i;
472                i++;
473        }
474       
475        if( n == -1) return -1;
476       
477        posterior = &(file[n]);
478       
479        for( i = 0; i < ntypes; i++)
480        {
481                if( strcmp( posterior, postfixes[i]) == 0) return i;
482        }
483       
484        return -1;
485}
486
487void DataLoader::free_file( void* resource, int type)
488{
489        if( type <= ntypes && type >= 0) free_funcs[type]( resource);
490}
491
492void* DataLoader::get_placeholder( int type)
493{
494        if( type <= ntypes && type >= 0) return placeholders[type];
495        else return NULL;
496}
Note: See TracBrowser for help on using the repository browser.