GCC Code Coverage Report


Directory: ./
File: pdserv-1.1.0/src/msrproto/Parameter.cpp
Date: 2026-10-18 04:09:42
Exec Total Coverage
Lines: 1 67 1.5%
Branches: 0 94 0.0%

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 ✗ Parameter::Parameter(const PdServ::Parameter *p, size_t index,
57 const PdServ::DataType& dtype,
58 const PdServ::DataType::DimType& dim,
59 ✗ size_t offset, Parameter *parent):
60 Variable(p, index, dtype, dim, offset, parent),
61 mainParam(p),
62 ✗ dependent(parent != 0)
63 {
64 }
65
66 /////////////////////////////////////////////////////////////////////////////
67 ✗ void Parameter::setXmlAttributes(XmlElement &element, const char *valueBuf,
68 struct timespec const& mtime, bool shortReply, bool hex,
69 size_t precision) const
70 {
71 ✗ unsigned int flags = MSR_R | MSR_W | MSR_WOP;
72
73 // <parameter name="/lan/Control/EPC/EnableMotor/Value/2"
74 // index="30" value="0"/>
75
76 ✗ setAttributes(element, shortReply);
77
78 ✗ if (!shortReply) {
79 ✗ XmlElement::Attribute(element, "flags")
80 ✗ << flags + (dependent ? 0x100 : 0);
81
82 // persistent=
83 ✗ if (mainParam->persistent)
84 ✗ XmlElement::Attribute(element, "persistent") << 1;
85 }
86
87 // mtime=
88 ✗ XmlElement::Attribute(element, "mtime") << mtime;
89
90 ✗ if (valueBuf) {
91 ✗ if (hex)
92 ✗ XmlElement::Attribute(element, "hexvalue")
93 ✗ .hexDec(valueBuf + offset, dtype.size);
94 else
95 ✗ XmlElement::Attribute(element, "value").csv( this,
96 ✗ valueBuf + offset, 1, precision);
97 }
98
99 ✗ addCompoundFields(element, variable->dtype);
100
101 ✗ return;
102 }
103
104 /////////////////////////////////////////////////////////////////////////////
105 ✗ int Parameter::setHexValue(const Session *session,
106 const char *s, size_t startindex, size_t &count) const
107 {
108 ✗ char valueBuf[memSize];
109 ✗ const char *valueEnd = valueBuf + memSize;
110 static const char hexNum[] = {
111 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 0, 0, 0, 0, 0,
112 0,10,11,12,13,14,15, 0, 0, 0, 0, 0, 0, 0, 0, 0,
113 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
114 0,10,11,12,13,14,15
115 };
116
117 char *c;
118 ✗ for (c = valueBuf; *s and c < valueEnd; c++) {
119 ✗ unsigned char c1 = *s++ - '0';
120 ✗ unsigned char c2 = *s++ - '0';
121 ✗ if (std::max(c1,c2) >= sizeof(hexNum))
122 ✗ return -EINVAL;
123 ✗ *c = hexNum[c1] << 4 | hexNum[c2];
124 }
125 // FIXME: actually the setting operation must also check for
126 // endianness!
127
128 ✗ count = c - valueBuf;
129 ✗ return mainParam->setValue( session, valueBuf,
130 ✗ offset + startindex * dtype.size, count);
131 }
132
133 /////////////////////////////////////////////////////////////////////////////
134 ✗ int Parameter::setElements(std::istream& is,
135 const PdServ::DataType& dtype, const PdServ::DataType::DimType& dim,
136 char*& buf, size_t& count) const
137 {
138 ✗ if (dtype.primary() == dtype.compound_T) {
139 ✗ const PdServ::DataType::FieldList& fieldList = dtype.getFieldList();
140 ✗ PdServ::DataType::FieldList::const_iterator it;
141 ✗ for (size_t i = 0; i < dim.nelem; ++i) {
142 ✗ for (it = fieldList.begin(); it != fieldList.end(); ++it) {
143 ✗ int rv = setElements(is, (*it)->type, (*it)->dim, buf, count);
144 ✗ if (rv)
145 ✗ return rv;
146 }
147 }
148 ✗ return 0;
149 }
150
151 ✗ double v;
152 ✗ char c;
153 ✗ for (size_t i = 0; i < dim.nelem; ++i) {
154
155 ✗ is >> v;
156 ✗ if (!is)
157 ✗ return -EINVAL;
158
159 ✗ dtype.setValue(buf, v);
160 ✗ count += dtype.size;
161
162 ✗ is >> c;
163 ✗ if (!is)
164 ✗ return 1;
165
166 ✗ if (c != ',' and c != ';' and !isspace(c))
167 ✗ return -EINVAL;
168 }
169
170 ✗ return 0;
171 }
172
173 /////////////////////////////////////////////////////////////////////////////
174 ✗ int Parameter::setDoubleValue(const Session *session,
175 const char *buf, size_t startindex, size_t &count) const
176 {
177 ✗ char valueBuf[memSize];
178 ✗ char *dataBuf = valueBuf;
179
180 ✗ std::istringstream is(buf);
181 ✗ is.imbue(std::locale::classic());
182
183 //log_debug("buf=%s", buf);
184 ✗ count = 0;
185 ✗ int rv = setElements(is, dtype, dim, dataBuf, count);
186
187 // log_debug("rv=%i startindex=%zu offset=%zu count=%zu",
188 // rv, startindex, offset/dtype.size + startindex, count);
189 // for (size_t i = 0; i < count; i++)
190 // std::cerr << ((const double*)valueBuf)[i] << ' ';
191 // std::cerr << std::endl;
192 return rv < 0
193 ✗ ? rv
194 ✗ : mainParam->setValue( session, valueBuf,
195 ✗ offset + startindex * dtype.size, count);
196 3 }
197