Adobe Source Libraries 1.49.0
A collection of C++ libraries.
Loading...
Searching...
No Matches
table_index.hpp
Go to the documentation of this file.
1/*
2 Copyright 2013 Adobe
3 Distributed under the Boost Software License, Version 1.0.
4 (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
5*/
6/**************************************************************************************************/
7
8#ifndef ADOBE_TABLE_INDEX_HPP
9#define ADOBE_TABLE_INDEX_HPP
10
11/**************************************************************************************************/
12
13#include <adobe/config.hpp>
14
15#include <functional>
16#include <stdexcept>
17#include <vector>
18
19#include <boost/iterator/indirect_iterator.hpp>
20#include <boost/iterator/transform_iterator.hpp>
21#include <boost/next_prior.hpp>
22#include <boost/operators.hpp>
23
30
31#include <adobe/closed_hash.hpp>
32#include <adobe/functional.hpp>
33
34/**************************************************************************************************/
35
36namespace adobe {
37
38/**************************************************************************************************/
39
61
67
73
79
85
91
97
103
109
115
121
127
133
139
145
151
159
165
172
179
186
192
199
206
213
220
227
234
241
248
257
265
272
279
286
293
302
308
322
335
344
355
361
368
375
382
394
406
418
431
444
458
472
486
500
513
526
536
537
538template <typename T, // models Regular
539 typename H = std::hash<T>, // models UnaryFunction key_type -> size_t
540 typename C = std::equal_to<T>, // models EqualityComparison(key_type, key_type)
541 typename P = identity<T>> // models UnaryFunction T -> key_type
543public:
544 typedef T value_type;
546
547 using key_type = std::remove_reference_t<adobe::invoke_result_t<P, T>>;
548
549 typedef H hasher;
550 typedef C key_equal;
552 typedef const value_type* const_pointer;
555 typedef std::size_t size_type;
556 typedef std::ptrdiff_t difference_type;
557
559
561
562 typedef boost::indirect_iterator<typename index_type::iterator> iterator;
563 typedef boost::indirect_iterator<typename index_type::const_iterator> const_iterator;
564 typedef std::reverse_iterator<iterator> reverse_iterator;
565 typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
566
567 /*
568 REVISIT (sparent@adobe.com) : This is a very limited set of constructors - need to have a
569 general strategy for which constructors to provide.
570 */
571
572
574
575 /*
576 NOTE: The constructor is templatized so things like mem_fun are not necessary.
577 */
578
579 template <typename F> // F is convertible to key_function_type
581 : index_m(0, hf, eq, compose(key_function_type(kf), indirect<value_type>())) {}
582
583 // allocator_type get_allocator() const;
584 size_type max_size() const { return index_m.max_size(); }
585
586 size_type size() const { return index_m.size(); }
587 bool empty() const { return index_m.empty(); }
588 size_type capacity() const { return index_m.capacity(); }
589
590 void reserve(size_type) { index_m.reserve(); }
591
592 iterator begin() { return iterator(index_m.begin()); }
593 iterator end() { return iterator(index_m.end()); }
594
595 const_iterator begin() const { return const_iterator(index_m.begin()); }
596 const_iterator end() const { return const_iterator(index_m.end()); }
597
598 reverse_iterator rbegin() { return reverse_iterator(index_m.rbegin()); }
599 reverse_iterator rend() { return reverse_iterator(index_m.rend()); }
600
601 const_reverse_iterator rbegin() const { return const_reverse_iterator(index_m.rbegin()); }
602 const_reverse_iterator rend() const { return const_reverse_iterator(index_m.rend()); }
603
604 std::pair<iterator, bool> insert(value_type& x) {
605 std::pair<typename index_type::iterator, bool> result = index_m.insert(&x);
606 return std::make_pair(iterator(result.first), result.second);
607 }
608
609 template <typename I>
610 void insert(I f, I l) {
611 index_m.insert(boost::make_transform_iterator(f, pointer_to<value_type>()),
612 boost::make_transform_iterator(l, pointer_to<value_type>()));
613 }
614
615 iterator insert(iterator i, value_type& x) { return iterator(index_m.insert(i, &x)); }
616
617 iterator erase(iterator i) { return index_m.erase(i.base()); }
618 size_type erase(const key_type& x) { return index_m.erase(x); }
619
620 void clear() { index_m.clear(); }
621
622 index_type& index() { return index_m; }
623 const index_type& index() const { return index_m; }
624
625 iterator find(const key_type& x) { return iterator(index_m.find(x)); }
626 const_iterator find(const key_type& x) const { return const_iterator(index_m.find(x)); }
627 size_type count(const key_type& x) const { return index_m.count(x); }
628
629 iterator lower_bound(const key_type&) { return iterator(index_m.lower_bound()); }
631 return const_iterator(index_m.lower_bound());
632 }
633 iterator upper_bound(const key_type&) { return iterator(index_m.upper_bound()); }
635 return const_iterator(index_m.upper_bound());
636 }
637
638 std::pair<iterator, iterator> equal_range(const key_type& x) {
639 std::pair<typename index_type::iterator, typename index_type::iterator> result =
640 index_m.equal_range(x);
641 return std::make_pair(iterator(result.first), iterator(result.second));
642 }
643 std::pair<const_iterator, const_iterator> equal_range(const key_type& x) const {
644 std::pair<typename index_type::const_iterator, typename index_type::const_iterator> result =
645 index_m.equal_range(x);
646
647 return std::make_pair(const_iterator(result.first), const_iterator(result.second));
648 }
649
650 key_function_type key_function() const { return index_m.key_function(); }
651 hasher hash_function() const { return index_m.hash_function(); }
652 key_equal key_eq() const { return index_m.key_eq(); }
653
654 friend void swap(hash_index& x, hash_index& y) { swap(x.index_m, y.index_m); }
655
656private:
657 index_type index_m;
658};
659
660/**************************************************************************************************/
661
662template <typename Key, // models Regular
663 typename T, // models Regular
664 typename Transform = mem_data_t<T, const Key>, // models UnaryFunction Key(T)
665 typename Compare = std::less<Key> // models BinaryFunction bool(Key, Key)
666 >
668
669public:
670 typedef typename std::vector<T*> index_type;
671 typedef Transform transform_type;
672
673 typedef Key key_type;
674 typedef T value_type;
675 typedef Compare key_compare; // Revisit?
676 // typedef Allocator allocator_type;
677 typedef T& reference;
678 typedef const T& const_reference;
679 typedef typename index_type::size_type size_type;
680 typedef typename index_type::difference_type difference_type;
681 typedef T* pointer;
682 typedef const T* const_pointer;
683
684 typedef boost::indirect_iterator<typename index_type::iterator> iterator;
685 typedef boost::indirect_iterator<typename index_type::const_iterator> const_iterator;
686 typedef std::reverse_iterator<iterator> reverse_iterator;
687 typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
688
689 template <class TransformPrimitive>
690 explicit table_index(TransformPrimitive transform, const key_compare& compare = key_compare())
691 : transform_m(transform), compare_m(compare) {}
692 explicit table_index(const transform_type&, const key_compare& = key_compare());
693
702 template <typename InputIterator, typename TransformPrimitive>
703 table_index(InputIterator first, InputIterator last, TransformPrimitive transform,
704 const key_compare& compare = key_compare())
705 : transform_m(transform), compare_m(compare) {
706 insert(begin(), first, last);
707 }
708
709 // allocator_type get_allocator() const;
710 size_type max_size() const;
711
712 size_type size() const;
713 bool empty() const;
714
715 iterator begin();
716 const_iterator begin() const;
717 iterator end();
718 const_iterator end() const;
719
724
727
732
733 void push_back(value_type&);
734 void pop_back();
735
737 template <class InputIterator>
738 void insert(iterator position, InputIterator first, InputIterator last);
739
740 iterator erase(iterator location);
741 iterator erase(iterator first, iterator last);
742 void clear();
743
744 index_type& index();
745 const index_type& index() const;
746
747 /*
748 REVISIT (sparent) : If we wanted to allow sort() and unique() - and other algoriths to
749 operate directly on the index rather than being built in, what would be required of the
750 index interface?
751 */
752
753 void sort();
754
755 // Operations on a sorted index.
756
757 void unique();
758
760 const_reference operator[](const key_type&) const;
761
762 iterator find(const key_type& x);
763 const_iterator find(const key_type& x) const;
764 size_type count(const key_type& x) const;
765
766 iterator lower_bound(const key_type& x);
767 const_iterator lower_bound(const key_type& x) const;
768 iterator upper_bound(const key_type& x);
769 const_iterator upper_bound(const key_type& x) const;
770
771 std::pair<iterator, iterator> equal_range(const key_type& x);
772 std::pair<const_iterator, const_iterator> equal_range(const key_type& x) const;
773
774 transform_type transform() const { return transform_m; }
775
776 friend void swap(table_index& x, table_index& y) {
777 swap(x.transform_m, y.transform_m);
778 swap(x.compare_m, y.compare_m);
779 swap(x.index_m, y.index_m);
780 }
781
782private:
783#ifndef ADOBE_NO_DOCUMENTATION
784 struct indirect_compare_t {
785 typedef bool result_type;
786
787 indirect_compare_t(transform_type& transform, const key_compare& compare)
788 : transform_m(transform), compare_m(compare) {}
789
790 bool operator()(pointer x, pointer y) const {
791 return compare_m(transform_m(*x), transform_m(*y));
792 }
793
794 private:
795 transform_type transform_m; /* REVISIT (sparent) : want reference here? */
796 key_compare compare_m;
797 };
798
799#endif
800
801 transform_type transform_m;
802 key_compare compare_m;
803 index_type index_m;
804};
805
806/**************************************************************************************************/
807
808template <class Key, class T, class Compare, class Transform>
810 const key_compare& compare)
811 : transform_m(transform), compare_m(compare) {}
812
813/**************************************************************************************************/
814
815template <class Key, class T, class Compare, class Transform>
818 return iterator(index_m.begin());
819}
820
821/**************************************************************************************************/
822
823template <class Key, class T, class Compare, class Transform>
826 return const_iterator(index_m.begin());
827}
828
829/**************************************************************************************************/
830
831template <class Key, class T, class Compare, class Transform>
834 return iterator(index_m.end());
835}
836
837/**************************************************************************************************/
838
839template <class Key, class T, class Compare, class Transform>
842 return const_iterator(index_m.end());
843}
844
845/**************************************************************************************************/
846
847template <class Key, class T, class Compare, class Transform>
852
853/**************************************************************************************************/
854
855template <class Key, class T, class Compare, class Transform>
860
861/**************************************************************************************************/
862
863template <class Key, class T, class Compare, class Transform>
868
869/**************************************************************************************************/
870
871template <class Key, class T, class Compare, class Transform>
874 return reverse_iterator(index_m.rend());
875}
876
877/**************************************************************************************************/
878
879template <class Key, class T, class Compare, class Transform>
882 return index_m.max_size();
883}
884
885/**************************************************************************************************/
886
887template <class Key, class T, class Compare, class Transform>
890 return index_m.size();
891}
892
893/**************************************************************************************************/
894
895template <class Key, class T, class Compare, class Transform>
897 return index_m.empty();
898}
899
900/**************************************************************************************************/
901
902template <class Key, class T, class Compare, class Transform>
904 index_m.push_back(&x);
905}
906
907/**************************************************************************************************/
908
909template <class Key, class T, class Compare, class Transform>
911 index_m.pop_back();
912}
913
914/**************************************************************************************************/
915
916template <class Key, class T, class Compare, class Transform>
919 return index_m.insert(position, &x);
920}
921
922/**************************************************************************************************/
923
924/*
925 REVISIT (sparent) : We should be able to greatly improve the table_index class - this function
926 in particular could be much more efficient.
927*/
928
929template <class Key, class T, class Compare, class Transform>
930template <class InputIterator>
931inline void table_index<Key, T, Compare, Transform>::insert(iterator position, InputIterator first,
932 InputIterator last) {
933 typename index_type::iterator iter = position.base();
934
935 while (first != last) {
936 iter = index_m.insert(iter, &*first);
937 ++iter;
938 ++first;
939 }
940}
941
942/**************************************************************************************************/
943
944template <class Key, class T, class Compare, class Transform>
947 return index_m.erase(position.base());
948}
949
950/**************************************************************************************************/
951
952template <class Key, class T, class Compare, class Transform>
955 return index_m.erase(first.base(), last.base());
956}
957
958/**************************************************************************************************/
959
960template <class Key, class T, class Compare, class Transform>
962 index_m.clear();
963}
964
965/**************************************************************************************************/
966
967template <class Key, class T, class Compare, class Transform>
969 adobe::sort(index_m, indirect_compare_t(transform_m, compare_m));
970}
971
972/**************************************************************************************************/
973
974template <class Key, class T, class Compare, class Transform>
976 typename index_type::iterator i(
977 adobe::unique(index_m, indirect_compare_t(transform_m, compare_m)));
978 index_m.erase(i, index_m.end());
979}
980
981/**************************************************************************************************/
982
983template <class Key, class T, class Compare, class Transform>
986 return *index_m.at(n);
987}
988
989/**************************************************************************************************/
990
991template <class Key, class T, class Compare, class Transform>
994 return *index_m.at(n);
995}
996
997/**************************************************************************************************/
998
999template <class Key, class T, class Compare, class Transform>
1002 iterator iter(find(key));
1003
1004 if (iter == end())
1005 throw std::range_error("Key not present in table.");
1006
1007 return *iter;
1008}
1009
1010/**************************************************************************************************/
1011
1012template <class Key, class T, class Compare, class Transform>
1015 const_iterator iter(find(key));
1016
1017 if (iter == end())
1018 throw std::range_error("Key not present in table.");
1019
1020 return *iter;
1021}
1022
1023/**************************************************************************************************/
1024
1025template <class Key, class T, class Compare, class Transform>
1028 typename index_type::iterator iter = lower_bound(key).base();
1029
1030 if (iter != index_m.end() && transform_m(**iter) != key)
1031 iter = index_m.end();
1032
1033 return iter;
1034}
1035
1036/**************************************************************************************************/
1037
1038template <class Key, class T, class Compare, class Transform>
1041 typename index_type::const_iterator iter = lower_bound(key).base();
1042
1043 if (iter != index_m.end() && transform_m(**iter) != key)
1044 iter = index_m.end();
1045
1046 return iter;
1047}
1048
1049/**************************************************************************************************/
1050
1051template <class Key, class T, class Compare, class Transform>
1054 return adobe::count_if(index_m, bound_predicate_t(key, transform_m, compare_m));
1055}
1056
1057/**************************************************************************************************/
1058
1059template <class Key, class T, class Compare, class Transform>
1062 return adobe::lower_bound(
1063 index_m, key, compare_m,
1064 std::bind(transform_m, bind(indirect<value_type>(), std::placeholders::_1)));
1065}
1066
1067/**************************************************************************************************/
1068
1069template <class Key, class T, class Compare, class Transform>
1072 return adobe::lower_bound(
1073 index_m, key, compare_m,
1074 std::bind(transform_m, bind(indirect<value_type>(), std::placeholders::_1)));
1075}
1076
1077/**************************************************************************************************/
1078
1079template <class Key, class T, class Compare, class Transform>
1082 return adobe::upper_bound(
1083 index_m, key, compare_m,
1084 std::bind(transform_m, bind(indirect<value_type>(), std::placeholders::_1)));
1085}
1086
1087/**************************************************************************************************/
1088
1089template <class Key, class T, class Compare, class Transform>
1092 return adobe::upper_bound(
1093 index_m, key, compare_m,
1094 std::bind(transform_m, bind(indirect<value_type>(), std::placeholders::_1)));
1095}
1096
1097/**************************************************************************************************/
1098
1099template <class Key, class T, class Compare, class Transform>
1100inline std::pair<typename table_index<Key, T, Compare, Transform>::iterator,
1103 return adobe::equal_range(
1104 index_m, key, compare_m,
1105 std::bind(transform_m, bind(indirect<value_type>(), std::placeholders::_1)));
1106}
1107
1108/**************************************************************************************************/
1109
1110template <class Key, class T, class Compare, class Transform>
1111inline std::pair<typename table_index<Key, T, Compare, Transform>::const_iterator,
1114 return adobe::equal_range(
1115 index_m, key, compare_m,
1116 std::bind(transform_m, bind(indirect<value_type>(), std::placeholders::_1)));
1117}
1118
1119/**************************************************************************************************/
1120
1121template <class Key, class T, class Compare, class Transform>
1126
1127/**************************************************************************************************/
1128
1129template <class Key, class T, class Compare, class Transform>
1132 return index_m;
1133}
1134
1135/**************************************************************************************************/
1136
1137} // namespace adobe
1138
1139/**************************************************************************************************/
1140
1141#endif
1142
1143/**************************************************************************************************/
const_reverse_iterator rend() const
key_equal key_eq() const
std::pair< const_iterator, const_iterator > equal_range(const key_type &x) const
const value_type * const_pointer
iterator erase(iterator i)
iterator find(const key_type &x)
const_iterator begin() const
size_type erase(const key_type &x)
void reserve(size_type)
hash_index(hasher hf, key_equal eq, F kf)
iterator upper_bound(const key_type &)
std::reverse_iterator< const_iterator > const_reverse_iterator
index_type & index()
const index_type & index() const
size_type size() const
void insert(I f, I l)
bool empty() const
const_iterator find(const key_type &x) const
reverse_iterator rend()
hasher hash_function() const
boost::indirect_iterator< typename index_type::const_iterator > const_iterator
std::size_t size_type
std::reverse_iterator< iterator > reverse_iterator
size_type max_size() const
iterator insert(iterator i, value_type &x)
unary_compose< key_function_type, indirect< value_type > > indirect_key_function_type
key_function_type key_function() const
friend void swap(hash_index &x, hash_index &y)
value_type & reference
boost::indirect_iterator< typename index_type::iterator > iterator
const_iterator end() const
reverse_iterator rbegin()
size_type capacity() const
value_type * pointer
std::ptrdiff_t difference_type
const_iterator lower_bound(const key_type &) const
size_type count(const key_type &x) const
iterator lower_bound(const key_type &)
std::pair< iterator, iterator > equal_range(const key_type &x)
const_iterator upper_bound(const key_type &) const
std::pair< iterator, bool > insert(value_type &x)
closed_hash_set< pointer, indirect_key_function_type, hasher, key_equal > index_type
const_reverse_iterator rbegin() const
std::remove_reference_t< adobe::invoke_result_t< P, T > > key_type
const value_type & const_reference
index_type::size_type size_type
const_reference at(size_type n) const
const_reference front() const
friend void swap(table_index &x, table_index &y)
iterator erase(iterator location)
transform_type transform() const
iterator find(const key_type &x)
std::reverse_iterator< const_iterator > const_reverse_iterator
table_index(TransformPrimitive transform, const key_compare &compare=key_compare())
const_reference back() const
reference front()
reference operator[](const key_type &)
std::pair< iterator, iterator > equal_range(const key_type &x)
boost::indirect_iterator< typename index_type::const_iterator > const_iterator
std::vector< T * > index_type
iterator upper_bound(const key_type &x)
std::reverse_iterator< iterator > reverse_iterator
iterator insert(iterator, value_type &)
reverse_iterator rbegin()
index_type & index()
size_type count(const key_type &x) const
boost::indirect_iterator< typename index_type::iterator > iterator
size_type size() const
iterator lower_bound(const key_type &x)
index_type::difference_type difference_type
table_index(InputIterator first, InputIterator last, TransformPrimitive transform, const key_compare &compare=key_compare())
size_type max_size() const
reverse_iterator rend()
reference back()
const T & const_reference
void push_back(value_type &)
A hash based associative container.
std::iterator_traits< InputIterator >::difference_type count_if(InputIterator first, InputIterator last, Predicate pred)
count implementation
Definition count.hpp:61
std::pair< I, I > equal_range(I f, I l, const T &x)
boost::range_iterator< InputRange >::type find(InputRange &range, const T &value)
find implementation
Definition find.hpp:144
unary_compose< F, G > compose(F f, G g)
void sort(RandomAccessRange &range)
sort implementation
Definition sort.hpp:40
OutputIterator transform(InputIterator first, InputIterator last, OutputIterator result, UnaryOperation op)
transform implementation
Definition transform.hpp:38
auto unique(ForwardRange &range)
unique implementation
Definition unique.hpp:39
I upper_bound(I f, I l, const T &x)
I lower_bound(I f, I l, const T &x)