root/trunk/src/shared/Database/dbcfile.cpp @ 102

Revision 102, 6.4 kB (checked in by yumileroy, 17 years ago)

[svn] Fixed copyright notices to comply with GPL.

Original author: w12x
Date: 2008-10-23 03:29:52-05:00

Line 
1/*
2 * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/>
3 *
4 * Copyright (C) 2008 Trinity <http://www.trinitycore.org/>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 */
20
21#include <stdio.h>
22#include <stdlib.h>
23#include <string.h>
24
25#include "dbcfile.h"
26
27DBCFile::DBCFile()
28{
29    data = NULL;
30    fieldsOffset = NULL;
31}
32
33bool DBCFile::Load(const char *filename, const char *fmt)
34{
35
36    uint32 header;
37    if(data)
38    {
39        delete [] data;
40        data=NULL;
41    }
42    FILE * f=fopen(filename,"rb");
43    if(!f)return false;
44
45    fread(&header,4,1,f);                                   // Number of records
46    EndianConvert(header);
47    if(header!=0x43424457)
48    {
49        //printf("not dbc file");
50        return false;                                       //'WDBC'
51    }
52    fread(&recordCount,4,1,f);                              // Number of records
53    EndianConvert(recordCount);
54    fread(&fieldCount,4,1,f);                               // Number of fields
55    EndianConvert(fieldCount);
56    fread(&recordSize,4,1,f);                               // Size of a record
57    EndianConvert(recordSize);
58    fread(&stringSize,4,1,f);                               // String size
59    EndianConvert(stringSize);
60
61    fieldsOffset = new uint32[fieldCount];
62    fieldsOffset[0] = 0;
63    for(uint32 i = 1; i < fieldCount; i++)
64    {
65        fieldsOffset[i] = fieldsOffset[i - 1];
66        if (fmt[i - 1] == 'b' || fmt[i - 1] == 'X')         // byte fields
67            fieldsOffset[i] += 1;
68        else                                                // 4 byte fields (int32/float/strings)
69            fieldsOffset[i] += 4;
70    }
71
72    data = new unsigned char[recordSize*recordCount+stringSize];
73    stringTable = data + recordSize*recordCount;
74    fread(data,recordSize*recordCount+stringSize,1,f);
75    fclose(f);
76    return true;
77}
78
79DBCFile::~DBCFile()
80{
81    if(data)
82        delete [] data;
83    if(fieldsOffset)
84        delete [] fieldsOffset;
85}
86
87DBCFile::Record DBCFile::getRecord(size_t id)
88{
89    assert(data);
90    return Record(*this, data + id*recordSize);
91}
92
93uint32 DBCFile::GetFormatRecordSize(const char * format,int32* index_pos)
94{
95    uint32 recordsize = 0;
96    int32 i = -1;
97    for(uint32 x=0; format[x];++x)
98        switch(format[x])
99        {
100            case FT_FLOAT:
101            case FT_INT:
102                recordsize+=4;
103                break;
104            case FT_STRING:
105                recordsize+=sizeof(char*);
106                break;
107            case FT_SORT:
108                i=x;
109                break;
110            case FT_IND:
111                i=x;
112                recordsize+=4;
113                break;
114            case FT_BYTE:
115                recordsize += 1;
116                break;
117        }
118
119    if(index_pos)
120        *index_pos = i;
121
122    return recordsize;
123}
124
125char* DBCFile::AutoProduceData(const char* format, uint32& records, char**& indexTable)
126{
127    /*
128    format STRING, NA, FLOAT,NA,INT <=>
129    struct{
130    char* field0,
131    float field1,
132    int field2
133    }entry;
134
135    this func will generate  entry[rows] data;
136    */
137
138    typedef char * ptr;
139    if(strlen(format)!=fieldCount)
140        return NULL;
141
142    //get struct size and index pos
143    int32 i;
144    uint32 recordsize=GetFormatRecordSize(format,&i);
145
146    if(i>=0)
147    {
148        uint32 maxi=0;
149        //find max index
150        for(uint32 y=0;y<recordCount;y++)
151        {
152            uint32 ind=getRecord(y).getUInt (i);
153            if(ind>maxi)maxi=ind;
154        }
155
156        ++maxi;
157        records=maxi;
158        indexTable=new ptr[maxi];
159        memset(indexTable,0,maxi*sizeof(ptr));
160    }
161    else
162    {
163        records = recordCount;
164        indexTable = new ptr[recordCount];
165    }
166
167    char* dataTable= new char[recordCount*recordsize];
168
169    uint32 offset=0;
170
171    for(uint32 y =0;y<recordCount;y++)
172    {
173        if(i>=0)
174        {
175            indexTable[getRecord(y).getUInt(i)]=&dataTable[offset];
176        }
177        else
178            indexTable[y]=&dataTable[offset];
179
180        for(uint32 x=0;x<fieldCount;x++)
181        {
182            switch(format[x])
183            {
184                case FT_FLOAT:
185                    *((float*)(&dataTable[offset]))=getRecord(y).getFloat(x);
186                    offset+=4;
187                    break;
188                case FT_IND:
189                case FT_INT:
190                    *((uint32*)(&dataTable[offset]))=getRecord(y).getUInt(x);
191                    offset+=4;
192                    break;
193                case FT_BYTE:
194                    *((uint8*)(&dataTable[offset]))=getRecord(y).getUInt8(x);
195                    offset+=1;
196                    break;
197                case FT_STRING:
198                    *((char**)(&dataTable[offset]))=NULL;   // will be replaces non-empty or "" strings in AutoProduceStrings
199                    offset+=sizeof(char*);
200                    break;
201            }
202        }
203    }
204
205    return dataTable;
206}
207
208char* DBCFile::AutoProduceStrings(const char* format, char* dataTable)
209{
210    if(strlen(format)!=fieldCount)
211        return NULL;
212
213    char* stringPool= new char[stringSize];
214    memcpy(stringPool,stringTable,stringSize);
215
216    uint32 offset=0;
217
218    for(uint32 y =0;y<recordCount;y++)
219    {
220        for(uint32 x=0;x<fieldCount;x++)
221            switch(format[x])
222        {
223            case FT_FLOAT:
224            case FT_IND:
225            case FT_INT:
226                offset+=4;
227                break;
228            case FT_BYTE:
229                offset+=1;
230                break;
231            case FT_STRING:
232                // fill only not filled entries
233                char** slot = (char**)(&dataTable[offset]);
234                if(!*slot || !**slot)
235                {
236                    const char * st = getRecord(y).getString(x);
237                    *slot=stringPool+(st-(const char*)stringTable);
238                }
239                offset+=sizeof(char*);
240                break;
241        }
242    }
243
244    return stringPool;
245}
Note: See TracBrowser for help on using the browser.