//------------------------------------------------------------------------
//                           Library String-List
//
// Author: Mattias Hansson
// Copyright (c) : 2005 Mattias Hansson
// License: GNU LGPL 2
// Language: 65CM v0.4+
// Dependencies: string.c65 memlib.c65
// Target: generic 6502
//
// Purpose: Provide some functions the help to create, update and access
//          a linked list of strings.
//------------------------------------------------------------------------

#IFNDEF __LIB_STRLIST
#DEFINE __LIB_STRLIST = 1

GOTO lib_strlist_skip

#INCLUDE <string.c65>
#INCLUDE <memlib.c65>

//-----------------------------------------------------------
// lib_strlist_get
//
// purpose:
//   To get address to an item# (0..count-1)
//   (send in item# $ffff for last item)
//
// lib_strlist_strget
//
// purpose:
//   To get address of an string inside item#
//   (send in item# $ffff for last item)
//
// lib_strlist_count
// purpose:
//   To get the # of items in the list.
//   NOTE: Returns the value in computer notation. I.e.
//   1 string, count == 0; 2 strings, count == 1 etc.
//-----------------------------------------------------------


FUNC lib_strlist_count ( {WORD objref} out:{WORD count} )

  WORD itemnr
  LET itemnr = $ffff

FUNC lib_strlist_get ( objref itemnr out:{WORD itemptr} )

FUNC lib_strlist_strget ( objref itemnr out:{WORD s} )

  WORD nextptr

  IF objref == NULL //no list, no action
    EXIT
  ENDIF

  //return values reset
  LET count = 0
  LET itemptr = objref
  LET s = NULL

  WHILE 1
    ADD 2 + itemptr -> s
    GETASWORD@ itemptr -> nextptr
    IF nextptr == NULL //are we at last item?
      EXIT
    ENDIF
    IF itemnr == count
      EXIT //if searching for this item we're done.
    ENDIF
    INC count
    LET itemptr = nextptr
    //MH TAG 20051218 debug
    //CALL lib_cbmio_hexoutw ( itemptr )
  WEND
FEND

//-----------------------------------------------------------
// lib_strlist_add
//
// purpose:
//   To either create a new linklist (send in NULL as
//   root-node), or add a new node to an existing linklist.
//
// Params:
//   objref - send in root-node-pointer to the
//                           list. If new list is to be created
//                           send in the value NULL.
//                           returns: address to the root node
//                           on successful add, or NULL on error
//                           (normal cause: out of memory)
//-----------------------------------------------------------

FUNC lib_strlist_add ( io:{WORD objref} {WORD s} )
  WORD link_length
  WORD link_ptr
  WORD old_link_ptr

  IF objref != 0 //add new link
    CALL lib_strlist_get ( objref $ffff old_link_ptr )
  ENDIF

  CALL lib_string_strlen ( s link_length )
  //Add space for:
  // 1. "link to next member" (2)
  // 2. null terminator (1)
  ADD 3 + link_length -> link_length
  CALL lib_mem_malloc ( link_length link_ptr )
  IF link_ptr == NULL // Alloc failed == out of memory
    LET objref = NULL
    EXIT
  ENDIF
  IF objref == 0 //create new list
    LET objref = link_ptr //return the start of the list to the caller
  ELSE //link up the new link to the end of the old list
    PUTASWORD@ old_link_ptr , link_ptr
  ENDIF
  PUTASWORD@ link_ptr , NULL //Mark as last link
  //move beyond link-pointer
  INC link_ptr
  INC link_ptr
  //and finally add the string to memory
  CALL lib_string_strcpy ( s link_ptr )

FEND

//-----------------------------------------------------------
// lib_strlist_free
//
// purpose:
//   To remove a strlist and free all resources allocated by
//   it.
//
// Params:
//   lib_strlist_f_rootptr - Address to root item.
//-----------------------------------------------------------

FUNC lib_strlist_free ( io:{WORD objref} )
  WORD nextptr

  WHILE objref
    GETASWORD@ objref -> nextptr
    CALL lib_mem_free ( objref )
    LET objref = nextptr
  WEND
  LET objref = NULL
FEND

LABEL lib_strlist_skip

#IFEND
