-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathSaveData.py
More file actions
executable file
·151 lines (130 loc) · 5.62 KB
/
SaveData.py
File metadata and controls
executable file
·151 lines (130 loc) · 5.62 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
from ctypes import *
from enum import Enum
import sys
class SaveSection(Enum):
UNDEFINED = 0x00
# Container type UNDEFINED if none of them
STRING_MAP = 0x01 # string map (hard limit : 65535 entries)
ADDRESS_MAP = 0x02 # uint64_t map (hard limit : 65535 entries)
LIST = 0x03 # list (hard limit : 65535 entries)
POINTER = 0x40 # pointer to another SaveData (not implemented yet)
SHORT_MAP = 0x42 # Map of uint16_t (hard limit : 65535 entries)
WIDE_LIST = 0x43 # List (hard limit : 4294967295 entries)
# Attached data size length UNDEFINED for no attached data
CHAR_SIZE = 0x04
SHORT_SIZE = 0x08
INT_SIZE = 0x0c
# Attached data type for special data only
SUBFILE = 0x10
# This object hold a reference in the BigSave reference table
REFERENCED = 0x20
# Use an extended type
EXTENDED_TYPE = 0x80
TYPE_MASK = 0x43
SIZE_MASK = 0x0c
SPECIAL_MASK = 0x10
vec3 = c_double * 3
c_str = c_void_p
class SaveData:
"""SaveData interface with C++, note that methods start with _
The operator[](const std::string &key) is the . operator
The operator[](uint64_t address) is the [] operator
"""
_lib = None
_parent = None
def init(lib):
"Initialize the SaveData system"
SaveData._lib = lib
SaveData._lib.sd_strmap.restype = c_void_p
SaveData._lib.sd_nbrmap.restype = c_void_p
SaveData._lib.sd_new.restype = c_void_p
SaveData._lib.sd_get.restype = c_void_p
SaveData._lib.sd_file.restype = c_void_p
SaveData._lib.sd_getraw.restype = c_void_p
SaveData._lib.sd_computesize.restype = c_uint64
SaveData._lib.sd_repr.restype = c_char_p
SaveData._lib.sd_size.restype = c_int
SaveData._lib.sd_push.restype = c_int
SaveData._lib.sd_copy.restype = None
SaveData._lib.sd_delete.restype = None
SaveData._lib.sd_set.restype = None
SaveData._lib.sd_save.restype = None
SaveData._lib.sd_load.restype = None
SaveData._lib.sd_truncate.restype = None
SaveData._lib.sd_reset.restype = None
SaveData._lib.sd_close.restype = None
SaveData._lib.bs_new.restype = c_void_p
SaveData._lib.bs_delete.restype = None
SaveData._lib.bs_open.restype = c_bool
SaveData._lib.bs_store.restype = c_bool
def detach():
"Detach the SaveData library"
SaveData._lib = None
def __init__(self, ptr = None, parent = None):
self._ = SaveData._lib
if ptr is None:
self._ref = self._.sd_new()
else:
self._ref = ptr
self._parent = parent
def __del__(self):
if self._parent is None:
self._.sd_delete(c_void_p(self._ref))
def __repr__(self):
return str(self._.sd_repr(c_void_p(self._ref)), "utf-8");
# for [] operator, usefull for integral entries
def __getitem__(self, key):
if type(key) is str:
return SaveData(self._.sd_strmap(c_void_p(self._ref), c_char_p(bytes(name, encoding="utf-8"))), self)
else:
return SaveData(self._.sd_nbrmap(c_void_p(self._ref), c_uint64(key)), self)
def __setitem__(self, key, value):
if type(key) is str:
if type(value) is SaveData:
self._.sd_copy(self._.sd_strmap(c_void_p(self._ref), c_char_p(bytes(name, encoding="utf-8"))), c_void_p(value._ref))
else:
self._.sd_set(self._.sd_strmap(c_void_p(self._ref), c_char_p(bytes(name, encoding="utf-8"))), byref(value), sizeof(value))
else:
if type(value) is SaveData:
self._.sd_copy(self._.sd_nbrmap(c_void_p(self._ref), c_uint64(key)), c_void_p(value._ref))
else:
self._.sd_set(self._.sd_nbrmap(c_void_p(self._ref), c_uint64(key)), byref(value), sizeof(value))
def append(self, value):
if type(value) is SaveData:
return self._.sd_push(c_void_p(self._ref), c_void_p(value._ref))
else:
raise TypeError("Value must be a SaveData")
def get(self, ctype):
"Return the stored data of the given type"
return cast(self._.sd_get(c_void_p(self._ref), sizeof(ctype)), POINTER(ctype)).contents
def raw(self):
"Return the stored bytes as a c_char array"
sz = c_int()
return cast(self._.sd_getraw(c_void_p(self._ref), byref(sz)), c_char * sz)
def set(self, value):
"Store the given bytes or c_type in this SaveData"
if type(value) is bytes:
self._.sd_set(c_void_p(self._ref), cast(value, c_void_p), len(value))
else:
self._.sd_set(c_void_p(self._ref), byref(value), sizeof(value))
def __len__(self):
"Return the number of SaveData directly attached to this SaveData"
self._.sd_size(c_void_p(self._ref))
def load(self, buffer):
"Load a SaveData from a buffer"
self._.sd_load(c_void_p(self._ref), cast(buffer, c_void_p))
def save(self):
"Save a SaveData to a c_char array and return it"
ret = c_char * self._.sd_computesize(c_void_p(self._ref))
self._.sd_save(c_void_p(self._ref), ret)
return ret
def copy(self):
"Copy this SaveData"
ret = SaveData();
self._.sd_copy(ret._ref, self._ref)
return ret
def file(self, path=None):
if (path is None):
return BigSave(self._.sd_file(ret._ref, c_void_p(0)), self);
else:
return BigSave(self._.sd_file(ret._ref, c_char_p(bytes(path, encoding="utf-8"))), self);