Project SkyFire Core
SkyFire 5.4.8 server core API documentation
Loading...
Searching...
No Matches
DB2FileLoader.cpp
Go to the documentation of this file.
1/*
2* This file is part of Project SkyFire https://www.projectskyfire.org.
3* See LICENSE.md file for Copyright information
4*/
5
6#include "Common.h"
7
8#include "DB2FileLoader.h"
9#include <stdio.h>
10#include <stdlib.h>
11#include <string.h>
12
13bool DB2FileLoader::Load(const char* filename, const char* fmt)
14{
15 if (data)
16 {
17 delete[] data;
18 data = NULL;
19 }
20
21 FILE* f = fopen(filename, "rb");
22 if (!f)
23 return false;
24
25 uint32 header;
26 if (fread(&header, 4, 1, f) != 1) // Signature
27 {
28 fclose(f);
29 return false;
30 }
31
32 EndianConvert(header);
33
34 if (header != 0x32424457)
35 {
36 fclose(f);
37 return false; //'WDB2'
38 }
39
40 if (fread(&recordCount, 4, 1, f) != 1) // Number of records
41 {
42 fclose(f);
43 return false;
44 }
45
47
48 if (fread(&fieldCount, 4, 1, f) != 1) // Number of fields
49 {
50 fclose(f);
51 return false;
52 }
53
55
56 if (fread(&recordSize, 4, 1, f) != 1) // Size of a record
57 {
58 fclose(f);
59 return false;
60 }
61
63
64 if (fread(&stringSize, 4, 1, f) != 1) // String size
65 {
66 fclose(f);
67 return false;
68 }
69
71
72 /* NEW WDB2 FIELDS*/
73 if (fread(&tableHash, 4, 1, f) != 1) // Table hash
74 {
75 fclose(f);
76 return false;
77 }
78
80
81 if (fread(&build, 4, 1, f) != 1) // Build
82 {
83 fclose(f);
84 return false;
85 }
86
88
89 if (fread(&unk1, 4, 1, f) != 1) // Unknown WDB2
90 {
91 fclose(f);
92 return false;
93 }
94
96
97 if (build > 12880)
98 {
99 if (fread(&minIndex, 4, 1, f) != 1) // MinIndex WDB2
100 {
101 fclose(f);
102 return false;
103 }
105
106 if (fread(&maxIndex, 4, 1, f) != 1) // MaxIndex WDB2
107 {
108 fclose(f);
109 return false;
110 }
112
113 if (fread(&locale, 4, 1, f) != 1) // Locales
114 {
115 fclose(f);
116 return false;
117 }
119
120 if (fread(&unk5, 4, 1, f) != 1) // Unknown WDB2
121 {
122 fclose(f);
123 return false;
124 }
126 }
127
128 if (maxIndex != 0)
129 {
130 int32 diff = maxIndex - minIndex + 1;
131 fseek(f, diff * 4 + diff * 2, SEEK_CUR); // diff * 4: an index for rows, diff * 2: a memory allocation bank
132 }
133
135 fieldsOffset[0] = 0;
136 for (uint32 i = 1; i < fieldCount; i++)
137 {
138 fieldsOffset[i] = fieldsOffset[i - 1];
139 if (fmt[i - 1] == 'b' || fmt[i - 1] == 'X')
140 fieldsOffset[i] += 1;
141 else
142 fieldsOffset[i] += 4;
143 }
144
145 data = new unsigned char[recordSize * recordCount + stringSize];
147
148 if (fread(data, recordSize * recordCount + stringSize, 1, f) != 1)
149 {
150 fclose(f);
151 return false;
152 }
153
154 fclose(f);
155 return true;
156}
157
159{
160 if (data)
161 delete[] data;
162 if (fieldsOffset)
163 delete[] fieldsOffset;
164}
165
167{
168 assert(data);
169 return Record(*this, data + id * recordSize);
170}
171
172uint32 DB2FileLoader::GetFormatRecordSize(std::string format, int32* index_pos)
173{
174 uint32 recordsize = 0;
175 int32 i = -1;
176 for (uint32 x = 0; format[x]; ++x)
177 {
178 switch (format[x])
179 {
180 case FT_FLOAT:
181 case FT_INT:
182 recordsize += 4;
183 break;
184 case FT_STRING:
185 recordsize += sizeof(char*);
186 break;
187 case FT_SORT:
188 i = x;
189 break;
190 case FT_IND:
191 i = x;
192 recordsize += 4;
193 break;
194 case FT_BYTE:
195 recordsize += 1;
196 break;
197 }
198 }
199
200 if (index_pos)
201 *index_pos = i;
202
203 return recordsize;
204}
205
207{
208 uint32 stringfields = 0;
209 for (uint32 x = 0; format[x]; ++x)
210 if (format[x] == FT_STRING)
211 ++stringfields;
212
213 return stringfields;
214}
215
216char* DB2FileLoader::AutoProduceData(std::string format, uint32& records, char**& indexTable)
217{
218 typedef char* ptr;
219 if (format.length() != fieldCount)
220 return NULL;
221
222 //get struct size and index pos
223 int32 i;
224 uint32 recordsize = GetFormatRecordSize(format, &i);
225
226 if (i >= 0)
227 {
228 uint32 maxi = 0;
229 //find max index
230 for (uint32 y = 0; y < recordCount; y++)
231 {
232 uint32 ind = getRecord(y).getUInt(i);
233 if (ind > maxi)
234 maxi = ind;
235 }
236
237 ++maxi;
238 records = maxi;
239 indexTable = new ptr[maxi];
240 memset(indexTable, 0, maxi * sizeof(ptr));
241 }
242 else
243 {
244 records = recordCount;
245 indexTable = new ptr[recordCount];
246 }
247
248 char* dataTable = new char[recordCount * recordsize];
249
250 uint32 offset = 0;
251
252 for (uint32 y = 0; y < recordCount; y++)
253 {
254 if (i >= 0)
255 {
256 indexTable[getRecord(y).getUInt(i)] = &dataTable[offset];
257 }
258 else
259 indexTable[y] = &dataTable[offset];
260
261 for (uint32 x = 0; x < fieldCount; x++)
262 {
263 switch (format[x])
264 {
265 case FT_FLOAT:
266 *((float*)(&dataTable[offset])) = getRecord(y).getFloat(x);
267 offset += 4;
268 break;
269 case FT_IND:
270 case FT_INT:
271 *((uint32*)(&dataTable[offset])) = getRecord(y).getUInt(x);
272 offset += 4;
273 break;
274 case FT_BYTE:
275 *((uint8*)(&dataTable[offset])) = getRecord(y).getUInt8(x);
276 offset += 1;
277 break;
278 case FT_STRING:
279 *((char**)(&dataTable[offset])) = NULL; // will be replaces non-empty or "" strings in AutoProduceStrings
280 offset += sizeof(char*);
281 break;
282 }
283 }
284 }
285
286 return dataTable;
287}
288
289static char const* const nullStr = "";
290
291char* DB2FileLoader::AutoProduceStringsArrayHolders(std::string format, char* dataTable)
292{
293 if (format.length() != fieldCount)
294 return NULL;
295
296 // we store flat holders pool as single memory block
297 size_t stringFields = GetFormatStringsFields(format);
298 // each string field at load have array of string for each locale
299 size_t stringHolderSize = sizeof(char*) * TOTAL_LOCALES;
300 size_t stringHoldersRecordPoolSize = stringFields * stringHolderSize;
301 size_t stringHoldersPoolSize = stringHoldersRecordPoolSize * recordCount;
302
303 char* stringHoldersPool = new char[stringHoldersPoolSize];
304
305 // DB2 strings expected to have at least empty string
306 for (size_t i = 0; i < stringHoldersPoolSize / sizeof(char*); ++i)
307 ((char const**)stringHoldersPool)[i] = nullStr;
308
309 uint32 offset = 0;
310
311 // assign string holders to string field slots
312 for (uint32 y = 0; y < recordCount; y++)
313 {
314 uint32 stringFieldNum = 0;
315
316 for (uint32 x = 0; x < fieldCount; x++)
317 switch (format[x])
318 {
319 case FT_FLOAT:
320 case FT_IND:
321 case FT_INT:
322 offset += 4;
323 break;
324 case FT_BYTE:
325 offset += 1;
326 break;
327 case FT_STRING:
328 {
329 // init db2 string field slots by pointers to string holders
330 char const*** slot = (char const***)(&dataTable[offset]);
331 *slot = (char const**)(&stringHoldersPool[stringHoldersRecordPoolSize * y + stringHolderSize * stringFieldNum]);
332 ++stringFieldNum;
333 offset += sizeof(char*);
334 break;
335 }
336 case FT_NA:
337 case FT_NA_BYTE:
338 case FT_SORT:
339 break;
340 default:
341 assert(false && "unknown format character");
342 }
343 }
344
345 //send as char* for store in char* pool list for free at unload
346 return stringHoldersPool;
347}
348
349char* DB2FileLoader::AutoProduceStrings(std::string format, char* dataTable, uint32 locale)
350{
351 if (format.length() != fieldCount)
352 return NULL;
353
354 char* stringPool = new char[stringSize];
355 memcpy(stringPool, stringTable, stringSize);
356
357 uint32 offset = 0;
358
359 for (uint32 y = 0; y < recordCount; y++)
360 {
361 for (uint32 x = 0; x < fieldCount; x++)
362 switch (format[x])
363 {
364 case FT_FLOAT:
365 case FT_IND:
366 case FT_INT:
367 offset += 4;
368 break;
369 case FT_BYTE:
370 offset += 1;
371 break;
372 case FT_STRING:
373 {
374 // fill only not filled entries
375 LocalizedString* db2str = *(LocalizedString**)(&dataTable[offset]);
376 if (db2str->Str[locale] == nullStr)
377 {
378 const char* st = getRecord(y).getString(x);
379 db2str->Str[locale] = stringPool + (st - (const char*)stringTable);
380 }
381
382 offset += sizeof(char*);
383 break;
384 }
385 }
386 }
387
388 return stringPool;
389}
void EndianConvert(T &)
const uint8 TOTAL_LOCALES
Definition Common.h:153
static char const *const nullStr
std::int32_t int32
Definition Define.h:73
std::uint8_t uint8
Definition Define.h:79
std::uint32_t uint32
Definition Define.h:77
@ FT_IND
Definition Define.h:90
@ FT_NA
Definition Define.h:83
@ FT_FLOAT
Definition Define.h:86
@ FT_STRING
Definition Define.h:85
@ FT_SORT
Definition Define.h:89
@ FT_NA_BYTE
Definition Define.h:84
@ FT_INT
Definition Define.h:87
@ FT_BYTE
Definition Define.h:88
float getFloat(size_t field) const
uint8 getUInt8(size_t field) const
uint32 getUInt(size_t field) const
const char * getString(size_t field) const
static uint32 GetFormatStringsFields(std::string format)
unsigned char * data
static uint32 GetFormatRecordSize(std::string format, int32 *index_pos=NULL)
bool Load(const char *filename, const char *fmt)
char * AutoProduceStrings(std::string fmt, char *dataTable, uint32 locale)
char * AutoProduceData(std::string fmt, uint32 &count, char **&indexTable)
Record getRecord(size_t id)
unsigned char * stringTable
uint32 * fieldsOffset
char * AutoProduceStringsArrayHolders(std::string fmt, char *dataTable)
char const * Str[TOTAL_LOCALES]
Definition Common.h:173