(* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License, Version 1.0 only * (the "License"). You may not use this file except in compliance * with the License. * * You can obtain a copy of the license at * http://www.opensource.org/licenses/cddl1.php. * See the License for the specific language governing permissions * and limitations under the License. * * When distributing Covered Code, include this CDDL HEADER in each * file and include the License file at * http://www.opensource.org/licenses/cddl1.php. If applicable, * add the following below this CDDL HEADER, with the fields enclosed * by brackets "[]" replaced with your own identifying * information: * Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END * * * Portions Copyright 2007 Andreas Schneider *) unit ULinkedList; interface uses SysUtils; type PLinkedItem = ^TLinkedItem; TLinkedItem = record ID: Integer; Data: Pointer; Next: PLinkedItem; end; TLinkedList = class(TObject) constructor Create; virtual; destructor Destroy; override; protected FFirst: PLinkedItem; FLast: PLinkedItem; public procedure Clear; virtual; function Iterate(var ALinkedItem: PLinkedItem): Boolean; virtual; function Add(AID: Integer; AData: Pointer): PLinkedItem; virtual; procedure Delete(AData: Pointer); overload; virtual; procedure Delete(AID: Integer); overload; virtual; function Get(AID: Integer): Pointer; virtual; property Last: PLinkedItem read FLast; end; implementation { TBlockList } function TLinkedList.Add(AID: Integer; AData: Pointer): PLinkedItem; var current: PLinkedItem; begin New(current); current^.ID := AID; current^.Data := AData; current^.Next := nil; if FFirst = nil then FFirst := current; if FLast <> nil then FLast^.Next := current; FLast := current; Result := current; end; procedure TLinkedList.Clear; var current, next: PLinkedItem; begin current := FFirst; while current <> nil do begin next := current^.Next; Dispose(current); current := next; end; FFirst := nil; FLast := nil; end; constructor TLinkedList.Create; begin inherited Create; FFirst := nil; FLast := nil; end; procedure TLinkedList.Delete(AData: Pointer); var currentItem, lastItem, nextItem: PLinkedItem; begin lastItem := nil; currentItem := FFirst; while currentItem <> nil do begin if currentItem^.Data = AData then begin if FFirst = currentItem then FFirst := currentItem^.Next; if FLast = currentItem then FLast := lastItem; if lastItem <> nil then lastItem^.Next := currentItem^.Next; Dispose(currentItem); nextItem := nil; end else nextItem := currentItem^.Next; lastItem := currentItem; currentItem := nextItem; end; end; procedure TLinkedList.Delete(AID: Integer); var currentItem, lastItem, nextItem: PLinkedItem; begin lastItem := nil; currentItem := FFirst; while currentItem <> nil do begin if currentItem^.ID = AID then begin if FFirst = currentItem then FFirst := currentItem^.Next; if FLast = currentItem then FLast := lastItem; if lastItem <> nil then lastItem^.Next := currentItem^.Next; Dispose(currentItem); nextItem := nil; end else nextItem := currentItem^.Next; lastItem := currentItem; currentItem := nextItem; end; end; destructor TLinkedList.Destroy; begin Clear; inherited Destroy; end; function TLinkedList.Get(AID: Integer): Pointer; var item: PLinkedItem; begin Result := nil; item := nil; while Iterate(item) and (Result = nil) do if item^.ID = AID then Result := item^.Data; end; function TLinkedList.Iterate(var ALinkedItem: PLinkedItem): Boolean; begin if ALinkedItem = nil then ALinkedItem := FFirst else ALinkedItem := ALinkedItem^.Next; Result := ALinkedItem <> nil; end; end.