blob: 5185584cf7a17e0edf26a2f3a18e965d669ed5ff [file] [log] [blame]
///////////////////////////////////////////////////////////////////////////////
// //
// Copyright (c) 2000-2019 Ericsson Telecom AB //
// //
// All rights reserved. This program and the accompanying materials //
// are made available under the terms of the Eclipse Public License v2.0 //
// which accompanies this distribution, and is available at //
// https://www.eclipse.org/org/documents/epl-2.0/EPL-2.0.html //
///////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////
// Module: EPTF_CLL_GenericRingBuffer_Functions
//
// Purpose:
// This module provides the interface of generic ring buffer container.
// The public functions are defined by macros.
//
// Module Parameters:
// (none)
//
// Module depends on:
// <EPTF_CLL_RingBuffer_Definitions>
// <EPTF_CLL_GenericRingBuffer_Definitions>
//
// Current Owner:
// Istvan Falusi (eistfal)
//
// Last Review Date:
// 2007-11-19
//
// Detailed Comments:
// The Makefile Generator treats this file as TTCN-3 include file. The .ttcnin file will be
// added to the Makefile as special TTCN-3 include file which will not be translated by the
// compiler, but will be checked for modification when building the test suite.
//
// Previous definition of <EPTF_BASE_TYPE> macro (type of buffered items) in a .ttcnpp file
// is a precondition of using this ring buffer implementation as a TTCN-3 include!
// (p.e.
//
// #define EPTF_BASE_TYPE *UserType*
//
// )
// This macro sets the <EPTF_BASE_TYPE> as the user type *UserType*.
// An appropriate TTCN-3 types module must also be provided (and imported into the .ttncpp module)
// by the user with the type definition of *UserType*:
//
// type record of integer *UserType*;
//
//////////////////////////////////////////////////////////////////////////////////////////////////
#include "EPTF_CLL_GenericRingBuffer_Definitions.ttcnin"
#ifndef EPTF_BASE_TYPE
#error "undefined EPTF_BASE_TYPE"
#endif
/////////////////////////////////////////////////////////////////////////////////////////////////
// Function: f_EPTF_##EPTF_BASE_TYPE##_RB_init
//
// Purpose:
// Function to initialise an empty <EPTF_BASE_TYPE##RingBuffer>.
//
// Parameters:
// pl_buffer - *inout* <EPTF_BASE_TYPE##RingBuffer> - the ring buffer to be initialized
// pl_capacity - *in* <integer> - the maximum nuber of elements can be stored in the buffer
//
// Return Value:
// -
//
// Detailed Comments:
// The default value of <pl_capacity> is defined by <c_EPTF_RB_default_capacity> constant.
//
/////////////////////////////////////////////////////////
#define F_INIT_RB_(TYPEARG) \
public function f_EPTF_##TYPEARG##_RB_init( \
inout TYPEARG##RingBuffer pl_buffer, \
in integer pl_capacity := c_EPTF_RB_default_capacity \
) \
{ \
pl_buffer.data := {}; \
pl_buffer.status := c_EPTF_emptyRingBufferStatus; \
if (pl_capacity > 0) \
{ \
pl_buffer.status.capacity := pl_capacity; \
} \
f_EPTF_##TYPEARG##_RB_clear(pl_buffer) \
}
#define F_INIT_RB(TYPEARG) F_INIT_RB_(TYPEARG)
F_INIT_RB(EPTF_BASE_TYPE)
/////////////////////////////////////////////////////////////////////////////////////////////////
// Function: f_EPTF_##EPTF_BASE_TYPE##_RB_size
//
// Purpose:
// Function to ask the size of the buffer.
//
// Parameters:
// pl_buffer - *in* <EPTF_BASE_TYPE##RingBuffer> - the ring buffer
//
// Return Value:
// *integer* - the number of stored elements.
//
/////////////////////////////////////////////////////////
#define F_SIZE_RB_(TYPEARG) \
public function f_EPTF_##TYPEARG##_RB_size( \
in TYPEARG##RingBuffer pl_buffer \
) return integer \
{ \
return pl_buffer.status.content_size; \
}
#define F_SIZE_RB(TYPEARG) F_SIZE_RB_(TYPEARG)
F_SIZE_RB(EPTF_BASE_TYPE)
/////////////////////////////////////////////////////////////////////////////////////////////////
// Function: f_EPTF_##EPTF_BASE_TYPE##_RB_capacity
//
// Purpose:
// Function to ask the capacity of the buffer.
//
// Parameters:
// pl_buffer - *in* <EPTF_BASE_TYPE##RingBuffer> - the ring buffer
//
// Return Value:
// *integer* - the possible maximum nuber of elements can be stored in the buffer.
//
/////////////////////////////////////////////////////////
#define F_CAPACITY_RB_(TYPEARG) \
public function f_EPTF_##TYPEARG##_RB_capacity( \
in TYPEARG##RingBuffer pl_buffer \
) return integer \
{ \
return pl_buffer.status.capacity; \
}
#define F_CAPACITY_RB(TYPEARG) F_CAPACITY_RB_(TYPEARG)
F_CAPACITY_RB(EPTF_BASE_TYPE)
/////////////////////////////////////////////////////////////////////////////////////////////////
// Function: f_EPTF_##EPTF_BASE_TYPE##_RB_empty
//
// Purpose:
// Checks whether the buffer is empty.
//
// Parameters:
// pl_buffer - *in* <EPTF_BASE_TYPE##RingBuffer> - the ring buffer
//
// Return Value:
// *boolean* - true, if the buffer is empty, otherwise false.
//
/////////////////////////////////////////////////////////
#define F_EMPTY_RB_(TYPEARG) \
public function f_EPTF_##TYPEARG##_RB_empty( \
in TYPEARG##RingBuffer pl_buffer \
) return boolean \
{ \
return (pl_buffer.status.content_size == 0); \
}
#define F_EMPTY_RB(TYPEARG) F_EMPTY_RB_(TYPEARG)
F_EMPTY_RB(EPTF_BASE_TYPE)
/////////////////////////////////////////////////////////////////////////////////////////////////
// Function: f_EPTF_##EPTF_BASE_TYPE##_RB_front
//
// Purpose:
// Function to get the first (eldest) element from the buffer.
//
// Parameters:
// pl_buffer - *in* <EPTF_BASE_TYPE##RingBuffer> - the ring buffer
//
// Return Value:
// <EPTF_BASE_TYPE> - the head of the buffer.
//
// Detailed Comments:
// IMPORTANT NOTE: the function does not perform boundary check.
// On empty buffer the operstion leads to undefined behaviour.
//
/////////////////////////////////////////////////////////////
#define F_FRONT_RB_(TYPEARG) \
public function f_EPTF_##TYPEARG##_RB_front( \
in TYPEARG##RingBuffer pl_buffer \
) return TYPEARG \
{ \
return pl_buffer.data[pl_buffer.status.head]; \
}
#define F_FRONT_RB(TYPEARG) F_FRONT_RB_(TYPEARG)
F_FRONT_RB(EPTF_BASE_TYPE)
/////////////////////////////////////////////////////////////////////////////////////////////////
// Function: f_EPTF_##EPTF_BASE_TYPE##_RB_back
//
// Purpose:
// Function to get the last (latest) element from the buffer.
//
// Parameters:
// pl_buffer - *in* <EPTF_BASE_TYPE##RingBuffer> - the ring buffer
//
// Return Value:
// <EPTF_BASE_TYPE> - the tail of the buffer.
//
// Detailed Comments:
// IMPORTANT NOTE: the function does not perform boundary check.
// On empty buffer the operation leads to undefined behaviour.
//
/////////////////////////////////////////////////////////////
#define F_BACK_RB_(TYPEARG) \
public function f_EPTF_##TYPEARG##_RB_back( \
in TYPEARG##RingBuffer pl_buffer \
) return TYPEARG \
{ \
return(pl_buffer.data[pl_buffer.status.tail]); \
}
#define F_BACK_RB(TYPEARG) F_BACK_RB_(TYPEARG)
F_BACK_RB(EPTF_BASE_TYPE)
/////////////////////////////////////////////////////////////////////////////////////////////////
// Function: f_EPTF_##EPTF_BASE_TYPE##_RB_push_back
//
// Purpose:
// Function to store a new data item at end of buffer.
//
// Parameters:
// pl_buffer - *in* <EPTF_BASE_TYPE##RingBuffer> - the ring buffer
//
// pl_dataItem - *in* <EPTF_BASE_TYPE> - the data item to be stored
//
// Return Value:
// -
//
// Detailed Comments:
// The operation is always possible. If buffer is full,
// the first data item (item at beginning of buffer) is overwritten.
//
//////////////////////////////////////////////////////////////////////
#define F_PUSH_BACK_RB_(TYPEARG) \
public function f_EPTF_##TYPEARG##_RB_push_back( \
inout TYPEARG##RingBuffer pl_buffer, \
in TYPEARG pl_dataItem \
) \
{ \
f_EPTF_RB_increment_tail(pl_buffer.status); \
pl_buffer.data[pl_buffer.status.tail] := pl_dataItem; \
if (pl_buffer.status.content_size > pl_buffer.status.capacity) \
{ \
f_EPTF_RB_increment_head(pl_buffer.status); \
} \
}
#define F_PUSH_BACK_RB(TYPEARG) F_PUSH_BACK_RB_(TYPEARG)
F_PUSH_BACK_RB(EPTF_BASE_TYPE)
/////////////////////////////////////////////////////////////////////////////////////////////////
// Function: f_EPTF_##EPTF_BASE_TYPE##_RB_push_front
//
// Purpose:
// Function to store a new data item at beginning of the buffer.
//
// Parameters:
// pl_buffer - *in* <EPTF_BASE_TYPE##RingBuffer> - the ring buffer
//
// pl_dataItem - *in* <EPTF_BASE_TYPE> - the data item to be stored
//
// Return Value:
// -
//
// Detailed Comments:
// The operation is always possible. If buffer is full,
// the last data item is (item at end of buffer) overwritten.
//
//////////////////////////////////////////////////////////////////////
#define F_PUSH_FRONT_RB_(TYPEARG) \
public function f_EPTF_##TYPEARG##_RB_push_front( \
inout TYPEARG##RingBuffer pl_buffer, \
in TYPEARG pl_dataItem \
) \
{ \
f_EPTF_RB_decrement_head(pl_buffer.status); \
pl_buffer.data[pl_buffer.status.head] := pl_dataItem; \
if (pl_buffer.status.content_size > pl_buffer.status.capacity) \
{ \
f_EPTF_RB_decrement_tail(pl_buffer.status); \
} \
}
#define F_PUSH_FRONT_RB(TYPEARG) F_PUSH_FRONT_RB_(TYPEARG)
F_PUSH_FRONT_RB(EPTF_BASE_TYPE)
/////////////////////////////////////////////////////////////////////////////////////////////////
// Function: f_EPTF_##EPTF_BASE_TYPE##_RB_pop_front
//
// Purpose:
// Function to drop the first data item.
//
// Parameters:
// pl_buffer - *in* <EPTF_BASE_TYPE##RingBuffer> - the ring buffer
//
// pl_dataItem - *in* <EPTF_BASE_TYPE> - the data item to be stored
//
// Return Value:
// -
//
//////////////////////////////////////////////////////////////
#define F_POP_FRONT_RB_(TYPEARG) \
public function f_EPTF_##TYPEARG##_RB_pop_front( \
inout TYPEARG##RingBuffer pl_buffer \
) \
{ \
if (pl_buffer.status.content_size != 0) \
{ \
f_EPTF_RB_increment_head(pl_buffer.status); \
} \
}
#define F_POP_FRONT_RB(TYPEARG) F_POP_FRONT_RB_(TYPEARG)
F_POP_FRONT_RB(EPTF_BASE_TYPE)
/////////////////////////////////////////////////////////////////////////////////////////////////
// Function: f_EPTF_##EPTF_BASE_TYPE##_RB_pop_back
//
// Purpose:
// Function to drop the last data item.
//
// Parameters:
// pl_buffer - *in* <EPTF_BASE_TYPE##RingBuffer> - the ring buffer
//
// pl_dataItem - *in* <EPTF_BASE_TYPE> - the data item to be stored
//
// Return Value:
// -
//
//////////////////////////////////////////////////////////////
#define F_POP_BACK_RB_(TYPEARG) \
public function f_EPTF_##TYPEARG##_RB_pop_back( \
inout TYPEARG##RingBuffer pl_buffer \
) \
{ \
if (pl_buffer.status.content_size != 0) \
{ \
f_EPTF_RB_decrement_tail(pl_buffer.status); \
} \
}
#define F_POP_BACK_RB(TYPEARG) F_POP_BACK_RB_(TYPEARG)
F_POP_BACK_RB(EPTF_BASE_TYPE)
/////////////////////////////////////////////////////////////////////////////////////////////////
// Function: f_EPTF_##EPTF_BASE_TYPE##_RB_clear
//
// Purpose:
// Function to remove all data from the buffer.
//
// Parameters:
// pl_buffer - *inout* <EPTF_BASE_TYPE##RingBuffer> - the ring buffer
//
// Return Value:
// -
//
//////////////////////////////////////////////////////////
#define F_CLEAR_RB_(TYPEARG) \
public function f_EPTF_##TYPEARG##_RB_clear( \
inout TYPEARG##RingBuffer pl_buffer \
) \
{ \
pl_buffer.status.head := 0; \
pl_buffer.status.tail := pl_buffer.status.capacity - 1; \
pl_buffer.status.content_size := 0; \
}
#define F_CLEAR_RB(TYPEARG) F_CLEAR_RB_(TYPEARG)
F_CLEAR_RB(EPTF_BASE_TYPE)
/////////////////////////////////////////////////////////////////////////////////////////////////
// Function: f_EPTF_##EPTF_BASE_TYPE##_RB_get
//
// Purpose:
// Function to perform an unchecked random access to the buffer.
//
// Parameters:
// pl_buffer - *inout* <EPTF_BASE_TYPE##RingBuffer> - the ring buffer
//
// pl_index - *in* *integer* - the index of desired data item
//
// Return Value:
// <EPTF_BASE_TYPE> - the data item at the given index.
//
// Detailed Comments:
// - IMPORTANT NOTE: the function does not perform boundary check.
// If index is invalid the operation leads to undefined behaviour.
// - The index of the first (eldest) item is 0.
//
//////////////////////////////////////////////////////////
#define F_GET_RB_(TYPEARG) \
public function f_EPTF_##TYPEARG##_RB_get( \
in TYPEARG##RingBuffer pl_buffer, \
in integer pl_index \
) return TYPEARG \
{ \
return( pl_buffer.data[ (pl_buffer.status.head + pl_index) mod pl_buffer.status.capacity ] );\
}
#define F_GET_RB(TYPEARG) F_GET_RB_(TYPEARG)
F_GET_RB(EPTF_BASE_TYPE)
/////////////////////////////////////////////////////////////////////////////////////////////////
// Function: f_EPTF_##EPTF_BASE_TYPE##_RB_at
//
// Purpose:
// Function to perform a secure access to the buffer.
//
// Parameters:
// pl_buffer - *inout* <EPTF_BASE_TYPE##RingBuffer> - the ring buffer
//
// pl_index - *in* *integer* - the index of desired data item
//
// pl_dataItem - *out* <EPTF_BASE_TYPE> - the data item at the given index.
//
// Return Value:
// *boolean* - false, if index is invalid, otherwise true.
//
// Detailed Comments:
// - The function performs boundary check.
// - The index of the first (eldest) item is 0.
//
///////////////////////////////////////////////////////////////////////////
#define F_AT_RB_(TYPEARG) \
public function f_EPTF_##TYPEARG##_RB_at( \
in TYPEARG##RingBuffer pl_buffer, \
in integer pl_index, \
out TYPEARG pl_dataItem \
) return boolean \
{ \
if (pl_index < 0 or pl_index >= f_EPTF_##TYPEARG##_RB_size(pl_buffer)) \
{ \
return false; \
} \
pl_dataItem := f_EPTF_##TYPEARG##_RB_get(pl_buffer, pl_index); \
return true; \
}
#define F_AT_RB(TYPEARG) F_AT_RB_(TYPEARG)
F_AT_RB(EPTF_BASE_TYPE)
/////////////////////////////////////////////////////////////////////////////////////////////////
// Function: f_EPTF_##EPTF_BASE_TYPE##_RB_dump
//
// Purpose:
// Function to dump the content of the buffer into a list.
//
// Parameters:
// pl_buffer - *in* <EPTF_BASE_TYPE##RingBuffer> - the ring buffer to be dumped
//
// pl_dest - *out* <EPTF_BASE_TYPE##List> - the destination array
//
// Return Value:
// -
//
/////////////////////////////////////////////////////////////////////////
#define F_DUMP_RB_(TYPEARG) \
public function f_EPTF_##TYPEARG##_RB_dump( \
in TYPEARG##RingBuffer pl_buffer, \
out TYPEARG##List pl_dest \
) \
{ \
pl_dest:= {}; \
for (var integer i:=0; i<pl_buffer.status.content_size; i:= i+1) \
{ \
pl_dest[i] := pl_buffer.data[(pl_buffer.status.head + i) mod pl_buffer.status.capacity];\
} \
}
#define F_DUMP_RB(TYPEARG) F_DUMP_RB_(TYPEARG)
F_DUMP_RB(EPTF_BASE_TYPE)
//=========================================================================
// Private Functions
//=========================================================================
///////////////////////////////////////////////////////////
// Function: f_EPTF_RB_increment_tail
//
// Purpose:
// Function to increment the tail of a ring buffer.
//
// Parameters:
// pl_status - *inout* <EPTF_RingBufferStatus> - the status structure of ring buffer to be modified
//
// Return Value:
// -
//
///////////////////////////////////////////////////////////
private function f_EPTF_RB_increment_tail( inout EPTF_RingBufferStatus pl_status )
{
pl_status.content_size := pl_status.content_size + 1;
pl_status.tail := (pl_status.tail + 1) mod pl_status.capacity;
}
///////////////////////////////////////////////////////////
// Function: f_EPTF_RB_increment_head
//
// Purpose:
// Function to increment the head of a ring buffer.
//
// Parameters:
// pl_status - *inout* <EPTF_RingBufferStatus> - the status structure of ring buffer to be modified
//
// Return Value:
// -
//
// Detailed Comments:
// Precondition of calling this function: ring buffer is not empty.
//
///////////////////////////////////////////////////////////
private function f_EPTF_RB_increment_head( inout EPTF_RingBufferStatus pl_status )
{
pl_status.head := (pl_status.head + 1) mod pl_status.capacity;
pl_status.content_size := pl_status.content_size - 1;
}
///////////////////////////////////////////////////////////
// Function: f_EPTF_RB_decrement_tail
//
// Purpose:
// Function to decrement the tail of a ring buffer.
//
// Parameters:
// pl_status - *inout* <EPTF_RingBufferStatus> - the status structure of ring buffer to be modified
//
// Return Value:
// -
//
// Detailed Comments:
// Precondition of calling this function: ring buffer is not empty.
//
///////////////////////////////////////////////////////////
private function f_EPTF_RB_decrement_tail( inout EPTF_RingBufferStatus pl_status )
{
pl_status.tail := (pl_status.tail - 1) mod pl_status.capacity;
pl_status.content_size := pl_status.content_size - 1;
}
///////////////////////////////////////////////////////////
// Function: f_EPTF_RB_decrement_head
//
// Purpose:
// Function to decrement the head of a ring buffer.
//
// Parameters:
// pl_status - *inout* <EPTF_RingBufferStatus> - the status structure of ring buffer to be modified
//
// Return Value:
// -
//
///////////////////////////////////////////////////////////
private function f_EPTF_RB_decrement_head( inout EPTF_RingBufferStatus pl_status )
{
pl_status.content_size := pl_status.content_size + 1;
pl_status.head := (pl_status.head - 1) mod pl_status.capacity;
}