unit BoxPrimitives;
//=== File Prolog ============================================================
//    This code was developed by RiverSoftAVG.
//
//--- Notes ------------------------------------------------------------------
//
//--- Development History  ---------------------------------------------------
//
//  07/2013 T. Grubb
//          - Initial Version
//
//      File Contents:
//        TRSBoxPrimitive<T>       simple class for boxing and unboxing a primitive type
//
//--- Warning ----------------------------------------------------------------
//    This software is property of RiverSoftAVG. Unauthorized use or
//    duplication of this software is strictly prohibited. Authorized users
//    are subject to the following restrictions:
//      * RiverSoftAVG is not responsible for
//        any consequence of the use of this software.
//      * The origin of this software must not be misrepresented either by
//        explicit claim or by omission.
//      * Altered versions of this software must be plainly marked as such.
//      * This notice may not be removed or altered.
//
//      © 2013, Thomas G. Grubb
//
//=== End File Prolog ========================================================
interface

uses
  Classes, Types, Generics.Defaults;

type
  TRSBoxPrimitive<T> = class(TObject)
  { Purpose: To provide a simple class for boxing and unboxing a primitive type
    Note: this class is only for use by AUTOREFCOUNT compilers }
  private
    { private declarations }
    FValue: T;
  protected
    { protected declarations }
  public
    { public declarations }
    constructor Create( const V: T );
    class operator Equal(a,b: TRSBoxPrimitive<T>): Boolean;
    class operator NotEqual(a,b: TRSBoxPrimitive<T>): Boolean;
    class function IndexOf( const Strings: TStrings; a: T ): Integer;
    class operator Implicit(a: T): TRSBoxPrimitive<T>;            // Implicit conversion of an T to type TRSBoxPrimitive
    class operator Implicit(a: TRSBoxPrimitive<T>): T;            // Implicit conversion of TRSBoxPrimitive to T
    class operator Explicit(a: T): TRSBoxPrimitive<T>;            // Explicit conversion of an T to type TRSBoxPrimitive
    class operator Explicit(a: TRSBoxPrimitive<T>): T;            // Explicit conversion of TRSBoxPrimitive to T
  end; { TRSBoxPrimitive<T> }

  TBoxInteger = TRSBoxPrimitive<Integer>;
  TBoxShortInt = TRSBoxPrimitive<ShortInt>;
  TBoxSmallInt = TRSBoxPrimitive<SmallInt>;
  TBoxNativeInt = TRSBoxPrimitive<NativeInt>;
  TBoxByte = TRSBoxPrimitive<Byte>;
  TBoxWord = TRSBoxPrimitive<Word>;
  TBoxCardinal = TRSBoxPrimitive<Cardinal>;
  TBoxBoolean = TRSBoxPrimitive<Boolean>;
  TBoxChar = TRSBoxPrimitive<Char>;
  TBoxExtended = TRSBoxPrimitive<Extended>;
  TBoxString = TRSBoxPrimitive<String>;
  TBoxPointer = TRSBoxPrimitive<Pointer>;
  TBoxPChar = TRSBoxPrimitive<PChar>;
  TBoxCurrency = TRSBoxPrimitive<Currency>;
  TBoxVariant = TRSBoxPrimitive<Variant>;
  TBoxInt64 = TRSBoxPrimitive<Int64>;
  TBoxUInt64 = TRSBoxPrimitive<UInt64>;
  TBoxSingle = TRSBoxPrimitive<Single>;
  TBoxDouble = TRSBoxPrimitive<Double>;

implementation

{ TRSBoxPrimitive<T> }

constructor TRSBoxPrimitive<T>.Create(const V: T);
begin
  inherited Create;
  FValue := V;
end;

class operator TRSBoxPrimitive<T>.Implicit(a: T): TRSBoxPrimitive<T>;
begin
 result := TRSBoxPrimitive<T>.Create(a);
end;

class operator TRSBoxPrimitive<T>.Explicit(a: T): TRSBoxPrimitive<T>;
begin
 result := TRSBoxPrimitive<T>.Create(a);
end;

class operator TRSBoxPrimitive<T>.Equal(a, b: TRSBoxPrimitive<T>): Boolean;
var
  lComparer: IEqualityComparer<T>;
begin
  lComparer := TEqualityComparer<T>.Default;
  result := ((a <> nil) and (b <> nil) and lComparer.Equals(a, b));
end;

class operator TRSBoxPrimitive<T>.Explicit(a: TRSBoxPrimitive<T>): T;
begin
  result := a.FValue;
end;

class operator TRSBoxPrimitive<T>.Implicit(a: TRSBoxPrimitive<T>): T;
begin
  result := a.FValue;
end;

class function TRSBoxPrimitive<T>.IndexOf(const Strings: TStrings;
  a: T): Integer;
begin
  for result := 0 to Strings.Count-1 do
    if TRSBoxPrimitive<T>(Strings.Objects[result]) = a then Exit;
  result := -1;
end;

class operator TRSBoxPrimitive<T>.NotEqual(a, b: TRSBoxPrimitive<T>): Boolean;
var
  lComparer: IEqualityComparer<T>;
begin
  lComparer := TEqualityComparer<T>.Default;
  result := (a = nil) or (b = nil) or (not lComparer.Equals(a, b));
end;

end.
