• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

OpenLightingProject / ola / 11783254300

11 Nov 2024 05:23PM UTC coverage: 45.767% (+0.09%) from 45.677%
11783254300

push

github

web-flow
Merge pull request #1978 from DMXControl/add_nodle_r4s

Add DMXControl Projects e.V. Nodle R4S

7798 of 17938 branches covered (43.47%)

0 of 1 new or added line in 1 file covered. (0.0%)

721 existing lines in 11 files now uncovered.

22344 of 48821 relevant lines covered (45.77%)

64.39 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

87.37
/common/rdm/StringMessageBuilder.cpp
1
/*
2
 * This library is free software; you can redistribute it and/or
3
 * modify it under the terms of the GNU Lesser General Public
4
 * License as published by the Free Software Foundation; either
5
 * version 2.1 of the License, or (at your option) any later version.
6
 *
7
 * This library is distributed in the hope that it will be useful,
8
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
10
 * Lesser General Public License for more details.
11
 *
12
 * You should have received a copy of the GNU Lesser General Public
13
 * License along with this library; if not, write to the Free Software
14
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
15
 *
16
 * StringMessageBuilder.cpp
17
 * Builds a Message object from a list of strings & a Descriptor.
18
 * Copyright (C) 2011 Simon Newton
19
 */
20

21

22
#include <ola/Logging.h>
23
#include <ola/StringUtils.h>
24
#include <ola/messaging/Descriptor.h>
25
#include <ola/messaging/Message.h>
26
#include <ola/network/IPV4Address.h>
27
#include <ola/network/IPV6Address.h>
28
#include <ola/network/MACAddress.h>
29
#include <ola/rdm/StringMessageBuilder.h>
30
#include <ola/rdm/UID.h>
31
#include <memory>
32
#include <string>
33
#include <vector>
34

35
#include "common/rdm/GroupSizeCalculator.h"
36

37
namespace ola {
38
namespace rdm {
39

40
using ola::messaging::MessageFieldInterface;
41
using ola::rdm::UID;
42
using std::auto_ptr;
43
using std::string;
44
using std::vector;
45

46

47
StringMessageBuilder::StringMessageBuilder()
64✔
48
    : m_offset(0),
64✔
49
      m_input_size(0),
64✔
50
      m_group_instance_count(0),
64✔
51
      m_error(false) {
64✔
52
}
64✔
53

54

55
/**
56
 * @brief Clean up
57
 */
58
StringMessageBuilder::~StringMessageBuilder() {
128✔
59
  CleanUpVector();
128✔
60
}
130✔
61

62

63
/**
64
 * @brief Get the Message object that this Builder created
65
 *
66
 * This method is *not* re-entrant.
67
 * @param inputs the string inputs provided to build the Message
68
 * @param descriptor the descriptor to use to build the Message
69
 * @returns a Message object, or NULL if the inputs failed.
70
 */
71
const ola::messaging::Message *StringMessageBuilder::GetMessage(
64✔
72
    const vector<string> &inputs,
73
    const ola::messaging::Descriptor *descriptor) {
74
  InitVars(inputs);
64✔
75

76
  // first figure out if the number of inputs provided matches the number
77
  // expected by the descriptor. This accounts for repeating groups.
78
  GroupSizeCalculator calculator;
64✔
79
  GroupSizeCalculator::calculator_state state = calculator.CalculateGroupSize(
64✔
80
      inputs.size(),
64✔
81
      descriptor,
82
      &m_group_instance_count);
83

84
  switch (state) {
64✔
85
    case GroupSizeCalculator::INSUFFICIENT_TOKENS:
1✔
86
      SetError("Insufficient tokens");
1✔
87
      return NULL;
1✔
88
    case GroupSizeCalculator::EXTRA_TOKENS:
1✔
89
      SetError("Extra tokens");
1✔
90
      return NULL;
1✔
91
    case GroupSizeCalculator::MISMATCHED_TOKENS:
×
92
      SetError("Mismatched tokens");
×
93
      return NULL;
×
94
    case GroupSizeCalculator::MULTIPLE_VARIABLE_GROUPS:
×
95
      SetError("Multiple variable groups");
×
96
      return NULL;
×
97
    case GroupSizeCalculator::NESTED_VARIABLE_GROUPS:
×
98
      SetError("Nested variable groups");
×
99
      return NULL;
×
100
    case GroupSizeCalculator::SINGLE_VARIABLE_GROUP:
101
    case GroupSizeCalculator::NO_VARIABLE_GROUPS:
102
      break;
103
  }
104

105
  // now we now that this list of inputs can be parsed, and we know the number
106
  // of instances of a repeating group if there is one.
107
  descriptor->Accept(this);
62✔
108

109
  if (m_error) {
62✔
110
    OLA_WARN << "Error building message, field is: " << m_error_string;
32✔
111
    return NULL;
32✔
112
  }
113

114
  if (m_groups.size() != 1) {
30✔
115
    OLA_WARN << "Mismatched stack, size was " << m_groups.size();
×
116
    return NULL;
×
117
  }
118

119
  const ola::messaging::Message *message =  new ola::messaging::Message(
30✔
120
      m_groups.top());
30✔
121
  m_groups.top().clear();
30✔
122
  return message;
123
}
64✔
124

125

126
/**
127
 * Bool values can be true,false,0,1
128
 */
129
void StringMessageBuilder::Visit(
23✔
130
    const ola::messaging::BoolFieldDescriptor *descriptor) {
131
  if (StopParsing()) {
23✔
132
    return;
2✔
133
  }
134

135
  bool value = false;
23✔
136
  bool valid = false;
23✔
137
  string token = m_inputs[m_offset++];
23✔
138
  ola::StringTrim(&token);
23✔
139
  ola::ToLower(&token);
23✔
140

141
  if (token == "true") {
23✔
142
    valid = value = true;
143
  } else if (token == "false") {
9✔
144
    value = false;
5✔
145
    valid = true;
5✔
146
  }
147

148
  if (!valid) {
23✔
149
    uint8_t int_value;
4✔
150
    if (ola::StringToInt(token, &int_value)) {
4✔
151
      if (int_value == 1) {
3✔
152
        valid = value = true;
153
      } else if (int_value == 0) {
2✔
154
        valid = true;
4✔
155
        value = false;
4✔
156
      }
157
    }
158
  }
159

160
  if (!valid) {
23✔
161
    SetError(descriptor->Name());
2✔
162
    return;
2✔
163
  }
164

165
  m_groups.top().push_back(
21✔
166
      new ola::messaging::BoolMessageField(descriptor, value));
21✔
167
}
23✔
168

169

170
/**
171
 * IPV4 Addresses
172
 */
173
void StringMessageBuilder::Visit(
2✔
174
    const ola::messaging::IPV4FieldDescriptor *descriptor) {
175
  if (StopParsing()) {
2✔
176
    return;
×
177
  }
178

179
  string token = m_inputs[m_offset++];
2✔
180
  ola::network::IPV4Address ip_address;
2✔
181
  if (!ola::network::IPV4Address::FromString(token, &ip_address)) {
2✔
182
    SetError(descriptor->Name());
×
183
    return;
×
184
  }
185

186
  m_groups.top().push_back(
2✔
187
      new ola::messaging::IPV4MessageField(descriptor, ip_address));
2✔
188
}
2✔
189

190

191
/**
192
 * IPV6 Addresses
193
 */
194
void StringMessageBuilder::Visit(
2✔
195
    const ola::messaging::IPV6FieldDescriptor *descriptor) {
196
  if (StopParsing()) {
2✔
197
    return;
×
198
  }
199

200
  string token = m_inputs[m_offset++];
2✔
201
  ola::network::IPV6Address ipv6_address;
2✔
202
  if (!ola::network::IPV6Address::FromString(token, &ipv6_address)) {
2✔
203
    SetError(descriptor->Name());
×
204
    return;
×
205
  }
206

207
  m_groups.top().push_back(
2✔
208
      new ola::messaging::IPV6MessageField(descriptor, ipv6_address));
2✔
209
}
2✔
210

211

212
/**
213
 * MAC Addresses
214
 */
215
void StringMessageBuilder::Visit(
2✔
216
    const ola::messaging::MACFieldDescriptor *descriptor) {
217
  if (StopParsing()) {
2✔
218
    return;
×
219
  }
220

221
  string token = m_inputs[m_offset++];
2✔
222
  ola::network::MACAddress mac_address;
2✔
223
  if (!ola::network::MACAddress::FromString(token, &mac_address)) {
2✔
224
    SetError(descriptor->Name());
×
225
    return;
×
226
  }
227

228
  m_groups.top().push_back(
2✔
229
      new ola::messaging::MACMessageField(descriptor, mac_address));
4✔
230
}
2✔
231

232

233
/**
234
 * UIDs.
235
 */
236
void StringMessageBuilder::Visit(
1✔
237
    const ola::messaging::UIDFieldDescriptor *descriptor) {
238
  if (StopParsing()) {
1✔
239
    return;
×
240
  }
241

242
  string token = m_inputs[m_offset++];
1✔
243
  auto_ptr<UID> uid(UID::FromString(token));
1✔
244

245
  if (!uid.get()) {
1✔
246
    SetError(descriptor->Name());
×
247
    return;
×
248
  }
249

250
  m_groups.top().push_back(
1✔
251
      new ola::messaging::UIDMessageField(descriptor, *uid));
1✔
252
}
1✔
253

254

255
/**
256
 * Handle strings
257
 */
258
void StringMessageBuilder::Visit(
7✔
259
    const ola::messaging::StringFieldDescriptor *descriptor) {
260
  if (StopParsing()) {
7✔
261
    return;
262
  }
263

264
  const string &token = m_inputs[m_offset++];
7✔
265
  if (descriptor->MaxSize() != 0 &&
7✔
266
      token.size() > descriptor->MaxSize()) {
7✔
267
    SetError(descriptor->Name());
1✔
268
    return;
1✔
269
  }
270

271
  m_groups.top().push_back(
6✔
272
      new ola::messaging::StringMessageField(descriptor, token));
12✔
273
}
274

275

276
/**
277
 * uint8
278
 */
279
void StringMessageBuilder::Visit(
63✔
280
    const ola::messaging::UInt8FieldDescriptor *descriptor) {
281
  VisitInt(descriptor);
63✔
282
}
63✔
283

284

285
void StringMessageBuilder::Visit(
13✔
286
    const ola::messaging::UInt16FieldDescriptor *descriptor) {
287
  VisitInt(descriptor);
13✔
288
}
13✔
289

290

291
void StringMessageBuilder::Visit(
10✔
292
    const ola::messaging::UInt32FieldDescriptor *descriptor) {
293
  VisitInt(descriptor);
10✔
294
}
10✔
295

296

297
void StringMessageBuilder::Visit(
3✔
298
    const ola::messaging::UInt64FieldDescriptor *descriptor) {
299
  VisitInt(descriptor);
3✔
300
}
3✔
301

302

303
void StringMessageBuilder::Visit(
6✔
304
    const ola::messaging::Int8FieldDescriptor *descriptor) {
305
  VisitInt(descriptor);
6✔
306
}
6✔
307

308

309
void StringMessageBuilder::Visit(
6✔
310
    const ola::messaging::Int16FieldDescriptor *descriptor) {
311
  VisitInt(descriptor);
6✔
312
}
6✔
313

314

315
void StringMessageBuilder::Visit(
3✔
316
    const ola::messaging::Int32FieldDescriptor *descriptor) {
317
  VisitInt(descriptor);
3✔
318
}
3✔
319

320

321
void StringMessageBuilder::Visit(
3✔
322
    const ola::messaging::Int64FieldDescriptor *descriptor) {
323
  VisitInt(descriptor);
3✔
324
}
3✔
325

326

327
/**
328
 * Visit a group
329
 */
330
void StringMessageBuilder::Visit(
10✔
331
    const ola::messaging::FieldDescriptorGroup *descriptor) {
332

333
  unsigned int iterations = descriptor->FixedSize() ? descriptor->MinBlocks() :
10✔
334
    m_group_instance_count;
10✔
335

336
  for (unsigned int i = 0; i < iterations; ++i) {
30✔
337
    vector<const MessageFieldInterface*> fields;
20✔
338
    m_groups.push(fields);
20✔
339

340
    for (unsigned int j = 0; j < descriptor->FieldCount(); ++j) {
54✔
341
      descriptor->GetField(j)->Accept(this);
68✔
342
    }
343

344
    const vector<const MessageFieldInterface*> &populated_fields =
20✔
345
        m_groups.top();
20✔
346
    const ola::messaging::MessageFieldInterface *message =
20✔
347
        new ola::messaging::GroupMessageField(descriptor, populated_fields);
20✔
348
    m_groups.pop();
20✔
349
    m_groups.top().push_back(message);
20✔
350
  }
20✔
351
}
10✔
352

353

354
/**
355
 * This is a no-op since we handle descending ourselves in Visit()
356
 */
357
void StringMessageBuilder::PostVisit(
10✔
358
    const ola::messaging::FieldDescriptorGroup *descriptor) {
359
  (void) descriptor;
10✔
360
}
10✔
361

362

363
bool StringMessageBuilder::StopParsing() const {
144✔
364
  return m_error ||  m_offset >= m_input_size;
144✔
365
}
366

367

368
void StringMessageBuilder::SetError(const string &error) {
34✔
369
  m_error = true;
34✔
370
  m_error_string = error;
34✔
371
}
34✔
372

373

374
template<typename type>
375
void StringMessageBuilder::VisitInt(
214✔
376
    const ola::messaging::IntegerFieldDescriptor<type> *descriptor) {
377
  if (StopParsing()) {
214✔
UNCOV
378
    return;
×
379
  }
380

381
  type int_value;
382
  string input = m_inputs[m_offset++];
214✔
383
  if (descriptor->LookupLabel(input, &int_value) ||
420✔
384
      ola::PrefixedHexStringToInt(input, &int_value) ||
418✔
385
      ola::StringToInt(input, &int_value)) {
204✔
386
    if (descriptor->IsValid(int_value)) {
180✔
387
      m_groups.top().push_back(
156✔
388
          new ola::messaging::BasicMessageField<type>(descriptor, int_value));
156✔
389
    } else {
390
      SetError(descriptor->Name());
24✔
391
    }
392
  } else {
393
    SetError(descriptor->Name());
34✔
394
  }
395
}
214✔
396

397

398
void StringMessageBuilder::InitVars(const vector<string> &inputs) {
64✔
399
  CleanUpVector();
64✔
400
  // add the first fields vector to the stack
401
  vector<const MessageFieldInterface*> fields;
64✔
402
  m_groups.push(fields);
64✔
403

404
  m_inputs = inputs;
64✔
405
  m_input_size = inputs.size();
64✔
406
  m_error = false;
64✔
407
  m_offset = 0;
64✔
408
}
64✔
409

410

411
void StringMessageBuilder::CleanUpVector() {
128✔
412
  while (!m_groups.empty()) {
192✔
413
    const vector<const MessageFieldInterface*> &fields = m_groups.top();
64✔
414
    vector<const MessageFieldInterface*>::const_iterator iter = fields.begin();
64✔
415
    for (; iter != fields.end(); ++iter) {
64✔
UNCOV
416
      delete *iter;
×
417
    }
418
    m_groups.pop();
64✔
419
  }
420
}
128✔
421
}  // namespace rdm
422
}  // namespace ola
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc