Last active
December 13, 2015 15:04
-
-
Save owlsperspective/dba5c918f98dde911600 to your computer and use it in GitHub Desktop.
値範囲が0..255に収まらない部分範囲型の集合型
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
unit Unit3; | |
interface | |
uses | |
{$IF CompilerVersion >= 23.0} | |
System.SysUtils; | |
{$ELSE} | |
SysUtils; | |
{$IFEND} | |
const | |
BYTE_BIT = 8; // Number of bits in byte | |
type | |
{ Base enumeration type } | |
TBar = -1..257; | |
// TBarSetX = set of TBar; // E2028 Sets may have at most 256 elements | |
{ Set of large enumeration } | |
PBarSet = ^TBarSet; | |
TBarSet = record | |
private | |
type | |
TEnumerator = class(TObject) | |
private | |
FContainer: PBarSet; | |
FIndex: Integer; | |
function GetCurrent: TBar; | |
public | |
constructor Create(Container: PBarSet); | |
function MoveNext: Boolean; | |
property Current: TBar | |
read GetCurrent; | |
end; | |
private | |
FData: array [0..((Ord(High(TBar)) - Ord(Low(TBar)) + 1 + (BYTE_BIT - 1)) div BYTE_BIT) - 1] of Byte; | |
class procedure CalcOffsets(Value: TBar; var AOffset: Integer; var ABit: Byte); static; | |
public | |
procedure Clear; | |
procedure Empty; | |
function IsEmpty: Boolean; | |
procedure Include(Value: TBar); overload; | |
procedure Include(const Values: array of TBar); overload; | |
procedure Exclude(Value: TBar); overload; | |
procedure Exclude(const Values: array of TBar); overload; | |
function &In(Value: TBar): Boolean; | |
function ToString(ZeroSuppression: Boolean = True): String; | |
class function Parse(const Value: String): TBarSet; static; | |
{$IF CompilerVersion>=24.00} | |
class operator Implicit(const Values: array of TBar): TBarSet; | |
{$IFEND} | |
class operator Add(const lvalue: TBarSet; const rvalue: TBarSet): TBarSet; overload; | |
{$IF CompilerVersion>=28.00} | |
class operator Add(const lvalue: TBarSet; const rvalue: array of TBar): TBarSet; overload; | |
{$IFEND} | |
class operator Subtract(const lvalue: TBarSet; const rvalue: TBarSet): TBarSet; overload; | |
{$IF CompilerVersion>=28.00} | |
class operator Subtract(const lvalue: TBarSet; const rvalue: array of TBar): TBarSet; overload; | |
{$IFEND} | |
class operator Multiply(const lvalue: TBarSet; const rvalue: TBarSet): TBarSet; overload; | |
{$IF CompilerVersion>=28.00} | |
class operator Multiply(const lvalue: TBarSet; const rvalue: array of TBar): TBarSet; overload; | |
{$IFEND} | |
class operator LessThanOrEqual(const lvalue: TBarSet; const rvalue: TBarSet): Boolean; overload; | |
class operator GreaterThanOrEqual(const lvalue: TBarSet; const rvalue: TBarSet): Boolean; overload; | |
class operator Equal(const lvalue: TBarSet; const rvalue: TBarSet): Boolean; overload; | |
class operator NotEqual(const lvalue: TBarSet; const rvalue: TBarSet): Boolean; overload; | |
class operator In(lvalue: TBar; const rvalue: TBarSet): Boolean; | |
function GetEnumerator: TEnumerator; | |
end; | |
implementation | |
{ TBarSet } | |
procedure TBarSet.Clear; | |
begin | |
Self.Empty; | |
end; | |
procedure TBarSet.Empty; | |
begin | |
FillChar(FData[0],SizeOf(FData),0); | |
end; | |
function TBarSet.IsEmpty: Boolean; | |
var | |
Offset: Integer; | |
begin | |
Result := False; | |
for Offset := Low(FData) to High(FData) do | |
begin | |
if FData[Offset] <> 0 then | |
begin | |
Result := True; | |
Exit; | |
end; | |
end; | |
end; | |
procedure TBarSet.Include(Value: TBar); | |
var | |
Offset: Integer; | |
Bit: Byte; | |
begin | |
CalcOffsets(Value,Offset,Bit); | |
FData[Offset] := FData[Offset] or Bit; | |
end; | |
procedure TBarSet.Include(const Values: array of TBar); | |
var | |
Value: TBar; | |
begin | |
if Length(Values) > 0 then | |
begin | |
for Value in Values do | |
begin | |
Include(Value); | |
end; | |
end; | |
end; | |
procedure TBarSet.Exclude(Value: TBar); | |
var | |
Offset: Integer; | |
Bit: Byte; | |
begin | |
CalcOffsets(Value,Offset,Bit); | |
FData[Offset] := FData[Offset] and (not Bit); | |
end; | |
procedure TBarSet.Exclude(const Values: array of TBar); | |
var | |
Value: TBar; | |
begin | |
for Value in Values do | |
begin | |
Exclude(Value); | |
end; | |
end; | |
function TBarSet.&In(Value: TBar): Boolean; | |
var | |
Offset: Integer; | |
Bit: Byte; | |
begin | |
CalcOffsets(Value,Offset,Bit); | |
Result := (FData[Offset] and Bit) <> 0; | |
end; | |
function TBarSet.ToString(ZeroSuppression: Boolean): String; | |
var | |
Index: Integer; | |
Len: Integer; | |
Offset: Integer; | |
begin | |
Result := ''; | |
for Offset := Low(FData) to High(FData) do | |
begin | |
Result := IntToHex(FData[Offset],2) + Result; | |
end; | |
if ZeroSuppression = True then | |
begin | |
Index := 1; | |
Len := Length(Result); | |
while (Index < Len) and (Result[Index] = '0') do | |
begin | |
Index := Index + 1; | |
end; | |
if Index > 1 then | |
begin | |
Delete(Result,1,Index - 1); | |
end; | |
end; | |
end; | |
class function TBarSet.Parse(const Value: String): TBarSet; | |
var | |
Offset: Integer; | |
S: String; | |
begin | |
Result.Clear; | |
S := StringOfChar('0',(SizeOf(Result.FData) * 2) - Length(Value)) + Value; | |
for Offset := Low(Result.FData) to High(Result.FData) do | |
begin | |
Result.FData[Offset] := StrToInt('$' + Copy(S,(SizeOf(Result.FData) * 2) - (Offset * 2) - 1,2)); | |
end; | |
end; | |
{$IF CompilerVersion>=24.00} | |
class operator TBarSet.Implicit(const Values: array of TBar): TBarSet; | |
begin | |
Result.Clear; | |
Result.Include(Values); | |
end; | |
{$IFEND} | |
class operator TBarSet.Add(const lvalue: TBarSet; const rvalue: TBarSet): TBarSet; | |
var | |
Offset: Integer; | |
begin | |
Result.Clear; | |
for Offset := Low(Result.FData) to High(Result.FData) do | |
begin | |
Result.FData[Offset] := lvalue.FData[Offset] or rvalue.FData[Offset]; | |
end; | |
end; | |
{$IF CompilerVersion>=28.00} | |
class operator TBarSet.Add(const lvalue: TBarSet; const rvalue: array of TBar): TBarSet; | |
var | |
Value: TBar; | |
begin | |
Result := lvalue; | |
for Value in rvalue do | |
begin | |
Result.Include(Value); | |
end; | |
end; | |
{$IFEND} | |
class operator TBarSet.Subtract(const lvalue: TBarSet; const rvalue: TBarSet): TBarSet; | |
var | |
Offset: Integer; | |
begin | |
Result.Clear; | |
for Offset := Low(Result.FData) to High(Result.FData) do | |
begin | |
Result.FData[Offset] := lvalue.FData[Offset] and (not rvalue.FData[Offset]); | |
end; | |
end; | |
{$IF CompilerVersion>=28.00} | |
class operator TBarSet.Subtract(const lvalue: TBarSet; const rvalue: array of TBar): TBarSet; | |
var | |
Value: TBar; | |
begin | |
Result := lvalue; | |
for Value in rvalue do | |
begin | |
Result.Exclude(Value); | |
end; | |
end; | |
{$IFEND} | |
class operator TBarSet.Multiply(const lvalue: TBarSet; const rvalue: TBarSet): TBarSet; | |
var | |
Offset: Integer; | |
begin | |
Result.Clear; | |
for Offset := Low(Result.FData) to High(Result.FData) do | |
begin | |
Result.FData[Offset] := lvalue.FData[Offset] and rvalue.FData[Offset]; | |
end; | |
end; | |
{$IF CompilerVersion>=28.00} | |
class operator TBarSet.Multiply(const lvalue: TBarSet; const rvalue: array of TBar): TBarSet; | |
begin | |
Result := lvalue * TBarSet(rvalue); | |
end; | |
{$IFEND} | |
class operator TBarSet.LessThanOrEqual(const lvalue: TBarSet; const rvalue: TBarSet): Boolean; | |
var | |
Offset: Integer; | |
begin | |
for Offset := Low(lvalue.FData) to High(lvalue.FData) do | |
begin | |
if (lvalue.FData[Offset] and rvalue.FData[Offset]) <> lvalue.FData[Offset] then | |
begin | |
Result := False; | |
Exit; | |
end; | |
end; | |
Result := True; | |
end; | |
class operator TBarSet.GreaterThanOrEqual(const lvalue: TBarSet; const rvalue: TBarSet): Boolean; | |
var | |
Offset: Integer; | |
begin | |
for Offset := Low(lvalue.FData) to High(lvalue.FData) do | |
begin | |
if (lvalue.FData[Offset] and rvalue.FData[Offset]) <> rvalue.FData[Offset] then | |
begin | |
Result := False; | |
Exit; | |
end; | |
end; | |
Result := True; | |
end; | |
class operator TBarSet.Equal(const lvalue: TBarSet; const rvalue: TBarSet): Boolean; | |
var | |
Offset: Integer; | |
begin | |
for Offset := Low(lvalue.FData) to High(lvalue.FData) do | |
begin | |
if (lvalue.FData[Offset] xor rvalue.FData[Offset]) <> 0 then | |
begin | |
Result := False; | |
Exit; | |
end; | |
end; | |
Result := True; | |
end; | |
class operator TBarSet.NotEqual(const lvalue: TBarSet; const rvalue: TBarSet): Boolean; | |
begin | |
Result := not (lvalue = rvalue); | |
end; | |
class operator TBarSet.In(lvalue: TBar; const rvalue: TBarSet): Boolean; | |
begin | |
Result := rvalue.&In(lvalue); | |
end; | |
function TBarSet.GetEnumerator: TEnumerator; | |
begin | |
Result := TEnumerator.Create(@Self); | |
end; | |
class procedure TBarSet.CalcOffsets(Value: TBar; var AOffset: Integer; var ABit: Byte); | |
var | |
RelPos: Integer; | |
begin | |
RelPos := Ord(Value) - Ord(Low(TBar)); | |
AOffset := RelPos div BYTE_BIT; | |
ABit := 1 shl (RelPos mod BYTE_BIT); | |
end; | |
{ TEnumerator } | |
constructor TBarSet.TEnumerator.Create(Container: PBarSet); | |
begin | |
inherited Create; | |
FIndex := Ord(Low(TBar)) - 1; | |
FContainer := Container; | |
end; | |
function TBarSet.TEnumerator.MoveNext: Boolean; | |
begin | |
while (FIndex < Ord(High(TBar))) do | |
begin | |
FIndex := FIndex + 1; | |
if FContainer^.&In(TBar(FIndex)) = True then | |
begin | |
Result := True; | |
Exit; | |
end; | |
end; | |
Result := False; | |
end; | |
function TBarSet.TEnumerator.GetCurrent: TBar; | |
begin | |
Result := TBar(FIndex); | |
end; | |
end. |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment