OSDN Git Service

まちBBSで削除レスがあるレス番号とスレの件数がずれる不具合を修正
[gikonavigoeson/gikonavi.git] / GikoXMLDoc.pas
index 99cba6c..7b35439 100644 (file)
@@ -1,8 +1,11 @@
 unit GikoXMLDoc;
 
-{
-       XMLIntf, XMLDoc \82 \82½\82è\82Ì\83N\83\8d\81[\83\93
-       Delphi 6 Personal \97p
+{!
+\file          GikoXMLDoc.pas
+\brief XMLIntf, XMLDoc \82 \82½\82è\82Ì\83N\83\8d\81[\83\93<br>
+                               Delphi 6 Personal \97p
+
+$Id: GikoXMLDoc.pas,v 1.10 2004/10/09 15:07:20 yoffy Exp $
 }
 interface
 
@@ -10,7 +13,7 @@ interface
 uses
 //==================================================
 
-       Classes, SysUtils,
+       Classes, SysUtils, Windows,
        YofUtils;
 
 //==================================================
@@ -26,6 +29,7 @@ type
        IXMLNode = class
        private
                FNodeName : string;
+               FCapacity : Integer;
                FCount : Integer;
                FAttributeCount : Integer;
                FChildNodes : IXMLNode;
@@ -34,7 +38,8 @@ type
                function GetAttribute( const Name : string ) : string;
                function GetNode( Index : Integer ) : IXMLNode;
        public
-               constructor Create;
+               constructor     Create;
+               destructor      Destroy; override;
 
                property NodeName : string read FNodeName write FNodeName;
                property Attributes[ const Name : string ] : string read GetAttribute;
@@ -53,43 +58,64 @@ type
        end;
 
 function XMLCloseCheck(
-       var f : TFileStream;
+       var p                           : PChar;
+       const tail      : PChar;
        var node : IXMLNode;
-       ch : char;
        out tag : string;
        out closed : boolean // \8cÄ\82Ñ\8fo\82µ\82½\83\8b\81[\83`\83\93\82ª node \82ð\95Â\82\82é\82×\82«\82È\82ç true
 ) : boolean; // ch \82ð\82±\82Ì\83\8b\81[\83`\83\93\82ª\8f\88\97\9d\82µ\82½\82È\82ç true
 
 function XMLReadNode(
-       var f : TFileStream;
+       var p                           : PChar;
+       const tail      : PChar;
        var node : IXMLNode
 ) : string; // node \88È\8aO\82Ì\83m\81[\83h\82ª\95Â\82\82ç\82ê\82½\8fê\8d\87\82Ì\83m\81[\83h\96¼
 
-function LoadXMLDocument(
-       const fileName : string
-) : IXMLDocument;
+procedure LoadXMLDocument(
+       const fileName : string;
+    var doc : IXMLDocument
+);
 
 //==================================================
 const
 //==================================================
        kXMLWhite : TSysCharSet = [#0..#$20];
+       kXMLNodeNameStop : TSysCharSet = [#0..#$20, '/', '>'];
+       kXMLAttributeNameStop : TSysCharSet = [#0..#$20, '=', '/', '>'];
        kXMLDQuote : TSysCharSet = ['"'];
        kXMLTagStart : TSysCharSet = ['<'];
        kXMLTagEnd : TSysCharSet = ['>'];
-       kXMLKanji : TSysCharSet = [#$80..#$A0, #$E0..#$ff];
+       kXMLKanji : TSysCharSet = [#$81..#$9f, #$E0..#$fc];
 
 //==================================================
 implementation
 //==================================================
 
 // Constructor
-constructor IXMLNode.Create();
+constructor    IXMLNode.Create;
 begin
 
+       inherited;
+
+       FCapacity := 0;
        FCount := 0;
 
 end;
 
+// Destructor
+destructor     IXMLNode.Destroy;
+var
+       i : Integer;
+begin
+
+       for i := FCount - 1 downto 0 do
+               FNodes[ i ].Free;
+       FChildNodes.Free;
+
+       inherited;
+
+end;
+
 function IXMLNode.GetAttribute( const Name : string ) : string;
 var
        i : Integer;
@@ -120,7 +146,11 @@ procedure IXMLNode.Add( node : IXMLNode );
 begin
 
        Inc( FCount );
-       SetLength( FNodes, FCount );
+       if FCount > FCapacity then begin
+               FCapacity := FCapacity + (FCapacity shr 2) + 1;
+               SetLength( FNodes, FCapacity );
+       end;
+
        FNodes[ FCount - 1 ] := node;
 
 end;
@@ -136,6 +166,7 @@ begin
        index := FAttributeCount;
        Inc( FAttributeCount );
        SetLength( FAttributes, FAttributeCount );
+
        FAttributes[ index ].Name := Name;
        FAttributes[ index ].Value := Value;
 
@@ -148,116 +179,133 @@ begin
 
 end;
 
-// untilSet \82É\82È\82é\82Ü\82Å\94ò\82Î\82·
-procedure FileThruUntil(
-       var f : TFileStream;
-       const untilSet : TSysCharSet
-);
-var
-       ch : char;
+{!
+\brief tok \82ð\92T\82·
+\param p                       \92T\8dõ\8aJ\8en\88Ê\92u
+\param tail    \8fI\97¹\88Ê\92u + 1
+\param tok             \92T\82·\83L\83\83\83\89\83N\83^
+\return        tok \82ª\8dÅ\8f\89\82É\8c©\82Â\82©\82Á\82½\88Ê\92u
+}
+function AnsiStrTok(
+       p                       : PChar;
+       const tail      : PChar;
+       const tok : TSysCharSet
+) : PChar;
 begin
 
-       while f.Position < f.Size do
+       while p < tail do
        begin
-               f.ReadBuffer( ch, 1 );
-               if ch in untilSet then
+               if p^ in tok then
                begin
-                       f.Seek( -1, soFromCurrent );
-                       exit;
-               end else if ch in kXMLKanji then
-                       f.Seek( 1, soFromCurrent );
+                       Break;
+               end else if p^ in kXMLKanji then
+                       p := p + 2
+               else
+                       Inc( p );
        end;
 
+       Result := p;
+
 end;
 
-// whileSet \82Ì\8aÔ\94ò\82Î\82·
-procedure FileThruWhile(
-       var f : TFileStream;
-       const whileSet : TSysCharSet
-);
-var
-       ch : char;
+{!
+\brief tok \82Å\82Í\96³\82¢\83L\83\83\83\89\83N\83^\82ð\92T\82·
+\param p                       \92T\8dõ\8aJ\8en\88Ê\92u
+\param tail    \8fI\97¹\88Ê\92u + 1
+\param tok             \92T\82·\83L\83\83\83\89\83N\83^
+\return        tok \82Å\82Í\82È\82¢\83L\83\83\83\89\83N\83^\82ª\8dÅ\8f\89\82É\8c©\82Â\82©\82Á\82½\88Ê\92u
+}
+function AnsiStrNonTok(
+       p                       : PChar;
+       const tail      : PChar;
+       const tok : TSysCharSet
+) : PChar;
 begin
 
-       while f.Position < f.Size do
+       while p < tail do
        begin
-               f.ReadBuffer( ch, 1 );
-               if ch in whileSet then
+               if p^ in tok then
                begin
-                       if ch in kXMLKanji then
-                               f.ReadBuffer( ch, 1 );
+                       if p^ in kXMLKanji then
+                               p := p + 2
+                       else
+                               Inc( p );
                end else begin
-                       f.Seek( -1, soFromCurrent );
-                       exit;
+                       Break;
                end;
        end;
 
+       Result := p;
+
 end;
 
 function XMLCloseCheck(
-       var f : TFileStream;
+       var p : PChar;
+       const tail      : PChar;
        var node : IXMLNode;
-       ch : char;
        out tag : string;
        out closed : boolean
 ) : boolean; // ch \82ð\82±\82Ì\83\8b\81[\83`\83\93\82ª\8f\88\97\9d\82µ\82½\82È\82ç true
 var
-       last : Integer;
-       tagLen : Integer;
+       found           : PChar;
 begin
 
        closed := false;
        Result := false;
        tag := '';
 
-       if ch = '>' then
-       begin
-               // \8aJ\8en\83^\83O\82Ì\8dÅ\8cã\82Ü\82Å\93Ç\82ñ\82¾
-               Result := true;
-       end else if ch = '?' then
-       begin
-               // <?xml?> \82Ý\82½\82¢\82È\82â\82Â\81B\82æ\82Á\82Ä\96³\8e\8b
-               FileThruUntil( f, kXMLTagEnd );
-               FileThruUntil( f, kXMLTagStart );
-               f.Seek( 1, soFromCurrent );
-               FileThruWhile( f, kXMLWhite );
-               //closed := true;
-               Result := true;
-       end else if ch = '/' then
-       begin
-               // \83^\83O\96¼\82ð\93Ç\82Ý\8d\9e\82ñ\82Å\95Ô\82·
-               last := f.Position;
-               FileThruUntil( f, kXMLTagEnd );
-               tagLen := f.Position - last;
-               SetLength( tag, tagLen );
-
-               f.Seek( last, soFromBeginning );
-               f.ReadBuffer( PChar( tag )^, tagLen );
-
-               f.Seek( f.Position + 1, soFromBeginning ); // '>' \94ò\82Î\82µ
-               closed := true;
-               Result := true;
+       case p^ of
+       '>':
+               begin
+                       // \8aJ\8en\83^\83O\82Ì\8dÅ\8cã\82Ü\82Å\93Ç\82ñ\82¾
+                       Inc( p );       // '>' \94ò\82Î\82µ
+                       Result := true;
+               end;
+
+       '?':
+               begin
+                       // <?xml?> \82Ý\82½\82¢\82È\82â\82Â\81B\82æ\82Á\82Ä\96³\8e\8b
+                       p := AnsiStrTok( p, tail, kXMLTagEnd );
+                       p := AnsiStrTok( p, tail, kXMLTagStart );
+                       Inc( p );       // '<' \94ò\82Î\82µ
+                       p := AnsiStrNonTok( p, tail, kXMLWhite );
+                       //closed := true;
+                       Result := true;
+               end;
+
+       '/':
+               begin
+                       // \83^\83O\96¼\82ð\93Ç\82Ý\8d\9e\82ñ\82Å\95Ô\82·
+                       Inc( p );       // '/' \94ò\82Î\82µ
+                       found := AnsiStrTok( p, tail, kXMLTagEnd );
+//                     tag := Copy( p, 0, found - p ); // \89½\8cÌ\82©\8c\83\92x
+                       SetLength( tag, found - p );
+                       CopyMemory( PChar( tag ), p, found - p );
+
+                       p := found + 1; // '>' \94ò\82Î\82µ
+                       closed := true;
+                       Result := true;
+               end;
        end;
 
 end;
 
 function XMLReadNode(
-       var f : TFileStream;
+       var p : PChar;
+       const tail      : PChar;
        var node : IXMLNode
 ) : string; // node \88È\8aO\82Ì\83m\81[\83h\82ª\95Â\82\82ç\82ê\82½\8fê\8d\87\82Ì\83m\81[\83h\96¼
 var
        child : IXMLNode;
 
-       last : Integer;
+       found : PChar;
        tag : string;
-       tagLen : Integer;
 
        isClosed : boolean;
 
+       nodeName : string;
        attributeName : string;
        attributeValue : string;
-
-       ch : char;
 label
        NextNode;
 begin
@@ -265,16 +313,14 @@ begin
                // node \82Ì\93Ç\82Ý\8d\9e\82Ý(1 \83\8b\81[\83v\82É\82Â\82« 1 \83m\81[\83h)
                node.ChildNodes := IXMLNode.Create;
 
-               while f.Position < f.Size do
+               while p < tail do
                begin
                        // NodeName \93Ç\82Ý\8d\9e\82Ý
-                       FileThruWhile( f, kXMLWhite );
+                       p := AnsiStrNonTok( p, tail, kXMLWhite );
 
-                       while f.Position < f.Size do
+                       while p < tail do
                        begin
-                               f.ReadBuffer( ch, 1 );
-
-                               if XMLCloseCheck( f, node, ch, tag, isClosed ) then
+                               if XMLCloseCheck( p, tail, node, tag, isClosed ) then
                                begin
                                        if isClosed then
                                        begin
@@ -283,11 +329,12 @@ begin
                                        end;
 
                                        goto NextNode;
-                               end else if ch = '<' then
+                               end else if p^ = '<' then
                                begin
                                        // \90V\8bK\83m\81[\83h
+                                       Inc( p );
                                        child := IXMLNode.Create;
-                                       tag := XMLReadNode( f, child );
+                                       tag := XMLReadNode( p, tail, child );
                                        node.ChildNodes.Add( child );
 
                                        // \83^\83O\82ª\95Â\82\82ç\82ê\82½
@@ -300,35 +347,32 @@ begin
                                        end;
 
                                        goto NextNode;
-                               end else if ch in kXMLWhite then
+                               end else if p^ in kXMLWhite then
                                begin
                                        // NodeName \8a®\97¹
                                        break;
                                end else begin
-                                       node.NodeName := node.NodeName + ch;
+                                       found := AnsiStrTok( p, tail, kXMLNodeNameStop );
+                                       SetLength( nodeName, found - p );
+                                       CopyMemory( PChar( nodeName ), p, found - p );
+                                       node.NodeName := nodeName;
 
-                                       if ch in kXMLKanji then
-                                       begin
-                                               f.ReadBuffer( ch, 1 );
-                                               node.NodeName := node.NodeName + ch;
-                                       end;
+                                       p := found;
                                end;
                        end;
 
                        // Attribute \82Ì\93Ç\82Ý\8d\9e\82Ý
-                       while f.Position < f.Size do
+                       while p < tail do
                        begin
                                // Attribute \82Ì\96¼\91O\82ð\93Ç\82Ý\8d\9e\82Ý
                                attributeName := '';
                                attributeValue := '';
 
-                               FileThruWhile( f, kXMLWhite );
+                               p := AnsiStrNonTok( p, tail, kXMLWhite );
 
-                               while f.Position < f.Size do
+                               while p < tail do
                                begin
-                                       f.ReadBuffer( ch, 1 );
-
-                                       if XMLCloseCheck( f, node, ch, tag, isClosed ) then
+                                       if XMLCloseCheck( p, tail, node, tag, isClosed ) then
                                        begin
                                                if isClosed then
                                                begin
@@ -340,33 +384,30 @@ begin
 
                                                // \8e\9f\82Ì\83m\81[\83h\82Ö
                                                goto NextNode;
-                                       end else if ch = '=' then
+                                       end else if p^ = '=' then
                                        begin
                                                // \82±\82±\82©\82ç\82Í\92l\82ª\8en\82Ü\82é\82Ì\82Å\96¼\91O\82Í\8fI\97¹
+                                               Inc( p );
                                                break;
-                                       end else if ch in kXMLWhite then
+                                       end else if p^ in kXMLWhite then
                                        begin
                                                // Value \82ª\91\8dÝ\82µ\82È\82¢(\8bK\8ai\8aO)\82Ì\82Å\8e\9f\82Ì\83m\81[\83h\82Ö
                                                goto NextNode;
                                        end else begin
-                                               attributeName := attributeName + ch;
+                                               found := AnsiStrTok( p, tail, kXMLAttributeNameStop );
+                                               SetLength( attributeName, found - p );
+                                               CopyMemory( PChar( attributeName ), p, found - p );
 
-                                               if ch in kXMLKanji then
-                                               begin
-                                                       f.ReadBuffer( ch, 1 );
-                                                       attributeName := attributeName + ch;
-                                               end;
+                                               p := found;
                                        end;
                                end;
 
                                // Attribute \82Ì\92l\82ð\93Ç\82Ý\8d\9e\82Ý
-                               FileThruWhile( f, kXMLWhite );
+                               p := AnsiStrNonTok( p, tail, kXMLWhite );
 
-                               while f.Position < f.Size do
+                               while p < tail do
                                begin
-                                       f.ReadBuffer( ch, 1 );
-
-                                       if XMLCloseCheck( f, node, ch, tag, isClosed ) then
+                                       if XMLCloseCheck( p, tail, node, tag, isClosed ) then
                                        begin
                                                if isClosed then
                                                begin
@@ -382,37 +423,37 @@ begin
 
                                                // \8e\9f\82Ì\83m\81[\83h\82Ö
                                                goto NextNode;
-                                       end else if ch = '"' then
+                                       end else if p^ = '"' then
                                        begin
                                                // \92l\82ª "" \82Å\8a\87\82ç\82ê\82Ä\82é\82Ì\82Å(\82Ä\82¢\82¤\82©\8a\87\82ç\82ê\82Ä\82È\82«\82á\82¢\82¯\82È\82¢\82ñ\82¾\82¯\82Ç)
                                                // \92l\82ð\88ê\8a\87\93Ç\82Ý\8d\9e\82Ý
-                                               last := f.Position;
-                                               FileThruUntil( f, kXMLDQuote );
-                                               tagLen := f.Position - last;
-                                               SetLength( attributeValue, tagLen );
-
-                                               f.Seek( last, soFromBeginning );
-                                               f.ReadBuffer( PChar( attributeValue )^, tagLen );
+                                               Inc( p );
+                                               found := AnsiStrTok( p, tail, kXMLDQuote );
+//                                             attributeValue := Copy( p, 0, found - p );      // \89½\8cÌ\82©\8c\83\92x
+                                               SetLength( attributeValue, found - p );
+                                               CopyMemory( PChar( attributeValue ), p, found - p );
 
-                                               node.AddAttribute( attributeName, HttpDecode( attributeValue ) );
+                                               node.AddAttribute( attributeName, HtmlDecode( attributeValue ) );
 
                                                // \92l\82ð\93Ç\82Ý\8fI\82í\82Á\82½\82Ì\82Å\8fI\97¹
-                                               f.Seek( f.Position + 1, soFromBeginning ); // '"' \94ò\82Î\82µ
+                                               p := found + 1; // '"' \94ò\82Î\82µ
                                                break;
-                                       end else if ch in kXMLWhite then
+                                       end else if p^ in kXMLWhite then
                                        begin
                                                // \8bK\8ai\8aO\82¾\82¯\82Ç\82Ë
-                                               node.AddAttribute( attributeName, HttpDecode( attributeValue ) );
+                                               node.AddAttribute( attributeName, HtmlDecode( attributeValue ) );
 
                                                goto NextNode;
                                        end else begin
                                                // \8bK\8ai\8aO\82¾\82¯\82Ç\88ê\89\9e\8eæ\82Á\82Ä\82¨\82­
-                                               attributeValue := attributeValue + ch;
+                                               attributeValue := attributeValue + p^;
 
-                                               if ch in kXMLKanji then
+                                               if p^ in kXMLKanji then
                                                begin
-                                                       f.ReadBuffer( ch, 1 );
-                                                       attributeValue := attributeValue + ch;
+                                                       attributeValue := attributeValue + (p + 1)^;
+                                                       p := p + 2;
+                                               end else begin
+                                                       Inc( p );
                                                end;
                                        end;
                                end;
@@ -424,25 +465,31 @@ begin
        end;
 end;
 
-function LoadXMLDocument(
-       const fileName : string
-) : IXMLDocument;
+procedure LoadXMLDocument(
+       const fileName : string;
+       var doc : IXMLDocument
+);
 type
        xmlMode = ( xmlHoge );
 var
-       xmlFile : TFileStream;
-       doc : IXMLDocument;
+       xmlFile : TMappedFile;
+       p                               : PChar;
 begin
+               //Result := IXMLDocument.Create;
+       //doc := IXMLDocument.Create;
 
-       doc := IXMLDocument.Create;
+       xmlFile := TMappedFile.Create( fileName );
 
-       xmlFile := TFileStream.Create( fileName, fmOpenRead );
-       XMLReadNode( xmlFile, IXMLNode( doc ) );
-       xmlFile.Free;
+       try
+               p := xmlFile.Memory;
+               XMLReadNode( p, p + xmlFile.Size, IXMLNode( doc ) );
+               //XMLReadNode( xmlFile, IXMLNode( Result ) );
+       finally
+               xmlFile.Free;
+       end;
 
-       Result := doc;
+       //Result := doc;
 
 end;
 
 end.
\ No newline at end of file