1 | /* (c) Magnus Auvinen. See licence.txt in the root of the distribution for more information. */ |
2 | /* If you are missing that file, acquire a complete release at teeworlds.com. */ |
3 | #ifndef ENGINE_SHARED_SNAPSHOT_H |
4 | #define ENGINE_SHARED_SNAPSHOT_H |
5 | |
6 | #include <cstddef> |
7 | #include <cstdint> |
8 | |
9 | // CSnapshot |
10 | |
11 | class CSnapshotItem |
12 | { |
13 | friend class CSnapshotBuilder; |
14 | |
15 | int *Data() { return (int *)(this + 1); } |
16 | |
17 | public: |
18 | int m_TypeAndId; |
19 | |
20 | const int *Data() const { return (int *)(this + 1); } |
21 | int Type() const { return m_TypeAndId >> 16; } |
22 | int Id() const { return m_TypeAndId & 0xffff; } |
23 | int Key() const { return m_TypeAndId; } |
24 | }; |
25 | |
26 | class CSnapshot |
27 | { |
28 | friend class CSnapshotBuilder; |
29 | int m_DataSize = 0; |
30 | int m_NumItems = 0; |
31 | |
32 | int *Offsets() const { return (int *)(this + 1); } |
33 | char *DataStart() const { return (char *)(Offsets() + m_NumItems); } |
34 | |
35 | size_t OffsetSize() const { return sizeof(int) * m_NumItems; } |
36 | size_t TotalSize() const { return sizeof(CSnapshot) + OffsetSize() + m_DataSize; } |
37 | |
38 | static const CSnapshot ms_EmptySnapshot; |
39 | |
40 | public: |
41 | enum |
42 | { |
43 | OFFSET_UUID_TYPE = 0x4000, |
44 | MAX_TYPE = 0x7fff, |
45 | MAX_ID = 0xffff, |
46 | MAX_ITEMS = 1024, |
47 | MAX_PARTS = 64, |
48 | MAX_SIZE = MAX_PARTS * 1024 |
49 | }; |
50 | |
51 | int NumItems() const { return m_NumItems; } |
52 | const CSnapshotItem *GetItem(int Index) const; |
53 | int GetItemSize(int Index) const; |
54 | int GetItemIndex(int Key) const; |
55 | int GetItemType(int Index) const; |
56 | int GetExternalItemType(int InternalType) const; |
57 | const void *FindItem(int Type, int Id) const; |
58 | |
59 | unsigned Crc() const; |
60 | void DebugDump() const; |
61 | bool IsValid(size_t ActualSize) const; |
62 | |
63 | static const CSnapshot *EmptySnapshot() { return &ms_EmptySnapshot; } |
64 | }; |
65 | |
66 | // CSnapshotDelta |
67 | |
68 | class CSnapshotDelta |
69 | { |
70 | public: |
71 | class CData |
72 | { |
73 | public: |
74 | int m_NumDeletedItems; |
75 | int m_NumUpdateItems; |
76 | int m_NumTempItems; // needed? |
77 | int m_aData[1]; |
78 | }; |
79 | |
80 | private: |
81 | enum |
82 | { |
83 | MAX_NETOBJSIZES = 64 |
84 | }; |
85 | short m_aItemSizes[MAX_NETOBJSIZES]; |
86 | int m_aSnapshotDataRate[CSnapshot::MAX_TYPE + 1]; |
87 | int m_aSnapshotDataUpdates[CSnapshot::MAX_TYPE + 1]; |
88 | CData m_Empty; |
89 | |
90 | static void UndiffItem(const int *pPast, const int *pDiff, int *pOut, int Size, int *pDataRate); |
91 | |
92 | public: |
93 | static int DiffItem(const int *pPast, const int *pCurrent, int *pOut, int Size); |
94 | CSnapshotDelta(); |
95 | CSnapshotDelta(const CSnapshotDelta &Old); |
96 | int GetDataRate(int Index) const { return m_aSnapshotDataRate[Index]; } |
97 | int GetDataUpdates(int Index) const { return m_aSnapshotDataUpdates[Index]; } |
98 | void SetStaticsize(int ItemType, size_t Size); |
99 | const CData *EmptyDelta() const; |
100 | int CreateDelta(const CSnapshot *pFrom, const CSnapshot *pTo, void *pDstData); |
101 | int UnpackDelta(const CSnapshot *pFrom, CSnapshot *pTo, const void *pSrcData, int DataSize); |
102 | int DebugDumpDelta(const void *pSrcData, int DataSize); |
103 | }; |
104 | |
105 | // CSnapshotStorage |
106 | |
107 | class CSnapshotStorage |
108 | { |
109 | public: |
110 | class CHolder |
111 | { |
112 | public: |
113 | CHolder *m_pPrev; |
114 | CHolder *m_pNext; |
115 | |
116 | int64_t m_Tagtime; |
117 | int m_Tick; |
118 | |
119 | int m_SnapSize; |
120 | int m_AltSnapSize; |
121 | |
122 | CSnapshot *m_pSnap; |
123 | CSnapshot *m_pAltSnap; |
124 | }; |
125 | |
126 | CHolder *m_pFirst; |
127 | CHolder *m_pLast; |
128 | |
129 | CSnapshotStorage() { Init(); } |
130 | ~CSnapshotStorage() { PurgeAll(); } |
131 | void Init(); |
132 | void PurgeAll(); |
133 | void PurgeUntil(int Tick); |
134 | void Add(int Tick, int64_t Tagtime, size_t DataSize, const void *pData, size_t AltDataSize, const void *pAltData); |
135 | int Get(int Tick, int64_t *pTagtime, const CSnapshot **ppData, const CSnapshot **ppAltData) const; |
136 | }; |
137 | |
138 | class CSnapshotBuilder |
139 | { |
140 | enum |
141 | { |
142 | MAX_EXTENDED_ITEM_TYPES = 64, |
143 | }; |
144 | |
145 | char m_aData[CSnapshot::MAX_SIZE]; |
146 | int m_DataSize; |
147 | |
148 | int m_aOffsets[CSnapshot::MAX_ITEMS]; |
149 | int m_NumItems; |
150 | |
151 | int m_aExtendedItemTypes[MAX_EXTENDED_ITEM_TYPES]; |
152 | int m_NumExtendedItemTypes; |
153 | |
154 | void AddExtendedItemType(int Index); |
155 | int GetExtendedItemTypeIndex(int TypeId); |
156 | int GetTypeFromIndex(int Index) const; |
157 | |
158 | bool m_Sixup; |
159 | |
160 | public: |
161 | CSnapshotBuilder(); |
162 | |
163 | void Init(bool Sixup = false); |
164 | |
165 | void *NewItem(int Type, int Id, int Size); |
166 | |
167 | CSnapshotItem *GetItem(int Index); |
168 | int *GetItemData(int Key); |
169 | |
170 | int Finish(void *pSnapdata); |
171 | }; |
172 | |
173 | #endif // ENGINE_SNAPSHOT_H |
174 | |