LLVMFuzzerTestOneInput:
   45|  7.72k|{
   46|  7.72k|    FuzzHelper f(data, size);
   47|  7.72k|    f.run();
   48|  7.72k|    return 0;
   49|  7.72k|}
_ZN10FuzzHelperC2EPKhm:
   13|  7.72k|        data(data),
   14|  7.72k|        size(size)
   15|  7.72k|    {
   16|  7.72k|    }
_ZN10FuzzHelper3runEv:
   20|  7.72k|    {
   21|  7.72k|        qpdf::global::options::fuzz_mode(true);
   22|  7.72k|        try {
   23|  7.72k|            JSON::parse(std::string(reinterpret_cast<char const*>(data), size));
   24|  7.72k|        } catch (std::runtime_error& e) {
   25|  7.58k|            std::cerr << "runtime_error parsing json: " << e.what() << '\n';
   26|  7.58k|        }
   27|       |
   28|  7.72k|        QPDF q;
   29|  7.72k|        Buffer buf(const_cast<unsigned char*>(data), size);
   30|  7.72k|        auto is = std::make_shared<BufferInputSource>("json", &buf);
   31|  7.72k|        try {
   32|  7.72k|            q.createFromJSON(is);
   33|  7.72k|        } catch (std::runtime_error const& e) {
   34|  7.72k|            std::cerr << "runtime_error: " << e.what() << '\n';
   35|  7.72k|        }
   36|  7.72k|    }

_ZN11InputSourceC2Ev:
   35|  49.7k|    InputSource() = default;
_ZN11InputSourceD2Ev:
   37|  49.7k|    virtual ~InputSource() = default;
_ZN11InputSource6FinderC2Ev:
   43|  15.4k|        Finder() = default;

_ZN4JSON10JSON_valueC2ENS_12value_type_eE:
  306|  4.11M|            type_code(type_code)
  307|  4.11M|        {
  308|  4.11M|        }
_ZN4JSON15JSON_dictionaryC2Ev:
  316|   123k|            JSON_value(vt_dictionary)
  317|   123k|        {
  318|   123k|        }
_ZN4JSON9JSON_nullC2Ev:
  350|  9.57k|            JSON_value(vt_null)
  351|  9.57k|        {
  352|  9.57k|        }
_ZN4JSON10JSON_arrayC2Ev:
  396|  46.4k|        JSON_value(vt_array)
  397|  46.4k|    {
  398|  46.4k|    }
_ZN4JSON10JSON_valueD2Ev:
  309|  4.11M|        virtual ~JSON_value() = default;
_ZN4JSONC2Ev:
   50|  8.99M|    JSON() = default;
_ZN4JSON15JSON_dictionaryD2Ev:
  319|   123k|        ~JSON_dictionary() override = default;
_ZN4JSON10JSON_arrayD2Ev:
  399|  46.4k|    ~JSON_array() override = default;
_ZN4JSON11JSON_stringD2Ev:
  327|  1.59M|        ~JSON_string() override = default;
_ZN4JSON11JSON_numberD2Ev:
  336|  2.32M|        ~JSON_number() override = default;
_ZN4JSON7MembersD2Ev:
  378|  4.11M|        ~Members() = default;
_ZN4JSON7ReactorD2Ev:
  212|  7.72k|        virtual ~Reactor() = default;

_ZN4qpdf10BaseHandleC2ERKNSt3__110shared_ptrI10QPDFObjectEE:
  120|  2.00M|            obj(obj) {};
_ZN4qpdf10BaseHandleC2EONSt3__110shared_ptrI10QPDFObjectEE:
  122|  1.98M|            obj(std::move(obj)) {};
_ZN4qpdf10BaseHandleC2Ev:
  118|  2.16M|        BaseHandle() = default;
_ZN4qpdf10BaseHandleD2Ev:
  131|  11.1M|        ~BaseHandle() = default;
_ZN4qpdf10BaseHandleC2ERKS0_:
  123|  2.26M|        BaseHandle(BaseHandle const&) = default;
_ZN4qpdf10BaseHandleaSEOS0_:
  126|  2.04M|        BaseHandle& operator=(BaseHandle&&) = default;
_ZN4qpdf10BaseHandleC2EOS0_:
  125|  2.68M|        BaseHandle(BaseHandle&&) = default;
_ZN4qpdf10BaseHandleaSERKS0_:
  124|   134k|        BaseHandle& operator=(BaseHandle const&) = default;

_ZNK8Pipeline4nextEv:
  103|      1|    {
  104|      1|        return next_;
  105|      1|    }
_ZN8PipelineD2Ev:
   52|      4|    virtual ~Pipeline() = default;

_ZN5QIntC11range_checkIxEEvRKT_S3_:
  274|  7.72k|    {
  275|  7.72k|        if ((delta > 0) != (cur > 0)) {
  ------------------
  |  Branch (275:13): [True: 7.72k, False: 0]
  ------------------
  276|  7.72k|            return;
  277|  7.72k|        }
  278|      0|        QIntC::range_check_error<T>(cur, delta);
  279|      0|    }
_ZN5QIntC7to_sizeIxEEmRKT_:
  215|   198k|    {
  216|   198k|        return IntConverter<T, size_t>::convert(i);
  217|   198k|    }
_ZN5QIntC12IntConverterIxmLb1ELb0EE7convertERKx:
  119|   198k|        {
  120|       |            // From is signed, and To is unsigned. If i > 0, it's safe to
  121|       |            // convert it to the corresponding unsigned type and to
  122|       |            // compare with To's max.
  123|   198k|            auto ii = static_cast<typename to_u<From>::type>(i);
  124|   198k|            if ((i < 0) || (ii > std::numeric_limits<To>::max())) {
  ------------------
  |  Branch (124:17): [True: 0, False: 198k]
  |  Branch (124:28): [True: 0, False: 198k]
  ------------------
  125|      0|                error(i);
  126|      0|            }
  127|   198k|            return static_cast<To>(i);
  128|   198k|        }
_ZN5QIntC9to_offsetImEExRKT_:
  222|   172k|    {
  223|   172k|        return IntConverter<T, qpdf_offset_t>::convert(i);
  224|   172k|    }
_ZN5QIntC12IntConverterImxLb0ELb1EE7convertERKm:
  147|   172k|        {
  148|       |            // From is unsigned, and to is signed. Convert To's max to the
  149|       |            // unsigned version of To and compare i against that.
  150|   172k|            auto maxval = static_cast<typename to_u<To>::type>(std::numeric_limits<To>::max());
  151|   172k|            if (i > maxval) {
  ------------------
  |  Branch (151:17): [True: 0, False: 172k]
  ------------------
  152|      0|                error(i);
  153|      0|            }
  154|   172k|            return static_cast<To>(i);
  155|   172k|        }
_ZN5QIntC7to_sizeIlEEmRKT_:
  215|  15.4k|    {
  216|  15.4k|        return IntConverter<T, size_t>::convert(i);
  217|  15.4k|    }
_ZN5QIntC12IntConverterIlmLb1ELb0EE7convertERKl:
  119|  15.4k|        {
  120|       |            // From is signed, and To is unsigned. If i > 0, it's safe to
  121|       |            // convert it to the corresponding unsigned type and to
  122|       |            // compare with To's max.
  123|  15.4k|            auto ii = static_cast<typename to_u<From>::type>(i);
  124|  15.4k|            if ((i < 0) || (ii > std::numeric_limits<To>::max())) {
  ------------------
  |  Branch (124:17): [True: 0, False: 15.4k]
  |  Branch (124:28): [True: 0, False: 15.4k]
  ------------------
  125|      0|                error(i);
  126|      0|            }
  127|  15.4k|            return static_cast<To>(i);
  128|  15.4k|        }
_ZN5QIntC6to_intImEEiRKT_:
  201|  1.12M|    {
  202|  1.12M|        return IntConverter<T, int>::convert(i);
  203|  1.12M|    }
_ZN5QIntC12IntConverterImiLb0ELb1EE7convertERKm:
  147|  1.12M|        {
  148|       |            // From is unsigned, and to is signed. Convert To's max to the
  149|       |            // unsigned version of To and compare i against that.
  150|  1.12M|            auto maxval = static_cast<typename to_u<To>::type>(std::numeric_limits<To>::max());
  151|  1.12M|            if (i > maxval) {
  ------------------
  |  Branch (151:17): [True: 0, False: 1.12M]
  ------------------
  152|      0|                error(i);
  153|      0|            }
  154|  1.12M|            return static_cast<To>(i);
  155|  1.12M|        }
_ZN5QIntC12IntConverterIimLb1ELb0EE7convertERKi:
  119|  3.77k|        {
  120|       |            // From is signed, and To is unsigned. If i > 0, it's safe to
  121|       |            // convert it to the corresponding unsigned type and to
  122|       |            // compare with To's max.
  123|  3.77k|            auto ii = static_cast<typename to_u<From>::type>(i);
  124|  3.77k|            if ((i < 0) || (ii > std::numeric_limits<To>::max())) {
  ------------------
  |  Branch (124:17): [True: 0, False: 3.77k]
  |  Branch (124:28): [True: 0, False: 3.77k]
  ------------------
  125|      0|                error(i);
  126|      0|            }
  127|  3.77k|            return static_cast<To>(i);
  128|  3.77k|        }
_ZN5QIntC6to_intIxEEiRKT_:
  201|  1.53M|    {
  202|  1.53M|        return IntConverter<T, int>::convert(i);
  203|  1.53M|    }
_ZN5QIntC12IntConverterIxiLb1ELb1EE7convertERKx:
   94|  1.53M|        {
   95|       |            // From and To are both signed.
   96|  1.53M|            if ((i < std::numeric_limits<To>::min()) || (i > std::numeric_limits<To>::max())) {
  ------------------
  |  Branch (96:17): [True: 58, False: 1.53M]
  |  Branch (96:57): [True: 19, False: 1.53M]
  ------------------
   97|     77|                error(i);
   98|     77|            }
   99|  1.53M|            return static_cast<To>(i);
  100|  1.53M|        }
_ZN5QIntC12IntConverterIxiLb1ELb1EE5errorEx:
  104|     77|        {
  105|     77|            std::ostringstream msg;
  106|     77|            msg.imbue(std::locale::classic());
  107|     77|            msg << "integer out of range converting " << i << " from a " << sizeof(From)
  108|     77|                << "-byte signed type to a " << sizeof(To) << "-byte signed type";
  109|     77|            throw std::range_error(msg.str());
  110|     77|        }
_ZN5QIntC6to_intIlEEiRKT_:
  201|  7.72k|    {
  202|  7.72k|        return IntConverter<T, int>::convert(i);
  203|  7.72k|    }
_ZN5QIntC12IntConverterIliLb1ELb1EE7convertERKl:
   94|  7.72k|        {
   95|       |            // From and To are both signed.
   96|  7.72k|            if ((i < std::numeric_limits<To>::min()) || (i > std::numeric_limits<To>::max())) {
  ------------------
  |  Branch (96:17): [True: 0, False: 7.72k]
  |  Branch (96:57): [True: 0, False: 7.72k]
  ------------------
   97|      0|                error(i);
   98|      0|            }
   99|  7.72k|            return static_cast<To>(i);
  100|  7.72k|        }
_ZN5QIntC8to_ulongIcEEmRKT_:
  236|  10.3M|    {
  237|  10.3M|        return IntConverter<T, unsigned long>::convert(i);
  238|  10.3M|    }
_ZN5QIntC12IntConverterIcmLb1ELb0EE7convertERKc:
  119|  10.3M|        {
  120|       |            // From is signed, and To is unsigned. If i > 0, it's safe to
  121|       |            // convert it to the corresponding unsigned type and to
  122|       |            // compare with To's max.
  123|  10.3M|            auto ii = static_cast<typename to_u<From>::type>(i);
  124|  10.3M|            if ((i < 0) || (ii > std::numeric_limits<To>::max())) {
  ------------------
  |  Branch (124:17): [True: 0, False: 10.3M]
  |  Branch (124:28): [True: 0, False: 10.3M]
  ------------------
  125|      0|                error(i);
  126|      0|            }
  127|  10.3M|            return static_cast<To>(i);
  128|  10.3M|        }
_ZN5QIntC8to_ulongIhEEmRKT_:
  236|  13.9k|    {
  237|  13.9k|        return IntConverter<T, unsigned long>::convert(i);
  238|  13.9k|    }
_ZN5QIntC12IntConverterIhmLb0ELb0EE7convertERKh:
   69|  13.9k|        {
   70|       |            // From and To are both unsigned.
   71|  13.9k|            if (i > std::numeric_limits<To>::max()) {
  ------------------
  |  Branch (71:17): [True: 0, False: 13.9k]
  ------------------
   72|      0|                error(i);
   73|      0|            }
   74|  13.9k|            return static_cast<To>(i);
   75|  13.9k|        }
_ZN5QIntC8to_ulongIiEEmRKT_:
  236|  3.77k|    {
  237|  3.77k|        return IntConverter<T, unsigned long>::convert(i);
  238|  3.77k|    }

_ZN7QPDFExcD2Ev:
   50|   167k|    ~QPDFExc() noexcept override = default;

_ZN10QPDFObjGenC2Eii:
   40|   768k|        obj(obj),
   41|   768k|        gen(gen)
   42|   768k|    {
   43|   768k|    }
_ZNK10QPDFObjGenltERKS_:
   46|  3.54M|    {
   47|  3.54M|        return (obj < rhs.obj) || (obj == rhs.obj && gen < rhs.gen);
  ------------------
  |  Branch (47:16): [True: 1.45M, False: 2.09M]
  |  Branch (47:36): [True: 1.73M, False: 358k]
  |  Branch (47:54): [True: 143k, False: 1.58M]
  ------------------
   48|  3.54M|    }
_ZNK10QPDFObjGeneqERKS_:
   51|  7.47k|    {
   52|  7.47k|        return obj == rhs.obj && gen == rhs.gen;
  ------------------
  |  Branch (52:16): [True: 7.24k, False: 225]
  |  Branch (52:34): [True: 7.21k, False: 35]
  ------------------
   53|  7.47k|    }
_ZNK10QPDFObjGen6getObjEv:
   61|  50.8k|    {
   62|  50.8k|        return obj;
   63|  50.8k|    }
_ZNK10QPDFObjGen10isIndirectEv:
   71|  3.65M|    {
   72|  3.65M|        return obj != 0;
   73|  3.65M|    }
_ZNK10QPDFObjGen7unparseEc:
   76|  3.30k|    {
   77|  3.30k|        return std::to_string(obj) + separator + std::to_string(gen);
   78|  3.30k|    }
_ZN10QPDFObjGenC2Ev:
   38|  2.39M|    QPDFObjGen() = default;

_ZN16QPDFObjectHandleC2ERKNSt3__110shared_ptrI10QPDFObjectEE:
 1315|  37.3k|        qpdf::BaseHandle(obj)
 1316|  37.3k|    {
 1317|  37.3k|    }
_ZN16QPDFObjectHandleC2EONSt3__110shared_ptrI10QPDFObjectEE:
 1319|  1.97M|        qpdf::BaseHandle(std::move(obj))
 1320|  1.97M|    {
 1321|  1.97M|    }
_ZNK4qpdf10BaseHandlecvbEv:
 1559|  5.95M|    {
 1560|  5.95M|        return static_cast<bool>(obj);
 1561|  5.95M|    }
_ZNK4qpdf10BaseHandlecv16QPDFObjectHandleEv:
 1565|  3.30k|    {
 1566|  3.30k|        return {obj};
 1567|  3.30k|    }
_ZN16QPDFObjectHandleC2Ev:
  289|  2.16M|    QPDFObjectHandle() = default;
_ZN16QPDFObjectHandleC2ERKS_:
  290|  2.26M|    QPDFObjectHandle(QPDFObjectHandle const&) = default;
_ZN16QPDFObjectHandleaSEOS_:
  293|  2.04M|    QPDFObjectHandle& operator=(QPDFObjectHandle&&) = default;
_ZN16QPDFObjectHandleC2EOS_:
  292|  2.68M|    QPDFObjectHandle(QPDFObjectHandle&&) = default;
_ZN16QPDFObjectHandleaSERKS_:
  291|   134k|    QPDFObjectHandle& operator=(QPDFObjectHandle const&) = default;

_ZN13QPDFTokenizer5TokenC2Ev:
   71|  38.6k|            type(tt_bad)
   72|  38.6k|        {
   73|  38.6k|        }
_ZN13QPDFTokenizer5TokenC2ENS_12token_type_eERKNSt3__112basic_stringIcNS2_11char_traitsIcEENS2_9allocatorIcEEEES8_S8_:
   81|  38.6k|            type(type),
   82|  38.6k|            value(value),
   83|  38.6k|            raw_value(raw_value),
   84|  38.6k|            error_message(error_message)
   85|  38.6k|        {
   86|  38.6k|        }
_ZNK13QPDFTokenizer5Token7getTypeEv:
   89|  38.6k|        {
   90|  38.6k|            return this->type;
   91|  38.6k|        }
_ZNK13QPDFTokenizer5Token8getValueEv:
   94|  7.72k|        {
   95|  7.72k|            return this->value;
   96|  7.72k|        }
_ZNK13QPDFTokenizer5Token9isIntegerEv:
  116|  7.72k|        {
  117|  7.72k|            return this->type == tt_integer;
  118|  7.72k|        }
_ZNK13QPDFTokenizer5Token6isWordERKNSt3__112basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEE:
  126|  23.1k|        {
  127|  23.1k|            return this->type == tt_word && this->value == value;
  ------------------
  |  Branch (127:20): [True: 23.1k, False: 0]
  |  Branch (127:45): [True: 15.4k, False: 7.72k]
  ------------------
  128|  23.1k|        }

_ZN3QTC2TCEPKcS1_i:
   36|   674k|    {
   37|       |#ifndef QPDF_DISABLE_QTC
   38|       |        TC_real(scope, ccase, n);
   39|       |#endif // QPDF_DISABLE_QTC
   40|   674k|    }

_ZN4qpdf6global7options9fuzz_modeEb:
  132|  7.72k|        {
  133|  7.72k|            set_uint32(qpdf_p_fuzz_mode, value ? QPDF_TRUE : QPDF_FALSE);
  ------------------
  |  |  142|  7.72k|#define QPDF_TRUE 1
  ------------------
                          set_uint32(qpdf_p_fuzz_mode, value ? QPDF_TRUE : QPDF_FALSE);
  ------------------
  |  |  143|  7.72k|#define QPDF_FALSE 0
  ------------------
  |  Branch (133:42): [True: 7.72k, False: 0]
  ------------------
  134|  7.72k|        }
_ZN4qpdf6global10set_uint32E12qpdf_param_ej:
   53|  7.72k|    {
   54|  7.72k|        handle_result(qpdf_global_set_uint32(param, value));
   55|  7.72k|    }
_ZN4qpdf6global13handle_resultE13qpdf_result_e:
   35|  7.72k|    {
   36|  7.72k|        if (result != qpdf_r_ok) {
  ------------------
  |  Branch (36:13): [True: 0, False: 7.72k]
  ------------------
   37|      0|            QUtil::handle_result_code(result, "qpdf::global");
   38|      0|        }
   39|  7.72k|    }

_ZN6BufferC2EONSt3__112basic_stringIcNS0_11char_traitsIcEENS0_9allocatorIcEEEE:
   43|  2.57k|    m(std::make_unique<Members>(std::move(content)))
   44|  2.57k|{
   45|  2.57k|}
_ZN6BufferC2EPhm:
   48|  7.72k|    m(std::make_unique<Members>(size, reinterpret_cast<char*>(buf)))
   49|  7.72k|{
   50|  7.72k|}
_ZN6BufferD2Ev:
   69|  10.2k|Buffer::~Buffer() = default;
_ZNK6Buffer7getSizeEv:
   73|  18.0k|{
   74|  18.0k|    return m->size;
   75|  18.0k|}
_ZN6Buffer9getBufferEv:
   85|  7.72k|{
   86|  7.72k|    return reinterpret_cast<unsigned char*>(m->buf);
   87|  7.72k|}
_ZN6Buffer7MembersD2Ev:
   24|  10.2k|    ~Members() = default;
_ZN6Buffer7MembersC2EONSt3__112basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEE:
   18|  2.57k|        str(std::move(content)),
   19|  2.57k|        size(str.size()),
   20|  2.57k|        buf(str.data())
   21|  2.57k|    {
   22|  2.57k|    }
_ZN6Buffer7MembersC2EmPc:
   13|  7.72k|        size(size),
   14|  7.72k|        buf(buf)
   15|  7.72k|    {
   16|  7.72k|    }

_ZN17BufferInputSourceC2ERKNSt3__112basic_stringIcNS0_11char_traitsIcEENS0_9allocatorIcEEEEP6Bufferb:
  170|  7.72k|    m(std::make_unique<Members>(description, buf, own_memory))
  171|  7.72k|{
  172|  7.72k|}
_ZN17BufferInputSourceD2Ev:
  178|  7.72k|BufferInputSource::~BufferInputSource() = default;
_ZNK17BufferInputSource7getNameEv:
  189|  73.1k|{
  190|  73.1k|    return m->is.getName();
  191|  73.1k|}
_ZN17BufferInputSource4readEPcm:
  209|  22.6k|{
  210|  22.6k|    auto result = m->is.read(buffer, length);
  211|  22.6k|    last_offset = m->is.getLastOffset();
  212|  22.6k|    return result;
  213|  22.6k|}
_ZN4qpdf2is12OffsetBuffer4seekExi:
  258|   230k|{
  259|   230k|    switch (whence) {
  260|   222k|    case SEEK_SET:
  ------------------
  |  Branch (260:5): [True: 222k, False: 7.72k]
  ------------------
  261|   222k|        pos = offset - global_offset;
  262|   222k|        break;
  263|       |
  264|  7.72k|    case SEEK_END:
  ------------------
  |  Branch (264:5): [True: 7.72k, False: 222k]
  ------------------
  265|  7.72k|        QIntC::range_check(static_cast<qpdf_offset_t>(view_.size()), offset);
  266|  7.72k|        pos = static_cast<qpdf_offset_t>(view_.size()) + offset;
  267|  7.72k|        break;
  268|       |
  269|      0|    default:
  ------------------
  |  Branch (269:5): [True: 0, False: 230k]
  ------------------
  270|      0|        util::assertion(whence == SEEK_CUR, "invalid argument to BufferInputSource::seek");
  271|      0|        QIntC::range_check(pos, offset);
  272|      0|        pos += offset;
  273|   230k|    }
  274|       |
  275|   230k|    if (pos < 0) {
  ------------------
  |  Branch (275:9): [True: 0, False: 230k]
  ------------------
  276|      0|        throw std::runtime_error(description + ": seek before beginning of buffer");
  277|      0|    }
  278|   230k|}
_ZN4qpdf2is12OffsetBuffer4readEPcm:
  282|   191k|{
  283|   191k|    util::internal_error_if(pos < 0, "is::OffsetBuffer offset < 0");
  284|   191k|    auto end_pos = static_cast<qpdf_offset_t>(view_.size());
  285|   191k|    if (pos >= end_pos) {
  ------------------
  |  Branch (285:9): [True: 19.4k, False: 172k]
  ------------------
  286|  19.4k|        last_offset = end_pos + global_offset;
  287|  19.4k|        return 0;
  288|  19.4k|    }
  289|       |
  290|   172k|    last_offset = pos + global_offset;
  291|   172k|    size_t len = std::min(QIntC::to_size(end_pos - pos), length);
  292|   172k|    memcpy(buffer, view_.data() + pos, len);
  293|   172k|    pos += QIntC::to_offset(len);
  294|   172k|    return len;
  295|   191k|}
_ZN17BufferInputSource7MembersC2ERKNSt3__112basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEEP6Bufferb:
  148|  7.72k|        buf(own_memory ? buf : nullptr),
  ------------------
  |  Branch (148:13): [True: 0, False: 7.72k]
  ------------------
  149|  7.72k|        is(description,
  150|  7.72k|           buf && buf->getSize() > 0
  ------------------
  |  Branch (150:12): [True: 7.72k, False: 0]
  |  Branch (150:19): [True: 7.72k, False: 0]
  ------------------
  151|  7.72k|               ? std::string_view(reinterpret_cast<const char*>(buf->getBuffer()), buf->getSize())
  152|  7.72k|               : std::string_view())
  153|  7.72k|    {
  154|  7.72k|    }
_ZN17BufferInputSource7MembersD2Ev:
  162|  7.72k|    ~Members() = default;

_ZN11InputSource13setLastOffsetEx:
   15|  88.4k|{
   16|  88.4k|    this->last_offset = offset;
   17|  88.4k|}
_ZNK11InputSource13getLastOffsetEv:
   21|  46.3k|{
   22|  46.3k|    return this->last_offset;
   23|  46.3k|}
_ZN11InputSource9read_lineERNSt3__112basic_stringIcNS0_11char_traitsIcEENS0_9allocatorIcEEEEmx:
   27|  7.72k|{
   28|       |    // Return at most max_line_length characters from the next line. Lines are terminated by one or
   29|       |    // more \r or \n characters. Consume the trailing newline characters but don't return them.
   30|       |    // After this is called, the file will be positioned after a line terminator or at the end of
   31|       |    // the file, and last_offset will point to position the file had when this method was called.
   32|       |
   33|  7.72k|    read(str, count, at);
   34|  7.72k|    auto eol = str.find_first_of("\n\r"sv);
   35|  7.72k|    if (eol != std::string::npos) {
  ------------------
  |  Branch (35:9): [True: 7.72k, False: 0]
  ------------------
   36|  7.72k|        auto next_line = str.find_first_not_of("\n\r"sv, eol);
   37|  7.72k|        str.resize(eol);
   38|  7.72k|        if (eol != std::string::npos) {
  ------------------
  |  Branch (38:13): [True: 7.72k, False: 0]
  ------------------
   39|  7.72k|            seek(last_offset + static_cast<qpdf_offset_t>(next_line), SEEK_SET);
   40|  7.72k|            return eol;
   41|  7.72k|        }
   42|  7.72k|    }
   43|       |    // We did not necessarily find the end of the trailing newline sequence.
   44|      0|    seek(last_offset, SEEK_SET);
   45|      0|    findAndSkipNextEOL();
   46|      0|    return eol;
   47|  7.72k|}
_ZN11InputSource8readLineEm:
   51|  7.72k|{
   52|  7.72k|    return read_line(max_line_length);
   53|  7.72k|}
_ZN11InputSource9findFirstEPKcxmRNS_6FinderE:
   65|  23.1k|{
   66|       |    // Basic approach: search for the first character of start_chars starting from offset but not
   67|       |    // going past len (if len != 0). Once the first character is found, see if it is the beginning
   68|       |    // of a sequence of characters matching start_chars. If so, call finder.check() to do
   69|       |    // caller-specific additional checks. If not, keep searching.
   70|       |
   71|       |    // This code is tricky and highly subject to off-by-one or other edge case logic errors. See
   72|       |    // comments throughout that explain how we're not missing any edge cases. There are also tests
   73|       |    // specifically constructed to make sure we caught the edge cases in testing.
   74|       |
   75|  23.1k|    char buf[1025]; // size known to input_source.cc in libtests
   76|       |    // To enable us to guarantee null-termination, save an extra byte so that buf[size] is valid
   77|       |    // memory.
   78|  23.1k|    size_t size = sizeof(buf) - 1;
   79|  23.1k|    util::assertion(
   80|  23.1k|        !(strlen(start_chars) < 1 || strlen(start_chars) > size),
  ------------------
  |  Branch (80:11): [True: 0, False: 23.1k]
  |  Branch (80:38): [True: 0, False: 23.1k]
  ------------------
   81|  23.1k|        "InputSource::findSource called with too small or too large of a character sequence" //
   82|  23.1k|    );
   83|       |
   84|  23.1k|    char* p = nullptr;
   85|  23.1k|    qpdf_offset_t buf_offset = offset;
   86|  23.1k|    size_t bytes_read = 0;
   87|       |
   88|       |    // Guarantee that we return from this loop. Each time through, we either return, advance p, or
   89|       |    // restart the loop with a condition that will cause return on the next pass. Eventually we will
   90|       |    // either be out of range or hit EOF, either of which forces us to return.
   91|  23.1k|    while (true) {
  ------------------
  |  Branch (91:12): [True: 23.1k, Folded]
  ------------------
   92|       |        // Do we need to read more data? Pretend size = 5, buf starts at 0, and start_chars has 3
   93|       |        // characters. buf[5] is valid and null. If p == 2, start_chars could be buf[2] through
   94|       |        // buf[4], so p + strlen(start_chars) == buf + size is okay. If p points to buf[size], since
   95|       |        // strlen(start_chars) is always >= 1, this overflow test will be correct for that case
   96|       |        // regardless of start_chars.
   97|  23.1k|        if ((p == nullptr) || ((p + strlen(start_chars)) > (buf + bytes_read))) {
  ------------------
  |  Branch (97:13): [True: 23.1k, False: 0]
  |  Branch (97:31): [True: 0, False: 0]
  ------------------
   98|  23.1k|            if (p) {
  ------------------
  |  Branch (98:17): [True: 0, False: 23.1k]
  ------------------
   99|      0|                QTC::TC(
  100|      0|                    "libtests", "InputSource read next block", ((p == buf + bytes_read) ? 0 : 1));
  ------------------
  |  Branch (100:65): [True: 0, False: 0]
  ------------------
  101|      0|                buf_offset += (p - buf);
  102|      0|            }
  103|  23.1k|            this->seek(buf_offset, SEEK_SET);
  104|       |            // Read into buffer and zero out the rest of the buffer including buf[size]. We
  105|       |            // allocated an extra byte so that we could guarantee null termination as an extra
  106|       |            // protection against overrun when using string functions.
  107|  23.1k|            bytes_read = this->read(buf, size);
  108|  23.1k|            if (bytes_read < strlen(start_chars)) {
  ------------------
  |  Branch (108:17): [True: 7.72k, False: 15.4k]
  ------------------
  109|  7.72k|                QTC::TC("libtests", "InputSource find EOF", bytes_read == 0 ? 0 : 1);
  ------------------
  |  Branch (109:61): [True: 0, False: 7.72k]
  ------------------
  110|  7.72k|                return false;
  111|  7.72k|            }
  112|  15.4k|            memset(buf + bytes_read, '\0', 1 + (size - bytes_read));
  113|  15.4k|            p = buf;
  114|  15.4k|        }
  115|       |
  116|       |        // Search for the first character.
  117|  15.4k|        if ((p = static_cast<char*>(
  ------------------
  |  Branch (117:13): [True: 15.4k, False: 0]
  ------------------
  118|       |                 // line-break
  119|  15.4k|                 memchr(p, start_chars[0], bytes_read - QIntC::to_size(p - buf)))) != nullptr) {
  120|  15.4k|            if (p == buf) {
  ------------------
  |  Branch (120:17): [True: 7.72k, False: 7.72k]
  ------------------
  121|  7.72k|                QTC::TC("libtests", "InputSource found match at buf[0]");
  122|  7.72k|            }
  123|       |            // Found first letter.
  124|  15.4k|            if (len != 0) {
  ------------------
  |  Branch (124:17): [True: 7.72k, False: 7.72k]
  ------------------
  125|       |                // Make sure it's in range.
  126|  7.72k|                size_t p_relative_offset = QIntC::to_size((p - buf) + (buf_offset - offset));
  127|  7.72k|                if (p_relative_offset >= len) {
  ------------------
  |  Branch (127:21): [True: 0, False: 7.72k]
  ------------------
  128|       |                    // out of range
  129|      0|                    QTC::TC("libtests", "InputSource out of range");
  130|      0|                    return false;
  131|      0|                }
  132|  7.72k|            }
  133|  15.4k|            if ((p + strlen(start_chars)) > (buf + bytes_read)) {
  ------------------
  |  Branch (133:17): [True: 0, False: 15.4k]
  ------------------
  134|       |                // If there are not enough bytes left in the file for start_chars, we will detect
  135|       |                // this on the next pass as EOF and return.
  136|      0|                QTC::TC("libtests", "InputSource not enough bytes");
  137|      0|                continue;
  138|      0|            }
  139|       |
  140|       |            // See if p points to a sequence matching start_chars. We already checked above to make
  141|       |            // sure we are not going to overrun memory.
  142|  15.4k|            if (strncmp(p, start_chars, strlen(start_chars)) == 0) {
  ------------------
  |  Branch (142:17): [True: 15.4k, False: 0]
  ------------------
  143|       |                // Call finder.check() with the input source positioned to the point of the match.
  144|  15.4k|                this->seek(buf_offset + (p - buf), SEEK_SET);
  145|  15.4k|                if (finder.check()) {
  ------------------
  |  Branch (145:21): [True: 15.4k, False: 0]
  ------------------
  146|  15.4k|                    return true;
  147|  15.4k|                } else {
  148|      0|                    QTC::TC("libtests", "InputSource start_chars matched but not check");
  149|      0|                }
  150|  15.4k|            } else {
  151|      0|                QTC::TC("libtests", "InputSource first char matched but not string");
  152|      0|            }
  153|       |            // This occurrence of the first character wasn't a match. Skip over it and keep
  154|       |            // searching.
  155|      0|            ++p;
  156|      0|        } else {
  157|       |            // Trigger reading the next block
  158|      0|            p = buf + bytes_read;
  159|      0|        }
  160|  15.4k|    }
  161|  23.1k|}
_ZN11InputSource8findLastEPKcxmRNS_6FinderE:
  165|  7.72k|{
  166|  7.72k|    bool found = false;
  167|  7.72k|    qpdf_offset_t after_found_offset = 0;
  168|  7.72k|    qpdf_offset_t cur_offset = offset;
  169|  7.72k|    size_t cur_len = len;
  170|  15.4k|    while (this->findFirst(start_chars, cur_offset, cur_len, finder)) {
  ------------------
  |  Branch (170:12): [True: 7.72k, False: 7.72k]
  ------------------
  171|  7.72k|        if (found) {
  ------------------
  |  Branch (171:13): [True: 0, False: 7.72k]
  ------------------
  172|      0|            QTC::TC("libtests", "InputSource findLast found more than one");
  173|  7.72k|        } else {
  174|  7.72k|            found = true;
  175|  7.72k|        }
  176|  7.72k|        after_found_offset = this->tell();
  177|  7.72k|        cur_offset = after_found_offset;
  178|  7.72k|        cur_len = len - QIntC::to_size((cur_offset - offset));
  179|  7.72k|    }
  180|  7.72k|    if (found) {
  ------------------
  |  Branch (180:9): [True: 7.72k, False: 0]
  ------------------
  181|       |        this->seek(after_found_offset, SEEK_SET);
  182|  7.72k|    }
  183|  7.72k|    return found;
  184|  7.72k|}
_ZN11InputSource9read_lineEmx:
   57|  7.72k|{
   58|  7.72k|    std::string result(count, '\0');
   59|  7.72k|    read_line(result, count, at);
   60|  7.72k|    return result;
   61|  7.72k|}

_ZN4JSON7MembersC2ENSt3__110unique_ptrINS_10JSON_valueENS1_14default_deleteIS3_EEEE:
   19|  4.11M|    value(std::move(value))
   20|  4.11M|{
   21|  4.11M|}
_ZN4JSONC2ENSt3__110unique_ptrINS_10JSON_valueENS0_14default_deleteIS2_EEEE:
   24|  4.11M|    m(new Members(std::move(value)))
   25|  4.11M|{
   26|  4.11M|}
_ZN4JSON11JSON_stringC2ERKNSt3__112basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEE:
  126|  1.59M|    JSON_value(vt_string),
  127|  1.59M|    utf8(utf8)
  128|  1.59M|{
  129|  1.59M|}
_ZN4JSON11JSON_numberC2ERKNSt3__112basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEE:
  150|  2.32M|    JSON_value(vt_number),
  151|  2.32M|    encoded(value)
  152|  2.32M|{
  153|  2.32M|}
_ZN4JSON9JSON_boolC2Eb:
  162|  14.1k|    JSON_value(vt_bool),
  163|  14.1k|    value(val)
  164|  14.1k|{
  165|  14.1k|}
_ZN4JSON6Writer13encode_stringERKNSt3__112basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEE:
  220|   185k|{
  221|   185k|    static auto constexpr hexchars = "0123456789abcdef";
  222|       |
  223|   185k|    auto begin = str.cbegin();
  224|   185k|    auto end = str.cend();
  225|   185k|    auto iter = begin;
  226|  69.9M|    while (iter != end) {
  ------------------
  |  Branch (226:12): [True: 69.7M, False: 180k]
  ------------------
  227|  69.7M|        auto c = static_cast<unsigned char>(*iter);
  228|  69.7M|        if ((c > 34 && c != '\\') || c == ' ' || c == 33) {
  ------------------
  |  Branch (228:14): [True: 31.7M, False: 38.0M]
  |  Branch (228:24): [True: 31.7M, False: 775]
  |  Branch (228:38): [True: 37.9M, False: 36.3k]
  |  Branch (228:50): [True: 30.8k, False: 5.50k]
  ------------------
  229|       |            // Optimistically check that no char in str requires escaping. Hopefully we can just
  230|       |            // return the input str.
  231|  69.7M|            ++iter;
  232|  69.7M|        } else {
  233|       |            // We found a char that requires escaping. Initialize result to the chars scanned so
  234|       |            // far, append/replace the rest of str one char at a time, and return the result.
  235|  5.50k|            std::string result{begin, iter};
  236|       |
  237|  21.4M|            for (; iter != end; ++iter) {
  ------------------
  |  Branch (237:20): [True: 21.4M, False: 5.50k]
  ------------------
  238|  21.4M|                auto ch = static_cast<unsigned char>(*iter);
  239|  21.4M|                if ((ch > 34 && ch != '\\') || ch == ' ' || ch == 33) {
  ------------------
  |  Branch (239:22): [True: 16.2M, False: 5.12M]
  |  Branch (239:33): [True: 16.2M, False: 27.0k]
  |  Branch (239:48): [True: 5.08M, False: 67.4k]
  |  Branch (239:61): [True: 10.8k, False: 56.6k]
  ------------------
  240|       |                    // Check for most common case first.
  241|  21.3M|                    result += *iter;
  242|  21.3M|                } else {
  243|  56.6k|                    switch (ch) {
  244|  27.0k|                    case '\\':
  ------------------
  |  Branch (244:21): [True: 27.0k, False: 29.5k]
  ------------------
  245|  27.0k|                        result += "\\\\";
  246|  27.0k|                        break;
  247|  1.44k|                    case '\"':
  ------------------
  |  Branch (247:21): [True: 1.44k, False: 55.1k]
  ------------------
  248|  1.44k|                        result += "\\\"";
  249|  1.44k|                        break;
  250|  3.43k|                    case '\b':
  ------------------
  |  Branch (250:21): [True: 3.43k, False: 53.1k]
  ------------------
  251|  3.43k|                        result += "\\b";
  252|  3.43k|                        break;
  253|  3.12k|                    case '\f':
  ------------------
  |  Branch (253:21): [True: 3.12k, False: 53.4k]
  ------------------
  254|  3.12k|                        result += "\\f";
  255|  3.12k|                        break;
  256|  3.56k|                    case '\n':
  ------------------
  |  Branch (256:21): [True: 3.56k, False: 53.0k]
  ------------------
  257|  3.56k|                        result += "\\n";
  258|  3.56k|                        break;
  259|  3.89k|                    case '\r':
  ------------------
  |  Branch (259:21): [True: 3.89k, False: 52.7k]
  ------------------
  260|  3.89k|                        result += "\\r";
  261|  3.89k|                        break;
  262|  3.18k|                    case '\t':
  ------------------
  |  Branch (262:21): [True: 3.18k, False: 53.4k]
  ------------------
  263|  3.18k|                        result += "\\t";
  264|  3.18k|                        break;
  265|  10.8k|                    default:
  ------------------
  |  Branch (265:21): [True: 10.8k, False: 45.7k]
  ------------------
  266|  10.8k|                        result += ch < 16 ? "\\u000" : "\\u001";
  ------------------
  |  Branch (266:35): [True: 4.49k, False: 6.38k]
  ------------------
  267|  10.8k|                        result += hexchars[ch % 16];
  268|  56.6k|                    }
  269|  56.6k|                }
  270|  21.4M|            }
  271|  5.50k|            return result;
  272|  5.50k|        }
  273|  69.7M|    }
  274|   180k|    return str;
  275|   185k|}
_ZN4JSON14makeDictionaryEv:
  279|   123k|{
  280|   123k|    return {std::make_unique<JSON_dictionary>()};
  281|   123k|}
_ZN4JSON19addDictionaryMemberERKNSt3__112basic_stringIcNS0_11char_traitsIcEENS0_9allocatorIcEEEERKS_:
  285|   185k|{
  286|   185k|    if (auto* obj = m ? dynamic_cast<JSON_dictionary*>(m->value.get()) : nullptr) {
  ------------------
  |  Branch (286:15): [True: 185k, False: 0]
  ------------------
  287|   185k|        return obj->members[Writer::encode_string(key)] = val.m ? val : makeNull();
  ------------------
  |  Branch (287:59): [True: 185k, False: 0]
  ------------------
  288|   185k|    } else {
  289|      0|        throw std::runtime_error("JSON::addDictionaryMember called on non-dictionary");
  290|      0|    }
  291|   185k|}
_ZN4JSON9makeArrayEv:
  295|  46.4k|{
  296|  46.4k|    return {std::make_unique<JSON_array>()};
  297|  46.4k|}
_ZN4JSON15addArrayElementERKS_:
  301|  1.86M|{
  302|  1.86M|    if (auto* arr = m ? dynamic_cast<JSON_array*>(m->value.get()) : nullptr) {
  ------------------
  |  Branch (302:15): [True: 1.86M, False: 0]
  ------------------
  303|  1.86M|        if (val.m) {
  ------------------
  |  Branch (303:13): [True: 1.86M, False: 0]
  ------------------
  304|  1.86M|            arr->elements.push_back(val);
  305|  1.86M|        } else {
  306|      0|            arr->elements.push_back(makeNull());
  307|      0|        }
  308|  1.86M|        return arr->elements.back();
  309|  1.86M|    }
  310|      0|    throw std::runtime_error("JSON::addArrayElement called on non-array");
  311|      0|    return {}; // unreachable
  312|  1.86M|}
_ZN4JSON10makeStringERKNSt3__112basic_stringIcNS0_11char_traitsIcEENS0_9allocatorIcEEEE:
  316|  1.59M|{
  317|  1.59M|    return {std::make_unique<JSON_string>(utf8)};
  318|  1.59M|}
_ZN4JSON10makeNumberERKNSt3__112basic_stringIcNS0_11char_traitsIcEENS0_9allocatorIcEEEE:
  334|  2.32M|{
  335|  2.32M|    return {std::make_unique<JSON_number>(encoded)};
  336|  2.32M|}
_ZN4JSON8makeBoolEb:
  340|  14.1k|{
  341|  14.1k|    return {std::make_unique<JSON_bool>(value)};
  342|  14.1k|}
_ZN4JSON8makeNullEv:
  346|  9.57k|{
  347|  9.57k|    return {std::make_unique<JSON_null>()};
  348|  9.57k|}
_ZNK4JSON7isArrayEv:
  358|  5.98M|{
  359|  5.98M|    return m ? m->value->type_code == vt_array : false;
  ------------------
  |  Branch (359:12): [True: 5.98M, False: 0]
  ------------------
  360|  5.98M|}
_ZNK4JSON12isDictionaryEv:
  364|  6.29M|{
  365|  6.29M|    return m && m->value->type_code == vt_dictionary;
  ------------------
  |  Branch (365:12): [True: 6.29M, False: 0]
  |  Branch (365:17): [True: 311k, False: 5.98M]
  ------------------
  366|  6.29M|}
_ZNK4JSON9getStringERNSt3__112basic_stringIcNS0_11char_traitsIcEENS0_9allocatorIcEEEE:
  370|   797k|{
  371|   797k|    if (m && m->value->type_code == vt_string) {
  ------------------
  |  Branch (371:9): [True: 797k, False: 0]
  |  Branch (371:14): [True: 794k, False: 3.19k]
  ------------------
  372|   794k|        auto v = dynamic_cast<JSON_string const*>(m->value.get());
  373|   794k|        utf8 = v->utf8;
  374|   794k|        return true;
  375|   794k|    }
  376|  3.19k|    return false;
  377|   797k|}
_ZNK4JSON9getNumberERNSt3__112basic_stringIcNS0_11char_traitsIcEENS0_9allocatorIcEEEE:
  381|  1.91M|{
  382|  1.91M|    if (m && m->value->type_code == vt_number) {
  ------------------
  |  Branch (382:9): [True: 1.91M, False: 0]
  |  Branch (382:14): [True: 1.13M, False: 786k]
  ------------------
  383|  1.13M|        auto v = dynamic_cast<JSON_number const*>(m->value.get());
  384|  1.13M|        value = v->encoded;
  385|  1.13M|        return true;
  386|  1.13M|    }
  387|   786k|    return false;
  388|  1.91M|}
_ZNK4JSON7getBoolERb:
  392|  1.92M|{
  393|  1.92M|    if (m && m->value->type_code == vt_bool) {
  ------------------
  |  Branch (393:9): [True: 1.92M, False: 0]
  |  Branch (393:14): [True: 6.07k, False: 1.91M]
  ------------------
  394|  6.07k|        auto v = dynamic_cast<JSON_bool const*>(m->value.get());
  395|  6.07k|        value = v->value;
  396|  6.07k|        return true;
  397|  6.07k|    }
  398|  1.91M|    return false;
  399|  1.92M|}
_ZNK4JSON6isNullEv:
  403|  1.92M|{
  404|  1.92M|    return m && m->value->type_code == vt_null;
  ------------------
  |  Branch (404:12): [True: 1.92M, False: 0]
  |  Branch (404:17): [True: 4.39k, False: 1.92M]
  ------------------
  405|  1.92M|}
_ZN4JSON5parseER11InputSourcePNS_7ReactorE:
 1335|  7.72k|{
 1336|  7.72k|    JSONParser jp(is, reactor);
 1337|  7.72k|    return jp.parse();
 1338|  7.72k|}
_ZN4JSON5parseERKNSt3__112basic_stringIcNS0_11char_traitsIcEENS0_9allocatorIcEEEE:
 1342|  7.72k|{
 1343|  7.72k|    is::OffsetBuffer bis("json input", s);
 1344|  7.72k|    JSONParser jp(bis, nullptr);
 1345|  7.72k|    return jp.parse();
 1346|  7.72k|}
_ZN4JSON8setStartEx:
 1350|  4.11M|{
 1351|  4.11M|    if (m) {
  ------------------
  |  Branch (1351:9): [True: 4.11M, False: 0]
  ------------------
 1352|  4.11M|        m->start = start;
 1353|  4.11M|    }
 1354|  4.11M|}
_ZN4JSON6setEndEx:
 1358|  4.17M|{
 1359|  4.17M|    if (m) {
  ------------------
  |  Branch (1359:9): [True: 4.17M, False: 0]
  ------------------
 1360|  4.17M|        m->end = end;
 1361|  4.17M|    }
 1362|  4.17M|}
_ZNK4JSON8getStartEv:
 1366|  1.28M|{
 1367|  1.28M|    return m ? m->start : 0;
  ------------------
  |  Branch (1367:12): [True: 1.28M, False: 0]
  ------------------
 1368|  1.28M|}
_ZNK4JSON6getEndEv:
 1372|  5.50k|{
 1373|  5.50k|    return m ? m->end : 0;
  ------------------
  |  Branch (1373:12): [True: 5.50k, False: 0]
  ------------------
 1374|  5.50k|}
JSON.cc:_ZN12_GLOBAL__N_110JSONParserC2ER11InputSourcePN4JSON7ReactorE:
  577|  15.4k|            is(is),
  578|  15.4k|            reactor(reactor),
  579|  15.4k|            p(buf)
  580|  15.4k|        {
  581|  15.4k|        }
JSON.cc:_ZN12_GLOBAL__N_110JSONParser5parseEv:
 1317|  15.4k|{
 1318|  8.90M|    while (!done) {
  ------------------
  |  Branch (1318:12): [True: 8.88M, False: 15.4k]
  ------------------
 1319|  8.88M|        getToken();
 1320|  8.88M|        handleToken();
 1321|  8.88M|    }
 1322|  15.4k|    if (parser_state != ps_done) {
  ------------------
  |  Branch (1322:9): [True: 10.2k, False: 5.22k]
  ------------------
 1323|  10.2k|        QTC::TC("libtests", "JSON parse premature EOF");
 1324|  10.2k|        throw std::runtime_error("JSON: premature end of input");
 1325|  10.2k|    }
 1326|  5.22k|    auto const& tos = stack.back().item;
 1327|  5.22k|    if (reactor && !(tos.isArray() || tos.isDictionary())) {
  ------------------
  |  Branch (1327:9): [True: 119, False: 5.10k]
  |  Branch (1327:22): [True: 0, False: 119]
  |  Branch (1327:39): [True: 51, False: 68]
  ------------------
 1328|     68|        reactor->topLevelScalar();
 1329|     68|    }
 1330|  5.22k|    return tos;
 1331|  15.4k|}
JSON.cc:_ZN12_GLOBAL__N_110JSONParser8getTokenEv:
  807|  8.88M|{
  808|  8.88M|    token.clear();
  809|       |
  810|       |    // Keep track of UTF-16 surrogate pairs.
  811|  8.88M|    unsigned long high_surrogate = 0;
  812|  8.88M|    qpdf_offset_t high_offset = 0;
  813|       |
  814|   319M|    while (true) {
  ------------------
  |  Branch (814:12): [True: 319M, Folded]
  ------------------
  815|   319M|        if (p == (buf + bytes)) {
  ------------------
  |  Branch (815:13): [True: 46.1k, False: 319M]
  ------------------
  816|  46.1k|            p = buf;
  817|  46.1k|            bytes = is.read(buf, sizeof(buf));
  818|  46.1k|            if (bytes == 0) {
  ------------------
  |  Branch (818:17): [True: 12.2k, False: 33.9k]
  ------------------
  819|  12.2k|                done = true;
  820|  12.2k|                break;
  821|  12.2k|            }
  822|  46.1k|        }
  823|       |
  824|   319M|        if ((*p < 32 && *p >= 0)) {
  ------------------
  |  Branch (824:14): [True: 60.5M, False: 258M]
  |  Branch (824:25): [True: 284k, False: 60.2M]
  ------------------
  825|   284k|            if (*p == '\t' || *p == '\n' || *p == '\r') {
  ------------------
  |  Branch (825:17): [True: 718, False: 284k]
  |  Branch (825:31): [True: 283k, False: 402]
  |  Branch (825:45): [True: 245, False: 157]
  ------------------
  826|       |                // Legal white space not permitted in strings. This will always end the current
  827|       |                // token (unless we are still before the start of the token).
  828|   284k|                if (lex_state == ls_top) {
  ------------------
  |  Branch (828:21): [True: 272k, False: 12.1k]
  ------------------
  829|   272k|                    ignore();
  830|   272k|                } else {
  831|  12.1k|                    break;
  832|  12.1k|                }
  833|       |
  834|   284k|            } else {
  835|    157|                QTC::TC("libtests", "JSON parse null character");
  836|    157|                throw std::runtime_error(
  837|    157|                    "JSON: control or null character at offset " + std::to_string(offset));
  838|    157|            }
  839|   318M|        } else if (*p == ',') {
  ------------------
  |  Branch (839:20): [True: 7.73M, False: 311M]
  ------------------
  840|  7.73M|            if (lex_state == ls_top) {
  ------------------
  |  Branch (840:17): [True: 3.95M, False: 3.77M]
  ------------------
  841|  3.95M|                ignore(ls_comma);
  842|  3.95M|                return;
  843|  3.95M|            } else if (lex_state == ls_string) {
  ------------------
  |  Branch (843:24): [True: 1.44M, False: 2.32M]
  ------------------
  844|  1.44M|                append();
  845|  2.32M|            } else {
  846|  2.32M|                break;
  847|  2.32M|            }
  848|   311M|        } else if (*p == ':') {
  ------------------
  |  Branch (848:20): [True: 540k, False: 310M]
  ------------------
  849|   540k|            if (lex_state == ls_top) {
  ------------------
  |  Branch (849:17): [True: 372k, False: 168k]
  ------------------
  850|   372k|                ignore(ls_colon);
  851|   372k|                return;
  852|   372k|            } else if (lex_state == ls_string) {
  ------------------
  |  Branch (852:24): [True: 168k, False: 98]
  ------------------
  853|   168k|                append();
  854|   168k|            } else {
  855|     98|                break;
  856|     98|            }
  857|   310M|        } else if (*p == ' ') {
  ------------------
  |  Branch (857:20): [True: 124M, False: 186M]
  ------------------
  858|   124M|            if (lex_state == ls_top) {
  ------------------
  |  Branch (858:17): [True: 5.64M, False: 118M]
  ------------------
  859|  5.64M|                ignore();
  860|   118M|            } else if (lex_state == ls_string) {
  ------------------
  |  Branch (860:24): [True: 118M, False: 342]
  ------------------
  861|   118M|                append();
  862|   118M|            } else {
  863|    342|                break;
  864|    342|            }
  865|   186M|        } else if (*p == '{') {
  ------------------
  |  Branch (865:20): [True: 197k, False: 186M]
  ------------------
  866|   197k|            if (lex_state == ls_top) {
  ------------------
  |  Branch (866:17): [True: 123k, False: 74.5k]
  ------------------
  867|   123k|                token_start = offset;
  868|   123k|                ignore(ls_begin_dict);
  869|   123k|                return;
  870|   123k|            } else if (lex_state == ls_string) {
  ------------------
  |  Branch (870:24): [True: 74.4k, False: 81]
  ------------------
  871|  74.4k|                append();
  872|  74.4k|            } else {
  873|     81|                break;
  874|     81|            }
  875|   186M|        } else if (*p == '}') {
  ------------------
  |  Branch (875:20): [True: 68.1k, False: 186M]
  ------------------
  876|  68.1k|            if (lex_state == ls_top) {
  ------------------
  |  Branch (876:17): [True: 57.0k, False: 11.0k]
  ------------------
  877|  57.0k|                ignore(ls_end_dict);
  878|  57.0k|                return;
  879|  57.0k|            } else if (lex_state == ls_string) {
  ------------------
  |  Branch (879:24): [True: 5.45k, False: 5.59k]
  ------------------
  880|  5.45k|                append();
  881|  5.59k|            } else {
  882|  5.59k|                break;
  883|  5.59k|            }
  884|   186M|        } else if (*p == '[') {
  ------------------
  |  Branch (884:20): [True: 71.0k, False: 185M]
  ------------------
  885|  71.0k|            if (lex_state == ls_top) {
  ------------------
  |  Branch (885:17): [True: 46.4k, False: 24.6k]
  ------------------
  886|  46.4k|                token_start = offset;
  887|  46.4k|                ignore(ls_begin_array);
  888|  46.4k|                return;
  889|  46.4k|            } else if (lex_state == ls_string) {
  ------------------
  |  Branch (889:24): [True: 24.5k, False: 27]
  ------------------
  890|  24.5k|                append();
  891|  24.5k|            } else {
  892|     27|                break;
  893|     27|            }
  894|   185M|        } else if (*p == ']') {
  ------------------
  |  Branch (894:20): [True: 77.9k, False: 185M]
  ------------------
  895|  77.9k|            if (lex_state == ls_top) {
  ------------------
  |  Branch (895:17): [True: 6.06k, False: 71.8k]
  ------------------
  896|  6.06k|                ignore(ls_end_array);
  897|  6.06k|                return;
  898|  71.8k|            } else if (lex_state == ls_string) {
  ------------------
  |  Branch (898:24): [True: 71.1k, False: 701]
  ------------------
  899|  71.1k|                append();
  900|  71.1k|            } else {
  901|    701|                break;
  902|    701|            }
  903|   185M|        } else {
  904|   185M|            switch (lex_state) {
  905|  4.31M|            case ls_top:
  ------------------
  |  Branch (905:13): [True: 4.31M, False: 181M]
  ------------------
  906|  4.31M|                token_start = offset;
  907|  4.31M|                if (*p == '"') {
  ------------------
  |  Branch (907:21): [True: 1.97M, False: 2.34M]
  ------------------
  908|  1.97M|                    ignore(ls_string);
  909|  2.34M|                } else if ((*p >= 'a') && (*p <= 'z')) {
  ------------------
  |  Branch (909:28): [True: 24.4k, False: 2.32M]
  |  Branch (909:43): [True: 24.4k, False: 9]
  ------------------
  910|  24.4k|                    append(ls_alpha);
  911|  2.32M|                } else if (*p == '-') {
  ------------------
  |  Branch (911:28): [True: 2.52k, False: 2.32M]
  ------------------
  912|  2.52k|                    append(ls_number_minus);
  913|  2.32M|                } else if ((*p >= '1') && (*p <= '9')) {
  ------------------
  |  Branch (913:28): [True: 1.87M, False: 449k]
  |  Branch (913:43): [True: 1.87M, False: 149]
  ------------------
  914|  1.87M|                    append(ls_number_before_point);
  915|  1.87M|                } else if (*p == '0') {
  ------------------
  |  Branch (915:28): [True: 449k, False: 471]
  ------------------
  916|   449k|                    append(ls_number_leading_zero);
  917|   449k|                } else {
  918|    471|                    QTC::TC("libtests", "JSON parse bad character");
  919|    471|                    throw std::runtime_error(
  920|    471|                        "JSON: offset " + std::to_string(offset) + ": unexpected character " +
  921|    471|                        std::string(p, 1));
  922|    471|                }
  923|  4.31M|                break;
  924|       |
  925|  4.31M|            case ls_number_minus:
  ------------------
  |  Branch (925:13): [True: 2.48k, False: 185M]
  ------------------
  926|  2.48k|                if ((*p >= '1') && (*p <= '9')) {
  ------------------
  |  Branch (926:21): [True: 1.95k, False: 532]
  |  Branch (926:36): [True: 1.93k, False: 19]
  ------------------
  927|  1.93k|                    append(ls_number_before_point);
  928|  1.93k|                } else if (*p == '0') {
  ------------------
  |  Branch (928:28): [True: 519, False: 32]
  ------------------
  929|    519|                    append(ls_number_leading_zero);
  930|    519|                } else {
  931|     32|                    QTC::TC("libtests", "JSON parse number minus no digits");
  932|     32|                    throw std::runtime_error(
  933|     32|                        "JSON: offset " + std::to_string(offset) +
  934|     32|                        ": numeric literal: no digit after minus sign");
  935|     32|                }
  936|  2.45k|                break;
  937|       |
  938|  3.58k|            case ls_number_leading_zero:
  ------------------
  |  Branch (938:13): [True: 3.58k, False: 185M]
  ------------------
  939|  3.58k|                if (*p == '.') {
  ------------------
  |  Branch (939:21): [True: 489, False: 3.09k]
  ------------------
  940|    489|                    append(ls_number_point);
  941|  3.09k|                } else if (*p == 'e' || *p == 'E') {
  ------------------
  |  Branch (941:28): [True: 976, False: 2.12k]
  |  Branch (941:41): [True: 2.05k, False: 69]
  ------------------
  942|  3.02k|                    append(ls_number_e);
  943|  3.02k|                } else {
  944|     69|                    QTC::TC("libtests", "JSON parse leading zero");
  945|     69|                    throw std::runtime_error(
  946|     69|                        "JSON: offset " + std::to_string(offset) + ": number with leading zero");
  947|     69|                }
  948|  3.51k|                break;
  949|       |
  950|   342k|            case ls_number_before_point:
  ------------------
  |  Branch (950:13): [True: 342k, False: 185M]
  ------------------
  951|   342k|                if ((*p >= '0') && (*p <= '9')) {
  ------------------
  |  Branch (951:21): [True: 340k, False: 1.73k]
  |  Branch (951:36): [True: 327k, False: 13.1k]
  ------------------
  952|   327k|                    append();
  953|   327k|                } else if (*p == '.') {
  ------------------
  |  Branch (953:28): [True: 1.66k, False: 13.2k]
  ------------------
  954|  1.66k|                    append(ls_number_point);
  955|  13.2k|                } else if (*p == 'e' || *p == 'E') {
  ------------------
  |  Branch (955:28): [True: 1.64k, False: 11.5k]
  |  Branch (955:41): [True: 11.4k, False: 106]
  ------------------
  956|  13.0k|                    append(ls_number_e);
  957|  13.0k|                } else {
  958|    106|                    tokenError();
  959|    106|                }
  960|   342k|                break;
  961|       |
  962|  2.12k|            case ls_number_point:
  ------------------
  |  Branch (962:13): [True: 2.12k, False: 185M]
  ------------------
  963|  2.12k|                if ((*p >= '0') && (*p <= '9')) {
  ------------------
  |  Branch (963:21): [True: 2.10k, False: 21]
  |  Branch (963:36): [True: 2.09k, False: 11]
  ------------------
  964|  2.09k|                    append(ls_number_after_point);
  965|  2.09k|                } else {
  966|     32|                    tokenError();
  967|     32|                }
  968|  2.12k|                break;
  969|       |
  970|  2.72M|            case ls_number_after_point:
  ------------------
  |  Branch (970:13): [True: 2.72M, False: 183M]
  ------------------
  971|  2.72M|                if ((*p >= '0') && (*p <= '9')) {
  ------------------
  |  Branch (971:21): [True: 2.72M, False: 27]
  |  Branch (971:36): [True: 2.72M, False: 700]
  ------------------
  972|  2.72M|                    append();
  973|  2.72M|                } else if (*p == 'e' || *p == 'E') {
  ------------------
  |  Branch (973:28): [True: 416, False: 311]
  |  Branch (973:41): [True: 274, False: 37]
  ------------------
  974|    690|                    append(ls_number_e);
  975|    690|                } else {
  976|     37|                    tokenError();
  977|     37|                }
  978|  2.72M|                break;
  979|       |
  980|  16.7k|            case ls_number_e:
  ------------------
  |  Branch (980:13): [True: 16.7k, False: 185M]
  ------------------
  981|  16.7k|                if ((*p >= '0') && (*p <= '9')) {
  ------------------
  |  Branch (981:21): [True: 14.4k, False: 2.23k]
  |  Branch (981:36): [True: 14.4k, False: 16]
  ------------------
  982|  14.4k|                    append(ls_number);
  983|  14.4k|                } else if ((*p == '+') || (*p == '-')) {
  ------------------
  |  Branch (983:28): [True: 1.15k, False: 1.10k]
  |  Branch (983:43): [True: 1.06k, False: 37]
  ------------------
  984|  2.21k|                    append(ls_number_e_sign);
  985|  2.21k|                } else {
  986|     37|                    tokenError();
  987|     37|                }
  988|  16.7k|                break;
  989|       |
  990|  2.19k|            case ls_number_e_sign:
  ------------------
  |  Branch (990:13): [True: 2.19k, False: 185M]
  ------------------
  991|  2.19k|                if ((*p >= '0') && (*p <= '9')) {
  ------------------
  |  Branch (991:21): [True: 2.18k, False: 15]
  |  Branch (991:36): [True: 2.16k, False: 14]
  ------------------
  992|  2.16k|                    append(ls_number);
  993|  2.16k|                } else {
  994|     29|                    tokenError();
  995|     29|                }
  996|  2.19k|                break;
  997|       |
  998|  4.22M|            case ls_number:
  ------------------
  |  Branch (998:13): [True: 4.22M, False: 181M]
  ------------------
  999|       |                // We only get here after we have seen an exponent.
 1000|  4.22M|                if ((*p >= '0') && (*p <= '9')) {
  ------------------
  |  Branch (1000:21): [True: 4.22M, False: 19]
  |  Branch (1000:36): [True: 4.22M, False: 19]
  ------------------
 1001|  4.22M|                    append();
 1002|  4.22M|                } else {
 1003|     38|                    tokenError();
 1004|     38|                }
 1005|  4.22M|                break;
 1006|       |
 1007|  1.72M|            case ls_alpha:
  ------------------
  |  Branch (1007:13): [True: 1.72M, False: 184M]
  ------------------
 1008|  1.72M|                if ((*p >= 'a') && (*p <= 'z')) {
  ------------------
  |  Branch (1008:21): [True: 1.71M, False: 234]
  |  Branch (1008:36): [True: 1.71M, False: 5]
  ------------------
 1009|  1.71M|                    append();
 1010|  1.71M|                } else {
 1011|    239|                    tokenError();
 1012|    239|                }
 1013|  1.72M|                break;
 1014|       |
 1015|   172M|            case ls_string:
  ------------------
  |  Branch (1015:13): [True: 172M, False: 13.6M]
  ------------------
 1016|   172M|                if (*p == '"') {
  ------------------
  |  Branch (1016:21): [True: 1.96M, False: 170M]
  ------------------
 1017|  1.96M|                    if (high_offset) {
  ------------------
  |  Branch (1017:25): [True: 35, False: 1.96M]
  ------------------
 1018|     35|                        QTC::TC("libtests", "JSON 16 dangling high");
 1019|     35|                        throw std::runtime_error(
 1020|     35|                            "JSON: offset " + std::to_string(high_offset) +
 1021|     35|                            ": UTF-16 high surrogate not followed by low surrogate");
 1022|     35|                    }
 1023|  1.96M|                    ignore(ls_after_string);
 1024|  1.96M|                    return;
 1025|   170M|                } else if (*p == '\\') {
  ------------------
  |  Branch (1025:28): [True: 138k, False: 170M]
  ------------------
 1026|   138k|                    ignore(ls_backslash);
 1027|   170M|                } else {
 1028|   170M|                    append();
 1029|   170M|                }
 1030|   170M|                break;
 1031|       |
 1032|   170M|            case ls_backslash:
  ------------------
  |  Branch (1032:13): [True: 138k, False: 185M]
  ------------------
 1033|   138k|                lex_state = ls_string;
 1034|   138k|                switch (*p) {
 1035|  55.5k|                case '\\':
  ------------------
  |  Branch (1035:17): [True: 55.5k, False: 83.2k]
  ------------------
 1036|  59.4k|                case '\"':
  ------------------
  |  Branch (1036:17): [True: 3.87k, False: 134k]
  ------------------
 1037|  59.9k|                case '/':
  ------------------
  |  Branch (1037:17): [True: 459, False: 138k]
  ------------------
 1038|       |                    // \/ is allowed in json input, but so is /, so we don't map / to \/ in output.
 1039|  59.9k|                    token += *p;
 1040|  59.9k|                    break;
 1041|  7.18k|                case 'b':
  ------------------
  |  Branch (1041:17): [True: 7.18k, False: 131k]
  ------------------
 1042|  7.18k|                    token += '\b';
 1043|  7.18k|                    break;
 1044|  6.90k|                case 'f':
  ------------------
  |  Branch (1044:17): [True: 6.90k, False: 131k]
  ------------------
 1045|  6.90k|                    token += '\f';
 1046|  6.90k|                    break;
 1047|  8.64k|                case 'n':
  ------------------
  |  Branch (1047:17): [True: 8.64k, False: 130k]
  ------------------
 1048|  8.64k|                    token += '\n';
 1049|  8.64k|                    break;
 1050|  7.90k|                case 'r':
  ------------------
  |  Branch (1050:17): [True: 7.90k, False: 130k]
  ------------------
 1051|  7.90k|                    token += '\r';
 1052|  7.90k|                    break;
 1053|  3.28k|                case 't':
  ------------------
  |  Branch (1053:17): [True: 3.28k, False: 135k]
  ------------------
 1054|  3.28k|                    token += '\t';
 1055|  3.28k|                    break;
 1056|  45.0k|                case 'u':
  ------------------
  |  Branch (1056:17): [True: 45.0k, False: 93.8k]
  ------------------
 1057|  45.0k|                    lex_state = ls_u4;
 1058|  45.0k|                    u_count = 0;
 1059|  45.0k|                    u_value = 0;
 1060|  45.0k|                    break;
 1061|     17|                default:
  ------------------
  |  Branch (1061:17): [True: 17, False: 138k]
  ------------------
 1062|     17|                    lex_state = ls_backslash;
 1063|     17|                    tokenError();
 1064|   138k|                }
 1065|   138k|                ignore();
 1066|   138k|                break;
 1067|       |
 1068|   179k|            case ls_u4:
  ------------------
  |  Branch (1068:13): [True: 179k, False: 185M]
  ------------------
 1069|   179k|                using ui = unsigned int;
 1070|   179k|                if (ui val = ui(util::hex_decode_char(*p)); val < 16) {
  ------------------
  |  Branch (1070:61): [True: 179k, False: 85]
  ------------------
 1071|   179k|                    u_value = 16 * u_value + val;
 1072|   179k|                } else {
 1073|     85|                    tokenError();
 1074|     85|                }
 1075|   179k|                if (++u_count == 4) {
  ------------------
  |  Branch (1075:21): [True: 44.8k, False: 134k]
  ------------------
 1076|  44.8k|                    handle_u_code(u_value, offset - 5, high_surrogate, high_offset, token);
 1077|  44.8k|                    lex_state = ls_string;
 1078|  44.8k|                }
 1079|   179k|                ignore();
 1080|   179k|                break;
 1081|       |
 1082|      0|            default:
  ------------------
  |  Branch (1082:13): [True: 0, False: 185M]
  ------------------
 1083|      0|                throw std::logic_error("JSONParser::getToken : trying to handle delimiter state");
 1084|   185M|            }
 1085|   185M|        }
 1086|   319M|    }
 1087|       |
 1088|       |    // We only get here if on end of input or if the last character was a control character or other
 1089|       |    // delimiter.
 1090|       |
 1091|  2.35M|    if (!token.empty()) {
  ------------------
  |  Branch (1091:9): [True: 2.34M, False: 7.70k]
  ------------------
 1092|  2.34M|        switch (lex_state) {
 1093|      0|        case ls_top:
  ------------------
  |  Branch (1093:9): [True: 0, False: 2.34M]
  ------------------
 1094|       |            // Can't happen
 1095|      0|            throw std::logic_error("tok_start set in ls_top while parsing");
 1096|      0|            break;
 1097|       |
 1098|   446k|        case ls_number_leading_zero:
  ------------------
  |  Branch (1098:9): [True: 446k, False: 1.90M]
  ------------------
 1099|  2.30M|        case ls_number_before_point:
  ------------------
  |  Branch (1099:9): [True: 1.85M, False: 489k]
  ------------------
 1100|  2.30M|        case ls_number_after_point:
  ------------------
  |  Branch (1100:9): [True: 1.36k, False: 2.34M]
  ------------------
 1101|  2.30M|            lex_state = ls_number;
 1102|  2.30M|            break;
 1103|       |
 1104|  16.6k|        case ls_number:
  ------------------
  |  Branch (1104:9): [True: 16.6k, False: 2.33M]
  ------------------
 1105|  40.7k|        case ls_alpha:
  ------------------
  |  Branch (1105:9): [True: 24.1k, False: 2.32M]
  ------------------
 1106|       |            // terminal state
 1107|  40.7k|            break;
 1108|       |
 1109|  1.14k|        default:
  ------------------
  |  Branch (1109:9): [True: 1.14k, False: 2.34M]
  ------------------
 1110|  1.14k|            tokenError();
 1111|  2.34M|        }
 1112|  2.34M|    }
 1113|  2.35M|}
JSON.cc:_ZN12_GLOBAL__N_110JSONParser6ignoreEv:
  790|  6.23M|{
  791|  6.23M|    ++p;
  792|  6.23M|    ++offset;
  793|  6.23M|}
JSON.cc:_ZN12_GLOBAL__N_110JSONParser6ignoreENS0_11lex_state_eE:
  799|  8.63M|{
  800|  8.63M|    lex_state = next;
  801|  8.63M|    ++p;
  802|  8.63M|    ++offset;
  803|  8.63M|}
JSON.cc:_ZN12_GLOBAL__N_110JSONParser6appendEv:
  770|   299M|{
  771|   299M|    token += *p;
  772|   299M|    ++p;
  773|   299M|    ++offset;
  774|   299M|}
JSON.cc:_ZN12_GLOBAL__N_110JSONParser6appendENS0_11lex_state_eE:
  780|  2.39M|{
  781|  2.39M|    lex_state = next;
  782|  2.39M|    token += *p;
  783|  2.39M|    ++p;
  784|  2.39M|    ++offset;
  785|  2.39M|}
JSON.cc:_ZN12_GLOBAL__N_110JSONParser10tokenErrorEv:
  705|  1.76k|{
  706|  1.76k|    if (done) {
  ------------------
  |  Branch (706:9): [True: 1.04k, False: 720]
  ------------------
  707|  1.04k|        QTC::TC("libtests", "JSON parse ls premature end of input");
  708|  1.04k|        throw std::runtime_error("JSON: premature end of input");
  709|  1.04k|    }
  710|       |
  711|    720|    if (lex_state == ls_u4) {
  ------------------
  |  Branch (711:9): [True: 93, False: 627]
  ------------------
  712|     93|        QTC::TC("libtests", "JSON parse bad hex after u");
  713|     93|        throw std::runtime_error(
  714|     93|            "JSON: offset " + std::to_string(offset - u_count - 1) +
  715|     93|            ": \\u must be followed by four hex digits");
  716|    627|    } else if (lex_state == ls_alpha) {
  ------------------
  |  Branch (716:16): [True: 239, False: 388]
  ------------------
  717|    239|        QTC::TC("libtests", "JSON parse keyword bad character");
  718|    239|        throw std::runtime_error(
  719|    239|            "JSON: offset " + std::to_string(offset) + ": keyword: unexpected character " +
  720|    239|            std::string(p, 1));
  721|    388|    } else if (lex_state == ls_string) {
  ------------------
  |  Branch (721:16): [True: 25, False: 363]
  ------------------
  722|     25|        QTC::TC("libtests", "JSON parse control char in string");
  723|     25|        throw std::runtime_error(
  724|     25|            "JSON: offset " + std::to_string(offset) +
  725|     25|            ": control character in string (missing \"?)");
  726|    363|    } else if (lex_state == ls_backslash) {
  ------------------
  |  Branch (726:16): [True: 29, False: 334]
  ------------------
  727|     29|        QTC::TC("libtests", "JSON parse backslash bad character");
  728|     29|        throw std::runtime_error(
  729|     29|            "JSON: offset " + std::to_string(offset) +
  730|     29|            ": invalid character after backslash: " + std::string(p, 1));
  731|     29|    }
  732|       |
  733|    334|    if (*p == '.') {
  ------------------
  |  Branch (733:9): [True: 16, False: 318]
  ------------------
  734|     16|        if (lex_state == ls_number || lex_state == ls_number_e || lex_state == ls_number_e_sign) {
  ------------------
  |  Branch (734:13): [True: 3, False: 13]
  |  Branch (734:39): [True: 3, False: 10]
  |  Branch (734:67): [True: 3, False: 7]
  ------------------
  735|      9|            QTC::TC("libtests", "JSON parse point after e");
  736|      9|            throw std::runtime_error(
  737|      9|                "JSON: offset " + std::to_string(offset) +
  738|      9|                ": numeric literal: decimal point after e");
  739|      9|        } else {
  740|      7|            QTC::TC("libtests", "JSON parse duplicate point");
  741|      7|            throw std::runtime_error(
  742|      7|                "JSON: offset " + std::to_string(offset) +
  743|      7|                ": numeric literal: decimal point already seen");
  744|      7|        }
  745|    318|    } else if (*p == 'e' || *p == 'E') {
  ------------------
  |  Branch (745:16): [True: 11, False: 307]
  |  Branch (745:29): [True: 12, False: 295]
  ------------------
  746|     23|        QTC::TC("libtests", "JSON parse duplicate e");
  747|     23|        throw std::runtime_error(
  748|     23|            "JSON: offset " + std::to_string(offset) + ": numeric literal: e already seen");
  749|    295|    } else if ((*p == '+') || (*p == '-')) {
  ------------------
  |  Branch (749:16): [True: 7, False: 288]
  |  Branch (749:31): [True: 15, False: 273]
  ------------------
  750|     22|        QTC::TC("libtests", "JSON parse unexpected sign");
  751|     22|        throw std::runtime_error(
  752|     22|            "JSON: offset " + std::to_string(offset) + ": numeric literal: unexpected sign");
  753|    273|    } else if (util::is_space(*p) || strchr("{}[]:,", *p)) {
  ------------------
  |  Branch (753:16): [True: 16, False: 257]
  |  Branch (753:38): [True: 39, False: 218]
  ------------------
  754|     55|        QTC::TC("libtests", "JSON parse incomplete number");
  755|     55|        throw std::runtime_error(
  756|     55|            "JSON: offset " + std::to_string(offset) + ": numeric literal: incomplete number");
  757|       |
  758|    218|    } else {
  759|    218|        QTC::TC("libtests", "JSON parse numeric bad character");
  760|    218|        throw std::runtime_error(
  761|    218|            "JSON: offset " + std::to_string(offset) + ": numeric literal: unexpected character " +
  762|    218|            std::string(p, 1));
  763|    218|    }
  764|      0|    throw std::logic_error("JSON::tokenError : unhandled error");
  765|    334|}
JSON.cc:_ZN12_GLOBAL__N_110JSONParser13handle_u_codeEmxRmRxRNSt3__112basic_stringIcNS3_11char_traitsIcEENS3_9allocatorIcEEEE:
  674|  44.8k|{
  675|  44.8k|    if ((codepoint & 0xFC00) == 0xD800) {
  ------------------
  |  Branch (675:9): [True: 2.80k, False: 42.0k]
  ------------------
  676|       |        // high surrogate
  677|  2.80k|        qpdf_offset_t new_high_offset = offset;
  678|  2.80k|        if (high_offset) {
  ------------------
  |  Branch (678:13): [True: 32, False: 2.77k]
  ------------------
  679|     32|            QTC::TC("libtests", "JSON 16 high high");
  680|     32|            throw std::runtime_error(
  681|     32|                "JSON: offset " + std::to_string(new_high_offset) +
  682|     32|                ": UTF-16 high surrogate found after previous high surrogate at offset " +
  683|     32|                std::to_string(high_offset));
  684|     32|        }
  685|  2.77k|        high_offset = new_high_offset;
  686|  2.77k|        high_surrogate = codepoint;
  687|  42.0k|    } else if ((codepoint & 0xFC00) == 0xDC00) {
  ------------------
  |  Branch (687:16): [True: 2.71k, False: 39.3k]
  ------------------
  688|       |        // low surrogate
  689|  2.71k|        if (offset != (high_offset + 6)) {
  ------------------
  |  Branch (689:13): [True: 21, False: 2.69k]
  ------------------
  690|     21|            QTC::TC("libtests", "JSON 16 low not after high");
  691|     21|            throw std::runtime_error(
  692|     21|                "JSON: offset " + std::to_string(offset) +
  693|     21|                ": UTF-16 low surrogate found not immediately after high surrogate");
  694|     21|        }
  695|  2.69k|        high_offset = 0;
  696|  2.69k|        codepoint = 0x10000U + ((high_surrogate & 0x3FFU) << 10U) + (codepoint & 0x3FF);
  697|  2.69k|        result += QUtil::toUTF8(codepoint);
  698|  39.3k|    } else {
  699|  39.3k|        result += QUtil::toUTF8(codepoint);
  700|  39.3k|    }
  701|  44.8k|}
JSON.cc:_ZN12_GLOBAL__N_110JSONParser11handleTokenEv:
 1117|  8.88M|{
 1118|  8.88M|    if (lex_state == ls_top) {
  ------------------
  |  Branch (1118:9): [True: 7.45k, False: 8.87M]
  ------------------
 1119|  7.45k|        return;
 1120|  7.45k|    }
 1121|       |
 1122|  8.87M|    if (parser_state == ps_done) {
  ------------------
  |  Branch (1122:9): [True: 77, False: 8.87M]
  ------------------
 1123|     77|        QTC::TC("libtests", "JSON parse junk after object");
 1124|     77|        throw std::runtime_error(
 1125|     77|            "JSON: offset " + std::to_string(offset) +
 1126|     77|            ": material follows end of object: " + token);
 1127|     77|    }
 1128|       |
 1129|  8.87M|    const static JSON null_item = JSON::makeNull();
 1130|  8.87M|    JSON item;
 1131|  8.87M|    auto tos = stack.empty() ? null_item : stack.back().item;
  ------------------
  |  Branch (1131:16): [True: 14.5k, False: 8.86M]
  ------------------
 1132|  8.87M|    auto ls = lex_state;
 1133|  8.87M|    lex_state = ls_top;
 1134|       |
 1135|  8.87M|    switch (ls) {
 1136|   123k|    case ls_begin_dict:
  ------------------
  |  Branch (1136:5): [True: 123k, False: 8.75M]
  ------------------
 1137|   123k|        item = JSON::makeDictionary();
 1138|   123k|        break;
 1139|       |
 1140|  46.4k|    case ls_begin_array:
  ------------------
  |  Branch (1140:5): [True: 46.4k, False: 8.83M]
  ------------------
 1141|  46.4k|        item = JSON::makeArray();
 1142|  46.4k|        break;
 1143|       |
 1144|   372k|    case ls_colon:
  ------------------
  |  Branch (1144:5): [True: 372k, False: 8.50M]
  ------------------
 1145|   372k|        if (parser_state != ps_dict_after_key) {
  ------------------
  |  Branch (1145:13): [True: 257, False: 371k]
  ------------------
 1146|    257|            QTC::TC("libtests", "JSON parse unexpected :");
 1147|    257|            throw std::runtime_error(
 1148|    257|                "JSON: offset " + std::to_string(offset) + ": unexpected colon");
 1149|    257|        }
 1150|   371k|        parser_state = ps_dict_after_colon;
 1151|   371k|        return;
 1152|       |
 1153|  3.95M|    case ls_comma:
  ------------------
  |  Branch (1153:5): [True: 3.95M, False: 4.92M]
  ------------------
 1154|  3.95M|        if (!((parser_state == ps_dict_after_item) || (parser_state == ps_array_after_item))) {
  ------------------
  |  Branch (1154:15): [True: 270k, False: 3.68M]
  |  Branch (1154:55): [True: 3.68M, False: 84]
  ------------------
 1155|     84|            QTC::TC("libtests", "JSON parse unexpected ,");
 1156|     84|            throw std::runtime_error(
 1157|     84|                "JSON: offset " + std::to_string(offset) + ": unexpected comma");
 1158|     84|        }
 1159|  3.95M|        if (parser_state == ps_dict_after_item) {
  ------------------
  |  Branch (1159:13): [True: 270k, False: 3.68M]
  ------------------
 1160|   270k|            parser_state = ps_dict_after_comma;
 1161|  3.68M|        } else if (parser_state == ps_array_after_item) {
  ------------------
  |  Branch (1161:20): [True: 3.68M, False: 0]
  ------------------
 1162|  3.68M|            parser_state = ps_array_after_comma;
 1163|  3.68M|        } else {
 1164|      0|            throw std::logic_error("JSONParser::handleToken: unexpected parser state for comma");
 1165|      0|        }
 1166|  3.95M|        return;
 1167|       |
 1168|  3.95M|    case ls_end_array:
  ------------------
  |  Branch (1168:5): [True: 6.06k, False: 8.87M]
  ------------------
 1169|  6.06k|        if (!(parser_state == ps_array_begin || parser_state == ps_array_after_item)) {
  ------------------
  |  Branch (1169:15): [True: 3.21k, False: 2.84k]
  |  Branch (1169:49): [True: 2.81k, False: 31]
  ------------------
 1170|     31|            QTC::TC("libtests", "JSON parse unexpected ]");
 1171|     31|            throw std::runtime_error(
 1172|     31|                "JSON: offset " + std::to_string(offset) + ": unexpected array end delimiter");
 1173|     31|        }
 1174|  6.03k|        parser_state = stack.back().state;
 1175|  6.03k|        tos.setEnd(offset);
 1176|  6.03k|        if (reactor) {
  ------------------
  |  Branch (1176:13): [True: 2.90k, False: 3.13k]
  ------------------
 1177|  2.90k|            reactor->containerEnd(tos);
 1178|  2.90k|        }
 1179|  6.03k|        if (parser_state != ps_done) {
  ------------------
  |  Branch (1179:13): [True: 6.02k, False: 15]
  ------------------
 1180|  6.02k|            stack.pop_back();
 1181|  6.02k|        }
 1182|  6.03k|        return;
 1183|       |
 1184|  57.0k|    case ls_end_dict:
  ------------------
  |  Branch (1184:5): [True: 57.0k, False: 8.82M]
  ------------------
 1185|  57.0k|        if (!((parser_state == ps_dict_begin) || (parser_state == ps_dict_after_item))) {
  ------------------
  |  Branch (1185:15): [True: 18.3k, False: 38.7k]
  |  Branch (1185:50): [True: 38.7k, False: 17]
  ------------------
 1186|     17|            QTC::TC("libtests", "JSON parse unexpected }");
 1187|     17|            throw std::runtime_error(
 1188|     17|                "JSON: offset " + std::to_string(offset) + ": unexpected dictionary end delimiter");
 1189|     17|        }
 1190|  57.0k|        parser_state = stack.back().state;
 1191|  57.0k|        tos.setEnd(offset);
 1192|  57.0k|        if (reactor) {
  ------------------
  |  Branch (1192:13): [True: 28.4k, False: 28.5k]
  ------------------
 1193|  28.4k|            reactor->containerEnd(tos);
 1194|  28.4k|        }
 1195|  57.0k|        if (parser_state != ps_done) {
  ------------------
  |  Branch (1195:13): [True: 56.9k, False: 134]
  ------------------
 1196|  56.9k|            stack.pop_back();
 1197|  56.9k|        }
 1198|  57.0k|        return;
 1199|       |
 1200|  2.32M|    case ls_number:
  ------------------
  |  Branch (1200:5): [True: 2.32M, False: 6.55M]
  ------------------
 1201|  2.32M|        item = JSON::makeNumber(token);
 1202|  2.32M|        break;
 1203|       |
 1204|  24.1k|    case ls_alpha:
  ------------------
  |  Branch (1204:5): [True: 24.1k, False: 8.85M]
  ------------------
 1205|  24.1k|        if (token == "true") {
  ------------------
  |  Branch (1205:13): [True: 11.1k, False: 12.9k]
  ------------------
 1206|  11.1k|            item = JSON::makeBool(true);
 1207|  12.9k|        } else if (token == "false") {
  ------------------
  |  Branch (1207:20): [True: 3.00k, False: 9.99k]
  ------------------
 1208|  3.00k|            item = JSON::makeBool(false);
 1209|  9.99k|        } else if (token == "null") {
  ------------------
  |  Branch (1209:20): [True: 9.57k, False: 425]
  ------------------
 1210|  9.57k|            item = JSON::makeNull();
 1211|  9.57k|        } else {
 1212|    425|            QTC::TC("libtests", "JSON parse invalid keyword");
 1213|    425|            throw std::runtime_error(
 1214|    425|                "JSON: offset " + std::to_string(offset) + ": invalid keyword " + token);
 1215|    425|        }
 1216|  23.7k|        break;
 1217|       |
 1218|  1.96M|    case ls_after_string:
  ------------------
  |  Branch (1218:5): [True: 1.96M, False: 6.90M]
  ------------------
 1219|  1.96M|        if (parser_state == ps_dict_begin || parser_state == ps_dict_after_comma) {
  ------------------
  |  Branch (1219:13): [True: 102k, False: 1.86M]
  |  Branch (1219:46): [True: 269k, False: 1.59M]
  ------------------
 1220|   372k|            dict_key = token;
 1221|   372k|            dict_key_offset = token_start;
 1222|   372k|            parser_state = ps_dict_after_key;
 1223|   372k|            return;
 1224|  1.59M|        } else {
 1225|  1.59M|            item = JSON::makeString(token);
 1226|  1.59M|        }
 1227|  1.59M|        break;
 1228|       |
 1229|  1.59M|    default:
  ------------------
  |  Branch (1229:5): [True: 248, False: 8.87M]
  ------------------
 1230|    248|        throw std::runtime_error(
 1231|    248|            "JSON: offset " + std::to_string(offset) + ": premature end of input");
 1232|      0|        break;
 1233|  8.87M|    }
 1234|       |
 1235|  4.11M|    item.setStart(token_start);
 1236|  4.11M|    item.setEnd(offset);
 1237|       |
 1238|  4.11M|    switch (parser_state) {
  ------------------
  |  Branch (1238:13): [True: 4.11M, False: 0]
  ------------------
 1239|     24|    case ps_dict_begin:
  ------------------
  |  Branch (1239:5): [True: 24, False: 4.11M]
  ------------------
 1240|     66|    case ps_dict_after_comma:
  ------------------
  |  Branch (1240:5): [True: 42, False: 4.11M]
  ------------------
 1241|     66|        QTC::TC("libtests", "JSON parse string as dict key");
 1242|     66|        throw std::runtime_error(
 1243|     66|            "JSON: offset " + std::to_string(offset) + ": expect string as dictionary key");
 1244|      0|        break;
 1245|       |
 1246|   371k|    case ps_dict_after_colon:
  ------------------
  |  Branch (1246:5): [True: 371k, False: 3.74M]
  ------------------
 1247|   371k|        if (!reactor || !reactor->dictionaryItem(dict_key, item)) {
  ------------------
  |  Branch (1247:13): [True: 185k, False: 185k]
  |  Branch (1247:25): [True: 490, False: 185k]
  ------------------
 1248|   185k|            tos.addDictionaryMember(dict_key, item);
 1249|   185k|        }
 1250|   371k|        parser_state = ps_dict_after_item;
 1251|   371k|        break;
 1252|       |
 1253|  41.8k|    case ps_array_begin:
  ------------------
  |  Branch (1253:5): [True: 41.8k, False: 4.07M]
  ------------------
 1254|  3.72M|    case ps_array_after_comma:
  ------------------
  |  Branch (1254:5): [True: 3.68M, False: 428k]
  ------------------
 1255|  3.72M|        if (!reactor || !reactor->arrayItem(item)) {
  ------------------
  |  Branch (1255:13): [True: 1.86M, False: 1.86M]
  |  Branch (1255:25): [True: 22, False: 1.86M]
  ------------------
 1256|  1.86M|            tos.addArrayElement(item);
 1257|  1.86M|        }
 1258|  3.72M|        parser_state = ps_array_after_item;
 1259|  3.72M|        break;
 1260|       |
 1261|  14.3k|    case ps_top:
  ------------------
  |  Branch (1261:5): [True: 14.3k, False: 4.09M]
  ------------------
 1262|  14.3k|        if (!(item.isDictionary() || item.isArray())) {
  ------------------
  |  Branch (1262:15): [True: 13.4k, False: 914]
  |  Branch (1262:38): [True: 678, False: 236]
  ------------------
 1263|    236|            stack.emplace_back(ps_done, item);
 1264|    236|            parser_state = ps_done;
 1265|    236|            return;
 1266|    236|        }
 1267|  14.1k|        parser_state = ps_done;
 1268|  14.1k|        break;
 1269|       |
 1270|     53|    case ps_dict_after_key:
  ------------------
  |  Branch (1270:5): [True: 53, False: 4.11M]
  ------------------
 1271|     53|        QTC::TC("libtests", "JSON parse expected colon");
 1272|     53|        throw std::runtime_error("JSON: offset " + std::to_string(offset) + ": expected ':'");
 1273|      0|        break;
 1274|       |
 1275|    161|    case ps_dict_after_item:
  ------------------
  |  Branch (1275:5): [True: 161, False: 4.11M]
  ------------------
 1276|    161|        QTC::TC("libtests", "JSON parse expected , or }");
 1277|    161|        throw std::runtime_error(
 1278|    161|            "JSON: offset " + std::to_string(offset) + ": expected ',' or '}'");
 1279|      0|        break;
 1280|       |
 1281|    103|    case ps_array_after_item:
  ------------------
  |  Branch (1281:5): [True: 103, False: 4.11M]
  ------------------
 1282|    103|        QTC::TC("libtests", "JSON parse expected, or ]");
 1283|    103|        throw std::runtime_error(
 1284|    103|            "JSON: offset " + std::to_string(offset) + ": expected ',' or ']'");
 1285|      0|        break;
 1286|       |
 1287|      0|    case ps_done:
  ------------------
  |  Branch (1287:5): [True: 0, False: 4.11M]
  ------------------
 1288|      0|        throw std::logic_error("JSONParser::handleToken: unexpected parser state");
 1289|  4.11M|    }
 1290|       |
 1291|  4.11M|    if (item.isDictionary() || item.isArray()) {
  ------------------
  |  Branch (1291:9): [True: 123k, False: 3.98M]
  |  Branch (1291:32): [True: 46.3k, False: 3.94M]
  ------------------
 1292|   169k|        stack.emplace_back(parser_state, item);
 1293|       |        // Calling container start method is postponed until after adding the containers to their
 1294|       |        // parent containers, if any. This makes it much easier to keep track of the current nesting
 1295|       |        // level.
 1296|   169k|        if (item.isDictionary()) {
  ------------------
  |  Branch (1296:13): [True: 123k, False: 46.3k]
  ------------------
 1297|   123k|            if (reactor) {
  ------------------
  |  Branch (1297:17): [True: 61.5k, False: 61.7k]
  ------------------
 1298|  61.5k|                reactor->dictionaryStart();
 1299|  61.5k|            }
 1300|   123k|            parser_state = ps_dict_begin;
 1301|   123k|        } else if (item.isArray()) {
  ------------------
  |  Branch (1301:20): [True: 46.3k, False: 0]
  ------------------
 1302|  46.3k|            if (reactor) {
  ------------------
  |  Branch (1302:17): [True: 21.6k, False: 24.7k]
  ------------------
 1303|  21.6k|                reactor->arrayStart();
 1304|  21.6k|            }
 1305|  46.3k|            parser_state = ps_array_begin;
 1306|  46.3k|        }
 1307|       |
 1308|   169k|        if (stack.size() > 500) {
  ------------------
  |  Branch (1308:13): [True: 7, False: 169k]
  ------------------
 1309|      7|            throw std::runtime_error(
 1310|      7|                "JSON: offset " + std::to_string(offset) + ": maximum object depth exceeded");
 1311|      7|        }
 1312|   169k|    }
 1313|  4.11M|}
JSON.cc:_ZN12_GLOBAL__N_110JSONParser10StackFrameC2ENS0_14parser_state_eER4JSON:
  625|   169k|                state(state),
  626|   169k|                item(item)
  627|   169k|            {
  628|   169k|            }

_ZN8PipelineC2EPKcPS_:
   11|      4|    identifier(identifier),
   12|      4|    next_(next)
   13|      4|{
   14|      4|}
_ZN8Pipeline9writeCStrEPKc:
   32|   149k|{
   33|   149k|    write(cstr, strlen(cstr));
   34|   149k|}
_ZN8PipelinelsEPKc:
   44|   149k|{
   45|   149k|    writeCStr(cstr);
   46|   149k|    return *this;
   47|   149k|}
_ZN8Pipeline5writeEPKcm:
  114|   149k|{
  115|   149k|    write(reinterpret_cast<unsigned char const*>(data), len);
  116|   149k|}

_ZN10Pl_DiscardC2Ev:
    9|      1|    Pipeline("discard", nullptr)
   10|      1|{
   11|      1|}
_ZN10Pl_DiscardD2Ev:
   14|      1|Pl_Discard::~Pl_Discard() = default;

_ZN10Pl_OStreamC2EPKcRNSt3__113basic_ostreamIcNS2_11char_traitsIcEEEE:
   19|      2|    Pipeline(identifier, nullptr),
   20|      2|    m(std::make_unique<Members>(os))
   21|      2|{
   22|      2|}
_ZN10Pl_OStreamD2Ev:
   25|      2|Pl_OStream::~Pl_OStream() = default;
_ZN10Pl_OStream5writeEPKhm:
   29|   149k|{
   30|   149k|    m->os.write(reinterpret_cast<char const*>(buf), static_cast<std::streamsize>(len));
   31|   149k|}
_ZN10Pl_OStream6finishEv:
   35|      2|{
   36|      2|    m->os.flush();
   37|      2|}
_ZN10Pl_OStream7MembersC2ERNSt3__113basic_ostreamIcNS1_11char_traitsIcEEEE:
    9|      2|        os(os)
   10|      2|    {
   11|      2|    }

_ZN4QPDF7MembersC2ERS_:
  131|  7.72k|    Doc(qpdf, this),
  132|  7.72k|    c(qpdf, this),
  133|  7.72k|    lin(*this),
  134|  7.72k|    objects(*this),
  135|  7.72k|    pages(*this),
  136|  7.72k|    file(std::make_shared<InvalidInputSource>()),
  137|  7.72k|    encp(std::make_shared<EncryptionParameters>())
  138|  7.72k|{
  139|  7.72k|}
_ZN4QPDFC2Ev:
  142|  7.72k|    m(std::make_unique<Members>(*this))
  143|  7.72k|{
  144|  7.72k|    m->tokenizer.allowEOF();
  145|       |    // Generate a unique ID. It just has to be unique among all QPDF objects allocated throughout
  146|       |    // the lifetime of this running application.
  147|  7.72k|    static std::atomic<unsigned long long> unique_id{0};
  148|  7.72k|    m->unique_id = unique_id.fetch_add(1ULL);
  149|  7.72k|}
_ZN4QPDFD2Ev:
  186|  7.72k|{
  187|       |    // If two objects are mutually referential (through each object having an array or dictionary
  188|       |    // that contains an indirect reference to the other), the circular references in the
  189|       |    // std::shared_ptr objects will prevent the objects from being deleted. Walk through all objects
  190|       |    // in the object cache, which is those objects that we read from the file, and break all
  191|       |    // resolved indirect references by replacing them with an internal object type representing that
  192|       |    // they have been destroyed. Note that we can't break references like this at any time when the
  193|       |    // QPDF object is active. The call to reset also causes all direct QPDFObjectHandle objects that
  194|       |    // are reachable from this object to release their association with this QPDF. Direct objects
  195|       |    // are not destroyed since they can be moved to other QPDF objects safely.
  196|       |
  197|       |    // At this point, obviously no one is still using the QPDF object, but we'll explicitly clear
  198|       |    // the xref table anyway just to prevent any possibility of resolve() succeeding.
  199|  7.72k|    m->xref_table.clear();
  200|  12.8k|    for (auto const& iter: m->obj_cache) {
  ------------------
  |  Branch (200:26): [True: 12.8k, False: 7.72k]
  ------------------
  201|  12.8k|        Disconnect(iter.second.object).disconnect();
  202|  12.8k|    }
  203|  7.72k|}
_ZN4QPDF17processMemoryFileEPKcS1_mS1_:
  228|  7.72k|{
  229|  7.72k|    auto is = std::make_shared<is::OffsetBuffer>(description, std::string_view{buf, length});
  230|  7.72k|    processInputSource(is, password);
  231|  7.72k|}
_ZN4QPDF18processInputSourceENSt3__110shared_ptrI11InputSourceEEPKc:
  235|  7.72k|{
  236|  7.72k|    m->file = source;
  237|  7.72k|    m->objects.parse(password);
  238|  7.72k|}
_ZN4QPDF3Doc6Common4warnERK7QPDFExc:
  343|  49.9k|{
  344|  49.9k|    if (cf.max_warnings() > 0 && m->warnings.size() >= cf.max_warnings()) {
  ------------------
  |  Branch (344:9): [True: 49.9k, False: 0]
  |  Branch (344:34): [True: 30, False: 49.9k]
  ------------------
  345|     30|        stopOnError("Too many warnings - file is too badly damaged");
  346|     30|    }
  347|  49.9k|    m->warnings.emplace_back(e);
  348|  49.9k|    if (!cf.suppress_warnings()) {
  ------------------
  |  Branch (348:9): [True: 49.9k, False: 30]
  ------------------
  349|  49.9k|        *cf.log()->getWarn() << "WARNING: " << m->warnings.back().what() << "\n";
  350|  49.9k|    }
  351|  49.9k|}
_ZN4QPDF4warnE17qpdf_error_code_eRKNSt3__112basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEExS9_:
  359|  49.9k|{
  360|  49.9k|    m->c.warn(QPDFExc(error_code, getFilename(), object, offset, message));
  361|  49.9k|}
_ZNK4QPDF11getFilenameEv:
  625|   103k|{
  626|   103k|    return m->file->getName();
  627|   103k|}
_ZN4QPDF3Doc6Common11stopOnErrorERKNSt3__112basic_stringIcNS2_11char_traitsIcEENS2_9allocatorIcEEEE:
  799|     30|{
  800|     30|    throw damagedPDF("", message);
  801|     30|}
_ZNK4QPDF3Doc6Common10damagedPDFERKNSt3__112basic_stringIcNS2_11char_traitsIcEENS2_9allocatorIcEEEExSA_:
  823|     30|{
  824|     30|    return {qpdf_e_damaged_pdf, m->file->getName(), object, offset, message, true};
  825|     30|}
_ZNK4QPDF3Doc6Common10damagedPDFERKNSt3__112basic_stringIcNS2_11char_traitsIcEENS2_9allocatorIcEEEESA_:
  831|     30|{
  832|     30|    return damagedPDF(object, m->file->getLastOffset(), message);
  833|     30|}
_ZN10DisconnectC2ERKNSt3__110shared_ptrI10QPDFObjectEE:
  172|  12.8k|        BaseHandle(obj)
  173|  12.8k|    {
  174|  12.8k|    }
_ZN10Disconnect10disconnectEv:
  177|  12.8k|    {
  178|  12.8k|        BaseHandle::disconnect(false);
  179|  12.8k|        if (raw_type_code() != ::ot_null) {
  ------------------
  |  Branch (179:13): [True: 6.85k, False: 5.97k]
  ------------------
  180|  6.85k|            obj->value = QPDF_Destroyed();
  181|  6.85k|        }
  182|  12.8k|    }

_ZN7QPDFExcC2E17qpdf_error_code_eRKNSt3__112basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEES9_xS9_:
    9|  50.3k|    std::runtime_error(createWhat(filename, object, (offset ? offset : -1), message)),
  ------------------
  |  Branch (9:54): [True: 49.4k, False: 902]
  ------------------
   10|  50.3k|    error_code(error_code),
   11|  50.3k|    filename(filename),
   12|  50.3k|    object(object),
   13|  50.3k|    offset(offset ? offset : -1),
  ------------------
  |  Branch (13:12): [True: 49.4k, False: 902]
  ------------------
   14|  50.3k|    message(message)
   15|  50.3k|{
   16|  50.3k|}
_ZN7QPDFExcC2E17qpdf_error_code_eRKNSt3__112basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEES9_xS9_b:
   25|     30|    std::runtime_error(
   26|     30|        createWhat(filename, object, (offset || zero_offset_valid ? offset : -1), message)),
  ------------------
  |  Branch (26:39): [True: 30, False: 0]
  |  Branch (26:49): [True: 0, False: 0]
  ------------------
   27|     30|    error_code(error_code),
   28|     30|    filename(filename),
   29|     30|    object(object),
   30|     30|    offset(offset || zero_offset_valid ? offset : -1),
  ------------------
  |  Branch (30:12): [True: 30, False: 0]
  |  Branch (30:22): [True: 0, False: 0]
  ------------------
   31|     30|    message(message)
   32|     30|{
   33|     30|}
_ZN7QPDFExc10createWhatERKNSt3__112basic_stringIcNS0_11char_traitsIcEENS0_9allocatorIcEEEES8_xS8_:
   41|  50.3k|{
   42|  50.3k|    std::string result;
   43|  50.3k|    if (!filename.empty()) {
  ------------------
  |  Branch (43:9): [True: 50.3k, False: 0]
  ------------------
   44|  50.3k|        result += filename;
   45|  50.3k|    }
   46|  50.3k|    if (!(object.empty() && offset < 0)) {
  ------------------
  |  Branch (46:11): [True: 16.0k, False: 34.3k]
  |  Branch (46:29): [True: 506, False: 15.5k]
  ------------------
   47|  49.8k|        if (!filename.empty()) {
  ------------------
  |  Branch (47:13): [True: 49.8k, False: 0]
  ------------------
   48|  49.8k|            result += " (";
   49|  49.8k|        }
   50|  49.8k|        if (!object.empty()) {
  ------------------
  |  Branch (50:13): [True: 34.3k, False: 15.5k]
  ------------------
   51|  34.3k|            result += object;
   52|  34.3k|            if (offset >= 0) {
  ------------------
  |  Branch (52:17): [True: 33.6k, False: 678]
  ------------------
   53|  33.6k|                result += ", ";
   54|  33.6k|            }
   55|  34.3k|        }
   56|  49.8k|        if (offset >= 0) {
  ------------------
  |  Branch (56:13): [True: 49.2k, False: 678]
  ------------------
   57|  49.2k|            result += "offset " + std::to_string(offset);
   58|  49.2k|        }
   59|  49.8k|        if (!filename.empty()) {
  ------------------
  |  Branch (59:13): [True: 49.8k, False: 0]
  ------------------
   60|  49.8k|            result += ")";
   61|  49.8k|        }
   62|  49.8k|    }
   63|  50.3k|    if (!result.empty()) {
  ------------------
  |  Branch (63:9): [True: 50.3k, False: 0]
  ------------------
   64|  50.3k|        result += ": ";
   65|  50.3k|    }
   66|  50.3k|    result += message;
   67|  50.3k|    return result;
   68|  50.3k|}

_ZN10QPDFLogger7MembersC2Ev:
   47|      1|    p_discard(new Pl_Discard()),
   48|      1|    p_real_stdout(new Pl_OStream("standard output", std::cout)),
   49|      1|    p_stdout(new Pl_Track("track stdout", p_real_stdout.get())),
   50|      1|    p_stderr(new Pl_OStream("standard error", std::cerr)),
   51|      1|    p_info(p_stdout),
   52|      1|    p_warn(nullptr),
   53|      1|    p_error(p_stderr),
   54|      1|    p_save(nullptr)
   55|      1|{
   56|      1|}
_ZN10QPDFLogger7MembersD2Ev:
   59|      1|{
   60|      1|    p_stdout->finish();
   61|      1|    p_stderr->finish();
   62|      1|}
_ZN10QPDFLoggerC2Ev:
   65|      1|    m(new Members())
   66|      1|{
   67|      1|}
_ZN10QPDFLogger6createEv:
   71|      1|{
   72|      1|    return std::shared_ptr<QPDFLogger>(new QPDFLogger);
   73|      1|}
_ZN10QPDFLogger13defaultLoggerEv:
   77|  7.72k|{
   78|  7.72k|    static auto l = create();
   79|  7.72k|    return l;
   80|  7.72k|}
_ZN10QPDFLogger7getWarnEb:
  114|  49.9k|{
  115|  49.9k|    if (m->p_warn) {
  ------------------
  |  Branch (115:9): [True: 0, False: 49.9k]
  ------------------
  116|      0|        return m->p_warn;
  117|      0|    }
  118|  49.9k|    return getError(null_okay);
  119|  49.9k|}
_ZN10QPDFLogger8getErrorEb:
  135|  49.9k|{
  136|  49.9k|    return throwIfNull(m->p_error, null_okay);
  137|  49.9k|}
_ZN10QPDFLogger11throwIfNullENSt3__110shared_ptrI8PipelineEEb:
  254|  49.9k|{
  255|  49.9k|    if (!(null_okay || p)) {
  ------------------
  |  Branch (255:11): [True: 0, False: 49.9k]
  |  Branch (255:24): [True: 49.9k, False: 0]
  ------------------
  256|      0|        throw std::logic_error("QPDFLogger: requested a null pipeline without null_okay == true");
  257|      0|    }
  258|  49.9k|    return p;
  259|  49.9k|}
QPDFLogger.cc:_ZN12_GLOBAL__N_18Pl_TrackC2EPKcP8Pipeline:
   15|      1|            Pipeline(identifier, next)
   16|      1|        {
   17|      1|            if (!next) {
  ------------------
  |  Branch (17:17): [True: 0, False: 1]
  ------------------
   18|      0|                throw std::logic_error("Attempt to create Pl_Track with nullptr as next");
   19|      0|            }
   20|      1|        }
QPDFLogger.cc:_ZN12_GLOBAL__N_18Pl_Track6finishEv:
   31|      1|        {
   32|      1|            next()->finish();
   33|      1|        }

_ZN10QPDFObject14getDescriptionEv:
    5|  3.30k|{
    6|  3.30k|    qpdf_offset_t shift = (getTypeCode() == ::ot_dictionary) ? 2
  ------------------
  |  Branch (6:27): [True: 0, False: 3.30k]
  ------------------
    7|  3.30k|        : (getTypeCode() == ::ot_array)                      ? 1
  ------------------
  |  Branch (7:11): [True: 0, False: 3.30k]
  ------------------
    8|  3.30k|                                                             : 0;
    9|       |
   10|  3.30k|    if (object_description) {
  ------------------
  |  Branch (10:9): [True: 3.30k, False: 0]
  ------------------
   11|  3.30k|        switch (object_description->index()) {
  ------------------
  |  Branch (11:17): [True: 3.30k, False: 0]
  ------------------
   12|  3.30k|        case 0:
  ------------------
  |  Branch (12:9): [True: 3.30k, False: 0]
  ------------------
   13|  3.30k|            {
   14|       |                // Simple template string
   15|  3.30k|                auto description = std::get<0>(*object_description);
   16|       |
   17|  3.30k|                if (auto pos = description.find("$OG"); pos != std::string::npos) {
  ------------------
  |  Branch (17:57): [True: 0, False: 3.30k]
  ------------------
   18|      0|                    description.replace(pos, 3, og.unparse(' '));
   19|      0|                }
   20|  3.30k|                if (auto pos = description.find("$PO"); pos != std::string::npos) {
  ------------------
  |  Branch (20:57): [True: 0, False: 3.30k]
  ------------------
   21|      0|                    description.replace(pos, 3, std::to_string(parsed_offset + shift));
   22|      0|                }
   23|  3.30k|                return description;
   24|      0|            }
   25|      0|        case 1:
  ------------------
  |  Branch (25:9): [True: 0, False: 3.30k]
  ------------------
   26|      0|            {
   27|       |                // QPDF::JSONReactor generated description
   28|      0|                auto j_descr = std::get<1>(*object_description);
   29|      0|                return (
   30|      0|                    *j_descr.input + (j_descr.object.empty() ? "" : ", " + j_descr.object) +
  ------------------
  |  Branch (30:39): [True: 0, False: 0]
  ------------------
   31|      0|                    " at offset " + std::to_string(parsed_offset));
   32|      0|            }
   33|      0|        case 2:
  ------------------
  |  Branch (33:9): [True: 0, False: 3.30k]
  ------------------
   34|      0|            {
   35|       |                // Child object description
   36|      0|                auto j_descr = std::get<2>(*object_description);
   37|      0|                std::string result;
   38|      0|                if (auto p = j_descr.parent.lock()) {
  ------------------
  |  Branch (38:26): [True: 0, False: 0]
  ------------------
   39|      0|                    result = p->getDescription();
   40|      0|                }
   41|      0|                result += j_descr.static_descr;
   42|      0|                if (auto pos = result.find("$VD"); pos != std::string::npos) {
  ------------------
  |  Branch (42:52): [True: 0, False: 0]
  ------------------
   43|      0|                    result.replace(pos, 3, j_descr.var_descr);
   44|      0|                }
   45|      0|                return result;
   46|      0|            }
   47|      0|        case 3:
  ------------------
  |  Branch (47:9): [True: 0, False: 3.30k]
  ------------------
   48|      0|            auto [stream_id, obj_id] = std::get<3>(*object_description);
   49|      0|            std::string result = qpdf ? qpdf->getFilename() : "";
  ------------------
  |  Branch (49:34): [True: 0, False: 0]
  ------------------
   50|      0|            result += " object stream " + std::to_string(stream_id) + ", object " +
   51|      0|                std::to_string(obj_id) + " 0 at offset " + std::to_string(parsed_offset + shift);
   52|      0|            return result;
   53|  3.30k|        }
   54|       |
   55|  3.30k|    } else if (og.isIndirect()) {
  ------------------
  |  Branch (55:16): [True: 0, False: 0]
  ------------------
   56|      0|        return "object " + og.unparse(' ');
   57|      0|    }
   58|      0|    return {};
   59|  3.30k|}

_ZN16QPDFObjectHandle18StreamDataProviderC2Eb:
   46|  14.5k|    supports_retry(supports_retry)
   47|  14.5k|{
   48|  14.5k|}
_ZN16QPDFObjectHandle18StreamDataProviderD2Ev:
   51|  14.5k|{
   52|       |    // Must be explicit and not inline -- see QPDF_DLL_CLASS in README-maintainer
   53|  14.5k|}
_ZN4qpdf10BaseHandle10disconnectEb:
  683|  1.82M|{
  684|       |    // QPDF::~QPDF() calls disconnect for indirect objects, so we don't do that here.
  685|  1.82M|    if (only_direct && indirect()) {
  ------------------
  |  Branch (685:9): [True: 1.81M, False: 12.8k]
  |  Branch (685:24): [True: 679k, False: 1.13M]
  ------------------
  686|   679k|        return;
  687|   679k|    }
  688|       |
  689|  1.14M|    switch (raw_type_code()) {
  690|  9.48k|    case ::ot_array:
  ------------------
  |  Branch (690:5): [True: 9.48k, False: 1.13M]
  ------------------
  691|  9.48k|        {
  692|  9.48k|            auto& a = std::get<QPDF_Array>(obj->value);
  693|  9.48k|            if (a.sp) {
  ------------------
  |  Branch (693:17): [True: 0, False: 9.48k]
  ------------------
  694|      0|                for (auto& item: a.sp->elements) {
  ------------------
  |  Branch (694:32): [True: 0, False: 0]
  ------------------
  695|      0|                    item.second.disconnect();
  696|      0|                }
  697|  9.48k|            } else {
  698|  1.77M|                for (auto& oh: a.elements) {
  ------------------
  |  Branch (698:30): [True: 1.77M, False: 9.48k]
  ------------------
  699|  1.77M|                    oh.disconnect();
  700|  1.77M|                }
  701|  9.48k|            }
  702|  9.48k|        }
  703|  9.48k|        break;
  704|  8.04k|    case ::ot_dictionary:
  ------------------
  |  Branch (704:5): [True: 8.04k, False: 1.14M]
  ------------------
  705|  34.3k|        for (auto& iter: std::get<QPDF_Dictionary>(obj->value).items) {
  ------------------
  |  Branch (705:24): [True: 34.3k, False: 8.04k]
  ------------------
  706|  34.3k|            iter.second.disconnect();
  707|  34.3k|        }
  708|  8.04k|        break;
  709|  2.59k|    case ::ot_stream:
  ------------------
  |  Branch (709:5): [True: 2.59k, False: 1.14M]
  ------------------
  710|  2.59k|        {
  711|  2.59k|            auto& s = std::get<QPDF_Stream>(obj->value);
  712|  2.59k|            s.m->stream_provider = nullptr;
  713|  2.59k|            s.m->stream_dict.disconnect();
  714|  2.59k|        }
  715|  2.59k|        break;
  716|      0|    case ::ot_uninitialized:
  ------------------
  |  Branch (716:5): [True: 0, False: 1.14M]
  ------------------
  717|      0|        return;
  718|  1.12M|    default:
  ------------------
  |  Branch (718:5): [True: 1.12M, False: 20.1k]
  ------------------
  719|  1.12M|        break;
  720|  1.14M|    }
  721|  1.14M|    obj->qpdf = nullptr;
  722|  1.14M|    obj->og = QPDFObjGen();
  723|  1.14M|}
_ZNK16QPDFObjectHandle9isIntegerEv:
  794|  7.72k|{
  795|  7.72k|    return type_code() == ::ot_integer;
  796|  7.72k|}
_ZNK16QPDFObjectHandle12isDictionaryEv:
  866|   127k|{
  867|   127k|    return type_code() == ::ot_dictionary;
  868|   127k|}
_ZNK16QPDFObjectHandle8isStreamEv:
  872|   126k|{
  873|   126k|    return type_code() == ::ot_stream;
  874|   126k|}
_ZN16QPDFObjectHandle10newIntegerEx:
  944|  1.12M|{
  945|  1.12M|    return {QPDFObject::create<QPDF_Integer>(value)};
  946|  1.12M|}
_ZNK4qpdf7Integer5valueEv:
  950|  7.72k|{
  951|  7.72k|    auto* i = as<QPDF_Integer>();
  952|  7.72k|    if (!i) {
  ------------------
  |  Branch (952:9): [True: 0, False: 7.72k]
  ------------------
  953|      0|        throw invalid_error("Integer");
  954|      0|    }
  955|  7.72k|    return i->val;
  956|  7.72k|}
_ZNK16QPDFObjectHandle16getIntValueAsIntEv:
  981|  7.72k|{
  982|  7.72k|    try {
  983|  7.72k|        return Integer(*this).value<int>();
  984|  7.72k|    } catch (std::invalid_argument&) {
  985|      0|        typeWarning("integer", "returning 0");
  986|      0|        return 0;
  987|      0|    }
  988|  7.72k|}
_ZN16QPDFObjectHandle7newNameERKNSt3__112basic_stringIcNS0_11char_traitsIcEENS0_9allocatorIcEEEE:
 1068|  10.8k|{
 1069|  10.8k|    return {QPDFObject::create<QPDF_Name>(name)};
 1070|  10.8k|}
_ZNK16QPDFObjectHandle7getNameEv:
 1094|  4.44k|{
 1095|  4.44k|    if (auto* name = as<QPDF_Name>()) {
  ------------------
  |  Branch (1095:15): [True: 4.44k, False: 0]
  ------------------
 1096|  4.44k|        return name->name;
 1097|  4.44k|    }
 1098|      0|    typeWarning("name", "returning dummy name");
 1099|      0|    return "/QPDFFakeName";
 1100|  4.44k|}
_ZN16QPDFObjectHandle9newStringERKNSt3__112basic_stringIcNS0_11char_traitsIcEENS0_9allocatorIcEEEE:
 1116|  1.17k|{
 1117|  1.17k|    return {QPDFObject::create<QPDF_String>(str)};
 1118|  1.17k|}
_ZN16QPDFObjectHandle16newUnicodeStringERKNSt3__112basic_stringIcNS0_11char_traitsIcEENS0_9allocatorIcEEEE:
 1122|  5.84k|{
 1123|  5.84k|    return {String::utf16(utf8_str).obj_sp()};
 1124|  5.84k|}
_ZN4qpdf6StringC2ERKNSt3__112basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEE:
 1127|  1.33k|    BaseHandle(QPDFObject::create<QPDF_String>(str))
 1128|  1.33k|{
 1129|  1.33k|}
_ZN4qpdf6StringC2EONSt3__112basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEE:
 1132|  4.51k|    BaseHandle(QPDFObject::create<QPDF_String>(std::move(str)))
 1133|  4.51k|{
 1134|  4.51k|}
_ZN4qpdf6String5utf16ERKNSt3__112basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEE:
 1138|  5.84k|{
 1139|  5.84k|    std::string result;
 1140|  5.84k|    if (QUtil::utf8_to_pdf_doc(utf8_str, result, '?')) {
  ------------------
  |  Branch (1140:9): [True: 1.33k, False: 4.51k]
  ------------------
 1141|  1.33k|        return String(result);
 1142|  1.33k|    }
 1143|  4.51k|    return String(QUtil::utf8_to_utf16(utf8_str));
 1144|  5.84k|}
_ZN16QPDFObjectHandle5parseERKNSt3__112basic_stringIcNS0_11char_traitsIcEENS0_9allocatorIcEEEES8_:
 1653|  11.1k|{
 1654|  11.1k|    return parse(nullptr, object_str, object_description);
 1655|  11.1k|}
_ZN16QPDFObjectHandle5parseEP4QPDFRKNSt3__112basic_stringIcNS2_11char_traitsIcEENS2_9allocatorIcEEEESA_:
 1660|  11.1k|{
 1661|  11.1k|    auto input = is::OffsetBuffer("parsed object", object_str);
 1662|  11.1k|    auto result = Parser::parse(input, object_description, context);
 1663|  11.1k|    size_t offset = QIntC::to_size(input.tell());
 1664|  1.03M|    while (offset < object_str.length()) {
  ------------------
  |  Branch (1664:12): [True: 1.02M, False: 11.1k]
  ------------------
 1665|  1.02M|        if (!isspace(object_str.at(offset))) {
  ------------------
  |  Branch (1665:13): [True: 61, False: 1.02M]
  ------------------
 1666|     61|            QTC::TC("qpdf", "QPDFObjectHandle trailing data in parse");
 1667|     61|            throw QPDFExc(
 1668|     61|                qpdf_e_damaged_pdf,
 1669|     61|                "parsed object",
 1670|     61|                object_description,
 1671|     61|                input.getLastOffset(),
 1672|     61|                "trailing data found parsing object from string");
 1673|     61|        }
 1674|  1.02M|        ++offset;
 1675|  1.02M|    }
 1676|  11.1k|    return result;
 1677|  11.1k|}
_ZN16QPDFObjectHandle7newBoolEb:
 1880|  5.58k|{
 1881|  5.58k|    return {QPDFObject::create<QPDF_Bool>(value)};
 1882|  5.58k|}
_ZN16QPDFObjectHandle7newNullEv:
 1886|  25.5k|{
 1887|  25.5k|    return {QPDFObject::create<QPDF_Null>()};
 1888|  25.5k|}
_ZN16QPDFObjectHandle7newRealERKNSt3__112basic_stringIcNS0_11char_traitsIcEENS0_9allocatorIcEEEE:
 1892|  8.60k|{
 1893|  8.60k|    return {QPDFObject::create<QPDF_Real>(value)};
 1894|  8.60k|}
_ZN16QPDFObjectHandle8newArrayEv:
 1916|  11.8k|{
 1917|  11.8k|    return newArray(std::vector<QPDFObjectHandle>());
 1918|  11.8k|}
_ZN16QPDFObjectHandle8newArrayERKNSt3__16vectorIS_NS0_9allocatorIS_EEEE:
 1922|  11.8k|{
 1923|  11.8k|    return {QPDFObject::create<QPDF_Array>(items)};
 1924|  11.8k|}
_ZN16QPDFObjectHandle13newDictionaryEv:
 1976|  23.6k|{
 1977|  23.6k|    return newDictionary(std::map<std::string, QPDFObjectHandle>());
 1978|  23.6k|}
_ZN16QPDFObjectHandle13newDictionaryERKNSt3__13mapINS0_12basic_stringIcNS0_11char_traitsIcEENS0_9allocatorIcEEEES_NS0_4lessIS7_EENS5_INS0_4pairIKS7_S_EEEEEE:
 1982|  23.6k|{
 1983|  23.6k|    return {QPDFObject::create<QPDF_Dictionary>(items)};
 1984|  23.6k|}
_ZN16QPDFObjectHandle20setObjectDescriptionEP4QPDFRKNSt3__112basic_stringIcNS2_11char_traitsIcEENS2_9allocatorIcEEEE:
 2033|  3.30k|{
 2034|  3.30k|    if (obj) {
  ------------------
  |  Branch (2034:9): [True: 3.30k, False: 0]
  ------------------
 2035|  3.30k|        auto descr = std::make_shared<QPDFObject::Description>(object_description);
 2036|  3.30k|        obj->setDescription(owning_qpdf, descr);
 2037|  3.30k|    }
 2038|  3.30k|}
_ZNK16QPDFObjectHandle20hasObjectDescriptionEv:
 2042|  1.96M|{
 2043|  1.96M|    return obj && obj->hasDescription();
  ------------------
  |  Branch (2043:12): [True: 1.96M, False: 0]
  |  Branch (2043:19): [True: 749k, False: 1.21M]
  ------------------
 2044|  1.96M|}
_ZNK16QPDFObjectHandle9getObjGenEv:
 2513|  64.1k|{
 2514|  64.1k|    return obj ? obj->getObjGen() : QPDFObjGen();
  ------------------
  |  Branch (2514:12): [True: 64.1k, False: 0]
  ------------------
 2515|  64.1k|}
_ZNK16QPDFObjectHandle11getObjectIDEv:
 2519|  35.3k|{
 2520|  35.3k|    return getObjGen().getObj();
 2521|  35.3k|}
_ZNK16QPDFObjectHandle10isIndirectEv:
 2531|  35.3k|{
 2532|  35.3k|    return getObjectID() != 0;
 2533|  35.3k|}
_ZNK16QPDFObjectHandle13getOwningQPDFEv:
 2538|   200k|{
 2539|   200k|    return obj ? obj->getQPDF() : nullptr;
  ------------------
  |  Branch (2539:12): [True: 200k, False: 0]
  ------------------
 2540|   200k|}

_ZN4qpdf4impl6Parser5parseER11InputSourceRKNSt3__112basic_stringIcNS4_11char_traitsIcEENS4_9allocatorIcEEEEP4QPDF:
   53|  11.1k|{
   54|  11.1k|    qpdf::Tokenizer tokenizer;
   55|  11.1k|    if (auto result = Parser(
  ------------------
  |  Branch (55:14): [True: 10.8k, False: 340]
  ------------------
   56|  11.1k|                          input,
   57|  11.1k|                          make_description(input.getName(), object_description),
   58|  11.1k|                          object_description,
   59|  11.1k|                          tokenizer,
   60|  11.1k|                          nullptr,
   61|  11.1k|                          context,
   62|  11.1k|                          false)
   63|  11.1k|                          .parse()) {
   64|  10.8k|        return result;
   65|  10.8k|    }
   66|    340|    return {QPDFObject::create<QPDF_Null>()};
   67|  11.1k|}
_ZN4qpdf4impl6Parser5parseER11InputSourceRKNSt3__112basic_stringIcNS4_11char_traitsIcEENS4_9allocatorIcEEEERNS_9TokenizerEPN16QPDFObjectHandle15StringDecrypterER4QPDFb:
  129|  7.72k|{
  130|  7.72k|    return Parser(
  131|  7.72k|               input,
  132|  7.72k|               make_description(input.getName(), object_description),
  133|  7.72k|               object_description,
  134|  7.72k|               tokenizer,
  135|  7.72k|               decrypter,
  136|  7.72k|               &context,
  137|  7.72k|               true,
  138|  7.72k|               0,
  139|  7.72k|               0,
  140|  7.72k|               sanity_checks)
  141|  7.72k|        .parse();
  142|  7.72k|}
_ZN4qpdf4impl6Parser5parseEb:
  164|  18.8k|{
  165|  18.8k|    try {
  166|  18.8k|        return parse_first(content_stream);
  167|  18.8k|    } catch (Error&) {
  168|      0|        return {};
  169|    340|    } catch (QPDFExc& e) {
  170|    340|        throw e;
  171|    340|    } catch (std::logic_error& e) {
  172|      0|        throw e;
  173|      0|    } catch (std::exception& e) {
  174|      0|        warn("treating object as null because of error during parsing: "s + e.what());
  175|      0|        return {};
  176|      0|    }
  177|  18.8k|}
_ZN4qpdf4impl6Parser11parse_firstEb:
  181|  18.8k|{
  182|       |    // This method must take care not to resolve any objects. Don't check the type of any object
  183|       |    // without first ensuring that it is a direct object. Otherwise, doing so may have the side
  184|       |    // effect of reading the object and changing the file pointer. If you do this, it will cause a
  185|       |    // logic error to be thrown from QPDF::inParse().
  186|       |
  187|  18.8k|    QPDF::Doc::ParseGuard pg(context_);
  188|  18.8k|    start_ = input_.tell();
  189|  18.8k|    if (!tokenizer_.nextToken(input_, object_description_)) {
  ------------------
  |  Branch (189:9): [True: 340, False: 18.5k]
  ------------------
  190|    340|        warn(tokenizer_.getErrorMessage());
  191|    340|    }
  192|       |
  193|  18.8k|    switch (tokenizer_.getType()) {
  194|      0|    case QPDFTokenizer::tt_eof:
  ------------------
  |  Branch (194:5): [True: 0, False: 18.8k]
  ------------------
  195|      0|        if (content_stream) {
  ------------------
  |  Branch (195:13): [True: 0, False: 0]
  ------------------
  196|       |            // In content stream mode, leave object uninitialized to indicate EOF
  197|      0|            empty_ = true;
  198|      0|            return {};
  199|      0|        }
  200|      0|        warn("unexpected EOF");
  201|      0|        return {};
  202|       |
  203|      0|    case QPDFTokenizer::tt_bad:
  ------------------
  |  Branch (203:5): [True: 0, False: 18.8k]
  ------------------
  204|      0|        return {};
  205|       |
  206|      0|    case QPDFTokenizer::tt_brace_open:
  ------------------
  |  Branch (206:5): [True: 0, False: 18.8k]
  ------------------
  207|      0|    case QPDFTokenizer::tt_brace_close:
  ------------------
  |  Branch (207:5): [True: 0, False: 18.8k]
  ------------------
  208|      0|        warn("treating unexpected brace token as null");
  209|      0|        return {};
  210|       |
  211|      0|    case QPDFTokenizer::tt_array_close:
  ------------------
  |  Branch (211:5): [True: 0, False: 18.8k]
  ------------------
  212|      0|        warn("treating unexpected array close token as null");
  213|      0|        return {};
  214|       |
  215|      0|    case QPDFTokenizer::tt_dict_close:
  ------------------
  |  Branch (215:5): [True: 0, False: 18.8k]
  ------------------
  216|      0|        warn("unexpected dictionary close token");
  217|      0|        return {};
  218|       |
  219|      0|    case QPDFTokenizer::tt_array_open:
  ------------------
  |  Branch (219:5): [True: 0, False: 18.8k]
  ------------------
  220|  7.72k|    case QPDFTokenizer::tt_dict_open:
  ------------------
  |  Branch (220:5): [True: 7.72k, False: 11.1k]
  ------------------
  221|  7.72k|        stack_.clear();
  222|  7.72k|        stack_.emplace_back(
  223|  7.72k|            input_,
  224|  7.72k|            (tokenizer_.getType() == QPDFTokenizer::tt_array_open) ? st_array : st_dictionary_key);
  ------------------
  |  Branch (224:13): [True: 0, False: 7.72k]
  ------------------
  225|  7.72k|        frame_ = &stack_.back();
  226|  7.72k|        return parse_remainder(content_stream);
  227|       |
  228|      0|    case QPDFTokenizer::tt_bool:
  ------------------
  |  Branch (228:5): [True: 0, False: 18.8k]
  ------------------
  229|      0|        return with_description<QPDF_Bool>(tokenizer_.getValue() == "true");
  230|       |
  231|      0|    case QPDFTokenizer::tt_null:
  ------------------
  |  Branch (231:5): [True: 0, False: 18.8k]
  ------------------
  232|      0|        return {QPDFObject::create<QPDF_Null>()};
  233|       |
  234|      0|    case QPDFTokenizer::tt_integer:
  ------------------
  |  Branch (234:5): [True: 0, False: 18.8k]
  ------------------
  235|      0|        return with_description<QPDF_Integer>(QUtil::string_to_ll(tokenizer_.getValue().c_str()));
  236|       |
  237|      0|    case QPDFTokenizer::tt_real:
  ------------------
  |  Branch (237:5): [True: 0, False: 18.8k]
  ------------------
  238|      0|        return with_description<QPDF_Real>(tokenizer_.getValue());
  239|       |
  240|  10.8k|    case QPDFTokenizer::tt_name:
  ------------------
  |  Branch (240:5): [True: 10.8k, False: 8.06k]
  ------------------
  241|  10.8k|        return with_description<QPDF_Name>(tokenizer_.getValue());
  242|       |
  243|      0|    case QPDFTokenizer::tt_word:
  ------------------
  |  Branch (243:5): [True: 0, False: 18.8k]
  ------------------
  244|      0|        {
  245|      0|            auto const& value = tokenizer_.getValue();
  246|      0|            if (content_stream) {
  ------------------
  |  Branch (246:17): [True: 0, False: 0]
  ------------------
  247|      0|                return with_description<QPDF_Operator>(value);
  248|      0|            } else if (value == "endobj") {
  ------------------
  |  Branch (248:24): [True: 0, False: 0]
  ------------------
  249|       |                // We just saw endobj without having read anything. Nothing in the PDF spec appears
  250|       |                // to allow empty objects, but they have been encountered in actual PDF files and
  251|       |                // Adobe Reader appears to ignore them. Treat this as a null and do not move the
  252|       |                // input source's offset.
  253|      0|                empty_ = true;
  254|      0|                input_.seek(input_.getLastOffset(), SEEK_SET);
  255|      0|                if (!content_stream) {
  ------------------
  |  Branch (255:21): [True: 0, False: 0]
  ------------------
  256|      0|                    warn("empty object treated as null");
  257|      0|                }
  258|      0|                return {};
  259|      0|            } else {
  260|      0|                warn("unknown token while reading object; treating as string");
  261|      0|                return with_description<QPDF_String>(value);
  262|      0|            }
  263|      0|        }
  264|       |
  265|      0|    case QPDFTokenizer::tt_string:
  ------------------
  |  Branch (265:5): [True: 0, False: 18.8k]
  ------------------
  266|      0|        if (decrypter_) {
  ------------------
  |  Branch (266:13): [True: 0, False: 0]
  ------------------
  267|      0|            std::string s{tokenizer_.getValue()};
  268|      0|            decrypter_->decryptString(s);
  269|      0|            return with_description<QPDF_String>(s);
  270|      0|        } else {
  271|      0|            return with_description<QPDF_String>(tokenizer_.getValue());
  272|      0|        }
  273|       |
  274|      0|    default:
  ------------------
  |  Branch (274:5): [True: 0, False: 18.8k]
  ------------------
  275|      0|        warn("treating unknown token type as null while reading object");
  276|      0|        return {};
  277|  18.8k|    }
  278|  18.8k|}
_ZN4qpdf4impl6Parser15parse_remainderEb:
  282|  7.72k|{
  283|       |    // This method must take care not to resolve any objects. Don't check the type of any object
  284|       |    // without first ensuring that it is a direct object. Otherwise, doing so may have the side
  285|       |    // effect of reading the object and changing the file pointer. If you do this, it will cause a
  286|       |    // logic error to be thrown from QPDF::inParse().
  287|       |
  288|  7.72k|    bad_count_ = 0;
  289|  7.72k|    bool b_contents = false;
  290|       |
  291|  23.1k|    while (true) {
  ------------------
  |  Branch (291:12): [True: 23.1k, Folded]
  ------------------
  292|  23.1k|        if (!tokenizer_.nextToken(input_, object_description_)) {
  ------------------
  |  Branch (292:13): [True: 0, False: 23.1k]
  ------------------
  293|      0|            warn(tokenizer_.getErrorMessage());
  294|      0|        }
  295|  23.1k|        ++good_count_; // optimistically
  296|       |
  297|  23.1k|        if (int_count_ != 0) {
  ------------------
  |  Branch (297:13): [True: 7.72k, False: 15.4k]
  ------------------
  298|       |            // Special handling of indirect references. Treat integer tokens as part of an indirect
  299|       |            // reference until proven otherwise.
  300|  7.72k|            if (tokenizer_.getType() == QPDFTokenizer::tt_integer) {
  ------------------
  |  Branch (300:17): [True: 0, False: 7.72k]
  ------------------
  301|      0|                if (++int_count_ > 2) {
  ------------------
  |  Branch (301:21): [True: 0, False: 0]
  ------------------
  302|       |                    // Process the oldest buffered integer.
  303|      0|                    add_int(int_count_);
  304|      0|                }
  305|      0|                last_offset_buffer_[int_count_ % 2] = input_.getLastOffset();
  306|      0|                int_buffer_[int_count_ % 2] = QUtil::string_to_ll(tokenizer_.getValue().c_str());
  307|      0|                continue;
  308|       |
  309|  7.72k|            } else if (
  310|  7.72k|                int_count_ >= 2 && tokenizer_.getType() == QPDFTokenizer::tt_word &&
  ------------------
  |  Branch (310:17): [True: 0, False: 7.72k]
  |  Branch (310:36): [True: 0, False: 0]
  ------------------
  311|      0|                tokenizer_.getValue() == "R") {
  ------------------
  |  Branch (311:17): [True: 0, False: 0]
  ------------------
  312|      0|                if (!context_) {
  ------------------
  |  Branch (312:21): [True: 0, False: 0]
  ------------------
  313|      0|                    throw std::logic_error(
  314|      0|                        "Parser::parse called without context on an object with indirect "
  315|      0|                        "references");
  316|      0|                }
  317|      0|                auto id = QIntC::to_int(int_buffer_[(int_count_ - 1) % 2]);
  318|      0|                auto gen = QIntC::to_int(int_buffer_[(int_count_) % 2]);
  319|      0|                if (!(id < 1 || gen < 0 || gen >= 65535)) {
  ------------------
  |  Branch (319:23): [True: 0, False: 0]
  |  Branch (319:33): [True: 0, False: 0]
  |  Branch (319:44): [True: 0, False: 0]
  ------------------
  320|      0|                    add(ParseGuard::getObject(context_, id, gen, parse_pdf_));
  321|      0|                } else {
  322|      0|                    add_bad_null(
  323|      0|                        "treating bad indirect reference (" + std::to_string(id) + " " +
  324|      0|                        std::to_string(gen) + " R) as null");
  325|      0|                }
  326|      0|                int_count_ = 0;
  327|      0|                continue;
  328|       |
  329|  7.72k|            } else if (int_count_ > 0) {
  ------------------
  |  Branch (329:24): [True: 7.72k, False: 0]
  ------------------
  330|       |                // Process the buffered integers before processing the current token.
  331|  7.72k|                if (int_count_ > 1) {
  ------------------
  |  Branch (331:21): [True: 0, False: 7.72k]
  ------------------
  332|      0|                    add_int(int_count_ - 1);
  333|      0|                }
  334|  7.72k|                add_int(int_count_);
  335|  7.72k|                int_count_ = 0;
  336|  7.72k|            }
  337|  7.72k|        }
  338|       |
  339|  23.1k|        switch (tokenizer_.getType()) {
  340|      0|        case QPDFTokenizer::tt_eof:
  ------------------
  |  Branch (340:9): [True: 0, False: 23.1k]
  ------------------
  341|      0|            warn("parse error while reading object");
  342|      0|            if (content_stream) {
  ------------------
  |  Branch (342:17): [True: 0, False: 0]
  ------------------
  343|       |                // In content stream mode, leave object uninitialized to indicate EOF
  344|      0|                return {};
  345|      0|            }
  346|      0|            warn("unexpected EOF");
  347|      0|            return {};
  348|       |
  349|      0|        case QPDFTokenizer::tt_bad:
  ------------------
  |  Branch (349:9): [True: 0, False: 23.1k]
  ------------------
  350|      0|            check_too_many_bad_tokens();
  351|      0|            add_null();
  352|      0|            continue;
  353|       |
  354|      0|        case QPDFTokenizer::tt_brace_open:
  ------------------
  |  Branch (354:9): [True: 0, False: 23.1k]
  ------------------
  355|      0|        case QPDFTokenizer::tt_brace_close:
  ------------------
  |  Branch (355:9): [True: 0, False: 23.1k]
  ------------------
  356|      0|            add_bad_null("treating unexpected brace token as null");
  357|      0|            continue;
  358|       |
  359|      0|        case QPDFTokenizer::tt_array_close:
  ------------------
  |  Branch (359:9): [True: 0, False: 23.1k]
  ------------------
  360|      0|            if (frame_->state == st_array) {
  ------------------
  |  Branch (360:17): [True: 0, False: 0]
  ------------------
  361|      0|                auto object = frame_->null_count > 100
  ------------------
  |  Branch (361:31): [True: 0, False: 0]
  ------------------
  362|      0|                    ? QPDFObject::create<QPDF_Array>(std::move(frame_->olist), true)
  363|      0|                    : QPDFObject::create<QPDF_Array>(std::move(frame_->olist));
  364|      0|                set_description(object, frame_->offset - 1);
  365|       |                // The `offset` points to the next of "[".  Set the rewind offset to point to the
  366|       |                // beginning of "[". This has been explicitly tested with whitespace surrounding the
  367|       |                // array start delimiter. getLastOffset points to the array end token and therefore
  368|       |                // can't be used here.
  369|      0|                if (stack_.size() <= 1) {
  ------------------
  |  Branch (369:21): [True: 0, False: 0]
  ------------------
  370|      0|                    return object;
  371|      0|                }
  372|      0|                stack_.pop_back();
  373|      0|                frame_ = &stack_.back();
  374|      0|                add(std::move(object));
  375|      0|            } else {
  376|      0|                if (sanity_checks_) {
  ------------------
  |  Branch (376:21): [True: 0, False: 0]
  ------------------
  377|       |                    // During sanity checks, assume nesting of containers is corrupt and object is
  378|       |                    // unusable.
  379|      0|                    warn("unexpected array close token; giving up on reading object");
  380|      0|                    return {};
  381|      0|                }
  382|      0|                add_bad_null("treating unexpected array close token as null");
  383|      0|            }
  384|      0|            continue;
  385|       |
  386|  7.72k|        case QPDFTokenizer::tt_dict_close:
  ------------------
  |  Branch (386:9): [True: 7.72k, False: 15.4k]
  ------------------
  387|  7.72k|            if (frame_->state <= st_dictionary_value) {
  ------------------
  |  Branch (387:17): [True: 7.72k, False: 0]
  ------------------
  388|       |                // Attempt to recover more or less gracefully from invalid dictionaries.
  389|  7.72k|                auto& dict = frame_->dict;
  390|       |
  391|  7.72k|                if (frame_->state == st_dictionary_value) {
  ------------------
  |  Branch (391:21): [True: 0, False: 7.72k]
  ------------------
  392|      0|                    warn(
  393|      0|                        frame_->offset,
  394|      0|                        "dictionary ended prematurely; using null as value for last key");
  395|      0|                    dict[frame_->key] = QPDFObject::create<QPDF_Null>();
  396|      0|                }
  397|  7.72k|                if (!frame_->olist.empty()) {
  ------------------
  |  Branch (397:21): [True: 0, False: 7.72k]
  ------------------
  398|      0|                    if (sanity_checks_) {
  ------------------
  |  Branch (398:25): [True: 0, False: 0]
  ------------------
  399|      0|                        warn(
  400|      0|                            frame_->offset,
  401|      0|                            "expected dictionary keys but found non-name objects; ignoring");
  402|      0|                    } else {
  403|      0|                        fix_missing_keys();
  404|      0|                    }
  405|      0|                }
  406|       |
  407|  7.72k|                if (!frame_->contents_string.empty() && dict.contains("/Type") &&
  ------------------
  |  Branch (407:21): [True: 0, False: 7.72k]
  |  Branch (407:21): [True: 0, False: 7.72k]
  |  Branch (407:57): [True: 0, False: 0]
  ------------------
  408|      0|                    dict["/Type"].isNameAndEquals("/Sig") && dict.contains("/ByteRange") &&
  ------------------
  |  Branch (408:21): [True: 0, False: 0]
  |  Branch (408:62): [True: 0, False: 0]
  ------------------
  409|      0|                    dict.contains("/Contents") && dict["/Contents"].isString()) {
  ------------------
  |  Branch (409:21): [True: 0, False: 0]
  |  Branch (409:51): [True: 0, False: 0]
  ------------------
  410|      0|                    dict["/Contents"] = QPDFObjectHandle::newString(frame_->contents_string);
  411|      0|                    dict["/Contents"].setParsedOffset(frame_->contents_offset);
  412|      0|                }
  413|  7.72k|                auto object = QPDFObject::create<QPDF_Dictionary>(std::move(dict));
  414|  7.72k|                set_description(object, frame_->offset - 2);
  415|       |                // The `offset` points to the next of "<<". Set the rewind offset to point to the
  416|       |                // beginning of "<<". This has been explicitly tested with whitespace surrounding
  417|       |                // the dictionary start delimiter. getLastOffset points to the dictionary end token
  418|       |                // and therefore can't be used here.
  419|  7.72k|                if (stack_.size() <= 1) {
  ------------------
  |  Branch (419:21): [True: 7.72k, False: 0]
  ------------------
  420|  7.72k|                    return object;
  421|  7.72k|                }
  422|      0|                stack_.pop_back();
  423|      0|                frame_ = &stack_.back();
  424|      0|                add(std::move(object));
  425|      0|            } else {
  426|      0|                if (sanity_checks_) {
  ------------------
  |  Branch (426:21): [True: 0, False: 0]
  ------------------
  427|       |                    // During sanity checks, assume nesting of containers is corrupt and object is
  428|       |                    // unusable.
  429|      0|                    warn("unexpected dictionary close token; giving up on reading object");
  430|      0|                    return {};
  431|      0|                }
  432|      0|                add_bad_null("unexpected dictionary close token");
  433|      0|            }
  434|      0|            continue;
  435|       |
  436|      0|        case QPDFTokenizer::tt_array_open:
  ------------------
  |  Branch (436:9): [True: 0, False: 23.1k]
  ------------------
  437|      0|        case QPDFTokenizer::tt_dict_open:
  ------------------
  |  Branch (437:9): [True: 0, False: 23.1k]
  ------------------
  438|      0|            if (stack_.size() > max_nesting) {
  ------------------
  |  Branch (438:17): [True: 0, False: 0]
  ------------------
  439|      0|                limits_error(
  440|      0|                    "parser-max-nesting", "ignoring excessively deeply nested data structure");
  441|      0|            }
  442|      0|            b_contents = false;
  443|      0|            stack_.emplace_back(
  444|      0|                input_,
  445|      0|                (tokenizer_.getType() == QPDFTokenizer::tt_array_open) ? st_array
  ------------------
  |  Branch (445:17): [True: 0, False: 0]
  ------------------
  446|      0|                                                                       : st_dictionary_key);
  447|      0|            frame_ = &stack_.back();
  448|      0|            continue;
  449|       |
  450|      0|        case QPDFTokenizer::tt_bool:
  ------------------
  |  Branch (450:9): [True: 0, False: 23.1k]
  ------------------
  451|      0|            add_scalar<QPDF_Bool>(tokenizer_.getValue() == "true");
  452|      0|            continue;
  453|       |
  454|      0|        case QPDFTokenizer::tt_null:
  ------------------
  |  Branch (454:9): [True: 0, False: 23.1k]
  ------------------
  455|      0|            add_null();
  456|      0|            continue;
  457|       |
  458|  7.72k|        case QPDFTokenizer::tt_integer:
  ------------------
  |  Branch (458:9): [True: 7.72k, False: 15.4k]
  ------------------
  459|  7.72k|            if (!content_stream) {
  ------------------
  |  Branch (459:17): [True: 7.72k, False: 0]
  ------------------
  460|       |                // Buffer token in case it is part of an indirect reference.
  461|  7.72k|                last_offset_buffer_[1] = input_.getLastOffset();
  462|  7.72k|                int_buffer_[1] = QUtil::string_to_ll(tokenizer_.getValue().c_str());
  463|  7.72k|                int_count_ = 1;
  464|  7.72k|            } else {
  465|      0|                add_scalar<QPDF_Integer>(QUtil::string_to_ll(tokenizer_.getValue().c_str()));
  466|      0|            }
  467|  7.72k|            continue;
  468|       |
  469|      0|        case QPDFTokenizer::tt_real:
  ------------------
  |  Branch (469:9): [True: 0, False: 23.1k]
  ------------------
  470|      0|            add_scalar<QPDF_Real>(tokenizer_.getValue());
  471|      0|            continue;
  472|       |
  473|  7.72k|        case QPDFTokenizer::tt_name:
  ------------------
  |  Branch (473:9): [True: 7.72k, False: 15.4k]
  ------------------
  474|  7.72k|            if (frame_->state == st_dictionary_key) {
  ------------------
  |  Branch (474:17): [True: 7.72k, False: 0]
  ------------------
  475|  7.72k|                frame_->key = tokenizer_.getValue();
  476|  7.72k|                frame_->state = st_dictionary_value;
  477|  7.72k|                b_contents = decrypter_ && frame_->key == "/Contents";
  ------------------
  |  Branch (477:30): [True: 0, False: 7.72k]
  |  Branch (477:44): [True: 0, False: 0]
  ------------------
  478|  7.72k|                continue;
  479|  7.72k|            } else {
  480|      0|                add_scalar<QPDF_Name>(tokenizer_.getValue());
  481|      0|            }
  482|      0|            continue;
  483|       |
  484|      0|        case QPDFTokenizer::tt_word:
  ------------------
  |  Branch (484:9): [True: 0, False: 23.1k]
  ------------------
  485|      0|            if (content_stream) {
  ------------------
  |  Branch (485:17): [True: 0, False: 0]
  ------------------
  486|      0|                add_scalar<QPDF_Operator>(tokenizer_.getValue());
  487|      0|                continue;
  488|      0|            }
  489|       |
  490|      0|            if (sanity_checks_) {
  ------------------
  |  Branch (490:17): [True: 0, False: 0]
  ------------------
  491|      0|                if (tokenizer_.getValue() == "endobj" || tokenizer_.getValue() == "endstream") {
  ------------------
  |  Branch (491:21): [True: 0, False: 0]
  |  Branch (491:58): [True: 0, False: 0]
  ------------------
  492|       |                    // During sanity checks, assume an unexpected endobj or endstream indicates that
  493|       |                    // we are parsing past the end of the object.
  494|      0|                    warn(
  495|      0|                        "unexpected 'endobj' or 'endstream' while reading object; giving up on "
  496|      0|                        "reading object");
  497|      0|                    return {};
  498|      0|                }
  499|       |
  500|      0|                add_bad_null("unknown token while reading object; treating as null");
  501|      0|                continue;
  502|      0|            }
  503|       |
  504|      0|            warn("unknown token while reading object; treating as string");
  505|      0|            check_too_many_bad_tokens();
  506|      0|            add_scalar<QPDF_String>(tokenizer_.getValue());
  507|       |
  508|      0|            continue;
  509|       |
  510|      0|        case QPDFTokenizer::tt_string:
  ------------------
  |  Branch (510:9): [True: 0, False: 23.1k]
  ------------------
  511|      0|            {
  512|      0|                auto const& val = tokenizer_.getValue();
  513|      0|                if (decrypter_) {
  ------------------
  |  Branch (513:21): [True: 0, False: 0]
  ------------------
  514|      0|                    if (b_contents) {
  ------------------
  |  Branch (514:25): [True: 0, False: 0]
  ------------------
  515|      0|                        frame_->contents_string = val;
  516|      0|                        frame_->contents_offset = input_.getLastOffset();
  517|      0|                        b_contents = false;
  518|      0|                    }
  519|      0|                    std::string s{val};
  520|      0|                    decrypter_->decryptString(s);
  521|      0|                    add_scalar<QPDF_String>(s);
  522|      0|                } else {
  523|      0|                    add_scalar<QPDF_String>(val);
  524|      0|                }
  525|      0|            }
  526|      0|            continue;
  527|       |
  528|      0|        default:
  ------------------
  |  Branch (528:9): [True: 0, False: 23.1k]
  ------------------
  529|      0|            add_bad_null("treating unknown token type as null while reading object");
  530|  23.1k|        }
  531|  23.1k|    }
  532|  7.72k|}
_ZN4qpdf4impl6Parser3addEONSt3__110shared_ptrI10QPDFObjectEE:
  536|  7.72k|{
  537|  7.72k|    if (frame_->state != st_dictionary_value) {
  ------------------
  |  Branch (537:9): [True: 0, False: 7.72k]
  ------------------
  538|       |        // If state is st_dictionary_key then there is a missing key. Push onto olist for
  539|       |        // processing once the tt_dict_close token has been found.
  540|      0|        frame_->olist.emplace_back(std::move(obj));
  541|  7.72k|    } else {
  542|  7.72k|        if (auto res = frame_->dict.insert_or_assign(frame_->key, std::move(obj)); !res.second) {
  ------------------
  |  Branch (542:84): [True: 0, False: 7.72k]
  ------------------
  543|      0|            warn_duplicate_key();
  544|      0|        }
  545|  7.72k|        frame_->state = st_dictionary_key;
  546|  7.72k|    }
  547|  7.72k|}
_ZN4qpdf4impl6Parser7add_intEi:
  577|  7.72k|{
  578|  7.72k|    auto obj = QPDFObject::create<QPDF_Integer>(int_buffer_[count % 2]);
  579|  7.72k|    obj->setDescription(context_, description_, last_offset_buffer_[count % 2]);
  580|  7.72k|    add(std::move(obj));
  581|  7.72k|}
_ZN4qpdf4impl6Parser15set_descriptionERNSt3__110shared_ptrI10QPDFObjectEEx:
  610|  7.72k|{
  611|  7.72k|    if (obj) {
  ------------------
  |  Branch (611:9): [True: 7.72k, False: 0]
  ------------------
  612|  7.72k|        obj->setDescription(context_, description_, parsed_offset);
  613|  7.72k|    }
  614|  7.72k|}
_ZNK4qpdf4impl6Parser4warnERK7QPDFExc:
  687|    340|{
  688|       |    // If parsing on behalf of a QPDF object and want to give a warning, we can warn through the
  689|       |    // object. If parsing for some other reason, such as an explicit creation of an object from a
  690|       |    // string, then just throw the exception.
  691|    340|    if (context_) {
  ------------------
  |  Branch (691:9): [True: 0, False: 340]
  ------------------
  692|      0|        context_->warn(e);
  693|    340|    } else {
  694|    340|        throw e;
  695|    340|    }
  696|    340|}
_ZNK4qpdf4impl6Parser4warnExRKNSt3__112basic_stringIcNS2_11char_traitsIcEENS2_9allocatorIcEEEE:
  710|    340|{
  711|    340|    if (stream_id_) {
  ------------------
  |  Branch (711:9): [True: 0, False: 340]
  ------------------
  712|      0|        std::string descr = "object "s + std::to_string(obj_id_) + " 0";
  713|      0|        std::string name = context_->getFilename() + " object stream " + std::to_string(stream_id_);
  714|      0|        warn(QPDFExc(qpdf_e_damaged_pdf, name, descr, offset, msg));
  715|    340|    } else {
  716|    340|        warn(QPDFExc(qpdf_e_damaged_pdf, input_.getName(), object_description_, offset, msg));
  717|    340|    }
  718|    340|}
_ZNK4qpdf4impl6Parser4warnERKNSt3__112basic_stringIcNS2_11char_traitsIcEENS2_9allocatorIcEEEE:
  722|    340|{
  723|    340|    warn(input_.getLastOffset(), msg);
  724|    340|}
_ZN4QPDF3Doc10ParseGuardC2EPS_:
   26|  18.8k|        objects(qpdf ? &qpdf->m->objects : nullptr)
  ------------------
  |  Branch (26:17): [True: 7.72k, False: 11.1k]
  ------------------
   27|  18.8k|    {
   28|  18.8k|        if (objects) {
  ------------------
  |  Branch (28:13): [True: 7.72k, False: 11.1k]
  ------------------
   29|  7.72k|            objects->inParse(true);
   30|  7.72k|        }
   31|  18.8k|    }
_ZN4QPDF3Doc10ParseGuardD2Ev:
   40|  18.8k|    {
   41|  18.8k|        if (objects) {
  ------------------
  |  Branch (41:13): [True: 7.72k, False: 11.1k]
  ------------------
   42|  7.72k|            objects->inParse(false);
   43|  7.72k|        }
   44|  18.8k|    }
_ZN4qpdf4impl6Parser16with_descriptionI9QPDF_NameJRKNSt3__112basic_stringIcNS4_11char_traitsIcEENS4_9allocatorIcEEEEEEE16QPDFObjectHandleDpOT0_:
  602|  10.8k|{
  603|  10.8k|    auto obj = QPDFObject::create<T>(std::forward<Args>(args)...);
  604|  10.8k|    obj->setDescription(context_, description_, start_);
  605|  10.8k|    return {obj};
  606|  10.8k|}

_ZN4qpdf9Tokenizer5resetEv:
   85|   138k|{
   86|   138k|    state = st_before_token;
   87|   138k|    type = tt::tt_bad;
   88|   138k|    val.clear();
   89|   138k|    raw_val.clear();
   90|   138k|    error_message = "";
   91|   138k|    before_token = true;
   92|   138k|    in_token = false;
   93|   138k|    char_to_unread = '\0';
   94|   138k|    inline_image_bytes = 0;
   95|   138k|    string_depth = 0;
   96|   138k|    bad = false;
   97|   138k|}
_ZN4qpdf9TokenizerC2Ev:
  119|  18.8k|{
  120|  18.8k|    reset();
  121|  18.8k|}
_ZN4qpdf9Tokenizer8allowEOFEv:
  131|  7.72k|{
  132|  7.72k|    allow_eof = true;
  133|  7.72k|}
_ZN4qpdf9Tokenizer7isSpaceEc:
  149|   127k|{
  150|   127k|    return (ch == '\0' || util::is_space(ch));
  ------------------
  |  Branch (150:13): [True: 0, False: 127k]
  |  Branch (150:27): [True: 46.3k, False: 80.7k]
  ------------------
  151|   127k|}
_ZN4qpdf9Tokenizer11isDelimiterEc:
  155|  5.71M|{
  156|  5.71M|    return is_delimiter(ch);
  157|  5.71M|}
_ZN4qpdf9Tokenizer16presentCharacterEc:
  167|  7.20k|{
  168|  7.20k|    handleCharacter(ch);
  169|       |
  170|  7.20k|    if (in_token) {
  ------------------
  |  Branch (170:9): [True: 0, False: 7.20k]
  ------------------
  171|      0|        raw_val += ch;
  172|      0|    }
  173|  7.20k|}
_ZN4qpdf9Tokenizer15handleCharacterEc:
  177|  6.85M|{
  178|       |    // In some cases, functions called below may call a second handler. This happens whenever you
  179|       |    // have to use a character from the next token to detect the end of the current token.
  180|       |
  181|  6.85M|    switch (state) {
  182|      0|    case st_top:
  ------------------
  |  Branch (182:5): [True: 0, False: 6.85M]
  ------------------
  183|      0|        inTop(ch);
  184|      0|        return;
  185|       |
  186|      0|    case st_in_space:
  ------------------
  |  Branch (186:5): [True: 0, False: 6.85M]
  ------------------
  187|      0|        inSpace(ch);
  188|      0|        return;
  189|       |
  190|      0|    case st_in_comment:
  ------------------
  |  Branch (190:5): [True: 0, False: 6.85M]
  ------------------
  191|      0|        inComment(ch);
  192|      0|        return;
  193|       |
  194|  7.72k|    case st_lt:
  ------------------
  |  Branch (194:5): [True: 7.72k, False: 6.84M]
  ------------------
  195|  7.72k|        inLt(ch);
  196|  7.72k|        return;
  197|       |
  198|  7.72k|    case st_gt:
  ------------------
  |  Branch (198:5): [True: 7.72k, False: 6.84M]
  ------------------
  199|  7.72k|        inGt(ch);
  200|  7.72k|        return;
  201|       |
  202|      0|    case st_in_string:
  ------------------
  |  Branch (202:5): [True: 0, False: 6.85M]
  ------------------
  203|      0|        inString(ch);
  204|      0|        return;
  205|       |
  206|  5.32M|    case st_name:
  ------------------
  |  Branch (206:5): [True: 5.32M, False: 1.53M]
  ------------------
  207|  5.32M|        inName(ch);
  208|  5.32M|        return;
  209|       |
  210|  23.1k|    case st_number:
  ------------------
  |  Branch (210:5): [True: 23.1k, False: 6.83M]
  ------------------
  211|  23.1k|        inNumber(ch);
  212|  23.1k|        return;
  213|       |
  214|      0|    case st_real:
  ------------------
  |  Branch (214:5): [True: 0, False: 6.85M]
  ------------------
  215|      0|        inReal(ch);
  216|      0|        return;
  217|       |
  218|      0|    case st_string_after_cr:
  ------------------
  |  Branch (218:5): [True: 0, False: 6.85M]
  ------------------
  219|      0|        inStringAfterCR(ch);
  220|      0|        return;
  221|       |
  222|      0|    case st_string_escape:
  ------------------
  |  Branch (222:5): [True: 0, False: 6.85M]
  ------------------
  223|      0|        inStringEscape(ch);
  224|      0|        return;
  225|       |
  226|      0|    case st_char_code:
  ------------------
  |  Branch (226:5): [True: 0, False: 6.85M]
  ------------------
  227|      0|        inCharCode(ch);
  228|      0|        return;
  229|       |
  230|   193k|    case st_literal:
  ------------------
  |  Branch (230:5): [True: 193k, False: 6.66M]
  ------------------
  231|   193k|        inLiteral(ch);
  232|   193k|        return;
  233|       |
  234|      0|    case st_inline_image:
  ------------------
  |  Branch (234:5): [True: 0, False: 6.85M]
  ------------------
  235|      0|        inInlineImage(ch);
  236|      0|        return;
  237|       |
  238|      0|    case st_in_hexstring:
  ------------------
  |  Branch (238:5): [True: 0, False: 6.85M]
  ------------------
  239|      0|        inHexstring(ch);
  240|      0|        return;
  241|       |
  242|      0|    case st_in_hexstring_2nd:
  ------------------
  |  Branch (242:5): [True: 0, False: 6.85M]
  ------------------
  243|      0|        inHexstring2nd(ch);
  244|      0|        return;
  245|       |
  246|   645k|    case st_name_hex1:
  ------------------
  |  Branch (246:5): [True: 645k, False: 6.21M]
  ------------------
  247|   645k|        inNameHex1(ch);
  248|   645k|        return;
  249|       |
  250|   528k|    case st_name_hex2:
  ------------------
  |  Branch (250:5): [True: 528k, False: 6.32M]
  ------------------
  251|   528k|        inNameHex2(ch);
  252|   528k|        return;
  253|       |
  254|      0|    case st_sign:
  ------------------
  |  Branch (254:5): [True: 0, False: 6.85M]
  ------------------
  255|      0|        inSign(ch);
  256|      0|        return;
  257|       |
  258|      0|    case st_decimal:
  ------------------
  |  Branch (258:5): [True: 0, False: 6.85M]
  ------------------
  259|      0|        inDecimal(ch);
  260|      0|        return;
  261|       |
  262|   127k|    case (st_before_token):
  ------------------
  |  Branch (262:5): [True: 127k, False: 6.72M]
  ------------------
  263|   127k|        inBeforeToken(ch);
  264|   127k|        return;
  265|       |
  266|      0|    case (st_token_ready):
  ------------------
  |  Branch (266:5): [True: 0, False: 6.85M]
  ------------------
  267|      0|        inTokenReady(ch);
  268|      0|        return;
  269|       |
  270|      0|    default:
  ------------------
  |  Branch (270:5): [True: 0, False: 6.85M]
  ------------------
  271|      0|        throw std::logic_error("INTERNAL ERROR: invalid state while reading token");
  272|  6.85M|    }
  273|  6.85M|}
_ZN4qpdf9Tokenizer13inBeforeTokenEc:
  284|   127k|{
  285|       |    // Note: we specifically do not use ctype here.  It is locale-dependent.
  286|   127k|    if (isSpace(ch)) {
  ------------------
  |  Branch (286:9): [True: 46.3k, False: 80.7k]
  ------------------
  287|  46.3k|        before_token = !include_ignorable;
  288|  46.3k|        in_token = include_ignorable;
  289|  46.3k|        if (include_ignorable) {
  ------------------
  |  Branch (289:13): [True: 0, False: 46.3k]
  ------------------
  290|      0|            state = st_in_space;
  291|      0|        }
  292|  80.7k|    } else if (ch == '%') {
  ------------------
  |  Branch (292:16): [True: 0, False: 80.7k]
  ------------------
  293|      0|        before_token = !include_ignorable;
  294|      0|        in_token = include_ignorable;
  295|      0|        state = st_in_comment;
  296|  80.7k|    } else {
  297|  80.7k|        before_token = false;
  298|  80.7k|        in_token = true;
  299|  80.7k|        inTop(ch);
  300|  80.7k|    }
  301|   127k|}
_ZN4qpdf9Tokenizer5inTopEc:
  305|  80.7k|{
  306|  80.7k|    switch (ch) {
  307|      0|    case '(':
  ------------------
  |  Branch (307:5): [True: 0, False: 80.7k]
  ------------------
  308|      0|        string_depth = 1;
  309|      0|        state = st_in_string;
  310|      0|        return;
  311|       |
  312|  7.72k|    case '<':
  ------------------
  |  Branch (312:5): [True: 7.72k, False: 72.9k]
  ------------------
  313|  7.72k|        state = st_lt;
  314|  7.72k|        return;
  315|       |
  316|  7.72k|    case '>':
  ------------------
  |  Branch (316:5): [True: 7.72k, False: 72.9k]
  ------------------
  317|  7.72k|        state = st_gt;
  318|  7.72k|        return;
  319|       |
  320|      0|    case (')'):
  ------------------
  |  Branch (320:5): [True: 0, False: 80.7k]
  ------------------
  321|      0|        type = tt::tt_bad;
  322|      0|        QTC::TC("qpdf", "QPDFTokenizer bad )");
  323|      0|        error_message = "unexpected )";
  324|      0|        state = st_token_ready;
  325|      0|        return;
  326|       |
  327|      0|    case '[':
  ------------------
  |  Branch (327:5): [True: 0, False: 80.7k]
  ------------------
  328|      0|        type = tt::tt_array_open;
  329|      0|        state = st_token_ready;
  330|      0|        return;
  331|       |
  332|      0|    case ']':
  ------------------
  |  Branch (332:5): [True: 0, False: 80.7k]
  ------------------
  333|      0|        type = tt::tt_array_close;
  334|      0|        state = st_token_ready;
  335|      0|        return;
  336|       |
  337|      0|    case '{':
  ------------------
  |  Branch (337:5): [True: 0, False: 80.7k]
  ------------------
  338|      0|        type = tt::tt_brace_open;
  339|      0|        state = st_token_ready;
  340|      0|        return;
  341|       |
  342|      0|    case '}':
  ------------------
  |  Branch (342:5): [True: 0, False: 80.7k]
  ------------------
  343|      0|        type = tt::tt_brace_close;
  344|      0|        state = st_token_ready;
  345|      0|        return;
  346|       |
  347|  18.8k|    case '/':
  ------------------
  |  Branch (347:5): [True: 18.8k, False: 61.8k]
  ------------------
  348|  18.8k|        state = st_name;
  349|  18.8k|        val += ch;
  350|  18.8k|        return;
  351|       |
  352|      0|    case '0':
  ------------------
  |  Branch (352:5): [True: 0, False: 80.7k]
  ------------------
  353|  7.72k|    case '1':
  ------------------
  |  Branch (353:5): [True: 7.72k, False: 72.9k]
  ------------------
  354|  7.72k|    case '2':
  ------------------
  |  Branch (354:5): [True: 0, False: 80.7k]
  ------------------
  355|  7.72k|    case '3':
  ------------------
  |  Branch (355:5): [True: 0, False: 80.7k]
  ------------------
  356|  7.72k|    case '4':
  ------------------
  |  Branch (356:5): [True: 0, False: 80.7k]
  ------------------
  357|  7.72k|    case '5':
  ------------------
  |  Branch (357:5): [True: 0, False: 80.7k]
  ------------------
  358|  7.72k|    case '6':
  ------------------
  |  Branch (358:5): [True: 0, False: 80.7k]
  ------------------
  359|  7.72k|    case '7':
  ------------------
  |  Branch (359:5): [True: 0, False: 80.7k]
  ------------------
  360|  7.72k|    case '8':
  ------------------
  |  Branch (360:5): [True: 0, False: 80.7k]
  ------------------
  361|  23.1k|    case '9':
  ------------------
  |  Branch (361:5): [True: 15.4k, False: 65.2k]
  ------------------
  362|  23.1k|        state = st_number;
  363|  23.1k|        return;
  364|       |
  365|      0|    case '+':
  ------------------
  |  Branch (365:5): [True: 0, False: 80.7k]
  ------------------
  366|      0|    case '-':
  ------------------
  |  Branch (366:5): [True: 0, False: 80.7k]
  ------------------
  367|      0|        state = st_sign;
  368|      0|        return;
  369|       |
  370|      0|    case '.':
  ------------------
  |  Branch (370:5): [True: 0, False: 80.7k]
  ------------------
  371|      0|        state = st_decimal;
  372|      0|        return;
  373|       |
  374|  23.1k|    default:
  ------------------
  |  Branch (374:5): [True: 23.1k, False: 57.5k]
  ------------------
  375|  23.1k|        state = st_literal;
  376|  23.1k|        return;
  377|  80.7k|    }
  378|  80.7k|}
_ZN4qpdf9Tokenizer6inNameEc:
  448|  5.49M|{
  449|  5.49M|    if (isDelimiter(ch)) {
  ------------------
  |  Branch (449:9): [True: 18.8k, False: 5.47M]
  ------------------
  450|       |        // A C-locale whitespace character or delimiter terminates token.  It is important to unread
  451|       |        // the whitespace character even though it is ignored since it may be the newline after a
  452|       |        // stream keyword.  Removing it here could make the stream-reading code break on some files,
  453|       |        // though not on any files in the test suite as of this
  454|       |        // writing.
  455|       |
  456|  18.8k|        type = bad ? tt::tt_bad : tt::tt_name;
  ------------------
  |  Branch (456:16): [True: 83, False: 18.8k]
  ------------------
  457|  18.8k|        in_token = false;
  458|  18.8k|        char_to_unread = ch;
  459|  18.8k|        state = st_token_ready;
  460|  5.47M|    } else if (ch == '#') {
  ------------------
  |  Branch (460:16): [True: 645k, False: 4.83M]
  ------------------
  461|   645k|        char_code = 0;
  462|   645k|        state = st_name_hex1;
  463|  4.83M|    } else {
  464|  4.83M|        val += ch;
  465|  4.83M|    }
  466|  5.49M|}
_ZN4qpdf9Tokenizer10inNameHex1Ec:
  470|   645k|{
  471|   645k|    hex_char = ch;
  472|       |
  473|   645k|    if (char hval = util::hex_decode_char(ch); hval < '\20') {
  ------------------
  |  Branch (473:48): [True: 528k, False: 116k]
  ------------------
  474|   528k|        char_code = int(hval) << 4;
  475|   528k|        state = st_name_hex2;
  476|   528k|    } else {
  477|   116k|        QTC::TC("qpdf", "QPDFTokenizer bad name 1");
  478|   116k|        error_message = "name with stray # will not work with PDF >= 1.2";
  479|       |        // Use null to encode a bad # -- this is reversed in QPDF_Name::normalizeName.
  480|   116k|        val += '\0';
  481|   116k|        state = st_name;
  482|   116k|        inName(ch);
  483|   116k|    }
  484|   645k|}
_ZN4qpdf9Tokenizer10inNameHex2Ec:
  488|   528k|{
  489|   528k|    if (char hval = util::hex_decode_char(ch); hval < '\20') {
  ------------------
  |  Branch (489:48): [True: 469k, False: 59.1k]
  ------------------
  490|   469k|        char_code |= int(hval);
  491|   469k|    } else {
  492|  59.1k|        QTC::TC("qpdf", "QPDFTokenizer bad name 2");
  493|  59.1k|        error_message = "name with stray # will not work with PDF >= 1.2";
  494|       |        // Use null to encode a bad # -- this is reversed in QPDF_Name::normalizeName.
  495|  59.1k|        val += '\0';
  496|  59.1k|        val += hex_char;
  497|  59.1k|        state = st_name;
  498|  59.1k|        inName(ch);
  499|  59.1k|        return;
  500|  59.1k|    }
  501|   469k|    if (char_code == 0) {
  ------------------
  |  Branch (501:9): [True: 423k, False: 46.6k]
  ------------------
  502|   423k|        QTC::TC("qpdf", "QPDFTokenizer null in name");
  503|   423k|        error_message = "null character not allowed in name token";
  504|   423k|        val += "#00";
  505|   423k|        state = st_name;
  506|   423k|        bad = true;
  507|   423k|    } else {
  508|  46.6k|        val += char(char_code);
  509|  46.6k|        state = st_name;
  510|  46.6k|    }
  511|   469k|}
_ZN4qpdf9Tokenizer8inNumberEc:
  539|  23.1k|{
  540|  23.1k|    if (util::is_digit(ch)) {
  ------------------
  |  Branch (540:9): [True: 0, False: 23.1k]
  ------------------
  541|  23.1k|    } else if (ch == '.') {
  ------------------
  |  Branch (541:16): [True: 0, False: 23.1k]
  ------------------
  542|      0|        state = st_real;
  543|  23.1k|    } else if (isDelimiter(ch)) {
  ------------------
  |  Branch (543:16): [True: 23.1k, False: 0]
  ------------------
  544|  23.1k|        type = tt::tt_integer;
  545|  23.1k|        state = st_token_ready;
  546|  23.1k|        in_token = false;
  547|  23.1k|        char_to_unread = ch;
  548|  23.1k|    } else {
  549|      0|        state = st_literal;
  550|      0|    }
  551|  23.1k|}
_ZN4qpdf9Tokenizer4inLtEc:
  630|  7.72k|{
  631|  7.72k|    if (ch == '<') {
  ------------------
  |  Branch (631:9): [True: 7.72k, False: 0]
  ------------------
  632|  7.72k|        type = tt::tt_dict_open;
  633|  7.72k|        state = st_token_ready;
  634|  7.72k|        return;
  635|  7.72k|    }
  636|       |
  637|      0|    state = st_in_hexstring;
  638|      0|    inHexstring(ch);
  639|      0|}
_ZN4qpdf9Tokenizer4inGtEc:
  643|  7.72k|{
  644|  7.72k|    if (ch == '>') {
  ------------------
  |  Branch (644:9): [True: 7.72k, False: 0]
  ------------------
  645|  7.72k|        type = tt::tt_dict_close;
  646|  7.72k|        state = st_token_ready;
  647|  7.72k|    } else {
  648|      0|        type = tt::tt_bad;
  649|      0|        QTC::TC("qpdf", "QPDFTokenizer bad >");
  650|      0|        error_message = "unexpected >";
  651|      0|        in_token = false;
  652|      0|        char_to_unread = ch;
  653|      0|        state = st_token_ready;
  654|      0|    }
  655|  7.72k|}
_ZN4qpdf9Tokenizer9inLiteralEc:
  659|   193k|{
  660|   193k|    if (isDelimiter(ch)) {
  ------------------
  |  Branch (660:9): [True: 23.1k, False: 169k]
  ------------------
  661|       |        // A C-locale whitespace character or delimiter terminates token.  It is important to unread
  662|       |        // the whitespace character even though it is ignored since it may be the newline after a
  663|       |        // stream keyword.  Removing it here could make the stream-reading code break on some files,
  664|       |        // though not on any files in the test suite as of this writing.
  665|       |
  666|  23.1k|        in_token = false;
  667|  23.1k|        char_to_unread = ch;
  668|  23.1k|        state = st_token_ready;
  669|  23.1k|        type = (raw_val == "true") || (raw_val == "false")
  ------------------
  |  Branch (669:16): [True: 0, False: 23.1k]
  |  Branch (669:39): [True: 0, False: 23.1k]
  ------------------
  670|  23.1k|            ? tt::tt_bool
  671|  23.1k|            : (raw_val == "null" ? tt::tt_null : tt::tt_word);
  ------------------
  |  Branch (671:16): [True: 0, False: 23.1k]
  ------------------
  672|  23.1k|    }
  673|   193k|}
_ZN4qpdf9Tokenizer10presentEOFEv:
  760|  7.20k|{
  761|  7.20k|    switch (state) {
  762|  7.14k|    case st_name:
  ------------------
  |  Branch (762:5): [True: 7.14k, False: 56]
  ------------------
  763|  7.17k|    case st_name_hex1:
  ------------------
  |  Branch (763:5): [True: 30, False: 7.17k]
  ------------------
  764|  7.20k|    case st_name_hex2:
  ------------------
  |  Branch (764:5): [True: 26, False: 7.17k]
  ------------------
  765|  7.20k|    case st_number:
  ------------------
  |  Branch (765:5): [True: 0, False: 7.20k]
  ------------------
  766|  7.20k|    case st_real:
  ------------------
  |  Branch (766:5): [True: 0, False: 7.20k]
  ------------------
  767|  7.20k|    case st_sign:
  ------------------
  |  Branch (767:5): [True: 0, False: 7.20k]
  ------------------
  768|  7.20k|    case st_decimal:
  ------------------
  |  Branch (768:5): [True: 0, False: 7.20k]
  ------------------
  769|  7.20k|    case st_literal:
  ------------------
  |  Branch (769:5): [True: 0, False: 7.20k]
  ------------------
  770|  7.20k|        QTC::TC("qpdf", "QPDFTokenizer EOF reading appendable token");
  771|       |        // Push any delimiter to the state machine to finish off the final token.
  772|  7.20k|        presentCharacter('\f');
  773|  7.20k|        in_token = true;
  774|  7.20k|        break;
  775|       |
  776|      0|    case st_top:
  ------------------
  |  Branch (776:5): [True: 0, False: 7.20k]
  ------------------
  777|      0|    case st_before_token:
  ------------------
  |  Branch (777:5): [True: 0, False: 7.20k]
  ------------------
  778|      0|        type = tt::tt_eof;
  779|      0|        break;
  780|       |
  781|      0|    case st_in_space:
  ------------------
  |  Branch (781:5): [True: 0, False: 7.20k]
  ------------------
  782|      0|        type = include_ignorable ? tt::tt_space : tt::tt_eof;
  ------------------
  |  Branch (782:16): [True: 0, False: 0]
  ------------------
  783|      0|        break;
  784|       |
  785|      0|    case st_in_comment:
  ------------------
  |  Branch (785:5): [True: 0, False: 7.20k]
  ------------------
  786|      0|        type = include_ignorable ? tt::tt_comment : tt::tt_bad;
  ------------------
  |  Branch (786:16): [True: 0, False: 0]
  ------------------
  787|      0|        break;
  788|       |
  789|      0|    case st_token_ready:
  ------------------
  |  Branch (789:5): [True: 0, False: 7.20k]
  ------------------
  790|      0|        break;
  791|       |
  792|      0|    default:
  ------------------
  |  Branch (792:5): [True: 0, False: 7.20k]
  ------------------
  793|      0|        QTC::TC("qpdf", "QPDFTokenizer EOF reading token");
  794|      0|        type = tt::tt_bad;
  795|      0|        error_message = "EOF while reading token";
  796|  7.20k|    }
  797|  7.20k|    state = st_token_ready;
  798|  7.20k|}
_ZN4qpdf9Tokenizer8getTokenERN13QPDFTokenizer5TokenERbRc:
  916|  38.6k|{
  917|  38.6k|    bool ready = (state == st_token_ready);
  918|  38.6k|    unread_char = !in_token && !before_token;
  ------------------
  |  Branch (918:19): [True: 38.6k, False: 0]
  |  Branch (918:32): [True: 38.6k, False: 0]
  ------------------
  919|  38.6k|    ch = char_to_unread;
  920|  38.6k|    if (ready) {
  ------------------
  |  Branch (920:9): [True: 38.6k, False: 0]
  ------------------
  921|  38.6k|        token = (!(type == tt::tt_name || type == tt::tt_string))
  ------------------
  |  Branch (921:20): [True: 0, False: 38.6k]
  |  Branch (921:43): [True: 0, False: 38.6k]
  ------------------
  922|  38.6k|            ? Token(type, raw_val, raw_val, error_message)
  923|  38.6k|            : Token(type, val, raw_val, error_message);
  924|       |
  925|  38.6k|        reset();
  926|  38.6k|    }
  927|  38.6k|    return ready;
  928|  38.6k|}
_ZN4qpdf9Tokenizer9readTokenER11InputSourceRKNSt3__112basic_stringIcNS3_11char_traitsIcEENS3_9allocatorIcEEEEbm:
  958|  38.6k|{
  959|  38.6k|    nextToken(input, context, max_len);
  960|       |
  961|  38.6k|    Token token;
  962|  38.6k|    bool unread_char;
  963|  38.6k|    char char_to_unread;
  964|  38.6k|    getToken(token, unread_char, char_to_unread);
  965|       |
  966|  38.6k|    if (token.getType() == tt::tt_bad) {
  ------------------
  |  Branch (966:9): [True: 0, False: 38.6k]
  ------------------
  967|      0|        if (allow_bad) {
  ------------------
  |  Branch (967:13): [True: 0, False: 0]
  ------------------
  968|      0|            QTC::TC("qpdf", "QPDFTokenizer allowing bad token");
  969|      0|        } else {
  970|      0|            throw QPDFExc(
  971|      0|                qpdf_e_damaged_pdf,
  972|      0|                input.getName(),
  973|      0|                context.empty() ? "offset " + std::to_string(input.getLastOffset()) : context,
  ------------------
  |  Branch (973:17): [True: 0, False: 0]
  ------------------
  974|      0|                input.getLastOffset(),
  975|      0|                token.getErrorMessage());
  976|      0|        }
  977|      0|    }
  978|  38.6k|    return token;
  979|  38.6k|}
_ZN4qpdf9Tokenizer9nextTokenER11InputSourceRKNSt3__112basic_stringIcNS3_11char_traitsIcEENS3_9allocatorIcEEEEm:
  983|  80.7k|{
  984|  80.7k|    if (state != st_inline_image) {
  ------------------
  |  Branch (984:9): [True: 80.7k, False: 0]
  ------------------
  985|  80.7k|        reset();
  986|  80.7k|    }
  987|  80.7k|    qpdf_offset_t offset = input.fastTell();
  988|       |
  989|  6.93M|    while (state != st_token_ready) {
  ------------------
  |  Branch (989:12): [True: 6.85M, False: 80.7k]
  ------------------
  990|  6.85M|        char ch;
  991|  6.85M|        if (!input.fastRead(ch)) {
  ------------------
  |  Branch (991:13): [True: 7.20k, False: 6.84M]
  ------------------
  992|  7.20k|            presentEOF();
  993|       |
  994|  7.20k|            if ((type == tt::tt_eof) && (!allow_eof)) {
  ------------------
  |  Branch (994:17): [True: 0, False: 7.20k]
  |  Branch (994:41): [True: 0, False: 0]
  ------------------
  995|       |                // Nothing in the qpdf library calls readToken without allowEOF anymore, so this
  996|       |                // case is not exercised.
  997|      0|                type = tt::tt_bad;
  998|      0|                error_message = "unexpected EOF";
  999|      0|                offset = input.getLastOffset();
 1000|      0|            }
 1001|  6.84M|        } else {
 1002|  6.84M|            handleCharacter(ch);
 1003|  6.84M|            if (before_token) {
  ------------------
  |  Branch (1003:17): [True: 46.3k, False: 6.80M]
  ------------------
 1004|  46.3k|                ++offset;
 1005|  46.3k|            }
 1006|  6.84M|            if (in_token) {
  ------------------
  |  Branch (1006:17): [True: 6.74M, False: 104k]
  ------------------
 1007|  6.74M|                raw_val += ch;
 1008|  6.74M|            }
 1009|  6.84M|            if (max_len && (raw_val.length() >= max_len) && (state != st_token_ready)) {
  ------------------
  |  Branch (1009:17): [True: 0, False: 6.84M]
  |  Branch (1009:28): [True: 0, False: 0]
  |  Branch (1009:61): [True: 0, False: 0]
  ------------------
 1010|       |                // terminate this token now
 1011|      0|                QTC::TC("qpdf", "QPDFTokenizer block long token");
 1012|      0|                type = tt::tt_bad;
 1013|      0|                state = st_token_ready;
 1014|      0|                error_message = "exceeded allowable length while reading token";
 1015|      0|            }
 1016|  6.84M|        }
 1017|  6.85M|    }
 1018|       |
 1019|  80.7k|    input.fastUnread(!in_token && !before_token);
  ------------------
  |  Branch (1019:22): [True: 58.0k, False: 22.6k]
  |  Branch (1019:35): [True: 58.0k, False: 0]
  ------------------
 1020|       |
 1021|  80.7k|    if (type != tt::tt_eof) {
  ------------------
  |  Branch (1021:9): [True: 80.7k, False: 0]
  ------------------
 1022|  80.7k|        input.setLastOffset(offset);
 1023|  80.7k|    }
 1024|       |
 1025|  80.7k|    return error_message.empty();
 1026|  80.7k|}
QPDFTokenizer.cc:_ZL12is_delimiterc:
   25|  5.71M|{
   26|  5.71M|    return (
   27|  5.71M|        ch == ' ' || ch == '\n' || ch == '/' || ch == '(' || ch == ')' || ch == '{' || ch == '}' ||
  ------------------
  |  Branch (27:9): [True: 26.2k, False: 5.68M]
  |  Branch (27:22): [True: 31.1k, False: 5.65M]
  |  Branch (27:36): [True: 18, False: 5.65M]
  |  Branch (27:49): [True: 10, False: 5.65M]
  |  Branch (27:62): [True: 6, False: 5.65M]
  |  Branch (27:75): [True: 14, False: 5.65M]
  |  Branch (27:88): [True: 7, False: 5.65M]
  ------------------
   28|  5.65M|        ch == '<' || ch == '>' || ch == '[' || ch == ']' || ch == '%' || ch == '\t' || ch == '\r' ||
  ------------------
  |  Branch (28:9): [True: 9, False: 5.65M]
  |  Branch (28:22): [True: 6, False: 5.65M]
  |  Branch (28:35): [True: 11, False: 5.65M]
  |  Branch (28:48): [True: 6, False: 5.65M]
  |  Branch (28:61): [True: 5, False: 5.65M]
  |  Branch (28:74): [True: 196, False: 5.65M]
  |  Branch (28:88): [True: 249, False: 5.65M]
  ------------------
   29|  5.65M|        ch == '\v' || ch == '\f' || ch == 0);
  ------------------
  |  Branch (29:9): [True: 196, False: 5.65M]
  |  Branch (29:23): [True: 7.20k, False: 5.64M]
  |  Branch (29:37): [True: 3, False: 5.64M]
  ------------------
   30|  5.71M|}

_ZNK4qpdf5Array5arrayEv:
   55|  1.83M|{
   56|  1.83M|    if (auto a = as<QPDF_Array>()) {
  ------------------
  |  Branch (56:14): [True: 1.83M, False: 0]
  ------------------
   57|  1.83M|        return a;
   58|  1.83M|    }
   59|       |
   60|      0|    throw std::runtime_error("Expected an array but found a non-array object");
   61|      0|    return nullptr; // unreachable
   62|  1.83M|}
_ZN4qpdf5Array9push_backERK16QPDFObjectHandle:
  333|  1.83M|{
  334|  1.83M|    auto a = array();
  335|  1.83M|    checkOwnership(item);
  336|  1.83M|    if (a->sp) {
  ------------------
  |  Branch (336:9): [True: 0, False: 1.83M]
  ------------------
  337|      0|        a->sp->elements[(a->sp->size)++] = item;
  338|  1.83M|    } else {
  339|  1.83M|        a->elements.emplace_back(item);
  340|  1.83M|    }
  341|  1.83M|}
_ZN16QPDFObjectHandle10appendItemERKS_:
  526|  1.83M|{
  527|  1.83M|    if (auto array = as_array(strict)) {
  ------------------
  |  Branch (527:14): [True: 1.83M, False: 0]
  ------------------
  528|  1.83M|        array.push_back(item);
  529|  1.83M|    } else {
  530|      0|        typeWarning("array", "ignoring attempt to append item");
  531|      0|        QTC::TC("qpdf", "QPDFObjectHandle array ignoring append item");
  532|      0|    }
  533|  1.83M|}
_ZNK4qpdf5Array14checkOwnershipERK16QPDFObjectHandle:
   27|  1.83M|{
   28|  1.83M|    if (!item) {
  ------------------
  |  Branch (28:9): [True: 0, False: 1.83M]
  ------------------
   29|      0|        throw std::logic_error("Attempting to add an uninitialized object to a QPDF_Array.");
   30|      0|    }
   31|  1.83M|    if (qpdf() && item.qpdf() && qpdf() != item.qpdf()) {
  ------------------
  |  Branch (31:9): [True: 1.83M, False: 0]
  |  Branch (31:19): [True: 1.83M, False: 5.63k]
  |  Branch (31:34): [True: 0, False: 1.83M]
  ------------------
   32|      0|        throw std::logic_error(
   33|      0|            "Attempting to add an object from a different QPDF. Use "
   34|      0|            "QPDF::copyForeignObject to add objects from another file.");
   35|      0|    }
   36|  1.83M|}

_ZNK4qpdf10BaseHandleixERKNSt3__112basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEE:
   22|  46.3k|{
   23|  46.3k|    if (auto d = as<QPDF_Dictionary>()) {
  ------------------
  |  Branch (23:14): [True: 46.3k, False: 0]
  ------------------
   24|  46.3k|        auto it = d->items.find(key);
   25|  46.3k|        if (it != d->items.end()) {
  ------------------
  |  Branch (25:13): [True: 23.1k, False: 23.1k]
  ------------------
   26|  23.1k|            return it->second;
   27|  23.1k|        }
   28|  46.3k|    }
   29|  23.1k|    static const QPDFObjectHandle null_obj;
   30|  23.1k|    return null_obj;
   31|  46.3k|}
_ZNK4qpdf10BaseHandle8containsERKNSt3__112basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEE:
   63|  30.9k|{
   64|  30.9k|    return !(*this)[key].null();
   65|  30.9k|}
_ZN4qpdf10BaseHandle5eraseERKNSt3__112basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEE:
  117|  9.39k|{
  118|       |    // no-op if key does not exist
  119|  9.39k|    if (auto d = as<QPDF_Dictionary>()) {
  ------------------
  |  Branch (119:14): [True: 9.39k, False: 0]
  ------------------
  120|  9.39k|        return d->items.erase(key);
  121|  9.39k|    }
  122|      0|    return 0;
  123|  9.39k|}
_ZN4qpdf10BaseHandle7replaceERKNSt3__112basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEE16QPDFObjectHandle:
  140|   100k|{
  141|   100k|    if (auto d = as<QPDF_Dictionary>()) {
  ------------------
  |  Branch (141:14): [True: 100k, False: 0]
  ------------------
  142|   100k|        if (value.null() && !value.indirect()) {
  ------------------
  |  Branch (142:13): [True: 18.8k, False: 81.2k]
  |  Branch (142:29): [True: 13.3k, False: 5.48k]
  ------------------
  143|       |            // The PDF spec doesn't distinguish between keys with null values and missing keys.
  144|       |            // Allow indirect nulls which are equivalent to a dangling reference, which is permitted
  145|       |            // by the spec.
  146|  13.3k|            d->items.erase(key);
  147|  86.7k|        } else {
  148|       |            // add or replace value
  149|  86.7k|            d->items[key] = value;
  150|  86.7k|        }
  151|   100k|        return true;
  152|   100k|    }
  153|      0|    return false;
  154|   100k|}
_ZN4qpdf14BaseDictionary7replaceERKNSt3__112basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEE16QPDFObjectHandle:
  172|   100k|{
  173|   100k|    if (!BaseHandle::replace(key, value)) {
  ------------------
  |  Branch (173:9): [True: 0, False: 100k]
  ------------------
  174|      0|        (void)dict();
  175|      0|    }
  176|   100k|}
_ZN4qpdf10DictionaryC2ERKNSt3__110shared_ptrI10QPDFObjectEE:
  184|   100k|    BaseDictionary(obj)
  185|   100k|{
  186|   100k|}
_ZNK16QPDFObjectHandle14checkOwnershipERKS_:
  196|   100k|{
  197|   100k|    auto qpdf = getOwningQPDF();
  198|   100k|    auto item_qpdf = item.getOwningQPDF();
  199|   100k|    if (qpdf && item_qpdf && qpdf != item_qpdf) {
  ------------------
  |  Branch (199:9): [True: 100k, False: 0]
  |  Branch (199:17): [True: 99.8k, False: 229]
  |  Branch (199:30): [True: 0, False: 99.8k]
  ------------------
  200|      0|        throw std::logic_error(
  201|      0|            "Attempting to add an object from a different QPDF. Use "
  202|      0|            "QPDF::copyForeignObject to add objects from another file.");
  203|      0|    }
  204|   100k|}
_ZNK16QPDFObjectHandle6hasKeyERKNSt3__112basic_stringIcNS0_11char_traitsIcEENS0_9allocatorIcEEEE:
  208|  23.1k|{
  209|  23.1k|    if (Dictionary dict = *this) {
  ------------------
  |  Branch (209:20): [True: 23.1k, False: 0]
  ------------------
  210|  23.1k|        return dict.contains(key);
  211|  23.1k|    } else {
  212|      0|        typeWarning("dictionary", "returning false for a key containment request");
  213|      0|        QTC::TC("qpdf", "QPDFObjectHandle dictionary false for hasKey");
  214|      0|        return false;
  215|      0|    }
  216|  23.1k|}
_ZNK16QPDFObjectHandle6getKeyERKNSt3__112basic_stringIcNS0_11char_traitsIcEENS0_9allocatorIcEEEE:
  220|  15.4k|{
  221|  15.4k|    if (auto result = get(key)) {
  ------------------
  |  Branch (221:14): [True: 15.4k, False: 0]
  ------------------
  222|  15.4k|        return result;
  223|  15.4k|    }
  224|      0|    if (isDictionary()) {
  ------------------
  |  Branch (224:9): [True: 0, False: 0]
  ------------------
  225|      0|        static auto constexpr msg = " -> dictionary key $VD"sv;
  226|      0|        return QPDF_Null::create(obj, msg, key);
  227|      0|    }
  228|      0|    typeWarning("dictionary", "returning null for attempted key retrieval");
  229|      0|    static auto constexpr msg = " -> null returned from getting key $VD from non-Dictionary"sv;
  230|      0|    return QPDF_Null::create(obj, msg, "");
  231|      0|}
_ZN16QPDFObjectHandle10replaceKeyERKNSt3__112basic_stringIcNS0_11char_traitsIcEENS0_9allocatorIcEEEERKS_:
  263|   100k|{
  264|   100k|    if (auto dict = as_dictionary(strict)) {
  ------------------
  |  Branch (264:14): [True: 100k, False: 0]
  ------------------
  265|   100k|        checkOwnership(value);
  266|   100k|        dict.replace(key, value);
  267|   100k|        return;
  268|   100k|    }
  269|      0|    typeWarning("dictionary", "ignoring key replacement request");
  270|      0|}
_ZN16QPDFObjectHandle9removeKeyERKNSt3__112basic_stringIcNS0_11char_traitsIcEENS0_9allocatorIcEEEE:
  289|  9.39k|{
  290|  9.39k|    if (erase(key) || isDictionary()) {
  ------------------
  |  Branch (290:9): [True: 465, False: 8.92k]
  |  Branch (290:23): [True: 8.92k, False: 0]
  ------------------
  291|  9.39k|        return;
  292|  9.39k|    }
  293|      0|    typeWarning("dictionary", "ignoring key removal request");
  294|      0|}

_ZN4QPDF3Doc7Objects7StreamsC2ERNS0_6CommonE:
  126|  7.72k|    Common(common),
  127|  7.72k|    copier_(std::make_shared<Copier>(*this))
  128|  7.72k|{
  129|  7.72k|}
_ZN4qpdf6StreamC2ER4QPDF10QPDFObjGen16QPDFObjectHandlexm:
  283|  3.30k|    BaseHandle(QPDFObject::create<QPDF_Stream>(&qpdf, og, std::move(stream_dict), length))
  284|  3.30k|{
  285|  3.30k|    auto descr = std::make_shared<QPDFObject::Description>(
  286|  3.30k|        qpdf.getFilename() + ", stream object " + og.unparse(' '));
  287|  3.30k|    obj->setDescription(&qpdf, descr, offset);
  288|  3.30k|    setDictDescription();
  289|  3.30k|}
_ZN4qpdf6Stream18setDictDescriptionEv:
  451|  6.06k|{
  452|  6.06k|    auto s = stream();
  453|  6.06k|    if (!s->stream_dict.hasObjectDescription()) {
  ------------------
  |  Branch (453:9): [True: 3.30k, False: 2.75k]
  ------------------
  454|  3.30k|        s->stream_dict.setObjectDescription(
  455|  3.30k|            obj->getQPDF(), obj->getDescription() + " -> stream dictionary");
  456|  3.30k|    }
  457|  6.06k|}
_ZN4qpdf6Stream17replaceStreamDataEONSt3__112basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEERK16QPDFObjectHandleSB_:
  738|  2.57k|{
  739|  2.57k|    auto s = stream();
  740|  2.57k|    s->stream_data = std::make_shared<Buffer>(std::move(data));
  741|  2.57k|    s->stream_provider = nullptr;
  742|  2.57k|    replaceFilterData(filter, decode_parms, s->stream_data->getSize());
  743|  2.57k|}
_ZN4qpdf6Stream17replaceStreamDataENSt3__110shared_ptrIN16QPDFObjectHandle18StreamDataProviderEEERKS3_S7_:
  762|  6.82k|{
  763|  6.82k|    auto s = stream();
  764|  6.82k|    s->stream_provider = provider;
  765|  6.82k|    s->stream_data = nullptr;
  766|  6.82k|    replaceFilterData(filter, decode_parms, 0);
  767|  6.82k|}
_ZN4qpdf6Stream17replaceFilterDataERK16QPDFObjectHandleS3_m:
  772|  9.39k|{
  773|  9.39k|    auto s = stream();
  774|  9.39k|    if (filter) {
  ------------------
  |  Branch (774:9): [True: 0, False: 9.39k]
  ------------------
  775|      0|        s->stream_dict.replaceKey("/Filter", filter);
  776|      0|    }
  777|  9.39k|    if (decode_parms) {
  ------------------
  |  Branch (777:9): [True: 0, False: 9.39k]
  ------------------
  778|      0|        s->stream_dict.replaceKey("/DecodeParms", decode_parms);
  779|      0|    }
  780|  9.39k|    if (length == 0) {
  ------------------
  |  Branch (780:9): [True: 9.39k, False: 0]
  ------------------
  781|  9.39k|        s->stream_dict.removeKey("/Length");
  782|  9.39k|    } else {
  783|      0|        Length(length);
  784|      0|    }
  785|  9.39k|}
_ZN16QPDFObjectHandle11replaceDictERKS_:
  819|  2.75k|{
  820|  2.75k|    as_stream(error).replaceDict(new_dict);
  821|  2.75k|}
_ZN16QPDFObjectHandle17replaceStreamDataERKNSt3__112basic_stringIcNS0_11char_traitsIcEENS0_9allocatorIcEEEERKS_SA_:
  897|  2.57k|{
  898|  2.57k|    std::string s(data);
  899|  2.57k|    as_stream(error).replaceStreamData(std::move(s), filter, decode_parms);
  900|  2.57k|}
_ZN16QPDFObjectHandle17replaceStreamDataENSt3__18functionIFvP8PipelineEEERKS_S7_:
  953|  6.82k|{
  954|  6.82k|    auto sdp = std::shared_ptr<StreamDataProvider>(new FunctionProvider(provider));
  955|  6.82k|    as_stream(error).replaceStreamData(sdp, filter, decode_parms);
  956|  6.82k|}
QPDF_Stream.cc:_ZN12_GLOBAL__N_116FunctionProviderC2ENSt3__18functionIFvP8PipelineEEE:
  917|  6.82k|            StreamDataProvider(false),
  918|  6.82k|            p1(provider),
  919|  6.82k|            p2(nullptr)
  920|  6.82k|        {
  921|  6.82k|        }
_ZN4QPDF3Doc7Objects7Streams6CopierC2ERS2_:
   67|  7.72k|        QPDFObjectHandle::StreamDataProvider(true),
   68|  7.72k|        streams(streams)
   69|  7.72k|    {
   70|  7.72k|    }
_ZN4QPDF3Doc7Objects7Streams6CopierD2Ev:
   64|  7.72k|    ~Copier() final = default;

_ZN4QPDF20EncryptionParameters10initializeERS_:
  732|  7.72k|{
  733|  7.72k|    if (encryption_initialized) {
  ------------------
  |  Branch (733:9): [True: 0, False: 7.72k]
  ------------------
  734|      0|        return;
  735|      0|    }
  736|  7.72k|    encryption_initialized = true;
  737|       |
  738|  7.72k|    auto& c = qpdf.m->c;
  739|  7.72k|    auto& qm = *qpdf.m;
  740|  7.72k|    auto& trailer = qm.trailer;
  741|  7.72k|    auto& file = qm.file;
  742|       |
  743|  7.72k|    auto warn_damaged_pdf = [&qpdf, c](std::string const& msg) {
  744|  7.72k|        qpdf.warn(c.damagedPDF("encryption dictionary", msg));
  745|  7.72k|    };
  746|  7.72k|    auto throw_damaged_pdf = [&qpdf](std::string const& msg) {
  747|  7.72k|        throw qpdf.m->c.damagedPDF("encryption dictionary", msg);
  748|  7.72k|    };
  749|  7.72k|    auto unsupported = [&file](std::string const& msg) -> QPDFExc {
  750|  7.72k|        return {
  751|  7.72k|            qpdf_e_unsupported,
  752|  7.72k|            file->getName(),
  753|  7.72k|            "encryption dictionary",
  754|  7.72k|            file->getLastOffset(),
  755|  7.72k|            msg};
  756|  7.72k|    };
  757|       |
  758|       |    // After we initialize encryption parameters, we must use stored key information and never look
  759|       |    // at /Encrypt again.  Otherwise, things could go wrong if someone mutates the encryption
  760|       |    // dictionary.
  761|       |
  762|  7.72k|    if (!trailer.contains("/Encrypt")) {
  ------------------
  |  Branch (762:9): [True: 7.72k, False: 0]
  ------------------
  763|  7.72k|        return;
  764|  7.72k|    }
  765|       |
  766|       |    // Go ahead and set m->encrypted here.  That way, isEncrypted will return true even if there
  767|       |    // were errors reading the encryption dictionary.
  768|      0|    encrypted = true;
  769|       |
  770|      0|    std::string id1;
  771|      0|    auto id_obj = trailer.getKey("/ID");
  772|      0|    if (id_obj.size() != 2 || !id_obj.getArrayItem(0).isString()) {
  ------------------
  |  Branch (772:9): [True: 0, False: 0]
  |  Branch (772:9): [True: 0, False: 0]
  |  Branch (772:31): [True: 0, False: 0]
  ------------------
  773|       |        // Treating a missing ID as the empty string enables qpdf to decrypt some invalid encrypted
  774|       |        // files with no /ID that poppler can read but Adobe Reader can't.
  775|      0|        qpdf.warn(qpdf.m->c.damagedPDF("trailer", "invalid /ID in trailer dictionary"));
  776|      0|    } else {
  777|      0|        id1 = id_obj.getArrayItem(0).getStringValue();
  778|      0|    }
  779|       |
  780|      0|    auto encryption_dict = trailer.getKey("/Encrypt");
  781|      0|    if (!encryption_dict.isDictionary()) {
  ------------------
  |  Branch (781:9): [True: 0, False: 0]
  ------------------
  782|      0|        throw qpdf.m->c.damagedPDF("/Encrypt in trailer dictionary is not a dictionary");
  783|      0|    }
  784|       |
  785|      0|    if (Name(encryption_dict["/Filter"]) != "/Standard") {
  ------------------
  |  Branch (785:9): [True: 0, False: 0]
  ------------------
  786|      0|        throw unsupported("unsupported encryption filter");
  787|      0|    }
  788|      0|    if (!encryption_dict.getKey("/SubFilter").null()) {
  ------------------
  |  Branch (788:9): [True: 0, False: 0]
  ------------------
  789|      0|        qpdf.warn(unsupported("file uses encryption SubFilters, which qpdf does not support"));
  790|      0|    }
  791|       |
  792|      0|    if (!(encryption_dict.getKey("/V").isInteger() && encryption_dict.getKey("/R").isInteger() &&
  ------------------
  |  Branch (792:9): [True: 0, False: 0]
  |  Branch (792:11): [True: 0, False: 0]
  |  Branch (792:55): [True: 0, False: 0]
  ------------------
  793|      0|          encryption_dict.getKey("/O").isString() && encryption_dict.getKey("/U").isString() &&
  ------------------
  |  Branch (793:11): [True: 0, False: 0]
  |  Branch (793:54): [True: 0, False: 0]
  ------------------
  794|      0|          encryption_dict.getKey("/P").isInteger())) {
  ------------------
  |  Branch (794:11): [True: 0, False: 0]
  ------------------
  795|      0|        throw_damaged_pdf("some encryption dictionary parameters are missing or the wrong type");
  796|      0|    }
  797|       |
  798|      0|    int V = encryption_dict.getKey("/V").getIntValueAsInt();
  799|      0|    int R = encryption_dict.getKey("/R").getIntValueAsInt();
  800|      0|    std::string O = encryption_dict.getKey("/O").getStringValue();
  801|      0|    std::string U = encryption_dict.getKey("/U").getStringValue();
  802|      0|    int p = static_cast<int>(encryption_dict.getKey("/P").getIntValue());
  803|       |
  804|       |    // If supporting new encryption R/V values, remember to update error message inside this if
  805|       |    // statement.
  806|      0|    if (!(2 <= R && R <= 6 && (V == 1 || V == 2 || V == 4 || V == 5))) {
  ------------------
  |  Branch (806:11): [True: 0, False: 0]
  |  Branch (806:21): [True: 0, False: 0]
  |  Branch (806:32): [True: 0, False: 0]
  |  Branch (806:42): [True: 0, False: 0]
  |  Branch (806:52): [True: 0, False: 0]
  |  Branch (806:62): [True: 0, False: 0]
  ------------------
  807|      0|        throw unsupported(
  808|      0|            "Unsupported /R or /V in encryption dictionary; R = " + std::to_string(R) +
  809|      0|            " (max 6), V = " + std::to_string(V) + " (max 5)");
  810|      0|    }
  811|       |
  812|      0|    P_ = std::bitset<32>(static_cast<unsigned long long>(p));
  813|      0|    encryption_V = V;
  814|      0|    R_ = R;
  815|       |
  816|       |    // OE, UE, and Perms are only present if V >= 5.
  817|      0|    std::string OE;
  818|      0|    std::string UE;
  819|      0|    std::string Perms;
  820|       |
  821|      0|    if (V < 5) {
  ------------------
  |  Branch (821:9): [True: 0, False: 0]
  ------------------
  822|       |        // These must be exactly the right number of bytes.
  823|      0|        pad_short_parameter(O, key_bytes);
  824|      0|        pad_short_parameter(U, key_bytes);
  825|      0|        if (!(O.length() == key_bytes && U.length() == key_bytes)) {
  ------------------
  |  Branch (825:15): [True: 0, False: 0]
  |  Branch (825:42): [True: 0, False: 0]
  ------------------
  826|      0|            throw_damaged_pdf("incorrect length for /O and/or /U in encryption dictionary");
  827|      0|        }
  828|      0|    } else {
  829|      0|        if (!(encryption_dict.getKey("/OE").isString() &&
  ------------------
  |  Branch (829:13): [True: 0, False: 0]
  |  Branch (829:15): [True: 0, False: 0]
  ------------------
  830|      0|              encryption_dict.getKey("/UE").isString() &&
  ------------------
  |  Branch (830:15): [True: 0, False: 0]
  ------------------
  831|      0|              encryption_dict.getKey("/Perms").isString())) {
  ------------------
  |  Branch (831:15): [True: 0, False: 0]
  ------------------
  832|      0|            throw_damaged_pdf(
  833|      0|                "some V=5 encryption dictionary parameters are missing or the wrong type");
  834|      0|        }
  835|      0|        OE = encryption_dict.getKey("/OE").getStringValue();
  836|      0|        UE = encryption_dict.getKey("/UE").getStringValue();
  837|      0|        Perms = encryption_dict.getKey("/Perms").getStringValue();
  838|       |
  839|       |        // These may be longer than the minimum number of bytes.
  840|      0|        pad_short_parameter(O, OU_key_bytes_V5);
  841|      0|        pad_short_parameter(U, OU_key_bytes_V5);
  842|      0|        pad_short_parameter(OE, OUE_key_bytes_V5);
  843|      0|        pad_short_parameter(UE, OUE_key_bytes_V5);
  844|      0|        pad_short_parameter(Perms, Perms_key_bytes_V5);
  845|      0|    }
  846|       |
  847|      0|    int Length = 128; // Just take a guess.
  848|      0|    if (V <= 1) {
  ------------------
  |  Branch (848:9): [True: 0, False: 0]
  ------------------
  849|      0|        Length = 40;
  850|      0|    } else if (V == 4) {
  ------------------
  |  Branch (850:16): [True: 0, False: 0]
  ------------------
  851|      0|        Length = 128;
  852|      0|    } else if (V == 5) {
  ------------------
  |  Branch (852:16): [True: 0, False: 0]
  ------------------
  853|      0|        Length = 256;
  854|      0|    } else {
  855|      0|        if (encryption_dict.getKey("/Length").isInteger()) {
  ------------------
  |  Branch (855:13): [True: 0, False: 0]
  ------------------
  856|      0|            Length = encryption_dict.getKey("/Length").getIntValueAsInt();
  857|      0|            if (Length % 8 || Length < 40 || Length > 128) {
  ------------------
  |  Branch (857:17): [True: 0, False: 0]
  |  Branch (857:31): [True: 0, False: 0]
  |  Branch (857:46): [True: 0, False: 0]
  ------------------
  858|      0|                Length = 128; // Just take a guess.
  859|      0|            }
  860|      0|        }
  861|      0|    }
  862|       |
  863|      0|    encrypt_metadata = true;
  864|      0|    if (V >= 4 && encryption_dict.getKey("/EncryptMetadata").isBool()) {
  ------------------
  |  Branch (864:9): [True: 0, False: 0]
  |  Branch (864:9): [True: 0, False: 0]
  |  Branch (864:19): [True: 0, False: 0]
  ------------------
  865|      0|        encrypt_metadata = encryption_dict.getKey("/EncryptMetadata").getBoolValue();
  866|      0|    }
  867|       |
  868|      0|    if (V == 4 || V == 5) {
  ------------------
  |  Branch (868:9): [True: 0, False: 0]
  |  Branch (868:19): [True: 0, False: 0]
  ------------------
  869|      0|        auto CF = encryption_dict.getKey("/CF");
  870|      0|        for (auto const& [filter, cdict]: CF.as_dictionary()) {
  ------------------
  |  Branch (870:41): [True: 0, False: 0]
  ------------------
  871|      0|            if (cdict.isDictionary()) {
  ------------------
  |  Branch (871:17): [True: 0, False: 0]
  ------------------
  872|      0|                encryption_method_e method = e_none;
  873|      0|                if (Name const& CFM = cdict["/CFM"]) {
  ------------------
  |  Branch (873:33): [True: 0, False: 0]
  ------------------
  874|      0|                    if (CFM == "/V2") {
  ------------------
  |  Branch (874:25): [True: 0, False: 0]
  ------------------
  875|      0|                        method = e_rc4;
  876|      0|                    } else if (CFM == "/AESV2") {
  ------------------
  |  Branch (876:32): [True: 0, False: 0]
  ------------------
  877|      0|                        method = e_aes;
  878|      0|                    } else if (CFM == "/AESV3") {
  ------------------
  |  Branch (878:32): [True: 0, False: 0]
  ------------------
  879|      0|                        method = e_aesv3;
  880|      0|                    } else {
  881|       |                        // Don't complain now -- maybe we won't need to reference this type.
  882|      0|                        method = e_unknown;
  883|      0|                    }
  884|      0|                }
  885|      0|                crypt_filters[filter] = method;
  886|      0|            }
  887|      0|        }
  888|       |
  889|      0|        cf_stream = interpretCF(encryption_dict["/StmF"]);
  890|      0|        cf_string = interpretCF(encryption_dict["/StrF"]);
  891|      0|        if (Name const& EFF = encryption_dict["/EFF"]) {
  ------------------
  |  Branch (891:25): [True: 0, False: 0]
  ------------------
  892|       |            // qpdf does not use this for anything other than informational purposes. This is
  893|       |            // intended to instruct conforming writers on which crypt filter should be used when new
  894|       |            // file attachments are added to a PDF file, but qpdf never generates encrypted files
  895|       |            // with non-default crypt filters. Prior to 10.2, I was under the mistaken impression
  896|       |            // that this was supposed to be used for decrypting attachments, but the code was wrong
  897|       |            // in a way that turns out not to have mattered because no writers were generating files
  898|       |            // the way I was imagining. Still, providing this information could be useful when
  899|       |            // looking at a file generated by something else, such as Acrobat when specifying that
  900|       |            // only attachments should be encrypted.
  901|      0|            cf_file = interpretCF(EFF);
  902|      0|        } else {
  903|      0|            cf_file = cf_stream;
  904|      0|        }
  905|      0|    }
  906|       |
  907|      0|    Encryption data(V, R, Length / 8, p, O, U, OE, UE, Perms, id1, encrypt_metadata);
  908|      0|    if (qm.cf.password_is_hex_key()) {
  ------------------
  |  Branch (908:9): [True: 0, False: 0]
  ------------------
  909|       |        // ignore passwords in file
  910|      0|        encryption_key = QUtil::hex_decode(provided_password);
  911|      0|        return;
  912|      0|    }
  913|       |
  914|      0|    owner_password_matched = data.check_owner_password(user_password, provided_password);
  915|      0|    if (owner_password_matched && V < 5) {
  ------------------
  |  Branch (915:9): [True: 0, False: 0]
  |  Branch (915:35): [True: 0, False: 0]
  ------------------
  916|       |        // password supplied was owner password; user_password has been initialized for V < 5
  917|      0|        if (qpdf.getTrimmedUserPassword() == provided_password) {
  ------------------
  |  Branch (917:13): [True: 0, False: 0]
  ------------------
  918|      0|            user_password_matched = true;
  919|      0|            QTC::TC("qpdf", "QPDF_encryption user matches owner V < 5");
  920|      0|        }
  921|      0|    } else {
  922|      0|        user_password_matched = data.check_user_password(provided_password);
  923|      0|        if (user_password_matched) {
  ------------------
  |  Branch (923:13): [True: 0, False: 0]
  ------------------
  924|      0|            user_password = provided_password;
  925|      0|        }
  926|      0|    }
  927|      0|    if (user_password_matched && owner_password_matched) {
  ------------------
  |  Branch (927:9): [True: 0, False: 0]
  |  Branch (927:34): [True: 0, False: 0]
  ------------------
  928|      0|        QTC::TC("qpdf", "QPDF_encryption same password", (V < 5) ? 0 : 1);
  ------------------
  |  Branch (928:58): [True: 0, False: 0]
  ------------------
  929|      0|    }
  930|      0|    if (!(owner_password_matched || user_password_matched)) {
  ------------------
  |  Branch (930:11): [True: 0, False: 0]
  |  Branch (930:37): [True: 0, False: 0]
  ------------------
  931|      0|        throw QPDFExc(qpdf_e_password, file->getName(), "", 0, "invalid password");
  932|      0|    }
  933|       |
  934|      0|    if (V < 5) {
  ------------------
  |  Branch (934:9): [True: 0, False: 0]
  ------------------
  935|       |        // For V < 5, the user password is encrypted with the owner password, and the user password
  936|       |        // is always used for computing the encryption key.
  937|      0|        encryption_key = data.compute_encryption_key(user_password);
  938|      0|    } else {
  939|       |        // For V >= 5, either password can be used independently to compute the encryption key, and
  940|       |        // neither password can be used to recover the other.
  941|      0|        bool perms_valid;
  942|      0|        encryption_key = data.recover_encryption_key_with_password(provided_password, perms_valid);
  943|      0|        if (!perms_valid) {
  ------------------
  |  Branch (943:13): [True: 0, False: 0]
  ------------------
  944|      0|            warn_damaged_pdf("/Perms field in encryption dictionary doesn't match expected value");
  945|      0|        }
  946|      0|    }
  947|      0|}

_ZN4QPDF11JSONReactor5errorExRKNSt3__112basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEE:
  310|  49.9k|{
  311|  49.9k|    errors = true;
  312|  49.9k|    std::string object = this->cur_object;
  313|  49.9k|    if (is->getName() != pdf.getFilename()) {
  ------------------
  |  Branch (313:9): [True: 0, False: 49.9k]
  ------------------
  314|      0|        object += " from " + is->getName();
  315|      0|    }
  316|  49.9k|    pdf.warn(qpdf_e_json, object, offset, msg);
  317|  49.9k|}
_ZNK4QPDF11JSONReactor9anyErrorsEv:
  321|     51|{
  322|     51|    return errors;
  323|     51|}
_ZN4QPDF11JSONReactor14containerStartEv:
  327|  82.8k|{
  328|  82.8k|    if (next_obj) {
  ------------------
  |  Branch (328:9): [True: 49.6k, False: 33.2k]
  ------------------
  329|  49.6k|        stack.emplace_back(next_state, std::move(next_obj));
  330|  49.6k|        next_obj = QPDFObjectHandle();
  331|  49.6k|    } else {
  332|  33.2k|        stack.emplace_back(next_state);
  333|  33.2k|    }
  334|  82.8k|}
_ZN4QPDF11JSONReactor15dictionaryStartEv:
  338|  61.5k|{
  339|  61.5k|    containerStart();
  340|  61.5k|}
_ZN4QPDF11JSONReactor10arrayStartEv:
  344|  21.6k|{
  345|  21.6k|    if (stack.empty()) {
  ------------------
  |  Branch (345:9): [True: 339, False: 21.3k]
  ------------------
  346|    339|        QTC::TC("qpdf", "QPDF_json top-level array");
  347|    339|        throw std::runtime_error("QPDF JSON must be a dictionary");
  348|    339|    }
  349|  21.3k|    containerStart();
  350|  21.3k|}
_ZN4QPDF11JSONReactor12containerEndERK4JSON:
  354|  31.3k|{
  355|  31.3k|    auto from_state = stack.back().state;
  356|  31.3k|    stack.pop_back();
  357|  31.3k|    if (stack.empty()) {
  ------------------
  |  Branch (357:9): [True: 62, False: 31.3k]
  ------------------
  358|     62|        if (!this->saw_qpdf) {
  ------------------
  |  Branch (358:13): [True: 20, False: 42]
  ------------------
  359|     20|            QTC::TC("qpdf", "QPDF_json missing qpdf");
  360|     20|            error(0, "\"qpdf\" object was not seen");
  361|     42|        } else {
  362|     42|            if (!this->saw_json_version) {
  ------------------
  |  Branch (362:17): [True: 34, False: 8]
  ------------------
  363|     34|                QTC::TC("qpdf", "QPDF_json missing json version");
  364|     34|                error(0, "\"qpdf[0].jsonversion\" was not seen");
  365|     34|            }
  366|     42|            if (must_be_complete && !this->saw_pdf_version) {
  ------------------
  |  Branch (366:17): [True: 41, False: 1]
  |  Branch (366:37): [True: 33, False: 8]
  ------------------
  367|     33|                QTC::TC("qpdf", "QPDF_json missing pdf version");
  368|     33|                error(0, "\"qpdf[0].pdfversion\" was not seen");
  369|     33|            }
  370|     42|            if (!this->saw_objects) {
  ------------------
  |  Branch (370:17): [True: 8, False: 34]
  ------------------
  371|      8|                QTC::TC("qpdf", "QPDF_json missing objects");
  372|      8|                error(0, "\"qpdf[1]\" was not seen");
  373|     34|            } else {
  374|     34|                if (must_be_complete && !this->saw_trailer) {
  ------------------
  |  Branch (374:21): [True: 32, False: 2]
  |  Branch (374:41): [True: 24, False: 8]
  ------------------
  375|     24|                    QTC::TC("qpdf", "QPDF_json missing trailer");
  376|     24|                    error(0, "\"qpdf[1].trailer\" was not seen");
  377|     24|                }
  378|     34|            }
  379|     42|        }
  380|  31.3k|    } else if (from_state == st_trailer) {
  ------------------
  |  Branch (380:16): [True: 884, False: 30.4k]
  ------------------
  381|    884|        if (!saw_value) {
  ------------------
  |  Branch (381:13): [True: 433, False: 451]
  ------------------
  382|    433|            QTC::TC("qpdf", "QPDF_json trailer no value");
  383|    433|            error(value.getStart(), "\"trailer\" is missing \"value\"");
  384|    433|        }
  385|  30.4k|    } else if (from_state == st_object_top) {
  ------------------
  |  Branch (385:16): [True: 9.78k, False: 20.6k]
  ------------------
  386|  9.78k|        if (saw_value == saw_stream) {
  ------------------
  |  Branch (386:13): [True: 979, False: 8.80k]
  ------------------
  387|    979|            QTC::TC("qpdf", "QPDF_json value stream both or neither");
  388|    979|            error(value.getStart(), "object must have exactly one of \"value\" or \"stream\"");
  389|    979|        }
  390|  9.78k|        if (saw_stream) {
  ------------------
  |  Branch (390:13): [True: 4.13k, False: 5.64k]
  ------------------
  391|  4.13k|            if (!saw_dict) {
  ------------------
  |  Branch (391:17): [True: 1.65k, False: 2.48k]
  ------------------
  392|  1.65k|                QTC::TC("qpdf", "QPDF_json stream no dict");
  393|  1.65k|                error(value.getStart(), "\"stream\" is missing \"dict\"");
  394|  1.65k|            }
  395|  4.13k|            if (saw_data == saw_datafile) {
  ------------------
  |  Branch (395:17): [True: 1.23k, False: 2.90k]
  ------------------
  396|  1.23k|                if (this_stream_needs_data) {
  ------------------
  |  Branch (396:21): [True: 701, False: 531]
  ------------------
  397|    701|                    QTC::TC("qpdf", "QPDF_json data datafile both or neither");
  398|    701|                    error(
  399|    701|                        value.getStart(),
  400|    701|                        "new \"stream\" must have exactly one of \"data\" or \"datafile\"");
  401|    701|                } else if (saw_datafile) {
  ------------------
  |  Branch (401:28): [True: 165, False: 366]
  ------------------
  402|    165|                    QTC::TC("qpdf", "QPDF_json data and datafile");
  403|    165|                    error(
  404|    165|                        value.getStart(),
  405|    165|                        "existing \"stream\" may at most one of \"data\" or \"datafile\"");
  406|    366|                } else {
  407|    366|                    QTC::TC("qpdf", "QPDF_json no stream data in update mode");
  408|    366|                }
  409|  1.23k|            }
  410|  4.13k|        }
  411|  9.78k|    }
  412|  31.3k|    if (!stack.empty()) {
  ------------------
  |  Branch (412:9): [True: 31.3k, False: 68]
  ------------------
  413|  31.3k|        auto state = stack.back().state;
  414|  31.3k|        if (state == st_objects) {
  ------------------
  |  Branch (414:13): [True: 12.1k, False: 19.2k]
  ------------------
  415|  12.1k|            this->cur_object = "";
  416|  12.1k|            this->saw_dict = false;
  417|  12.1k|            this->saw_data = false;
  418|  12.1k|            this->saw_datafile = false;
  419|  12.1k|            this->saw_value = false;
  420|  12.1k|            this->saw_stream = false;
  421|  12.1k|        }
  422|  31.3k|    }
  423|  31.3k|}
_ZN4QPDF11JSONReactor13replaceObjectEO16QPDFObjectHandleRK4JSON:
  427|  18.0k|{
  428|  18.0k|    auto& tos = stack.back();
  429|  18.0k|    auto og = tos.object.getObjGen();
  430|  18.0k|    if (replacement.isIndirect() && !(replacement.isStream() && replacement.getObjGen() == og)) {
  ------------------
  |  Branch (430:9): [True: 4.27k, False: 13.7k]
  |  Branch (430:9): [True: 669, False: 17.3k]
  |  Branch (430:39): [True: 3.86k, False: 409]
  |  Branch (430:65): [True: 3.60k, False: 260]
  ------------------
  431|    669|        error(
  432|    669|            replacement.offset(), "the value of an object may not be an indirect object reference");
  433|    669|        return;
  434|    669|    }
  435|  17.3k|    pdf.replaceObject(og, replacement);
  436|  17.3k|    next_obj = pdf.getObject(og);
  437|  17.3k|    setObjectDescription(tos.object, value);
  438|  17.3k|}
_ZN4QPDF11JSONReactor14topLevelScalarEv:
  442|     68|{
  443|     68|    QTC::TC("qpdf", "QPDF_json top-level scalar");
  444|     68|    throw std::runtime_error("QPDF JSON must be a dictionary");
  445|     68|}
_ZN4QPDF11JSONReactor24setNextStateIfDictionaryERKNSt3__112basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEERK4JSONNS0_7state_eE:
  449|  37.7k|{
  450|       |    // Use this method when the next state is for processing a nested dictionary.
  451|  37.7k|    if (value.isDictionary()) {
  ------------------
  |  Branch (451:9): [True: 31.1k, False: 6.55k]
  ------------------
  452|  31.1k|        this->next_state = next;
  453|  31.1k|        return true;
  454|  31.1k|    }
  455|  6.55k|    error(value.getStart(), "\"" + key + "\" must be a dictionary");
  456|  6.55k|    return false;
  457|  37.7k|}
_ZN4QPDF11JSONReactor14dictionaryItemERKNSt3__112basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEERK4JSON:
  461|   185k|{
  462|   185k|    if (stack.empty()) {
  ------------------
  |  Branch (462:9): [True: 0, False: 185k]
  ------------------
  463|      0|        throw std::logic_error("stack is empty in dictionaryItem");
  464|      0|    }
  465|   185k|    next_state = st_ignore;
  466|   185k|    auto state = stack.back().state;
  467|   185k|    if (state == st_ignore) {
  ------------------
  |  Branch (467:9): [True: 4.84k, False: 180k]
  ------------------
  468|  4.84k|        return true; // ignore
  469|  4.84k|    }
  470|   180k|    if (state == st_top) {
  ------------------
  |  Branch (470:9): [True: 9.99k, False: 170k]
  ------------------
  471|  9.99k|        if (key == "qpdf") {
  ------------------
  |  Branch (471:13): [True: 6.51k, False: 3.47k]
  ------------------
  472|  6.51k|            saw_qpdf = true;
  473|  6.51k|            if (!value.isArray()) {
  ------------------
  |  Branch (473:17): [True: 789, False: 5.72k]
  ------------------
  474|    789|                error(value.getStart(), "\"qpdf\" must be an array");
  475|  5.72k|            } else {
  476|  5.72k|                next_state = st_qpdf;
  477|  5.72k|            }
  478|  6.51k|            return true;
  479|  6.51k|        }
  480|  3.47k|        return true; // Ignore all other fields.
  481|  9.99k|    }
  482|       |
  483|   170k|    if (state == st_qpdf_meta) {
  ------------------
  |  Branch (483:9): [True: 8.16k, False: 162k]
  ------------------
  484|  8.16k|        if (key == "pdfversion") {
  ------------------
  |  Branch (484:13): [True: 2.45k, False: 5.71k]
  ------------------
  485|  2.45k|            saw_pdf_version = true;
  486|  2.45k|            std::string v;
  487|  2.45k|            if (value.getString(v)) {
  ------------------
  |  Branch (487:17): [True: 1.82k, False: 623]
  ------------------
  488|  1.82k|                std::string version;
  489|  1.82k|                char const* p = v.c_str();
  490|  1.82k|                if (objects.validatePDFVersion(p, version) && *p == '\0') {
  ------------------
  |  Branch (490:21): [True: 963, False: 866]
  |  Branch (490:63): [True: 591, False: 372]
  ------------------
  491|    591|                    pdf.m->pdf_version = version;
  492|    591|                    return true;
  493|    591|                }
  494|  1.82k|            }
  495|  1.86k|            error(value.getStart(), "invalid PDF version (must be \"x.y\")");
  496|  1.86k|            return true;
  497|  2.45k|        }
  498|  5.71k|        if (key == "jsonversion") {
  ------------------
  |  Branch (498:13): [True: 1.60k, False: 4.10k]
  ------------------
  499|  1.60k|            saw_json_version = true;
  500|  1.60k|            std::string v;
  501|  1.60k|            if (value.getNumber(v)) {
  ------------------
  |  Branch (501:17): [True: 1.41k, False: 196]
  ------------------
  502|  1.41k|                std::string version;
  503|  1.41k|                if (QUtil::string_to_int(v.c_str()) == 2) {
  ------------------
  |  Branch (503:21): [True: 266, False: 1.14k]
  ------------------
  504|    266|                    return true;
  505|    266|                }
  506|  1.41k|            }
  507|  1.34k|            error(value.getStart(), "invalid JSON version (must be numeric value 2)");
  508|  1.34k|            return true;
  509|  1.60k|        }
  510|  4.10k|        if (key == "pushedinheritedpageresources") {
  ------------------
  |  Branch (510:13): [True: 787, False: 3.31k]
  ------------------
  511|    787|            bool v;
  512|    787|            if (value.getBool(v)) {
  ------------------
  |  Branch (512:17): [True: 239, False: 548]
  ------------------
  513|    239|                if (!must_be_complete && v) {
  ------------------
  |  Branch (513:21): [True: 0, False: 239]
  |  Branch (513:42): [True: 0, False: 0]
  ------------------
  514|      0|                    pdf.pushInheritedAttributesToPage();
  515|      0|                }
  516|    239|                return true;
  517|    239|            }
  518|    548|            error(value.getStart(), "pushedinheritedpageresources must be a boolean");
  519|    548|            return true;
  520|    787|        }
  521|  3.31k|        if (key == "calledgetallpages") {
  ------------------
  |  Branch (521:13): [True: 649, False: 2.66k]
  ------------------
  522|    649|            bool v;
  523|    649|            if (value.getBool(v)) {
  ------------------
  |  Branch (523:17): [True: 250, False: 399]
  ------------------
  524|    250|                if (!must_be_complete && v) {
  ------------------
  |  Branch (524:21): [True: 0, False: 250]
  |  Branch (524:42): [True: 0, False: 0]
  ------------------
  525|      0|                    (void)pdf.doc().pages().all();
  526|      0|                }
  527|    250|                return true;
  528|    250|            }
  529|    399|            error(value.getStart(), "calledgetallpages must be a boolean");
  530|    399|            return true;
  531|    649|        }
  532|       |        // ignore unknown keys for forward compatibility and to skip keys we don't care about
  533|       |        // like "maxobjectid".
  534|  2.66k|        return true;
  535|  3.31k|    }
  536|       |
  537|   162k|    if (state == st_objects) {
  ------------------
  |  Branch (537:9): [True: 22.2k, False: 140k]
  ------------------
  538|  22.2k|        if (key == "trailer") {
  ------------------
  |  Branch (538:13): [True: 2.87k, False: 19.3k]
  ------------------
  539|  2.87k|            saw_trailer = true;
  540|  2.87k|            cur_object = "trailer";
  541|  2.87k|            setNextStateIfDictionary(key, value, st_trailer);
  542|  2.87k|            return true;
  543|  2.87k|        }
  544|       |
  545|  19.3k|        int obj = 0;
  546|  19.3k|        int gen = 0;
  547|  19.3k|        if (is_obj_key(key, obj, gen)) {
  ------------------
  |  Branch (547:13): [True: 13.7k, False: 5.65k]
  ------------------
  548|  13.7k|            cur_object = key;
  549|  13.7k|            if (setNextStateIfDictionary(key, value, st_object_top)) {
  ------------------
  |  Branch (549:17): [True: 12.6k, False: 1.09k]
  ------------------
  550|  12.6k|                next_obj = objects.getObjectForJSON(obj, gen);
  551|  12.6k|            }
  552|  13.7k|            return true;
  553|  13.7k|        }
  554|  5.65k|        error(value.getStart(), "object key should be \"trailer\" or \"obj:n n R\"");
  555|  5.65k|        return true;
  556|  19.3k|    }
  557|       |
  558|   140k|    if (state == st_object_top) {
  ------------------
  |  Branch (558:9): [True: 22.1k, False: 118k]
  ------------------
  559|  22.1k|        util::assertion(!stack.empty(), "QPDF_json: stack empty in st_object_top");
  560|  22.1k|        auto& tos = stack.back();
  561|  22.1k|        util::assertion(!!tos.object, "current object uninitialized in st_object_top");
  562|  22.1k|        if (key == "value") {
  ------------------
  |  Branch (562:13): [True: 15.0k, False: 7.09k]
  ------------------
  563|       |            // Don't use setNextStateIfDictionary since this can have any type.
  564|  15.0k|            saw_value = true;
  565|  15.0k|            replaceObject(makeObject(value), value);
  566|  15.0k|            next_state = st_object;
  567|  15.0k|            return true;
  568|  15.0k|        }
  569|  7.09k|        if (key == "stream") {
  ------------------
  |  Branch (569:13): [True: 4.89k, False: 2.19k]
  ------------------
  570|  4.89k|            saw_stream = true;
  571|  4.89k|            if (setNextStateIfDictionary(key, value, st_stream)) {
  ------------------
  |  Branch (571:17): [True: 4.55k, False: 337]
  ------------------
  572|  4.55k|                this_stream_needs_data = false;
  573|  4.55k|                if (tos.object.isStream()) {
  ------------------
  |  Branch (573:21): [True: 1.25k, False: 3.30k]
  ------------------
  574|  1.25k|                    QTC::TC("qpdf", "QPDF_json updating existing stream");
  575|  3.30k|                } else {
  576|  3.30k|                    this_stream_needs_data = true;
  577|  3.30k|                    replaceObject(
  578|  3.30k|                        qpdf::Stream(
  579|  3.30k|                            pdf, tos.object.getObjGen(), QPDFObjectHandle::newDictionary(), 0, 0),
  580|  3.30k|                        value);
  581|  3.30k|                }
  582|  4.55k|                next_obj = tos.object;
  583|  4.55k|                return true;
  584|  4.55k|            }
  585|    337|            return true; // Error message already given above
  586|  4.89k|        }
  587|  2.19k|        return true; // Ignore unknown keys for forward compatibility
  588|  7.09k|    }
  589|       |
  590|   118k|    if (state == st_trailer) {
  ------------------
  |  Branch (590:9): [True: 4.74k, False: 113k]
  ------------------
  591|  4.74k|        if (key == "value") {
  ------------------
  |  Branch (591:13): [True: 2.51k, False: 2.23k]
  ------------------
  592|  2.51k|            saw_value = true;
  593|       |            // The trailer must be a dictionary, so we can use setNextStateIfDictionary.
  594|  2.51k|            if (setNextStateIfDictionary("trailer.value", value, st_object)) {
  ------------------
  |  Branch (594:17): [True: 1.97k, False: 537]
  ------------------
  595|  1.97k|                pdf.m->trailer = makeObject(value);
  596|  1.97k|                setObjectDescription(pdf.m->trailer, value);
  597|  1.97k|            }
  598|  2.51k|            return true;
  599|  2.51k|        }
  600|  2.23k|        if (key == "stream") {
  ------------------
  |  Branch (600:13): [True: 394, False: 1.83k]
  ------------------
  601|       |            // Don't need to set saw_stream here since there's already an error.
  602|    394|            error(value.getStart(), "the trailer may not be a stream");
  603|    394|            return true;
  604|    394|        }
  605|  1.83k|        return true; // Ignore unknown keys for forward compatibility
  606|  2.23k|    }
  607|       |
  608|   113k|    if (state == st_stream) {
  ------------------
  |  Branch (608:9): [True: 13.4k, False: 100k]
  ------------------
  609|  13.4k|        util::assertion(!stack.empty(), "stack empty in st_stream");
  610|  13.4k|        auto& tos = stack.back();
  611|  13.4k|        util::assertion(tos.object.isStream(), "current object is not stream in st_stream");
  612|  13.4k|        if (key == "dict") {
  ------------------
  |  Branch (612:13): [True: 3.22k, False: 10.1k]
  ------------------
  613|  3.22k|            saw_dict = true;
  614|  3.22k|            if (setNextStateIfDictionary("stream.dict", value, st_object)) {
  ------------------
  |  Branch (614:17): [True: 2.75k, False: 471]
  ------------------
  615|  2.75k|                tos.object.replaceDict(makeObject(value));
  616|  2.75k|                return true;
  617|  2.75k|            }
  618|    471|            return true; // An error had already been given by setNextStateIfDictionary
  619|  3.22k|        }
  620|  10.1k|        if (key == "data") {
  ------------------
  |  Branch (620:13): [True: 7.67k, False: 2.50k]
  ------------------
  621|  7.67k|            saw_data = true;
  622|  7.67k|            std::string v;
  623|  7.67k|            if (!value.getString(v)) {
  ------------------
  |  Branch (623:17): [True: 2.17k, False: 5.50k]
  ------------------
  624|  2.17k|                error(value.getStart(), "\"stream.data\" must be a string");
  625|  2.17k|                tos.object.replaceStreamData("", {}, {});
  626|  2.17k|                return true;
  627|  2.17k|            }
  628|       |            // The range includes the quotes.
  629|  5.50k|            auto start = value.getStart() + 1;
  630|  5.50k|            auto end = value.getEnd() - 1;
  631|  5.50k|            util::assertion(end >= start, "QPDF_json: JSON string length < 0");
  632|  5.50k|            tos.object.replaceStreamData(provide_data(is, start, end), {}, {});
  633|  5.50k|            return true;
  634|  7.67k|        }
  635|  2.50k|        if (key == "datafile") {
  ------------------
  |  Branch (635:13): [True: 1.71k, False: 783]
  ------------------
  636|  1.71k|            saw_datafile = true;
  637|  1.71k|            std::string filename;
  638|  1.71k|            if (!value.getString(filename)) {
  ------------------
  |  Branch (638:17): [True: 399, False: 1.32k]
  ------------------
  639|    399|                error(
  640|    399|                    value.getStart(),
  641|    399|                    "\"stream.datafile\" must be a string containing a file name");
  642|    399|                tos.object.replaceStreamData("", {}, {});
  643|    399|                return true;
  644|    399|            }
  645|  1.32k|            tos.object.replaceStreamData(QUtil::file_provider(filename), {}, {});
  646|  1.32k|            return true;
  647|  1.71k|        }
  648|    783|        return true; // Ignore unknown keys for forward compatibility.
  649|  2.50k|    }
  650|       |
  651|   100k|    util::assertion(state == st_object, "QPDF_json: unknown state " + std::to_string(state));
  652|   100k|    util::assertion(!stack.empty(), "stack empty in st_object");
  653|   100k|    auto& tos = stack.back();
  654|   100k|    auto dict = tos.object;
  655|   100k|    if (dict.isStream()) {
  ------------------
  |  Branch (655:9): [True: 0, False: 100k]
  ------------------
  656|      0|        dict = dict.getDict();
  657|      0|    }
  658|   100k|    util::assertion(
  659|   100k|        dict.isDictionary(),
  660|   100k|        "current object is not stream or dictionary in st_object dictionary item");
  661|   100k|    dict.replaceKey(
  662|   100k|        is_pdf_name(key) ? QPDFObjectHandle::parse(key.substr(2)).getName() : key,
  ------------------
  |  Branch (662:9): [True: 4.47k, False: 95.6k]
  ------------------
  663|   100k|        makeObject(value));
  664|   100k|    return true;
  665|   113k|}
_ZN4QPDF11JSONReactor9arrayItemERK4JSON:
  669|  1.86M|{
  670|  1.86M|    if (stack.empty()) {
  ------------------
  |  Branch (670:9): [True: 0, False: 1.86M]
  ------------------
  671|      0|        throw std::logic_error("stack is empty in arrayItem");
  672|      0|    }
  673|  1.86M|    next_state = st_ignore;
  674|  1.86M|    auto state = stack.back().state;
  675|  1.86M|    if (state == st_qpdf) {
  ------------------
  |  Branch (675:9): [True: 14.5k, False: 1.84M]
  ------------------
  676|  14.5k|        if (!this->saw_qpdf_meta) {
  ------------------
  |  Branch (676:13): [True: 5.53k, False: 9.01k]
  ------------------
  677|  5.53k|            this->saw_qpdf_meta = true;
  678|  5.53k|            setNextStateIfDictionary("qpdf[0]", value, st_qpdf_meta);
  679|  9.01k|        } else if (!this->saw_objects) {
  ------------------
  |  Branch (679:20): [True: 4.97k, False: 4.04k]
  ------------------
  680|  4.97k|            this->saw_objects = true;
  681|  4.97k|            setNextStateIfDictionary("qpdf[1]", value, st_objects);
  682|  4.97k|        } else {
  683|  4.04k|            QTC::TC("qpdf", "QPDF_json more than two qpdf elements");
  684|  4.04k|            error(value.getStart(), "\"qpdf\" must have two elements");
  685|  4.04k|        }
  686|  1.84M|    } else if (state == st_object) {
  ------------------
  |  Branch (686:16): [True: 1.83M, False: 6.65k]
  ------------------
  687|  1.83M|        stack.back().object.appendItem(makeObject(value));
  688|  1.83M|    }
  689|  1.86M|    return true;
  690|  1.86M|}
_ZN4QPDF11JSONReactor20setObjectDescriptionER16QPDFObjectHandleRK4JSON:
  694|  1.23M|{
  695|  1.23M|    auto j_descr = std::get<QPDFObject::JSON_Descr>(*descr);
  696|  1.23M|    if (j_descr.object != cur_object) {
  ------------------
  |  Branch (696:9): [True: 10.7k, False: 1.22M]
  ------------------
  697|  10.7k|        descr = std::make_shared<QPDFObject::Description>(
  698|  10.7k|            QPDFObject::JSON_Descr(j_descr.input, cur_object));
  699|  10.7k|    }
  700|       |
  701|  1.23M|    oh.obj_sp()->setDescription(&pdf, descr, value.getStart());
  702|  1.23M|}
_ZN4QPDF11JSONReactor10makeObjectERK4JSON:
  706|  1.95M|{
  707|  1.95M|    QPDFObjectHandle result;
  708|  1.95M|    std::string str_v;
  709|  1.95M|    bool bool_v = false;
  710|  1.95M|    if (value.isDictionary()) {
  ------------------
  |  Branch (710:9): [True: 20.3k, False: 1.93M]
  ------------------
  711|  20.3k|        result = QPDFObjectHandle::newDictionary();
  712|  20.3k|        next_obj = result;
  713|  20.3k|        next_state = st_object;
  714|  1.93M|    } else if (value.isArray()) {
  ------------------
  |  Branch (714:16): [True: 11.8k, False: 1.92M]
  ------------------
  715|  11.8k|        result = QPDFObjectHandle::newArray();
  716|  11.8k|        next_obj = result;
  717|  11.8k|        next_state = st_object;
  718|  1.92M|    } else if (value.isNull()) {
  ------------------
  |  Branch (718:16): [True: 4.39k, False: 1.92M]
  ------------------
  719|  4.39k|        result = QPDFObjectHandle::newNull();
  720|  1.92M|    } else if (value.getBool(bool_v)) {
  ------------------
  |  Branch (720:16): [True: 5.58k, False: 1.91M]
  ------------------
  721|  5.58k|        result = QPDFObjectHandle::newBool(bool_v);
  722|  1.91M|    } else if (value.getNumber(str_v)) {
  ------------------
  |  Branch (722:16): [True: 1.13M, False: 786k]
  ------------------
  723|  1.13M|        if (QUtil::is_long_long(str_v.c_str())) {
  ------------------
  |  Branch (723:13): [True: 1.12M, False: 8.60k]
  ------------------
  724|  1.12M|            result = QPDFObjectHandle::newInteger(QUtil::string_to_ll(str_v.c_str()));
  725|  1.12M|        } else {
  726|       |            // JSON allows scientific notation, but PDF does not.
  727|  8.60k|            if (str_v.find('e') != std::string::npos || str_v.find('E') != std::string::npos) {
  ------------------
  |  Branch (727:17): [True: 1.03k, False: 7.56k]
  |  Branch (727:57): [True: 5.71k, False: 1.85k]
  ------------------
  728|  6.74k|                try {
  729|  6.74k|                    auto v = std::stod(str_v);
  730|  6.74k|                    str_v = QUtil::double_to_string(v);
  731|  6.74k|                } catch (std::exception&) {
  732|       |                    // Keep it as it was
  733|    223|                }
  734|  6.74k|            }
  735|  8.60k|            result = QPDFObjectHandle::newReal(str_v);
  736|  8.60k|        }
  737|  1.13M|    } else if (value.getString(str_v)) {
  ------------------
  |  Branch (737:16): [True: 786k, False: 0]
  ------------------
  738|   786k|        int obj = 0;
  739|   786k|        int gen = 0;
  740|   786k|        std::string str;
  741|   786k|        if (is_indirect_object(str_v, obj, gen)) {
  ------------------
  |  Branch (741:13): [True: 740k, False: 45.7k]
  ------------------
  742|   740k|            result = objects.getObjectForJSON(obj, gen);
  743|   740k|        } else if (is_unicode_string(str_v, str)) {
  ------------------
  |  Branch (743:20): [True: 5.84k, False: 39.9k]
  ------------------
  744|  5.84k|            result = QPDFObjectHandle::newUnicodeString(str);
  745|  39.9k|        } else if (is_binary_string(str_v, str)) {
  ------------------
  |  Branch (745:20): [True: 1.17k, False: 38.7k]
  ------------------
  746|  1.17k|            result = QPDFObjectHandle::newString(QUtil::hex_decode(str));
  747|  38.7k|        } else if (is_name(str_v)) {
  ------------------
  |  Branch (747:20): [True: 10.8k, False: 27.8k]
  ------------------
  748|  10.8k|            result = QPDFObjectHandle::newName(str_v);
  749|  27.8k|        } else if (is_pdf_name(str_v)) {
  ------------------
  |  Branch (749:20): [True: 6.69k, False: 21.1k]
  ------------------
  750|  6.69k|            result = QPDFObjectHandle::parse(str_v.substr(2));
  751|  21.1k|        } else {
  752|  21.1k|            QTC::TC("qpdf", "QPDF_json unrecognized string value");
  753|  21.1k|            error(value.getStart(), "unrecognized string value");
  754|  21.1k|            result = QPDFObjectHandle::newNull();
  755|  21.1k|        }
  756|   786k|    }
  757|  1.95M|    if (!result) {
  ------------------
  |  Branch (757:9): [True: 0, False: 1.95M]
  ------------------
  758|      0|        throw std::logic_error("JSONReactor::makeObject didn't initialize the object");
  759|      0|    }
  760|       |
  761|  1.95M|    if (!result.hasObjectDescription()) {
  ------------------
  |  Branch (761:9): [True: 1.21M, False: 746k]
  ------------------
  762|  1.21M|        setObjectDescription(result, value);
  763|  1.21M|    }
  764|  1.95M|    return result;
  765|  1.95M|}
_ZN4QPDF14createFromJSONENSt3__110shared_ptrI11InputSourceEE:
  775|  7.72k|{
  776|  7.72k|    auto mw = m->cf.max_warnings();
  777|  7.72k|    (void)m->cf.max_warnings(0);
  778|  7.72k|    processMemoryFile(is->getName().c_str(), JSON_PDF, strlen(JSON_PDF));
  779|  7.72k|    (void)m->cf.max_warnings(mw);
  780|  7.72k|    importJSON(is, true);
  781|  7.72k|    (void)m->cf.max_warnings(0);
  782|  7.72k|}
_ZN4QPDF10importJSONENSt3__110shared_ptrI11InputSourceEEb:
  798|  7.72k|{
  799|  7.72k|    JSONReactor reactor(*this, is, must_be_complete);
  800|  7.72k|    try {
  801|  7.72k|        JSON::parse(*is, &reactor);
  802|  7.72k|    } catch (std::runtime_error& e) {
  803|  7.67k|        throw std::runtime_error(is->getName() + ": " + e.what());
  804|  7.67k|    }
  805|     51|    if (reactor.anyErrors()) {
  ------------------
  |  Branch (805:9): [True: 45, False: 6]
  ------------------
  806|     45|        throw std::runtime_error(is->getName() + ": errors found in JSON");
  807|     45|    }
  808|     51|}
QPDF_json.cc:_ZL18is_indirect_objectRKNSt3__112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEERiS8_:
   71|   801k|{
   72|   801k|    char const* p = v.c_str();
   73|   801k|    std::string o_str;
   74|   801k|    std::string g_str;
   75|   801k|    if (!util::is_digit(*p)) {
  ------------------
  |  Branch (75:9): [True: 40.1k, False: 761k]
  ------------------
   76|  40.1k|        return false;
   77|  40.1k|    }
   78|  1.62M|    while (util::is_digit(*p)) {
  ------------------
  |  Branch (78:12): [True: 865k, False: 761k]
  ------------------
   79|   865k|        o_str.append(1, *p++);
   80|   865k|    }
   81|   761k|    if (*p != ' ') {
  ------------------
  |  Branch (81:9): [True: 1.75k, False: 759k]
  ------------------
   82|  1.75k|        return false;
   83|  1.75k|    }
   84|  4.48M|    while (*p == ' ') {
  ------------------
  |  Branch (84:12): [True: 3.72M, False: 759k]
  ------------------
   85|  3.72M|        ++p;
   86|  3.72M|    }
   87|   759k|    if (!util::is_digit(*p)) {
  ------------------
  |  Branch (87:9): [True: 1.71k, False: 758k]
  ------------------
   88|  1.71k|        return false;
   89|  1.71k|    }
   90|  3.89M|    while (util::is_digit(*p)) {
  ------------------
  |  Branch (90:12): [True: 3.14M, False: 758k]
  ------------------
   91|  3.14M|        g_str.append(1, *p++);
   92|  3.14M|    }
   93|   758k|    if (*p != ' ') {
  ------------------
  |  Branch (93:9): [True: 1.07k, False: 757k]
  ------------------
   94|  1.07k|        return false;
   95|  1.07k|    }
   96|  8.76M|    while (*p == ' ') {
  ------------------
  |  Branch (96:12): [True: 8.00M, False: 757k]
  ------------------
   97|  8.00M|        ++p;
   98|  8.00M|    }
   99|   757k|    if (*p++ != 'R') {
  ------------------
  |  Branch (99:9): [True: 2.04k, False: 755k]
  ------------------
  100|  2.04k|        return false;
  101|  2.04k|    }
  102|   755k|    if (*p) {
  ------------------
  |  Branch (102:9): [True: 789, False: 754k]
  ------------------
  103|    789|        return false;
  104|    789|    }
  105|   754k|    obj = QUtil::string_to_int(o_str.c_str());
  106|   754k|    gen = QUtil::string_to_int(g_str.c_str());
  107|   754k|    return obj > 0;
  108|   755k|}
QPDF_json.cc:_ZL10is_obj_keyRKNSt3__112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEERiS8_:
  112|  19.3k|{
  113|  19.3k|    if (v.substr(0, 4) != "obj:") {
  ------------------
  |  Branch (113:9): [True: 3.52k, False: 15.8k]
  ------------------
  114|  3.52k|        return false;
  115|  3.52k|    }
  116|  15.8k|    return is_indirect_object(v.substr(4), obj, gen);
  117|  19.3k|}
QPDF_json.cc:_ZL17is_unicode_stringRKNSt3__112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEERS5_:
  121|  45.7k|{
  122|  45.7k|    if (v.substr(0, 2) == "u:") {
  ------------------
  |  Branch (122:9): [True: 5.84k, False: 39.8k]
  ------------------
  123|  5.84k|        str = v.substr(2);
  124|  5.84k|        return true;
  125|  5.84k|    }
  126|  39.8k|    return false;
  127|  45.7k|}
QPDF_json.cc:_ZL16is_binary_stringRKNSt3__112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEERS5_:
  131|  39.8k|{
  132|  39.8k|    if (v.substr(0, 2) == "b:") {
  ------------------
  |  Branch (132:9): [True: 2.49k, False: 37.4k]
  ------------------
  133|  2.49k|        str = v.substr(2);
  134|  2.49k|        int count = 0;
  135|  26.3k|        for (char c: str) {
  ------------------
  |  Branch (135:20): [True: 26.3k, False: 1.27k]
  ------------------
  136|  26.3k|            if (!util::is_hex_digit(c)) {
  ------------------
  |  Branch (136:17): [True: 1.21k, False: 25.1k]
  ------------------
  137|  1.21k|                return false;
  138|  1.21k|            }
  139|  25.1k|            ++count;
  140|  25.1k|        }
  141|  1.27k|        return (count % 2 == 0);
  142|  2.49k|    }
  143|  37.4k|    return false;
  144|  39.8k|}
QPDF_json.cc:_ZL7is_nameRKNSt3__112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEE:
  148|  38.7k|{
  149|  38.7k|    return v.starts_with('/');
  150|  38.7k|}
QPDF_json.cc:_ZL11is_pdf_nameRKNSt3__112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEE:
  154|   128k|{
  155|   128k|    return v.starts_with("n:/");
  156|   128k|}
_ZN4QPDF11JSONReactor10StackFrameC2ENS0_7state_eEO16QPDFObjectHandle:
  271|  49.6k|            state(state),
  272|  49.6k|            object(object) {};
_ZN4QPDF11JSONReactor10StackFrameC2ENS0_7state_eE:
  269|  33.2k|            state(state) {};
QPDF_json.cc:_ZL12provide_dataNSt3__110shared_ptrI11InputSourceEExx:
  222|  5.50k|{
  223|  5.50k|    return [is, start, end](Pipeline* p) {
  224|  5.50k|        auto data = is->read(QIntC::to_size(end - start), start);
  225|  5.50k|        data = Pl_Base64::decode(data);
  226|  5.50k|        p->write(reinterpret_cast<const unsigned char*>(data.data()), data.size());
  227|  5.50k|        p->finish();
  228|  5.50k|    };
  229|  5.50k|}
_ZN4QPDF11JSONReactorC2ERS_NSt3__110shared_ptrI11InputSourceEEb:
  235|  7.72k|        pdf(pdf),
  236|  7.72k|        is(is),
  237|  7.72k|        must_be_complete(must_be_complete),
  238|       |        descr(
  239|  7.72k|            std::make_shared<QPDFObject::Description>(
  240|  7.72k|                QPDFObject::JSON_Descr(std::make_shared<std::string>(is->getName()), "")))
  241|  7.72k|    {
  242|  7.72k|    }
_ZN4QPDF11JSONReactorD2Ev:
  243|  7.72k|    ~JSONReactor() override = default;

_ZN4QPDF3Doc7Objects18validatePDFVersionERPKcRNSt3__112basic_stringIcNS5_11char_traitsIcEENS5_9allocatorIcEEEE:
  165|  9.55k|{
  166|  9.55k|    if (!util::is_digit(*p)) {
  ------------------
  |  Branch (166:9): [True: 263, False: 9.29k]
  ------------------
  167|    263|        return false;
  168|    263|    }
  169|  21.3k|    while (util::is_digit(*p)) {
  ------------------
  |  Branch (169:12): [True: 12.0k, False: 9.29k]
  ------------------
  170|  12.0k|        version.append(1, *p++);
  171|  12.0k|    }
  172|  9.29k|    if (!(*p == '.' && util::is_digit(*(p + 1)))) {
  ------------------
  |  Branch (172:11): [True: 8.91k, False: 380]
  |  Branch (172:24): [True: 8.68k, False: 223]
  ------------------
  173|    603|        return false;
  174|    603|    }
  175|  8.68k|    version.append(1, *p++);
  176|  90.9k|    while (util::is_digit(*p)) {
  ------------------
  |  Branch (176:12): [True: 82.2k, False: 8.68k]
  ------------------
  177|  82.2k|        version.append(1, *p++);
  178|  82.2k|    }
  179|  8.68k|    return true;
  180|  9.29k|}
_ZN4QPDF3Doc7Objects10findHeaderEv:
  184|  7.72k|{
  185|  7.72k|    qpdf_offset_t global_offset = m->file->tell();
  186|  7.72k|    std::string line = m->file->readLine(1024);
  187|  7.72k|    char const* p = line.data();
  188|  7.72k|    util::assertion(strncmp(p, "%PDF-", 5) == 0, "findHeader is not looking at %PDF-");
  189|  7.72k|    p += 5;
  190|  7.72k|    std::string version;
  191|       |    // Note: The string returned by line.data() is always null-terminated. The code below never
  192|       |    // overruns the buffer because a null character always short-circuits further advancement.
  193|  7.72k|    if (!validatePDFVersion(p, version)) {
  ------------------
  |  Branch (193:9): [True: 0, False: 7.72k]
  ------------------
  194|      0|        return false;
  195|      0|    }
  196|  7.72k|    m->pdf_version = version;
  197|  7.72k|    if (global_offset != 0) {
  ------------------
  |  Branch (197:9): [True: 0, False: 7.72k]
  ------------------
  198|       |        // Empirical evidence strongly suggests (codified in PDF 2.0 spec) that when there is
  199|       |        // leading material prior to the PDF header, all explicit offsets in the file are such that
  200|       |        // 0 points to the beginning of the header.
  201|      0|        m->file = std::make_shared<OffsetInputSource>(m->file, global_offset);
  202|      0|    }
  203|  7.72k|    return true;
  204|  7.72k|}
_ZN4QPDF3Doc7Objects13findStartxrefEv:
  208|  7.72k|{
  209|  7.72k|    if (readToken(*m->file).isWord("startxref") && readToken(*m->file).isInteger()) {
  ------------------
  |  Branch (209:9): [True: 7.72k, False: 0]
  |  Branch (209:9): [True: 7.72k, False: 0]
  |  Branch (209:52): [True: 7.72k, False: 0]
  ------------------
  210|       |        // Position in front of offset token
  211|  7.72k|        m->file->seek(m->file->getLastOffset(), SEEK_SET);
  212|  7.72k|        return true;
  213|  7.72k|    }
  214|      0|    return false;
  215|  7.72k|}
_ZN4QPDF3Doc7Objects5parseEPKc:
  219|  7.72k|{
  220|  7.72k|    if (password) {
  ------------------
  |  Branch (220:9): [True: 0, False: 7.72k]
  ------------------
  221|      0|        m->encp->provided_password = password;
  222|      0|    }
  223|       |
  224|       |    // Find the header anywhere in the first 1024 bytes of the file.
  225|  7.72k|    PatternFinder hf(*this, &Objects::findHeader);
  226|  7.72k|    if (!m->file->findFirst("%PDF-", 0, 1024, hf)) {
  ------------------
  |  Branch (226:9): [True: 0, False: 7.72k]
  ------------------
  227|      0|        warn(damagedPDF("", -1, "can't find PDF header"));
  228|       |        // QPDFWriter writes files that usually require at least version 1.2 for /FlateDecode
  229|      0|        m->pdf_version = "1.2";
  230|      0|    }
  231|       |
  232|       |    // PDF spec says %%EOF must be found within the last 1024 bytes of/ the file.  We add an extra
  233|       |    // 30 characters to leave room for the startxref stuff.
  234|  7.72k|    m->file->seek(0, SEEK_END);
  235|  7.72k|    qpdf_offset_t end_offset = m->file->tell();
  236|  7.72k|    m->xref_table_max_offset = end_offset;
  237|       |    // Sanity check on object ids. All objects must appear in xref table / stream. In all realistic
  238|       |    // scenarios at least 3 bytes are required.
  239|  7.72k|    if (m->xref_table_max_id > m->xref_table_max_offset / 3) {
  ------------------
  |  Branch (239:9): [True: 7.72k, False: 0]
  ------------------
  240|  7.72k|        m->xref_table_max_id = static_cast<int>(m->xref_table_max_offset / 3);
  241|  7.72k|    }
  242|  7.72k|    qpdf_offset_t start_offset = (end_offset > 1054 ? end_offset - 1054 : 0);
  ------------------
  |  Branch (242:35): [True: 0, False: 7.72k]
  ------------------
  243|  7.72k|    PatternFinder sf(*this, &Objects::findStartxref);
  244|  7.72k|    qpdf_offset_t xref_offset = 0;
  245|  7.72k|    if (m->file->findLast("startxref", start_offset, 0, sf)) {
  ------------------
  |  Branch (245:9): [True: 7.72k, False: 0]
  ------------------
  246|  7.72k|        xref_offset = QUtil::string_to_ll(readToken(*m->file).getValue().c_str());
  247|  7.72k|    }
  248|       |
  249|  7.72k|    try {
  250|  7.72k|        if (xref_offset == 0) {
  ------------------
  |  Branch (250:13): [True: 0, False: 7.72k]
  ------------------
  251|      0|            throw damagedPDF("", -1, "can't find startxref");
  252|      0|        }
  253|  7.72k|        try {
  254|  7.72k|            read_xref(xref_offset);
  255|  7.72k|        } catch (QPDFExc&) {
  256|      0|            throw;
  257|      0|        } catch (std::exception& e) {
  258|      0|            throw damagedPDF("", -1, std::string("error reading xref: ") + e.what());
  259|      0|        }
  260|  7.72k|    } catch (QPDFExc& e) {
  261|      0|        if (global::Options::inspection_mode()) {
  ------------------
  |  Branch (261:13): [True: 0, False: 0]
  ------------------
  262|      0|            try {
  263|      0|                reconstruct_xref(e, xref_offset > 0);
  264|      0|            } catch (std::exception& er) {
  265|      0|                warn(damagedPDF("", -1, "error reconstructing xref: "s + er.what()));
  266|      0|            }
  267|      0|            if (!m->trailer) {
  ------------------
  |  Branch (267:17): [True: 0, False: 0]
  ------------------
  268|      0|                m->trailer = Dictionary::empty();
  269|      0|            }
  270|      0|            return;
  271|      0|        }
  272|      0|        if (cf.surpress_recovery()) {
  ------------------
  |  Branch (272:13): [True: 0, False: 0]
  ------------------
  273|      0|            throw;
  274|      0|        }
  275|      0|        reconstruct_xref(e, xref_offset > 0);
  276|      0|    }
  277|       |
  278|  7.72k|    m->encp->initialize(qpdf);
  279|  7.72k|    m->parsed = true;
  280|  7.72k|    if (!m->xref_table.empty() && !qpdf.getRoot().getKey("/Pages").isDictionary()) {
  ------------------
  |  Branch (280:9): [True: 0, False: 7.72k]
  |  Branch (280:9): [True: 0, False: 7.72k]
  |  Branch (280:35): [True: 0, False: 0]
  ------------------
  281|       |        // QPDFs created from JSON have an empty xref table and no root object yet.
  282|      0|        throw damagedPDF("", -1, "unable to find page tree");
  283|      0|    }
  284|  7.72k|    if (m->cf.max_warnings()) {
  ------------------
  |  Branch (284:9): [True: 0, False: 7.72k]
  ------------------
  285|      0|        if (m->pages.empty()) {
  ------------------
  |  Branch (285:13): [True: 0, False: 0]
  ------------------
  286|      0|            throw damagedPDF("", -1, "no pages found");
  287|      0|        }
  288|      0|        (void)m->cf.max_warnings(0);
  289|      0|    }
  290|  7.72k|}
_ZN4QPDF3Doc7Objects7inParseEb:
  294|  15.4k|{
  295|  15.4k|    util::internal_error_if(
  296|  15.4k|        m->in_parse == v, "QPDF: re-entrant parsing detected"
  297|       |        // This happens if QPDFParser::parse tries to resolve an indirect object while it is
  298|       |        // parsing.
  299|  15.4k|    );
  300|  15.4k|    m->in_parse = v;
  301|  15.4k|}
_ZN4QPDF3Doc7Objects10setTrailerE16QPDFObjectHandle:
  305|  7.72k|{
  306|  7.72k|    if (m->trailer) {
  ------------------
  |  Branch (306:9): [True: 0, False: 7.72k]
  ------------------
  307|      0|        return;
  308|      0|    }
  309|  7.72k|    m->trailer = obj;
  310|  7.72k|}
_ZN4QPDF3Doc7Objects9read_xrefExb:
  521|  7.72k|{
  522|  7.72k|    std::map<int, int> free_table;
  523|  7.72k|    std::set<qpdf_offset_t> visited;
  524|  15.4k|    while (xref_offset) {
  ------------------
  |  Branch (524:12): [True: 7.72k, False: 7.72k]
  ------------------
  525|  7.72k|        visited.insert(xref_offset);
  526|  7.72k|        char buf[7];
  527|  7.72k|        memset(buf, 0, sizeof(buf));
  528|  7.72k|        m->file->seek(xref_offset, SEEK_SET);
  529|       |        // Some files miss the mark a little with startxref. We could do a better job of searching
  530|       |        // in the neighborhood for something that looks like either an xref table or stream, but the
  531|       |        // simple heuristic of skipping whitespace can help with the xref table case and is harmless
  532|       |        // with the stream case.
  533|  7.72k|        bool done = false;
  534|  7.72k|        bool skipped_space = false;
  535|  15.4k|        while (!done) {
  ------------------
  |  Branch (535:16): [True: 7.72k, False: 7.72k]
  ------------------
  536|  7.72k|            char ch;
  537|  7.72k|            if (1 == m->file->read(&ch, 1)) {
  ------------------
  |  Branch (537:17): [True: 7.72k, False: 0]
  ------------------
  538|  7.72k|                if (util::is_space(ch)) {
  ------------------
  |  Branch (538:21): [True: 0, False: 7.72k]
  ------------------
  539|      0|                    skipped_space = true;
  540|  7.72k|                } else {
  541|  7.72k|                    m->file->unreadCh(ch);
  542|  7.72k|                    done = true;
  543|  7.72k|                }
  544|  7.72k|            } else {
  545|      0|                QTC::TC("qpdf", "QPDF eof skipping spaces before xref", skipped_space ? 0 : 1);
  ------------------
  |  Branch (545:73): [True: 0, False: 0]
  ------------------
  546|      0|                done = true;
  547|      0|            }
  548|  7.72k|        }
  549|       |
  550|  7.72k|        m->file->read(buf, sizeof(buf) - 1);
  551|       |        // The PDF spec says xref must be followed by a line terminator, but files exist in the wild
  552|       |        // where it is terminated by arbitrary whitespace.
  553|  7.72k|        if ((strncmp(buf, "xref", 4) == 0) && util::is_space(buf[4])) {
  ------------------
  |  Branch (553:13): [True: 7.72k, False: 0]
  |  Branch (553:47): [True: 7.72k, False: 0]
  ------------------
  554|  7.72k|            if (skipped_space) {
  ------------------
  |  Branch (554:17): [True: 0, False: 7.72k]
  ------------------
  555|      0|                warn(damagedPDF("", -1, "extraneous whitespace seen before xref"));
  556|      0|            }
  557|  7.72k|            QTC::TC(
  558|  7.72k|                "qpdf",
  559|  7.72k|                "QPDF xref space",
  560|  7.72k|                ((buf[4] == '\n')       ? 0
  ------------------
  |  Branch (560:18): [True: 7.72k, False: 0]
  ------------------
  561|  7.72k|                     : (buf[4] == '\r') ? 1
  ------------------
  |  Branch (561:24): [True: 0, False: 0]
  ------------------
  562|      0|                     : (buf[4] == ' ')  ? 2
  ------------------
  |  Branch (562:24): [True: 0, False: 0]
  ------------------
  563|      0|                                        : 9999));
  564|  7.72k|            int skip = 4;
  565|       |            // buf is null-terminated, and util::is_space('\0') is false, so this won't overrun.
  566|  15.4k|            while (util::is_space(buf[skip])) {
  ------------------
  |  Branch (566:20): [True: 7.72k, False: 7.72k]
  ------------------
  567|  7.72k|                ++skip;
  568|  7.72k|            }
  569|  7.72k|            xref_offset = read_xrefTable(xref_offset + skip);
  570|  7.72k|        } else {
  571|      0|            xref_offset = read_xrefStream(xref_offset, in_stream_recovery);
  572|      0|        }
  573|  7.72k|        if (visited.contains(xref_offset)) {
  ------------------
  |  Branch (573:13): [True: 0, False: 7.72k]
  ------------------
  574|      0|            throw damagedPDF("", -1, "loop detected following xref tables");
  575|      0|        }
  576|  7.72k|    }
  577|       |
  578|  7.72k|    if (!m->trailer) {
  ------------------
  |  Branch (578:9): [True: 0, False: 7.72k]
  ------------------
  579|      0|        throw damagedPDF("", -1, "unable to find trailer while reading xref");
  580|      0|    }
  581|  7.72k|    int size = m->trailer.getKey("/Size").getIntValueAsInt();
  582|  7.72k|    int max_obj = 0;
  583|  7.72k|    if (!m->xref_table.empty()) {
  ------------------
  |  Branch (583:9): [True: 0, False: 7.72k]
  ------------------
  584|      0|        max_obj = m->xref_table.rbegin()->first.getObj();
  585|      0|    }
  586|  7.72k|    if (!m->deleted_objects.empty()) {
  ------------------
  |  Branch (586:9): [True: 7.72k, False: 0]
  ------------------
  587|  7.72k|        max_obj = std::max(max_obj, *(m->deleted_objects.rbegin()));
  588|  7.72k|    }
  589|  7.72k|    if (size < 1 || (size - 1) != max_obj) {
  ------------------
  |  Branch (589:9): [True: 0, False: 7.72k]
  |  Branch (589:21): [True: 0, False: 7.72k]
  ------------------
  590|      0|        if (size == (max_obj + 2) && qpdf.getObject(max_obj + 1, 0).isStreamOfType("/XRef")) {
  ------------------
  |  Branch (590:13): [True: 0, False: 0]
  |  Branch (590:13): [True: 0, False: 0]
  |  Branch (590:38): [True: 0, False: 0]
  ------------------
  591|      0|            warn(damagedPDF(
  592|      0|                "",
  593|      0|                -1,
  594|      0|                "xref entry for the xref stream itself is missing - a common error handled "
  595|      0|                "correctly by qpdf and most other applications"));
  596|      0|        } else {
  597|      0|            warn(damagedPDF(
  598|      0|                "",
  599|      0|                -1,
  600|      0|                ("reported number of objects (" + std::to_string(size) +
  601|      0|                 ") is not one plus the highest object number (" + std::to_string(max_obj) + ")")));
  602|      0|        }
  603|      0|    }
  604|       |
  605|       |    // We no longer need the deleted_objects table, so go ahead and clear it out to make sure we
  606|       |    // never depend on its being set.
  607|  7.72k|    m->deleted_objects.clear();
  608|       |
  609|       |    // Make sure we keep only the highest generation for any object.
  610|  7.72k|    QPDFObjGen last_og{-1, 0};
  611|  7.72k|    for (auto const& item: m->xref_table) {
  ------------------
  |  Branch (611:26): [True: 0, False: 7.72k]
  ------------------
  612|      0|        auto id = item.first.getObj();
  613|      0|        if (id == last_og.getObj() && id > 0) {
  ------------------
  |  Branch (613:13): [True: 0, False: 0]
  |  Branch (613:39): [True: 0, False: 0]
  ------------------
  614|      0|            qpdf.removeObject(last_og);
  615|      0|        }
  616|      0|        last_og = item.first;
  617|      0|    }
  618|  7.72k|}
_ZN4QPDF3Doc7Objects15parse_xrefFirstERKNSt3__112basic_stringIcNS2_11char_traitsIcEENS2_9allocatorIcEEEERiSB_SB_:
  622|  7.72k|{
  623|       |    // is_space and is_digit both return false on '\0', so this will not overrun the null-terminated
  624|       |    // buffer.
  625|  7.72k|    char const* p = line.c_str();
  626|  7.72k|    char const* start = line.c_str();
  627|       |
  628|       |    // Skip zero or more spaces
  629|  7.72k|    while (util::is_space(*p)) {
  ------------------
  |  Branch (629:12): [True: 0, False: 7.72k]
  ------------------
  630|      0|        ++p;
  631|      0|    }
  632|       |    // Require digit
  633|  7.72k|    if (!util::is_digit(*p)) {
  ------------------
  |  Branch (633:9): [True: 0, False: 7.72k]
  ------------------
  634|      0|        return false;
  635|      0|    }
  636|       |    // Gather digits
  637|  7.72k|    std::string obj_str;
  638|  15.4k|    while (util::is_digit(*p)) {
  ------------------
  |  Branch (638:12): [True: 7.72k, False: 7.72k]
  ------------------
  639|  7.72k|        obj_str.append(1, *p++);
  640|  7.72k|    }
  641|       |    // Require space
  642|  7.72k|    if (!util::is_space(*p)) {
  ------------------
  |  Branch (642:9): [True: 0, False: 7.72k]
  ------------------
  643|      0|        return false;
  644|      0|    }
  645|       |    // Skip spaces
  646|  15.4k|    while (util::is_space(*p)) {
  ------------------
  |  Branch (646:12): [True: 7.72k, False: 7.72k]
  ------------------
  647|  7.72k|        ++p;
  648|  7.72k|    }
  649|       |    // Require digit
  650|  7.72k|    if (!util::is_digit(*p)) {
  ------------------
  |  Branch (650:9): [True: 0, False: 7.72k]
  ------------------
  651|      0|        return false;
  652|      0|    }
  653|       |    // Gather digits
  654|  7.72k|    std::string num_str;
  655|  15.4k|    while (util::is_digit(*p)) {
  ------------------
  |  Branch (655:12): [True: 7.72k, False: 7.72k]
  ------------------
  656|  7.72k|        num_str.append(1, *p++);
  657|  7.72k|    }
  658|       |    // Skip any space including line terminators
  659|  15.4k|    while (util::is_space(*p)) {
  ------------------
  |  Branch (659:12): [True: 7.72k, False: 7.72k]
  ------------------
  660|  7.72k|        ++p;
  661|  7.72k|    }
  662|  7.72k|    bytes = toI(p - start);
  663|  7.72k|    obj = QUtil::string_to_int(obj_str.c_str());
  664|  7.72k|    num = QUtil::string_to_int(num_str.c_str());
  665|  7.72k|    return true;
  666|  7.72k|}
_ZN4QPDF3Doc7Objects14read_xrefEntryERxRiRc:
  748|  7.72k|{
  749|  7.72k|    std::array<char, 21> line;
  750|  7.72k|    if (m->file->read(line.data(), 20) != 20) {
  ------------------
  |  Branch (750:9): [True: 0, False: 7.72k]
  ------------------
  751|       |        // C++20: [[unlikely]]
  752|      0|        return false;
  753|      0|    }
  754|  7.72k|    line[20] = '\0';
  755|  7.72k|    char const* p = line.data();
  756|       |
  757|  7.72k|    int f1_len = 0;
  758|  7.72k|    int f2_len = 0;
  759|       |
  760|       |    // is_space and is_digit both return false on '\0', so this will not overrun the null-terminated
  761|       |    // buffer.
  762|       |
  763|       |    // Gather f1 digits. NB No risk of overflow as 9'999'999'999 < max long long.
  764|  84.9k|    while (*p == '0') {
  ------------------
  |  Branch (764:12): [True: 77.2k, False: 7.72k]
  ------------------
  765|  77.2k|        ++f1_len;
  766|  77.2k|        ++p;
  767|  77.2k|    }
  768|  7.72k|    while (util::is_digit(*p) && f1_len++ < 10) {
  ------------------
  |  Branch (768:12): [True: 0, False: 7.72k]
  |  Branch (768:34): [True: 0, False: 0]
  ------------------
  769|      0|        f1 *= 10;
  770|      0|        f1 += *p++ - '0';
  771|      0|    }
  772|       |    // Require space
  773|  7.72k|    if (!util::is_space(*p++)) {
  ------------------
  |  Branch (773:9): [True: 0, False: 7.72k]
  ------------------
  774|       |        // Entry doesn't start with space or digit.
  775|       |        // C++20: [[unlikely]]
  776|      0|        return false;
  777|      0|    }
  778|       |    // Gather digits. NB No risk of overflow as 99'999 < max int.
  779|  7.72k|    while (*p == '0') {
  ------------------
  |  Branch (779:12): [True: 0, False: 7.72k]
  ------------------
  780|      0|        ++f2_len;
  781|      0|        ++p;
  782|      0|    }
  783|  46.3k|    while (util::is_digit(*p) && f2_len++ < 5) {
  ------------------
  |  Branch (783:12): [True: 38.6k, False: 7.72k]
  |  Branch (783:34): [True: 38.6k, False: 0]
  ------------------
  784|  38.6k|        f2 *= 10;
  785|  38.6k|        f2 += static_cast<int>(*p++ - '0');
  786|  38.6k|    }
  787|  7.72k|    if (util::is_space(*p++) && (*p == 'f' || *p == 'n')) {
  ------------------
  |  Branch (787:9): [True: 7.72k, False: 0]
  |  Branch (787:34): [True: 7.72k, False: 0]
  |  Branch (787:47): [True: 0, False: 0]
  ------------------
  788|       |        // C++20: [[likely]]
  789|  7.72k|        type = *p;
  790|       |        // No test for valid line[19].
  791|  7.72k|        if (*(++p) && *(++p) && (*p == '\n' || *p == '\r') && f1_len == 10 && f2_len == 5) {
  ------------------
  |  Branch (791:13): [True: 7.72k, False: 0]
  |  Branch (791:23): [True: 7.72k, False: 0]
  |  Branch (791:34): [True: 7.72k, False: 0]
  |  Branch (791:48): [True: 0, False: 0]
  |  Branch (791:63): [True: 7.72k, False: 0]
  |  Branch (791:79): [True: 7.72k, False: 0]
  ------------------
  792|       |            // C++20: [[likely]]
  793|  7.72k|            return true;
  794|  7.72k|        }
  795|  7.72k|    }
  796|      0|    return read_bad_xrefEntry(f1, f2, type);
  797|  7.72k|}
_ZN4QPDF3Doc7Objects14read_xrefTableEx:
  802|  7.72k|{
  803|  7.72k|    m->file->seek(xref_offset, SEEK_SET);
  804|  7.72k|    std::string line;
  805|  7.72k|    while (true) {
  ------------------
  |  Branch (805:12): [True: 7.72k, Folded]
  ------------------
  806|  7.72k|        line.assign(50, '\0');
  807|  7.72k|        m->file->read(line.data(), line.size());
  808|  7.72k|        int obj = 0;
  809|  7.72k|        int num = 0;
  810|  7.72k|        int bytes = 0;
  811|  7.72k|        if (!parse_xrefFirst(line, obj, num, bytes)) {
  ------------------
  |  Branch (811:13): [True: 0, False: 7.72k]
  ------------------
  812|      0|            throw damagedPDF("xref table", "xref syntax invalid");
  813|      0|        }
  814|  7.72k|        m->file->seek(m->file->getLastOffset() + bytes, SEEK_SET);
  815|  15.4k|        for (qpdf_offset_t i = obj; i - num < obj; ++i) {
  ------------------
  |  Branch (815:37): [True: 7.72k, False: 7.72k]
  ------------------
  816|  7.72k|            if (i == 0) {
  ------------------
  |  Branch (816:17): [True: 7.72k, False: 0]
  ------------------
  817|       |                // This is needed by checkLinearization()
  818|  7.72k|                first_xref_item_offset_ = m->file->tell();
  819|  7.72k|            }
  820|       |            // For xref_table, these will always be small enough to be ints
  821|  7.72k|            qpdf_offset_t f1 = 0;
  822|  7.72k|            int f2 = 0;
  823|  7.72k|            char type = '\0';
  824|  7.72k|            if (!read_xrefEntry(f1, f2, type)) {
  ------------------
  |  Branch (824:17): [True: 0, False: 7.72k]
  ------------------
  825|      0|                throw damagedPDF(
  826|      0|                    "xref table", "invalid xref entry (obj=" + std::to_string(i) + ")");
  827|      0|            }
  828|  7.72k|            if (type == 'f') {
  ------------------
  |  Branch (828:17): [True: 7.72k, False: 0]
  ------------------
  829|  7.72k|                insertFreeXrefEntry(QPDFObjGen(toI(i), f2));
  830|  7.72k|            } else {
  831|      0|                insertXrefEntry(toI(i), 1, f1, f2);
  832|      0|            }
  833|  7.72k|        }
  834|  7.72k|        qpdf_offset_t pos = m->file->tell();
  835|  7.72k|        if (readToken(*m->file).isWord("trailer")) {
  ------------------
  |  Branch (835:13): [True: 7.72k, False: 0]
  ------------------
  836|  7.72k|            break;
  837|  7.72k|        } else {
  838|      0|            m->file->seek(pos, SEEK_SET);
  839|      0|        }
  840|  7.72k|    }
  841|       |
  842|       |    // Set offset to previous xref table if any
  843|  7.72k|    QPDFObjectHandle cur_trailer = m->objects.readTrailer();
  844|  7.72k|    if (!cur_trailer.isDictionary()) {
  ------------------
  |  Branch (844:9): [True: 0, False: 7.72k]
  ------------------
  845|      0|        throw damagedPDF("", "expected trailer dictionary");
  846|      0|    }
  847|       |
  848|  7.72k|    if (!m->trailer) {
  ------------------
  |  Branch (848:9): [True: 7.72k, False: 0]
  ------------------
  849|  7.72k|        setTrailer(cur_trailer);
  850|       |
  851|  7.72k|        if (!m->trailer.hasKey("/Size")) {
  ------------------
  |  Branch (851:13): [True: 0, False: 7.72k]
  ------------------
  852|      0|            throw damagedPDF("trailer", "trailer dictionary lacks /Size key");
  853|      0|        }
  854|  7.72k|        if (!m->trailer.getKey("/Size").isInteger()) {
  ------------------
  |  Branch (854:13): [True: 0, False: 7.72k]
  ------------------
  855|      0|            throw damagedPDF("trailer", "/Size key in trailer dictionary is not an integer");
  856|      0|        }
  857|  7.72k|    }
  858|       |
  859|  7.72k|    if (cur_trailer.hasKey("/XRefStm")) {
  ------------------
  |  Branch (859:9): [True: 0, False: 7.72k]
  ------------------
  860|      0|        if (cf.ignore_xref_streams()) {
  ------------------
  |  Branch (860:13): [True: 0, False: 0]
  ------------------
  861|      0|            QTC::TC("qpdf", "QPDF ignoring XRefStm in trailer");
  862|      0|        } else {
  863|      0|            if (cur_trailer.getKey("/XRefStm").isInteger()) {
  ------------------
  |  Branch (863:17): [True: 0, False: 0]
  ------------------
  864|       |                // Read the xref stream but disregard any return value -- we'll use our trailer's
  865|       |                // /Prev key instead of the xref stream's.
  866|      0|                (void)read_xrefStream(cur_trailer.getKey("/XRefStm").getIntValue());
  867|      0|            } else {
  868|      0|                throw damagedPDF("xref stream", xref_offset, "invalid /XRefStm");
  869|      0|            }
  870|      0|        }
  871|      0|    }
  872|       |
  873|  7.72k|    if (cur_trailer.hasKey("/Prev")) {
  ------------------
  |  Branch (873:9): [True: 0, False: 7.72k]
  ------------------
  874|      0|        if (!cur_trailer.getKey("/Prev").isInteger()) {
  ------------------
  |  Branch (874:13): [True: 0, False: 0]
  ------------------
  875|      0|            throw damagedPDF("trailer", "/Prev key in trailer dictionary is not an integer");
  876|      0|        }
  877|      0|        return cur_trailer.getKey("/Prev").getIntValue();
  878|      0|    }
  879|       |
  880|  7.72k|    return 0;
  881|  7.72k|}
_ZN4QPDF3Doc7Objects19insertFreeXrefEntryE10QPDFObjGen:
 1188|  7.72k|{
 1189|  7.72k|    if (!m->xref_table.contains(og) && og.getObj() <= m->xref_table_max_id) {
  ------------------
  |  Branch (1189:9): [True: 7.72k, False: 0]
  |  Branch (1189:40): [True: 7.72k, False: 0]
  ------------------
 1190|  7.72k|        m->deleted_objects.insert(og.getObj());
 1191|  7.72k|    }
 1192|  7.72k|}
_ZN4QPDF3Doc7Objects11readTrailerEv:
 1294|  7.72k|{
 1295|  7.72k|    qpdf_offset_t offset = m->file->tell();
 1296|  7.72k|    auto object =
 1297|  7.72k|        Parser::parse(*m->file, "trailer", m->tokenizer, nullptr, qpdf, m->reconstructed_xref);
 1298|  7.72k|    if (object.isDictionary() && m->objects.readToken(*m->file).isWord("stream")) {
  ------------------
  |  Branch (1298:9): [True: 7.72k, False: 0]
  |  Branch (1298:9): [True: 0, False: 7.72k]
  |  Branch (1298:34): [True: 0, False: 7.72k]
  ------------------
 1299|      0|        warn(damagedPDF("trailer", m->file->tell(), "stream keyword found in trailer"));
 1300|      0|    }
 1301|       |    // Override last_offset so that it points to the beginning of the object we just read
 1302|  7.72k|    m->file->setLastOffset(offset);
 1303|  7.72k|    return object;
 1304|  7.72k|}
_ZN4QPDF3Doc7Objects9readTokenER11InputSourcem:
 1489|  38.6k|{
 1490|  38.6k|    return m->tokenizer.readToken(input, m->last_object_description, true, max_len);
 1491|  38.6k|}
_ZN4QPDF3Doc7Objects11updateCacheE10QPDFObjGenRKNSt3__110shared_ptrI10QPDFObjectEExxb:
 1867|  17.3k|{
 1868|  17.3k|    object->setObjGen(&qpdf, og);
 1869|  17.3k|    if (isCached(og)) {
  ------------------
  |  Branch (1869:9): [True: 17.3k, False: 0]
  ------------------
 1870|  17.3k|        auto& cache = m->obj_cache[og];
 1871|  17.3k|        object->move_to(cache.object, destroy);
 1872|  17.3k|        cache.end_before_space = end_before_space;
 1873|  17.3k|        cache.end_after_space = end_after_space;
 1874|  17.3k|    } else {
 1875|      0|        m->obj_cache[og] = ObjCache(object, end_before_space, end_after_space);
 1876|      0|    }
 1877|  17.3k|}
_ZN4QPDF3Doc7Objects8isCachedE10QPDFObjGen:
 1881|  17.3k|{
 1882|  17.3k|    return m->obj_cache.contains(og);
 1883|  17.3k|}
_ZN4QPDF3Doc7Objects16getObjectForJSONEii:
 1938|   752k|{
 1939|   752k|    auto og = QPDFObjGen(id, gen);
 1940|   752k|    auto [it, inserted] = m->obj_cache.try_emplace(og);
 1941|   752k|    auto& obj = it->second.object;
 1942|   752k|    if (inserted) {
  ------------------
  |  Branch (1942:9): [True: 12.8k, False: 740k]
  ------------------
 1943|  12.8k|        obj = (m->parsed && !m->xref_table.contains(og))
  ------------------
  |  Branch (1943:16): [True: 12.8k, False: 0]
  |  Branch (1943:29): [True: 12.8k, False: 0]
  ------------------
 1944|  12.8k|            ? QPDFObject::create<QPDF_Null>(&qpdf, og)
 1945|  12.8k|            : QPDFObject::create<QPDF_Unresolved>(&qpdf, og);
 1946|  12.8k|    }
 1947|   752k|    return obj;
 1948|   752k|}
_ZN4QPDF9getObjectE10QPDFObjGen:
 1952|  17.3k|{
 1953|  17.3k|    if (auto it = m->obj_cache.find(og); it != m->obj_cache.end()) {
  ------------------
  |  Branch (1953:42): [True: 17.3k, False: 0]
  ------------------
 1954|  17.3k|        return {it->second.object};
 1955|  17.3k|    } else if (m->parsed && !m->xref_table.contains(og)) {
  ------------------
  |  Branch (1955:16): [True: 0, False: 0]
  |  Branch (1955:29): [True: 0, False: 0]
  ------------------
 1956|      0|        return QPDFObject::create<QPDF_Null>();
 1957|      0|    } else {
 1958|      0|        auto result =
 1959|      0|            m->obj_cache.try_emplace(og, QPDFObject::create<QPDF_Unresolved>(this, og), -1, -1);
 1960|      0|        return {result.first->second.object};
 1961|      0|    }
 1962|  17.3k|}
_ZN4QPDF13replaceObjectE10QPDFObjGen16QPDFObjectHandle:
 1972|  17.3k|{
 1973|  17.3k|    if (!oh || (oh.isIndirect() && !(oh.isStream() && oh.getObjGen() == og))) {
  ------------------
  |  Branch (1973:9): [True: 0, False: 17.3k]
  |  Branch (1973:9): [True: 0, False: 17.3k]
  |  Branch (1973:17): [True: 3.60k, False: 13.7k]
  |  Branch (1973:38): [True: 3.60k, False: 0]
  |  Branch (1973:55): [True: 3.60k, False: 0]
  ------------------
 1974|      0|        throw std::logic_error("QPDF::replaceObject called with indirect object handle");
 1975|      0|    }
 1976|  17.3k|    m->objects.updateCache(og, oh.obj_sp(), -1, -1, false);
 1977|  17.3k|}
_ZN4QPDF3Doc7Objects13PatternFinderC2ERS1_MS1_FbvE:
  147|  15.4k|        o(o),
  148|  15.4k|        checker(checker)
  149|  15.4k|    {
  150|  15.4k|    }
_ZN4QPDF3Doc7Objects13PatternFinder5checkEv:
  154|  15.4k|    {
  155|  15.4k|        return (this->o.*checker)();
  156|  15.4k|    }

_ZN5QUtil13int_to_stringExi:
  331|  1.12M|{
  332|  1.12M|    return int_to_string_base(num, 10, length);
  333|  1.12M|}
_ZN5QUtil18int_to_string_baseExii:
  343|  1.12M|{
  344|  1.12M|    return int_to_string_base_internal(num, base, length);
  345|  1.12M|}
_ZN5QUtil16double_to_stringEdib:
  355|  6.52k|{
  356|       |    // Backward compatibility -- this code used to use sprintf and treated decimal_places <= 0 to
  357|       |    // mean to use the default, which was six decimal places. Starting in 10.2, we trim trailing
  358|       |    // zeroes by default.
  359|  6.52k|    if (decimal_places <= 0) {
  ------------------
  |  Branch (359:9): [True: 6.52k, False: 0]
  ------------------
  360|  6.52k|        decimal_places = 6;
  361|  6.52k|    }
  362|  6.52k|    std::ostringstream buf;
  363|  6.52k|    buf.imbue(std::locale::classic());
  364|  6.52k|    buf << std::setprecision(decimal_places) << std::fixed << num;
  365|  6.52k|    std::string result = buf.str();
  366|  6.52k|    if (trim_trailing_zeroes) {
  ------------------
  |  Branch (366:9): [True: 6.52k, False: 0]
  ------------------
  367|  44.1k|        while ((result.length() > 1) && (result.back() == '0')) {
  ------------------
  |  Branch (367:16): [True: 44.1k, False: 0]
  |  Branch (367:41): [True: 37.6k, False: 6.52k]
  ------------------
  368|  37.6k|            result.pop_back();
  369|  37.6k|        }
  370|  6.52k|        if ((result.length() > 1) && (result.back() == '.')) {
  ------------------
  |  Branch (370:13): [True: 6.52k, False: 0]
  |  Branch (370:38): [True: 6.12k, False: 400]
  ------------------
  371|  6.12k|            result.pop_back();
  372|  6.12k|        }
  373|  6.52k|    }
  374|  6.52k|    return result;
  375|  6.52k|}
_ZN5QUtil12string_to_llEPKc:
  379|  3.79M|{
  380|  3.79M|    errno = 0;
  381|       |#ifdef _MSC_VER
  382|       |    long long result = _strtoi64(str, 0, 10);
  383|       |#else
  384|  3.79M|    long long result = strtoll(str, nullptr, 10);
  385|  3.79M|#endif
  386|  3.79M|    if (errno == ERANGE) {
  ------------------
  |  Branch (386:9): [True: 1.52k, False: 3.79M]
  ------------------
  387|  1.52k|        throw std::range_error(
  388|  1.52k|            std::string("overflow/underflow converting ") + str + " to 64-bit integer");
  389|  1.52k|    }
  390|  3.79M|    return result;
  391|  3.79M|}
_ZN5QUtil13string_to_intEPKc:
  395|  1.52M|{
  396|       |    // QIntC::to_int does range checking
  397|  1.52M|    return QIntC::to_int(string_to_ll(str));
  398|  1.52M|}
_ZN5QUtil12is_long_longEPKc:
  434|  1.13M|{
  435|  1.13M|    try {
  436|  1.13M|        auto i1 = string_to_ll(str);
  437|  1.13M|        std::string s1 = int_to_string(i1);
  438|  1.13M|        return str == s1;
  439|  1.13M|    } catch (std::exception&) {
  440|       |        // overflow or other error
  441|  1.51k|    }
  442|  1.51k|    return false;
  443|  1.13M|}
_ZN5QUtil13file_providerERKNSt3__112basic_stringIcNS0_11char_traitsIcEENS0_9allocatorIcEEEE:
  666|  1.32k|{
  667|  1.32k|    return [filename](Pipeline* p) { pipe_file(filename.c_str(), p); };
  668|  1.32k|}
_ZN5QUtil10hex_decodeERKNSt3__112basic_stringIcNS0_11char_traitsIcEENS0_9allocatorIcEEEE:
  740|  1.17k|{
  741|  1.17k|    std::string result;
  742|       |    // We know result.size() <= 0.5 * input.size() + 1. However, reserving string space for this
  743|       |    // upper bound has a negative impact.
  744|  1.17k|    bool first = true;
  745|  1.17k|    char decoded;
  746|  22.9k|    for (auto ch: input) {
  ------------------
  |  Branch (746:17): [True: 22.9k, False: 1.17k]
  ------------------
  747|  22.9k|        ch = util::hex_decode_char(ch);
  748|  22.9k|        if (ch < '\20') {
  ------------------
  |  Branch (748:13): [True: 22.9k, False: 0]
  ------------------
  749|  22.9k|            if (first) {
  ------------------
  |  Branch (749:17): [True: 11.4k, False: 11.4k]
  ------------------
  750|  11.4k|                decoded = static_cast<char>(ch << 4);
  751|  11.4k|                first = false;
  752|  11.4k|            } else {
  753|  11.4k|                result.push_back(decoded | ch);
  754|  11.4k|                first = true;
  755|  11.4k|            }
  756|  22.9k|        }
  757|  22.9k|    }
  758|  1.17k|    if (!first) {
  ------------------
  |  Branch (758:9): [True: 0, False: 1.17k]
  ------------------
  759|      0|        result.push_back(decoded);
  760|      0|    }
  761|  1.17k|    return result;
  762|  1.17k|}
_ZN5QUtil6toUTF8Em:
 1004|  42.0k|{
 1005|  42.0k|    std::string result;
 1006|       |
 1007|       |    // A UTF-8 encoding of a Unicode value is a single byte for Unicode values <= 127.  For larger
 1008|       |    // values, the first byte of the UTF-8 encoding has '1' as each of its n highest bits and '0'
 1009|       |    // for its (n+1)th highest bit where n is the total number of bytes required.  Subsequent bytes
 1010|       |    // start with '10' and have the remaining 6 bits free for encoding.  For example, an 11-bit
 1011|       |    // Unicode value can be stored in two bytes where the first is 110zzzzz, the second is 10zzzzzz,
 1012|       |    // and the z's represent the remaining bits.
 1013|       |
 1014|  42.0k|    if (uval > 0x7fffffff) {
  ------------------
  |  Branch (1014:9): [True: 0, False: 42.0k]
  ------------------
 1015|      0|        throw std::runtime_error("bounds error in QUtil::toUTF8");
 1016|  42.0k|    } else if (uval < 128) {
  ------------------
  |  Branch (1016:16): [True: 38.2k, False: 3.77k]
  ------------------
 1017|  38.2k|        result += static_cast<char>(uval);
 1018|  38.2k|    } else {
 1019|  3.77k|        unsigned char bytes[7];
 1020|  3.77k|        bytes[6] = '\0';
 1021|  3.77k|        unsigned char* cur_byte = &bytes[5];
 1022|       |
 1023|       |        // maximum value that will fit in the current number of bytes
 1024|  3.77k|        unsigned char maxval = 0x3f; // six bits
 1025|       |
 1026|  13.9k|        while (uval > QIntC::to_ulong(maxval)) {
  ------------------
  |  Branch (1026:16): [True: 10.1k, False: 3.77k]
  ------------------
 1027|       |            // Assign low six bits plus 10000000 to lowest unused byte position, then shift
 1028|  10.1k|            *cur_byte = static_cast<unsigned char>(0x80 + (uval & 0x3f));
 1029|  10.1k|            uval >>= 6;
 1030|       |            // Maximum that will fit in high byte now shrinks by one bit
 1031|  10.1k|            maxval = static_cast<unsigned char>(maxval >> 1);
 1032|       |            // Slide to the left one byte
 1033|  10.1k|            if (cur_byte <= bytes) {
  ------------------
  |  Branch (1033:17): [True: 0, False: 10.1k]
  ------------------
 1034|      0|                throw std::logic_error("QUtil::toUTF8: overflow error");
 1035|      0|            }
 1036|  10.1k|            --cur_byte;
 1037|  10.1k|        }
 1038|       |        // If maxval is k bits long, the high (7 - k) bits of the resulting byte must be high.
 1039|  3.77k|        *cur_byte = static_cast<unsigned char>(QIntC::to_ulong(0xff - (1 + (maxval << 1))) + uval);
 1040|       |
 1041|  3.77k|        result += reinterpret_cast<char*>(cur_byte);
 1042|  3.77k|    }
 1043|       |
 1044|  42.0k|    return result;
 1045|  42.0k|}
_ZN5QUtil7toUTF16Em:
 1049|  10.3M|{
 1050|  10.3M|    std::string result;
 1051|  10.3M|    if ((uval >= 0xd800) && (uval <= 0xdfff)) {
  ------------------
  |  Branch (1051:9): [True: 30.3k, False: 10.3M]
  |  Branch (1051:29): [True: 317, False: 29.9k]
  ------------------
 1052|    317|        result = "\xff\xfd";
 1053|  10.3M|    } else if (uval <= 0xffff) {
  ------------------
  |  Branch (1053:16): [True: 10.3M, False: 29.7k]
  ------------------
 1054|  10.3M|        char out[2];
 1055|  10.3M|        out[0] = static_cast<char>((uval & 0xff00) >> 8);
 1056|  10.3M|        out[1] = static_cast<char>(uval & 0xff);
 1057|  10.3M|        result = std::string(out, 2);
 1058|  10.3M|    } else if (uval <= 0x10ffff) {
  ------------------
  |  Branch (1058:16): [True: 2.89k, False: 26.8k]
  ------------------
 1059|  2.89k|        char out[4];
 1060|  2.89k|        uval -= 0x10000;
 1061|  2.89k|        unsigned short high = static_cast<unsigned short>(((uval & 0xffc00) >> 10) + 0xd800);
 1062|  2.89k|        unsigned short low = static_cast<unsigned short>((uval & 0x3ff) + 0xdc00);
 1063|  2.89k|        out[0] = static_cast<char>((high & 0xff00) >> 8);
 1064|  2.89k|        out[1] = static_cast<char>(high & 0xff);
 1065|  2.89k|        out[2] = static_cast<char>((low & 0xff00) >> 8);
 1066|  2.89k|        out[3] = static_cast<char>(low & 0xff);
 1067|  2.89k|        result = std::string(out, 4);
 1068|  26.8k|    } else {
 1069|  26.8k|        result = "\xff\xfd";
 1070|  26.8k|    }
 1071|       |
 1072|  10.3M|    return result;
 1073|  10.3M|}
_ZN5QUtil23get_next_utf8_codepointERKNSt3__112basic_stringIcNS0_11char_traitsIcEENS0_9allocatorIcEEEERmRb:
 1479|  26.5M|{
 1480|  26.5M|    auto o_pos = pos;
 1481|  26.5M|    size_t len = utf8_val.length();
 1482|  26.5M|    unsigned char ch = static_cast<unsigned char>(utf8_val.at(pos++));
 1483|  26.5M|    error = false;
 1484|  26.5M|    if (ch < 128) {
  ------------------
  |  Branch (1484:9): [True: 20.6M, False: 5.86M]
  ------------------
 1485|  20.6M|        return static_cast<unsigned long>(ch);
 1486|  20.6M|    }
 1487|       |
 1488|  5.86M|    size_t bytes_needed = 0;
 1489|  5.86M|    unsigned bit_check = 0x40;
 1490|  5.86M|    unsigned char to_clear = 0x80;
 1491|  16.1M|    while (ch & bit_check) {
  ------------------
  |  Branch (1491:12): [True: 10.2M, False: 5.86M]
  ------------------
 1492|  10.2M|        ++bytes_needed;
 1493|  10.2M|        to_clear = static_cast<unsigned char>(to_clear | bit_check);
 1494|  10.2M|        bit_check >>= 1;
 1495|  10.2M|    }
 1496|  5.86M|    if (((bytes_needed > 5) || (bytes_needed < 1)) || ((pos + bytes_needed) > len)) {
  ------------------
  |  Branch (1496:10): [True: 995k, False: 4.86M]
  |  Branch (1496:32): [True: 3.59M, False: 1.26M]
  |  Branch (1496:55): [True: 3.32k, False: 1.26M]
  ------------------
 1497|  4.59M|        error = true;
 1498|  4.59M|        return 0xfffd;
 1499|  4.59M|    }
 1500|       |
 1501|  1.26M|    auto codepoint = static_cast<unsigned long>(ch & ~to_clear);
 1502|  1.57M|    while (bytes_needed > 0) {
  ------------------
  |  Branch (1502:12): [True: 1.48M, False: 90.4k]
  ------------------
 1503|  1.48M|        --bytes_needed;
 1504|  1.48M|        ch = static_cast<unsigned char>(utf8_val.at(pos++));
 1505|  1.48M|        if ((ch & 0xc0) != 0x80) {
  ------------------
  |  Branch (1505:13): [True: 1.17M, False: 311k]
  ------------------
 1506|  1.17M|            --pos;
 1507|  1.17M|            error = true;
 1508|  1.17M|            return 0xfffd;
 1509|  1.17M|        }
 1510|   311k|        codepoint <<= 6;
 1511|   311k|        codepoint += (ch & 0x3f);
 1512|   311k|    }
 1513|  90.4k|    unsigned long lower_bound = 0;
 1514|  90.4k|    switch (pos - o_pos) {
 1515|  27.1k|    case 2:
  ------------------
  |  Branch (1515:5): [True: 27.1k, False: 63.2k]
  ------------------
 1516|  27.1k|        lower_bound = 1 << 7;
 1517|  27.1k|        break;
 1518|  3.73k|    case 3:
  ------------------
  |  Branch (1518:5): [True: 3.73k, False: 86.6k]
  ------------------
 1519|  3.73k|        lower_bound = 1 << 11;
 1520|  3.73k|        break;
 1521|  13.2k|    case 4:
  ------------------
  |  Branch (1521:5): [True: 13.2k, False: 77.1k]
  ------------------
 1522|  13.2k|        lower_bound = 1 << 16;
 1523|  13.2k|        break;
 1524|  33.9k|    case 5:
  ------------------
  |  Branch (1524:5): [True: 33.9k, False: 56.4k]
  ------------------
 1525|  33.9k|        lower_bound = 1 << 12;
 1526|  33.9k|        break;
 1527|  12.3k|    case 6:
  ------------------
  |  Branch (1527:5): [True: 12.3k, False: 78.0k]
  ------------------
 1528|  12.3k|        lower_bound = 1 << 26;
 1529|  12.3k|        break;
 1530|      0|    default:
  ------------------
  |  Branch (1530:5): [True: 0, False: 90.4k]
  ------------------
 1531|      0|        lower_bound = 0;
 1532|  90.4k|    }
 1533|       |
 1534|  90.4k|    if (lower_bound > 0 && codepoint < lower_bound) {
  ------------------
  |  Branch (1534:9): [True: 90.4k, False: 0]
  |  Branch (1534:28): [True: 330, False: 90.0k]
  ------------------
 1535|       |        // Too many bytes were used, but return whatever character was encoded.
 1536|    330|        error = true;
 1537|    330|    }
 1538|  90.4k|    return codepoint;
 1539|  90.4k|}
_ZN5QUtil13utf8_to_utf16ERKNSt3__112basic_stringIcNS0_11char_traitsIcEENS0_9allocatorIcEEEE:
 1637|  4.51k|{
 1638|  4.51k|    return transcode_utf8(utf8, e_utf16, 0);
 1639|  4.51k|}
_ZN5QUtil15utf8_to_pdf_docERKNSt3__112basic_stringIcNS0_11char_traitsIcEENS0_9allocatorIcEEEERS6_c:
 1685|  5.84k|{
 1686|  5.84k|    return transcode_utf8(utf8, pdfdoc, e_pdfdoc, unknown_char);
 1687|  5.84k|}
QUtil.cc:_ZL14transcode_utf8RKNSt3__112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEE10encoding_ec:
 1629|  4.51k|{
 1630|  4.51k|    std::string result;
 1631|  4.51k|    transcode_utf8(utf8_val, result, encoding, unknown);
 1632|  4.51k|    return result;
 1633|  4.51k|}
QUtil.cc:_ZL14transcode_utf8RKNSt3__112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEERS5_10encoding_ec:
 1543|  10.3k|{
 1544|  10.3k|    bool okay = true;
 1545|  10.3k|    result.clear();
 1546|  10.3k|    size_t len = utf8_val.length();
 1547|  10.3k|    switch (encoding) {
 1548|  4.51k|    case e_utf16:
  ------------------
  |  Branch (1548:5): [True: 4.51k, False: 5.84k]
  ------------------
 1549|  4.51k|        result += "\xfe\xff";
 1550|  4.51k|        break;
 1551|  5.84k|    case e_pdfdoc:
  ------------------
  |  Branch (1551:5): [True: 5.84k, False: 4.51k]
  ------------------
 1552|       |        // We need to avoid having the result start with something that will be interpreted as
 1553|       |        // UTF-16 or UTF-8, meaning we can't end up with a string that starts with "fe ff",
 1554|       |        // (UTF-16-BE) "ff fe" (UTF-16-LE, not officially part of the PDF spec, but recognized by
 1555|       |        // most readers including qpdf), or "ef bb bf" (UTF-8). It's more efficient to check the
 1556|       |        // input string to see if it will map to one of those sequences than to check the output
 1557|       |        // string since all cases start with the same starting character.
 1558|  5.84k|        if ((len >= 4) && (utf8_val[0] == '\xc3')) {
  ------------------
  |  Branch (1558:13): [True: 4.50k, False: 1.34k]
  |  Branch (1558:27): [True: 2.45k, False: 2.04k]
  ------------------
 1559|  2.45k|            static std::string fe_ff("\xbe\xc3\xbf");
 1560|  2.45k|            static std::string ff_fe("\xbf\xc3\xbe");
 1561|  2.45k|            static std::string ef_bb_bf("\xaf\xc2\xbb\xc2\xbf");
 1562|       |            // C++-20 has starts_with, but when this was written, qpdf had a minimum supported
 1563|       |            // version of C++-17.
 1564|  2.45k|            if ((utf8_val.compare(1, 3, fe_ff) == 0) || (utf8_val.compare(1, 3, ff_fe) == 0) ||
  ------------------
  |  Branch (1564:17): [True: 203, False: 2.25k]
  |  Branch (1564:57): [True: 196, False: 2.05k]
  ------------------
 1565|  2.05k|                (utf8_val.compare(1, 5, ef_bb_bf) == 0)) {
  ------------------
  |  Branch (1565:17): [True: 326, False: 1.73k]
  ------------------
 1566|    725|                result += unknown;
 1567|    725|                okay = false;
 1568|    725|            }
 1569|  2.45k|        }
 1570|  5.84k|        break;
 1571|      0|    default:
  ------------------
  |  Branch (1571:5): [True: 0, False: 10.3k]
  ------------------
 1572|      0|        break;
 1573|  10.3k|    }
 1574|  10.3k|    size_t pos = 0;
 1575|  26.5M|    while (pos < len) {
  ------------------
  |  Branch (1575:12): [True: 26.5M, False: 10.3k]
  ------------------
 1576|  26.5M|        bool error = false;
 1577|  26.5M|        unsigned long codepoint = QUtil::get_next_utf8_codepoint(utf8_val, pos, error);
 1578|  26.5M|        if (error) {
  ------------------
  |  Branch (1578:13): [True: 5.77M, False: 20.7M]
  ------------------
 1579|  5.77M|            okay = false;
 1580|  5.77M|            if (encoding == e_utf16) {
  ------------------
  |  Branch (1580:17): [True: 2.88M, False: 2.88M]
  ------------------
 1581|  2.88M|                result += "\xff\xfd";
 1582|  2.88M|            } else {
 1583|  2.88M|                result.append(1, unknown);
 1584|  2.88M|            }
 1585|  20.7M|        } else if (codepoint < 128) {
  ------------------
  |  Branch (1585:20): [True: 20.6M, False: 90.0k]
  ------------------
 1586|  20.6M|            char ch = static_cast<char>(codepoint);
 1587|  20.6M|            if (encoding == e_utf16) {
  ------------------
  |  Branch (1587:17): [True: 10.3M, False: 10.3M]
  ------------------
 1588|  10.3M|                result += QUtil::toUTF16(QIntC::to_ulong(ch));
 1589|  10.3M|            } else if ((encoding == e_pdfdoc) && (((ch >= 0x18) && (ch <= 0x1f)) || (ch == 127))) {
  ------------------
  |  Branch (1589:24): [True: 10.3M, False: 0]
  |  Branch (1589:52): [True: 10.3M, False: 525]
  |  Branch (1589:68): [True: 197, False: 10.3M]
  |  Branch (1589:85): [True: 1.50k, False: 10.3M]
  ------------------
 1590|       |                // PDFDocEncoding maps some low characters to Unicode, so if we encounter those
 1591|       |                // invalid UTF-8 code points, map them to unknown so reversing the mapping doesn't
 1592|       |                // change them into other characters.
 1593|  1.69k|                okay = false;
 1594|  1.69k|                result.append(1, unknown);
 1595|  10.3M|            } else {
 1596|  10.3M|                result.append(1, ch);
 1597|  10.3M|            }
 1598|  20.6M|        } else if (encoding == e_utf16) {
  ------------------
  |  Branch (1598:20): [True: 44.6k, False: 45.4k]
  ------------------
 1599|  44.6k|            result += QUtil::toUTF16(codepoint);
 1600|  45.4k|        } else if ((codepoint == 0xad) && (encoding == e_pdfdoc)) {
  ------------------
  |  Branch (1600:20): [True: 357, False: 45.0k]
  |  Branch (1600:43): [True: 357, False: 0]
  ------------------
 1601|       |            // PDFDocEncoding omits 0x00ad (soft hyphen).
 1602|    357|            okay = false;
 1603|    357|            result.append(1, unknown);
 1604|  45.0k|        } else if (
 1605|  45.0k|            (codepoint > 160) && (codepoint < 256) &&
  ------------------
  |  Branch (1605:13): [True: 42.7k, False: 2.32k]
  |  Branch (1605:34): [True: 5.92k, False: 36.8k]
  ------------------
 1606|  5.92k|            ((encoding == e_winansi) || (encoding == e_pdfdoc))) {
  ------------------
  |  Branch (1606:14): [True: 0, False: 5.92k]
  |  Branch (1606:41): [True: 5.92k, False: 0]
  ------------------
 1607|  5.92k|            result.append(1, static_cast<char>(codepoint & 0xff));
 1608|  39.1k|        } else {
 1609|  39.1k|            unsigned char ch = '\0';
 1610|  39.1k|            if (encoding == e_winansi) {
  ------------------
  |  Branch (1610:17): [True: 0, False: 39.1k]
  ------------------
 1611|      0|                ch = encode_winansi(codepoint);
 1612|  39.1k|            } else if (encoding == e_macroman) {
  ------------------
  |  Branch (1612:24): [True: 0, False: 39.1k]
  ------------------
 1613|      0|                ch = encode_macroman(codepoint);
 1614|  39.1k|            } else if (encoding == e_pdfdoc) {
  ------------------
  |  Branch (1614:24): [True: 39.1k, False: 0]
  ------------------
 1615|  39.1k|                ch = encode_pdfdoc(codepoint);
 1616|  39.1k|            }
 1617|  39.1k|            if (ch == '\0') {
  ------------------
  |  Branch (1617:17): [True: 38.4k, False: 674]
  ------------------
 1618|  38.4k|                okay = false;
 1619|  38.4k|                ch = static_cast<unsigned char>(unknown);
 1620|  38.4k|            }
 1621|  39.1k|            result.append(1, static_cast<char>(ch));
 1622|  39.1k|        }
 1623|  26.5M|    }
 1624|  10.3k|    return okay;
 1625|  10.3k|}
QUtil.cc:_ZL13encode_pdfdocm:
 1469|  39.1k|{
 1470|  39.1k|    auto i = unicode_to_pdf_doc.find(codepoint);
 1471|  39.1k|    if (i != unicode_to_pdf_doc.end()) {
  ------------------
  |  Branch (1471:9): [True: 674, False: 38.4k]
  ------------------
 1472|    674|        return i->second;
 1473|    674|    }
 1474|  38.4k|    return '\0';
 1475|  39.1k|}
QUtil.cc:_ZL27int_to_string_base_internalIxENSt3__112basic_stringIcNS0_11char_traitsIcEENS0_9allocatorIcEEEET_ii:
  300|  1.12M|{
  301|       |    // Backward compatibility -- int_to_string, which calls this function, used to use sprintf with
  302|       |    // %0*d, so we interpret length such that a negative value appends spaces and a positive value
  303|       |    // prepends zeroes.
  304|  1.12M|    if (!((base == 8) || (base == 10) || (base == 16))) {
  ------------------
  |  Branch (304:11): [True: 0, False: 1.12M]
  |  Branch (304:26): [True: 1.12M, False: 0]
  |  Branch (304:42): [True: 0, False: 0]
  ------------------
  305|      0|        throw std::logic_error("int_to_string_base called with unsupported base");
  306|      0|    }
  307|  1.12M|    std::string cvt;
  308|  1.12M|    if (base == 10) {
  ------------------
  |  Branch (308:9): [True: 1.12M, False: 0]
  ------------------
  309|       |        // Use the more efficient std::to_string when possible
  310|  1.12M|        cvt = std::to_string(num);
  311|  1.12M|    } else {
  312|      0|        std::ostringstream buf;
  313|      0|        buf.imbue(std::locale::classic());
  314|      0|        buf << std::setbase(base) << std::nouppercase << num;
  315|      0|        cvt = buf.str();
  316|      0|    }
  317|  1.12M|    std::string result;
  318|  1.12M|    int str_length = QIntC::to_int(cvt.length());
  319|  1.12M|    if ((length > 0) && (str_length < length)) {
  ------------------
  |  Branch (319:9): [True: 0, False: 1.12M]
  |  Branch (319:25): [True: 0, False: 0]
  ------------------
  320|      0|        result.append(QIntC::to_size(length - str_length), '0');
  321|      0|    }
  322|  1.12M|    result += cvt;
  323|  1.12M|    if ((length < 0) && (str_length < -length)) {
  ------------------
  |  Branch (323:9): [True: 0, False: 1.12M]
  |  Branch (323:25): [True: 0, False: 0]
  ------------------
  324|      0|        result.append(QIntC::to_size(-length - str_length), ' ');
  325|      0|    }
  326|  1.12M|    return result;
  327|  1.12M|}

_ZN4qpdf6global7Options9fuzz_modeEb:
   13|  7.72k|{
   14|  7.72k|    if (value) {
  ------------------
  |  Branch (14:9): [True: 7.72k, False: 0]
  ------------------
   15|  7.72k|        o.fuzz_mode_ = true;
   16|       |        // Limit the memory used to decompress JPEG files during fuzzing. Excessive memory use
   17|       |        // during fuzzing is due to corrupt JPEG data which sometimes cannot be detected before
   18|       |        // jpeg_start_decompress is called. During normal use of qpdf very large JPEGs can
   19|       |        // occasionally occur legitimately and therefore must be allowed during normal operations.
   20|  7.72k|        Limits::dct_max_memory(10'000'000);
   21|  7.72k|        Limits::dct_max_progressive_scans(50);
   22|       |        // Do not decompress corrupt data. This may cause extended runtime within jpeglib without
   23|       |        // exercising additional code paths in qpdf.
   24|  7.72k|        dct_throw_on_corrupt_data(true);
   25|  7.72k|        Limits::png_max_memory(1'000'000);
   26|  7.72k|        Limits::flate_max_memory(200'000);
   27|  7.72k|        Limits::run_length_max_memory(1'000'000);
   28|  7.72k|        Limits::tiff_max_memory(1'000'000);
   29|       |        // Set a reasonable default maximum warnings per document for fuzzing to avoid time-outs due
   30|       |        // to extensive recovery efforts.
   31|  7.72k|        Limits::doc_max_warnings(200);
   32|  7.72k|    }
   33|  7.72k|}
qpdf_global_set_uint32:
  129|  7.72k|{
  130|  7.72k|    switch (param) {
  131|      0|    case qpdf_p_inspection_mode:
  ------------------
  |  Branch (131:5): [True: 0, False: 7.72k]
  ------------------
  132|      0|        Options::inspection_mode(value);
  133|      0|        return qpdf_r_ok;
  134|  7.72k|    case qpdf_p_fuzz_mode:
  ------------------
  |  Branch (134:5): [True: 7.72k, False: 0]
  ------------------
  135|  7.72k|        Options::fuzz_mode(value);
  136|  7.72k|        return qpdf_r_ok;
  137|      0|    case qpdf_p_default_limits:
  ------------------
  |  Branch (137:5): [True: 0, False: 7.72k]
  ------------------
  138|      0|        Options::default_limits(value);
  139|      0|        return qpdf_r_ok;
  140|      0|    case qpdf_p_dct_throw_on_corrupt_data:
  ------------------
  |  Branch (140:5): [True: 0, False: 7.72k]
  ------------------
  141|      0|        Options::dct_throw_on_corrupt_data(value);
  142|      0|        return qpdf_r_ok;
  143|      0|    case qpdf_p_doc_max_warnings:
  ------------------
  |  Branch (143:5): [True: 0, False: 7.72k]
  ------------------
  144|      0|        Limits::doc_max_warnings(value);
  145|      0|        return qpdf_r_ok;
  146|      0|    case qpdf_p_parser_max_nesting:
  ------------------
  |  Branch (146:5): [True: 0, False: 7.72k]
  ------------------
  147|      0|        Limits::parser_max_nesting(value);
  148|      0|        return qpdf_r_ok;
  149|      0|    case qpdf_p_parser_max_errors:
  ------------------
  |  Branch (149:5): [True: 0, False: 7.72k]
  ------------------
  150|      0|        Limits::parser_max_errors(value);
  151|      0|        return qpdf_r_ok;
  152|      0|    case qpdf_p_parser_max_container_size:
  ------------------
  |  Branch (152:5): [True: 0, False: 7.72k]
  ------------------
  153|      0|        Limits::parser_max_container_size(false, value);
  154|      0|        return qpdf_r_ok;
  155|      0|    case qpdf_p_parser_max_container_size_damaged:
  ------------------
  |  Branch (155:5): [True: 0, False: 7.72k]
  ------------------
  156|      0|        Limits::parser_max_container_size(true, value);
  157|      0|        return qpdf_r_ok;
  158|      0|    case qpdf_p_max_stream_filters:
  ------------------
  |  Branch (158:5): [True: 0, False: 7.72k]
  ------------------
  159|      0|        Limits::max_stream_filters(value);
  160|      0|        return qpdf_r_ok;
  161|      0|    case qpdf_p_dct_max_memory:
  ------------------
  |  Branch (161:5): [True: 0, False: 7.72k]
  ------------------
  162|      0|        Limits::dct_max_memory(util::fits<long>(value) ? static_cast<long>(value) : 0);
  ------------------
  |  Branch (162:32): [True: 0, False: 0]
  ------------------
  163|      0|        return qpdf_r_ok;
  164|      0|    case qpdf_p_dct_max_progressive_scans:
  ------------------
  |  Branch (164:5): [True: 0, False: 7.72k]
  ------------------
  165|      0|        Limits::dct_max_progressive_scans(util::fits<int>(value) ? static_cast<int>(value) : 0);
  ------------------
  |  Branch (165:43): [True: 0, False: 0]
  ------------------
  166|      0|        return qpdf_r_ok;
  167|      0|    case qpdf_p_flate_max_memory:
  ------------------
  |  Branch (167:5): [True: 0, False: 7.72k]
  ------------------
  168|      0|        Limits::flate_max_memory(value);
  169|      0|        return qpdf_r_ok;
  170|      0|    case qpdf_p_png_max_memory:
  ------------------
  |  Branch (170:5): [True: 0, False: 7.72k]
  ------------------
  171|      0|        Limits::png_max_memory(value);
  172|      0|        return qpdf_r_ok;
  173|      0|    case qpdf_p_run_length_max_memory:
  ------------------
  |  Branch (173:5): [True: 0, False: 7.72k]
  ------------------
  174|      0|        Limits::run_length_max_memory(value);
  175|      0|        return qpdf_r_ok;
  176|      0|    case qpdf_p_tiff_max_memory:
  ------------------
  |  Branch (176:5): [True: 0, False: 7.72k]
  ------------------
  177|      0|        Limits::tiff_max_memory(value);
  178|      0|        return qpdf_r_ok;
  179|      0|    default:
  ------------------
  |  Branch (179:5): [True: 0, False: 7.72k]
  ------------------
  180|      0|        return qpdf_r_bad_parameter;
  181|  7.72k|    }
  182|  7.72k|}

_ZNK4qpdf2is12OffsetBuffer7getNameEv:
   48|   195k|        {
   49|   195k|            return description;
   50|   195k|        }
_ZN4qpdf2is12OffsetBuffer4tellEv:
   54|   202k|        {
   55|   202k|            return pos + global_offset;
   56|   202k|        }
_ZN4qpdf2is12OffsetBuffer8unreadChEc:
   70|  7.72k|        {
   71|  7.72k|            if (pos > 0) {
  ------------------
  |  Branch (71:17): [True: 7.72k, False: 0]
  ------------------
   72|  7.72k|                --pos;
   73|  7.72k|            }
   74|  7.72k|        }
_ZN4qpdf2is12OffsetBufferD2Ev:
   42|  34.3k|        ~OffsetBuffer() final = default;
_ZN4qpdf2is12OffsetBufferC2ERKNSt3__112basic_stringIcNS2_11char_traitsIcEENS2_9allocatorIcEEEENS2_17basic_string_viewIcS5_EEx:
   21|  34.3k|            description(description),
   22|  34.3k|            view_(view),
   23|  34.3k|            global_offset(global_offset)
   24|  34.3k|        {
   25|  34.3k|            if (global_offset < 0) {
  ------------------
  |  Branch (25:17): [True: 0, False: 34.3k]
  ------------------
   26|      0|                throw std::logic_error("is::OffsetBuffer constructed with negative offset");
   27|      0|            }
   28|  34.3k|            last_offset = global_offset;
   29|  34.3k|        }
_ZN11InputSource4readERNSt3__112basic_stringIcNS0_11char_traitsIcEENS0_9allocatorIcEEEEmx:
   87|  7.72k|{
   88|  7.72k|    if (at >= 0) {
  ------------------
  |  Branch (88:9): [True: 0, False: 7.72k]
  ------------------
   89|       |        seek(at, SEEK_SET);
   90|      0|    }
   91|  7.72k|    str.resize(count);
   92|  7.72k|    str.resize(read(str.data(), count));
   93|  7.72k|    return str.size();
   94|  7.72k|}
_ZN11InputSource10loadBufferEv:
  106|  83.6k|{
  107|  83.6k|    buf_idx = 0;
  108|  83.6k|    buf_len = qpdf_offset_t(read(buffer, buf_size));
  109|       |    // NB read sets last_offset
  110|  83.6k|    buf_start = last_offset;
  111|  83.6k|}
_ZN11InputSource8fastTellEv:
  115|   137k|{
  116|   137k|    if (buf_len == 0) {
  ------------------
  |  Branch (116:9): [True: 18.8k, False: 118k]
  ------------------
  117|  18.8k|        loadBuffer();
  118|   118k|    } else {
  119|   118k|        auto curr = tell();
  120|   118k|        if (curr < buf_start || curr >= (buf_start + buf_len)) {
  ------------------
  |  Branch (120:13): [True: 7.72k, False: 111k]
  |  Branch (120:33): [True: 56.9k, False: 54.0k]
  ------------------
  121|  64.7k|            loadBuffer();
  122|  64.7k|        } else {
  123|  54.0k|            last_offset = curr;
  124|  54.0k|            buf_idx = curr - buf_start;
  125|  54.0k|        }
  126|   118k|    }
  127|   137k|    return last_offset;
  128|   137k|}
_ZN11InputSource8fastReadERc:
  132|  6.91M|{
  133|       |    // Before calling fastRead, fastTell must be called to prepare the buffer. Once reading is
  134|       |    // complete, fastUnread must be called to set the correct file position.
  135|  6.91M|    if (buf_idx < buf_len) {
  ------------------
  |  Branch (135:9): [True: 6.84M, False: 64.1k]
  ------------------
  136|  6.84M|        ch = buffer[buf_idx];
  137|  6.84M|        ++(buf_idx);
  138|  6.84M|        ++(last_offset);
  139|  6.84M|        return true;
  140|       |
  141|  6.84M|    } else if (buf_len == 0) {
  ------------------
  |  Branch (141:16): [True: 7.20k, False: 56.9k]
  ------------------
  142|  7.20k|        return false;
  143|  56.9k|    } else {
  144|       |        seek(buf_start + buf_len, SEEK_SET);
  145|  56.9k|        fastTell();
  146|  56.9k|        return fastRead(ch);
  147|  56.9k|    }
  148|  6.91M|}
_ZN11InputSource10fastUnreadEb:
  152|  80.7k|{
  153|  80.7k|    last_offset -= back ? 1 : 0;
  ------------------
  |  Branch (153:20): [True: 58.0k, False: 22.6k]
  ------------------
  154|       |    seek(last_offset, SEEK_SET);
  155|  80.7k|}

_ZNK4qpdf10BaseHandle13raw_type_codeEv:
  933|  8.19M|    {
  934|  8.19M|        return obj ? static_cast<qpdf_object_type_e>(obj->value.index()) : ::ot_uninitialized;
  ------------------
  |  Branch (934:16): [True: 8.19M, False: 0]
  ------------------
  935|  8.19M|    }
_ZNK4qpdf10BaseHandle4qpdfEv:
  927|  7.34M|    {
  928|  7.34M|        return obj ? obj->qpdf : nullptr;
  ------------------
  |  Branch (928:16): [True: 7.34M, False: 0]
  ------------------
  929|  7.34M|    }
_ZNK4qpdf10BaseHandle6offsetEv:
  921|    669|    {
  922|    669|        return obj ? obj->parsed_offset : -1;
  ------------------
  |  Branch (922:16): [True: 669, False: 0]
  ------------------
  923|    669|    }
_ZNK4qpdf10BaseHandle9type_codeEv:
  951|  2.32M|    {
  952|  2.32M|        if (!obj) {
  ------------------
  |  Branch (952:13): [True: 0, False: 2.32M]
  ------------------
  953|      0|            return ::ot_uninitialized;
  954|      0|        }
  955|  2.32M|        if (raw_type_code() == ::ot_unresolved) {
  ------------------
  |  Branch (955:13): [True: 0, False: 2.32M]
  ------------------
  956|      0|            return QPDF::Doc::Resolver::resolved(obj->qpdf, obj->og)->getTypeCode();
  957|      0|        }
  958|  2.32M|        if (raw_type_code() == ::ot_reference) {
  ------------------
  |  Branch (958:13): [True: 739, False: 2.32M]
  ------------------
  959|    739|            return std::get<QPDF_Reference>(obj->value).obj->getTypeCode();
  960|    739|        }
  961|  2.32M|        return raw_type_code();
  962|  2.32M|    }
_ZNK4qpdf10BaseHandle8indirectEv:
  860|  1.83M|    {
  861|  1.83M|        return obj ? obj->og.isIndirect() : false;
  ------------------
  |  Branch (861:16): [True: 1.83M, False: 0]
  ------------------
  862|  1.83M|    }
_ZNK4qpdf10BaseHandle4nullEv:
  907|   131k|    {
  908|   131k|        return !obj || type_code() == ::ot_null;
  ------------------
  |  Branch (908:16): [True: 23.1k, False: 107k]
  |  Branch (908:24): [True: 18.8k, False: 89.0k]
  ------------------
  909|   131k|    }
_ZNK4qpdf10BaseHandle18resolved_type_codeEv:
  939|  23.1k|    {
  940|  23.1k|        if (!obj) {
  ------------------
  |  Branch (940:13): [True: 0, False: 23.1k]
  ------------------
  941|      0|            return ::ot_uninitialized;
  942|      0|        }
  943|  23.1k|        if (raw_type_code() == ::ot_unresolved) {
  ------------------
  |  Branch (943:13): [True: 0, False: 23.1k]
  ------------------
  944|      0|            return QPDF::Doc::Resolver::resolved(obj->qpdf, obj->og)->getTypeCode();
  945|      0|        }
  946|  23.1k|        return raw_type_code();
  947|  23.1k|    }
_ZN4qpdf10BaseHandleC2ERK16QPDFObjectHandle:
  788|  30.9k|        obj(oh.obj)
  789|  30.9k|    {
  790|  30.9k|    }
_ZN4qpdf10DictionaryC2ERK16QPDFObjectHandle:
  268|  23.1k|            BaseDictionary(oh)
  269|  23.1k|        {
  270|  23.1k|        }
_ZN4qpdf14BaseDictionaryC2ERK16QPDFObjectHandle:
  238|  23.1k|            BaseHandle(oh.resolved_type_code() == ::ot_dictionary ? oh : QPDFObjectHandle())
  ------------------
  |  Branch (238:24): [True: 23.1k, False: 0]
  ------------------
  239|  23.1k|        {
  240|  23.1k|        }
_ZNK4qpdf10BaseHandle2asI15QPDF_DictionaryEEPT_v:
  770|   155k|    {
  771|   155k|        if (!obj) {
  ------------------
  |  Branch (771:13): [True: 0, False: 155k]
  ------------------
  772|      0|            return nullptr;
  773|      0|        }
  774|   155k|        if (std::holds_alternative<T>(obj->value)) {
  ------------------
  |  Branch (774:13): [True: 155k, False: 0]
  ------------------
  775|   155k|            return &std::get<T>(obj->value);
  776|   155k|        }
  777|      0|        if (std::holds_alternative<QPDF_Unresolved>(obj->value)) {
  ------------------
  |  Branch (777:13): [True: 0, False: 0]
  ------------------
  778|      0|            return BaseHandle(QPDF::Doc::Resolver::resolved(obj->qpdf, obj->og)).as<T>();
  779|      0|        }
  780|      0|        if (std::holds_alternative<QPDF_Reference>(obj->value)) {
  ------------------
  |  Branch (780:13): [True: 0, False: 0]
  ------------------
  781|       |            // see comment in QPDF_Reference.
  782|      0|            return BaseHandle(std::get<QPDF_Reference>(obj->value).obj).as<T>();
  783|      0|        }
  784|      0|        return nullptr;
  785|      0|    }
_ZNK4qpdf6Stream6streamEv:
  697|  27.5k|        {
  698|  27.5k|            if (auto s = as<QPDF_Stream>()) {
  ------------------
  |  Branch (698:22): [True: 27.5k, False: 0]
  ------------------
  699|  27.5k|                if (auto ptr = s->m.get()) {
  ------------------
  |  Branch (699:26): [True: 27.5k, False: 0]
  ------------------
  700|  27.5k|                    return ptr;
  701|  27.5k|                }
  702|      0|                throw std::logic_error("QPDF_Stream: unexpected nullptr");
  703|  27.5k|            }
  704|      0|            throw std::runtime_error("operation for stream attempted on non-stream object");
  705|      0|            return nullptr; // unreachable
  706|  27.5k|        }
_ZNK4qpdf10BaseHandle2asI11QPDF_StreamEEPT_v:
  770|  27.5k|    {
  771|  27.5k|        if (!obj) {
  ------------------
  |  Branch (771:13): [True: 0, False: 27.5k]
  ------------------
  772|      0|            return nullptr;
  773|      0|        }
  774|  27.5k|        if (std::holds_alternative<T>(obj->value)) {
  ------------------
  |  Branch (774:13): [True: 27.5k, False: 0]
  ------------------
  775|  27.5k|            return &std::get<T>(obj->value);
  776|  27.5k|        }
  777|      0|        if (std::holds_alternative<QPDF_Unresolved>(obj->value)) {
  ------------------
  |  Branch (777:13): [True: 0, False: 0]
  ------------------
  778|      0|            return BaseHandle(QPDF::Doc::Resolver::resolved(obj->qpdf, obj->og)).as<T>();
  779|      0|        }
  780|      0|        if (std::holds_alternative<QPDF_Reference>(obj->value)) {
  ------------------
  |  Branch (780:13): [True: 0, False: 0]
  ------------------
  781|       |            // see comment in QPDF_Reference.
  782|      0|            return BaseHandle(std::get<QPDF_Reference>(obj->value).obj).as<T>();
  783|      0|        }
  784|      0|        return nullptr;
  785|      0|    }
_ZN4qpdf7IntegerC2ERK16QPDFObjectHandle:
  319|  7.72k|            BaseHandle(oh.type_code() == ::ot_integer ? oh : QPDFObjectHandle())
  ------------------
  |  Branch (319:24): [True: 7.72k, False: 0]
  ------------------
  320|  7.72k|        {
  321|  7.72k|        }
_ZN10QPDFObject6createI9QPDF_NullJEEENSt3__110shared_ptrIS_EEDpOT0_:
  988|  25.5k|{
  989|  25.5k|    return std::make_shared<QPDFObject>(std::forward<T>(T(std::forward<Args>(args)...)));
  990|  25.5k|}
_ZNK4qpdf7Integer5valueITkNSt3__18integralEiEET_v:
  361|  7.72k|        {
  362|  7.72k|            try {
  363|  7.72k|                return static_cast<T>(*this);
  364|  7.72k|            } catch (std::underflow_error&) {
  365|      0|                if constexpr (std::is_same_v<T, int>) {
  366|      0|                    warn("requested value of integer is too small; returning INT_MIN");
  367|       |                } else if constexpr (std::is_same_v<T, unsigned int>) {
  368|       |                    warn("unsigned integer value request for negative number; returning 0");
  369|       |                } else if constexpr (std::is_same_v<T, unsigned long long>) {
  370|       |                    warn("unsigned value request for negative number; returning 0");
  371|       |                } else {
  372|       |                    warn(
  373|       |                        "underflow while converting integer object; returning smallest possible "
  374|       |                        "value");
  375|       |                }
  376|      0|                return std::numeric_limits<T>::min();
  377|      0|            } catch (std::overflow_error&) {
  378|      0|                if constexpr (std::is_same_v<T, int>) {
  379|      0|                    warn("requested value of integer is too big; returning INT_MAX");
  380|       |                } else if constexpr (std::is_same_v<T, unsigned int>) {
  381|       |                    warn("requested value of unsigned integer is too big; returning UINT_MAX");
  382|       |                } else {
  383|       |                    warn(
  384|       |                        "overflow while converting integer object; returning largest possible "
  385|       |                        "value");
  386|       |                }
  387|      0|                return std::numeric_limits<T>::max();
  388|      0|            }
  389|  7.72k|        }
_ZNK4qpdf7IntegercvT_ITkNSt3__18integralEiEEv:
  339|  7.72k|        {
  340|  7.72k|            auto v = value();
  341|       |
  342|  7.72k|            if (std::cmp_greater(v, std::numeric_limits<T>::max())) {
  ------------------
  |  Branch (342:17): [True: 0, False: 7.72k]
  ------------------
  343|      0|                throw std::overflow_error("Integer conversion overflow");
  344|      0|            }
  345|  7.72k|            if (std::cmp_less(v, std::numeric_limits<T>::min())) {
  ------------------
  |  Branch (345:17): [True: 0, False: 7.72k]
  ------------------
  346|      0|                throw std::underflow_error("Integer conversion underflow");
  347|      0|            }
  348|  7.72k|            return static_cast<T>(v);
  349|  7.72k|        }
_ZN4qpdf5ArrayC2ERKNSt3__110shared_ptrI10QPDFObjectEE:
   47|  1.83M|            BaseHandle(obj)
   48|  1.83M|        {
   49|  1.83M|        }
_ZN4qpdf14BaseDictionaryC2ERKNSt3__110shared_ptrI10QPDFObjectEE:
  225|   100k|            BaseHandle(obj)
  226|   100k|        {
  227|   100k|        }
_ZN4qpdf4NullC2Ev:
  483|      2|            BaseHandle(QPDFObject::create<QPDF_Null>())
  484|      2|        {
  485|      2|        }
_ZN4qpdf6StreamC2ERKNSt3__110shared_ptrI10QPDFObjectEE:
  515|  12.1k|            BaseHandle(obj)
  516|  12.1k|        {
  517|  12.1k|        }
_ZN4qpdf6Stream11replaceDictERK16QPDFObjectHandle:
  681|  2.75k|        {
  682|  2.75k|            auto s = stream();
  683|  2.75k|            s->stream_dict = new_dict;
  684|  2.75k|            setDictDescription();
  685|  2.75k|        }
_ZNK4qpdf10BaseHandle6obj_spEv:
  799|  1.25M|    {
  800|  1.25M|        return obj;
  801|  1.25M|    }
_ZNK4qpdf10BaseHandle3getERKNSt3__112basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEE:
  901|  15.4k|    {
  902|  15.4k|        return (*this)[key];
  903|  15.4k|    }
_ZNK16QPDFObjectHandle8as_arrayEN4qpdf5typedE:
 1006|  1.83M|{
 1007|  1.83M|    if (options & qpdf::error) {
  ------------------
  |  Branch (1007:9): [True: 0, False: 1.83M]
  ------------------
 1008|      0|        assertType("array", false);
 1009|      0|    }
 1010|  1.83M|    if (options & qpdf::any_flag || type_code() == ::ot_array ||
  ------------------
  |  Branch (1010:9): [True: 0, False: 1.83M]
  |  Branch (1010:37): [True: 1.83M, False: 0]
  ------------------
 1011|  1.83M|        (options & qpdf::optional && type_code() == ::ot_null)) {
  ------------------
  |  Branch (1011:10): [True: 0, False: 0]
  |  Branch (1011:38): [True: 0, False: 0]
  ------------------
 1012|  1.83M|        return qpdf::Array(obj);
 1013|  1.83M|    }
 1014|      0|    return qpdf::Array(std::shared_ptr<QPDFObject>());
 1015|  1.83M|}
_ZNK16QPDFObjectHandle13as_dictionaryEN4qpdf5typedE:
 1019|   100k|{
 1020|   100k|    if (options & qpdf::any_flag || type_code() == ::ot_dictionary ||
  ------------------
  |  Branch (1020:9): [True: 0, False: 100k]
  |  Branch (1020:37): [True: 100k, False: 0]
  ------------------
 1021|   100k|        (options & qpdf::optional && type_code() == ::ot_null)) {
  ------------------
  |  Branch (1021:10): [True: 0, False: 0]
  |  Branch (1021:38): [True: 0, False: 0]
  ------------------
 1022|   100k|        return qpdf::Dictionary(obj);
 1023|   100k|    }
 1024|      0|    if (options & qpdf::error) {
  ------------------
  |  Branch (1024:9): [True: 0, False: 0]
  ------------------
 1025|      0|        assertType("dictionary", false);
 1026|      0|    }
 1027|      0|    return qpdf::Dictionary(std::shared_ptr<QPDFObject>());
 1028|   100k|}
_ZNK16QPDFObjectHandle9as_streamEN4qpdf5typedE:
 1032|  12.1k|{
 1033|  12.1k|    if (options & qpdf::any_flag || type_code() == ::ot_stream ||
  ------------------
  |  Branch (1033:9): [True: 0, False: 12.1k]
  |  Branch (1033:37): [True: 12.1k, False: 0]
  ------------------
 1034|  12.1k|        (options & qpdf::optional && type_code() == ::ot_null)) {
  ------------------
  |  Branch (1034:10): [True: 0, False: 0]
  |  Branch (1034:38): [True: 0, False: 0]
  ------------------
 1035|  12.1k|        return qpdf::Stream(obj);
 1036|  12.1k|    }
 1037|      0|    if (options & qpdf::error) {
  ------------------
  |  Branch (1037:9): [True: 0, False: 0]
  ------------------
 1038|      0|        assertType("stream", false);
 1039|      0|    }
 1040|      0|    return qpdf::Stream(std::shared_ptr<QPDFObject>());
 1041|  12.1k|}
_ZN10QPDFObject6createI15QPDF_DictionaryJRKNSt3__13mapINS2_12basic_stringIcNS2_11char_traitsIcEENS2_9allocatorIcEEEE16QPDFObjectHandleNS2_4lessIS9_EENS7_INS2_4pairIKS9_SA_EEEEEEEEENS2_10shared_ptrIS_EEDpOT0_:
  988|  23.6k|{
  989|  23.6k|    return std::make_shared<QPDFObject>(std::forward<T>(T(std::forward<Args>(args)...)));
  990|  23.6k|}
_ZN10QPDFObject6createI15QPDF_DictionaryJNSt3__13mapINS2_12basic_stringIcNS2_11char_traitsIcEENS2_9allocatorIcEEEE16QPDFObjectHandleNS2_4lessIS9_EENS7_INS2_4pairIKS9_SA_EEEEEEEEENS2_10shared_ptrIS_EEDpOT0_:
  988|  7.72k|{
  989|  7.72k|    return std::make_shared<QPDFObject>(std::forward<T>(T(std::forward<Args>(args)...)));
  990|  7.72k|}
_ZN10QPDFObject6createI9QPDF_BoolJRbEEENSt3__110shared_ptrIS_EEDpOT0_:
  988|  5.58k|{
  989|  5.58k|    return std::make_shared<QPDFObject>(std::forward<T>(T(std::forward<Args>(args)...)));
  990|  5.58k|}
_ZN10QPDFObject6createI12QPDF_IntegerJRxEEENSt3__110shared_ptrIS_EEDpOT0_:
  988|  1.13M|{
  989|  1.13M|    return std::make_shared<QPDFObject>(std::forward<T>(T(std::forward<Args>(args)...)));
  990|  1.13M|}
_ZNK4qpdf10BaseHandle2asI12QPDF_IntegerEEPT_v:
  770|  7.72k|    {
  771|  7.72k|        if (!obj) {
  ------------------
  |  Branch (771:13): [True: 0, False: 7.72k]
  ------------------
  772|      0|            return nullptr;
  773|      0|        }
  774|  7.72k|        if (std::holds_alternative<T>(obj->value)) {
  ------------------
  |  Branch (774:13): [True: 7.72k, False: 0]
  ------------------
  775|  7.72k|            return &std::get<T>(obj->value);
  776|  7.72k|        }
  777|      0|        if (std::holds_alternative<QPDF_Unresolved>(obj->value)) {
  ------------------
  |  Branch (777:13): [True: 0, False: 0]
  ------------------
  778|      0|            return BaseHandle(QPDF::Doc::Resolver::resolved(obj->qpdf, obj->og)).as<T>();
  779|      0|        }
  780|      0|        if (std::holds_alternative<QPDF_Reference>(obj->value)) {
  ------------------
  |  Branch (780:13): [True: 0, False: 0]
  ------------------
  781|       |            // see comment in QPDF_Reference.
  782|      0|            return BaseHandle(std::get<QPDF_Reference>(obj->value).obj).as<T>();
  783|      0|        }
  784|      0|        return nullptr;
  785|      0|    }
_ZN10QPDFObject6createI9QPDF_NameJRKNSt3__112basic_stringIcNS2_11char_traitsIcEENS2_9allocatorIcEEEEEEENS2_10shared_ptrIS_EEDpOT0_:
  988|  21.6k|{
  989|  21.6k|    return std::make_shared<QPDFObject>(std::forward<T>(T(std::forward<Args>(args)...)));
  990|  21.6k|}
_ZNK4qpdf10BaseHandle2asI9QPDF_NameEEPT_v:
  770|  4.44k|    {
  771|  4.44k|        if (!obj) {
  ------------------
  |  Branch (771:13): [True: 0, False: 4.44k]
  ------------------
  772|      0|            return nullptr;
  773|      0|        }
  774|  4.44k|        if (std::holds_alternative<T>(obj->value)) {
  ------------------
  |  Branch (774:13): [True: 4.44k, False: 0]
  ------------------
  775|  4.44k|            return &std::get<T>(obj->value);
  776|  4.44k|        }
  777|      0|        if (std::holds_alternative<QPDF_Unresolved>(obj->value)) {
  ------------------
  |  Branch (777:13): [True: 0, False: 0]
  ------------------
  778|      0|            return BaseHandle(QPDF::Doc::Resolver::resolved(obj->qpdf, obj->og)).as<T>();
  779|      0|        }
  780|      0|        if (std::holds_alternative<QPDF_Reference>(obj->value)) {
  ------------------
  |  Branch (780:13): [True: 0, False: 0]
  ------------------
  781|       |            // see comment in QPDF_Reference.
  782|      0|            return BaseHandle(std::get<QPDF_Reference>(obj->value).obj).as<T>();
  783|      0|        }
  784|      0|        return nullptr;
  785|      0|    }
_ZN10QPDFObject6createI11QPDF_StringJRKNSt3__112basic_stringIcNS2_11char_traitsIcEENS2_9allocatorIcEEEEEEENS2_10shared_ptrIS_EEDpOT0_:
  988|  2.50k|{
  989|  2.50k|    return std::make_shared<QPDFObject>(std::forward<T>(T(std::forward<Args>(args)...)));
  990|  2.50k|}
_ZN10QPDFObject6createI11QPDF_StringJNSt3__112basic_stringIcNS2_11char_traitsIcEENS2_9allocatorIcEEEEEEENS2_10shared_ptrIS_EEDpOT0_:
  988|  4.51k|{
  989|  4.51k|    return std::make_shared<QPDFObject>(std::forward<T>(T(std::forward<Args>(args)...)));
  990|  4.51k|}
_ZN10QPDFObject6createI9QPDF_RealJRKNSt3__112basic_stringIcNS2_11char_traitsIcEENS2_9allocatorIcEEEEEEENS2_10shared_ptrIS_EEDpOT0_:
  988|  8.60k|{
  989|  8.60k|    return std::make_shared<QPDFObject>(std::forward<T>(T(std::forward<Args>(args)...)));
  990|  8.60k|}
_ZN10QPDFObject6createI10QPDF_ArrayJRKNSt3__16vectorI16QPDFObjectHandleNS2_9allocatorIS4_EEEEEEENS2_10shared_ptrIS_EEDpOT0_:
  988|  11.8k|{
  989|  11.8k|    return std::make_shared<QPDFObject>(std::forward<T>(T(std::forward<Args>(args)...)));
  990|  11.8k|}
_ZN15QPDF_DictionaryC2EONSt3__13mapINS0_12basic_stringIcNS0_11char_traitsIcEENS0_9allocatorIcEEEE16QPDFObjectHandleNS0_4lessIS7_EENS5_INS0_4pairIKS7_S8_EEEEEE:
  967|  7.72k|    items(std::move(items))
  968|  7.72k|{
  969|  7.72k|}
_ZNK4qpdf10BaseHandle2asI10QPDF_ArrayEEPT_v:
  770|  1.83M|    {
  771|  1.83M|        if (!obj) {
  ------------------
  |  Branch (771:13): [True: 0, False: 1.83M]
  ------------------
  772|      0|            return nullptr;
  773|      0|        }
  774|  1.83M|        if (std::holds_alternative<T>(obj->value)) {
  ------------------
  |  Branch (774:13): [True: 1.83M, False: 0]
  ------------------
  775|  1.83M|            return &std::get<T>(obj->value);
  776|  1.83M|        }
  777|      0|        if (std::holds_alternative<QPDF_Unresolved>(obj->value)) {
  ------------------
  |  Branch (777:13): [True: 0, False: 0]
  ------------------
  778|      0|            return BaseHandle(QPDF::Doc::Resolver::resolved(obj->qpdf, obj->og)).as<T>();
  779|      0|        }
  780|      0|        if (std::holds_alternative<QPDF_Reference>(obj->value)) {
  ------------------
  |  Branch (780:13): [True: 0, False: 0]
  ------------------
  781|       |            // see comment in QPDF_Reference.
  782|      0|            return BaseHandle(std::get<QPDF_Reference>(obj->value).obj).as<T>();
  783|      0|        }
  784|      0|        return nullptr;
  785|      0|    }

_ZNK10QPDFObject11getTypeCodeEv:
  329|  7.34k|    {
  330|  7.34k|        return static_cast<qpdf_object_type_e>(value.index());
  331|  7.34k|    }
_ZN10QPDFObjectC2I9QPDF_NullEEOT_:
  300|  25.5k|        value(std::forward<T>(value))
  301|  25.5k|    {
  302|  25.5k|    }
_ZN10QPDF_ArrayC2ERKNSt3__16vectorI16QPDFObjectHandleNS0_9allocatorIS2_EEEE:
   67|  11.8k|        elements(items)
   68|  11.8k|    {
   69|  11.8k|    }
_ZN9QPDF_BoolC2Eb:
   94|  5.58k|        val(val)
   95|  5.58k|    {
   96|  5.58k|    }
_ZN15QPDF_DictionaryC2ERKNSt3__13mapINS0_12basic_stringIcNS0_11char_traitsIcEENS0_9allocatorIcEEEE16QPDFObjectHandleNS0_4lessIS7_EENS5_INS0_4pairIKS7_S8_EEEEEE:
  111|  23.6k|        items(items)
  112|  23.6k|    {
  113|  23.6k|    }
_ZN12QPDF_IntegerC2Ex:
  140|  1.13M|        val(val)
  141|  1.13M|    {
  142|  1.13M|    }
_ZN9QPDF_NameC2ENSt3__112basic_stringIcNS0_11char_traitsIcEENS0_9allocatorIcEEEE:
  154|  21.6k|        name(std::move(name))
  155|  21.6k|    {
  156|  21.6k|    }
_ZN9QPDF_RealC2ENSt3__112basic_stringIcNS0_11char_traitsIcEENS0_9allocatorIcEEEE:
  193|  8.60k|        val(std::move(val))
  194|  8.60k|    {
  195|  8.60k|    }
_ZN14QPDF_ReferenceC2ENSt3__110shared_ptrI10QPDFObjectEE:
  210|  17.3k|        obj(std::move(obj))
  211|  17.3k|    {
  212|  17.3k|    }
_ZN11QPDF_Stream7MembersC2E16QPDFObjectHandlem:
  232|  3.30k|            stream_dict(std::move(stream_dict)),
  233|  3.30k|            length(length)
  234|  3.30k|        {
  235|  3.30k|        }
_ZN11QPDF_StreamC2E16QPDFObjectHandlem:
  254|  3.30k|        m(std::make_unique<Members>(stream_dict, length))
  255|  3.30k|    {
  256|  3.30k|        if (!stream_dict.isDictionary()) {
  ------------------
  |  Branch (256:13): [True: 0, False: 3.30k]
  ------------------
  257|      0|            throw std::logic_error(
  258|      0|                "stream object instantiated with non-dictionary object for dictionary");
  259|      0|        }
  260|  3.30k|    }
_ZN11QPDF_StringC2ERKNSt3__112basic_stringIcNS0_11char_traitsIcEENS0_9allocatorIcEEEE:
  279|  2.50k|        val(val)
  280|  2.50k|    {
  281|  2.50k|    }
_ZN11QPDF_StringC2EONSt3__112basic_stringIcNS0_11char_traitsIcEENS0_9allocatorIcEEEE:
  283|  4.51k|        val(std::move(val))
  284|  4.51k|    {
  285|  4.51k|    }
_ZN10QPDFObject7move_toERNSt3__110shared_ptrIS_EEb:
  343|  17.3k|    {
  344|  17.3k|        o->value = std::move(value);
  345|  17.3k|        o->qpdf = qpdf;
  346|  17.3k|        o->og = og;
  347|  17.3k|        o->object_description = object_description;
  348|  17.3k|        o->parsed_offset = parsed_offset;
  349|  17.3k|        if (!destroy) {
  ------------------
  |  Branch (349:13): [True: 17.3k, False: 0]
  ------------------
  350|  17.3k|            value = QPDF_Reference(o);
  351|  17.3k|        }
  352|  17.3k|    }
_ZN10QPDFObject9setObjGenEP4QPDF10QPDFObjGen:
  364|  17.3k|    {
  365|  17.3k|        qpdf = a_qpdf;
  366|  17.3k|        og = a_og;
  367|  17.3k|    }
_ZN10QPDFObject10JSON_DescrC2ENSt3__110shared_ptrINS1_12basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEEEERKS8_:
  378|  18.4k|            input(input),
  379|  18.4k|            object(object)
  380|  18.4k|        {
  381|  18.4k|        }
_ZN10QPDFObject14setDescriptionEP4QPDFRNSt3__110shared_ptrINS2_7variantIJNS2_12basic_stringIcNS2_11char_traitsIcEENS2_9allocatorIcEEEENS_10JSON_DescrENS_10ChildDescrENS_14ObjStreamDescrEEEEEEx:
  419|  1.26M|    {
  420|  1.26M|        qpdf = qpdf_p;
  421|  1.26M|        object_description = description;
  422|  1.26M|        setParsedOffset(offset);
  423|  1.26M|    }
_ZN10QPDFObject14hasDescriptionEv:
  444|  1.96M|    {
  445|  1.96M|        return object_description || og.isIndirect();
  ------------------
  |  Branch (445:16): [True: 147k, False: 1.81M]
  |  Branch (445:38): [True: 601k, False: 1.21M]
  ------------------
  446|  1.96M|    }
_ZN10QPDFObject15setParsedOffsetEx:
  449|  1.26M|    {
  450|  1.26M|        if (parsed_offset < 0) {
  ------------------
  |  Branch (450:13): [True: 1.24M, False: 19.3k]
  ------------------
  451|  1.24M|            parsed_offset = offset;
  452|  1.24M|        }
  453|  1.26M|    }
_ZN10QPDFObject7getQPDFEv:
  456|   203k|    {
  457|   203k|        return qpdf;
  458|   203k|    }
_ZN10QPDFObject9getObjGenEv:
  461|  64.1k|    {
  462|  64.1k|        return og;
  463|  64.1k|    }
_ZN10QPDFObjectC2I15QPDF_DictionaryEEOT_:
  300|  31.3k|        value(std::forward<T>(value))
  301|  31.3k|    {
  302|  31.3k|    }
_ZN10QPDFObjectC2I9QPDF_BoolEEOT_:
  300|  5.58k|        value(std::forward<T>(value))
  301|  5.58k|    {
  302|  5.58k|    }
_ZN10QPDFObjectC2I12QPDF_IntegerEEOT_:
  300|  1.13M|        value(std::forward<T>(value))
  301|  1.13M|    {
  302|  1.13M|    }
_ZN10QPDFObjectC2I9QPDF_RealEEOT_:
  300|  8.60k|        value(std::forward<T>(value))
  301|  8.60k|    {
  302|  8.60k|    }
_ZN10QPDFObjectC2I11QPDF_StringEEOT_:
  300|  7.01k|        value(std::forward<T>(value))
  301|  7.01k|    {
  302|  7.01k|    }
_ZN10QPDFObjectC2I9QPDF_NameEEOT_:
  300|  21.6k|        value(std::forward<T>(value))
  301|  21.6k|    {
  302|  21.6k|    }
_ZN10QPDFObjectC2I10QPDF_ArrayEEOT_:
  300|  11.8k|        value(std::forward<T>(value))
  301|  11.8k|    {
  302|  11.8k|    }
_ZN10QPDF_ArrayC2EOS_:
   58|  13.0k|    QPDF_Array(QPDF_Array&&) = default;
_ZN10QPDFObject6createI11QPDF_StreamJ16QPDFObjectHandleRmEEENSt3__110shared_ptrIS_EEP4QPDF10QPDFObjGenDpOT0_:
  318|  3.30k|    {
  319|  3.30k|        return std::make_shared<QPDFObject>(
  320|  3.30k|            qpdf, og, std::forward<T>(T(std::forward<Args>(args)...)));
  321|  3.30k|    }
_ZN10QPDFObjectC2I11QPDF_StreamEEP4QPDF10QPDFObjGenOT_:
  306|  3.30k|        value(std::forward<T>(value)),
  307|  3.30k|        qpdf(qpdf),
  308|  3.30k|        og(og)
  309|  3.30k|    {
  310|  3.30k|    }
_ZN10QPDF_ArrayaSEOS_:
   59|    348|    QPDF_Array& operator=(QPDF_Array&&) = default;
_ZN10QPDFObject6createI9QPDF_NullJEEENSt3__110shared_ptrIS_EEP4QPDF10QPDFObjGenDpOT0_:
  318|  12.8k|    {
  319|  12.8k|        return std::make_shared<QPDFObject>(
  320|  12.8k|            qpdf, og, std::forward<T>(T(std::forward<Args>(args)...)));
  321|  12.8k|    }
_ZN10QPDFObjectC2I9QPDF_NullEEP4QPDF10QPDFObjGenOT_:
  306|  12.8k|        value(std::forward<T>(value)),
  307|  12.8k|        qpdf(qpdf),
  308|  12.8k|        og(og)
  309|  12.8k|    {
  310|  12.8k|    }

_ZN4qpdf4impl6Parser16make_descriptionERKNSt3__112basic_stringIcNS2_11char_traitsIcEENS2_9allocatorIcEEEESA_:
  110|  18.8k|        {
  111|  18.8k|            using namespace std::literals;
  112|  18.8k|            return std::make_shared<QPDFObject::Description>(
  113|  18.8k|                input_name + ", " + object_description + " at offset $PO");
  114|  18.8k|        }
_ZN4qpdf4impl6ParserC2ER11InputSourceNSt3__110shared_ptrINS4_7variantIJNS4_12basic_stringIcNS4_11char_traitsIcEENS4_9allocatorIcEEEEN10QPDFObject10JSON_DescrENSD_10ChildDescrENSD_14ObjStreamDescrEEEEEERKSC_RNS_9TokenizerEPN16QPDFObjectHandle15StringDecrypterEP4QPDFbiib:
  139|  18.8k|            input_(input),
  140|  18.8k|            object_description_(object_description),
  141|  18.8k|            tokenizer_(tokenizer),
  142|  18.8k|            decrypter_(decrypter),
  143|  18.8k|            context_(context),
  144|  18.8k|            description_(std::move(sp_description)),
  145|  18.8k|            parse_pdf_(parse_pdf),
  146|  18.8k|            stream_id_(stream_id),
  147|  18.8k|            obj_id_(obj_id),
  148|  18.8k|            sanity_checks_(sanity_checks)
  149|  18.8k|        {
  150|  18.8k|        }
_ZN4qpdf4impl6Parser10StackFrameC2ER11InputSourceNS1_14parser_state_eE:
  160|  7.72k|                state(state),
  161|  7.72k|                offset(input.tell())
  162|  7.72k|            {
  163|  7.72k|            }

_ZNK4qpdf9Tokenizer7getTypeEv:
   64|  57.1k|        {
   65|  57.1k|            return this->type;
   66|  57.1k|        }
_ZNK4qpdf9Tokenizer8getValueEv:
   69|  26.2k|        {
   70|  26.2k|            return (this->type == QPDFTokenizer::tt_name || this->type == QPDFTokenizer::tt_string)
  ------------------
  |  Branch (70:21): [True: 18.5k, False: 7.72k]
  |  Branch (70:61): [True: 0, False: 7.72k]
  ------------------
   71|  26.2k|                ? this->val
   72|  26.2k|                : this->raw_val;
   73|  26.2k|        }
_ZNK4qpdf9Tokenizer15getErrorMessageEv:
   81|    340|        {
   82|    340|            return this->error_message;
   83|    340|        }

_ZN4QPDF3DocC2ERS_PNS_7MembersE:
  351|  7.72k|        qpdf(qpdf),
  352|  7.72k|        m(m)
  353|  7.72k|    {
  354|  7.72k|    }
_ZN4qpdf3Doc6ConfigC2Ev:
   43|  7.72k|                log_(QPDFLogger::defaultLogger())
   44|  7.72k|            {
   45|  7.72k|            }
_ZN4QPDF3Doc6CommonC2ERS_PNS_7MembersE:
 1285|  30.9k|    qpdf(qpdf),
 1286|  30.9k|    m(m),
 1287|  30.9k|    cf(m->cf),
 1288|  30.9k|    pages(m->pages),
 1289|  30.9k|    objects(m->objects)
 1290|  30.9k|{
 1291|  30.9k|}
_ZN4QPDF3Doc13LinearizationC2ERS0_:
  601|  7.72k|        Common(doc)
  602|  7.72k|    {
  603|  7.72k|    }
_ZN4QPDF3Doc6CommonC2ERS0_:
 1294|  23.1k|    Common(doc.qpdf, doc.m)
 1295|  23.1k|{
 1296|  23.1k|}
_ZN4QPDF3Doc7ObjectsC2ERS0_:
  995|  7.72k|        Common(doc),
  996|  7.72k|        foreign_(*this),
  997|  7.72k|        streams_(*this)
  998|  7.72k|    {
  999|  7.72k|    }
_ZN4QPDF3Doc7Objects7ForeignC2ERNS0_6CommonE:
  910|  7.72k|            Common(common)
  911|  7.72k|        {
  912|  7.72k|        }
_ZN4QPDF3Doc7Objects7ForeignD2Ev:
  919|  7.72k|        ~Foreign() = default;
_ZN4QPDF3Doc5PagesC2ERS0_:
 1138|  7.72k|        Common(doc)
 1139|  7.72k|    {
 1140|  7.72k|    }
_ZN4QPDF3Doc5PagesD2Ev:
 1135|  7.72k|    ~Pages() = default;
_ZN4QPDF3Doc7ObjectsD2Ev:
  992|  7.72k|    ~Objects() = default;
_ZN4QPDF3Doc7Objects7StreamsD2Ev:
  948|  7.72k|        ~Streams() = default;
_ZN4QPDF3Doc13LinearizationD2Ev:
  598|  7.72k|    ~Linearization() = default;
_ZN4QPDF3DocD2Ev:
  348|  7.72k|    ~Doc() = default;
_ZN4qpdf3Doc6Config12max_warningsEm:
  107|  15.4k|            {
  108|  15.4k|                max_warnings_ = val;
  109|  15.4k|                return *this;
  110|  15.4k|            }
_ZNK4qpdf3Doc6Config3logEv:
   75|  49.9k|            {
   76|  49.9k|                return log_;
   77|  49.9k|            }
_ZNK4qpdf3Doc6Config12max_warningsEv:
  101|   115k|            {
  102|   115k|                return max_warnings_;
  103|   115k|            }
_ZNK4qpdf3Doc6Config17suppress_warningsEv:
   88|  49.9k|            {
   89|  49.9k|                return suppress_warnings_;
   90|  49.9k|            }
_ZN4QPDF20EncryptionParametersC2Ev:
  191|  7.72k|    EncryptionParameters() = default;
_ZN4QPDF7MembersD2Ev:
 1238|  7.72k|    ~Members() = default;
_ZN4QPDF3Doc6Common3toIIlEEiRKT_:
  325|  7.72k|        {
  326|  7.72k|            return QIntC::to_int(i);
  327|  7.72k|        }
_ZN4QPDF3Doc6Common3toIIxEEiRKT_:
  325|  7.72k|        {
  326|  7.72k|            return QIntC::to_int(i);
  327|  7.72k|        }
_ZN4QPDF8ObjCacheC2Ev:
  170|  12.8k|    ObjCache() = default;

_ZN4qpdf4util17internal_error_ifIRA28_KcEEvbOT_:
   36|   191k|    {
   37|   191k|        if (cond) {
  ------------------
  |  Branch (37:13): [True: 0, False: 191k]
  ------------------
   38|      0|            throw std::logic_error("INTERNAL ERROR: "s.append(std::forward<T>(msg))
   39|      0|                                       .append(
   40|      0|                                           "\nThis is a qpdf bug. Please report at "
   41|      0|                                           "https://github.com/qpdf/qpdf/issues"));
   42|      0|        }
   43|   191k|    }
_ZN4qpdf4util15hex_decode_charEc:
   99|  1.40M|    {
  100|  1.40M|        return digit <= '9' && digit >= '0'
  ------------------
  |  Branch (100:16): [True: 1.33M, False: 73.1k]
  |  Branch (100:32): [True: 1.17M, False: 151k]
  ------------------
  101|  1.40M|            ? char(digit - '0')
  102|  1.40M|            : (digit >= 'a' ? char(digit - 'a' + 10)
  ------------------
  |  Branch (102:16): [True: 46.8k, False: 177k]
  ------------------
  103|   224k|                            : (digit >= 'A' ? char(digit - 'A' + 10) : '\20'));
  ------------------
  |  Branch (103:32): [True: 13.8k, False: 163k]
  ------------------
  104|  1.40M|    }
_ZN4qpdf4util12is_hex_digitEc:
  108|  26.3k|    {
  109|  26.3k|        return hex_decode_char(ch) < '\20';
  110|  26.3k|    }
_ZN4qpdf4util8is_spaceEc:
  114|   220k|    {
  115|   220k|        return ch == ' ' || ch == '\n' || ch == '\r' || ch == '\t' || ch == '\f' || ch == '\v';
  ------------------
  |  Branch (115:16): [True: 61.8k, False: 158k]
  |  Branch (115:29): [True: 38.6k, False: 119k]
  |  Branch (115:43): [True: 3, False: 119k]
  |  Branch (115:57): [True: 3, False: 119k]
  |  Branch (115:71): [True: 0, False: 119k]
  |  Branch (115:85): [True: 0, False: 119k]
  ------------------
  116|   220k|    }
_ZN4qpdf4util8is_digitEc:
  120|  7.34M|    {
  121|  7.34M|        return (ch >= '0' && ch <= '9');
  ------------------
  |  Branch (121:17): [True: 5.72M, False: 1.61M]
  |  Branch (121:30): [True: 5.70M, False: 18.9k]
  ------------------
  122|  7.34M|    }
_ZN4qpdf4util9assertionIRA83_KcEEvbOT_:
   27|  23.1k|    {
   28|  23.1k|        if (!cond) {
  ------------------
  |  Branch (28:13): [True: 0, False: 23.1k]
  ------------------
   29|      0|            throw std::logic_error(std::forward<T>(msg));
   30|      0|        }
   31|  23.1k|    }
_ZN4qpdf4util9assertionINSt3__112basic_stringIcNS2_11char_traitsIcEENS2_9allocatorIcEEEEEEvbOT_:
   27|   100k|    {
   28|   100k|        if (!cond) {
  ------------------
  |  Branch (28:13): [True: 0, False: 100k]
  ------------------
   29|      0|            throw std::logic_error(std::forward<T>(msg));
   30|      0|        }
   31|   100k|    }
_ZN4qpdf4util4fitsIjTkNSt3__18integralElQsr3stdE8integralIT_EEEbT0_:
   63|  7.72k|    {
   64|       |        if constexpr (std::cmp_less(
   65|       |                          std::numeric_limits<decltype(val)>::min(),
   66|  7.72k|                          std::numeric_limits<T>::min())) {
   67|  7.72k|            if (std::cmp_less(val, std::numeric_limits<T>::min())) {
  ------------------
  |  Branch (67:17): [True: 0, False: 7.72k]
  ------------------
   68|      0|                return false;
   69|      0|            }
   70|  7.72k|        }
   71|       |        if constexpr (std::cmp_greater(
   72|       |                          std::numeric_limits<decltype(val)>::max(),
   73|  7.72k|                          std::numeric_limits<T>::max())) {
   74|  7.72k|            if (std::cmp_greater(val, std::numeric_limits<T>::max())) {
  ------------------
  |  Branch (74:17): [True: 0, False: 7.72k]
  ------------------
   75|      0|                return false;
   76|      0|            }
   77|  7.72k|        }
   78|  7.72k|        return true;
   79|  7.72k|    }
_ZN4qpdf4util4fitsIjTkNSt3__18integralEiQsr3stdE8integralIT_EEEbT0_:
   63|  7.72k|    {
   64|       |        if constexpr (std::cmp_less(
   65|       |                          std::numeric_limits<decltype(val)>::min(),
   66|  7.72k|                          std::numeric_limits<T>::min())) {
   67|  7.72k|            if (std::cmp_less(val, std::numeric_limits<T>::min())) {
  ------------------
  |  Branch (67:17): [True: 0, False: 7.72k]
  ------------------
   68|      0|                return false;
   69|      0|            }
   70|  7.72k|        }
   71|       |        if constexpr (std::cmp_greater(
   72|       |                          std::numeric_limits<decltype(val)>::max(),
   73|       |                          std::numeric_limits<T>::max())) {
   74|       |            if (std::cmp_greater(val, std::numeric_limits<T>::max())) {
   75|       |                return false;
   76|       |            }
   77|       |        }
   78|  7.72k|        return true;
   79|  7.72k|    }
_ZN4qpdf4util4fitsIjTkNSt3__18integralEyQsr3stdE8integralIT_EEEbT0_:
   63|  30.9k|    {
   64|       |        if constexpr (std::cmp_less(
   65|       |                          std::numeric_limits<decltype(val)>::min(),
   66|       |                          std::numeric_limits<T>::min())) {
   67|       |            if (std::cmp_less(val, std::numeric_limits<T>::min())) {
   68|       |                return false;
   69|       |            }
   70|       |        }
   71|       |        if constexpr (std::cmp_greater(
   72|       |                          std::numeric_limits<decltype(val)>::max(),
   73|  30.9k|                          std::numeric_limits<T>::max())) {
   74|  30.9k|            if (std::cmp_greater(val, std::numeric_limits<T>::max())) {
  ------------------
  |  Branch (74:17): [True: 0, False: 30.9k]
  ------------------
   75|      0|                return false;
   76|      0|            }
   77|  30.9k|        }
   78|  30.9k|        return true;
   79|  30.9k|    }
_ZN4qpdf4util9assertionIRA40_KcEEvbOT_:
   27|  22.1k|    {
   28|  22.1k|        if (!cond) {
  ------------------
  |  Branch (28:13): [True: 0, False: 22.1k]
  ------------------
   29|      0|            throw std::logic_error(std::forward<T>(msg));
   30|      0|        }
   31|  22.1k|    }
_ZN4qpdf4util9assertionIRA46_KcEEvbOT_:
   27|  22.1k|    {
   28|  22.1k|        if (!cond) {
  ------------------
  |  Branch (28:13): [True: 0, False: 22.1k]
  ------------------
   29|      0|            throw std::logic_error(std::forward<T>(msg));
   30|      0|        }
   31|  22.1k|    }
_ZN4qpdf4util9assertionIRA25_KcEEvbOT_:
   27|   113k|    {
   28|   113k|        if (!cond) {
  ------------------
  |  Branch (28:13): [True: 0, False: 113k]
  ------------------
   29|      0|            throw std::logic_error(std::forward<T>(msg));
   30|      0|        }
   31|   113k|    }
_ZN4qpdf4util9assertionIRA42_KcEEvbOT_:
   27|  13.4k|    {
   28|  13.4k|        if (!cond) {
  ------------------
  |  Branch (28:13): [True: 0, False: 13.4k]
  ------------------
   29|      0|            throw std::logic_error(std::forward<T>(msg));
   30|      0|        }
   31|  13.4k|    }
_ZN4qpdf4util9assertionIRA34_KcEEvbOT_:
   27|  5.50k|    {
   28|  5.50k|        if (!cond) {
  ------------------
  |  Branch (28:13): [True: 0, False: 5.50k]
  ------------------
   29|      0|            throw std::logic_error(std::forward<T>(msg));
   30|      0|        }
   31|  5.50k|    }
_ZN4qpdf4util9assertionIRA72_KcEEvbOT_:
   27|   100k|    {
   28|   100k|        if (!cond) {
  ------------------
  |  Branch (28:13): [True: 0, False: 100k]
  ------------------
   29|      0|            throw std::logic_error(std::forward<T>(msg));
   30|      0|        }
   31|   100k|    }
_ZN4qpdf4util9assertionIRA35_KcEEvbOT_:
   27|  7.72k|    {
   28|  7.72k|        if (!cond) {
  ------------------
  |  Branch (28:13): [True: 0, False: 7.72k]
  ------------------
   29|      0|            throw std::logic_error(std::forward<T>(msg));
   30|      0|        }
   31|  7.72k|    }
_ZN4qpdf4util17internal_error_ifIRA34_KcEEvbOT_:
   36|  15.4k|    {
   37|  15.4k|        if (cond) {
  ------------------
  |  Branch (37:13): [True: 0, False: 15.4k]
  ------------------
   38|      0|            throw std::logic_error("INTERNAL ERROR: "s.append(std::forward<T>(msg))
   39|      0|                                       .append(
   40|      0|                                           "\nThis is a qpdf bug. Please report at "
   41|      0|                                           "https://github.com/qpdf/qpdf/issues"));
   42|      0|        }
   43|  15.4k|    }

_ZN4qpdf6global6Limits16doc_max_warningsEv:
   22|  7.72k|        {
   23|  7.72k|            return l.doc_max_warnings_;
   24|  7.72k|        }
_ZN4qpdf6global6Limits16doc_max_warningsEj:
   28|  7.72k|        {
   29|  7.72k|            l.doc_max_warnings_ = value;
   30|  7.72k|        }
_ZN4qpdf6global6Limits18parser_max_nestingEv:
   34|      2|        {
   35|      2|            return l.parser_max_nesting_;
   36|      2|        }
_ZN4qpdf6global6Limits17parser_max_errorsEv:
   46|  18.8k|        {
   47|  18.8k|            return l.parser_max_errors_;
   48|  18.8k|        }
_ZN4qpdf6global6Limits14dct_max_memoryEv:
   80|      2|        {
   81|      2|            return l.dct_max_memory_;
   82|      2|        }
_ZN4qpdf6global6Limits14dct_max_memoryEl:
   86|  7.72k|        {
   87|  7.72k|            l.dct_max_memory_ = util::fits<uint32_t>(value) ? value : 0;
  ------------------
  |  Branch (87:33): [True: 7.72k, False: 0]
  ------------------
   88|  7.72k|        }
_ZN4qpdf6global6Limits25dct_max_progressive_scansEv:
   92|      2|        {
   93|      2|            return l.dct_max_progressive_scans_;
   94|      2|        }
_ZN4qpdf6global6Limits25dct_max_progressive_scansEi:
   98|  7.72k|        {
   99|  7.72k|            l.dct_max_progressive_scans_ = util::fits<uint32_t>(value) ? value : 0;
  ------------------
  |  Branch (99:44): [True: 7.72k, False: 0]
  ------------------
  100|  7.72k|        }
_ZN4qpdf6global6Limits16flate_max_memoryEv:
  104|      2|        {
  105|      2|            return l.flate_max_memory_;
  106|      2|        }
_ZN4qpdf6global6Limits16flate_max_memoryEy:
  110|  7.72k|        {
  111|  7.72k|            l.flate_max_memory_ = util::fits<uint32_t>(value) ? value : 0;
  ------------------
  |  Branch (111:35): [True: 7.72k, False: 0]
  ------------------
  112|  7.72k|        }
_ZN4qpdf6global6Limits14png_max_memoryEv:
  116|      2|        {
  117|      2|            return l.png_max_memory_;
  118|      2|        }
_ZN4qpdf6global6Limits14png_max_memoryEy:
  122|  7.72k|        {
  123|  7.72k|            l.png_max_memory_ = util::fits<uint32_t>(value) ? value : 0;
  ------------------
  |  Branch (123:33): [True: 7.72k, False: 0]
  ------------------
  124|  7.72k|        }
_ZN4qpdf6global6Limits21run_length_max_memoryEv:
  128|      2|        {
  129|      2|            return l.run_length_max_memory_;
  130|      2|        }
_ZN4qpdf6global6Limits21run_length_max_memoryEy:
  134|  7.72k|        {
  135|  7.72k|            l.run_length_max_memory_ = util::fits<uint32_t>(value) ? value : 0;
  ------------------
  |  Branch (135:40): [True: 7.72k, False: 0]
  ------------------
  136|  7.72k|        }
_ZN4qpdf6global6Limits15tiff_max_memoryEv:
  140|      2|        {
  141|      2|            return l.tiff_max_memory_;
  142|      2|        }
_ZN4qpdf6global6Limits15tiff_max_memoryEy:
  146|  7.72k|        {
  147|  7.72k|            l.tiff_max_memory_ = util::fits<uint32_t>(value) ? value : 0;
  ------------------
  |  Branch (147:34): [True: 7.72k, False: 0]
  ------------------
  148|  7.72k|        }
_ZN4qpdf6global7Options25dct_throw_on_corrupt_dataEv:
  234|      2|        {
  235|      2|            return o.dct_throw_on_corrupt_data_;
  236|      2|        }
_ZN4qpdf6global7Options25dct_throw_on_corrupt_dataEb:
  240|  7.72k|        {
  241|  7.72k|            o.dct_throw_on_corrupt_data_ = value;
  242|  7.72k|        }

