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
11class CSnapshotItem
12{
13 friend class CSnapshotBuilder;
14
15 int *Data() { return (int *)(this + 1); }
16
17public:
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
26class 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
40public:
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
68class CSnapshotDelta
69{
70public:
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
80private:
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
92public:
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
107class CSnapshotStorage
108{
109public:
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
138class 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
160public:
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