summaryrefslogtreecommitdiff
path: root/avx512-0037785/packages/rtl-objpas/src/inc/nullable.pp
blob: c66e7d914c532e05df915b7907af07ac8c7ca3ce (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
unit nullable;

{$mode objfpc}
{$modeswitch advancedrecords}

interface

uses sysutils;

Type

  { TNullable }

  generic TNullable<T> = record
  private
    FValue: T;
    FHasValue: Boolean; // Default False
    function GetIsNull: Boolean;
    function GetValue: T;
    function GetValueOrDefault: T;
    procedure SetHasValue(AValue: Boolean);
    procedure SetValue(AValue: T);
  Public
    // Make things more readable
    Type
      TMyType = specialize TNullable<T>;
    // Clear value, no value present after this.
    procedure Clear;
    // Is a value present ?
    property HasValue: Boolean read FHasValue write SetHasValue;
    // Is No value present
    property IsNull: Boolean read GetIsNull;
    // return the value.
    property Value: T read GetValue write SetValue;
    // If a value is present, return it, otherwise return the default.
    property ValueOrDefault: T read GetValueOrDefault;
    // Return an empty value
    class function Empty: TMyType; static;
    // management operator
    class operator Initialize(var aSelf : TNullable);
    // Conversion.
    class operator Explicit(aValue: T): TMyType;
    class operator Explicit(aValue: TMyType): T;
    class operator := (aValue: T): TMyType;
    class operator := (aValue: TMyType): T;
   end;

implementation

uses rtlconsts,typinfo;

{ TNullable }

function TNullable.GetIsNull: Boolean;
begin
  Result:=Not HasValue;
end;

function TNullable.GetValue: T;
begin
  if not FHasValue then
    raise EConvertError.CreateFmt(SErrCannotConvertNullToType,[PtypeInfo(TypeInfo(T))^.Name]);
  Result:=FValue;
end;

function TNullable.GetValueOrDefault: T;
begin
  if HasValue then
    Result:=Value
  else
    Result:=Default(T);
end;

procedure TNullable.SetHasValue(AValue: Boolean);
begin
  if FHasValue=AValue then Exit;
  if aValue then
    Value:=Default(T)
  else
    FHasValue:=False;
end;

procedure TNullable.SetValue(AValue: T);
begin
  FValue:=aValue;
  FHasValue:=True;
end;

procedure TNullable.Clear;
begin
  HasValue:=False;
end;

class operator TNullable.Initialize(var aSelf: TNullable);
begin
  aSelf.FHasValue:=False;
end;

class function TNullable.Empty: TMyType; static;

begin
  Result.HasValue:=False;
end;

class operator TNullable.Explicit(aValue: T): TMyType;

begin
  Result.Value:=aValue;
end;

class operator TNullable.Explicit(aValue: TMyType): T;

begin
  Result:=aValue.Value;
end;

class operator TNullable.:= (aValue: T): TMyType;
begin
  Result.Value:=aValue;
end;

class operator TNullable.:= (aValue: TMyType): T;

begin
  // We could use :=This is in line with TField's behaviour.
  Result:=aValue.Value;
end;

end.