mirror of
https://github.com/StephenGenusa/DCPCrypt.git
synced 2025-06-12 21:57:27 +02:00
1223 lines
35 KiB
ObjectPascal
1223 lines
35 KiB
ObjectPascal
![]() |
unit ORawByteString;
|
||
|
|
||
|
{
|
||
|
|
||
|
Author:
|
||
|
Ondrej Pokorny, http://www.kluug.net
|
||
|
All Rights Reserved.
|
||
|
|
||
|
Version
|
||
|
0.2 2014-04-12
|
||
|
|
||
|
License:
|
||
|
MPL 1.1: http://www.mozilla.org/MPL/1.1/
|
||
|
|
||
|
}
|
||
|
|
||
|
{
|
||
|
ORawByteString.pas
|
||
|
|
||
|
TORawByteString
|
||
|
- a replacement of RawByteString for NextGen (iOS/Android) for use
|
||
|
as a plain byte buffer (no explicit string data inside)
|
||
|
- please note that all indices used in TORawByteString are 0-based if not stated differently.
|
||
|
this is necessary to keep things simple
|
||
|
|
||
|
TORawByteChar
|
||
|
- a replacement for AnsiChar
|
||
|
|
||
|
TORawSingleByteEncoding
|
||
|
- Encoding that converts the byte representation of chars (only within $FF) directly to/from byte
|
||
|
(no character codepage involved).
|
||
|
|
||
|
}
|
||
|
|
||
|
{.$DEFINE ORAW_IMPLICIT}//define to allow implicit conversions (a little less secure)
|
||
|
|
||
|
{$BOOLEVAL OFF}
|
||
|
|
||
|
interface
|
||
|
|
||
|
uses
|
||
|
SysUtils, Classes, Generics.Collections;
|
||
|
|
||
|
type
|
||
|
TORawSingleByteEncoding = class(TEncoding)
|
||
|
strict private
|
||
|
class var
|
||
|
FSavedInstance: TORawSingleByteEncoding;
|
||
|
class destructor Destroy;
|
||
|
strict protected
|
||
|
function GetByteCount(Chars: PChar; CharCount: Integer): Integer; override;
|
||
|
function GetBytes(Chars: PChar; CharCount: Integer; Bytes: PByte; ByteCount: Integer): Integer; override;
|
||
|
function GetCharCount(Bytes: PByte; ByteCount: Integer): Integer; override;
|
||
|
function GetChars(Bytes: PByte; ByteCount: Integer; Chars: PChar; CharCount: Integer): Integer; override;
|
||
|
public
|
||
|
constructor Create;
|
||
|
public
|
||
|
class function Use: TORawSingleByteEncoding;
|
||
|
destructor Destroy; override;
|
||
|
|
||
|
function GetMaxByteCount(CharCount: Integer): Integer; override;
|
||
|
function GetMaxCharCount(ByteCount: Integer): Integer; override;
|
||
|
function GetPreamble: TBytes; override;
|
||
|
end;
|
||
|
|
||
|
TEncodingHelper = class helper for TEncoding
|
||
|
public
|
||
|
class function RawByte: TEncoding;
|
||
|
end;
|
||
|
|
||
|
TORawByteChar = packed record
|
||
|
strict private
|
||
|
FChar: Byte;
|
||
|
public
|
||
|
//operators
|
||
|
class operator Equal(const a1, a2: TORawByteChar): Boolean;
|
||
|
class operator Equal(const a1: TORawByteChar; const a2: Char): Boolean;
|
||
|
class operator Equal(const a1: Char; const a2: TORawByteChar): Boolean;
|
||
|
|
||
|
class operator NotEqual(const a1, a2: TORawByteChar): Boolean;
|
||
|
class operator NotEqual(const a1: TORawByteChar; const a2: Char): Boolean;
|
||
|
class operator NotEqual(const a1: Char; const a2: TORawByteChar): Boolean;
|
||
|
|
||
|
class operator GreaterThan(const a1, a2: TORawByteChar): Boolean;
|
||
|
class operator GreaterThan(const a1: TORawByteChar; const a2: Char): Boolean;
|
||
|
class operator GreaterThan(const a1: Char; const a2: TORawByteChar): Boolean;
|
||
|
|
||
|
class operator GreaterThanOrEqual(const a1, a2: TORawByteChar): Boolean;
|
||
|
class operator GreaterThanOrEqual(const a1: TORawByteChar; const a2: Char): Boolean;
|
||
|
class operator GreaterThanOrEqual(const a1: Char; const a2: TORawByteChar): Boolean;
|
||
|
|
||
|
class operator LessThan(const a1, a2: TORawByteChar): Boolean;
|
||
|
class operator LessThan(const a1: TORawByteChar; const a2: Char): Boolean;
|
||
|
class operator LessThan(const a1: Char; const a2: TORawByteChar): Boolean;
|
||
|
|
||
|
class operator LessThanOrEqual(const a1, a2: TORawByteChar): Boolean;
|
||
|
class operator LessThanOrEqual(const a1: TORawByteChar; const a2: Char): Boolean;
|
||
|
class operator LessThanOrEqual(const a1: Char; const a2: TORawByteChar): Boolean;
|
||
|
|
||
|
{$IFDEF ORAW_IMPLICIT}
|
||
|
class operator Implicit(const a: Char): TORawByteChar;
|
||
|
class operator Implicit(const a: TORawByteChar): Char;
|
||
|
class operator Implicit(const a: Byte): TORawByteChar;
|
||
|
class operator Implicit(const a: TORawByteChar): Byte;
|
||
|
{$ELSE}
|
||
|
class operator Explicit(const a: Char): TORawByteChar;
|
||
|
class operator Explicit(const a: TORawByteChar): Char;
|
||
|
class operator Explicit(const a: Byte): TORawByteChar;
|
||
|
class operator Explicit(const a: TORawByteChar): Byte;
|
||
|
{$ENDIF}
|
||
|
public
|
||
|
//ANSI functions
|
||
|
function ToUpper: TORawByteChar;
|
||
|
function ToLower: TORawByteChar;
|
||
|
end;
|
||
|
TORawByteCharArray = array[0..High(Integer)-1] of TORawByteChar;
|
||
|
PORawByteChar = ^TORawByteCharArray;
|
||
|
|
||
|
TORawByteString = packed record
|
||
|
strict private class var
|
||
|
FDefaultEncoding: TEncoding;//default encoding for AnsiString operations, use TORawSingleByteEncoding
|
||
|
strict private type
|
||
|
PORawByteString = ^TORawByteString;
|
||
|
TORawByteStringCharEnumerator = class
|
||
|
strict private
|
||
|
FIndex: Integer;
|
||
|
FString: PORawByteString;
|
||
|
public
|
||
|
constructor Create(aBuffer: PORawByteString);
|
||
|
function GetCurrent: TORawByteChar; inline;
|
||
|
function MoveNext: Boolean;
|
||
|
property Current: TORawByteChar read GetCurrent;
|
||
|
end;
|
||
|
strict private
|
||
|
FStrBuffer: String;//We store the real buffer length in the first two char positions!
|
||
|
|
||
|
function GetChar(const aIndex: Integer): TORawByteChar;
|
||
|
procedure SetChar(const aIndex: Integer; const aChar: TORawByteChar);
|
||
|
function GetDefChar(const aIndex: Integer): TORawByteChar;
|
||
|
procedure SetDefChar(const aIndex: Integer; const aChar: TORawByteChar);
|
||
|
function GetLength: Integer;
|
||
|
|
||
|
procedure CopyOnWriteCheck;
|
||
|
public
|
||
|
//operators
|
||
|
|
||
|
function GetBuffer: PByteArray;
|
||
|
procedure SetLength(const aLength: Integer);
|
||
|
class operator Add(const a1, a2: TORawByteString): TORawByteString;
|
||
|
class operator Add(const a1: TORawByteString; const a2: TBytes): TORawByteString;
|
||
|
class operator Add(const a1: TBytes; const a2: TORawByteString): TORawByteString;
|
||
|
class operator Add(const a1: TORawByteString; const a2: TORawByteChar): TORawByteString;
|
||
|
class operator Add(const a1: TORawByteChar; const a2: TORawByteString): TORawByteString;
|
||
|
class operator Equal(const a1, a2: TORawByteString): Boolean;
|
||
|
class operator NotEqual(const a1, a2: TORawByteString): Boolean;
|
||
|
|
||
|
{$IFDEF ORAW_IMPLICIT}
|
||
|
class operator Implicit(const a: string): TORawByteString;
|
||
|
class operator Implicit(const a: TORawByteString): string;
|
||
|
class operator Implicit(const a: TBytes): TORawByteString;
|
||
|
class operator Implicit(const a: TORawByteString): TBytes;
|
||
|
class operator Implicit(const a: TORawByteString): PORawByteChar;
|
||
|
class operator Implicit(const a: PORawByteChar): TORawByteString;
|
||
|
{$ELSE}
|
||
|
class operator Explicit(const a: string): TORawByteString;
|
||
|
class operator Explicit(const a: TORawByteString): string;
|
||
|
class operator Explicit(const a: TBytes): TORawByteString;
|
||
|
class operator Explicit(const a: TORawByteString): TBytes;
|
||
|
class operator Explicit(const a: TORawByteString): PORawByteChar;
|
||
|
class operator Explicit(const a: PORawByteChar): TORawByteString;
|
||
|
{$ENDIF}
|
||
|
|
||
|
function GetEnumerator: TORawByteStringCharEnumerator;
|
||
|
public
|
||
|
//constructors
|
||
|
|
||
|
constructor Create(const aBytes: TBytes); overload;
|
||
|
constructor Create(const aString: string; aEncoding: TEncoding = nil); overload;
|
||
|
public
|
||
|
//byte functions -> they act on raw byte string as "Array of Byte"
|
||
|
|
||
|
//clear
|
||
|
procedure Clear;
|
||
|
//get the byte position of string, result is 0-based!
|
||
|
function Pos(const aSubStr: TORawByteString): Integer;
|
||
|
function PosEx(const aSubStr: TORawByteString; aOffset: Integer): Integer;
|
||
|
|
||
|
//Append
|
||
|
procedure Append(const aBytes: TBytes); overload;
|
||
|
procedure Append(const aBuffer: TORawByteString); overload;
|
||
|
procedure Append(const aBuffer; aBufferLength: Integer); overload;
|
||
|
//Prepend
|
||
|
procedure Prepend(const aBytes: TBytes); overload;
|
||
|
procedure Prepend(const aBuffer: TORawByteString); overload;
|
||
|
procedure Prepend(const aBuffer; aBufferLength: Integer); overload;
|
||
|
//insert into a byte index, 0-based!!!
|
||
|
procedure Insert(const aSubBytes: TBytes; aIndex: Integer); overload;
|
||
|
procedure Insert(const aSubBuffer: TORawByteString; aIndex: Integer); overload;
|
||
|
procedure Insert(const aSubBuffer; aSubBufferLength, aIndex: Integer); overload;
|
||
|
|
||
|
//copy, 0-based!!!
|
||
|
function Copy(aIndex, aCount: Integer): TORawByteString;
|
||
|
//delete, 0-based!!!
|
||
|
procedure Delete(aIndex, aCount: Integer);
|
||
|
|
||
|
procedure ToUpper(aEncoding: TEncoding = nil);
|
||
|
procedure ToLower(aEncoding: TEncoding = nil);
|
||
|
public
|
||
|
//String & TBytes conversion utilities
|
||
|
function GetString(aEncoding: TEncoding = nil): string;
|
||
|
procedure SetString(const aString: string; aEncoding: TEncoding = nil);
|
||
|
function GetBytes: TBytes;
|
||
|
procedure SetBytes(const aBytes: TBytes);
|
||
|
public
|
||
|
//stream & file functions
|
||
|
procedure LoadFromStream(const aStream: TStream);
|
||
|
procedure LoadFromFile(const aFileName: string);
|
||
|
procedure SaveToStream(const aStream: TStream; const aWriteBOM: Boolean = True);
|
||
|
procedure SaveToFile(const aFileName: string; const aWriteBOM: Boolean = True);
|
||
|
public
|
||
|
class function GetDefaultEncoding: TEncoding; static;
|
||
|
class procedure SetDefaultEncoding(aEncoding: TEncoding); static;//default is TORawSingleByteEncoding = RawByteString, if you want to simulate AnsiString, use TEncoding.ANSI
|
||
|
public
|
||
|
//properties
|
||
|
|
||
|
property Length: Integer read GetLength write SetLength;
|
||
|
//get/set raw bytes by index, 0-based !!!
|
||
|
property Chars[const aIndex: Integer]: TORawByteChar read GetChar write SetChar;
|
||
|
//get/set raw bytes by index, 1-based !!!
|
||
|
property DefChars[const aIndex: Integer]: TORawByteChar read GetDefChar write SetDefChar; default;
|
||
|
end;
|
||
|
|
||
|
//Ansi* definitions and helper function
|
||
|
|
||
|
{$IFDEF NEXTGEN}
|
||
|
AnsiString = TORawByteString;
|
||
|
AnsiChar = TORawByteChar;
|
||
|
RawByteString = TORawByteString;
|
||
|
PAnsiChar = PORawByteChar;
|
||
|
PRawByteChar = PORawByteChar;
|
||
|
{$ENDIF}
|
||
|
|
||
|
//All following string functions are 1-based
|
||
|
function UTF8ToString(const aUTF8String: TORawByteString): String; inline; overload;
|
||
|
function UTF8Decode(const aUTF8String: TORawByteString): String; inline; overload;
|
||
|
function UTF8Encode(const aString: String): TORawByteString; inline; overload;
|
||
|
function Pos(const aSubStr: String; const aString: TORawByteString): Integer; inline; overload;
|
||
|
function Pos(const aSubStr, aString: TORawByteString): Integer; inline; overload;
|
||
|
function PosEx(const aSubStr: String; const aString: TORawByteString; aOffset: Integer): Integer; inline; overload;
|
||
|
function PosEx(const aSubStr, aString: TORawByteString; aOffset: Integer): Integer; inline; overload;
|
||
|
function LowerCase(const aString: TORawByteString): TORawByteString; inline; overload;
|
||
|
function UpperCase(const aString: TORawByteString): TORawByteString; inline; overload;
|
||
|
function CompareStr(const S1, S2: TORawByteString): Integer; inline; overload;
|
||
|
function CompareText(const S1, S2: TORawByteString): Integer; inline; overload;
|
||
|
|
||
|
//the following functions can't be declared without Ansi prefix because they are compiler magic
|
||
|
function AnsiCopy(const aString: TORawByteString; aIndex, aCount: Integer): TORawByteString; inline; overload;
|
||
|
procedure AnsiInsert(const aSubString: TORawByteString; var aString: TORawByteString; aIndex: Integer); inline; overload;
|
||
|
procedure AnsiDelete(var aString: TORawByteString; aIndex, aCount: Integer); inline; overload;
|
||
|
function AnsiLength(const aString: TORawByteString): Integer; inline; overload;
|
||
|
function AnsiLow(const aString: TORawByteString): Integer; inline; overload;
|
||
|
function AnsiHigh(const aString: TORawByteString): Integer; inline; overload;
|
||
|
{$IFNDEF NEXTGEN}
|
||
|
function AnsiCopy(const aString: RawByteString; aIndex, aCount: Integer): RawByteString; inline; overload;
|
||
|
procedure AnsiInsert(const aSubString: RawByteString; var aString: RawByteString; aIndex: Integer); inline; overload;
|
||
|
procedure AnsiDelete(var aString: RawByteString; aIndex, aCount: Integer); inline; overload;
|
||
|
function AnsiLength(const aString: RawByteString): Integer; inline; overload;
|
||
|
function AnsiLow(const aString: RawByteString): Integer; inline; overload;
|
||
|
function AnsiHigh(const aString: RawByteString): Integer; inline; overload;
|
||
|
{$ENDIF}
|
||
|
|
||
|
implementation
|
||
|
|
||
|
function UTF8ToString(const aUTF8String: TORawByteString): String;
|
||
|
begin
|
||
|
Result := aUTF8String.GetString(TEncoding.UTF8);
|
||
|
end;
|
||
|
|
||
|
function UTF8Decode(const aUTF8String: TORawByteString): String;
|
||
|
begin
|
||
|
Result := aUTF8String.GetString(TEncoding.UTF8);
|
||
|
end;
|
||
|
|
||
|
function UTF8Encode(const aString: String): TORawByteString;
|
||
|
begin
|
||
|
Result.SetString(aString, TEncoding.UTF8);
|
||
|
end;
|
||
|
|
||
|
function Pos(const aSubStr: String; const aString: TORawByteString): Integer;
|
||
|
begin
|
||
|
Result := aString.Pos(TORawByteString(aSubStr)) + 1;
|
||
|
end;
|
||
|
|
||
|
function Pos(const aSubStr, aString: TORawByteString): Integer;
|
||
|
begin
|
||
|
Result := aString.Pos(aSubStr) + 1;
|
||
|
end;
|
||
|
|
||
|
function PosEx(const aSubStr: String; const aString: TORawByteString; aOffset: Integer): Integer; inline; overload;
|
||
|
begin
|
||
|
Result := aString.PosEx(TORawByteString(aSubStr), aOffset - 1) + 1;
|
||
|
end;
|
||
|
|
||
|
function PosEx(const aSubStr, aString: TORawByteString; aOffset: Integer): Integer; inline; overload;
|
||
|
begin
|
||
|
Result := aString.PosEx(aSubStr, aOffset - 1) + 1;
|
||
|
end;
|
||
|
|
||
|
function LowerCase(const aString: TORawByteString): TORawByteString;
|
||
|
begin
|
||
|
Result := aString;
|
||
|
Result.ToLower;
|
||
|
end;
|
||
|
|
||
|
function UpperCase(const aString: TORawByteString): TORawByteString;
|
||
|
begin
|
||
|
Result := aString;
|
||
|
Result.ToUpper;
|
||
|
end;
|
||
|
|
||
|
function CompareStr(const S1, S2: TORawByteString): Integer;
|
||
|
begin
|
||
|
Result := SysUtils.CompareStr(S1.GetString, S2.GetString);
|
||
|
end;
|
||
|
|
||
|
function CompareText(const S1, S2: TORawByteString): Integer;
|
||
|
begin
|
||
|
Result := SysUtils.CompareText(S1.GetString, S2.GetString);
|
||
|
end;
|
||
|
|
||
|
function AnsiCopy(const aString: TORawByteString; aIndex, aCount: Integer): TORawByteString;
|
||
|
begin
|
||
|
Result := aString.Copy(aIndex - 1, aCount);
|
||
|
end;
|
||
|
|
||
|
procedure AnsiInsert(const aSubString: TORawByteString; var aString: TORawByteString; aIndex: Integer);
|
||
|
begin
|
||
|
aString.Insert(aSubString, aIndex-1);
|
||
|
end;
|
||
|
|
||
|
procedure AnsiDelete(var aString: TORawByteString; aIndex, aCount: Integer);
|
||
|
begin
|
||
|
aString.Delete(aIndex-1, aCount);
|
||
|
end;
|
||
|
|
||
|
function AnsiLength(const aString: TORawByteString): Integer;
|
||
|
begin
|
||
|
Result := aString.Length;
|
||
|
end;
|
||
|
|
||
|
function AnsiLow(const aString: TORawByteString): Integer;
|
||
|
begin
|
||
|
Result := 1;
|
||
|
end;
|
||
|
|
||
|
function AnsiHigh(const aString: TORawByteString): Integer;
|
||
|
begin
|
||
|
Result := aString.Length;;
|
||
|
end;
|
||
|
|
||
|
{$IFNDEF NEXTGEN}
|
||
|
function AnsiCopy(const aString: RawByteString; aIndex, aCount: Integer): RawByteString;
|
||
|
begin
|
||
|
Result := System.Copy(aString, aIndex, aCount);
|
||
|
end;
|
||
|
|
||
|
procedure AnsiInsert(const aSubString: RawByteString; var aString: RawByteString; aIndex: Integer);
|
||
|
begin
|
||
|
System.Insert(aSubString, aString, aIndex);
|
||
|
end;
|
||
|
|
||
|
procedure AnsiDelete(var aString: RawByteString; aIndex, aCount: Integer);
|
||
|
begin
|
||
|
System.Delete(aString, aIndex, aCount);
|
||
|
end;
|
||
|
|
||
|
function AnsiLength(const aString: RawByteString): Integer;
|
||
|
begin
|
||
|
Result := System.Length(aString);
|
||
|
end;
|
||
|
|
||
|
function AnsiLow(const aString: RawByteString): Integer;
|
||
|
begin
|
||
|
Result := 1;
|
||
|
end;
|
||
|
|
||
|
function AnsiHigh(const aString: RawByteString): Integer;
|
||
|
begin
|
||
|
Result := Length(aString);
|
||
|
end;
|
||
|
{$ENDIF}
|
||
|
|
||
|
{ TORawByteString }
|
||
|
|
||
|
class operator TORawByteString.Add(const a1, a2: TORawByteString): TORawByteString;
|
||
|
begin
|
||
|
Result := a1;
|
||
|
Result.Append(a2);
|
||
|
end;
|
||
|
|
||
|
class operator TORawByteString.Add(const a1: TORawByteString;
|
||
|
const a2: TBytes): TORawByteString;
|
||
|
begin
|
||
|
Result := a1;
|
||
|
Result.Append(a2);
|
||
|
end;
|
||
|
|
||
|
class operator TORawByteString.Add(const a1: TBytes;
|
||
|
const a2: TORawByteString): TORawByteString;
|
||
|
begin
|
||
|
Result := a2;
|
||
|
Result.Prepend(a1);
|
||
|
end;
|
||
|
|
||
|
class operator TORawByteString.Add(const a1: TORawByteString;
|
||
|
const a2: TORawByteChar): TORawByteString;
|
||
|
begin
|
||
|
Result.Length := a1.Length + 1;
|
||
|
if a1.Length > 0 then
|
||
|
System.Move(a1.GetBuffer[0], Result.GetBuffer[0], a1.Length);//we don't need COW check, writing to result
|
||
|
Result[Result.Length-1] := a2;
|
||
|
end;
|
||
|
|
||
|
class operator TORawByteString.Add(const a1: TORawByteChar;
|
||
|
const a2: TORawByteString): TORawByteString;
|
||
|
begin
|
||
|
Result := a2 + a1;
|
||
|
end;
|
||
|
|
||
|
procedure TORawByteString.Append(const aBuffer;
|
||
|
aBufferLength: Integer);
|
||
|
var
|
||
|
xOldLength: Integer;
|
||
|
begin
|
||
|
if aBufferLength > 0 then
|
||
|
begin
|
||
|
xOldLength := Length;
|
||
|
Length := Length + aBufferLength;
|
||
|
|
||
|
System.Move(aBuffer, GetBuffer[xOldLength], aBufferLength);//we don't need COW check, SetLength does it
|
||
|
end;
|
||
|
end;
|
||
|
|
||
|
procedure TORawByteString.Append(
|
||
|
const aBuffer: TORawByteString);
|
||
|
begin
|
||
|
if aBuffer.Length > 0 then
|
||
|
Append(aBuffer.GetBuffer[0], aBuffer.Length)
|
||
|
end;
|
||
|
|
||
|
procedure TORawByteString.Append(const aBytes: TBytes);
|
||
|
begin
|
||
|
if System.Length(aBytes) > 0 then
|
||
|
Append(aBytes[0], System.Length(aBytes))
|
||
|
end;
|
||
|
|
||
|
procedure TORawByteString.Clear;
|
||
|
begin
|
||
|
SetLength(0);
|
||
|
end;
|
||
|
|
||
|
function TORawByteString.Copy(aIndex, aCount: Integer): TORawByteString;
|
||
|
begin
|
||
|
Assert((aIndex >= 0) and (aIndex + aCount <= Length));
|
||
|
|
||
|
Result.Length := aCount;
|
||
|
if aCount > 0 then
|
||
|
System.Move(GetBuffer[aIndex], Result.GetBuffer[0], aCount);//we don't need COW check, writing to result
|
||
|
end;
|
||
|
|
||
|
procedure TORawByteString.CopyOnWriteCheck;
|
||
|
function RefCount: Integer;
|
||
|
var
|
||
|
xStrPtr: ^Integer;
|
||
|
begin
|
||
|
//get reference count of FStrBuffer, correct results on 32bit, 64bit and also mobile
|
||
|
xStrPtr := Pointer(PChar(FStrBuffer));
|
||
|
Dec(xStrPtr, 2);
|
||
|
Result := xStrPtr^;
|
||
|
end;
|
||
|
begin
|
||
|
if (FStrBuffer <> '') and (RefCount > 1) then//if RefCount is only 1, we don't need CopyOnWrite
|
||
|
FStrBuffer := System.Copy(FStrBuffer, 1, System.Length(FStrBuffer));//Simulate COW
|
||
|
end;
|
||
|
|
||
|
constructor TORawByteString.Create(const aString: string;
|
||
|
aEncoding: TEncoding);
|
||
|
begin
|
||
|
SetString(aString, aEncoding);
|
||
|
end;
|
||
|
|
||
|
procedure TORawByteString.Delete(aIndex, aCount: Integer);
|
||
|
begin
|
||
|
Assert((aIndex >= 0) and (aIndex + aCount <= Length));
|
||
|
|
||
|
if aCount <= 0 then
|
||
|
Exit;
|
||
|
|
||
|
CopyOnWriteCheck;//we need copy on write check here because Move() is performed on Self before SetLength!
|
||
|
|
||
|
if aIndex+aCount < Length then
|
||
|
System.Move(GetBuffer[aIndex+aCount], GetBuffer[aIndex], Length-(aIndex+aCount));
|
||
|
|
||
|
Length := Length-aCount;
|
||
|
end;
|
||
|
|
||
|
constructor TORawByteString.Create(const aBytes: TBytes);
|
||
|
begin
|
||
|
SetBytes(aBytes);
|
||
|
end;
|
||
|
|
||
|
class operator TORawByteString.Equal(const a1, a2: TORawByteString): Boolean;
|
||
|
var
|
||
|
xL1, xL2: Integer;
|
||
|
begin
|
||
|
//optimization -> compare memory
|
||
|
xL1 := a1.Length;
|
||
|
xL2 := a2.Length;
|
||
|
|
||
|
Result :=
|
||
|
(a1.GetBuffer = a2.GetBuffer) or (//same string reference
|
||
|
(xL1 = xL2) and
|
||
|
((xL1 = 0) or (CompareMem(a1.GetBuffer, a2.GetBuffer, xL1))));
|
||
|
end;
|
||
|
|
||
|
{$IFDEF ORAW_IMPLICIT}
|
||
|
class operator TORawByteString.Implicit(const a: TORawByteString): PORawByteChar;
|
||
|
{$ELSE}
|
||
|
class operator TORawByteString.Explicit(const a: TORawByteString): PORawByteChar;
|
||
|
{$ENDIF}
|
||
|
begin
|
||
|
if a.Length > 0 then
|
||
|
begin
|
||
|
Result := PORawByteChar(a.GetBuffer);
|
||
|
end else
|
||
|
Result := nil;
|
||
|
end;
|
||
|
|
||
|
function TORawByteString.GetBuffer: PByteArray;
|
||
|
begin
|
||
|
if FStrBuffer <> '' then
|
||
|
Result := PByteArray(@PChar(FStrBuffer)[2])//real buffer length is stored in the first 2 char positions
|
||
|
else
|
||
|
Result := nil;
|
||
|
end;
|
||
|
|
||
|
function TORawByteString.GetBytes: TBytes;
|
||
|
begin
|
||
|
System.SetLength(Result, Length);
|
||
|
if Length > 0 then
|
||
|
System.Move(GetBuffer[0], Result[0], Length);//we don't need COW check, writing to result
|
||
|
end;
|
||
|
|
||
|
function TORawByteString.GetEnumerator: TORawByteStringCharEnumerator;
|
||
|
begin
|
||
|
Result := TORawByteStringCharEnumerator.Create(@Self);
|
||
|
end;
|
||
|
|
||
|
function TORawByteString.GetLength: Integer;
|
||
|
begin
|
||
|
if FStrBuffer = '' then//must be here -> FBufferByteLength may be uninitialized
|
||
|
Result := 0
|
||
|
else
|
||
|
Result := PInteger(PChar(FStrBuffer))^;//real buffer length is stored in the first 2 char positions
|
||
|
end;
|
||
|
|
||
|
function TORawByteString.GetChar(const aIndex: Integer): TORawByteChar;
|
||
|
begin
|
||
|
Result := TORawByteChar(GetBuffer[aIndex]);
|
||
|
end;
|
||
|
|
||
|
class function TORawByteString.GetDefaultEncoding: TEncoding;
|
||
|
begin
|
||
|
if not Assigned(FDefaultEncoding) then
|
||
|
FDefaultEncoding := TEncoding.RawByte;
|
||
|
|
||
|
Result := FDefaultEncoding;
|
||
|
end;
|
||
|
|
||
|
function TORawByteString.GetDefChar(const aIndex: Integer): TORawByteChar;
|
||
|
begin
|
||
|
Result := GetChar(aIndex-1);
|
||
|
end;
|
||
|
|
||
|
type
|
||
|
TEncodingProt = class(TEncoding)
|
||
|
public
|
||
|
function GetCharCountProt(Bytes: PByte; ByteCount: Integer): Integer;
|
||
|
function GetCharsProt(Bytes: PByte; ByteCount: Integer; Chars: PChar; CharCount: Integer): Integer;
|
||
|
function GetByteCountProt(Chars: PChar; CharCount: Integer): Integer;
|
||
|
function GetBytesProt(Chars: PChar; CharCount: Integer; Bytes: PByte; ByteCount: Integer): Integer;
|
||
|
end;
|
||
|
|
||
|
function TEncodingProt.GetCharCountProt(Bytes: PByte; ByteCount: Integer): Integer;
|
||
|
begin
|
||
|
Result := GetCharCount(Bytes, ByteCount);
|
||
|
end;
|
||
|
|
||
|
function TEncodingProt.GetCharsProt(Bytes: PByte; ByteCount: Integer; Chars: PChar; CharCount: Integer): Integer;
|
||
|
begin
|
||
|
Result := GetChars(Bytes, ByteCount, Chars, CharCount);
|
||
|
end;
|
||
|
|
||
|
function TEncodingProt.GetByteCountProt(Chars: PChar; CharCount: Integer): Integer;
|
||
|
begin
|
||
|
Result := GetByteCount(Chars, CharCount);
|
||
|
end;
|
||
|
|
||
|
function TEncodingProt.GetBytesProt(Chars: PChar; CharCount: Integer; Bytes: PByte; ByteCount: Integer): Integer;
|
||
|
begin
|
||
|
Result := GetBytes(Chars, CharCount, Bytes, ByteCount);
|
||
|
end;
|
||
|
|
||
|
function TORawByteString.GetString(aEncoding: TEncoding): string;
|
||
|
var
|
||
|
xCharCount: Integer;
|
||
|
begin
|
||
|
if not Assigned(aEncoding) then
|
||
|
aEncoding := GetDefaultEncoding;
|
||
|
|
||
|
xCharCount := TEncodingProt(aEncoding).GetCharCountProt(PByte(GetBuffer), Length);
|
||
|
System.SetLength(Result, xCharCount);
|
||
|
if xCharCount = 0 then
|
||
|
Exit('');
|
||
|
TEncodingProt(aEncoding).GetCharsProt(PByte(GetBuffer), Length, PChar(Result), xCharCount);//we don't need COW check, writing to result
|
||
|
end;
|
||
|
|
||
|
{$IFDEF ORAW_IMPLICIT}
|
||
|
class operator TORawByteString.Implicit(const a: TBytes): TORawByteString;
|
||
|
{$ELSE}
|
||
|
class operator TORawByteString.Explicit(const a: TBytes): TORawByteString;
|
||
|
{$ENDIF}
|
||
|
begin
|
||
|
Result.SetBytes(a);
|
||
|
end;
|
||
|
|
||
|
{$IFDEF ORAW_IMPLICIT}
|
||
|
class operator TORawByteString.Implicit(const a: TORawByteString): TBytes;
|
||
|
{$ELSE}
|
||
|
class operator TORawByteString.Explicit(const a: TORawByteString): TBytes;
|
||
|
{$ENDIF}
|
||
|
begin
|
||
|
Result := a.GetBytes;
|
||
|
end;
|
||
|
|
||
|
procedure TORawByteString.Insert(const aSubBuffer: TORawByteString;
|
||
|
aIndex: Integer);
|
||
|
begin
|
||
|
if aSubBuffer.Length > 0 then
|
||
|
Insert(aSubBuffer.GetBuffer[0], aSubBuffer.Length, aIndex)
|
||
|
end;
|
||
|
|
||
|
procedure TORawByteString.Insert(const aSubBytes: TBytes;
|
||
|
aIndex: Integer);
|
||
|
begin
|
||
|
if System.Length(aSubBytes) > 0 then
|
||
|
Insert(aSubBytes[0], System.Length(aSubBytes), aIndex)
|
||
|
end;
|
||
|
|
||
|
procedure TORawByteString.Insert(const aSubBuffer;
|
||
|
aSubBufferLength, aIndex: Integer);
|
||
|
var
|
||
|
xOldLength: Integer;
|
||
|
begin
|
||
|
if aSubBufferLength > 0 then
|
||
|
begin
|
||
|
Assert((aIndex >= 0) and (aIndex <= Length));
|
||
|
|
||
|
xOldLength := Length;
|
||
|
Length := Length + aSubBufferLength;
|
||
|
if aIndex < xOldLength then
|
||
|
System.Move(GetBuffer[aIndex], GetBuffer[aIndex+aSubBufferLength], xOldLength-aIndex);//we don't need COW check, SetLength does it
|
||
|
System.Move(aSubBuffer, GetBuffer[aIndex], aSubBufferLength);
|
||
|
end;
|
||
|
end;
|
||
|
|
||
|
{$IFDEF ORAW_IMPLICIT}
|
||
|
class operator TORawByteString.Implicit(const a: string): TORawByteString;
|
||
|
{$ELSE}
|
||
|
class operator TORawByteString.Explicit(const a: string): TORawByteString;
|
||
|
{$ENDIF}
|
||
|
begin
|
||
|
Result.SetString(a);
|
||
|
end;
|
||
|
|
||
|
{$IFDEF ORAW_IMPLICIT}
|
||
|
class operator TORawByteString.Implicit(const a: TORawByteString): string;
|
||
|
{$ELSE}
|
||
|
class operator TORawByteString.Explicit(const a: TORawByteString): string;
|
||
|
{$ENDIF}
|
||
|
begin
|
||
|
Result := a.GetString;
|
||
|
end;
|
||
|
|
||
|
procedure TORawByteString.LoadFromFile(const aFileName: string);
|
||
|
var
|
||
|
xS: TStream;
|
||
|
begin
|
||
|
xS := TFileStream.Create(aFileName, fmOpenRead or fmShareDenyWrite);
|
||
|
try
|
||
|
LoadFromStream(xS);
|
||
|
finally
|
||
|
xS.Free;
|
||
|
end;
|
||
|
end;
|
||
|
|
||
|
procedure TORawByteString.LoadFromStream(const aStream: TStream);
|
||
|
begin
|
||
|
Length := aStream.Size-aStream.Position;
|
||
|
if Length > 0 then
|
||
|
begin
|
||
|
CopyOnWriteCheck;//we need COW check, Length may stay unchanged!!!
|
||
|
aStream.ReadBuffer(GetBuffer[0], Length);
|
||
|
end;
|
||
|
end;
|
||
|
|
||
|
class operator TORawByteString.NotEqual(const a1, a2: TORawByteString): Boolean;
|
||
|
begin
|
||
|
Result := not(a1 = a2);
|
||
|
end;
|
||
|
|
||
|
function TORawByteString.Pos(const aSubStr: TORawByteString): Integer;
|
||
|
begin
|
||
|
Result := PosEx(aSubStr, 0);
|
||
|
end;
|
||
|
|
||
|
function TORawByteString.PosEx(const aSubStr: TORawByteString; aOffset: Integer): Integer;
|
||
|
var
|
||
|
xSubBuffer: PByteArray;
|
||
|
xSubLength: Integer;
|
||
|
xSelfBuffer: PByteArray;
|
||
|
xSelfLength: Integer;
|
||
|
begin
|
||
|
Assert((aSubStr.Length > 0) and (aOffset >= 0));
|
||
|
|
||
|
xSelfBuffer := GetBuffer;
|
||
|
xSelfLength := Length;
|
||
|
xSubBuffer := aSubStr.GetBuffer;
|
||
|
xSubLength := aSubStr.Length;
|
||
|
while aOffset <= (xSelfLength-xSubLength) do
|
||
|
begin
|
||
|
if CompareMem(@xSubBuffer[0], @xSelfBuffer[aOffset], xSubLength) then
|
||
|
begin
|
||
|
Result := aOffset;
|
||
|
Exit;
|
||
|
end;
|
||
|
Inc(aOffset);
|
||
|
end;
|
||
|
Result := -1;
|
||
|
end;
|
||
|
|
||
|
procedure TORawByteString.Prepend(const aBuffer;
|
||
|
aBufferLength: Integer);
|
||
|
var
|
||
|
xOldLength: Integer;
|
||
|
begin
|
||
|
if aBufferLength > 0 then
|
||
|
begin
|
||
|
xOldLength := Length;
|
||
|
Length := Length + aBufferLength;
|
||
|
|
||
|
if xOldLength > 0 then
|
||
|
System.Move(GetBuffer[0], GetBuffer[aBufferLength], xOldLength);//we don't need COW check, SetLength does it
|
||
|
if aBufferLength > 0 then
|
||
|
System.Move(aBuffer, GetBuffer[0], aBufferLength);
|
||
|
end;
|
||
|
end;
|
||
|
|
||
|
procedure TORawByteString.Prepend(
|
||
|
const aBuffer: TORawByteString);
|
||
|
begin
|
||
|
if aBuffer.Length > 0 then
|
||
|
Prepend(aBuffer.GetBuffer[0], aBuffer.Length)
|
||
|
end;
|
||
|
|
||
|
procedure TORawByteString.Prepend(const aBytes: TBytes);
|
||
|
begin
|
||
|
if System.Length(aBytes) > 0 then
|
||
|
Prepend(aBytes[0], System.Length(aBytes))
|
||
|
end;
|
||
|
|
||
|
procedure TORawByteString.SaveToFile(const aFileName: string;
|
||
|
const aWriteBOM: Boolean);
|
||
|
var
|
||
|
xS: TStream;
|
||
|
begin
|
||
|
xS := TFileStream.Create(aFileName, fmCreate);
|
||
|
try
|
||
|
SaveToStream(xS, aWriteBOM);
|
||
|
finally
|
||
|
xS.Free;
|
||
|
end;
|
||
|
end;
|
||
|
|
||
|
procedure TORawByteString.SaveToStream(const aStream: TStream;
|
||
|
const aWriteBOM: Boolean);
|
||
|
begin
|
||
|
if Length > 0 then
|
||
|
aStream.WriteBuffer(GetBuffer[0], Length);
|
||
|
end;
|
||
|
|
||
|
procedure TORawByteString.SetBytes(const aBytes: TBytes);
|
||
|
begin
|
||
|
Length := System.Length(aBytes);
|
||
|
if Length > 0 then
|
||
|
begin
|
||
|
CopyOnWriteCheck;//we need COW check, the length may stay unchanged
|
||
|
System.Move(aBytes[0], GetBuffer[0], Length);
|
||
|
end;
|
||
|
end;
|
||
|
|
||
|
procedure TORawByteString.SetLength(const aLength: Integer);
|
||
|
var
|
||
|
xNewLength: Integer;
|
||
|
begin
|
||
|
if aLength = 0 then//empty string, just empty the buffer
|
||
|
FStrBuffer := ''
|
||
|
else
|
||
|
if Length <> aLength then
|
||
|
begin
|
||
|
xNewLength := (aLength div 2) + 3;//we need max 3 extra characters (2 for integer length + 1/2 for trailing zero).
|
||
|
|
||
|
if xNewLength = System.Length(FStrBuffer) then
|
||
|
CopyOnWriteCheck//byte length is different, but FStrBuffer remained the same -> we need COW
|
||
|
else
|
||
|
System.SetLength(FStrBuffer, xNewLength);//different lengths -> Delphi handles COW
|
||
|
|
||
|
PInteger(PChar(FStrBuffer))^ := aLength;//real buffer length is stored in the first 2 char positions
|
||
|
GetBuffer[Length] := 0;//write trailing zero (for PAnsiChar support)!
|
||
|
end;
|
||
|
end;
|
||
|
|
||
|
procedure TORawByteString.SetChar(const aIndex: Integer; const aChar: TORawByteChar);
|
||
|
begin
|
||
|
Assert((aIndex >= 0) and (aIndex < Length));
|
||
|
|
||
|
CopyOnWriteCheck;//we need COW check here because we change buffer value of the string
|
||
|
GetBuffer[aIndex] := Byte(aChar);
|
||
|
end;
|
||
|
|
||
|
class procedure TORawByteString.SetDefaultEncoding(aEncoding: TEncoding);
|
||
|
begin
|
||
|
FDefaultEncoding := aEncoding;
|
||
|
end;
|
||
|
|
||
|
procedure TORawByteString.SetDefChar(const aIndex: Integer;
|
||
|
const aChar: TORawByteChar);
|
||
|
begin
|
||
|
SetChar(aIndex-1, aChar);
|
||
|
end;
|
||
|
|
||
|
procedure TORawByteString.SetString(const aString: string; aEncoding: TEncoding);
|
||
|
begin
|
||
|
if not Assigned(aEncoding) then
|
||
|
aEncoding := GetDefaultEncoding;
|
||
|
|
||
|
Length := TEncodingProt(aEncoding).GetByteCountProt(PChar(aString), System.Length(aString));
|
||
|
if Length > 0 then
|
||
|
begin
|
||
|
CopyOnWriteCheck;//we need COW check here because the length may stay unchanged!
|
||
|
TEncodingProt(aEncoding).GetBytesProt(PChar(aString), System.Length(aString), PByte(GetBuffer), Length);
|
||
|
end;
|
||
|
end;
|
||
|
|
||
|
procedure TORawByteString.ToLower(aEncoding: TEncoding);
|
||
|
var
|
||
|
I: Integer;
|
||
|
xByte: PByte;
|
||
|
begin
|
||
|
if not Assigned(aEncoding) then
|
||
|
aEncoding := GetDefaultEncoding;
|
||
|
|
||
|
if aEncoding is TORawSingleByteEncoding then
|
||
|
begin//RawByteString
|
||
|
CopyOnWriteCheck;//we need COW check here because we modify buffer directly
|
||
|
xByte := PByte(GetBuffer);
|
||
|
for I := 0 to Length-1 do
|
||
|
begin
|
||
|
case xByte^ of
|
||
|
Ord('A')..Ord('Z'): xByte^ := xByte^ + $20;
|
||
|
end;
|
||
|
Inc(xByte);
|
||
|
end;
|
||
|
end else
|
||
|
SetString(SysUtils.LowerCase(GetString(aEncoding)), aEncoding);
|
||
|
end;
|
||
|
|
||
|
procedure TORawByteString.ToUpper(aEncoding: TEncoding);
|
||
|
var
|
||
|
I: Integer;
|
||
|
xByte: PByte;
|
||
|
begin
|
||
|
if not Assigned(aEncoding) then
|
||
|
aEncoding := GetDefaultEncoding;
|
||
|
|
||
|
if aEncoding is TORawSingleByteEncoding then
|
||
|
begin//RawByteString
|
||
|
CopyOnWriteCheck;//we need COW check here because we modify buffer directly
|
||
|
xByte := PByte(GetBuffer);
|
||
|
for I := 0 to Length-1 do
|
||
|
begin
|
||
|
case xByte^ of
|
||
|
Ord('a')..Ord('z'): xByte^ := xByte^ - $20;
|
||
|
end;
|
||
|
Inc(xByte);
|
||
|
end;
|
||
|
end else
|
||
|
SetString(SysUtils.UpperCase(GetString(aEncoding)), aEncoding);
|
||
|
end;
|
||
|
|
||
|
{$IFDEF ORAW_IMPLICIT}
|
||
|
class operator TORawByteString.Implicit(const a: PORawByteChar): TORawByteString;
|
||
|
{$ELSE}
|
||
|
class operator TORawByteString.Explicit(const a: PORawByteChar): TORawByteString;
|
||
|
{$ENDIF}
|
||
|
var
|
||
|
xC: PByte;
|
||
|
begin
|
||
|
xC := PByte(a);
|
||
|
while xC^ <> 0 do
|
||
|
Inc(xC);
|
||
|
|
||
|
Result.Length := 0;
|
||
|
Result.Append(a^, NativeInt(xC)-NativeInt(a));
|
||
|
end;
|
||
|
|
||
|
{ TORawByteString.TORawByteStringCharEnumerator }
|
||
|
|
||
|
constructor TORawByteString.TORawByteStringCharEnumerator.Create(
|
||
|
aBuffer: PORawByteString);
|
||
|
begin
|
||
|
inherited Create;
|
||
|
|
||
|
FIndex := -1;
|
||
|
FString := aBuffer;
|
||
|
end;
|
||
|
|
||
|
function TORawByteString.TORawByteStringCharEnumerator.GetCurrent: TORawByteChar;
|
||
|
begin
|
||
|
Result := FString^.GetChar(FIndex);
|
||
|
end;
|
||
|
|
||
|
function TORawByteString.TORawByteStringCharEnumerator.MoveNext: Boolean;
|
||
|
begin
|
||
|
Result := FIndex < FString.Length - 1;
|
||
|
if Result then
|
||
|
Inc(FIndex);
|
||
|
end;
|
||
|
|
||
|
{ TORawSingleByteEncoding }
|
||
|
|
||
|
constructor TORawSingleByteEncoding.Create;
|
||
|
begin
|
||
|
inherited;
|
||
|
|
||
|
FIsSingleByte := True;
|
||
|
FMaxCharSize := 1;
|
||
|
end;
|
||
|
|
||
|
destructor TORawSingleByteEncoding.Destroy;
|
||
|
begin
|
||
|
if Self = FSavedInstance then
|
||
|
FSavedInstance := nil;
|
||
|
|
||
|
inherited;
|
||
|
end;
|
||
|
|
||
|
class destructor TORawSingleByteEncoding.Destroy;
|
||
|
begin
|
||
|
//no need to initialize FSavedInstance in class constructor to nil
|
||
|
// (global variables are automatically initialized).
|
||
|
//the FSavedInstance is set to nil in the destructor
|
||
|
FSavedInstance.Free;
|
||
|
|
||
|
inherited;
|
||
|
end;
|
||
|
|
||
|
function TORawSingleByteEncoding.GetByteCount(Chars: PChar;
|
||
|
CharCount: Integer): Integer;
|
||
|
begin
|
||
|
Result := CharCount;
|
||
|
end;
|
||
|
|
||
|
function TORawSingleByteEncoding.GetBytes(Chars: PChar; CharCount: Integer;
|
||
|
Bytes: PByte; ByteCount: Integer): Integer;
|
||
|
var
|
||
|
I: Integer;
|
||
|
C: PWord;
|
||
|
begin
|
||
|
Result := ByteCount;
|
||
|
if Result > CharCount then
|
||
|
Result := CharCount;
|
||
|
|
||
|
if Result > 0 then
|
||
|
begin
|
||
|
C := PWord(Chars);
|
||
|
for I := 0 to Result-1 do
|
||
|
begin
|
||
|
Bytes[I] := (C^ and $FF);
|
||
|
Inc(C);
|
||
|
end;
|
||
|
end;
|
||
|
end;
|
||
|
|
||
|
function TORawSingleByteEncoding.GetCharCount(Bytes: PByte;
|
||
|
ByteCount: Integer): Integer;
|
||
|
begin
|
||
|
Result := ByteCount;
|
||
|
end;
|
||
|
|
||
|
function TORawSingleByteEncoding.GetChars(Bytes: PByte; ByteCount: Integer;
|
||
|
Chars: PChar; CharCount: Integer): Integer;
|
||
|
var
|
||
|
I: Integer;
|
||
|
C: PWord;
|
||
|
begin
|
||
|
Result := ByteCount;
|
||
|
if Result > CharCount then
|
||
|
Result := CharCount;
|
||
|
|
||
|
if Result > 0 then
|
||
|
begin
|
||
|
C := PWord(Chars);
|
||
|
for I := 0 to Result-1 do
|
||
|
begin
|
||
|
C^ := Bytes[I];
|
||
|
Inc(C);
|
||
|
end;
|
||
|
end;
|
||
|
end;
|
||
|
|
||
|
function TORawSingleByteEncoding.GetMaxByteCount(CharCount: Integer): Integer;
|
||
|
begin
|
||
|
Result := CharCount;
|
||
|
end;
|
||
|
|
||
|
function TORawSingleByteEncoding.GetMaxCharCount(ByteCount: Integer): Integer;
|
||
|
begin
|
||
|
Result := ByteCount;
|
||
|
end;
|
||
|
|
||
|
function TORawSingleByteEncoding.GetPreamble: TBytes;
|
||
|
begin
|
||
|
SetLength(Result, 0);
|
||
|
end;
|
||
|
|
||
|
class function TORawSingleByteEncoding.Use: TORawSingleByteEncoding;
|
||
|
begin
|
||
|
if not Assigned(FSavedInstance) then
|
||
|
FSavedInstance := TORawSingleByteEncoding.Create;
|
||
|
|
||
|
Result := FSavedInstance;
|
||
|
end;
|
||
|
|
||
|
{ TORawByteChar }
|
||
|
|
||
|
class operator TORawByteChar.Equal(const a1, a2: TORawByteChar): Boolean;
|
||
|
begin
|
||
|
Result := a1.FChar = a2.FChar;
|
||
|
end;
|
||
|
|
||
|
class operator TORawByteChar.Equal(const a1: TORawByteChar;
|
||
|
const a2: Char): Boolean;
|
||
|
begin
|
||
|
Result := a1.FChar = (Ord(a2) and $FF);
|
||
|
end;
|
||
|
|
||
|
class operator TORawByteChar.Equal(const a1: Char;
|
||
|
const a2: TORawByteChar): Boolean;
|
||
|
begin
|
||
|
Result := (Ord(a1) and $FF) = a2.FChar;
|
||
|
end;
|
||
|
|
||
|
{$IFDEF ORAW_IMPLICIT}
|
||
|
class operator TORawByteChar.Implicit(const a: Char): TORawByteChar;
|
||
|
{$ELSE}
|
||
|
class operator TORawByteChar.Explicit(const a: Char): TORawByteChar;
|
||
|
{$ENDIF}
|
||
|
begin
|
||
|
Result.FChar := (Ord(a) and $FF);
|
||
|
end;
|
||
|
|
||
|
{$IFDEF ORAW_IMPLICIT}
|
||
|
class operator TORawByteChar.Implicit(const a: TORawByteChar): Char;
|
||
|
{$ELSE}
|
||
|
class operator TORawByteChar.Explicit(const a: TORawByteChar): Char;
|
||
|
{$ENDIF}
|
||
|
begin
|
||
|
Result := Char(a.FChar);
|
||
|
end;
|
||
|
|
||
|
class operator TORawByteChar.GreaterThan(const a1, a2: TORawByteChar): Boolean;
|
||
|
begin
|
||
|
Result := a1.FChar > a2.FChar;
|
||
|
end;
|
||
|
|
||
|
class operator TORawByteChar.GreaterThan(const a1: TORawByteChar;
|
||
|
const a2: Char): Boolean;
|
||
|
begin
|
||
|
Result := a1.FChar > (Ord(a2) and $FF);
|
||
|
end;
|
||
|
|
||
|
class operator TORawByteChar.GreaterThan(const a1: Char;
|
||
|
const a2: TORawByteChar): Boolean;
|
||
|
begin
|
||
|
Result := (Ord(a1) and $FF) > a2.FChar;
|
||
|
end;
|
||
|
|
||
|
class operator TORawByteChar.GreaterThanOrEqual(const a1: Char;
|
||
|
const a2: TORawByteChar): Boolean;
|
||
|
begin
|
||
|
Result := (Ord(a1) and $FF) >= a2.FChar;
|
||
|
end;
|
||
|
|
||
|
class operator TORawByteChar.GreaterThanOrEqual(const a1: TORawByteChar;
|
||
|
const a2: Char): Boolean;
|
||
|
begin
|
||
|
Result := a1.FChar >= (Ord(a2) and $FF);
|
||
|
end;
|
||
|
|
||
|
class operator TORawByteChar.GreaterThanOrEqual(const a1,
|
||
|
a2: TORawByteChar): Boolean;
|
||
|
begin
|
||
|
Result := a1.FChar >= a2.FChar;
|
||
|
end;
|
||
|
|
||
|
class operator TORawByteChar.LessThan(const a1: Char;
|
||
|
const a2: TORawByteChar): Boolean;
|
||
|
begin
|
||
|
Result := (Ord(a1) and $FF) < a2.FChar;
|
||
|
end;
|
||
|
|
||
|
class operator TORawByteChar.LessThan(const a1: TORawByteChar;
|
||
|
const a2: Char): Boolean;
|
||
|
begin
|
||
|
Result := a1.FChar < (Ord(a2) and $FF);
|
||
|
end;
|
||
|
|
||
|
class operator TORawByteChar.LessThan(const a1, a2: TORawByteChar): Boolean;
|
||
|
begin
|
||
|
Result := a1.FChar < a2.FChar;
|
||
|
end;
|
||
|
|
||
|
class operator TORawByteChar.LessThanOrEqual(const a1,
|
||
|
a2: TORawByteChar): Boolean;
|
||
|
begin
|
||
|
Result := a1.FChar <= a2.FChar;
|
||
|
end;
|
||
|
|
||
|
class operator TORawByteChar.LessThanOrEqual(const a1: TORawByteChar;
|
||
|
const a2: Char): Boolean;
|
||
|
begin
|
||
|
Result := a1.FChar <= (Ord(a2) and $FF);
|
||
|
end;
|
||
|
|
||
|
class operator TORawByteChar.LessThanOrEqual(const a1: Char;
|
||
|
const a2: TORawByteChar): Boolean;
|
||
|
begin
|
||
|
Result := (Ord(a1) and $FF) <= a2.FChar;
|
||
|
end;
|
||
|
|
||
|
class operator TORawByteChar.NotEqual(const a1: TORawByteChar;
|
||
|
const a2: Char): Boolean;
|
||
|
begin
|
||
|
Result := a1.FChar = (Ord(a2) and $FF);
|
||
|
end;
|
||
|
|
||
|
class operator TORawByteChar.NotEqual(const a1: Char;
|
||
|
const a2: TORawByteChar): Boolean;
|
||
|
begin
|
||
|
Result := (Ord(a1) and $FF) = a2.FChar;
|
||
|
end;
|
||
|
|
||
|
function TORawByteChar.ToLower: TORawByteChar;
|
||
|
begin
|
||
|
case FChar of
|
||
|
Ord('A')..Ord('Z'): Result.FChar := FChar + $20;
|
||
|
else
|
||
|
Result := Self;
|
||
|
end;
|
||
|
end;
|
||
|
|
||
|
function TORawByteChar.ToUpper: TORawByteChar;
|
||
|
begin
|
||
|
case FChar of
|
||
|
Ord('a')..Ord('z'): Result.FChar := FChar - $20;
|
||
|
else
|
||
|
Result := Self;
|
||
|
end;
|
||
|
end;
|
||
|
|
||
|
class operator TORawByteChar.NotEqual(const a1, a2: TORawByteChar): Boolean;
|
||
|
begin
|
||
|
Result := a1.FChar <> a2.FChar;
|
||
|
end;
|
||
|
|
||
|
{$IFDEF ORAW_IMPLICIT}
|
||
|
class operator TORawByteChar.Implicit(const a: Byte): TORawByteChar;
|
||
|
{$ELSE}
|
||
|
class operator TORawByteChar.Explicit(const a: Byte): TORawByteChar;
|
||
|
{$ENDIF}
|
||
|
begin
|
||
|
Result.FChar := a;
|
||
|
end;
|
||
|
|
||
|
{$IFDEF ORAW_IMPLICIT}
|
||
|
class operator TORawByteChar.Implicit(const a: TORawByteChar): Byte;
|
||
|
{$ELSE}
|
||
|
class operator TORawByteChar.Explicit(const a: TORawByteChar): Byte;
|
||
|
{$ENDIF}
|
||
|
begin
|
||
|
Result := a.FChar;
|
||
|
end;
|
||
|
|
||
|
{ TEncodingHelper }
|
||
|
|
||
|
class function TEncodingHelper.RawByte: TEncoding;
|
||
|
begin
|
||
|
Result := TORawSingleByteEncoding.Use;
|
||
|
end;
|
||
|
|
||
|
end.
|