source: abuse/trunk/src/lcache.cpp @ 504

Last change on this file since 504 was 504, checked in by Sam Hocevar, 10 years ago

lisp: always align the lisp allocator results, even on x86 or architectures
that have hardware realignment. Get rid of now useless bus_type.h.

File size: 4.4 KB
Line 
1/*
2 *  Abuse - dark 2D side-scrolling platform game
3 *  Copyright (c) 1995 Crack dot Com
4 *  Copyright (c) 2005-2011 Sam Hocevar <sam@hocevar.net>
5 *
6 *  This software was released into the Public Domain. As with most public
7 *  domain software, no warranty is made or implied by Crack dot Com or
8 *  Jonathan Clark.
9 */
10
11/*
12 * This file contains serialisation methods for the cache system. It
13 * is NOT used to load and save games.
14 * XXX: this code has not been tested after the LObject refactor.
15 */
16
17#include "config.h"
18
19#include "lisp.h"
20#include "specs.h"
21
22size_t block_size(LObject *level)  // return size needed to recreate this block
23{
24    if (!level) // NULL pointers don't need to be stored
25        return 0;
26
27    switch (item_type(level))
28    {
29    case L_CONS_CELL:
30        {
31            size_t ret = sizeof(uint8_t) + sizeof(uint32_t);
32            void *b = level;
33            for (; b && item_type(b) == L_CONS_CELL; b = CDR(b))
34                ;
35            if (b)
36                ret += block_size((LObject *)b);
37            for (b = level; b && item_type(b) == L_CONS_CELL; b = CDR(b))
38                ret += block_size(CAR(b));
39            return ret;
40        }
41    case L_CHARACTER:
42        return sizeof(uint8_t) + sizeof(uint16_t);
43    case L_STRING:
44        return sizeof(uint8_t) + sizeof(uint32_t)
45                               + strlen(lstring_value(level)) + 1;
46    case L_NUMBER:
47        return sizeof(uint8_t) + sizeof(uint32_t);
48    case L_SYMBOL:
49        return sizeof(uint8_t) + sizeof(uintptr_t);
50    }
51
52    /* Do not serialise other types */
53    return 0;
54}
55
56void write_level(bFILE *fp, LObject *level)
57{
58    int type = item_type(level);
59    fp->write_uint8(type);
60
61    switch (type)
62    {
63    case L_CONS_CELL:
64        if (!level)
65            fp->write_uint32(0);
66        else
67        {
68            size_t count = 0;
69            void *b = level;
70            for (; b && item_type(b) == L_CONS_CELL; b = CDR(b))
71                count++;
72            /* If last element is not the empty list, it's a dotted list
73             * and we need to save the last object. Write a negative size
74             * to reflect that. */
75            fp->write_uint32(b ? -(int32_t)count : count);
76            if (b)
77                write_level(fp, (LObject *)b);
78
79            for (b = level; b && item_type(b) == L_CONS_CELL; b = CDR(b))
80                write_level(fp, CAR(b));
81        }
82        break;
83    case L_CHARACTER:
84        fp->write_uint16(lcharacter_value(level));
85        break;
86    case L_STRING:
87        {
88            size_t count = strlen(lstring_value(level)) + 1;
89            fp->write_uint32(count);
90            fp->write(lstring_value(level), count);
91        }
92        break;
93    case L_NUMBER:
94        fp->write_uint32(lnumber_value(level));
95        break;
96    case L_SYMBOL:
97        {
98            uintptr_t p = (uintptr_t)level;
99            for (size_t i = 0; i < sizeof(uintptr_t); i++)
100            {
101                fp->write_uint8((uint8_t)p);
102                p >>= 8;
103            }
104        }
105    }
106}
107
108LObject *load_block(bFILE *fp)
109{
110    int type = fp->read_uint8();
111
112    switch (type)
113    {
114    case L_CONS_CELL:
115        {
116            int32_t t = (int32_t)fp->read_uint32();
117
118            if (!t)
119                return NULL;
120
121            LList *last = NULL, *first = NULL;
122            for (size_t count = abs(t); count--; )
123            {
124                LList *c = LList::Create();
125                if (first)
126                    last->cdr = c;
127                else
128                    first = c;
129                last = c;
130            }
131            last->cdr = (t < 0) ? (LObject *)load_block(fp) : NULL;
132
133            last = first;
134            for (size_t count = abs(t); count--; last = (LList *)last->cdr)
135                last->car = load_block(fp);
136            return first;
137        }
138    case L_CHARACTER:
139        return LChar::Create(fp->read_uint16());
140    case L_STRING:
141        {
142            size_t count = fp->read_uint32();
143            LString *s = LString::Create(count);
144            fp->read(s->GetString(), count);
145            return s;
146        }
147    case L_NUMBER:
148        return LNumber::Create(fp->read_uint32());
149    case L_SYMBOL:
150        {
151            uintptr_t ret = 0, mul = 1;
152            for (size_t i = 0; i < sizeof(uintptr_t); i++)
153            {
154                ret |= mul * fp->read_uint8();
155                mul *= 8;
156            }
157            return (LObject *)ret;
158        }
159    }
160
161    return NULL;
162}
163
Note: See TracBrowser for help on using the repository browser.