/** 
 *  @author   ETSI
 *  @version  $URL$
 *            $Id$
 *  @desc     A collection of functions for abstract data types which may be
 *            useful in the implementation of any TTCN-3 test suite.
 *  @remark   End users should be aware that any changes made to the  in
 *            definitions this module may be overwritten in future releases.
 *            End users are encouraged to contact the distributers of this
 *            module regarding their modifications or additions so that future
 *            updates will include your changes.
 *  @copyright  ETSI Copyright Notification
 *                No part may be reproduced except as authorized by written permission.
 *                The copyright and the foregoing restriction extend to reproduction in all media.
 *                All rights reserved.
 *
 */
 module LibCommon_AbstractData {

  import from LibCommon_BasicTypesAndValues all;

  group stringStack {

    type record StringStack {
      UInt        stackSize,
      StringItems stringItems
    }

    type record of charstring StringItems;

    /**
     * @desc    Constant which can be used to initialize a
     *          string stack. A string stack can be intialized by
     *          assigning this value in the variable declariation.
     *          An alternative is to call the initlialization function.
     * @see     LibCommon_AbstractData.f_initStringStack
     * @remark  Note that an initlialized stack stack is not
     *          necessarily the same as an empty string stack.
     *          An empty tring stack as 0 zero elements but may
     *          have a non empty list of (empty) items.
     */
    const StringStack c_initStringStack := { 0, {} }

    /**
     * @desc    The invocation of this function will initialize
     *          a string stack to an empty string stack.
     *          An alternative is to initlialize a stack using a
     *          constant value.
     * @see     LibCommon_AbstractData.c_initStringStack
     * @param   p_stack String stack to be initialized.
     */
    function f_initStringStack ( inout StringStack p_stack ) {
      p_stack := c_initStringStack
    }

    /**
     * @desc    This function checks if a string stack is empty.
     * @param   p_stack String stack to be checked.
     * @return  true if empty, false if not empty
     */
    function f_isStringStackEmpty ( inout StringStack p_stack )
    return boolean {
      if ( p_stack.stackSize == 0 ) {return true}
      else {return false}
    }

    /**
     * @desc    This function checks if a given string is on the
     *          string stack.
     * @param   p_stack String stack where the string item
     *          is to be looked for.
     * @param   p_item  String to be checked for.
     * @return  true if found, false if not found
     */
    function f_isItemOnStringStack ( inout StringStack p_stack,
                       in    charstring  p_item )
    return boolean {
      var integer i;
      for (i := 0; i < p_stack.stackSize; i := i+1 ) {
        if ( p_stack.stringItems[i] == p_item ) {
          return true;
        }
      }
      return false;
    }

    /**
     * @desc    This function checks if a given string is on the
     *          string stack.
     * @param   p_stack String stack where the string item
     *          is to be looked for.
     * @param   p_item  String item on top of the stack.
     * @return  false if stack is empty, true otherwise
     */
    function f_peekStringStackTop ( inout StringStack p_stack,
                    out   charstring  p_item)
    return boolean {
      if (p_stack.stackSize == 0) {
        p_item := "f_peekTopStringStack: String stack is empty!";
        return false;
      }
      p_item := valueof(p_stack.stringItems[p_stack.stackSize-1]);
      return true;
    }


    /**
     * @desc    This function puts a string to the top of a
     *          string stack.
     * @param   p_stack String stack to which the string item
     *          is to be added.
     * @param   p_item  String to be added.
     */
    function f_pushStringStack ( inout StringStack p_stack,
                   in    charstring  p_item ) {
      p_stack.stringItems[p_stack.stackSize] := p_item;
      p_stack.stackSize := p_stack.stackSize + 1;
    }

    /**
     * @desc    This function removes the string from the top of a
     *          string stack. If the stack is empty nothing is done
     * @param   p_stack String stack from which the top string item
     *          is to be removed.
     */
    function f_popStringStack ( inout StringStack p_stack ) {
            if ( p_stack.stackSize > 0 ) {
        p_stack.stackSize := p_stack.stackSize-1;
        // "delete" top stack item to be safe
        // Note: due to record of index the "old top" is size-1!
        p_stack.stringItems[p_stack.stackSize] := "";
      }
    }

  } // end group stringStack

} // end module LibCommon_AbstractData
