GCC Code Coverage Report


Directory: ./
File: pdserv-1.1.0/src/msrproto/Parameter.cpp
Date: 2023-11-12 04:06:57
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