[Back to OOP SWAG index]  [Back to Main SWAG index]  [Original]

{
LARRY HADLEY

>Right now, I have an Array of Pointers that point to the beginning
>of each page.  The entire File is loaded into memory using BlockRead.
>To jump to a page, it checks the current page number, jumps to that
>offset (as specified by the Page Array) and dumps the contents
>to the screen Until it reaches the bottom.

 I think I see. You have a monolithic block of memory...problem!

> There are a lot of ways to do it. One way would be to store the
> File as Arrays of *Pointers* to Strings...this would allow 64k of
> *sentences*, not just 64k of Text. It's a Variation on the old

   Actually, this is wrong. Since TP use 4 Byte Pointers, you can
   only <g> store 16k of sentences in a single Array, but even
   though that should still be plenty, you can use linked lists to
   overcome that limitation!

>I have an Array of Pointers to the offset of each page.  Could you
>provide a short code fragment?

   Instead of treating the Pointers as offsets, you should be using
   them as actual data collections.

{
 *****************************************************************

 Strings Unit With StrArray Object. Manage linked lists of Strings
 transparently.

 By Larry Hadley - May be used freely, provided credit is given
 wherever this code is used.

 *****************************************************************
}
Unit Strings;

Interface

Type
  PString = ^String;

  PStringList = ^StringList;
  StringList  = Record
    P    : PString;
    Next : PStringList;
  end;

  pStrArray = ^oStrArray;
  oStrArray = Object
    Root   : PStringList;
    total  : Word;
    eolist : Boolean; {end of list - only valid after calling At,
                       AtInsert, and AtDelete}
    Constructor Init;
    Destructor  Done;

    Procedure Insert(s : String);
    Procedure Delete;
    Function  At(item : Word) : PString;
    Procedure AtInsert(item : Word; s : String);
    Procedure AtDelete(item : Word);
    Function  First : PString;
    Function  Last  : PString;

  Private
    Procedure NewNode(N : PStringList);
    Function  AllocateS(s : String) : PString;
    Procedure DeallocateS(Var P : PString);
  end;

Implementation

Constructor oStrArray.Init;
begin
  Root   := NIL;
  total  := 0;
  eolist := False;
end;

Destructor oStrArray.Done;
Var
  T : PStringList;
begin
  While Root <> NIL do
  begin
    T := Root^.Next;
    if Root^.P <> NIL then
      DeallocateS(Root^.P);
    Dispose(Root);
    Root := T;
  end;
end;

Procedure oStrArray.Insert(s : String);
Var
  T, T1 : PStringList;
begin
  NewNode(T1);
  T1^.P := AllocateS(s);
  Inc(total);
  if Root <> NIL then
  begin
    T := Root;
    While T^.Next <> NIL do
       T := T^.Next;
    T^.Next := T1;
  end
  else
    Root := T1;
end;

Procedure oStrArray.Delete;
Var
  T, T1 : PStringList;
begin
  T := Root;
  if T <> NIL then
  While T^.Next <> NIL do
  begin
     T1 := T;
     T  := T^.Next;
  end;
  T1^.Next := T^.Next;
  if T^.P <> NIL then
    DeallocateS(T^.P);
  Dispose(T);
  Dec(total);
end;

Function oStrArray.At(item : Word) : PString;
Var
  count : Word;
  T     : PStringList;
begin
  if item>total then
    eolist := True
  else
    eolist := False;
  count := 1; {1 based offset}
  T := Root;
  While (count < item) and (T^.Next <> NIL) do
  begin
    T := T^.Next;
    Inc(count);
  end;
  At := T^.P;
end;

Procedure oStrArray.AtInsert(item : Word; s : String);
Var
  count : Word;
  T, T1 : PStringList;
begin
  if item > total then
    eolist := True
  else
    eolist := False;
  NewNode(T1);
  T1^.P := AllocateS(s);
  Inc(total);
  count := 1;
  if Root <> NIL then
  begin
    T := Root;
    While (count < Item) and (T^.Next <> NIL) do
    begin
      T := T^.Next;
      Inc(count);
    end;
    T1^.Next := T^.Next;
    T^.Next  := T1;
  end
  else
    Root := T1;
end;

Procedure oStrArray.AtDelete(item : Word);
Var
  count : Word;
  T, T1 : PStringList;
begin
  if item > total then { don't delete if item bigger than list total -
                       explicit only! }
  begin
    eolist := True;
    Exit;
  end
  else
    eolist := False;

  count := 1;
  T     := Root;
  T1    := NIL;

  While (count < item) and (T^.Next <> NIL) do
  begin
    T1 := T;
    T  := T^.Next;
    Inc(count);
  end;
  if T1 = NIL then
    Root := Root^.Next
  else
    T1^.Next := T^.Next;
  DeallocateS(T^.P);
  Dispose(T);
  Dec(total);
end;

Function oStrArray.First : PString;
begin
  First := Root^.P;
end;

Function oStrArray.Last : PString;
Var
  T : PStringList;
begin
  T := Root;
  if T <> NIL then
  While T^.Next <> NIL do
    T := T^.Next;
  Last := T^.P;
end;

Procedure oStrArray.NewNode(N : PStringList);
Var
  T : PStringList;
begin
  New(T);
  T^.Next := NIL;
  T^.P := NIL;
  if N = NIL then
    N := T
  else
  begin
    T^.Next := N^.Next;
    N^.Next := T;
  end;
end;

Function oStrArray.AllocateS(s : String) : PString;
Var
  P : PString;
begin
  GetMem(P, Ord(s[0]) + 1);
  P^ := s;
  AllocateS := P;
end;

Procedure oStrArray.DeallocateS(Var P : PString);
begin
  FreeMem(P, Ord(P^[0]) + 1);
  P := NIL;  {for error checking}
end;

end. {Unit StringS}


{
Code fragment :

Var
  TextList : pStrArray;

...

  New(TextList, Init);

...

  Repeat
    ReadLn(TextFile, s);
    TextList^.Insert(s);
  Until Eof(TextFile) or LowMemory;

...

  For Loop := 1 to PageLen do
  if Not(TextList^.eolist) then
    Writeln(TextList^At(PageTop + Loop)^);
...

etc.
}

[Back to OOP SWAG index]  [Back to Main SWAG index]  [Original]