LIST Object
Updated: Oct 24, 2008

The LIST object facilitates creation and use of lists of text strings.  Unlike
some string list implementations using "atom" API calls, HotBasic LIST items
can be any length within the practical size of user RAM.

Please see hotlist.bas for example code.

In HotBasic, any dimensioned STRING or MEMORY object can be used as a LIST.
Why?  You deserve it.

While this flexibility is available, if you are more comfortable, just
dimension STRING's, MEMORY's and LIST's, as you might already have in existing
code, and use these objects conventionally.

The conventional members of the LIST object are presented below.  In addition,
MEMORY properties and methods apply and can be used for special purposes if
appropriate.


PROPERTIES (Read/Write):
~~~~~~~~~~ ~~~~~~~~~~~~~
Length     Length in bytes of LIST.  ListLength = MyList.Length
           IF MyList.Length THEN  'List is not empty

Position   Current position for next read/write

  Note: In conventional LIST usage, .Position should not be changed, because
  .Position always equals .Length so .AddItems works.


PROPERTIES (Read Only String):
~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~
Build      (first_item, last_item, delimiter$)

  Note: Build a new string$ using LIST first_item to last_item.
  In the new string, the LIST items will be separated by delimiter$

Item       (index) Assign LIST item index to string$
           This$ = MyList.Item(i)  'i is 0-based .Item index

  Note: For sequential reads, .ReadLine is much faster:

  MyList.Position = zero
  WHILE MyList.Position < MyList.Length
    r$ = MyList.ReadLine
    'code
  END WHILE


PROPERTIES (Read Only Numeric):
~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~
Handle     Memory handle of object stream data

IndexOf    (string$) Finds index of string$; 0 to .ItemCount;
           Returns -1 if string$ not found in LIST.

  Note: IndexOf is a basic "lookup" function.  You may not care what the index
  of string$ is, but rather want to know if it exists.

  IF MyList.IndexOf("Mary") < 0 THEN PRINT "We haven't met yet"

  To avoid duplicates in a LIST, one can

  IF MyList.IndexOf(LookUp$) < 0 THEN MyList.AddItems LookUp$

  RapidQ Basic and "atom" APIs do, I think, non-case-sensitive string item
  comparisons.  In many cases, this is desirable, to lookup names of people or
  things -- Bolt size 10 or BOLT size 10?

  In such cases, one can just make a copy of a LIST like this:

  UCList = UCASE$(MyList) 'or LCList = LCASE$(MyList) 

ItemCount  Item count of LIST; same as .LineCount

  Note:  Many text files lack a trailing CRLF and therefore are not valid LIST
  database files and .ItemCount or .LineCount will not be correct.  Your
  program may check LIST file integrity and fix malformed files:

  a$.loadfrom file "data.lst"
  if right$(a$,2)<>crlf then
    a$.position=a$.length: a$.additems null
    a$.savetofile "data.lst"  'save fixed file
  end if
  'code

LineCount  Line count of LIST

Pointer    Address of LIST stream data

Ram        Bytes of memory currently allocated for LIST use

  Note: If more memory is required, it is automatically allocated as write
  methods add data to the stream object.  Use of .Clear or .Close is
  recommended when computing is completed on large streams to free memory that
  is not immediately used further by the application.  After .Close, the
  dimensioned stream still exists for further use.


METHODS    Arguments & Comments
~~~~~~~    ~~~~~~~~~~~~~~~~~~~~
AddItems   (string$) Adds string$ to LIST.  MyList.AddItems string$

AddList    (list) Adds list to LIST.   MyList.Additems MyOtherList 

Clear      Clears data and frees allocated RAM if > about 256 bytes
           s$.Clear 'same as s$="" or s$=NULL

Close      Clears data; same as .Clear

Decrypt    Decrypts data; obviously, do this first if data encrypted

DelItems   (index[, index]) Deletes LIST item(s) with specified indeces
           MyList.DelItems 3, 6, 8

Encrypt    Encrypts data; obviously, this is last method used before save

  Note: an optional key argument -- any numeric expression -- may be used with
  .Encrypt and .Decrypt.

  MyList.Encrypt key
  'code
  MyList.Decrypt key  'same key value as used with .Encrypt

ExChange   (index1, index2) Exchanges items index1 and index2 in LIST

ExtractRes (resource) Extracts resource to .Position in LIST object

  Note: resource may be (1) Resource(n) where n is an immediate integer or
  (2) a quoted string for the resource descriptor used in $RESOURCE.
 
InsertItem (index, string$) Insert string$ at index position
           Existing data is not deleted but rather moved up.

LoadFromFile
           (filename$) Loads filename$ into LIST at current position
           Any text file may be viewed and used as a LIST of items.
           Each text file line maps to a LIST item.

  After .LoadFromFile, the LIST .Position = 0, assuming sequential access
  with .ReadLine is likely.  To use as LIST, LIST .Position = LIST .Length

  Note: SOCKET programmers can use this feature for line-based, text-only
  protocols, such has smtp or http.  The incoming packet can be assigned to a
  LIST and lines processed as items.  E.g.,
  r$=MySock.Read(S,8000) 'ask for 8K and we will see what we get.
  'get first line of http header (from server) or request (from client)
  h$=r$.Item(0)
  'this illustrates the idea, but some network peers fail to use CRLF!

LoadFromHandle +
           (mem_obj_handle, bytes) Read bytes of data from a memory
           object identified by its handle.

  If bytes is 0, .LoadFromHandle assumes the data is a text string and uses the
  LEN function to set bytes to load.  If successful, .LoadFromHandle replaces
  object stream data with memory object data.
           
  MyList.LoadFromHandle mem_obj_handle, bytes

LoadFromStream
           (stream) Loads stream into LIST starting at current .Position

Parse      (string$, delimiter$) Parse string$ using delimiter$ and add parsed
           items to LIST.

Replace    (index, string$) Replace index item with string$.

           MyList.Replace 3, "three"  '0-based item 3 replaced with "three"

           As with .InsertItem, .DelItems and similar methods that rewrite a
           LIST, .Replace will be slow for larger LISTs, in which case use of
           a STRING array should be considered, where the above syntax would
           be simply MyArray(3)="three".

SaveToFile (filename$) Save LIST to filename$
           If filename$ exists, filename$ is overwritten.

SaveToStream
           (stream) Save LIST to stream starting at stream .Position


###########
Sorting Lists:
=============
Please see SortList.inc in HotInclude.

Strings as Lists:
================
Any dimensioned STRING may utilize any of the above properties and methods.
E.g., s$.length is faster than LEN(s$).  The former just reads the .Length
property; the latter evaluates the length by looking for the first null byte
as would be customary for text-only string data.


+ PentHouse registered version

Copyright 2003-2007 James J Keene PhD
Original Publication: Oct 9, 2003
