Coverage Report

Created: 2025-12-05 06:54

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/qpdf/libqpdf/QPDFOutlineObjectHelper.cc
Line
Count
Source
1
#include <qpdf/QPDFOutlineObjectHelper.hh>
2
3
#include <qpdf/QPDFObjectHandle_private.hh>
4
#include <qpdf/QPDFOutlineDocumentHelper.hh>
5
#include <qpdf/QTC.hh>
6
7
QPDFOutlineObjectHelper::Members::Members(QPDFOutlineDocumentHelper& dh) :
8
7.02k
    dh(dh)
9
7.02k
{
10
7.02k
}
11
12
QPDFOutlineObjectHelper::QPDFOutlineObjectHelper(
13
    QPDFObjectHandle a_oh, QPDFOutlineDocumentHelper& dh, int depth) :
14
7.02k
    QPDFObjectHelper(a_oh),
15
7.02k
    m(new Members(dh))
16
7.02k
{
17
7.02k
    if (depth > 50) {
18
        // Not exercised in test suite, but was tested manually by temporarily changing max depth
19
        // to 1.
20
0
        return;
21
0
    }
22
7.02k
    if (QPDFOutlineDocumentHelper::Accessor::checkSeen(m->dh, a_oh.getObjGen())) {
23
3.78k
        a_oh.warn("Loop detected loop in /Outlines tree");
24
3.78k
        return;
25
3.78k
    }
26
27
3.24k
    QPDFObjGen::set children;
28
3.24k
    QPDFObjectHandle cur = a_oh.getKey("/First");
29
8.46k
    while (!cur.null() && cur.isIndirect()) {
30
5.66k
        if (!children.add(cur)) {
31
447
            cur.warn("Loop detected loop in /Outlines tree");
32
447
            break;
33
447
        }
34
5.22k
        QPDFOutlineObjectHelper new_ooh(cur, dh, 1 + depth);
35
5.22k
        new_ooh.m->parent = std::make_shared<QPDFOutlineObjectHelper>(*this);
36
5.22k
        m->kids.emplace_back(new_ooh);
37
5.22k
        cur = cur.getKey("/Next");
38
5.22k
    }
39
3.24k
}
40
41
std::shared_ptr<QPDFOutlineObjectHelper>
42
QPDFOutlineObjectHelper::getParent()
43
0
{
44
0
    return m->parent;
45
0
}
46
47
std::vector<QPDFOutlineObjectHelper>
48
QPDFOutlineObjectHelper::getKids()
49
6.54k
{
50
6.54k
    return m->kids;
51
6.54k
}
52
53
QPDFObjectHandle
54
QPDFOutlineObjectHelper::getDest()
55
6.78k
{
56
6.78k
    auto dest = get("/Dest");
57
6.78k
    if (dest.null()) {
58
6.15k
        auto const& A = get("/A");
59
6.15k
        if (Name(A["/S"]) == "/GoTo") {
60
2.48k
            dest = A["/D"];
61
2.48k
        }
62
6.15k
    }
63
6.78k
    if (dest.null()) {
64
3.72k
        return QPDFObjectHandle::newNull();
65
3.72k
    }
66
3.05k
    if (dest.isName() || dest.isString()) {
67
2.70k
        return m->dh.resolveNamedDest(dest);
68
2.70k
    }
69
356
    return dest;
70
3.05k
}
71
72
QPDFObjectHandle
73
QPDFOutlineObjectHelper::getDestPage()
74
6.78k
{
75
6.78k
    QPDFObjectHandle dest = getDest();
76
6.78k
    if (!dest.empty() && dest.isArray()) {
77
268
        return dest.getArrayItem(0);
78
268
    }
79
6.51k
    return QPDFObjectHandle::newNull();
80
6.78k
}
81
82
int
83
QPDFOutlineObjectHelper::getCount()
84
0
{
85
0
    int count = 0;
86
0
    if (oh().hasKey("/Count")) {
87
0
        count = oh().getKey("/Count").getIntValueAsInt();
88
0
    }
89
0
    return count;
90
0
}
91
92
std::string
93
QPDFOutlineObjectHelper::getTitle()
94
0
{
95
0
    std::string result;
96
0
    if (oh().hasKey("/Title")) {
97
0
        result = oh().getKey("/Title").getUTF8Value();
98
0
    }
99
0
    return result;
100
0
}