home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / sp15demo.zip / libsrc.zip / LIBSRC / COLLECT.PAS < prev    next >
Pascal/Delphi Source File  |  1996-01-14  |  10KB  |  383 lines

  1. UNIT Collect;
  2.  
  3. INTERFACE
  4.  
  5. USES ObjectPM;
  6.  
  7. CONST
  8.   MaxCollectionSize = $7FFFFFFF;
  9.   vmtHeaderSize     = 8;
  10.  
  11.   { TCollection error codes }
  12.   coIndexError = 1;              { Index out of range }
  13.   coOverflow   = 2;              { Overflow }
  14.  
  15. TYPE
  16.     {TCollection types}
  17.     PItemList = ^TItemList;
  18.     TItemList = array[0..655350] OF Pointer;
  19.  
  20.     {TCollection object}
  21.     PCollection = ^TCollection;
  22.     TCollection = OBJECT
  23.                      Items: PItemList;
  24.                      Count: LONGINT;
  25.                      Limit: LONGINT;
  26.                      Delta: LONGINT;
  27.                      CONSTRUCTOR Init(ALimit, ADelta: LONGINT);
  28.                      DESTRUCTOR  Done;VIRTUAL;
  29.                      FUNCTION    At(Index:LONGINT): Pointer;
  30.                      PROCEDURE   AtDelete(Index:LONGINT);
  31.                      PROCEDURE   AtFree(Index:LONGINT);
  32.                      PROCEDURE   AtInsert(Index:LONGINT; Item: Pointer);
  33.                      PROCEDURE   AtPut(Index: LONGINT; Item: Pointer);
  34.                      PROCEDURE   Delete(Item: Pointer);
  35.                      PROCEDURE   DeleteAll;
  36.                      PROCEDURE   Error(Code, Info: Integer);VIRTUAL;
  37.                      FUNCTION    FirstThat(Test: Pointer): Pointer;
  38.                      PROCEDURE   ForEach(Action: Pointer);
  39.                      PROCEDURE   Free(Item: Pointer);
  40.                      PROCEDURE   FreeAll;
  41.                      PROCEDURE   FreeItem(Item: Pointer);VIRTUAL;
  42.                      FUNCTION    IndexOf(Item: Pointer): LONGINT;VIRTUAL;
  43.                      PROCEDURE   Insert(Item: Pointer); virtual;
  44.                      FUNCTION    LastThat(Test: Pointer): Pointer;
  45.                      PROCEDURE   Pack;
  46.                      PROCEDURE  SetLimit(ALimit: LONGINT);VIRTUAL;
  47.                 END;
  48.  
  49.  
  50.  
  51.      {TSortedCollection object}
  52.      PSortedCollection = ^TSortedCollection;
  53.      TSortedCollection = OBJECT(TCollection)
  54.                  Duplicates: Boolean;
  55.                  CONSTRUCTOR Init(ALimit, ADelta: Integer);
  56.                  FUNCTION    Compare(Key1, Key2: Pointer): Integer;VIRTUAL;
  57.                  FUNCTION    IndexOf(Item: Pointer): LONGINT;VIRTUAL;
  58.                  PROCEDURE   Insert(Item: Pointer);VIRTUAL;
  59.                  FUNCTION    KeyOf(Item: Pointer): Pointer;VIRTUAL;
  60.                  FUNCTION    Search(Key: Pointer; var Index: LONGINT): Boolean;VIRTUAL;
  61.             END;
  62.  
  63.  
  64. IMPLEMENTATION
  65.  
  66. {*************************************************************************
  67.  *                                                                       *
  68.  *  Object TCollection                                                   *
  69.  *                                                                       *
  70.  *************************************************************************}
  71.  
  72. CONSTRUCTOR TCollection.Init(ALimit, ADelta: LONGINT);
  73. BEGIN
  74.      Items := NIL;
  75.      Count := 0;
  76.      Limit := 0;
  77.      Delta := ADelta;
  78.      SetLimit(ALimit);
  79. END;
  80.  
  81. DESTRUCTOR TCollection.Done;
  82. BEGIN
  83.      FreeAll;
  84.      SetLimit(0);
  85. END;
  86.  
  87. FUNCTION TCollection.At(Index: LONGINT): Pointer;
  88. BEGIN
  89.      IF (Index >= Count) OR (Index < 0) then Error(coIndexError,1);
  90.      At := Items^[Index];
  91. END;
  92.  
  93. PROCEDURE TCollection.AtDelete(Index: LONGINT);
  94. VAR t:LONGINT;
  95. BEGIN
  96.     IF (Index >= Count) OR (Index < 0) then Error(coIndexError,2);
  97.  
  98.     t:=Count-Index;
  99.     IF t>1 THEN Move(Items^[Index+1],Items^[Index],(t-1) * 4);
  100.     Dec(Count);
  101. end;
  102.  
  103. PROCEDURE TCollection.AtFree(Index: LONGINT);
  104. BEGIN
  105.      IF (Index > Count) OR (Index < 0) THEN Error(coIndexError,3);
  106.  
  107.      FreeItem(Items^[index]);
  108.      AtDelete(Index);
  109. end;
  110.  
  111. PROCEDURE TCollection.AtInsert(Index: LONGINT; Item: Pointer);
  112. BEGIN
  113.      IF (Index > Count) OR (Index < 0) THEN Error(coIndexError,3);
  114.  
  115.      IF Count >= Limit THEN SetLimit(Limit+Delta);
  116.      IF Index < Count THEN
  117.        Move(Items^[Index],Items^[Index+1],(Count-Index) * 4);
  118.      Items^[Index] := Item;
  119.      Inc(Count);
  120. END;
  121.  
  122. PROCEDURE TCollection.AtPut(Index: LONGINT; Item: Pointer);
  123. BEGIN
  124.      IF (Index >= Count) OR (Index < 0) THEN Error(coIndexError,3);
  125.  
  126.      Items^[Index] := Item;
  127. END;
  128.  
  129. PROCEDURE TCollection.Delete(Item: Pointer);
  130. BEGIN
  131.      AtDelete(IndexOf(Item));
  132. end;
  133.  
  134. PROCEDURE TCollection.DeleteAll;
  135. BEGIN
  136.      Count := 0;
  137. end;
  138.  
  139. PROCEDURE TCollection.Error(Code, Info: Integer);
  140. BEGIN
  141.      RunError(214 - Code);
  142. END;
  143.  
  144. FUNCTION TCollection.FirstThat(Test: Pointer): Pointer;
  145. VAR
  146.     t:LONGINT;
  147.     ThatFunc : FUNCTION(p:POINTER):BOOLEAN;
  148.     result:POINTER;
  149. LABEL l;
  150. BEGIN
  151.   ThatFunc := Test;
  152.   IF Count>0 THEN
  153.   FOR t:=0 TO Count-1 DO
  154.   BEGIN
  155.        IF ThatFunc(Items^[t]) THEN
  156.        BEGIN
  157.             result:=Items^[t];
  158.             goto l;
  159.        END;
  160.   END;
  161.   result:=NIL;
  162. l:
  163.   FirstThat:=result;
  164. END;
  165.  
  166. PROCEDURE TCollection.ForEach(Action: Pointer);
  167. VAR
  168.     EachFunc:PROCEDURE(P:Pointer);
  169.     t:LONGINT;
  170. BEGIN
  171.      EachFunc := Action;
  172.      IF Count>0 THEN
  173.        FOR t:= 0 to Count-1 DO EachFunc(Items^[t]);
  174. END;
  175.  
  176. PROCEDURE TCollection.Free(Item: Pointer);
  177. BEGIN
  178.     Delete(Item);
  179.     FreeItem(Item);
  180. END;
  181.  
  182. PROCEDURE TCollection.FreeAll;
  183. VAR
  184.    t:LONGINT;
  185. BEGIN
  186.      IF Count>0 THEN
  187.        FOR t:= 0 TO Count - 1 DO FreeItem(Items^[t]);
  188.      Count := 0;
  189. end;
  190.  
  191. PROCEDURE TCollection.FreeItem(Item: Pointer);
  192. VAR
  193.     p : POPMLObject;
  194. BEGIN
  195.     p:=Item;
  196.     IF p <> NIL THEN Dispose(P, Done);
  197. END;
  198.  
  199.  
  200. FUNCTION TCollection.IndexOf(Item: Pointer):LONGINT;
  201. VAR
  202.    t : LONGINT;
  203.    Result:LONGINT;
  204. LABEL l;
  205. BEGIN
  206.      IF Count>0 THEN
  207.      FOR t:=0 TO Count-1 DO
  208.      BEGIN
  209.           IF Items^[t]=Item THEN
  210.           BEGIN
  211.                result:=t;
  212.                goto l;
  213.           END;
  214.      END;
  215.      result:=-1;
  216. l:
  217.      IndexOf:=result;
  218. END;
  219.  
  220. PROCEDURE TCollection.Insert(Item: Pointer);
  221. BEGIN
  222.      AtInsert(Count, Item);
  223. END;
  224.  
  225. FUNCTION TCollection.LastThat(Test: Pointer): Pointer;
  226. VAR
  227.     t:LONGINT;
  228.     ThatFunc:FUNCTION(p:Pointer):Boolean;;
  229.     result:POINTER;
  230. LABEL l;
  231. BEGIN
  232.      ThatFunc:=Test;
  233.      IF Count>0 THEN
  234.      FOR t:=Count-1 DOWNTO 0 DO
  235.      BEGIN
  236.           IF ThatFunc(Items^[t]) THEN
  237.           BEGIN
  238.                result:=Items^[t];
  239.                goto l;
  240.           END;
  241.      END;
  242.      result:=NIL;
  243. l:
  244.      LastThat:=result;
  245. END;
  246.  
  247. PROCEDURE TCollection.Pack;
  248. VAR
  249.    t:LONGINT;
  250.    t1:LONGINT;
  251. BEGIN
  252.      IF Count=0 THEN exit;
  253.      FOR t:=0 TO Count-1 DO
  254.      BEGIN
  255.           IF Items^[t]=NIL THEN
  256.           BEGIN
  257.                t1:=Count-t;
  258.                IF t1>1 THEN Move(Items^[t+1],Items^[t],t1-1);
  259.                Dec(Count);
  260.           END;
  261.      END;
  262. END;
  263.  
  264.  
  265. PROCEDURE TCollection.SetLimit(ALimit: LONGINT);
  266. VAR
  267.    dummy:PItemList;
  268. BEGIN
  269.      IF ALimit=0 THEN
  270.      BEGIN
  271.           IF Items<>NIL THEN FreeMem(Items,Limit*4);
  272.           Items:=NIL;
  273.           Limit:=0;
  274.           exit;
  275.      END;
  276.  
  277.      IF ALimit<Count THEN ALimit:=Count;
  278.      GetMem(dummy,ALimit*4);
  279.      Move(Items^[0],dummy^[0],Count*4);
  280.      IF Limit<>0 THEN FreeMem(Items,Limit*4);
  281.      Limit:=ALimit;
  282.      Items:=dummy;
  283. END;
  284.  
  285.  
  286. {*************************************************************************
  287.  *                                                                       *
  288.  *  Object TCollection                                                   *
  289.  *                                                                       *
  290.  *************************************************************************}
  291.  
  292. CONSTRUCTOR TSortedCollection.Init(ALimit, ADelta: Integer);
  293. BEGIN
  294.   TCollection.Init(ALimit, ADelta);
  295.   Duplicates := False;
  296. END;
  297.  
  298.  
  299. FUNCTION TSortedCollection.Compare(Key1, Key2: Pointer): Integer;
  300. BEGIN
  301.      Abstract;
  302. END;
  303.  
  304. FUNCTION TSortedCollection.IndexOf(Item: Pointer): LONGINT;
  305. VAR
  306.   t: LONGINT;
  307.   result:LONGINT;
  308. BEGIN
  309.      result := -1;
  310.      IF Count>0 THEN IF Search(KeyOf(Item), t) THEN
  311.      BEGIN
  312.          IF Duplicates THEN
  313.            WHILE (t< Count) AND (Item <> Items^[t]) DO Inc(t);
  314.          IF t < Count THEN result := t;
  315.      END;
  316.      IndexOf:=result;
  317. END;
  318.  
  319. PROCEDURE TSortedCollection.Insert(Item: Pointer);
  320. VAR
  321.    I: LONGINT;
  322. BEGIN
  323.      IF Search(KeyOf(Item), I) THEN
  324.      BEGIN
  325.           IF Duplicates THEN AtInsert(I, Item);
  326.      END
  327.      ELSE AtInsert(I,Item);
  328. END;
  329.  
  330. FUNCTION TSortedCollection.KeyOf(Item: Pointer): Pointer;
  331. BEGIN
  332.      KeyOf := Item;
  333. END;
  334.  
  335. FUNCTION TSortedCollection.Search(Key: Pointer;
  336.                                   VAR Index: LONGINT): BOOLEAN;
  337. VAR
  338.    L, H, I, C: LONGINT;
  339.    result:BOOLEAN;
  340. LABEL ll;
  341. BEGIN
  342.      L := 0;
  343.      H := Count - 1;
  344.      result:=FALSE;
  345.      WHILE L <= H do
  346.      BEGIN
  347.           I := (L + H) DIV 2;
  348.           C := Compare(KeyOf(Items^[I]), Key);
  349.           CASE C OF
  350.              0:
  351.              BEGIN
  352.                   result:=TRUE;
  353.                   IF NOT Duplicates THEN
  354.                   BEGIN
  355.                        L:=I;
  356.                        goto ll;
  357.                   END
  358.                   ELSE
  359.                   BEGIN
  360.                        WHILE ((c = 0)AND(i > 0)) DO
  361.                        BEGIN
  362.                             Dec(i);
  363.                             C := Compare(KeyOf(Items^[i]), Key);
  364.                        END;
  365.                        L:=I;
  366.                        goto ll;
  367.                   END;
  368.              END;
  369.              ELSE
  370.              BEGIN
  371.                   IF C < 0 then L := I + 1
  372.                   ELSE  H := I - 1;
  373.              END;
  374.           END; {case}
  375.     END; {WHILE}
  376. ll:
  377.     Index := L;
  378.     Search:=Result;
  379. END;
  380.  
  381.  
  382. BEGIN
  383. END.