|
@@ -14,7 +14,7 @@
|
|
**********************************************************************}
|
|
**********************************************************************}
|
|
unit xmlutils;
|
|
unit xmlutils;
|
|
|
|
|
|
-{$mode objfpc}
|
|
|
|
|
|
+{$ifdef fpc}{$mode objfpc}{$endif}
|
|
{$H+}
|
|
{$H+}
|
|
|
|
|
|
interface
|
|
interface
|
|
@@ -38,6 +38,10 @@ function WStrLIComp(S1, S2: PWideChar; Len: Integer): Integer;
|
|
{ a simple hash table with WideString keys }
|
|
{ a simple hash table with WideString keys }
|
|
|
|
|
|
type
|
|
type
|
|
|
|
+{$ifndef fpc}
|
|
|
|
+ PtrInt = LongInt;
|
|
|
|
+{$endif}
|
|
|
|
+
|
|
PPHashItem = ^PHashItem;
|
|
PPHashItem = ^PHashItem;
|
|
PHashItem = ^THashItem;
|
|
PHashItem = ^THashItem;
|
|
THashItem = record
|
|
THashItem = record
|
|
@@ -46,6 +50,8 @@ type
|
|
Next: PHashItem;
|
|
Next: PHashItem;
|
|
Data: TObject;
|
|
Data: TObject;
|
|
end;
|
|
end;
|
|
|
|
+ THashItemArray = array[0..0] of PHashItem;
|
|
|
|
+ PHashItemArray = ^THashItemArray;
|
|
|
|
|
|
THashForEach = function(Entry: PHashItem; arg: Pointer): Boolean;
|
|
THashForEach = function(Entry: PHashItem; arg: Pointer): Boolean;
|
|
|
|
|
|
@@ -53,7 +59,7 @@ type
|
|
private
|
|
private
|
|
FCount: LongWord;
|
|
FCount: LongWord;
|
|
FBucketCount: LongWord;
|
|
FBucketCount: LongWord;
|
|
- FBucket: PPHashItem;
|
|
|
|
|
|
+ FBucket: PHashItemArray;
|
|
FOwnsObjects: Boolean;
|
|
FOwnsObjects: Boolean;
|
|
function Lookup(Key: PWideChar; KeyLength: Integer; out Found: Boolean; CanCreate: Boolean): PHashItem;
|
|
function Lookup(Key: PWideChar; KeyLength: Integer; out Found: Boolean; CanCreate: Boolean): PHashItem;
|
|
procedure Resize(NewCapacity: LongWord);
|
|
procedure Resize(NewCapacity: LongWord);
|
|
@@ -73,7 +79,6 @@ type
|
|
|
|
|
|
{ another hash, for detecting duplicate namespaced attributes without memory allocations }
|
|
{ another hash, for detecting duplicate namespaced attributes without memory allocations }
|
|
|
|
|
|
- PExpHashEntry = ^TExpHashEntry;
|
|
|
|
TExpHashEntry = record
|
|
TExpHashEntry = record
|
|
rev: LongWord;
|
|
rev: LongWord;
|
|
hash: LongWord;
|
|
hash: LongWord;
|
|
@@ -81,12 +86,14 @@ type
|
|
lname: PWideChar;
|
|
lname: PWideChar;
|
|
lnameLen: Integer;
|
|
lnameLen: Integer;
|
|
end;
|
|
end;
|
|
|
|
+ TExpHashEntryArray = array[0..0] of TExpHashEntry;
|
|
|
|
+ PExpHashEntryArray = ^TExpHashEntryArray;
|
|
|
|
|
|
TDblHashArray = class(TObject)
|
|
TDblHashArray = class(TObject)
|
|
private
|
|
private
|
|
FSizeLog: Integer;
|
|
FSizeLog: Integer;
|
|
FRevision: LongWord;
|
|
FRevision: LongWord;
|
|
- FData: PExpHashEntry;
|
|
|
|
|
|
+ FData: PExpHashEntryArray;
|
|
public
|
|
public
|
|
procedure Init(NumSlots: Integer);
|
|
procedure Init(NumSlots: Integer);
|
|
function Locate(uri: PWideString; localName: PWideChar; localLength: Integer): Boolean;
|
|
function Locate(uri: PWideString; localName: PWideChar; localLength: Integer): Boolean;
|
|
@@ -128,7 +135,7 @@ begin
|
|
Result := Xml11Pg;
|
|
Result := Xml11Pg;
|
|
end;
|
|
end;
|
|
|
|
|
|
-function IsXml11Char(Value: PWideChar; var Index: Integer): Boolean;
|
|
|
|
|
|
+function IsXml11Char(Value: PWideChar; var Index: Integer): Boolean; overload;
|
|
begin
|
|
begin
|
|
if (Value[Index] >= #$D800) and (Value[Index] <= #$DB7F) then
|
|
if (Value[Index] >= #$D800) and (Value[Index] <= #$DB7F) then
|
|
begin
|
|
begin
|
|
@@ -139,7 +146,7 @@ begin
|
|
Result := False;
|
|
Result := False;
|
|
end;
|
|
end;
|
|
|
|
|
|
-function IsXml11Char(const Value: WideString; var Index: Integer): Boolean;
|
|
|
|
|
|
+function IsXml11Char(const Value: WideString; var Index: Integer): Boolean; overload;
|
|
begin
|
|
begin
|
|
if (Value[Index] >= #$D800) and (Value[Index] <= #$DB7F) then
|
|
if (Value[Index] >= #$D800) and (Value[Index] <= #$DB7F) then
|
|
begin
|
|
begin
|
|
@@ -346,7 +353,11 @@ end;
|
|
|
|
|
|
function KeyCompare(const Key1: WideString; Key2: Pointer; Key2Len: Integer): Boolean;
|
|
function KeyCompare(const Key1: WideString; Key2: Pointer; Key2Len: Integer): Boolean;
|
|
begin
|
|
begin
|
|
|
|
+{$IFDEF FPC}
|
|
Result := (Length(Key1)=Key2Len) and (CompareWord(Pointer(Key1)^, Key2^, Key2Len) = 0);
|
|
Result := (Length(Key1)=Key2Len) and (CompareWord(Pointer(Key1)^, Key2^, Key2Len) = 0);
|
|
|
|
+{$ELSE}
|
|
|
|
+ Result := (Length(Key1)=Key2Len) and CompareMem(Pointer(Key1), Key2, Key2Len*2);
|
|
|
|
+{$ENDIF}
|
|
end;
|
|
end;
|
|
|
|
|
|
{ THashTable }
|
|
{ THashTable }
|
|
@@ -377,7 +388,7 @@ var
|
|
begin
|
|
begin
|
|
for I := 0 to FBucketCount-1 do
|
|
for I := 0 to FBucketCount-1 do
|
|
begin
|
|
begin
|
|
- item := FBucket[I];
|
|
|
|
|
|
+ item := FBucket^[I];
|
|
while Assigned(item) do
|
|
while Assigned(item) do
|
|
begin
|
|
begin
|
|
next := item^.Next;
|
|
next := item^.Next;
|
|
@@ -386,8 +397,8 @@ begin
|
|
Dispose(item);
|
|
Dispose(item);
|
|
item := next;
|
|
item := next;
|
|
end;
|
|
end;
|
|
|
|
+ FBucket^[I] := nil;
|
|
end;
|
|
end;
|
|
- FillChar(FBucket^, FBucketCount * sizeof(PHashItem), 0);
|
|
|
|
end;
|
|
end;
|
|
|
|
|
|
function THashTable.Find(Key: PWideChar; KeyLen: Integer): PHashItem;
|
|
function THashTable.Find(Key: PWideChar; KeyLen: Integer): PHashItem;
|
|
@@ -460,14 +471,15 @@ end;
|
|
|
|
|
|
procedure THashTable.Resize(NewCapacity: LongWord);
|
|
procedure THashTable.Resize(NewCapacity: LongWord);
|
|
var
|
|
var
|
|
- p, chain: PPHashItem;
|
|
|
|
|
|
+ p: PHashItemArray;
|
|
|
|
+ chain: PPHashItem;
|
|
i: Integer;
|
|
i: Integer;
|
|
e, n: PHashItem;
|
|
e, n: PHashItem;
|
|
begin
|
|
begin
|
|
p := AllocMem(NewCapacity * sizeof(PHashItem));
|
|
p := AllocMem(NewCapacity * sizeof(PHashItem));
|
|
for i := 0 to FBucketCount-1 do
|
|
for i := 0 to FBucketCount-1 do
|
|
begin
|
|
begin
|
|
- e := FBucket[i];
|
|
|
|
|
|
+ e := FBucket^[i];
|
|
while Assigned(e) do
|
|
while Assigned(e) do
|
|
begin
|
|
begin
|
|
chain := @p[e^.HashValue mod NewCapacity];
|
|
chain := @p[e^.HashValue mod NewCapacity];
|
|
@@ -538,7 +550,7 @@ var
|
|
begin
|
|
begin
|
|
for i := 0 to FBucketCount-1 do
|
|
for i := 0 to FBucketCount-1 do
|
|
begin
|
|
begin
|
|
- e := FBucket[i];
|
|
|
|
|
|
+ e := FBucket^[i];
|
|
while Assigned(e) do
|
|
while Assigned(e) do
|
|
begin
|
|
begin
|
|
if not proc(e, arg) then
|
|
if not proc(e, arg) then
|
|
@@ -572,7 +584,7 @@ begin
|
|
begin
|
|
begin
|
|
FRevision := $FFFFFFFF;
|
|
FRevision := $FFFFFFFF;
|
|
for i := (1 shl FSizeLog)-1 downto 0 do
|
|
for i := (1 shl FSizeLog)-1 downto 0 do
|
|
- FData[i].rev := FRevision;
|
|
|
|
|
|
+ FData^[i].rev := FRevision;
|
|
end;
|
|
end;
|
|
Dec(FRevision);
|
|
Dec(FRevision);
|
|
end;
|
|
end;
|
|
@@ -591,18 +603,18 @@ begin
|
|
step := (HashValue and (not mask)) shr (FSizeLog-1) and (mask shr 2) or 1;
|
|
step := (HashValue and (not mask)) shr (FSizeLog-1) and (mask shr 2) or 1;
|
|
idx := HashValue and mask;
|
|
idx := HashValue and mask;
|
|
result := True;
|
|
result := True;
|
|
- while FData[idx].rev = FRevision do
|
|
|
|
|
|
+ while FData^[idx].rev = FRevision do
|
|
begin
|
|
begin
|
|
- if (HashValue = FData[idx].hash) and (FData[idx].uriPtr^ = uri^) and
|
|
|
|
- (FData[idx].lnameLen = localLength) and
|
|
|
|
- CompareMem(FData[idx].lname, localName, localLength * sizeof(WideChar)) then
|
|
|
|
|
|
+ if (HashValue = FData^[idx].hash) and (FData^[idx].uriPtr^ = uri^) and
|
|
|
|
+ (FData^[idx].lnameLen = localLength) and
|
|
|
|
+ CompareMem(FData^[idx].lname, localName, localLength * sizeof(WideChar)) then
|
|
Exit;
|
|
Exit;
|
|
if idx < step then
|
|
if idx < step then
|
|
Inc(idx, (1 shl FSizeLog) - step)
|
|
Inc(idx, (1 shl FSizeLog) - step)
|
|
else
|
|
else
|
|
Dec(idx, step);
|
|
Dec(idx, step);
|
|
end;
|
|
end;
|
|
- with FData[idx] do
|
|
|
|
|
|
+ with FData^[idx] do
|
|
begin
|
|
begin
|
|
rev := FRevision;
|
|
rev := FRevision;
|
|
hash := HashValue;
|
|
hash := HashValue;
|