begin of config file parsing
Stefan Schuermans authored 7 years ago
|
1) /*
2) * EtherPix simulator
3) *
4) * Copyright 2017 Stefan Schuermans <stefan schuermans info>
5) *
6) * This program is free software: you can redistribute it and/or modify
7) * it under the terms of the GNU General Public License as published by
8) * the Free Software Foundation, version 3 of the License.
9) *
10) *
11) * This program is distributed in the hope that it will be useful,
12) * but WITHOUT ANY WARRANTY; without even the implied warranty of
13) * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14) * GNU General Public License for more details.
15) *
16) * You should have received a copy of the GNU Lesser General Public License
17) * along with this program. If not, see <http://www.gnu.org/licenses/>.
18) */
19)
20) #include <algorithm>
|
complete implementation of...
Stefan Schuermans authored 7 years ago
|
21) #include <arpa/inet.h>
|
begin of config file parsing
Stefan Schuermans authored 7 years ago
|
22) #include <cctype>
|
continue implementing confi...
Stefan Schuermans authored 7 years ago
|
23) #include <cmath>
24) #include <cstdlib>
|
begin of config file parsing
Stefan Schuermans authored 7 years ago
|
25) #include <functional>
26) #include <fstream>
|
continue implementing confi...
Stefan Schuermans authored 7 years ago
|
27) #include <map>
|
complete implementation of...
Stefan Schuermans authored 7 years ago
|
28) #include <netinet/in.h>
|
begin of config file parsing
Stefan Schuermans authored 7 years ago
|
29) #include <stdexcept>
30) #include <sstream>
31) #include <string>
|
complete implementation of...
Stefan Schuermans authored 7 years ago
|
32) #include <sys/socket.h>
|
begin of config file parsing
Stefan Schuermans authored 7 years ago
|
33)
|
implement drawing pixels
Stefan Schuermans authored 7 years ago
|
34) #include "bbox.h"
|
begin of config file parsing
Stefan Schuermans authored 7 years ago
|
35) #include "config.h"
|
continue implementing confi...
Stefan Schuermans authored 7 years ago
|
36) #include "distri.h"
37) #include "mapping.h"
|
complete implementation of...
Stefan Schuermans authored 7 years ago
|
38) #include "pixel.h"
|
begin of config file parsing
Stefan Schuermans authored 7 years ago
|
39)
40) /**
41) * @brief constructor
42) * @param[in] configFile name of config file
43) */
|
implement drawing pixels
Stefan Schuermans authored 7 years ago
|
44) Config::Config(std::string const &configFile):
45) m_distriMap(),
46) m_bb()
|
begin of config file parsing
Stefan Schuermans authored 7 years ago
|
47) {
48) readFile(configFile);
49) }
50)
|
implement receiving packets
Stefan Schuermans authored 7 years ago
|
51) /**
52) * @brief create sockets and listen for incoming packets
53) * @throws std::exception in case of error
54) */
55) void Config::start()
56) {
57) try {
58) DistriMap::iterator dist;
59) for (dist = m_distriMap.begin(); dist != m_distriMap.end(); ++dist) {
60) Distri &distri = dist->second;
61) distri.start();
62) }
63) } catch (...) {
64) stop();
65) throw;
66) }
67) }
68)
69) /**
70) * @brief stop listening for incoming packets and close sockets
71) */
72) void Config::stop()
73) {
74) DistriMap::iterator dist;
75) for (dist = m_distriMap.begin(); dist != m_distriMap.end(); ++dist) {
76) Distri &distri = dist->second;
77) distri.stop();
78) }
79) }
80)
81) /// get and reset packet counter of all distributors
82) unsigned long Config::getPacketCounterAndReset()
83) {
84) unsigned long sum = 0;
85) DistriMap::iterator dist;
86) for (dist = m_distriMap.begin(); dist != m_distriMap.end(); ++dist) {
87) Distri &distri = dist->second;
88) sum += distri.getPacketCounterAndReset();
89) }
90) return sum;
91) }
92)
|
implement drawing pixels
Stefan Schuermans authored 7 years ago
|
93) /**
94) * @brief draw pixels of all distributors
95) * @param[in] cairo cairo context for drawing
96) * @param[in] tf coordinate transformation
97) */
98) void Config::draw(Cairo::RefPtr<Cairo::Context> &cairo,
99) Transform const &tf) const
100) {
101) DistriMap::const_iterator dist;
102) for (dist = m_distriMap.begin(); dist != m_distriMap.end(); ++dist) {
103) Distri const &distri = dist->second;
104) distri.draw(cairo, tf);
105) }
106) }
107)
|
begin of config file parsing
Stefan Schuermans authored 7 years ago
|
108) /**
109) * @brief remove whitespace at beging and end of string
110) * @param[in,out] str string to process
111) */
112) void Config::trim(std::string &str)
113) {
114) // remove leading whitespace
115) str.erase(str.begin(),
116) std::find_if(str.begin(), str.end(),
117) std::not1(std::ptr_fun<int, int>(std::isspace))));
118)
119) // remove trailing whitespace
120) str.erase(std::find_if(str.rbegin(), str.rend(),
121) std::not1(std::ptr_fun<int, int>(std::isspace))).base(),
122) str.end());
123) }
124)
125) /**
126) * @brief split string at sequences of whitespace
127) * @param[in] str string to split
128) * @param[out] fields fields of string
129) */
130) void Config::split(std::string const &str, std::vector<std::string> &fields)
131) {
132) std::stringstream strm(str);
133) fields.clear();
134) while (! strm.eof()) {
135) std::string field;
136) strm >> field;
137) if (! field.empty()) {
138) fields.push_back(field);
139) }
140) }
141) }
142)
|
continue implementing confi...
Stefan Schuermans authored 7 years ago
|
143) /**
144) * @brief split string at specific character
145) * @param[in] str string to split
146) * @param[in] delim delimiter character
147) * @param[out] fields fields of string
148) */
149) void Config::split_chr(std::string const &str, char delim,
150) std::vector<std::string> &fields)
151) {
152) std::string::size_type pos = 0, end;
153) fields.clear();
154) while ((end = str.find(delim, pos)) != std::string::npos) {
155) fields.push_back(str.substr(pos, end - pos));
156) pos = end + 1;
157) }
158) fields.push_back(str.substr(pos));
159) }
160)
161) /**
162) * @brief convert string to unsigned long
163) * @param[in] str string to convert
164) * @return unsigned long parsed from string
165) * @throws std::exception in case of error
166) */
167) unsigned long Config::str2ul(std::string const &str)
168) {
169) char const *sz = str.c_str();
170) char *end;
171) unsigned long ul = strtoul(sz, &end, 0);
172) if (end == sz || *end != 0) {
173) std::stringstream msg;
174) msg << "invalid unsigned integer \"" << str << "\"";
175) throw std::runtime_error(msg.str());
176) }
177) return ul;
178) }
179)
180) /**
181) * @brief convert string to two unsigned longs
182) * @param[in] str string containing two comma-separated unsigned integers
183) * @param[out] ul1 first unsigned long parsed from string
184) * @param[out] ul2 second unsigned long parsed from string
185) * @throws std::exception in case of error
186) */
187) void Config::str2ul2(std::string const &str,
188) unsigned long &ul1, unsigned long &ul2)
189) {
190) std::vector<std::string> fields;
191) split_chr(str, ',', fields);
192) if (fields.size() != 2) {
193) std::stringstream msg;
194) msg << "expected two comma-separated unsigned integers, found \""
195) << str << "\"";
196) throw std::runtime_error(msg.str());
197) }
198) try {
199) ul1 = str2ul(fields[0]);
200) ul2 = str2ul(fields[1]);
201) } catch (std::exception &ex) {
202) std::stringstream msg;
203) msg << "invalid unsigned integer pair \"" << str << "\": " << ex.what();
204) throw std::runtime_error(msg.str());
205) }
206) }
207)
208) /**
209) * @brief convert string to double (using the decimal dot for any locale)
210) * @param[in] str string to convert
211) * @return double parsed from string
212) * @throws std::exception in case of error
213) */
214) double Config::str2d(std::string const &str)
215) {
216) char const *sz = str.c_str();
217)
218) // skip leading whitespace
219) while (isspace(*sz)) {
220) ++sz;
221) }
222)
223) // start processing after leading whitespace
224) char const *ptr = sz;
225)
226) // read optional sign
227) double sign = 1.0;
228) if (*ptr == '+') {
229) sign = 1.0;
230) ++ptr;
231) } else if (*ptr == '-') {
232) sign = -1.0;
233) ++ptr;
234) }
235)
236) // read digits before dot
237) double value = 0.0;
238) while (*ptr >= '0' && *ptr <= '9') {
239) value = value * 10.0 + (double)(*ptr - '0');
240) ++ptr;
241) }
242)
243) // read dot and digits after it
244) double weight = 0.1;
245) if (*ptr == '.') {
246) ++ptr;
247)
248) /* read digits after dot */
249) while (*ptr >= '0' && *ptr <= '9') {
250) value += weight * (double)(*ptr - '0');
251) weight *= 0.1;
252) ++ptr;
253) }
254)
255) } // if (*ptr == '.')
256)
257) // merge sign into value
258) value *= sign;
259)
260) // read exponent
261) if (*ptr == 'E' || *ptr == 'e') {
262) ++ptr;
263)
264) /* read optional sign */
265) int exp_sign = 1;
266) if (*ptr == '+') {
267) exp_sign = 1;
268) ++ptr;
269) } else if (*ptr == '-') {
270) exp_sign = -1;
271) ++ptr;
272) }
273)
274) /* read digits */
275) int exp_value = 0;
276) while (*ptr >= '0' && *ptr <= '9') {
277) exp_value = exp_value * 10 + (int)(*ptr - '0');
278) ++ptr;
279) }
280)
281) /* merge exponent into value */
282) value *= pow(10.0, exp_sign * exp_value);
283)
284) } // if (*nptr == 'E' || *nptr == 'e')
285)
286) // skip trailing whitespace
287) while (isspace(*ptr)) {
288) ++ptr;
289) }
290)
291) // leftover characters -> error */
292) if (ptr == sz || *ptr != 0) {
293) std::stringstream msg;
294) msg << "invalid floating point value \"" << str << "\"";
295) throw std::runtime_error(msg.str());
296) }
297)
298) // return value
299) return value;
300) }
301)
302) /**
303) * @brief convert string to three doubles (decimal dot for any locale)
304) * @param[in] str string containing three comma-separated doubles
305) * @param[out] d1 first double parsed from string
306) * @param[out] d2 second double parsed from string
307) * @param[out] d3 third double parsed from string
308) * @throws std::exception in case of error
309) */
310) void Config::str2d3(std::string const &str,
311) double &d1, double &d2, double &d3)
312) {
313) std::vector<std::string> fields;
314) split_chr(str, ',', fields);
315) if (fields.size() != 3) {
316) std::stringstream msg;
317) msg << "expected three comma-separated floating point values, found \""
318) << str << "\"";
319) throw std::runtime_error(msg.str());
320) }
321) try {
322) d1 = str2d(fields[0]);
323) d2 = str2d(fields[1]);
324) d3 = str2d(fields[2]);
325) } catch (std::exception &ex) {
326) std::stringstream msg;
327) msg << "invalid floating point triplet \"" << str << "\": " << ex.what();
328) throw std::runtime_error(msg.str());
329) }
330) }
331)
|
complete implementation of...
Stefan Schuermans authored 7 years ago
|
332) /**
333) * @brief convert string to IPv4/port address
334) * @param[in] str string containing IPv4/port address
335) * @throws std::exception in case of error
336) */
337) void Config::str2addr(std::string const &str, struct sockaddr_in &addr)
338) {
339) // split address into IPv4 and port
340) std::vector<std::string> fields;
341) split_chr(str, ':', fields);
342) if (fields.size() != 2) {
343) std::stringstream msg;
344) msg << "expected \"<IPv4>:<port>\", found \"" << str << "\"";
345) throw std::runtime_error(msg.str());
346) }
347) std::string &strIPv4 = fields[0], &strPort = fields[1];
348)
349) // parse IPv4 address
350) if (! inet_aton(strIPv4.c_str(), &addr.sin_addr)) {
351) std::stringstream msg;
352) msg << "invalid IPv4 \"" << strIPv4 << "\"";
353) throw std::runtime_error(msg.str());
354) }
355)
356) // parse port
357) unsigned long port;
358) try {
359) port = str2ul(strPort);
360) if (port == 0 || port > 65535) {
361) throw std::runtime_error("port number out of range");
362) }
363) } catch (std::exception &ex) {
364) std::stringstream msg;
365) msg << "invalid port number \"" << strPort << "\": " << ex.what();
366) throw std::runtime_error(msg.str());
367) }
368) addr.sin_port = htons(port);
369)
370) // fin in remaining fields of address structure
371) addr.sin_family = AF_INET;
372) }
373)
|
begin of config file parsing
Stefan Schuermans authored 7 years ago
|
374) /**
375) * @brief read config file
376) * @param[in] configFile name of config file
377) * @throws std::exception in case of error
378) */
379) void Config::readFile(std::string const &configFile)
380) {
381) // open file
382) std::ifstream cf(configFile.c_str(), std::ios::in);
383) if (! cf.is_open()) {
384) std::stringstream msg;
385) msg << "cannot open config file \"" << configFile << "\" for reading";
386) throw std::runtime_error(msg.str());
387) }
388)
389) // read lines and process them
390) std::string line;
391) size_t no;
392) for (no = 1; std::getline(cf, line); ++no) {
393) // process line
394) try {
395) procLine(line);
396) } catch (std::exception &ex) {
397) std::stringstream msg;
398) msg << "error in line " << no << " of config file \"" << configFile
399) << "\": " << ex.what();
400) throw std::runtime_error(msg.str());
401) }
402) }
403)
404) // close file
405) cf.close();
|
implement drawing pixels
Stefan Schuermans authored 7 years ago
|
406)
407) // update internal data
408) update();
|
begin of config file parsing
Stefan Schuermans authored 7 years ago
|
409) }
410)
411) /**
412) * @brief process line from config file
413) * @param[in] line line to process
414) * @throws std::exception in case of error
415) */
416) void Config::procLine(std::string line)
417) {
418) // remove comment ("# ...")
419) size_t commentStart = line.find("#");
420) if (commentStart != std::string::npos) {
421) line.erase(commentStart);
422) }
423)
424) trim(line);
425)
426) // ignore empty lines
427) if (line.empty()) {
428) return;
429) }
430)
431) // split line at equal sign
432) size_t equalSign = line.find("=");
433) if (equalSign == std::string::npos) {
434) std::stringstream msg;
435) msg << "no equal sign found in \"" << line << "\"";
436) throw std::runtime_error(msg.str());
437) }
438) std::string setting = line.substr(0, equalSign);
439) std::string value = line.substr(equalSign + 1);
440) trim(setting);
441) trim(value);
442)
443) procSetting(setting, value);
444) }
445)
446) /**
447) * @brief process setting from config file
448) * @param[in] setting name of the setting
449) * @param[in] value value for setting
450) * @throws std::exception in case of error
451) */
452) void Config::procSetting(std::string const &setting, std::string const &value)
453) {
454) std::vector<std::string> setFields, valFields;
455) split(setting, setFields);
456) split(value, valFields);
457)
458) // empty setting
459) if (setFields.size() < 1) {
460) throw std::runtime_error("empty setting name");
461) }
462)
463) // distributor
464) if (setFields[0] == "distributor") {
|
continue implementing confi...
Stefan Schuermans authored 7 years ago
|
465) proc_distributor(setFields, valFields);
|
begin of config file parsing
Stefan Schuermans authored 7 years ago
|
466) }
467) // distributor address
468) else if (setFields[0] == "distributorAddr") {
|
continue implementing confi...
Stefan Schuermans authored 7 years ago
|
469) proc_distributorAddr(setFields, valFields);
|
begin of config file parsing
Stefan Schuermans authored 7 years ago
|
470) }
471) // mapping
472) else if (setFields[0] == "mapping") {
|
continue implementing confi...
Stefan Schuermans authored 7 years ago
|
473) proc_mapping(setFields, valFields);
|
begin of config file parsing
Stefan Schuermans authored 7 years ago
|
474) }
475) // output
476) else if (setFields[0] == "output") {
|
continue implementing confi...
Stefan Schuermans authored 7 years ago
|
477) proc_output(setFields, valFields);
|
begin of config file parsing
Stefan Schuermans authored 7 years ago
|
478) }
479) // unknown setting
480) else {
481) std::stringstream msg;
482) msg << "unknown setting \"" << setting << "\"";
483) throw std::runtime_error(msg.str());
484) }
485) }
486)
|
continue implementing confi...
Stefan Schuermans authored 7 years ago
|
487) /**
488) * @brief process distributor line from config file
489) * @param[in] setFields fields of the setting parts
490) * @param[in] valFields fields of the value part
491) * @throws std::exception in case of error
492) */
493) void Config::proc_distributor(std::vector<std::string> const &setFields,
494) std::vector<std::string> const &valFields)
495) {
496) // check number of setting fields
497) if (setFields.size() != 2) {
498) std::stringstream msg;
499) msg << "invalid \"distributor\" setting with " << setFields.size()
500) << " fields, expected \"distributor <distno>\"";
501) throw std::runtime_error(msg.str());
502) }
503)
504) // get and check distributor number
505) unsigned long distno;
506) try {
507) distno = str2ul(setFields[1]);
508) } catch (std::exception &ex) {
509) std::stringstream msg;
510) msg << "invalid distributor number \"" << setFields[1] << "\": "
511) << ex.what();
512) throw std::runtime_error(msg.str());
513) }
514) if (m_distriMap.find(distno) != m_distriMap.end()) {
515) std::stringstream msg;
516) msg << "duplicate \"distributor " << distno << "\" setting";
517) throw std::runtime_error(msg.str());
518) }
519)
520) // check number of value fields
521) if (valFields.size() != 1) {
522) std::stringstream msg;
523) msg << "invalid value for \"distributor " << distno << "\": "
524) << setFields.size() << " fields, expected \"<outputs>,<pixels>\"";
525) throw std::runtime_error(msg.str());
526) }
527)
528) // get and check outputs and pixels per output
529) unsigned long outputs, pixels;
530) try {
531) str2ul2(valFields[0], outputs, pixels);
532) if (outputs < 1) {
533) std::stringstream msg;
534) msg << "invalid number of outputs \"" << outputs << "\"";
535) throw std::runtime_error(msg.str());
536) }
537) if (pixels < 1) {
538) std::stringstream msg;
539) msg << "invalid number of pixels per output \"" << pixels << "\"";
540) throw std::runtime_error(msg.str());
541) }
542) } catch (std::exception &ex) {
543) std::stringstream msg;
544) msg << "invalid value for \"distributor " << distno << "\": "
545) << ex.what();
546) throw std::runtime_error(msg.str());
547) }
548)
549) // create distributor
550) m_distriMap[distno].init(distno, outputs, pixels);
551) }
552)
553) /**
554) * @brief process distributorAddr line from config file
555) * @param[in] setFields fields of the setting parts
556) * @param[in] valFields fields of the value part
557) * @throws std::exception in case of error
558) */
559) void Config::proc_distributorAddr(std::vector<std::string> const &setFields,
560) std::vector<std::string> const &valFields)
561) {
562) // check number of setting fields
563) if (setFields.size() != 2) {
564) std::stringstream msg;
565) msg << "invalid \"distributorAddr\" setting with " << setFields.size()
566) << " fields, expected \"distributorAddr <distno>\"";
567) throw std::runtime_error(msg.str());
568) }
569)
570) // get distributor
571) Distri &distri = getDistri(setFields[1]);
572)
573) // check number of value fields
574) if (valFields.size() != 1) {
575) std::stringstream msg;
576) msg << "invalid value for \"distributorAddr " << distri.getNo() << "\": "
577) << setFields.size() << " fields, expected \"<IPv4>:<port>\"";
578) throw std::runtime_error(msg.str());
579) }
580)
581) // parse address
|
complete implementation of...
Stefan Schuermans authored 7 years ago
|
582) struct sockaddr_in addr;
583) try {
584) str2addr(valFields[0], addr);
585) } catch (std::exception &ex) {
586) std::stringstream msg;
587) msg << "invalid value for \"mdistributorAddr " << distri.getNo() << "\": "
588) << ex.what();
589) throw std::runtime_error(msg.str());
590) }
591)
592) // set address
593) distri.setAddr(addr);
|
continue implementing confi...
Stefan Schuermans authored 7 years ago
|
594) }
595)
596) /**
597) * @brief process mapping line from config file
598) * @param[in] setFields fields of the setting parts
599) * @param[in] valFields fields of the value part
600) * @throws std::exception in case of error
601) */
602) void Config::proc_mapping(std::vector<std::string> const &setFields,
603) std::vector<std::string> const &valFields)
604) {
605) // check number of setting fields
606) if (setFields.size() != 3) {
607) std::stringstream msg;
608) msg << "invalid \"mapping\" setting with " << setFields.size()
609) << " fields, expected \"mapping <distno> [red|green|blue]\"";
610) throw std::runtime_error(msg.str());
611) }
612)
613) // get distributor
614) Distri &distri = getDistri(setFields[1]);
615)
616) // get channel
617) std::string strColor = setFields[2];
618) Mapping::Channel channel;
619) if (strColor == "red" ) {
620) channel = Mapping::Red;
621) } else if (strColor == "green" ) {
622) channel = Mapping::Green;
623) } else if (strColor == "blue" ) {
624) channel = Mapping::Blue;
625) } else {
626) std::stringstream msg;
627) msg << "invalid \"mapping\" setting: unknown color \"" << strColor
628) << "\" fields, expected \"red\", \"green\" or \"blue\"";
629) throw std::runtime_error(msg.str());
630) }
631)
632) // check number of value fields
633) if (valFields.size() != 3) {
634) std::stringstream msg;
635) msg << "invalid value for \"mapping " << distri.getNo() << " "
636) << strColor << "\": " << setFields.size()
637) << " fields, expected \"<base> <factor> <gamma>\"";
638) throw std::runtime_error(msg.str());
639) }
640)
641) // parse value fields
642) double base, factor, gamma;
643) try {
644) base = str2d(valFields[0]);
645) } catch (std::exception &ex) {
646) std::stringstream msg;
647) msg << "invalid value for \"mapping " << distri.getNo() << " "
648) << strColor << "\": invalid value \"" << valFields[0]
649) << "\"for \"base\": " << ex.what();
650) throw std::runtime_error(msg.str());
651) }
652) try {
653) factor = str2d(valFields[1]);
654) } catch (std::exception &ex) {
655) std::stringstream msg;
656) msg << "invalid value for \"mapping " << distri.getNo() << " "
657) << strColor << "\": invalid value \"" << valFields[1]
658) << "\"for \"factor\": " << ex.what();
659) throw std::runtime_error(msg.str());
660) }
661) try {
662) gamma = str2d(valFields[2]);
663) if (gamma <= 0.0) {
664) throw std::runtime_error("gamma value must be positive");
665) }
666) } catch (std::exception &ex) {
667) std::stringstream msg;
668) msg << "invalid value for \"mapping " << distri.getNo() << " "
669) << strColor << "\": invalid value \"" << valFields[2]
670) << "\"for \"base\": " << ex.what();
671) throw std::runtime_error(msg.str());
672) }
673)
674) // set mapping of distributor
675) distri.setMapping(channel, Mapping(base, factor, gamma));
676) }
677)
678) /**
679) * @brief process output line from config file
680) * @param[in] setFields fields of the setting parts
681) * @param[in] valFields fields of the value part
682) * @throws std::exception in case of error
683) */
684) void Config::proc_output(std::vector<std::string> const &setFields,
685) std::vector<std::string> const &valFields)
686) {
687) // check number of setting fields
688) if (setFields.size() != 2) {
689) std::stringstream msg;
690) msg << "invalid \"output\" setting with " << setFields.size()
691) << " fields, expected \"output <distno>,<outno>\"";
692) throw std::runtime_error(msg.str());
693) }
694)
695) // parse distributor and output numbers
696) unsigned long distno, outno;
697) try {
698) str2ul2(setFields[1], distno, outno);
699) } catch (std::exception &ex) {
700) std::stringstream msg;
701) msg << "invalid output specifier \"" << setFields[1]
702) << "\": expected \"<distno>,<outno>\": " << ex.what();
703) throw std::runtime_error(msg.str());
704) }
705)
706) // get distributor
707) Distri &distri = getDistri(distno);
708)
709) // check output number
710) unsigned long outputs = distri.getOutputs();
711) if (outno > outputs) {
712) std::stringstream msg;
713) msg << "invalid output number " << outno << " for distributor " << distno
714) << ": only " << outputs << " outputs available";
715) throw std::runtime_error(msg.str());
716) }
717)
|
complete implementation of...
Stefan Schuermans authored 7 years ago
|
718) // add output to distributor
719) try {
720) distri.addOutput(outno);
721) } catch (std::exception &ex) {
722) std::stringstream msg;
723) msg << "cannot add output " << outno << " to distributor " << distno
724) << ": " << ex.what();
725) throw std::runtime_error(msg.str());
726) }
727)
|
continue implementing confi...
Stefan Schuermans authored 7 years ago
|
728) // parse all pixels
729) std::vector<std::string>::const_iterator pix;
730) unsigned long p;
731) for (pix = valFields.begin(), p = 0; pix != valFields.end(); ++pix, ++p) {
732) // parse pixel description
733) double x, y, r;
734) try {
735) str2d3(*pix, x, y, r);
736) } catch (std::exception &ex) {
737) std::stringstream msg;
738) msg << "invalid pixel description \"" << *pix << "\" for pixel "
739) << p << " at output " << outno << " of distributor " << distno
740) << ": expected \"<x>,<y>,<r>\": " << ex.what();
741) throw std::runtime_error(msg.str());
742) }
743) // add pixel
|
complete implementation of...
Stefan Schuermans authored 7 years ago
|
744) try {
745) distri.addPixel(outno, Pixel(x, y, r));
746) } catch (std::exception &ex) {
747) std::stringstream msg;
748) msg << "cannot add pixel \"" << *pix << "\" (pixel "
749) << p << ") to output " << outno << " of distributor " << distno
750) << ": " << ex.what();
751) throw std::runtime_error(msg.str());
752) }
|
continue implementing confi...
Stefan Schuermans authored 7 years ago
|
753) } // for pixel
754) }
755)
756) /**
757) * @brief get distributor
758) * @param[in] strDistno distributor number as string
759) * @return reference to distributor object in map
760) * @throws std::exception in case of error
761) */
762) Distri & Config::getDistri(std::string const &strDistno)
763) {
764) unsigned long distno;
765) try {
766) distno = str2ul(strDistno);
767) } catch (std::exception &ex) {
768) std::stringstream msg;
769) msg << "invalid distributor number \"" << strDistno << "\": "
770) << ex.what();
771) throw std::runtime_error(msg.str());
772) }
773) return getDistri(distno);
774) }
775)
776) /**
777) * @brief get distributor
778) * @param[in] distno distributor number
779) * @return reference to distributor object in map
780) * @throws std::exception in case of error
781) */
782) Distri & Config::getDistri(unsigned long distno)
783) {
784) DistriMap::iterator distri = m_distriMap.find(distno);
785) if (distri == m_distriMap.end()) {
786) std::stringstream msg;
787) msg << "no distributor with number \"" << distno << "\" found";
788) throw std::runtime_error(msg.str());
789) }
790) return distri->second;
791) }
792)
|