View Issue Details

IDProjectCategoryView StatusLast Update
0039268FPCRTLpublic2021-07-23 11:09
ReporterZeljko Avramovic Assigned ToMichael Van Canneyt  
PrioritynormalSeverityminorReproducibilityalways
Status assignedResolutionopen 
Product Version3.3.1 
Summary0039268: extended ordinal type helpers in sysutils
DescriptionAdded direct access to bit, nibble, byte, word and dword parts in ordinal types. Added international formatting for easily customized boolean, binary and hexadecimal string representation, following principles of current date/time/local international formatting principles in FPC (FormatSettings/DefaultFormatSettings).

Until I create FPC documentation, you can take a look here for more info about the added features:
https://forum.lazarus.freepascal.org/index.php/topic,41672.0.html
https://wiki.freepascal.org/BitHelpers

I am not quite sure if I have to change something about copyright or license info in the code to comply with FPC. My original library was LGPLv3/FPC modified LGPL/BSD3, but I don't mind if it becomes "FPC modified GPL" only. It is all my code so I can do any change needed.
TagsNo tags attached.
Fixed in Revision
FPCOldBugId
FPCTarget
Attached Files

Activities

Zeljko Avramovic

2021-07-20 09:25

reporter  

sysutils-bithelpers.patch (74,317 bytes)   
diff --git a/rtl/objpas/sysutils/syshelp.inc b/rtl/objpas/sysutils/syshelp.inc
index 1d6d4e50c2..2669a19452 100644
--- a/rtl/objpas/sysutils/syshelp.inc
+++ b/rtl/objpas/sysutils/syshelp.inc
@@ -1567,7 +1567,11 @@ end;
 {$define TORDINALHELPER:=TByteHelper}
 {$define TORDINALTYPE:=Byte}
 {$define TORDINALBITINDEX:=TByteBitIndex}
+{$define TORDINALNIBBLEINDEX:=TByteNibbleIndex}
+{$define TORDINALOVERLAY:=TByteOverlay}
+{$define TORDINALTYPESIZE1}
 {$i syshelpo.inc}
+{$undef TORDINALTYPESIZE1}
 
 { ---------------------------------------------------------------------
   TShortintHelper
@@ -1576,7 +1580,11 @@ end;
 {$define TORDINALHELPER:=TShortIntHelper}
 {$define TORDINALTYPE:=ShortInt}
 {$define TORDINALBITINDEX:=TShortIntBitIndex}
+{$define TORDINALNIBBLEINDEX:=TShortIntNibbleIndex}
+{$define TORDINALOVERLAY:=TShortIntOverlay}
+{$define TORDINALTYPESIZE1}
 {$i syshelpo.inc}
+{$undef TORDINALTYPESIZE1}
 
 { ---------------------------------------------------------------------
   TSmallintHelper
@@ -1585,7 +1593,12 @@ end;
 {$define TORDINALHELPER:=TSmallIntHelper}
 {$define TORDINALTYPE:=SmallInt}
 {$define TORDINALBITINDEX:=TSmallIntBitIndex}
+{$define TORDINALNIBBLEINDEX:=TSmallIntNibbleIndex}
+{$define TORDINALBYTEINDEX:=TWordByteIndex}
+{$define TORDINALOVERLAY:=TWordOverlay}
+{$define TORDINALTYPESIZE2}
 {$i syshelpo.inc}
+{$undef TORDINALTYPESIZE2}
 
 { ---------------------------------------------------------------------
   TWordHelper
@@ -1594,7 +1607,12 @@ end;
 {$define TORDINALHELPER:=TWordHelper}
 {$define TORDINALTYPE:=Word}
 {$define TORDINALBITINDEX:=TWordBitIndex}
+{$define TORDINALNIBBLEINDEX:=TWordNibbleIndex}
+{$define TORDINALBYTEINDEX:=TWordByteIndex}
+{$define TORDINALOVERLAY:=TWordOverlay}
+{$define TORDINALTYPESIZE2}
 {$i syshelpo.inc}
+{$undef TORDINALTYPESIZE2}
 
 { ---------------------------------------------------------------------
   TCardinalHelper
@@ -1603,7 +1621,13 @@ end;
 {$define TORDINALHELPER:=TCardinalHelper}
 {$define TORDINALTYPE:=Cardinal}
 {$define TORDINALBITINDEX:=TCardinalBitIndex}
+{$define TORDINALNIBBLEINDEX:=TCardinalNibbleIndex}
+{$define TORDINALBYTEINDEX:=TCardinalByteIndex}
+{$define TORDINALWORDINDEX:=TCardinalWordIndex}
+{$define TORDINALOVERLAY:=TDwordOverlay}
+{$define TORDINALTYPESIZE4}
 {$i syshelpo.inc}
+{$undef TORDINALTYPESIZE4}
 
 { ---------------------------------------------------------------------
   TIntegerHelper
@@ -1612,7 +1636,13 @@ end;
 {$define TORDINALHELPER:=TIntegerHelper}
 {$define TORDINALTYPE:=Integer}
 {$define TORDINALBITINDEX:=TIntegerBitIndex}
+{$define TORDINALNIBBLEINDEX:=TIntegerNibbleIndex}
+{$define TORDINALBYTEINDEX:=TIntegerByteIndex}
+{$define TORDINALWORDINDEX:=TIntegerWordIndex}
+{$define TORDINALOVERLAY:=TDwordOverlay}
+{$define TORDINALTYPESIZE4}
 {$i syshelpo.inc}
+{$undef TORDINALTYPESIZE4}
 
 { ---------------------------------------------------------------------
   TInt64Helper
@@ -1621,7 +1651,14 @@ end;
 {$define TORDINALHELPER:=TInt64Helper}
 {$define TORDINALTYPE:=Int64}
 {$define TORDINALBITINDEX:=TInt64BitIndex}
+{$define TORDINALNIBBLEINDEX:=TInt64NibbleIndex}
+{$define TORDINALBYTEINDEX:=TInt64ByteIndex}
+{$define TORDINALWORDINDEX:=TInt64WordIndex}
+{$define TORDINALDWORDINDEX:=TInt64DWordIndex}
+{$define TORDINALOVERLAY:=TQwordOverlay}
+{$define TORDINALTYPESIZE8}
 {$i syshelpo.inc}
+{$undef TORDINALTYPESIZE8}
 
 { ---------------------------------------------------------------------
   TQWordHelper
@@ -1630,7 +1667,14 @@ end;
 {$define TORDINALHELPER:=TQWordHelper}
 {$define TORDINALTYPE:=QWord}
 {$define TORDINALBITINDEX:=TQwordBitIndex}
+{$define TORDINALNIBBLEINDEX:=TQwordNibbleIndex}
+{$define TORDINALBYTEINDEX:=TQwordByteIndex}
+{$define TORDINALWORDINDEX:=TQWordWordIndex}
+{$define TORDINALDWORDINDEX:=TQWordDWordIndex}
+{$define TORDINALOVERLAY:=TQwordOverlay}
+{$define TORDINALTYPESIZE8}
 {$i syshelpo.inc}
+{$undef TORDINALTYPESIZE8}
 
 { ---------------------------------------------------------------------
   TNativeIntHelper
@@ -1639,7 +1683,31 @@ end;
 {$define TORDINALHELPER:=TNativeIntHelper}
 {$define TORDINALTYPE:=NativeInt}
 {$define TORDINALBITINDEX:=TNativeIntBitIndex}
+{$ifdef cpu16}
+  {$define TORDINALNIBBLEINDEX:=TSmallIntNibbleIndex}
+  {$define TORDINALBYTEINDEX:=TSmallIntByteIndex}
+  {$define TORDINALOVERLAY:=TSmallIntOverlay}
+  {$define TORDINALTYPESIZE2}
+{$endif}
+{$ifdef cpu32}
+  {$define TORDINALNIBBLEINDEX:=TIntegerNibbleIndex}
+  {$define TORDINALBYTEINDEX:=TIntegerByteIndex}
+  {$define TORDINALWORDINDEX:=TIntegerWordIndex}
+  {$define TORDINALOVERLAY:=TIntegerOverlay}
+  {$define TORDINALTYPESIZE4}
+{$endif}
+{$ifdef cpu64}
+  {$define TORDINALNIBBLEINDEX:=TInt64NibbleIndex}
+  {$define TORDINALBYTEINDEX:=TInt64ByteIndex}
+  {$define TORDINALWORDINDEX:=TInt64WordIndex}
+  {$define TORDINALDWORDINDEX:=TInt64DWordIndex}
+  {$define TORDINALOVERLAY:=TInt64Overlay}
+  {$define TORDINALTYPESIZE8}
+{$endif}
 {$i syshelpo.inc}
+{$undef TORDINALTYPESIZE2}
+{$undef TORDINALTYPESIZE4}
+{$undef TORDINALTYPESIZE8}
 
 { ---------------------------------------------------------------------
   TNativeUIntHelper
@@ -1648,7 +1716,31 @@ end;
 {$define TORDINALHELPER:=TNativeUIntHelper}
 {$define TORDINALTYPE:=NativeUInt}
 {$define TORDINALBITINDEX:=TNativeUIntBitIndex}
+{$ifdef cpu16}
+  {$define TORDINALNIBBLEINDEX:=TWordNibbleIndex}
+  {$define TORDINALBYTEINDEX:=TWordByteIndex}
+  {$define TORDINALOVERLAY:=TWordOverlay}
+  {$define TORDINALTYPESIZE2}
+{$endif}
+{$ifdef cpu32}
+  {$define TORDINALNIBBLEINDEX:=TDwordNibbleIndex}
+  {$define TORDINALBYTEINDEX:=TDwordByteIndex}
+  {$define TORDINALWORDINDEX:=TDwordWordIndex}
+  {$define TORDINALOVERLAY:=TDwordOverlay}
+  {$define TORDINALTYPESIZE4}
+{$endif}
+{$ifdef cpu64}
+  {$define TORDINALNIBBLEINDEX:=TQwordNibbleIndex}
+  {$define TORDINALBYTEINDEX:=TQwordByteIndex}
+  {$define TORDINALWORDINDEX:=TQwordWordIndex}
+  {$define TORDINALDWORDINDEX:=TQwordDWordIndex}
+  {$define TORDINALOVERLAY:=TQwordOverlay}
+  {$define TORDINALTYPESIZE8}
+{$endif}
 {$i syshelpo.inc}
+{$undef TORDINALTYPESIZE2}
+{$undef TORDINALTYPESIZE4}
+{$undef TORDINALTYPESIZE8}
 
 { ---------------------------------------------------------------------
   TBooleanHelper
diff --git a/rtl/objpas/sysutils/syshelpb.inc b/rtl/objpas/sysutils/syshelpb.inc
index 09149a11be..882268dbf2 100644
--- a/rtl/objpas/sysutils/syshelpb.inc
+++ b/rtl/objpas/sysutils/syshelpb.inc
@@ -1,36 +1,69 @@
 
 Class Function TBOOLHELPER.Parse(const S: string): Boolean; inline; static;
-
 begin
   Result:=StrToBool(S);
 end;
 
 Class Function TBOOLHELPER.Size: Integer; inline; static;
-
 begin
   Result:=SizeOf(TBOOLTYPE);
 end;
 
 Class Function TBOOLHELPER.ToString(const AValue: Boolean; UseBoolStrs: TUseBoolStrs = TUseBoolStrs.False): string; overload; inline; static;
-
 begin
   Result:=BoolToStr(AValue,UseBoolStrs=TUseBoolStrs.True);
 end;
 
 Class Function TBOOLHELPER.TryToParse(const S: string; out AValue: Boolean): Boolean; inline; static;
-
 begin
   Result:=TryStrToBool(S,AValue);
 end;
 
 Function TBOOLHELPER.ToInteger: Integer; inline;
-
 begin
   Result:=Integer(Self);
 end;
 
 Function TBOOLHELPER.ToString(UseBoolStrs: TUseBoolStrs = TUseBoolStrs.False): string; overload; inline;
-
 begin
   Result:=BoolToStr(Self,UseBoolStrs=TUseBoolStrs.True);
 end;
+
+class function TBOOLHELPER.ToString(const aValue: boolean; const aTrueStr, aFalseStr: string; const aCharsCase: TStringCaseFormat = scfUnchangedCase): string; overload; static;
+begin
+  if aValue then
+    case aCharsCase of
+      scfLowerCase:        Result := aTrueStr.ToLower;
+      scfUpperCase:        Result := aTrueStr.ToUpper;
+    else
+      {scfUnchangedCase:}  Result := aTrueStr;
+    end
+  else
+    case aCharsCase of
+      scfLowerCase:        Result := aFalseStr.ToLower;
+      scfUpperCase:        Result := aFalseStr.ToUpper;
+    else
+      {scfUnchangedCase:}  Result := aFalseStr;
+    end;
+end;
+
+function TBOOLHELPER.ToOneZeroString(const aCharsCase: TStringCaseFormat = scfUnchangedCase): string; inline;
+begin
+  Result := ToString(BitOneString, BitZeroString, aCharsCase);
+end;
+
+function TBOOLHELPER.ToOnOffString(const aCharsCase: TStringCaseFormat = scfUnchangedCase): string; inline;
+begin
+  Result := ToString(BitOnString, BitOffString, aCharsCase);
+end;
+
+function TBOOLHELPER.ToTrueFalseString(const aCharsCase: TStringCaseFormat = scfUnchangedCase): string; inline;
+begin
+  Result := ToString(BitTrueString, BitFalseString, aCharsCase);
+end;
+
+function TBOOLHELPER.ToString(const aTrueStr, aFalseStr: string; const aCharsCase: TStringCaseFormat = scfUnchangedCase): string; overload; inline;
+begin
+  Result := ToString(Self, aTrueStr, aFalseStr, aCharsCase);
+end;
+
diff --git a/rtl/objpas/sysutils/syshelph.inc b/rtl/objpas/sysutils/syshelph.inc
index 2a4fe31477..1ed01ee77b 100644
--- a/rtl/objpas/sysutils/syshelph.inc
+++ b/rtl/objpas/sysutils/syshelph.inc
@@ -381,254 +381,708 @@ Type
   end;
 {$ENDIF FPC_HAS_TYPE_EXTENDED}
 
+  nibble           = 0..15;
+  TNibbleBitIndex  = 0..3;
+
+  // TByteBitIndex is already defined
+  TByteNibbleIndex = 0..1;
+
+  TByteOverlay = bitpacked record case integer of     // for fast extraction of bits
+    0: (AsBit:    bitpacked array[TByteBitIndex]    of boolean);
+    1: (AsNibble: bitpacked array[TByteNibbleIndex] of nibble);
+    2: (AsByte:   byte);
+  end;
+
   TByteHelper = Type Helper for Byte
-  public
-    const
-      MaxValue = 255;
-      MinValue = 0;
+  const
+    MaxValue  = High(byte);
+    MinValue  = Low(byte);
+    MaxBit    = High(TByteBitIndex);
+    MinBit    = Low(TByteBitIndex);
+    MaxNibble = High(TByteNibbleIndex);
+    MinNibble = Low(TByteNibbleIndex);
   public
     Class Function Parse(const AString: string): Byte; inline; static;
     Class Function Size: Integer; inline; static;
     Class Function ToString(const AValue: Byte): string; overload; inline; static;
     Class Function TryParse(const AString: string; out AValue: Byte): Boolean; inline; static;
-  Public
-    Function ToBoolean: Boolean; inline;
-    Function ToDouble: Double; inline;
-    Function ToExtended: Extended; inline;
-    Function ToBinString:string;
-    Function ToHexString(const AMinDigits: Integer): string; overload; inline;
-    Function ToHexString: string; overload; inline;
-    Function ToSingle: Single; inline;
-    Function ToString: string; overload; inline;
-    Function SetBit(const Index: TByteBitIndex) : Byte; inline;
-    Function ClearBit(const Index: TByteBitIndex) : Byte; inline;
-    Function ToggleBit(const Index: TByteBitIndex) : Byte; inline;
-    Function TestBit(const Index:TByteBitIndex):Boolean; inline;
+  protected
+    function  GetBit(const aIndex: TByteBitIndex): boolean; inline;
+    procedure PutBit(const aIndex: TByteBitIndex; const aNewValue: boolean); inline;
+    function  GetNibble(const aIndex: TByteNibbleIndex): nibble; inline;
+    procedure PutNibble(const aIndex: TByteNibbleIndex; const aNewValue: nibble); inline;
+  public
+    Function  ToBoolean: Boolean; inline;
+    Function  ToDouble: Double; inline;
+    Function  ToExtended: Extended; inline;
+    Function  ToSingle: Single; inline;
+    Function  ToString: string; overload; inline;
+    Function  SetBit(const Index: TByteBitIndex): Byte; inline;
+    Function  ClearBit(const Index: TByteBitIndex): Byte; inline;
+    Function  ToggleBit(const Index: TByteBitIndex): Byte; inline;
+    Function  TestBit(const Index: TByteBitIndex): Boolean; inline;
+    procedure Clear; inline;
+    function  ToBinString(const aBinFormatSettings: TBinFormatSettings; const aShowLeadingZeros: boolean = true; const aMinDigits: integer = 0): string; overload;
+    function  ToBinString(const aBinFormatSettings: TBinFormatSettings; const aMinDigits: integer): string; overload; inline;
+    function  ToBinString(const aMinDigits: integer): string; overload; inline;
+    function  ToBinString(const aShowLeadingZeros: boolean = true): string; overload; inline;
+    function  ToHexString(const aHexFormatSettings: THexFormatSettings; const aShowLeadingZeros: boolean = true; const aMinDigits: integer = 0): string; overload;
+    function  ToHexString(const aHexFormatSettings: THexFormatSettings; const aMinDigits: integer): string; overload; inline;
+    function  ToHexString(const aMinDigits: integer): string; overload; inline;
+    function  ToHexString(const aShowLeadingZeros: boolean = true): string; overload; inline;
+    function  HighestBitPos: cardinal; inline;
+    function  LowestBitPos: cardinal; inline;
+    function  BitsCount: byte; inline;
+    property  Bit   [aIndex: TByteBitIndex]: boolean   read GetBit    write PutBit;
+    property  Nibble[aIndex: TByteNibbleIndex]: nibble read GetNibble write PutNibble;
   end;
 
+  // TShortIntBitIndex is already defined
+
+  TShortIntNibbleIndex = TByteNibbleIndex;
+
+  TShortIntOverlay = TByteOverlay;
+
   TShortIntHelper = Type Helper for ShortInt
-  public
-    const
-      MaxValue = 127;
-      MinValue = -128;
+  const
+    MaxValue  = High(shortint);
+    MinValue  = Low(shortint);
+    MaxBit    = High(TShortIntBitIndex);
+    MinBit    = Low(TShortIntBitIndex);
+    MaxNibble = High(TShortIntNibbleIndex);
+    MinNibble = Low(TShortIntNibbleIndex);
   public
     Class Function Parse(const AString: string): ShortInt; inline; static;
     Class Function Size: Integer; inline; static;
     Class Function ToString(const AValue: ShortInt): string; overload; inline; static;
     Class Function TryParse(const AString: string; out AValue: ShortInt): Boolean; inline; static;
+  protected
+    function  GetBit(const aIndex: TShortIntBitIndex): boolean; inline;
+    procedure PutBit(const aIndex: TShortIntBitIndex; const aNewValue: boolean); inline;
+    function  GetNibble(const aIndex: TShortIntNibbleIndex): nibble; inline;
+    procedure PutNibble(const aIndex: TShortIntNibbleIndex; const aNewValue: nibble); inline;
   public
-    Function ToBoolean: Boolean; inline;
-    Function ToDouble: Double; inline;
-    Function ToExtended: Extended; inline;
-    Function ToBinString:string; inline;
-    Function ToHexString(const AMinDigits: Integer): string; overload; inline;
-    Function ToHexString: string; overload; inline;
-    Function ToSingle: Single; inline;
-    Function ToString: string; overload; inline;
-    Function SetBit(const Index: TShortIntBitIndex): Shortint; inline;
-    Function ClearBit(const Index: TShortIntBitIndex): Shortint; inline;
-    Function ToggleBit(const Index: TShortIntBitIndex): Shortint; inline;
-    Function TestBit(const Index:TShortIntBitIndex):Boolean;
+    Function  ToBoolean: Boolean; inline;
+    Function  ToDouble: Double; inline;
+    Function  ToExtended: Extended; inline;
+    Function  ToSingle: Single; inline;
+    Function  ToString: string; overload; inline;
+    Function  SetBit(const Index: TShortIntBitIndex): Shortint; inline;
+    Function  ClearBit(const Index: TShortIntBitIndex): Shortint; inline;
+    Function  ToggleBit(const Index: TShortIntBitIndex): Shortint; inline;
+    Function  TestBit(const Index: TShortIntBitIndex): Boolean;
+    procedure Clear; inline;
+    function  ToBinString(const aBinFormatSettings: TBinFormatSettings; const aShowLeadingZeros: boolean = true; const aMinDigits: integer = 0): string; overload;
+    function  ToBinString(const aBinFormatSettings: TBinFormatSettings; const aMinDigits: integer): string; overload; inline;
+    function  ToBinString(const aMinDigits: integer): string; overload; inline;
+    function  ToBinString(const aShowLeadingZeros: boolean = true): string; overload; inline;
+    function  ToHexString(const aHexFormatSettings: THexFormatSettings; const aShowLeadingZeros: boolean = true; const aMinDigits: integer = 0): string; overload;
+    function  ToHexString(const aHexFormatSettings: THexFormatSettings; const aMinDigits: integer): string; overload; inline;
+    function  ToHexString(const aMinDigits: integer): string; overload; inline;
+    function  ToHexString(const aShowLeadingZeros: boolean = true): string; overload; inline;
+    function  HighestBitPos: cardinal; inline;
+    function  LowestBitPos: cardinal; inline;
+    function  BitsCount: byte; inline;
+    property  Bit   [aIndex: TShortIntBitIndex]: boolean   read GetBit    write PutBit;
+    property  Nibble[aIndex: TShortIntNibbleIndex]: nibble read GetNibble write PutNibble;
   end;
 
-  TSmallIntHelper = Type Helper for SmallInt
+  // TWordBitIndex is already defined
+  TWordByteIndex   = 0..1;
+  TWordNibbleIndex = 0..3;
+
+  TWordOverlay = bitpacked record case integer of     // for fast extraction of bytes and bits
+    0: (AsBit:    bitpacked array[TWordBitIndex]    of boolean);
+    1: (AsNibble: bitpacked array[TWordNibbleIndex] of nibble);
+    2: (AsByte:             array[TWordByteIndex]   of byte);
+    3: (AsWord:             word);
+    // recursive overlay:
+    4: (AsByteOverlay:      array[TWordByteIndex]   of TByteOverlay);
+  end;
+
+  TWordHelper = Type Helper for Word
+  const
+    MaxValue  = High(word);
+    MinValue  = Low(word);
+    MaxBit    = High(TWordBitIndex);
+    MinBit    = Low(TWordBitIndex);
+    MaxNibble = High(TWordNibbleIndex);
+    MinNibble = Low(TWordNibbleIndex);
+    MaxByte   = High(TWordByteIndex);
+    MinByte   = Low(TWordByteIndex);
   public
-    const
-      MaxValue = 32767;
-      MinValue = -32768;
+    Class Function Parse(const AString: string): Word; inline; static;
+    Class Function Size: Integer; inline; static;
+    Class Function ToString(const AValue: Word): string; overload; inline; static;
+    Class Function TryParse(const AString: string; out AValue: Word): Boolean; inline; static;
+  protected
+    function  GetBit(const aIndex: TWordBitIndex): boolean; inline;
+    procedure PutBit(const aIndex: TWordBitIndex; const aNewValue: boolean); inline;
+    function  GetNibble(const aIndex: TWordNibbleIndex): nibble; inline;
+    procedure PutNibble(const aIndex: TWordNibbleIndex; const aNewValue: nibble); inline;
+    function  GetByte(const aIndex: TWordByteIndex): byte;
+    procedure PutByte(const aIndex: TWordByteIndex; const aNewValue: byte);
+  public
+    Function  ToBoolean: Boolean; inline;
+    Function  ToDouble: Double; inline;
+    Function  ToExtended: Extended; inline;
+    Function  ToSingle: Single; inline;
+    Function  ToString: string; overload; inline;
+    Function  SetBit(const Index: TWordBitIndex): Word; inline;
+    Function  ClearBit(const Index: TWordBitIndex): Word; inline;
+    Function  ToggleBit(const Index: TWordBitIndex): Word; inline;
+    Function  TestBit(const Index: TWordBitIndex): Boolean; inline;
+    procedure Clear; inline;
+    function  ToBinString(const aBinFormatSettings: TBinFormatSettings; const aShowLeadingZeros: boolean = true; const aMinDigits: integer = 0): string; overload;
+    function  ToBinString(const aBinFormatSettings: TBinFormatSettings; const aMinDigits: integer): string; overload; inline;
+    function  ToBinString(const aMinDigits: integer): string; overload; inline;
+    function  ToBinString(const aShowLeadingZeros: boolean = true): string; overload; inline;
+    function  ToHexString(const aHexFormatSettings: THexFormatSettings; const aShowLeadingZeros: boolean = true; const aMinDigits: integer = 0): string; overload;
+    function  ToHexString(const aHexFormatSettings: THexFormatSettings; const aMinDigits: integer): string; overload; inline;
+    function  ToHexString(const aMinDigits: integer): string; overload; inline;
+    function  ToHexString(const aShowLeadingZeros: boolean = true): string; overload; inline;
+    function  HighestBitPos: cardinal; inline;
+    function  LowestBitPos: cardinal; inline;
+    function  BitsCount: byte; inline;
+    property  Bit   [aIndex: TWordBitIndex]: boolean   read GetBit  write PutBit;
+    property  Nibble[aIndex: TWordNibbleIndex]: nibble read GetNibble write PutNibble;
+    property  Byte  [aIndex: TWordByteIndex]: byte     read GetByte write PutByte;
+  end;
+
+  // TSmallIntBitIndex is already defined
+  TSmallIntByteIndex   = TWordByteIndex;
+  TSmallIntNibbleIndex = TWordNibbleIndex;
+
+  TSmallIntOverlay = TWordOverlay;
+
+  TSmallIntHelper = Type Helper for SmallInt
+  const
+    MaxValue  = High(SmallInt);
+    MinValue  = Low(SmallInt);
+    MaxBit    = High(TSmallIntBitIndex);
+    MinBit    = Low(TSmallIntBitIndex);
+    MaxNibble = High(TSmallIntNibbleIndex);
+    MinNibble = Low(TSmallIntNibbleIndex);
+    MaxByte   = High(TSmallIntByteIndex);
+    MinByte   = Low(TSmallIntByteIndex);
   public
     Class Function Parse(const AString: string): SmallInt; inline; static;
     Class Function Size: Integer; inline; static;
     Class Function ToString(const AValue: SmallInt): string; overload; inline; static;
     Class Function TryParse(const AString: string; out AValue: SmallInt): Boolean; inline; static;
+  protected
+    function  GetBit(const aIndex: TSmallIntBitIndex): boolean; inline;
+    procedure PutBit(const aIndex: TSmallIntBitIndex; const aNewValue: boolean); inline;
+    function  GetNibble(const aIndex: TSmallIntNibbleIndex): nibble; inline;
+    procedure PutNibble(const aIndex: TSmallIntNibbleIndex; const aNewValue: nibble); inline;
+    function  GetByte(const aIndex: TSmallIntByteIndex): byte;
+    procedure PutByte(const aIndex: TSmallIntByteIndex; const aNewValue: byte);
   public
     Function ToString: string; overload; inline;
     Function ToBoolean: Boolean; inline;
-    Function ToBinString:string; inline;
-    Function ToHexString: string; overload; inline;
-    Function ToHexString(const AMinDigits: Integer): string; overload; inline;
     Function ToSingle: Single; inline;
     Function ToDouble: Double; inline;
     Function ToExtended: Extended; inline;
-    Function SetBit(const Index: TSmallIntBitIndex) : Smallint; inline;
-    Function ClearBit(const Index: TSmallIntBitIndex) : Smallint; inline;
-    Function ToggleBit(const Index: TSmallIntBitIndex) : Smallint; inline;
-    Function TestBit(const Index:TSmallIntBitIndex):Boolean;    
+    Function SetBit(const Index: TSmallIntBitIndex): Smallint; inline;
+    Function ClearBit(const Index: TSmallIntBitIndex): Smallint; inline;
+    Function ToggleBit(const Index: TSmallIntBitIndex): Smallint; inline;
+    Function TestBit(const Index: TSmallIntBitIndex): Boolean;
+    procedure Clear; inline;
+    function  ToBinString(const aBinFormatSettings: TBinFormatSettings; const aShowLeadingZeros: boolean = true; const aMinDigits: integer = 0): string; overload;
+    function  ToBinString(const aBinFormatSettings: TBinFormatSettings; const aMinDigits: integer): string; overload; inline;
+    function  ToBinString(const aMinDigits: integer): string; overload; inline;
+    function  ToBinString(const aShowLeadingZeros: boolean = true): string; overload; inline;
+    function  ToHexString(const aHexFormatSettings: THexFormatSettings; const aShowLeadingZeros: boolean = true; const aMinDigits: integer = 0): string; overload;
+    function  ToHexString(const aHexFormatSettings: THexFormatSettings; const aMinDigits: integer): string; overload; inline;
+    function  ToHexString(const aMinDigits: integer): string; overload; inline;
+    function  ToHexString(const aShowLeadingZeros: boolean = true): string; overload; inline;
+    function  HighestBitPos: cardinal; inline;
+    function  LowestBitPos: cardinal; inline;
+    function  BitsCount: byte; inline;
+    property  Bit   [aIndex: TSmallIntBitIndex]: boolean   read GetBit  write PutBit;
+    property  Nibble[aIndex: TSmallIntNibbleIndex]: nibble read GetNibble write PutNibble;
+    property  Byte  [aIndex: TSmallIntByteIndex]: byte     read GetByte write PutByte;
   end;
 
-  TWordHelper = Type Helper for Word
-  public
-    const
-      MaxValue = 65535;
-      MinValue = 0;
-  Public
-    Class Function Parse(const AString: string): Word; inline; static;
-    Class Function Size: Integer; inline; static;
-    Class Function ToString(const AValue: Word): string; overload; inline; static;
-    Class Function TryParse(const AString: string; out AValue: Word): Boolean; inline; static;
-  Public
-    Function ToBoolean: Boolean; inline;
-    Function ToDouble: Double; inline;
-    Function ToExtended: Extended; inline;
-    Function ToBinString:string; inline;
-    Function ToHexString(const AMinDigits: Integer): string; overload; inline;
-    Function ToHexString: string; overload; inline;
-    Function ToSingle: Single; inline;
-    Function ToString: string; overload; inline;
-    Function SetBit(const Index: TWordBitIndex) : Word; inline;
-    Function ClearBit(const Index: TWordBitIndex) : Word; inline;
-    Function ToggleBit(const Index: TWordBitIndex) : Word; inline;
-    Function TestBit(const Index:TWordBitIndex):Boolean; inline;    
+  TDwordBitIndex    = TCardinalBitIndex;
+  TDwordNibbleIndex = 0..7;
+  TDwordByteIndex   = 0..3;
+  TDwordWordIndex   = 0..1;
+
+  TDwordOverlay = bitpacked record case integer of     // for fast extraction of words, bytes and bits
+    0: (AsBit:    bitpacked array[TDwordBitIndex]    of boolean);
+    1: (AsNibble: bitpacked array[TDwordNibbleIndex] of nibble);
+    2: (AsByte:             array[TDwordByteIndex]   of byte);
+    3: (AsWord:             array[TDwordWordIndex]   of word);
+    4: (AsDword:            dword);
+    // recursive overlays:
+    5: (AsByteOverlay:      array[TDwordByteIndex]   of TByteOverlay);
+    6: (AsWordOverlay:      array[TDwordWordIndex]   of TWordOverlay);
   end;
 
+  // TCardinalBitIndex is already defined
+  TCardinalNibbleIndex = TDwordNibbleIndex;
+  TCardinalByteIndex   = TDwordByteIndex;
+  TCardinalWordIndex   = TDwordWordIndex;
+
+  TCardinalOverlay = TDwordOverlay;
+
   TCardinalHelper = Type Helper for Cardinal { for LongWord Type too }
+  const
+    MaxValue  = High(Cardinal);
+    MinValue  = Low(Cardinal);
+    MaxBit    = High(TCardinalBitIndex);
+    MinBit    = Low(TCardinalBitIndex);
+    MaxNibble = High(TCardinalNibbleIndex);
+    MinNibble = Low(TCardinalNibbleIndex);
+    MaxByte   = High(TCardinalByteIndex);
+    MinByte   = Low(TCardinalByteIndex);
+    MaxWord   = High(TCardinalWordIndex);
+    MinWord   = Low(TCardinalWordIndex);
   public
-    const
-      MaxValue = 4294967295;
-      MinValue = 0;
-  Public
     Class Function Parse(const AString: string): Cardinal; inline; static;
     Class Function Size: Integer; inline; static;
     Class Function ToString(const AValue: Cardinal): string; overload; inline; static;
     Class Function TryParse(const AString: string; out AValue: Cardinal): Boolean; inline; static;
-  Public
-    Function ToBoolean: Boolean; inline;
-    Function ToDouble: Double; inline;
-    Function ToExtended: Extended; inline;
-    Function ToBinString:string; inline;
-    Function ToHexString(const AMinDigits: Integer): string; overload; inline;
-    Function ToHexString: string; overload; inline;
-    Function ToSingle: Single; inline;
-    Function ToString: string; overload; inline;
-    Function SetBit(const Index: TCardinalBitIndex) : Cardinal; inline;
-    Function ClearBit(const Index: TCardinalBitIndex) : Cardinal; inline;
-    Function ToggleBit(const Index: TCardinalBitIndex) : Cardinal; inline;
-    Function TestBit(const Index:TCardinalBitIndex):Boolean; inline;   
+  protected
+    function  GetBit(const aIndex: TCardinalBitIndex): boolean; inline;
+    procedure PutBit(const aIndex: TCardinalBitIndex; const aNewValue: boolean); inline;
+    function  GetNibble(const aIndex: TCardinalNibbleIndex): nibble; inline;
+    procedure PutNibble(const aIndex: TCardinalNibbleIndex; const aNewValue: nibble); inline;
+    function  GetByte(const aIndex: TCardinalByteIndex): byte;
+    procedure PutByte(const aIndex: TCardinalByteIndex; const aNewValue: byte);
+    function  GetWord(const aIndex: TCardinalWordIndex): word;
+    procedure PutWord(const aIndex: TCardinalWordIndex; const aNewValue: word);
+  public
+    Function  ToBoolean: Boolean; inline;
+    Function  ToDouble: Double; inline;
+    Function  ToExtended: Extended; inline;
+    Function  ToSingle: Single; inline;
+    Function  ToString: string; overload; inline;
+    Function  SetBit(const Index: TCardinalBitIndex): Cardinal; inline;
+    Function  ClearBit(const Index: TCardinalBitIndex): Cardinal; inline;
+    Function  ToggleBit(const Index: TCardinalBitIndex): Cardinal; inline;
+    Function  TestBit(const Index:TCardinalBitIndex): Boolean; inline;
+    procedure Clear; inline;
+    function  ToBinString(const aBinFormatSettings: TBinFormatSettings; const aShowLeadingZeros: boolean = true; const aMinDigits: integer = 0): string; overload;
+    function  ToBinString(const aBinFormatSettings: TBinFormatSettings; const aMinDigits: integer): string; overload; inline;
+    function  ToBinString(const aMinDigits: integer): string; overload; inline;
+    function  ToBinString(const aShowLeadingZeros: boolean = true): string; overload; inline;
+    function  ToHexString(const aHexFormatSettings: THexFormatSettings; const aShowLeadingZeros: boolean = true; const aMinDigits: integer = 0): string; overload;
+    function  ToHexString(const aHexFormatSettings: THexFormatSettings; const aMinDigits: integer): string; overload; inline;
+    function  ToHexString(const aMinDigits: integer): string; overload; inline;
+    function  ToHexString(const aShowLeadingZeros: boolean = true): string; overload; inline;
+    function  HighestBitPos: cardinal; inline;
+    function  LowestBitPos: cardinal; inline;
+    function  BitsCount: byte; inline;
+    property  Bit   [aIndex: TCardinalBitIndex]: boolean   read GetBit    write PutBit;
+    property  Nibble[aIndex: TCardinalNibbleIndex]: nibble read GetNibble write PutNibble;
+    property  Byte  [aIndex: TCardinalByteIndex]: byte     read GetByte   write PutByte;
+    property  Word  [aIndex: TCardinalWordIndex]: word     read GetWord   write PutWord;
   end;
 
+  // TIntegerBitIndex is already defined
+  TIntegerNibbleIndex = TDwordNibbleIndex;
+  TIntegerByteIndex   = TDwordByteIndex;
+  TIntegerWordIndex   = TDwordWordIndex;
+
+  TIntegerOverlay = TDwordOverlay;
+
   TIntegerHelper = Type Helper for Integer { for LongInt Type too }
+  const
+    MaxValue  = High(integer);
+    MinValue  = Low(integer);
+    MaxBit    = High(TIntegerBitIndex);
+    MinBit    = Low(TIntegerBitIndex);
+    MaxNibble = High(TIntegerNibbleIndex);
+    MinNibble = Low(TIntegerNibbleIndex);
+    MaxByte   = High(TIntegerByteIndex);
+    MinByte   = Low(TIntegerByteIndex);
+    MaxWord   = High(TIntegerWordIndex);
+    MinWord   = Low(TIntegerWordIndex);
   public
-    const
-      MaxValue = 2147483647;
-      MinValue = -2147483648;
-  Public
     Class Function Size: Integer; inline; static;
     Class Function ToString(const AValue: Integer): string; overload; inline; static;
     Class Function Parse(const AString: string): Integer; inline; static;
     Class Function TryParse(const AString: string; out AValue: Integer): Boolean; inline; static;
-  Public
-    Function ToBoolean: Boolean; inline;
-    Function ToDouble: Double; inline;
-    Function ToExtended: Extended; inline;
-    Function ToBinString:string; inline;
-    Function ToHexString(const AMinDigits: Integer): string; overload; inline;
-    Function ToHexString: string; overload; inline;
-    Function ToSingle: Single; inline;
-    Function ToString: string; overload; inline;
-    Function SetBit(const Index: TIntegerBitIndex) : Integer; inline;
-    Function ClearBit(const Index: TIntegerBitIndex) : Integer; inline;
-    Function ToggleBit(const Index: TIntegerBitIndex) : Integer; inline;
-    Function TestBit(const Index:TIntegerBitIndex):Boolean; inline;   
+  protected
+    function  GetBit(const aIndex: TIntegerBitIndex): boolean; inline;
+    procedure PutBit(const aIndex: TIntegerBitIndex; const aNewValue: boolean); inline;
+    function  GetNibble(const aIndex: TIntegerNibbleIndex): nibble; inline;
+    procedure PutNibble(const aIndex: TIntegerNibbleIndex; const aNewValue: nibble); inline;
+    function  GetByte(const aIndex: TIntegerByteIndex): byte;
+    procedure PutByte(const aIndex: TIntegerByteIndex; const aNewValue: byte);
+    function  GetWord(const aIndex: TIntegerWordIndex): word;
+    procedure PutWord(const aIndex: TIntegerWordIndex; const aNewValue: word);
+  public
+    Function  ToBoolean: Boolean; inline;
+    Function  ToDouble: Double; inline;
+    Function  ToExtended: Extended; inline;
+    Function  ToSingle: Single; inline;
+    Function  ToString: string; overload; inline;
+    Function  SetBit(const Index: TIntegerBitIndex) : Integer; inline;
+    Function  ClearBit(const Index: TIntegerBitIndex) : Integer; inline;
+    Function  ToggleBit(const Index: TIntegerBitIndex) : Integer; inline;
+    Function  TestBit(const Index:TIntegerBitIndex):Boolean; inline;
+    procedure Clear; inline;
+    function  ToBinString(const aBinFormatSettings: TBinFormatSettings; const aShowLeadingZeros: boolean = true; const aMinDigits: integer = 0): string; overload;
+    function  ToBinString(const aBinFormatSettings: TBinFormatSettings; const aMinDigits: integer): string; overload; inline;
+    function  ToBinString(const aMinDigits: integer): string; overload; inline;
+    function  ToBinString(const aShowLeadingZeros: boolean = true): string; overload; inline;
+    function  ToHexString(const aHexFormatSettings: THexFormatSettings; const aShowLeadingZeros: boolean = true; const aMinDigits: integer = 0): string; overload;
+    function  ToHexString(const aHexFormatSettings: THexFormatSettings; const aMinDigits: integer): string; overload; inline;
+    function  ToHexString(const aMinDigits: integer): string; overload; inline;
+    function  ToHexString(const aShowLeadingZeros: boolean = true): string; overload; inline;
+    function  HighestBitPos: cardinal; inline;
+    function  LowestBitPos: cardinal; inline;
+    function  BitsCount: byte; inline;
+    property  Bit   [aIndex: TIntegerBitIndex]: boolean    read GetBit    write PutBit;
+    property  Nibble[aIndex: TCardinalNibbleIndex]: nibble read GetNibble write PutNibble;
+    property  Byte  [aIndex: TIntegerByteIndex]:  byte     read GetByte   write PutByte;
+    property  Word  [aIndex: TIntegerWordIndex]:  word     read GetWord   write PutWord;
   end;
 
-  TInt64Helper = Type Helper for Int64
-  public
-    const
-      MaxValue = 9223372036854775807;
-      MinValue = -9223372036854775808;
-  Public
-    Class Function Parse(const AString: string): Int64; inline; static;
-    Class Function Size: Integer; inline; static;
-    Class Function ToString(const AValue: Int64): string; overload; inline; static;
-    Class Function TryParse(const AString: string; out AValue: Int64): Boolean; inline; static;
-  Public
-    Function ToBoolean: Boolean; inline;
-    Function ToDouble: Double; inline;
-    Function ToExtended: Extended; inline;
-    Function ToBinString:string; inline;
-    Function ToHexString(const AMinDigits: Integer): string; overload; inline;
-    Function ToHexString: string; overload; inline;
-    Function ToSingle: Single; inline;
-    Function ToString: string; overload; inline;
-    Function SetBit(const Index: TInt64BitIndex) : Int64; inline;
-    Function ClearBit(const Index: TInt64BitIndex) : Int64; inline;
-    Function ToggleBit(const Index: TInt64BitIndex) : Int64; inline;
-    Function TestBit(const Index:TInt64BitIndex):Boolean; inline; 
+  // TQwordBitIndex is already defined
+  TQwordNibbleIndex = 0..15;
+  TQwordByteIndex   = 0..7;
+  TQwordWordIndex   = 0..3;
+  TQwordDwordIndex  = 0..1;
+
+  TQwordOverlay = bitpacked record case integer of     // for fast extraction of longwords, words, bytes and bits
+    0: (AsBit:    bitpacked array[TQwordBitIndex]    of boolean);
+    1: (AsNibble: bitpacked array[TQwordNibbleIndex] of nibble);
+    2: (AsByte:             array[TQwordByteIndex]   of byte);
+    3: (AsWord:             array[TQwordWordIndex]   of word);
+    4: (AsDword:            array[TQwordDwordIndex]  of dword);
+    5: (AsQword:            qword);
+    // recursive overlays:
+    6: (AsByteOverlay:      array[TQwordByteIndex]   of TByteOverlay);
+    7: (AsWordOverlay:      array[TQwordWordIndex]   of TWordOverlay);
+    8: (AsDwordOverlay:     array[TQwordDwordIndex]  of TDwordOverlay);
   end;
 
   TQWordHelper = Type Helper for QWord
+  const
+    MaxValue  = High(qword);
+    MinValue  = Low(qword);
+    MaxBit    = High(TQwordBitIndex);
+    MinBit    = Low(TQwordBitIndex);
+    MaxNibble = High(TQwordNibbleIndex);
+    MinNibble = Low(TQwordNibbleIndex);
+    MaxByte   = High(TQwordByteIndex);
+    MinByte   = Low(TQwordByteIndex);
+    MaxWord   = High(TQwordWordIndex);
+    MinWord   = Low(TQwordWordIndex);
+    MaxDword  = High(TQwordDwordIndex);
+    MinDword  = Low(TQwordDwordIndex);
   public
-    const
-      MaxValue = 18446744073709551615;
-      MinValue = 0;
-  Public
     Class Function Parse(const AString: string): QWord; inline; static;
     Class Function Size: Integer; inline; static;
     Class Function ToString(const AValue: QWord): string; overload; inline; static;
     Class Function TryParse(const AString: string; out AValue: QWord): Boolean; inline; static;
-  Public
-    Function ToBoolean: Boolean; inline;
-    Function ToDouble: Double; inline;
-    Function ToExtended: Extended; inline;
-    Function ToBinString:string; inline;
-    Function ToHexString(const AMinDigits: Integer): string; overload; inline;
-    Function ToHexString: string; overload; inline;
-    Function ToSingle: Single; inline;
-    Function ToString: string; overload; inline;
-    Function SetBit(const Index: TQwordBitIndex) : QWord; inline;
-    Function ClearBit(const Index: TQwordBitIndex) : QWord; inline;
-    Function ToggleBit(const Index: TQwordBitIndex) : QWord; inline;
-    Function TestBit(const Index:TQwordBitIndex):Boolean; inline; 
+  protected
+    function  GetBit(const aIndex: TQwordBitIndex): boolean; inline;
+    procedure PutBit(const aIndex: TQwordBitIndex; const aNewValue: boolean); inline;
+    function  GetNibble(const aIndex: TQwordNibbleIndex): nibble; inline;
+    procedure PutNibble(const aIndex: TQwordNibbleIndex; const aNewValue: nibble); inline;
+    function  GetByte(const aIndex: TQwordByteIndex): byte;
+    procedure PutByte(const aIndex: TQwordByteIndex; const aNewValue: byte);
+    function  GetWord(const aIndex: TQwordWordIndex): word;
+    procedure PutWord(const aIndex: TQwordWordIndex; const aNewValue: word);
+    function  GetDword(const aIndex: TQwordDwordIndex): dword;
+    procedure PutDword(const aIndex: TQwordDwordIndex; const aNewValue: dword);
+  public
+    Function  ToBoolean: Boolean; inline;
+    Function  ToDouble: Double; inline;
+    Function  ToExtended: Extended; inline;
+    Function  ToSingle: Single; inline;
+    Function  ToString: string; overload; inline;
+    Function  SetBit(const Index: TQwordBitIndex): QWord; inline;
+    Function  ClearBit(const Index: TQwordBitIndex): QWord; inline;
+    Function  ToggleBit(const Index: TQwordBitIndex): QWord; inline;
+    Function  TestBit(const Index:TQwordBitIndex): Boolean; inline;
+    procedure Clear; inline;
+    function  ToBinString(const aBinFormatSettings: TBinFormatSettings; const aShowLeadingZeros: boolean = true; const aMinDigits: integer = 0): string; overload;
+    function  ToBinString(const aBinFormatSettings: TBinFormatSettings; const aMinDigits: integer): string; overload; inline;
+    function  ToBinString(const aMinDigits: integer): string; overload; inline;
+    function  ToBinString(const aShowLeadingZeros: boolean = true): string; overload; inline;
+    function  ToHexString(const aHexFormatSettings: THexFormatSettings; const aShowLeadingZeros: boolean = true; const aMinDigits: integer = 0): string; overload;
+    function  ToHexString(const aHexFormatSettings: THexFormatSettings; const aMinDigits: integer): string; overload; inline;
+    function  ToHexString(const aMinDigits: integer): string; overload; inline;
+    function  ToHexString(const aShowLeadingZeros: boolean = true): string; overload; inline;
+    function  HighestBitPos: cardinal; inline;
+    function  LowestBitPos: cardinal; inline;
+    function  BitsCount: byte; inline;
+    property  Bit   [aIndex: TQwordBitIndex]: boolean   read GetBit    write PutBit;
+    property  Nibble[aIndex: TQwordNibbleIndex]: nibble read GetNibble write PutNibble;
+    property  Byte  [aIndex: TQwordByteIndex]: byte     read GetByte   write PutByte;
+    property  Word  [aIndex: TQwordWordIndex]: word     read GetWord   write PutWord;
+    property  DWord [aIndex: TQwordDwordIndex]: dword   read GetDWord  write PutDWord;
+  end;
+
+  // TInt64BitIndex is already defined
+  TInt64NibbleIndex = TQwordNibbleIndex;
+  TInt64ByteIndex   = TQwordByteIndex;
+  TInt64WordIndex   = TQwordWordIndex;
+  TInt64DwordIndex  = TQwordDwordIndex;
+
+  TInt64Overlay = TQwordOverlay;
+
+  TInt64Helper = Type Helper for Int64
+  const
+    MaxValue  = High(int64);
+    MinValue  = Low(int64);
+    MaxBit    = High(TInt64BitIndex);
+    MinBit    = Low(TInt64BitIndex);
+    MaxNibble = High(TInt64NibbleIndex);
+    MinNibble = Low(TInt64NibbleIndex);
+    MaxByte   = High(TInt64ByteIndex);
+    MinByte   = Low(TInt64ByteIndex);
+    MaxWord   = High(TInt64WordIndex);
+    MinWord   = Low(TInt64WordIndex);
+    MaxDword  = High(TInt64DwordIndex);
+    MinDword  = Low(TInt64DwordIndex);
+  public
+    Class Function Parse(const AString: string): Int64; inline; static;
+    Class Function Size: Integer; inline; static;
+    Class Function ToString(const AValue: Int64): string; overload; inline; static;
+    Class Function TryParse(const AString: string; out AValue: Int64): Boolean; inline; static;
+  protected
+    function  GetBit(const aIndex: TInt64BitIndex): boolean; inline;
+    procedure PutBit(const aIndex: TInt64BitIndex; const aNewValue: boolean); inline;
+    function  GetNibble(const aIndex: TInt64NibbleIndex): nibble; inline;
+    procedure PutNibble(const aIndex: TInt64NibbleIndex; const aNewValue: nibble); inline;
+    function  GetByte(const aIndex: TInt64ByteIndex): byte;
+    procedure PutByte(const aIndex: TInt64ByteIndex; const aNewValue: byte);
+    function  GetWord(const aIndex: TInt64WordIndex): word;
+    procedure PutWord(const aIndex: TInt64WordIndex; const aNewValue: word);
+    function  GetDword(const aIndex: TInt64DwordIndex): dword;
+    procedure PutDword(const aIndex: TInt64DwordIndex; const aNewValue: dword);
+  public
+    Function  ToBoolean: Boolean; inline;
+    Function  ToDouble: Double; inline;
+    Function  ToExtended: Extended; inline;
+    Function  ToSingle: Single; inline;
+    Function  ToString: string; overload; inline;
+    Function  SetBit(const Index: TInt64BitIndex) : Int64; inline;
+    Function  ClearBit(const Index: TInt64BitIndex) : Int64; inline;
+    Function  ToggleBit(const Index: TInt64BitIndex) : Int64; inline;
+    Function  TestBit(const Index:TInt64BitIndex):Boolean; inline;
+    procedure Clear; inline;
+    function  ToBinString(const aBinFormatSettings: TBinFormatSettings; const aShowLeadingZeros: boolean = true; const aMinDigits: integer = 0): string; overload;
+    function  ToBinString(const aBinFormatSettings: TBinFormatSettings; const aMinDigits: integer): string; overload; inline;
+    function  ToBinString(const aMinDigits: integer): string; overload; inline;
+    function  ToBinString(const aShowLeadingZeros: boolean = true): string; overload; inline;
+    function  ToHexString(const aHexFormatSettings: THexFormatSettings; const aShowLeadingZeros: boolean = true; const aMinDigits: integer = 0): string; overload;
+    function  ToHexString(const aHexFormatSettings: THexFormatSettings; const aMinDigits: integer): string; overload; inline;
+    function  ToHexString(const aMinDigits: integer): string; overload; inline;
+    function  ToHexString(const aShowLeadingZeros: boolean = true): string; overload; inline;
+    function  HighestBitPos: cardinal; inline;
+    function  LowestBitPos: cardinal; inline;
+    function  BitsCount: byte; inline;
+    property  Bit   [aIndex: TInt64BitIndex]: boolean   read GetBit    write PutBit;
+    property  Nibble[aIndex: TInt64NibbleIndex]: nibble read GetNibble write PutNibble;
+    property  Byte  [aIndex: TInt64ByteIndex]: byte     read GetByte   write PutByte;
+    property  Word  [aIndex: TInt64WordIndex]: word     read GetWord   write PutWord;
+    property  DWord [aIndex: TInt64DwordIndex]: dword   read GetDWord  write PutDWord;
   end;
 
+  // TNativeIntBitIndex is already defined
+  {$ifdef cpu16}
+    TNativeIntNibbleIndex = TSmallIntNibbleIndex;
+    TNativeIntByteIndex   = TSmallIntByteIndex;
+    TNativeIntOverlay     = TSmallIntOverlay;
+  {$endif}
+  {$ifdef cpu32}
+    TNativeIntNibbleIndex = TIntegerNibbleIndex;
+    TNativeIntByteIndex   = TIntegerByteIndex;
+    TNativeIntWordIndex   = TIntegerWordIndex;
+    TNativeIntOverlay     = TIntegerOverlay;
+  {$endif}
+  {$ifdef cpu64}
+    TNativeIntNibbleIndex = TInt64NibbleIndex;
+    TNativeIntByteIndex   = TInt64ByteIndex;
+    TNativeIntWordIndex   = TInt64WordIndex;
+    TNativeIntDwordIndex  = TInt64DWordIndex;
+    TNativeIntOverlay     = TInt64Overlay;
+  {$endif}
+
   TNativeIntHelper = Type Helper for NativeInt
+  const
+    MaxValue  = High(NativeInt);
+    MinValue  = Low(NativeInt);
+    MaxBit    = High(TNativeIntBitIndex);
+    MinBit    = Low(TNativeIntBitIndex);
+    MaxNibble = High(TNativeIntNibbleIndex);
+    MinNibble = Low(TNativeIntNibbleIndex);
+    // NativeInt on cpu16 has 2 bytes, so no need for cpu16 check because we always need MaxByte and MinByte
+    MaxByte   = High(TNativeIntByteIndex);
+    MinByte   = Low(TNativeIntByteIndex);
+    {$ifdef cpu32}
+    MaxWord   = High(TNativeIntWordIndex);
+    MinWord   = Low(TNativeIntWordIndex);
+    {$endif}
+    {$ifdef cpu64}
+    MaxWord   = High(TNativeIntWordIndex);
+    MinWord   = Low(TNativeIntWordIndex);
+    MaxDword  = High(TNativeIntDwordIndex);
+    MinDword  = Low(TNativeIntDwordIndex);
+    {$endif}
   public
-    const
-      MaxValue = High(NativeInt);
-      MinValue = Low(NativeInt);
-  Public
     Class Function Parse(const AString: string): NativeInt; inline; static;
     Class Function Size: Integer; inline; static;
     Class Function ToString(const AValue: NativeInt): string; overload; inline; static;
     Class Function TryParse(const AString: string; out AValue: NativeInt): Boolean; inline; static;
-  Public
-    Function ToBoolean: Boolean; inline;
-    Function ToDouble: Double; inline;
-    Function ToExtended: Extended; inline;
-    Function ToBinString:string; inline;
-    Function ToHexString(const AMinDigits: Integer): string; overload; inline;
-    Function ToHexString: string; overload; inline;
-    Function ToSingle: Single; inline;
-    Function ToString: string; overload; inline;
-    Function SetBit(const Index: TNativeIntBitIndex) : NativeInt; inline;
-    Function ClearBit(const Index: TNativeIntBitIndex) : NativeInt; inline;
-    Function ToggleBit(const Index: TNativeIntBitIndex) : NativeInt; inline;
-    Function TestBit(const Index:TNativeIntBitIndex):Boolean; inline; 
+  protected
+    function  GetBit(const aIndex: TNativeIntBitIndex): boolean; inline;
+    procedure PutBit(const aIndex: TNativeIntBitIndex; const aNewValue: boolean); inline;
+    function  GetNibble(const aIndex: TNativeIntNibbleIndex): nibble; inline;
+    procedure PutNibble(const aIndex: TNativeIntNibbleIndex; const aNewValue: nibble); inline;
+    // NativeInt on cpu16 has 2 bytes, so no need for cpu16 check because we always need GetByte and PutByte
+    function  GetByte(const aIndex: TNativeIntByteIndex): byte;
+    procedure PutByte(const aIndex: TNativeIntByteIndex; const aNewValue: byte);
+    {$ifdef cpu32}
+    function  GetWord(const aIndex: TNativeIntWordIndex): word;
+    procedure PutWord(const aIndex: TNativeIntWordIndex; const aNewValue: word);
+    {$endif}
+    {$ifdef cpu64}
+    function  GetWord(const aIndex: TNativeIntWordIndex): word;
+    procedure PutWord(const aIndex: TNativeIntWordIndex; const aNewValue: word);
+    function  GetDword(const aIndex: TNativeIntDwordIndex): dword;
+    procedure PutDword(const aIndex: TNativeIntDwordIndex; const aNewValue: dword);
+    {$endif}
+  public
+    Function  ToBoolean: Boolean; inline;
+    Function  ToDouble: Double; inline;
+    Function  ToExtended: Extended; inline;
+    Function  ToSingle: Single; inline;
+    Function  ToString: string; overload; inline;
+    Function  SetBit(const Index: TNativeIntBitIndex): NativeInt; inline;
+    Function  ClearBit(const Index: TNativeIntBitIndex): NativeInt; inline;
+    Function  ToggleBit(const Index: TNativeIntBitIndex): NativeInt; inline;
+    Function  TestBit(const Index: TNativeIntBitIndex): Boolean; inline;
+    procedure Clear; inline;
+    function  ToBinString(const aBinFormatSettings: TBinFormatSettings; const aShowLeadingZeros: boolean = true; const aMinDigits: integer = 0): string; overload;
+    function  ToBinString(const aBinFormatSettings: TBinFormatSettings; const aMinDigits: integer): string; overload; inline;
+    function  ToBinString(const aMinDigits: integer): string; overload; inline;
+    function  ToBinString(const aShowLeadingZeros: boolean = true): string; overload; inline;
+    function  ToHexString(const aHexFormatSettings: THexFormatSettings; const aShowLeadingZeros: boolean = true; const aMinDigits: integer = 0): string; overload;
+    function  ToHexString(const aHexFormatSettings: THexFormatSettings; const aMinDigits: integer): string; overload; inline;
+    function  ToHexString(const aMinDigits: integer): string; overload; inline;
+    function  ToHexString(const aShowLeadingZeros: boolean = true): string; overload; inline;
+    function  HighestBitPos: cardinal; inline;
+    function  LowestBitPos: cardinal; inline;
+    function  BitsCount: byte; inline;
+    property  Bit   [aIndex: TNativeIntBitIndex]: boolean   read GetBit    write PutBit;
+    property  Nibble[aIndex: TNativeIntNibbleIndex]: nibble read GetNibble write PutNibble;
+    // NativeInt on cpu16 has 2 bytes, so no need for cpu16 check because we always need Byte[]
+    property  Byte  [aIndex: TNativeIntByteIndex]: byte     read GetByte   write PutByte;
+    {$ifdef cpu32}
+    property  Word  [aIndex: TNativeIntWordIndex]: word     read GetWord   write PutWord;
+    {$endif}
+    {$ifdef cpu64}
+    property  Word  [aIndex: TNativeIntWordIndex]: word     read GetWord   write PutWord;
+    property  DWord [aIndex: TNativeIntDwordIndex]: dword   read GetDWord  write PutDWord;
+    {$endif}
   end;
 
+  // TNativeUIntBitIndex is already defined
+  {$ifdef cpu16}
+    TNativeUIntNibbleIndex = TWordNibbleIndex;
+    TNativeUIntByteIndex   = TWordByteIndex;
+    TNativeUIntOverlay     = TWordOverlay;
+  {$endif}
+  {$ifdef cpu32}
+    TNativeUIntNibbleIndex = TDwordNibbleIndex;
+    TNativeUIntByteIndex   = TDwordByteIndex;
+    TNativeUIntWordIndex   = TDwordWordIndex;
+    TNativeUIntOverlay     = TDwordOverlay;
+  {$endif}
+  {$ifdef cpu64}
+    TNativeUIntNibbleIndex = TQwordNibbleIndex;
+    TNativeUIntByteIndex   = TQwordByteIndex;
+    TNativeUIntWordIndex   = TQwordWordIndex;
+    TNativeUIntDwordIndex  = TQwordDWordIndex;
+    TNativeUIntOverlay     = TQwordOverlay;
+  {$endif}
+
   TNativeUIntHelper = Type Helper for NativeUInt
+  const
+    MaxValue  = High(NativeUInt);
+    MinValue  = 0;
+    MaxBit    = High(TNativeUIntBitIndex);
+    MinBit    = Low(TNativeUIntBitIndex);
+    MaxNibble = High(TNativeUIntNibbleIndex);
+    MinNibble = Low(TNativeUIntNibbleIndex);
+    // NativeInt on cpu16 has 2 bytes, so no need for cpu16 check because we always need MaxByte and MinByte
+    MaxByte   = High(TNativeUIntByteIndex);
+    MinByte   = Low(TNativeUIntByteIndex);
+    {$ifdef cpu32}
+    MaxWord   = High(TNativeUIntWordIndex);
+    MinWord   = Low(TNativeUIntWordIndex);
+    {$endif}
+    {$ifdef cpu64}
+    MaxWord   = High(TNativeUIntWordIndex);
+    MinWord   = Low(TNativeUIntWordIndex);
+    MaxDword  = High(TNativeUIntDwordIndex);
+    MinDword  = Low(TNativeUIntDwordIndex);
+    {$endif}
   public
-    const
-      MaxValue = High(NativeUInt);
-      MinValue = 0;
-  Public
     Class Function Parse(const AString: string): NativeUInt; inline; static;
     Class Function Size: Integer; inline; static;
     Class Function ToString(const AValue: NativeUInt): string; overload; inline; static;
     Class Function TryParse(const AString: string; out AValue: NativeUInt): Boolean; inline; static;
-  Public
+  protected
+    function  GetBit(const aIndex: TNativeUIntBitIndex): boolean; inline;
+    procedure PutBit(const aIndex: TNativeUIntBitIndex; const aNewValue: boolean); inline;
+    function  GetNibble(const aIndex: TNativeUIntNibbleIndex): nibble; inline;
+    procedure PutNibble(const aIndex: TNativeUIntNibbleIndex; const aNewValue: nibble); inline;
+    // NativeInt on cpu16 has 2 bytes, so no need for cpu16 check because we always need GetByte and PutByte
+    function  GetByte(const aIndex: TNativeUIntByteIndex): byte;
+    procedure PutByte(const aIndex: TNativeUIntByteIndex; const aNewValue: byte);
+    {$ifdef cpu32}
+    function  GetWord(const aIndex: TNativeUIntWordIndex): word;
+    procedure PutWord(const aIndex: TNativeUIntWordIndex; const aNewValue: word);
+    {$endif}
+    {$ifdef cpu64}
+    function  GetWord(const aIndex: TNativeUIntWordIndex): word;
+    procedure PutWord(const aIndex: TNativeUIntWordIndex; const aNewValue: word);
+    function  GetDword(const aIndex: TNativeUIntDwordIndex): dword;
+    procedure PutDword(const aIndex: TNativeUIntDwordIndex; const aNewValue: dword);
+    {$endif}
+  public
     Function ToBoolean: Boolean; inline;
     Function ToDouble: Double; inline;
     Function ToExtended: Extended; inline;
-    Function ToBinString:string; inline;
-    Function ToHexString(const AMinDigits: Integer): string; overload; inline;
-    Function ToHexString: string; overload; inline;
     Function ToSingle: Single; inline;
     Function ToString: string; overload; inline;
     Function SetBit(const Index: TNativeUIntBitIndex) : NativeUint; inline;
     Function ClearBit(const Index: TNativeUIntBitIndex): NativeUint; inline;
     Function ToggleBit(const Index: TNativeUIntBitIndex) : NativeUint; inline;
     Function TestBit(const Index:TNativeUIntBitIndex) :Boolean; inline;
+    procedure Clear; inline;
+    function  ToBinString(const aBinFormatSettings: TBinFormatSettings; const aShowLeadingZeros: boolean = true; const aMinDigits: integer = 0): string; overload;
+    function  ToBinString(const aBinFormatSettings: TBinFormatSettings; const aMinDigits: integer): string; overload; inline;
+    function  ToBinString(const aMinDigits: integer): string; overload; inline;
+    function  ToBinString(const aShowLeadingZeros: boolean = true): string; overload; inline;
+    function  ToHexString(const aHexFormatSettings: THexFormatSettings; const aShowLeadingZeros: boolean = true; const aMinDigits: integer = 0): string; overload;
+    function  ToHexString(const aHexFormatSettings: THexFormatSettings; const aMinDigits: integer): string; overload; inline;
+    function  ToHexString(const aMinDigits: integer): string; overload; inline;
+    function  ToHexString(const aShowLeadingZeros: boolean = true): string; overload; inline;
+    function  HighestBitPos: cardinal; inline;
+    function  LowestBitPos: cardinal; inline;
+    function  BitsCount: byte; inline;
+    property  Bit   [aIndex: TNativeUIntBitIndex]: boolean   read GetBit    write PutBit;
+    property  Nibble[aIndex: TNativeUIntNibbleIndex]: nibble read GetNibble write PutNibble;
+    // NativeInt on cpu16 has 2 bytes, so no need for cpu16 check because we always need Byte[]
+    property  Byte  [aIndex: TNativeUIntByteIndex]: byte     read GetByte   write PutByte;
+    {$ifdef cpu32}
+    property  Word  [aIndex: TNativeUIntWordIndex]: word     read GetWord   write PutWord;
+    {$endif}
+    {$ifdef cpu64}
+    property  Word  [aIndex: TNativeUIntWordIndex]: word     read GetWord   write PutWord;
+    property  DWord [aIndex: TNativeUIntDwordIndex]: dword   read GetDWord  write PutDWord;
+    {$endif}
   end;
 
   {$SCOPEDENUMS ON}
@@ -641,9 +1095,14 @@ Type
     Class Function Size: Integer; inline; static;
     Class Function ToString(const AValue: Boolean; UseBoolStrs: TUseBoolStrs = TUseBoolStrs.False): string; overload; inline; static;
     Class Function TryToParse(const S: string; out AValue: Boolean): Boolean; inline; static;
+    class function ToString(const aValue: boolean; const aTrueStr, aFalseStr: string; const aCharsCase: TStringCaseFormat = scfUnchangedCase): string; overload; static;
   Public
     Function ToInteger: Integer; inline;
     Function ToString(UseBoolStrs: TUseBoolStrs = TUseBoolStrs.False): string; overload; inline;
+    function ToOneZeroString(const aCharsCase: TStringCaseFormat = scfUnchangedCase): string; inline;
+    function ToOnOffString(const aCharsCase: TStringCaseFormat = scfUnchangedCase): string; inline;
+    function ToTrueFalseString(const aCharsCase: TStringCaseFormat = scfUnchangedCase): string; inline;
+    function ToString(const aTrueStr, aFalseStr: string; const aCharsCase: TStringCaseFormat = scfUnchangedCase): string; overload; inline;
   end;
 
   TByteBoolHelper = Type Helper for ByteBool
@@ -652,9 +1111,14 @@ Type
     Class Function Size: Integer; inline; static;
     Class Function ToString(const AValue: Boolean; UseBoolStrs: TUseBoolStrs = TUseBoolStrs.False): string; overload; inline; static;
     Class Function TryToParse(const S: string; out AValue: Boolean): Boolean; inline; static;
+    class function ToString(const aValue: boolean; const aTrueStr, aFalseStr: string; const aCharsCase: TStringCaseFormat = scfUnchangedCase): string; overload; static;
   Public
     Function ToInteger: Integer; inline;
     Function ToString(UseBoolStrs: TUseBoolStrs = TUseBoolStrs.False): string; overload; inline;
+    function ToOneZeroString(const aCharsCase: TStringCaseFormat = scfUnchangedCase): string; inline;
+    function ToOnOffString(const aCharsCase: TStringCaseFormat = scfUnchangedCase): string; inline;
+    function ToTrueFalseString(const aCharsCase: TStringCaseFormat = scfUnchangedCase): string; inline;
+    function ToString(const aTrueStr, aFalseStr: string; const aCharsCase: TStringCaseFormat = scfUnchangedCase): string; overload; inline;
   end;
 
   TWordBoolHelper = Type Helper for WordBool
@@ -663,9 +1127,14 @@ Type
     Class Function Size: Integer; inline; static;
     Class Function ToString(const AValue: Boolean; UseBoolStrs: TUseBoolStrs = TUseBoolStrs.False): string; overload; inline; static;
     Class Function TryToParse(const S: string; out AValue: Boolean): Boolean; inline; static;
+    class function ToString(const aValue: boolean; const aTrueStr, aFalseStr: string; const aCharsCase: TStringCaseFormat = scfUnchangedCase): string; overload; static;
   Public
     Function ToInteger: Integer; inline;
     Function ToString(UseBoolStrs: TUseBoolStrs = TUseBoolStrs.False): string; overload; inline;
+    function ToOneZeroString(const aCharsCase: TStringCaseFormat = scfUnchangedCase): string; inline;
+    function ToOnOffString(const aCharsCase: TStringCaseFormat = scfUnchangedCase): string; inline;
+    function ToTrueFalseString(const aCharsCase: TStringCaseFormat = scfUnchangedCase): string; inline;
+    function ToString(const aTrueStr, aFalseStr: string; const aCharsCase: TStringCaseFormat = scfUnchangedCase): string; overload; inline;
   end;
 
   TLongBoolHelper = Type Helper for LongBool
@@ -674,7 +1143,12 @@ Type
     Class Function Size: Integer; inline; static;
     Class Function ToString(const AValue: Boolean; UseBoolStrs: TUseBoolStrs = TUseBoolStrs.False): string; overload; inline; static;
     Class Function TryToParse(const S: string; out AValue: Boolean): Boolean; inline; static;
+    class function ToString(const aValue: boolean; const aTrueStr, aFalseStr: string; const aCharsCase: TStringCaseFormat = scfUnchangedCase): string; overload; static;
   public
     Function ToInteger: Integer; inline;
     Function ToString(UseBoolStrs: TUseBoolStrs = TUseBoolStrs.False): string; overload; inline;
+    function ToOneZeroString(const aCharsCase: TStringCaseFormat = scfUnchangedCase): string; inline;
+    function ToOnOffString(const aCharsCase: TStringCaseFormat = scfUnchangedCase): string; inline;
+    function ToTrueFalseString(const aCharsCase: TStringCaseFormat = scfUnchangedCase): string; inline;
+    function ToString(const aTrueStr, aFalseStr: string; const aCharsCase: TStringCaseFormat = scfUnchangedCase): string; overload; inline;
   end;
diff --git a/rtl/objpas/sysutils/syshelpo.inc b/rtl/objpas/sysutils/syshelpo.inc
index 497d0ef508..34f2873340 100644
--- a/rtl/objpas/sysutils/syshelpo.inc
+++ b/rtl/objpas/sysutils/syshelpo.inc
@@ -1,6 +1,5 @@
 
 Class Function TORDINALHELPER.Parse(const AString: string): TORDINALTYPE; inline; static;
-
 var
   Error: Integer;
 begin
@@ -10,99 +9,274 @@ begin
 end;
 
 Class Function TORDINALHELPER.Size: Integer; inline; static;
-
 begin
   Result:=SizeOf(TORDINALTYPE);
 end;
 
 Class Function TORDINALHELPER.ToString(const AValue: TORDINALTYPE): string; overload; inline; static;
-
 begin
   Str(AValue,Result);
 end;
 
 Class Function TORDINALHELPER.TryParse(const AString: string; out AValue: TORDINALTYPE): Boolean; inline; static;
-
 Var
   C : Integer;
-
 begin
   Val(AString,AValue,C);
   Result:=(C=0);
 end;
 
 Function TORDINALHELPER.ToBoolean: Boolean; inline;
-
 begin
   Result:=(Self<>0);
 end;
 
 Function TORDINALHELPER.ToDouble: Double; inline;
-
 begin
   Result:=Self;
 end;
 
 Function TORDINALHELPER.ToExtended: Extended; inline;
+begin
+  Result:=Self;
+end;
 
+Function TORDINALHELPER.ToSingle: Single; inline;
 begin
   Result:=Self;
 end;
 
-Function TORDINALHELPER.ToBinString: string; inline;
+Function TORDINALHELPER.ToString: string; overload; inline;
+begin
+  Str(Self,Result);
+end;
 
+Function TORDINALHELPER.SetBit(const index: TORDINALBITINDEX) : TORDINALTYPE; inline;
 begin
-  Result:=BinStr(Self,SizeOf(TORDINALTYPE)*8);
+  Self := Self or (TORDINALTYPE(1) shl index);
+  Result:=Self;
 end;
 
-Function TORDINALHELPER.ToHexString(const AMinDigits: Integer): string;
-overload; inline;
+Function TORDINALHELPER.ClearBit(const index: TORDINALBITINDEX) : TORDINALTYPE; inline;
+begin
+  Self:=Self and not TORDINALTYPE((TORDINALTYPE(1) shl index));
+  Result:=Self;
+end;
 
+Function TORDINALHELPER.ToggleBit(const index: TORDINALBITINDEX) : TORDINALTYPE; inline;
 begin
-  Result:=IntToHex(Self,AMinDigits);
+  Self := Self xor TORDINALTYPE((TORDINALTYPE(1) shl index));
+  Result:=Self;
 end;
 
-Function TORDINALHELPER.ToHexString: string; overload; inline;
+Function TORDINALHELPER.TestBit(const Index: TORDINALBITINDEX):Boolean; inline;
+begin
+  Result := (Self and TORDINALTYPE((TORDINALTYPE(1) shl index)))<>0;
+end;
 
+procedure TORDINALHELPER.Clear;
 begin
-  Result:=IntToHex(Self);
+  Self := 0;
 end;
 
-Function TORDINALHELPER.ToSingle: Single; inline;
+function TORDINALHELPER.ToBinString(const aBinFormatSettings: TBinFormatSettings; const aShowLeadingZeros: boolean = true; const aMinDigits: integer = 0): string; overload;
+var
+  BitCounter: TORDINALBITINDEX;
+  LeadingZeros: boolean;
+begin
+  Result := aBinFormatSettings.BinPrefixString;
+  LeadingZeros := true;
+  for BitCounter := MaxBit downto MinBit do
+  begin
+    LeadingZeros := LeadingZeros and not Self.Bit[BitCounter];
+    if aShowLeadingZeros or (not LeadingZeros) or (BitCounter = MinBit) or (BitCounter < aMinDigits) then
+    begin
+      if BitCounter <> MaxBit then // time for separator ?
+        if ((BitCounter + 1) mod 32 = 0) then // every 32 bits we have a dword
+          Result := Result + aBinFormatSettings.BinDwordSeparator
+        else
+          if ((BitCounter + 1) mod 16 = 0) then // every 16 bits we have a word
+            Result := Result + aBinFormatSettings.BinWordSeparator
+          else
+            if ((BitCounter + 1) mod 8 = 0) then // every 8 bits we have a byte
+              Result := Result + aBinFormatSettings.BinByteSeparator
+            else
+              if ((BitCounter + 1) mod 4 = 0) then // every 4 bits we have a nibble
+                Result := Result + aBinFormatSettings.BinNibbleSeparator;
+      Result := Result + Self.Bit[BitCounter].ToOneZeroString;
+    end;
+  end;
+  Result := Result + aBinFormatSettings.BinSufixString;
+end;
 
+function TORDINALHELPER.ToBinString(const aBinFormatSettings: TBinFormatSettings; const aMinDigits: integer): string; overload;
 begin
-  Result:=Self;
+  Result := ToBinString(aBinFormatSettings, false, aMinDigits);
 end;
 
-Function TORDINALHELPER.ToString: string; overload; inline;
+function TORDINALHELPER.ToBinString(const aMinDigits: integer): string; overload;
+begin
+  Result := ToBinString(DefaultBinFormatSettings, false, aMinDigits);
+end;
 
+function TORDINALHELPER.ToBinString(const aShowLeadingZeros: boolean = true): string; overload;
 begin
-  Str(Self,Result);
+  Result := ToBinString(DefaultBinFormatSettings, aShowLeadingZeros, 0);
 end;
 
-Function TORDINALHELPER.SetBit(const index: TORDINALBITINDEX) : TORDINALTYPE; inline;
+function TORDINALHELPER.ToHexString(const aHexFormatSettings: THexFormatSettings; const aShowLeadingZeros: boolean = true; const aMinDigits: integer = 0): string; overload;
+var
+  NibbleCounter: TORDINALNIBBLEINDEX;
+  LeadingZeros, PassedFirstNibble: boolean;
+begin
+  Result := aHexFormatSettings.HexPrefixString;
+  LeadingZeros := true;
+  PassedFirstNibble := false;
+  for NibbleCounter := MaxNibble downto MinNibble do
+  begin
+    LeadingZeros := LeadingZeros and (Self.Nibble[NibbleCounter] = 0);
+    if aShowLeadingZeros or (not LeadingZeros) or (NibbleCounter = MinNibble) or (NibbleCounter < aMinDigits) then
+    begin
+      if PassedFirstNibble then // time for separator ?
+        if ((NibbleCounter + 1) mod 8 = 0) then // every 8 nibbles we have a dword
+          Result := Result + aHexFormatSettings.HexDwordSeparator
+        else
+          if ((NibbleCounter + 1) mod 4 = 0) then // every 4 nibbles we have a word
+            Result := Result + aHexFormatSettings.HexWordSeparator
+          else
+            if ((NibbleCounter + 1) mod 2 = 0) then // every 2 nibbles we have a byte
+              Result := Result + aHexFormatSettings.HexByteSeparator
+            else
+              if PassedFirstNibble then
+                Result := Result + aHexFormatSettings.HexNibbleSeparator;
+      Result := Result + HexDigits[Self.Nibble[NibbleCounter]];
+      PassedFirstNibble := true;
+    end;
+  end;
+  Result := Result + aHexFormatSettings.HexSufixString;
+end;
 
+function TORDINALHELPER.ToHexString(const aHexFormatSettings: THexFormatSettings; const aMinDigits: integer): string; overload;
 begin
-  Self := Self or (TORDINALTYPE(1) shl index);
-  Result:=Self;
+  Result := ToHexString(aHexFormatSettings, false, aMinDigits);
 end;
 
-Function TORDINALHELPER.ClearBit(const index: TORDINALBITINDEX) : TORDINALTYPE; inline;
+function TORDINALHELPER.ToHexString(const aMinDigits: integer): string; overload;
+begin
+  Result := ToHexString(DefaultHexFormatSettings, false, aMinDigits);
+end;
 
+function TORDINALHELPER.ToHexString(const aShowLeadingZeros: boolean = true): string; overload;
 begin
-  Self:=Self and not TORDINALTYPE((TORDINALTYPE(1) shl index));
-  Result:=Self;
+  Result := ToHexString(DefaultHexFormatSettings, aShowLeadingZeros, 0);
 end;
 
-Function TORDINALHELPER.ToggleBit(const index: TORDINALBITINDEX) : TORDINALTYPE; inline;
+function TORDINALHELPER.HighestBitPos: cardinal;
+begin
+  {$ifdef TORDINALTYPESIZE1}
+        Result := BsrByte(byte(Self));
+  {$else}
+    {$ifdef TORDINALTYPESIZE2}
+        Result := BsrWord(word(Self));
+    {$else}
+      {$ifdef TORDINALTYPESIZE4}
+        Result := BsrDWord(dword(Self));
+      {$else} // TORDINALTYPESIZE8
+        Result := BsrQWord(qword(Self));
+      {$endif}
+    {$endif}
+  {$endif}
+end;
 
+function TORDINALHELPER.LowestBitPos: cardinal;
 begin
-  Self := Self xor TORDINALTYPE((TORDINALTYPE(1) shl index));
-  Result:=Self;
+  {$ifdef TORDINALTYPESIZE1}
+        Result := BsfByte(byte(Self));
+  {$else}
+    {$ifdef TORDINALTYPESIZE2}
+        Result := BsfWord(word(Self));
+    {$else}
+      {$ifdef TORDINALTYPESIZE4}
+        Result := BsfDWord(dword(Self));
+      {$else} // TORDINALTYPESIZE8
+        Result := BsfQWord(qword(Self));
+      {$endif}
+    {$endif}
+  {$endif}
 end;
 
-Function TORDINALHELPER.TestBit(const Index: TORDINALBITINDEX):Boolean; inline;
+function TORDINALHELPER.BitsCount: byte;
+begin
+  {$ifdef TORDINALTYPESIZE1}
+        Result := PopCnt(byte(Self));
+  {$else}
+    {$ifdef TORDINALTYPESIZE2}
+        Result := PopCnt(word(Self));
+    {$else}
+      {$ifdef TORDINALTYPESIZE4}
+        Result := PopCnt(dword(Self));
+      {$else} // TORDINALTYPESIZE8
+        Result := PopCnt(qword(Self));
+      {$endif}
+    {$endif}
+  {$endif}
+end;
 
+function TORDINALHELPER.GetBit(const aIndex: TORDINALBITINDEX): boolean;
 begin
-  Result := (Self and TORDINALTYPE((TORDINALTYPE(1) shl index)))<>0;
+  Result := ((Self shr aIndex) and TORDINALTYPE(1)) = TORDINALTYPE(1);
+end;
+
+procedure TORDINALHELPER.PutBit(const aIndex: TORDINALBITINDEX; const aNewValue: boolean);
+begin
+  Self := Self or (TORDINALTYPE(1) shl aIndex) xor (TORDINALTYPE(not aNewValue) shl aIndex);
+end;
+
+function TORDINALHELPER.GetNibble(const aIndex: TORDINALNIBBLEINDEX): nibble;
+begin
+  Result := TORDINALOVERLAY(Self).AsNibble[aIndex];
+end;
+
+procedure TORDINALHELPER.PutNibble(const aIndex: TORDINALNIBBLEINDEX; const aNewValue: nibble);
+begin
+  TORDINALOVERLAY(Self).AsNibble[aIndex] := aNewValue;
 end;
+
+{$ifndef TORDINALTYPESIZE1} // TWordHelper, TDWordHelper, TQWordHelper jump in here (and others with 2, 4 and 8 bytes)
+  function TORDINALHELPER.GetByte(const aIndex: TORDINALBYTEINDEX): byte;
+  begin
+    Result := TORDINALOVERLAY(Self).AsByte[aIndex];
+  end;
+
+  procedure TORDINALHELPER.PutByte(const aIndex: TORDINALBYTEINDEX; const aNewValue: byte);
+  begin
+    TORDINALOVERLAY(Self).AsByte[aIndex] := aNewValue;
+  end;
+
+  {$ifndef TORDINALTYPESIZE2} // TDWordHelper, TQWordHelper jump in here (and others with 4 and 8 bytes)
+    function TORDINALHELPER.GetWord(const aIndex: TORDINALWORDINDEX): word;
+    begin
+      Result := TORDINALOVERLAY(Self).AsWord[aIndex];
+    end;
+
+    procedure TORDINALHELPER.PutWord(const aIndex: TORDINALWORDINDEX; const aNewValue: word);
+    begin
+      TORDINALOVERLAY(Self).AsWord[aIndex] := aNewValue;
+    end;
+
+    {$ifndef TORDINALTYPESIZE4} // TQWordHelper jumps in here (and others with 8 bytes)
+      function TORDINALHELPER.GetDword(const aIndex: TORDINALDWORDINDEX): dword;
+      begin
+        Result := TORDINALOVERLAY(Self).AsDword[aIndex];
+      end;
+
+      procedure TORDINALHELPER.PutDword(const aIndex: TORDINALDWORDINDEX; const aNewValue: dword);
+      begin
+        TORDINALOVERLAY(Self).AsDword[aIndex] := aNewValue;
+      end;
+    {$endif}
+
+  {$endif}
+
+{$endif}
+
diff --git a/rtl/objpas/sysutils/sysstr.inc b/rtl/objpas/sysutils/sysstr.inc
index 82725fc8fa..b12c18524e 100644
--- a/rtl/objpas/sysutils/sysstr.inc
+++ b/rtl/objpas/sysutils/sysstr.inc
@@ -877,8 +877,8 @@ end;
 
 {   IntToHex returns a string representing the hexadecimal value of Value   }
 
-const
-   HexDigits: array[0..15] of char = '0123456789ABCDEF';
+//const
+//   HexDigits: array[0..15] of char = '0123456789ABCDEF'; // moved to sysstrh.inc so that it also becomes available to HexToString in syshelpo.inc
 
 function IntToHex(Value: Longint; Digits: integer): string;
 var i: integer;
@@ -2015,13 +2015,17 @@ procedure CheckBoolStrs;
 begin
     If Length(TrueBoolStrs)=0 then
       begin
-        SetLength(TrueBoolStrs,1);
-        TrueBoolStrs[0]:='True';
+        SetLength(TrueBoolStrs,3);
+        TrueBoolStrs[0]:=DefaultBitFormatSettings.BitTrueString;
+        TrueBoolStrs[1]:=DefaultBitFormatSettings.BitOnString;
+        TrueBoolStrs[2]:=DefaultBitFormatSettings.BitOneString;
       end;
     If Length(FalseBoolStrs)=0 then
       begin
-        SetLength(FalseBoolStrs,1);
-        FalseBoolStrs[0]:='False';
+        SetLength(FalseBoolStrs,3);
+        FalseBoolStrs[0]:=DefaultBitFormatSettings.BitFalseString;
+        FalseBoolStrs[1]:=DefaultBitFormatSettings.BitOffString;
+        FalseBoolStrs[2]:=DefaultBitFormatSettings.BitZeroString;
       end;
 end;
 
diff --git a/rtl/objpas/sysutils/sysstrh.inc b/rtl/objpas/sysutils/sysstrh.inc
index 370ca8356a..8a380dcf1c 100644
--- a/rtl/objpas/sysutils/sysstrh.inc
+++ b/rtl/objpas/sysutils/sysstrh.inc
@@ -62,6 +62,9 @@ Const
 Var TrueBoolStrs,
     FalseBoolStrs : Array of String;
 
+const
+   HexDigits: array[0..15] of char = '0123456789ABCDEF';
+
 // declaring this breaks delphi compatibility and e.g. tw3721.pp
 // function NewStr(Const S: ShortString): PShortString; overload;
 function NewStr(const S: string): PString; overload;
diff --git a/rtl/objpas/sysutils/sysutilh.inc b/rtl/objpas/sysutils/sysutilh.inc
index 16d2da23dc..be38012c80 100644
--- a/rtl/objpas/sysutils/sysutilh.inc
+++ b/rtl/objpas/sysutils/sysutilh.inc
@@ -18,6 +18,9 @@
   { Read internationalization settings }
   {$i sysinth.inc}
 
+  { Read internationalization settings for boolean, binary and hex to strings conversion }
+  {$i sysintextrah.inc}
+
   { Read date & Time function declarations }
   {$i osutilsh.inc}
 
diff --git a/rtl/objpas/sysutils/sysutils.inc b/rtl/objpas/sysutils/sysutils.inc
index 7855753b97..1de80e0b53 100644
--- a/rtl/objpas/sysutils/sysutils.inc
+++ b/rtl/objpas/sysutils/sysutils.inc
@@ -136,6 +136,9 @@ end;
   { generic internationalisation code }
   {$i sysint.inc}
 
+  { boolean, binary and hex conversion internationalisation code }
+  {$i sysintextra.inc}
+
   { wide string functions }
   {$i syswide.inc}
 
sysutils-bithelpers.patch (74,317 bytes)   

Michael Van Canneyt

2021-07-20 09:37

administrator   ~0131948

This is not acceptable.

Please split out your patch.
A patch for the bit access, a patch for boolean changes, a patch for additional changes.
Throwing these things together is really not done.

Additionally:
I'm willing to put in the patches for bit access in sysutils since it extends the current functionality slightly,

But all the other stuff must go in a separate unit: These helpers take up way too much size.
The SysUtils unit is already bloated as it is.

Zeljko Avramovic

2021-07-20 11:54

reporter   ~0131955

Last edited: 2021-07-20 12:08

View 2 revisions

Before implementing the request I would like to clear things to avoid misunderstanding and to save everyone's time.

My changes could be split to these 3 parts:

Patch1) Bit and index based handling for ordinal types via helpers for byte, shortint, word, smallint, dword, cardinal, integer, qword, in64, nativeint and nativeuint. If I understand well (please be more specific if not), then this logical group of helper changes should be considered as one patch to sysutils:

  const
    MaxBit = High(TQwordBitIndex);
    MinBit = Low(TQwordBitIndex);
    MaxNibble = High(TQwordNibbleIndex);
    MinNibble = Low(TQwordNibbleIndex);
    MaxByte = High(TQwordByteIndex);
    MinByte = Low(TQwordByteIndex);
    MaxWord = High(TQwordWordIndex);
    MinWord = Low(TQwordWordIndex);
    MaxDword = High(TQwordDwordIndex);
    MinDword = Low(TQwordDwordIndex);
  protected
    function GetBit(const aIndex: TQwordBitIndex): boolean; inline;
    procedure PutBit(const aIndex: TQwordBitIndex; const aNewValue: boolean); inline;
    function GetNibble(const aIndex: TQwordNibbleIndex): nibble; inline;
    procedure PutNibble(const aIndex: TQwordNibbleIndex; const aNewValue: nibble); inline;
    function GetByte(const aIndex: TQwordByteIndex): byte;
    procedure PutByte(const aIndex: TQwordByteIndex; const aNewValue: byte);
    function GetWord(const aIndex: TQwordWordIndex): word;
    procedure PutWord(const aIndex: TQwordWordIndex; const aNewValue: word);
    function GetDword(const aIndex: TQwordDwordIndex): dword;
    procedure PutDword(const aIndex: TQwordDwordIndex; const aNewValue: dword);
public
    function HighestBitPos: cardinal; inline;
    function LowestBitPos: cardinal; inline;
    function BitsCount: byte; inline;
    property Bit [aIndex: TQwordBitIndex]: boolean read GetBit write PutBit;
    property Nibble[aIndex: TQwordNibbleIndex]: nibble read GetNibble write PutNibble;
    property Byte [aIndex: TQwordByteIndex]: byte read GetByte write PutByte;
    property Word [aIndex: TQwordWordIndex]: word read GetWord write PutWord;
    property DWord [aIndex: TQwordDwordIndex]: dword read GetDWord write PutDWord;

Patch2) Boolean changes include TBitFormatSettings, TDefaultBitFormatSettings, patching for BoolToStr() and TryStrToBool() to accept new internationalized customizable strings, and these methods:

class function TBOOLHELPER.ToString(const aValue: boolean; const aTrueStr, aFalseStr: string; const aCharsCase: TStringCaseFormat = scfUnchangedCase): string; overload; static;
function TBOOLHELPER.ToOneZeroString(const aCharsCase: TStringCaseFormat = scfUnchangedCase): string; inline;
function TBOOLHELPER.ToOnOffString(const aCharsCase: TStringCaseFormat = scfUnchangedCase): string; inline;
function TBOOLHELPER.ToTrueFalseString(const aCharsCase: TStringCaseFormat = scfUnchangedCase): string; inline;
function TBOOLHELPER.ToString(const aTrueStr, aFalseStr: string; const aCharsCase: TStringCaseFormat = scfUnchangedCase): string; overload; inline;

Patch3) extending ordinal type conversion to binary and hex string representation. Changes include TBinFormatSettings, TDefaultBinFormatSettings, THexFormatSettings, TDefaultHexFormatSettings and these helper methods:

    function ToBinString(const aBinFormatSettings: TBinFormatSettings; const aShowLeadingZeros: boolean = true; const aMinDigits: integer = 0): string; overload;
    function ToBinString(const aBinFormatSettings: TBinFormatSettings; const aMinDigits: integer): string; overload; inline;
    function ToBinString(const aMinDigits: integer): string; overload; inline;
    function ToBinString(const aShowLeadingZeros: boolean = true): string; overload; inline;
    function ToHexString(const aHexFormatSettings: THexFormatSettings; const aShowLeadingZeros: boolean = true; const aMinDigits: integer = 0): string; overload;
    function ToHexString(const aHexFormatSettings: THexFormatSettings; const aMinDigits: integer): string; overload; inline;
    function ToHexString(const aMinDigits: integer): string; overload; inline;
    function ToHexString(const aShowLeadingZeros: boolean = true): string; overload; inline;

If bloating sysutils is an issue, then I would prefer to completelly give up on extending sysutils, and provide a single unit with all extended helpers that a user can simply include and use out of the box. All would be in one single place and sysutils stay the way they are now. Something similar to what I did earlier providing bithelpers as a separate library in a single unit (https://bitbucket.org/avra/bithelpers/src/master/bithelpers.pas). What do you think, would that be more acceptable?

Michael Van Canneyt

2021-07-20 12:13

administrator   ~0131956

Your division is correct.

But I want to see patches 2 and 3 in a new unit called syshelpers - which I will include in rtl-objpas.

The helpers in these units can descend from the ones in SysUtils, so that if someone includes syshelpers, both helpers are available.

But if you prefer, you can also put your complete implementation in the syshelpers unit.
That is also fine for me, and maybe easier for you.

Zeljko Avramovic

2021-07-20 12:24

reporter   ~0131957

Ok, I will see what it takes to prepare Patch1 to extend sysutils, and to put everything else into new unit syshelpers. Should I put into syshelpers also functionality from sysintextra.inc and sysintextrah.inc (TBitFormatSettings, TDefaultBitFormatSettings, TBinFormatSettings, TDefaultBinFormatSettings, THexFormatSettings, TDefaultHexFormatSettings), or leave it as a separate unit? If it should be in a separate unit, then maybe there is some better name then sysintextra?

Michael Van Canneyt

2021-07-20 12:48

administrator   ~0131959

Please put everything in SysHelpers.
There is little sense in putting these settings things in a separate unit.

Zeljko Avramovic

2021-07-20 12:57

reporter   ~0131960

Ok, thanks for your input!

Zeljko Avramovic

2021-07-20 22:46

reporter   ~0131966

Here is only the first patch. Please review.
1.patch (43,095 bytes)   
diff --git a/rtl/objpas/sysutils/syshelp.inc b/rtl/objpas/sysutils/syshelp.inc
index 1d6d4e50c2..2669a19452 100644
--- a/rtl/objpas/sysutils/syshelp.inc
+++ b/rtl/objpas/sysutils/syshelp.inc
@@ -1567,7 +1567,11 @@ end;
 {$define TORDINALHELPER:=TByteHelper}
 {$define TORDINALTYPE:=Byte}
 {$define TORDINALBITINDEX:=TByteBitIndex}
+{$define TORDINALNIBBLEINDEX:=TByteNibbleIndex}
+{$define TORDINALOVERLAY:=TByteOverlay}
+{$define TORDINALTYPESIZE1}
 {$i syshelpo.inc}
+{$undef TORDINALTYPESIZE1}
 
 { ---------------------------------------------------------------------
   TShortintHelper
@@ -1576,7 +1580,11 @@ end;
 {$define TORDINALHELPER:=TShortIntHelper}
 {$define TORDINALTYPE:=ShortInt}
 {$define TORDINALBITINDEX:=TShortIntBitIndex}
+{$define TORDINALNIBBLEINDEX:=TShortIntNibbleIndex}
+{$define TORDINALOVERLAY:=TShortIntOverlay}
+{$define TORDINALTYPESIZE1}
 {$i syshelpo.inc}
+{$undef TORDINALTYPESIZE1}
 
 { ---------------------------------------------------------------------
   TSmallintHelper
@@ -1585,7 +1593,12 @@ end;
 {$define TORDINALHELPER:=TSmallIntHelper}
 {$define TORDINALTYPE:=SmallInt}
 {$define TORDINALBITINDEX:=TSmallIntBitIndex}
+{$define TORDINALNIBBLEINDEX:=TSmallIntNibbleIndex}
+{$define TORDINALBYTEINDEX:=TWordByteIndex}
+{$define TORDINALOVERLAY:=TWordOverlay}
+{$define TORDINALTYPESIZE2}
 {$i syshelpo.inc}
+{$undef TORDINALTYPESIZE2}
 
 { ---------------------------------------------------------------------
   TWordHelper
@@ -1594,7 +1607,12 @@ end;
 {$define TORDINALHELPER:=TWordHelper}
 {$define TORDINALTYPE:=Word}
 {$define TORDINALBITINDEX:=TWordBitIndex}
+{$define TORDINALNIBBLEINDEX:=TWordNibbleIndex}
+{$define TORDINALBYTEINDEX:=TWordByteIndex}
+{$define TORDINALOVERLAY:=TWordOverlay}
+{$define TORDINALTYPESIZE2}
 {$i syshelpo.inc}
+{$undef TORDINALTYPESIZE2}
 
 { ---------------------------------------------------------------------
   TCardinalHelper
@@ -1603,7 +1621,13 @@ end;
 {$define TORDINALHELPER:=TCardinalHelper}
 {$define TORDINALTYPE:=Cardinal}
 {$define TORDINALBITINDEX:=TCardinalBitIndex}
+{$define TORDINALNIBBLEINDEX:=TCardinalNibbleIndex}
+{$define TORDINALBYTEINDEX:=TCardinalByteIndex}
+{$define TORDINALWORDINDEX:=TCardinalWordIndex}
+{$define TORDINALOVERLAY:=TDwordOverlay}
+{$define TORDINALTYPESIZE4}
 {$i syshelpo.inc}
+{$undef TORDINALTYPESIZE4}
 
 { ---------------------------------------------------------------------
   TIntegerHelper
@@ -1612,7 +1636,13 @@ end;
 {$define TORDINALHELPER:=TIntegerHelper}
 {$define TORDINALTYPE:=Integer}
 {$define TORDINALBITINDEX:=TIntegerBitIndex}
+{$define TORDINALNIBBLEINDEX:=TIntegerNibbleIndex}
+{$define TORDINALBYTEINDEX:=TIntegerByteIndex}
+{$define TORDINALWORDINDEX:=TIntegerWordIndex}
+{$define TORDINALOVERLAY:=TDwordOverlay}
+{$define TORDINALTYPESIZE4}
 {$i syshelpo.inc}
+{$undef TORDINALTYPESIZE4}
 
 { ---------------------------------------------------------------------
   TInt64Helper
@@ -1621,7 +1651,14 @@ end;
 {$define TORDINALHELPER:=TInt64Helper}
 {$define TORDINALTYPE:=Int64}
 {$define TORDINALBITINDEX:=TInt64BitIndex}
+{$define TORDINALNIBBLEINDEX:=TInt64NibbleIndex}
+{$define TORDINALBYTEINDEX:=TInt64ByteIndex}
+{$define TORDINALWORDINDEX:=TInt64WordIndex}
+{$define TORDINALDWORDINDEX:=TInt64DWordIndex}
+{$define TORDINALOVERLAY:=TQwordOverlay}
+{$define TORDINALTYPESIZE8}
 {$i syshelpo.inc}
+{$undef TORDINALTYPESIZE8}
 
 { ---------------------------------------------------------------------
   TQWordHelper
@@ -1630,7 +1667,14 @@ end;
 {$define TORDINALHELPER:=TQWordHelper}
 {$define TORDINALTYPE:=QWord}
 {$define TORDINALBITINDEX:=TQwordBitIndex}
+{$define TORDINALNIBBLEINDEX:=TQwordNibbleIndex}
+{$define TORDINALBYTEINDEX:=TQwordByteIndex}
+{$define TORDINALWORDINDEX:=TQWordWordIndex}
+{$define TORDINALDWORDINDEX:=TQWordDWordIndex}
+{$define TORDINALOVERLAY:=TQwordOverlay}
+{$define TORDINALTYPESIZE8}
 {$i syshelpo.inc}
+{$undef TORDINALTYPESIZE8}
 
 { ---------------------------------------------------------------------
   TNativeIntHelper
@@ -1639,7 +1683,31 @@ end;
 {$define TORDINALHELPER:=TNativeIntHelper}
 {$define TORDINALTYPE:=NativeInt}
 {$define TORDINALBITINDEX:=TNativeIntBitIndex}
+{$ifdef cpu16}
+  {$define TORDINALNIBBLEINDEX:=TSmallIntNibbleIndex}
+  {$define TORDINALBYTEINDEX:=TSmallIntByteIndex}
+  {$define TORDINALOVERLAY:=TSmallIntOverlay}
+  {$define TORDINALTYPESIZE2}
+{$endif}
+{$ifdef cpu32}
+  {$define TORDINALNIBBLEINDEX:=TIntegerNibbleIndex}
+  {$define TORDINALBYTEINDEX:=TIntegerByteIndex}
+  {$define TORDINALWORDINDEX:=TIntegerWordIndex}
+  {$define TORDINALOVERLAY:=TIntegerOverlay}
+  {$define TORDINALTYPESIZE4}
+{$endif}
+{$ifdef cpu64}
+  {$define TORDINALNIBBLEINDEX:=TInt64NibbleIndex}
+  {$define TORDINALBYTEINDEX:=TInt64ByteIndex}
+  {$define TORDINALWORDINDEX:=TInt64WordIndex}
+  {$define TORDINALDWORDINDEX:=TInt64DWordIndex}
+  {$define TORDINALOVERLAY:=TInt64Overlay}
+  {$define TORDINALTYPESIZE8}
+{$endif}
 {$i syshelpo.inc}
+{$undef TORDINALTYPESIZE2}
+{$undef TORDINALTYPESIZE4}
+{$undef TORDINALTYPESIZE8}
 
 { ---------------------------------------------------------------------
   TNativeUIntHelper
@@ -1648,7 +1716,31 @@ end;
 {$define TORDINALHELPER:=TNativeUIntHelper}
 {$define TORDINALTYPE:=NativeUInt}
 {$define TORDINALBITINDEX:=TNativeUIntBitIndex}
+{$ifdef cpu16}
+  {$define TORDINALNIBBLEINDEX:=TWordNibbleIndex}
+  {$define TORDINALBYTEINDEX:=TWordByteIndex}
+  {$define TORDINALOVERLAY:=TWordOverlay}
+  {$define TORDINALTYPESIZE2}
+{$endif}
+{$ifdef cpu32}
+  {$define TORDINALNIBBLEINDEX:=TDwordNibbleIndex}
+  {$define TORDINALBYTEINDEX:=TDwordByteIndex}
+  {$define TORDINALWORDINDEX:=TDwordWordIndex}
+  {$define TORDINALOVERLAY:=TDwordOverlay}
+  {$define TORDINALTYPESIZE4}
+{$endif}
+{$ifdef cpu64}
+  {$define TORDINALNIBBLEINDEX:=TQwordNibbleIndex}
+  {$define TORDINALBYTEINDEX:=TQwordByteIndex}
+  {$define TORDINALWORDINDEX:=TQwordWordIndex}
+  {$define TORDINALDWORDINDEX:=TQwordDWordIndex}
+  {$define TORDINALOVERLAY:=TQwordOverlay}
+  {$define TORDINALTYPESIZE8}
+{$endif}
 {$i syshelpo.inc}
+{$undef TORDINALTYPESIZE2}
+{$undef TORDINALTYPESIZE4}
+{$undef TORDINALTYPESIZE8}
 
 { ---------------------------------------------------------------------
   TBooleanHelper
diff --git a/rtl/objpas/sysutils/syshelph.inc b/rtl/objpas/sysutils/syshelph.inc
index 2a4fe31477..e71f93c194 100644
--- a/rtl/objpas/sysutils/syshelph.inc
+++ b/rtl/objpas/sysutils/syshelph.inc
@@ -381,17 +381,37 @@ Type
   end;
 {$ENDIF FPC_HAS_TYPE_EXTENDED}
 
+  nibble           = 0..15;
+  TNibbleBitIndex  = 0..3;
+
+  // TByteBitIndex is already defined
+  TByteNibbleIndex = 0..1;
+
+  TByteOverlay = bitpacked record case integer of     // for fast extraction of bits
+    0: (AsBit:    bitpacked array[TByteBitIndex]    of boolean);
+    1: (AsNibble: bitpacked array[TByteNibbleIndex] of nibble);
+    2: (AsByte:   byte);
+  end;
+  
   TByteHelper = Type Helper for Byte
-  public
-    const
-      MaxValue = 255;
-      MinValue = 0;
+  const
+    MaxValue  = High(byte);
+    MinValue  = Low(byte);
+    MaxBit    = High(TByteBitIndex);
+    MinBit    = Low(TByteBitIndex);
+    MaxNibble = High(TByteNibbleIndex);
+    MinNibble = Low(TByteNibbleIndex);
   public
     Class Function Parse(const AString: string): Byte; inline; static;
     Class Function Size: Integer; inline; static;
     Class Function ToString(const AValue: Byte): string; overload; inline; static;
     Class Function TryParse(const AString: string; out AValue: Byte): Boolean; inline; static;
-  Public
+  protected
+    function  GetBit(const aIndex: TByteBitIndex): boolean; inline;
+    procedure PutBit(const aIndex: TByteBitIndex; const aNewValue: boolean); inline;
+    function  GetNibble(const aIndex: TByteNibbleIndex): nibble; inline;
+    procedure PutNibble(const aIndex: TByteNibbleIndex; const aNewValue: nibble); inline;
+  public
     Function ToBoolean: Boolean; inline;
     Function ToDouble: Double; inline;
     Function ToExtended: Extended; inline;
@@ -404,18 +424,38 @@ Type
     Function ClearBit(const Index: TByteBitIndex) : Byte; inline;
     Function ToggleBit(const Index: TByteBitIndex) : Byte; inline;
     Function TestBit(const Index:TByteBitIndex):Boolean; inline;
+    procedure Clear; inline;
+    function  HighestBitPos: cardinal; inline;
+    function  LowestBitPos: cardinal; inline;
+    function  BitsCount: byte; inline;
+    property  Bit   [aIndex: TByteBitIndex]: boolean   read GetBit    write PutBit;
+    property  Nibble[aIndex: TByteNibbleIndex]: nibble read GetNibble write PutNibble;
   end;
 
+  // TShortIntBitIndex is already defined
+
+  TShortIntNibbleIndex = TByteNibbleIndex;
+
+  TShortIntOverlay = TByteOverlay;
+
   TShortIntHelper = Type Helper for ShortInt
-  public
-    const
-      MaxValue = 127;
-      MinValue = -128;
+  const
+    MaxValue  = High(shortint);
+    MinValue  = Low(shortint);
+    MaxBit    = High(TShortIntBitIndex);
+    MinBit    = Low(TShortIntBitIndex);
+    MaxNibble = High(TShortIntNibbleIndex);
+    MinNibble = Low(TShortIntNibbleIndex);
   public
     Class Function Parse(const AString: string): ShortInt; inline; static;
     Class Function Size: Integer; inline; static;
     Class Function ToString(const AValue: ShortInt): string; overload; inline; static;
     Class Function TryParse(const AString: string; out AValue: ShortInt): Boolean; inline; static;
+  protected
+    function  GetBit(const aIndex: TShortIntBitIndex): boolean; inline;
+    procedure PutBit(const aIndex: TShortIntBitIndex; const aNewValue: boolean); inline;
+    function  GetNibble(const aIndex: TShortIntNibbleIndex): nibble; inline;
+    procedure PutNibble(const aIndex: TShortIntNibbleIndex; const aNewValue: nibble); inline;
   public
     Function ToBoolean: Boolean; inline;
     Function ToDouble: Double; inline;
@@ -429,18 +469,99 @@ Type
     Function ClearBit(const Index: TShortIntBitIndex): Shortint; inline;
     Function ToggleBit(const Index: TShortIntBitIndex): Shortint; inline;
     Function TestBit(const Index:TShortIntBitIndex):Boolean;
+    procedure Clear; inline;
+    function  HighestBitPos: cardinal; inline;
+    function  LowestBitPos: cardinal; inline;
+    function  BitsCount: byte; inline;
+    property  Bit   [aIndex: TShortIntBitIndex]: boolean   read GetBit    write PutBit;
+    property  Nibble[aIndex: TShortIntNibbleIndex]: nibble read GetNibble write PutNibble;
   end;
 
-  TSmallIntHelper = Type Helper for SmallInt
+  // TWordBitIndex is already defined
+  TWordByteIndex   = 0..1;
+  TWordNibbleIndex = 0..3;
+
+  TWordOverlay = bitpacked record case integer of     // for fast extraction of bytes and bits
+    0: (AsBit:    bitpacked array[TWordBitIndex]    of boolean);
+    1: (AsNibble: bitpacked array[TWordNibbleIndex] of nibble);
+    2: (AsByte:             array[TWordByteIndex]   of byte);
+    3: (AsWord:             word);
+    // recursive overlay:
+    4: (AsByteOverlay:      array[TWordByteIndex]   of TByteOverlay);
+  end;
+  
+  TWordHelper = Type Helper for Word
+  const
+    MaxValue  = High(word);
+    MinValue  = Low(word);
+    MaxBit    = High(TWordBitIndex);
+    MinBit    = Low(TWordBitIndex);
+    MaxNibble = High(TWordNibbleIndex);
+    MinNibble = Low(TWordNibbleIndex);
+    MaxByte   = High(TWordByteIndex);
+    MinByte   = Low(TWordByteIndex);
   public
-    const
-      MaxValue = 32767;
-      MinValue = -32768;
+    Class Function Parse(const AString: string): Word; inline; static;
+    Class Function Size: Integer; inline; static;
+    Class Function ToString(const AValue: Word): string; overload; inline; static;
+    Class Function TryParse(const AString: string; out AValue: Word): Boolean; inline; static;
+  protected
+    function  GetBit(const aIndex: TWordBitIndex): boolean; inline;
+    procedure PutBit(const aIndex: TWordBitIndex; const aNewValue: boolean); inline;
+    function  GetNibble(const aIndex: TWordNibbleIndex): nibble; inline;
+    procedure PutNibble(const aIndex: TWordNibbleIndex; const aNewValue: nibble); inline;
+    function  GetByte(const aIndex: TWordByteIndex): byte;
+    procedure PutByte(const aIndex: TWordByteIndex; const aNewValue: byte);
+  public
+    Function ToBoolean: Boolean; inline;
+    Function ToDouble: Double; inline;
+    Function ToExtended: Extended; inline;
+    Function ToBinString:string; inline;
+    Function ToHexString(const AMinDigits: Integer): string; overload; inline;
+    Function ToHexString: string; overload; inline;
+    Function ToSingle: Single; inline;
+    Function ToString: string; overload; inline;
+    Function SetBit(const Index: TWordBitIndex) : Word; inline;
+    Function ClearBit(const Index: TWordBitIndex) : Word; inline;
+    Function ToggleBit(const Index: TWordBitIndex) : Word; inline;
+    Function TestBit(const Index:TWordBitIndex):Boolean; inline;   
+    procedure Clear; inline;
+    function  HighestBitPos: cardinal; inline;
+    function  LowestBitPos: cardinal; inline;
+    function  BitsCount: byte; inline;
+    property  Bit   [aIndex: TWordBitIndex]: boolean   read GetBit  write PutBit;
+    property  Nibble[aIndex: TWordNibbleIndex]: nibble read GetNibble write PutNibble;
+    property  Byte  [aIndex: TWordByteIndex]: byte     read GetByte write PutByte;
+  end;
+
+  // TSmallIntBitIndex is already defined
+  TSmallIntByteIndex   = TWordByteIndex;
+  TSmallIntNibbleIndex = TWordNibbleIndex;
+
+  TSmallIntOverlay = TWordOverlay;
+  
+  TSmallIntHelper = Type Helper for SmallInt
+  const
+    MaxValue  = High(SmallInt);
+    MinValue  = Low(SmallInt);
+    MaxBit    = High(TSmallIntBitIndex);
+    MinBit    = Low(TSmallIntBitIndex);
+    MaxNibble = High(TSmallIntNibbleIndex);
+    MinNibble = Low(TSmallIntNibbleIndex);
+    MaxByte   = High(TSmallIntByteIndex);
+    MinByte   = Low(TSmallIntByteIndex);
   public
     Class Function Parse(const AString: string): SmallInt; inline; static;
     Class Function Size: Integer; inline; static;
     Class Function ToString(const AValue: SmallInt): string; overload; inline; static;
     Class Function TryParse(const AString: string; out AValue: SmallInt): Boolean; inline; static;
+  protected
+    function  GetBit(const aIndex: TSmallIntBitIndex): boolean; inline;
+    procedure PutBit(const aIndex: TSmallIntBitIndex; const aNewValue: boolean); inline;
+    function  GetNibble(const aIndex: TSmallIntNibbleIndex): nibble; inline;
+    procedure PutNibble(const aIndex: TSmallIntNibbleIndex; const aNewValue: nibble); inline;
+    function  GetByte(const aIndex: TSmallIntByteIndex): byte;
+    procedure PutByte(const aIndex: TSmallIntByteIndex; const aNewValue: byte);
   public
     Function ToString: string; overload; inline;
     Function ToBoolean: Boolean; inline;
@@ -454,44 +575,65 @@ Type
     Function ClearBit(const Index: TSmallIntBitIndex) : Smallint; inline;
     Function ToggleBit(const Index: TSmallIntBitIndex) : Smallint; inline;
     Function TestBit(const Index:TSmallIntBitIndex):Boolean;    
+    procedure Clear; inline;
+    function  HighestBitPos: cardinal; inline;
+    function  LowestBitPos: cardinal; inline;
+    function  BitsCount: byte; inline;
+    property  Bit   [aIndex: TSmallIntBitIndex]: boolean   read GetBit  write PutBit;
+    property  Nibble[aIndex: TSmallIntNibbleIndex]: nibble read GetNibble write PutNibble;
+    property  Byte  [aIndex: TSmallIntByteIndex]: byte     read GetByte write PutByte;
   end;
+  
+  TDwordBitIndex    = TCardinalBitIndex;
+  TDwordNibbleIndex = 0..7;
+  TDwordByteIndex   = 0..3;
+  TDwordWordIndex   = 0..1;
 
-  TWordHelper = Type Helper for Word
-  public
-    const
-      MaxValue = 65535;
-      MinValue = 0;
-  Public
-    Class Function Parse(const AString: string): Word; inline; static;
-    Class Function Size: Integer; inline; static;
-    Class Function ToString(const AValue: Word): string; overload; inline; static;
-    Class Function TryParse(const AString: string; out AValue: Word): Boolean; inline; static;
-  Public
-    Function ToBoolean: Boolean; inline;
-    Function ToDouble: Double; inline;
-    Function ToExtended: Extended; inline;
-    Function ToBinString:string; inline;
-    Function ToHexString(const AMinDigits: Integer): string; overload; inline;
-    Function ToHexString: string; overload; inline;
-    Function ToSingle: Single; inline;
-    Function ToString: string; overload; inline;
-    Function SetBit(const Index: TWordBitIndex) : Word; inline;
-    Function ClearBit(const Index: TWordBitIndex) : Word; inline;
-    Function ToggleBit(const Index: TWordBitIndex) : Word; inline;
-    Function TestBit(const Index:TWordBitIndex):Boolean; inline;    
+  TDwordOverlay = bitpacked record case integer of     // for fast extraction of words, bytes and bits
+    0: (AsBit:    bitpacked array[TDwordBitIndex]    of boolean);
+    1: (AsNibble: bitpacked array[TDwordNibbleIndex] of nibble);
+    2: (AsByte:             array[TDwordByteIndex]   of byte);
+    3: (AsWord:             array[TDwordWordIndex]   of word);
+    4: (AsDword:            dword);
+    // recursive overlays:
+    5: (AsByteOverlay:      array[TDwordByteIndex]   of TByteOverlay);
+    6: (AsWordOverlay:      array[TDwordWordIndex]   of TWordOverlay);
   end;
 
+  // TCardinalBitIndex is already defined
+  TCardinalNibbleIndex = TDwordNibbleIndex;
+  TCardinalByteIndex   = TDwordByteIndex;
+  TCardinalWordIndex   = TDwordWordIndex;
+
+  TCardinalOverlay = TDwordOverlay;
+  
   TCardinalHelper = Type Helper for Cardinal { for LongWord Type too }
+  const
+    MaxValue  = High(Cardinal);
+    MinValue  = Low(Cardinal);
+    MaxBit    = High(TCardinalBitIndex);
+    MinBit    = Low(TCardinalBitIndex);
+    MaxNibble = High(TCardinalNibbleIndex);
+    MinNibble = Low(TCardinalNibbleIndex);
+    MaxByte   = High(TCardinalByteIndex);
+    MinByte   = Low(TCardinalByteIndex);
+    MaxWord   = High(TCardinalWordIndex);
+    MinWord   = Low(TCardinalWordIndex);
   public
-    const
-      MaxValue = 4294967295;
-      MinValue = 0;
-  Public
     Class Function Parse(const AString: string): Cardinal; inline; static;
     Class Function Size: Integer; inline; static;
     Class Function ToString(const AValue: Cardinal): string; overload; inline; static;
     Class Function TryParse(const AString: string; out AValue: Cardinal): Boolean; inline; static;
-  Public
+  protected
+    function  GetBit(const aIndex: TCardinalBitIndex): boolean; inline;
+    procedure PutBit(const aIndex: TCardinalBitIndex; const aNewValue: boolean); inline;
+    function  GetNibble(const aIndex: TCardinalNibbleIndex): nibble; inline;
+    procedure PutNibble(const aIndex: TCardinalNibbleIndex; const aNewValue: nibble); inline;
+    function  GetByte(const aIndex: TCardinalByteIndex): byte;
+    procedure PutByte(const aIndex: TCardinalByteIndex; const aNewValue: byte);
+    function  GetWord(const aIndex: TCardinalWordIndex): word;
+    procedure PutWord(const aIndex: TCardinalWordIndex; const aNewValue: word);
+  public
     Function ToBoolean: Boolean; inline;
     Function ToDouble: Double; inline;
     Function ToExtended: Extended; inline;
@@ -504,19 +646,50 @@ Type
     Function ClearBit(const Index: TCardinalBitIndex) : Cardinal; inline;
     Function ToggleBit(const Index: TCardinalBitIndex) : Cardinal; inline;
     Function TestBit(const Index:TCardinalBitIndex):Boolean; inline;   
+    procedure Clear; inline;
+    function  HighestBitPos: cardinal; inline;
+    function  LowestBitPos: cardinal; inline;
+    function  BitsCount: byte; inline;
+    property  Bit   [aIndex: TCardinalBitIndex]: boolean   read GetBit    write PutBit;
+    property  Nibble[aIndex: TCardinalNibbleIndex]: nibble read GetNibble write PutNibble;
+    property  Byte  [aIndex: TCardinalByteIndex]: byte     read GetByte   write PutByte;
+    property  Word  [aIndex: TCardinalWordIndex]: word     read GetWord   write PutWord;
   end;
 
+  // TIntegerBitIndex is already defined
+  TIntegerNibbleIndex = TDwordNibbleIndex;
+  TIntegerByteIndex   = TDwordByteIndex;
+  TIntegerWordIndex   = TDwordWordIndex;
+
+  TIntegerOverlay = TDwordOverlay;
+
   TIntegerHelper = Type Helper for Integer { for LongInt Type too }
+  const
+    MaxValue  = High(integer);
+    MinValue  = Low(integer);
+    MaxBit    = High(TIntegerBitIndex);
+    MinBit    = Low(TIntegerBitIndex);
+    MaxNibble = High(TIntegerNibbleIndex);
+    MinNibble = Low(TIntegerNibbleIndex);
+    MaxByte   = High(TIntegerByteIndex);
+    MinByte   = Low(TIntegerByteIndex);
+    MaxWord   = High(TIntegerWordIndex);
+    MinWord   = Low(TIntegerWordIndex);
   public
-    const
-      MaxValue = 2147483647;
-      MinValue = -2147483648;
-  Public
     Class Function Size: Integer; inline; static;
     Class Function ToString(const AValue: Integer): string; overload; inline; static;
     Class Function Parse(const AString: string): Integer; inline; static;
     Class Function TryParse(const AString: string; out AValue: Integer): Boolean; inline; static;
-  Public
+  protected
+    function  GetBit(const aIndex: TIntegerBitIndex): boolean; inline;
+    procedure PutBit(const aIndex: TIntegerBitIndex; const aNewValue: boolean); inline;
+    function  GetNibble(const aIndex: TIntegerNibbleIndex): nibble; inline;
+    procedure PutNibble(const aIndex: TIntegerNibbleIndex; const aNewValue: nibble); inline;
+    function  GetByte(const aIndex: TIntegerByteIndex): byte;
+    procedure PutByte(const aIndex: TIntegerByteIndex; const aNewValue: byte);
+    function  GetWord(const aIndex: TIntegerWordIndex): word;
+    procedure PutWord(const aIndex: TIntegerWordIndex; const aNewValue: word);
+  public
     Function ToBoolean: Boolean; inline;
     Function ToDouble: Double; inline;
     Function ToExtended: Extended; inline;
@@ -529,19 +702,66 @@ Type
     Function ClearBit(const Index: TIntegerBitIndex) : Integer; inline;
     Function ToggleBit(const Index: TIntegerBitIndex) : Integer; inline;
     Function TestBit(const Index:TIntegerBitIndex):Boolean; inline;   
+    procedure Clear; inline;
+    function  HighestBitPos: cardinal; inline;
+    function  LowestBitPos: cardinal; inline;
+    function  BitsCount: byte; inline;
+    property  Bit   [aIndex: TIntegerBitIndex]: boolean    read GetBit    write PutBit;
+    property  Nibble[aIndex: TCardinalNibbleIndex]: nibble read GetNibble write PutNibble;
+    property  Byte  [aIndex: TIntegerByteIndex]:  byte     read GetByte   write PutByte;
+    property  Word  [aIndex: TIntegerWordIndex]:  word     read GetWord   write PutWord;
   end;
 
-  TInt64Helper = Type Helper for Int64
+  // TQwordBitIndex is already defined
+  TQwordNibbleIndex = 0..15;
+  TQwordByteIndex   = 0..7;
+  TQwordWordIndex   = 0..3;
+  TQwordDwordIndex  = 0..1;
+
+  TQwordOverlay = bitpacked record case integer of     // for fast extraction of longwords, words, bytes and bits
+    0: (AsBit:    bitpacked array[TQwordBitIndex]    of boolean);
+    1: (AsNibble: bitpacked array[TQwordNibbleIndex] of nibble);
+    2: (AsByte:             array[TQwordByteIndex]   of byte);
+    3: (AsWord:             array[TQwordWordIndex]   of word);
+    4: (AsDword:            array[TQwordDwordIndex]  of dword);
+    5: (AsQword:            qword);
+    // recursive overlays:
+    6: (AsByteOverlay:      array[TQwordByteIndex]   of TByteOverlay);
+    7: (AsWordOverlay:      array[TQwordWordIndex]   of TWordOverlay);
+    8: (AsDwordOverlay:     array[TQwordDwordIndex]  of TDwordOverlay);
+  end;
+
+  TQWordHelper = Type Helper for QWord
+  const
+    MaxValue  = High(qword);
+    MinValue  = Low(qword);
+    MaxBit    = High(TQwordBitIndex);
+    MinBit    = Low(TQwordBitIndex);
+    MaxNibble = High(TQwordNibbleIndex);
+    MinNibble = Low(TQwordNibbleIndex);
+    MaxByte   = High(TQwordByteIndex);
+    MinByte   = Low(TQwordByteIndex);
+    MaxWord   = High(TQwordWordIndex);
+    MinWord   = Low(TQwordWordIndex);
+    MaxDword  = High(TQwordDwordIndex);
+    MinDword  = Low(TQwordDwordIndex);
   public
-    const
-      MaxValue = 9223372036854775807;
-      MinValue = -9223372036854775808;
-  Public
-    Class Function Parse(const AString: string): Int64; inline; static;
+    Class Function Parse(const AString: string): Qword; inline; static;
     Class Function Size: Integer; inline; static;
-    Class Function ToString(const AValue: Int64): string; overload; inline; static;
-    Class Function TryParse(const AString: string; out AValue: Int64): Boolean; inline; static;
-  Public
+    Class Function ToString(const AValue: Qword): string; overload; inline; static;
+    Class Function TryParse(const AString: string; out AValue: Qword): Boolean; inline; static;
+  protected
+    function  GetBit(const aIndex: TQwordBitIndex): boolean; inline;
+    procedure PutBit(const aIndex: TQwordBitIndex; const aNewValue: boolean); inline;
+    function  GetNibble(const aIndex: TQwordNibbleIndex): nibble; inline;
+    procedure PutNibble(const aIndex: TQwordNibbleIndex; const aNewValue: nibble); inline;
+    function  GetByte(const aIndex: TQwordByteIndex): byte;
+    procedure PutByte(const aIndex: TQwordByteIndex; const aNewValue: byte);
+    function  GetWord(const aIndex: TQwordWordIndex): word;
+    procedure PutWord(const aIndex: TQwordWordIndex; const aNewValue: word);
+    function  GetDword(const aIndex: TQwordDwordIndex): dword;
+    procedure PutDword(const aIndex: TQwordDwordIndex; const aNewValue: dword);
+  public
     Function ToBoolean: Boolean; inline;
     Function ToDouble: Double; inline;
     Function ToExtended: Extended; inline;
@@ -550,23 +770,60 @@ Type
     Function ToHexString: string; overload; inline;
     Function ToSingle: Single; inline;
     Function ToString: string; overload; inline;
-    Function SetBit(const Index: TInt64BitIndex) : Int64; inline;
-    Function ClearBit(const Index: TInt64BitIndex) : Int64; inline;
-    Function ToggleBit(const Index: TInt64BitIndex) : Int64; inline;
-    Function TestBit(const Index:TInt64BitIndex):Boolean; inline; 
+    Function SetBit(const Index: TQwordBitIndex): Qword; inline;
+    Function ClearBit(const Index: TQwordBitIndex): Qword; inline;
+    Function ToggleBit(const Index: TQwordBitIndex): Qword; inline;
+    Function TestBit(const Index:TQwordBitIndex): Boolean; inline;
+    procedure Clear; inline;
+    function  HighestBitPos: cardinal; inline;
+    function  LowestBitPos: cardinal; inline;
+    function  BitsCount: byte; inline;
+    property  Bit   [aIndex: TQwordBitIndex]: boolean   read GetBit    write PutBit;
+    property  Nibble[aIndex: TQwordNibbleIndex]: nibble read GetNibble write PutNibble;
+    property  Byte  [aIndex: TQwordByteIndex]: byte     read GetByte   write PutByte;
+    property  Word  [aIndex: TQwordWordIndex]: word     read GetWord   write PutWord;
+    property  DWord [aIndex: TQwordDwordIndex]: dword   read GetDWord  write PutDWord;
   end;
 
-  TQWordHelper = Type Helper for QWord
+  // TInt64BitIndex is already defined
+  TInt64NibbleIndex = TQwordNibbleIndex;
+  TInt64ByteIndex   = TQwordByteIndex;
+  TInt64WordIndex   = TQwordWordIndex;
+  TInt64DwordIndex  = TQwordDwordIndex;
+
+  TInt64Overlay = TQwordOverlay;
+
+  TInt64Helper = Type Helper for Int64
+  const
+    MaxValue  = High(int64);
+    MinValue  = Low(int64);
+    MaxBit    = High(TInt64BitIndex);
+    MinBit    = Low(TInt64BitIndex);
+    MaxNibble = High(TInt64NibbleIndex);
+    MinNibble = Low(TInt64NibbleIndex);
+    MaxByte   = High(TInt64ByteIndex);
+    MinByte   = Low(TInt64ByteIndex);
+    MaxWord   = High(TInt64WordIndex);
+    MinWord   = Low(TInt64WordIndex);
+    MaxDword  = High(TInt64DwordIndex);
+    MinDword  = Low(TInt64DwordIndex);
   public
-    const
-      MaxValue = 18446744073709551615;
-      MinValue = 0;
-  Public
-    Class Function Parse(const AString: string): QWord; inline; static;
+    Class Function Parse(const AString: string): Int64; inline; static;
     Class Function Size: Integer; inline; static;
-    Class Function ToString(const AValue: QWord): string; overload; inline; static;
-    Class Function TryParse(const AString: string; out AValue: QWord): Boolean; inline; static;
-  Public
+    Class Function ToString(const AValue: Int64): string; overload; inline; static;
+    Class Function TryParse(const AString: string; out AValue: Int64): Boolean; inline; static;
+  protected
+    function  GetBit(const aIndex: TInt64BitIndex): boolean; inline;
+    procedure PutBit(const aIndex: TInt64BitIndex; const aNewValue: boolean); inline;
+    function  GetNibble(const aIndex: TInt64NibbleIndex): nibble; inline;
+    procedure PutNibble(const aIndex: TInt64NibbleIndex; const aNewValue: nibble); inline;
+    function  GetByte(const aIndex: TInt64ByteIndex): byte;
+    procedure PutByte(const aIndex: TInt64ByteIndex; const aNewValue: byte);
+    function  GetWord(const aIndex: TInt64WordIndex): word;
+    procedure PutWord(const aIndex: TInt64WordIndex; const aNewValue: word);
+    function  GetDword(const aIndex: TInt64DwordIndex): dword;
+    procedure PutDword(const aIndex: TInt64DwordIndex; const aNewValue: dword);
+  public
     Function ToBoolean: Boolean; inline;
     Function ToDouble: Double; inline;
     Function ToExtended: Extended; inline;
@@ -575,23 +832,86 @@ Type
     Function ToHexString: string; overload; inline;
     Function ToSingle: Single; inline;
     Function ToString: string; overload; inline;
-    Function SetBit(const Index: TQwordBitIndex) : QWord; inline;
-    Function ClearBit(const Index: TQwordBitIndex) : QWord; inline;
-    Function ToggleBit(const Index: TQwordBitIndex) : QWord; inline;
-    Function TestBit(const Index:TQwordBitIndex):Boolean; inline; 
+    Function SetBit(const Index: TInt64BitIndex) : Int64; inline;
+    Function ClearBit(const Index: TInt64BitIndex) : Int64; inline;
+    Function ToggleBit(const Index: TInt64BitIndex) : Int64; inline;
+    Function TestBit(const Index: TInt64BitIndex): Boolean; inline;
+    procedure Clear; inline;
+    function  HighestBitPos: cardinal; inline;
+    function  LowestBitPos: cardinal; inline;
+    function  BitsCount: byte; inline;
+    property  Bit   [aIndex: TInt64BitIndex]: boolean   read GetBit    write PutBit;
+    property  Nibble[aIndex: TInt64NibbleIndex]: nibble read GetNibble write PutNibble;
+    property  Byte  [aIndex: TInt64ByteIndex]: byte     read GetByte   write PutByte;
+    property  Word  [aIndex: TInt64WordIndex]: word     read GetWord   write PutWord;
+    property  DWord [aIndex: TInt64DwordIndex]: dword   read GetDWord  write PutDWord;
   end;
 
+  // TNativeIntBitIndex is already defined
+  {$ifdef cpu16}
+    TNativeIntNibbleIndex = TSmallIntNibbleIndex;
+    TNativeIntByteIndex   = TSmallIntByteIndex;
+    TNativeIntOverlay     = TSmallIntOverlay;
+  {$endif}
+  {$ifdef cpu32}
+    TNativeIntNibbleIndex = TIntegerNibbleIndex;
+    TNativeIntByteIndex   = TIntegerByteIndex;
+    TNativeIntWordIndex   = TIntegerWordIndex;
+    TNativeIntOverlay     = TIntegerOverlay;
+  {$endif}
+  {$ifdef cpu64}
+    TNativeIntNibbleIndex = TInt64NibbleIndex;
+    TNativeIntByteIndex   = TInt64ByteIndex;
+    TNativeIntWordIndex   = TInt64WordIndex;
+    TNativeIntDwordIndex  = TInt64DWordIndex;
+    TNativeIntOverlay     = TInt64Overlay;
+  {$endif}
+
   TNativeIntHelper = Type Helper for NativeInt
+  const
+    MaxValue  = High(NativeInt);
+    MinValue  = Low(NativeInt);
+    MaxBit    = High(TNativeIntBitIndex);
+    MinBit    = Low(TNativeIntBitIndex);
+    MaxNibble = High(TNativeIntNibbleIndex);
+    MinNibble = Low(TNativeIntNibbleIndex);
+    // NativeInt on cpu16 has 2 bytes, so no need for cpu16 check because we always need MaxByte and MinByte
+    MaxByte   = High(TNativeIntByteIndex);
+    MinByte   = Low(TNativeIntByteIndex);
+    {$ifdef cpu32}
+    MaxWord   = High(TNativeIntWordIndex);
+    MinWord   = Low(TNativeIntWordIndex);
+    {$endif}
+    {$ifdef cpu64}
+    MaxWord   = High(TNativeIntWordIndex);
+    MinWord   = Low(TNativeIntWordIndex);
+    MaxDword  = High(TNativeIntDwordIndex);
+    MinDword  = Low(TNativeIntDwordIndex);
+    {$endif}
   public
-    const
-      MaxValue = High(NativeInt);
-      MinValue = Low(NativeInt);
-  Public
     Class Function Parse(const AString: string): NativeInt; inline; static;
     Class Function Size: Integer; inline; static;
     Class Function ToString(const AValue: NativeInt): string; overload; inline; static;
     Class Function TryParse(const AString: string; out AValue: NativeInt): Boolean; inline; static;
-  Public
+  protected
+    function  GetBit(const aIndex: TNativeIntBitIndex): boolean; inline;
+    procedure PutBit(const aIndex: TNativeIntBitIndex; const aNewValue: boolean); inline;
+    function  GetNibble(const aIndex: TNativeIntNibbleIndex): nibble; inline;
+    procedure PutNibble(const aIndex: TNativeIntNibbleIndex; const aNewValue: nibble); inline;
+    // NativeInt on cpu16 has 2 bytes, so no need for cpu16 check because we always need GetByte and PutByte
+    function  GetByte(const aIndex: TNativeIntByteIndex): byte;
+    procedure PutByte(const aIndex: TNativeIntByteIndex; const aNewValue: byte);
+    {$ifdef cpu32}
+    function  GetWord(const aIndex: TNativeIntWordIndex): word;
+    procedure PutWord(const aIndex: TNativeIntWordIndex; const aNewValue: word);
+    {$endif}
+    {$ifdef cpu64}
+    function  GetWord(const aIndex: TNativeIntWordIndex): word;
+    procedure PutWord(const aIndex: TNativeIntWordIndex; const aNewValue: word);
+    function  GetDword(const aIndex: TNativeIntDwordIndex): dword;
+    procedure PutDword(const aIndex: TNativeIntDwordIndex; const aNewValue: dword);
+    {$endif}
+  public
     Function ToBoolean: Boolean; inline;
     Function ToDouble: Double; inline;
     Function ToExtended: Extended; inline;
@@ -604,19 +924,88 @@ Type
     Function ClearBit(const Index: TNativeIntBitIndex) : NativeInt; inline;
     Function ToggleBit(const Index: TNativeIntBitIndex) : NativeInt; inline;
     Function TestBit(const Index:TNativeIntBitIndex):Boolean; inline; 
+    procedure Clear; inline;
+    function  HighestBitPos: cardinal; inline;
+    function  LowestBitPos: cardinal; inline;
+    function  BitsCount: byte; inline;
+    property  Bit   [aIndex: TNativeIntBitIndex]: boolean   read GetBit    write PutBit;
+    property  Nibble[aIndex: TNativeIntNibbleIndex]: nibble read GetNibble write PutNibble;
+    // NativeInt on cpu16 has 2 bytes, so no need for cpu16 check because we always need Byte[]
+    property  Byte  [aIndex: TNativeIntByteIndex]: byte     read GetByte   write PutByte;
+    {$ifdef cpu32}
+    property  Word  [aIndex: TNativeIntWordIndex]: word     read GetWord   write PutWord;
+    {$endif}
+    {$ifdef cpu64}
+    property  Word  [aIndex: TNativeIntWordIndex]: word     read GetWord   write PutWord;
+    property  DWord [aIndex: TNativeIntDwordIndex]: dword   read GetDWord  write PutDWord;
+    {$endif}
   end;
 
+  // TNativeUIntBitIndex is already defined
+  {$ifdef cpu16}
+    TNativeUIntNibbleIndex = TWordNibbleIndex;
+    TNativeUIntByteIndex   = TWordByteIndex;
+    TNativeUIntOverlay     = TWordOverlay;
+  {$endif}
+  {$ifdef cpu32}
+    TNativeUIntNibbleIndex = TDwordNibbleIndex;
+    TNativeUIntByteIndex   = TDwordByteIndex;
+    TNativeUIntWordIndex   = TDwordWordIndex;
+    TNativeUIntOverlay     = TDwordOverlay;
+  {$endif}
+  {$ifdef cpu64}
+    TNativeUIntNibbleIndex = TQwordNibbleIndex;
+    TNativeUIntByteIndex   = TQwordByteIndex;
+    TNativeUIntWordIndex   = TQwordWordIndex;
+    TNativeUIntDwordIndex  = TQwordDWordIndex;
+    TNativeUIntOverlay     = TQwordOverlay;
+  {$endif}
+
   TNativeUIntHelper = Type Helper for NativeUInt
+  const
+    MaxValue  = High(NativeUInt);
+    MinValue  = 0;
+    MaxBit    = High(TNativeUIntBitIndex);
+    MinBit    = Low(TNativeUIntBitIndex);
+    MaxNibble = High(TNativeUIntNibbleIndex);
+    MinNibble = Low(TNativeUIntNibbleIndex);
+    // NativeInt on cpu16 has 2 bytes, so no need for cpu16 check because we always need MaxByte and MinByte
+    MaxByte   = High(TNativeUIntByteIndex);
+    MinByte   = Low(TNativeUIntByteIndex);
+    {$ifdef cpu32}
+    MaxWord   = High(TNativeUIntWordIndex);
+    MinWord   = Low(TNativeUIntWordIndex);
+    {$endif}
+    {$ifdef cpu64}
+    MaxWord   = High(TNativeUIntWordIndex);
+    MinWord   = Low(TNativeUIntWordIndex);
+    MaxDword  = High(TNativeUIntDwordIndex);
+    MinDword  = Low(TNativeUIntDwordIndex);
+    {$endif}
   public
-    const
-      MaxValue = High(NativeUInt);
-      MinValue = 0;
-  Public
     Class Function Parse(const AString: string): NativeUInt; inline; static;
     Class Function Size: Integer; inline; static;
     Class Function ToString(const AValue: NativeUInt): string; overload; inline; static;
     Class Function TryParse(const AString: string; out AValue: NativeUInt): Boolean; inline; static;
-  Public
+  protected
+    function  GetBit(const aIndex: TNativeUIntBitIndex): boolean; inline;
+    procedure PutBit(const aIndex: TNativeUIntBitIndex; const aNewValue: boolean); inline;
+    function  GetNibble(const aIndex: TNativeUIntNibbleIndex): nibble; inline;
+    procedure PutNibble(const aIndex: TNativeUIntNibbleIndex; const aNewValue: nibble); inline;
+    // NativeInt on cpu16 has 2 bytes, so no need for cpu16 check because we always need GetByte and PutByte
+    function  GetByte(const aIndex: TNativeUIntByteIndex): byte;
+    procedure PutByte(const aIndex: TNativeUIntByteIndex; const aNewValue: byte);
+    {$ifdef cpu32}
+    function  GetWord(const aIndex: TNativeUIntWordIndex): word;
+    procedure PutWord(const aIndex: TNativeUIntWordIndex; const aNewValue: word);
+    {$endif}
+    {$ifdef cpu64}
+    function  GetWord(const aIndex: TNativeUIntWordIndex): word;
+    procedure PutWord(const aIndex: TNativeUIntWordIndex; const aNewValue: word);
+    function  GetDword(const aIndex: TNativeUIntDwordIndex): dword;
+    procedure PutDword(const aIndex: TNativeUIntDwordIndex; const aNewValue: dword);
+    {$endif}
+  public
     Function ToBoolean: Boolean; inline;
     Function ToDouble: Double; inline;
     Function ToExtended: Extended; inline;
@@ -629,6 +1018,21 @@ Type
     Function ClearBit(const Index: TNativeUIntBitIndex): NativeUint; inline;
     Function ToggleBit(const Index: TNativeUIntBitIndex) : NativeUint; inline;
     Function TestBit(const Index:TNativeUIntBitIndex) :Boolean; inline;
+    procedure Clear; inline;
+    function  HighestBitPos: cardinal; inline;
+    function  LowestBitPos: cardinal; inline;
+    function  BitsCount: byte; inline;
+    property  Bit   [aIndex: TNativeUIntBitIndex]: boolean   read GetBit    write PutBit;
+    property  Nibble[aIndex: TNativeUIntNibbleIndex]: nibble read GetNibble write PutNibble;
+    // NativeInt on cpu16 has 2 bytes, so no need for cpu16 check because we always need Byte[]
+    property  Byte  [aIndex: TNativeUIntByteIndex]: byte     read GetByte   write PutByte;
+    {$ifdef cpu32}
+    property  Word  [aIndex: TNativeUIntWordIndex]: word     read GetWord   write PutWord;
+    {$endif}
+    {$ifdef cpu64}
+    property  Word  [aIndex: TNativeUIntWordIndex]: word     read GetWord   write PutWord;
+    property  DWord [aIndex: TNativeUIntDwordIndex]: dword   read GetDWord  write PutDWord;
+    {$endif}
   end;
 
   {$SCOPEDENUMS ON}
diff --git a/rtl/objpas/sysutils/syshelpo.inc b/rtl/objpas/sysutils/syshelpo.inc
index 497d0ef508..dd3de573be 100644
--- a/rtl/objpas/sysutils/syshelpo.inc
+++ b/rtl/objpas/sysutils/syshelpo.inc
@@ -106,3 +106,117 @@ Function TORDINALHELPER.TestBit(const Index: TORDINALBITINDEX):Boolean; inline;
 begin
   Result := (Self and TORDINALTYPE((TORDINALTYPE(1) shl index)))<>0;
 end;
+
+procedure TORDINALHELPER.Clear;
+begin
+  Self := 0;
+end;
+
+function TORDINALHELPER.HighestBitPos: cardinal;
+begin
+  {$ifdef TORDINALTYPESIZE1}
+        Result := BsrByte(byte(Self));
+  {$else}
+    {$ifdef TORDINALTYPESIZE2}
+        Result := BsrWord(word(Self));
+    {$else}
+      {$ifdef TORDINALTYPESIZE4}
+        Result := BsrDWord(dword(Self));
+      {$else} // TORDINALTYPESIZE8
+        Result := BsrQWord(qword(Self));
+      {$endif}
+    {$endif}
+  {$endif}
+end;
+
+function TORDINALHELPER.LowestBitPos: cardinal;
+begin
+  {$ifdef TORDINALTYPESIZE1}
+        Result := BsfByte(byte(Self));
+  {$else}
+    {$ifdef TORDINALTYPESIZE2}
+        Result := BsfWord(word(Self));
+    {$else}
+      {$ifdef TORDINALTYPESIZE4}
+        Result := BsfDWord(dword(Self));
+      {$else} // TORDINALTYPESIZE8
+        Result := BsfQWord(qword(Self));
+      {$endif}
+    {$endif}
+  {$endif}
+end;
+
+function TORDINALHELPER.BitsCount: byte;
+begin
+  {$ifdef TORDINALTYPESIZE1}
+        Result := PopCnt(byte(Self));
+  {$else}
+    {$ifdef TORDINALTYPESIZE2}
+        Result := PopCnt(word(Self));
+    {$else}
+      {$ifdef TORDINALTYPESIZE4}
+        Result := PopCnt(dword(Self));
+      {$else} // TORDINALTYPESIZE8
+        Result := PopCnt(qword(Self));
+      {$endif}
+    {$endif}
+  {$endif}
+end;
+
+function TORDINALHELPER.GetBit(const aIndex: TORDINALBITINDEX): boolean;
+begin
+  Result := ((Self shr aIndex) and TORDINALTYPE(1)) = TORDINALTYPE(1);
+end;
+
+procedure TORDINALHELPER.PutBit(const aIndex: TORDINALBITINDEX; const aNewValue: boolean);
+begin
+  Self := Self or (TORDINALTYPE(1) shl aIndex) xor (TORDINALTYPE(not aNewValue) shl aIndex);
+end;
+
+function TORDINALHELPER.GetNibble(const aIndex: TORDINALNIBBLEINDEX): nibble;
+begin
+  Result := TORDINALOVERLAY(Self).AsNibble[aIndex];
+end;
+
+procedure TORDINALHELPER.PutNibble(const aIndex: TORDINALNIBBLEINDEX; const aNewValue: nibble);
+begin
+  TORDINALOVERLAY(Self).AsNibble[aIndex] := aNewValue;
+end;
+
+{$ifndef TORDINALTYPESIZE1} // TWordHelper, TDWordHelper, TQWordHelper jump in here (and others with 2, 4 and 8 bytes)
+  function TORDINALHELPER.GetByte(const aIndex: TORDINALBYTEINDEX): byte;
+  begin
+    Result := TORDINALOVERLAY(Self).AsByte[aIndex];
+  end;
+
+  procedure TORDINALHELPER.PutByte(const aIndex: TORDINALBYTEINDEX; const aNewValue: byte);
+  begin
+    TORDINALOVERLAY(Self).AsByte[aIndex] := aNewValue;
+  end;
+
+  {$ifndef TORDINALTYPESIZE2} // TDWordHelper, TQWordHelper jump in here (and others with 4 and 8 bytes)
+    function TORDINALHELPER.GetWord(const aIndex: TORDINALWORDINDEX): word;
+    begin
+      Result := TORDINALOVERLAY(Self).AsWord[aIndex];
+    end;
+
+    procedure TORDINALHELPER.PutWord(const aIndex: TORDINALWORDINDEX; const aNewValue: word);
+    begin
+      TORDINALOVERLAY(Self).AsWord[aIndex] := aNewValue;
+    end;
+
+    {$ifndef TORDINALTYPESIZE4} // TQWordHelper jumps in here (and others with 8 bytes)
+      function TORDINALHELPER.GetDword(const aIndex: TORDINALDWORDINDEX): dword;
+      begin
+        Result := TORDINALOVERLAY(Self).AsDword[aIndex];
+      end;
+
+      procedure TORDINALHELPER.PutDword(const aIndex: TORDINALDWORDINDEX; const aNewValue: dword);
+      begin
+        TORDINALOVERLAY(Self).AsDword[aIndex] := aNewValue;
+      end;
+    {$endif}
+
+  {$endif}
+
+{$endif}
1.patch (43,095 bytes)   

Zeljko Avramovic

2021-07-21 00:45

reporter   ~0131968

I just wonder if HighestBitPos(), LowestBitPos() and BitsCount() should be called HighestOnBitPos(), LowestOnBitPos() and BitsOnCount()? Or even HighestSetBitPos(), LowestSetBitPos() and SetBitsCount()? Maybe that would be more clear and more descriptive? What do you think?

Michael Van Canneyt

2021-07-21 07:00

administrator   ~0131969

I think HighestSetBitPos LowestSetBitPos and SetBitsCount are the best names.

Zeljko Avramovic

2021-07-21 09:28

reporter   ~0131973

Here is an updated Patch1 with renamed methods HighestSetBitPos, LowestSetBitPos and SetBitsCount.
1b.patch (43,194 bytes)   
diff --git a/rtl/objpas/sysutils/syshelp.inc b/rtl/objpas/sysutils/syshelp.inc
index 1d6d4e50c2..2669a19452 100644
--- a/rtl/objpas/sysutils/syshelp.inc
+++ b/rtl/objpas/sysutils/syshelp.inc
@@ -1567,7 +1567,11 @@ end;
 {$define TORDINALHELPER:=TByteHelper}
 {$define TORDINALTYPE:=Byte}
 {$define TORDINALBITINDEX:=TByteBitIndex}
+{$define TORDINALNIBBLEINDEX:=TByteNibbleIndex}
+{$define TORDINALOVERLAY:=TByteOverlay}
+{$define TORDINALTYPESIZE1}
 {$i syshelpo.inc}
+{$undef TORDINALTYPESIZE1}
 
 { ---------------------------------------------------------------------
   TShortintHelper
@@ -1576,7 +1580,11 @@ end;
 {$define TORDINALHELPER:=TShortIntHelper}
 {$define TORDINALTYPE:=ShortInt}
 {$define TORDINALBITINDEX:=TShortIntBitIndex}
+{$define TORDINALNIBBLEINDEX:=TShortIntNibbleIndex}
+{$define TORDINALOVERLAY:=TShortIntOverlay}
+{$define TORDINALTYPESIZE1}
 {$i syshelpo.inc}
+{$undef TORDINALTYPESIZE1}
 
 { ---------------------------------------------------------------------
   TSmallintHelper
@@ -1585,7 +1593,12 @@ end;
 {$define TORDINALHELPER:=TSmallIntHelper}
 {$define TORDINALTYPE:=SmallInt}
 {$define TORDINALBITINDEX:=TSmallIntBitIndex}
+{$define TORDINALNIBBLEINDEX:=TSmallIntNibbleIndex}
+{$define TORDINALBYTEINDEX:=TWordByteIndex}
+{$define TORDINALOVERLAY:=TWordOverlay}
+{$define TORDINALTYPESIZE2}
 {$i syshelpo.inc}
+{$undef TORDINALTYPESIZE2}
 
 { ---------------------------------------------------------------------
   TWordHelper
@@ -1594,7 +1607,12 @@ end;
 {$define TORDINALHELPER:=TWordHelper}
 {$define TORDINALTYPE:=Word}
 {$define TORDINALBITINDEX:=TWordBitIndex}
+{$define TORDINALNIBBLEINDEX:=TWordNibbleIndex}
+{$define TORDINALBYTEINDEX:=TWordByteIndex}
+{$define TORDINALOVERLAY:=TWordOverlay}
+{$define TORDINALTYPESIZE2}
 {$i syshelpo.inc}
+{$undef TORDINALTYPESIZE2}
 
 { ---------------------------------------------------------------------
   TCardinalHelper
@@ -1603,7 +1621,13 @@ end;
 {$define TORDINALHELPER:=TCardinalHelper}
 {$define TORDINALTYPE:=Cardinal}
 {$define TORDINALBITINDEX:=TCardinalBitIndex}
+{$define TORDINALNIBBLEINDEX:=TCardinalNibbleIndex}
+{$define TORDINALBYTEINDEX:=TCardinalByteIndex}
+{$define TORDINALWORDINDEX:=TCardinalWordIndex}
+{$define TORDINALOVERLAY:=TDwordOverlay}
+{$define TORDINALTYPESIZE4}
 {$i syshelpo.inc}
+{$undef TORDINALTYPESIZE4}
 
 { ---------------------------------------------------------------------
   TIntegerHelper
@@ -1612,7 +1636,13 @@ end;
 {$define TORDINALHELPER:=TIntegerHelper}
 {$define TORDINALTYPE:=Integer}
 {$define TORDINALBITINDEX:=TIntegerBitIndex}
+{$define TORDINALNIBBLEINDEX:=TIntegerNibbleIndex}
+{$define TORDINALBYTEINDEX:=TIntegerByteIndex}
+{$define TORDINALWORDINDEX:=TIntegerWordIndex}
+{$define TORDINALOVERLAY:=TDwordOverlay}
+{$define TORDINALTYPESIZE4}
 {$i syshelpo.inc}
+{$undef TORDINALTYPESIZE4}
 
 { ---------------------------------------------------------------------
   TInt64Helper
@@ -1621,7 +1651,14 @@ end;
 {$define TORDINALHELPER:=TInt64Helper}
 {$define TORDINALTYPE:=Int64}
 {$define TORDINALBITINDEX:=TInt64BitIndex}
+{$define TORDINALNIBBLEINDEX:=TInt64NibbleIndex}
+{$define TORDINALBYTEINDEX:=TInt64ByteIndex}
+{$define TORDINALWORDINDEX:=TInt64WordIndex}
+{$define TORDINALDWORDINDEX:=TInt64DWordIndex}
+{$define TORDINALOVERLAY:=TQwordOverlay}
+{$define TORDINALTYPESIZE8}
 {$i syshelpo.inc}
+{$undef TORDINALTYPESIZE8}
 
 { ---------------------------------------------------------------------
   TQWordHelper
@@ -1630,7 +1667,14 @@ end;
 {$define TORDINALHELPER:=TQWordHelper}
 {$define TORDINALTYPE:=QWord}
 {$define TORDINALBITINDEX:=TQwordBitIndex}
+{$define TORDINALNIBBLEINDEX:=TQwordNibbleIndex}
+{$define TORDINALBYTEINDEX:=TQwordByteIndex}
+{$define TORDINALWORDINDEX:=TQWordWordIndex}
+{$define TORDINALDWORDINDEX:=TQWordDWordIndex}
+{$define TORDINALOVERLAY:=TQwordOverlay}
+{$define TORDINALTYPESIZE8}
 {$i syshelpo.inc}
+{$undef TORDINALTYPESIZE8}
 
 { ---------------------------------------------------------------------
   TNativeIntHelper
@@ -1639,7 +1683,31 @@ end;
 {$define TORDINALHELPER:=TNativeIntHelper}
 {$define TORDINALTYPE:=NativeInt}
 {$define TORDINALBITINDEX:=TNativeIntBitIndex}
+{$ifdef cpu16}
+  {$define TORDINALNIBBLEINDEX:=TSmallIntNibbleIndex}
+  {$define TORDINALBYTEINDEX:=TSmallIntByteIndex}
+  {$define TORDINALOVERLAY:=TSmallIntOverlay}
+  {$define TORDINALTYPESIZE2}
+{$endif}
+{$ifdef cpu32}
+  {$define TORDINALNIBBLEINDEX:=TIntegerNibbleIndex}
+  {$define TORDINALBYTEINDEX:=TIntegerByteIndex}
+  {$define TORDINALWORDINDEX:=TIntegerWordIndex}
+  {$define TORDINALOVERLAY:=TIntegerOverlay}
+  {$define TORDINALTYPESIZE4}
+{$endif}
+{$ifdef cpu64}
+  {$define TORDINALNIBBLEINDEX:=TInt64NibbleIndex}
+  {$define TORDINALBYTEINDEX:=TInt64ByteIndex}
+  {$define TORDINALWORDINDEX:=TInt64WordIndex}
+  {$define TORDINALDWORDINDEX:=TInt64DWordIndex}
+  {$define TORDINALOVERLAY:=TInt64Overlay}
+  {$define TORDINALTYPESIZE8}
+{$endif}
 {$i syshelpo.inc}
+{$undef TORDINALTYPESIZE2}
+{$undef TORDINALTYPESIZE4}
+{$undef TORDINALTYPESIZE8}
 
 { ---------------------------------------------------------------------
   TNativeUIntHelper
@@ -1648,7 +1716,31 @@ end;
 {$define TORDINALHELPER:=TNativeUIntHelper}
 {$define TORDINALTYPE:=NativeUInt}
 {$define TORDINALBITINDEX:=TNativeUIntBitIndex}
+{$ifdef cpu16}
+  {$define TORDINALNIBBLEINDEX:=TWordNibbleIndex}
+  {$define TORDINALBYTEINDEX:=TWordByteIndex}
+  {$define TORDINALOVERLAY:=TWordOverlay}
+  {$define TORDINALTYPESIZE2}
+{$endif}
+{$ifdef cpu32}
+  {$define TORDINALNIBBLEINDEX:=TDwordNibbleIndex}
+  {$define TORDINALBYTEINDEX:=TDwordByteIndex}
+  {$define TORDINALWORDINDEX:=TDwordWordIndex}
+  {$define TORDINALOVERLAY:=TDwordOverlay}
+  {$define TORDINALTYPESIZE4}
+{$endif}
+{$ifdef cpu64}
+  {$define TORDINALNIBBLEINDEX:=TQwordNibbleIndex}
+  {$define TORDINALBYTEINDEX:=TQwordByteIndex}
+  {$define TORDINALWORDINDEX:=TQwordWordIndex}
+  {$define TORDINALDWORDINDEX:=TQwordDWordIndex}
+  {$define TORDINALOVERLAY:=TQwordOverlay}
+  {$define TORDINALTYPESIZE8}
+{$endif}
 {$i syshelpo.inc}
+{$undef TORDINALTYPESIZE2}
+{$undef TORDINALTYPESIZE4}
+{$undef TORDINALTYPESIZE8}
 
 { ---------------------------------------------------------------------
   TBooleanHelper
diff --git a/rtl/objpas/sysutils/syshelph.inc b/rtl/objpas/sysutils/syshelph.inc
index 2a4fe31477..955ff9c41e 100644
--- a/rtl/objpas/sysutils/syshelph.inc
+++ b/rtl/objpas/sysutils/syshelph.inc
@@ -381,17 +381,37 @@ Type
   end;
 {$ENDIF FPC_HAS_TYPE_EXTENDED}
 
+  nibble           = 0..15;
+  TNibbleBitIndex  = 0..3;
+
+  // TByteBitIndex is already defined
+  TByteNibbleIndex = 0..1;
+
+  TByteOverlay = bitpacked record case integer of     // for fast extraction of bits
+    0: (AsBit:    bitpacked array[TByteBitIndex]    of boolean);
+    1: (AsNibble: bitpacked array[TByteNibbleIndex] of nibble);
+    2: (AsByte:   byte);
+  end;
+  
   TByteHelper = Type Helper for Byte
-  public
-    const
-      MaxValue = 255;
-      MinValue = 0;
+  const
+    MaxValue  = High(byte);
+    MinValue  = Low(byte);
+    MaxBit    = High(TByteBitIndex);
+    MinBit    = Low(TByteBitIndex);
+    MaxNibble = High(TByteNibbleIndex);
+    MinNibble = Low(TByteNibbleIndex);
   public
     Class Function Parse(const AString: string): Byte; inline; static;
     Class Function Size: Integer; inline; static;
     Class Function ToString(const AValue: Byte): string; overload; inline; static;
     Class Function TryParse(const AString: string; out AValue: Byte): Boolean; inline; static;
-  Public
+  protected
+    function  GetBit(const aIndex: TByteBitIndex): boolean; inline;
+    procedure PutBit(const aIndex: TByteBitIndex; const aNewValue: boolean); inline;
+    function  GetNibble(const aIndex: TByteNibbleIndex): nibble; inline;
+    procedure PutNibble(const aIndex: TByteNibbleIndex; const aNewValue: nibble); inline;
+  public
     Function ToBoolean: Boolean; inline;
     Function ToDouble: Double; inline;
     Function ToExtended: Extended; inline;
@@ -404,18 +424,38 @@ Type
     Function ClearBit(const Index: TByteBitIndex) : Byte; inline;
     Function ToggleBit(const Index: TByteBitIndex) : Byte; inline;
     Function TestBit(const Index:TByteBitIndex):Boolean; inline;
+    procedure Clear; inline;
+    function  HighestSetBitPos: cardinal; inline;
+    function  LowestSetBitPos: cardinal; inline;
+    function  SetBitsCount: byte; inline;
+    property  Bit   [aIndex: TByteBitIndex]: boolean   read GetBit    write PutBit;
+    property  Nibble[aIndex: TByteNibbleIndex]: nibble read GetNibble write PutNibble;
   end;
 
+  // TShortIntBitIndex is already defined
+
+  TShortIntNibbleIndex = TByteNibbleIndex;
+
+  TShortIntOverlay = TByteOverlay;
+
   TShortIntHelper = Type Helper for ShortInt
-  public
-    const
-      MaxValue = 127;
-      MinValue = -128;
+  const
+    MaxValue  = High(shortint);
+    MinValue  = Low(shortint);
+    MaxBit    = High(TShortIntBitIndex);
+    MinBit    = Low(TShortIntBitIndex);
+    MaxNibble = High(TShortIntNibbleIndex);
+    MinNibble = Low(TShortIntNibbleIndex);
   public
     Class Function Parse(const AString: string): ShortInt; inline; static;
     Class Function Size: Integer; inline; static;
     Class Function ToString(const AValue: ShortInt): string; overload; inline; static;
     Class Function TryParse(const AString: string; out AValue: ShortInt): Boolean; inline; static;
+  protected
+    function  GetBit(const aIndex: TShortIntBitIndex): boolean; inline;
+    procedure PutBit(const aIndex: TShortIntBitIndex; const aNewValue: boolean); inline;
+    function  GetNibble(const aIndex: TShortIntNibbleIndex): nibble; inline;
+    procedure PutNibble(const aIndex: TShortIntNibbleIndex; const aNewValue: nibble); inline;
   public
     Function ToBoolean: Boolean; inline;
     Function ToDouble: Double; inline;
@@ -429,18 +469,99 @@ Type
     Function ClearBit(const Index: TShortIntBitIndex): Shortint; inline;
     Function ToggleBit(const Index: TShortIntBitIndex): Shortint; inline;
     Function TestBit(const Index:TShortIntBitIndex):Boolean;
+    procedure Clear; inline;
+    function  HighestSetBitPos: cardinal; inline;
+    function  LowestSetBitPos: cardinal; inline;
+    function  SetBitsCount: byte; inline;
+    property  Bit   [aIndex: TShortIntBitIndex]: boolean   read GetBit    write PutBit;
+    property  Nibble[aIndex: TShortIntNibbleIndex]: nibble read GetNibble write PutNibble;
   end;
 
-  TSmallIntHelper = Type Helper for SmallInt
+  // TWordBitIndex is already defined
+  TWordByteIndex   = 0..1;
+  TWordNibbleIndex = 0..3;
+
+  TWordOverlay = bitpacked record case integer of     // for fast extraction of bytes and bits
+    0: (AsBit:    bitpacked array[TWordBitIndex]    of boolean);
+    1: (AsNibble: bitpacked array[TWordNibbleIndex] of nibble);
+    2: (AsByte:             array[TWordByteIndex]   of byte);
+    3: (AsWord:             word);
+    // recursive overlay:
+    4: (AsByteOverlay:      array[TWordByteIndex]   of TByteOverlay);
+  end;
+  
+  TWordHelper = Type Helper for Word
+  const
+    MaxValue  = High(word);
+    MinValue  = Low(word);
+    MaxBit    = High(TWordBitIndex);
+    MinBit    = Low(TWordBitIndex);
+    MaxNibble = High(TWordNibbleIndex);
+    MinNibble = Low(TWordNibbleIndex);
+    MaxByte   = High(TWordByteIndex);
+    MinByte   = Low(TWordByteIndex);
   public
-    const
-      MaxValue = 32767;
-      MinValue = -32768;
+    Class Function Parse(const AString: string): Word; inline; static;
+    Class Function Size: Integer; inline; static;
+    Class Function ToString(const AValue: Word): string; overload; inline; static;
+    Class Function TryParse(const AString: string; out AValue: Word): Boolean; inline; static;
+  protected
+    function  GetBit(const aIndex: TWordBitIndex): boolean; inline;
+    procedure PutBit(const aIndex: TWordBitIndex; const aNewValue: boolean); inline;
+    function  GetNibble(const aIndex: TWordNibbleIndex): nibble; inline;
+    procedure PutNibble(const aIndex: TWordNibbleIndex; const aNewValue: nibble); inline;
+    function  GetByte(const aIndex: TWordByteIndex): byte;
+    procedure PutByte(const aIndex: TWordByteIndex; const aNewValue: byte);
+  public
+    Function ToBoolean: Boolean; inline;
+    Function ToDouble: Double; inline;
+    Function ToExtended: Extended; inline;
+    Function ToBinString:string; inline;
+    Function ToHexString(const AMinDigits: Integer): string; overload; inline;
+    Function ToHexString: string; overload; inline;
+    Function ToSingle: Single; inline;
+    Function ToString: string; overload; inline;
+    Function SetBit(const Index: TWordBitIndex) : Word; inline;
+    Function ClearBit(const Index: TWordBitIndex) : Word; inline;
+    Function ToggleBit(const Index: TWordBitIndex) : Word; inline;
+    Function TestBit(const Index:TWordBitIndex):Boolean; inline;   
+    procedure Clear; inline;
+    function  HighestSetBitPos: cardinal; inline;
+    function  LowestSetBitPos: cardinal; inline;
+    function  SetBitsCount: byte; inline;
+    property  Bit   [aIndex: TWordBitIndex]: boolean   read GetBit  write PutBit;
+    property  Nibble[aIndex: TWordNibbleIndex]: nibble read GetNibble write PutNibble;
+    property  Byte  [aIndex: TWordByteIndex]: byte     read GetByte write PutByte;
+  end;
+
+  // TSmallIntBitIndex is already defined
+  TSmallIntByteIndex   = TWordByteIndex;
+  TSmallIntNibbleIndex = TWordNibbleIndex;
+
+  TSmallIntOverlay = TWordOverlay;
+  
+  TSmallIntHelper = Type Helper for SmallInt
+  const
+    MaxValue  = High(SmallInt);
+    MinValue  = Low(SmallInt);
+    MaxBit    = High(TSmallIntBitIndex);
+    MinBit    = Low(TSmallIntBitIndex);
+    MaxNibble = High(TSmallIntNibbleIndex);
+    MinNibble = Low(TSmallIntNibbleIndex);
+    MaxByte   = High(TSmallIntByteIndex);
+    MinByte   = Low(TSmallIntByteIndex);
   public
     Class Function Parse(const AString: string): SmallInt; inline; static;
     Class Function Size: Integer; inline; static;
     Class Function ToString(const AValue: SmallInt): string; overload; inline; static;
     Class Function TryParse(const AString: string; out AValue: SmallInt): Boolean; inline; static;
+  protected
+    function  GetBit(const aIndex: TSmallIntBitIndex): boolean; inline;
+    procedure PutBit(const aIndex: TSmallIntBitIndex; const aNewValue: boolean); inline;
+    function  GetNibble(const aIndex: TSmallIntNibbleIndex): nibble; inline;
+    procedure PutNibble(const aIndex: TSmallIntNibbleIndex; const aNewValue: nibble); inline;
+    function  GetByte(const aIndex: TSmallIntByteIndex): byte;
+    procedure PutByte(const aIndex: TSmallIntByteIndex; const aNewValue: byte);
   public
     Function ToString: string; overload; inline;
     Function ToBoolean: Boolean; inline;
@@ -454,44 +575,65 @@ Type
     Function ClearBit(const Index: TSmallIntBitIndex) : Smallint; inline;
     Function ToggleBit(const Index: TSmallIntBitIndex) : Smallint; inline;
     Function TestBit(const Index:TSmallIntBitIndex):Boolean;    
+    procedure Clear; inline;
+    function  HighestSetBitPos: cardinal; inline;
+    function  LowestSetBitPos: cardinal; inline;
+    function  SetBitsCount: byte; inline;
+    property  Bit   [aIndex: TSmallIntBitIndex]: boolean   read GetBit  write PutBit;
+    property  Nibble[aIndex: TSmallIntNibbleIndex]: nibble read GetNibble write PutNibble;
+    property  Byte  [aIndex: TSmallIntByteIndex]: byte     read GetByte write PutByte;
   end;
+  
+  TDwordBitIndex    = TCardinalBitIndex;
+  TDwordNibbleIndex = 0..7;
+  TDwordByteIndex   = 0..3;
+  TDwordWordIndex   = 0..1;
 
-  TWordHelper = Type Helper for Word
-  public
-    const
-      MaxValue = 65535;
-      MinValue = 0;
-  Public
-    Class Function Parse(const AString: string): Word; inline; static;
-    Class Function Size: Integer; inline; static;
-    Class Function ToString(const AValue: Word): string; overload; inline; static;
-    Class Function TryParse(const AString: string; out AValue: Word): Boolean; inline; static;
-  Public
-    Function ToBoolean: Boolean; inline;
-    Function ToDouble: Double; inline;
-    Function ToExtended: Extended; inline;
-    Function ToBinString:string; inline;
-    Function ToHexString(const AMinDigits: Integer): string; overload; inline;
-    Function ToHexString: string; overload; inline;
-    Function ToSingle: Single; inline;
-    Function ToString: string; overload; inline;
-    Function SetBit(const Index: TWordBitIndex) : Word; inline;
-    Function ClearBit(const Index: TWordBitIndex) : Word; inline;
-    Function ToggleBit(const Index: TWordBitIndex) : Word; inline;
-    Function TestBit(const Index:TWordBitIndex):Boolean; inline;    
+  TDwordOverlay = bitpacked record case integer of     // for fast extraction of words, bytes and bits
+    0: (AsBit:    bitpacked array[TDwordBitIndex]    of boolean);
+    1: (AsNibble: bitpacked array[TDwordNibbleIndex] of nibble);
+    2: (AsByte:             array[TDwordByteIndex]   of byte);
+    3: (AsWord:             array[TDwordWordIndex]   of word);
+    4: (AsDword:            dword);
+    // recursive overlays:
+    5: (AsByteOverlay:      array[TDwordByteIndex]   of TByteOverlay);
+    6: (AsWordOverlay:      array[TDwordWordIndex]   of TWordOverlay);
   end;
 
+  // TCardinalBitIndex is already defined
+  TCardinalNibbleIndex = TDwordNibbleIndex;
+  TCardinalByteIndex   = TDwordByteIndex;
+  TCardinalWordIndex   = TDwordWordIndex;
+
+  TCardinalOverlay = TDwordOverlay;
+  
   TCardinalHelper = Type Helper for Cardinal { for LongWord Type too }
+  const
+    MaxValue  = High(Cardinal);
+    MinValue  = Low(Cardinal);
+    MaxBit    = High(TCardinalBitIndex);
+    MinBit    = Low(TCardinalBitIndex);
+    MaxNibble = High(TCardinalNibbleIndex);
+    MinNibble = Low(TCardinalNibbleIndex);
+    MaxByte   = High(TCardinalByteIndex);
+    MinByte   = Low(TCardinalByteIndex);
+    MaxWord   = High(TCardinalWordIndex);
+    MinWord   = Low(TCardinalWordIndex);
   public
-    const
-      MaxValue = 4294967295;
-      MinValue = 0;
-  Public
     Class Function Parse(const AString: string): Cardinal; inline; static;
     Class Function Size: Integer; inline; static;
     Class Function ToString(const AValue: Cardinal): string; overload; inline; static;
     Class Function TryParse(const AString: string; out AValue: Cardinal): Boolean; inline; static;
-  Public
+  protected
+    function  GetBit(const aIndex: TCardinalBitIndex): boolean; inline;
+    procedure PutBit(const aIndex: TCardinalBitIndex; const aNewValue: boolean); inline;
+    function  GetNibble(const aIndex: TCardinalNibbleIndex): nibble; inline;
+    procedure PutNibble(const aIndex: TCardinalNibbleIndex; const aNewValue: nibble); inline;
+    function  GetByte(const aIndex: TCardinalByteIndex): byte;
+    procedure PutByte(const aIndex: TCardinalByteIndex; const aNewValue: byte);
+    function  GetWord(const aIndex: TCardinalWordIndex): word;
+    procedure PutWord(const aIndex: TCardinalWordIndex; const aNewValue: word);
+  public
     Function ToBoolean: Boolean; inline;
     Function ToDouble: Double; inline;
     Function ToExtended: Extended; inline;
@@ -504,19 +646,50 @@ Type
     Function ClearBit(const Index: TCardinalBitIndex) : Cardinal; inline;
     Function ToggleBit(const Index: TCardinalBitIndex) : Cardinal; inline;
     Function TestBit(const Index:TCardinalBitIndex):Boolean; inline;   
+    procedure Clear; inline;
+    function  HighestSetBitPos: cardinal; inline;
+    function  LowestSetBitPos: cardinal; inline;
+    function  SetBitsCount: byte; inline;
+    property  Bit   [aIndex: TCardinalBitIndex]: boolean   read GetBit    write PutBit;
+    property  Nibble[aIndex: TCardinalNibbleIndex]: nibble read GetNibble write PutNibble;
+    property  Byte  [aIndex: TCardinalByteIndex]: byte     read GetByte   write PutByte;
+    property  Word  [aIndex: TCardinalWordIndex]: word     read GetWord   write PutWord;
   end;
 
+  // TIntegerBitIndex is already defined
+  TIntegerNibbleIndex = TDwordNibbleIndex;
+  TIntegerByteIndex   = TDwordByteIndex;
+  TIntegerWordIndex   = TDwordWordIndex;
+
+  TIntegerOverlay = TDwordOverlay;
+
   TIntegerHelper = Type Helper for Integer { for LongInt Type too }
+  const
+    MaxValue  = High(integer);
+    MinValue  = Low(integer);
+    MaxBit    = High(TIntegerBitIndex);
+    MinBit    = Low(TIntegerBitIndex);
+    MaxNibble = High(TIntegerNibbleIndex);
+    MinNibble = Low(TIntegerNibbleIndex);
+    MaxByte   = High(TIntegerByteIndex);
+    MinByte   = Low(TIntegerByteIndex);
+    MaxWord   = High(TIntegerWordIndex);
+    MinWord   = Low(TIntegerWordIndex);
   public
-    const
-      MaxValue = 2147483647;
-      MinValue = -2147483648;
-  Public
     Class Function Size: Integer; inline; static;
     Class Function ToString(const AValue: Integer): string; overload; inline; static;
     Class Function Parse(const AString: string): Integer; inline; static;
     Class Function TryParse(const AString: string; out AValue: Integer): Boolean; inline; static;
-  Public
+  protected
+    function  GetBit(const aIndex: TIntegerBitIndex): boolean; inline;
+    procedure PutBit(const aIndex: TIntegerBitIndex; const aNewValue: boolean); inline;
+    function  GetNibble(const aIndex: TIntegerNibbleIndex): nibble; inline;
+    procedure PutNibble(const aIndex: TIntegerNibbleIndex; const aNewValue: nibble); inline;
+    function  GetByte(const aIndex: TIntegerByteIndex): byte;
+    procedure PutByte(const aIndex: TIntegerByteIndex; const aNewValue: byte);
+    function  GetWord(const aIndex: TIntegerWordIndex): word;
+    procedure PutWord(const aIndex: TIntegerWordIndex; const aNewValue: word);
+  public
     Function ToBoolean: Boolean; inline;
     Function ToDouble: Double; inline;
     Function ToExtended: Extended; inline;
@@ -529,19 +702,66 @@ Type
     Function ClearBit(const Index: TIntegerBitIndex) : Integer; inline;
     Function ToggleBit(const Index: TIntegerBitIndex) : Integer; inline;
     Function TestBit(const Index:TIntegerBitIndex):Boolean; inline;   
+    procedure Clear; inline;
+    function  HighestSetBitPos: cardinal; inline;
+    function  LowestSetBitPos: cardinal; inline;
+    function  SetBitsCount: byte; inline;
+    property  Bit   [aIndex: TIntegerBitIndex]: boolean    read GetBit    write PutBit;
+    property  Nibble[aIndex: TCardinalNibbleIndex]: nibble read GetNibble write PutNibble;
+    property  Byte  [aIndex: TIntegerByteIndex]:  byte     read GetByte   write PutByte;
+    property  Word  [aIndex: TIntegerWordIndex]:  word     read GetWord   write PutWord;
   end;
 
-  TInt64Helper = Type Helper for Int64
+  // TQwordBitIndex is already defined
+  TQwordNibbleIndex = 0..15;
+  TQwordByteIndex   = 0..7;
+  TQwordWordIndex   = 0..3;
+  TQwordDwordIndex  = 0..1;
+
+  TQwordOverlay = bitpacked record case integer of     // for fast extraction of longwords, words, bytes and bits
+    0: (AsBit:    bitpacked array[TQwordBitIndex]    of boolean);
+    1: (AsNibble: bitpacked array[TQwordNibbleIndex] of nibble);
+    2: (AsByte:             array[TQwordByteIndex]   of byte);
+    3: (AsWord:             array[TQwordWordIndex]   of word);
+    4: (AsDword:            array[TQwordDwordIndex]  of dword);
+    5: (AsQword:            qword);
+    // recursive overlays:
+    6: (AsByteOverlay:      array[TQwordByteIndex]   of TByteOverlay);
+    7: (AsWordOverlay:      array[TQwordWordIndex]   of TWordOverlay);
+    8: (AsDwordOverlay:     array[TQwordDwordIndex]  of TDwordOverlay);
+  end;
+
+  TQWordHelper = Type Helper for QWord
+  const
+    MaxValue  = High(qword);
+    MinValue  = Low(qword);
+    MaxBit    = High(TQwordBitIndex);
+    MinBit    = Low(TQwordBitIndex);
+    MaxNibble = High(TQwordNibbleIndex);
+    MinNibble = Low(TQwordNibbleIndex);
+    MaxByte   = High(TQwordByteIndex);
+    MinByte   = Low(TQwordByteIndex);
+    MaxWord   = High(TQwordWordIndex);
+    MinWord   = Low(TQwordWordIndex);
+    MaxDword  = High(TQwordDwordIndex);
+    MinDword  = Low(TQwordDwordIndex);
   public
-    const
-      MaxValue = 9223372036854775807;
-      MinValue = -9223372036854775808;
-  Public
-    Class Function Parse(const AString: string): Int64; inline; static;
+    Class Function Parse(const AString: string): Qword; inline; static;
     Class Function Size: Integer; inline; static;
-    Class Function ToString(const AValue: Int64): string; overload; inline; static;
-    Class Function TryParse(const AString: string; out AValue: Int64): Boolean; inline; static;
-  Public
+    Class Function ToString(const AValue: Qword): string; overload; inline; static;
+    Class Function TryParse(const AString: string; out AValue: Qword): Boolean; inline; static;
+  protected
+    function  GetBit(const aIndex: TQwordBitIndex): boolean; inline;
+    procedure PutBit(const aIndex: TQwordBitIndex; const aNewValue: boolean); inline;
+    function  GetNibble(const aIndex: TQwordNibbleIndex): nibble; inline;
+    procedure PutNibble(const aIndex: TQwordNibbleIndex; const aNewValue: nibble); inline;
+    function  GetByte(const aIndex: TQwordByteIndex): byte;
+    procedure PutByte(const aIndex: TQwordByteIndex; const aNewValue: byte);
+    function  GetWord(const aIndex: TQwordWordIndex): word;
+    procedure PutWord(const aIndex: TQwordWordIndex; const aNewValue: word);
+    function  GetDword(const aIndex: TQwordDwordIndex): dword;
+    procedure PutDword(const aIndex: TQwordDwordIndex; const aNewValue: dword);
+  public
     Function ToBoolean: Boolean; inline;
     Function ToDouble: Double; inline;
     Function ToExtended: Extended; inline;
@@ -550,23 +770,60 @@ Type
     Function ToHexString: string; overload; inline;
     Function ToSingle: Single; inline;
     Function ToString: string; overload; inline;
-    Function SetBit(const Index: TInt64BitIndex) : Int64; inline;
-    Function ClearBit(const Index: TInt64BitIndex) : Int64; inline;
-    Function ToggleBit(const Index: TInt64BitIndex) : Int64; inline;
-    Function TestBit(const Index:TInt64BitIndex):Boolean; inline; 
+    Function SetBit(const Index: TQwordBitIndex): Qword; inline;
+    Function ClearBit(const Index: TQwordBitIndex): Qword; inline;
+    Function ToggleBit(const Index: TQwordBitIndex): Qword; inline;
+    Function TestBit(const Index:TQwordBitIndex): Boolean; inline;
+    procedure Clear; inline;
+    function  HighestSetBitPos: cardinal; inline;
+    function  LowestSetBitPos: cardinal; inline;
+    function  SetBitsCount: byte; inline;
+    property  Bit   [aIndex: TQwordBitIndex]: boolean   read GetBit    write PutBit;
+    property  Nibble[aIndex: TQwordNibbleIndex]: nibble read GetNibble write PutNibble;
+    property  Byte  [aIndex: TQwordByteIndex]: byte     read GetByte   write PutByte;
+    property  Word  [aIndex: TQwordWordIndex]: word     read GetWord   write PutWord;
+    property  DWord [aIndex: TQwordDwordIndex]: dword   read GetDWord  write PutDWord;
   end;
 
-  TQWordHelper = Type Helper for QWord
+  // TInt64BitIndex is already defined
+  TInt64NibbleIndex = TQwordNibbleIndex;
+  TInt64ByteIndex   = TQwordByteIndex;
+  TInt64WordIndex   = TQwordWordIndex;
+  TInt64DwordIndex  = TQwordDwordIndex;
+
+  TInt64Overlay = TQwordOverlay;
+
+  TInt64Helper = Type Helper for Int64
+  const
+    MaxValue  = High(int64);
+    MinValue  = Low(int64);
+    MaxBit    = High(TInt64BitIndex);
+    MinBit    = Low(TInt64BitIndex);
+    MaxNibble = High(TInt64NibbleIndex);
+    MinNibble = Low(TInt64NibbleIndex);
+    MaxByte   = High(TInt64ByteIndex);
+    MinByte   = Low(TInt64ByteIndex);
+    MaxWord   = High(TInt64WordIndex);
+    MinWord   = Low(TInt64WordIndex);
+    MaxDword  = High(TInt64DwordIndex);
+    MinDword  = Low(TInt64DwordIndex);
   public
-    const
-      MaxValue = 18446744073709551615;
-      MinValue = 0;
-  Public
-    Class Function Parse(const AString: string): QWord; inline; static;
+    Class Function Parse(const AString: string): Int64; inline; static;
     Class Function Size: Integer; inline; static;
-    Class Function ToString(const AValue: QWord): string; overload; inline; static;
-    Class Function TryParse(const AString: string; out AValue: QWord): Boolean; inline; static;
-  Public
+    Class Function ToString(const AValue: Int64): string; overload; inline; static;
+    Class Function TryParse(const AString: string; out AValue: Int64): Boolean; inline; static;
+  protected
+    function  GetBit(const aIndex: TInt64BitIndex): boolean; inline;
+    procedure PutBit(const aIndex: TInt64BitIndex; const aNewValue: boolean); inline;
+    function  GetNibble(const aIndex: TInt64NibbleIndex): nibble; inline;
+    procedure PutNibble(const aIndex: TInt64NibbleIndex; const aNewValue: nibble); inline;
+    function  GetByte(const aIndex: TInt64ByteIndex): byte;
+    procedure PutByte(const aIndex: TInt64ByteIndex; const aNewValue: byte);
+    function  GetWord(const aIndex: TInt64WordIndex): word;
+    procedure PutWord(const aIndex: TInt64WordIndex; const aNewValue: word);
+    function  GetDword(const aIndex: TInt64DwordIndex): dword;
+    procedure PutDword(const aIndex: TInt64DwordIndex; const aNewValue: dword);
+  public
     Function ToBoolean: Boolean; inline;
     Function ToDouble: Double; inline;
     Function ToExtended: Extended; inline;
@@ -575,23 +832,86 @@ Type
     Function ToHexString: string; overload; inline;
     Function ToSingle: Single; inline;
     Function ToString: string; overload; inline;
-    Function SetBit(const Index: TQwordBitIndex) : QWord; inline;
-    Function ClearBit(const Index: TQwordBitIndex) : QWord; inline;
-    Function ToggleBit(const Index: TQwordBitIndex) : QWord; inline;
-    Function TestBit(const Index:TQwordBitIndex):Boolean; inline; 
+    Function SetBit(const Index: TInt64BitIndex) : Int64; inline;
+    Function ClearBit(const Index: TInt64BitIndex) : Int64; inline;
+    Function ToggleBit(const Index: TInt64BitIndex) : Int64; inline;
+    Function TestBit(const Index: TInt64BitIndex): Boolean; inline;
+    procedure Clear; inline;
+    function  HighestSetBitPos: cardinal; inline;
+    function  LowestSetBitPos: cardinal; inline;
+    function  SetBitsCount: byte; inline;
+    property  Bit   [aIndex: TInt64BitIndex]: boolean   read GetBit    write PutBit;
+    property  Nibble[aIndex: TInt64NibbleIndex]: nibble read GetNibble write PutNibble;
+    property  Byte  [aIndex: TInt64ByteIndex]: byte     read GetByte   write PutByte;
+    property  Word  [aIndex: TInt64WordIndex]: word     read GetWord   write PutWord;
+    property  DWord [aIndex: TInt64DwordIndex]: dword   read GetDWord  write PutDWord;
   end;
 
+  // TNativeIntBitIndex is already defined
+  {$ifdef cpu16}
+    TNativeIntNibbleIndex = TSmallIntNibbleIndex;
+    TNativeIntByteIndex   = TSmallIntByteIndex;
+    TNativeIntOverlay     = TSmallIntOverlay;
+  {$endif}
+  {$ifdef cpu32}
+    TNativeIntNibbleIndex = TIntegerNibbleIndex;
+    TNativeIntByteIndex   = TIntegerByteIndex;
+    TNativeIntWordIndex   = TIntegerWordIndex;
+    TNativeIntOverlay     = TIntegerOverlay;
+  {$endif}
+  {$ifdef cpu64}
+    TNativeIntNibbleIndex = TInt64NibbleIndex;
+    TNativeIntByteIndex   = TInt64ByteIndex;
+    TNativeIntWordIndex   = TInt64WordIndex;
+    TNativeIntDwordIndex  = TInt64DWordIndex;
+    TNativeIntOverlay     = TInt64Overlay;
+  {$endif}
+
   TNativeIntHelper = Type Helper for NativeInt
+  const
+    MaxValue  = High(NativeInt);
+    MinValue  = Low(NativeInt);
+    MaxBit    = High(TNativeIntBitIndex);
+    MinBit    = Low(TNativeIntBitIndex);
+    MaxNibble = High(TNativeIntNibbleIndex);
+    MinNibble = Low(TNativeIntNibbleIndex);
+    // NativeInt on cpu16 has 2 bytes, so no need for cpu16 check because we always need MaxByte and MinByte
+    MaxByte   = High(TNativeIntByteIndex);
+    MinByte   = Low(TNativeIntByteIndex);
+    {$ifdef cpu32}
+    MaxWord   = High(TNativeIntWordIndex);
+    MinWord   = Low(TNativeIntWordIndex);
+    {$endif}
+    {$ifdef cpu64}
+    MaxWord   = High(TNativeIntWordIndex);
+    MinWord   = Low(TNativeIntWordIndex);
+    MaxDword  = High(TNativeIntDwordIndex);
+    MinDword  = Low(TNativeIntDwordIndex);
+    {$endif}
   public
-    const
-      MaxValue = High(NativeInt);
-      MinValue = Low(NativeInt);
-  Public
     Class Function Parse(const AString: string): NativeInt; inline; static;
     Class Function Size: Integer; inline; static;
     Class Function ToString(const AValue: NativeInt): string; overload; inline; static;
     Class Function TryParse(const AString: string; out AValue: NativeInt): Boolean; inline; static;
-  Public
+  protected
+    function  GetBit(const aIndex: TNativeIntBitIndex): boolean; inline;
+    procedure PutBit(const aIndex: TNativeIntBitIndex; const aNewValue: boolean); inline;
+    function  GetNibble(const aIndex: TNativeIntNibbleIndex): nibble; inline;
+    procedure PutNibble(const aIndex: TNativeIntNibbleIndex; const aNewValue: nibble); inline;
+    // NativeInt on cpu16 has 2 bytes, so no need for cpu16 check because we always need GetByte and PutByte
+    function  GetByte(const aIndex: TNativeIntByteIndex): byte;
+    procedure PutByte(const aIndex: TNativeIntByteIndex; const aNewValue: byte);
+    {$ifdef cpu32}
+    function  GetWord(const aIndex: TNativeIntWordIndex): word;
+    procedure PutWord(const aIndex: TNativeIntWordIndex; const aNewValue: word);
+    {$endif}
+    {$ifdef cpu64}
+    function  GetWord(const aIndex: TNativeIntWordIndex): word;
+    procedure PutWord(const aIndex: TNativeIntWordIndex; const aNewValue: word);
+    function  GetDword(const aIndex: TNativeIntDwordIndex): dword;
+    procedure PutDword(const aIndex: TNativeIntDwordIndex; const aNewValue: dword);
+    {$endif}
+  public
     Function ToBoolean: Boolean; inline;
     Function ToDouble: Double; inline;
     Function ToExtended: Extended; inline;
@@ -604,19 +924,88 @@ Type
     Function ClearBit(const Index: TNativeIntBitIndex) : NativeInt; inline;
     Function ToggleBit(const Index: TNativeIntBitIndex) : NativeInt; inline;
     Function TestBit(const Index:TNativeIntBitIndex):Boolean; inline; 
+    procedure Clear; inline;
+    function  HighestSetBitPos: cardinal; inline;
+    function  LowestSetBitPos: cardinal; inline;
+    function  SetBitsCount: byte; inline;
+    property  Bit   [aIndex: TNativeIntBitIndex]: boolean   read GetBit    write PutBit;
+    property  Nibble[aIndex: TNativeIntNibbleIndex]: nibble read GetNibble write PutNibble;
+    // NativeInt on cpu16 has 2 bytes, so no need for cpu16 check because we always need Byte[]
+    property  Byte  [aIndex: TNativeIntByteIndex]: byte     read GetByte   write PutByte;
+    {$ifdef cpu32}
+    property  Word  [aIndex: TNativeIntWordIndex]: word     read GetWord   write PutWord;
+    {$endif}
+    {$ifdef cpu64}
+    property  Word  [aIndex: TNativeIntWordIndex]: word     read GetWord   write PutWord;
+    property  DWord [aIndex: TNativeIntDwordIndex]: dword   read GetDWord  write PutDWord;
+    {$endif}
   end;
 
+  // TNativeUIntBitIndex is already defined
+  {$ifdef cpu16}
+    TNativeUIntNibbleIndex = TWordNibbleIndex;
+    TNativeUIntByteIndex   = TWordByteIndex;
+    TNativeUIntOverlay     = TWordOverlay;
+  {$endif}
+  {$ifdef cpu32}
+    TNativeUIntNibbleIndex = TDwordNibbleIndex;
+    TNativeUIntByteIndex   = TDwordByteIndex;
+    TNativeUIntWordIndex   = TDwordWordIndex;
+    TNativeUIntOverlay     = TDwordOverlay;
+  {$endif}
+  {$ifdef cpu64}
+    TNativeUIntNibbleIndex = TQwordNibbleIndex;
+    TNativeUIntByteIndex   = TQwordByteIndex;
+    TNativeUIntWordIndex   = TQwordWordIndex;
+    TNativeUIntDwordIndex  = TQwordDWordIndex;
+    TNativeUIntOverlay     = TQwordOverlay;
+  {$endif}
+
   TNativeUIntHelper = Type Helper for NativeUInt
+  const
+    MaxValue  = High(NativeUInt);
+    MinValue  = 0;
+    MaxBit    = High(TNativeUIntBitIndex);
+    MinBit    = Low(TNativeUIntBitIndex);
+    MaxNibble = High(TNativeUIntNibbleIndex);
+    MinNibble = Low(TNativeUIntNibbleIndex);
+    // NativeInt on cpu16 has 2 bytes, so no need for cpu16 check because we always need MaxByte and MinByte
+    MaxByte   = High(TNativeUIntByteIndex);
+    MinByte   = Low(TNativeUIntByteIndex);
+    {$ifdef cpu32}
+    MaxWord   = High(TNativeUIntWordIndex);
+    MinWord   = Low(TNativeUIntWordIndex);
+    {$endif}
+    {$ifdef cpu64}
+    MaxWord   = High(TNativeUIntWordIndex);
+    MinWord   = Low(TNativeUIntWordIndex);
+    MaxDword  = High(TNativeUIntDwordIndex);
+    MinDword  = Low(TNativeUIntDwordIndex);
+    {$endif}
   public
-    const
-      MaxValue = High(NativeUInt);
-      MinValue = 0;
-  Public
     Class Function Parse(const AString: string): NativeUInt; inline; static;
     Class Function Size: Integer; inline; static;
     Class Function ToString(const AValue: NativeUInt): string; overload; inline; static;
     Class Function TryParse(const AString: string; out AValue: NativeUInt): Boolean; inline; static;
-  Public
+  protected
+    function  GetBit(const aIndex: TNativeUIntBitIndex): boolean; inline;
+    procedure PutBit(const aIndex: TNativeUIntBitIndex; const aNewValue: boolean); inline;
+    function  GetNibble(const aIndex: TNativeUIntNibbleIndex): nibble; inline;
+    procedure PutNibble(const aIndex: TNativeUIntNibbleIndex; const aNewValue: nibble); inline;
+    // NativeInt on cpu16 has 2 bytes, so no need for cpu16 check because we always need GetByte and PutByte
+    function  GetByte(const aIndex: TNativeUIntByteIndex): byte;
+    procedure PutByte(const aIndex: TNativeUIntByteIndex; const aNewValue: byte);
+    {$ifdef cpu32}
+    function  GetWord(const aIndex: TNativeUIntWordIndex): word;
+    procedure PutWord(const aIndex: TNativeUIntWordIndex; const aNewValue: word);
+    {$endif}
+    {$ifdef cpu64}
+    function  GetWord(const aIndex: TNativeUIntWordIndex): word;
+    procedure PutWord(const aIndex: TNativeUIntWordIndex; const aNewValue: word);
+    function  GetDword(const aIndex: TNativeUIntDwordIndex): dword;
+    procedure PutDword(const aIndex: TNativeUIntDwordIndex; const aNewValue: dword);
+    {$endif}
+  public
     Function ToBoolean: Boolean; inline;
     Function ToDouble: Double; inline;
     Function ToExtended: Extended; inline;
@@ -629,6 +1018,21 @@ Type
     Function ClearBit(const Index: TNativeUIntBitIndex): NativeUint; inline;
     Function ToggleBit(const Index: TNativeUIntBitIndex) : NativeUint; inline;
     Function TestBit(const Index:TNativeUIntBitIndex) :Boolean; inline;
+    procedure Clear; inline;
+    function  HighestSetBitPos: cardinal; inline;
+    function  LowestSetBitPos: cardinal; inline;
+    function  SetBitsCount: byte; inline;
+    property  Bit   [aIndex: TNativeUIntBitIndex]: boolean   read GetBit    write PutBit;
+    property  Nibble[aIndex: TNativeUIntNibbleIndex]: nibble read GetNibble write PutNibble;
+    // NativeInt on cpu16 has 2 bytes, so no need for cpu16 check because we always need Byte[]
+    property  Byte  [aIndex: TNativeUIntByteIndex]: byte     read GetByte   write PutByte;
+    {$ifdef cpu32}
+    property  Word  [aIndex: TNativeUIntWordIndex]: word     read GetWord   write PutWord;
+    {$endif}
+    {$ifdef cpu64}
+    property  Word  [aIndex: TNativeUIntWordIndex]: word     read GetWord   write PutWord;
+    property  DWord [aIndex: TNativeUIntDwordIndex]: dword   read GetDWord  write PutDWord;
+    {$endif}
   end;
 
   {$SCOPEDENUMS ON}
diff --git a/rtl/objpas/sysutils/syshelpo.inc b/rtl/objpas/sysutils/syshelpo.inc
index 497d0ef508..ad3365f67e 100644
--- a/rtl/objpas/sysutils/syshelpo.inc
+++ b/rtl/objpas/sysutils/syshelpo.inc
@@ -106,3 +106,117 @@ Function TORDINALHELPER.TestBit(const Index: TORDINALBITINDEX):Boolean; inline;
 begin
   Result := (Self and TORDINALTYPE((TORDINALTYPE(1) shl index)))<>0;
 end;
+
+procedure TORDINALHELPER.Clear;
+begin
+  Self := 0;
+end;
+
+function TORDINALHELPER.HighestSetBitPos: cardinal;
+begin
+  {$ifdef TORDINALTYPESIZE1}
+        Result := BsrByte(byte(Self));
+  {$else}
+    {$ifdef TORDINALTYPESIZE2}
+        Result := BsrWord(word(Self));
+    {$else}
+      {$ifdef TORDINALTYPESIZE4}
+        Result := BsrDWord(dword(Self));
+      {$else} // TORDINALTYPESIZE8
+        Result := BsrQWord(qword(Self));
+      {$endif}
+    {$endif}
+  {$endif}
+end;
+
+function TORDINALHELPER.LowestSetBitPos: cardinal;
+begin
+  {$ifdef TORDINALTYPESIZE1}
+        Result := BsfByte(byte(Self));
+  {$else}
+    {$ifdef TORDINALTYPESIZE2}
+        Result := BsfWord(word(Self));
+    {$else}
+      {$ifdef TORDINALTYPESIZE4}
+        Result := BsfDWord(dword(Self));
+      {$else} // TORDINALTYPESIZE8
+        Result := BsfQWord(qword(Self));
+      {$endif}
+    {$endif}
+  {$endif}
+end;
+
+function TORDINALHELPER.SetBitsCount: byte;
+begin
+  {$ifdef TORDINALTYPESIZE1}
+        Result := PopCnt(byte(Self));
+  {$else}
+    {$ifdef TORDINALTYPESIZE2}
+        Result := PopCnt(word(Self));
+    {$else}
+      {$ifdef TORDINALTYPESIZE4}
+        Result := PopCnt(dword(Self));
+      {$else} // TORDINALTYPESIZE8
+        Result := PopCnt(qword(Self));
+      {$endif}
+    {$endif}
+  {$endif}
+end;
+
+function TORDINALHELPER.GetBit(const aIndex: TORDINALBITINDEX): boolean;
+begin
+  Result := ((Self shr aIndex) and TORDINALTYPE(1)) = TORDINALTYPE(1);
+end;
+
+procedure TORDINALHELPER.PutBit(const aIndex: TORDINALBITINDEX; const aNewValue: boolean);
+begin
+  Self := Self or (TORDINALTYPE(1) shl aIndex) xor (TORDINALTYPE(not aNewValue) shl aIndex);
+end;
+
+function TORDINALHELPER.GetNibble(const aIndex: TORDINALNIBBLEINDEX): nibble;
+begin
+  Result := TORDINALOVERLAY(Self).AsNibble[aIndex];
+end;
+
+procedure TORDINALHELPER.PutNibble(const aIndex: TORDINALNIBBLEINDEX; const aNewValue: nibble);
+begin
+  TORDINALOVERLAY(Self).AsNibble[aIndex] := aNewValue;
+end;
+
+{$ifndef TORDINALTYPESIZE1} // TWordHelper, TDWordHelper, TQWordHelper jump in here (and others with 2, 4 and 8 bytes)
+  function TORDINALHELPER.GetByte(const aIndex: TORDINALBYTEINDEX): byte;
+  begin
+    Result := TORDINALOVERLAY(Self).AsByte[aIndex];
+  end;
+
+  procedure TORDINALHELPER.PutByte(const aIndex: TORDINALBYTEINDEX; const aNewValue: byte);
+  begin
+    TORDINALOVERLAY(Self).AsByte[aIndex] := aNewValue;
+  end;
+
+  {$ifndef TORDINALTYPESIZE2} // TDWordHelper, TQWordHelper jump in here (and others with 4 and 8 bytes)
+    function TORDINALHELPER.GetWord(const aIndex: TORDINALWORDINDEX): word;
+    begin
+      Result := TORDINALOVERLAY(Self).AsWord[aIndex];
+    end;
+
+    procedure TORDINALHELPER.PutWord(const aIndex: TORDINALWORDINDEX; const aNewValue: word);
+    begin
+      TORDINALOVERLAY(Self).AsWord[aIndex] := aNewValue;
+    end;
+
+    {$ifndef TORDINALTYPESIZE4} // TQWordHelper jumps in here (and others with 8 bytes)
+      function TORDINALHELPER.GetDword(const aIndex: TORDINALDWORDINDEX): dword;
+      begin
+        Result := TORDINALOVERLAY(Self).AsDword[aIndex];
+      end;
+
+      procedure TORDINALHELPER.PutDword(const aIndex: TORDINALDWORDINDEX; const aNewValue: dword);
+      begin
+        TORDINALOVERLAY(Self).AsDword[aIndex] := aNewValue;
+      end;
+    {$endif}
+
+  {$endif}
+
+{$endif}
1b.patch (43,194 bytes)   

Zeljko Avramovic

2021-07-21 10:51

reporter   ~0131975

I have just seen that for example TExtendedHelper has properties named Bytes[] and Words[] while I have Byte[] and Word[]. It also has private methods GetB(), SetB() GetW() and SetW() while I have protected methods GetByte(), SetByte(), GetWord() and SetWord(). I regret not looking at TExtendedHelper earlier, but that's the way it is. I do not like these changes, but if you think that it is needed for unification I will do it, of course. Unification reason is an argument good enough. I just think that protected methods should be everywhere instead of private methods, but if you don't like it I will change my methods to private, too.

Michael Van Canneyt

2021-07-21 11:37

administrator   ~0131976

I applied your patch, but made all properties plural, so it is the same as for float types: bytes, bits, words, nibbles etc. This is more consistent.

Zeljko Avramovic

2021-07-21 11:59

reporter   ~0131977

Thanks! I will now deal with syshelpers

Zeljko Avramovic

2021-07-21 20:10

reporter   ~0131988

HexDigits[] already exist in sysstr.inc, but it is not visible since it was in implementation section. With this tiny patch I moved HexDigits[] to sysstrh.inc so that it can be used by other parties (like syshelpers). It is needed if we want to avoid 16 bytes wasted without any need, and it might also be useful to someone else later on.
1c.patch (1,121 bytes)   
diff --git a/rtl/objpas/sysutils/sysstr.inc b/rtl/objpas/sysutils/sysstr.inc
index 82725fc8fa..68659ff20a 100644
--- a/rtl/objpas/sysutils/sysstr.inc
+++ b/rtl/objpas/sysutils/sysstr.inc
@@ -877,8 +877,8 @@ end;
 
 {   IntToHex returns a string representing the hexadecimal value of Value   }
 
-const
-   HexDigits: array[0..15] of char = '0123456789ABCDEF';
+//const
+//   HexDigits: array[0..15] of char = '0123456789ABCDEF'; // moved to sysstrh.inc so that it becomes more visible to others (like syshelpers)
 
 function IntToHex(Value: Longint; Digits: integer): string;
 var i: integer;
diff --git a/rtl/objpas/sysutils/sysstrh.inc b/rtl/objpas/sysutils/sysstrh.inc
index 370ca8356a..8a380dcf1c 100644
--- a/rtl/objpas/sysutils/sysstrh.inc
+++ b/rtl/objpas/sysutils/sysstrh.inc
@@ -62,6 +62,9 @@ Const
 Var TrueBoolStrs,
     FalseBoolStrs : Array of String;
 
+const
+   HexDigits: array[0..15] of char = '0123456789ABCDEF';
+
 // declaring this breaks delphi compatibility and e.g. tw3721.pp
 // function NewStr(Const S: ShortString): PShortString; overload;
 function NewStr(const S: string): PString; overload;
1c.patch (1,121 bytes)   

Zeljko Avramovic

2021-07-22 10:20

reporter   ~0131995

Here are patches 2 and 3 - syshelpers for rtl objpas.

I have also attached temporary example console program for windows, but that is just for your quick funcionality test - please do not include it yet since I need also to test under linux console before submitting and change a little. Once I finish it, in what directory should this test example end up?
syshelpers.zip (4,006 bytes)
testsyshelpers.lpr (6,467 bytes)   
program testsyshelpers;

uses
  {$IFDEF WINDOWS}windows,{$ENDIF}
  sysutils, syshelpers;

procedure Print(aValue: boolean);
begin
  WriteLn(aValue.ToTrueFalseString, ': ', aValue.ToString, ' ', aValue.ToOneZeroString, ' ', aValue.ToOnOffString);
end;

var
  MyBitFormatSettings: TBitFormatSettings = (
    BitTrueString:      'True';
    BitFalseString:     'False';
    //
    BitOnString:        'On';
    BitOffString:       'Off';
    //
    BitOneString:       '1';
    BitZeroString:      '0';
  );

  PreviousValue: uint;
  MyBool: boolean;
  MyByte: byte;
  MyWord: word;
  MyDword: dword;
  MyQword: qword;
  MyNativeInt: NativeInt;
  MyNewByteOverlay: TByteOverlay;
begin
  {$IFDEF WINDOWS}
    PreviousValue := GetConsoleOutputCP;
    DefaultSystemCodePage := CP_UTF8;
    SetConsoleOutputCP(CP_UTF8);
    SetTextCodePage(Output, CP_UTF8);
  {$ENDIF}

  MyByte.Clear;
  MyByte.Bits[1] := true;
  MyByte.Bits[5] := MyByte.Bits[1]; // Bit[8+] is SEGSEV if range check is off
  WriteLn('MyByte.ToBinString        = ', MyByte.ToBinString);
  WriteLn('MyByte.ToBinString(true)  = ', MyByte.ToBinString(true));
  WriteLn('MyByte.ToBinString(false) = ', MyByte.ToBinString(false));

  WriteLn('True.ToTrueFalseString(scfUpperCase) = ', True.ToTrueFalseString(scfUpperCase));
  WriteLn('True.ToString(''OnState'', ''OffState'') = ', True.ToString('OnState', 'OffState'));
  WriteLn('True.ToString(''Running'', ''Stopped'', scfUpperCase) = ', True.ToString('Running', 'Stopped', scfUpperCase));
  WriteLn('True.ToString(''Ради'', ''Не ради'', scfUpperCase) = ', True.ToString('Ради', 'Не ради', scfUpperCase), ' (console uppers ASCII only, gui uppers unicode as well)');

  MyNativeInt := -10000;
  WriteLn('MyNativeInt = ', MyNativeInt);
  WriteLn('MyNativeInt.ToBinString = ', MyNativeInt.ToBinString);
  WriteLn('MyNativeInt.Bits[MyNativeInt.MaxBit].ToTrueFalseString = ', MyNativeInt.Bits[MyNativeInt.MaxBit].ToTrueFalseString);

  MyDword := %111000111000111000111;
  MyDword.Words[0] := 1;
  //MyDword.Bits[9] := true;
  //MyDword.Bits[13] := true;
  MyNativeInt := -10000;
  WriteLn('MyDword.ToBinString     = ', MyDword.ToBinString);
  WriteLn('MyDword.ToHexString     = ', MyDword.ToHexString);
  WriteLn('MyDword.ToHexString(7)  = ', MyDword.ToHexString(7));

  MyByte.Clear;
  MyByte.Nibbles[0] := 7;
  MyByte.Nibbles[1] := 1;
  BinNibbleSeparator := '_';
  WriteLn('MyByte.ToBinString = ', MyByte.ToBinString);
  BinNibbleSeparator := '';

  Print(False);
  Print(True);

  WriteLn('MyDword.Bits[5].ToTrueFalseString = ', MyDword.Bits[5].ToTrueFalseString, ' (BitTrueString = ', BitTrueString, ')');
  WriteLn('MyDword.Bits[5].ToString = ', MyDword.Bits[5].ToString{, ' ', BitTrueString});
  WriteLn('TryStrToBool(''trUE'', MyBool) = ', TryStrToBool('trUE', MyBool){.ToString, ' ', MyBool});
  WriteLn('BoolToStr(true, true) = ', BoolToStr(true, true){, ' ', TrueBoolStrs[0]});

  with MyBitFormatSettings do
  begin
    BitTrueString  := 'Истина';    // BEWARE! This changes all boolean to string text outputs (TryStrToBool compares string against upcase[BitTrueString, BitOnString, BitOneString], but upcase() is by default good only for ASCII on console, while GUI is good for unicode)
    BitFalseString := 'Неистина';  // BEWARE! This changes all boolean to string text outputs (TryStrToBool compares string against upcase[BitFalseString, BitOffString, BitZeroString], but upcase() is by default good only for ASCII on console, while GUI is good for unicode)
    BitOnString    := 'Укључено';
    BitOffString   := 'Искључено';
    BitOneString   := 'X';
    BitZeroString  := 'O';
  end;
  MyBitFormatSettings.CopyToDefaultBoolStrings;
  MyBitFormatSettings.CopyToDefaultBitFormatSettings;

  WriteLn('MyDword.Bits[5].ToTrueFalseString = ', MyDword.Bits[5].ToTrueFalseString, ' (BitTrueString = ', BitTrueString, ')');
  WriteLn('MyDword.Bits[5].ToString          = ', MyDword.Bits[5].ToString{, ', BitTrueString = ', BitTrueString});
  WriteLn('TryStrToBool(''Истина'', MyBool)    = ', TryStrToBool('Истина', MyBool).ToString, ', (MyBool = ', MyBool);
  WriteLn('TryStrToBool(''ИСТИна'', MyBool)    = ', TryStrToBool('ИСТИна', MyBool).ToString, ' (console uppers ASCII only, gui uppers unicode as well)');
  WriteLn('BoolToStr(true, true)             = ', BoolToStr(true, true), ', TrueBoolStrs[0] = ', TrueBoolStrs[0]);

  Print(False);
  Print(True);

  MyQword := $ABCDEFFFFFF;
  WriteLn('MyQword.ToBinString                                = ', MyQword.ToBinString);
  WriteLn('MyQword.ToBinString(false)                         = ', MyQword.ToBinString(false));
  WriteLn('MyQword.ToBinString(50)                            = ', MyQword.ToBinString(50)); //
  WriteLn('MyQword.ToBinString(DefaultBinSettings, false)     = ', MyQword.ToBinString(DefaultBinFormatSettings, false));
  WriteLn('MyQword.ToBinString(DefaultBinSettings, 50)        = ', MyQword.ToBinString(DefaultBinFormatSettings, 50)); //

  WriteLn('MyQword.ToHexString                                      = ', MyQword.ToHexString);
  WriteLn('MyQword.ToHexString(3)                                   = ', MyQword.ToHexString(3));
  WriteLn('MyQword.ToHexString(13)                                  = ', MyQword.ToHexString(13));
  WriteLn('MyQword.ToHexString(true)                                = ', MyQword.ToHexString(true));
  WriteLn('MyQword.ToHexString(false)                               = ', MyQword.ToHexString(false));
  WriteLn('MyQword.ToHexString(DefaultHexFormatSettings)            = ', MyQword.ToHexString(DefaultHexFormatSettings));
  WriteLn('MyQword.ToHexString(DefaultHexFormatSettings, false)     = ', MyQword.ToHexString(DefaultHexFormatSettings, false));
  WriteLn('MyQword.ToHexString(DefaultHexFormatSettings, 13)        = ', MyQword.ToHexString(DefaultHexFormatSettings, 13));

  HexPrefixString    := '[$';
  HexSufixString     := ']';
  HexNibbleSeparator := '.';
  HexByteSeparator   := '^';
  HexWordSeparator   := '_';
  HexDwordSeparator  := '--';

  WriteLn('MyQword.ToHexString        = ', MyQword.ToHexString);
  WriteLn('MyQword.ToHexString(true)  = ', MyQword.ToHexString(true));
  WriteLn('MyQword.ToHexString(false) = ', MyQword.ToHexString(false));

  {$IFDEF WINDOWS}
    SetConsoleOutputCP(PreviousValue);
  {$ENDIF}
end.

testsyshelpers.lpr (6,467 bytes)   

Michael Van Canneyt

2021-07-22 10:30

administrator   ~0131996

If it is a real automated test program, then it should go in a packages/rtl-objpas/tests/tsyshelpers.pp
If it is more for demonstration purposes, packages/rtl-objpas/examples is more suitable.

jamie philbrook

2021-07-22 22:51

reporter   ~0132000

I guess I have one question basically.
how does the compiler deal with all these added helpers in the rtl ?

All I see is loads and loads of code being added by default without use in applications?

Can't we separate these added features in optional units so they don't get linked in to the RTL ?

 Or did I miss understand how helpers work?

can't there be some units that users can add that do not ever get used in the RTL ? or even some way to mark the units so no one gets tempted to use them in base code that forces every one else to bloat their apps with unused code ?

Zeljko Avramovic

2021-07-22 23:43

reporter   ~0132002

@jamie:

Did you see that, as requested by Michael, only important part was added to sysutils? Bytes[] and Words[] already existed for some types, so it was natural to extend ordinal types with Bits[], Nibbles[], Bytes[], Words[] and Dwords[]. Once overlay types were introduced, getters and setters became simple inlined one liners. Just look at the code. The rest of my RTL changes related to customizable boolean, binary and hexadecimal data internationalized string representation is put in separate syshelpers unit (look at content of syshelpers.zip).

In syshelpers for booleans you finally get proper ToString method that you complained were returning odd 0 and -1 in one forum thread. So this code:

  uses
    syshelpers;
  ...
  procedure TForm1.BooleanBitTestBtnClick(Sender: TObject);
  var
    MyBool: boolean;
  begin
    MyBool := true;
    Memo1.Append(MyBool.ToOneZeroString);
    Memo1.Append(MyBool.ToOnOffString); // default is scfUnchangedCase and can be ommited
    Memo1.Append(MyBool.ToOnOffString(scfLowerCase));
    Memo1.Append(MyBool.ToTrueFalseString(scfUpperCase));
    Memo1.Append(MyBool.ToString('OnState', 'OffState')); // true/false custom strings
    Memo1.Append(MyBool.ToString('Укључено', 'Искључено', scfUpperCase)); // when case and unicode matter
  end;

produces this output:

  1
  On
  on
  TRUE
  OnState
  УКЉУЧЕНО

Zeljko Avramovic

2021-07-23 10:48

reporter   ~0132010

Here is the syshelpers to include in rtl-objpas. Please review.

In case it is not obvious, syshelpers need 1c.patch to be applied first to fix visibilty of HexDigits[].
syshelpers-2.zip (4,102 bytes)

Sven Barth

2021-07-23 10:53

manager   ~0132011

Last edited: 2021-07-23 10:53

View 2 revisions

@jamie
> All I see is loads and loads of code being added by default without use in applications?

Code of a unit that is not used by your application (directly or indirectly) is not linked in.

This can be nicely seen by looking at the size of the SysUtils object file: In 3.2.2 for x86_64-win64 it has a size of 1.87 MB (without debug information). If I now create an empty program that only uses the SysUtils unit the size of the binary will be 114 KB. If I leave out the SysUtils unit then it will be 45 KB. This difference is due to some registration that is part of the units initialization (and anything that needs), but the majority of the unit is simply not used and thus is also not part of the final executable.

Michael Van Canneyt

2021-07-23 11:09

administrator   ~0132012

Sven, this is only true when you turn on smartlinking, which by default is off.
A regular compile on linux without options results in a 2.7 Mb program,
if the uses clause just contains the sysutils unit, no code.

Issue History

Date Modified Username Field Change
2021-07-20 09:25 Zeljko Avramovic New Issue
2021-07-20 09:25 Zeljko Avramovic File Added: sysutils-bithelpers.patch
2021-07-20 09:33 Michael Van Canneyt Assigned To => Michael Van Canneyt
2021-07-20 09:33 Michael Van Canneyt Status new => assigned
2021-07-20 09:37 Michael Van Canneyt Note Added: 0131948
2021-07-20 11:54 Zeljko Avramovic Note Added: 0131955
2021-07-20 12:08 Zeljko Avramovic Note Edited: 0131955 View Revisions
2021-07-20 12:13 Michael Van Canneyt Note Added: 0131956
2021-07-20 12:24 Zeljko Avramovic Note Added: 0131957
2021-07-20 12:48 Michael Van Canneyt Note Added: 0131959
2021-07-20 12:57 Zeljko Avramovic Note Added: 0131960
2021-07-20 22:46 Zeljko Avramovic Note Added: 0131966
2021-07-20 22:46 Zeljko Avramovic File Added: 1.patch
2021-07-21 00:45 Zeljko Avramovic Note Added: 0131968
2021-07-21 07:00 Michael Van Canneyt Note Added: 0131969
2021-07-21 09:28 Zeljko Avramovic Note Added: 0131973
2021-07-21 09:28 Zeljko Avramovic File Added: 1b.patch
2021-07-21 10:51 Zeljko Avramovic Note Added: 0131975
2021-07-21 11:37 Michael Van Canneyt Note Added: 0131976
2021-07-21 11:59 Zeljko Avramovic Note Added: 0131977
2021-07-21 20:10 Zeljko Avramovic Note Added: 0131988
2021-07-21 20:10 Zeljko Avramovic File Added: 1c.patch
2021-07-22 10:20 Zeljko Avramovic Note Added: 0131995
2021-07-22 10:20 Zeljko Avramovic File Added: syshelpers.zip
2021-07-22 10:20 Zeljko Avramovic File Added: testsyshelpers.lpr
2021-07-22 10:30 Michael Van Canneyt Note Added: 0131996
2021-07-22 22:51 jamie philbrook Note Added: 0132000
2021-07-22 23:43 Zeljko Avramovic Note Added: 0132002
2021-07-23 10:48 Zeljko Avramovic Note Added: 0132010
2021-07-23 10:48 Zeljko Avramovic File Added: syshelpers-2.zip
2021-07-23 10:53 Sven Barth Note Added: 0132011
2021-07-23 10:53 Sven Barth Note Edited: 0132011 View Revisions
2021-07-23 11:09 Michael Van Canneyt Note Added: 0132012