home *** CD-ROM | disk | FTP | other *** search
/ Collection of Education / collectionofeducationcarat1997.iso / COMPUSCI / TOT11.ZIP / TOTDOC11.ZIP / CHAPT19.TXT < prev    next >
Text File  |  1991-02-11  |  20KB  |  456 lines

  1.                                                                      Customizing
  2.                                                                           Linked
  3.                                                                            Lists
  4.  
  5.  
  6.  
  7.          "As we acquire knowledge, things do not become more comprehensible, but
  8.          more mysterious."
  9.  
  10.                                                                      Will Durant
  11.  
  12.  
  13.  
  14.          Doubly-linked lists are ideal for managing large lists of data, they
  15.          are memory efficient and fast. The only problem is they are compli-
  16.          cated! Fortunately, the Toolkit provides a very easy to use doubly-
  17.          linked list object called DLLOBJ. DLLOBJ is an abstract object designed
  18.          specifically to simplify the task of extending the object. In this
  19.          chapter, techniques for developing a custom doubly-linked list for
  20.          managing records is discussed.
  21.  
  22.          You might want to consider re-reading the section on linked list theory
  23.          (page 9-1) before proceeding.
  24.  
  25.  
  26. DLLOBJ
  27.          Unlike many objects, you do not need to understand very much about
  28.          DLLOBJ to create descendant objects. All the following methods (which
  29.          were described in chapter 9) are unaffected by the type of data stored
  30.          in the list, and do not need to be modified in descendant objects:
  31.  
  32.          procedure   Advance(Amount:longint);
  33.          procedure   Retreat(Amount:longint);
  34.          function    NodePtr(NodeNumber:longint): DLLNodePtr;
  35.          procedure   Jump(NodeNumber:longint);
  36.          procedure   ShiftActiveNode(NewNode: DLLNodePtr; NodeNumber: longint);
  37.          procedure   DelNode(Node:DLLNodePtr);
  38.          procedure   DelAllStatus(BitPos:byte;On:boolean);
  39.          function    TotalNodes: longint;
  40.          function    ActiveNodeNumber: longint;
  41.          function    ActiveNodePtr: DLLNodePtr;
  42.          function    StartNodePtr: DLLNodePtr;
  43.          function    EndNodePtr: DLLNodePtr;
  44.          procedure   EmptyList;
  45.          procedure   Sort(SortID:shortint;Ascending:boolean);
  46.          procedure   SwapNodes(Node1,Node2:DLLNodePtr);
  47.  
  48.          The DLLOBJ stores un-typed data in binary format. You can literally
  49.          stored any type of data in a DLLOBJ list. The following methods add and
  50.          modify data in a list:
  51.  
  52.  
  53. 19-2                                                       Extending the Toolkit
  54. --------------------------------------------------------------------------------
  55.  
  56.          function Add(var TheData;Size:longint): integer;
  57.          function Change(Node:DLLNodePtr;var TheData;Size:longint): integer;
  58.          function InsertBefore(Node:DLLNodePtr;var TheData;Size:longint): inte-
  59.          ger;
  60.  
  61.  
  62.          Each of these three methods are passed an untyped parameter and a lon-
  63.          gint indicating the size of the data. In descendant objects, you will
  64.          call these methods to manipulate the data in the list. The following
  65.          methods return information about the data stored in the list:
  66.          procedure   Get(var TheData);
  67.          procedure   GetNodeData(Node:DLLNodePtr;Var TheData);
  68.          function    GetNodeDataSize(Node:DLLNodePtr):longint;
  69.          function    GetMaxNodeSize: longint;
  70.  
  71.  
  72.          The most used method is GetNodeData, which will update a passed un-
  73.          typed parameter with the data stored in the list. It is the fundamental
  74.          way for a descendant object to get data from the list.
  75.  
  76.  
  77. Extending DLLOBJ
  78.  
  79.          The main reason for extending DLLOBJ is to make the new object manage a
  80.          specific type of data. The Toolkit includes the descendant StrDLLOBJ,
  81.          which is specifically designed to store strings, and FileDLLOBJ, which
  82.          stores DOS file details.
  83.          In this section, DLLOBJ will be extended and customized to store a
  84.          record. To illustrate the principles involved, we will create a new
  85.          object RecordDLLOBJ to store the following record data:
  86.  
  87.          RecordInfo = record
  88.             FirstName: string[15];
  89.             LastName: string[15];
  90.             Company: string[20];
  91.             Tel: string[10];
  92.             CumDollarsSpent: real;
  93.             LastOrder: longint;
  94.             Comments: string[40];
  95.          end;
  96.  
  97.          The main methods that need to be customized are the data manipulation
  98.          methods, i.e. Add, Change and InsertBefore. If you want to display the
  99.          object in a Browse or List window you must also customize the GetStr
  100.          virtual method. GetStr is called by the browse and list objects, and is
  101.          simply a function which returns the data stored at a node in string
  102.          form. The fifth method which usually needs to be customized is Wron-
  103.  
  104.  
  105.  
  106. Customizing Linked Lists                                                    19-3
  107. --------------------------------------------------------------------------------
  108.  
  109.          gOrder. This method provides the Sort method with the information
  110.          needed to sort the data, and is discussed in a later section. The new
  111.          object would therefore be declared as follows:
  112.  
  113.          RecordListOBJ = object (DLLOBJ)
  114.             constructor Init;
  115.             function    Add(Rec:RecordInfo): integer;
  116.             function    Change(Node:DLLNodePtr;Rec:RecordInfo): integer;
  117.             function    InsertBefore(Node:DLLNodePtr;Rec:RecordInfo): integer;
  118.             function    WrongOrder(Node1,Node2:DLLNodePtr;
  119.                                    Asc:boolean): boolean;        VIRTUAL;
  120.             function    GetStr(Node:DLLNodePtr;
  121.                                Start,Finish: longint):string;    VIRTUAL;
  122.             destructor  Done;                                    VIRTUAL;
  123.          end; {RecordListOBJ}
  124.  
  125.          Notice that Add, Change and InsertBefore are each passed a variable of
  126.          type RecordInfo. All these methods need to do is call their correspond-
  127.          ing DLLOBJ method and pass the record as an untyped parameter together
  128.          with the record size. The three methods would be implemented as
  129.          follows:
  130.  
  131.          function RecordDLLOBJ.Add(Rec:RecordInfo): integer;
  132.          begin
  133.             Add := DLLOBJ.Add(Rec,sizeof(Rec));
  134.          end; {RecordDLLOBJ.Add}
  135.          function RecordDLLOBJ.Change(Node:DLLNodePtr;
  136.                                        Rec:RecordInfo): integer;
  137.          begin
  138.             Change := DLLOBJ.Change(Node,Rec,sizeof(Rec));
  139.          end; {RecordDLLOBJ.Change}
  140.  
  141.          function RecordDLLOBJ.InsertBefore(Node:DLLNodePtr;
  142.                                              Rec:RecordInfo): integer;
  143.          {}
  144.          begin
  145.             InsertBefore := DLLOBJ.InsertBefore(Node,Rec,sizeof(Rec));
  146.          end; {RecordDLLOBJ.InsertBefore}
  147.  
  148.          It's really as simple as that.
  149.  
  150.          The function method GetStr is passed three parameters; a node pointer
  151.          indicating which data to access, and the Start and Finish parameters of
  152.          type longint. Start and Finish identify the first and last character
  153.          positions of the sub-string to be returned by the function. The DLLOBJ
  154.          method GetNodeData can be used to retrieve the node data, and then the
  155.          data must be converted into string form. The requested portion of this
  156.          string can then be returned. GetStr could be implemented as follows:
  157.  
  158.  
  159.  
  160. 19-4                                                       Extending the Toolkit
  161. --------------------------------------------------------------------------------
  162.  
  163.          function RecordDLLOBJ.GetStr(Node:DLLNodePtr;Start,Finish: lon-
  164.          gint):string;
  165.          {Returns string representation of record}
  166.          var
  167.            Temp: string;
  168.            Rec: RecordInfo;
  169.          begin
  170.             if Node = nil then
  171.                GetStr := 'Not found'
  172.             else
  173.             begin
  174.                GetNodeData(Node,Rec);  {inherited method}
  175.                with Rec do
  176.                begin
  177.                   Temp := inttostr(ActiveNo