Project

General

Profile

Statistics
| Branch: | Revision:

root / src / scave / xyplotnode.cc @ a3be1d55

History | View | Annotate | Download (3.85 KB)

1
//=========================================================================
2
//  XYPLOTNODE.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 <string.h>
19
#include <stdlib.h>
20
#include "channel.h"
21
#include "xyplotnode.h"
22

    
23
USING_NAMESPACE
24

    
25

    
26
Port *XYPlotNode::getPortY(int k)
27
{
28
    if (k<0 || yin.size()< (unsigned)k)
29
        throw opp_runtime_error("XYPlotNode::getPortY(k): k=%d out of range, size of yin[] is %d",k,yin.size());
30
    if (yin.size()==(unsigned)k)
31
    {
32
        yin.push_back(Port(this));
33
        out.push_back(Port(this));
34
    }
35
    return &yin[k];
36
}
37

    
38
Port *XYPlotNode::getPortOut(int k)
39
{
40
    if (k<0 || out.size()<=(unsigned)k)
41
        throw opp_runtime_error("XYPlotNode::getPortOut(k): k=%d out of range, size of out[] is %d",k,out.size());
42
    return &out[k];
43
}
44

    
45
bool XYPlotNode::isReady() const
46
{
47
    // if no "x" data, we're not ready
48
    if (xin()->length()==0)
49
        return false;
50
    // otherwise, we're ready only if all "y" ports have something (except those at EOF)
51
    for (PortVector::const_iterator it=yin.begin(); it!=yin.end(); it++)
52
        if ((*it)()->length()==0 && !(*it)()->isClosing())
53
            return false;
54
    return true;
55
}
56

    
57
void XYPlotNode::process()
58
{
59
    // read one value from "x" port, then read "y" ports until their peek()'s
60
    // return ty>tx values (where tx is timestamp of the "x" value). Meanwhile,
61
    // if we find ty==tx values, output the (x,y) pair. If a port has reached
62
    // EOF, skip it.
63
    Assert(xin()->length()>0);
64
    Datum xd;
65
    xin()->read(&xd,1);
66

    
67
    for (unsigned int i=0; i<yin.size(); i++)
68
    {
69
        Channel *ychan = yin[i]();
70
        Assert(ychan->eof() || ychan->length()>0);
71
        const Datum *yp;
72
        Datum d;
73
        while ((yp=ychan->peek())!=NULL && yp->x < xd.x)
74
        {
75
            ychan->read(&d,1);  // discard if timestamps not equal
76
        }
77
        while ((yp=ychan->peek())!=NULL && yp->x == xd.x)
78
        {
79
            ychan->read(&d,1);
80
            d.x = xd.y;
81
            out[i]()->write(&d,1);
82
        }
83
        if (ychan->eof())
84
        {
85
            out[i]()->close(); // doesn't hurt
86
        }
87
    }
88
}
89

    
90
bool XYPlotNode::isFinished() const
91
{
92
    // if "x" reached eof, we're finished in any case
93
    if (xin()->eof())
94
        return true;
95
    // otherwise only if all "y" ports are at EOF
96
    for (PortVector::const_iterator it=yin.begin(); it!=yin.end(); it++)
97
        if (!(*it)()->eof())
98
            return false;
99
    return true;
100
}
101

    
102
//-------
103

    
104
const char *XYPlotNodeType::getDescription() const
105
{
106
    return "Creates x-y plot by matching values that arrive on one x and several\n"
107
           "y ports by their timestamps. (One value on x and one on y create one\n"
108
           "output value when their timestamps are equal).";
109
}
110

    
111
void XYPlotNodeType::getAttributes(StringMap& attrs) const
112
{
113
}
114

    
115
Node *XYPlotNodeType::create(DataflowManager *mgr, StringMap& attrs) const
116
{
117
    checkAttrNames(attrs);
118

    
119
    Node *node = new XYPlotNode();
120
    node->setNodeType(this);
121
    mgr->addNode(node);
122
    return node;
123
}
124

    
125
Port *XYPlotNodeType::getPort(Node *node, const char *portname) const
126
{
127
    XYPlotNode *node1 = dynamic_cast<XYPlotNode *>(node);
128
    if (!strcmp(portname,"x"))
129
        return &(node1->xin);
130
    if (portname[0]=='y')
131
        return node1->getPortY(atoi(portname+1));
132
    else if (!strncmp(portname,"out",3))
133
        return node1->getPortOut(atoi(portname+3));
134
    throw opp_runtime_error("no such port `%s'", portname);
135
}
136

    
137

    
138