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

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

[svn] * Proper SVN structure

Original author: Neo2003
Date: 2008-10-02 16:23:55-05:00

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