lsst.daf.base 23.0.0+57f5c03693
PropertySet.cc
Go to the documentation of this file.
1// -*- lsst-c++ -*-
2
3/*
4 * LSST Data Management System
5 * Copyright 2008, 2009, 2010 LSST Corporation.
6 *
7 * This product includes software developed by the
8 * LSST Project (http://www.lsst.org/).
9 *
10 * This program is free software: you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation, either version 3 of the License, or
13 * (at your option) any later version.
14 *
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more errors.
19 *
20 * You should have received a copy of the LSST License Statement and
21 * the GNU General Public License along with this program. If not,
22 * see <http://www.lsstcorp.org/LegalNotices/>.
23 */
24
26
27#include <algorithm>
28#include <iomanip>
29#include <sstream>
30#include <stdexcept>
31#include <any>
32
35
36namespace lsst {
37namespace daf {
38namespace base {
39
40namespace {
41
48template <typename T>
49void _append(std::vector<std::any>& dest, std::vector<T> const& src) {
50 dest.reserve(dest.size() + src.size());
51 for (const T& val : src) {
52 dest.push_back(static_cast<T>(val));
53 }
54}
55
56} // namespace
57
58PropertySet::PropertySet(bool flat) : _flat(flat) {}
59
60PropertySet::~PropertySet() noexcept = default;
61
63// Accessors
65
66PropertySet::Ptr PropertySet::deepCopy() const {
67 Ptr n(new PropertySet(_flat));
68 for (auto const& elt : _map) {
69 if (elt.second->back().type() == typeid(Ptr)) {
70 for (auto const& j : *elt.second) {
71 Ptr p = std::any_cast<Ptr>(j);
72 if (p.get() == 0) {
73 n->add(elt.first, Ptr());
74 } else {
75 n->add(elt.first, p->deepCopy());
76 }
77 }
78 } else {
80 n->_map[elt.first] = vp;
81 }
82 }
83 return n;
84}
85
86size_t PropertySet::nameCount(bool topLevelOnly) const {
87 int n = 0;
88 for (auto const& elt : _map) {
89 ++n;
90 if (!topLevelOnly && elt.second->back().type() == typeid(Ptr)) {
91 Ptr p = std::any_cast<Ptr>(elt.second->back());
92 if (p.get() != 0) {
93 n += p->nameCount(false);
94 }
95 }
96 }
97 return n;
98}
99
100std::vector<std::string> PropertySet::names(bool topLevelOnly) const {
102 for (auto const& elt : _map) {
103 v.push_back(elt.first);
104 if (!topLevelOnly && elt.second->back().type() == typeid(Ptr)) {
105 Ptr p = std::any_cast<Ptr>(elt.second->back());
106 if (p.get() != 0) {
107 std::vector<std::string> w = p->names(false);
108 for (auto const& k : w) {
109 v.push_back(elt.first + "." + k);
110 }
111 }
112 }
113 }
114 return v;
115}
116
117std::vector<std::string> PropertySet::paramNames(bool topLevelOnly) const {
119 for (auto const& elt : _map) {
120 if (elt.second->back().type() == typeid(Ptr)) {
121 Ptr p = std::any_cast<Ptr>(elt.second->back());
122 if (p.get() != 0 && !topLevelOnly) {
123 std::vector<std::string> w = p->paramNames(false);
124 for (auto const& k : w) {
125 v.push_back(elt.first + "." + k);
126 }
127 }
128 } else {
129 v.push_back(elt.first);
130 }
131 }
132 return v;
133}
134
135std::vector<std::string> PropertySet::propertySetNames(bool topLevelOnly) const {
137 for (auto const& elt : _map) {
138 if (elt.second->back().type() == typeid(Ptr)) {
139 v.push_back(elt.first);
140 Ptr p = std::any_cast<Ptr>(elt.second->back());
141 if (p.get() != 0 && !topLevelOnly) {
142 std::vector<std::string> w = p->propertySetNames(false);
143 for (auto const& k : w) {
144 v.push_back(elt.first + "." + k);
145 }
146 }
147 }
148 }
149 return v;
150}
151
152bool PropertySet::exists(std::string const& name) const { return _find(name) != _map.end(); }
153
154bool PropertySet::isArray(std::string const& name) const {
155 auto const i = _find(name);
156 return i != _map.end() && i->second->size() > 1U;
157}
158
159bool PropertySet::isPropertySetPtr(std::string const& name) const {
160 auto const i = _find(name);
161 return i != _map.end() && i->second->back().type() == typeid(Ptr);
162}
163
164bool PropertySet::isUndefined(std::string const& name) const {
165 auto const i = _find(name);
166 return i != _map.end() && i->second->back().type() == typeid(nullptr);
167}
168
169size_t PropertySet::valueCount() const {
170 size_t sum = 0;
171 for (auto const& name : paramNames(false)) {
172 sum += valueCount(name);
173 }
174 return sum;
175}
176
177size_t PropertySet::valueCount(std::string const& name) const {
178 auto const i = _find(name);
179 if (i == _map.end()) return 0;
180 return i->second->size();
181}
182
183std::type_info const& PropertySet::typeOf(std::string const& name) const {
184 auto const i = _find(name);
185 if (i == _map.end()) {
186 throw LSST_EXCEPT(pex::exceptions::NotFoundError, name + " not found");
187 }
188 return i->second->back().type();
189}
190
191template <typename T>
192std::type_info const& PropertySet::typeOfT() {
193 return typeid(T);
194}
195
196// The following throw an exception if the type does not match exactly.
197
198template <typename T>
199T PropertySet::get(std::string const& name)
200 const { /* parasoft-suppress LsstDm-3-4a LsstDm-4-6 "allow template over bool" */
201 auto const i = _find(name);
202 if (i == _map.end()) {
203 throw LSST_EXCEPT(pex::exceptions::NotFoundError, name + " not found");
204 }
205 try {
206 return std::any_cast<T>(i->second->back());
207 } catch (std::bad_any_cast &) {
208 std::throw_with_nested(LSST_EXCEPT(pex::exceptions::TypeError, name));
209 }
210 // not reached
211 return std::any_cast<T>(i->second->back());
212}
213
214template <typename T>
215T PropertySet::get(std::string const& name, T const& defaultValue)
216 const { /* parasoft-suppress LsstDm-3-4a LsstDm-4-6 "allow template over bool" */
217 auto const i = _find(name);
218 if (i == _map.end()) {
219 return defaultValue;
220 }
221 try {
222 return std::any_cast<T>(i->second->back());
223 } catch (std::bad_any_cast &) {
224 std::throw_with_nested(LSST_EXCEPT(pex::exceptions::TypeError, name));
225 }
226 // not reached
227 return std::any_cast<T>(i->second->back());
228}
229
230template <typename T>
231std::vector<T> PropertySet::getArray(std::string const& name) const {
232 auto const i = _find(name);
233 if (i == _map.end()) {
234 throw LSST_EXCEPT(pex::exceptions::NotFoundError, name + " not found");
235 }
237 for (auto const& j : *(i->second)) {
238 try {
239 v.push_back(std::any_cast<T>(j));
240 } catch (std::bad_any_cast &) {
241 std::throw_with_nested(LSST_EXCEPT(pex::exceptions::TypeError, name));
242 }
243 }
244 return v;
245}
246
247// The following throw an exception if the conversion is inappropriate.
248
249bool PropertySet::getAsBool(std::string const& name)
250 const { /* parasoft-suppress LsstDm-3-4a LsstDm-4-6 "for symmetry with other types" */
251 return get<bool>(name);
252}
253
254int PropertySet::getAsInt(std::string const& name) const {
255 auto const i = _find(name);
256 if (i == _map.end()) {
257 throw LSST_EXCEPT(pex::exceptions::NotFoundError, name + " not found");
258 }
259 std::any v = i->second->back();
260 std::type_info const& t = v.type();
261 if (t == typeid(bool)) {
262 return std::any_cast<bool>(v);
263 } else if (t == typeid(char)) {
264 return std::any_cast<char>(v);
265 } else if (t == typeid(signed char)) {
266 return std::any_cast<signed char>(v);
267 } else if (t == typeid(unsigned char)) {
268 return std::any_cast<unsigned char>(v);
269 } else if (t == typeid(short)) {
270 return std::any_cast<short>(v);
271 } else if (t == typeid(unsigned short)) {
272 return std::any_cast<unsigned short>(v);
273 }
274 try {
275 return std::any_cast<int>(v);
276 } catch (std::bad_any_cast &) {
277 std::throw_with_nested(LSST_EXCEPT(pex::exceptions::TypeError, name));
278 }
279 // not reached
280 return std::any_cast<int>(v);
281}
282
283int64_t PropertySet::getAsInt64(std::string const& name) const {
284 auto const i = _find(name);
285 if (i == _map.end()) {
286 throw LSST_EXCEPT(pex::exceptions::NotFoundError, name + " not found");
287 }
288 std::any v = i->second->back();
289 std::type_info const& t = v.type();
290 if (t == typeid(bool)) return std::any_cast<bool>(v);
291 if (t == typeid(char)) return std::any_cast<char>(v);
292 if (t == typeid(signed char)) return std::any_cast<signed char>(v);
293 if (t == typeid(unsigned char)) return std::any_cast<unsigned char>(v);
294 if (t == typeid(short)) return std::any_cast<short>(v);
295 if (t == typeid(unsigned short)) return std::any_cast<unsigned short>(v);
296 if (t == typeid(int)) return std::any_cast<int>(v);
297 if (t == typeid(unsigned int)) return std::any_cast<unsigned int>(v);
298 if (t == typeid(long)) return std::any_cast<long>(v);
299 if (t == typeid(long long)) return std::any_cast<long long>(v);
300 try {
301 return std::any_cast<int64_t>(v);
302 } catch (std::bad_any_cast &) {
303 std::throw_with_nested(LSST_EXCEPT(pex::exceptions::TypeError, name));
304 }
305 // not reached
306 return std::any_cast<int64_t>(v);
307}
308
309uint64_t PropertySet::getAsUInt64(std::string const& name) const {
310 auto const i = _find(name);
311 if (i == _map.end()) {
312 throw LSST_EXCEPT(pex::exceptions::NotFoundError, name + " not found");
313 }
314 std::any v = i->second->back();
315 std::type_info const& t = v.type();
316 if (t == typeid(bool)) return std::any_cast<bool>(v);
317 if (t == typeid(char)) return std::any_cast<char>(v);
318 if (t == typeid(signed char)) return std::any_cast<signed char>(v);
319 if (t == typeid(unsigned char)) return std::any_cast<unsigned char>(v);
320 if (t == typeid(short)) return std::any_cast<short>(v);
321 if (t == typeid(unsigned short)) return std::any_cast<unsigned short>(v);
322 if (t == typeid(int)) return std::any_cast<int>(v);
323 if (t == typeid(unsigned int)) return std::any_cast<unsigned int>(v);
324 if (t == typeid(long)) return std::any_cast<long>(v);
325 if (t == typeid(long long)) return std::any_cast<long long>(v);
326 if (t == typeid(unsigned long long)) return std::any_cast<unsigned long long>(v);
327 try {
328 return std::any_cast<uint64_t>(v);
329 } catch (std::bad_any_cast &) {
330 std::throw_with_nested(LSST_EXCEPT(pex::exceptions::TypeError, name));
331 }
332 // not reached
333 return std::any_cast<uint64_t>(v);
334}
335
336double PropertySet::getAsDouble(std::string const& name) const {
337 auto const i = _find(name);
338 if (i == _map.end()) {
339 throw LSST_EXCEPT(pex::exceptions::NotFoundError, name + " not found");
340 }
341 std::any v = i->second->back();
342 std::type_info const& t = v.type();
343 if (t == typeid(bool)) return std::any_cast<bool>(v);
344 if (t == typeid(char)) return std::any_cast<char>(v);
345 if (t == typeid(signed char)) return std::any_cast<signed char>(v);
346 if (t == typeid(unsigned char)) return std::any_cast<unsigned char>(v);
347 if (t == typeid(short)) return std::any_cast<short>(v);
348 if (t == typeid(unsigned short)) return std::any_cast<unsigned short>(v);
349 if (t == typeid(int)) return std::any_cast<int>(v);
350 if (t == typeid(unsigned int)) return std::any_cast<unsigned int>(v);
351 if (t == typeid(long)) return std::any_cast<long>(v);
352 if (t == typeid(unsigned long)) return std::any_cast<unsigned long>(v);
353 if (t == typeid(long long)) return std::any_cast<long long>(v);
354 if (t == typeid(unsigned long long)) return std::any_cast<unsigned long long>(v);
355 if (t == typeid(float)) return std::any_cast<float>(v);
356 try {
357 return std::any_cast<double>(v);
358 } catch (std::bad_any_cast &) {
359 std::throw_with_nested(LSST_EXCEPT(pex::exceptions::TypeError, name));
360 }
361 // not reached
362 return std::any_cast<double>(v);
363}
364
365std::string PropertySet::getAsString(std::string const& name) const { return get<std::string>(name); }
366
367PropertySet::Ptr PropertySet::getAsPropertySetPtr(std::string const& name) const { return get<Ptr>(name); }
368
369Persistable::Ptr PropertySet::getAsPersistablePtr(std::string const& name) const {
370 return get<Persistable::Ptr>(name);
371}
372
373std::string PropertySet::toString(bool topLevelOnly, std::string const& indent) const {
375 std::vector<std::string> nv = names();
376 sort(nv.begin(), nv.end());
377 for (auto const& i : nv) {
378 std::shared_ptr<std::vector<std::any>> vp = _map.find(i)->second;
379 std::type_info const& t = vp->back().type();
380 if (t == typeid(Ptr)) {
381 s << indent << i << " = ";
382 if (topLevelOnly) {
383 s << "{ ... }";
384 } else {
385 Ptr p = std::any_cast<Ptr>(vp->back());
386 if (p.get() == 0) {
387 s << "{ NULL }";
388 } else {
389 s << '{' << std::endl;
390 s << p->toString(false, indent + "..");
391 s << indent << '}';
392 }
393 }
394 s << std::endl;
395 } else {
396 s << indent << _format(i);
397 }
398 }
399 return s.str();
400}
401
402std::string PropertySet::_format(std::string const& name) const {
404 s << std::showpoint; // Always show a decimal point for floats
405 auto const j = _map.find(name);
406 s << j->first << " = ";
408 if (vp->size() > 1) {
409 s << "[ ";
410 }
411 std::type_info const& t = vp->back().type();
412 bool isFirst = true;
413 for (auto const& k : *vp) {
414 if (isFirst) {
415 isFirst = false;
416 } else {
417 s << ", ";
418 }
419 std::any const& v(k);
420 if (t == typeid(bool)) {
421 s << std::any_cast<bool>(v);
422 } else if (t == typeid(char)) {
423 s << '\'' << std::any_cast<char>(v) << '\'';
424 } else if (t == typeid(signed char)) {
425 s << '\'' << std::any_cast<signed char>(v) << '\'';
426 } else if (t == typeid(unsigned char)) {
427 s << '\'' << std::any_cast<unsigned char>(v) << '\'';
428 } else if (t == typeid(short)) {
429 s << std::any_cast<short>(v);
430 } else if (t == typeid(unsigned short)) {
431 s << std::any_cast<unsigned short>(v);
432 } else if (t == typeid(int)) {
433 s << std::any_cast<int>(v);
434 } else if (t == typeid(unsigned int)) {
435 s << std::any_cast<unsigned int>(v);
436 } else if (t == typeid(long)) {
437 s << std::any_cast<long>(v);
438 } else if (t == typeid(unsigned long)) {
439 s << std::any_cast<unsigned long>(v);
440 } else if (t == typeid(long long)) {
441 s << std::any_cast<long long>(v);
442 } else if (t == typeid(unsigned long long)) {
443 s << std::any_cast<unsigned long long>(v);
444 } else if (t == typeid(float)) {
445 s << std::setprecision(7) << std::any_cast<float>(v);
446 } else if (t == typeid(double)) {
447 s << std::setprecision(14) << std::any_cast<double>(v);
448 } else if (t == typeid(std::string)) {
449 s << '"' << std::any_cast<std::string>(v) << '"';
450 } else if (t == typeid(DateTime)) {
451 s << std::any_cast<DateTime>(v).toString(DateTime::UTC);
452 } else if (t == typeid(Ptr)) {
453 s << "{ ... }";
454 } else if (t == typeid(Persistable::Ptr)) {
455 s << "<Persistable>";
456 } else {
457 s << "<Unknown>";
458 }
459 }
460 if (j->second->size() > 1) {
461 s << " ]";
462 }
463 s << std::endl;
464 return s.str();
465}
466
468// Modifiers
470
471template <typename T>
472void PropertySet::set(std::string const& name, T const& value) {
474 vp->push_back(value);
475 _set(name, vp);
476}
477
478template <typename T>
479void PropertySet::set(std::string const& name, std::vector<T> const& value) {
480 if (value.empty()) return;
482 _append(*vp, value);
483 _set(name, vp);
484}
485
486void PropertySet::set(std::string const& name, char const* value) { set(name, std::string(value)); }
487
488template <typename T>
489void PropertySet::add(std::string const& name, T const& value) {
490 AnyMap::iterator i = _find(name);
491 if (i == _map.end()) {
492 set(name, value);
493 } else {
494 if (i->second->back().type() != typeid(T)) {
495 throw LSST_EXCEPT(pex::exceptions::TypeError, name + " has mismatched type");
496 }
497 i->second->push_back(value);
498 }
499}
500
501// Specialize for Ptrs to check for cycles.
502template <>
503void PropertySet::add<PropertySet::Ptr>(std::string const& name, Ptr const& value) {
504 AnyMap::iterator i = _find(name);
505 if (i == _map.end()) {
506 set(name, value);
507 } else {
508 if (i->second->back().type() != typeid(Ptr)) {
509 throw LSST_EXCEPT(pex::exceptions::TypeError, name + " has mismatched type");
510 }
511 _cycleCheckPtr(value, name);
512 i->second->push_back(value);
513 }
514}
515
516template <typename T>
517void PropertySet::add(std::string const& name, std::vector<T> const& value) {
518 AnyMap::iterator i = _find(name);
519 if (i == _map.end()) {
520 set(name, value);
521 } else {
522 if (i->second->back().type() != typeid(T)) {
523 throw LSST_EXCEPT(pex::exceptions::TypeError, name + " has mismatched type");
524 }
525 _append(*(i->second), value);
526 }
527}
528
529// Specialize for Ptrs to check for cycles.
530template <>
531void PropertySet::add<PropertySet::Ptr>(std::string const& name, std::vector<Ptr> const& value) {
532 AnyMap::iterator i = _find(name);
533 if (i == _map.end()) {
534 set(name, value);
535 } else {
536 if (i->second->back().type() != typeid(Ptr)) {
537 throw LSST_EXCEPT(pex::exceptions::TypeError, name + " has mismatched type");
538 }
539 _cycleCheckPtrVec(value, name);
540 _append(*(i->second), value);
541 }
542}
543
544void PropertySet::add(std::string const& name, char const* value) { add(name, std::string(value)); }
545
546void PropertySet::copy(std::string const& dest, ConstPtr source, std::string const& name, bool asScalar) {
547 if (source.get() == 0) {
548 throw LSST_EXCEPT(pex::exceptions::InvalidParameterError, "Missing source");
549 }
550 auto const sj = source->_find(name);
551 if (sj == source->_map.end()) {
552 throw LSST_EXCEPT(pex::exceptions::InvalidParameterError, name + " not in source");
553 }
554 remove(dest);
555 if (asScalar) {
556 auto vp = std::make_shared<std::vector<std::any>>();
557 vp->push_back(sj->second->back());
558 _set(dest, vp);
559 } else {
560 auto vp = std::make_shared<std::vector<std::any>>(*(sj->second));
561 _set(dest, vp);
562 }
563}
564
565void PropertySet::combine(ConstPtr source) {
566 if (source.get() == 0) {
567 return;
568 }
569 std::vector<std::string> names = source->paramNames(false);
570 for (auto const& name : names) {
571 auto const sp = source->_find(name);
572 _add(name, sp->second);
573 }
574}
575
576void PropertySet::remove(std::string const& name) {
577 std::string::size_type i = name.find('.');
578 if (_flat || i == name.npos) {
579 _map.erase(name);
580 return;
581 }
582 std::string prefix(name, 0, i);
583 AnyMap::iterator j = _map.find(prefix);
584 if (j == _map.end() || j->second->back().type() != typeid(Ptr)) {
585 return;
586 }
587 Ptr p = std::any_cast<Ptr>(j->second->back());
588 if (p.get() != 0) {
589 std::string suffix(name, i + 1);
590 p->remove(suffix);
591 }
592}
593
595// Private member functions
597
598PropertySet::AnyMap::iterator PropertySet::_find(std::string const& name) {
599 std::string::size_type i = name.find('.');
600 if (_flat || i == name.npos) {
601 return _map.find(name);
602 }
603 std::string prefix(name, 0, i);
604 AnyMap::iterator j = _map.find(prefix);
605 if (j == _map.end() || j->second->back().type() != typeid(Ptr)) {
606 return _map.end();
607 }
608 Ptr p = std::any_cast<Ptr>(j->second->back());
609 if (p.get() == 0) {
610 return _map.end();
611 }
612 std::string suffix(name, i + 1);
613 AnyMap::iterator x = p->_find(suffix);
614 if (x == p->_map.end()) {
615 return _map.end();
616 }
617 return x;
618}
619
620PropertySet::AnyMap::const_iterator PropertySet::_find(std::string const& name) const {
621 std::string::size_type i = name.find('.');
622 if (_flat || i == name.npos) {
623 return _map.find(name);
624 }
625 std::string prefix(name, 0, i);
626 auto const j = _map.find(prefix);
627 if (j == _map.end() || j->second->back().type() != typeid(Ptr)) {
628 return _map.end();
629 }
630 Ptr p = std::any_cast<Ptr>(j->second->back());
631 if (p.get() == 0) {
632 return _map.end();
633 }
634 std::string suffix(name, i + 1);
635 auto const x = p->_find(suffix);
636 if (x == p->_map.end()) {
637 return _map.end();
638 }
639 return x;
640}
641
642void PropertySet::_set(std::string const& name, std::shared_ptr<std::vector<std::any>> vp) {
643 _findOrInsert(name, vp);
644}
645
646void PropertySet::_add(std::string const& name, std::shared_ptr<std::vector<std::any>> vp) {
647 auto const dp = _find(name);
648 if (dp == _map.end()) {
649 _set(name, vp);
650 } else {
651 if (vp->back().type() != dp->second->back().type()) {
652 throw LSST_EXCEPT(pex::exceptions::TypeError, name + " has mismatched type");
653 }
654 // Check for cycles
655 if (vp->back().type() == typeid(Ptr)) {
656 _cycleCheckAnyVec(*vp, name);
657 }
658 _append(*(dp->second), *vp);
659 }
660}
661
662void PropertySet::_findOrInsert(std::string const& name, std::shared_ptr<std::vector<std::any>> vp) {
663 if (vp->back().type() == typeid(Ptr)) {
664 if (_flat) {
665 Ptr source = std::any_cast<Ptr>(vp->back());
666 std::vector<std::string> names = source->paramNames(false);
667 for (auto const& i : names) {
668 auto const sp = source->_find(i);
669 _add(name + "." + i, sp->second);
670 }
671 return;
672 }
673
674 // Check for cycles
675 _cycleCheckAnyVec(*vp, name);
676 }
677
678 std::string::size_type i = name.find('.');
679 if (_flat || i == name.npos) {
680 _map[name] = vp;
681 return;
682 }
683 std::string prefix(name, 0, i);
684 std::string suffix(name, i + 1);
685 AnyMap::iterator j = _map.find(prefix);
686 if (j == _map.end()) {
687 PropertySet::Ptr pp(new PropertySet);
688 pp->_findOrInsert(suffix, vp);
690 temp->push_back(pp);
691 _map[prefix] = temp;
692 return;
693 } else if (j->second->back().type() != typeid(Ptr)) {
694 throw LSST_EXCEPT(pex::exceptions::InvalidParameterError,
695 prefix + " exists but does not contain PropertySet::Ptrs");
696 }
697 Ptr p = std::any_cast<Ptr>(j->second->back());
698 if (p.get() == 0) {
699 throw LSST_EXCEPT(pex::exceptions::InvalidParameterError,
700 prefix + " exists but contains null PropertySet::Ptr");
701 }
702 p->_findOrInsert(suffix, vp);
703}
704
705void PropertySet::_cycleCheckPtrVec(std::vector<Ptr> const& v, std::string const& name) {
706 for (auto const& i : v) {
707 _cycleCheckPtr(i, name);
708 }
709}
710
711void PropertySet::_cycleCheckAnyVec(std::vector<std::any> const& v, std::string const& name) {
712 for (auto const& i : v) {
713 _cycleCheckPtr(std::any_cast<Ptr>(i), name);
714 }
715}
716
717void PropertySet::_cycleCheckPtr(Ptr const& v, std::string const& name) {
718 if (v.get() == this) {
719 throw LSST_EXCEPT(pex::exceptions::InvalidParameterError, name + " would cause a cycle");
720 }
721 std::vector<std::string> sets = v->propertySetNames(false);
722 for (auto const& i : sets) {
723 if (v->getAsPropertySetPtr(i).get() == this) {
724 throw LSST_EXCEPT(pex::exceptions::InvalidParameterError, name + " would cause a cycle");
725 }
726 }
727}
728
730 // Explicit template instantiations
732
734 // Explicit template instantiations are not well understood by doxygen.
735
736#define INSTANTIATE(t) \
737 template std::type_info const& PropertySet::typeOfT<t>(); \
738 template t PropertySet::get<t>(std::string const& name) const; \
739 template t PropertySet::get<t>(std::string const& name, t const& defaultValue) const; \
740 template std::vector<t> PropertySet::getArray<t>(std::string const& name) const; \
741 template void PropertySet::set<t>(std::string const& name, t const& value); \
742 template void PropertySet::set<t>(std::string const& name, std::vector<t> const& value); \
743 template void PropertySet::add<t>(std::string const& name, t const& value); \
744 template void PropertySet::add<t>(std::string const& name, std::vector<t> const& value);
745
746#define INSTANTIATE_PROPERTY_SET(t) \
747 template std::type_info const& PropertySet::typeOfT<t>(); \
748 template t PropertySet::get<t>(std::string const& name) const; \
749 template t PropertySet::get<t>(std::string const& name, t const& defaultValue) const; \
750 template std::vector<t> PropertySet::getArray<t>(std::string const& name) const; \
751 template void PropertySet::set<t>(std::string const& name, t const& value); \
752 template void PropertySet::set<t>(std::string const& name, std::vector<t> const& value);
753
754INSTANTIATE(bool)
755INSTANTIATE(char)
756INSTANTIATE(signed char)
757INSTANTIATE(unsigned char)
758INSTANTIATE(short)
759INSTANTIATE(unsigned short)
760INSTANTIATE(int)
761INSTANTIATE(unsigned int)
762INSTANTIATE(long)
763INSTANTIATE(unsigned long)
764INSTANTIATE(long long)
765INSTANTIATE(unsigned long long)
766INSTANTIATE(float)
767INSTANTIATE(double)
768INSTANTIATE(std::nullptr_t)
769INSTANTIATE(std::string)
770INSTANTIATE_PROPERTY_SET(PropertySet::Ptr)
771INSTANTIATE(Persistable::Ptr)
772INSTANTIATE(DateTime)
773
774} // namespace base
775} // namespace daf
776} // namespace lsst
777
Interface for DateTime class.
#define LSST_EXCEPT(type,...)
T back(T... args)
T begin(T... args)
PropertySet(bool flat=false)
Construct an empty PropertySet.
T empty(T... args)
T end(T... args)
T endl(T... args)
T find(T... args)
T push_back(T... args)
T remove(T... args)
T reserve(T... args)
T showpoint(T... args)
T size(T... args)
T sort(T... args)
T str(T... args)
T throw_with_nested(T... args)