GCC Code Coverage Report


Directory: ./
File: pdserv/src/msrproto/Parameter.cpp
Date: 2024-11-17 04:08:36
Exec Total Coverage
Lines: 49 85 57.6%
Branches: 39 114 34.2%

Line Branch Exec Source
1 /*****************************************************************************
2 *
3 * $Id$
4 *
5 * Copyright 2010 Richard Hacker (lerichi at gmx dot net)
6 *
7 * This file is part of the pdserv library.
8 *
9 * The pdserv library is free software: you can redistribute it and/or modify
10 * it under the terms of the GNU Lesser General Public License as published
11 * by the Free Software Foundation, either version 3 of the License, or (at
12 * your option) any later version.
13 *
14 * The pdserv library is distributed in the hope that it will be useful, but
15 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
16 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
17 * License for more details.
18 *
19 * You should have received a copy of the GNU Lesser General Public License
20 * along with the pdserv library. If not, see <http://www.gnu.org/licenses/>.
21 *
22 *****************************************************************************/
23
24 #include "Parameter.h"
25 #include "XmlElement.h"
26 #include "Session.h"
27 #include "../Parameter.h"
28 #include "../Debug.h"
29 #include "../DataType.h"
30
31 #include <sstream>
32 #include <cerrno>
33 #include <stdint.h>
34
35 #define MSR_R 0x01 /* Parameter is readable */
36 #define MSR_W 0x02 /* Parameter is writeable */
37 #define MSR_WOP 0x04 /* Parameter is writeable in real-time */
38 //#define MSR_MONOTONIC 0x8 /* List must be monotonic */
39 //#define MSR_S 0x10 /* Parameter must be saved by clients */
40 #define MSR_G 0x20 /* Gruppenbezeichnung (unused) */
41 #define MSR_AW 0x40 /* Writeable by admin only */
42 #define MSR_P 0x80 /* Persistant parameter, written to disk */
43 #define MSR_DEP 0x100 /* This parameter is an exerpt of another parameter.
44 Writing to this parameter also causes an update
45 notice for the encompassing parameter */
46 #define MSR_AIC 0x200 /* Asynchronous input channel */
47
48 /* ein paar Kombinationen */
49 #define MSR_RWS (MSR_R | MSR_W | MSR_S)
50 #define MSR_RP (MSR_R | MSR_P)
51
52
53 using namespace MsrProto;
54
55 /////////////////////////////////////////////////////////////////////////////
56 2464 Parameter::Parameter(const PdServ::Parameter *p, size_t index,
57 const PdServ::DataType& dtype,
58 const PdServ::DataType::DimType& dim,
59 2464 size_t offset, Parameter *parent):
60 Variable(p, index, dtype, dim, offset),
61 mainParam(p),
62 persistent(false),
63 2464 dependent(parent)
64 {
65
2/2
✓ Branch 0 taken 1540 times.
✓ Branch 1 taken 924 times.
2464 if (parent) {
66
1/2
✓ Branch 4 taken 1540 times.
✗ Branch 5 not taken.
1540 parent->addChild(this);
67
1/2
✗ Branch 5 not taken.
✓ Branch 6 taken 1540 times.
1540 hidden = parent->hidden;
68
1/2
✗ Branch 5 not taken.
✓ Branch 6 taken 1540 times.
1540 persistent = parent->persistent;
69 }
70 2464 }
71
72 /////////////////////////////////////////////////////////////////////////////
73 180 bool Parameter::inform(Session* session, size_t begin, size_t end,
74 const char* data, const struct timespec* time) const
75 {
76
2/2
✓ Branch 6 taken 35 times.
✓ Branch 7 taken 145 times.
180 if (begin >= offset + memSize)
77 35 return false;
78
2/2
✓ Branch 3 taken 11 times.
✓ Branch 4 taken 134 times.
145 else if (offset >= end)
79 11 return true;
80
81 134 session->parameterChanged(this, data, time);
82 257 for (List::const_iterator it = children.begin();
83
2/2
✓ Branch 6 taken 134 times.
✓ Branch 7 taken 123 times.
257 it != children.end(); ++it) {
84
3/4
✓ Branch 6 taken 134 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 11 times.
✓ Branch 9 taken 123 times.
134 if ((*it)->inform(session, begin, end, data, time))
85 11 break;
86 }
87
88 134 return false;
89 }
90
91 /////////////////////////////////////////////////////////////////////////////
92 1540 void Parameter::addChild(const Parameter* child)
93 {
94 1540 children.push_back(child);
95 1540 }
96
97 /////////////////////////////////////////////////////////////////////////////
98 159 void Parameter::setXmlAttributes(XmlElement &element, const char *valueBuf,
99 struct timespec const& mtime,
100 bool shortReply, bool hex, bool derived,
101 std::streamsize precision) const
102 {
103 159 unsigned int flags = MSR_R | MSR_W | MSR_WOP;
104
105 // <parameter name="/lan/Control/EPC/EnableMotor/Value/2"
106 // index="30" value="0"/>
107
108 159 setAttributes(element, shortReply, derived);
109
110
2/2
✓ Branch 0 taken 118 times.
✓ Branch 1 taken 41 times.
159 if (!shortReply) {
111 236 XmlElement::Attribute(element, "flags")
112
4/6
✗ Branch 6 not taken.
✓ Branch 7 taken 118 times.
✓ Branch 8 taken 52 times.
✓ Branch 9 taken 66 times.
✓ Branch 12 taken 118 times.
✗ Branch 13 not taken.
236 << flags + (dependent ? 0x100 : 0);
113
114 // persistent=
115
2/4
✗ Branch 3 not taken.
✓ Branch 4 taken 118 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 118 times.
118 if (persistent)
116 XmlElement::Attribute(element, "persistent") << 1;
117 }
118
119 // mtime=
120
1/2
✓ Branch 4 taken 159 times.
✗ Branch 5 not taken.
159 XmlElement::Attribute(element, "mtime") << mtime;
121
122
1/2
✓ Branch 0 taken 159 times.
✗ Branch 1 not taken.
159 if (valueBuf) {
123
2/2
✓ Branch 0 taken 45 times.
✓ Branch 1 taken 114 times.
159 if (hex)
124 90 XmlElement::Attribute(element, "hexvalue")
125
1/2
✓ Branch 9 taken 45 times.
✗ Branch 10 not taken.
90 .hexDec(valueBuf + offset, memSize);
126 else
127 228 XmlElement::Attribute(element, "value")
128
1/2
✓ Branch 6 taken 114 times.
✗ Branch 7 not taken.
228 .csv(this, valueBuf + offset, 1, precision);
129 }
130
131
2/2
✓ Branch 0 taken 118 times.
✓ Branch 1 taken 41 times.
159 if (!shortReply)
132 118 addCompoundFields(element, variable->dtype);
133
134 159 return;
135 }
136
137 /////////////////////////////////////////////////////////////////////////////
138 43 int Parameter::setHexValue(const Session *session,
139 const char *s, size_t startindex) const
140 {
141
1/2
✗ Branch 3 not taken.
✓ Branch 4 taken 43 times.
43 char valueBuf[memSize];
142 43 const char *valueEnd = valueBuf + memSize;
143 static const char hexNum[] = {
144 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 0, 0, 0, 0, 0,
145 0,10,11,12,13,14,15, 0, 0, 0, 0, 0, 0, 0, 0, 0,
146 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
147 0,10,11,12,13,14,15
148 };
149
150 char *c;
151
3/4
✓ Branch 1 taken 412 times.
✓ Branch 2 taken 43 times.
✓ Branch 3 taken 412 times.
✗ Branch 4 not taken.
455 for (c = valueBuf; *s and c < valueEnd; c++) {
152 412 unsigned char c1 = *s++ - '0';
153 412 unsigned char c2 = *s++ - '0';
154
1/2
✗ Branch 2 not taken.
✓ Branch 3 taken 412 times.
412 if (std::max(c1,c2) >= sizeof(hexNum))
155 return -EINVAL;
156
2/4
✗ Branch 5 not taken.
✓ Branch 6 taken 412 times.
✓ Branch 16 taken 412 times.
✗ Branch 17 not taken.
412 *c = hexNum[c1] << 4 | hexNum[c2];
157 }
158 // FIXME: actually the setting operation must also check for
159 // endianness!
160
161
1/2
✓ Branch 21 taken 43 times.
✗ Branch 22 not taken.
129 return mainParam->setValue( session, valueBuf,
162
1/2
✓ Branch 12 taken 43 times.
✗ Branch 13 not taken.
172 offset + startindex * dtype.size, c - valueBuf);
163 }
164
165 /////////////////////////////////////////////////////////////////////////////
166 int Parameter::setElements(std::istream& is,
167 const PdServ::DataType& dtype, const PdServ::DataType::DimType& dim,
168 char*& buf, size_t& count) const
169 {
170 if (dtype.primary() == dtype.compound_T) {
171 const PdServ::DataType::FieldList& fieldList = dtype.getFieldList();
172 PdServ::DataType::FieldList::const_iterator it;
173 for (size_t i = 0; i < dim.nelem; ++i) {
174 for (it = fieldList.begin(); it != fieldList.end(); ++it) {
175 int rv = setElements(is, (*it)->type, (*it)->dim, buf, count);
176 if (rv)
177 return rv;
178 }
179 }
180 return 0;
181 }
182
183 double v;
184 char c;
185 for (size_t i = 0; i < dim.nelem; ++i) {
186
187 is >> v;
188 if (!is)
189 return -EINVAL;
190
191 dtype.setValue(buf, v);
192 count += dtype.size;
193
194 is >> c;
195 if (!is)
196 return 1;
197
198 if (c != ',' and c != ';' and !isspace(c))
199 return -EINVAL;
200 }
201
202 return 0;
203 }
204
205 /////////////////////////////////////////////////////////////////////////////
206 int Parameter::setDoubleValue(const Session *session,
207 const char *buf, size_t startindex) const
208 {
209 char valueBuf[memSize];
210 char *dataBuf = valueBuf;
211
212 std::istringstream is(buf);
213 is.imbue(std::locale::classic());
214
215 //log_debug("buf=%s", buf);
216 size_t count = 0;
217 int rv = setElements(is, dtype, dim, dataBuf, count);
218
219 // log_debug("rv=%i startindex=%zu offset=%zu count=%zu",
220 // rv, startindex, offset/dtype.size + startindex, count);
221 // for (size_t i = 0; i < count; i++)
222 // std::cerr << ((const double*)valueBuf)[i] << ' ';
223 // std::cerr << std::endl;
224 return rv < 0
225 ? rv
226 : mainParam->setValue( session, valueBuf,
227 offset + startindex * dtype.size, count);
228 }
229