Commit 7777ea84e7117a305a74450ae37ed3ecb7739583
1 parent
4badc78a
Add new method ObjTable::emplace_back
Showing
3 changed files
with
52 additions
and
2 deletions
libqpdf/qpdf/ObjTable.hh
| @@ -28,6 +28,7 @@ template <class T> | @@ -28,6 +28,7 @@ template <class T> | ||
| 28 | class ObjTable: public std::vector<T> | 28 | class ObjTable: public std::vector<T> |
| 29 | { | 29 | { |
| 30 | public: | 30 | public: |
| 31 | + using reference = T&; | ||
| 31 | ObjTable() = default; | 32 | ObjTable() = default; |
| 32 | ObjTable(const ObjTable&) = delete; | 33 | ObjTable(const ObjTable&) = delete; |
| 33 | ObjTable(ObjTable&&) = delete; | 34 | ObjTable(ObjTable&&) = delete; |
| @@ -99,6 +100,18 @@ class ObjTable: public std::vector<T> | @@ -99,6 +100,18 @@ class ObjTable: public std::vector<T> | ||
| 99 | return element(id); | 100 | return element(id); |
| 100 | } | 101 | } |
| 101 | 102 | ||
| 103 | + // emplace_back to the end of the vector. If there are any conflicting sparse elements, emplace | ||
| 104 | + // them to the back of the vector before adding the current element. | ||
| 105 | + template <class... Args> | ||
| 106 | + inline T& | ||
| 107 | + emplace_back(Args&&... args) | ||
| 108 | + { | ||
| 109 | + if (min_sparse == std::vector<T>::size()) { | ||
| 110 | + return emplace_back_large(std::forward<Args&&...>(args...)); | ||
| 111 | + } | ||
| 112 | + return std::vector<T>::emplace_back(std::forward<Args&&...>(args...)); | ||
| 113 | + } | ||
| 114 | + | ||
| 102 | void | 115 | void |
| 103 | resize(size_t a_size) | 116 | resize(size_t a_size) |
| 104 | { | 117 | { |
| @@ -168,6 +181,22 @@ class ObjTable: public std::vector<T> | @@ -168,6 +181,22 @@ class ObjTable: public std::vector<T> | ||
| 168 | throw std::runtime_error("Impossibly large object id encountered accessing ObjTable"); | 181 | throw std::runtime_error("Impossibly large object id encountered accessing ObjTable"); |
| 169 | return element(0); // doesn't return | 182 | return element(0); // doesn't return |
| 170 | } | 183 | } |
| 184 | + | ||
| 185 | + // Must only be called by emplace_back. Separated out from emplace_back to keep inlined code | ||
| 186 | + // tight. | ||
| 187 | + template <class... Args> | ||
| 188 | + T& | ||
| 189 | + emplace_back_large(Args&&... args) | ||
| 190 | + { | ||
| 191 | + auto it = sparse_elements.begin(); | ||
| 192 | + auto end = sparse_elements.end(); | ||
| 193 | + while (it != end && it->first == std::vector<T>::size()) { | ||
| 194 | + std::vector<T>::emplace_back(std::move(it->second)); | ||
| 195 | + it = sparse_elements.erase(it); | ||
| 196 | + } | ||
| 197 | + min_sparse = (it == end) ? std::numeric_limits<size_t>::max() : it->first; | ||
| 198 | + return std::vector<T>::emplace_back(std::forward<Args&&...>(args...)); | ||
| 199 | + } | ||
| 171 | }; | 200 | }; |
| 172 | 201 | ||
| 173 | #endif // OBJTABLE_HH | 202 | #endif // OBJTABLE_HH |
libtests/obj_table.cc
| @@ -2,6 +2,11 @@ | @@ -2,6 +2,11 @@ | ||
| 2 | 2 | ||
| 3 | struct Test | 3 | struct Test |
| 4 | { | 4 | { |
| 5 | + Test() = default; | ||
| 6 | + Test(int value) : | ||
| 7 | + value(value) | ||
| 8 | + { | ||
| 9 | + } | ||
| 5 | int value{0}; | 10 | int value{0}; |
| 6 | }; | 11 | }; |
| 7 | 12 | ||
| @@ -24,11 +29,15 @@ class Table: public ObjTable<Test> | @@ -24,11 +29,15 @@ class Table: public ObjTable<Test> | ||
| 24 | (*this)[i].value = 2 * i; | 29 | (*this)[i].value = 2 * i; |
| 25 | } | 30 | } |
| 26 | resize(100); | 31 | resize(100); |
| 27 | - for (int i: {1, 99, 100, 105, 110, 120, 220}) { | 32 | + for (int i: {1, 99, 100, 105, 110, 120, 205, 206, 207, 210}) { |
| 28 | (*this)[i].value = 3 * i; | 33 | (*this)[i].value = 3 * i; |
| 29 | } | 34 | } |
| 30 | resize(200); | 35 | resize(200); |
| 31 | 36 | ||
| 37 | + for (int i = 1; i < 10; ++i) { | ||
| 38 | + emplace_back(i); | ||
| 39 | + } | ||
| 40 | + | ||
| 32 | forEach([](auto i, auto const& item) -> void { | 41 | forEach([](auto i, auto const& item) -> void { |
| 33 | if (item.value) { | 42 | if (item.value) { |
| 34 | std::cout << std::to_string(i) << " : " << std::to_string(item.value) << "\n"; | 43 | std::cout << std::to_string(i) << " : " << std::to_string(item.value) << "\n"; |
libtests/qtest/obj_table/obj_table.out
| @@ -22,7 +22,19 @@ | @@ -22,7 +22,19 @@ | ||
| 22 | 199 : 398 | 22 | 199 : 398 |
| 23 | 200 : 400 | 23 | 200 : 400 |
| 24 | 201 : 402 | 24 | 201 : 402 |
| 25 | -220 : 660 | 25 | +202 : 1 |
| 26 | +203 : 2 | ||
| 27 | +204 : 3 | ||
| 28 | +205 : 615 | ||
| 29 | +206 : 618 | ||
| 30 | +207 : 621 | ||
| 31 | +208 : 4 | ||
| 32 | +209 : 5 | ||
| 33 | +210 : 630 | ||
| 34 | +211 : 6 | ||
| 35 | +212 : 7 | ||
| 36 | +213 : 8 | ||
| 37 | +214 : 9 | ||
| 26 | 1000 : 2000 | 38 | 1000 : 2000 |
| 27 | 1001 : 2002 | 39 | 1001 : 2002 |
| 28 | 1002 : 2004 | 40 | 1002 : 2004 |