blob: ad852accaa8398f03f5c7766f4de6b48c6c64766 [file] [log] [blame]
(*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*)
unit Thrift.Collections;
interface
uses
SysUtils, Generics.Collections, Generics.Defaults, Thrift.Utils;
type
{$IF CompilerVersion < 21.0}
TArray<T> = array of T;
{$IFEND}
IThriftContainer = interface( ISupportsToString)
['{E05C0F9D-A4F5-491D-AADA-C926B4BDB6E4}']
end;
IThriftDictionary<TKey,TValue> = interface(IThriftContainer)
['{25EDD506-F9D1-4008-A40F-5940364B7E46}']
function GetEnumerator: TEnumerator<TPair<TKey,TValue>>;
function GetKeys: TDictionary<TKey,TValue>.TKeyCollection;
function GetValues: TDictionary<TKey,TValue>.TValueCollection;
function GetItem(const Key: TKey): TValue;
procedure SetItem(const Key: TKey; const Value: TValue);
function GetCount: Integer;
procedure Add(const Key: TKey; const Value: TValue);
procedure Remove(const Key: TKey);
{$IF CompilerVersion >= 21.0}
function ExtractPair(const Key: TKey): TPair<TKey,TValue>;
{$IFEND}
procedure Clear;
procedure TrimExcess;
function TryGetValue(const Key: TKey; out Value: TValue): Boolean;
procedure AddOrSetValue(const Key: TKey; const Value: TValue);
function ContainsKey(const Key: TKey): Boolean;
function ContainsValue(const Value: TValue): Boolean;
function ToArray: TArray<TPair<TKey,TValue>>;
property Items[const Key: TKey]: TValue read GetItem write SetItem; default;
property Count: Integer read GetCount;
property Keys: TDictionary<TKey,TValue>.TKeyCollection read GetKeys;
property Values: TDictionary<TKey,TValue>.TValueCollection read GetValues;
end;
TThriftDictionaryImpl<TKey,TValue> = class( TInterfacedObject, IThriftDictionary<TKey,TValue>, IThriftContainer, ISupportsToString)
strict private
FDictionaly : TDictionary<TKey,TValue>;
strict protected
function GetEnumerator: TEnumerator<TPair<TKey,TValue>>;
function GetKeys: TDictionary<TKey,TValue>.TKeyCollection;
function GetValues: TDictionary<TKey,TValue>.TValueCollection;
function GetItem(const Key: TKey): TValue;
procedure SetItem(const Key: TKey; const Value: TValue);
function GetCount: Integer;
procedure Add(const Key: TKey; const Value: TValue);
procedure Remove(const Key: TKey);
{$IF CompilerVersion >= 21.0}
function ExtractPair(const Key: TKey): TPair<TKey,TValue>;
{$IFEND}
procedure Clear;
procedure TrimExcess;
function TryGetValue(const Key: TKey; out Value: TValue): Boolean;
procedure AddOrSetValue(const Key: TKey; const Value: TValue);
function ContainsKey(const Key: TKey): Boolean;
function ContainsValue(const Value: TValue): Boolean;
function ToArray: TArray<TPair<TKey,TValue>>;
property Items[const Key: TKey]: TValue read GetItem write SetItem; default;
property Count: Integer read GetCount;
property Keys: TDictionary<TKey,TValue>.TKeyCollection read GetKeys;
property Values: TDictionary<TKey,TValue>.TValueCollection read GetValues;
public
constructor Create(ACapacity: Integer = 0);
destructor Destroy; override;
function ToString : string; override;
end;
IThriftList<T> = interface(IThriftContainer)
['{29BEEE31-9CB4-401B-AA04-5148A75F473B}']
function GetEnumerator: TEnumerator<T>;
function GetCapacity: Integer;
procedure SetCapacity(Value: Integer);
function GetCount: Integer;
procedure SetCount(Value: Integer);
function GetItem(Index: Integer): T;
procedure SetItem(Index: Integer; const Value: T);
function Add(const Value: T): Integer;
procedure AddRange(const Values: array of T); overload;
procedure AddRange(const Collection: IEnumerable<T>); overload;
procedure AddRange(Collection: TEnumerable<T>); overload;
procedure Insert(Index: Integer; const Value: T);
procedure InsertRange(Index: Integer; const Values: array of T); overload;
procedure InsertRange(Index: Integer; const Collection: IEnumerable<T>); overload;
procedure InsertRange(Index: Integer; const Collection: TEnumerable<T>); overload;
function Remove(const Value: T): Integer;
procedure Delete(Index: Integer);
procedure DeleteRange(AIndex, ACount: Integer);
function Extract(const Value: T): T;
{$IF CompilerVersion >= 21.0}
procedure Exchange(Index1, Index2: Integer);
procedure Move(CurIndex, NewIndex: Integer);
function First: T;
function Last: T;
{$IFEND}
procedure Clear;
function Contains(const Value: T): Boolean;
function IndexOf(const Value: T): Integer;
function LastIndexOf(const Value: T): Integer;
procedure Reverse;
procedure Sort; overload;
procedure Sort(const AComparer: IComparer<T>); overload;
function BinarySearch(const Item: T; out Index: Integer): Boolean; overload;
function BinarySearch(const Item: T; out Index: Integer; const AComparer: IComparer<T>): Boolean; overload;
procedure TrimExcess;
function ToArray: TArray<T>;
property Capacity: Integer read GetCapacity write SetCapacity;
property Count: Integer read GetCount write SetCount;
property Items[Index: Integer]: T read GetItem write SetItem; default;
end;
TThriftListImpl<T> = class( TInterfacedObject, IThriftList<T>, IThriftContainer, ISupportsToString)
strict private
FList : TList<T>;
strict protected
function GetEnumerator: TEnumerator<T>;
function GetCapacity: Integer;
procedure SetCapacity(Value: Integer);
function GetCount: Integer;
procedure SetCount(Value: Integer);
function GetItem(Index: Integer): T;
procedure SetItem(Index: Integer; const Value: T);
function Add(const Value: T): Integer;
procedure AddRange(const Values: array of T); overload;
procedure AddRange(const Collection: IEnumerable<T>); overload;
procedure AddRange(Collection: TEnumerable<T>); overload;
procedure Insert(Index: Integer; const Value: T);
procedure InsertRange(Index: Integer; const Values: array of T); overload;
procedure InsertRange(Index: Integer; const Collection: IEnumerable<T>); overload;
procedure InsertRange(Index: Integer; const Collection: TEnumerable<T>); overload;
function Remove(const Value: T): Integer;
procedure Delete(Index: Integer);
procedure DeleteRange(AIndex, ACount: Integer);
function Extract(const Value: T): T;
{$IF CompilerVersion >= 21.0}
procedure Exchange(Index1, Index2: Integer);
procedure Move(CurIndex, NewIndex: Integer);
function First: T;
function Last: T;
{$IFEND}
procedure Clear;
function Contains(const Value: T): Boolean;
function IndexOf(const Value: T): Integer;
function LastIndexOf(const Value: T): Integer;
procedure Reverse;
procedure Sort; overload;
procedure Sort(const AComparer: IComparer<T>); overload;
function BinarySearch(const Item: T; out Index: Integer): Boolean; overload;
function BinarySearch(const Item: T; out Index: Integer; const AComparer: IComparer<T>): Boolean; overload;
procedure TrimExcess;
function ToArray: TArray<T>;
property Capacity: Integer read GetCapacity write SetCapacity;
property Count: Integer read GetCount write SetCount;
property Items[Index: Integer]: T read GetItem write SetItem; default;
public
constructor Create;
destructor Destroy; override;
function ToString : string; override;
end;
IHashSet<TValue> = interface(IThriftContainer)
['{0923A3B5-D4D4-48A8-91AD-40238E2EAD66}']
function GetEnumerator: TEnumerator<TValue>;
function GetIsReadOnly: Boolean;
function GetCount: Integer;
property Count: Integer read GetCount;
property IsReadOnly: Boolean read GetIsReadOnly;
procedure Add( const item: TValue);
procedure Clear;
function Contains( const item: TValue): Boolean;
procedure CopyTo(var A: TArray<TValue>; arrayIndex: Integer);
function Remove( const item: TValue ): Boolean;
end;
THashSetImpl<TValue> = class( TInterfacedObject, IHashSet<TValue>, IThriftContainer, ISupportsToString)
strict private
FDictionary : IThriftDictionary<TValue,Integer>;
FIsReadOnly: Boolean;
strict protected
function GetEnumerator: TEnumerator<TValue>;
function GetIsReadOnly: Boolean;
function GetCount: Integer;
property Count: Integer read GetCount;
property IsReadOnly: Boolean read FIsReadOnly;
procedure Add( const item: TValue);
procedure Clear;
function Contains( const item: TValue): Boolean;
procedure CopyTo(var A: TArray<TValue>; arrayIndex: Integer);
function Remove( const item: TValue ): Boolean;
public
constructor Create;
function ToString : string; override;
end;
implementation
{ THashSetImpl<TValue> }
procedure THashSetImpl<TValue>.Add( const item: TValue);
begin
if not FDictionary.ContainsKey(item) then
begin
FDictionary.Add( item, 0);
end;
end;
procedure THashSetImpl<TValue>.Clear;
begin
FDictionary.Clear;
end;
function THashSetImpl<TValue>.Contains( const item: TValue): Boolean;
begin
Result := FDictionary.ContainsKey(item);
end;
procedure THashSetImpl<TValue>.CopyTo(var A: TArray<TValue>; arrayIndex: Integer);
var
i : Integer;
Enumlator : TEnumerator<TValue>;
begin
Enumlator := GetEnumerator;
while Enumlator.MoveNext do
begin
A[arrayIndex] := Enumlator.Current;
Inc(arrayIndex);
end;
end;
constructor THashSetImpl<TValue>.Create;
begin
inherited;
FDictionary := TThriftDictionaryImpl<TValue,Integer>.Create;
end;
function THashSetImpl<TValue>.GetCount: Integer;
begin
Result := FDictionary.Count;
end;
function THashSetImpl<TValue>.GetEnumerator: TEnumerator<TValue>;
begin
Result := FDictionary.Keys.GetEnumerator;
end;
function THashSetImpl<TValue>.GetIsReadOnly: Boolean;
begin
Result := FIsReadOnly;
end;
function THashSetImpl<TValue>.Remove( const item: TValue): Boolean;
begin
Result := False;
if FDictionary.ContainsKey( item ) then
begin
FDictionary.Remove( item );
Result := not FDictionary.ContainsKey( item );
end;
end;
function THashSetImpl<TValue>.ToString : string;
var elm : TValue;
sb : TThriftStringBuilder;
first : Boolean;
begin
sb := TThriftStringBuilder.Create('{');
try
first := TRUE;
for elm in FDictionary.Keys do begin
if first
then first := FALSE
else sb.Append(', ');
sb.Append( StringUtils<TValue>.ToString(elm));
end;
sb.Append('}');
Result := sb.ToString;
finally
sb.Free;
end;
end;
{ TThriftDictionaryImpl<TKey, TValue> }
procedure TThriftDictionaryImpl<TKey, TValue>.Add(const Key: TKey;
const Value: TValue);
begin
FDictionaly.Add( Key, Value);
end;
procedure TThriftDictionaryImpl<TKey, TValue>.AddOrSetValue(const Key: TKey;
const Value: TValue);
begin
FDictionaly.AddOrSetValue( Key, Value);
end;
procedure TThriftDictionaryImpl<TKey, TValue>.Clear;
begin
FDictionaly.Clear;
end;
function TThriftDictionaryImpl<TKey, TValue>.ContainsKey(
const Key: TKey): Boolean;
begin
Result := FDictionaly.ContainsKey( Key );
end;
function TThriftDictionaryImpl<TKey, TValue>.ContainsValue(
const Value: TValue): Boolean;
begin
Result := FDictionaly.ContainsValue( Value );
end;
constructor TThriftDictionaryImpl<TKey, TValue>.Create(ACapacity: Integer);
begin
inherited Create;
FDictionaly := TDictionary<TKey,TValue>.Create( ACapacity );
end;
destructor TThriftDictionaryImpl<TKey, TValue>.Destroy;
begin
FDictionaly.Free;
inherited;
end;
{$IF CompilerVersion >= 21.0}
function TThriftDictionaryImpl<TKey, TValue>.ExtractPair( const Key: TKey): TPair<TKey, TValue>;
begin
Result := FDictionaly.ExtractPair( Key);
end;
{$IFEND}
function TThriftDictionaryImpl<TKey, TValue>.GetCount: Integer;
begin
Result := FDictionaly.Count;
end;
function TThriftDictionaryImpl<TKey, TValue>.GetEnumerator: TEnumerator<TPair<TKey, TValue>>;
begin
Result := FDictionaly.GetEnumerator;
end;
function TThriftDictionaryImpl<TKey, TValue>.GetItem(const Key: TKey): TValue;
begin
Result := FDictionaly.Items[Key];
end;
function TThriftDictionaryImpl<TKey, TValue>.GetKeys: TDictionary<TKey, TValue>.TKeyCollection;
begin
Result := FDictionaly.Keys;
end;
function TThriftDictionaryImpl<TKey, TValue>.GetValues: TDictionary<TKey, TValue>.TValueCollection;
begin
Result := FDictionaly.Values;
end;
procedure TThriftDictionaryImpl<TKey, TValue>.Remove(const Key: TKey);
begin
FDictionaly.Remove( Key );
end;
procedure TThriftDictionaryImpl<TKey, TValue>.SetItem(const Key: TKey;
const Value: TValue);
begin
FDictionaly.AddOrSetValue( Key, Value);
end;
function TThriftDictionaryImpl<TKey, TValue>.ToArray: TArray<TPair<TKey, TValue>>;
{$IF CompilerVersion < 22.0}
var
x : TPair<TKey, TValue>;
i : Integer;
{$IFEND}
begin
{$IF CompilerVersion < 22.0}
SetLength(Result, Count);
i := 0;
for x in FDictionaly do
begin
Result[i] := x;
Inc( i );
end;
{$ELSE}
Result := FDictionaly.ToArray;
{$IFEND}
end;
function TThriftDictionaryImpl<TKey, TValue>.ToString : string;
var pair : TPair<TKey, TValue>;
sb : TThriftStringBuilder;
first : Boolean;
begin
sb := TThriftStringBuilder.Create('{');
try
first := TRUE;
for pair in FDictionaly do begin
if first
then first := FALSE
else sb.Append(', ');
sb.Append( '(');
sb.Append( StringUtils<TKey>.ToString(pair.Key));
sb.Append(' => ');
sb.Append( StringUtils<TValue>.ToString(pair.Value));
sb.Append(')');
end;
sb.Append('}');
Result := sb.ToString;
finally
sb.Free;
end;
end;
procedure TThriftDictionaryImpl<TKey, TValue>.TrimExcess;
begin
FDictionaly.TrimExcess;
end;
function TThriftDictionaryImpl<TKey, TValue>.TryGetValue(const Key: TKey;
out Value: TValue): Boolean;
begin
Result := FDictionaly.TryGetValue( Key, Value);
end;
{ TThriftListImpl<T> }
function TThriftListImpl<T>.Add(const Value: T): Integer;
begin
Result := FList.Add( Value );
end;
procedure TThriftListImpl<T>.AddRange(Collection: TEnumerable<T>);
begin
FList.AddRange( Collection );
end;
procedure TThriftListImpl<T>.AddRange(const Collection: IEnumerable<T>);
begin
FList.AddRange( Collection );
end;
procedure TThriftListImpl<T>.AddRange(const Values: array of T);
begin
FList.AddRange( Values );
end;
function TThriftListImpl<T>.BinarySearch(const Item: T;
out Index: Integer): Boolean;
begin
Result := FList.BinarySearch( Item, Index);
end;
function TThriftListImpl<T>.BinarySearch(const Item: T; out Index: Integer;
const AComparer: IComparer<T>): Boolean;
begin
Result := FList.BinarySearch( Item, Index, AComparer);
end;
procedure TThriftListImpl<T>.Clear;
begin
FList.Clear;
end;
function TThriftListImpl<T>.Contains(const Value: T): Boolean;
begin
Result := FList.Contains( Value );
end;
constructor TThriftListImpl<T>.Create;
begin
inherited;
FList := TList<T>.Create;
end;
procedure TThriftListImpl<T>.Delete(Index: Integer);
begin
FList.Delete( Index )
end;
procedure TThriftListImpl<T>.DeleteRange(AIndex, ACount: Integer);
begin
FList.DeleteRange( AIndex, ACount)
end;
destructor TThriftListImpl<T>.Destroy;
begin
FList.Free;
inherited;
end;
{$IF CompilerVersion >= 21.0}
procedure TThriftListImpl<T>.Exchange(Index1, Index2: Integer);
begin
FList.Exchange( Index1, Index2 )
end;
{$IFEND}
function TThriftListImpl<T>.Extract(const Value: T): T;
begin
Result := FList.Extract( Value )
end;
{$IF CompilerVersion >= 21.0}
function TThriftListImpl<T>.First: T;
begin
Result := FList.First;
end;
{$IFEND}
function TThriftListImpl<T>.GetCapacity: Integer;
begin
Result := FList.Capacity;
end;
function TThriftListImpl<T>.GetCount: Integer;
begin
Result := FList.Count;
end;
function TThriftListImpl<T>.GetEnumerator: TEnumerator<T>;
begin
Result := FList.GetEnumerator;
end;
function TThriftListImpl<T>.GetItem(Index: Integer): T;
begin
Result := FList[Index];
end;
function TThriftListImpl<T>.IndexOf(const Value: T): Integer;
begin
Result := FList.IndexOf( Value );
end;
procedure TThriftListImpl<T>.Insert(Index: Integer; const Value: T);
begin
FList.Insert( Index, Value);
end;
procedure TThriftListImpl<T>.InsertRange(Index: Integer;
const Collection: TEnumerable<T>);
begin
FList.InsertRange( Index, Collection );
end;
procedure TThriftListImpl<T>.InsertRange(Index: Integer;
const Values: array of T);
begin
FList.InsertRange( Index, Values);
end;
procedure TThriftListImpl<T>.InsertRange(Index: Integer;
const Collection: IEnumerable<T>);
begin
FList.InsertRange( Index, Collection );
end;
{$IF CompilerVersion >= 21.0}
function TThriftListImpl<T>.Last: T;
begin
Result := FList.Last;
end;
{$IFEND}
function TThriftListImpl<T>.LastIndexOf(const Value: T): Integer;
begin
Result := FList.LastIndexOf( Value );
end;
{$IF CompilerVersion >= 21.0}
procedure TThriftListImpl<T>.Move(CurIndex, NewIndex: Integer);
begin
FList.Move( CurIndex, NewIndex);
end;
{$IFEND}
function TThriftListImpl<T>.Remove(const Value: T): Integer;
begin
Result := FList.Remove( Value );
end;
procedure TThriftListImpl<T>.Reverse;
begin
FList.Reverse;
end;
procedure TThriftListImpl<T>.SetCapacity(Value: Integer);
begin
FList.Capacity := Value;
end;
procedure TThriftListImpl<T>.SetCount(Value: Integer);
begin
FList.Count := Value;
end;
procedure TThriftListImpl<T>.SetItem(Index: Integer; const Value: T);
begin
FList[Index] := Value;
end;
procedure TThriftListImpl<T>.Sort;
begin
FList.Sort;
end;
procedure TThriftListImpl<T>.Sort(const AComparer: IComparer<T>);
begin
FList.Sort(AComparer);
end;
function TThriftListImpl<T>.ToArray: TArray<T>;
{$IF CompilerVersion < 22.0}
var
x : T;
i : Integer;
{$IFEND}
begin
{$IF CompilerVersion < 22.0}
SetLength(Result, Count);
i := 0;
for x in FList do
begin
Result[i] := x;
Inc( i );
end;
{$ELSE}
Result := FList.ToArray;
{$IFEND}
end;
function TThriftListImpl<T>.ToString : string;
var elm : T;
sb : TThriftStringBuilder;
first : Boolean;
begin
sb := TThriftStringBuilder.Create('{');
try
first := TRUE;
for elm in FList do begin
if first
then first := FALSE
else sb.Append(', ');
sb.Append( StringUtils<T>.ToString(elm));
end;
sb.Append('}');
Result := sb.ToString;
finally
sb.Free;
end;
end;
procedure TThriftListImpl<T>.TrimExcess;
begin
FList.TrimExcess;
end;
end.