--- /dev/null
+unit GikoDB;
+
+(*!
+\file GikoDB.pas
+\brief \8aÈ\88Õ\83f\81[\83^\83x\81[\83X
+
+$Id: GikoDB.pas,v 1.1 2004/10/09 15:08:43 yoffy Exp $
+
+
+<h2>\83f\81[\83^\83x\81[\83X\83t\83H\81[\83}\83b\83g 0.0d1</h2>
+<p>
+\81@2 \8e\9f\8c³\82Ì\83X\83v\83\8c\83b\83h\83V\81[\83g\82Å\8d\\90¬\82³\82ê\81A
+\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>
+\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
+</p>
+
+<hr>
+<h3>\83t\83@\83C\83\8b\83C\83\81\81[\83W</h3>
+<table border="1" style="text-align:center">
+<tr><td><a href="#header">\83w\83b\83_</a></td></tr>
+<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>
+<tr><td><a href="#cols">\83J\83\89\83\80\83\8a\83X\83g\83Z\83N\83V\83\87\83\93</a></td></tr>
+<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>
+<tr><td><a href="#idex">\83C\83\93\83f\83b\83N\83X\83Z\83N\83V\83\87\83\93</a></td></tr>
+<tr><td><a href="#sect">\83Z\83N\83^\83Z\83N\83V\83\87\83\93</a></td></tr>
+<tr><td>\81c</td></tr>
+<tr><td><a href="#idex">\83C\83\93\83f\83b\83N\83X\83Z\83N\83V\83\87\83\93</a></td></tr>
+<tr><td><a href="#sect">\83Z\83N\83^\83Z\83N\83V\83\87\83\93</a></td></tr>
+</table>
+<p>
+<b>\8aT\97v</b><br>
+\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
+</p>
+
+<hr>
+<a name="header"></a>
+<h3>\83w\83b\83_</h3>
+<table border="1" style="text-align:center">
+<tr><td>\83V\83O\83l\83`\83\83</td><td>4 byte</td></tr>
+<tr><td>\83\81\83W\83\83\81[\83o\81[\83W\83\87\83\93</td><td>1 byte</td></tr>
+<tr><td>\83}\83C\83i\81[\83o\81[\83W\83\87\83\93</td><td>1 byte</td></tr>
+<tr><td>\83\8a\83\8a\81[\83X\92i\8aK\96¼</td><td>1 byte</td></tr>
+<tr><td>\83\8a\83r\83W\83\87\83\93\83i\83\93\83o\81[</td><td>1 byte</td></tr>
+</table>
+<p>
+<b>\83V\83O\83l\83`\83\83</b><br>
+\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>
+\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
+</p>
+<p>
+<b>\83\81\83W\83\83\81[\83o\81[\83W\83\87\83\93</b><br>
+\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
+</p>
+<p>
+<b>\83}\83C\83i\81[\83o\81[\83W\83\87\83\93</b><br>
+\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
+</p>
+<p>
+<b>\83\8a\83\8a\81[\83X\92i\8aK\96¼</b><br>
+\81@\83\8a\83\8a\81[\83X\82Ì\92i\8aK\81B\92l\82Í\8e©\97R\82¾\82ª\81A
+\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 />
+\81@\88È\89º\82Í\8eQ\8dl\92l\81B
+</p>
+<table border="1">
+<tr><td>\83f\83x\83\8d\83b\83p\83\8a\83\8a\81[\83X</td><td>0</td></tr>
+<tr><td>\83A\83\8b\83t\83@\83\8a\83\8a\81[\83X</td><td>1</td></tr>
+<tr><td>\83x\81[\83^\83\8a\83\8a\81[\83X</td><td>2</td></tr>
+<tr><td>Release Candidate</td><td>3</td></tr>
+<tr><td>\83v\83\8c\83r\83\85\81[\83\8a\83\8a\81[\83X</td><td>4</td></tr>
+<tr><td>\83t\83@\83C\83i\83\8b(\83}\83X\83^)\83\8a\83\8a\81[\83X</td><td>5</td></tr>
+</table>
+<p>
+<b>\83\8a\83r\83W\83\87\83\93\83i\83\93\83o\81[</b><br>
+\81@\83\8a\83\8a\81[\83X\94Ô\8d\86\82È\82Ç\81B
+</p>
+<p>
+
+<hr>
+<a name="section"></a>
+<h3>\83Z\83N\83V\83\87\83\93</h3>
+<table border="1" style="text-align:center">
+<tr><td>\83Z\83N\83V\83\87\83\93\83T\83C\83Y</td><td>4 byte</td></tr>
+<tr><td>\83Z\83N\83V\83\87\83\93\83^\83C\83v</td><td>4 chars</td></tr>
+<tr><td>\83Z\83N\83V\83\87\83\93\93à\97e</td><td>\89Â\95Ï</td></tr>
+</table>
+<p>
+<b>\83Z\83N\83V\83\87\83\93\83T\83C\83Y</b><br>
+\81@\83Z\83N\83V\83\87\83\93\91S\91Ì\82Ì\83T\83C\83Y\81B
+\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
+\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>
+\81@\8cã\91±\82É\83Z\83N\83V\83\87\83\93\82ª\82È\82¢\8fê\8d\87\82Í 0 \82É\82·\82é\81B
+</p>
+<p>
+<b>\83Z\83N\83V\83\87\83\93\83^\83C\83v</b><br>
+\81@\83Z\83N\83V\83\87\83\93\82Ì\8eí\97Þ\82ð\95\\82· 4 byte \82Ì\95¶\8e\9a\97ñ\81B<br>
+\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
+</p>
+
+<hr>
+<a name="info"></a>
+<h3>\83C\83\93\83t\83H\83\81\81[\83V\83\87\83\93\83Z\83N\83V\83\87\83\93</h3>
+<table border="1" style="text-align:center">
+<tr><td>\83Z\83N\83V\83\87\83\93\83T\83C\83Y</td><td>4 byte</td></tr>
+<tr><td>'info'</td><td>4 chars</td></tr>
+<tr><td>\83Z\83N\83^\83T\83C\83Y</td><td>4 byte</td></tr>
+<tr><td>\83\8c\83R\81[\83h\90\94</td><td>4 byte</td></tr>
+</table>
+<p>
+<b>\83Z\83N\83^\83T\83C\83Y</b><br>
+\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@
+</p>
+<p>
+<b>\83\8c\83R\81[\83h\90\94</b><br>
+\81@\83f\81[\83^\83x\81[\83X\91S\91Ì\82Ì\83\8c\83R\81[\83h\90\94\81B\81@
+</p>
+
+<hr>
+<a name="cols"></a>
+<h3>\83J\83\89\83\80\83\8a\83X\83g\83Z\83N\83V\83\87\83\93</h3>
+<table border="1" style="text-align:center">
+<tr><td>\83Z\83N\83V\83\87\83\93\83T\83C\83Y</td><td>4 byte</td></tr>
+<tr><td>'cols'</td><td>4 chars</td></tr>
+<tr><td>\83J\83\89\83\80\90\94</td><td>4 byte</td></tr>
+<tr><td>\83J\83\89\83\80\96¼0</td><td>pascal string</td></tr>
+<tr><td>\83f\81[\83^\83^\83C\83v0</td><td>4 chars</td></tr>
+<tr><td>\81c</td><td></td></tr>
+<tr><td>\83J\83\89\83\80\96¼n</td><td>pascal string</td></tr>
+<tr><td>\83f\81[\83^\83^\83C\83vn</td><td>4 chars</td></tr>
+</table>
+<p>
+<b>\90§\8cÀ</b><br>
+\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
+</p>
+<p>
+<b>\83J\83\89\83\80\90\94</b><br>
+\81@\8cã\91±\82·\82é\83J\83\89\83\80\82Ì\8cÂ\90\94\81B
+</p>
+<p>
+<b>\83J\83\89\83\80\96¼</b><br>
+\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>
+\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
+</p>
+<p>
+<b>\83f\81[\83^\83^\83C\83v</b><br>
+\81@\8ai\94[\82³\82ê\82Ä\82¢\82é\83f\81[\83^\82Ì\83^\83C\83v\81B<br>
+\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
+\81@\8fÚ\8d×\82Í\88È\89º\82Ì\92Ê\82è\81B
+</p>
+<p>
+\81@\98_\97\9d\92l\82Í 1 byte \8fÁ\94ï\82·\82é\81B<br>
+\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>
+\81@pascal string \82Í 1 byte \82Ì\95¶\8e\9a\97ñ\92·\82Æ\82»\82ê\82É\91±\82\95¶\8e\9a\97ñ\81A
+data \82Í 4 byte \82Ì\83f\81[\83^\92·\82Æ\82»\82ê\82É\91±\82\83f\81[\83^\81B<br>
+\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
+\83f\81[\83^\92·\82ð\8e¦\82·\92l\82Í\92·\82³\82É\8aÜ\82Ü\82ê\82Ä\82¢\82È\82¢\81B
+\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>
+\81@unix time \82Í\92Ê\8eZ\95b\82ð\95\\82µ\82½ 8 byte integer \82Å\81AUTC \82ª\90\84\8f§\82³\82ê\82é\81B
+</p>
+<table border="1">
+<tr><td>\98_\97\9d\92l</td><td>'bool'</td></tr>
+<tr><td rowspan="4">\95\84\8d\86\95t\82«\90®\90\94</td><td>'si01'</td></tr>
+<tr><td>'si02'</td></tr>
+<tr><td>'si04'</td></tr>
+<tr><td>'si08'</td></tr>
+<tr><td rowspan="4">\95\84\8d\86\96³\82µ\90®\90\94</td><td>'ui01'</td></tr>
+<tr><td>'ui02'</td></tr>
+<tr><td>'ui04'</td></tr>
+<tr><td>'ui08'</td></tr>
+<tr><td rowspan="2">\95\82\93®\8f¬\90\94</td><td>'fp04'</td></tr>
+<tr><td>'fp08'</td></tr>
+<tr><td>pascal string</td><td>'pstr'</td></tr>
+<tr><td>data (long string)</td><td>'data'</td></tr>
+<tr><td>unix time</td><td>'time'</td></tr>
+</table>
+
+<hr>
+<a name="atlb"></a>
+<h3>\83A\83\8d\83P\81[\83V\83\87\83\93\83e\81[\83u\83\8b\83Z\83N\83V\83\87\83\93</h3>
+<table border="1" style="text-align:center">
+<tr><td>\83Z\83N\83V\83\87\83\93\83T\83C\83Y</td><td>4 byte</td></tr>
+<tr><td>'atlb'</td><td>4 chars</td></tr>
+<tr><td>\8cp\91±\83e\81[\83u\83\8b</td><td>4 byte</td></tr>
+<tr><td>\81c</td><td></td></tr>
+<tr><td>\8cp\91±\83e\81[\83u\83\8b</td><td>4 byte</td></tr>
+</table>
+<p>
+<b>\8aT\97v</b><br>
+\81@\82±\82Ì\83e\81[\83u\83\8b\82Ì\83C\83\93\83f\83b\83N\83X\82Æ
+<a href="#sect">\83Z\83N\83^</a>\82Ì\83C\83\93\83f\83b\83N\83X\82ª\91Î\82É\82È\82Á\82Ä\82¢\82é\81B
+</p>
+<p>
+<b>\90§\8cÀ</b><br>
+\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
+</p>
+<p>
+<b>\8cp\91±\83e\81[\83u\83\8b</b><br>
+\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
+\8cp\91±\82µ\82È\82¢\8fê\8d\87\82Í 0xffffffff\81B
+</p>
+
+<hr>
+<a name="idex"></a>
+<h3>\83\\81[\83g\8dÏ\82Ý\83C\83\93\83f\83b\83N\83X\83Z\83N\83V\83\87\83\93</h3>
+<table border="1" style="text-align:center">
+<tr><td>\83Z\83N\83V\83\87\83\93\83T\83C\83Y</td><td>4 byte</td></tr>
+<tr><td>'idex'</td><td>4 chars</td></tr>
+<tr><td>\83J\83\89\83\80\94Ô\8d\86</td><td>2 byte</td></tr>
+<tr><td>\83v\83\8d\83p\83e\83B</td><td>2 byte</td></tr>
+<tr><td>\83e\81[\83u\83\8b\94Ô\8d\86</td><td>4 byte</td></tr>
+<tr><td>\92l</td><td>4 byte</td></tr>
+<tr><td>\81c</td><td></td></tr>
+<tr><td>\83e\81[\83u\83\8b\94Ô\8d\86</td><td>4 byte</td></tr>
+<tr><td>\92l</td><td>4 byte</td></tr>
+</table>
+<p>
+<b>\8aT\97v</b><br>
+\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>
+\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
+</p>
+<p>
+<b>\90§\8cÀ</b><br>
+\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
+</p>
+<p>
+<b>\83J\83\89\83\80\94Ô\8d\86</b><br>
+\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
+</p>
+<p>
+<b>\83v\83\8d\83p\83e\83B</b><br>
+\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>
+\81@\83v\83\8d\83p\83e\83B\82Ì\88ê\97\97\82Í\88È\89º\82Ì\92Ê\82è\81B
+</p>
+<table border="1">
+<tr><td>0bit</td><td>\83\\81[\83g\83I\81[\83_\81[\81B0...\8f¸\8f\87, 1...\8d~\8f\87</td></tr>
+</table>
+<p>
+<b>\83e\81[\83u\83\8b\94Ô\8d\86</b><br>
+\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>
+</p>
+<p>
+<b>\92l</b><br>
+\81@\83\8c\83R\81[\83h\82É\8ai\94[\82³\82ê\82Ä\82¢\82é\92l\81B<br>
+\81@\83\8c\83R\81[\83h\82É\82à\92l\82ª\8ai\94[\82³\82ê\82Ä\82¢\82é\82½\82ß\81A
+\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
+\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>
+\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
+</p>
+
+<hr>
+<a name="sect"></a>
+<h3>\83Z\83N\83^\83Z\83N\83V\83\87\83\93</h3>
+<table border="1" style="text-align:center">
+<tr><td>\83Z\83N\83V\83\87\83\93\83T\83C\83Y</td><td>4 byte</td></tr>
+<tr><td>'sect'</td><td>4 chars</td></tr>
+<tr><td>\83Z\83N\83V\83\87\83\93\94Ô\8d\86</td><td>4 byte</td></tr>
+<tr><td>\83Z\83N\83^0</td><td></td></tr>
+<tr><td>\81c</td><td></td></tr>
+<tr><td>\83Z\83N\83^n</td><td></td></tr>
+</table>
+<p>
+<b>\83Z\83N\83V\83\87\83\93\94Ô\8d\86</b><br>
+\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>
+\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É
+\83Z\83N\83^\94Ô\8d\86\82ª\8a\84\82è\93\96\82Ä\82ç\82ê\82Ü\82·\81B
+</p>
+<p>
+<b>\83Z\83N\83^</b><br>
+\81@\8ae\83J\83\89\83\80\82Ì\92l\82ª\8f\87\82É\8ai\94[\82³\82ê\82é\81B
+</p>
+*)
+interface
+
+//==================================================
+uses
+//==================================================
+
+ Classes, SysUtils, IniFiles,
+ Windows,
+ YofUtils;
+
+
+//==================================================
+type
+//==================================================
+
+ TGikoDB = class;
+
+ {!***********************************************************
+ \brief \83Z\83N\83V\83\87\83\93
+ ************************************************************}
+ TSection = class( TObject )
+ private
+ FMemory : Pointer; //!< \83Z\83N\83V\83\87\83\93\83A\83h\83\8c\83X
+ FParent : TGikoDB;
+
+ function GetSize : Longword;
+ procedure SetSize( newSize : Longword );
+ function GetType : Longword;
+ procedure SetType( newType : Longword );
+ function GetNext : Pointer;
+ function GetContents : Pointer;
+
+ public
+ constructor Create( parent : TGikoDB; const address : Pointer );
+
+ property Memory : Pointer read FMemory;
+ property Size : Longword read GetSize;
+ property SectionType : Longword read GetType;
+ property Next : Pointer read GetNext;
+ end;
+
+ {!***********************************************************
+ \brief \83Z\83N\83^\83Z\83N\83V\83\87\83\93
+ ************************************************************}
+ TSector = class( TSection )
+ private
+ FSectionNo : Longword; //!< \83Z\83N\83V\83\87\83\93\94Ô\8d\86
+ FCount : Integer; //!< \83Z\83N\83^\90\94
+
+ function GetContents : Pointer;
+ function GetSector( index : Integer ) : Pointer;
+
+ public
+ constructor Create( parent : TGikoDB; const address : Pointer );
+
+ property Count : Integer read FCount;
+ property Sector[ index : Integer ] : Pointer read GetSector; default;
+ end;
+
+ {!***********************************************************
+ \brief \83\\81[\83g\8dÏ\82Ý\83C\83\93\83f\83b\83N\83X\8d\\91¢\91Ì
+ ************************************************************}
+ RSortIndex = record
+ FATIndex : Word; //!< \83A\83\8d\83P\81[\83V\83\87\83\93\83e\81[\83u\83\8b\83C\83\93\83f\83b\83N\83X
+ FValue : Longword; //!< \92l
+ end;
+
+ PSortIndex = ^RSortIndex;
+
+ {!***********************************************************
+ \brief \83\\81[\83g\8dÏ\82Ý\83C\83\93\83f\83b\83N\83X
+ ************************************************************}
+ TSortIndex = class( TSection )
+ private
+ FColumnIndex : Word; //!< \83J\83\89\83\80\83C\83\93\83f\83b\83N\83X
+ FColumnProperty : Word; //!< \83C\83\93\83f\83b\83N\83X\83v\83\8d\83p\83e\83B
+
+ function GetContents : Pointer;
+ function GetCount : Integer;
+ function GetItem( index : Integer ) : PSortIndex;
+
+ public
+ constructor Create( parent : TGikoDB; const address : Pointer );
+
+ property Count : Integer read GetCount;
+ property Items[ index : Integer ] : PSortIndex read GetItem; default;
+ property ColumnIndex : Word read FColumnIndex;
+ property ColumnProperty : Word read FColumnProperty;
+ end;
+
+ {!***********************************************************
+ \brief \83A\83\8d\83P\81[\83V\83\87\83\93\83e\81[\83u\83\8b
+ ************************************************************}
+ TAllocationTable = class( TSection )
+ private
+ function GetTable( index : Integer ) : Longword;
+
+ public
+ constructor Create( parent : TGikoDB; const address : Pointer );
+
+ property Table[ index : Integer ] : Longword read GetTable; default;
+ end;
+
+ {!***********************************************************
+ \brief \83J\83\89\83\80
+ ************************************************************}
+ TColumn = class( TObject )
+ private
+ FIndex : Word; //!< \83J\83\89\83\80\83C\83\93\83f\83b\83N\83X
+ FType : Longword; //!< \83f\81[\83^\83^\83C\83v
+
+ public
+ constructor Create( colIndex : Word; colType : Longword );
+
+ property ColumnIndex : Word read FIndex;
+ property ColumnType : Longword read FType;
+ end;
+
+ {!***********************************************************
+ \brief \83J\83\89\83\80\83\8a\83X\83g
+ ************************************************************}
+ TColumnList = class( TSection )
+ private
+ FList : THashedStringList; //!< \83J\83\89\83\80\83\8a\83X\83g\96{\91Ì
+ FColumnEnd : PChar; //!< \8e\9f\82Ì\83J\83\89\83\80\92Ç\89Á\88Ê\92u
+
+ function GetContents : Pointer;
+ function GetColumnCount : Longword;
+ procedure SetColumnCount( n : Longword );
+
+ function GetItemFromIndex( index : Integer ) : TColumn;
+ function GetItemFromColumnIndex( index : Integer ) : TColumn;
+ function GetItemFromName( const columnName : string ) : TColumn;
+ procedure WriteBack;
+
+ public
+ //! \todo \8dí\8f\9c\82³\82ê\82½\83J\83\89\83\80\88È\8d~\82Ì index \82ð\82Â\82¯\82©\82¦\82é
+ constructor Create( parent : TGikoDB; const address : Pointer );
+ destructor Destroy; override;
+
+ {!
+ \warning \8f\87\8f\98\82Í\95s\92è\82Å\82·\81B\8f\87\8f\98\82ª\8fd\97v\82È\8fê\8d\87\82Í
+ ObjectsFromColumnIndex \82ð\8eg\97p\82µ\82Ä\89º\82³\82¢\81B
+ }
+ property Objects[ index : Integer ] : TColumn read GetItemFromIndex;
+ {!
+ \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
+ }
+ property ObjectsFromColumnIndex[ index : Integer ] : TColumn
+ read GetItemFromColumnIndex;
+ property Items[ const columnName : string ] : TColumn read GetItemFromName; default;
+
+ {!
+ \brief \83J\83\89\83\80\82Ì\8dí\8f\9c
+ \param columnName \8dí\8f\9c\82·\82é\83J\83\89\83\80\96¼
+ \todo \8dí\8f\9c\82³\82ê\82½\83J\83\89\83\80\88È\8d~\82Ì index \82ð\82Â\82¯\82©\82¦\82é
+
+ 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
+ }
+ procedure Delete( const columnName : string );
+
+ {!
+ \brief \83J\83\89\83\80\82Ì\92Ç\89Á
+ \param columnName \92Ç\89Á\82·\82é\83J\83\89\83\80\96¼
+ \param columnType \92Ç\89Á\82·\82é\83J\83\89\83\80\82Ì\83f\81[\83^\83^\83C\83v
+
+ 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
+ }
+ procedure Add( const columnName : string; columnType : Longword );
+ end;
+
+ {!***********************************************************
+ \brief \83C\83\93\83t\83H\83\81\81[\83V\83\87\83\93\83Z\83N\83V\83\87\83\93
+ ************************************************************}
+ TInfomation = class( TSection )
+ private
+ function GetSectorSize : Longword;
+ function GetRecordCount : Longword;
+
+ public
+ constructor Create( parent : TGikoDB; const address : Pointer );
+
+ property SectorSize : Longword read GetSectorSize;
+ property RecordCount : Longword read GetRecordCount;
+ end;
+
+ {!***********************************************************
+ \brief \83\8c\83R\81[\83h
+ ************************************************************}
+ TRecord = class( TObject )
+ private
+ FParent : TGikoDB;
+ FSectorNo : Longword; //!< \83Z\83N\83^\94Ô\8d\86
+
+ //! \todo \8dì\90¬\92\86
+ function GetStringByName( const columnName : string ) : string;
+ //! \todo \8dì\90¬\92\86
+ procedure SetStringByName(
+ const columnName : string;
+ const value : string );
+ //! \todo \8dì\90¬\92\86
+ function GetStringByIndex( index : Longword ) : string;
+ //! \todo \8dì\90¬\92\86
+ function GetIntegerByName( const columnName : string ) : Integer;
+ //! \todo \8dì\90¬\92\86
+ procedure SetIntegerByName(
+ const columnName : string;
+ const value : Integer );
+ //! \todo \8dì\90¬\92\86
+ function GetIntegerByIndex( index : Longword ) : Integer;
+
+ public
+ constructor Create( parent : TGikoDB; sectorNo : Longword );
+
+ //! \brief \92l\82ð\95¶\8e\9a\97ñ\82Å\8eæ\93¾\81^\90Ý\92è
+ property StringValue[ const columnName : string ] : string
+ read GetStringByName write SetStringByName;
+
+ //! \brief \92l\82ð\90\94\92l\82Å\8eæ\93¾\81^\90Ý\92è
+ property IntegerValue[ const columnName : string ] : Integer
+ read GetIntegerByName write SetIntegerByName;
+ end;
+
+ {!***********************************************************
+ \brief \83T\83|\81[\83g\82³\82ê\82Ä\82¢\82È\82¢\83f\81[\83^\83x\81[\83X\83t\83H\81[\83}\83b\83g
+ ************************************************************}
+ EGikoDBUnssuportedFormatError = class( Exception );
+
+ {!***********************************************************
+ \brief \8aÈ\88Õ\83f\81[\83^\83x\81[\83X
+ ************************************************************}
+ TGikoDB = class( TObject )
+ private
+ FFilePath : string; //!< \8aJ\82¢\82½\83t\83@\83C\83\8b\82Ì\83p\83X
+ FFile : TMappedFile; //!< \83f\81[\83^\83x\81[\83X\82ð\95Û\8e\9d\82·\82é\83t\83@\83C\83\8b
+ FPageSize : Longword; //!< \83y\81[\83W\83T\83C\83Y
+ FSectorSize : Integer; //!< \83Z\83N\83^\83T\83C\83Y
+ FSections : TList; //!< \83Z\83N\83V\83\87\83\93\83\8a\83X\83g
+ FChanged : Boolean; //!< FSections \82Ì\8dÄ\8d\\92z\82ª\95K\97v\81B
+
+ FInfomation : TInfomation;
+ FColumnList : TColumnList;
+ FSectors : TList;
+ FIndexes : TList;
+ FAllocationTable : TAllocationTable;
+
+ procedure CreateInitialSections;
+ procedure ReadSections;
+ procedure ReadSection0_0d1( const address : PChar );
+
+ {!
+ \brief \83Z\83N\83V\83\87\83\93\82Ì\8dì\90¬
+ \warning \8cã\82Å\95K\82¸ Changed \82ð\8eÀ\8ds\82µ\82Ä\82\82¾\82³\82¢\81B
+ \warning sectionSize \82æ\82è\82à\97]\95ª\82É\8am\95Û\82³\82ê\82é\8e\96\82ª\82 \82è\82Ü\82·\81B
+ }
+ function CreateSection(
+ sectionSize : Longword;
+ sectionType : Longword
+ ) : Pointer;
+
+ {!
+ \brief \83Z\83N\83V\83\87\83\93\82Ì\8ag\92£\81E\8fk\8f¬
+ \warning \8cã\82Å\95K\82¸ Changed \82ð\8eÀ\8ds\82µ\82Ä\82\82¾\82³\82¢\81B
+ \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
+ \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
+ \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
+ }
+ procedure ReallocateSection(
+ section : TSection;
+ sectionSize : Longword );
+
+ {!
+ \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é
+ \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
+ \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
+ \warning \91S\82Ä\82Ì\83Z\83N\83V\83\87\83\93\83N\83\89\83X\82Í\89ð\95ú\82³\82ê\82Ü\82·\81B
+ }
+ procedure Changed( force : Boolean = False );
+
+ {!
+ \brief \91S\83Z\83N\83^\82©\82ç\93Á\92è\82Ì\83J\83\89\83\80\82Ì\92l\82ð\92T\82µ\8fo\82·
+ \param founds \8c©\82Â\82©\82Á\82½\92l\82ª\97ñ\8b\93\82³\82ê\82é
+ \param value \92T\82µ\8fo\82·\92l
+ \param columnIndex \83J\83\89\83\80\83C\83\93\83f\83b\83N\83X
+ \return 1 \82Â\88È\8fã\8c©\82Â\82©\82Á\82½\8fê\8d\87\82Í True
+ \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
+ \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
+ }
+ function SelectValue(
+ founds : TList;
+ value : Longword;
+ columnIndex : Word = 0
+ ) : Boolean;
+
+ {!
+ \brief \83\8c\83R\81[\83h\82ð\8eæ\93¾
+ \param primalyValue \83\8c\83R\81[\83h\92l
+ \return \83\8c\83R\81[\83h\92l\82É\88ê\92v\82µ\82½\83\8c\83R\81[\83h
+ \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
+ }
+ function GetRecordByInteger( primalyValue : Integer ) : TRecord;
+
+ {!
+ \brief \83\8c\83R\81[\83h\82ð\8eæ\93¾
+ \param primalyValue \83\8c\83R\81[\83h\96¼
+ \return \83\8c\83R\81[\83h\96¼\82É\88ê\92v\82µ\82½\83\8c\83R\81[\83h
+ \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
+ }
+ function GetRecordByString( const primalyValue : string ) : TRecord;
+
+ {!
+ \brief \83Z\83N\83^\82Ì\83|\83C\83\93\83^\82ð\8eæ\93¾
+ \param sectorNo \83Z\83N\83^\94Ô\8d\86
+ \return \83Z\83N\83^\82Ì\88Ê\92u\82ð\8ew\82·\83|\83C\83\93\83^
+ \todo \8dì\90¬\92\86
+ }
+ function GetSector( sectorNo : Integer ) : Pointer;
+
+ public
+ {!
+ \brief \83f\81[\83^\83x\81[\83X\82Ì\83I\81[\83v\83\93
+ \param filePath \8aJ\82\83t\83@\83C\83\8b\82Ì\83p\83X
+ \param mode fmOpenRead (\83f\83t\83H\83\8b\83g) \82Ü\82½\82Í fmOpenReadWrite
+ \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
+ \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
+ \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
+ \todo MapViewOfFile \82Å 64bit \8bó\8aÔ\82ð\83A\83N\83Z\83X\82Å\82«\82é\82æ\82¤\82É\8ag\92£\82·\82é\81B
+
+ filePath \82ª\91¶\8dÝ\82¹\82¸\81Amode \82É fmOpenReadWrite \82ª\8ew\92è\82³\82ê\82½\8fê\8d\87\82Í
+ \90V\8bK\82É\83f\81[\83^\83x\81[\83X\82ª\8dì\90¬\82³\82ê\82Ü\82·\81B
+ }
+ constructor Create(
+ const filePath : string;
+ mode : Longword = fmOpenRead );
+ destructor Destroy; override;
+
+ {!
+ \brief \93à\97e\82ð\83e\83L\83X\83g\83t\83@\83C\83\8b\82É\83_\83\93\83v
+ \param filePath \95Û\91¶\82·\82é\83t\83@\83C\83\8b\82Ì\83p\83X
+ \todo \8dì\90¬\92\86
+ }
+ procedure Dump(
+ const filePath : string );
+
+ {!
+ \brief \83\8c\83R\81[\83h\82ð\8eæ\93¾
+ \param primalyValue \83\8c\83R\81[\83h\92l
+ \return \83\8c\83R\81[\83h\92l\82É\88ê\92v\82µ\82½\83\8c\83R\81[\83h
+ \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
+ }
+ property RecordByInteger[ primalyValue : Integer ] : TRecord
+ read GetRecordByInteger;
+
+ {!
+ \brief \83\8c\83R\81[\83h\82ð\8eæ\93¾
+ \param primalyValue \83\8c\83R\81[\83h\96¼
+ \return \83\8c\83R\81[\83h\96¼\82É\88ê\92v\82µ\82½\83\8c\83R\81[\83h
+ \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
+ }
+ property RecordByString[ const primalyValue : string ] : TRecord
+ read GetRecordByString;
+ end;
+
+//==================================================
+implementation
+//==================================================
+
+uses
+ Math;
+
+const
+ MINIMUM_PAGE_SIZE = $10000; //!< \8dÅ\8f¬\82Ì\83y\81[\83W\83T\83C\83Y ( 64KB )
+ SECTOR_SIZE = $40; //!< \83Z\83N\83^\83T\83C\83Y ( 64Byte )
+ SIGNATURE_LITTLE_ENDIAN
+ = $676b6462; //!< 'bdkg' \83f\81[\83^\83x\81[\83X\83V\83O\83l\83`\83\83
+ DATABASE_VERSION = $01000000; //!< \83o\81[\83W\83\87\83\93\83i\83\93\83o\81[ ( 0.0d1 )
+
+ NULL_SECTION = $00000000; //!< \96¢\8eg\97p\83Z\83N\83V\83\87\83\93
+ INFOMATION_SECTION = $6f666e69; //!< 'info' \83C\83\93\83t\83H\83\81\81[\83V\83\87\83\93\83Z\83N\83V\83\87\83\93
+ COLUMN_LIST_SECTION = $736c6f63; //!< 'cols' \83J\83\89\83\80\83\8a\83X\83g\83Z\83N\83V\83\87\83\93
+ ALLOCATION_TABLE_SECTION
+ = $626c7461; //!< 'atlb' \83A\83\8d\83P\81[\83V\83\87\83\93\83e\81[\83u\83\8b\83Z\83N\83V\83\87\83\93
+ INDEX_SECTION = $78656469; //!< 'idex' \83C\83\93\83f\83b\83N\83X\83Z\83N\83V\83\87\83\93
+ SECTOR_SECTION = $74636573; //!< 'sect' \83Z\83N\83^\83Z\83N\83V\83\87\83\93
+ NULL_SECTOR_NO = $ffffffff; //!< \8fI\92[\82ð\95\\82·\83Z\83N\83^\94Ô\8d\86
+
+ TYPE_BOOL = $6c6f6f62; //!< 'bool' \98_\97\9d\92l
+ TYPE_INT8 = $31306973; //!< 'si01' signed int 1 byte
+ TYPE_INT16 = $32306973; //!< 'si02'
+ TYPE_INT32 = $34306973; //!< 'si04'
+ TYPE_INT64 = $38306973; //!< 'si08'
+ TYPE_UINT8 = $31306975; //!< 'ui01' unsigned int 1 byte
+ TYPE_UINT16 = $32306975; //!< 'ui02'
+ TYPE_UINT32 = $34306975; //!< 'ui04'
+ TYPE_UINT64 = $38306975; //!< 'ui08'
+ TYPE_FLOAT32 = $34306c66; //!< 'fp04' floating point 4 byte
+ TYPE_FLOAT64 = $38306c66; //!< 'fp08'
+ TYPE_PSTR = $72747370; //!< 'pstr' pascal string
+ TYPE_DATA = $61746164; //!< 'data' data (long string)
+
+ COLUMN_DELETED = '_.-*+/DELETED+*./_-'; //!< \8dí\8f\9c\82³\82ê\82½\83J\83\89\83\80\96¼
+
+
+
+//************************************************************
+// misc
+//************************************************************
+
+//==============================
+// SortSectionsByPtr
+//==============================
+function SortSectionsByPtr( Item1, Item2 : Pointer ) : Integer;
+begin
+
+ Result := PChar( TSection( Item1 ).Memory ) -
+ PChar( TSection( Item2 ).Memory );
+
+end;
+
+//==============================
+// SortSectorSections
+//==============================
+function SortSectorSections( Item1, Item2 : Pointer ) : Integer;
+begin
+
+ Result := PChar( TSector( Item1 ).FSectionNo ) -
+ PChar( TSector( Item2 ).FSectionNo );
+
+end;
+
+
+
+//************************************************************
+// TSection class
+//************************************************************
+
+//==============================
+// Create
+//==============================
+constructor TSection.Create( parent : TGikoDB; const address : Pointer );
+begin
+
+ FParent := parent;
+ FMemory := address;
+
+end;
+
+//==============================
+// GetSize
+//==============================
+function TSection.GetSize : Longword;
+begin
+
+ Result := PDword( FMemory )^;
+
+end;
+
+//==============================
+// SetSize
+//==============================
+procedure TSection.SetSize( newSize : Longword );
+begin
+
+ PDword( FMemory )^ := newSize;
+
+end;
+
+//==============================
+// GetType
+//==============================
+function TSection.GetType : Longword;
+begin
+
+ Result := PDword( PChar( FMemory ) + 4 )^;
+
+end;
+
+//==============================
+// SetType
+//==============================
+procedure TSection.SetType( newType : Longword );
+begin
+
+ PDword( PChar( FMemory ) + 4 )^ := newType;
+
+end;
+
+//==============================
+// GetNext
+//==============================
+function TSection.GetNext : Pointer;
+begin
+
+ Result := PChar( FMemory ) + Size;
+
+end;
+
+//==============================
+// GetContents
+//==============================
+function TSection.GetContents : Pointer;
+begin
+
+ Result := PChar( FMemory ) + 8;
+
+end;
+
+
+
+//************************************************************
+// TSector class
+//************************************************************
+
+//==============================
+// Create
+//==============================
+constructor TSector.Create( parent : TGikoDB; const address : Pointer );
+begin
+
+ inherited;
+ FSectionNo := PDWord( PChar( Memory ) + 8 )^;
+ FCount := Size - Longword( 12 ) div SECTOR_SIZE;
+
+end;
+
+//==============================
+// GetContents
+//==============================
+function TSector.GetContents : Pointer;
+begin
+
+ Result := PChar( FMemory ) + 12;
+
+end;
+
+//==============================
+// GetSector
+//==============================
+function TSector.GetSector( index : Integer ) : Pointer;
+begin
+
+ Assert( (index > 0) and (index <= FCount) );
+ // 8 = sizeof(section size) + sizeof(section type) + sizeof(section no) -
+ // 1 base * sizeof(Longword)
+ Result := PChar( GetContents ) + Longword( index ) * SECTOR_SIZE;
+
+end;
+
+
+
+//************************************************************
+// TSortIndex class
+//************************************************************
+
+//==============================
+// Create
+//==============================
+constructor TSortIndex.Create( parent : TGikoDB; const address : Pointer );
+begin
+
+ inherited;
+ FColumnIndex := PWORD( PChar( Memory ) + 4 )^;
+ FColumnProperty := PWORD( PChar( Memory ) + 6 )^;
+
+end;
+
+//==============================
+// GetContents
+//==============================
+function TSortIndex.GetContents : Pointer;
+begin
+
+ Result := PChar( FMemory ) + 12;
+
+end;
+
+//==============================
+// GetCount
+//==============================
+function TSortIndex.GetCount : Integer;
+begin
+
+ Result := FParent.FInfomation.RecordCount;
+
+end;
+
+//==============================
+// GetItem
+//==============================
+function TSortIndex.GetItem( index : Integer ) : PSortIndex;
+begin
+
+ Result := PSortIndex( PChar( GetContents ) + index * SizeOf( RSortIndex ) );
+
+end;
+
+
+
+//************************************************************
+// TAllocationTable class
+//************************************************************
+
+//==============================
+// Create
+//==============================
+constructor TAllocationTable.Create( parent : TGikoDB; const address : Pointer );
+begin
+
+ inherited;
+
+end;
+
+function TAllocationTable.GetTable( index : Integer ) : Longword;
+begin
+
+ Result := PDword( PChar( GetContents ) + index * SizeOf( DWORD ) )^
+
+end;
+
+
+
+//************************************************************
+// TColumn class
+//************************************************************
+
+//==============================
+// Create
+//==============================
+constructor TColumn.Create( colIndex : Word; colType : Longword );
+begin
+
+ FIndex := colIndex;
+ FType := colType;
+
+end;
+
+
+
+//************************************************************
+// TColumnList class
+//************************************************************
+
+//==============================
+// Create
+//==============================
+constructor TColumnList.Create( parent : TGikoDB; const address : Pointer );
+var
+ i, j : Word;
+ p, p2, tail : PChar;
+ l : Integer;
+ columnCount : Longword;
+ col : TColumn;
+ colType : Longword;
+ colName : string;
+begin
+
+ inherited;
+ FList := THashedStringList.Create;
+ FList.Sorted := True;
+ FList.Duplicates := dupError;
+ columnCount := GetColumnCount;
+ p := PChar( GetContents );
+ tail := Next;
+
+ j := Random( MaxInt );
+ for i := 0 to columnCount - 1 do begin
+ p2 := p; // Break \8e\9e\82É FColumnEnd \82É\89e\8b¿\82³\82¹\82È\82¢\82½\82ß
+
+ if p2 >= tail then Break;
+ l := PByte( p2 )^; Inc( p2 );
+ if p2 + l + SizeOf( Dword ) >= tail then Break;
+ colName := Copy( p2, 0, l ); p2 := p2 + l;
+ colType := PDword( p2 )^; p2 := p2 + SizeOf( colType );
+
+ p := p2;
+
+ if l = 0 then begin
+ // \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é
+ while true do begin
+ Inc( j );
+ colName := COLUMN_DELETED + IntToStr( j );
+ if FList.IndexOf( colName ) < 0 then
+ Break;
+ end;
+ end;
+ col := TColumn.Create( i, colType );
+ FList.AddObject( colName, col );
+ end;
+
+ FColumnEnd := p;
+
+end;
+
+//==============================
+// Destroy
+//==============================
+destructor TColumnList.Destroy;
+var
+ i : Integer;
+begin
+
+ for i := FList.Count - 1 downto 0 do
+ FList.Objects[ i ].Free;
+ FList.Free;
+
+end;
+
+//==============================
+// GetContents
+//==============================
+function TColumnList.GetContents : Pointer;
+begin
+
+ Result := PChar( FMemory ) + 12;
+
+end;
+
+//==============================
+// GetColumnCount
+//==============================
+function TColumnList.GetColumnCount : Longword;
+begin
+
+ Result := PDword( PChar( Memory ) + 8 )^;
+
+end;
+
+//==============================
+// SetColumnCount
+//==============================
+procedure TColumnList.SetColumnCount( n : Longword );
+begin
+
+ PDword( PChar( Memory ) + 8 )^ := n;
+
+end;
+
+//==============================
+// GetItemFromIndex
+//==============================
+function TColumnList.GetItemFromIndex( index : Integer ) : TColumn;
+begin
+
+ Result := TColumn( FList.Objects[ index ] );
+
+end;
+
+//==============================
+// GetItemFromColumnIndex
+//==============================
+function TColumnList.GetItemFromColumnIndex( index : Integer ) : TColumn;
+var
+ i : Integer;
+ col : TColumn;
+begin
+
+ Result := nil;
+ for i := 0 to FList.Count - 1 do begin
+ col := Objects[ i ];
+ if col.ColumnIndex = index then begin
+ Result := col;
+ Break;
+ end;
+ end;
+
+end;
+
+//==============================
+// GetItemFromName
+//==============================
+function TColumnList.GetItemFromName( const columnName : string ) : TColumn;
+var
+ i : Integer;
+begin
+
+ i := FList.IndexOf( columnName );
+ if i >= 0 then
+ Result := Objects[ i ]
+ else
+ Result := nil;
+
+end;
+
+//==============================
+// Delete
+//==============================
+procedure TColumnList.Delete( const columnName : string );
+var
+ i, j : Integer;
+ s : string;
+begin
+
+ i := FList.IndexOf( columnName );
+ if i >= 0 then begin
+ j := Random( MaxInt );
+ while true do begin
+ Inc( j );
+ s := COLUMN_DELETED + IntToStr( j );
+ if FList.IndexOf( s ) < 0 then begin
+ FList[ i ] := s;
+ Break;
+ end;
+ end;
+
+ WriteBack;
+ end;
+
+end;
+
+//==============================
+// Add
+//==============================
+procedure TColumnList.Add( const columnName : string; columnType : Longword );
+var
+ i, l : Integer;
+ col : TColumn;
+ p : PChar;
+begin
+
+ i := FList.IndexOf( columnName );
+ if i >= 0 then begin
+ col := TColumn.Create( FList.Count, columnType );
+ FList.AddObject( columnName, col );
+ p := FColumnEnd;
+ l := Length( columnName );
+ Assert( l <= 255 );
+ if 255 < l then
+ Exit;
+ if p + l + 5 <= Next then begin
+ // \83Z\83N\83V\83\87\83\93\82É\8bó\82«\82ª\82 \82é\82Ì\82Å\92Ç\8bL\82·\82é
+ PByte( p )^ := l; Inc( p );
+ Move( PChar( columnName )^, p^, l ); p := p + l;
+ PDword( p )^ := columnType; p := p + SizeOf( columnType );
+
+ FColumnEnd := p;
+ SetColumnCount( FList.Count );
+ end else begin
+ // \83Z\83N\83V\83\87\83\93\82É\93ü\82è\82«\82ç\82È\82¢\82Ì\82Å WriteBack \82É\94C\82¹\82é
+ WriteBack;
+ end;
+ end;
+
+end;
+
+//==============================
+// WriteBack
+//==============================
+procedure TColumnList.WriteBack;
+var
+ p, tail : PChar;
+ i, j : Integer;
+ idx, l : Integer;
+ col : TColumn;
+begin
+
+ // \95K\97v\82È\83Z\83N\83V\83\87\83\93\83T\83C\83Y\82ð\8cv\8eZ\82·\82é
+ p := PChar( GetContents );
+ for i := 0 to FList.Count - 1 do begin
+ p := p + 5;
+ if AnsiPos( COLUMN_DELETED, FList[ i ] ) <> 1 then
+ p := p + Length( FList[ i ] );
+ end;
+
+ if p > Next then
+ // \83Z\83N\83V\83\87\83\93\83T\83C\83Y\82ª\91«\82ç\82È\82¢\82Ì\82Å\8ag\92£
+ FParent.ReallocateSection( Self, p - Memory );
+
+ p := PChar( GetContents );
+ for i := 0 to FList.Count - 1 do begin
+ // FList \82Í\83J\83\89\83\80\96¼\82Å\83\\81[\83g\82³\82ê\82Ä\82¢\82é\82Ì\82Å
+ // ColumnIndex \82Å\95À\82×\82é\82É\82Í\8c\9f\8dõ\82µ\82È\82\82Ä\82Í\82È\82ç\82È\82¢
+ idx := -1;
+ col := nil;
+ for j := 0 to FList.Count - 1 do begin
+ col := TColumn( FList.Objects[ j ] );
+ if col.ColumnIndex = i then begin
+ idx := j;
+ Break;
+ end;
+ end;
+ Assert( idx <> -1 );
+
+ if AnsiPos( COLUMN_DELETED, FList[ idx ] ) = 1 then
+ l := 0
+ else
+ l := Length( FList[ idx ] );
+ PByte( p )^ := l; Inc( p );
+ Move( PChar( FList[ idx ] )^, p^, l ); p := p + l;
+ PDWord( p )^ := col.ColumnType; p := p + SizeOf( DWORD );
+ Assert( p <= Next );
+ end;
+
+ FColumnEnd := p;
+ SetColumnCount( FList.Count );
+
+ FParent.Changed;
+
+end;
+
+
+
+//************************************************************
+// TInfomation class
+//************************************************************
+
+//==============================
+// Create
+//==============================
+constructor TInfomation.Create( parent : TGikoDB; const address : Pointer );
+begin
+
+ inherited;
+
+end;
+
+//==============================
+// GetSectorSize
+//==============================
+function TInfomation.GetSectorSize : Longword;
+begin
+
+ Result := PDword( PChar( GetContents ) )^;
+
+end;
+
+//==============================
+// GetRecordCount
+//==============================
+function TInfomation.GetRecordCount : Longword;
+begin
+
+ Result := PDword( PChar( GetContents ) + 4 )^;
+end;
+
+
+
+//************************************************************
+// TRecord class
+//************************************************************
+
+//==============================
+// Create
+//==============================
+constructor TRecord.Create( parent : TGikoDB; sectorNo : Longword );
+begin
+
+ inherited Create;
+ FParent := parent;
+ FSectorNo := sectorNo;
+
+end;
+
+//==============================
+// GetStringByName
+//==============================
+function TRecord.GetStringByName( const columnName : string ) : string;
+begin
+ //!!!!! \8dì\90¬\92\86 !!!!!
+end;
+
+//==============================
+// SetStringByName
+//==============================
+procedure TRecord.SetStringByName(
+ const columnName : string;
+ const value : string );
+begin
+ //!!!!! \8dì\90¬\92\86 !!!!!
+end;
+
+//==============================
+// GetStringByIndex
+//==============================
+function TRecord.GetStringByIndex( index : Longword ) : string;
+begin
+ //!!!!! \8dì\90¬\92\86 !!!!!
+end;
+
+//==============================
+// GetIntegerByName
+//==============================
+function TRecord.GetIntegerByName( const columnName : string ) : Integer;
+begin
+ //!!!!! \8dì\90¬\92\86 !!!!!
+end;
+
+//==============================
+// SetIntegerByName
+//==============================
+procedure TRecord.SetIntegerByName(
+ const columnName : string;
+ const value : Integer );
+var
+ col, c : TColumn;
+ sectorNo : Integer;
+ offset : Longword;
+ i : Integer;
+begin
+
+ col := FParent.FColumnList[ columnName ];
+ if col = nil then
+ Exit;
+ sectorNo := FSectorNo;
+ offset := 0;
+
+ for i := 0 to col.ColumnIndex - 1 do begin
+ c := FParent.FColumnList.GetItemFromColumnIndex( i );
+ case c.ColumnType of
+ TYPE_BOOL, TYPE_INT8, TYPE_UINT8: Inc( offset );
+ TYPE_INT16, TYPE_UINT16: offset := offset + 2;
+ TYPE_INT32, TYPE_UINT32, TYPE_FLOAT32: offset := offset + 4;
+ TYPE_INT64, TYPE_UINT64, TYPE_FLOAT64: offset := offset + 8;
+
+ TYPE_PSTR:
+ begin
+ //!!!!! \8dì\90¬\92\86 !!!!!
+ offset := PByte( PChar( FParent.GetSector( sectorNo ) ) + offset )^;
+ while offset >= FParent.FSectorSize do begin
+ sectorNo := FParent.FAllocationTable[ sectorNo ];
+ if sectorNo = NULL_SECTOR_NO then
+ Exit;
+ offset := offset - FParent.FSectorSize;
+ end;
+ end;
+
+ TYPE_DATA:
+ begin
+ //!!!!! \8dì\90¬\92\86 !!!!!
+ end;
+ end;
+ end;
+
+ //!!!!! \8dì\90¬\92\86 !!!!!
+
+end;
+
+//==============================
+// GetIntegerByIndex
+//==============================
+function TRecord.GetIntegerByIndex( index : Longword ) : Integer;
+begin
+ //!!!!! \8dì\90¬\92\86 !!!!!
+end;
+
+
+
+//************************************************************
+// TGikoDB class
+//************************************************************
+
+//==============================
+// Create
+//==============================
+constructor TGikoDB.Create(
+ const filePath : string;
+ mode : Longword = fmOpenRead );
+var
+ info : _SYSTEM_INFO;
+ maximumSize : Integer;
+begin
+
+ Randomize;
+ FFilePath := ExpandUNCFileName( filePath );
+ FChanged := False;
+
+ GetSystemInfo( info );
+ FPageSize := Max( info.dwPageSize, MINIMUM_PAGE_SIZE );
+ if FileExists( filePath ) then begin
+ maximumSize := 0;
+ FFile := TMappedFile.Create( FFilePath, mode, maximumSize );
+ ReadSections;
+ end else begin
+ maximumSize := FPageSize;
+ FFile := TMappedFile.Create( FFilePath, mode, maximumSize );
+ CreateInitialSections;
+ ReadSections;
+ end;
+
+end;
+
+//==============================
+// Destroy
+//==============================
+destructor TGikoDB.Destroy;
+var
+ i : Integer;
+begin
+
+ FFile.Free;
+ for i := FSections.Count - 1 downto 0 do
+ TObject( FSections[ i ] ).Free;
+ FSections.Free;
+
+end;
+
+//==============================
+// CreateInitialSections
+//==============================
+procedure TGikoDB.CreateInitialSections;
+var
+ i : Integer;
+ p, p2 : PChar;
+ emptySize : Longword;
+ sectionCount : Longword;
+begin
+
+ FSections := TList.Create;
+ p := PChar( FFile.Memory );
+
+ //===== \83w\83b\83_
+ // \83V\83O\83l\83`\83\83
+ PDword( p )^ := SIGNATURE_LITTLE_ENDIAN; p := p + SizeOf( DWORD );
+ // \83o\81[\83W\83\87\83\93
+ PDword( p )^ := DATABASE_VERSION; p := p + SizeOf( DWORD );
+
+ //===== \83C\83\93\83t\83H\83\81\81[\83V\83\87\83\93\83Z\83N\83V\83\87\83\93
+ p2 := p;
+ // \83Z\83N\83V\83\87\83\93\83T\83C\83Y
+ PDword( p2 )^ := 16; p2 := p2 + SizeOf( DWORD );
+ // \83Z\83N\83V\83\87\83\93\83^\83C\83v
+ PDword( p2 )^ := INFOMATION_SECTION; p2 := p2 + SizeOf( DWORD );
+ // \83Z\83N\83^\83T\83C\83Y
+ PDword( p2 )^ := SECTOR_SIZE; p2 := p2 + SizeOf( DWORD );
+ // \83\8c\83R\81[\83h\90\94
+ PDword( p2 )^ := 0; p2 := p2 + SizeOf( DWORD );
+ p := p + PDword( p )^;
+
+ //===== \83J\83\89\83\80\83\8a\83X\83g\83Z\83N\83V\83\87\83\93
+ // 1 \83Z\83N\83^\82É SECTOR_SIZE / SizeOf( DWORD ) \8cÂ\82Ì\83J\83\89\83\80\82ª\93ü\82é\82Æ\8dl\82¦\81A
+ // 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è
+ p2 := p;
+ // \83Z\83N\83V\83\87\83\93\83T\83C\83Y
+ PDword( p2 )^ := 8 + (SECTOR_SIZE div SizeOf( DWORD )) * 16;
+ p2 := p2 + SizeOf( DWORD );
+ // \83Z\83N\83V\83\87\83\93\83^\83C\83v
+ PDword( p2 )^ := COLUMN_LIST_SECTION; p2 := p2 + SizeOf( DWORD );
+ // \83J\83\89\83\80\90\94
+ PDword( p2 )^ := 0; p2 := p2 + SizeOf( DWORD );
+ p := p + PDword( p )^;
+
+ //===== \83A\83\8d\83P\81[\83V\83\87\83\93\83e\81[\83u\83\8b\83Z\83N\83V\83\87\83\93
+ // - 8 = allocation table section
+ // -12 = index section + column no + property
+ // -12 = sector section + section no
+ p2 := p;
+ emptySize := p2 - PChar( FFile.Memory ) - 8 - 12 - 12;
+ // emptySize = sectionCount *
+ // (SECTOR_SIZE + allocation table + table no + value)
+ // sectionCount = emptySize / (SECTOR_SIZE + 12)
+ sectionCount := emptySize div (SECTOR_SIZE + 12);
+ // \83Z\83N\83V\83\87\83\93\83T\83C\83Y
+ PDword( p2 )^ := 8 + sectionCount * SizeOf( DWORD );
+ p2 := p2 + SizeOf( DWORD );
+ // \83Z\83N\83V\83\87\83\93\83^\83C\83v
+ PDword( p2 )^ := ALLOCATION_TABLE_SECTION;
+ p2 := p2 + SizeOf( DWORD );
+ // \83e\81[\83u\83\8b
+ for i := 1 to sectionCount do begin
+ PDword( p2 )^ := 0; p2 := p2 + SizeOf( DWORD );
+ end;
+ p := p + PDword( p )^;
+
+ //===== \83C\83\93\83f\83b\83N\83X\83Z\83N\83V\83\87\83\93
+ p2 := p;
+ // \83Z\83N\83V\83\87\83\93\83T\83C\83Y
+ PDword( p2 )^ := 12 + sectionCount * SizeOf( DWORD ) * 2;
+ p2 := p2 + SizeOf( DWORD );
+ // \83Z\83N\83V\83\87\83\93\83^\83C\83v
+ PDword( p2 )^ := INDEX_SECTION; p2 := p2 + SizeOf( DWORD );
+ // \83J\83\89\83\80\94Ô\8d\86 ( 2 byte ) + \83v\83\8d\83p\83e\83B ( 2 byte )
+ PDword( p2 )^ := 0; p2 := p2 + SizeOf( DWORD );
+ // \83e\81[\83u\83\8b\94Ô\8d\86 + \92l
+ for i := 1 to sectionCount * 2 do begin
+ PDword( p2 )^ := 0; p2 := p2 + SizeOf( DWORD );
+ end;
+ p := p + PDword( p )^;
+
+ //===== \83Z\83N\83^\83Z\83N\83V\83\87\83\93
+ p2 := p;
+ // \83Z\83N\83V\83\87\83\93\83T\83C\83Y
+ PDword( p2 )^ := 8 + sectionCount * SECTOR_SIZE;
+ p2 := p2 + SizeOf( DWORD );
+ // \83Z\83N\83V\83\87\83\93\83^\83C\83v
+ PDword( p2 )^ := SECTOR_SECTION; p2 := p2 + SizeOf( DWORD );
+ // \83Z\83N\83V\83\87\83\93\94Ô\8d\86
+ PDword( p2 )^ := 0; p2 := p2 + SizeOf( DWORD );
+ p := p + PDword( p )^;
+
+ if p + 8 <= PChar( FFile.Memory ) + FFile.Size then begin
+ // \8fI\92[\8bL\8d\86
+ PDWord( p )^ := 0;
+ PDWord( p + 4 )^ := NULL_SECTION;
+ end;
+
+end;
+
+//==============================
+// ReadSections
+//==============================
+procedure TGikoDB.ReadSections;
+var
+ p : PChar;
+ dbVersion : Longword;
+begin
+
+ FSections := TList.Create;
+ p := FFile.Memory;
+ // \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Ý)
+ if PDword( p )^ <> SIGNATURE_LITTLE_ENDIAN then
+ raise EGikoDBUnssuportedFormatError.Create(
+ '\83f\81[\83^\83x\81[\83X\82Ì\83t\83H\81[\83}\83b\83g\82ª\95s\96¾\82Å\82·\81B' );
+ p := p + SizeOf( DWORD );
+
+ dbVersion := PDword( p )^; p := p + SizeOf( DWORD );
+ case dbVersion of
+ DATABASE_VERSION:
+ ReadSection0_0d1( p );
+ else
+ raise EGikoDBUnssuportedFormatError.Create(
+ '\83T\83|\81[\83g\82³\82ê\82Ä\82¢\82È\82¢\83t\83H\81[\83}\83b\83g\82Å\82·\81B' );
+ end;
+
+end;
+
+//==============================
+// ReadSection0_0d1
+//==============================
+procedure TGikoDB.ReadSection0_0d1( const address : PChar );
+var
+ p, tail : PChar;
+ sectionSize : Longword;
+ sectionType : Longword;
+ section : TSection;
+begin
+
+ p := address;
+ tail := PChar( FFile.Memory ) + FFile.Size - 8;
+ while p < tail do begin
+ sectionSize := PDword( p )^;
+ sectionType := PDword( p + 4 )^;
+ if sectionSize = 0 then
+ Break;
+
+ case sectionType of
+ NULL_SECTION:
+ FSections.Add( TSection.Create( Self, p ) );
+
+ INFOMATION_SECTION:
+ begin
+ FInfomation := TInfomation.Create( Self, p );
+ FSections.Add( FInfomation );
+ end;
+
+ COLUMN_LIST_SECTION:
+ begin
+ FColumnList := TColumnList.Create( Self, p );
+ FSections.Add( FColumnList );
+ end;
+
+ ALLOCATION_TABLE_SECTION:
+ begin
+ FAllocationTable := TAllocationTable.Create( Self, p );
+ FSections.Add( FAllocationTable );
+ end;
+
+ INDEX_SECTION:
+ begin
+ section := TSortIndex.Create( Self, p );
+ FIndexes.Add( section );
+ FSections.Add( section );
+ end;
+
+ SECTOR_SECTION:
+ begin
+ section := TSector.Create( Self, p );
+ FSectors.Add( section );
+ FSections.Add( section );
+ end;
+
+ else
+ FSections.Add( TSection.Create( Self, p ) )
+ end;
+ p := p + sectionSize;
+ end;
+
+end;
+
+//==============================
+// CreateSection
+//==============================
+function TGikoDB.CreateSection(
+ sectionSize : Longword;
+ sectionType : Longword
+) : Pointer;
+var
+ i, j : Integer;
+ section : TSection;
+ emptySection : TSection;
+ emptySize : Longword;
+ emptyIndex : Integer;
+ fileSize : Longword;
+ oldBegin : PChar;
+ p : PChar;
+begin
+
+ // \82Ü\82¸\82Í\8bó\82«\83Z\83N\83V\83\87\83\93\82ð\92T\82·
+ emptySection := nil;
+ section := nil;
+ emptyIndex := 0;
+ // \98A\91±\82µ\82½\8bó\82«\97Ì\88æ\82ª FSection \82Ì\93Y\82¦\8e\9a\82Å\82à
+ // \98A\91±\82µ\82Ä\82¢\82È\82¯\82ê\82Î\82È\82ç\82È\82¢\82Ì\82Å\83\\81[\83g
+ FSections.Sort( SortSectionsByPtr );
+
+ for i := 0 to FSections.Count - 1 do begin
+ section := TSection( FSections[ i ] );
+ if (section.SectionType = NULL_SECTION) then begin
+ // emptySection \82Í\98A\91±\82µ\82½\8bó\82«\97Ì\88æ\82Ì\90æ\93ª\82ð\8ew\82·
+ if emptySection = nil then begin
+ emptySection := section;
+ emptyIndex := i;
+ end;
+
+ emptySize := PChar( section.Memory ) + section.Size -
+ PChar( emptySection.Memory );
+ if sectionSize <= emptySize then begin
+ // \8bó\82«\83Z\83N\83V\83\87\83\93\94\8c©
+ Result := emptySection.Memory;
+ PDword( Result )^ := emptySize;
+ PDword( PChar( Result ) + 4 )^ := sectionType;
+ // \8bó\82«\83Z\83N\83V\83\87\83\93\82Ì\8dí\8f\9c
+ for j := i downto emptyIndex do begin
+ TSection( FSections[ j ] ).Free;
+ FSections.Delete( j );
+ end;
+ 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\
+ end;
+ end else begin
+ emptySection := nil;
+ end;
+ end;
+
+ // \83t\83@\83C\83\8b\82Ì\96\96\94ö\82É\82É\8bó\82«\97Ì\88æ\82ª\82 \82é\82©
+ oldBegin := FFile.Memory;
+ if PChar( section.Next ) + sectionSize <= oldBegin + FFile.Size then begin
+ // \8bó\82«\97Ì\88æ\94\8c©
+ Result := section.Next;
+ PDword( Result )^ := sectionSize;
+ PDword( PChar( Result ) + 4 )^ := sectionType;
+ Exit;
+ end;
+
+ // sectionSize \82ð\96\9e\82½\82·\97Ì\88æ\82ª\82È\82¢\82Ì\82Å\83t\83@\83C\83\8b\82ð\8ag\92£
+ FChanged := True;
+
+ // \8ag\92£\82·\82é\83T\83C\83Y\82Ì\8cv\8eZ
+ fileSize := (sectionSize div FPageSize + 1) * FPageSize;
+
+ // \8ag\92£\82µ\82Ä\83t\83@\83C\83\8b\82ð\8aJ\82«\82È\82¨\82µ
+ FFile.Free;
+ FFile := TMappedFile.Create( FFilePath, fmOpenReadWrite, fileSize );
+
+ // \96\96\94ö\82É\92Ç\89Á
+ Result := PChar( FFile.Memory ) + (PChar( section.Next ) - oldBegin);
+ PDword( Result )^ := sectionSize;
+ PDword( PChar( Result ) + 4 )^ := sectionType;
+
+ p := PChar( Result ) + sectionSize;
+ if p + 8 <= PChar( FFile.Memory ) + FFile.Size then begin
+ // \8fI\92[\8bL\8d\86
+ PDword( p )^ := 0; p := p + SizeOf( DWORD );
+ PDword( p )^ := NULL_SECTION;
+ end;
+
+end;
+
+//==============================
+// ReallocateSection
+//==============================
+procedure TGikoDB.ReallocateSection(
+ section : TSection;
+ sectionSize : Longword );
+var
+ nextSection : PChar;
+ fileEnd : PChar;
+ p : PChar;
+ size : Longword;
+ sectionType : Longword;
+begin
+
+ FChanged := True;
+ fileEnd := PChar( FFile.Memory ) + FFile.Size;
+
+ if sectionSize <= section.Size then begin
+
+ // \8fk\8f¬
+ nextSection := PChar( section.Next );
+ section.SetSize( sectionSize );
+ if 8 >= fileEnd - PChar( nextSection ) then
+ // \82±\82±\82ª\8dÅ\8cã\82Ì\83Z\83N\83V\83\87\83\93
+ nextSection := fileEnd;
+
+ if 16 >= nextSection - PChar( section.Next ) then begin
+ // \8cã\91±\82·\82é\8bó\82«\82ª\8f¬\82³\82¢\82Ì\82Å section \82É\98A\8c\8b\82·\82é
+ section.SetSize( nextSection - PChar( section.Memory ) );
+ end else begin
+ // \8cã\91±\82·\82é\8bó\82«\82ª\91å\82«\82¢\82Ì\82Å\8bó\83Z\83N\83V\83\87\83\93\82É\82·\82é
+ p := section.Next;
+ if PDword( nextSection )^ = 0 then
+ // \8bó\82«\83Z\83N\83V\83\87\83\93\82Í\8dÅ\8fI\83Z\83N\83V\83\87\83\93
+ PDword( p )^ := 0
+ else
+ // \92f\95Ð\89»\82µ\82½\8bó\82«\83Z\83N\83V\83\87\83\93
+ PDword( p )^ := nextSection - p;
+ PDword( p + 4 )^ := NULL_SECTION;
+ end;
+
+ end else begin
+
+ // \8ag\92£
+ size := section.Size;
+ p := PChar( section.Next );
+
+ // section \82Ì\82·\82®\8cã\82É\98A\91±\82µ\82½\8bó\82«\82ð\92T\82·
+ while (8 < fileEnd - p) and (size < sectionSize) do begin
+ if PDword( p )^ = 0 then begin
+ size := size + Longword( fileEnd - p );
+ Break;
+ end else if PDword( p + 4 )^ = 0 then begin
+ size := size + PDword( p )^;
+ p := p + PDword( p )^;
+ end else begin
+ Break;
+ end;
+ end;
+
+ if size >= sectionSize then begin
+ // \98A\91±\82µ\82½\8bó\82«\83Z\83N\83V\83\87\83\93\82Å\98d\82¦\82é
+ section.SetSize( size );
+ end else begin
+ // \98A\91±\82µ\82½\8bó\82«\83Z\83N\83V\83\87\83\93\82Å\98d\82¦\82È\82¢\82Ì\82Å\90V\8bK\8dì\90¬
+ size := section.Size;
+ sectionType := section.SectionType;
+ section.SetType( NULL_SECTION );
+
+ p := CreateSection( sectionSize, sectionType );
+ Move( PChar( section.FMemory )^, p^, size );
+
+ section.FMemory := p;
+ end;
+
+ end;
+
+end;
+
+//==============================
+// Dump
+//==============================
+procedure TGikoDB.Dump(
+ const filePath : string );
+begin
+ //!!!!! \8dì\90¬\92\86 !!!!!
+end;
+
+//==============================
+// Changed
+//==============================
+procedure TGikoDB.Changed( force : Boolean = False );
+var
+ i : Integer;
+begin
+
+ if FChanged or force then begin
+ // FSections \82Ì\8aJ\95ú
+ for i := FSections.Count - 1 downto 0 do
+ TObject( FSections[ i ] ).Free;
+ FSections.Free;
+
+ // FSections \82ð\8dÄ\8d\\92z
+ ReadSections;
+ end;
+
+end;
+
+//==============================
+// SelectValue
+//==============================
+function TGikoDB.SelectValue(
+ founds : TList;
+ value : Longword;
+ columnIndex : Word = 0
+) : Boolean;
+var
+ foundIdx : Integer;
+ l, h, m : Integer;
+ index : TSortIndex;
+begin
+
+ Result := False;
+ index := nil;
+ foundIdx := -1;
+ for l := 0 to FIndexes.Count - 1 do begin
+ index := TSortIndex( FIndexes[ l ] );
+ if index.ColumnIndex = columnIndex then
+ Break;
+ end;
+ if index = nil then
+ Exit;
+
+ // \92P\8f\83\82È\93ñ\95ª\92T\8dõ
+ l := 0;
+ h := index.Count;
+ m := 0;
+ while l < h do begin
+ m := (l + h) shr 1;
+ if index[ m ].FValue = value then begin
+ foundIdx := m;
+ founds.Add( Pointer( index[ m ].FATIndex ) );
+ Break;
+ end else if index[ m ].FValue < value then begin
+ h := m;
+ end else begin
+ l := m;
+ end;
+ end;
+ if foundIdx < 0 then
+ Exit;
+
+ for l := m - 1 downto 0 do begin
+ if index[ l ].FValue <> value then
+ Break;
+ founds.Add( Pointer( l ) );
+ end;
+ for l := m + 1 downto index.Count - 1 do begin
+ if index[ l ].FValue <> value then
+ Break;
+ founds.Add( Pointer( index[ m ].FATIndex ) );
+ end;
+
+ Result := True;
+
+end;
+
+//==============================
+// GetRecordByInteger
+//==============================
+function TGikoDB.GetRecordByInteger( primalyValue : Integer ) : TRecord;
+var
+ founds : TList;
+ sector : Integer;
+begin
+
+ Result := nil;
+ founds := TList.Create;
+ try
+ if not SelectValue( founds, primalyValue ) then
+ Exit;
+
+ sector := Integer( founds[ 0 ] );
+ Result := TRecord.Create( Self, FAllocationTable[ sector ] );
+ finally
+ founds.Free;
+ end;
+
+end;
+
+//==============================
+// GetRecordByString
+//==============================
+function TGikoDB.GetRecordByString( const primalyValue : string ) : TRecord;
+var
+ hash : Longword;
+begin
+
+ hash := GetStringHash( primalyValue );
+ Result := GetRecordByInteger( hash );
+
+end;
+
+//==============================
+// GetSector
+//==============================
+function TGikoDB.GetSector( sectorNo : Integer ) : Pointer;
+begin
+ //!!!!! \8dì\90¬\92\86 !!!!!
+end;
+
+end.