2 * @brief Append only vector of Xapian PIMPL objects
4 /* Copyright (C) 2012,2013,2014 Olly Betts
6 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 * of this software and associated documentation files (the "Software"), to
8 * deal in the Software without restriction, including without limitation the
9 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
10 * sell copies of the Software, and to permit persons to whom the Software is
11 * furnished to do so, subject to the following conditions:
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
25 #ifndef XAPIAN_INCLUDED_SMALLVECTOR_H
26 #define XAPIAN_INCLUDED_SMALLVECTOR_H
28 #include <cstddef> // For std::size_t
34 SmallVector_() : c(0) { }
40 void do_reserve(std::size_t n
);
43 /** Vector of Xapian PIMPL objects.
45 * A notable feature is that if the vector holds <= 2 objects, there's no
46 * extra storage - the two internal pointers are held in the two
47 * pointers which otherwise point to the first and just after the last
50 * This means that for the fairly common cases of pair-wise Query operators
51 * and Database objects with one or two subdatabases, we use less space than
52 * std::vector<Xapian::Foo> would.
55 class SmallVector
: private SmallVector_
{
57 typedef std::size_t size_type
;
58 class const_iterator
{
64 explicit const_iterator(void * const * ptr_
) : ptr(ptr_
) { }
66 const_iterator
& operator++() { ++ptr
; return *this; }
68 const_iterator
operator++(int) { return const_iterator(ptr
++); }
71 return T(static_cast<typename
T::Internal
*>(*ptr
));
74 T
operator[](size_type idx
) const {
75 return T(static_cast<typename
T::Internal
*>(ptr
[idx
]));
78 bool operator==(const const_iterator
& o
) const { return ptr
== o
.ptr
; }
80 bool operator!=(const const_iterator
& o
) const { return !(*this == o
); }
82 const_iterator
operator+(int n
) { return const_iterator(ptr
+ n
); }
85 // Create an empty SmallVector.
86 SmallVector() : SmallVector_() { }
88 // Create an empty SmallVector with n elements reserved.
89 explicit SmallVector(size_type n
) : SmallVector_() {
97 const_iterator
begin() const {
98 return const_iterator(c
> sizeof(p
) / sizeof(*p
) ?
99 static_cast<void * const *>(p
[0]) :
103 const_iterator
end() const {
104 return const_iterator(c
> sizeof(p
) / sizeof(*p
) ?
105 static_cast<void * const *>(p
[1]) :
109 size_type
size() const {
110 return c
> sizeof(p
) / sizeof(*p
) ?
111 static_cast<void**>(p
[1]) - static_cast<void**>(p
[0]) : c
;
114 size_type
capacity() const {
115 return c
> sizeof(p
) / sizeof(*p
) ? c
: sizeof(p
) / sizeof(*p
);
119 return c
> sizeof(p
) / sizeof(*p
) ? p
[0] == p
[1] : c
== 0;
123 for (const_iterator i
= begin(); i
!= end(); ++i
)
124 if ((*i
).internal
.get() && --(*i
).internal
->_refs
== 0)
125 delete (*i
).internal
.get();
127 if (c
> sizeof(p
) / sizeof(*p
))
128 delete [] static_cast<typename
T::Internal
**>(p
[0]);
133 void reserve(size_type n
) {
134 if (n
> sizeof(p
) / sizeof(*p
) && n
> c
) {
140 void push_back(const T
& elt
) {
141 size_type cap
= capacity();
147 if (elt
.internal
.get())
148 ++elt
.internal
->_refs
;
149 if (c
>= sizeof(p
) / sizeof(*p
)) {
150 void ** e
= static_cast<void **>(p
[1]);
151 *e
++ = static_cast<void*>(elt
.internal
.get());
152 p
[1] = static_cast<void*>(e
);
154 p
[c
++] = elt
.internal
.get();
158 T
operator[](size_type idx
) const {
165 #endif // XAPIAN_INCLUDED_SMALLVECTOR_H