//
//  NAME
//    plist.cpp
//
//  DESCRIPTION
//    This file contains the functions used to implement the
//    Person-List module.
//
//    For descriptions of parameters and return value of 
//    exported (non-static) functions, see plist.h.
//


//
//  Include files.
//

#include <stdlib.h>
#include "bool.h"
#include "person.h"
#include "plist.h"


//
//  NAME
//    personElem
//
//  DESCRIPTION
//    This structure represents an element in a singly-linked list
//    of people.
//
//  MEMBERS
//    p     - information about a person.
//    next  - a pointer to the next element in the list.
//

struct personElem {
   person      p;
   personElem* next;
   };


//
//  Function prototypes.
//

static personElem* newElem(person& p);
static void moveToEnd();


//
//  Module variables.
//

static personElem* head    = NULL;     //  Pointer to the head of the list.
static personElem* current = NULL;     //  Pointer to the "current" element.


//
//  NAME
//    addToEnd
//
//  DESCRIPTION
//    This functions adds the given person to the end of the list.
//    It traverse the list from the head to find the end, then adds
//    a new element to the end of the list.
//

void addToEnd(person& p) {
   personElem* pe = newElem(p);

   if (head == NULL) {
      head = pe;
      current = head;
      return;
      }

   moveToEnd();
   current->next = pe;
   current = pe;
   return;
}


//
//  NAME
//    getFirst
//
//  DESCRIPTION
//    This function gets the first person from the list.  The module
//    variable "current" is set to point to the head of the list, and
//    the person information stored in that element is returned, if such
//    an element exists.
//

bool getFirst(person& p) {
   current = head;

   if (current == NULL) {
      return false;
      }
   p = current->p;
   return true;
}


//
//  NAME
//    getNext
//
//  DESCRIPTION
//    This function gets the person information for the next person.
//    The "current" pointer is moved ahead one position in the list,
//    and the person information stored in that element is returned,
//    if such an element exists.
//

bool getNext(person& p) {
   current = current->next;

   if (current == NULL) {
      return false;
      }
   p = current->p;
   return true;
}


//
//  NAME
//    atEnd
//
//  DESCRIPTION
//    This function determines if the list is empty by seeing if the
//    "current" module variable is NULL or not.
//

bool atEnd() {
   return (current == NULL) ? true : false;
}


//
//  NAME
//    clearList
//
//  DESCRIPTION
//    This function removes all elements from the list by traversing 
//    the list from the head and deallocating each element.  The
//    "current" module variable is used to traverse the list, and the
//    local variable "next" points to the next element.  When the
//    list has been empties, the "head" and "current" module variables
//    are set to NULL.
//

void clearList() {
   personElem* next;

   current = head;
   while (current != NULL) {
      next = current->next;
      delete current;
      current = next;
      }

   head    = NULL;
   current = head;
   return;
}


//
//  NAME
//    newElem
//
//  DESCRIPTION
//    This function allocates a new list element and copies the given
//    person information into it.
//
//  PARAMETESRS
//    p  (in) - person information to copy into the new element.
//
//  RETURNS
//    pointer to the newly allocated list element
//

static personElem* newElem(person& p) {
   personElem* pe = new personElem;
   pe->p = p;
   pe->next = NULL;
   return pe;
}


//
//  NAME
//    moveToEnd
//
//  DESCRIPTION
//    This function causes the "current" module variable to point to
//    the last element in the list.  This function assumes that the
//    list is not empty.
//
//  PARAMETERS
//    (none)
// 
//  RETURNS
//    (none)

static void moveToEnd() {
   if (current == NULL) {
      current = head;
      }
   while (current->next != NULL) {
      current = current->next;
      }
   return;
}


//
//  End of file.
//