1 | unit UDBC;
|
---|
2 |
|
---|
3 | {$mode Delphi}{$H+}
|
---|
4 |
|
---|
5 | interface
|
---|
6 |
|
---|
7 | uses
|
---|
8 | Classes, SysUtils, Strings, Variants;
|
---|
9 |
|
---|
10 | const
|
---|
11 | HeaderSize = 20;
|
---|
12 | DBCSignature = $43424457;
|
---|
13 |
|
---|
14 | type
|
---|
15 | TDBCColumnType = (ctUInt32, ctSInt32, ctSingle, ctString, ctByte);
|
---|
16 |
|
---|
17 | { TDBC }
|
---|
18 |
|
---|
19 | TDBC = class
|
---|
20 | private
|
---|
21 | FileStream: TFileStream;
|
---|
22 | RecordCount: Integer;
|
---|
23 | FieldCount: Integer;
|
---|
24 | RecordSize: Integer;
|
---|
25 | StringBlockSize: Integer;
|
---|
26 | public
|
---|
27 | Cells: array of array of Variant;
|
---|
28 | ColumnFormat: array of TDBCColumnType;
|
---|
29 | function DetectColumnType(Column: Integer): TDBCColumnType;
|
---|
30 | procedure LoadFromFile(FileName: string);
|
---|
31 | procedure LoadColumnStrings(Column: Integer);
|
---|
32 | procedure SaveToFile(FileName: string);
|
---|
33 | procedure SetString(Row, Column: Integer; Text: AnsiString);
|
---|
34 | end;
|
---|
35 |
|
---|
36 | implementation
|
---|
37 |
|
---|
38 | { TDBC }
|
---|
39 |
|
---|
40 | procedure TDBC.LoadFromFile(FileName: string);
|
---|
41 | var
|
---|
42 | Signature: Cardinal;
|
---|
43 | Row, Col: Integer;
|
---|
44 | begin
|
---|
45 | FileStream := TFileStream.Create(FileName, fmOpenRead);
|
---|
46 | with FileStream do begin
|
---|
47 | Signature := ReadDWord;
|
---|
48 | if Signature <> DBCSignature then
|
---|
49 | raise Exception.Create('DBC type mismatch.');
|
---|
50 |
|
---|
51 | RecordCount := ReadDWord;
|
---|
52 | FieldCount := ReadDWord;
|
---|
53 | RecordSize := ReadDWord;
|
---|
54 | StringBlockSize := ReadDWord;
|
---|
55 |
|
---|
56 | SetLength(Cells, RecordCount, FieldCount);
|
---|
57 | for Row := 0 to RecordCount - 1 do
|
---|
58 | for Col := 0 to FieldCount - 1 do begin
|
---|
59 | Cells[Row, Col] := ReadDWord;
|
---|
60 | end;
|
---|
61 | end;
|
---|
62 | end;
|
---|
63 |
|
---|
64 | procedure TDBC.LoadColumnStrings(Column: Integer);
|
---|
65 | var
|
---|
66 | Row: Integer;
|
---|
67 | Offset: Integer;
|
---|
68 | Text: AnsiString;
|
---|
69 | C: Char;
|
---|
70 | begin
|
---|
71 | with FileStream do
|
---|
72 | for Row := 0 to RecordCount - 1 do begin
|
---|
73 | Offset := HeaderSize + RecordCount * RecordSize + Cells[Row, Column];
|
---|
74 | if Position <> Offset then Seek(Offset, soBeginning);
|
---|
75 |
|
---|
76 | Text := '';
|
---|
77 | C := ' ';
|
---|
78 | while (C <> #0) do begin
|
---|
79 | C := Chr(ReadByte);
|
---|
80 | if C <> #0 then Text := Text + C;
|
---|
81 | end;
|
---|
82 | Cells[Row, Column] := Text;
|
---|
83 | end;
|
---|
84 | end;
|
---|
85 |
|
---|
86 | procedure TDBC.SaveToFile(FileName: string);
|
---|
87 | var
|
---|
88 | Row, Col: Integer;
|
---|
89 | Offset: Integer;
|
---|
90 | StringList: array of string;
|
---|
91 | begin
|
---|
92 | if Assigned(FileStream) then FileStream.Free;
|
---|
93 | FileStream := TFileStream.Create(FileName, fmCreate);
|
---|
94 | with FileStream do begin
|
---|
95 | WriteDWord(DBCSignature);
|
---|
96 | WriteDWord(RecordCount);
|
---|
97 | WriteDWord(FieldCount);
|
---|
98 | WriteDWord(RecordSize);
|
---|
99 | WriteDWord(StringBlockSize);
|
---|
100 |
|
---|
101 | Size := RecordSize * RecordCount;
|
---|
102 | SetLength(StringList, 0);
|
---|
103 | Offset := 1;
|
---|
104 | // Write cells
|
---|
105 | for Row := 0 to RecordCount - 1 do begin
|
---|
106 | for Col := 0 to FieldCount - 1 do begin
|
---|
107 | if VarIsStr(Cells[Row, Col]) then begin
|
---|
108 | //System.Write(IntToStr(Offset) + ': "' + Cells[Row, Col] + '", ');
|
---|
109 | WriteDWord(Offset);
|
---|
110 | Offset := Offset + Length(Cells[Row, Col]) + 1;
|
---|
111 | SetLength(StringList, Length(StringList) + 1);
|
---|
112 | StringList[High(StringList)] := Cells[Row, Col];
|
---|
113 | end else begin
|
---|
114 | //System.Write(IntToStr(Cells[Row, Col]) + ', ');
|
---|
115 | WriteDWord(Cells[Row, Col]);
|
---|
116 | end;
|
---|
117 | end;
|
---|
118 | //WriteLn;
|
---|
119 | end;
|
---|
120 |
|
---|
121 | // Write strings
|
---|
122 | Offset := 1;
|
---|
123 | WriteByte(0);
|
---|
124 | for Row := 0 to Length(StringList) - 1 do begin
|
---|
125 | //WriteLn('Id: ' + IntToStr(Row) + ', Offset: ' + IntToStr(Offset) + ', "' + StringList[Row] + '"');
|
---|
126 | for Col := 1 to Length(StringList[Row]) do
|
---|
127 | WriteByte(Ord(StringList[Row][Col]));
|
---|
128 | WriteByte(0);
|
---|
129 | Offset := Offset + Length(StringList[Row]) + 1;
|
---|
130 | end;
|
---|
131 |
|
---|
132 | // Update string block size
|
---|
133 | StringBlockSize := Offset;
|
---|
134 | Seek(16, soFromBeginning);
|
---|
135 | WriteDWord(StringBlockSize);
|
---|
136 | end;
|
---|
137 | end;
|
---|
138 |
|
---|
139 | procedure TDBC.SetString(Row, Column: Integer; Text: AnsiString);
|
---|
140 | begin
|
---|
141 | if VarIsStr(Cells[Row,Column]) then begin
|
---|
142 | StringBlockSize := StringBlockSize + strlen(Pchar(Text)) - strlen(Pchar(VarToStr(Cells[Row,Column])));
|
---|
143 | Cells[Row,Column] := Text;
|
---|
144 | end;
|
---|
145 | end;
|
---|
146 |
|
---|
147 | function TDBC.DetectColumnType(Column: Integer): TDBCColumnType;
|
---|
148 | //var
|
---|
149 | // Row: Integer;
|
---|
150 | begin
|
---|
151 | (*
|
---|
152 | Result := ctString;
|
---|
153 | for Row := 0 to RecordCount - 1 do
|
---|
154 | if GetStringByOffset(Cells[Row, Column]) = '' then Result := ctInt32;
|
---|
155 | if Result = ctString then Exit;
|
---|
156 | *)
|
---|
157 | end;
|
---|
158 |
|
---|
159 | end.
|
---|