CorsixTH engine (the C++ part)
Open source implementation of Theme Hospital
Loading...
Searching...
No Matches
persist_lua.h
Go to the documentation of this file.
1/*
2Copyright (c) 2010 Peter "Corsix" Cawley
3
4Permission is hereby granted, free of charge, to any person obtaining a copy of
5this software and associated documentation files (the "Software"), to deal in
6the Software without restriction, including without limitation the rights to
7use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
8of the Software, and to permit persons to whom the Software is furnished to do
9so, subject to the following conditions:
10
11The above copyright notice and this permission notice shall be included in all
12copies or substantial portions of the Software.
13
14THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20SOFTWARE.
21*/
22
23#ifndef CORSIX_TH_PERSIST_LUA_H_
24#define CORSIX_TH_PERSIST_LUA_H_
25#include "config.h"
26
27#include <type_traits>
28#include <vector>
29
30#include "lua.hpp"
31
32template <class T>
34template <>
35struct lua_persist_int<int> {
36 typedef unsigned int T;
37};
38
40
45 public:
46 virtual ~lua_persist_writer() = default;
47
48 virtual lua_State* get_stack() = 0;
49 virtual void write_stack_object(int iIndex) = 0;
50 virtual void write_byte_stream(const uint8_t* pBytes, size_t iCount) = 0;
51 virtual void set_error(const char* sError) = 0;
52
53 // write_stack_object for userdata without growing the Lua call stack
54 // The given index should be a userdata whose __persist metamethod supports
55 // fast persistence (being called with extra arguments and the wrong
56 // environment / upvalues).
57 virtual void fast_write_stack_object(int iIndex) = 0;
58
59 // Writes an unsigned integer as a variable number of bytes
60 // Endian independent and underlying type size independent
61 template <class T>
62 void write_uint(T tValue) {
63 static_assert(std::is_integral<T>::value, "T must be an integer type");
64
65 T tTemp(tValue);
66 int iNumBytes;
67 for (iNumBytes = 1; tTemp >= (T)0x80; tTemp /= (T)0x80) ++iNumBytes;
68 if (iNumBytes == 1) {
69 uint8_t iByte = (uint8_t)tValue;
70 write_byte_stream(&iByte, 1);
71 } else {
72 std::vector<uint8_t> bytes(iNumBytes);
73 bytes[iNumBytes - 1] = 0x7F & (uint8_t)(tValue);
74 for (int i = 1; i < iNumBytes; ++i) {
75 tValue /= (T)0x80;
76 bytes[iNumBytes - 1 - i] = 0x80 | (0x7F & (uint8_t)tValue);
77 }
78 write_byte_stream(bytes.data(), iNumBytes);
79 }
80 }
81
82 template <class T>
83 void write_int(T tValue) {
84 typename lua_persist_int<T>::T tValueToWrite;
85 if (tValue >= 0) {
86 tValueToWrite = (typename lua_persist_int<T>::T)tValue;
87 tValueToWrite <<= 1;
88 } else {
89 tValueToWrite = (typename lua_persist_int<T>::T)(-(tValue + 1));
90 tValueToWrite <<= 1;
91 tValueToWrite |= 1;
92 }
93 write_uint(tValueToWrite);
94 }
95
96 template <class T>
97 void write_float(T fValue) {
98 write_byte_stream(reinterpret_cast<uint8_t*>(&fValue), sizeof(T));
99 }
100};
101
103
108 public:
109 virtual ~lua_persist_reader() = default;
110
111 virtual lua_State* get_stack() = 0;
112 virtual bool read_stack_object() = 0;
113 virtual bool read_byte_stream(uint8_t* pBytes, size_t iCount) = 0;
114 virtual void set_error(const char* sError) = 0;
115
116 // Reads an integer previously written by lua_persist_writer::write_uint()
117 template <class T>
118 bool read_uint(T& tValue) {
119 T tTemp(0);
120 uint8_t iByte;
121
122 while (true) {
123 if (!read_byte_stream(&iByte, 1)) return false;
124 if (iByte & 0x80) {
125 tTemp = static_cast<T>(tTemp | (iByte & 0x7F));
126 tTemp = static_cast<T>(tTemp << 7);
127 } else {
128 tTemp = static_cast<T>(tTemp | iByte);
129 break;
130 }
131 }
132
133 tValue = tTemp;
134 return true;
135 }
136
137 template <class T>
138 bool read_int(T& tValue) {
139 typename lua_persist_int<T>::T tWrittenValue;
140 if (!read_uint(tWrittenValue)) return false;
141 if (tWrittenValue & 1)
142 tValue = (-(T)(tWrittenValue >> 1)) - 1;
143 else
144 tValue = static_cast<T>(tWrittenValue >> 1);
145 return true;
146 }
147
148 template <class T>
149 bool read_float(T& fValue) {
150 if (!read_byte_stream(reinterpret_cast<uint8_t*>(&fValue), sizeof(T)))
151 return false;
152 return true;
153 }
154};
155
156int luaopen_persist(lua_State* L);
157
158#endif // CORSIX_TH_PERSIST_LUA_H_
Interface used for depersisting Lua objects.
Definition persist_lua.h:107
bool read_float(T &fValue)
Definition persist_lua.h:149
virtual ~lua_persist_reader()=default
virtual bool read_stack_object()=0
virtual void set_error(const char *sError)=0
virtual bool read_byte_stream(uint8_t *pBytes, size_t iCount)=0
virtual lua_State * get_stack()=0
bool read_uint(T &tValue)
Definition persist_lua.h:118
bool read_int(T &tValue)
Definition persist_lua.h:138
Interface used for persisting Lua objects.
Definition persist_lua.h:44
virtual void write_byte_stream(const uint8_t *pBytes, size_t iCount)=0
void write_uint(T tValue)
Definition persist_lua.h:62
void write_int(T tValue)
Definition persist_lua.h:83
virtual lua_State * get_stack()=0
void write_float(T fValue)
Definition persist_lua.h:97
virtual ~lua_persist_writer()=default
virtual void fast_write_stack_object(int iIndex)=0
virtual void write_stack_object(int iIndex)=0
virtual void set_error(const char *sError)=0
int luaopen_persist(lua_State *L)
Definition persist_lua.cpp:1326
unsigned int T
Definition persist_lua.h:36
Definition persist_lua.h:33