Project

General

Profile

Statistics
| Branch: | Revision:

root / src / scave / customfilter.cc @ a3be1d55

History | View | Annotate | Download (3.75 KB)

1
//=========================================================================
2
//  CUSTOMFILTER.CC - part of
3
//                  OMNeT++/OMNEST
4
//           Discrete System Simulation in C++
5
//
6
//  Author: Andras Varga
7
//
8
//=========================================================================
9

    
10
/*--------------------------------------------------------------*
11
  Copyright (C) 1992-2008 Andras Varga
12
  Copyright (C) 2006-2008 OpenSim Ltd.
13

14
  This file is distributed WITHOUT ANY WARRANTY. See the file
15
  `license' for details on this and other legal matters.
16
*--------------------------------------------------------------*/
17

    
18
#include <math.h>
19
#include "channel.h"
20
#include "customfilter.h"
21
#include "scaveutils.h"
22

    
23
USING_NAMESPACE
24

    
25

    
26

    
27
/**
28
 * Resolves variables (x, y) and functions (sin, fabs, etc) in
29
 * ExpressionFilterNode expressions.
30
 */
31
class Resolver : public Expression::Resolver
32
{
33
  private:
34
    ExpressionFilterNode *hostnode;
35
  public:
36
    Resolver(ExpressionFilterNode *node) {hostnode = node;}
37
    virtual ~Resolver() {};
38
    virtual Expression::Functor *resolveVariable(const char *varname);
39
    virtual Expression::Functor *resolveFunction(const char *funcname, int argcount);
40
};
41

    
42
Expression::Functor *Resolver::resolveVariable(const char *varname)
43
{
44
    if (strcmp(varname, "t")==0 || strcmp(varname, "y")==0 || strcmp(varname, "tprev")==0 || strcmp(varname, "yprev")==0)
45
        return new ExpressionFilterNode::NodeVar(hostnode, varname);
46
    else
47
        throw opp_runtime_error("Unrecognized variable: %s", varname);
48
}
49

    
50
Expression::Functor *Resolver::resolveFunction(const char *funcname, int argcount)
51
{
52
    //FIXME check argcount!
53
    if (MathFunction::supports(funcname))
54
        return new MathFunction(funcname);
55
    else
56
        throw opp_runtime_error("Unrecognized function: %s()", funcname);
57
}
58

    
59
ExpressionFilterNode::ExpressionFilterNode(const char *text)
60
{
61
    skipFirstDatum = false;
62
    expr = new Expression();
63
    Resolver resolver(this);
64
    expr->parse(text, &resolver);
65
    prevDatum.x = prevDatum.y = NaN;
66
}
67

    
68
ExpressionFilterNode::~ExpressionFilterNode()
69
{
70
    delete expr;
71
}
72

    
73
bool ExpressionFilterNode::isReady() const
74
{
75
    return in()->length()>0;
76
}
77

    
78
void ExpressionFilterNode::process()
79
{
80
    int n = in()->length();
81
    if (skipFirstDatum && n > 0) {
82
        in()->read(&prevDatum,1);
83
        n--;
84
        skipFirstDatum = false;
85
    }
86
    for (int i=0; i<n; i++)
87
    {
88
        in()->read(&currentDatum,1);
89
        double value = expr->doubleValue();
90
        prevDatum = currentDatum;
91
        currentDatum.y = value;
92
        out()->write(&currentDatum,1);
93
    }
94
}
95

    
96
double ExpressionFilterNode::getVariable(const char *varname)
97
{
98
    if (varname[0]=='t' && varname[1]==0)
99
        return currentDatum.x;
100
    else if (varname[0]=='y' && varname[1]==0)
101
        return currentDatum.y;
102
    else if (varname[0]=='t' && strcmp(varname, "tprev")==0)
103
        return prevDatum.x;
104
    else if (varname[0]=='y' && strcmp(varname, "yprev")==0)
105
        return prevDatum.y;
106
    else
107
        return 0.0;  // cannot happen, as validation has already taken place in Resolver
108
}
109

    
110
//--
111

    
112
const char *ExpressionFilterNodeType::getDescription() const
113
{
114
    return "Evaluates an arbitrary expression. Use t for time, y for value, and tprev, yprev for the previous values."; //FIXME use "t" and "y" instead?
115
}
116

    
117
void ExpressionFilterNodeType::getAttributes(StringMap& attrs) const
118
{
119
    attrs["expression"] = "The expression to evaluate.";
120
}
121

    
122
Node *ExpressionFilterNodeType::create(DataflowManager *mgr, StringMap& attrs) const
123
{
124
    checkAttrNames(attrs);
125

    
126
    Node *node = new ExpressionFilterNode(attrs["expression"].c_str());
127
    node->setNodeType(this);
128
    mgr->addNode(node);
129
    return node;
130
}
131

    
132
void ExpressionFilterNodeType::mapVectorAttributes(/*inout*/StringMap &attrs) const
133
{
134
    attrs["type"] = "double";
135
}