unit U_SCSLists; interface Uses Windows, Classes, SysUtils, ComCtrls, Controls, Contnrs, idGlobal, DateUtils, RTLConsts, U_Common_Classes; resourcestring SInvalidFieldOffset = 'Field offset (%d) differ from first'; type TPtrList = array of Pointer; PPtrList = ^TPtrList; TRapList = class(TMyObject) private FList: PPointerList; FCount: Integer; FCapacity: Integer; FSortFieldOffset: Integer; protected function Get(Index: Integer): Pointer; procedure Grow; virtual; procedure Put(Index: Integer; Item: Pointer); //procedure Notify(Ptr: Pointer; Action: TListNotification); virtual; procedure SetCapacity(NewCapacity: Integer); procedure SetCount(NewCount: Integer); public constructor Create; destructor Destroy; override; procedure Add(Item: Pointer); procedure AddList(AList: TRapList); procedure Clear; virtual; procedure ClearOwnObjects; procedure Delete(Index: Integer); procedure DeleteRange(Index, Len: Integer); class procedure Error(const Msg: string; Data: Integer); overload; virtual; class procedure Error(Msg: PResStringRec; Data: Integer); overload; procedure Exchange(Index1, Index2: Integer); //function Expand: TRapList; function Extract(Item: Pointer): Pointer; function First: Pointer; function IndexOf(Item: Pointer): Integer; procedure Insert(Index: Integer; Item: Pointer); function Last: Pointer; procedure Move(CurIndex, NewIndex: Integer); function Remove(Item: Pointer): Integer; procedure Pack; procedure Sort(Compare: TListSortCompare); procedure Assign(ListA: TRapList; AOperator: TListAssignOp = laCopy; ListB: TRapList = nil); property Capacity: Integer read FCapacity write SetCapacity; property Count: Integer read FCount write SetCount; property Items[Index: Integer]: Pointer read Get write Put; default; property List: PPointerList read FList; //property List: TPtrList read FList; end; TRapObjectList = class(TMyObject) private FItems: TRapList; FSortFieldOffset: Integer; FOwnsObjects: Boolean; FAllowDuplicates: Boolean; function FindObject(AValue: Pointer; AObject: TObject; AFieldAdress: Pointer; var Index: Integer): Boolean; function Get(Index: Integer): Pointer; function GetCount: Integer; public constructor Create(AOwnsObjects: Boolean=false; AAllowDuplicates: Boolean=true); overload; destructor Destroy; override; procedure Clear; function GetObject(AFieldValue: Integer): TObject; function Insert(AObject: TObject; AFieldAdress: Pointer): Integer; function Remove(AFieldValue: Integer): Integer; property Count: Integer read GetCount; property Items[Index: Integer]: Pointer read Get; default; property List: TRapList read FItems; end; TRapRecordList = class(TRapObjectList) private FOwnsObjects: Boolean; public constructor Create(AOwnsObjects: Boolean); overload; destructor Destroy; override; end; TIntList = class(TMyObject) protected FItems: TList; function GetCount: Integer; function GetItem(Index: Integer): Integer; procedure SetItem(Index: Integer; AInt: Integer); public constructor Create; overload; destructor Destroy; override; function Add(AInt: Integer): Integer; procedure Assign(ListA: TIntList; AOperator: TListAssignOp = laCopy; ListB: TIntList = nil); procedure Clear; procedure Delete(AIndex: Integer); procedure Fill(AVal: Integer; AToIndex: Integer=-1); procedure Move(CurrIndex, NewIndex: Integer); function Remove(AInt: Integer): Integer; procedure RemoveDublicates; function RemoveItems(AItems: TIntList): Integer; function IndexOf(AInt: Integer): Integer; procedure Insert(Index: Integer; AInt: Integer); property Count: Integer read GetCount; property Items[index: integer]: Integer read GetItem write SetItem; default; property List: TList read FItems; end; TIDStringList = class(TMyObject) protected FIDs: TIntList; FStrings: TStringList; function GetCount: Integer; public property Count: Integer read GetCount; property IDs: TIntList read FIDs write FIDs; property Strings: TStringList read FStrings write FStrings; constructor Create; overload; // Tolik 16/01/2019 -- //destructor Destroy; overload; destructor Destroy; override; // function Add(AID: Integer; AString: String): Integer; overload; function Add(AID: Integer; AString: String; AObject: TObject): Integer; overload; procedure Assign(ListA: TIDStringList; AOperator: TListAssignOp = laCopy; ListB: TIDStringList = nil); procedure Clear; procedure Delete(AIndex: Integer); function GetIDByIndex(AIndex: Integer): Integer; function GetIDByString(AString: String): Integer; function GetStringByID(AID: Integer): String; function GetStringByIndex(AIndex: Integer): String; function IndexOfByID(AID: Integer): Integer; function IndexOfByString(AString: String): Integer; function RemoveByID(AID: Integer): Integer; function RemoveByString(AString: String): Integer; end; TBasicArrayList = class(TMyObject) protected FCount: Integer; FItemsCount: Integer; procedure Assign(ASrc: TBasicArrayList); public property Count: Integer read FCount; constructor Create; destructor Destroy; override; procedure Clear; virtual; end; TConnectedComponsInfo = record ID: Integer; ComponWholeID: Integer; IDConnectObject: Integer; IDConnectCompon: Integer; IDSideCompon: Integer; TypeConnect: Integer; end; PConnectedComponsInfo = ^TConnectedComponsInfo; TConnectedComponsList = class(TBasicArrayList) protected FItems: array of TConnectedComponsInfo; function GetItem(Index: Integer): TConnectedComponsInfo; procedure SetItem(Index: Integer; AConnectedComponsInfo: TConnectedComponsInfo); public constructor Create; overload; destructor Destroy; override; function Add(AConnectedComponsInfo: TConnectedComponsInfo): Integer; procedure Assign(AConnectedComponsList: TConnectedComponsList); procedure Clear; override; procedure Delete(Index: Integer); function GetConnectedComponsInfoByWholeID(AWholeID: Integer): TList; function GetConnectedComponsInfoByWholeIDAndType(AWholeID, AType: Integer): TConnectedComponsInfo; procedure GetConnectedComponsInfosByWholeID(AWholeID: Integer; var aResFrom, aResTo: TConnectedComponsInfo); procedure InsertRecord(AComponWholeID, AIDConnectedObject, AIDConnectedCompon, AIDSideCompon, ATypeConnect: Integer); procedure RemoveByWholeID(AWholeID: Integer); //function IndexOf(AConnectedComponsInfo: PConnectedComponsInfo): Integer; //procedure Insert(Index: Integer; AConnectedComponsInfo: PConnectedComponsInfo); property Items[index: integer]: TConnectedComponsInfo read GetItem write SetItem; default; end; TJoinComponsInfo = record IDCompon1: Integer; IDCompon2: Integer; DBKind1: Integer; DBKind2: Integer; end; TJoinComponsInfoList = class(TBasicArrayList) protected FItems: array of TJoinComponsInfo; function GetItem(Index: Integer): TJoinComponsInfo; procedure SetItem(Index: Integer; AJoinComponsInfo: TJoinComponsInfo); public constructor Create; overload; destructor Destroy; override; function Add: Integer; function AddRecord(AIDCompon1, AIDCompon2, ADBKind1, ADBKind2: Integer): Integer; procedure Clear; function FindJoinComponsInfo(AIDCompon1, AIDCompon2, ADBKind1, ADBKind2: Integer): Boolean; property Items[index: integer]: TJoinComponsInfo read GetItem write SetItem; default; end; TLog = class(TMyObject) private FDirectory: String; FFilePrefix: String; FFileExtension: String; FCurrData: TDate; FCurrFileIndex: Integer; FCurrLog: TStringList; FCurrLogSize: Integer; FExistsFiles: TStringList; FImmediateSave: Boolean; function CheckDirectoryExists: Boolean; procedure DefineExistsFiles; procedure SaveStringToFile(AText, AFileName: String); public procedure AddStringToLog(AText: String); constructor Create(ADirectory, AFilePrefix, AFileExtension: String; AImmediateSave: Boolean); destructor Destroy; override; end; TStreamList = class(TMyObject) private FOwnObjects: Boolean; FStreams: TObjectList; FStreamsCodes: TIntList; FFileCode: Integer; //FFileCodeStr: string; FFileCodeStr: AnsiString; FISStrCode: Boolean; FEOF: Boolean; FFileStream: TFileStream; FReadedStreamCode: Integer; procedure AfterCreate(AOwnObjects: Boolean); procedure CheckIsEnd; public property OwnObjects: Boolean read FOwnObjects write FOwnObjects; property ReadedStreamCode: Integer read FReadedStreamCode; property Streams: TObjectList read FStreams {write FStreams}; property StreamsCodes: TIntList read FStreamsCodes {write FStreamsCodes}; property EOF: Boolean read FEOF; property FileCode: Integer read FFileCode write FFileCode; //property FileCodeStr: string read FFileCodeStr write FFileCodeStr; property FileCodeStr: AnsiString read FFileCodeStr write FFileCodeStr; procedure Add(AStream: TStream; AStreamCode: Integer); procedure Clear; constructor Create(AFileCode: Integer; AOwnObjects: Boolean); overload; constructor Create(AFileCode: string; AOwnObjects: Boolean); overload; destructor Destroy; override; function GetStreamByCode(ACode: Integer): TStream; function LoadFromFile(AFileName: String): Boolean; procedure ReadFileEnd; function ReadFileHeader(AFileName: String; AFileCodeSizeToCheck: Integer): Boolean; function ReadStreamFromFile(AStream: TStream; AAddToList: Boolean): Boolean; procedure RotateList; procedure SaveToFile(AFileName: String); end; TStringObject = class(TObject) FString: String; end; TStringsHash = class protected FStrings: TStringList; public property Strings: TStringList read FStrings write FStrings; constructor Create; destructor Destroy; override; function GetVal(const aKey: String; var aVal: String): Boolean; function SetVal(const aKey, aVal: String): Integer; end; procedure QuickSortPointerList(SortList: PPointerList; L, R: Integer; SCompare: TListSortCompare); procedure DeleteArrayItem(var X; const Index, ItemSize: Integer) ; function FindInSortedIntList(AValue: Integer; AList: TIntList; var Index: Integer): Boolean; function FindInSortedList(AValue: Pointer; AList: TList; var Index: Integer): Boolean; function FindInSortedRapList(AValue: Pointer; AList: TRapList; var Index: Integer): Boolean; function FindObjectInSortedRapList(AObject: TObject; AFieldAdress: Pointer; AList: TRapList; var Index: Integer): Boolean; function InsertObjectToSortetRapList(AObject: TObject; AFieldAdress: Pointer; AList: TRapList): Integer; function InsertValueToSortetList(AValue: Pointer; AList: TList): Integer; function InsertValueToSortetRapList(AValue: Pointer; AList: TRapList): Integer; function InsertValueToSortetIntList(AValue: Integer; AList: TIntList): Integer; function IntListToList(AIntList: TIntList): TList; function IntListToSorted(AIntList: TIntList): TIntList; function GetValueIndexFromSortedRapList(AValue: Pointer; AList: TRapList): Integer; function GetValueIndexFromSortedIntList(AValue: Integer; AList: TIntList): Integer; procedure LoadIntListFromStream(AStream: TStream; AIntList: TIntList); procedure SaveIntListToStream(AStream: TStream; AIntList: TIntList); function AddStrObjToStrings(AStrings: TStrings; const AKeyStr, AStrObj: String): Integer; function GetObjFromStringsByStr(AStrings: TStrings; const AStr: String): TObject; function GetStrFromStringsByKey(AStrings: TStrings; const AKey: String): String; function GetStrFromStringsByIdx(AStrings: TStrings; AIdx: Integer): String; procedure FreeStringsObjects(AStrings: TStrings; AClear: Boolean); procedure SetStrToStringsByIdx(AStrings: TStrings; AIdx: Integer; const aVal: String); procedure SortListByItemField(AList: TList; AItem, AFieldAdress: Pointer); //procedure SortListByObjItemField(AList: TList; AItem: TObject; AFieldAdress: Pointer); procedure RotateTObjectList(AList: TObjectList); procedure RotateTList(AList: TList); implementation Uses U_BaseCommon; { TRapList } constructor TRapList.Create; begin inherited; //FAddBy := 10; FSortFieldOffset := -1; end; destructor TRapList.Destroy; begin Clear; inherited; end; procedure TRapList.Add(Item: Pointer); //var //Delta: Integer; begin {Result := FCount; if Result = FCapacity then Grow; FList^[Result] := Item; Inc(FCount); if Item <> nil then Notify(Item, lnAdded);} //if FCount = FCapacity then // Grow; //FList^[FCount] := Item; //Inc(FCount); if FCapacity <= FCount then begin //Capacity := FCount + FAddBy; {if FCapacity > 64 then Delta := FCapacity div 4 else if FCapacity > 8 then Delta := 16 else Delta := 4; Capacity := FCount + Delta;} Grow; end; FList^[FCount] := Item; FCount := FCount + 1; //Inc(FCount); end; procedure TRapList.AddList(AList: TRapList); var NewCount: Integer; Delta: Integer; i: Integer; begin NewCount := FCount + AList.FCount; if FCapacity <= NewCount then begin if FCapacity > 64 then Delta := FCapacity div 4 else if FCapacity > 8 then Delta := 16 else Delta := 4; Capacity := NewCount + Delta; end; for i := 0 to AList.FCount - 1 do FList^[FCount + i] := AList.FList^[i]; FCount := NewCount; end; procedure TRapList.Clear; var i, j: Integer; begin //Tolik if FCount > 0 then begin while FCount > 0 do Delete(0); end; // SetCount(0); SetCapacity(0); end; procedure TRapList.ClearOwnObjects; var i: Integer; begin for i := 0 to FCount - 1 do begin if FList^[i] <> nil then TObject(FList^[i]).Free; end; Clear; end; procedure TRapList.Delete(Index: Integer); //var //Temp: Pointer; begin {if (Index < 0) or (Index >= FCount) then Error(@SListIndexError, Index); Temp := Items[Index]; Dec(FCount); if Index < FCount then System.Move(FList^[Index + 1], FList^[Index], (FCount - Index) * SizeOf(Pointer)); if Temp <> nil then Notify(Temp, lnDeleted);} //DeleteRange(Index, 1); if (Index < 0) or (Index >= FCount) then Error(@SListIndexError, Index); FCount := FCount - 1; //if Index < FCount - 1 then //Tolik //if Index < FCount then if Index <= FCount then // (а то хер оно удалит нулевой элемент при количестве 1) // begin //FCount := FCount - 1; System.Move(FList^[Index + 1], FList^[Index], (FCount - Index) * SizeOf(Pointer)); end; end; procedure TRapList.DeleteRange(Index, Len: Integer); begin if Len <= 0 then Exit; if (Index < 0) or (Index >= FCount) then Error(@SListIndexError, Index); if Index + Len > FCount then Len := FCount - Index; //Если удаляется хвост, то память не уменьшаем if (Index + Len) < FCount then System.Move(FList^[ Index + Len ], FList^[ Index ], Sizeof( Pointer ) * (FCount - Index - Len) ); FCount := FCount - Len; //Dec( fCount, Len ); end; class procedure TRapList.Error(const Msg: string; Data: Integer); function ReturnAddr: Pointer; asm MOV EAX,[EBP+4] end; begin raise EListError.CreateFmt(Msg, [Data]) at ReturnAddr; end; class procedure TRapList.Error(Msg: PResStringRec; Data: Integer); begin TRapList.Error(LoadResString(Msg), Data); end; procedure TRapList.Exchange(Index1, Index2: Integer); var Item: Pointer; begin if (Index1 < 0) or (Index1 >= FCount) then Error(@SListIndexError, Index1); if (Index2 < 0) or (Index2 >= FCount) then Error(@SListIndexError, Index2); Item := FList^[Index1]; FList^[Index1] := FList^[Index2]; FList^[Index2] := Item; end; { function TRapList.Expand: TRapList; begin if FCount = FCapacity then Grow; Result := Self; end;} function TRapList.First: Pointer; begin Result := Get(0); end; function TRapList.Get(Index: Integer): Pointer; begin if (Index < 0) or (Index >= FCount) then Error(@SListIndexError, Index); Result := FList^[Index]; end; procedure TRapList.Grow; var Delta: Integer; begin if FCapacity > 64 then Delta := FCapacity div 4 else if FCapacity > 8 then Delta := 16 else Delta := 4; SetCapacity(FCapacity + Delta); end; function TRapList.IndexOf(Item: Pointer): Integer; var i: Integer; MiddleIndex: Integer; LastIndex: Integer; begin //Result := 0; //while (Result < FCount) and (FList^[Result] <> Item) do // Inc(Result); //if Result = FCount then // Result := -1; Result := -1; for i := 0 to FCount - 1 do if FList^[i] = Item then begin Result := i; Break; //// BREAK //// end; { Result := -1; MiddleIndex := FCount div 2; if (FCount mod 2) <> 0 then MiddleIndex := MiddleIndex + 1; LastIndex := FCount - 1; for i := 0 to MiddleIndex - 1 do if FList^[i] = Item then begin Result := i; Break; //// BREAK //// end else if FList^[LastIndex - i] = Item then begin Result := i; Break; //// BREAK //// end; } end; procedure TRapList.Insert(Index: Integer; Item: Pointer); begin {if (Index < 0) or (Index > FCount) then Error(@SListIndexError, Index); if FCount = FCapacity then Grow; if Index < FCount then System.Move(FList^[Index], FList^[Index + 1], (FCount - Index) * SizeOf(Pointer)); FList^[Index] := Item; Inc(FCount); if Item <> nil then Notify(Item, lnAdded);} if (Index < 0) or (Index > FCount) then Error(@SListIndexError, Index); if FCount = FCapacity then Grow; if Index < FCount then System.Move(FList^[Index], FList^[Index + 1], (FCount - Index) * SizeOf(Pointer)); FList^[Index] := Item; FCount := FCount + 1; end; function TRapList.Last: Pointer; begin Result := Get(FCount - 1); end; procedure TRapList.Move(CurIndex, NewIndex: Integer); var Item: Pointer; begin if CurIndex <> NewIndex then begin if (NewIndex < 0) or (NewIndex >= FCount) then Error(@SListIndexError, NewIndex); Item := Get(CurIndex); FList^[CurIndex] := nil; Delete(CurIndex); Insert(NewIndex, nil); FList^[NewIndex] := Item; end; end; procedure TRapList.Put(Index: Integer; Item: Pointer); //var //Temp: Pointer; begin {if (Index < 0) or (Index >= FCount) then Error(@SListIndexError, Index); if Item <> FList^[Index] then begin Temp := FList^[Index]; FList^[Index] := Item; if Temp <> nil then Notify(Temp, lnDeleted); if Item <> nil then Notify(Item, lnAdded); end;} if (Index < 0) or (Index >= FCount) then Error(@SListIndexError, Index); FList^[Index] := Item; end; function TRapList.Remove(Item: Pointer): Integer; begin Result := IndexOf(Item); if Result >= 0 then Delete(Result); end; procedure TRapList.Pack; var I: Integer; begin for I := FCount - 1 downto 0 do if Items[I] = nil then Delete(I); end; procedure TRapList.SetCapacity(NewCapacity: Integer); begin {if (NewCapacity < FCount) or (NewCapacity > MaxListSize) then Error(@SListCapacityError, NewCapacity); if NewCapacity <> FCapacity then begin ReallocMem(FList, NewCapacity * SizeOf(Pointer)); FCapacity := NewCapacity; end;} if NewCapacity < FCount then NewCapacity := FCount; if NewCapacity <> FCapacity then begin ReallocMem(FList, NewCapacity * SizeOf(Pointer)); FCapacity := NewCapacity; end; end; procedure TRapList.SetCount(NewCount: Integer); //var //I: Integer; begin { if (NewCount < 0) or (NewCount > MaxListSize) then Error(@SListCountError, NewCount); if NewCount > FCapacity then SetCapacity(NewCount); if NewCount > FCount then FillChar(FList^[FCount], (NewCount - FCount) * SizeOf(Pointer), 0) else for I := FCount - 1 downto NewCount do Delete(I); FCount := NewCount;} if NewCount >= FCount then Exit; FCount := NewCount; end; procedure QuickSortPointerList(SortList: PPointerList; L, R: Integer; SCompare: TListSortCompare); var I, J: Integer; P, T: Pointer; begin repeat I := L; J := R; P := SortList^[(L + R) shr 1]; repeat while SCompare(SortList^[I], P) < 0 do Inc(I); while SCompare(SortList^[J], P) > 0 do Dec(J); if I <= J then begin T := SortList^[I]; SortList^[I] := SortList^[J]; SortList^[J] := T; Inc(I); Dec(J); end; until I > J; if L < J then QuickSortPointerList(SortList, L, J, SCompare); L := I; until I >= R; end; procedure TRapList.Sort(Compare: TListSortCompare); begin if (FList <> nil) and (Count > 0) then QuickSortPointerList(FList, 0, Count - 1, Compare); end; function TRapList.Extract(Item: Pointer): Pointer; var I: Integer; begin {Result := nil; I := IndexOf(Item); if I >= 0 then begin Result := Item; FList^[I] := nil; Delete(I); Notify(Result, lnExtracted); end; } Result := nil; I := IndexOf(Item); if I >= 0 then begin Result := Item; FList^[I] := nil; Delete(I); end; end; //procedure TRapList.Notify(Ptr: Pointer; Action: TListNotification); //begin //end; procedure TRapList.Assign(ListA: TRapList; AOperator: TListAssignOp; ListB: TRapList); var I: Integer; LTemp, LSource: TRapList; begin // ListB given? if ListB <> nil then begin LSource := ListB; Assign(ListA); end else LSource := ListA; // on with the show case AOperator of // 12345, 346 = 346 : only those in the new list laCopy: begin Clear; Capacity := LSource.Capacity; for I := 0 to LSource.Count - 1 do Add(LSource[I]); end; // 12345, 346 = 34 : intersection of the two lists laAnd: for I := Count - 1 downto 0 do if LSource.IndexOf(Items[I]) = -1 then Delete(I); // 12345, 346 = 123456 : union of the two lists laOr: for I := 0 to LSource.Count - 1 do if IndexOf(LSource[I]) = -1 then Add(LSource[I]); // 12345, 346 = 1256 : only those not in both lists laXor: begin LTemp := TRapList.Create; // Temp holder of 4 byte values try LTemp.Capacity := LSource.Count; for I := 0 to LSource.Count - 1 do if IndexOf(LSource[I]) = -1 then LTemp.Add(LSource[I]); for I := Count - 1 downto 0 do if LSource.IndexOf(Items[I]) <> -1 then Delete(I); I := Count + LTemp.Count; if Capacity < I then Capacity := I; for I := 0 to LTemp.Count - 1 do Add(LTemp[I]); finally LTemp.Free; end; end; // 12345, 346 = 125 : only those unique to source laSrcUnique: for I := Count - 1 downto 0 do if LSource.IndexOf(Items[I]) <> -1 then Delete(I); // 12345, 346 = 6 : only those unique to dest laDestUnique: begin LTemp := TRapList.Create; try LTemp.Capacity := LSource.Count; for I := LSource.Count - 1 downto 0 do if IndexOf(LSource[I]) = -1 then LTemp.Add(LSource[I]); Assign(LTemp); finally LTemp.Free; end; end; end; end; { TRapObjectList } constructor TRapObjectList.Create(AOwnsObjects: Boolean=false; AAllowDuplicates: Boolean=true); begin inherited create;// Tolik 12/12/2019 -- FItems := TRapList.Create; //FSortFieldOffset := -1; FOwnsObjects := AOwnsObjects; FAllowDuplicates := AAllowDuplicates; Clear; end; destructor TRapObjectList.Destroy; begin FreeAndNil(FItems); inherited; end; procedure TRapObjectList.Clear; var i: Integer; begin if FOwnsObjects then for i := FItems.Count - 1 downto 0 do TObject(FItems[i]).Free; FItems.Clear; FSortFieldOffset := -1; end; function TRapObjectList.FindObject(AValue: Pointer; AObject: TObject; AFieldAdress: Pointer; var Index: Integer): Boolean; var L, H, I, C: Integer; FieldOffset: Integer; ValueParam: Integer; ValueI: Integer; begin Result := False; ValueParam := 0; if AValue = nil then begin // Ищем смещение поля FieldOffset := Integer(Integer(AFieldAdress) - Integer(AObject)); if FSortFieldOffset = -1 then FSortFieldOffset := FieldOffset else if FSortFieldOffset <> FieldOffset then FItems.Error(@SInvalidFieldOffset, FieldOffset); ValueParam := Integer(Pointer(AFieldAdress)^); end else begin FieldOffset := FSortFieldOffset; ValueParam := Integer(AValue^); end; L := 0; H := FItems.FCount - 1; while L <= H do begin I := (L + H) shr 1; ValueI := Integer(Pointer(Integer(FItems.FList^[I]) + FieldOffset)^); //C := CompareStrings(FList^[I].FString, S); if ValueI < ValueParam then //if C < 0 then L := I + 1 else begin H := I - 1; //if C = 0 then if ValueI = ValueParam then begin Result := True; L := I; Break; //// BREAK //// end; end; end; Index := L; end; function TRapObjectList.Get(Index: Integer): Pointer; begin Result := FItems.Get(Index); end; function TRapObjectList.GetCount: Integer; begin Result := FItems.FCount; end; function TRapObjectList.GetObject(AFieldValue: Integer): TObject; var ObjectIndex: Integer; begin Result := nil; if FSortFieldOffset <> -1 then begin if FindObject(@AFieldValue, nil, nil, ObjectIndex) then if ObjectIndex <> -1 then Result := TObject(FItems[ObjectIndex]); end; end; function TRapObjectList.Insert(AObject: TObject; AFieldAdress: Pointer): Integer; var IndexToInsert: Integer; Finded: Boolean; begin Result := -1; IndexToInsert := 0; Finded := FindObject(nil, AObject, AFieldAdress, IndexToInsert); if Not Finded or FAllowDuplicates then begin FItems.Insert(IndexToInsert, TObject(AObject)); Result := IndexToInsert; end; end; function TRapObjectList.Remove(AFieldValue: Integer): Integer; var ObjectIndex: Integer; begin Result := -1; if FSortFieldOffset <> -1 then begin if FindObject(@AFieldValue, nil, nil, ObjectIndex) then if ObjectIndex <> -1 then begin Result := ObjectIndex; FItems.Delete(ObjectIndex); end; end; end; { TRapRecordList } constructor TRapRecordList.Create(AOwnsObjects: Boolean); begin inherited Create; end; destructor TRapRecordList.Destroy; var i: Integer; ptrToFree: Pointer; begin if FOwnsObjects then begin for i := 0 to FItems.Count - 1 do begin ptrToFree := FItems.List^[i]; if ptrToFree <> nil then FreeMem(ptrToFree); end; FItems.Clear; end; inherited; end; { TIntList } function TIntList.Add(AInt: Integer): Integer; begin Result := FItems.Add(Pointer(AInt)); //inherited Add(Pointer(AInt)); end; procedure TIntList.Assign(ListA: TIntList; AOperator: TListAssignOp = laCopy; ListB: TIntList = nil); var LAItems: TList; LBItems: TList; begin LAItems := nil; LBItems := nil; if Assigned(ListA) then LAItems := ListA.FItems; if Assigned(ListB) then LBItems := ListB.FItems; FItems.Assign(LAItems, AOperator, LBItems); end; procedure TIntList.Clear; begin FItems.Clear; end; procedure TIntList.Delete(AIndex: Integer); begin FItems.Delete(AIndex); end; procedure TIntList.Fill(AVal: Integer; AToIndex: Integer=-1); var i: Integer; AddCount: Integer; begin for i := 0 to FItems.Count - 1 do FItems[i] := Pointer(AVal); AddCount := AToIndex - (FItems.Count - 1); if AddCount > 0 then for i := 1 to AddCount do FItems.Add(Pointer(AVal)); end; procedure TIntList.Move(CurrIndex, NewIndex: Integer); begin FItems.Move(CurrIndex, NewIndex); end; constructor TIntList.Create; begin inherited Create; FItems := Tlist.Create; end; destructor TIntList.Destroy; begin FItems.Free; inherited; end; function TIntList.GetCount: Integer; begin Result := FItems.Count; end; function TIntList.GetItem(Index: Integer): Integer; begin Result := Integer(FItems[Index]); //Integer(inherited Items[Index]); end; function TIntList.IndexOf(AInt: Integer): Integer; var i: Integer; begin Result := -1; //Result := FItems.IndexOf(Pointer(AInt)); //inherited IndexOf(Pointer(AInt)); for i := 0 to FItems.Count - 1 do if Integer(FItems.List^[i]) = AInt then begin Result := i; Break; //// BREAK //// end; end; procedure TIntList.Insert(Index, AInt: Integer); begin FItems.Insert(Index, Pointer(AInt)); //inherited Insert(Index, Pointer(AInt)); end; function TIntList.Remove(AInt: Integer): Integer; begin Result := FItems.Remove(Pointer(AInt)); //inherited Remove(Pointer(AInt)); end; procedure TIntList.RemoveDublicates; var i, j: Integer; ValueI, ValueJ: Integer; begin i := 0; while i <= FItems.Count - 1 do begin ValueI := Integer(FItems[i]); j := i+1; while j <= FItems.Count - 1 do begin ValueJ := Integer(FItems[j]); if ValueJ = ValueI then FItems.Delete(j) else Inc(j); end; Inc(i); end; end; function TIntList.RemoveItems(AItems: TIntList): Integer; var i: Integer; begin for i := 0 to AItems.Count - 1 do Remove(AItems[i]); end; procedure TIntList.SetItem(Index, AInt: Integer); begin FItems.Items[Index] := Pointer(AInt); //inherited Items[Index] := Pointer(AInt); end; { TIDStringList } constructor TIDStringList.Create; begin inherited; FIDs := TIntList.Create; FStrings := TStringList.Create; end; destructor TIDStringList.Destroy; begin FreeAndNil(FIDs); FreeAndNil(FStrings); inherited; end; function TIDStringList.Add(AID: Integer; AString: String): Integer; begin Result := FIDs.Add(AID); FStrings.Add(AString); end; function TIDStringList.Add(AID: Integer; AString: String; AObject: TObject): Integer; begin Result := FIDs.Add(AID); FStrings.AddObject(AString, AObject); end; procedure TIDStringList.Assign(ListA: TIDStringList; AOperator: TListAssignOp = laCopy; ListB: TIDStringList = nil); begin if ListB <> nil then FIDs.Assign(ListA.FIDs, AOperator, ListB.FIDs) else FIDs.Assign(ListA.FIDs, AOperator, nil); FStrings.Assign(ListA.FStrings); end; procedure TIDStringList.Clear; begin FIDs.Clear; FStrings.Clear; end; procedure TIDStringList.Delete(AIndex: Integer); begin FIDs.Delete(AIndex); FStrings.Delete(AIndex); end; function TIDStringList.GetCount: Integer; begin Result := FIDs.Count; end; function TIDStringList.GetIDByIndex(AIndex: Integer): Integer; begin Result := FIDs[AIndex]; end; function TIDStringList.GetIDByString(AString: String): Integer; var Index: Integer; begin Result := -1; Index := FStrings.IndexOf(AString); if Index <> -1 then Result := FIDs.Items[Index]; end; function TIDStringList.GetStringByID(AID: Integer): String; var Index: Integer; begin Result := ''; Index := FIDs.IndexOf(AID); if Index <> -1 then Result := FStrings[Index]; end; function TIDStringList.GetStringByIndex(AIndex: Integer): String; begin Result := FStrings[AIndex]; end; function TIDStringList.IndexOfByID(AID: Integer): Integer; begin Result := FIDs.IndexOf(AID); end; function TIDStringList.IndexOfByString(AString: String): Integer; begin Result := FStrings.IndexOf(AString); end; function TIDStringList.RemoveByID(AID: Integer): Integer; var RemIndex: Integer; begin RemIndex := FIDs.Remove(AID); if RemIndex <> -1 then FStrings.Delete(RemIndex); Result := RemIndex; end; function TIDStringList.RemoveByString(AString: String): Integer; var RemIndex: Integer; begin RemIndex := FStrings.IndexOf(AString); if RemIndex <> -1 then begin FIDs.Delete(RemIndex); FStrings.Delete(RemIndex); end; Result := RemIndex; end; { TBasicArrayList } procedure TBasicArrayList.Assign(ASrc: TBasicArrayList); begin FCount := ASrc.FCount; FItemsCount := ASrc.FItemsCount; end; procedure TBasicArrayList.Clear; begin FCount := 0; FItemsCount := 0; end; constructor TBasicArrayList.Create; begin inherited Create; FCount := 0; FItemsCount := 0; end; destructor TBasicArrayList.Destroy; begin Clear; inherited; end; { TConnectedComponsList } function TConnectedComponsList.Add(AConnectedComponsInfo: TConnectedComponsInfo): Integer; begin //Result := inherited Add(AConnectedComponsInfo); Inc(FCount); if FCount > FItemsCount then begin FItemsCount := FItemsCount + 200; SetLength(FItems, FItemsCount); end; FItems[FCount - 1] := AConnectedComponsInfo; Result := FCount - 1; end; procedure TConnectedComponsList.Assign(AConnectedComponsList: TConnectedComponsList); begin inherited Assign(AConnectedComponsList); SetLength(FItems, Length(AConnectedComponsList.FItems)); FItems := AConnectedComponsList.FItems; //CopyMemory(@FItems, @AConnectedComponsList.FItems, Length(AConnectedComponsList.FItems)); end; procedure TConnectedComponsList.Clear; begin //Tolik SetLength(FItems,0); // inherited; end; procedure TConnectedComponsList.Delete(Index: Integer); var Len: Integer; begin if Index >= FCount then raise Exception.Create('Index out of bounds '+IntToStr(FCount - Index)); Len := High(FItems); if index < Len then begin if index < FCount - 1 then Move(FItems[Index+1], FItems[Index], (Len - Index)*SizeOf(FItems[Index])); end; Dec(FCount); if FItemsCount - FCount = 200 then begin FItemsCount := FItemsCount - 200; SetLength(FItems, FItemsCount); end; end; function TConnectedComponsList.GetConnectedComponsInfoByWholeID(AWholeID: Integer): TList; var i: Integer; ConnectedComponsInfo: TConnectedComponsInfo; ptrConnectedComponsInfo: PConnectedComponsInfo; begin Result := TList.Create; for i := 0 to Count - 1 do begin ConnectedComponsInfo := FItems[i]; if ConnectedComponsInfo.ComponWholeID = AWholeID then begin GetMem(ptrConnectedComponsInfo, SizeOf(TConnectedComponsInfo)); ptrConnectedComponsInfo^ := ConnectedComponsInfo; Result.Add(ptrConnectedComponsInfo); end; end; end; function TConnectedComponsList.GetConnectedComponsInfoByWholeIDAndType(AWholeID, AType: Integer): TConnectedComponsInfo; var i: Integer; ConnectedComponsInfo: TConnectedComponsInfo; begin ZeroMemory(@Result, SizeOf(TConnectedComponsInfo)); for i := 0 to FCount - 1 do begin ConnectedComponsInfo := FItems[i]; if (ConnectedComponsInfo.ComponWholeID = AWholeID) and (ConnectedComponsInfo.TypeConnect = AType) then begin Result := ConnectedComponsInfo; Break; ///// BREAK ///// end; end; end; procedure TConnectedComponsList.GetConnectedComponsInfosByWholeID(AWholeID: Integer; var aResFrom, aResTo: TConnectedComponsInfo); var i: Integer; ptrConnectedComponsInfo: PConnectedComponsInfo; RecCnt: SmallInt; begin ZeroMemory(@aResFrom, SizeOf(TConnectedComponsInfo)); ZeroMemory(@aResTo, SizeOf(TConnectedComponsInfo)); RecCnt := 0; for i := 0 to FCount - 1 do begin ptrConnectedComponsInfo := @FItems[i]; if ptrConnectedComponsInfo.ComponWholeID = AWholeID then begin if ptrConnectedComponsInfo.TypeConnect = tcoFrom then begin aResFrom := ptrConnectedComponsInfo^; Inc(RecCnt); end else if ptrConnectedComponsInfo.TypeConnect = tcoTo then begin aResTo := ptrConnectedComponsInfo^; Inc(RecCnt); end; if RecCnt = 2 then Break; ///// BREAK ///// end; end; end; constructor TConnectedComponsList.Create; begin //Tolik Clear; // inherited Create; end; destructor TConnectedComponsList.Destroy; begin Clear; inherited; end; function TConnectedComponsList.GetItem(Index: Integer): TConnectedComponsInfo; begin Result := FItems[Index]; //PConnectedComponsInfo(inherited Items[Index]); end; procedure TConnectedComponsList.RemoveByWholeID(AWholeID: Integer); var ConnectedComponsInfo: TConnectedComponsInfo; i: Integer; begin i := 0; while i <= FCount - 1 do begin ConnectedComponsInfo := Items[i]; if ConnectedComponsInfo.ComponWholeID = AWholeID then begin Delete(i); //Remove(ptrConnectedComponsInfo); //FreeMem(ptrConnectedComponsInfo); end else Inc(i); end; {ptrConnectedComponsInfo := GetConnectedComponsInfoByWholeIDAndType(AWholeID, tcoFrom); if ptrConnectedComponsInfo <> nil then begin Remove(ptrConnectedComponsInfo); FreeMem(ptrConnectedComponsInfo); end; ptrConnectedComponsInfo := GetConnectedComponsInfoByWholeIDAndType(AWholeID, tcoTo); if ptrConnectedComponsInfo <> nil then begin Remove(ptrConnectedComponsInfo); FreeMem(ptrConnectedComponsInfo); end;} end; procedure TConnectedComponsList.InsertRecord(AComponWholeID, AIDConnectedObject, AIDConnectedCompon, AIDSideCompon, ATypeConnect: Integer); var ConnectedComponsInfo: TConnectedComponsInfo; begin ZeroMemory(@ConnectedComponsInfo, SizeOf(TConnectedComponsInfo)); ConnectedComponsInfo.ID := 0; ConnectedComponsInfo.ComponWholeID := AComponWholeID; ConnectedComponsInfo.IDConnectObject := AIDConnectedObject; ConnectedComponsInfo.IDConnectCompon := AIDConnectedCompon; ConnectedComponsInfo.IDSideCompon := AIDSideCompon; ConnectedComponsInfo.TypeConnect := ATypeConnect; Add(ConnectedComponsInfo); end; procedure TConnectedComponsList.SetItem(Index: Integer; AConnectedComponsInfo: TConnectedComponsInfo); begin FItems[Index] := AConnectedComponsInfo; //inherited Items[Index] := AConnectedComponsInfo; end; { TJoinComponsInfoList } function TJoinComponsInfoList.Add: Integer; begin FCount := FCount + 1; if FCount > FItemsCount then begin FItemsCount := FItemsCount + 200; SetLength(FItems, FItemsCount); end; //FItems[FCount - 1] := AJoinComponsInfo; Result := FCount - 1; end; function TJoinComponsInfoList.AddRecord(AIDCompon1, AIDCompon2, ADBKind1, ADBKind2: Integer): Integer; //var //JoinComponsInfo: TJoinComponsInfo; begin {//11.03.2009 Result := -1; ZeroMemory(@JoinComponsInfo, SizeOf(TJoinComponsInfo)); JoinComponsInfo.IDCompon1 := AIDCompon1; JoinComponsInfo.IDCompon2 := AIDCompon2; JoinComponsInfo.DBKind1 := ADBKind1; JoinComponsInfo.DBKind2 := ADBKind2; Result := Add(JoinComponsInfo); } Result := Add; FItems[Result].IDCompon1 := AIDCompon1; FItems[Result].IDCompon2 := AIDCompon2; FItems[Result].DBKind1 := ADBKind1; FItems[Result].DBKind2 := ADBKind2; end; procedure TJoinComponsInfoList.Clear; begin SetLength(FItems, 0); inherited; end; constructor TJoinComponsInfoList.Create; begin //Tolik Clear; // inherited Create; end; destructor TJoinComponsInfoList.Destroy; begin // Tolik Clear; // inherited; end; function TJoinComponsInfoList.GetItem(Index: Integer): TJoinComponsInfo; begin Result := FItems[Index]; //PJoinComponsInfo(inherited Items[Index]); end; function TJoinComponsInfoList.FindJoinComponsInfo(AIDCompon1, AIDCompon2, ADBKind1, ADBKind2: Integer): Boolean; var i: Integer; JoinComponsInfo: TJoinComponsInfo; begin Result := false; for i := 0 to FCount - 1 do begin JoinComponsInfo := FItems[i]; if ((JoinComponsInfo.IDCompon1 = AIDCompon1) and (JoinComponsInfo.IDCompon2 = AIDCompon2) and (JoinComponsInfo.DBKind1 = ADBKind1) and (JoinComponsInfo.DBKind2 = ADBKind2)) or ((JoinComponsInfo.IDCompon1 = AIDCompon2) and (JoinComponsInfo.IDCompon2 = AIDCompon1) and (JoinComponsInfo.DBKind1 = ADBKind2) and (JoinComponsInfo.DBKind2 = ADBKind1)) then begin Result := true; Break; ///// BREAK ///// end; end; end; procedure TJoinComponsInfoList.SetItem(Index: Integer; AJoinComponsInfo: TJoinComponsInfo); begin Items[Index] := AJoinComponsInfo; end; { TLog } function TLog.CheckDirectoryExists: Boolean; begin Result := false; if Not DirectoryExists(FDirectory) then CreateDir(FDirectory); if DirectoryExists(FDirectory) then Result := true; end; procedure TLog.DefineExistsFiles; var SearchRec: TSearchRec; DirName: String; FileAttrs: Integer; begin DirName := FDirectory; if DirName[Length(DirName)] <> '\' then DirName := DirName + '\'; FileAttrs := faAnyFile + faHidden; if FindFirst(DirName + '*.*', FileAttrs, SearchRec) <> 0 then begin repeat if (SearchRec.Attr and FileAttrs) = SearchRec.Attr then if Pos(FFilePrefix, SearchRec.Name) = 1 then FExistsFiles.Add(SearchRec.Name); until FindNext(SearchRec) <> 0; FindClose(SearchRec); end; end; procedure TLog.SaveStringToFile(AText, AFileName: String); var FHandle: TextFile; begin if FileExists(AFileName) then Append(FHandle) else Rewrite(FHandle); try WriteLn(FHandle, AText); finally CloseFile(FHandle); end; end; procedure TLog.AddStringToLog(AText: String); var TextLength: Integer; FileName: String; NewData: TDate; begin TextLength := Length(AText); NewData := Date; if (FCurrData <> NewData) then begin FileName := FFilePrefix + '_'+ IntToStrF(YearOf(NewData), 4)+ IntToStrF(MonthOf(NewData), 2)+ IntToStrF(DayOf(NewData), 2)+'.'+FFileExtension; FCurrLogSize := 0; FCurrFileIndex := 0; end; if FileName = '' then if ((FCurrLogSize + TextLength) > 2048) then begin end; if FImmediateSave then begin end else begin end; end; constructor TLog.Create(ADirectory, AFilePrefix, AFileExtension: String; AImmediateSave: Boolean); begin inherited Create; FDirectory := ADirectory + '\'; FFilePrefix := AFilePrefix; FFileExtension := AFileExtension; FImmediateSave := AImmediateSave; FCurrData := Date; FCurrFileIndex := 0; FCurrLog := nil; FCurrLogSize := 0; if Not AImmediateSave then FCurrLog := TStringList.Create; FExistsFiles := TStringList.Create; if CheckDirectoryExists then DefineExistsFiles; end; destructor TLog.Destroy; begin if Assigned(FCurrLog) then FreeAndNil(FCurrLog); if Assigned(FExistsFiles) then FreeAndNil(FExistsFiles); inherited; end; function AddStrObjToStrings(AStrings: TStrings; const AKeyStr, AStrObj: String): Integer; var StringObject: TStringObject; begin Result := -1; StringObject := TStringObject.Create; StringObject.FString := AStrObj; Result := AStrings.AddObject(AKeyStr, StringObject); end; procedure DeleteArrayItem(var X; const Index, ItemSize: Integer); begin {if Index > High(X) then Exit; if Index < Low(X) then Exit; if Index = High(X) then begin SetLength(X, Length(X) - 1) ; Exit; end; Finalize(X[Index]) ; System.Move(X[Index +1], X[Index],(Length(X) - Index -1) * ItemSize + 1); SetLength(X, Length(X) - 1);} end; function FindInSortedIntList(AValue: Integer; AList: TIntList; var Index: Integer): Boolean; var L, H, I, C: Integer; begin Result := False; L := 0; H := AList.Count - 1; while L <= H do begin I := (L + H) shr 1; //C := CompareStrings(FList^[I].FString, S); if Integer(AList.List.List^[I]) < AValue then //if C < 0 then L := I + 1 else begin H := I - 1; //if C = 0 then if Integer(AList.List.List^[I]) = AValue then begin Result := True; L := I; Break; //// BREAK //// end; end; end; Index := L; end; function FindInSortedList(AValue: Pointer; AList: TList; var Index: Integer): Boolean; var L, H, I, C: Integer; begin Result := False; L := 0; H := AList.Count - 1; while L <= H do begin I := (L + H) shr 1; //C := CompareStrings(FList^[I].FString, S); if Integer(AList.List^[I]) < Integer(AValue) then //if C < 0 then L := I + 1 else begin H := I - 1; //if C = 0 then if Integer(AList.List^[I]) = Integer(AValue) then begin Result := True; L := I; Break; //// BREAK //// end; end; end; Index := L; end; function FindInSortedRapList(AValue: Pointer; AList: TRapList; var Index: Integer): Boolean; var L, H, I, C: Integer; begin Result := False; L := 0; H := AList.FCount - 1; while L <= H do begin I := (L + H) shr 1; //C := CompareStrings(FList^[I].FString, S); if LongInt(AList.FList^[I]) < LongInt(AValue) then //if C < 0 then L := I + 1 else begin H := I - 1; //if C = 0 then if LongInt(AList.FList^[I]) = LongInt(AValue) then begin Result := True; L := I; Break; //// BREAK //// end; end; end; Index := L; end; function FindObjectInSortedRapList(AObject: TObject; AFieldAdress: Pointer; AList: TRapList; var Index: Integer): Boolean; var L, H, I, C: Integer; FieldOffset: Integer; ValueParam: Integer; ValueI: Integer; begin Result := False; // Ищем смещение поля FieldOffset := Integer(Integer(AFieldAdress) - Integer(AObject)); if AList.FSortFieldOffset = -1 then AList.FSortFieldOffset := FieldOffset; ValueParam := Integer(Pointer(AFieldAdress)^); L := 0; H := AList.FCount - 1; while L <= H do begin I := (L + H) shr 1; ValueI := Integer(Pointer(Integer(AList.FList^[I]) + FieldOffset)^); //C := CompareStrings(FList^[I].FString, S); if ValueI < ValueParam then //if C < 0 then L := I + 1 else begin H := I - 1; //if C = 0 then if ValueI = ValueParam then begin Result := True; Break; //// BREAK //// end; end; end; Index := L; end; function InsertObjectToSortetRapList(AObject: TObject; AFieldAdress: Pointer; AList: TRapList): Integer; var IndexToInsert: Integer; begin Result := -1; IndexToInsert := 0; //FindInSortedRapList(AValue, AList, IndexToInsert); FindObjectInSortedRapList(AObject, AFieldAdress, AList, IndexToInsert); AList.Insert(IndexToInsert, TObject(AObject)); Result := IndexToInsert; end; function InsertValueToSortetList(AValue: Pointer; AList: TList): Integer; var IndexToInsert: Integer; begin FindInSortedList(AValue, AList, IndexToInsert); AList.Insert(IndexToInsert, Pointer(AValue)); Result := IndexToInsert; end; function InsertValueToSortetRapList(AValue: Pointer; AList: TRapList): Integer; var FirstIndex: Integer; LastIndex: Integer; MidleIndex: Integer; IndexToInsert: Integer; begin Result := -1; IndexToInsert := 0; {if Alist.Count > 0 then begin FirstIndex := 0; LastIndex := AList.Count - 1; while FirstIndex <= LastIndex do begin if LongInt(Alist.List^[LastIndex]) = LongInt(AValue) then begin IndexToInsert := LastIndex; Break; //// BREAK //// end else begin // Найти средний индекс MidleIndex := LastIndex; if LastIndex > FirstIndex then MidleIndex := FirstIndex + Trunc((LastIndex-FirstIndex)/2); // На всякий случай проверить, не вышел ли средний индекс за диапазон if (MidleIndex < FirstIndex) or (MidleIndex > LastIndex) then begin Break; //// BREAK //// end else if (LongInt(AList.List^[MidleIndex]) < LongInt(AVAlue)) and (LongInt(AVAlue) < LongInt(AList.List^[LastIndex])) then begin if FirstIndex = MidleIndex then FirstIndex := MidleIndex + 1 else FirstIndex := MidleIndex; IndexToInsert := MidleIndex + 1; end else begin LastIndex := MidleIndex; if LongInt(AList.List^[LastIndex]) < LongInt(AValue) then IndexToInsert := LastIndex + 1 else IndexToInsert := LastIndex; end; if FirstIndex = LastIndex then Break; //// BREAK //// end; end; end; } FindInSortedRapList(AValue, AList, IndexToInsert); AList.Insert(IndexToInsert, AValue); Result := IndexToInsert; end; function InsertValueToSortetIntList(AValue: Integer; AList: TIntList): Integer; var //FirstIndex: Integer; //LastIndex: Integer; //MidleIndex: Integer; IndexToInsert: Integer; begin Result := -1; IndexToInsert := 0; {if Alist.Count > 0 then begin FirstIndex := 0; LastIndex := AList.Count - 1; while FirstIndex <= LastIndex do begin if Alist[LastIndex] = AValue then begin IndexToInsert := LastIndex; Break; //// BREAK //// end else begin // Найти средний индекс if LastIndex > FirstIndex then begin MidleIndex := FirstIndex + Trunc((LastIndex-FirstIndex)/2); // На всякий случай проверить, не вышел ли средний индекс за диапазон if (MidleIndex < FirstIndex) or (MidleIndex > LastIndex) then begin Break; //// BREAK //// end else if AList[MidleIndex] < AVAlue then begin if FirstIndex = MidleIndex then FirstIndex := MidleIndex + 1 else FirstIndex := MidleIndex; end else begin LastIndex := MidleIndex; end; end else begin if AList[LastIndex] < AValue then IndexToInsert := LastIndex + 1 else IndexToInsert := LastIndex; Break; //// BREAK //// end; end; end; end;} {РАБОТАЕТ if Alist.Count > 0 then begin FirstIndex := 0; LastIndex := AList.Count - 1; while FirstIndex <= LastIndex do begin if Alist[LastIndex] = AValue then begin IndexToInsert := LastIndex; Break; //// BREAK //// end else begin // Найти средний индекс MidleIndex := LastIndex; if LastIndex > FirstIndex then MidleIndex := FirstIndex + Trunc((LastIndex-FirstIndex)/2); // На всякий случай проверить, не вышел ли средний индекс за диапазон if (MidleIndex < FirstIndex) or (MidleIndex > LastIndex) then begin Break; //// BREAK //// end else if (AList[MidleIndex] < AVAlue) and (AVAlue < AList[LastIndex]) then begin if FirstIndex = MidleIndex then FirstIndex := MidleIndex + 1 else FirstIndex := MidleIndex; IndexToInsert := MidleIndex + 1; end else begin LastIndex := MidleIndex; if AList[LastIndex] < AValue then IndexToInsert := LastIndex + 1 else IndexToInsert := LastIndex; end; if FirstIndex = LastIndex then Break; //// BREAK //// end; end; end;} FindInSortedIntList(AValue, AList, IndexToInsert); AList.FItems.Insert(IndexToInsert, Pointer(AValue)); Result := IndexToInsert; end; function IntListToList(AIntList: TIntList): TList; var i: Integer; ptrInt: ^Integer; begin Result := TList.Create; for i := 0 to AIntList.Count - 1 do begin GetMem(ptrInt, SizeOf(Integer)); ptrInt^ := AIntList[i]; Result.Add(ptrInt); end; end; function IntListToSorted(AIntList: TIntList): TIntList; var i: integer; begin Result := TIntList.Create; for i := 0 to AIntList.Count - 1 do InsertValueToSortetIntList(Integer(AIntList.List.List^[i]), Result); end; function GetObjFromStringsByStr(AStrings: TStrings; const AStr: String): TObject; var ObjIndex: Integer; begin Result := nil; ObjIndex := AStrings.IndexOf(AStr); if ObjIndex <> -1 then Result := AStrings.Objects[ObjIndex]; end; function GetValueIndexFromSortedRapList(AValue: Pointer; AList: TRapList): Integer; //var //FirstIndex: Integer; //LastIndex: Integer; //MidleIndex: Integer; begin Result := -1; {try if Alist.Count > 0 then begin FirstIndex := 0; LastIndex := AList.Count - 1; while FirstIndex <= LastIndex do begin if LongInt(Alist.List^[LastIndex]) = LongInt(AValue) then begin Result := LastIndex; Break; //// BREAK //// end else begin // Найти средний индекс if LastIndex > FirstIndex then begin MidleIndex := FirstIndex + Trunc((LastIndex-FirstIndex)/2); // На всякий случай проверить, не вышел ли средний индекс за диапазон if (MidleIndex < FirstIndex) or (MidleIndex > LastIndex) then begin Break; //// BREAK //// end else if LongInt(AList.List^[MidleIndex]) < LongInt(AVAlue) then begin if FirstIndex = MidleIndex then FirstIndex := MidleIndex + 1 else FirstIndex := MidleIndex; end else begin LastIndex := MidleIndex; end; end else Break; //// BREAK //// end; end; end; except on E: Exception do AddExceptionToLogEx('GetValueIndexFromSortedRapList', E.Message); end; } if Not FindInSortedRapList(AValue, AList, Result) then Result := -1; end; function GetValueIndexFromSortedIntList(AValue: Integer; AList: TIntList): Integer; //var //FirstIndex: Integer; //LastIndex: Integer; //MidleIndex: Integer; begin Result := -1; {if Alist.Count > 0 then begin FirstIndex := 0; LastIndex := AList.Count - 1; while FirstIndex <= LastIndex do begin if Alist[LastIndex] = AValue then begin Result := LastIndex; Break; //// BREAK //// end else begin // Найти средний индекс if LastIndex > FirstIndex then begin MidleIndex := FirstIndex + Trunc((LastIndex-FirstIndex)/2); // На всякий случай проверить, не вышел ли средний индекс за диапазон if (MidleIndex < FirstIndex) or (MidleIndex > LastIndex) then begin Break; //// BREAK //// end else if AList[MidleIndex] < AVAlue then begin if FirstIndex = MidleIndex then FirstIndex := MidleIndex + 1 else FirstIndex := MidleIndex; end else begin LastIndex := MidleIndex; end; end else Break; //// BREAK //// end; end; end; } if Not FindInSortedIntList(AValue, AList, Result) then Result := -1; end; procedure LoadIntListFromStream(AStream: TStream; AIntList: TIntList); var StreamSize: Integer; StreamPos: Integer; CurrValue: Integer; begin AIntList.Clear; StreamSize := AStream.Size; StreamPos := AStream.Position; while StreamPos < StreamSize do begin AStream.ReadBuffer(CurrValue, SizeOf(Integer)); AIntList.Add(CurrValue); StreamPos := AStream.Position; end; end; procedure SaveIntListToStream(AStream: TStream; AIntList: TIntList); var i: Integer; CurrValue: Integer; begin for i := 0 to AIntList.Count - 1 do begin CurrValue := AIntList[i]; AStream.WriteBuffer(CurrValue, SizeOf(Integer)); end; end; { TStreamList } procedure TStreamList.Add(AStream: TStream; AStreamCode: Integer); begin FStreams.Add(AStream); FStreamsCodes.Add(AStreamCode); end; procedure TStreamList.AfterCreate(AOwnObjects: Boolean); begin FOwnObjects := AOwnObjects; FStreams := TObjectList.Create(FOwnObjects); FStreamsCodes := TIntList.Create; FFileStream := nil; Clear; end; procedure TStreamList.CheckIsEnd; begin if FFileStream.Position >= FFileStream.Size then ReadFileEnd; end; procedure TStreamList.Clear; begin FStreams.Clear; FStreamsCodes.Clear; FFileCode := 0; FFileCodeStr := ''; end; constructor TStreamList.Create(AFileCode: Integer; AOwnObjects: Boolean); begin inherited create; AfterCreate(AOwnObjects); FFileCode := AFileCode; FISStrCode := false; end; constructor TStreamList.Create(AFileCode: string; AOwnObjects: Boolean); begin inherited create; AfterCreate(AOwnObjects); FFileCodeStr := AFileCode; FISStrCode := true; end; destructor TStreamList.Destroy; begin Clear; FreeAndNil(FStreams); FreeAndNil(FStreamsCodes); inherited; end; function TStreamList.GetStreamByCode(ACode: Integer): TStream; var StreamIndex: Integer; i: Integer; begin Result := nil; StreamIndex := -1; for i := 0 to FStreamsCodes.FItems.Count - 1 do if Integer(FStreamsCodes.FItems.List^[i]) = ACode then begin StreamIndex := i; Break; //// BREAK //// end; if StreamIndex <> -1 then Result := TStream(FStreams[StreamIndex]); end; function TStreamList.LoadFromFile(AFileName: String): Boolean; var CurrStreamCode: Integer; CurrStreamSize: Integer; CurrStream: TMemoryStream; begin Result := false; if FileExists(AFileName) then begin if ReadFileHeader(AFileName, 0) then begin //*** Читать блоки while Not FEOF do begin CurrStream := TMemoryStream.Create; ReadStreamFromFile(CurrStream, true); end; Result := true; end; {try //*** Читать блоки while FFileStream.Position < FileStream.Size do begin FFileStream.ReadBuffer(CurrStreamCode, SizeOf(Integer)); FFileStream.ReadBuffer(CurrStreamSize, SizeOf(Integer)); CurrStream := TMemoryStream.Create; CurrStream.CopyFrom(FFileStream, CurrStreamSize); CurrStream.Position := 0; Add(CurrStream, CurrStreamCode); end; Result := true; finally FreeAndNil(FFileStream); end;} end; end; procedure TStreamList.ReadFileEnd; begin FEOF := true; if FFileStream <> nil then FreeAndNil(FFileStream); end; function TStreamList.ReadFileHeader(AFileName: String; AFileCodeSizeToCheck: Integer): Boolean; var StrSize: Integer; FirstBlockPos: Int64; begin Result := false; if FileExists(AFileName) then begin Clear; FEOF := false; if FFileStream <> nil then FreeAndNil(FFileStream); FFileStream := SafeOpenFileStream(AFileName, fmOpenRead, 'TStreamList.ReadFileHeader'); //TFileStream.Create(AFileName, fmOpenRead); if FFileStream <> nil then begin Result := true; FFileStream.Position := 0; //*** Читать код файла if Not FISStrCode then begin FFileStream.ReadBuffer(FFileCode, SizeOf(Integer)); end else begin FFileStream.ReadBuffer(StrSize, SizeOf(Integer)); // проверяем размер сигнатуры if (AFileCodeSizeToCheck <> 0) and (AFileCodeSizeToCheck <> StrSize) then begin Result := false; FEOF := true; FreeAndNil(FFileStream); end else begin SetLength(FFileCodeStr, StrSize); //FFileStream.ReadBuffer(pchar(FFileCodeStr)^, StrSize); FFileStream.ReadBuffer(pAnsiChar(FFileCodeStr)^, StrSize); end end; if Result then begin //*** Читать позицию для чтения первого блока FFileStream.ReadBuffer(FirstBlockPos, SizeOf(Int64)); FFileStream.Seek(FirstBlockPos, soFromBeginning); CheckIsEnd; end; end; end; end; function TStreamList.ReadStreamFromFile(AStream: TStream; AAddToList: Boolean): Boolean; var CurrStreamCode: Integer; CurrStreamSize: Integer; begin Result := Not FEOF; if Result then begin FFileStream.ReadBuffer(CurrStreamCode, SizeOf(Integer)); FFileStream.ReadBuffer(CurrStreamSize, SizeOf(Integer)); AStream.CopyFrom(FFileStream, CurrStreamSize); AStream.Position := 0; if AAddToList then Add(AStream, CurrStreamCode); FReadedStreamCode := CurrStreamCode; CheckIsEnd; end; end; procedure TStreamList.RotateList; var i: Integer; TmpCode: Integer; TmpStream: TObject; ItemsCount: Integer; IndexAtEnd: Integer; SavedOwnsObjects: Boolean; // Tolik 28/08/2019 -- //OldTick, CurrTick: Cardinal; OldTick, CurrTick: DWord; // begin OldTick := GetTickCount; if FStreams.Count = FStreamsCodes.Count then begin SavedOwnsObjects := FStreams.OwnsObjects; FStreams.OwnsObjects := false; try ItemsCount := FStreams.Count; for i := 0 to (ItemsCount div 2) - 1 do begin TmpCode := FStreamsCodes[i]; TmpStream := FStreams[i]; IndexAtEnd := ItemsCount - i - 1; FStreamsCodes[i] := FStreamsCodes[IndexAtEnd]; FStreams[i] := FStreams[IndexAtEnd]; FStreamsCodes[IndexAtEnd] := TmpCode; FStreams[IndexAtEnd] := TmpStream; end; finally FStreams.OwnsObjects := SavedOwnsObjects; end; end; CurrTick := GetTickCount - OldTick; CurrTick := GetTickCount - OldTick; end; procedure TStreamList.SaveToFile(AFileName: String); var FileStream: TFileStream; FirstBlockPos: Int64; CurrStream: TStream; IntToWrite: Integer; i: integer; begin if FileExists(AFileName) then DeleteFile(AFileName); if Not FileExists(AFileName) then begin FileStream := TFileStream.Create(AFileName, fmCreate); try FileStream.Position := 0; //*** Записать код файла if Not FISStrCode then FileStream.WriteBuffer(FFileCode, SizeOf(Integer)) else begin // длина строки IntToWrite := Length(FFileCodeStr); FileStream.WriteBuffer(IntToWrite, SizeOf(Integer)); // Строка //FileStream.WriteBuffer(pchar(FFileCodeStr)^, Length(FFileCodeStr)); FileStream.WriteBuffer(pAnsiChar(FFileCodeStr)^, Length(FFileCodeStr)); // Tolik 07/04/2019 -- end; // Записать позицию для чтения первого блока FirstBlockPos := FileStream.Position + SizeOf(Int64); FileStream.WriteBuffer(FirstBlockPos, SizeOf(Int64)); //*** Записать блоки if FStreams.Count = FStreamsCodes.Count then for i := 0 to FStreams.Count - 1 do begin CurrStream := TStream(FStreams[i]); //*** Записать код стрима IntToWrite := FStreamsCodes[i]; FileStream.WriteBuffer(IntToWrite, SizeOf(Integer)); //*** Записать размер стрима IntToWrite := CurrStream.Size; FileStream.WriteBuffer(IntToWrite, SizeOf(Integer)); //*** Записать стрим CurrStream.Position := 0; FileStream.CopyFrom(CurrStream, 0); end; finally FileStream.Free; end; end; end; function GetStrFromStringsByKey(AStrings: TStrings; const AKey: String): String; var ObjIndex: Integer; Obj: TObject; begin Result := ''; ObjIndex := AStrings.IndexOf(AKey); if ObjIndex <> -1 then begin Obj := AStrings.Objects[ObjIndex]; if Obj is TStringObject then Result := TStringObject(Obj).FString; end; end; function GetStrFromStringsByIdx(AStrings: TStrings; AIdx: Integer): String; var Obj: TObject; begin Result := ''; if AIdx <> -1 then begin Obj := AStrings.Objects[AIdx]; if Obj is TStringObject then Result := TStringObject(Obj).FString; end; end; procedure FreeStringsObjects(AStrings: TStrings; AClear: Boolean); var i: Integer; Obj: TObject; begin for i := 0 to AStrings.Count - 1 do begin Obj := AStrings.Objects[i]; if Assigned(Obj) then begin Obj.Free; if Not AClear then AStrings.Objects[i] := nil; end; end; if AClear then AStrings.Clear; end; procedure SetStrToStringsByIdx(AStrings: TStrings; AIdx: Integer; const aVal: String); var Obj: TObject; begin if AIdx <> -1 then begin Obj := AStrings.Objects[AIdx]; if Obj is TStringObject then TStringObject(Obj).FString := aVal; end; end; procedure SortListByItemField(AList: TList; AItem, AFieldAdress: Pointer); var SortFieldOffset: Integer; function CompareItems(Item1, Item2: Pointer): Integer; var val1, val2: Integer; begin val1 := Integer(Pointer(Integer(Item1) + SortFieldOffset)^); val2 := Integer(Pointer(Integer(Item2) + SortFieldOffset)^); Result := CompareInt(val1, val2); end; begin if (AList <> nil) and (AList.Count > 0) then begin SortFieldOffset := Integer(AFieldAdress) - Integer(AItem); QuickSortPointerList(AList.List, 0, AList.Count - 1, @CompareItems); end; end; { procedure SortListByObjItemField(AList: TList; AItem: TObject; AFieldAdress: Pointer); var temp: LongWord; SortFieldOffset: LongWord; ptr1, ptr2: LongWord; temp2: LongWord; function CmpItems(Item1, Item2: Pointer): Integer; var //ptr1, ptr2: LongWord; val1, val2: Integer; begin //ptr1 := Pointer(LongWord(Item1) + SortFieldOffset); //ptr2 := Pointer(LongWord(Item2) + SortFieldOffset); ptr1 := LongWord(Item1) + SortFieldOffset; ptr2 := LongWord(Item2) + SortFieldOffset; val1 := Integer(Pointer(ptr1)^); val2 := Integer(Pointer(ptr2)^); //val1 := Integer(Pointer(Integer(Item1) + SortFieldOffset)^); //val2 := Integer(Pointer(Integer(Item2) + SortFieldOffset)^); Result := CompareInt(val1, val2); end; function CompareItems(Item1, Item2: Pointer): Integer; begin Result := CmpItems(Item1, Item2); end; begin if (AList <> nil) and (AList.Count > 0) then begin SortFieldOffset := Integer(AFieldAdress) - Integer(AItem); QuickSortPointerList(AList.List, 0, AList.Count - 1, @CompareItems); end; end; } procedure RotateTObjectList(AList: TObjectList); var SavedOwnsObjects: Boolean; begin SavedOwnsObjects := AList.OwnsObjects; AList.OwnsObjects := false; RotateTList(AList); AList.OwnsObjects := SavedOwnsObjects; end; procedure RotateTList(AList: TList); var i: Integer; TmpValue: Pointer; TmpStream: TObject; ItemsCount: Integer; IndexAtEnd: Integer; SavedOwnsObjects: Boolean; begin ItemsCount := AList.Count; for i := 0 to (ItemsCount div 2) - 1 do begin TmpValue := AList[i]; IndexAtEnd := ItemsCount - i - 1; AList[i] := AList[IndexAtEnd]; AList[IndexAtEnd] := TmpValue; end; end; { TStringsHash } constructor TStringsHash.Create; begin FStrings := CreateStringListSorted; end; destructor TStringsHash.Destroy; begin FreeStringsObjects(FStrings, True); inherited; end; function TStringsHash.GetVal(const aKey: String; var aVal: String): Boolean; var ResIdx: Integer; begin Result := false; ResIdx := FStrings.IndexOf(aKey); if ResIdx <> -1 then begin Result := true; aVal := GetStrFromStringsByIdx(FStrings, ResIdx); end; end; function TStringsHash.SetVal(const aKey, aVal: String): Integer; begin Result := FStrings.IndexOf(aKey); if Result <> -1 then begin SetStrToStringsByIdx(FStrings, Result, aVal); end else Result := AddStrObjToStrings(FStrings, aKey, aVal); end; end.