mirror of
https://github.com/qpdf/qpdf.git
synced 2024-12-22 10:58:58 +00:00
commit
a238985087
@ -2077,8 +2077,8 @@ void
|
|||||||
QPDFWriter::initializeTables(size_t extra)
|
QPDFWriter::initializeTables(size_t extra)
|
||||||
{
|
{
|
||||||
auto size = QIntC::to_size(QPDF::Writer::tableSize(m->pdf) + 100) + extra;
|
auto size = QIntC::to_size(QPDF::Writer::tableSize(m->pdf) + 100) + extra;
|
||||||
m->obj.initialize(size);
|
m->obj.resize(size);
|
||||||
m->new_obj.initialize(size);
|
m->new_obj.resize(size);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -28,6 +28,7 @@ template <class T>
|
|||||||
class ObjTable: public std::vector<T>
|
class ObjTable: public std::vector<T>
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
using reference = T&;
|
||||||
ObjTable() = default;
|
ObjTable() = default;
|
||||||
ObjTable(const ObjTable&) = delete;
|
ObjTable(const ObjTable&) = delete;
|
||||||
ObjTable(ObjTable&&) = delete;
|
ObjTable(ObjTable&&) = delete;
|
||||||
@ -99,17 +100,30 @@ class ObjTable: public std::vector<T>
|
|||||||
return element(id);
|
return element(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
// emplace_back to the end of the vector. If there are any conflicting sparse elements, emplace
|
||||||
initialize(size_t idx)
|
// them to the back of the vector before adding the current element.
|
||||||
|
template <class... Args>
|
||||||
|
inline T&
|
||||||
|
emplace_back(Args&&... args)
|
||||||
{
|
{
|
||||||
if (std::vector<T>::size() > 0 || sparse_elements.size() > 0) {
|
if (min_sparse == std::vector<T>::size()) {
|
||||||
throw ::std::logic_error("ObjTable accessed before initialization");
|
return emplace_back_large(std::forward<Args&&...>(args...));
|
||||||
} else if (
|
}
|
||||||
idx >= static_cast<size_t>(std::numeric_limits<int>::max()) ||
|
return std::vector<T>::emplace_back(std::forward<Args&&...>(args...));
|
||||||
idx >= std::vector<T>::max_size()) {
|
}
|
||||||
throw std::runtime_error("Invalid maximum object id initializing ObjTable.");
|
|
||||||
} else {
|
void
|
||||||
std::vector<T>::resize(++idx);
|
resize(size_t a_size)
|
||||||
|
{
|
||||||
|
std::vector<T>::resize(a_size);
|
||||||
|
if (a_size > min_sparse) {
|
||||||
|
auto it = sparse_elements.begin();
|
||||||
|
auto end = sparse_elements.end();
|
||||||
|
while (it != end && it->first < a_size) {
|
||||||
|
std::vector<T>::operator[](it->first) = std::move(it->second);
|
||||||
|
it = sparse_elements.erase(it);
|
||||||
|
}
|
||||||
|
min_sparse = (it == end) ? std::numeric_limits<size_t>::max() : it->first;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -127,30 +141,62 @@ class ObjTable: public std::vector<T>
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
std::map<size_t, T> sparse_elements;
|
std::map<size_t, T> sparse_elements;
|
||||||
|
// Smallest id present in sparse_elements.
|
||||||
|
size_t min_sparse{std::numeric_limits<size_t>::max()};
|
||||||
|
|
||||||
inline T&
|
inline T&
|
||||||
element(size_t idx)
|
element(size_t idx)
|
||||||
{
|
{
|
||||||
if (idx < std::vector<T>::size()) {
|
if (idx < std::vector<T>::size()) {
|
||||||
return std::vector<T>::operator[](idx);
|
return std::vector<T>::operator[](idx);
|
||||||
} else if (idx < static_cast<size_t>(std::numeric_limits<int>::max())) {
|
}
|
||||||
|
return large_element(idx);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Must only be called by element. Separated out from element to keep inlined code tight.
|
||||||
|
T&
|
||||||
|
large_element(size_t idx)
|
||||||
|
{
|
||||||
|
static const size_t max_size = std::vector<T>::max_size();
|
||||||
|
if (idx < min_sparse) {
|
||||||
|
min_sparse = idx;
|
||||||
|
}
|
||||||
|
if (idx < max_size) {
|
||||||
return sparse_elements[idx];
|
return sparse_elements[idx];
|
||||||
}
|
}
|
||||||
throw std::runtime_error("Invalid object id accessing ObjTable.");
|
throw std::runtime_error("Impossibly large object id encountered accessing ObjTable");
|
||||||
return element(0); // doesn't return
|
return element(0); // doesn't return
|
||||||
}
|
}
|
||||||
|
|
||||||
inline T const&
|
inline T const&
|
||||||
element(size_t idx) const
|
element(size_t idx) const
|
||||||
{
|
{
|
||||||
|
static const size_t max_size = std::vector<T>::max_size();
|
||||||
if (idx < std::vector<T>::size()) {
|
if (idx < std::vector<T>::size()) {
|
||||||
return std::vector<T>::operator[](idx);
|
return std::vector<T>::operator[](idx);
|
||||||
} else if (idx < static_cast<size_t>(std::numeric_limits<int>::max())) {
|
}
|
||||||
|
if (idx < max_size) {
|
||||||
return sparse_elements.at(idx);
|
return sparse_elements.at(idx);
|
||||||
}
|
}
|
||||||
throw std::runtime_error("Invalid object id accessing ObjTable.");
|
throw std::runtime_error("Impossibly large object id encountered accessing ObjTable");
|
||||||
return element(0); // doesn't return
|
return element(0); // doesn't return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Must only be called by emplace_back. Separated out from emplace_back to keep inlined code
|
||||||
|
// tight.
|
||||||
|
template <class... Args>
|
||||||
|
T&
|
||||||
|
emplace_back_large(Args&&... args)
|
||||||
|
{
|
||||||
|
auto it = sparse_elements.begin();
|
||||||
|
auto end = sparse_elements.end();
|
||||||
|
while (it != end && it->first == std::vector<T>::size()) {
|
||||||
|
std::vector<T>::emplace_back(std::move(it->second));
|
||||||
|
it = sparse_elements.erase(it);
|
||||||
|
}
|
||||||
|
min_sparse = (it == end) ? std::numeric_limits<size_t>::max() : it->first;
|
||||||
|
return std::vector<T>::emplace_back(std::forward<Args&&...>(args...));
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // OBJTABLE_HH
|
#endif // OBJTABLE_HH
|
||||||
|
@ -2,6 +2,11 @@
|
|||||||
|
|
||||||
struct Test
|
struct Test
|
||||||
{
|
{
|
||||||
|
Test() = default;
|
||||||
|
Test(int value) :
|
||||||
|
value(value)
|
||||||
|
{
|
||||||
|
}
|
||||||
int value{0};
|
int value{0};
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -10,7 +15,7 @@ class Table: public ObjTable<Test>
|
|||||||
public:
|
public:
|
||||||
Table()
|
Table()
|
||||||
{
|
{
|
||||||
initialize(5);
|
resize(5);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -20,9 +25,23 @@ class Table: public ObjTable<Test>
|
|||||||
(*this)[i].value = 2 * i;
|
(*this)[i].value = 2 * i;
|
||||||
(*this)[1000 + i].value = 2 * (1000 + i);
|
(*this)[1000 + i].value = 2 * (1000 + i);
|
||||||
}
|
}
|
||||||
|
for (int i: {50, 60, 70, 98, 99, 100, 101, 150, 198, 199, 200, 201}) {
|
||||||
|
(*this)[i].value = 2 * i;
|
||||||
|
}
|
||||||
|
resize(100);
|
||||||
|
for (int i: {1, 99, 100, 105, 110, 120, 205, 206, 207, 210}) {
|
||||||
|
(*this)[i].value = 3 * i;
|
||||||
|
}
|
||||||
|
resize(200);
|
||||||
|
|
||||||
|
for (int i = 1; i < 10; ++i) {
|
||||||
|
emplace_back(i);
|
||||||
|
}
|
||||||
|
|
||||||
forEach([](auto i, auto const& item) -> void {
|
forEach([](auto i, auto const& item) -> void {
|
||||||
std::cout << std::to_string(i) << " : " << std::to_string(item.value) << "\n";
|
if (item.value) {
|
||||||
|
std::cout << std::to_string(i) << " : " << std::to_string(item.value) << "\n";
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
std::cout << "2000 : " << std::to_string((*this)[2000].value) << "\n";
|
std::cout << "2000 : " << std::to_string((*this)[2000].value) << "\n";
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
0 : 0
|
1 : 3
|
||||||
1 : 2
|
|
||||||
2 : 4
|
2 : 4
|
||||||
3 : 6
|
3 : 6
|
||||||
4 : 8
|
4 : 8
|
||||||
@ -8,6 +7,34 @@
|
|||||||
7 : 14
|
7 : 14
|
||||||
8 : 16
|
8 : 16
|
||||||
9 : 18
|
9 : 18
|
||||||
|
50 : 100
|
||||||
|
60 : 120
|
||||||
|
70 : 140
|
||||||
|
98 : 196
|
||||||
|
99 : 297
|
||||||
|
100 : 300
|
||||||
|
101 : 202
|
||||||
|
105 : 315
|
||||||
|
110 : 330
|
||||||
|
120 : 360
|
||||||
|
150 : 300
|
||||||
|
198 : 396
|
||||||
|
199 : 398
|
||||||
|
200 : 400
|
||||||
|
201 : 402
|
||||||
|
202 : 1
|
||||||
|
203 : 2
|
||||||
|
204 : 3
|
||||||
|
205 : 615
|
||||||
|
206 : 618
|
||||||
|
207 : 621
|
||||||
|
208 : 4
|
||||||
|
209 : 5
|
||||||
|
210 : 630
|
||||||
|
211 : 6
|
||||||
|
212 : 7
|
||||||
|
213 : 8
|
||||||
|
214 : 9
|
||||||
1000 : 2000
|
1000 : 2000
|
||||||
1001 : 2002
|
1001 : 2002
|
||||||
1002 : 2004
|
1002 : 2004
|
||||||
|
Loading…
Reference in New Issue
Block a user