source: abuse/branches/lol/src/lcache.cpp @ 732

Last change on this file since 732 was 732, checked in by Sam Hocevar, 8 years ago

build: SDL2 compilation fixes.

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