OpenTTCN/Developer corner/Implementing external functions/Final/C/PA impl.cxx
From OpenTTCN
Home | Developer's corner | Knowledge base | Working documents | Documentation | OpenTTCN IDE | Tutorials | Training | How do I | Frequently asked questions | Technical support |
PA_impl.cxx
#include <tri/tri.h>
#include <isl/TTCN3.h>
#include <stdio.h>
#include <stdlib.h>
#include <map>
#include <string>
/***************************************************************************
* Forward declarations of external functions implemented in the following
* sections of code in this file.
*/
TriStatus ef_calc_sum(const TriFunctionId* functionId,
TriParameterList* parameterList, TriParameter* returnValue);
TriStatus ef_calc_sub(const TriFunctionId* functionId,
TriParameterList* parameterList, TriParameter* returnValue);
TriStatus ef_calc_mul(const TriFunctionId* functionId,
TriParameterList* parameterList, TriParameter* returnValue);
TriStatus ef_calc_div(const TriFunctionId* functionId,
TriParameterList* parameterList, TriParameter* returnValue);
TriStatus ef_find_and_replace(const TriFunctionId* functionId,
TriParameterList* parameterList, TriParameter* returnValue);
/***************************************************************************
* Initialization of TRI interface (PA, user-provided part).
*/
typedef TriStatus (*ExtFuncPtr)(
const TriFunctionId*, TriParameterList*, TriParameter*);
// Key is function name, value is function pointer implementing the
// external function with the specified name.
typedef std::map<std::string, ExtFuncPtr> ExtFuncMapType;
// Contains mappings of available external function implementations.
static ExtFuncMapType _extFuncMap;
void initializePA()
{
_extFuncMap["ef_calc_sum"] = &ef_calc_sum;
_extFuncMap["ef_calc_sub"] = &ef_calc_sub;
_extFuncMap["ef_calc_mul"] = &ef_calc_mul;
_extFuncMap["ef_calc_div"] = &ef_calc_div;
_extFuncMap["ef_find_and_replace"] = &ef_find_and_replace;
}
/***************************************************************************
* Implementation of TRI interface (PA, user-provided part).
*/
TriStatus triExternalFunction
(const TriFunctionId* functionId, /* in parameter */
TriParameterList* parameterList, /* inout parameter */
TriParameter* returnValue /* out parameter */)
{
std::string funcId = functionId->objectName;
printf("**************************************************************************\n");
printf("*** DEBUG: triExternalFunction() callback called. Function: %s\n", funcId.c_str());
ExtFuncMapType::iterator iter = _extFuncMap.find(funcId);
if (iter != _extFuncMap.end())
{
return (*(iter->second))(functionId, parameterList, returnValue);
}
std::string errMsg = "Unrecognized external function " + funcId + " called.";
otReportError(errMsg.c_str());
return TRI_ERROR;
}
/***************************************************************************
* External function implementation helpers.
*/
long triParameterToLong(TriParameter* src)
{
return *((long *) src->par.data);
}
void assignLongToTriParameter(TriParameter* dst, long src)
{
int len = sizeof(long);
dst->par.data = (unsigned char *) malloc(len);
memcpy(dst->par.data, &src, len);
dst->par.bits = len << 3;
}
std::string triParameterToString(TriParameter* src)
{
long str_len =
(((unsigned long) src->par.data[0]) << 8) |
(((unsigned long) src->par.data[1]) << 0);
return std::string((const char *) (src->par.data + 2), str_len);
}
void assignStringToTriParameter(TriParameter* dst, const std::string& src)
{
long str_len = (long) src.size();
dst->par.data = (unsigned char *) malloc(str_len + 2);
dst->par.bits = (str_len + 2) << 3;
// String length, most significant byte first:
dst->par.data[0] = (unsigned char) (str_len >> 8);
dst->par.data[1] = (unsigned char) (str_len >> 0);
// String data:
memcpy(dst->par.data + 2, src.c_str(), str_len);
}
/***************************************************************************
* External function implementations.
*/
TriStatus ef_calc_sum(const TriFunctionId* functionId,
TriParameterList* parameterList, TriParameter* returnValue)
{
TriParameter** pars = parameterList->parList;
assignLongToTriParameter(returnValue,
triParameterToLong(pars[0]) + triParameterToLong(pars[1]));
return TRI_OK;
}
TriStatus ef_calc_sub(const TriFunctionId* functionId,
TriParameterList* parameterList, TriParameter* returnValue)
{
TriParameter** pars = parameterList->parList;
assignLongToTriParameter(returnValue,
triParameterToLong(pars[0]) - triParameterToLong(pars[1]));
return TRI_OK;
}
TriStatus ef_calc_mul(const TriFunctionId* functionId,
TriParameterList* parameterList, TriParameter* returnValue)
{
TriParameter** pars = parameterList->parList;
assignLongToTriParameter(returnValue,
triParameterToLong(pars[0]) * triParameterToLong(pars[1]));
return TRI_OK;
}
TriStatus ef_calc_div(const TriFunctionId* functionId,
TriParameterList* parameterList, TriParameter* returnValue)
{
TriParameter** pars = parameterList->parList;
assignLongToTriParameter(returnValue,
triParameterToLong(pars[0]) / triParameterToLong(pars[1]));
return TRI_OK;
}
void ef_find_and_replace_helper(
std::string& str /* inout */,
const std::string& search_substr /* in */,
const std::string& new_substr /* in */,
long& occurences_num /* out */)
{
int i, len;
int substr_size = (int) search_substr.size();
if (substr_size != new_substr.size())
{
otReportError("Strings size mismatch in ef_find_and_replace().");
return;
}
if (!substr_size)
{
otReportError("Search string size is zero in ef_find_and_replace().");
return;
}
occurences_num = 0;
if (substr_size > (int) str.size())
{
// No way bigger string can be a substring of the smaller one:
return;
}
len = ((int) str.size()) - substr_size;
for (i = 0; i <= len; i++)
{
if (str.substr(i, substr_size) == search_substr)
{
str.replace(i, substr_size, new_substr);
occurences_num++;
i += substr_size - 1;
}
}
}
TriStatus ef_find_and_replace(const TriFunctionId* functionId,
TriParameterList* parameterList, TriParameter* returnValue)
{
TriParameter** pars = parameterList->parList;
std::string str = triParameterToString(pars[0]);
std::string search_substr = triParameterToString(pars[1]);
std::string new_substr = triParameterToString(pars[2]);
long occurences_num = -1;
ef_find_and_replace_helper(
str, search_substr, new_substr, occurences_num);
// It is safe to assume that inout str always changes:
free(pars[0]->par.data);
assignStringToTriParameter(pars[0], str);
// Perform mandatory assignment of occurences_num out parameter:
assignLongToTriParameter(pars[3], occurences_num);
// Duplicate occurences_num in the return value:
assignLongToTriParameter(returnValue, occurences_num);
return TRI_OK;
}
