uses
//==================================================
- Classes, SysUtils,
+ Classes, SysUtils, Windows,
YofUtils;
//==================================================
IXMLNode = class
private
FNodeName : string;
+ FCapacity : Integer;
FCount : Integer;
FAttributeCount : Integer;
FChildNodes : IXMLNode;
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¼
const
//==================================================
kXMLWhite : TSysCharSet = [#0..#$20];
+ kXMLNodeNameStop : TSysCharSet = [#0..#$20, '/', '>'];
+ kXMLAttributeNameStop : TSysCharSet = [#0..#$20, '=', '/', '>'];
kXMLDQuote : TSysCharSet = ['"'];
kXMLTagStart : TSysCharSet = ['<'];
kXMLTagEnd : TSysCharSet = ['>'];
inherited;
+ FCapacity := 0;
FCount := 0;
end;
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;
const Value : string
);
var
+ t : Integer;
index : Integer;
begin
index := FAttributeCount;
Inc( FAttributeCount );
SetLength( FAttributes, FAttributeCount );
+
FAttributes[ index ].Name := Name;
FAttributes[ index ].Value := Value;
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;
+ t, t2 : Integer;
label
NextNode;
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
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½
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
// \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
// \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, 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, 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;
type
xmlMode = ( xmlHoge );
var
- xmlFile : TFileStream;
+ xmlFile : TMappedFile;
+ p : PChar;
begin
- //Result := IXMLDocument.Create;
+ //Result := IXMLDocument.Create;
//doc := IXMLDocument.Create;
- xmlFile := TFileStream.Create( fileName, fmOpenRead );
+ xmlFile := TMappedFile.Create( fileName );
- try
- XMLReadNode( xmlFile, IXMLNode( doc ) );
- //XMLReadNode( xmlFile, IXMLNode( Result ) );
- finally
+ try
+ p := xmlFile.Memory;
+ XMLReadNode( p, p + xmlFile.Size, IXMLNode( doc ) );
+ //XMLReadNode( xmlFile, IXMLNode( Result ) );
+ finally
xmlFile.Free;
- end;
+ end;
//Result := doc;