GCC Code Coverage Report


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

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