(* * 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 Generics.Collections, Generics.Defaults, Thrift.Utils; type {$IF CompilerVersion < 21.0} TArray = array of T; {$IFEND} IThriftContainer = interface ['{93DEF5A0-D162-461A-AB22-5B4EE0734050}'] function ToString: string; end; IThriftDictionary = interface(IThriftContainer) ['{25EDD506-F9D1-4008-A40F-5940364B7E46}'] function GetEnumerator: TEnumerator>; function GetKeys: TDictionary.TKeyCollection; function GetValues: TDictionary.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; {$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>; property Items[const Key: TKey]: TValue read GetItem write SetItem; default; property Count: Integer read GetCount; property Keys: TDictionary.TKeyCollection read GetKeys; property Values: TDictionary.TValueCollection read GetValues; end; TThriftDictionaryImpl = class( TInterfacedObject, IThriftDictionary) private FDictionaly : TDictionary; protected function GetEnumerator: TEnumerator>; function GetKeys: TDictionary.TKeyCollection; function GetValues: TDictionary.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; {$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>; property Items[const Key: TKey]: TValue read GetItem write SetItem; default; property Count: Integer read GetCount; property Keys: TDictionary.TKeyCollection read GetKeys; property Values: TDictionary.TValueCollection read GetValues; public constructor Create(ACapacity: Integer = 0); destructor Destroy; override; end; IThriftList = interface(IThriftContainer) ['{29BEEE31-9CB4-401B-AA04-5148A75F473B}'] function GetEnumerator: TEnumerator; 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); overload; procedure AddRange(Collection: TEnumerable); 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); overload; procedure InsertRange(Index: Integer; const Collection: TEnumerable); 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); overload; function BinarySearch(const Item: T; out Index: Integer): Boolean; overload; function BinarySearch(const Item: T; out Index: Integer; const AComparer: IComparer): Boolean; overload; procedure TrimExcess; function ToArray: TArray; 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 = class( TInterfacedObject, IThriftList) private FList : TList; protected function GetEnumerator: TEnumerator; 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); overload; procedure AddRange(Collection: TEnumerable); 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); overload; procedure InsertRange(Index: Integer; const Collection: TEnumerable); 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); overload; function BinarySearch(const Item: T; out Index: Integer): Boolean; overload; function BinarySearch(const Item: T; out Index: Integer; const AComparer: IComparer): Boolean; overload; procedure TrimExcess; function ToArray: TArray; 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; end; IHashSet = interface(IThriftContainer) ['{0923A3B5-D4D4-48A8-91AD-40238E2EAD66}'] function GetEnumerator: TEnumerator; 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; arrayIndex: Integer); function Remove( const item: TValue ): Boolean; end; THashSetImpl = class( TInterfacedObject, IHashSet) private FDictionary : IThriftDictionary; FIsReadOnly: Boolean; protected function GetEnumerator: TEnumerator; 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; arrayIndex: Integer); function Remove( const item: TValue ): Boolean; public constructor Create; end; implementation { THashSetImpl } procedure THashSetImpl.Add( const item: TValue); begin if not FDictionary.ContainsKey(item) then begin FDictionary.Add( item, 0); end; end; procedure THashSetImpl.Clear; begin FDictionary.Clear; end; function THashSetImpl.Contains( const item: TValue): Boolean; begin Result := FDictionary.ContainsKey(item); end; procedure THashSetImpl.CopyTo(var A: TArray; arrayIndex: Integer); var i : Integer; Enumlator : TEnumerator; begin Enumlator := GetEnumerator; while Enumlator.MoveNext do begin A[arrayIndex] := Enumlator.Current; Inc(arrayIndex); end; end; constructor THashSetImpl.Create; begin inherited; FDictionary := TThriftDictionaryImpl.Create; end; function THashSetImpl.GetCount: Integer; begin Result := FDictionary.Count; end; function THashSetImpl.GetEnumerator: TEnumerator; begin Result := FDictionary.Keys.GetEnumerator; end; function THashSetImpl.GetIsReadOnly: Boolean; begin Result := FIsReadOnly; end; function THashSetImpl.Remove( const item: TValue): Boolean; begin Result := False; if FDictionary.ContainsKey( item ) then begin FDictionary.Remove( item ); Result := not FDictionary.ContainsKey( item ); end; end; { TThriftDictionaryImpl } procedure TThriftDictionaryImpl.Add(const Key: TKey; const Value: TValue); begin FDictionaly.Add( Key, Value); end; procedure TThriftDictionaryImpl.AddOrSetValue(const Key: TKey; const Value: TValue); begin FDictionaly.AddOrSetValue( Key, Value); end; procedure TThriftDictionaryImpl.Clear; begin FDictionaly.Clear; end; function TThriftDictionaryImpl.ContainsKey( const Key: TKey): Boolean; begin Result := FDictionaly.ContainsKey( Key ); end; function TThriftDictionaryImpl.ContainsValue( const Value: TValue): Boolean; begin Result := FDictionaly.ContainsValue( Value ); end; constructor TThriftDictionaryImpl.Create(ACapacity: Integer); begin inherited Create; FDictionaly := TDictionary.Create( ACapacity ); end; destructor TThriftDictionaryImpl.Destroy; begin FDictionaly.Free; inherited; end; {$IF CompilerVersion >= 21.0} function TThriftDictionaryImpl.ExtractPair( const Key: TKey): TPair; begin Result := FDictionaly.ExtractPair( Key); end; {$IFEND} function TThriftDictionaryImpl.GetCount: Integer; begin Result := FDictionaly.Count; end; function TThriftDictionaryImpl.GetEnumerator: TEnumerator>; begin Result := FDictionaly.GetEnumerator; end; function TThriftDictionaryImpl.GetItem(const Key: TKey): TValue; begin Result := FDictionaly.Items[Key]; end; function TThriftDictionaryImpl.GetKeys: TDictionary.TKeyCollection; begin Result := FDictionaly.Keys; end; function TThriftDictionaryImpl.GetValues: TDictionary.TValueCollection; begin Result := FDictionaly.Values; end; procedure TThriftDictionaryImpl.Remove(const Key: TKey); begin FDictionaly.Remove( Key ); end; procedure TThriftDictionaryImpl.SetItem(const Key: TKey; const Value: TValue); begin FDictionaly.AddOrSetValue( Key, Value); end; function TThriftDictionaryImpl.ToArray: TArray>; {$IF CompilerVersion < 22.0} var x : TPair; 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; procedure TThriftDictionaryImpl.TrimExcess; begin FDictionaly.TrimExcess; end; function TThriftDictionaryImpl.TryGetValue(const Key: TKey; out Value: TValue): Boolean; begin Result := FDictionaly.TryGetValue( Key, Value); end; { TThriftListImpl } function TThriftListImpl.Add(const Value: T): Integer; begin Result := FList.Add( Value ); end; procedure TThriftListImpl.AddRange(Collection: TEnumerable); begin FList.AddRange( Collection ); end; procedure TThriftListImpl.AddRange(const Collection: IEnumerable); begin FList.AddRange( Collection ); end; procedure TThriftListImpl.AddRange(const Values: array of T); begin FList.AddRange( Values ); end; function TThriftListImpl.BinarySearch(const Item: T; out Index: Integer): Boolean; begin Result := FList.BinarySearch( Item, Index); end; function TThriftListImpl.BinarySearch(const Item: T; out Index: Integer; const AComparer: IComparer): Boolean; begin Result := FList.BinarySearch( Item, Index, AComparer); end; procedure TThriftListImpl.Clear; begin FList.Clear; end; function TThriftListImpl.Contains(const Value: T): Boolean; begin Result := FList.Contains( Value ); end; constructor TThriftListImpl.Create; begin inherited; FList := TList.Create; end; procedure TThriftListImpl.Delete(Index: Integer); begin FList.Delete( Index ) end; procedure TThriftListImpl.DeleteRange(AIndex, ACount: Integer); begin FList.DeleteRange( AIndex, ACount) end; destructor TThriftListImpl.Destroy; begin FList.Free; inherited; end; {$IF CompilerVersion >= 21.0} procedure TThriftListImpl.Exchange(Index1, Index2: Integer); begin FList.Exchange( Index1, Index2 ) end; {$IFEND} function TThriftListImpl.Extract(const Value: T): T; begin Result := FList.Extract( Value ) end; {$IF CompilerVersion >= 21.0} function TThriftListImpl.First: T; begin Result := FList.First; end; {$IFEND} function TThriftListImpl.GetCapacity: Integer; begin Result := FList.Capacity; end; function TThriftListImpl.GetCount: Integer; begin Result := FList.Count; end; function TThriftListImpl.GetEnumerator: TEnumerator; begin Result := FList.GetEnumerator; end; function TThriftListImpl.GetItem(Index: Integer): T; begin Result := FList[Index]; end; function TThriftListImpl.IndexOf(const Value: T): Integer; begin Result := FList.IndexOf( Value ); end; procedure TThriftListImpl.Insert(Index: Integer; const Value: T); begin FList.Insert( Index, Value); end; procedure TThriftListImpl.InsertRange(Index: Integer; const Collection: TEnumerable); begin FList.InsertRange( Index, Collection ); end; procedure TThriftListImpl.InsertRange(Index: Integer; const Values: array of T); begin FList.InsertRange( Index, Values); end; procedure TThriftListImpl.InsertRange(Index: Integer; const Collection: IEnumerable); begin FList.InsertRange( Index, Collection ); end; {$IF CompilerVersion >= 21.0} function TThriftListImpl.Last: T; begin Result := FList.Last; end; {$IFEND} function TThriftListImpl.LastIndexOf(const Value: T): Integer; begin Result := FList.LastIndexOf( Value ); end; {$IF CompilerVersion >= 21.0} procedure TThriftListImpl.Move(CurIndex, NewIndex: Integer); begin FList.Move( CurIndex, NewIndex); end; {$IFEND} function TThriftListImpl.Remove(const Value: T): Integer; begin Result := FList.Remove( Value ); end; procedure TThriftListImpl.Reverse; begin FList.Reverse; end; procedure TThriftListImpl.SetCapacity(Value: Integer); begin FList.Capacity := Value; end; procedure TThriftListImpl.SetCount(Value: Integer); begin FList.Count := Value; end; procedure TThriftListImpl.SetItem(Index: Integer; const Value: T); begin FList[Index] := Value; end; procedure TThriftListImpl.Sort; begin FList.Sort; end; procedure TThriftListImpl.Sort(const AComparer: IComparer); begin FList.Sort; end; function TThriftListImpl.ToArray: TArray; {$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; procedure TThriftListImpl.TrimExcess; begin FList.TrimExcess; end; end.