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