/*
 * Copyright (C) 1997-2003 by Objective Systems, Inc.
 *
 * This software is furnished under a license and may be used and copied
 * only in accordance with the terms of such license and with the
 * inclusion of the above copyright notice. This software or any other
 * copies thereof may not be provided or otherwise made available to any
 * other person. No title to and ownership of the software is hereby
 * transferred.
 *
 * The information in this software is subject to change without notice
 * and should not be construed as a commitment by Objective Systems, Inc.
 *
 * PROPRIETARY NOTICE
 *
 * This software is an unpublished work subject to a confidentiality agreement
 * and is protected by copyright and trade secret law.  Unauthorized copying,
 * redistribution or other use of this work is prohibited.
 *
 * The above notice of copyright on this source code product does not indicate
 * any actual or intended publication of such source code.
 *
 *****************************************************************************/
#ifndef _ASN1CSEQOFLIST_H_
#define _ASN1CSEQOFLIST_H_

#include <stdlib.h>
#include "asn1CppTypes.h"
/**
 * @file ASN1CSeqOfList.h 
 * ASN1CSeqOfList linked list control class definition.
 */
/**
 * @addtogroup asn1ctrl 
 * @{
 */

//////////////////////////////////////////////////////////////////////
//
// ASN1CSeqOfList
//
// Doubly-linked list implementation. This class provides all functionalty
// necessary for linked list. To iterate list use methods iterator, 
// iteratorFrom, iteratorFromLast. 
//
// Note: this implementation is not thread-safe.
//
// ASN1CSeqOfListIterator
//
// An iterator for lists that allows the programmer to traverse the
// list in either direction and modify the list during iteration.
//
// Author  Artem Bolgar
// version 1.09, 12 Nov, 2003
// version 1.08, 11 Feb, 2003
//
#ifndef _NO_UTILS_CLASSES

class EXTERNRT ASN1CSeqOfList;

//////////////////////////////////////////////////////////////////////
//
// ASN1CSeqOfListIterator
//
/**
 * Linked list iterator class. The ASN1CSeqOfListIterator class is an iterator
 * for linked lists (represented by ASN1CSeqOfList) that allows the programmer
 * to traverse the list in either direction and modify the list during
 * iteration. The iterator is fail-fast. This means the list is structurally
 * modified at any time after the ASN1CSeqOfListIterator class is created, in
 * any way except through the iterator's own remove or insert methods, the
 * iterator's methods next and prev methods will return NULL. The remove, set
 * and insert methods will return the ASN_E_CONCMODF error code.
 */
class EXTERNRT ASN1CSeqOfListIterator {
   friend class ASN1CSeqOfList;
 protected:
   ASN1CSeqOfList* pSeqList; // pointer to the list
   Asn1RTDListNode* nextNode; // next node
   Asn1RTDListNode* lastNode; // last returned node
   volatile int expectedModCount; // expect modification counter
   int stat;

   ASN1CSeqOfListIterator(ASN1CSeqOfList* list);
   ASN1CSeqOfListIterator(ASN1CSeqOfList* list, Asn1RTDListNode* startNode);

 public:
  /**
   * This method returns TRUE if this iterator has more elements when
   * traversing the list in the forward direction.
   *
   * In other words, the method returns TRUE if the \c next method would return
   * an element rather than returning a null value.
   *
   * @return             TRUE if next would return an element rather than
   *                       returning a null value.
   */
   inline ASN1BOOL hasNext() { return ASN1BOOL(nextNode != 0); }

  /**
   * This method returns TRUE if this iterator has more elements when
   * traversing the list in the reverse direction.
   *
   * In other words, this method will return TRUE if prev would return an
   * element rather than returning a null value.
   *
   * @return             TRUE if next would return an element rather than
   *                       returning a null value.
   */ 
   inline ASN1BOOL hasPrev() { return ASN1BOOL(nextNode != 0); }
   
  /**
   * This method returns the next element in the list.
   *
   * This method may be called repeatedly to iterate through the list or
   * intermixed with calls to prev to go back and forth.
   *
   * @return             The next element in the list. A null value will be
   *                       returned if the iteration is not successful.
   */
   void* next();

  /**
   * This method returns the previous element in the list.
   *
   * This method may be called repeatedly to iterate through the list or
   * intermixed with calls to next to go back and forth.
   *
   * @param             - none
   * @return             The previous element in the list. A null value will be
   *                       returned if the iteration is not successful.
   */
   void* prev();

  /**
   * This method removes from the list the last element that was returned by
   * the next or prev methods.
   *
   * This call can only be made once per call to the next or prev methods.
   *
   * @param             - none
   * @return             Completion status of operation:
   *                       - 0 (ASN_OK) = success,
   *                       - negative return value is error.
   */
   int remove();

  /**
   * This method replaces the last element returned by the next or prev methods
   * with the specified element.
   *
   * This call can be made only if neither remove nor insert methods have been
   * called after the last call to next or prev methods.
   *
   * @param data         The element that replaces the last element returned by
   *                       the next or prev methods
   * @return             Completion status of operation:
   *                       - 0 (ASN_OK) = success,
   *                       - negative return value is error.
   */
   int set(void* data);

  /**
   * This method inserts the specified element into the list.
   *
   * The element is inserted immediately before the next element that would be
   * returned by the next method, if any, and after the next element would be
   * returned by the prev method, if any. If the list contains no elements, the
   * new element becomes the sole element in the list. The new element is
   * inserted before the implicit cursor: a subsequent call to next would be
   * unaffected, and a subsequent call to prev would return the new element.
   *
   * @param data         The element to be inserted
   * @return             Completion status of operation:
   *                       - 0 (ASN_OK) = success,
   *                       - negative return value is error.
   */
   int insert(void* data);

   /* Returns the state of iterator. ASN_OK if it is OK, ASN_E_* value otherwise */
   inline int getState () { return stat; }

 protected:
   inline void* operator new(size_t, void* data) { return data; }
#if !defined(__xlC__)
   inline void operator delete(void*, void*) {}
#endif
#ifndef __BORLANDC__
   inline void operator delete(void*, size_t) {}
#endif
} ;


//////////////////////////////////////////////////////////////////////
//
// ASN1CSeqOfList
//
/**
 * Doubly-linked list implementation. This class provides all functionality
 * necessary for linked list operations. It is the base class for ASN1C
 * compiler-generated ASN1C_ control classes for SEQUENCE OF and SET OF PDU
 * types.
 */
class EXTERNRT ASN1CSeqOfList : public ASN1CType {
   friend class ASN1CSeqOfListIterator;
 protected:
   Asn1RTDList* pList;           // list
   volatile int modCount;  // modification counter
   ASN1BOOL wasAssigned;

   // The following protected ctor could be used to perform lists' operation, 
   // which do not require the memory allocation.
   ASN1CSeqOfList (Asn1RTDList& lst);
   ASN1CSeqOfList (ASN1TSeqOfList& lst);
   ASN1CSeqOfList (ASN1TPDUSeqOfList& lst);

 public:

  /**
   * This constructor creates a linked list using the Asn1RTDList argument. The
   * constructor does not deep-copy the variable; it assigns a reference to it
   * to an external variable.
   *
   * The object will then directly operate on the given list variable.
   *
   * @param msgBuf           Reference to an ASN1Message buffer derived object
   *                           (for example, an ASN1BEREncodeBuffer).
   * @param lst              Reference to a linked list structure.
   * @param initBeforeUse    Set to TRUE if the passed linked list needs to be
   *                           initialized (rtDListInit to be called).
   */
   ASN1CSeqOfList (ASN1MessageBufferIF& msgBuf, Asn1RTDList& lst, 
      ASN1BOOL initBeforeUse = TRUE);

  /**
   * This constructor creates an empty linked list.
   *
   * @param msgBuf       Reference to an ASN1Message buffer derived object (for
   *                       example, an ASN1BEREncodeBuffer).
   */
   ASN1CSeqOfList (ASN1MessageBufferIF& msgBuf);

  /**
   * This constructor creates a linked list using the ASN1TSeqOfList (holder of
   * Asn1RTDList) argument.
   *
   * The construction does not deep-copy the variable, it assigns a reference
   * to it to an internal variable. The object will then directly operate on
   * the given list variable. This constructor is used with a
   * compiler-generated linked list variable.
   *
   * @param msgBuf       Reference to an ASN1Message buffer derived object (for
   *                       example, an ASN1BEREncodeBuffer).
   * @param lst          Reference to a linked list holder.
   */
   ASN1CSeqOfList (ASN1MessageBufferIF& msgBuf, ASN1TSeqOfList& lst);

  /**
   * This constructor creates a linked list using the ASN1TPDUSeqOfList 
   * argument.
   *
   * The construction does not deep-copy the variable, it assigns a reference
   * to it to an internal variable. The object will then directly operate on
   * the given list variable. This constructor is used with a
   * compiler-generated linked list variable.
   *
   * @param msgBuf       Reference to an ASN1Message buffer derived object (for
   *                       example, an ASN1BEREncodeBuffer).
   * @param lst          Reference to a linked list holder.
   */
   ASN1CSeqOfList (ASN1MessageBufferIF& msgBuf, ASN1TPDUSeqOfList& lst);

   ASN1CSeqOfList (ASN1Context& ctxt, Asn1RTDList& lst, 
      ASN1BOOL initBeforeUse = TRUE);
   ASN1CSeqOfList (ASN1Context& ctxt);
   ASN1CSeqOfList (ASN1Context& ctxt, ASN1TSeqOfList& lst);
   ASN1CSeqOfList (ASN1Context& ctxt, ASN1TPDUSeqOfList& lst);

   ~ASN1CSeqOfList();

   // Appends new list node with data
  /**
   * This method appends an item to the linked list.
   *
   * This item is represented by a void pointer that can point to an object of
   * any type. The rtMemAlloc function is used to allocate memory for the list
   * node structure, therefore, all internal list memory will be released
   * whenever rtMemFree is called.
   *
   * @param data         Pointer to a data item to be appended to the list.
   * @return             - none
   */
   void append(void* data);

   // Appends array to list data. Data won't be copied, just assigned.
  /**
   * This method appends array items' pointers to a doubly linked list.
   *
   * The rtMemAlloc function is used to allocate memory for the list node
   * structure, therefore all internal list memory will be released whenever
   * the rtMemFree is called. The data is not copied; it is just assigned to
   * the node.
   *
   * @param data         Pointer to source array to be appended to the list.
   * @param numElems     The number of elements in the source array.
   * @param elemSize     The size of one element in the array. Use the
   *                       <i>sizeof()</i> operator to pass this parameter.
   * @return             - none
   */
   void appendArray(const void* data, int numElems, int elemSize);

   // Appends array to list data. Data will be copied.
  /**
   * This method appends array items into a doubly linked list.
   *
   * The rtMemAlloc function is used to allocate memory for the list node
   * structure; therefore all internal list memory will be released whenever
   * rtMemFree is called. The data will be copied; the memory will be allocated
   * via rtMemAlloc.
   *
   * @param data         Pointer to source array to be appended to the list.
   * @param numElems     The number of elements in the source array.
   * @param elemSize     The size of one element in the array. Use the sizeof()
   *                       operator to pass this parameter.
   * @return             - none
   */
   void appendArrayCopy(const void* data, int numElems, int elemSize);

   // Inserts new list node at the specified index
  /**
   * This method insert an item into the linked list structure.
   *
   * The item is represented by a void pointer that can point to an object of
   * any type. The rtMemAlloc function is used to allocate memory for the list
   * node structure. All internal list memory will be released when the
   * rtMemFree function is called.
   *
   * @param index        Index at which the specified item is to be inserted.
   * @param data         Pointer to data item to be appended to the list.
   * @return             - none
   */
   void insert(int index, void* data);

   // Removes list node at specified index from the list 
  /**
   * This method removed a node at the specified index from the linked list
   * structure.
   *
   * The rtMemAlloc function was used to allocate the memory for the list node
   * structure, therefore, all internal list memory will be released whenever
   * the rtMemFree is called.
   *
   * @param index        Index of the item to be removed.
   * @return             - none
   */
   void remove(int index);

   // Removes  the first occurrence of the specified element in the list.
  /**
   * This method removes the first occurrence of the node with specified data
   * from the linked list structure.
   *
   * The rtMemAlloc function was used to allocate the memory for the list node
   * structure, therefore, all internal list memory will be released whenever
   * the rtMemFree function is called.
   *
   * @param data         - Pointer to the data item to be appended to the list.
   */
   void remove(void* data);

   // Removes the first element from the list.
  /**
   * This method removes the first node (head) from the linked list structure.
   *
   * @param             - none
   * @return             - none
   */
   inline void removeFirst() {
      remove(pList->head);
   }

   // Removes the last element from the list.
  /**
   * This method removes the last node (tail) from the linked list structure.
   *
   * @param             - none
   * @return             - none
   */
   inline void removeLast() {
      remove(pList->tail);
   }

   // Returns index of the list node with specified data
  /**
   * This method returns the index in this list of the first occurrence of the
   * specified item, or -1 if the list does not contain the time.
   *
   * @param data         - Pointer to data item to searched.
   * @return             The index in this list of the first occurrence of the
   *                       specified item, or -1 if the list does not contain
   *                       the item.
   */
   int indexOf(void* data) const;

   // Returns 'TRUE' if this list contains the specified element.
  /**
   * This method returns TRUE if this list contains the specified pointer. Note
   * that a match is not done on the <i>contents</i> of each data item (i.e.
   * what is pointed at by the pointer), only the pointer values.
   *
   * @param data         - Pointer to data item.
   * @return             TRUE if this pointer value found in the list.
   */
   inline ASN1BOOL contains (void* data) const {
      return indexOf(data) != -1;
   }

  /**
   * This method returns the first item from the list or null if there are no
   * elements in the list.
   *
   * @return             The first item of the list.
   */
   void* getFirst();

  /**
   * This method returns the last item from the list or null if there are no
   * elements in the list.
   *
   * @return             The last item in the list.
   */
   void* getLast();

   // Returns element at specified index
  /**
   * This method returns the item at the specified position in the list.
   *
   * @param index        Index of the item to be returned.
   * @return             The item at the specified index in the list.
   */
   void* get(int index) const;

   // Sets data to list node at the specified index
  /**
   * This method replaces the item at the specified index in this list with the
   * specified item.
   *
   * @param index        The index of the item to be replaced.
   * @param data         The item to be stored at the specified index.
   * @return             The item previously at the specified position.
   */
   void* set(int index, void* data);

   // Clears list
  /**
   * This method removes all items from the list.
   *

   */
   void clear();

   // Clears and frees list
   void freeAll();

   // Returns TRUE, if list is empty
  /**
   * This method returns TRUE if the list is empty.
   *
   * @return             TRUE if this list is empty.
   */
   ASN1BOOL isEmpty() const;

   // Returns the number of list's nodes
  /**
   * This method returns the number of nodes in the list.
   *
   * @return             The number of items in this list.
   */
   int size() const;

   // Creates iterator from the head of the list
  /**
   * This method returns an iterator over the elements in the linked list in
   * the sequence from the fist to the last.
   *
   * @return                        The iterator over this linked list.

   */
   ASN1CSeqOfListIterator* iterator();

   // Creates iterator from the tail of the list
  /**
   * This method creates a reverse iterator over the elements in this linked
   * list in the sequence from last to first.
   *
   * @param                        - none
   * @return                        The reverse iterator over this linked list.

   */
   ASN1CSeqOfListIterator* iteratorFromLast();

   // Creates iterator from the node with specified data
  /**
   * This method runs an iterator over the elements in this linked list
   * starting from the specified item in the list.
   *
   * @param data                    The item of the list to be iterated first.
   * @return                        The iterator over this linked list.

   */
   ASN1CSeqOfListIterator* iteratorFrom(void* data);

   // Converts to array
  /**
   * This method converts the linked list into a new array.
   *
   * The rtMemAlloc function is used to allocate memory for an array.
   *
   * @param elemSize     The size of one element in the array. Use the
   *                       <i>sizeof()</i> operator to pass this parameter.
   * @return             The point to converted array.
   */
   void* toArray (int elemSize);
   
   // Converts to array
  /**
   * This method converts the linked list into an array.
   *
   * The rtMemAlloc function is used to allocate memory for the array if the
   * capacity of the specified array is exceeded.
   *
   * @param pArray            Pointer to destination array.
   * @param elemSize          The size of one element in the array. Use the
   *                            sizeof() operator to pass this parameter.
   * @param allocatedElems    The number of elements already allocated in the
   *                            array. If this number is less than the number
   *                            of nodes in the list, then a new array is
   *                            allocated and returned. Memory is allocated
   *                            using rtMemAlloc function.
   * @return                  The pointer to the converted array.
   */
   void* toArray (void* pArray, int elemSize, int allocatedElems);
   
   // Returns element at specified index
  /**
   * This method is the overloaded operator[].
   *
   * It returns the item at the specified position in the list.
   *
   * @see get           (int index)
   */
   inline void* operator[](int index) const {
      return get(index);
   }

   inline operator Asn1RTDList* () {
      return pList;
   }
 protected: 
   // Removes specified node from the list
   void remove(Asn1RTDListNode* node);

   // Inserts new node ('data') before another node ('node')
   void insertBefore(void* data, Asn1RTDListNode* node);

   // Inserts new node ('data') after another node ('node')
   void insertAfter(void* data, Asn1RTDListNode* node);


} ;
#else
typedef class _ASN1CSeqOfList : public ASN1CType {
 public:
   _ASN1CSeqOfList (ASN1MessageBufferIF& msgBuf, Asn1RTDList& lst, 
      ASN1BOOL initBeforeUse = TRUE) : ASN1CType (msgBuf) {}
   _ASN1CSeqOfList (ASN1MessageBufferIF& msgBuf, ASN1TSeqOfList& lst) :
      ASN1CType (msgBuf) {}
   _ASN1CSeqOfList (ASN1MessageBufferIF& msgBuf) : ASN1CType (msgBuf) {}
} ASN1CSeqOfList;

/**
 * @}
 */
#endif // _NO_UTILS_CLASSES
#endif // _ASN1CSEQOFLIST_H_
