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_DATAFILE_H
4#define ENGINE_SHARED_DATAFILE_H
5
6#include "uuid_manager.h"
7
8#include <base/hash.h>
9#include <base/types.h>
10
11#include <engine/storage.h>
12
13#include <cstdint>
14#include <map>
15#include <vector>
16
17enum
18{
19 ITEMTYPE_EX = 0xFFFF,
20};
21
22// raw datafile access
23class CDataFileReader
24{
25 class CDatafile *m_pDataFile = nullptr;
26
27 int GetExternalItemType(int InternalType, CUuid *pUuid);
28 int GetInternalItemType(int ExternalType);
29
30public:
31 ~CDataFileReader();
32 CDataFileReader &operator=(CDataFileReader &&Other);
33
34 [[nodiscard]] bool Open(class IStorage *pStorage, const char *pFilename, int StorageType);
35 void Close();
36 bool IsOpen() const;
37 IOHANDLE File() const;
38
39 int GetDataSize(int Index) const;
40 void *GetData(int Index);
41 void *GetDataSwapped(int Index); // makes sure that the data is 32bit LE ints when saved
42 const char *GetDataString(int Index);
43 void ReplaceData(int Index, char *pData, size_t Size); // memory for data must have been allocated with malloc
44 void UnloadData(int Index);
45 int NumData() const;
46
47 int GetItemSize(int Index) const;
48 void *GetItem(int Index, int *pType = nullptr, int *pId = nullptr, CUuid *pUuid = nullptr);
49 void GetType(int Type, int *pStart, int *pNum);
50 int FindItemIndex(int Type, int Id);
51 void *FindItem(int Type, int Id);
52 int NumItems() const;
53
54 SHA256_DIGEST Sha256() const;
55 unsigned Crc() const;
56 int MapSize() const;
57};
58
59// write access
60class CDataFileWriter
61{
62public:
63 enum ECompressionLevel
64 {
65 COMPRESSION_DEFAULT,
66 COMPRESSION_BEST,
67 };
68
69private:
70 class CDataInfo
71 {
72 public:
73 void *m_pUncompressedData;
74 int m_UncompressedSize;
75 void *m_pCompressedData;
76 int m_CompressedSize;
77 ECompressionLevel m_CompressionLevel;
78 };
79
80 class CItemInfo
81 {
82 public:
83 int m_Type;
84 int m_Id;
85 int m_Size;
86 int m_Next;
87 int m_Prev;
88 void *m_pData;
89 };
90
91 class CItemTypeInfo
92 {
93 public:
94 int m_Num = 0;
95 int m_First = -1;
96 int m_Last = -1;
97 };
98
99 class CExtendedItemType
100 {
101 public:
102 int m_Type;
103 CUuid m_Uuid;
104 };
105
106 IOHANDLE m_File;
107 std::map<uint16_t, CItemTypeInfo, std::less<>> m_ItemTypes; // item types must be sorted in ascending order
108 std::vector<CItemInfo> m_vItems;
109 std::vector<CDataInfo> m_vDatas;
110 std::vector<CExtendedItemType> m_vExtendedItemTypes;
111
112 int GetTypeFromIndex(int Index) const;
113 int GetExtendedItemTypeIndex(int Type, const CUuid *pUuid);
114
115public:
116 CDataFileWriter();
117 CDataFileWriter(CDataFileWriter &&Other)
118 {
119 m_File = Other.m_File;
120 Other.m_File = nullptr;
121 m_ItemTypes = std::move(Other.m_ItemTypes);
122 m_vItems = std::move(Other.m_vItems);
123 m_vDatas = std::move(Other.m_vDatas);
124 m_vExtendedItemTypes = std::move(Other.m_vExtendedItemTypes);
125 }
126 ~CDataFileWriter();
127
128 [[nodiscard]] bool Open(class IStorage *pStorage, const char *pFilename, int StorageType = IStorage::TYPE_SAVE);
129 int AddItem(int Type, int Id, size_t Size, const void *pData, const CUuid *pUuid = nullptr);
130 int AddData(size_t Size, const void *pData, ECompressionLevel CompressionLevel = COMPRESSION_DEFAULT);
131 int AddDataSwapped(size_t Size, const void *pData);
132 int AddDataString(const char *pStr);
133 void Finish();
134};
135
136#endif
137