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