Permalink
Browse files

FPC + ARC support

My first modifications of original OmniXML code to support FPC and ARC Delphi.
-> I tried to make as little changes as possible:

1) I replaced GpTextStream.pas and GpStreamWrapper.pas (that are Windows-only) with OTextReadWrite.pas (that is Lazarus and ARC enabled).
2) I made OmniXML_Dictionary.pas compatible with Lazarus.
3) I fixed a performance bottle neck in TXMLCustomList: the "FList: TInterfaceList" has horrible performance in Delphi prior to 2007 and Lazarus due to critical sections (that are not necessary in my opinion). I changed it to TList<IXMLNode> in D2009+ and to normal TList with manual reference counting for non-unicode Delphi. This little change made nodes create about 3-4 times faster in non-unicode Delphi.

Everything else is 1:1 the original OmniXML code so everybody can upgrade without any problems.
  • Loading branch information...
on.pokorny@gmail.com
on.pokorny@gmail.com committed Dec 12, 2013
1 parent 82df0f0 commit 5e405ea0957df3e6192af7258015fdedd4d5d5ee
Showing with 3,287 additions and 1,798 deletions.
  1. +0 −273 GpStreamWrapper.pas
  2. +0 −1,240 GpTextStream.pas
  3. +382 −0 OBufferedStreams.pas
  4. +839 −0 OEncoding.pas
  5. +714 −0 OTextReadWrite.pas
  6. +1,019 −0 OWideSupp.pas
  7. +71 −0 OXml.inc
  8. +14 −8 OmniXML.inc
  9. +152 −256 OmniXML.pas
  10. +11 −1 OmniXMLConf.pas
  11. +6 −0 OmniXMLDatabase.pas
  12. +7 −3 OmniXMLPersistent.pas
  13. +5 −0 OmniXMLProperties.pas
  14. +6 −1 OmniXMLUtils.pas
  15. +6 −0 OmniXMLXPath.pas
  16. +30 −4 OmniXML_Dictionary.pas
  17. +6 −0 OmniXML_LookupTables.pas
  18. +6 −1 OmniXML_MSXML.pas
  19. +13 −11 OmniXML_Types.pas
View
@@ -1,273 +0,0 @@
{$B-,H+,J+,Q-,T-,X+}
(*:Some useful stream wrappers.
@author Primoz Gabrijelcic
@desc <pre>
(c) 2012 Primoz Gabrijelcic
Free for personal and commercial use. No rights reserved.
Author : Primoz Gabrijelcic
Creation date : 2001-07-17
Last modification: 2012-04-24
Version : 1.05
</pre>
*)(*
History:
1.05: 2012-04-24
- Added overload for 64-bit Seek.
1.04: 2006-09-21
- TGpStreamWindow class moved to the GpStreams unit.
1.03: 2006-08-31
- Enable int64-based interface for Delphi 6.
1.02: 2006-04-14
- Added TGpStreamWindow class.
1.01: 2003-05-16
- Made Delphi 7 compatible.
1.0: 2001-07-17
- Released.
*)
unit GpStreamWrapper;
{$IFDEF CONDITIONALEXPRESSIONS}
{$IF (RTLVersion >= 14)} // Delphi 6.0 or newer
{$DEFINE D6PLUS}
{$IFEND}
{$ENDIF}
interface
uses
Classes;
type
{:Base stream wrapper class implementing the delayed Seek.
}
TGpStreamWrapper = class(TStream)
private
swDelayedSeek : boolean;
swSeekMode : word;
swSeekOffset : longint;
swStoredPosition: longint;
swStream : TStream;
{$IFDEF D6Plus}
private
swDelayedSeek64 : boolean;
swSeekOrigin : TSeekOrigin;
{$ENDIF D6Plus}
protected
function GetPosition: {$IFDEF D6PLUS}int64;{$ELSE}longint;{$ENDIF D6PLUS} virtual;
function GetSize: {$IFDEF D6PLUS}int64; override;{$ELSE}longint; virtual;{$ENDIF D6PLUS}
procedure SetPosition(newPosition: {$IFDEF D6PLUS}int64{$ELSE}longint{$ENDIF D6PLUS}); virtual;
procedure SetSize({$IFDEF D6PLUS}const{$ENDIF D6PLUS}newSize: {$IFDEF D6PLUS}int64{$ELSE}longint{$ENDIF D6PLUS}); override;
function WrappedSeek(offset: integer; mode: word): longint; {$IFDEF D6PLUS}overload;{$ENDIF D6PLUS}virtual;
{$IFDEF D6PLUS}
function WrappedSeek(offset: int64; origin: TSeekOrigin): int64; overload; virtual;
{$ENDIF D6PLUS}
public
constructor Create(wrappedStream: TStream);
procedure DelayedSeek; virtual;
function Seek(offset: integer; mode: word): longint; {$IFDEF D6PLUS}overload;{$ENDIF D6PLUS} override;
{$IFDEF D6Plus}
function Seek(const offset: int64; origin: TSeekOrigin): int64; overload; override;
{$ENDIF D6Plus} {:Wrapped (underlying) stream.}
property WrappedStream: TStream read swStream;
end; { TGpStreamWrapper }
implementation
{ TGpStreamWrapper }
constructor TGpStreamWrapper.Create(wrappedStream: TStream);
begin
inherited Create;
swStream := wrappedStream;
end; { TGpStreamWrapper.Create }
{:Repositions stream pointer in the wrapped stream (if required). Call this
method as a first thing in the descendant Read and Write methods.
}
procedure TGpStreamWrapper.DelayedSeek;
begin
{$IFDEF D6Plus}
if swDelayedSeek64 then begin
if (swSeekOffset <> 0) or (swSeekOrigin <> soCurrent) then
WrappedSeek(swSeekOffset, swSeekOrigin);
swDelayedSeek64 := false;
end
else
{$ENDIF D6Plus}
if swDelayedSeek then begin
if (swSeekOffset <> 0) or (swSeekMode <> soFromCurrent) then
WrappedSeek(swSeekOffset, swSeekMode);
swDelayedSeek := false;
end;
end; { TGpStreamWrapper.DelayedSeek }
{:Returns the position in the wrapping (virtual) stream. Trivial implementation
from this class returns position of the wrapped (underlying) stream.
If descendant overrides this method, it must never call TGpStreamWrapper.Seek
(directly or indirectly).
}
function TGpStreamWrapper.GetPosition: {$IFDEF D6PLUS}int64;{$ELSE}longint;{$ENDIF D6PLUS}
begin
Result := WrappedStream.Position;
end; { TGpStreamWrapper.GetPosition }
{:Returns the size of the wrapping (virtual) stream. Trivial implementation
from this class returns size of the wrapped (underlying) stream.
If descendant overrides this method, it must never call TGpStreamWrapper.Seek
(directly or indirectly).
}
function TGpStreamWrapper.GetSize: {$IFDEF D6PLUS}int64;{$ELSE}longint;{$ENDIF D6PLUS}
begin
Result := WrappedStream.Size;
end; { TGpStreamWrapper.GetSize }
{:Repositions stream pointer. Actually only stores this information for later
use (when stream pointer position is really used).
@param offset Offset from start, current position, or end of stream (as set
by the 'mode' parameter) in bytes.
@param mode Specifies starting point for offset calculation
(soFromBeginning, soFromCurrent, soFromEnd).
@returns New position of stream pointer.
}
function TGpStreamWrapper.Seek(offset: longint; mode: word): longint;
begin
// TStream is using following code to get Size of the stream:
// Pos := Seek(0, soFromCurrent);
// Result := Seek(0, soFromEnd);
// Seek(Pos, soFromBeginning);
// This code tries to hack around this stupid behaviour.
if not swDelayedSeek then begin
if (mode = soFromCurrent) and (offset = 0) then begin
// possible GetSize call
swDelayedSeek := true;
swSeekOffset := offset;
swSeekMode := mode;
swStoredPosition := GetPosition;
Result := swStoredPosition;
end
else // not a GetSize call, forward it
Result := WrappedSeek(offset,mode);
end
else begin
if mode = soFromCurrent then
// not a GetSize call; saved Seek can only be (0,fromCurrent) - it is not
// necessary to call DelayedSeek
Result := WrappedSeek(offset,mode)
else if mode = soFromEnd then begin
if swSeekMode = soFromCurrent then begin
// possible GetSize call
swSeekOffset := offset;
swSeekMode := mode;
Result := GetSize;
end
else // not a GetSize call
Result := WrappedSeek(offset,mode);
end
else {if mode = soFromBeginning} begin
if (swSeekMode = soFromEnd) and (swStoredPosition = offset) then begin
// definitely GetSize call
swDelayedSeek := false;
Result := swStoredPosition;
end
else // not a GetSize call
Result := WrappedSeek(offset,mode);
end;
end;
end; { TGpStreamWrapper.Seek }
{:Repositions stream pointer. Actually only stores this information for later
use (when stream pointer position is really used).
@param offset Offset from start, current position, or end of stream (as set
by the 'mode' parameter) in bytes.
@param mode Specifies starting point for offset calculation
(soFromBeginning, soFromCurrent, soFromEnd).
@returns New position of stream pointer.
}
function TGpStreamWrapper.Seek(const offset: int64; origin: TSeekOrigin): int64;
begin
// TStream is using following code to get Size of the stream:
// Pos := Seek(0, soFromCurrent);
// Result := Seek(0, soFromEnd);
// Seek(Pos, soFromBeginning);
// This code tries to hack around this stupid behaviour.
if not swDelayedSeek64 then begin
if (origin = soCurrent) and (offset = 0) then begin
// possible GetSize call
swDelayedSeek64 := true;
swSeekOffset := offset;
swSeekOrigin := origin;
swStoredPosition := GetPosition;
Result := swStoredPosition;
end
else // not a GetSize call, forward it
Result := WrappedSeek(offset, origin);
end
else begin
if origin = soCurrent then
// not a GetSize call; saved Seek can only be (0, fromCurrent) - it is not
// necessary to call DelayedSeek
Result := WrappedSeek(offset, origin)
else if origin = soEnd then begin
if swSeekOrigin = soCurrent then begin
// possible GetSize call
swSeekOffset := offset;
swSeekOrigin := origin;
Result := GetSize;
end
else // not a GetSize call
Result := WrappedSeek(offset, origin);
end
else {if mode = soBeginning} begin
if (swSeekOrigin = soEnd) and (swStoredPosition = offset) then begin
// definitely GetSize call
swDelayedSeek64 := false;
Result := swStoredPosition;
end
else // not a GetSize call
Result := WrappedSeek(offset, origin);
end;
end;
end; { TGpStreamWrapper.Seek }
{:Sets the position in the wrapping (virtual) stream. Trivial implementation
from this class sets position of the wrapped (underlying) stream.
If descendant overrides this method, it must never call TGpStreamWrapper.Seek
(directly or indirectly).
}
procedure TGpStreamWrapper.SetPosition(newPosition: {$IFDEF D6PLUS}int64{$ELSE}longint{$ENDIF D6PLUS});
begin
WrappedStream.Position := newPosition;
end; { TGpStreamWrapper.SetPosition }
{:Sets the size of the wrapping (virtual) stream. Trivial implementation
from this class sets position of the wrapped (underlying) stream.
If descendant overrides this method, it must never call TGpStreamWrapper.Seek
(directly or indirectly).
}
procedure TGpStreamWrapper.SetSize({$IFDEF D6PLUS}const{$ENDIF D6PLUS}newSize: {$IFDEF D6PLUS}int64{$ELSE}longint{$ENDIF D6PLUS});
begin
WrappedStream.Size := newSize;
end; { TGpStreamWrapper.SetSize }
{:Implementation of the 'true' Seek. Called only when Seek is really needed.
Trivial implementation from this class calls Seek on the wrapped (underlying) stream.
WrappedSeek must never call TGpStreamWrapper.Seek (directly or indirectly) but use
directly WrappedStream.Seek.
}
function TGpStreamWrapper.WrappedSeek(offset: integer;
mode: word): longint;
begin
Result := WrappedStream.Seek(offset, mode);
end; { TGpStreamWrapper.WrappedSeek }
{$IFDEF D6Plus}
function TGpStreamWrapper.WrappedSeek(offset: int64; origin: TSeekOrigin): int64;
begin
Result := WrappedStream.Seek(offset, origin);
end;
{$ENDIF D6Plus}
end.
Oops, something went wrong.

0 comments on commit 5e405ea

Please sign in to comment.