//list_c.cpp

#include "list_c.h"
/*
@function: List_ctor()
This constructor allocates and initializes a default list
*/
List* List_ctor()	{
   List *theList = new List;	//allocate the memory
   theList->count_=0;		//we have no elements
   theList->current_=-1;	//some invalid value
	//what the heck, itialize each element
   for (int i=0; i<List::ELEMENTS; i++)	{
	theList->values_[i]=0;	//just picked zero for a value
   }
   return theList;
}
/*
@function: List_ctor(const List&)
This constructor will copy the values from the passed in list. Note, only the
pointer values are copied and not the (unknown) objects themselves. The
result is two lists pointing to the same objects. Care should be taken when
deletion of those objects occur.
*/
List* List_ctor(const List& otherList)	{
   List* theList = new List;	//allocate the memory
   for (int i=0; i<List::ELEMENTS; i++)	{ //copy even unused bytes
	theList->values_[i] = otherList.values_[i]; //so we are init
   }
   theList->count_ = otherList.count_;  //we have their num of elements
   theList->current_ = -1;
   return theList;
}
/*
@function: dtor(List*)
This destructor will deallocate the memory for the list. Since we do not know
the types of the objects in our list, it is up to the user to actually delete
the memory allocated by the objects in the list.
*/
void dtor(List* theList)	{
   delete theList;
}
/*
@function: insert(List*,void*)
This service will insert the value in the list in the first unused position.
A 0 return indicates the insertion was successful. A value <0 indicates an
error.
*/
int insert(List* theList, void* value)	{
   int result = -1;	//default to error
   if (theList->count_ < List::ELEMENTS)	{ //check if room for value
	theList->values_[theList->count_] = value;  //add value
	theList->count_++;		//inform list of value
   }
   return result;		//tell caller if worked
}
/*
@function: at(const List*, size_t)
This service will return the element from the specified position or zero if
the position is out of bounds. It is up to the caller to call with a correct
index and interpret the 0 error return from a null address. The position
is zero relative.
*/
void *at(const List* theList, size_t pos)	{
   void *value=0;		//default to out of bounds
   if (pos < theList->count_)	{ //eval zero relative
	value = theList->values_[pos];
   }
   return value;
}
/*
@function: getFirst(List*)
This service will return the first element from the list or a zero if no
elements exist. It is up to the caller to interpret the zero error return
value from a null pointer.
*/
void* getFirst(List* theList)	{
   return (theList->values_[theList->current_=0]);
}
/*
@function: next(List*)
This service returns the next relative element in the list. A call to
getFirst() should be made before this is called. Each subsequent call
to next() will return the next value from the list.
*/
void* next(List* theList)	{
   void* value=0;		//default to out of bounds
   if (++theList->current_ <= theList->count_)	{
	value = theList->values_[theList->current_];
   }
   return value;
}
/*
@function: assign(List*,const List&)
This service will assign the values from the source list to the target list.
Only the values are copied and not the objects in the list. This call
will result in both lists pointing to the same objects. This is much like
the copy ctor() except that this list already exists instead be being
created. The former contents of this list are lost following the call.
*/
void assign(List* theList, const List& source)	{
   for (int i=0; i<List::ELEMENTS; i++)	{ //copy even unused bytes
	theList->values_[i] = source.values_[i]; //so we are init
   }
   theList->count_ = source.count_;  //we have their num of elements
   theList->current_=-1;
}
/*
@function: isEqual(List*, const List&)
This service will return a non-zero value if the two lists have the same
number of elements and the elements are of the same value. A zero return
means either they contain a differing amount or their values are not
identical.
*/
int isEqual(List* theList, const List& otherList)	{
   int result=0;	//default to different;
   if (theList->count_ == otherList.count_)	{
	result = 1;	//assume a match & wait till mismatch or end
	for(int i=0;i<theList->count_ && result;i++)	{
		result = theList->values_[i]==otherList.values_[i];
	}
   }
   return result;
}
/*
@function: saveOn(const List*, ostream& str, Writer)
This function will write the contents of the list to the specified output
stream. It handles the overhead associated with the list and uses the
specified writer to complete the save for the untyped void* information.
Note that all elements are saved by value. Meaning, duplicate entries will
result in multiple saves of the same object.
*/
int saveOn(const List*  theList, ostream& str, Writer writer) {
   int status = -1;   //default to error
   if (theList) {
         //write the number of elements in the list
      str << theList->count_ << endl;
      status = 0;
      for(int i=0; i<theList->count_ && !status; i++) {
            //write out an element from the list
         status = (*writer)(theList->values_[i], str);
      }
   }

   return status;
}

/*
@function: restoreFrom(List*, istream& str, Reader)
This function will read and restore the list from the specified input
stream. It handles the overhead of associated with the list and uses the
specified reader to complete the construction and reading of the list
element. Note that all elements are read back by value. Meaning, restored
objects will have a different address from their original instance and
multiply saved objects will also have separate instances.
*/
int restoreFrom(List* theList, istream& str, Reader reader) {
   int status = -1; //default to error
   if (theList) {
         //reda the number of elements in the list
      str >> theList->count_;
      str.ignore(1); //throw away \n after count
      status = 0;
      for(int i=0; i<theList->count_ && !status; i++) {
            //restore an element into the list
            //   -we supply caller reference to the pointer
            //   -caller supplies object, restored with values
         status = (*reader)(theList->values_[i], str);
      }
   }

   return status;
}
//end of file

