OSDN Git Service

This commit was manufactured by cvs2svn to create branch 'Bb62'.
[gikonavigoeson/gikonavi.git] / GikoDB.pas
1 unit GikoDB;
2
3 (*!
4 \file           GikoDB.pas
5 \brief  \8aÈ\88Õ\83f\81[\83^\83x\81[\83X
6
7 $Id: GikoDB.pas,v 1.1 2004/10/09 15:08:43 yoffy Exp $
8
9
10 <h2>\83f\81[\83^\83x\81[\83X\83t\83H\81[\83}\83b\83g 0.0d1</h2>
11 <p>
12 \81@2 \8e\9f\8c³\82Ì\83X\83v\83\8c\83b\83h\83V\81[\83g\82Å\8d\\90¬\82³\82ê\81A
13 \83\8d\83E\82ª 1 \83\8c\83R\81[\83h\81A\83J\83\89\83\80\82ª\83\8c\83R\81[\83h\82Ì\83v\83\8d\83p\83e\83B\82Æ\82µ\82Ä\88µ\82í\82ê\82é\81B<br>
14 \81@\83v\83\89\83C\83}\83\8a\83J\83\89\83\80 (\91æ 1 \83J\83\89\83\80\82Í\95K\82¸\83\86\83j\81[\83N\82È\92l\82É\82È\82ç\82È\82¯\82ê\82Î\82È\82ç\82È\82¢\81B
15 </p>
16
17 <hr>
18 <h3>\83t\83@\83C\83\8b\83C\83\81\81[\83W</h3>
19 <table border="1" style="text-align:center">
20 <tr><td><a href="#header">\83w\83b\83_</a></td></tr>
21 <tr><td><a href="#info">\83C\83\93\83t\83H\83\81\81[\83V\83\87\83\93\83Z\83N\83V\83\87\83\93</a></td></tr>
22 <tr><td><a href="#cols">\83J\83\89\83\80\83\8a\83X\83g\83Z\83N\83V\83\87\83\93</a></td></tr>
23 <tr><td><a href="#atlb">\83A\83\8d\83P\81[\83V\83\87\83\93\83e\81[\83u\83\8b\83Z\83N\83V\83\87\83\93</a></td></tr>
24 <tr><td><a href="#idex">\83C\83\93\83f\83b\83N\83X\83Z\83N\83V\83\87\83\93</a></td></tr>
25 <tr><td><a href="#sect">\83Z\83N\83^\83Z\83N\83V\83\87\83\93</a></td></tr>
26 <tr><td>\81c</td></tr>
27 <tr><td><a href="#idex">\83C\83\93\83f\83b\83N\83X\83Z\83N\83V\83\87\83\93</a></td></tr>
28 <tr><td><a href="#sect">\83Z\83N\83^\83Z\83N\83V\83\87\83\93</a></td></tr>
29 </table>
30 <p>
31 <b>\8aT\97v</b><br>
32 \81@FAT \83t\83@\83C\83\8b\83V\83X\83e\83\80\82ð\96Í\82µ\82½\8d\\91¢\82É\82È\82Á\82Ä\82¢\82é\81B
33 </p>
34
35 <hr>
36 <a name="header"></a>
37 <h3>\83w\83b\83_</h3>
38 <table border="1" style="text-align:center">
39 <tr><td>\83V\83O\83l\83`\83\83</td><td>4 byte</td></tr>
40 <tr><td>\83\81\83W\83\83\81[\83o\81[\83W\83\87\83\93</td><td>1 byte</td></tr>
41 <tr><td>\83}\83C\83i\81[\83o\81[\83W\83\87\83\93</td><td>1 byte</td></tr>
42 <tr><td>\83\8a\83\8a\81[\83X\92i\8aK\96¼</td><td>1 byte</td></tr>
43 <tr><td>\83\8a\83r\83W\83\87\83\93\83i\83\93\83o\81[</td><td>1 byte</td></tr>
44 </table>
45 <p>
46 <b>\83V\83O\83l\83`\83\83</b><br>
47 \81@'gkdb' \82ð\8f\88\97\9d\8cn\82É\93K\82µ\82½\83G\83\93\83f\83B\83A\83\93\82Å\8ai\94[\82·\82é\81B<br>
48 \81@\82±\82Ì\83G\83\93\83f\83B\83A\83\93\82Å\81A\83\8c\83R\81[\83h\82É\8ai\94[\82³\82ê\82Ä\82¢\82é\92l\82Ì\83G\83\93\83f\83B\83A\83\93\82ª\8c\88\82Ü\82é\81B
49 </p>
50 <p>
51 <b>\83\81\83W\83\83\81[\83o\81[\83W\83\87\83\93</b><br>
52 \81@\83t\83@\83C\83\8b\83t\83H\81[\83}\83b\83g\82Ì\83\81\83W\83\83\81[\83o\81[\83W\83\87\83\93\81B
53 </p>
54 <p>
55 <b>\83}\83C\83i\81[\83o\81[\83W\83\87\83\93</b><br>
56 \81@\83t\83@\83C\83\8b\83t\83H\81[\83}\83b\83g\82Ì\83}\83C\83i\81[\83o\81[\83W\83\87\83\93\81B
57 </p>
58 <p>
59 <b>\83\8a\83\8a\81[\83X\92i\8aK\96¼</b><br>
60 \81@\83\8a\83\8a\81[\83X\82Ì\92i\8aK\81B\92l\82Í\8e©\97R\82¾\82ª\81A
61 \95K\82¸\83o\83C\83g\92l\82Ì\91å\8f¬\82ª\83o\81[\83W\83\87\83\93\82Ì\91å\8f¬\82Æ\82µ\82Ä\94ä\8ar\82Å\82«\82é\8e\96\81B<br />
62 \81@\88È\89º\82Í\8eQ\8dl\92l\81B
63 </p>
64 <table border="1">
65 <tr><td>\83f\83x\83\8d\83b\83p\83\8a\83\8a\81[\83X</td><td>0</td></tr>
66 <tr><td>\83A\83\8b\83t\83@\83\8a\83\8a\81[\83X</td><td>1</td></tr>
67 <tr><td>\83x\81[\83^\83\8a\83\8a\81[\83X</td><td>2</td></tr>
68 <tr><td>Release Candidate</td><td>3</td></tr>
69 <tr><td>\83v\83\8c\83r\83\85\81[\83\8a\83\8a\81[\83X</td><td>4</td></tr>
70 <tr><td>\83t\83@\83C\83i\83\8b(\83}\83X\83^)\83\8a\83\8a\81[\83X</td><td>5</td></tr>
71 </table>
72 <p>
73 <b>\83\8a\83r\83W\83\87\83\93\83i\83\93\83o\81[</b><br>
74 \81@\83\8a\83\8a\81[\83X\94Ô\8d\86\82È\82Ç\81B
75 </p>
76 <p>
77
78 <hr>
79 <a name="section"></a>
80 <h3>\83Z\83N\83V\83\87\83\93</h3>
81 <table border="1" style="text-align:center">
82 <tr><td>\83Z\83N\83V\83\87\83\93\83T\83C\83Y</td><td>4 byte</td></tr>
83 <tr><td>\83Z\83N\83V\83\87\83\93\83^\83C\83v</td><td>4 chars</td></tr>
84 <tr><td>\83Z\83N\83V\83\87\83\93\93à\97e</td><td>\89Â\95Ï</td></tr>
85 </table>
86 <p>
87 <b>\83Z\83N\83V\83\87\83\93\83T\83C\83Y</b><br>
88 \81@\83Z\83N\83V\83\87\83\93\91S\91Ì\82Ì\83T\83C\83Y\81B
89 \8c»\8dÝ\82Ì\83A\83h\83\8c\83X\82É\83Z\83N\83V\83\87\83\93\83T\83C\83Y\82ð\89Á\8eZ\82·\82é\8e\96\82Å\8e\9f\82Ì\83Z\83N\83V\83\87\83\93\82ð\8ew\82·\81B
90 \82Â\82Ü\82è\81u\83Z\83N\83V\83\87\83\93\83T\83C\83Y\81v\8e©\90g\82Ì\97Ì\88æ\82à\83T\83C\83Y\82É\8aÜ\82Ü\82ê\82é\81B<br>
91 \81@\8cã\91±\82É\83Z\83N\83V\83\87\83\93\82ª\82È\82¢\8fê\8d\87\82Í 0 \82É\82·\82é\81B
92 </p>
93 <p>
94 <b>\83Z\83N\83V\83\87\83\93\83^\83C\83v</b><br>
95 \81@\83Z\83N\83V\83\87\83\93\82Ì\8eí\97Þ\82ð\95\\82· 4 byte \82Ì\95\8e\9a\97ñ\81B<br>
96 \81@\8eg\82í\82ê\82È\82­\82È\82Á\82½\8bó\82«\83Z\83N\83V\83\87\83\93\82Í 0 \83N\83\8a\83A\82³\82ê\82é\81B
97 </p>
98
99 <hr>
100 <a name="info"></a>
101 <h3>\83C\83\93\83t\83H\83\81\81[\83V\83\87\83\93\83Z\83N\83V\83\87\83\93</h3>
102 <table border="1" style="text-align:center">
103 <tr><td>\83Z\83N\83V\83\87\83\93\83T\83C\83Y</td><td>4 byte</td></tr>
104 <tr><td>'info'</td><td>4 chars</td></tr>
105 <tr><td>\83Z\83N\83^\83T\83C\83Y</td><td>4 byte</td></tr>
106 <tr><td>\83\8c\83R\81[\83h\90\94</td><td>4 byte</td></tr>
107 </table>
108 <p>
109 <b>\83Z\83N\83^\83T\83C\83Y</b><br>
110 \81@<a href="#sect">\83Z\83N\83^\83Z\83N\83V\83\87\83\93</a>\82Ì 1 \83Z\83N\83^\82 \82½\82è\82Ì byte \90\94\81B\81@
111 </p>
112 <p>
113 <b>\83\8c\83R\81[\83h\90\94</b><br>
114 \81@\83f\81[\83^\83x\81[\83X\91S\91Ì\82Ì\83\8c\83R\81[\83h\90\94\81B\81@
115 </p>
116
117 <hr>
118 <a name="cols"></a>
119 <h3>\83J\83\89\83\80\83\8a\83X\83g\83Z\83N\83V\83\87\83\93</h3>
120 <table border="1" style="text-align:center">
121 <tr><td>\83Z\83N\83V\83\87\83\93\83T\83C\83Y</td><td>4 byte</td></tr>
122 <tr><td>'cols'</td><td>4 chars</td></tr>
123 <tr><td>\83J\83\89\83\80\90\94</td><td>4 byte</td></tr>
124 <tr><td>\83J\83\89\83\80\96¼0</td><td>pascal string</td></tr>
125 <tr><td>\83f\81[\83^\83^\83C\83v0</td><td>4 chars</td></tr>
126 <tr><td>\81c</td><td></td></tr>
127 <tr><td>\83J\83\89\83\80\96¼n</td><td>pascal string</td></tr>
128 <tr><td>\83f\81[\83^\83^\83C\83vn</td><td>4 chars</td></tr>
129 </table>
130 <p>
131 <b>\90§\8cÀ</b><br>
132 \81@\95¡\90\94\82Ì\83Z\83N\83V\83\87\83\93\82É\82Ü\82½\82ª\82Á\82Ä\8bL\8fq\82·\82é\8e\96\82Í\8fo\97\88\82Ü\82¹\82ñ\81B
133 </p>
134 <p>
135 <b>\83J\83\89\83\80\90\94</b><br>
136 \81@\8cã\91±\82·\82é\83J\83\89\83\80\82Ì\8cÂ\90\94\81B
137 </p>
138 <p>
139 <b>\83J\83\89\83\80\96¼</b><br>
140 \81@\8eÀ\8dÛ\82É\83A\83N\83Z\83X\82·\82é\8dÛ\82É\97p\82¢\82é\83J\83\89\83\80\82Ì\96¼\8fÌ\81B<br>
141 \81@\8fI\92[\82Ü\82½\82Í\8dí\8f\9c\82³\82ê\82½\82Ü\82Ü\8dÄ\8d\\92z\82³\82ê\82Ä\82¢\82È\82¢\83J\83\89\83\80\82Í\8bó\95\8e\9a\97ñ\82É\82È\82Á\82Ä\82¢\82é\81B
142 </p>
143 <p>
144 <b>\83f\81[\83^\83^\83C\83v</b><br>
145 \81@\8ai\94[\82³\82ê\82Ä\82¢\82é\83f\81[\83^\82Ì\83^\83C\83v\81B<br>
146 \81@\83Z\83N\83V\83\87\83\93\83T\83C\83Y\82É\96\9e\82½\82È\82¢\82Ü\82Ü\8fI\97¹\82·\82é\8fê\8d\87\81A
147 \81@\8fÚ\8d×\82Í\88È\89º\82Ì\92Ê\82è\81B
148 </p>
149 <p>
150 \81@\98_\97\9d\92l\82Í 1 byte \8fÁ\94ï\82·\82é\81B<br>
151 \81@\90\94\92l\82ð\8e¦\82·\83f\81[\83^\83^\83C\83v\82É\82 \82é 2 \8c\85\82Ì\90\94\8e\9a\82Í byte \90\94\82ð\95\\82µ\82Ä\82¢\82é\81B<br>
152 \81@pascal string \82Í 1 byte \82Ì\95\8e\9a\97ñ\92·\82Æ\82»\82ê\82É\91±\82­\95\8e\9a\97ñ\81A
153 data \82Í 4 byte \82Ì\83f\81[\83^\92·\82Æ\82»\82ê\82É\91±\82­\83f\81[\83^\81B<br>
154 \81@\8a¨\88á\82¢\82µ\82Ä\82Í\82¢\82¯\82È\82¢\82Ì\82ª\81A\83Z\83N\83V\83\87\83\93\83T\83C\83Y\82Æ\88á\82¢\81A
155 \83f\81[\83^\92·\82ð\8e¦\82·\92l\82Í\92·\82³\82É\8aÜ\82Ü\82ê\82Ä\82¢\82È\82¢\81B
156 \82Â\82Ü\82è\81A\8e\9f\82Ì\83f\81[\83^\82ð\8ew\82·\82É\82Í\81u\83f\81[\83^\92· + 4 byte\81v\82Ì\89\89\8eZ\82ª\95K\97v\82É\82È\82é\81B<br>
157 \81@unix time \82Í\92Ê\8eZ\95b\82ð\95\\82µ\82½ 8 byte integer \82Å\81AUTC \82ª\90\84\8f§\82³\82ê\82é\81B
158 </p>
159 <table border="1">
160 <tr><td>\98_\97\9d\92l</td><td>'bool'</td></tr>
161 <tr><td rowspan="4">\95\84\8d\86\95t\82«\90®\90\94</td><td>'si01'</td></tr>
162 <tr><td>'si02'</td></tr>
163 <tr><td>'si04'</td></tr>
164 <tr><td>'si08'</td></tr>
165 <tr><td rowspan="4">\95\84\8d\86\96³\82µ\90®\90\94</td><td>'ui01'</td></tr>
166 <tr><td>'ui02'</td></tr>
167 <tr><td>'ui04'</td></tr>
168 <tr><td>'ui08'</td></tr>
169 <tr><td rowspan="2">\95\82\93®\8f¬\90\94</td><td>'fp04'</td></tr>
170 <tr><td>'fp08'</td></tr>
171 <tr><td>pascal string</td><td>'pstr'</td></tr>
172 <tr><td>data (long string)</td><td>'data'</td></tr>
173 <tr><td>unix time</td><td>'time'</td></tr>
174 </table>
175
176 <hr>
177 <a name="atlb"></a>
178 <h3>\83A\83\8d\83P\81[\83V\83\87\83\93\83e\81[\83u\83\8b\83Z\83N\83V\83\87\83\93</h3>
179 <table border="1" style="text-align:center">
180 <tr><td>\83Z\83N\83V\83\87\83\93\83T\83C\83Y</td><td>4 byte</td></tr>
181 <tr><td>'atlb'</td><td>4 chars</td></tr>
182 <tr><td>\8cp\91±\83e\81[\83u\83\8b</td><td>4 byte</td></tr>
183 <tr><td>\81c</td><td></td></tr>
184 <tr><td>\8cp\91±\83e\81[\83u\83\8b</td><td>4 byte</td></tr>
185 </table>
186 <p>
187 <b>\8aT\97v</b><br>
188 \81@\82±\82Ì\83e\81[\83u\83\8b\82Ì\83C\83\93\83f\83b\83N\83X\82Æ
189 <a href="#sect">\83Z\83N\83^</a>\82Ì\83C\83\93\83f\83b\83N\83X\82ª\91Î\82É\82È\82Á\82Ä\82¢\82é\81B
190 </p>
191 <p>
192 <b>\90§\8cÀ</b><br>
193 \81@\95¡\90\94\82Ì\83Z\83N\83V\83\87\83\93\82É\82Ü\82½\82ª\82Á\82Ä\8bL\8fq\82·\82é\8e\96\82Í\8fo\97\88\82Ü\82¹\82ñ\81B
194 </p>
195 <p>
196 <b>\8cp\91±\83e\81[\83u\83\8b</b><br>
197 \81@0 \82©\82ç\8en\82Ü\82é\81A\8cp\91±\82·\82é\83A\83\8d\83P\81[\83V\83\87\83\93\83e\81[\83u\83\8b\83C\83\93\83f\83b\83N\83X\81B
198 \8cp\91±\82µ\82È\82¢\8fê\8d\87\82Í 0xffffffff\81B
199 </p>
200
201 <hr>
202 <a name="idex"></a>
203 <h3>\83\\81[\83g\8dÏ\82Ý\83C\83\93\83f\83b\83N\83X\83Z\83N\83V\83\87\83\93</h3>
204 <table border="1" style="text-align:center">
205 <tr><td>\83Z\83N\83V\83\87\83\93\83T\83C\83Y</td><td>4 byte</td></tr>
206 <tr><td>'idex'</td><td>4 chars</td></tr>
207 <tr><td>\83J\83\89\83\80\94Ô\8d\86</td><td>2 byte</td></tr>
208 <tr><td>\83v\83\8d\83p\83e\83B</td><td>2 byte</td></tr>
209 <tr><td>\83e\81[\83u\83\8b\94Ô\8d\86</td><td>4 byte</td></tr>
210 <tr><td>\92l</td><td>4 byte</td></tr>
211 <tr><td>\81c</td><td></td></tr>
212 <tr><td>\83e\81[\83u\83\8b\94Ô\8d\86</td><td>4 byte</td></tr>
213 <tr><td>\92l</td><td>4 byte</td></tr>
214 </table>
215 <p>
216 <b>\8aT\97v</b><br>
217 \81@\83\8c\83R\81[\83h\82ð\93Á\92è\82Ì\83J\83\89\83\80\82Å\83\\81[\83g\82µ\82½\83C\83\93\83f\83b\83N\83X\81B<br>
218 \81@\8f­\82È\82­\82Æ\82à\83v\83\89\83C\83}\83\8a\83J\83\89\83\80\82Í\95K\82¸\83C\83\93\83f\83b\83N\83X\82ð\8e\9d\82½\82È\82­\82Ä\82Í\82È\82ç\82È\82¢\81B
219 </p>
220 <p>
221 <b>\90§\8cÀ</b><br>
222 \81@\95¡\90\94\82Ì\83Z\83N\83V\83\87\83\93\82É\82Ü\82½\82ª\82Á\82Ä\8bL\8fq\82·\82é\8e\96\82Í\8fo\97\88\82Ü\82¹\82ñ\81B
223 </p>
224 <p>
225 <b>\83J\83\89\83\80\94Ô\8d\86</b><br>
226 \81@0 \82©\82ç\90\94\82¦\82½\83J\83\89\83\80\82Ì\83C\83\93\83f\83b\83N\83X\81B\82Ç\82Ì\83J\83\89\83\80\82É\91Î\82·\82é\83C\83\93\83f\83b\83N\83X\82©\82ð\95\\82·\81B
227 </p>
228 <p>
229 <b>\83v\83\8d\83p\83e\83B</b><br>
230 \81@\8ae bit \82²\82Æ\82É\83C\83\93\83f\83b\83N\83X\82É\8aÖ\82·\82é\83v\83\8d\83p\83e\83B\82ð\95Û\8e\9d\82·\82é\81B<br>
231 \81@\83v\83\8d\83p\83e\83B\82Ì\88ê\97\97\82Í\88È\89º\82Ì\92Ê\82è\81B
232 </p>
233 <table border="1">
234 <tr><td>0bit</td><td>\83\\81[\83g\83I\81[\83_\81[\81B0...\8f¸\8f\87, 1...\8d~\8f\87</td></tr>
235 </table>
236 <p>
237 <b>\83e\81[\83u\83\8b\94Ô\8d\86</b><br>
238 \81@0 \82©\82ç\8en\82Ü\82é<a href="#atlb">\83A\83\8d\83P\81[\83V\83\87\83\93\83e\81[\83u\83\8b</a>\82Ì\83C\83\93\83f\83b\83N\83X\81B<br>
239 </p>
240 <p>
241 <b>\92l</b><br>
242 \81@\83\8c\83R\81[\83h\82É\8ai\94[\82³\82ê\82Ä\82¢\82é\92l\81B<br>
243 \81@\83\8c\83R\81[\83h\82É\82à\92l\82ª\8ai\94[\82³\82ê\82Ä\82¢\82é\82½\82ß\81A
244 \83C\83\93\83f\83b\83N\83X\82ð\8e\9d\82Â\83J\83\89\83\80\82Í\8fd\95¡\82µ\82Ä\92l\82ð\8ai\94[\82µ\82Ä\82¢\82é\8e\96\82É\82È\82é\81B
245 \92l\82ð\95Ï\8dX\82·\82é\82É\82Í\82±\82ê\82ç\91S\82Ä\82ð\95Ï\8dX\82µ\82È\82­\82Ä\82Í\82È\82ç\82È\82¢\81B<br>
246 \81@4 byte \82ð\92´\82¦\82é\83f\81[\83^\83^\83C\83v\82Ì\83J\83\89\83\80\82Í\81A\83n\83b\83V\83\85\92l\82ð\8ai\94[\82·\82é\81B
247 </p>
248
249 <hr>
250 <a name="sect"></a>
251 <h3>\83Z\83N\83^\83Z\83N\83V\83\87\83\93</h3>
252 <table border="1" style="text-align:center">
253 <tr><td>\83Z\83N\83V\83\87\83\93\83T\83C\83Y</td><td>4 byte</td></tr>
254 <tr><td>'sect'</td><td>4 chars</td></tr>
255 <tr><td>\83Z\83N\83V\83\87\83\93\94Ô\8d\86</td><td>4 byte</td></tr>
256 <tr><td>\83Z\83N\83^0</td><td></td></tr>
257 <tr><td>\81c</td><td></td></tr>
258 <tr><td>\83Z\83N\83^n</td><td></td></tr>
259 </table>
260 <p>
261 <b>\83Z\83N\83V\83\87\83\93\94Ô\8d\86</b><br>
262 \81@\83Z\83N\83V\83\87\83\93\82Ì\95À\82Ñ\82ð\8e¯\95Ê\82·\82é\82½\82ß\82Ì\94Ô\8d\86\82Å\82·\81B<br>
263 \81@\83Z\83N\83^\83Z\83N\83V\83\87\83\93\82ª\95¡\90\94\82 \82é\8fê\8d\87\81A\83Z\83N\83V\83\87\83\93\94Ô\8d\86\82Ì\8f¬\82³\82¢\8f\87\82É
264 \83Z\83N\83^\94Ô\8d\86\82ª\8a\84\82è\93\96\82Ä\82ç\82ê\82Ü\82·\81B
265 </p>
266 <p>
267 <b>\83Z\83N\83^</b><br>
268 \81@\8ae\83J\83\89\83\80\82Ì\92l\82ª\8f\87\82É\8ai\94[\82³\82ê\82é\81B
269 </p>
270 *)
271 interface
272
273 //==================================================
274 uses
275 //==================================================
276
277         Classes, SysUtils, IniFiles,
278         Windows,
279         YofUtils;
280
281
282 //==================================================
283 type
284 //==================================================
285
286         TGikoDB = class;
287
288         {!***********************************************************
289         \brief \83Z\83N\83V\83\87\83\93
290         ************************************************************}
291         TSection = class( TObject )
292         private
293                 FMemory : Pointer;                      //!< \83Z\83N\83V\83\87\83\93\83A\83h\83\8c\83X
294                 FParent : TGikoDB;
295
296                 function GetSize : Longword;
297                 procedure SetSize( newSize : Longword );
298                 function GetType : Longword;
299                 procedure SetType( newType : Longword );
300                 function GetNext : Pointer;
301                 function GetContents : Pointer;
302
303         public
304                 constructor Create( parent : TGikoDB; const address : Pointer );
305
306                 property Memory                                 : Pointer               read FMemory;
307                 property Size                                           : Longword      read GetSize;
308                 property SectionType            : Longword      read GetType;
309                 property Next                                           : Pointer               read GetNext;
310         end;
311
312         {!***********************************************************
313         \brief \83Z\83N\83^\83Z\83N\83V\83\87\83\93
314         ************************************************************}
315         TSector = class( TSection )
316         private
317                 FSectionNo      : Longword;     //!< \83Z\83N\83V\83\87\83\93\94Ô\8d\86
318                 FCount                  : Integer;      //!< \83Z\83N\83^\90\94
319
320                 function GetContents : Pointer;
321                 function GetSector( index : Integer ) : Pointer;
322
323         public
324                 constructor Create( parent : TGikoDB; const address : Pointer );
325
326                 property Count : Integer                                                                                        read FCount;
327                 property Sector[ index : Integer ] : Pointer    read GetSector; default;
328         end;
329
330         {!***********************************************************
331         \brief \83\\81[\83g\8dÏ\82Ý\83C\83\93\83f\83b\83N\83X\8d\\91¢\91Ì
332         ************************************************************}
333         RSortIndex = record
334                 FATIndex        : Word;                 //!< \83A\83\8d\83P\81[\83V\83\87\83\93\83e\81[\83u\83\8b\83C\83\93\83f\83b\83N\83X
335                 FValue          : Longword;     //!< \92l
336         end;
337
338         PSortIndex = ^RSortIndex;
339
340         {!***********************************************************
341         \brief \83\\81[\83g\8dÏ\82Ý\83C\83\93\83f\83b\83N\83X
342         ************************************************************}
343         TSortIndex = class( TSection )
344         private
345                 FColumnIndex            : Word; //!< \83J\83\89\83\80\83C\83\93\83f\83b\83N\83X
346                 FColumnProperty : Word; //!< \83C\83\93\83f\83b\83N\83X\83v\83\8d\83p\83e\83B
347
348                 function GetContents : Pointer;
349                 function GetCount : Integer;
350                 function GetItem( index : Integer ) : PSortIndex;
351
352         public
353                 constructor Create( parent : TGikoDB; const address : Pointer );
354
355                 property Count                                                                          : Integer                       read GetCount;
356                 property Items[ index : Integer ]       : PSortIndex    read GetItem; default;
357                 property ColumnIndex                                                    : Word                          read FColumnIndex;
358                 property ColumnProperty                                         : Word                          read FColumnProperty;
359         end;
360
361         {!***********************************************************
362         \brief \83A\83\8d\83P\81[\83V\83\87\83\93\83e\81[\83u\83\8b
363         ************************************************************}
364         TAllocationTable = class( TSection )
365         private
366                 function GetTable( index : Integer ) : Longword;
367
368         public
369                 constructor Create( parent : TGikoDB; const address : Pointer );
370
371                 property Table[ index : Integer ] : Longword read GetTable; default;
372         end;
373
374         {!***********************************************************
375         \brief \83J\83\89\83\80
376         ************************************************************}
377         TColumn = class( TObject )
378         private
379                 FIndex  : Word;                 //!< \83J\83\89\83\80\83C\83\93\83f\83b\83N\83X
380                 FType           : Longword;     //!< \83f\81[\83^\83^\83C\83v
381
382         public
383                 constructor Create( colIndex : Word; colType : Longword );
384
385                 property ColumnIndex    : Word                  read FIndex;
386                 property ColumnType             : Longword      read FType;
387         end;
388
389         {!***********************************************************
390         \brief \83J\83\89\83\80\83\8a\83X\83g
391         ************************************************************}
392         TColumnList = class( TSection )
393         private
394                 FList                           : THashedStringList;    //!< \83J\83\89\83\80\83\8a\83X\83g\96{\91Ì
395                 FColumnEnd      : PChar;                                                        //!< \8e\9f\82Ì\83J\83\89\83\80\92Ç\89Á\88Ê\92u
396
397                 function GetContents : Pointer;
398                 function GetColumnCount : Longword;
399                 procedure SetColumnCount( n : Longword );
400
401                 function GetItemFromIndex( index : Integer )                                    : TColumn;
402                 function GetItemFromColumnIndex( index : Integer )              : TColumn;
403                 function GetItemFromName( const columnName : string )   : TColumn;
404                 procedure WriteBack;
405
406         public
407                 //! \todo               \8dí\8f\9c\82³\82ê\82½\83J\83\89\83\80\88È\8d~\82Ì index \82ð\82Â\82¯\82©\82¦\82é
408                 constructor Create( parent : TGikoDB; const address : Pointer );
409                 destructor Destroy; override;
410
411                 {!
412                 \warning        \8f\87\8f\98\82Í\95s\92è\82Å\82·\81B\8f\87\8f\98\82ª\8fd\97v\82È\8fê\8d\87\82Í
413                                                         ObjectsFromColumnIndex \82ð\8eg\97p\82µ\82Ä\89º\82³\82¢\81B
414                 }
415                 property Objects[ index : Integer ]                                     : TColumn       read GetItemFromIndex;
416                 {!
417                 \warning        \8dÅ\93K\89»\82Ì\88×\82É\81A\89Â\94\\82Å\82 \82ê\82ΠObjects \82ð\8eg\97p\82·\82é\82æ\82¤\82É\82µ\82Ä\82­\82¾\82³\82¢\81B
418                 }
419                 property ObjectsFromColumnIndex[ index : Integer ]      : TColumn
420                         read GetItemFromColumnIndex;
421                 property Items[ const columnName : string ]     : TColumn       read GetItemFromName; default;
422
423                 {!
424                 \brief  \83J\83\89\83\80\82Ì\8dí\8f\9c
425                 \param  columnName      \8dí\8f\9c\82·\82é\83J\83\89\83\80\96¼
426                 \todo           \8dí\8f\9c\82³\82ê\82½\83J\83\89\83\80\88È\8d~\82Ì index \82ð\82Â\82¯\82©\82¦\82é
427
428                 columnName \82ª\91\8dÝ\82µ\82È\82¢\8fê\8d\87\81A\8f\88\97\9d\82Í\96³\8e\8b\82³\82ê\82é\8e\96\82ª\95Û\8fØ\82³\82ê\82Ä\82¢\82Ü\82·\81B
429                 }
430                 procedure Delete( const columnName : string );
431
432                 {!
433                 \brief  \83J\83\89\83\80\82Ì\92Ç\89Á
434                 \param  columnName      \92Ç\89Á\82·\82é\83J\83\89\83\80\96¼
435                 \param  columnType      \92Ç\89Á\82·\82é\83J\83\89\83\80\82Ì\83f\81[\83^\83^\83C\83v
436
437                 columnName \82ª\8aù\82É\91\8dÝ\82·\82é\8fê\8d\87\81A\8f\88\97\9d\82Í\96³\8e\8b\82³\82ê\82é\8e\96\82ª\95Û\8fØ\82³\82ê\82Ä\82¢\82Ü\82·\81B
438                 }
439                 procedure Add( const columnName : string; columnType : Longword );
440         end;
441
442         {!***********************************************************
443         \brief \83C\83\93\83t\83H\83\81\81[\83V\83\87\83\93\83Z\83N\83V\83\87\83\93
444         ************************************************************}
445         TInfomation = class( TSection )
446         private
447                 function GetSectorSize : Longword;
448                 function GetRecordCount : Longword;
449
450         public
451                 constructor Create( parent : TGikoDB; const address : Pointer );
452
453                 property SectorSize             : Longword      read GetSectorSize;
454                 property RecordCount    : Longword      read GetRecordCount;
455         end;
456
457         {!***********************************************************
458         \brief \83\8c\83R\81[\83h
459         ************************************************************}
460         TRecord = class( TObject )
461         private
462                 FParent         : TGikoDB;
463                 FSectorNo       : Longword;     //!< \83Z\83N\83^\94Ô\8d\86
464
465                 //! \todo               \8dì\90¬\92\86
466                 function GetStringByName( const columnName : string ) : string;
467                 //! \todo               \8dì\90¬\92\86
468                 procedure SetStringByName(
469                         const columnName        : string;
470                         const value                             : string );
471                 //! \todo               \8dì\90¬\92\86
472                 function GetStringByIndex( index : Longword ) : string;
473                 //! \todo               \8dì\90¬\92\86
474                 function GetIntegerByName( const columnName : string ) : Integer;
475                 //! \todo               \8dì\90¬\92\86
476                 procedure SetIntegerByName(
477                         const columnName        : string;
478                         const value                             : Integer );
479                 //! \todo               \8dì\90¬\92\86
480                 function GetIntegerByIndex( index : Longword ) : Integer;
481
482         public
483                 constructor Create( parent : TGikoDB; sectorNo : Longword );
484
485                 //! \brief      \92l\82ð\95\8e\9a\97ñ\82Å\8eæ\93¾\81^\90Ý\92è
486                 property StringValue[ const columnName : string ]               : string
487                         read GetStringByName    write SetStringByName;
488
489                 //! \brief      \92l\82ð\90\94\92l\82Å\8eæ\93¾\81^\90Ý\92è
490                 property IntegerValue[ const columnName : string ]      : Integer
491                         read GetIntegerByName   write SetIntegerByName;
492         end;
493
494         {!***********************************************************
495         \brief \83T\83|\81[\83g\82³\82ê\82Ä\82¢\82È\82¢\83f\81[\83^\83x\81[\83X\83t\83H\81[\83}\83b\83g
496         ************************************************************}
497         EGikoDBUnssuportedFormatError = class( Exception );
498
499         {!***********************************************************
500         \brief          \8aÈ\88Õ\83f\81[\83^\83x\81[\83X
501         ************************************************************}
502         TGikoDB = class( TObject )
503         private
504                 FFilePath               : string;                               //!< \8aJ\82¢\82½\83t\83@\83C\83\8b\82Ì\83p\83X
505                 FFile                           : TMappedFile;  //!< \83f\81[\83^\83x\81[\83X\82ð\95Û\8e\9d\82·\82é\83t\83@\83C\83\8b
506                 FPageSize               : Longword;                     //!< \83y\81[\83W\83T\83C\83Y
507                 FSectorSize     : Integer;                      //!< \83Z\83N\83^\83T\83C\83Y
508                 FSections               : TList;                                //!< \83Z\83N\83V\83\87\83\93\83\8a\83X\83g
509                 FChanged                : Boolean;                      //!< FSections \82Ì\8dÄ\8d\\92z\82ª\95K\97v\81B
510
511                 FInfomation                             : TInfomation;
512                 FColumnList                             :       TColumnList;
513                 FSectors                                        : TList;
514                 FIndexes                                        : TList;
515                 FAllocationTable        : TAllocationTable;
516
517                 procedure CreateInitialSections;
518                 procedure ReadSections;
519                 procedure ReadSection0_0d1( const address : PChar );
520
521                 {!
522                 \brief          \83Z\83N\83V\83\87\83\93\82Ì\8dì\90¬
523                 \warning        \8cã\82Å\95K\82¸ Changed \82ð\8eÀ\8ds\82µ\82Ä\82­\82¾\82³\82¢\81B
524                 \warning        sectionSize \82æ\82è\82à\97]\95ª\82É\8am\95Û\82³\82ê\82é\8e\96\82ª\82 \82è\82Ü\82·\81B
525                 }
526                 function CreateSection(
527                         sectionSize : Longword;
528                         sectionType : Longword
529                 ) : Pointer;
530
531                 {!
532                 \brief          \83Z\83N\83V\83\87\83\93\82Ì\8ag\92£\81E\8fk\8f¬
533                 \warning        \8cã\82Å\95K\82¸ Changed \82ð\8eÀ\8ds\82µ\82Ä\82­\82¾\82³\82¢\81B
534                 \warning        \91½\82­\82Ì\8fê\8d\87\81A\83Z\83N\83V\83\87\83\93\82Ì\83A\83h\83\8c\83X\82ª\95Ï\82í\82è\82Ü\82·\81B
535                 \warning        section \82É\8bó\82«\83Z\83N\83V\83\87\83\93\82ð\8ew\92è\82·\82é\8e\96\82Í\8fo\97\88\82Ü\82¹\82ñ\81B
536                                                         \8bó\82«\83Z\83N\83V\83\87\83\93\82ð\8am\95Û\82·\82é\82É\82Í CreateSection \82ð\8eg\97p\82µ\82Ä\82­\82¾\82³\82¢\81B
537                 }
538                 procedure ReallocateSection(
539                         section                 : TSection;
540                         sectionSize : Longword );
541
542                 {!
543                 \brief          \83Z\83N\83V\83\87\83\93\8fî\95ñ\82ð\93Ç\82Ý\92¼\82µ\81ATGikoDB \83N\83\89\83X\82ð\8dÄ\8d\\92z\82·\82é
544                 \param          force           \93Ç\82Ý\92¼\82µ\82ª\95s\95K\97v\82Æ\94»\92f\82³\82ê\82½\8fê\8d\87\82à\8b­\90§\93I\82É\93Ç\82Ý\92¼\82µ\82Ü\82·\81B
545                 \warning        \83Z\83N\83V\83\87\83\93\82ð\8f\91\82«\95Ï\82¦\82½\8cã\82Å\95K\82¸\8eÀ\8ds\82µ\82Ä\82­\82¾\82³\82¢\81B
546                 \warning        \91S\82Ä\82Ì\83Z\83N\83V\83\87\83\93\83N\83\89\83X\82Í\89ð\95ú\82³\82ê\82Ü\82·\81B
547                 }
548                 procedure Changed( force : Boolean = False );
549
550                 {!
551                 \brief          \91S\83Z\83N\83^\82©\82ç\93Á\92è\82Ì\83J\83\89\83\80\82Ì\92l\82ð\92T\82µ\8fo\82·
552                 \param          founds                  \8c©\82Â\82©\82Á\82½\92l\82ª\97ñ\8b\93\82³\82ê\82é
553                 \param          value                           \92T\82µ\8fo\82·\92l
554                 \param          columnIndex     \83J\83\89\83\80\83C\83\93\83f\83b\83N\83X
555                 \return         1 \82Â\88È\8fã\8c©\82Â\82©\82Á\82½\8fê\8d\87\82Í True
556                 \warning        \89Â\95Ï\92·\82Ì\92l\81A\82Ü\82½\82Í 4 byte \82ð\92´\82¦\82é\92l\82Í\83n\83b\83V\83\85\92l\82ð\93n\82µ\82Ä\82­\82¾\82³\82¢\81B
557                 \warning        \8eÀ\8dÛ\82Ì\92l\82ª\88á\82Á\82Ä\82à\83n\83b\83V\83\85\92l\82ª\93¯\82\8fê\8d\87\81A\82»\82ê\82ç\91S\82Ä\82ª\97ñ\8b\93\82³\82ê\82Ü\82·\81B
558                 }
559                 function SelectValue(
560                         founds                  : TList;
561                         value                           : Longword;
562                         columnIndex : Word = 0
563                 ) : Boolean;
564
565                 {!
566                 \brief          \83\8c\83R\81[\83h\82ð\8eæ\93¾
567                 \param          primalyValue    \83\8c\83R\81[\83h\92l
568                 \return         \83\8c\83R\81[\83h\92l\82É\88ê\92v\82µ\82½\83\8c\83R\81[\83h
569                 \warning        \83v\83\89\83C\83}\83\8a\83J\83\89\83\80\82ª\90\94\92l\82Å\82Í\82È\82­\95\8e\9a\97ñ\82Ì\8fê\8d\87\81A\82±\82Ì\8aÖ\90\94\82Í\8e¸\94s\82µ\82Ü\82·\81B
570                 }
571                 function GetRecordByInteger( primalyValue : Integer ) : TRecord;
572
573                 {!
574                 \brief          \83\8c\83R\81[\83h\82ð\8eæ\93¾
575                 \param          primalyValue    \83\8c\83R\81[\83h\96¼
576                 \return         \83\8c\83R\81[\83h\96¼\82É\88ê\92v\82µ\82½\83\8c\83R\81[\83h
577                 \warning        \83v\83\89\83C\83}\83\8a\83J\83\89\83\80\82ª\95\8e\9a\97ñ\82Å\82Í\82È\82­\90\94\92l\82Ì\8fê\8d\87\81A\82±\82Ì\8aÖ\90\94\82Í\8e¸\94s\82µ\82Ü\82·\81B
578                 }
579                 function GetRecordByString( const primalyValue : string ) : TRecord;
580
581                 {!
582                 \brief          \83Z\83N\83^\82Ì\83|\83C\83\93\83^\82ð\8eæ\93¾
583                 \param          sectorNo        \83Z\83N\83^\94Ô\8d\86
584                 \return         \83Z\83N\83^\82Ì\88Ê\92u\82ð\8ew\82·\83|\83C\83\93\83^
585                 \todo                   \8dì\90¬\92\86
586                 }
587                 function GetSector( sectorNo : Integer ) : Pointer;
588
589         public
590                 {!
591                 \brief          \83f\81[\83^\83x\81[\83X\82Ì\83I\81[\83v\83\93
592                 \param          filePath                \8aJ\82­\83t\83@\83C\83\8b\82Ì\83p\83X
593                 \param          mode                            fmOpenRead (\83f\83t\83H\83\8b\83g) \82Ü\82½\82Í fmOpenReadWrite
594                 \warning        \8c»\8dÝ\82Ì\83o\81[\83W\83\87\83\93\82Í\82¨\82æ\82» 2GB \82Ü\82Å\82µ\82©\88µ\82¦\82Ü\82¹\82ñ\81B
595                                                         \8eÀ\8dÛ\82Í\8bó\82«\83A\83h\83\8c\83X\8bó\8aÔ\82É\82æ\82è\8dX\82É\8f¬\82³\82­\82È\82è\82Ü\82·\81B
596                                                         \83T\83C\83Y\82É\8aÖ\82·\82é\83`\83F\83b\83N\82Í\8ds\82í\82ê\82È\82¢\82Ì\82Å\92\8d\88Ó\82µ\82Ä\82­\82¾\82³\82¢\81B
597                 \todo                   MapViewOfFile \82Å 64bit \8bó\8aÔ\82ð\83A\83N\83Z\83X\82Å\82«\82é\82æ\82¤\82É\8ag\92£\82·\82é\81B
598
599                 filePath \82ª\91\8dÝ\82¹\82¸\81Amode \82É fmOpenReadWrite \82ª\8ew\92è\82³\82ê\82½\8fê\8d\87\82Í
600                 \90V\8bK\82É\83f\81[\83^\83x\81[\83X\82ª\8dì\90¬\82³\82ê\82Ü\82·\81B
601                 }
602                 constructor Create(
603                         const filePath  : string;
604                         mode                                            : Longword = fmOpenRead );
605                 destructor Destroy; override;
606
607                 {!
608                 \brief  \93à\97e\82ð\83e\83L\83X\83g\83t\83@\83C\83\8b\82É\83_\83\93\83v
609                 \param  filePath                \95Û\91\82·\82é\83t\83@\83C\83\8b\82Ì\83p\83X
610                 \todo           \8dì\90¬\92\86
611                 }
612                 procedure Dump(
613                         const filePath  : string );
614
615                 {!
616                 \brief          \83\8c\83R\81[\83h\82ð\8eæ\93¾
617                 \param          primalyValue    \83\8c\83R\81[\83h\92l
618                 \return         \83\8c\83R\81[\83h\92l\82É\88ê\92v\82µ\82½\83\8c\83R\81[\83h
619                 \warning        \83v\83\89\83C\83}\83\8a\83J\83\89\83\80\82ª\90\94\92l\82Å\82Í\82È\82­\95\8e\9a\97ñ\82Ì\8fê\8d\87\81A\82±\82Ì\8aÖ\90\94\82Í\8e¸\94s\82µ\82Ü\82·\81B
620                 }
621                 property RecordByInteger[ primalyValue : Integer ]                      : TRecord
622                         read GetRecordByInteger;
623
624                 {!
625                 \brief          \83\8c\83R\81[\83h\82ð\8eæ\93¾
626                 \param          primalyValue    \83\8c\83R\81[\83h\96¼
627                 \return         \83\8c\83R\81[\83h\96¼\82É\88ê\92v\82µ\82½\83\8c\83R\81[\83h
628                 \warning        \83v\83\89\83C\83}\83\8a\83J\83\89\83\80\82ª\95\8e\9a\97ñ\82Å\82Í\82È\82­\90\94\92l\82Ì\8fê\8d\87\81A\82±\82Ì\8aÖ\90\94\82Í\8e¸\94s\82µ\82Ü\82·\81B
629                 }
630                 property RecordByString[ const primalyValue : string ]  : TRecord
631                         read GetRecordByString;
632         end;
633
634 //==================================================
635 implementation
636 //==================================================
637
638 uses
639         Math;
640
641 const
642         MINIMUM_PAGE_SIZE               = $10000;                       //!< \8dÅ\8f¬\82Ì\83y\81[\83W\83T\83C\83Y ( 64KB )
643         SECTOR_SIZE                                     = $40;                          //!< \83Z\83N\83^\83T\83C\83Y ( 64Byte )
644         SIGNATURE_LITTLE_ENDIAN
645                                                                                         = $676b6462;    //!< 'bdkg' \83f\81[\83^\83x\81[\83X\83V\83O\83l\83`\83\83
646         DATABASE_VERSION                = $01000000;    //!< \83o\81[\83W\83\87\83\93\83i\83\93\83o\81[ ( 0.0d1 )
647
648         NULL_SECTION                            = $00000000;    //!< \96¢\8eg\97p\83Z\83N\83V\83\87\83\93
649         INFOMATION_SECTION      = $6f666e69;    //!< 'info' \83C\83\93\83t\83H\83\81\81[\83V\83\87\83\93\83Z\83N\83V\83\87\83\93
650         COLUMN_LIST_SECTION     = $736c6f63;    //!< 'cols' \83J\83\89\83\80\83\8a\83X\83g\83Z\83N\83V\83\87\83\93
651         ALLOCATION_TABLE_SECTION
652                                                                                         = $626c7461;    //!< 'atlb' \83A\83\8d\83P\81[\83V\83\87\83\93\83e\81[\83u\83\8b\83Z\83N\83V\83\87\83\93
653         INDEX_SECTION                           = $78656469;    //!< 'idex' \83C\83\93\83f\83b\83N\83X\83Z\83N\83V\83\87\83\93
654         SECTOR_SECTION                  = $74636573;    //!< 'sect' \83Z\83N\83^\83Z\83N\83V\83\87\83\93
655         NULL_SECTOR_NO                  = $ffffffff;    //!< \8fI\92[\82ð\95\\82·\83Z\83N\83^\94Ô\8d\86
656
657         TYPE_BOOL                                               = $6c6f6f62;    //!< 'bool' \98_\97\9d\92l
658         TYPE_INT8                                               = $31306973;    //!< 'si01' signed int 1 byte
659         TYPE_INT16                                      = $32306973;    //!< 'si02'
660         TYPE_INT32                                      = $34306973;    //!< 'si04'
661         TYPE_INT64                                      = $38306973;    //!< 'si08'
662         TYPE_UINT8                                      = $31306975;    //!< 'ui01' unsigned int 1 byte
663         TYPE_UINT16                                     = $32306975;    //!< 'ui02'
664         TYPE_UINT32                                     = $34306975;    //!< 'ui04'
665         TYPE_UINT64                                     = $38306975;    //!< 'ui08'
666         TYPE_FLOAT32                            = $34306c66;    //!< 'fp04' floating point 4 byte
667         TYPE_FLOAT64                            = $38306c66;    //!< 'fp08'
668         TYPE_PSTR                                               = $72747370;    //!< 'pstr' pascal string
669         TYPE_DATA                                               = $61746164;    //!< 'data' data (long string)
670
671         COLUMN_DELETED                  = '_.-*+/DELETED+*./_-';        //!< \8dí\8f\9c\82³\82ê\82½\83J\83\89\83\80\96¼
672
673
674
675 //************************************************************
676 // misc
677 //************************************************************
678
679 //==============================
680 // SortSectionsByPtr
681 //==============================
682 function SortSectionsByPtr( Item1, Item2 : Pointer ) : Integer;
683 begin
684
685         Result := PChar( TSection( Item1 ).Memory ) -
686                 PChar( TSection( Item2 ).Memory );
687
688 end;
689
690 //==============================
691 // SortSectorSections
692 //==============================
693 function SortSectorSections( Item1, Item2 : Pointer ) : Integer;
694 begin
695
696         Result := PChar( TSector( Item1 ).FSectionNo ) -
697                 PChar( TSector( Item2 ).FSectionNo );
698
699 end;
700
701
702
703 //************************************************************
704 // TSection class
705 //************************************************************
706
707 //==============================
708 // Create
709 //==============================
710 constructor TSection.Create( parent : TGikoDB; const address : Pointer );
711 begin
712
713         FParent := parent;
714         FMemory := address;
715
716 end;
717
718 //==============================
719 // GetSize
720 //==============================
721 function TSection.GetSize : Longword;
722 begin
723
724         Result := PDword( FMemory )^;
725
726 end;
727
728 //==============================
729 // SetSize
730 //==============================
731 procedure TSection.SetSize( newSize : Longword );
732 begin
733
734         PDword( FMemory )^ := newSize;
735
736 end;
737
738 //==============================
739 // GetType
740 //==============================
741 function TSection.GetType : Longword;
742 begin
743
744         Result := PDword( PChar( FMemory ) + 4 )^;
745
746 end;
747
748 //==============================
749 // SetType
750 //==============================
751 procedure TSection.SetType( newType : Longword );
752 begin
753
754         PDword( PChar( FMemory ) + 4 )^ := newType;
755
756 end;
757
758 //==============================
759 // GetNext
760 //==============================
761 function TSection.GetNext : Pointer;
762 begin
763
764         Result := PChar( FMemory ) + Size;
765
766 end;
767
768 //==============================
769 // GetContents
770 //==============================
771 function TSection.GetContents : Pointer;
772 begin
773
774         Result := PChar( FMemory ) + 8;
775
776 end;
777
778
779
780 //************************************************************
781 // TSector class
782 //************************************************************
783
784 //==============================
785 // Create
786 //==============================
787 constructor TSector.Create( parent : TGikoDB; const address : Pointer );
788 begin
789
790         inherited;
791         FSectionNo      := PDWord( PChar( Memory ) + 8 )^;
792         FCount                  := Size - Longword( 12 ) div SECTOR_SIZE;
793
794 end;
795
796 //==============================
797 // GetContents
798 //==============================
799 function TSector.GetContents : Pointer;
800 begin
801
802         Result := PChar( FMemory ) + 12;
803
804 end;
805
806 //==============================
807 // GetSector
808 //==============================
809 function TSector.GetSector( index : Integer ) : Pointer;
810 begin
811
812         Assert( (index > 0) and (index <= FCount) );
813         // 8 = sizeof(section size) + sizeof(section type) + sizeof(section no) -
814         //     1 base * sizeof(Longword)
815         Result := PChar( GetContents ) + Longword( index ) * SECTOR_SIZE;
816
817 end;
818
819
820
821 //************************************************************
822 // TSortIndex class
823 //************************************************************
824
825 //==============================
826 // Create
827 //==============================
828 constructor TSortIndex.Create( parent : TGikoDB; const address : Pointer );
829 begin
830
831         inherited;
832         FColumnIndex            := PWORD( PChar( Memory ) + 4 )^;
833         FColumnProperty := PWORD( PChar( Memory ) + 6 )^;
834
835 end;
836
837 //==============================
838 // GetContents
839 //==============================
840 function TSortIndex.GetContents : Pointer;
841 begin
842
843         Result := PChar( FMemory ) + 12;
844
845 end;
846
847 //==============================
848 // GetCount
849 //==============================
850 function TSortIndex.GetCount : Integer;
851 begin
852
853         Result := FParent.FInfomation.RecordCount;
854
855 end;
856
857 //==============================
858 // GetItem
859 //==============================
860 function TSortIndex.GetItem( index : Integer ) : PSortIndex;
861 begin
862
863         Result := PSortIndex( PChar( GetContents ) + index * SizeOf( RSortIndex ) );
864
865 end;
866
867
868
869 //************************************************************
870 // TAllocationTable class
871 //************************************************************
872
873 //==============================
874 // Create
875 //==============================
876 constructor TAllocationTable.Create( parent : TGikoDB; const address : Pointer );
877 begin
878
879         inherited;
880
881 end;
882
883 function TAllocationTable.GetTable( index : Integer ) : Longword;
884 begin
885
886         Result := PDword( PChar( GetContents ) + index * SizeOf( DWORD ) )^
887
888 end;
889
890
891
892 //************************************************************
893 // TColumn class
894 //************************************************************
895
896 //==============================
897 // Create
898 //==============================
899 constructor TColumn.Create( colIndex : Word; colType : Longword );
900 begin
901
902         FIndex  := colIndex;
903         FType           := colType;
904
905 end;
906
907
908
909 //************************************************************
910 // TColumnList class
911 //************************************************************
912
913 //==============================
914 // Create
915 //==============================
916 constructor TColumnList.Create( parent : TGikoDB; const address : Pointer );
917 var
918         i, j                            : Word;
919         p, p2, tail     : PChar;
920         l                                               : Integer;
921         columnCount     : Longword;
922         col                                     : TColumn;
923         colType                 : Longword;
924         colName                 : string;
925 begin
926
927         inherited;
928         FList                                                   := THashedStringList.Create;
929         FList.Sorted                    := True;
930         FList.Duplicates        := dupError;
931         columnCount                             := GetColumnCount;
932         p                                                                       := PChar( GetContents );
933         tail                                                    := Next;
934
935         j := Random( MaxInt );
936         for i := 0 to columnCount - 1 do begin
937                 p2 := p;        // Break \8e\9e\82É FColumnEnd \82É\89e\8b¿\82³\82¹\82È\82¢\82½\82ß
938
939                 if p2 >= tail then Break;
940                 l                               := PByte( p2 )^;                        Inc( p2 );
941                 if p2 + l + SizeOf( Dword ) >= tail then Break;
942                 colName := Copy( p2, 0, l );    p2 := p2 + l;
943                 colType := PDword( p2 )^;                       p2 := p2 + SizeOf( colType );
944
945                 p := p2;
946
947                 if l = 0 then begin
948                         // \8dí\8f\9c\82³\82ê\82Ä\82¢\82é\83J\83\89\83\80\82È\82Ì\82Å\93K\93\96\82É\8fd\95¡\82µ\82È\82¢\96¼\91O\82ð\95t\82¯\82é
949                         while true do begin
950                                 Inc( j );
951                                 colName := COLUMN_DELETED + IntToStr( j );
952                                 if FList.IndexOf( colName ) < 0 then
953                                         Break;
954                         end;
955                 end;
956                 col := TColumn.Create( i, colType );
957                 FList.AddObject( colName, col );
958         end;
959
960         FColumnEnd := p;
961
962 end;
963
964 //==============================
965 // Destroy
966 //==============================
967 destructor TColumnList.Destroy;
968 var
969         i       : Integer;
970 begin
971
972         for i := FList.Count - 1 downto 0 do
973                 FList.Objects[ i ].Free;
974         FList.Free;
975
976 end;
977
978 //==============================
979 // GetContents
980 //==============================
981 function TColumnList.GetContents : Pointer;
982 begin
983
984         Result := PChar( FMemory ) + 12;
985
986 end;
987
988 //==============================
989 // GetColumnCount
990 //==============================
991 function TColumnList.GetColumnCount : Longword;
992 begin
993
994         Result := PDword( PChar( Memory ) + 8 )^;
995
996 end;
997
998 //==============================
999 // SetColumnCount
1000 //==============================
1001 procedure TColumnList.SetColumnCount( n : Longword );
1002 begin
1003
1004         PDword( PChar( Memory ) + 8 )^ := n;
1005
1006 end;
1007
1008 //==============================
1009 // GetItemFromIndex
1010 //==============================
1011 function TColumnList.GetItemFromIndex( index : Integer )                : TColumn;
1012 begin
1013
1014         Result := TColumn( FList.Objects[ index ] );
1015
1016 end;
1017
1018 //==============================
1019 // GetItemFromColumnIndex
1020 //==============================
1021 function TColumnList.GetItemFromColumnIndex( index : Integer )  : TColumn;
1022 var
1023         i               : Integer;
1024         col     : TColumn;
1025 begin
1026
1027         Result := nil;
1028         for i := 0 to FList.Count - 1 do begin
1029                 col := Objects[ i ];
1030                 if col.ColumnIndex = index then begin
1031                         Result := col;
1032                         Break;
1033                 end;
1034         end;
1035
1036 end;
1037
1038 //==============================
1039 // GetItemFromName
1040 //==============================
1041 function TColumnList.GetItemFromName( const columnName : string )       : TColumn;
1042 var
1043         i       : Integer;
1044 begin
1045
1046         i := FList.IndexOf( columnName );
1047         if i >= 0 then
1048                 Result := Objects[ i ]
1049         else
1050                 Result := nil;
1051
1052 end;
1053
1054 //==============================
1055 // Delete
1056 //==============================
1057 procedure TColumnList.Delete( const columnName : string );
1058 var
1059         i, j    : Integer;
1060         s                       : string;
1061 begin
1062
1063         i := FList.IndexOf( columnName );
1064         if i >= 0 then begin
1065                 j := Random( MaxInt );
1066                 while true do begin
1067                         Inc( j );
1068                         s := COLUMN_DELETED + IntToStr( j );
1069                         if FList.IndexOf( s ) < 0 then begin
1070                                 FList[ i ] := s;
1071                                 Break;
1072                         end;
1073                 end;
1074
1075                 WriteBack;
1076         end;
1077
1078 end;
1079
1080 //==============================
1081 // Add
1082 //==============================
1083 procedure TColumnList.Add( const columnName : string; columnType : Longword );
1084 var
1085         i, l    : Integer;
1086         col             : TColumn;
1087         p                       : PChar;
1088 begin
1089
1090         i := FList.IndexOf( columnName );
1091         if i >= 0 then begin
1092                 col := TColumn.Create( FList.Count, columnType );
1093                 FList.AddObject( columnName, col );
1094                 p := FColumnEnd;
1095                 l := Length( columnName );
1096                 Assert( l <= 255 );
1097                 if 255 < l then
1098                         Exit;
1099                 if p + l + 5 <= Next then begin
1100                         // \83Z\83N\83V\83\87\83\93\82É\8bó\82«\82ª\82 \82é\82Ì\82Å\92Ç\8bL\82·\82é
1101                         PByte( p )^             := l;                                                                           Inc( p );
1102                         Move( PChar( columnName )^, p^, l );    p := p + l;
1103                         PDword( p )^    := columnType;                                  p := p + SizeOf( columnType );
1104
1105                         FColumnEnd              := p;
1106                         SetColumnCount( FList.Count );
1107                 end else begin
1108                         // \83Z\83N\83V\83\87\83\93\82É\93ü\82è\82«\82ç\82È\82¢\82Ì\82Å WriteBack \82É\94C\82¹\82é
1109                         WriteBack;
1110                 end;
1111         end;
1112
1113 end;
1114
1115 //==============================
1116 // WriteBack
1117 //==============================
1118 procedure TColumnList.WriteBack;
1119 var
1120         p, tail : PChar;
1121         i, j            : Integer;
1122         idx, l  : Integer;
1123         col                     : TColumn;
1124 begin
1125
1126         // \95K\97v\82È\83Z\83N\83V\83\87\83\93\83T\83C\83Y\82ð\8cv\8eZ\82·\82é
1127         p := PChar( GetContents );
1128         for i := 0 to FList.Count - 1 do begin
1129                 p := p + 5;
1130                 if AnsiPos( COLUMN_DELETED, FList[ i ] ) <> 1 then
1131                         p := p + Length( FList[ i ] );
1132         end;
1133
1134         if p > Next then
1135                 // \83Z\83N\83V\83\87\83\93\83T\83C\83Y\82ª\91«\82ç\82È\82¢\82Ì\82Å\8ag\92£
1136                 FParent.ReallocateSection( Self, p - Memory );
1137
1138         p := PChar( GetContents );
1139         for i := 0 to FList.Count - 1 do begin
1140                 // FList \82Í\83J\83\89\83\80\96¼\82Å\83\\81[\83g\82³\82ê\82Ä\82¢\82é\82Ì\82Å
1141                 // ColumnIndex \82Å\95À\82×\82é\82É\82Í\8c\9f\8dõ\82µ\82È\82­\82Ä\82Í\82È\82ç\82È\82¢
1142                 idx := -1;
1143                 col     := nil;
1144                 for j := 0 to FList.Count - 1 do begin
1145                         col := TColumn( FList.Objects[ j ] );
1146                         if col.ColumnIndex = i then begin
1147                                 idx := j;
1148                                 Break;
1149                         end;
1150                 end;
1151                 Assert( idx <> -1 );
1152
1153                 if AnsiPos( COLUMN_DELETED, FList[ idx ] ) = 1 then
1154                         l := 0
1155                 else
1156                         l := Length( FList[ idx ] );
1157                 PByte( p )^             := l;                                                                                   Inc( p );
1158                 Move( PChar( FList[ idx ] )^, p^, l );  p := p + l;
1159                 PDWord( p )^    := col.ColumnType;                              p := p + SizeOf( DWORD );
1160                 Assert( p <= Next );
1161         end;
1162
1163         FColumnEnd := p;
1164         SetColumnCount( FList.Count );
1165
1166         FParent.Changed;
1167
1168 end;
1169
1170
1171
1172 //************************************************************
1173 // TInfomation class
1174 //************************************************************
1175
1176 //==============================
1177 // Create
1178 //==============================
1179 constructor TInfomation.Create( parent : TGikoDB; const address : Pointer );
1180 begin
1181
1182         inherited;
1183
1184 end;
1185
1186 //==============================
1187 // GetSectorSize
1188 //==============================
1189 function TInfomation.GetSectorSize : Longword;
1190 begin
1191
1192         Result := PDword( PChar( GetContents ) )^;
1193
1194 end;
1195
1196 //==============================
1197 // GetRecordCount
1198 //==============================
1199 function TInfomation.GetRecordCount : Longword;
1200 begin
1201
1202         Result := PDword( PChar( GetContents ) + 4 )^;
1203 end;
1204
1205
1206
1207 //************************************************************
1208 // TRecord class
1209 //************************************************************
1210
1211 //==============================
1212 // Create
1213 //==============================
1214 constructor TRecord.Create( parent : TGikoDB; sectorNo : Longword );
1215 begin
1216
1217         inherited Create;
1218         FParent         := parent;
1219         FSectorNo       := sectorNo;
1220
1221 end;
1222
1223 //==============================
1224 // GetStringByName
1225 //==============================
1226 function TRecord.GetStringByName( const columnName : string ) : string;
1227 begin
1228         //!!!!! \8dì\90¬\92\86 !!!!!
1229 end;
1230
1231 //==============================
1232 // SetStringByName
1233 //==============================
1234 procedure TRecord.SetStringByName(
1235         const columnName        : string;
1236         const value                             : string );
1237 begin
1238         //!!!!! \8dì\90¬\92\86 !!!!!
1239 end;
1240
1241 //==============================
1242 // GetStringByIndex
1243 //==============================
1244 function TRecord.GetStringByIndex( index : Longword ) : string;
1245 begin
1246         //!!!!! \8dì\90¬\92\86 !!!!!
1247 end;
1248
1249 //==============================
1250 // GetIntegerByName
1251 //==============================
1252 function TRecord.GetIntegerByName( const columnName : string ) : Integer;
1253 begin
1254         //!!!!! \8dì\90¬\92\86 !!!!!
1255 end;
1256
1257 //==============================
1258 // SetIntegerByName
1259 //==============================
1260 procedure TRecord.SetIntegerByName(
1261         const columnName        : string;
1262         const value                             : Integer );
1263 var
1264         col, c          : TColumn;
1265         sectorNo        : Integer;
1266         offset          : Longword;
1267         i                                       : Integer;
1268 begin
1269
1270         col                             := FParent.FColumnList[ columnName ];
1271         if col = nil then
1272                 Exit;
1273         sectorNo        := FSectorNo;
1274         offset          := 0;
1275
1276         for i := 0 to col.ColumnIndex - 1 do begin
1277                 c := FParent.FColumnList.GetItemFromColumnIndex( i );
1278                 case c.ColumnType of
1279                 TYPE_BOOL, TYPE_INT8, TYPE_UINT8:                               Inc( offset );
1280                 TYPE_INT16, TYPE_UINT16:                                                                offset := offset + 2;
1281                 TYPE_INT32, TYPE_UINT32, TYPE_FLOAT32:  offset := offset + 4;
1282                 TYPE_INT64, TYPE_UINT64, TYPE_FLOAT64:  offset := offset + 8;
1283
1284                 TYPE_PSTR:
1285                         begin
1286                                 //!!!!! \8dì\90¬\92\86 !!!!!
1287                                 offset := PByte( PChar( FParent.GetSector( sectorNo ) ) + offset )^;
1288                                 while offset >= FParent.FSectorSize do begin
1289                                         sectorNo := FParent.FAllocationTable[ sectorNo ];
1290                                         if sectorNo = NULL_SECTOR_NO then
1291                                                 Exit;
1292                                         offset := offset - FParent.FSectorSize;
1293                                 end;
1294                         end;
1295
1296                 TYPE_DATA:
1297                         begin
1298                                 //!!!!! \8dì\90¬\92\86 !!!!!
1299                         end;
1300                 end;
1301         end;
1302
1303         //!!!!! \8dì\90¬\92\86 !!!!!
1304
1305 end;
1306
1307 //==============================
1308 // GetIntegerByIndex
1309 //==============================
1310 function TRecord.GetIntegerByIndex( index : Longword ) : Integer;
1311 begin
1312         //!!!!! \8dì\90¬\92\86 !!!!!
1313 end;
1314
1315
1316
1317 //************************************************************
1318 // TGikoDB class
1319 //************************************************************
1320
1321 //==============================
1322 // Create
1323 //==============================
1324 constructor TGikoDB.Create(
1325         const filePath  : string;
1326         mode                                            : Longword = fmOpenRead );
1327 var
1328         info                                            : _SYSTEM_INFO;
1329         maximumSize                     : Integer;
1330 begin
1331
1332         Randomize;
1333         FFilePath       := ExpandUNCFileName( filePath );
1334         FChanged        := False;
1335
1336         GetSystemInfo( info );
1337         FPageSize := Max( info.dwPageSize, MINIMUM_PAGE_SIZE );
1338         if FileExists( filePath ) then begin
1339                 maximumSize := 0;
1340                 FFile := TMappedFile.Create( FFilePath, mode, maximumSize );
1341                 ReadSections;
1342         end else begin
1343                 maximumSize     := FPageSize;
1344                 FFile := TMappedFile.Create( FFilePath, mode, maximumSize );
1345                 CreateInitialSections;
1346                 ReadSections;
1347         end;
1348
1349 end;
1350
1351 //==============================
1352 // Destroy
1353 //==============================
1354 destructor TGikoDB.Destroy;
1355 var
1356         i       : Integer;
1357 begin
1358
1359         FFile.Free;
1360         for i := FSections.Count - 1 downto 0 do
1361                 TObject( FSections[ i ] ).Free;
1362         FSections.Free;
1363
1364 end;
1365
1366 //==============================
1367 // CreateInitialSections
1368 //==============================
1369 procedure TGikoDB.CreateInitialSections;
1370 var
1371         i                                                       : Integer;
1372         p, p2                                   : PChar;
1373         emptySize                       : Longword;
1374         sectionCount    : Longword;
1375 begin
1376
1377         FSections       := TList.Create;
1378         p                                       := PChar( FFile.Memory );
1379
1380         //===== \83w\83b\83_
1381         // \83V\83O\83l\83`\83\83
1382         PDword( p )^ := SIGNATURE_LITTLE_ENDIAN;        p := p + SizeOf( DWORD );
1383         // \83o\81[\83W\83\87\83\93
1384         PDword( p )^ := DATABASE_VERSION;                                       p := p + SizeOf( DWORD );
1385
1386         //===== \83C\83\93\83t\83H\83\81\81[\83V\83\87\83\93\83Z\83N\83V\83\87\83\93
1387         p2 := p;
1388         // \83Z\83N\83V\83\87\83\93\83T\83C\83Y
1389         PDword( p2 )^ := 16;                                                                                    p2 := p2 + SizeOf( DWORD );
1390         // \83Z\83N\83V\83\87\83\93\83^\83C\83v
1391         PDword( p2 )^ := INFOMATION_SECTION;                    p2 := p2 + SizeOf( DWORD );
1392         // \83Z\83N\83^\83T\83C\83Y
1393         PDword( p2 )^ := SECTOR_SIZE;                                                   p2 := p2 + SizeOf( DWORD );
1394         // \83\8c\83R\81[\83h\90\94
1395         PDword( p2 )^ := 0;                                                                                             p2 := p2 + SizeOf( DWORD );
1396         p := p + PDword( p )^;
1397
1398         //===== \83J\83\89\83\80\83\8a\83X\83g\83Z\83N\83V\83\87\83\93
1399         // 1 \83Z\83N\83^\82É SECTOR_SIZE / SizeOf( DWORD ) \8cÂ\82Ì\83J\83\89\83\80\82ª\93ü\82é\82Æ\8dl\82¦\81A
1400         // 1 \83J\83\89\83\80\82É 12 byte(11 \95\8e\9a) + 4 byte \83f\81[\83^\83^\83C\83v = 16 byte \8fÁ\94ï\82·\82é\82Æ\89¼\92è
1401         p2 := p;
1402         // \83Z\83N\83V\83\87\83\93\83T\83C\83Y
1403         PDword( p2 )^   := 8 + (SECTOR_SIZE div SizeOf( DWORD )) * 16;
1404                                                                                                                                                                                 p2 := p2 + SizeOf( DWORD );
1405         // \83Z\83N\83V\83\87\83\93\83^\83C\83v
1406         PDword( p2 )^   := COLUMN_LIST_SECTION;                 p2 := p2 + SizeOf( DWORD );
1407         // \83J\83\89\83\80\90\94
1408         PDword( p2 )^   := 0;                                                                                           p2 := p2 + SizeOf( DWORD );
1409         p := p + PDword( p )^;
1410
1411         //===== \83A\83\8d\83P\81[\83V\83\87\83\93\83e\81[\83u\83\8b\83Z\83N\83V\83\87\83\93
1412         // - 8 = allocation table section
1413         // -12 = index section + column no + property
1414         // -12 = sector section + section no
1415         p2 := p;
1416         emptySize                                       := p2 - PChar( FFile.Memory ) - 8 - 12 - 12;
1417         // emptySize = sectionCount *
1418         //              (SECTOR_SIZE + allocation table + table no + value)
1419         // sectionCount = emptySize / (SECTOR_SIZE + 12)
1420         sectionCount                    := emptySize div (SECTOR_SIZE + 12);
1421         // \83Z\83N\83V\83\87\83\93\83T\83C\83Y
1422         PDword( p2 )^                   := 8 + sectionCount * SizeOf( DWORD );
1423                                                                                                                                                                                 p2 := p2 + SizeOf( DWORD );
1424         // \83Z\83N\83V\83\87\83\93\83^\83C\83v
1425         PDword( p2 )^                   := ALLOCATION_TABLE_SECTION;
1426                                                                                                                                                                                 p2 := p2 + SizeOf( DWORD );
1427         // \83e\81[\83u\83\8b
1428         for i := 1 to sectionCount do begin
1429                 PDword( p2 )^           := 0;                                                                           p2 := p2 + SizeOf( DWORD );
1430         end;
1431         p := p + PDword( p )^;
1432
1433         //===== \83C\83\93\83f\83b\83N\83X\83Z\83N\83V\83\87\83\93
1434         p2 := p;
1435         // \83Z\83N\83V\83\87\83\93\83T\83C\83Y
1436         PDword( p2 )^                   := 12 + sectionCount * SizeOf( DWORD ) * 2;
1437                                                                                                                                                                                 p2 := p2 + SizeOf( DWORD );
1438         // \83Z\83N\83V\83\87\83\93\83^\83C\83v
1439         PDword( p2 )^                   := INDEX_SECTION;                               p2 := p2 + SizeOf( DWORD );
1440         // \83J\83\89\83\80\94Ô\8d\86 ( 2 byte ) + \83v\83\8d\83p\83e\83B ( 2 byte )
1441         PDword( p2 )^                   := 0;                                                                           p2 := p2 + SizeOf( DWORD );
1442         // \83e\81[\83u\83\8b\94Ô\8d\86 + \92l
1443         for i := 1 to sectionCount * 2 do begin
1444                 PDword( p2 )^           := 0;                                                                           p2 := p2 + SizeOf( DWORD );
1445         end;
1446         p := p + PDword( p )^;
1447
1448         //===== \83Z\83N\83^\83Z\83N\83V\83\87\83\93
1449         p2 := p;
1450         // \83Z\83N\83V\83\87\83\93\83T\83C\83Y
1451         PDword( p2 )^   := 8 + sectionCount * SECTOR_SIZE;
1452                                                                                                                                                                                 p2 := p2 + SizeOf( DWORD );
1453         // \83Z\83N\83V\83\87\83\93\83^\83C\83v
1454         PDword( p2 )^   := SECTOR_SECTION;                                      p2 := p2 + SizeOf( DWORD );
1455         // \83Z\83N\83V\83\87\83\93\94Ô\8d\86
1456         PDword( p2 )^   := 0;                                                                                           p2 := p2 + SizeOf( DWORD );
1457         p := p + PDword( p )^;
1458
1459         if p + 8 <= PChar( FFile.Memory ) + FFile.Size then begin
1460                 // \8fI\92[\8bL\8d\86
1461                 PDWord( p )^                    := 0;
1462                 PDWord( p + 4 )^        := NULL_SECTION;
1463         end;
1464
1465 end;
1466
1467 //==============================
1468 // ReadSections
1469 //==============================
1470 procedure TGikoDB.ReadSections;
1471 var
1472         p                                       : PChar;
1473         dbVersion       : Longword;
1474 begin
1475
1476         FSections       := TList.Create;
1477         p                                       := FFile.Memory;
1478         // \83V\83O\83l\83`\83\83\82Ì\83`\83F\83b\83N (\8c»\8dÝ\82Í\83\8a\83g\83\8b\83G\83\93\83f\83B\83A\83\93\82Ì\82Ý)
1479         if PDword( p )^ <> SIGNATURE_LITTLE_ENDIAN then
1480                 raise EGikoDBUnssuportedFormatError.Create(
1481                         '\83f\81[\83^\83x\81[\83X\82Ì\83t\83H\81[\83}\83b\83g\82ª\95s\96¾\82Å\82·\81B' );
1482         p := p + SizeOf( DWORD );
1483
1484         dbVersion := PDword( p )^;      p := p + SizeOf( DWORD );
1485         case dbVersion of
1486         DATABASE_VERSION:
1487                 ReadSection0_0d1( p );
1488         else
1489                 raise EGikoDBUnssuportedFormatError.Create(
1490                         '\83T\83|\81[\83g\82³\82ê\82Ä\82¢\82È\82¢\83t\83H\81[\83}\83b\83g\82Å\82·\81B' );
1491         end;
1492
1493 end;
1494
1495 //==============================
1496 // ReadSection0_0d1
1497 //==============================
1498 procedure TGikoDB.ReadSection0_0d1( const address : PChar );
1499 var
1500         p, tail                 : PChar;
1501         sectionSize     : Longword;
1502         sectionType     : Longword;
1503         section                 : TSection;
1504 begin
1505
1506         p                       := address;
1507         tail    := PChar( FFile.Memory ) + FFile.Size - 8;
1508         while p < tail do begin
1509                 sectionSize := PDword( p )^;
1510                 sectionType := PDword( p + 4 )^;
1511                 if sectionSize = 0 then
1512                         Break;
1513                         
1514                 case sectionType of
1515                 NULL_SECTION:
1516                         FSections.Add( TSection.Create( Self, p ) );
1517
1518                 INFOMATION_SECTION:
1519                         begin
1520                                 FInfomation := TInfomation.Create( Self, p );
1521                                 FSections.Add( FInfomation );
1522                         end;
1523
1524                 COLUMN_LIST_SECTION:
1525                         begin
1526                                 FColumnList := TColumnList.Create( Self, p );
1527                                 FSections.Add( FColumnList );
1528                         end;
1529
1530                 ALLOCATION_TABLE_SECTION:
1531                         begin
1532                                 FAllocationTable := TAllocationTable.Create( Self, p );
1533                                 FSections.Add( FAllocationTable );
1534                         end;
1535
1536                 INDEX_SECTION:
1537                         begin
1538                                 section := TSortIndex.Create( Self, p );
1539                                 FIndexes.Add( section );
1540                                 FSections.Add( section );
1541                         end;
1542
1543                 SECTOR_SECTION:
1544                         begin
1545                                 section := TSector.Create( Self, p );
1546                                 FSectors.Add( section );
1547                                 FSections.Add( section );
1548                         end;
1549
1550                 else
1551                         FSections.Add( TSection.Create( Self, p ) )
1552                 end;
1553                 p := p + sectionSize;
1554         end;
1555
1556 end;
1557
1558 //==============================
1559 // CreateSection
1560 //==============================
1561 function TGikoDB.CreateSection(
1562         sectionSize : Longword;
1563         sectionType : Longword
1564 ) : Pointer;
1565 var
1566         i, j                                    : Integer;
1567         section                         : TSection;
1568         emptySection    : TSection;
1569         emptySize                       : Longword;
1570         emptyIndex              : Integer;
1571         fileSize                        : Longword;
1572         oldBegin                        : PChar;
1573         p                                                       : PChar;
1574 begin
1575
1576         // \82Ü\82¸\82Í\8bó\82«\83Z\83N\83V\83\87\83\93\82ð\92T\82·
1577         emptySection    := nil;
1578         section                         := nil;
1579         emptyIndex              := 0;
1580         // \98A\91±\82µ\82½\8bó\82«\97Ì\88æ\82ª FSection \82Ì\93Y\82¦\8e\9a\82Å\82à
1581         // \98A\91±\82µ\82Ä\82¢\82È\82¯\82ê\82Î\82È\82ç\82È\82¢\82Ì\82Å\83\\81[\83g
1582         FSections.Sort( SortSectionsByPtr );
1583
1584         for i := 0 to FSections.Count - 1 do begin
1585                 section := TSection( FSections[ i ] );
1586                 if (section.SectionType = NULL_SECTION) then begin
1587                         // emptySection \82Í\98A\91±\82µ\82½\8bó\82«\97Ì\88æ\82Ì\90æ\93ª\82ð\8ew\82·
1588                         if emptySection = nil then begin
1589                                 emptySection    := section;
1590                                 emptyIndex              := i;
1591                         end;
1592
1593                         emptySize := PChar( section.Memory ) + section.Size -
1594                                 PChar( emptySection.Memory );
1595                         if sectionSize <= emptySize then begin
1596                                 // \8bó\82«\83Z\83N\83V\83\87\83\93\94­\8c©
1597                                 Result := emptySection.Memory;
1598                                 PDword( Result )^                                                               := emptySize;
1599                                 PDword( PChar( Result ) + 4 )^  := sectionType;
1600                                 // \8bó\82«\83Z\83N\83V\83\87\83\93\82Ì\8dí\8f\9c
1601                                 for j := i downto emptyIndex do begin
1602                                         TSection( FSections[ j ] ).Free;
1603                                         FSections.Delete( j );
1604                                 end;
1605                                 Exit; // \81¦\8bó\82«\83Z\83N\83V\83\87\83\93\82ª\8dí\8f\9c\82³\82ê\82Ä\82¢\82é\82Ì\82Å for i \82Í\91±\8ds\95s\89Â\94\
1606                         end;
1607                 end else begin
1608                         emptySection := nil;
1609                 end;
1610         end;
1611
1612         // \83t\83@\83C\83\8b\82Ì\96\96\94ö\82É\82É\8bó\82«\97Ì\88æ\82ª\82 \82é\82©
1613         oldBegin := FFile.Memory;
1614         if PChar( section.Next ) + sectionSize <= oldBegin + FFile.Size then begin
1615                 // \8bó\82«\97Ì\88æ\94­\8c©
1616                 Result := section.Next;
1617                 PDword( Result )^                                                               := sectionSize;
1618                 PDword( PChar( Result ) + 4 )^  := sectionType;
1619                 Exit;
1620         end;
1621
1622         // sectionSize \82ð\96\9e\82½\82·\97Ì\88æ\82ª\82È\82¢\82Ì\82Å\83t\83@\83C\83\8b\82ð\8ag\92£
1623         FChanged        := True;
1624
1625         // \8ag\92£\82·\82é\83T\83C\83Y\82Ì\8cv\8eZ
1626         fileSize        := (sectionSize div FPageSize + 1) * FPageSize;
1627
1628         // \8ag\92£\82µ\82Ä\83t\83@\83C\83\8b\82ð\8aJ\82«\82È\82¨\82µ
1629         FFile.Free;
1630         FFile                   := TMappedFile.Create( FFilePath, fmOpenReadWrite, fileSize );
1631
1632         // \96\96\94ö\82É\92Ç\89Á
1633         Result  := PChar( FFile.Memory ) + (PChar( section.Next ) - oldBegin);
1634         PDword( Result )^                                                               := sectionSize;
1635         PDword( PChar( Result ) + 4 )^  := sectionType;
1636
1637         p := PChar( Result ) + sectionSize;
1638         if p + 8 <= PChar( FFile.Memory ) + FFile.Size then begin
1639                 // \8fI\92[\8bL\8d\86
1640                 PDword( p )^    := 0;                                                   p := p + SizeOf( DWORD );
1641                 PDword( p )^    := NULL_SECTION;
1642         end;
1643
1644 end;
1645
1646 //==============================
1647 // ReallocateSection
1648 //==============================
1649 procedure TGikoDB.ReallocateSection(
1650         section                 : TSection;
1651         sectionSize : Longword );
1652 var
1653         nextSection             : PChar;
1654         fileEnd                         : PChar;
1655         p                                                       : PChar;
1656         size                                    : Longword;
1657         sectionType             : Longword;
1658 begin
1659
1660         FChanged := True;
1661         fileEnd         := PChar( FFile.Memory ) + FFile.Size;
1662
1663         if sectionSize <= section.Size then begin
1664
1665                 // \8fk\8f¬
1666                 nextSection             := PChar( section.Next );
1667                 section.SetSize( sectionSize );
1668                 if 8 >= fileEnd - PChar( nextSection ) then
1669                         // \82±\82±\82ª\8dÅ\8cã\82Ì\83Z\83N\83V\83\87\83\93
1670                         nextSection := fileEnd;
1671
1672                 if 16 >= nextSection - PChar( section.Next ) then begin
1673                         // \8cã\91±\82·\82é\8bó\82«\82ª\8f¬\82³\82¢\82Ì\82Å section \82É\98A\8c\8b\82·\82é
1674                         section.SetSize( nextSection - PChar( section.Memory ) );
1675                 end else begin
1676                         // \8cã\91±\82·\82é\8bó\82«\82ª\91å\82«\82¢\82Ì\82Å\8bó\83Z\83N\83V\83\87\83\93\82É\82·\82é
1677                         p := section.Next;
1678                         if PDword( nextSection )^ = 0 then
1679                                 // \8bó\82«\83Z\83N\83V\83\87\83\93\82Í\8dÅ\8fI\83Z\83N\83V\83\87\83\93
1680                                 PDword( p )^    := 0
1681                         else
1682                                 // \92f\95Ð\89»\82µ\82½\8bó\82«\83Z\83N\83V\83\87\83\93
1683                                 PDword( p )^    := nextSection - p;
1684                         PDword( p + 4 )^        := NULL_SECTION;
1685                 end;
1686
1687         end else begin
1688
1689                 // \8ag\92£
1690                 size    := section.Size;
1691                 p                       := PChar( section.Next );
1692
1693                 // section \82Ì\82·\82®\8cã\82É\98A\91±\82µ\82½\8bó\82«\82ð\92T\82·
1694                 while (8 < fileEnd - p) and (size < sectionSize) do begin
1695                         if PDword( p )^ = 0 then begin
1696                                 size := size + Longword( fileEnd - p );
1697                                 Break;
1698                         end else if PDword( p + 4 )^ = 0 then begin
1699                                 size    := size + PDword( p )^;
1700                                 p                       := p + PDword( p )^;
1701                         end else begin
1702                                 Break;
1703                         end;
1704                 end;
1705
1706                 if size >= sectionSize then begin
1707                         // \98A\91±\82µ\82½\8bó\82«\83Z\83N\83V\83\87\83\93\82Å\98d\82¦\82é
1708                         section.SetSize( size );
1709                 end else begin
1710                         // \98A\91±\82µ\82½\8bó\82«\83Z\83N\83V\83\87\83\93\82Å\98d\82¦\82È\82¢\82Ì\82Å\90V\8bK\8dì\90¬
1711                         size                                             := section.Size;
1712                         sectionType                      := section.SectionType;
1713                         section.SetType( NULL_SECTION );
1714
1715                         p := CreateSection( sectionSize, sectionType );
1716                         Move( PChar( section.FMemory )^, p^, size );
1717
1718                         section.FMemory  := p;
1719                 end;
1720
1721         end;
1722
1723 end;
1724
1725 //==============================
1726 // Dump
1727 //==============================
1728 procedure TGikoDB.Dump(
1729         const filePath  : string );
1730 begin
1731         //!!!!! \8dì\90¬\92\86 !!!!!
1732 end;
1733
1734 //==============================
1735 // Changed
1736 //==============================
1737 procedure TGikoDB.Changed( force : Boolean = False );
1738 var
1739         i       : Integer;
1740 begin
1741
1742         if FChanged or force then begin
1743                 // FSections \82Ì\8aJ\95ú
1744                 for i := FSections.Count - 1 downto 0 do
1745                         TObject( FSections[ i ] ).Free;
1746                 FSections.Free;
1747
1748                 // FSections \82ð\8dÄ\8d\\92z
1749                 ReadSections;
1750         end;
1751
1752 end;
1753
1754 //==============================
1755 // SelectValue
1756 //==============================
1757 function TGikoDB.SelectValue(
1758         founds                  : TList;
1759         value                           : Longword;
1760         columnIndex : Word = 0
1761 ) : Boolean;
1762 var
1763         foundIdx        : Integer;
1764         l, h, m         : Integer;
1765         index                   : TSortIndex;
1766 begin
1767
1768         Result          := False;
1769         index                   := nil;
1770         foundIdx        := -1;
1771         for l := 0 to FIndexes.Count - 1 do begin
1772                 index := TSortIndex( FIndexes[ l ] );
1773                 if index.ColumnIndex = columnIndex then
1774                         Break;
1775         end;
1776         if index = nil then
1777                 Exit;
1778
1779         // \92P\8f\83\82È\93ñ\95ª\92T\8dõ
1780         l := 0;
1781         h := index.Count;
1782         m := 0;
1783         while l < h do begin
1784                 m := (l + h) shr 1;
1785                 if index[ m ].FValue = value then begin
1786                         foundIdx := m;
1787                         founds.Add( Pointer( index[ m ].FATIndex ) );
1788                         Break;
1789                 end else if index[ m ].FValue < value then begin
1790                         h := m;
1791                 end else begin
1792                         l := m;
1793                 end;
1794         end;
1795         if foundIdx < 0 then
1796                 Exit;
1797
1798         for l := m - 1 downto 0 do begin
1799                 if index[ l ].FValue <> value then
1800                         Break;
1801                 founds.Add( Pointer( l ) );
1802         end;
1803         for l := m + 1 downto index.Count - 1 do begin
1804                 if index[ l ].FValue <> value then
1805                         Break;
1806                 founds.Add( Pointer( index[ m ].FATIndex ) );
1807         end;
1808
1809         Result := True;
1810
1811 end;
1812
1813 //==============================
1814 // GetRecordByInteger
1815 //==============================
1816 function TGikoDB.GetRecordByInteger( primalyValue : Integer ) : TRecord;
1817 var
1818         founds  : TList;
1819         sector  : Integer;
1820 begin
1821
1822         Result  := nil;
1823         founds  := TList.Create;
1824         try
1825                 if not SelectValue( founds, primalyValue ) then
1826                         Exit;
1827
1828                 sector := Integer( founds[ 0 ] );
1829                 Result := TRecord.Create( Self, FAllocationTable[ sector ] );
1830         finally
1831                 founds.Free;
1832         end;
1833
1834 end;
1835
1836 //==============================
1837 // GetRecordByString
1838 //==============================
1839 function TGikoDB.GetRecordByString( const primalyValue : string ) : TRecord;
1840 var
1841         hash            : Longword;
1842 begin
1843
1844         hash            := GetStringHash( primalyValue );
1845         Result  := GetRecordByInteger( hash );
1846
1847 end;
1848
1849 //==============================
1850 // GetSector
1851 //==============================
1852 function TGikoDB.GetSector( sectorNo : Integer ) : Pointer;
1853 begin
1854         //!!!!! \8dì\90¬\92\86 !!!!!
1855 end;
1856
1857 end.