Line data Source code
1 : /**
2 : * @file
3 : *
4 : * @brief
5 : *
6 : * @copyright BSD License (see LICENSE.md or https://www.libelektra.org)
7 : */
8 :
9 : #ifndef ELEKTRA_KEYSET_HPP
10 : #define ELEKTRA_KEYSET_HPP
11 :
12 : #ifndef ELEKTRA_WRONG
13 : #define ELEKTRA_WRONG // make swig happy
14 : #endif
15 :
16 : #include <string>
17 :
18 : #include <key.hpp>
19 :
20 : #include <kdb.h>
21 :
22 : namespace kdb
23 : {
24 :
25 : #ifndef ELEKTRA_WITHOUT_ITERATOR
26 : class KeySetIterator;
27 : class KeySetReverseIterator;
28 : #endif
29 :
30 :
31 : /**
32 : * @brief Needed to avoid constructor ambiguity
33 : *
34 : * when ... is same type as va_list
35 : */
36 : struct VaAlloc
37 : {
38 : explicit VaAlloc (size_t size) : alloc (size)
39 : {
40 : }
41 : size_t alloc;
42 : };
43 :
44 : /**
45 : * @brief A keyset holds together a set of keys.
46 : *
47 : * @copydoc keyset
48 : *
49 : * \invariant always holds an underlying elektra keyset.
50 : *
51 : * \note that the cursor is mutable,
52 : * so it might be changed even in const functions
53 : * as described.
54 : * */
55 : class KeySet
56 : {
57 : public:
58 : inline KeySet ();
59 : inline KeySet (ckdb::KeySet * k);
60 : inline KeySet (const KeySet & other);
61 :
62 : ELEKTRA_WRONG explicit KeySet (Key, ...);
63 :
64 : inline explicit KeySet (size_t alloc, ...) ELEKTRA_SENTINEL;
65 : inline explicit KeySet (VaAlloc alloc, va_list ap);
66 :
67 : inline ~KeySet ();
68 :
69 : ckdb::KeySet * release ();
70 :
71 : ckdb::KeySet * getKeySet () const;
72 : void setKeySet (ckdb::KeySet * k);
73 :
74 : KeySet & operator= (KeySet const & other);
75 :
76 : ssize_t size () const;
77 :
78 : ckdb::KeySet * dup () const;
79 :
80 : void copy (const KeySet & other);
81 : void clear ();
82 :
83 : ssize_t append (const Key & toAppend);
84 : ssize_t append (const KeySet & toAppend);
85 :
86 : Key head () const;
87 : Key tail () const;
88 :
89 : void rewind () const;
90 : Key next () const;
91 : Key current () const;
92 :
93 : void setCursor (cursor_t cursor) const;
94 : cursor_t getCursor () const;
95 :
96 : Key pop ();
97 : Key at (cursor_t pos) const;
98 :
99 : KeySet cut (Key k);
100 :
101 : Key lookup (const Key & k, const option_t options = KDB_O_NONE) const;
102 : Key lookup (std::string const & name, const option_t options = KDB_O_NONE) const;
103 : template <typename T>
104 : T get (std::string const & name, const option_t options = KDB_O_NONE) const;
105 :
106 : #ifndef ELEKTRA_WITHOUT_ITERATOR
107 : typedef KeySetIterator iterator;
108 : typedef KeySetIterator const_iterator;
109 : typedef KeySetReverseIterator reverse_iterator;
110 : typedef KeySetReverseIterator const_reverse_iterator;
111 :
112 : iterator begin ();
113 : const_iterator begin () const;
114 : iterator end ();
115 : const_iterator end () const;
116 : reverse_iterator rbegin ();
117 : const_reverse_iterator rbegin () const;
118 : reverse_iterator rend ();
119 : const_reverse_iterator rend () const;
120 :
121 : const_iterator cbegin () const noexcept;
122 : const_iterator cend () const noexcept;
123 : const_reverse_iterator crbegin () const noexcept;
124 : const_reverse_iterator crend () const noexcept;
125 : #endif // ELEKTRA_WITHOUT_ITERATOR
126 :
127 : private:
128 : ckdb::KeySet * ks; ///< holds an elektra keyset
129 : };
130 :
131 :
132 : #ifndef ELEKTRA_WITHOUT_ITERATOR
133 : /**
134 : * For C++ forward Iteration over KeySets.
135 : * (External Iterator)
136 : * @code
137 : for (Key k:ks3)
138 : {
139 : std::cout << k.getName() << std::endl;
140 : }
141 : * @endcode
142 : */
143 : class KeySetIterator
144 : {
145 : public:
146 : typedef Key value_type;
147 : typedef cursor_t difference_type;
148 : typedef Key pointer;
149 : typedef Key reference;
150 : typedef std::random_access_iterator_tag iterator_category;
151 :
152 : KeySetIterator (KeySet const & k) : ks (k), current (){};
153 : KeySetIterator (KeySet const & k, const cursor_t c) : ks (k), current (c){};
154 : // conversion to const iterator?
155 :
156 21397 : Key get () const
157 : {
158 64191 : return Key (ckdb::ksAtCursor (ks.getKeySet (), current));
159 : }
160 : Key get (cursor_t pos) const
161 : {
162 72 : return Key (ckdb::ksAtCursor (ks.getKeySet (), pos));
163 : }
164 :
165 : KeySet const & getKeySet () const
166 : {
167 : return ks;
168 : }
169 :
170 : // Forward iterator requirements
171 : reference operator* () const
172 : {
173 19347 : return get ();
174 : }
175 : pointer operator-> () const
176 : {
177 2048 : return get ();
178 : }
179 : KeySetIterator & operator++ ()
180 : {
181 20453 : ++current;
182 : return *this;
183 : }
184 : KeySetIterator operator++ (int)
185 : {
186 12 : return KeySetIterator (ks, current++);
187 : }
188 :
189 : // Bidirectional iterator requirements
190 : KeySetIterator & operator-- ()
191 : {
192 6 : --current;
193 : return *this;
194 : }
195 : KeySetIterator operator-- (int)
196 : {
197 12 : return KeySetIterator (ks, current--);
198 : }
199 :
200 : // Random access iterator requirements
201 : reference operator[] (const difference_type & pos) const
202 : {
203 48 : return get (pos);
204 : }
205 : KeySetIterator & operator+= (const difference_type & pos)
206 : {
207 12 : current += pos;
208 : return *this;
209 : }
210 : KeySetIterator operator+ (const difference_type & pos) const
211 : {
212 46 : return KeySetIterator (ks, current + pos);
213 : }
214 : KeySetIterator & operator-= (const difference_type & pos)
215 : {
216 12 : current -= pos;
217 : return *this;
218 : }
219 : KeySetIterator operator- (const difference_type & pos) const
220 : {
221 : return KeySetIterator (ks, current - pos);
222 : }
223 : const cursor_t & base () const
224 : {
225 : return current;
226 : }
227 :
228 : private:
229 : KeySet const & ks;
230 : cursor_t current;
231 : };
232 :
233 :
234 : // Forward iterator requirements
235 : inline bool operator== (const KeySetIterator & lhs, const KeySetIterator & rhs)
236 : {
237 69 : return &lhs.getKeySet () == &rhs.getKeySet () && lhs.base () == rhs.base ();
238 : }
239 :
240 : inline bool operator!= (const KeySetIterator & lhs, const KeySetIterator & rhs)
241 : {
242 24995 : return &lhs.getKeySet () != &rhs.getKeySet () || lhs.base () != rhs.base ();
243 : }
244 :
245 : // Random access iterator requirements
246 : inline bool operator< (const KeySetIterator & lhs, const KeySetIterator & rhs)
247 : {
248 : return lhs.base () < rhs.base ();
249 : }
250 :
251 : inline bool operator> (const KeySetIterator & lhs, const KeySetIterator & rhs)
252 : {
253 : return lhs.base () > rhs.base ();
254 : }
255 :
256 : inline bool operator<= (const KeySetIterator & lhs, const KeySetIterator & rhs)
257 : {
258 : return lhs.base () <= rhs.base ();
259 : }
260 :
261 : inline bool operator>= (const KeySetIterator & lhs, const KeySetIterator & rhs)
262 : {
263 : return lhs.base () >= rhs.base ();
264 : }
265 :
266 : // DR 685.
267 : inline auto operator- (const KeySetIterator & lhs, const KeySetIterator & rhs) -> decltype (lhs.base () - rhs.base ())
268 : {
269 3 : return lhs.base () - rhs.base ();
270 : }
271 :
272 : inline KeySetIterator operator+ (KeySetIterator::difference_type n, const KeySetIterator & i)
273 : {
274 : return KeySetIterator (i.getKeySet (), i.base () + n);
275 : }
276 :
277 :
278 : // some code duplication because std::reverse_iterator
279 : // does not work on value_types
280 : /**
281 : * For C++ reverse Iteration over KeySets.
282 : * (External Iterator)
283 : */
284 : class KeySetReverseIterator
285 : {
286 : public:
287 : typedef Key value_type;
288 : typedef cursor_t difference_type;
289 : typedef Key pointer;
290 : typedef Key reference;
291 : typedef std::random_access_iterator_tag iterator_category;
292 :
293 : KeySetReverseIterator (KeySet const & k) : ks (k), current (){};
294 : KeySetReverseIterator (KeySet const & k, const cursor_t c) : ks (k), current (c){};
295 : // conversion to const iterator?
296 :
297 72 : Key get () const
298 : {
299 216 : return Key (ckdb::ksAtCursor (ks.getKeySet (), current));
300 : }
301 : Key get (cursor_t pos) const
302 : {
303 72 : return Key (ckdb::ksAtCursor (ks.getKeySet (), pos));
304 : }
305 :
306 : KeySet const & getKeySet () const
307 : {
308 : return ks;
309 : }
310 :
311 : // Forward iterator requirements
312 : reference operator* () const
313 : {
314 40 : return get ();
315 : }
316 : pointer operator-> () const
317 : {
318 32 : return get ();
319 : }
320 : KeySetReverseIterator & operator++ ()
321 : {
322 24 : --current;
323 : return *this;
324 : }
325 : KeySetReverseIterator operator++ (int)
326 : {
327 : return KeySetReverseIterator (ks, current--);
328 : }
329 :
330 : // Bidirectional iterator requirements
331 : KeySetReverseIterator & operator-- ()
332 : {
333 0 : ++current;
334 : return *this;
335 : }
336 : KeySetReverseIterator operator-- (int)
337 : {
338 : return KeySetReverseIterator (ks, current++);
339 : }
340 :
341 : // Random access iterator requirements
342 24 : reference operator[] (const difference_type & pos) const
343 : {
344 72 : return get (ks.size () - pos - 1);
345 : }
346 : KeySetReverseIterator & operator+= (const difference_type & pos)
347 : {
348 : current -= pos;
349 : return *this;
350 : }
351 : KeySetReverseIterator operator+ (const difference_type & pos) const
352 : {
353 40 : return KeySetReverseIterator (ks, current - pos);
354 : }
355 : KeySetReverseIterator & operator-= (const difference_type & pos)
356 : {
357 : current += pos;
358 : return *this;
359 : }
360 : KeySetReverseIterator operator- (const difference_type & pos) const
361 : {
362 : return KeySetReverseIterator (ks, current + pos);
363 : }
364 : const cursor_t & base () const
365 : {
366 : return current;
367 : }
368 :
369 : private:
370 : KeySet const & ks;
371 : cursor_t current;
372 : };
373 :
374 :
375 : // Forward iterator requirements
376 : inline bool operator== (const KeySetReverseIterator & lhs, const KeySetReverseIterator & rhs)
377 : {
378 26 : return &lhs.getKeySet () == &rhs.getKeySet () && lhs.base () == rhs.base ();
379 : }
380 :
381 : inline bool operator!= (const KeySetReverseIterator & lhs, const KeySetReverseIterator & rhs)
382 : {
383 0 : return &lhs.getKeySet () != &rhs.getKeySet () || lhs.base () != rhs.base ();
384 : }
385 :
386 : // Random access iterator requirements
387 : inline bool operator< (const KeySetReverseIterator & lhs, const KeySetReverseIterator & rhs)
388 : {
389 : return lhs.base () < rhs.base ();
390 : }
391 :
392 : inline bool operator> (const KeySetReverseIterator & lhs, const KeySetReverseIterator & rhs)
393 : {
394 : return lhs.base () > rhs.base ();
395 : }
396 :
397 : inline bool operator<= (const KeySetReverseIterator & lhs, const KeySetReverseIterator & rhs)
398 : {
399 : return lhs.base () <= rhs.base ();
400 : }
401 :
402 : inline bool operator>= (const KeySetReverseIterator & lhs, const KeySetReverseIterator & rhs)
403 : {
404 : return lhs.base () >= rhs.base ();
405 : }
406 :
407 : // DR 685.
408 : inline auto operator- (const KeySetReverseIterator & lhs, const KeySetReverseIterator & rhs) -> decltype (lhs.base () - rhs.base ())
409 : {
410 0 : return lhs.base () - rhs.base ();
411 : }
412 :
413 : inline KeySetReverseIterator operator+ (KeySetReverseIterator::difference_type n, const KeySetReverseIterator & i)
414 : {
415 : return KeySetReverseIterator (i.getKeySet (), i.base () + n);
416 : }
417 :
418 :
419 : inline KeySet::iterator KeySet::begin ()
420 : {
421 4448 : return KeySet::iterator (*this, 0);
422 : }
423 :
424 : inline KeySet::const_iterator KeySet::begin () const
425 : {
426 4027 : return KeySet::const_iterator (*this, 0);
427 : }
428 :
429 : inline KeySet::iterator KeySet::end ()
430 : {
431 7267 : return KeySet::iterator (*this, size ());
432 : }
433 :
434 : inline KeySet::const_iterator KeySet::end () const
435 : {
436 1049 : return KeySet::const_iterator (*this, size ());
437 : }
438 :
439 : inline KeySet::reverse_iterator KeySet::rbegin ()
440 : {
441 28 : return KeySet::reverse_iterator (*this, size () - 1);
442 : }
443 :
444 : inline KeySet::const_reverse_iterator KeySet::rbegin () const
445 : {
446 24 : return KeySet::const_reverse_iterator (*this, size () - 1);
447 : }
448 :
449 : inline KeySet::reverse_iterator KeySet::rend ()
450 : {
451 4 : return KeySet::reverse_iterator (*this, -1);
452 : }
453 :
454 : inline KeySet::const_reverse_iterator KeySet::rend () const
455 : {
456 2 : return KeySet::const_reverse_iterator (*this, -1);
457 : }
458 :
459 : inline KeySet::const_iterator KeySet::cbegin () const noexcept
460 : {
461 48 : return KeySet::const_iterator (*this, 0);
462 : }
463 :
464 : inline KeySet::const_iterator KeySet::cend () const noexcept
465 : {
466 4 : return KeySet::const_iterator (*this, size ());
467 : }
468 :
469 : inline KeySet::const_reverse_iterator KeySet::crbegin () const noexcept
470 : {
471 48 : return KeySet::const_reverse_iterator (*this, size () - 1);
472 : }
473 :
474 : inline KeySet::const_reverse_iterator KeySet::crend () const noexcept
475 : {
476 4 : return KeySet::const_reverse_iterator (*this, -1);
477 : }
478 : #endif // ELEKTRA_WITHOUT_ITERATOR
479 :
480 :
481 : /**
482 : * Creates a new empty keyset with no keys
483 : *
484 : * @copydoc ksNew
485 : */
486 79764 : inline KeySet::KeySet () : ks (ckdb::ksNew (0, KS_END))
487 : {
488 : }
489 :
490 : /**
491 : * Takes ownership of keyset!
492 : *
493 : * Keyset will be destroyed at destructor
494 : * you cant continue to use keyset afterwards!
495 : *
496 : * Use KeySet::release() to avoid destruction.
497 : *
498 : * @param k the keyset to take the ownership from
499 : * @see release()
500 : * @see setKeySet()
501 : */
502 14986 : inline KeySet::KeySet (ckdb::KeySet * k) : ks (k)
503 : {
504 : }
505 :
506 : /**
507 : * Duplicate a keyset.
508 : *
509 : * This keyset will be a duplicate of the other afterwards.
510 : *
511 : * @note that they still reference to the same Keys, so
512 : * if you change key values also the keys in the original keyset
513 : * will be changed.
514 : *
515 : * So it is shallow copy, to create a deep copy you have to dup() every
516 : * key (it still won't copy metadata, but they are COW):
517 : * @snippet cpp_example_dup.cpp ksDeepCopy
518 : *
519 : * @see dup
520 : */
521 112193 : inline KeySet::KeySet (const KeySet & other)
522 : {
523 112193 : ks = other.dup ();
524 : }
525 :
526 : /**
527 : * @brief Create a new keyset.
528 : *
529 : * @param alloc minimum number of keys to allocate
530 : * @param ap variable arguments list
531 : *
532 : * Use va as first argument to use this constructor, e.g.:
533 : * @code
534 : * KeySet ks(va, 23, ...);
535 : * @endcode
536 : *
537 : * @copydoc ksVNew
538 : */
539 : inline KeySet::KeySet (VaAlloc alloc, va_list av)
540 : {
541 4 : ks = ckdb::ksVNew (alloc.alloc, av);
542 : }
543 :
544 : /**
545 : * @brief Create a new keyset
546 : *
547 : * @param alloc minimum number of keys to allocate
548 : * @param ... variable argument list
549 : *
550 : * @copydoc ksVNew
551 : */
552 4438 : inline KeySet::KeySet (size_t alloc, ...)
553 : {
554 : va_list vl;
555 :
556 4438 : va_start (vl, alloc);
557 4438 : ks = ckdb::ksVNew (alloc, vl);
558 4438 : va_end (vl);
559 4438 : }
560 :
561 : /**
562 : * @brief Deconstruct a keyset
563 : *
564 : * @copydoc ksDel
565 : */
566 124252 : inline KeySet::~KeySet ()
567 : {
568 212664 : ckdb::ksDel (ks);
569 0 : }
570 :
571 : /**
572 : * If you don't want destruction of keyset at
573 : * the end you can release the pointer.
574 : * */
575 : inline ckdb::KeySet * KeySet::release ()
576 : {
577 5365 : ckdb::KeySet * ret = ks;
578 5365 : ks = ckdb::ksNew (0, KS_END);
579 : return ret;
580 : }
581 :
582 : /**
583 : * @brief Passes out the raw keyset pointer
584 : *
585 : * @return pointer to internal ckdb KeySet
586 : *
587 : * @see release()
588 : * @see setKeySet()
589 : */
590 : inline ckdb::KeySet * KeySet::getKeySet () const
591 : {
592 84889 : return ks;
593 : }
594 :
595 : /**
596 : * @brief Take ownership of passed keyset
597 : *
598 : * @param k the keyset to take ownership from
599 : * @see release()
600 : * @see getKeySet()
601 : */
602 : inline void KeySet::setKeySet (ckdb::KeySet * k)
603 : {
604 0 : ckdb::ksDel (ks);
605 0 : ks = k;
606 : }
607 :
608 : /**
609 : * Duplicate a keyset.
610 : *
611 : * This keyset will be a duplicate of the other afterwards.
612 : *
613 : * @note that they still reference to the same Keys, so
614 : * if you change key values also the keys in the original keyset
615 : * will be changed.
616 : */
617 7358 : inline KeySet & KeySet::operator= (KeySet const & other)
618 : {
619 7358 : if (this != &other)
620 : {
621 8356 : ckdb::ksDel (ks);
622 8356 : ks = other.dup ();
623 : }
624 7358 : return *this;
625 : }
626 :
627 : /**
628 : * @brief The size of the keyset
629 : *
630 : * @return the number of keys in the keyset
631 : */
632 : inline ssize_t KeySet::size () const
633 : {
634 216578 : return ckdb::ksGetSize (ks);
635 : }
636 :
637 : /**
638 : * @brief Duplicate a keyset
639 : *
640 : * @return a copy of the keys
641 : *
642 : * This is only a shallow copy. For a deep copy you need to dup every
643 : * key.
644 : *
645 : * @copydoc ksDup()
646 : */
647 : inline ckdb::KeySet * KeySet::dup () const
648 : {
649 139881 : return ckdb::ksDup (ks);
650 : }
651 :
652 : /**
653 : * @brief Copy a keyset
654 : *
655 : * @param other other keyset to copy
656 : *
657 : * This is only a shallow copy. For a deep copy you need to dup every
658 : * key.
659 : *
660 : * @copydoc ksCopy()
661 : */
662 : inline void KeySet::copy (const KeySet & other)
663 : {
664 2 : ckdb::ksCopy (ks, other.ks);
665 : }
666 :
667 : /**
668 : * @brief Clear the keyset
669 : *
670 : * Keyset will have no keys afterwards.
671 : */
672 : inline void KeySet::clear ()
673 : {
674 445 : ckdb::ksCopy (ks, nullptr);
675 : }
676 :
677 : /**
678 : * @brief append a key
679 : *
680 : * @param toAppend key to append
681 : *
682 : * @return number of keys in the keyset
683 : *
684 : * @copydoc ksAppendKey()
685 : */
686 : inline ssize_t KeySet::append (const Key & toAppend)
687 : {
688 238783 : return ckdb::ksAppendKey (ks, toAppend.getKey ());
689 : }
690 :
691 : /**
692 : * @brief append a keyset
693 : *
694 : * @param toAppend keyset to append
695 : *
696 : * @return number of keys in the keyset
697 : *
698 : * @copydoc ksAppend()
699 : */
700 : inline ssize_t KeySet::append (KeySet const & toAppend)
701 : {
702 9475 : return ckdb::ksAppend (ks, toAppend.getKeySet ());
703 : }
704 :
705 : /**
706 : * @return alphabetical first key
707 : *
708 : * @copydoc ksHead()
709 : */
710 : inline Key KeySet::head () const
711 : {
712 214 : return Key (ckdb::ksHead (ks));
713 : }
714 :
715 : /**
716 : * @return alphabetical last key
717 : *
718 : * @copydoc ksTail()
719 : */
720 : inline Key KeySet::tail () const
721 : {
722 42 : return Key (ckdb::ksTail (ks));
723 : }
724 :
725 :
726 : /**
727 : * @copydoc ksRewind()
728 : */
729 : inline void KeySet::rewind () const
730 : {
731 32812 : ckdb::ksRewind (ks);
732 : }
733 :
734 : /**
735 : * @copydoc ksNext()
736 : */
737 : inline Key KeySet::next () const
738 : {
739 434000 : ckdb::Key * k = ckdb::ksNext (ks);
740 433927 : return Key (k);
741 : }
742 :
743 : /**
744 : * @copydoc ksCurrent()
745 : */
746 : inline Key KeySet::current () const
747 : {
748 15152 : return Key (ckdb::ksCurrent (ks));
749 : }
750 :
751 : /**
752 : * @copydoc ksSetCursor()
753 : */
754 : inline void KeySet::setCursor (cursor_t cursor) const
755 : {
756 909 : ckdb::ksSetCursor (ks, cursor);
757 : }
758 :
759 : /**
760 : * @copydoc ksGetCursor()
761 : */
762 : inline cursor_t KeySet::getCursor () const
763 : {
764 932 : return ckdb::ksGetCursor (ks);
765 : }
766 :
767 : /**
768 : * @copydoc ksPop()
769 : */
770 : inline Key KeySet::pop ()
771 : {
772 500 : ckdb::Key * k = ckdb::ksPop (ks);
773 500 : Key key (k);
774 : return key;
775 : }
776 :
777 : /**
778 : * @brief Lookup a key by index
779 : *
780 : * @param pos cursor position
781 : *
782 : * @return the found key
783 : */
784 102 : inline Key KeySet::at (cursor_t pos) const
785 : {
786 111 : if (pos < 0) pos += size ();
787 1032 : return Key (ckdb::ksAtCursor (ks, pos));
788 : }
789 :
790 : /**
791 : * @copydoc ksCut()
792 : */
793 : inline KeySet KeySet::cut (Key k)
794 : {
795 9868 : return KeySet (ckdb::ksCut (ks, k.getKey ()));
796 : }
797 :
798 : /**
799 : * @copydoc ksLookup()
800 : *
801 : * @note That the internal key cursor will point to the found key
802 : */
803 : inline Key KeySet::lookup (const Key & key, const option_t options) const
804 : {
805 160241 : ckdb::Key * k = ckdb::ksLookup (ks, key.getKey (), options);
806 160270 : return Key (k);
807 : }
808 :
809 : /**
810 : * @brief Lookup a key by name
811 : *
812 : * @param name the name to look for
813 : * @param options some options to pass
814 : *
815 : * @return the found key
816 : * @see lookup (const Key &key, const option_t options)
817 : *
818 : * @note That the internal key cursor will point to the found key
819 : */
820 : inline Key KeySet::lookup (std::string const & name, option_t const options) const
821 : {
822 170829 : ckdb::Key * k = ckdb::ksLookupByName (ks, name.c_str (), options);
823 170855 : return Key (k);
824 : }
825 :
826 : template <typename T>
827 : struct KeySetTypeWrapper;
828 :
829 : template <typename T>
830 : struct KeySetTypeWrapper
831 : {
832 14 : T operator() (KeySet const & ks, std::string const & name, option_t const options) const
833 : {
834 28 : Key k = ks.lookup (name, options);
835 26 : if (!k) throw kdb::KeyNotFoundException ("key " + name + " was not found");
836 16 : return k.get<T> ();
837 : }
838 : };
839 :
840 : /**
841 : * @brief Generic lookup+get for keysets
842 : *
843 : * @param name the key name to get
844 : * @param options the options to be passed to lookup()
845 : *
846 : * @throw KeyNotFoundException if no key found
847 : *
848 : * @note To specialize more complex types (which are generic themselves) you
849 : * can also specialize KeySetTypeWrapper<T>.
850 : *
851 : * Use
852 : * @code
853 : #include <keysetget.hpp>
854 : * @endcode
855 : * to include specializations for std types.
856 : *
857 : * @return the requested type
858 : */
859 : template <typename T>
860 : inline T KeySet::get (std::string const & name, option_t const options) const
861 : {
862 : KeySetTypeWrapper<T> typeWrapper;
863 10766 : return typeWrapper (*this, name, options);
864 : }
865 :
866 579 : inline bool operator== (const KeySet & lhs, const KeySet & rhs)
867 : {
868 3398 : return lhs.size () == rhs.size () && std::equal (lhs.begin (), lhs.end (), rhs.begin ());
869 : }
870 :
871 :
872 : inline bool operator!= (const KeySet & lhs, const KeySet & rhs)
873 : {
874 64 : return !(lhs == rhs);
875 : }
876 :
877 :
878 : } // end of namespace kdb
879 :
880 : #endif
|