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

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

_ZN4JSON10JSON_valueC2ENS_12value_type_eE:
  306|  4.39M|            type_code(type_code)
  307|  4.39M|        {
  308|  4.39M|        }
_ZN4JSON15JSON_dictionaryC2Ev:
  316|   147k|            JSON_value(vt_dictionary)
  317|   147k|        {
  318|   147k|        }
_ZN4JSON9JSON_nullC2Ev:
  350|  10.2k|            JSON_value(vt_null)
  351|  10.2k|        {
  352|  10.2k|        }
_ZN4JSON10JSON_arrayC2Ev:
  396|  47.5k|        JSON_value(vt_array)
  397|  47.5k|    {
  398|  47.5k|    }
_ZN4JSON10JSON_valueD2Ev:
  309|  4.39M|        virtual ~JSON_value() = default;
_ZN4JSONC2Ev:
   50|  9.76M|    JSON() = default;
_ZN4JSON15JSON_dictionaryD2Ev:
  319|   147k|        ~JSON_dictionary() override = default;
_ZN4JSON10JSON_arrayD2Ev:
  399|  47.5k|    ~JSON_array() override = default;
_ZN4JSON11JSON_stringD2Ev:
  327|  1.61M|        ~JSON_string() override = default;
_ZN4JSON11JSON_numberD2Ev:
  336|  2.55M|        ~JSON_number() override = default;
_ZN4JSON7MembersD2Ev:
  378|  4.39M|        ~Members() = default;
_ZN4JSON7ReactorD2Ev:
  212|  7.87k|        virtual ~Reactor() = default;

_ZN4qpdf10BaseHandleC2ERKNSt3__110shared_ptrI10QPDFObjectEE:
  120|  2.00M|            obj(obj) {};
_ZN4qpdf10BaseHandleC2EONSt3__110shared_ptrI10QPDFObjectEE:
  122|  1.99M|            obj(std::move(obj)) {};
_ZN4qpdf10BaseHandleC2Ev:
  118|  2.20M|        BaseHandle() = default;
_ZN4qpdf10BaseHandleD2Ev:
  131|  11.2M|        ~BaseHandle() = default;
_ZN4qpdf10BaseHandleC2ERKS0_:
  123|  2.34M|        BaseHandle(BaseHandle const&) = default;
_ZN4qpdf10BaseHandleaSEOS0_:
  126|  2.05M|        BaseHandle& operator=(BaseHandle&&) = default;
_ZN4qpdf10BaseHandleC2EOS0_:
  125|  2.71M|        BaseHandle(BaseHandle&&) = default;
_ZN4qpdf10BaseHandleaSERKS0_:
  124|   173k|        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.87k|    {
  275|  7.87k|        if ((delta > 0) != (cur > 0)) {
  ------------------
  |  Branch (275:13): [True: 7.87k, False: 0]
  ------------------
  276|  7.87k|            return;
  277|  7.87k|        }
  278|      0|        QIntC::range_check_error<T>(cur, delta);
  279|      0|    }
_ZN5QIntC7to_sizeIxEEmRKT_:
  215|   201k|    {
  216|   201k|        return IntConverter<T, size_t>::convert(i);
  217|   201k|    }
_ZN5QIntC12IntConverterIxmLb1ELb0EE7convertERKx:
  119|   201k|        {
  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|   201k|            auto ii = static_cast<typename to_u<From>::type>(i);
  124|   201k|            if ((i < 0) || (ii > std::numeric_limits<To>::max())) {
  ------------------
  |  Branch (124:17): [True: 0, False: 201k]
  |  Branch (124:28): [True: 0, False: 201k]
  ------------------
  125|      0|                error(i);
  126|      0|            }
  127|   201k|            return static_cast<To>(i);
  128|   201k|        }
_ZN5QIntC9to_offsetImEExRKT_:
  222|   174k|    {
  223|   174k|        return IntConverter<T, qpdf_offset_t>::convert(i);
  224|   174k|    }
_ZN5QIntC12IntConverterImxLb0ELb1EE7convertERKm:
  147|   174k|        {
  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|   174k|            auto maxval = static_cast<typename to_u<To>::type>(std::numeric_limits<To>::max());
  151|   174k|            if (i > maxval) {
  ------------------
  |  Branch (151:17): [True: 0, False: 174k]
  ------------------
  152|      0|                error(i);
  153|      0|            }
  154|   174k|            return static_cast<To>(i);
  155|   174k|        }
_ZN5QIntC7to_sizeIlEEmRKT_:
  215|  15.7k|    {
  216|  15.7k|        return IntConverter<T, size_t>::convert(i);
  217|  15.7k|    }
_ZN5QIntC12IntConverterIlmLb1ELb0EE7convertERKl:
  119|  15.7k|        {
  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.7k|            auto ii = static_cast<typename to_u<From>::type>(i);
  124|  15.7k|            if ((i < 0) || (ii > std::numeric_limits<To>::max())) {
  ------------------
  |  Branch (124:17): [True: 0, False: 15.7k]
  |  Branch (124:28): [True: 0, False: 15.7k]
  ------------------
  125|      0|                error(i);
  126|      0|            }
  127|  15.7k|            return static_cast<To>(i);
  128|  15.7k|        }
_ZN5QIntC6to_intImEEiRKT_:
  201|  1.11M|    {
  202|  1.11M|        return IntConverter<T, int>::convert(i);
  203|  1.11M|    }
_ZN5QIntC12IntConverterImiLb0ELb1EE7convertERKm:
  147|  1.11M|        {
  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.11M|            auto maxval = static_cast<typename to_u<To>::type>(std::numeric_limits<To>::max());
  151|  1.11M|            if (i > maxval) {
  ------------------
  |  Branch (151:17): [True: 0, False: 1.11M]
  ------------------
  152|      0|                error(i);
  153|      0|            }
  154|  1.11M|            return static_cast<To>(i);
  155|  1.11M|        }
_ZN5QIntC12IntConverterIimLb1ELb0EE7convertERKi:
  119|  4.23k|        {
  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|  4.23k|            auto ii = static_cast<typename to_u<From>::type>(i);
  124|  4.23k|            if ((i < 0) || (ii > std::numeric_limits<To>::max())) {
  ------------------
  |  Branch (124:17): [True: 0, False: 4.23k]
  |  Branch (124:28): [True: 0, False: 4.23k]
  ------------------
  125|      0|                error(i);
  126|      0|            }
  127|  4.23k|            return static_cast<To>(i);
  128|  4.23k|        }
_ZN5QIntC6to_intIxEEiRKT_:
  201|  1.54M|    {
  202|  1.54M|        return IntConverter<T, int>::convert(i);
  203|  1.54M|    }
_ZN5QIntC12IntConverterIxiLb1ELb1EE7convertERKx:
   94|  1.54M|        {
   95|       |            // From and To are both signed.
   96|  1.54M|            if ((i < std::numeric_limits<To>::min()) || (i > std::numeric_limits<To>::max())) {
  ------------------
  |  Branch (96:17): [True: 60, False: 1.54M]
  |  Branch (96:57): [True: 16, False: 1.54M]
  ------------------
   97|     76|                error(i);
   98|     76|            }
   99|  1.54M|            return static_cast<To>(i);
  100|  1.54M|        }
_ZN5QIntC12IntConverterIxiLb1ELb1EE5errorEx:
  104|     76|        {
  105|     76|            std::ostringstream msg;
  106|     76|            msg.imbue(std::locale::classic());
  107|     76|            msg << "integer out of range converting " << i << " from a " << sizeof(From)
  108|     76|                << "-byte signed type to a " << sizeof(To) << "-byte signed type";
  109|     76|            throw std::range_error(msg.str());
  110|     76|        }
_ZN5QIntC6to_intIlEEiRKT_:
  201|  7.87k|    {
  202|  7.87k|        return IntConverter<T, int>::convert(i);
  203|  7.87k|    }
_ZN5QIntC12IntConverterIliLb1ELb1EE7convertERKl:
   94|  7.87k|        {
   95|       |            // From and To are both signed.
   96|  7.87k|            if ((i < std::numeric_limits<To>::min()) || (i > std::numeric_limits<To>::max())) {
  ------------------
  |  Branch (96:17): [True: 0, False: 7.87k]
  |  Branch (96:57): [True: 0, False: 7.87k]
  ------------------
   97|      0|                error(i);
   98|      0|            }
   99|  7.87k|            return static_cast<To>(i);
  100|  7.87k|        }
_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|  15.1k|    {
  237|  15.1k|        return IntConverter<T, unsigned long>::convert(i);
  238|  15.1k|    }
_ZN5QIntC12IntConverterIhmLb0ELb0EE7convertERKh:
   69|  15.1k|        {
   70|       |            // From and To are both unsigned.
   71|  15.1k|            if (i > std::numeric_limits<To>::max()) {
  ------------------
  |  Branch (71:17): [True: 0, False: 15.1k]
  ------------------
   72|      0|                error(i);
   73|      0|            }
   74|  15.1k|            return static_cast<To>(i);
   75|  15.1k|        }
_ZN5QIntC8to_ulongIiEEmRKT_:
  236|  4.23k|    {
  237|  4.23k|        return IntConverter<T, unsigned long>::convert(i);
  238|  4.23k|    }

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

_ZN10QPDFObjGenC2Eii:
   40|   775k|        obj(obj),
   41|   775k|        gen(gen)
   42|   775k|    {
   43|   775k|    }
_ZNK10QPDFObjGenltERKS_:
   46|  3.57M|    {
   47|  3.57M|        return (obj < rhs.obj) || (obj == rhs.obj && gen < rhs.gen);
  ------------------
  |  Branch (47:16): [True: 1.44M, False: 2.13M]
  |  Branch (47:36): [True: 1.74M, False: 384k]
  |  Branch (47:54): [True: 140k, False: 1.60M]
  ------------------
   48|  3.57M|    }
_ZNK10QPDFObjGeneqERKS_:
   51|  8.35k|    {
   52|  8.35k|        return obj == rhs.obj && gen == rhs.gen;
  ------------------
  |  Branch (52:16): [True: 8.12k, False: 228]
  |  Branch (52:34): [True: 8.08k, False: 37]
  ------------------
   53|  8.35k|    }
_ZNK10QPDFObjGen6getObjEv:
   61|  53.4k|    {
   62|  53.4k|        return obj;
   63|  53.4k|    }
_ZNK10QPDFObjGen10isIndirectEv:
   71|  3.58M|    {
   72|  3.58M|        return obj != 0;
   73|  3.58M|    }
_ZNK10QPDFObjGen7unparseEc:
   76|  3.83k|    {
   77|  3.83k|        return std::to_string(obj) + separator + std::to_string(gen);
   78|  3.83k|    }
_ZN10QPDFObjGenC2Ev:
   38|  2.37M|    QPDFObjGen() = default;

_ZN16QPDFObjectHandleC2ERKNSt3__110shared_ptrI10QPDFObjectEE:
 1315|  38.7k|        qpdf::BaseHandle(obj)
 1316|  38.7k|    {
 1317|  38.7k|    }
_ZN16QPDFObjectHandleC2EONSt3__110shared_ptrI10QPDFObjectEE:
 1319|  1.98M|        qpdf::BaseHandle(std::move(obj))
 1320|  1.98M|    {
 1321|  1.98M|    }
_ZNK4qpdf10BaseHandlecvbEv:
 1559|  5.95M|    {
 1560|  5.95M|        return static_cast<bool>(obj);
 1561|  5.95M|    }
_ZNK4qpdf10BaseHandlecv16QPDFObjectHandleEv:
 1565|  3.83k|    {
 1566|  3.83k|        return {obj};
 1567|  3.83k|    }
_ZN16QPDFObjectHandleC2Ev:
  289|  2.20M|    QPDFObjectHandle() = default;
_ZN16QPDFObjectHandleC2ERKS_:
  290|  2.34M|    QPDFObjectHandle(QPDFObjectHandle const&) = default;
_ZN16QPDFObjectHandleaSEOS_:
  293|  2.05M|    QPDFObjectHandle& operator=(QPDFObjectHandle&&) = default;
_ZN16QPDFObjectHandleC2EOS_:
  292|  2.71M|    QPDFObjectHandle(QPDFObjectHandle&&) = default;
_ZN16QPDFObjectHandleaSERKS_:
  291|   173k|    QPDFObjectHandle& operator=(QPDFObjectHandle const&) = default;

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

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

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

_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.87k|    m(std::make_unique<Members>(size, reinterpret_cast<char*>(buf)))
   49|  7.87k|{
   50|  7.87k|}
_ZN6BufferD2Ev:
   69|  10.4k|Buffer::~Buffer() = default;
_ZNK6Buffer7getSizeEv:
   73|  18.3k|{
   74|  18.3k|    return m->size;
   75|  18.3k|}
_ZN6Buffer9getBufferEv:
   85|  7.87k|{
   86|  7.87k|    return reinterpret_cast<unsigned char*>(m->buf);
   87|  7.87k|}
_ZN6Buffer7MembersD2Ev:
   24|  10.4k|    ~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.87k|        size(size),
   14|  7.87k|        buf(buf)
   15|  7.87k|    {
   16|  7.87k|    }

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

_ZN11InputSource13setLastOffsetEx:
   15|  89.9k|{
   16|  89.9k|    this->last_offset = offset;
   17|  89.9k|}
_ZNK11InputSource13getLastOffsetEv:
   21|  47.8k|{
   22|  47.8k|    return this->last_offset;
   23|  47.8k|}
_ZN11InputSource9read_lineERNSt3__112basic_stringIcNS0_11char_traitsIcEENS0_9allocatorIcEEEEmx:
   27|  7.87k|{
   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.87k|    read(str, count, at);
   34|  7.87k|    auto eol = str.find_first_of("\n\r"sv);
   35|  7.87k|    if (eol != std::string::npos) {
  ------------------
  |  Branch (35:9): [True: 7.87k, False: 0]
  ------------------
   36|  7.87k|        auto next_line = str.find_first_not_of("\n\r"sv, eol);
   37|  7.87k|        str.resize(eol);
   38|  7.87k|        if (eol != std::string::npos) {
  ------------------
  |  Branch (38:13): [True: 7.87k, False: 0]
  ------------------
   39|  7.87k|            seek(last_offset + static_cast<qpdf_offset_t>(next_line), SEEK_SET);
   40|  7.87k|            return eol;
   41|  7.87k|        }
   42|  7.87k|    }
   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.87k|}
_ZN11InputSource8readLineEm:
   51|  7.87k|{
   52|  7.87k|    return read_line(max_line_length);
   53|  7.87k|}
_ZN11InputSource9findFirstEPKcxmRNS_6FinderE:
   65|  23.6k|{
   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.6k|    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.6k|    size_t size = sizeof(buf) - 1;
   79|  23.6k|    util::assertion(
   80|  23.6k|        !(strlen(start_chars) < 1 || strlen(start_chars) > size),
  ------------------
  |  Branch (80:11): [True: 0, False: 23.6k]
  |  Branch (80:38): [True: 0, False: 23.6k]
  ------------------
   81|  23.6k|        "InputSource::findSource called with too small or too large of a character sequence" //
   82|  23.6k|    );
   83|       |
   84|  23.6k|    char* p = nullptr;
   85|  23.6k|    qpdf_offset_t buf_offset = offset;
   86|  23.6k|    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.6k|    while (true) {
  ------------------
  |  Branch (91:12): [True: 23.6k, 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.6k|        if ((p == nullptr) || ((p + strlen(start_chars)) > (buf + bytes_read))) {
  ------------------
  |  Branch (97:13): [True: 23.6k, False: 0]
  |  Branch (97:31): [True: 0, False: 0]
  ------------------
   98|  23.6k|            if (p) {
  ------------------
  |  Branch (98:17): [True: 0, False: 23.6k]
  ------------------
   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.6k|            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.6k|            bytes_read = this->read(buf, size);
  108|  23.6k|            if (bytes_read < strlen(start_chars)) {
  ------------------
  |  Branch (108:17): [True: 7.87k, False: 15.7k]
  ------------------
  109|  7.87k|                QTC::TC("libtests", "InputSource find EOF", bytes_read == 0 ? 0 : 1);
  ------------------
  |  Branch (109:61): [True: 0, False: 7.87k]
  ------------------
  110|  7.87k|                return false;
  111|  7.87k|            }
  112|  15.7k|            memset(buf + bytes_read, '\0', 1 + (size - bytes_read));
  113|  15.7k|            p = buf;
  114|  15.7k|        }
  115|       |
  116|       |        // Search for the first character.
  117|  15.7k|        if ((p = static_cast<char*>(
  ------------------
  |  Branch (117:13): [True: 15.7k, False: 0]
  ------------------
  118|       |                 // line-break
  119|  15.7k|                 memchr(p, start_chars[0], bytes_read - QIntC::to_size(p - buf)))) != nullptr) {
  120|  15.7k|            if (p == buf) {
  ------------------
  |  Branch (120:17): [True: 7.87k, False: 7.87k]
  ------------------
  121|  7.87k|                QTC::TC("libtests", "InputSource found match at buf[0]");
  122|  7.87k|            }
  123|       |            // Found first letter.
  124|  15.7k|            if (len != 0) {
  ------------------
  |  Branch (124:17): [True: 7.87k, False: 7.87k]
  ------------------
  125|       |                // Make sure it's in range.
  126|  7.87k|                size_t p_relative_offset = QIntC::to_size((p - buf) + (buf_offset - offset));
  127|  7.87k|                if (p_relative_offset >= len) {
  ------------------
  |  Branch (127:21): [True: 0, False: 7.87k]
  ------------------
  128|       |                    // out of range
  129|      0|                    QTC::TC("libtests", "InputSource out of range");
  130|      0|                    return false;
  131|      0|                }
  132|  7.87k|            }
  133|  15.7k|            if ((p + strlen(start_chars)) > (buf + bytes_read)) {
  ------------------
  |  Branch (133:17): [True: 0, False: 15.7k]
  ------------------
  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.7k|            if (strncmp(p, start_chars, strlen(start_chars)) == 0) {
  ------------------
  |  Branch (142:17): [True: 15.7k, False: 0]
  ------------------
  143|       |                // Call finder.check() with the input source positioned to the point of the match.
  144|  15.7k|                this->seek(buf_offset + (p - buf), SEEK_SET);
  145|  15.7k|                if (finder.check()) {
  ------------------
  |  Branch (145:21): [True: 15.7k, False: 0]
  ------------------
  146|  15.7k|                    return true;
  147|  15.7k|                } else {
  148|      0|                    QTC::TC("libtests", "InputSource start_chars matched but not check");
  149|      0|                }
  150|  15.7k|            } 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.7k|    }
  161|  23.6k|}
_ZN11InputSource8findLastEPKcxmRNS_6FinderE:
  165|  7.87k|{
  166|  7.87k|    bool found = false;
  167|  7.87k|    qpdf_offset_t after_found_offset = 0;
  168|  7.87k|    qpdf_offset_t cur_offset = offset;
  169|  7.87k|    size_t cur_len = len;
  170|  15.7k|    while (this->findFirst(start_chars, cur_offset, cur_len, finder)) {
  ------------------
  |  Branch (170:12): [True: 7.87k, False: 7.87k]
  ------------------
  171|  7.87k|        if (found) {
  ------------------
  |  Branch (171:13): [True: 0, False: 7.87k]
  ------------------
  172|      0|            QTC::TC("libtests", "InputSource findLast found more than one");
  173|  7.87k|        } else {
  174|  7.87k|            found = true;
  175|  7.87k|        }
  176|  7.87k|        after_found_offset = this->tell();
  177|  7.87k|        cur_offset = after_found_offset;
  178|  7.87k|        cur_len = len - QIntC::to_size((cur_offset - offset));
  179|  7.87k|    }
  180|  7.87k|    if (found) {
  ------------------
  |  Branch (180:9): [True: 7.87k, False: 0]
  ------------------
  181|       |        this->seek(after_found_offset, SEEK_SET);
  182|  7.87k|    }
  183|  7.87k|    return found;
  184|  7.87k|}
_ZN11InputSource9read_lineEmx:
   57|  7.87k|{
   58|  7.87k|    std::string result(count, '\0');
   59|  7.87k|    read_line(result, count, at);
   60|  7.87k|    return result;
   61|  7.87k|}

_ZN4JSON7MembersC2ENSt3__110unique_ptrINS_10JSON_valueENS1_14default_deleteIS3_EEEE:
   19|  4.39M|    value(std::move(value))
   20|  4.39M|{
   21|  4.39M|}
_ZN4JSONC2ENSt3__110unique_ptrINS_10JSON_valueENS0_14default_deleteIS2_EEEE:
   24|  4.39M|    m(new Members(std::move(value)))
   25|  4.39M|{
   26|  4.39M|}
_ZN4JSON11JSON_stringC2ERKNSt3__112basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEE:
  126|  1.61M|    JSON_value(vt_string),
  127|  1.61M|    utf8(utf8)
  128|  1.61M|{
  129|  1.61M|}
_ZN4JSON11JSON_numberC2ERKNSt3__112basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEE:
  150|  2.55M|    JSON_value(vt_number),
  151|  2.55M|    encoded(value)
  152|  2.55M|{
  153|  2.55M|}
_ZN4JSON9JSON_boolC2Eb:
  162|  16.5k|    JSON_value(vt_bool),
  163|  16.5k|    value(val)
  164|  16.5k|{
  165|  16.5k|}
_ZN4JSON6Writer13encode_stringERKNSt3__112basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEE:
  220|   225k|{
  221|   225k|    static auto constexpr hexchars = "0123456789abcdef";
  222|       |
  223|   225k|    auto begin = str.cbegin();
  224|   225k|    auto end = str.cend();
  225|   225k|    auto iter = begin;
  226|  73.6M|    while (iter != end) {
  ------------------
  |  Branch (226:12): [True: 73.3M, False: 220k]
  ------------------
  227|  73.3M|        auto c = static_cast<unsigned char>(*iter);
  228|  73.3M|        if ((c > 34 && c != '\\') || c == ' ' || c == 33) {
  ------------------
  |  Branch (228:14): [True: 37.6M, False: 35.7M]
  |  Branch (228:24): [True: 37.6M, False: 581]
  |  Branch (228:38): [True: 35.6M, False: 32.8k]
  |  Branch (228:50): [True: 27.9k, False: 4.93k]
  ------------------
  229|       |            // Optimistically check that no char in str requires escaping. Hopefully we can just
  230|       |            // return the input str.
  231|  73.3M|            ++iter;
  232|  73.3M|        } 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|  4.93k|            std::string result{begin, iter};
  236|       |
  237|  24.4M|            for (; iter != end; ++iter) {
  ------------------
  |  Branch (237:20): [True: 24.4M, False: 4.93k]
  ------------------
  238|  24.4M|                auto ch = static_cast<unsigned char>(*iter);
  239|  24.4M|                if ((ch > 34 && ch != '\\') || ch == ' ' || ch == 33) {
  ------------------
  |  Branch (239:22): [True: 19.5M, False: 4.89M]
  |  Branch (239:33): [True: 19.5M, False: 23.5k]
  |  Branch (239:48): [True: 4.85M, False: 65.7k]
  |  Branch (239:61): [True: 12.4k, False: 53.2k]
  ------------------
  240|       |                    // Check for most common case first.
  241|  24.3M|                    result += *iter;
  242|  24.3M|                } else {
  243|  53.2k|                    switch (ch) {
  244|  23.5k|                    case '\\':
  ------------------
  |  Branch (244:21): [True: 23.5k, False: 29.7k]
  ------------------
  245|  23.5k|                        result += "\\\\";
  246|  23.5k|                        break;
  247|  1.43k|                    case '\"':
  ------------------
  |  Branch (247:21): [True: 1.43k, False: 51.8k]
  ------------------
  248|  1.43k|                        result += "\\\"";
  249|  1.43k|                        break;
  250|  3.29k|                    case '\b':
  ------------------
  |  Branch (250:21): [True: 3.29k, False: 50.0k]
  ------------------
  251|  3.29k|                        result += "\\b";
  252|  3.29k|                        break;
  253|  3.45k|                    case '\f':
  ------------------
  |  Branch (253:21): [True: 3.45k, False: 49.8k]
  ------------------
  254|  3.45k|                        result += "\\f";
  255|  3.45k|                        break;
  256|  3.59k|                    case '\n':
  ------------------
  |  Branch (256:21): [True: 3.59k, False: 49.7k]
  ------------------
  257|  3.59k|                        result += "\\n";
  258|  3.59k|                        break;
  259|  3.97k|                    case '\r':
  ------------------
  |  Branch (259:21): [True: 3.97k, False: 49.3k]
  ------------------
  260|  3.97k|                        result += "\\r";
  261|  3.97k|                        break;
  262|  3.39k|                    case '\t':
  ------------------
  |  Branch (262:21): [True: 3.39k, False: 49.9k]
  ------------------
  263|  3.39k|                        result += "\\t";
  264|  3.39k|                        break;
  265|  10.6k|                    default:
  ------------------
  |  Branch (265:21): [True: 10.6k, False: 42.6k]
  ------------------
  266|  10.6k|                        result += ch < 16 ? "\\u000" : "\\u001";
  ------------------
  |  Branch (266:35): [True: 3.98k, False: 6.64k]
  ------------------
  267|  10.6k|                        result += hexchars[ch % 16];
  268|  53.2k|                    }
  269|  53.2k|                }
  270|  24.4M|            }
  271|  4.93k|            return result;
  272|  4.93k|        }
  273|  73.3M|    }
  274|   220k|    return str;
  275|   225k|}
_ZN4JSON14makeDictionaryEv:
  279|   147k|{
  280|   147k|    return {std::make_unique<JSON_dictionary>()};
  281|   147k|}
_ZN4JSON19addDictionaryMemberERKNSt3__112basic_stringIcNS0_11char_traitsIcEENS0_9allocatorIcEEEERKS_:
  285|   225k|{
  286|   225k|    if (auto* obj = m ? dynamic_cast<JSON_dictionary*>(m->value.get()) : nullptr) {
  ------------------
  |  Branch (286:15): [True: 225k, False: 0]
  ------------------
  287|   225k|        return obj->members[Writer::encode_string(key)] = val.m ? val : makeNull();
  ------------------
  |  Branch (287:59): [True: 225k, False: 0]
  ------------------
  288|   225k|    } else {
  289|      0|        throw std::runtime_error("JSON::addDictionaryMember called on non-dictionary");
  290|      0|    }
  291|   225k|}
_ZN4JSON9makeArrayEv:
  295|  47.5k|{
  296|  47.5k|    return {std::make_unique<JSON_array>()};
  297|  47.5k|}
_ZN4JSON15addArrayElementERKS_:
  301|  1.97M|{
  302|  1.97M|    if (auto* arr = m ? dynamic_cast<JSON_array*>(m->value.get()) : nullptr) {
  ------------------
  |  Branch (302:15): [True: 1.97M, False: 0]
  ------------------
  303|  1.97M|        if (val.m) {
  ------------------
  |  Branch (303:13): [True: 1.97M, False: 0]
  ------------------
  304|  1.97M|            arr->elements.push_back(val);
  305|  1.97M|        } else {
  306|      0|            arr->elements.push_back(makeNull());
  307|      0|        }
  308|  1.97M|        return arr->elements.back();
  309|  1.97M|    }
  310|      0|    throw std::runtime_error("JSON::addArrayElement called on non-array");
  311|      0|    return {}; // unreachable
  312|  1.97M|}
_ZN4JSON10makeStringERKNSt3__112basic_stringIcNS0_11char_traitsIcEENS0_9allocatorIcEEEE:
  316|  1.61M|{
  317|  1.61M|    return {std::make_unique<JSON_string>(utf8)};
  318|  1.61M|}
_ZN4JSON10makeNumberERKNSt3__112basic_stringIcNS0_11char_traitsIcEENS0_9allocatorIcEEEE:
  334|  2.55M|{
  335|  2.55M|    return {std::make_unique<JSON_number>(encoded)};
  336|  2.55M|}
_ZN4JSON8makeBoolEb:
  340|  16.5k|{
  341|  16.5k|    return {std::make_unique<JSON_bool>(value)};
  342|  16.5k|}
_ZN4JSON8makeNullEv:
  346|  10.2k|{
  347|  10.2k|    return {std::make_unique<JSON_null>()};
  348|  10.2k|}
_ZNK4JSON7isArrayEv:
  358|  6.24M|{
  359|  6.24M|    return m ? m->value->type_code == vt_array : false;
  ------------------
  |  Branch (359:12): [True: 6.24M, False: 0]
  ------------------
  360|  6.24M|}
_ZNK4JSON12isDictionaryEv:
  364|  6.61M|{
  365|  6.61M|    return m && m->value->type_code == vt_dictionary;
  ------------------
  |  Branch (365:12): [True: 6.61M, False: 0]
  |  Branch (365:17): [True: 369k, False: 6.24M]
  ------------------
  366|  6.61M|}
_ZNK4JSON9getStringERNSt3__112basic_stringIcNS0_11char_traitsIcEENS0_9allocatorIcEEEE:
  370|   809k|{
  371|   809k|    if (m && m->value->type_code == vt_string) {
  ------------------
  |  Branch (371:9): [True: 809k, False: 0]
  |  Branch (371:14): [True: 806k, False: 3.39k]
  ------------------
  372|   806k|        auto v = dynamic_cast<JSON_string const*>(m->value.get());
  373|   806k|        utf8 = v->utf8;
  374|   806k|        return true;
  375|   806k|    }
  376|  3.39k|    return false;
  377|   809k|}
_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.11M, False: 797k]
  ------------------
  383|  1.11M|        auto v = dynamic_cast<JSON_number const*>(m->value.get());
  384|  1.11M|        value = v->encoded;
  385|  1.11M|        return true;
  386|  1.11M|    }
  387|   797k|    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: 7.35k, False: 1.91M]
  ------------------
  394|  7.35k|        auto v = dynamic_cast<JSON_bool const*>(m->value.get());
  395|  7.35k|        value = v->value;
  396|  7.35k|        return true;
  397|  7.35k|    }
  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.68k, False: 1.92M]
  ------------------
  405|  1.92M|}
_ZN4JSON5parseER11InputSourcePNS_7ReactorE:
 1335|  7.87k|{
 1336|  7.87k|    JSONParser jp(is, reactor);
 1337|  7.87k|    return jp.parse();
 1338|  7.87k|}
_ZN4JSON5parseERKNSt3__112basic_stringIcNS0_11char_traitsIcEENS0_9allocatorIcEEEE:
 1342|  7.87k|{
 1343|  7.87k|    is::OffsetBuffer bis("json input", s);
 1344|  7.87k|    JSONParser jp(bis, nullptr);
 1345|  7.87k|    return jp.parse();
 1346|  7.87k|}
_ZN4JSON8setStartEx:
 1350|  4.39M|{
 1351|  4.39M|    if (m) {
  ------------------
  |  Branch (1351:9): [True: 4.39M, False: 0]
  ------------------
 1352|  4.39M|        m->start = start;
 1353|  4.39M|    }
 1354|  4.39M|}
_ZN4JSON6setEndEx:
 1358|  4.48M|{
 1359|  4.48M|    if (m) {
  ------------------
  |  Branch (1359:9): [True: 4.48M, False: 0]
  ------------------
 1360|  4.48M|        m->end = end;
 1361|  4.48M|    }
 1362|  4.48M|}
_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.86k|{
 1373|  5.86k|    return m ? m->end : 0;
  ------------------
  |  Branch (1373:12): [True: 5.86k, False: 0]
  ------------------
 1374|  5.86k|}
JSON.cc:_ZN12_GLOBAL__N_110JSONParserC2ER11InputSourcePN4JSON7ReactorE:
  577|  15.7k|            is(is),
  578|  15.7k|            reactor(reactor),
  579|  15.7k|            p(buf)
  580|  15.7k|        {
  581|  15.7k|        }
JSON.cc:_ZN12_GLOBAL__N_110JSONParser5parseEv:
 1317|  15.7k|{
 1318|  9.63M|    while (!done) {
  ------------------
  |  Branch (1318:12): [True: 9.62M, False: 15.7k]
  ------------------
 1319|  9.62M|        getToken();
 1320|  9.62M|        handleToken();
 1321|  9.62M|    }
 1322|  15.7k|    if (parser_state != ps_done) {
  ------------------
  |  Branch (1322:9): [True: 10.7k, False: 4.94k]
  ------------------
 1323|  10.7k|        QTC::TC("libtests", "JSON parse premature EOF");
 1324|  10.7k|        throw std::runtime_error("JSON: premature end of input");
 1325|  10.7k|    }
 1326|  4.94k|    auto const& tos = stack.back().item;
 1327|  4.94k|    if (reactor && !(tos.isArray() || tos.isDictionary())) {
  ------------------
  |  Branch (1327:9): [True: 120, False: 4.82k]
  |  Branch (1327:22): [True: 0, False: 120]
  |  Branch (1327:39): [True: 60, False: 60]
  ------------------
 1328|     60|        reactor->topLevelScalar();
 1329|     60|    }
 1330|  4.94k|    return tos;
 1331|  15.7k|}
JSON.cc:_ZN12_GLOBAL__N_110JSONParser8getTokenEv:
  807|  9.62M|{
  808|  9.62M|    token.clear();
  809|       |
  810|       |    // Keep track of UTF-16 surrogate pairs.
  811|  9.62M|    unsigned long high_surrogate = 0;
  812|  9.62M|    qpdf_offset_t high_offset = 0;
  813|       |
  814|   343M|    while (true) {
  ------------------
  |  Branch (814:12): [True: 343M, Folded]
  ------------------
  815|   343M|        if (p == (buf + bytes)) {
  ------------------
  |  Branch (815:13): [True: 48.4k, False: 343M]
  ------------------
  816|  48.4k|            p = buf;
  817|  48.4k|            bytes = is.read(buf, sizeof(buf));
  818|  48.4k|            if (bytes == 0) {
  ------------------
  |  Branch (818:17): [True: 12.8k, False: 35.6k]
  ------------------
  819|  12.8k|                done = true;
  820|  12.8k|                break;
  821|  12.8k|            }
  822|  48.4k|        }
  823|       |
  824|   343M|        if ((*p < 32 && *p >= 0)) {
  ------------------
  |  Branch (824:14): [True: 73.0M, False: 270M]
  |  Branch (824:25): [True: 320k, False: 72.7M]
  ------------------
  825|   320k|            if (*p == '\t' || *p == '\n' || *p == '\r') {
  ------------------
  |  Branch (825:17): [True: 900, False: 319k]
  |  Branch (825:31): [True: 318k, False: 441]
  |  Branch (825:45): [True: 287, False: 154]
  ------------------
  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|   319k|                if (lex_state == ls_top) {
  ------------------
  |  Branch (828:21): [True: 303k, False: 16.6k]
  ------------------
  829|   303k|                    ignore();
  830|   303k|                } else {
  831|  16.6k|                    break;
  832|  16.6k|                }
  833|       |
  834|   319k|            } else {
  835|    154|                QTC::TC("libtests", "JSON parse null character");
  836|    154|                throw std::runtime_error(
  837|    154|                    "JSON: control or null character at offset " + std::to_string(offset));
  838|    154|            }
  839|   343M|        } else if (*p == ',') {
  ------------------
  |  Branch (839:20): [True: 9.33M, False: 333M]
  ------------------
  840|  9.33M|            if (lex_state == ls_top) {
  ------------------
  |  Branch (840:17): [True: 4.22M, False: 5.10M]
  ------------------
  841|  4.22M|                ignore(ls_comma);
  842|  4.22M|                return;
  843|  5.10M|            } else if (lex_state == ls_string) {
  ------------------
  |  Branch (843:24): [True: 2.54M, False: 2.55M]
  ------------------
  844|  2.54M|                append();
  845|  2.55M|            } else {
  846|  2.55M|                break;
  847|  2.55M|            }
  848|   333M|        } else if (*p == ':') {
  ------------------
  |  Branch (848:20): [True: 658k, False: 333M]
  ------------------
  849|   658k|            if (lex_state == ls_top) {
  ------------------
  |  Branch (849:17): [True: 450k, False: 207k]
  ------------------
  850|   450k|                ignore(ls_colon);
  851|   450k|                return;
  852|   450k|            } else if (lex_state == ls_string) {
  ------------------
  |  Branch (852:24): [True: 207k, False: 56]
  ------------------
  853|   207k|                append();
  854|   207k|            } else {
  855|     56|                break;
  856|     56|            }
  857|   333M|        } else if (*p == ' ') {
  ------------------
  |  Branch (857:20): [True: 117M, False: 215M]
  ------------------
  858|   117M|            if (lex_state == ls_top) {
  ------------------
  |  Branch (858:17): [True: 6.01M, False: 111M]
  ------------------
  859|  6.01M|                ignore();
  860|   111M|            } else if (lex_state == ls_string) {
  ------------------
  |  Branch (860:24): [True: 111M, False: 309]
  ------------------
  861|   111M|                append();
  862|   111M|            } else {
  863|    309|                break;
  864|    309|            }
  865|   215M|        } else if (*p == '{') {
  ------------------
  |  Branch (865:20): [True: 177k, False: 215M]
  ------------------
  866|   177k|            if (lex_state == ls_top) {
  ------------------
  |  Branch (866:17): [True: 147k, False: 30.0k]
  ------------------
  867|   147k|                token_start = offset;
  868|   147k|                ignore(ls_begin_dict);
  869|   147k|                return;
  870|   147k|            } else if (lex_state == ls_string) {
  ------------------
  |  Branch (870:24): [True: 30.0k, False: 78]
  ------------------
  871|  30.0k|                append();
  872|  30.0k|            } else {
  873|     78|                break;
  874|     78|            }
  875|   215M|        } else if (*p == '}') {
  ------------------
  |  Branch (875:20): [True: 85.6k, False: 215M]
  ------------------
  876|  85.6k|            if (lex_state == ls_top) {
  ------------------
  |  Branch (876:17): [True: 75.0k, False: 10.5k]
  ------------------
  877|  75.0k|                ignore(ls_end_dict);
  878|  75.0k|                return;
  879|  75.0k|            } else if (lex_state == ls_string) {
  ------------------
  |  Branch (879:24): [True: 4.74k, False: 5.84k]
  ------------------
  880|  4.74k|                append();
  881|  5.84k|            } else {
  882|  5.84k|                break;
  883|  5.84k|            }
  884|   215M|        } else if (*p == '[') {
  ------------------
  |  Branch (884:20): [True: 108k, False: 215M]
  ------------------
  885|   108k|            if (lex_state == ls_top) {
  ------------------
  |  Branch (885:17): [True: 47.5k, False: 60.8k]
  ------------------
  886|  47.5k|                token_start = offset;
  887|  47.5k|                ignore(ls_begin_array);
  888|  47.5k|                return;
  889|  60.8k|            } else if (lex_state == ls_string) {
  ------------------
  |  Branch (889:24): [True: 60.8k, False: 32]
  ------------------
  890|  60.8k|                append();
  891|  60.8k|            } else {
  892|     32|                break;
  893|     32|            }
  894|   215M|        } else if (*p == ']') {
  ------------------
  |  Branch (894:20): [True: 93.4k, False: 215M]
  ------------------
  895|  93.4k|            if (lex_state == ls_top) {
  ------------------
  |  Branch (895:17): [True: 6.66k, False: 86.7k]
  ------------------
  896|  6.66k|                ignore(ls_end_array);
  897|  6.66k|                return;
  898|  86.7k|            } else if (lex_state == ls_string) {
  ------------------
  |  Branch (898:24): [True: 85.6k, False: 1.08k]
  ------------------
  899|  85.6k|                append();
  900|  85.6k|            } else {
  901|  1.08k|                break;
  902|  1.08k|            }
  903|   215M|        } else {
  904|   215M|            switch (lex_state) {
  905|  4.65M|            case ls_top:
  ------------------
  |  Branch (905:13): [True: 4.65M, False: 210M]
  ------------------
  906|  4.65M|                token_start = offset;
  907|  4.65M|                if (*p == '"') {
  ------------------
  |  Branch (907:21): [True: 2.06M, False: 2.58M]
  ------------------
  908|  2.06M|                    ignore(ls_string);
  909|  2.58M|                } else if ((*p >= 'a') && (*p <= 'z')) {
  ------------------
  |  Branch (909:28): [True: 27.5k, False: 2.56M]
  |  Branch (909:43): [True: 27.4k, False: 7]
  ------------------
  910|  27.4k|                    append(ls_alpha);
  911|  2.56M|                } else if (*p == '-') {
  ------------------
  |  Branch (911:28): [True: 2.68k, False: 2.55M]
  ------------------
  912|  2.68k|                    append(ls_number_minus);
  913|  2.55M|                } else if ((*p >= '1') && (*p <= '9')) {
  ------------------
  |  Branch (913:28): [True: 2.21M, False: 344k]
  |  Branch (913:43): [True: 2.21M, False: 116]
  ------------------
  914|  2.21M|                    append(ls_number_before_point);
  915|  2.21M|                } else if (*p == '0') {
  ------------------
  |  Branch (915:28): [True: 344k, False: 342]
  ------------------
  916|   344k|                    append(ls_number_leading_zero);
  917|   344k|                } else {
  918|    342|                    QTC::TC("libtests", "JSON parse bad character");
  919|    342|                    throw std::runtime_error(
  920|    342|                        "JSON: offset " + std::to_string(offset) + ": unexpected character " +
  921|    342|                        std::string(p, 1));
  922|    342|                }
  923|  4.65M|                break;
  924|       |
  925|  4.65M|            case ls_number_minus:
  ------------------
  |  Branch (925:13): [True: 2.64k, False: 215M]
  ------------------
  926|  2.64k|                if ((*p >= '1') && (*p <= '9')) {
  ------------------
  |  Branch (926:21): [True: 1.84k, False: 800]
  |  Branch (926:36): [True: 1.83k, False: 13]
  ------------------
  927|  1.83k|                    append(ls_number_before_point);
  928|  1.83k|                } else if (*p == '0') {
  ------------------
  |  Branch (928:28): [True: 784, False: 29]
  ------------------
  929|    784|                    append(ls_number_leading_zero);
  930|    784|                } else {
  931|     29|                    QTC::TC("libtests", "JSON parse number minus no digits");
  932|     29|                    throw std::runtime_error(
  933|     29|                        "JSON: offset " + std::to_string(offset) +
  934|     29|                        ": numeric literal: no digit after minus sign");
  935|     29|                }
  936|  2.61k|                break;
  937|       |
  938|  2.61k|            case ls_number_leading_zero:
  ------------------
  |  Branch (938:13): [True: 1.72k, False: 215M]
  ------------------
  939|  1.72k|                if (*p == '.') {
  ------------------
  |  Branch (939:21): [True: 474, False: 1.25k]
  ------------------
  940|    474|                    append(ls_number_point);
  941|  1.25k|                } else if (*p == 'e' || *p == 'E') {
  ------------------
  |  Branch (941:28): [True: 697, False: 556]
  |  Branch (941:41): [True: 500, False: 56]
  ------------------
  942|  1.19k|                    append(ls_number_e);
  943|  1.19k|                } else {
  944|     56|                    QTC::TC("libtests", "JSON parse leading zero");
  945|     56|                    throw std::runtime_error(
  946|     56|                        "JSON: offset " + std::to_string(offset) + ": number with leading zero");
  947|     56|                }
  948|  1.67k|                break;
  949|       |
  950|  2.05M|            case ls_number_before_point:
  ------------------
  |  Branch (950:13): [True: 2.05M, False: 213M]
  ------------------
  951|  2.05M|                if ((*p >= '0') && (*p <= '9')) {
  ------------------
  |  Branch (951:21): [True: 2.05M, False: 1.47k]
  |  Branch (951:36): [True: 2.04M, False: 9.52k]
  ------------------
  952|  2.04M|                    append();
  953|  2.04M|                } else if (*p == '.') {
  ------------------
  |  Branch (953:28): [True: 1.41k, False: 9.58k]
  ------------------
  954|  1.41k|                    append(ls_number_point);
  955|  9.58k|                } else if (*p == 'e' || *p == 'E') {
  ------------------
  |  Branch (955:28): [True: 1.32k, False: 8.25k]
  |  Branch (955:41): [True: 8.17k, False: 87]
  ------------------
  956|  9.49k|                    append(ls_number_e);
  957|  9.49k|                } else {
  958|     87|                    tokenError();
  959|     87|                }
  960|  2.05M|                break;
  961|       |
  962|  1.85k|            case ls_number_point:
  ------------------
  |  Branch (962:13): [True: 1.85k, False: 215M]
  ------------------
  963|  1.85k|                if ((*p >= '0') && (*p <= '9')) {
  ------------------
  |  Branch (963:21): [True: 1.83k, False: 17]
  |  Branch (963:36): [True: 1.82k, False: 9]
  ------------------
  964|  1.82k|                    append(ls_number_after_point);
  965|  1.82k|                } else {
  966|     26|                    tokenError();
  967|     26|                }
  968|  1.85k|                break;
  969|       |
  970|  2.08M|            case ls_number_after_point:
  ------------------
  |  Branch (970:13): [True: 2.08M, False: 213M]
  ------------------
  971|  2.08M|                if ((*p >= '0') && (*p <= '9')) {
  ------------------
  |  Branch (971:21): [True: 2.08M, False: 19]
  |  Branch (971:36): [True: 2.08M, False: 614]
  ------------------
  972|  2.08M|                    append();
  973|  2.08M|                } else if (*p == 'e' || *p == 'E') {
  ------------------
  |  Branch (973:28): [True: 374, False: 259]
  |  Branch (973:41): [True: 232, False: 27]
  ------------------
  974|    606|                    append(ls_number_e);
  975|    606|                } else {
  976|     27|                    tokenError();
  977|     27|                }
  978|  2.08M|                break;
  979|       |
  980|  11.2k|            case ls_number_e:
  ------------------
  |  Branch (980:13): [True: 11.2k, False: 215M]
  ------------------
  981|  11.2k|                if ((*p >= '0') && (*p <= '9')) {
  ------------------
  |  Branch (981:21): [True: 9.19k, False: 2.00k]
  |  Branch (981:36): [True: 9.18k, False: 13]
  ------------------
  982|  9.18k|                    append(ls_number);
  983|  9.18k|                } else if ((*p == '+') || (*p == '-')) {
  ------------------
  |  Branch (983:28): [True: 999, False: 1.02k]
  |  Branch (983:43): [True: 989, False: 32]
  ------------------
  984|  1.98k|                    append(ls_number_e_sign);
  985|  1.98k|                } else {
  986|     32|                    tokenError();
  987|     32|                }
  988|  11.2k|                break;
  989|       |
  990|  1.97k|            case ls_number_e_sign:
  ------------------
  |  Branch (990:13): [True: 1.97k, False: 215M]
  ------------------
  991|  1.97k|                if ((*p >= '0') && (*p <= '9')) {
  ------------------
  |  Branch (991:21): [True: 1.96k, False: 13]
  |  Branch (991:36): [True: 1.95k, False: 9]
  ------------------
  992|  1.95k|                    append(ls_number);
  993|  1.95k|                } else {
  994|     22|                    tokenError();
  995|     22|                }
  996|  1.97k|                break;
  997|       |
  998|  4.21M|            case ls_number:
  ------------------
  |  Branch (998:13): [True: 4.21M, False: 211M]
  ------------------
  999|       |                // We only get here after we have seen an exponent.
 1000|  4.21M|                if ((*p >= '0') && (*p <= '9')) {
  ------------------
  |  Branch (1000:21): [True: 4.21M, False: 13]
  |  Branch (1000:36): [True: 4.21M, False: 15]
  ------------------
 1001|  4.21M|                    append();
 1002|  4.21M|                } else {
 1003|     28|                    tokenError();
 1004|     28|                }
 1005|  4.21M|                break;
 1006|       |
 1007|  2.08M|            case ls_alpha:
  ------------------
  |  Branch (1007:13): [True: 2.08M, False: 213M]
  ------------------
 1008|  2.08M|                if ((*p >= 'a') && (*p <= 'z')) {
  ------------------
  |  Branch (1008:21): [True: 2.08M, False: 217]
  |  Branch (1008:36): [True: 2.08M, False: 3]
  ------------------
 1009|  2.08M|                    append();
 1010|  2.08M|                } else {
 1011|    220|                    tokenError();
 1012|    220|                }
 1013|  2.08M|                break;
 1014|       |
 1015|   199M|            case ls_string:
  ------------------
  |  Branch (1015:13): [True: 199M, False: 15.4M]
  ------------------
 1016|   199M|                if (*p == '"') {
  ------------------
  |  Branch (1016:21): [True: 2.06M, False: 197M]
  ------------------
 1017|  2.06M|                    if (high_offset) {
  ------------------
  |  Branch (1017:25): [True: 29, False: 2.06M]
  ------------------
 1018|     29|                        QTC::TC("libtests", "JSON 16 dangling high");
 1019|     29|                        throw std::runtime_error(
 1020|     29|                            "JSON: offset " + std::to_string(high_offset) +
 1021|     29|                            ": UTF-16 high surrogate not followed by low surrogate");
 1022|     29|                    }
 1023|  2.06M|                    ignore(ls_after_string);
 1024|  2.06M|                    return;
 1025|   197M|                } else if (*p == '\\') {
  ------------------
  |  Branch (1025:28): [True: 132k, False: 197M]
  ------------------
 1026|   132k|                    ignore(ls_backslash);
 1027|   197M|                } else {
 1028|   197M|                    append();
 1029|   197M|                }
 1030|   197M|                break;
 1031|       |
 1032|   197M|            case ls_backslash:
  ------------------
  |  Branch (1032:13): [True: 132k, False: 215M]
  ------------------
 1033|   132k|                lex_state = ls_string;
 1034|   132k|                switch (*p) {
 1035|  47.1k|                case '\\':
  ------------------
  |  Branch (1035:17): [True: 47.1k, False: 85.0k]
  ------------------
 1036|  51.3k|                case '\"':
  ------------------
  |  Branch (1036:17): [True: 4.21k, False: 128k]
  ------------------
 1037|  51.8k|                case '/':
  ------------------
  |  Branch (1037:17): [True: 449, False: 131k]
  ------------------
 1038|       |                    // \/ is allowed in json input, but so is /, so we don't map / to \/ in output.
 1039|  51.8k|                    token += *p;
 1040|  51.8k|                    break;
 1041|  6.86k|                case 'b':
  ------------------
  |  Branch (1041:17): [True: 6.86k, False: 125k]
  ------------------
 1042|  6.86k|                    token += '\b';
 1043|  6.86k|                    break;
 1044|  7.50k|                case 'f':
  ------------------
  |  Branch (1044:17): [True: 7.50k, False: 124k]
  ------------------
 1045|  7.50k|                    token += '\f';
 1046|  7.50k|                    break;
 1047|  8.64k|                case 'n':
  ------------------
  |  Branch (1047:17): [True: 8.64k, False: 123k]
  ------------------
 1048|  8.64k|                    token += '\n';
 1049|  8.64k|                    break;
 1050|  8.20k|                case 'r':
  ------------------
  |  Branch (1050:17): [True: 8.20k, False: 124k]
  ------------------
 1051|  8.20k|                    token += '\r';
 1052|  8.20k|                    break;
 1053|  3.70k|                case 't':
  ------------------
  |  Branch (1053:17): [True: 3.70k, False: 128k]
  ------------------
 1054|  3.70k|                    token += '\t';
 1055|  3.70k|                    break;
 1056|  45.4k|                case 'u':
  ------------------
  |  Branch (1056:17): [True: 45.4k, False: 86.7k]
  ------------------
 1057|  45.4k|                    lex_state = ls_u4;
 1058|  45.4k|                    u_count = 0;
 1059|  45.4k|                    u_value = 0;
 1060|  45.4k|                    break;
 1061|     12|                default:
  ------------------
  |  Branch (1061:17): [True: 12, False: 132k]
  ------------------
 1062|     12|                    lex_state = ls_backslash;
 1063|     12|                    tokenError();
 1064|   132k|                }
 1065|   132k|                ignore();
 1066|   132k|                break;
 1067|       |
 1068|   181k|            case ls_u4:
  ------------------
  |  Branch (1068:13): [True: 181k, False: 215M]
  ------------------
 1069|   181k|                using ui = unsigned int;
 1070|   181k|                if (ui val = ui(util::hex_decode_char(*p)); val < 16) {
  ------------------
  |  Branch (1070:61): [True: 181k, False: 68]
  ------------------
 1071|   181k|                    u_value = 16 * u_value + val;
 1072|   181k|                } else {
 1073|     68|                    tokenError();
 1074|     68|                }
 1075|   181k|                if (++u_count == 4) {
  ------------------
  |  Branch (1075:21): [True: 45.3k, False: 136k]
  ------------------
 1076|  45.3k|                    handle_u_code(u_value, offset - 5, high_surrogate, high_offset, token);
 1077|  45.3k|                    lex_state = ls_string;
 1078|  45.3k|                }
 1079|   181k|                ignore();
 1080|   181k|                break;
 1081|       |
 1082|      0|            default:
  ------------------
  |  Branch (1082:13): [True: 0, False: 215M]
  ------------------
 1083|      0|                throw std::logic_error("JSONParser::getToken : trying to handle delimiter state");
 1084|   215M|            }
 1085|   215M|        }
 1086|   343M|    }
 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.59M|    if (!token.empty()) {
  ------------------
  |  Branch (1091:9): [True: 2.58M, False: 8.13k]
  ------------------
 1092|  2.58M|        switch (lex_state) {
 1093|      0|        case ls_top:
  ------------------
  |  Branch (1093:9): [True: 0, False: 2.58M]
  ------------------
 1094|       |            // Can't happen
 1095|      0|            throw std::logic_error("tok_start set in ls_top while parsing");
 1096|      0|            break;
 1097|       |
 1098|   343k|        case ls_number_leading_zero:
  ------------------
  |  Branch (1098:9): [True: 343k, False: 2.24M]
  ------------------
 1099|  2.54M|        case ls_number_before_point:
  ------------------
  |  Branch (1099:9): [True: 2.20M, False: 384k]
  ------------------
 1100|  2.54M|        case ls_number_after_point:
  ------------------
  |  Branch (1100:9): [True: 1.19k, False: 2.58M]
  ------------------
 1101|  2.54M|            lex_state = ls_number;
 1102|  2.54M|            break;
 1103|       |
 1104|  11.1k|        case ls_number:
  ------------------
  |  Branch (1104:9): [True: 11.1k, False: 2.57M]
  ------------------
 1105|  38.3k|        case ls_alpha:
  ------------------
  |  Branch (1105:9): [True: 27.2k, False: 2.56M]
  ------------------
 1106|       |            // terminal state
 1107|  38.3k|            break;
 1108|       |
 1109|  1.13k|        default:
  ------------------
  |  Branch (1109:9): [True: 1.13k, False: 2.58M]
  ------------------
 1110|  1.13k|            tokenError();
 1111|  2.58M|        }
 1112|  2.58M|    }
 1113|  2.59M|}
JSON.cc:_ZN12_GLOBAL__N_110JSONParser6ignoreEv:
  790|  6.63M|{
  791|  6.63M|    ++p;
  792|  6.63M|    ++offset;
  793|  6.63M|}
JSON.cc:_ZN12_GLOBAL__N_110JSONParser6ignoreENS0_11lex_state_eE:
  799|  9.22M|{
  800|  9.22M|    lex_state = next;
  801|  9.22M|    ++p;
  802|  9.22M|    ++offset;
  803|  9.22M|}
JSON.cc:_ZN12_GLOBAL__N_110JSONParser6appendEv:
  770|   322M|{
  771|   322M|    token += *p;
  772|   322M|    ++p;
  773|   322M|    ++offset;
  774|   322M|}
JSON.cc:_ZN12_GLOBAL__N_110JSONParser6appendENS0_11lex_state_eE:
  780|  2.61M|{
  781|  2.61M|    lex_state = next;
  782|  2.61M|    token += *p;
  783|  2.61M|    ++p;
  784|  2.61M|    ++offset;
  785|  2.61M|}
JSON.cc:_ZN12_GLOBAL__N_110JSONParser10tokenErrorEv:
  705|  1.65k|{
  706|  1.65k|    if (done) {
  ------------------
  |  Branch (706:9): [True: 1.05k, False: 606]
  ------------------
  707|  1.05k|        QTC::TC("libtests", "JSON parse ls premature end of input");
  708|  1.05k|        throw std::runtime_error("JSON: premature end of input");
  709|  1.05k|    }
  710|       |
  711|    606|    if (lex_state == ls_u4) {
  ------------------
  |  Branch (711:9): [True: 78, False: 528]
  ------------------
  712|     78|        QTC::TC("libtests", "JSON parse bad hex after u");
  713|     78|        throw std::runtime_error(
  714|     78|            "JSON: offset " + std::to_string(offset - u_count - 1) +
  715|     78|            ": \\u must be followed by four hex digits");
  716|    528|    } else if (lex_state == ls_alpha) {
  ------------------
  |  Branch (716:16): [True: 220, False: 308]
  ------------------
  717|    220|        QTC::TC("libtests", "JSON parse keyword bad character");
  718|    220|        throw std::runtime_error(
  719|    220|            "JSON: offset " + std::to_string(offset) + ": keyword: unexpected character " +
  720|    220|            std::string(p, 1));
  721|    308|    } else if (lex_state == ls_string) {
  ------------------
  |  Branch (721:16): [True: 17, False: 291]
  ------------------
  722|     17|        QTC::TC("libtests", "JSON parse control char in string");
  723|     17|        throw std::runtime_error(
  724|     17|            "JSON: offset " + std::to_string(offset) +
  725|     17|            ": control character in string (missing \"?)");
  726|    291|    } else if (lex_state == ls_backslash) {
  ------------------
  |  Branch (726:16): [True: 16, False: 275]
  ------------------
  727|     16|        QTC::TC("libtests", "JSON parse backslash bad character");
  728|     16|        throw std::runtime_error(
  729|     16|            "JSON: offset " + std::to_string(offset) +
  730|     16|            ": invalid character after backslash: " + std::string(p, 1));
  731|     16|    }
  732|       |
  733|    275|    if (*p == '.') {
  ------------------
  |  Branch (733:9): [True: 14, False: 261]
  ------------------
  734|     14|        if (lex_state == ls_number || lex_state == ls_number_e || lex_state == ls_number_e_sign) {
  ------------------
  |  Branch (734:13): [True: 3, False: 11]
  |  Branch (734:39): [True: 3, False: 8]
  |  Branch (734:67): [True: 3, False: 5]
  ------------------
  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|      5|            QTC::TC("libtests", "JSON parse duplicate point");
  741|      5|            throw std::runtime_error(
  742|      5|                "JSON: offset " + std::to_string(offset) +
  743|      5|                ": numeric literal: decimal point already seen");
  744|      5|        }
  745|    261|    } else if (*p == 'e' || *p == 'E') {
  ------------------
  |  Branch (745:16): [True: 6, False: 255]
  |  Branch (745:29): [True: 17, False: 238]
  ------------------
  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|    238|    } else if ((*p == '+') || (*p == '-')) {
  ------------------
  |  Branch (749:16): [True: 5, False: 233]
  |  Branch (749:31): [True: 13, False: 220]
  ------------------
  750|     18|        QTC::TC("libtests", "JSON parse unexpected sign");
  751|     18|        throw std::runtime_error(
  752|     18|            "JSON: offset " + std::to_string(offset) + ": numeric literal: unexpected sign");
  753|    220|    } else if (util::is_space(*p) || strchr("{}[]:,", *p)) {
  ------------------
  |  Branch (753:16): [True: 18, False: 202]
  |  Branch (753:38): [True: 35, False: 167]
  ------------------
  754|     53|        QTC::TC("libtests", "JSON parse incomplete number");
  755|     53|        throw std::runtime_error(
  756|     53|            "JSON: offset " + std::to_string(offset) + ": numeric literal: incomplete number");
  757|       |
  758|    167|    } else {
  759|    167|        QTC::TC("libtests", "JSON parse numeric bad character");
  760|    167|        throw std::runtime_error(
  761|    167|            "JSON: offset " + std::to_string(offset) + ": numeric literal: unexpected character " +
  762|    167|            std::string(p, 1));
  763|    167|    }
  764|      0|    throw std::logic_error("JSON::tokenError : unhandled error");
  765|    275|}
JSON.cc:_ZN12_GLOBAL__N_110JSONParser13handle_u_codeEmxRmRxRNSt3__112basic_stringIcNS3_11char_traitsIcEENS3_9allocatorIcEEEE:
  674|  45.3k|{
  675|  45.3k|    if ((codepoint & 0xFC00) == 0xD800) {
  ------------------
  |  Branch (675:9): [True: 2.64k, False: 42.6k]
  ------------------
  676|       |        // high surrogate
  677|  2.64k|        qpdf_offset_t new_high_offset = offset;
  678|  2.64k|        if (high_offset) {
  ------------------
  |  Branch (678:13): [True: 37, False: 2.60k]
  ------------------
  679|     37|            QTC::TC("libtests", "JSON 16 high high");
  680|     37|            throw std::runtime_error(
  681|     37|                "JSON: offset " + std::to_string(new_high_offset) +
  682|     37|                ": UTF-16 high surrogate found after previous high surrogate at offset " +
  683|     37|                std::to_string(high_offset));
  684|     37|        }
  685|  2.60k|        high_offset = new_high_offset;
  686|  2.60k|        high_surrogate = codepoint;
  687|  42.6k|    } else if ((codepoint & 0xFC00) == 0xDC00) {
  ------------------
  |  Branch (687:16): [True: 2.55k, False: 40.1k]
  ------------------
  688|       |        // low surrogate
  689|  2.55k|        if (offset != (high_offset + 6)) {
  ------------------
  |  Branch (689:13): [True: 19, False: 2.53k]
  ------------------
  690|     19|            QTC::TC("libtests", "JSON 16 low not after high");
  691|     19|            throw std::runtime_error(
  692|     19|                "JSON: offset " + std::to_string(offset) +
  693|     19|                ": UTF-16 low surrogate found not immediately after high surrogate");
  694|     19|        }
  695|  2.53k|        high_offset = 0;
  696|  2.53k|        codepoint = 0x10000U + ((high_surrogate & 0x3FFU) << 10U) + (codepoint & 0x3FF);
  697|  2.53k|        result += QUtil::toUTF8(codepoint);
  698|  40.1k|    } else {
  699|  40.1k|        result += QUtil::toUTF8(codepoint);
  700|  40.1k|    }
  701|  45.3k|}
JSON.cc:_ZN12_GLOBAL__N_110JSONParser11handleTokenEv:
 1117|  9.61M|{
 1118|  9.61M|    if (lex_state == ls_top) {
  ------------------
  |  Branch (1118:9): [True: 7.90k, False: 9.61M]
  ------------------
 1119|  7.90k|        return;
 1120|  7.90k|    }
 1121|       |
 1122|  9.61M|    if (parser_state == ps_done) {
  ------------------
  |  Branch (1122:9): [True: 76, False: 9.61M]
  ------------------
 1123|     76|        QTC::TC("libtests", "JSON parse junk after object");
 1124|     76|        throw std::runtime_error(
 1125|     76|            "JSON: offset " + std::to_string(offset) +
 1126|     76|            ": material follows end of object: " + token);
 1127|     76|    }
 1128|       |
 1129|  9.61M|    const static JSON null_item = JSON::makeNull();
 1130|  9.61M|    JSON item;
 1131|  9.61M|    auto tos = stack.empty() ? null_item : stack.back().item;
  ------------------
  |  Branch (1131:16): [True: 14.8k, False: 9.59M]
  ------------------
 1132|  9.61M|    auto ls = lex_state;
 1133|  9.61M|    lex_state = ls_top;
 1134|       |
 1135|  9.61M|    switch (ls) {
 1136|   147k|    case ls_begin_dict:
  ------------------
  |  Branch (1136:5): [True: 147k, False: 9.46M]
  ------------------
 1137|   147k|        item = JSON::makeDictionary();
 1138|   147k|        break;
 1139|       |
 1140|  47.5k|    case ls_begin_array:
  ------------------
  |  Branch (1140:5): [True: 47.5k, False: 9.56M]
  ------------------
 1141|  47.5k|        item = JSON::makeArray();
 1142|  47.5k|        break;
 1143|       |
 1144|   450k|    case ls_colon:
  ------------------
  |  Branch (1144:5): [True: 450k, False: 9.16M]
  ------------------
 1145|   450k|        if (parser_state != ps_dict_after_key) {
  ------------------
  |  Branch (1145:13): [True: 228, False: 450k]
  ------------------
 1146|    228|            QTC::TC("libtests", "JSON parse unexpected :");
 1147|    228|            throw std::runtime_error(
 1148|    228|                "JSON: offset " + std::to_string(offset) + ": unexpected colon");
 1149|    228|        }
 1150|   450k|        parser_state = ps_dict_after_colon;
 1151|   450k|        return;
 1152|       |
 1153|  4.22M|    case ls_comma:
  ------------------
  |  Branch (1153:5): [True: 4.22M, False: 5.38M]
  ------------------
 1154|  4.22M|        if (!((parser_state == ps_dict_after_item) || (parser_state == ps_array_after_item))) {
  ------------------
  |  Branch (1154:15): [True: 337k, False: 3.89M]
  |  Branch (1154:55): [True: 3.89M, False: 145]
  ------------------
 1155|    145|            QTC::TC("libtests", "JSON parse unexpected ,");
 1156|    145|            throw std::runtime_error(
 1157|    145|                "JSON: offset " + std::to_string(offset) + ": unexpected comma");
 1158|    145|        }
 1159|  4.22M|        if (parser_state == ps_dict_after_item) {
  ------------------
  |  Branch (1159:13): [True: 337k, False: 3.89M]
  ------------------
 1160|   337k|            parser_state = ps_dict_after_comma;
 1161|  3.89M|        } else if (parser_state == ps_array_after_item) {
  ------------------
  |  Branch (1161:20): [True: 3.89M, False: 0]
  ------------------
 1162|  3.89M|            parser_state = ps_array_after_comma;
 1163|  3.89M|        } else {
 1164|      0|            throw std::logic_error("JSONParser::handleToken: unexpected parser state for comma");
 1165|      0|        }
 1166|  4.22M|        return;
 1167|       |
 1168|  4.22M|    case ls_end_array:
  ------------------
  |  Branch (1168:5): [True: 6.65k, False: 9.60M]
  ------------------
 1169|  6.65k|        if (!(parser_state == ps_array_begin || parser_state == ps_array_after_item)) {
  ------------------
  |  Branch (1169:15): [True: 3.25k, False: 3.40k]
  |  Branch (1169:49): [True: 3.37k, False: 24]
  ------------------
 1170|     24|            QTC::TC("libtests", "JSON parse unexpected ]");
 1171|     24|            throw std::runtime_error(
 1172|     24|                "JSON: offset " + std::to_string(offset) + ": unexpected array end delimiter");
 1173|     24|        }
 1174|  6.63k|        parser_state = stack.back().state;
 1175|  6.63k|        tos.setEnd(offset);
 1176|  6.63k|        if (reactor) {
  ------------------
  |  Branch (1176:13): [True: 3.20k, False: 3.42k]
  ------------------
 1177|  3.20k|            reactor->containerEnd(tos);
 1178|  3.20k|        }
 1179|  6.63k|        if (parser_state != ps_done) {
  ------------------
  |  Branch (1179:13): [True: 6.62k, False: 14]
  ------------------
 1180|  6.62k|            stack.pop_back();
 1181|  6.62k|        }
 1182|  6.63k|        return;
 1183|       |
 1184|  75.0k|    case ls_end_dict:
  ------------------
  |  Branch (1184:5): [True: 75.0k, False: 9.53M]
  ------------------
 1185|  75.0k|        if (!((parser_state == ps_dict_begin) || (parser_state == ps_dict_after_item))) {
  ------------------
  |  Branch (1185:15): [True: 31.3k, False: 43.6k]
  |  Branch (1185:50): [True: 43.6k, False: 19]
  ------------------
 1186|     19|            QTC::TC("libtests", "JSON parse unexpected }");
 1187|     19|            throw std::runtime_error(
 1188|     19|                "JSON: offset " + std::to_string(offset) + ": unexpected dictionary end delimiter");
 1189|     19|        }
 1190|  75.0k|        parser_state = stack.back().state;
 1191|  75.0k|        tos.setEnd(offset);
 1192|  75.0k|        if (reactor) {
  ------------------
  |  Branch (1192:13): [True: 37.4k, False: 37.5k]
  ------------------
 1193|  37.4k|            reactor->containerEnd(tos);
 1194|  37.4k|        }
 1195|  75.0k|        if (parser_state != ps_done) {
  ------------------
  |  Branch (1195:13): [True: 74.8k, False: 151]
  ------------------
 1196|  74.8k|            stack.pop_back();
 1197|  74.8k|        }
 1198|  75.0k|        return;
 1199|       |
 1200|  2.55M|    case ls_number:
  ------------------
  |  Branch (1200:5): [True: 2.55M, False: 7.05M]
  ------------------
 1201|  2.55M|        item = JSON::makeNumber(token);
 1202|  2.55M|        break;
 1203|       |
 1204|  27.2k|    case ls_alpha:
  ------------------
  |  Branch (1204:5): [True: 27.2k, False: 9.58M]
  ------------------
 1205|  27.2k|        if (token == "true") {
  ------------------
  |  Branch (1205:13): [True: 14.0k, False: 13.2k]
  ------------------
 1206|  14.0k|            item = JSON::makeBool(true);
 1207|  14.0k|        } else if (token == "false") {
  ------------------
  |  Branch (1207:20): [True: 2.58k, False: 10.6k]
  ------------------
 1208|  2.58k|            item = JSON::makeBool(false);
 1209|  10.6k|        } else if (token == "null") {
  ------------------
  |  Branch (1209:20): [True: 10.2k, False: 417]
  ------------------
 1210|  10.2k|            item = JSON::makeNull();
 1211|  10.2k|        } else {
 1212|    417|            QTC::TC("libtests", "JSON parse invalid keyword");
 1213|    417|            throw std::runtime_error(
 1214|    417|                "JSON: offset " + std::to_string(offset) + ": invalid keyword " + token);
 1215|    417|        }
 1216|  26.8k|        break;
 1217|       |
 1218|  2.06M|    case ls_after_string:
  ------------------
  |  Branch (1218:5): [True: 2.06M, False: 7.54M]
  ------------------
 1219|  2.06M|        if (parser_state == ps_dict_begin || parser_state == ps_dict_after_comma) {
  ------------------
  |  Branch (1219:13): [True: 113k, False: 1.95M]
  |  Branch (1219:46): [True: 337k, False: 1.61M]
  ------------------
 1220|   450k|            dict_key = token;
 1221|   450k|            dict_key_offset = token_start;
 1222|   450k|            parser_state = ps_dict_after_key;
 1223|   450k|            return;
 1224|  1.61M|        } else {
 1225|  1.61M|            item = JSON::makeString(token);
 1226|  1.61M|        }
 1227|  1.61M|        break;
 1228|       |
 1229|  1.61M|    default:
  ------------------
  |  Branch (1229:5): [True: 234, False: 9.61M]
  ------------------
 1230|    234|        throw std::runtime_error(
 1231|    234|            "JSON: offset " + std::to_string(offset) + ": premature end of input");
 1232|      0|        break;
 1233|  9.61M|    }
 1234|       |
 1235|  4.39M|    item.setStart(token_start);
 1236|  4.39M|    item.setEnd(offset);
 1237|       |
 1238|  4.39M|    switch (parser_state) {
  ------------------
  |  Branch (1238:13): [True: 4.39M, False: 0]
  ------------------
 1239|     22|    case ps_dict_begin:
  ------------------
  |  Branch (1239:5): [True: 22, False: 4.39M]
  ------------------
 1240|     64|    case ps_dict_after_comma:
  ------------------
  |  Branch (1240:5): [True: 42, False: 4.39M]
  ------------------
 1241|     64|        QTC::TC("libtests", "JSON parse string as dict key");
 1242|     64|        throw std::runtime_error(
 1243|     64|            "JSON: offset " + std::to_string(offset) + ": expect string as dictionary key");
 1244|      0|        break;
 1245|       |
 1246|   450k|    case ps_dict_after_colon:
  ------------------
  |  Branch (1246:5): [True: 450k, False: 3.94M]
  ------------------
 1247|   450k|        if (!reactor || !reactor->dictionaryItem(dict_key, item)) {
  ------------------
  |  Branch (1247:13): [True: 225k, False: 224k]
  |  Branch (1247:25): [True: 497, False: 224k]
  ------------------
 1248|   225k|            tos.addDictionaryMember(dict_key, item);
 1249|   225k|        }
 1250|   450k|        parser_state = ps_dict_after_item;
 1251|   450k|        break;
 1252|       |
 1253|  43.0k|    case ps_array_begin:
  ------------------
  |  Branch (1253:5): [True: 43.0k, False: 4.35M]
  ------------------
 1254|  3.93M|    case ps_array_after_comma:
  ------------------
  |  Branch (1254:5): [True: 3.89M, False: 508k]
  ------------------
 1255|  3.93M|        if (!reactor || !reactor->arrayItem(item)) {
  ------------------
  |  Branch (1255:13): [True: 1.97M, False: 1.96M]
  |  Branch (1255:25): [True: 25, False: 1.96M]
  ------------------
 1256|  1.97M|            tos.addArrayElement(item);
 1257|  1.97M|        }
 1258|  3.93M|        parser_state = ps_array_after_item;
 1259|  3.93M|        break;
 1260|       |
 1261|  14.7k|    case ps_top:
  ------------------
  |  Branch (1261:5): [True: 14.7k, False: 4.38M]
  ------------------
 1262|  14.7k|        if (!(item.isDictionary() || item.isArray())) {
  ------------------
  |  Branch (1262:15): [True: 13.8k, False: 890]
  |  Branch (1262:38): [True: 668, False: 222]
  ------------------
 1263|    222|            stack.emplace_back(ps_done, item);
 1264|    222|            parser_state = ps_done;
 1265|    222|            return;
 1266|    222|        }
 1267|  14.4k|        parser_state = ps_done;
 1268|  14.4k|        break;
 1269|       |
 1270|     66|    case ps_dict_after_key:
  ------------------
  |  Branch (1270:5): [True: 66, False: 4.39M]
  ------------------
 1271|     66|        QTC::TC("libtests", "JSON parse expected colon");
 1272|     66|        throw std::runtime_error("JSON: offset " + std::to_string(offset) + ": expected ':'");
 1273|      0|        break;
 1274|       |
 1275|    128|    case ps_dict_after_item:
  ------------------
  |  Branch (1275:5): [True: 128, False: 4.39M]
  ------------------
 1276|    128|        QTC::TC("libtests", "JSON parse expected , or }");
 1277|    128|        throw std::runtime_error(
 1278|    128|            "JSON: offset " + std::to_string(offset) + ": expected ',' or '}'");
 1279|      0|        break;
 1280|       |
 1281|     95|    case ps_array_after_item:
  ------------------
  |  Branch (1281:5): [True: 95, False: 4.39M]
  ------------------
 1282|     95|        QTC::TC("libtests", "JSON parse expected, or ]");
 1283|     95|        throw std::runtime_error(
 1284|     95|            "JSON: offset " + std::to_string(offset) + ": expected ',' or ']'");
 1285|      0|        break;
 1286|       |
 1287|      0|    case ps_done:
  ------------------
  |  Branch (1287:5): [True: 0, False: 4.39M]
  ------------------
 1288|      0|        throw std::logic_error("JSONParser::handleToken: unexpected parser state");
 1289|  4.39M|    }
 1290|       |
 1291|  4.39M|    if (item.isDictionary() || item.isArray()) {
  ------------------
  |  Branch (1291:9): [True: 147k, False: 4.25M]
  |  Branch (1291:32): [True: 47.5k, False: 4.20M]
  ------------------
 1292|   194k|        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|   194k|        if (item.isDictionary()) {
  ------------------
  |  Branch (1296:13): [True: 147k, False: 47.5k]
  ------------------
 1297|   147k|            if (reactor) {
  ------------------
  |  Branch (1297:17): [True: 73.4k, False: 73.6k]
  ------------------
 1298|  73.4k|                reactor->dictionaryStart();
 1299|  73.4k|            }
 1300|   147k|            parser_state = ps_dict_begin;
 1301|   147k|        } else if (item.isArray()) {
  ------------------
  |  Branch (1301:20): [True: 47.5k, False: 0]
  ------------------
 1302|  47.5k|            if (reactor) {
  ------------------
  |  Branch (1302:17): [True: 22.2k, False: 25.3k]
  ------------------
 1303|  22.2k|                reactor->arrayStart();
 1304|  22.2k|            }
 1305|  47.5k|            parser_state = ps_array_begin;
 1306|  47.5k|        }
 1307|       |
 1308|   194k|        if (stack.size() > 500) {
  ------------------
  |  Branch (1308:13): [True: 3, False: 194k]
  ------------------
 1309|      3|            throw std::runtime_error(
 1310|      3|                "JSON: offset " + std::to_string(offset) + ": maximum object depth exceeded");
 1311|      3|        }
 1312|   194k|    }
 1313|  4.39M|}
JSON.cc:_ZN12_GLOBAL__N_110JSONParser10StackFrameC2ENS0_14parser_state_eER4JSON:
  625|   194k|                state(state),
  626|   194k|                item(item)
  627|   194k|            {
  628|   194k|            }

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

_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|   159k|{
   30|   159k|    m->os.write(reinterpret_cast<char const*>(buf), static_cast<std::streamsize>(len));
   31|   159k|}
_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.87k|    Doc(qpdf, this),
  132|  7.87k|    c(qpdf, this),
  133|  7.87k|    lin(*this),
  134|  7.87k|    objects(*this),
  135|  7.87k|    pages(*this),
  136|  7.87k|    file(std::make_shared<InvalidInputSource>()),
  137|  7.87k|    encp(std::make_shared<EncryptionParameters>())
  138|  7.87k|{
  139|  7.87k|}
_ZN4QPDFC2Ev:
  142|  7.87k|    m(std::make_unique<Members>(*this))
  143|  7.87k|{
  144|  7.87k|    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.87k|    static std::atomic<unsigned long long> unique_id{0};
  148|  7.87k|    m->unique_id = unique_id.fetch_add(1ULL);
  149|  7.87k|}
_ZN4QPDFD2Ev:
  186|  7.87k|{
  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.87k|    m->xref_table.clear();
  200|  13.7k|    for (auto const& iter: m->obj_cache) {
  ------------------
  |  Branch (200:26): [True: 13.7k, False: 7.87k]
  ------------------
  201|  13.7k|        Disconnect(iter.second.object).disconnect();
  202|  13.7k|    }
  203|  7.87k|}
_ZN4QPDF17processMemoryFileEPKcS1_mS1_:
  228|  7.87k|{
  229|  7.87k|    auto is = std::make_shared<is::OffsetBuffer>(description, std::string_view{buf, length});
  230|  7.87k|    processInputSource(is, password);
  231|  7.87k|}
_ZN4QPDF18processInputSourceENSt3__110shared_ptrI11InputSourceEEPKc:
  235|  7.87k|{
  236|  7.87k|    m->file = source;
  237|  7.87k|    m->objects.parse(password);
  238|  7.87k|}
_ZN4QPDF3Doc6Common4warnERK7QPDFExc:
  343|  53.0k|{
  344|  53.0k|    if (cf.max_warnings() > 0 && m->warnings.size() >= cf.max_warnings()) {
  ------------------
  |  Branch (344:9): [True: 53.0k, False: 0]
  |  Branch (344:34): [True: 32, False: 53.0k]
  ------------------
  345|     32|        stopOnError("Too many warnings - file is too badly damaged");
  346|     32|    }
  347|  53.0k|    m->warnings.emplace_back(e);
  348|  53.0k|    if (!cf.suppress_warnings()) {
  ------------------
  |  Branch (348:9): [True: 53.0k, False: 32]
  ------------------
  349|  53.0k|        *cf.log()->getWarn() << "WARNING: " << m->warnings.back().what() << "\n";
  350|  53.0k|    }
  351|  53.0k|}
_ZN4QPDF4warnE17qpdf_error_code_eRKNSt3__112basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEExS9_:
  359|  53.0k|{
  360|  53.0k|    m->c.warn(QPDFExc(error_code, getFilename(), object, offset, message));
  361|  53.0k|}
_ZNK4QPDF11getFilenameEv:
  625|   109k|{
  626|   109k|    return m->file->getName();
  627|   109k|}
_ZN4QPDF3Doc6Common11stopOnErrorERKNSt3__112basic_stringIcNS2_11char_traitsIcEENS2_9allocatorIcEEEE:
  799|     32|{
  800|     32|    throw damagedPDF("", message);
  801|     32|}
_ZNK4QPDF3Doc6Common10damagedPDFERKNSt3__112basic_stringIcNS2_11char_traitsIcEENS2_9allocatorIcEEEExSA_:
  823|     32|{
  824|     32|    return {qpdf_e_damaged_pdf, m->file->getName(), object, offset, message, true};
  825|     32|}
_ZNK4QPDF3Doc6Common10damagedPDFERKNSt3__112basic_stringIcNS2_11char_traitsIcEENS2_9allocatorIcEEEESA_:
  831|     32|{
  832|     32|    return damagedPDF(object, m->file->getLastOffset(), message);
  833|     32|}
_ZN10DisconnectC2ERKNSt3__110shared_ptrI10QPDFObjectEE:
  172|  13.7k|        BaseHandle(obj)
  173|  13.7k|    {
  174|  13.7k|    }
_ZN10Disconnect10disconnectEv:
  177|  13.7k|    {
  178|  13.7k|        BaseHandle::disconnect(false);
  179|  13.7k|        if (raw_type_code() != ::ot_null) {
  ------------------
  |  Branch (179:13): [True: 7.76k, False: 6.00k]
  ------------------
  180|  7.76k|            obj->value = QPDF_Destroyed();
  181|  7.76k|        }
  182|  13.7k|    }

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

_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.87k|{
   78|  7.87k|    static auto l = create();
   79|  7.87k|    return l;
   80|  7.87k|}
_ZN10QPDFLogger7getWarnEb:
  114|  53.0k|{
  115|  53.0k|    if (m->p_warn) {
  ------------------
  |  Branch (115:9): [True: 0, False: 53.0k]
  ------------------
  116|      0|        return m->p_warn;
  117|      0|    }
  118|  53.0k|    return getError(null_okay);
  119|  53.0k|}
_ZN10QPDFLogger8getErrorEb:
  135|  53.0k|{
  136|  53.0k|    return throwIfNull(m->p_error, null_okay);
  137|  53.0k|}
_ZN10QPDFLogger11throwIfNullENSt3__110shared_ptrI8PipelineEEb:
  254|  53.0k|{
  255|  53.0k|    if (!(null_okay || p)) {
  ------------------
  |  Branch (255:11): [True: 0, False: 53.0k]
  |  Branch (255:24): [True: 53.0k, False: 0]
  ------------------
  256|      0|        throw std::logic_error("QPDFLogger: requested a null pipeline without null_okay == true");
  257|      0|    }
  258|  53.0k|    return p;
  259|  53.0k|}
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.83k|{
    6|  3.83k|    qpdf_offset_t shift = (getTypeCode() == ::ot_dictionary) ? 2
  ------------------
  |  Branch (6:27): [True: 0, False: 3.83k]
  ------------------
    7|  3.83k|        : (getTypeCode() == ::ot_array)                      ? 1
  ------------------
  |  Branch (7:11): [True: 0, False: 3.83k]
  ------------------
    8|  3.83k|                                                             : 0;
    9|       |
   10|  3.83k|    if (object_description) {
  ------------------
  |  Branch (10:9): [True: 3.83k, False: 0]
  ------------------
   11|  3.83k|        switch (object_description->index()) {
  ------------------
  |  Branch (11:17): [True: 3.83k, False: 0]
  ------------------
   12|  3.83k|        case 0:
  ------------------
  |  Branch (12:9): [True: 3.83k, False: 0]
  ------------------
   13|  3.83k|            {
   14|       |                // Simple template string
   15|  3.83k|                auto description = std::get<0>(*object_description);
   16|       |
   17|  3.83k|                if (auto pos = description.find("$OG"); pos != std::string::npos) {
  ------------------
  |  Branch (17:57): [True: 0, False: 3.83k]
  ------------------
   18|      0|                    description.replace(pos, 3, og.unparse(' '));
   19|      0|                }
   20|  3.83k|                if (auto pos = description.find("$PO"); pos != std::string::npos) {
  ------------------
  |  Branch (20:57): [True: 0, False: 3.83k]
  ------------------
   21|      0|                    description.replace(pos, 3, std::to_string(parsed_offset + shift));
   22|      0|                }
   23|  3.83k|                return description;
   24|      0|            }
   25|      0|        case 1:
  ------------------
  |  Branch (25:9): [True: 0, False: 3.83k]
  ------------------
   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.83k]
  ------------------
   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.83k]
  ------------------
   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.83k|        }
   54|       |
   55|  3.83k|    } else if (og.isIndirect()) {
  ------------------
  |  Branch (55:16): [True: 0, False: 0]
  ------------------
   56|      0|        return "object " + og.unparse(' ');
   57|      0|    }
   58|      0|    return {};
   59|  3.83k|}

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

_ZN4qpdf4impl6Parser5parseER11InputSourceRKNSt3__112basic_stringIcNS4_11char_traitsIcEENS4_9allocatorIcEEEEP4QPDF:
   53|  11.2k|{
   54|  11.2k|    qpdf::Tokenizer tokenizer;
   55|  11.2k|    if (auto result = Parser(
  ------------------
  |  Branch (55:14): [True: 10.8k, False: 343]
  ------------------
   56|  11.2k|                          input,
   57|  11.2k|                          make_description(input.getName(), object_description),
   58|  11.2k|                          object_description,
   59|  11.2k|                          tokenizer,
   60|  11.2k|                          nullptr,
   61|  11.2k|                          context,
   62|  11.2k|                          false)
   63|  11.2k|                          .parse()) {
   64|  10.8k|        return result;
   65|  10.8k|    }
   66|    343|    return {QPDFObject::create<QPDF_Null>()};
   67|  11.2k|}
_ZN4qpdf4impl6Parser5parseER11InputSourceRKNSt3__112basic_stringIcNS4_11char_traitsIcEENS4_9allocatorIcEEEERNS_9TokenizerEPN16QPDFObjectHandle15StringDecrypterER4QPDFb:
  129|  7.87k|{
  130|  7.87k|    return Parser(
  131|  7.87k|               input,
  132|  7.87k|               make_description(input.getName(), object_description),
  133|  7.87k|               object_description,
  134|  7.87k|               tokenizer,
  135|  7.87k|               decrypter,
  136|  7.87k|               &context,
  137|  7.87k|               true,
  138|  7.87k|               0,
  139|  7.87k|               0,
  140|  7.87k|               sanity_checks)
  141|  7.87k|        .parse();
  142|  7.87k|}
_ZN4qpdf4impl6Parser5parseEb:
  164|  19.0k|{
  165|  19.0k|    try {
  166|  19.0k|        return parse_first(content_stream);
  167|  19.0k|    } catch (Error&) {
  168|      0|        return {};
  169|    343|    } catch (QPDFExc& e) {
  170|    343|        throw e;
  171|    343|    } 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|  19.0k|}
_ZN4qpdf4impl6Parser11parse_firstEb:
  181|  19.0k|{
  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|  19.0k|    QPDF::Doc::ParseGuard pg(context_);
  188|  19.0k|    start_ = input_.tell();
  189|  19.0k|    if (!tokenizer_.nextToken(input_, object_description_)) {
  ------------------
  |  Branch (189:9): [True: 343, False: 18.7k]
  ------------------
  190|    343|        warn(tokenizer_.getErrorMessage());
  191|    343|    }
  192|       |
  193|  19.0k|    switch (tokenizer_.getType()) {
  194|      0|    case QPDFTokenizer::tt_eof:
  ------------------
  |  Branch (194:5): [True: 0, False: 19.0k]
  ------------------
  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: 19.0k]
  ------------------
  204|      0|        return {};
  205|       |
  206|      0|    case QPDFTokenizer::tt_brace_open:
  ------------------
  |  Branch (206:5): [True: 0, False: 19.0k]
  ------------------
  207|      0|    case QPDFTokenizer::tt_brace_close:
  ------------------
  |  Branch (207:5): [True: 0, False: 19.0k]
  ------------------
  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: 19.0k]
  ------------------
  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: 19.0k]
  ------------------
  216|      0|        warn("unexpected dictionary close token");
  217|      0|        return {};
  218|       |
  219|      0|    case QPDFTokenizer::tt_array_open:
  ------------------
  |  Branch (219:5): [True: 0, False: 19.0k]
  ------------------
  220|  7.87k|    case QPDFTokenizer::tt_dict_open:
  ------------------
  |  Branch (220:5): [True: 7.87k, False: 11.2k]
  ------------------
  221|  7.87k|        stack_.clear();
  222|  7.87k|        stack_.emplace_back(
  223|  7.87k|            input_,
  224|  7.87k|            (tokenizer_.getType() == QPDFTokenizer::tt_array_open) ? st_array : st_dictionary_key);
  ------------------
  |  Branch (224:13): [True: 0, False: 7.87k]
  ------------------
  225|  7.87k|        frame_ = &stack_.back();
  226|  7.87k|        return parse_remainder(content_stream);
  227|       |
  228|      0|    case QPDFTokenizer::tt_bool:
  ------------------
  |  Branch (228:5): [True: 0, False: 19.0k]
  ------------------
  229|      0|        return with_description<QPDF_Bool>(tokenizer_.getValue() == "true");
  230|       |
  231|      0|    case QPDFTokenizer::tt_null:
  ------------------
  |  Branch (231:5): [True: 0, False: 19.0k]
  ------------------
  232|      0|        return {QPDFObject::create<QPDF_Null>()};
  233|       |
  234|      0|    case QPDFTokenizer::tt_integer:
  ------------------
  |  Branch (234:5): [True: 0, False: 19.0k]
  ------------------
  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: 19.0k]
  ------------------
  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.21k]
  ------------------
  241|  10.8k|        return with_description<QPDF_Name>(tokenizer_.getValue());
  242|       |
  243|      0|    case QPDFTokenizer::tt_word:
  ------------------
  |  Branch (243:5): [True: 0, False: 19.0k]
  ------------------
  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: 19.0k]
  ------------------
  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: 19.0k]
  ------------------
  275|      0|        warn("treating unknown token type as null while reading object");
  276|      0|        return {};
  277|  19.0k|    }
  278|  19.0k|}
_ZN4qpdf4impl6Parser15parse_remainderEb:
  282|  7.87k|{
  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.87k|    bad_count_ = 0;
  289|  7.87k|    bool b_contents = false;
  290|       |
  291|  23.6k|    while (true) {
  ------------------
  |  Branch (291:12): [True: 23.6k, Folded]
  ------------------
  292|  23.6k|        if (!tokenizer_.nextToken(input_, object_description_)) {
  ------------------
  |  Branch (292:13): [True: 0, False: 23.6k]
  ------------------
  293|      0|            warn(tokenizer_.getErrorMessage());
  294|      0|        }
  295|  23.6k|        ++good_count_; // optimistically
  296|       |
  297|  23.6k|        if (int_count_ != 0) {
  ------------------
  |  Branch (297:13): [True: 7.87k, False: 15.7k]
  ------------------
  298|       |            // Special handling of indirect references. Treat integer tokens as part of an indirect
  299|       |            // reference until proven otherwise.
  300|  7.87k|            if (tokenizer_.getType() == QPDFTokenizer::tt_integer) {
  ------------------
  |  Branch (300:17): [True: 0, False: 7.87k]
  ------------------
  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.87k|            } else if (
  310|  7.87k|                int_count_ >= 2 && tokenizer_.getType() == QPDFTokenizer::tt_word &&
  ------------------
  |  Branch (310:17): [True: 0, False: 7.87k]
  |  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.87k|            } else if (int_count_ > 0) {
  ------------------
  |  Branch (329:24): [True: 7.87k, False: 0]
  ------------------
  330|       |                // Process the buffered integers before processing the current token.
  331|  7.87k|                if (int_count_ > 1) {
  ------------------
  |  Branch (331:21): [True: 0, False: 7.87k]
  ------------------
  332|      0|                    add_int(int_count_ - 1);
  333|      0|                }
  334|  7.87k|                add_int(int_count_);
  335|  7.87k|                int_count_ = 0;
  336|  7.87k|            }
  337|  7.87k|        }
  338|       |
  339|  23.6k|        switch (tokenizer_.getType()) {
  340|      0|        case QPDFTokenizer::tt_eof:
  ------------------
  |  Branch (340:9): [True: 0, False: 23.6k]
  ------------------
  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.6k]
  ------------------
  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.6k]
  ------------------
  355|      0|        case QPDFTokenizer::tt_brace_close:
  ------------------
  |  Branch (355:9): [True: 0, False: 23.6k]
  ------------------
  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.6k]
  ------------------
  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.87k|        case QPDFTokenizer::tt_dict_close:
  ------------------
  |  Branch (386:9): [True: 7.87k, False: 15.7k]
  ------------------
  387|  7.87k|            if (frame_->state <= st_dictionary_value) {
  ------------------
  |  Branch (387:17): [True: 7.87k, False: 0]
  ------------------
  388|       |                // Attempt to recover more or less gracefully from invalid dictionaries.
  389|  7.87k|                auto& dict = frame_->dict;
  390|       |
  391|  7.87k|                if (frame_->state == st_dictionary_value) {
  ------------------
  |  Branch (391:21): [True: 0, False: 7.87k]
  ------------------
  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.87k|                if (!frame_->olist.empty()) {
  ------------------
  |  Branch (397:21): [True: 0, False: 7.87k]
  ------------------
  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.87k|                if (!frame_->contents_string.empty() && dict.contains("/Type") &&
  ------------------
  |  Branch (407:21): [True: 0, False: 7.87k]
  |  Branch (407:21): [True: 0, False: 7.87k]
  |  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.87k|                auto object = QPDFObject::create<QPDF_Dictionary>(std::move(dict));
  414|  7.87k|                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.87k|                if (stack_.size() <= 1) {
  ------------------
  |  Branch (419:21): [True: 7.87k, False: 0]
  ------------------
  420|  7.87k|                    return object;
  421|  7.87k|                }
  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.6k]
  ------------------
  437|      0|        case QPDFTokenizer::tt_dict_open:
  ------------------
  |  Branch (437:9): [True: 0, False: 23.6k]
  ------------------
  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.6k]
  ------------------
  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.6k]
  ------------------
  455|      0|            add_null();
  456|      0|            continue;
  457|       |
  458|  7.87k|        case QPDFTokenizer::tt_integer:
  ------------------
  |  Branch (458:9): [True: 7.87k, False: 15.7k]
  ------------------
  459|  7.87k|            if (!content_stream) {
  ------------------
  |  Branch (459:17): [True: 7.87k, False: 0]
  ------------------
  460|       |                // Buffer token in case it is part of an indirect reference.
  461|  7.87k|                last_offset_buffer_[1] = input_.getLastOffset();
  462|  7.87k|                int_buffer_[1] = QUtil::string_to_ll(tokenizer_.getValue().c_str());
  463|  7.87k|                int_count_ = 1;
  464|  7.87k|            } else {
  465|      0|                add_scalar<QPDF_Integer>(QUtil::string_to_ll(tokenizer_.getValue().c_str()));
  466|      0|            }
  467|  7.87k|            continue;
  468|       |
  469|      0|        case QPDFTokenizer::tt_real:
  ------------------
  |  Branch (469:9): [True: 0, False: 23.6k]
  ------------------
  470|      0|            add_scalar<QPDF_Real>(tokenizer_.getValue());
  471|      0|            continue;
  472|       |
  473|  7.87k|        case QPDFTokenizer::tt_name:
  ------------------
  |  Branch (473:9): [True: 7.87k, False: 15.7k]
  ------------------
  474|  7.87k|            if (frame_->state == st_dictionary_key) {
  ------------------
  |  Branch (474:17): [True: 7.87k, False: 0]
  ------------------
  475|  7.87k|                frame_->key = tokenizer_.getValue();
  476|  7.87k|                frame_->state = st_dictionary_value;
  477|  7.87k|                b_contents = decrypter_ && frame_->key == "/Contents";
  ------------------
  |  Branch (477:30): [True: 0, False: 7.87k]
  |  Branch (477:44): [True: 0, False: 0]
  ------------------
  478|  7.87k|                continue;
  479|  7.87k|            } 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.6k]
  ------------------
  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.6k]
  ------------------
  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.6k]
  ------------------
  529|      0|            add_bad_null("treating unknown token type as null while reading object");
  530|  23.6k|        }
  531|  23.6k|    }
  532|  7.87k|}
_ZN4qpdf4impl6Parser3addEONSt3__110shared_ptrI10QPDFObjectEE:
  536|  7.87k|{
  537|  7.87k|    if (frame_->state != st_dictionary_value) {
  ------------------
  |  Branch (537:9): [True: 0, False: 7.87k]
  ------------------
  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.87k|    } else {
  542|  7.87k|        if (auto res = frame_->dict.insert_or_assign(frame_->key, std::move(obj)); !res.second) {
  ------------------
  |  Branch (542:84): [True: 0, False: 7.87k]
  ------------------
  543|      0|            warn_duplicate_key();
  544|      0|        }
  545|  7.87k|        frame_->state = st_dictionary_key;
  546|  7.87k|    }
  547|  7.87k|}
_ZN4qpdf4impl6Parser7add_intEi:
  577|  7.87k|{
  578|  7.87k|    auto obj = QPDFObject::create<QPDF_Integer>(int_buffer_[count % 2]);
  579|  7.87k|    obj->setDescription(context_, description_, last_offset_buffer_[count % 2]);
  580|  7.87k|    add(std::move(obj));
  581|  7.87k|}
_ZN4qpdf4impl6Parser15set_descriptionERNSt3__110shared_ptrI10QPDFObjectEEx:
  610|  7.87k|{
  611|  7.87k|    if (obj) {
  ------------------
  |  Branch (611:9): [True: 7.87k, False: 0]
  ------------------
  612|  7.87k|        obj->setDescription(context_, description_, parsed_offset);
  613|  7.87k|    }
  614|  7.87k|}
_ZNK4qpdf4impl6Parser4warnERK7QPDFExc:
  687|    343|{
  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|    343|    if (context_) {
  ------------------
  |  Branch (691:9): [True: 0, False: 343]
  ------------------
  692|      0|        context_->warn(e);
  693|    343|    } else {
  694|    343|        throw e;
  695|    343|    }
  696|    343|}
_ZNK4qpdf4impl6Parser4warnExRKNSt3__112basic_stringIcNS2_11char_traitsIcEENS2_9allocatorIcEEEE:
  710|    343|{
  711|    343|    if (stream_id_) {
  ------------------
  |  Branch (711:9): [True: 0, False: 343]
  ------------------
  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|    343|    } else {
  716|    343|        warn(QPDFExc(qpdf_e_damaged_pdf, input_.getName(), object_description_, offset, msg));
  717|    343|    }
  718|    343|}
_ZNK4qpdf4impl6Parser4warnERKNSt3__112basic_stringIcNS2_11char_traitsIcEENS2_9allocatorIcEEEE:
  722|    343|{
  723|    343|    warn(input_.getLastOffset(), msg);
  724|    343|}
_ZN4QPDF3Doc10ParseGuardC2EPS_:
   26|  19.0k|        objects(qpdf ? &qpdf->m->objects : nullptr)
  ------------------
  |  Branch (26:17): [True: 7.87k, False: 11.2k]
  ------------------
   27|  19.0k|    {
   28|  19.0k|        if (objects) {
  ------------------
  |  Branch (28:13): [True: 7.87k, False: 11.2k]
  ------------------
   29|  7.87k|            objects->inParse(true);
   30|  7.87k|        }
   31|  19.0k|    }
_ZN4QPDF3Doc10ParseGuardD2Ev:
   40|  19.0k|    {
   41|  19.0k|        if (objects) {
  ------------------
  |  Branch (41:13): [True: 7.87k, False: 11.2k]
  ------------------
   42|  7.87k|            objects->inParse(false);
   43|  7.87k|        }
   44|  19.0k|    }
_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|   140k|{
   86|   140k|    state = st_before_token;
   87|   140k|    type = tt::tt_bad;
   88|   140k|    val.clear();
   89|   140k|    raw_val.clear();
   90|   140k|    error_message = "";
   91|   140k|    before_token = true;
   92|   140k|    in_token = false;
   93|   140k|    char_to_unread = '\0';
   94|   140k|    inline_image_bytes = 0;
   95|   140k|    string_depth = 0;
   96|   140k|    bad = false;
   97|   140k|}
_ZN4qpdf9TokenizerC2Ev:
  119|  19.0k|{
  120|  19.0k|    reset();
  121|  19.0k|}
_ZN4qpdf9Tokenizer8allowEOFEv:
  131|  7.87k|{
  132|  7.87k|    allow_eof = true;
  133|  7.87k|}
_ZN4qpdf9Tokenizer7isSpaceEc:
  149|   129k|{
  150|   129k|    return (ch == '\0' || util::is_space(ch));
  ------------------
  |  Branch (150:13): [True: 0, False: 129k]
  |  Branch (150:27): [True: 47.2k, False: 82.0k]
  ------------------
  151|   129k|}
_ZN4qpdf9Tokenizer11isDelimiterEc:
  155|  5.63M|{
  156|  5.63M|    return is_delimiter(ch);
  157|  5.63M|}
_ZN4qpdf9Tokenizer16presentCharacterEc:
  167|  6.66k|{
  168|  6.66k|    handleCharacter(ch);
  169|       |
  170|  6.66k|    if (in_token) {
  ------------------
  |  Branch (170:9): [True: 0, False: 6.66k]
  ------------------
  171|      0|        raw_val += ch;
  172|      0|    }
  173|  6.66k|}
_ZN4qpdf9Tokenizer15handleCharacterEc:
  177|  6.76M|{
  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.76M|    switch (state) {
  182|      0|    case st_top:
  ------------------
  |  Branch (182:5): [True: 0, False: 6.76M]
  ------------------
  183|      0|        inTop(ch);
  184|      0|        return;
  185|       |
  186|      0|    case st_in_space:
  ------------------
  |  Branch (186:5): [True: 0, False: 6.76M]
  ------------------
  187|      0|        inSpace(ch);
  188|      0|        return;
  189|       |
  190|      0|    case st_in_comment:
  ------------------
  |  Branch (190:5): [True: 0, False: 6.76M]
  ------------------
  191|      0|        inComment(ch);
  192|      0|        return;
  193|       |
  194|  7.87k|    case st_lt:
  ------------------
  |  Branch (194:5): [True: 7.87k, False: 6.75M]
  ------------------
  195|  7.87k|        inLt(ch);
  196|  7.87k|        return;
  197|       |
  198|  7.87k|    case st_gt:
  ------------------
  |  Branch (198:5): [True: 7.87k, False: 6.75M]
  ------------------
  199|  7.87k|        inGt(ch);
  200|  7.87k|        return;
  201|       |
  202|      0|    case st_in_string:
  ------------------
  |  Branch (202:5): [True: 0, False: 6.76M]
  ------------------
  203|      0|        inString(ch);
  204|      0|        return;
  205|       |
  206|  5.31M|    case st_name:
  ------------------
  |  Branch (206:5): [True: 5.31M, False: 1.45M]
  ------------------
  207|  5.31M|        inName(ch);
  208|  5.31M|        return;
  209|       |
  210|  23.6k|    case st_number:
  ------------------
  |  Branch (210:5): [True: 23.6k, False: 6.73M]
  ------------------
  211|  23.6k|        inNumber(ch);
  212|  23.6k|        return;
  213|       |
  214|      0|    case st_real:
  ------------------
  |  Branch (214:5): [True: 0, False: 6.76M]
  ------------------
  215|      0|        inReal(ch);
  216|      0|        return;
  217|       |
  218|      0|    case st_string_after_cr:
  ------------------
  |  Branch (218:5): [True: 0, False: 6.76M]
  ------------------
  219|      0|        inStringAfterCR(ch);
  220|      0|        return;
  221|       |
  222|      0|    case st_string_escape:
  ------------------
  |  Branch (222:5): [True: 0, False: 6.76M]
  ------------------
  223|      0|        inStringEscape(ch);
  224|      0|        return;
  225|       |
  226|      0|    case st_char_code:
  ------------------
  |  Branch (226:5): [True: 0, False: 6.76M]
  ------------------
  227|      0|        inCharCode(ch);
  228|      0|        return;
  229|       |
  230|   196k|    case st_literal:
  ------------------
  |  Branch (230:5): [True: 196k, False: 6.56M]
  ------------------
  231|   196k|        inLiteral(ch);
  232|   196k|        return;
  233|       |
  234|      0|    case st_inline_image:
  ------------------
  |  Branch (234:5): [True: 0, False: 6.76M]
  ------------------
  235|      0|        inInlineImage(ch);
  236|      0|        return;
  237|       |
  238|      0|    case st_in_hexstring:
  ------------------
  |  Branch (238:5): [True: 0, False: 6.76M]
  ------------------
  239|      0|        inHexstring(ch);
  240|      0|        return;
  241|       |
  242|      0|    case st_in_hexstring_2nd:
  ------------------
  |  Branch (242:5): [True: 0, False: 6.76M]
  ------------------
  243|      0|        inHexstring2nd(ch);
  244|      0|        return;
  245|       |
  246|   576k|    case st_name_hex1:
  ------------------
  |  Branch (246:5): [True: 576k, False: 6.18M]
  ------------------
  247|   576k|        inNameHex1(ch);
  248|   576k|        return;
  249|       |
  250|   508k|    case st_name_hex2:
  ------------------
  |  Branch (250:5): [True: 508k, False: 6.25M]
  ------------------
  251|   508k|        inNameHex2(ch);
  252|   508k|        return;
  253|       |
  254|      0|    case st_sign:
  ------------------
  |  Branch (254:5): [True: 0, False: 6.76M]
  ------------------
  255|      0|        inSign(ch);
  256|      0|        return;
  257|       |
  258|      0|    case st_decimal:
  ------------------
  |  Branch (258:5): [True: 0, False: 6.76M]
  ------------------
  259|      0|        inDecimal(ch);
  260|      0|        return;
  261|       |
  262|   129k|    case (st_before_token):
  ------------------
  |  Branch (262:5): [True: 129k, False: 6.63M]
  ------------------
  263|   129k|        inBeforeToken(ch);
  264|   129k|        return;
  265|       |
  266|      0|    case (st_token_ready):
  ------------------
  |  Branch (266:5): [True: 0, False: 6.76M]
  ------------------
  267|      0|        inTokenReady(ch);
  268|      0|        return;
  269|       |
  270|      0|    default:
  ------------------
  |  Branch (270:5): [True: 0, False: 6.76M]
  ------------------
  271|      0|        throw std::logic_error("INTERNAL ERROR: invalid state while reading token");
  272|  6.76M|    }
  273|  6.76M|}
_ZN4qpdf9Tokenizer13inBeforeTokenEc:
  284|   129k|{
  285|       |    // Note: we specifically do not use ctype here.  It is locale-dependent.
  286|   129k|    if (isSpace(ch)) {
  ------------------
  |  Branch (286:9): [True: 47.2k, False: 82.0k]
  ------------------
  287|  47.2k|        before_token = !include_ignorable;
  288|  47.2k|        in_token = include_ignorable;
  289|  47.2k|        if (include_ignorable) {
  ------------------
  |  Branch (289:13): [True: 0, False: 47.2k]
  ------------------
  290|      0|            state = st_in_space;
  291|      0|        }
  292|  82.0k|    } else if (ch == '%') {
  ------------------
  |  Branch (292:16): [True: 0, False: 82.0k]
  ------------------
  293|      0|        before_token = !include_ignorable;
  294|      0|        in_token = include_ignorable;
  295|      0|        state = st_in_comment;
  296|  82.0k|    } else {
  297|  82.0k|        before_token = false;
  298|  82.0k|        in_token = true;
  299|  82.0k|        inTop(ch);
  300|  82.0k|    }
  301|   129k|}
_ZN4qpdf9Tokenizer5inTopEc:
  305|  82.0k|{
  306|  82.0k|    switch (ch) {
  307|      0|    case '(':
  ------------------
  |  Branch (307:5): [True: 0, False: 82.0k]
  ------------------
  308|      0|        string_depth = 1;
  309|      0|        state = st_in_string;
  310|      0|        return;
  311|       |
  312|  7.87k|    case '<':
  ------------------
  |  Branch (312:5): [True: 7.87k, False: 74.1k]
  ------------------
  313|  7.87k|        state = st_lt;
  314|  7.87k|        return;
  315|       |
  316|  7.87k|    case '>':
  ------------------
  |  Branch (316:5): [True: 7.87k, False: 74.1k]
  ------------------
  317|  7.87k|        state = st_gt;
  318|  7.87k|        return;
  319|       |
  320|      0|    case (')'):
  ------------------
  |  Branch (320:5): [True: 0, False: 82.0k]
  ------------------
  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: 82.0k]
  ------------------
  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: 82.0k]
  ------------------
  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: 82.0k]
  ------------------
  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: 82.0k]
  ------------------
  343|      0|        type = tt::tt_brace_close;
  344|      0|        state = st_token_ready;
  345|      0|        return;
  346|       |
  347|  19.0k|    case '/':
  ------------------
  |  Branch (347:5): [True: 19.0k, False: 62.9k]
  ------------------
  348|  19.0k|        state = st_name;
  349|  19.0k|        val += ch;
  350|  19.0k|        return;
  351|       |
  352|      0|    case '0':
  ------------------
  |  Branch (352:5): [True: 0, False: 82.0k]
  ------------------
  353|  7.87k|    case '1':
  ------------------
  |  Branch (353:5): [True: 7.87k, False: 74.1k]
  ------------------
  354|  7.87k|    case '2':
  ------------------
  |  Branch (354:5): [True: 0, False: 82.0k]
  ------------------
  355|  7.87k|    case '3':
  ------------------
  |  Branch (355:5): [True: 0, False: 82.0k]
  ------------------
  356|  7.87k|    case '4':
  ------------------
  |  Branch (356:5): [True: 0, False: 82.0k]
  ------------------
  357|  7.87k|    case '5':
  ------------------
  |  Branch (357:5): [True: 0, False: 82.0k]
  ------------------
  358|  7.87k|    case '6':
  ------------------
  |  Branch (358:5): [True: 0, False: 82.0k]
  ------------------
  359|  7.87k|    case '7':
  ------------------
  |  Branch (359:5): [True: 0, False: 82.0k]
  ------------------
  360|  7.87k|    case '8':
  ------------------
  |  Branch (360:5): [True: 0, False: 82.0k]
  ------------------
  361|  23.6k|    case '9':
  ------------------
  |  Branch (361:5): [True: 15.7k, False: 66.2k]
  ------------------
  362|  23.6k|        state = st_number;
  363|  23.6k|        return;
  364|       |
  365|      0|    case '+':
  ------------------
  |  Branch (365:5): [True: 0, False: 82.0k]
  ------------------
  366|      0|    case '-':
  ------------------
  |  Branch (366:5): [True: 0, False: 82.0k]
  ------------------
  367|      0|        state = st_sign;
  368|      0|        return;
  369|       |
  370|      0|    case '.':
  ------------------
  |  Branch (370:5): [True: 0, False: 82.0k]
  ------------------
  371|      0|        state = st_decimal;
  372|      0|        return;
  373|       |
  374|  23.6k|    default:
  ------------------
  |  Branch (374:5): [True: 23.6k, False: 58.4k]
  ------------------
  375|  23.6k|        state = st_literal;
  376|  23.6k|        return;
  377|  82.0k|    }
  378|  82.0k|}
_ZN4qpdf9Tokenizer6inNameEc:
  448|  5.41M|{
  449|  5.41M|    if (isDelimiter(ch)) {
  ------------------
  |  Branch (449:9): [True: 19.0k, False: 5.39M]
  ------------------
  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|  19.0k|        type = bad ? tt::tt_bad : tt::tt_name;
  ------------------
  |  Branch (456:16): [True: 86, False: 18.9k]
  ------------------
  457|  19.0k|        in_token = false;
  458|  19.0k|        char_to_unread = ch;
  459|  19.0k|        state = st_token_ready;
  460|  5.39M|    } else if (ch == '#') {
  ------------------
  |  Branch (460:16): [True: 576k, False: 4.82M]
  ------------------
  461|   576k|        char_code = 0;
  462|   576k|        state = st_name_hex1;
  463|  4.82M|    } else {
  464|  4.82M|        val += ch;
  465|  4.82M|    }
  466|  5.41M|}
_ZN4qpdf9Tokenizer10inNameHex1Ec:
  470|   576k|{
  471|   576k|    hex_char = ch;
  472|       |
  473|   576k|    if (char hval = util::hex_decode_char(ch); hval < '\20') {
  ------------------
  |  Branch (473:48): [True: 508k, False: 68.0k]
  ------------------
  474|   508k|        char_code = int(hval) << 4;
  475|   508k|        state = st_name_hex2;
  476|   508k|    } else {
  477|  68.0k|        QTC::TC("qpdf", "QPDFTokenizer bad name 1");
  478|  68.0k|        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|  68.0k|        val += '\0';
  481|  68.0k|        state = st_name;
  482|  68.0k|        inName(ch);
  483|  68.0k|    }
  484|   576k|}
_ZN4qpdf9Tokenizer10inNameHex2Ec:
  488|   508k|{
  489|   508k|    if (char hval = util::hex_decode_char(ch); hval < '\20') {
  ------------------
  |  Branch (489:48): [True: 471k, False: 37.3k]
  ------------------
  490|   471k|        char_code |= int(hval);
  491|   471k|    } else {
  492|  37.3k|        QTC::TC("qpdf", "QPDFTokenizer bad name 2");
  493|  37.3k|        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|  37.3k|        val += '\0';
  496|  37.3k|        val += hex_char;
  497|  37.3k|        state = st_name;
  498|  37.3k|        inName(ch);
  499|  37.3k|        return;
  500|  37.3k|    }
  501|   471k|    if (char_code == 0) {
  ------------------
  |  Branch (501:9): [True: 450k, False: 20.7k]
  ------------------
  502|   450k|        QTC::TC("qpdf", "QPDFTokenizer null in name");
  503|   450k|        error_message = "null character not allowed in name token";
  504|   450k|        val += "#00";
  505|   450k|        state = st_name;
  506|   450k|        bad = true;
  507|   450k|    } else {
  508|  20.7k|        val += char(char_code);
  509|  20.7k|        state = st_name;
  510|  20.7k|    }
  511|   471k|}
_ZN4qpdf9Tokenizer8inNumberEc:
  539|  23.6k|{
  540|  23.6k|    if (util::is_digit(ch)) {
  ------------------
  |  Branch (540:9): [True: 0, False: 23.6k]
  ------------------
  541|  23.6k|    } else if (ch == '.') {
  ------------------
  |  Branch (541:16): [True: 0, False: 23.6k]
  ------------------
  542|      0|        state = st_real;
  543|  23.6k|    } else if (isDelimiter(ch)) {
  ------------------
  |  Branch (543:16): [True: 23.6k, False: 0]
  ------------------
  544|  23.6k|        type = tt::tt_integer;
  545|  23.6k|        state = st_token_ready;
  546|  23.6k|        in_token = false;
  547|  23.6k|        char_to_unread = ch;
  548|  23.6k|    } else {
  549|      0|        state = st_literal;
  550|      0|    }
  551|  23.6k|}
_ZN4qpdf9Tokenizer4inLtEc:
  630|  7.87k|{
  631|  7.87k|    if (ch == '<') {
  ------------------
  |  Branch (631:9): [True: 7.87k, False: 0]
  ------------------
  632|  7.87k|        type = tt::tt_dict_open;
  633|  7.87k|        state = st_token_ready;
  634|  7.87k|        return;
  635|  7.87k|    }
  636|       |
  637|      0|    state = st_in_hexstring;
  638|      0|    inHexstring(ch);
  639|      0|}
_ZN4qpdf9Tokenizer4inGtEc:
  643|  7.87k|{
  644|  7.87k|    if (ch == '>') {
  ------------------
  |  Branch (644:9): [True: 7.87k, False: 0]
  ------------------
  645|  7.87k|        type = tt::tt_dict_close;
  646|  7.87k|        state = st_token_ready;
  647|  7.87k|    } 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.87k|}
_ZN4qpdf9Tokenizer9inLiteralEc:
  659|   196k|{
  660|   196k|    if (isDelimiter(ch)) {
  ------------------
  |  Branch (660:9): [True: 23.6k, False: 173k]
  ------------------
  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.6k|        in_token = false;
  667|  23.6k|        char_to_unread = ch;
  668|  23.6k|        state = st_token_ready;
  669|  23.6k|        type = (raw_val == "true") || (raw_val == "false")
  ------------------
  |  Branch (669:16): [True: 0, False: 23.6k]
  |  Branch (669:39): [True: 0, False: 23.6k]
  ------------------
  670|  23.6k|            ? tt::tt_bool
  671|  23.6k|            : (raw_val == "null" ? tt::tt_null : tt::tt_word);
  ------------------
  |  Branch (671:16): [True: 0, False: 23.6k]
  ------------------
  672|  23.6k|    }
  673|   196k|}
_ZN4qpdf9Tokenizer10presentEOFEv:
  760|  6.66k|{
  761|  6.66k|    switch (state) {
  762|  6.61k|    case st_name:
  ------------------
  |  Branch (762:5): [True: 6.61k, False: 56]
  ------------------
  763|  6.64k|    case st_name_hex1:
  ------------------
  |  Branch (763:5): [True: 31, False: 6.63k]
  ------------------
  764|  6.66k|    case st_name_hex2:
  ------------------
  |  Branch (764:5): [True: 25, False: 6.64k]
  ------------------
  765|  6.66k|    case st_number:
  ------------------
  |  Branch (765:5): [True: 0, False: 6.66k]
  ------------------
  766|  6.66k|    case st_real:
  ------------------
  |  Branch (766:5): [True: 0, False: 6.66k]
  ------------------
  767|  6.66k|    case st_sign:
  ------------------
  |  Branch (767:5): [True: 0, False: 6.66k]
  ------------------
  768|  6.66k|    case st_decimal:
  ------------------
  |  Branch (768:5): [True: 0, False: 6.66k]
  ------------------
  769|  6.66k|    case st_literal:
  ------------------
  |  Branch (769:5): [True: 0, False: 6.66k]
  ------------------
  770|  6.66k|        QTC::TC("qpdf", "QPDFTokenizer EOF reading appendable token");
  771|       |        // Push any delimiter to the state machine to finish off the final token.
  772|  6.66k|        presentCharacter('\f');
  773|  6.66k|        in_token = true;
  774|  6.66k|        break;
  775|       |
  776|      0|    case st_top:
  ------------------
  |  Branch (776:5): [True: 0, False: 6.66k]
  ------------------
  777|      0|    case st_before_token:
  ------------------
  |  Branch (777:5): [True: 0, False: 6.66k]
  ------------------
  778|      0|        type = tt::tt_eof;
  779|      0|        break;
  780|       |
  781|      0|    case st_in_space:
  ------------------
  |  Branch (781:5): [True: 0, False: 6.66k]
  ------------------
  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: 6.66k]
  ------------------
  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: 6.66k]
  ------------------
  790|      0|        break;
  791|       |
  792|      0|    default:
  ------------------
  |  Branch (792:5): [True: 0, False: 6.66k]
  ------------------
  793|      0|        QTC::TC("qpdf", "QPDFTokenizer EOF reading token");
  794|      0|        type = tt::tt_bad;
  795|      0|        error_message = "EOF while reading token";
  796|  6.66k|    }
  797|  6.66k|    state = st_token_ready;
  798|  6.66k|}
_ZN4qpdf9Tokenizer8getTokenERN13QPDFTokenizer5TokenERbRc:
  916|  39.3k|{
  917|  39.3k|    bool ready = (state == st_token_ready);
  918|  39.3k|    unread_char = !in_token && !before_token;
  ------------------
  |  Branch (918:19): [True: 39.3k, False: 0]
  |  Branch (918:32): [True: 39.3k, False: 0]
  ------------------
  919|  39.3k|    ch = char_to_unread;
  920|  39.3k|    if (ready) {
  ------------------
  |  Branch (920:9): [True: 39.3k, False: 0]
  ------------------
  921|  39.3k|        token = (!(type == tt::tt_name || type == tt::tt_string))
  ------------------
  |  Branch (921:20): [True: 0, False: 39.3k]
  |  Branch (921:43): [True: 0, False: 39.3k]
  ------------------
  922|  39.3k|            ? Token(type, raw_val, raw_val, error_message)
  923|  39.3k|            : Token(type, val, raw_val, error_message);
  924|       |
  925|  39.3k|        reset();
  926|  39.3k|    }
  927|  39.3k|    return ready;
  928|  39.3k|}
_ZN4qpdf9Tokenizer9readTokenER11InputSourceRKNSt3__112basic_stringIcNS3_11char_traitsIcEENS3_9allocatorIcEEEEbm:
  958|  39.3k|{
  959|  39.3k|    nextToken(input, context, max_len);
  960|       |
  961|  39.3k|    Token token;
  962|  39.3k|    bool unread_char;
  963|  39.3k|    char char_to_unread;
  964|  39.3k|    getToken(token, unread_char, char_to_unread);
  965|       |
  966|  39.3k|    if (token.getType() == tt::tt_bad) {
  ------------------
  |  Branch (966:9): [True: 0, False: 39.3k]
  ------------------
  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|  39.3k|    return token;
  979|  39.3k|}
_ZN4qpdf9Tokenizer9nextTokenER11InputSourceRKNSt3__112basic_stringIcNS3_11char_traitsIcEENS3_9allocatorIcEEEEm:
  983|  82.0k|{
  984|  82.0k|    if (state != st_inline_image) {
  ------------------
  |  Branch (984:9): [True: 82.0k, False: 0]
  ------------------
  985|  82.0k|        reset();
  986|  82.0k|    }
  987|  82.0k|    qpdf_offset_t offset = input.fastTell();
  988|       |
  989|  6.84M|    while (state != st_token_ready) {
  ------------------
  |  Branch (989:12): [True: 6.76M, False: 82.0k]
  ------------------
  990|  6.76M|        char ch;
  991|  6.76M|        if (!input.fastRead(ch)) {
  ------------------
  |  Branch (991:13): [True: 6.66k, False: 6.75M]
  ------------------
  992|  6.66k|            presentEOF();
  993|       |
  994|  6.66k|            if ((type == tt::tt_eof) && (!allow_eof)) {
  ------------------
  |  Branch (994:17): [True: 0, False: 6.66k]
  |  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.75M|        } else {
 1002|  6.75M|            handleCharacter(ch);
 1003|  6.75M|            if (before_token) {
  ------------------
  |  Branch (1003:17): [True: 47.2k, False: 6.70M]
  ------------------
 1004|  47.2k|                ++offset;
 1005|  47.2k|            }
 1006|  6.75M|            if (in_token) {
  ------------------
  |  Branch (1006:17): [True: 6.64M, False: 106k]
  ------------------
 1007|  6.64M|                raw_val += ch;
 1008|  6.64M|            }
 1009|  6.75M|            if (max_len && (raw_val.length() >= max_len) && (state != st_token_ready)) {
  ------------------
  |  Branch (1009:17): [True: 0, False: 6.75M]
  |  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.75M|        }
 1017|  6.76M|    }
 1018|       |
 1019|  82.0k|    input.fastUnread(!in_token && !before_token);
  ------------------
  |  Branch (1019:22): [True: 59.6k, False: 22.4k]
  |  Branch (1019:35): [True: 59.6k, False: 0]
  ------------------
 1020|       |
 1021|  82.0k|    if (type != tt::tt_eof) {
  ------------------
  |  Branch (1021:9): [True: 82.0k, False: 0]
  ------------------
 1022|  82.0k|        input.setLastOffset(offset);
 1023|  82.0k|    }
 1024|       |
 1025|  82.0k|    return error_message.empty();
 1026|  82.0k|}
QPDFTokenizer.cc:_ZL12is_delimiterc:
   25|  5.63M|{
   26|  5.63M|    return (
   27|  5.63M|        ch == ' ' || ch == '\n' || ch == '/' || ch == '(' || ch == ')' || ch == '{' || ch == '}' ||
  ------------------
  |  Branch (27:9): [True: 27.2k, False: 5.61M]
  |  Branch (27:22): [True: 31.6k, False: 5.57M]
  |  Branch (27:36): [True: 18, False: 5.57M]
  |  Branch (27:49): [True: 9, False: 5.57M]
  |  Branch (27:62): [True: 10, False: 5.57M]
  |  Branch (27:75): [True: 12, False: 5.57M]
  |  Branch (27:88): [True: 7, False: 5.57M]
  ------------------
   28|  5.57M|        ch == '<' || ch == '>' || ch == '[' || ch == ']' || ch == '%' || ch == '\t' || ch == '\r' ||
  ------------------
  |  Branch (28:9): [True: 5, False: 5.57M]
  |  Branch (28:22): [True: 6, False: 5.57M]
  |  Branch (28:35): [True: 15, False: 5.57M]
  |  Branch (28:48): [True: 8, False: 5.57M]
  |  Branch (28:61): [True: 7, False: 5.57M]
  |  Branch (28:74): [True: 196, False: 5.57M]
  |  Branch (28:88): [True: 198, False: 5.57M]
  ------------------
   29|  5.57M|        ch == '\v' || ch == '\f' || ch == 0);
  ------------------
  |  Branch (29:9): [True: 196, False: 5.57M]
  |  Branch (29:23): [True: 6.66k, False: 5.57M]
  |  Branch (29:37): [True: 3, False: 5.57M]
  ------------------
   30|  5.63M|}

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

_ZNK4qpdf10BaseHandleixERKNSt3__112basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEE:
   22|  47.2k|{
   23|  47.2k|    if (auto d = as<QPDF_Dictionary>()) {
  ------------------
  |  Branch (23:14): [True: 47.2k, False: 0]
  ------------------
   24|  47.2k|        auto it = d->items.find(key);
   25|  47.2k|        if (it != d->items.end()) {
  ------------------
  |  Branch (25:13): [True: 23.6k, False: 23.6k]
  ------------------
   26|  23.6k|            return it->second;
   27|  23.6k|        }
   28|  47.2k|    }
   29|  23.6k|    static const QPDFObjectHandle null_obj;
   30|  23.6k|    return null_obj;
   31|  47.2k|}
_ZNK4qpdf10BaseHandle8containsERKNSt3__112basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEE:
   63|  31.4k|{
   64|  31.4k|    return !(*this)[key].null();
   65|  31.4k|}
_ZN4qpdf10BaseHandle5eraseERKNSt3__112basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEE:
  117|  9.76k|{
  118|       |    // no-op if key does not exist
  119|  9.76k|    if (auto d = as<QPDF_Dictionary>()) {
  ------------------
  |  Branch (119:14): [True: 9.76k, False: 0]
  ------------------
  120|  9.76k|        return d->items.erase(key);
  121|  9.76k|    }
  122|      0|    return 0;
  123|  9.76k|}
_ZN4qpdf10BaseHandle7replaceERKNSt3__112basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEE16QPDFObjectHandle:
  140|   132k|{
  141|   132k|    if (auto d = as<QPDF_Dictionary>()) {
  ------------------
  |  Branch (141:14): [True: 132k, False: 0]
  ------------------
  142|   132k|        if (value.null() && !value.indirect()) {
  ------------------
  |  Branch (142:13): [True: 22.4k, False: 109k]
  |  Branch (142:29): [True: 16.3k, False: 6.12k]
  ------------------
  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|  16.3k|            d->items.erase(key);
  147|   116k|        } else {
  148|       |            // add or replace value
  149|   116k|            d->items[key] = value;
  150|   116k|        }
  151|   132k|        return true;
  152|   132k|    }
  153|      0|    return false;
  154|   132k|}
_ZN4qpdf14BaseDictionary7replaceERKNSt3__112basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEE16QPDFObjectHandle:
  172|   132k|{
  173|   132k|    if (!BaseHandle::replace(key, value)) {
  ------------------
  |  Branch (173:9): [True: 0, False: 132k]
  ------------------
  174|      0|        (void)dict();
  175|      0|    }
  176|   132k|}
_ZN4qpdf10DictionaryC2ERKNSt3__110shared_ptrI10QPDFObjectEE:
  184|   132k|    BaseDictionary(obj)
  185|   132k|{
  186|   132k|}
_ZNK16QPDFObjectHandle14checkOwnershipERKS_:
  196|   132k|{
  197|   132k|    auto qpdf = getOwningQPDF();
  198|   132k|    auto item_qpdf = item.getOwningQPDF();
  199|   132k|    if (qpdf && item_qpdf && qpdf != item_qpdf) {
  ------------------
  |  Branch (199:9): [True: 132k, False: 0]
  |  Branch (199:17): [True: 132k, False: 225]
  |  Branch (199:30): [True: 0, False: 132k]
  ------------------
  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|   132k|}
_ZNK16QPDFObjectHandle6hasKeyERKNSt3__112basic_stringIcNS0_11char_traitsIcEENS0_9allocatorIcEEEE:
  208|  23.6k|{
  209|  23.6k|    if (Dictionary dict = *this) {
  ------------------
  |  Branch (209:20): [True: 23.6k, False: 0]
  ------------------
  210|  23.6k|        return dict.contains(key);
  211|  23.6k|    } 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.6k|}
_ZNK16QPDFObjectHandle6getKeyERKNSt3__112basic_stringIcNS0_11char_traitsIcEENS0_9allocatorIcEEEE:
  220|  15.7k|{
  221|  15.7k|    if (auto result = get(key)) {
  ------------------
  |  Branch (221:14): [True: 15.7k, False: 0]
  ------------------
  222|  15.7k|        return result;
  223|  15.7k|    }
  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|   132k|{
  264|   132k|    if (auto dict = as_dictionary(strict)) {
  ------------------
  |  Branch (264:14): [True: 132k, False: 0]
  ------------------
  265|   132k|        checkOwnership(value);
  266|   132k|        dict.replace(key, value);
  267|   132k|        return;
  268|   132k|    }
  269|      0|    typeWarning("dictionary", "ignoring key replacement request");
  270|      0|}
_ZN16QPDFObjectHandle9removeKeyERKNSt3__112basic_stringIcNS0_11char_traitsIcEENS0_9allocatorIcEEEE:
  289|  9.76k|{
  290|  9.76k|    if (erase(key) || isDictionary()) {
  ------------------
  |  Branch (290:9): [True: 316, False: 9.44k]
  |  Branch (290:23): [True: 9.44k, False: 0]
  ------------------
  291|  9.76k|        return;
  292|  9.76k|    }
  293|      0|    typeWarning("dictionary", "ignoring key removal request");
  294|      0|}

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

_ZN4QPDF20EncryptionParameters10initializeERS_:
  732|  7.87k|{
  733|  7.87k|    if (encryption_initialized) {
  ------------------
  |  Branch (733:9): [True: 0, False: 7.87k]
  ------------------
  734|      0|        return;
  735|      0|    }
  736|  7.87k|    encryption_initialized = true;
  737|       |
  738|  7.87k|    auto& c = qpdf.m->c;
  739|  7.87k|    auto& qm = *qpdf.m;
  740|  7.87k|    auto& trailer = qm.trailer;
  741|  7.87k|    auto& file = qm.file;
  742|       |
  743|  7.87k|    auto warn_damaged_pdf = [&qpdf, c](std::string const& msg) {
  744|  7.87k|        qpdf.warn(c.damagedPDF("encryption dictionary", msg));
  745|  7.87k|    };
  746|  7.87k|    auto throw_damaged_pdf = [&qpdf](std::string const& msg) {
  747|  7.87k|        throw qpdf.m->c.damagedPDF("encryption dictionary", msg);
  748|  7.87k|    };
  749|  7.87k|    auto unsupported = [&file](std::string const& msg) -> QPDFExc {
  750|  7.87k|        return {
  751|  7.87k|            qpdf_e_unsupported,
  752|  7.87k|            file->getName(),
  753|  7.87k|            "encryption dictionary",
  754|  7.87k|            file->getLastOffset(),
  755|  7.87k|            msg};
  756|  7.87k|    };
  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.87k|    if (!trailer.contains("/Encrypt")) {
  ------------------
  |  Branch (762:9): [True: 7.87k, False: 0]
  ------------------
  763|  7.87k|        return;
  764|  7.87k|    }
  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|  53.0k|{
  311|  53.0k|    errors = true;
  312|  53.0k|    std::string object = this->cur_object;
  313|  53.0k|    if (is->getName() != pdf.getFilename()) {
  ------------------
  |  Branch (313:9): [True: 0, False: 53.0k]
  ------------------
  314|      0|        object += " from " + is->getName();
  315|      0|    }
  316|  53.0k|    pdf.warn(qpdf_e_json, object, offset, msg);
  317|  53.0k|}
_ZNK4QPDF11JSONReactor9anyErrorsEv:
  321|     60|{
  322|     60|    return errors;
  323|     60|}
_ZN4QPDF11JSONReactor14containerStartEv:
  327|  95.4k|{
  328|  95.4k|    if (next_obj) {
  ------------------
  |  Branch (328:9): [True: 59.8k, False: 35.5k]
  ------------------
  329|  59.8k|        stack.emplace_back(next_state, std::move(next_obj));
  330|  59.8k|        next_obj = QPDFObjectHandle();
  331|  59.8k|    } else {
  332|  35.5k|        stack.emplace_back(next_state);
  333|  35.5k|    }
  334|  95.4k|}
_ZN4QPDF11JSONReactor15dictionaryStartEv:
  338|  73.4k|{
  339|  73.4k|    containerStart();
  340|  73.4k|}
_ZN4QPDF11JSONReactor10arrayStartEv:
  344|  22.2k|{
  345|  22.2k|    if (stack.empty()) {
  ------------------
  |  Branch (345:9): [True: 334, False: 21.9k]
  ------------------
  346|    334|        QTC::TC("qpdf", "QPDF_json top-level array");
  347|    334|        throw std::runtime_error("QPDF JSON must be a dictionary");
  348|    334|    }
  349|  21.9k|    containerStart();
  350|  21.9k|}
_ZN4QPDF11JSONReactor12containerEndERK4JSON:
  354|  40.6k|{
  355|  40.6k|    auto from_state = stack.back().state;
  356|  40.6k|    stack.pop_back();
  357|  40.6k|    if (stack.empty()) {
  ------------------
  |  Branch (357:9): [True: 72, False: 40.6k]
  ------------------
  358|     72|        if (!this->saw_qpdf) {
  ------------------
  |  Branch (358:13): [True: 24, False: 48]
  ------------------
  359|     24|            QTC::TC("qpdf", "QPDF_json missing qpdf");
  360|     24|            error(0, "\"qpdf\" object was not seen");
  361|     48|        } else {
  362|     48|            if (!this->saw_json_version) {
  ------------------
  |  Branch (362:17): [True: 40, False: 8]
  ------------------
  363|     40|                QTC::TC("qpdf", "QPDF_json missing json version");
  364|     40|                error(0, "\"qpdf[0].jsonversion\" was not seen");
  365|     40|            }
  366|     48|            if (must_be_complete && !this->saw_pdf_version) {
  ------------------
  |  Branch (366:17): [True: 47, False: 1]
  |  Branch (366:37): [True: 38, False: 9]
  ------------------
  367|     38|                QTC::TC("qpdf", "QPDF_json missing pdf version");
  368|     38|                error(0, "\"qpdf[0].pdfversion\" was not seen");
  369|     38|            }
  370|     48|            if (!this->saw_objects) {
  ------------------
  |  Branch (370:17): [True: 8, False: 40]
  ------------------
  371|      8|                QTC::TC("qpdf", "QPDF_json missing objects");
  372|      8|                error(0, "\"qpdf[1]\" was not seen");
  373|     40|            } else {
  374|     40|                if (must_be_complete && !this->saw_trailer) {
  ------------------
  |  Branch (374:21): [True: 38, False: 2]
  |  Branch (374:41): [True: 29, False: 9]
  ------------------
  375|     29|                    QTC::TC("qpdf", "QPDF_json missing trailer");
  376|     29|                    error(0, "\"qpdf[1].trailer\" was not seen");
  377|     29|                }
  378|     40|            }
  379|     48|        }
  380|  40.6k|    } else if (from_state == st_trailer) {
  ------------------
  |  Branch (380:16): [True: 645, False: 39.9k]
  ------------------
  381|    645|        if (!saw_value) {
  ------------------
  |  Branch (381:13): [True: 277, False: 368]
  ------------------
  382|    277|            QTC::TC("qpdf", "QPDF_json trailer no value");
  383|    277|            error(value.getStart(), "\"trailer\" is missing \"value\"");
  384|    277|        }
  385|  39.9k|    } else if (from_state == st_object_top) {
  ------------------
  |  Branch (385:16): [True: 10.3k, False: 29.5k]
  ------------------
  386|  10.3k|        if (saw_value == saw_stream) {
  ------------------
  |  Branch (386:13): [True: 869, False: 9.51k]
  ------------------
  387|    869|            QTC::TC("qpdf", "QPDF_json value stream both or neither");
  388|    869|            error(value.getStart(), "object must have exactly one of \"value\" or \"stream\"");
  389|    869|        }
  390|  10.3k|        if (saw_stream) {
  ------------------
  |  Branch (390:13): [True: 4.45k, False: 5.93k]
  ------------------
  391|  4.45k|            if (!saw_dict) {
  ------------------
  |  Branch (391:17): [True: 1.57k, False: 2.87k]
  ------------------
  392|  1.57k|                QTC::TC("qpdf", "QPDF_json stream no dict");
  393|  1.57k|                error(value.getStart(), "\"stream\" is missing \"dict\"");
  394|  1.57k|            }
  395|  4.45k|            if (saw_data == saw_datafile) {
  ------------------
  |  Branch (395:17): [True: 1.07k, False: 3.37k]
  ------------------
  396|  1.07k|                if (this_stream_needs_data) {
  ------------------
  |  Branch (396:21): [True: 560, False: 517]
  ------------------
  397|    560|                    QTC::TC("qpdf", "QPDF_json data datafile both or neither");
  398|    560|                    error(
  399|    560|                        value.getStart(),
  400|    560|                        "new \"stream\" must have exactly one of \"data\" or \"datafile\"");
  401|    560|                } else if (saw_datafile) {
  ------------------
  |  Branch (401:28): [True: 163, False: 354]
  ------------------
  402|    163|                    QTC::TC("qpdf", "QPDF_json data and datafile");
  403|    163|                    error(
  404|    163|                        value.getStart(),
  405|    163|                        "existing \"stream\" may at most one of \"data\" or \"datafile\"");
  406|    354|                } else {
  407|    354|                    QTC::TC("qpdf", "QPDF_json no stream data in update mode");
  408|    354|                }
  409|  1.07k|            }
  410|  4.45k|        }
  411|  10.3k|    }
  412|  40.6k|    if (!stack.empty()) {
  ------------------
  |  Branch (412:9): [True: 40.6k, False: 77]
  ------------------
  413|  40.6k|        auto state = stack.back().state;
  414|  40.6k|        if (state == st_objects) {
  ------------------
  |  Branch (414:13): [True: 12.4k, False: 28.1k]
  ------------------
  415|  12.4k|            this->cur_object = "";
  416|  12.4k|            this->saw_dict = false;
  417|  12.4k|            this->saw_data = false;
  418|  12.4k|            this->saw_datafile = false;
  419|  12.4k|            this->saw_value = false;
  420|  12.4k|            this->saw_stream = false;
  421|  12.4k|        }
  422|  40.6k|    }
  423|  40.6k|}
_ZN4QPDF11JSONReactor13replaceObjectEO16QPDFObjectHandleRK4JSON:
  427|  19.1k|{
  428|  19.1k|    auto& tos = stack.back();
  429|  19.1k|    auto og = tos.object.getObjGen();
  430|  19.1k|    if (replacement.isIndirect() && !(replacement.isStream() && replacement.getObjGen() == og)) {
  ------------------
  |  Branch (430:9): [True: 4.63k, False: 14.4k]
  |  Branch (430:9): [True: 596, False: 18.5k]
  |  Branch (430:39): [True: 4.30k, False: 331]
  |  Branch (430:65): [True: 4.04k, False: 265]
  ------------------
  431|    596|        error(
  432|    596|            replacement.offset(), "the value of an object may not be an indirect object reference");
  433|    596|        return;
  434|    596|    }
  435|  18.5k|    pdf.replaceObject(og, replacement);
  436|  18.5k|    next_obj = pdf.getObject(og);
  437|  18.5k|    setObjectDescription(tos.object, value);
  438|  18.5k|}
_ZN4QPDF11JSONReactor14topLevelScalarEv:
  442|     60|{
  443|     60|    QTC::TC("qpdf", "QPDF_json top-level scalar");
  444|     60|    throw std::runtime_error("QPDF JSON must be a dictionary");
  445|     60|}
_ZN4QPDF11JSONReactor24setNextStateIfDictionaryERKNSt3__112basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEERK4JSONNS0_7state_eE:
  449|  42.5k|{
  450|       |    // Use this method when the next state is for processing a nested dictionary.
  451|  42.5k|    if (value.isDictionary()) {
  ------------------
  |  Branch (451:9): [True: 35.3k, False: 7.12k]
  ------------------
  452|  35.3k|        this->next_state = next;
  453|  35.3k|        return true;
  454|  35.3k|    }
  455|  7.12k|    error(value.getStart(), "\"" + key + "\" must be a dictionary");
  456|  7.12k|    return false;
  457|  42.5k|}
_ZN4QPDF11JSONReactor14dictionaryItemERKNSt3__112basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEERK4JSON:
  461|   224k|{
  462|   224k|    if (stack.empty()) {
  ------------------
  |  Branch (462:9): [True: 0, False: 224k]
  ------------------
  463|      0|        throw std::logic_error("stack is empty in dictionaryItem");
  464|      0|    }
  465|   224k|    next_state = st_ignore;
  466|   224k|    auto state = stack.back().state;
  467|   224k|    if (state == st_ignore) {
  ------------------
  |  Branch (467:9): [True: 4.82k, False: 220k]
  ------------------
  468|  4.82k|        return true; // ignore
  469|  4.82k|    }
  470|   220k|    if (state == st_top) {
  ------------------
  |  Branch (470:9): [True: 10.1k, False: 209k]
  ------------------
  471|  10.1k|        if (key == "qpdf") {
  ------------------
  |  Branch (471:13): [True: 6.84k, False: 3.34k]
  ------------------
  472|  6.84k|            saw_qpdf = true;
  473|  6.84k|            if (!value.isArray()) {
  ------------------
  |  Branch (473:17): [True: 977, False: 5.86k]
  ------------------
  474|    977|                error(value.getStart(), "\"qpdf\" must be an array");
  475|  5.86k|            } else {
  476|  5.86k|                next_state = st_qpdf;
  477|  5.86k|            }
  478|  6.84k|            return true;
  479|  6.84k|        }
  480|  3.34k|        return true; // Ignore all other fields.
  481|  10.1k|    }
  482|       |
  483|   209k|    if (state == st_qpdf_meta) {
  ------------------
  |  Branch (483:9): [True: 7.72k, False: 202k]
  ------------------
  484|  7.72k|        if (key == "pdfversion") {
  ------------------
  |  Branch (484:13): [True: 2.39k, False: 5.32k]
  ------------------
  485|  2.39k|            saw_pdf_version = true;
  486|  2.39k|            std::string v;
  487|  2.39k|            if (value.getString(v)) {
  ------------------
  |  Branch (487:17): [True: 1.58k, False: 811]
  ------------------
  488|  1.58k|                std::string version;
  489|  1.58k|                char const* p = v.c_str();
  490|  1.58k|                if (objects.validatePDFVersion(p, version) && *p == '\0') {
  ------------------
  |  Branch (490:21): [True: 679, False: 906]
  |  Branch (490:63): [True: 461, False: 218]
  ------------------
  491|    461|                    pdf.m->pdf_version = version;
  492|    461|                    return true;
  493|    461|                }
  494|  1.58k|            }
  495|  1.93k|            error(value.getStart(), "invalid PDF version (must be \"x.y\")");
  496|  1.93k|            return true;
  497|  2.39k|        }
  498|  5.32k|        if (key == "jsonversion") {
  ------------------
  |  Branch (498:13): [True: 1.76k, False: 3.56k]
  ------------------
  499|  1.76k|            saw_json_version = true;
  500|  1.76k|            std::string v;
  501|  1.76k|            if (value.getNumber(v)) {
  ------------------
  |  Branch (501:17): [True: 1.54k, False: 218]
  ------------------
  502|  1.54k|                std::string version;
  503|  1.54k|                if (QUtil::string_to_int(v.c_str()) == 2) {
  ------------------
  |  Branch (503:21): [True: 253, False: 1.29k]
  ------------------
  504|    253|                    return true;
  505|    253|                }
  506|  1.54k|            }
  507|  1.50k|            error(value.getStart(), "invalid JSON version (must be numeric value 2)");
  508|  1.50k|            return true;
  509|  1.76k|        }
  510|  3.56k|        if (key == "pushedinheritedpageresources") {
  ------------------
  |  Branch (510:13): [True: 565, False: 3.00k]
  ------------------
  511|    565|            bool v;
  512|    565|            if (value.getBool(v)) {
  ------------------
  |  Branch (512:17): [True: 244, False: 321]
  ------------------
  513|    244|                if (!must_be_complete && v) {
  ------------------
  |  Branch (513:21): [True: 0, False: 244]
  |  Branch (513:42): [True: 0, False: 0]
  ------------------
  514|      0|                    pdf.pushInheritedAttributesToPage();
  515|      0|                }
  516|    244|                return true;
  517|    244|            }
  518|    321|            error(value.getStart(), "pushedinheritedpageresources must be a boolean");
  519|    321|            return true;
  520|    565|        }
  521|  3.00k|        if (key == "calledgetallpages") {
  ------------------
  |  Branch (521:13): [True: 469, False: 2.53k]
  ------------------
  522|    469|            bool v;
  523|    469|            if (value.getBool(v)) {
  ------------------
  |  Branch (523:17): [True: 258, False: 211]
  ------------------
  524|    258|                if (!must_be_complete && v) {
  ------------------
  |  Branch (524:21): [True: 0, False: 258]
  |  Branch (524:42): [True: 0, False: 0]
  ------------------
  525|      0|                    (void)pdf.doc().pages().all();
  526|      0|                }
  527|    258|                return true;
  528|    258|            }
  529|    211|            error(value.getStart(), "calledgetallpages must be a boolean");
  530|    211|            return true;
  531|    469|        }
  532|       |        // ignore unknown keys for forward compatibility and to skip keys we don't care about
  533|       |        // like "maxobjectid".
  534|  2.53k|        return true;
  535|  3.00k|    }
  536|       |
  537|   202k|    if (state == st_objects) {
  ------------------
  |  Branch (537:9): [True: 23.3k, False: 178k]
  ------------------
  538|  23.3k|        if (key == "trailer") {
  ------------------
  |  Branch (538:13): [True: 2.66k, False: 20.6k]
  ------------------
  539|  2.66k|            saw_trailer = true;
  540|  2.66k|            cur_object = "trailer";
  541|  2.66k|            setNextStateIfDictionary(key, value, st_trailer);
  542|  2.66k|            return true;
  543|  2.66k|        }
  544|       |
  545|  20.6k|        int obj = 0;
  546|  20.6k|        int gen = 0;
  547|  20.6k|        if (is_obj_key(key, obj, gen)) {
  ------------------
  |  Branch (547:13): [True: 14.8k, False: 5.79k]
  ------------------
  548|  14.8k|            cur_object = key;
  549|  14.8k|            if (setNextStateIfDictionary(key, value, st_object_top)) {
  ------------------
  |  Branch (549:17): [True: 13.3k, False: 1.54k]
  ------------------
  550|  13.3k|                next_obj = objects.getObjectForJSON(obj, gen);
  551|  13.3k|            }
  552|  14.8k|            return true;
  553|  14.8k|        }
  554|  5.79k|        error(value.getStart(), "object key should be \"trailer\" or \"obj:n n R\"");
  555|  5.79k|        return true;
  556|  20.6k|    }
  557|       |
  558|   178k|    if (state == st_object_top) {
  ------------------
  |  Branch (558:9): [True: 28.1k, False: 150k]
  ------------------
  559|  28.1k|        util::assertion(!stack.empty(), "QPDF_json: stack empty in st_object_top");
  560|  28.1k|        auto& tos = stack.back();
  561|  28.1k|        util::assertion(!!tos.object, "current object uninitialized in st_object_top");
  562|  28.1k|        if (key == "value") {
  ------------------
  |  Branch (562:13): [True: 15.6k, False: 12.4k]
  ------------------
  563|       |            // Don't use setNextStateIfDictionary since this can have any type.
  564|  15.6k|            saw_value = true;
  565|  15.6k|            replaceObject(makeObject(value), value);
  566|  15.6k|            next_state = st_object;
  567|  15.6k|            return true;
  568|  15.6k|        }
  569|  12.4k|        if (key == "stream") {
  ------------------
  |  Branch (569:13): [True: 8.24k, False: 4.21k]
  ------------------
  570|  8.24k|            saw_stream = true;
  571|  8.24k|            if (setNextStateIfDictionary(key, value, st_stream)) {
  ------------------
  |  Branch (571:17): [True: 7.91k, False: 337]
  ------------------
  572|  7.91k|                this_stream_needs_data = false;
  573|  7.91k|                if (tos.object.isStream()) {
  ------------------
  |  Branch (573:21): [True: 4.07k, False: 3.83k]
  ------------------
  574|  4.07k|                    QTC::TC("qpdf", "QPDF_json updating existing stream");
  575|  4.07k|                } else {
  576|  3.83k|                    this_stream_needs_data = true;
  577|  3.83k|                    replaceObject(
  578|  3.83k|                        qpdf::Stream(
  579|  3.83k|                            pdf, tos.object.getObjGen(), QPDFObjectHandle::newDictionary(), 0, 0),
  580|  3.83k|                        value);
  581|  3.83k|                }
  582|  7.91k|                next_obj = tos.object;
  583|  7.91k|                return true;
  584|  7.91k|            }
  585|    337|            return true; // Error message already given above
  586|  8.24k|        }
  587|  4.21k|        return true; // Ignore unknown keys for forward compatibility
  588|  12.4k|    }
  589|       |
  590|   150k|    if (state == st_trailer) {
  ------------------
  |  Branch (590:9): [True: 4.10k, False: 146k]
  ------------------
  591|  4.10k|        if (key == "value") {
  ------------------
  |  Branch (591:13): [True: 2.29k, False: 1.81k]
  ------------------
  592|  2.29k|            saw_value = true;
  593|       |            // The trailer must be a dictionary, so we can use setNextStateIfDictionary.
  594|  2.29k|            if (setNextStateIfDictionary("trailer.value", value, st_object)) {
  ------------------
  |  Branch (594:17): [True: 1.86k, False: 426]
  ------------------
  595|  1.86k|                pdf.m->trailer = makeObject(value);
  596|  1.86k|                setObjectDescription(pdf.m->trailer, value);
  597|  1.86k|            }
  598|  2.29k|            return true;
  599|  2.29k|        }
  600|  1.81k|        if (key == "stream") {
  ------------------
  |  Branch (600:13): [True: 394, False: 1.42k]
  ------------------
  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.42k|        return true; // Ignore unknown keys for forward compatibility
  606|  1.81k|    }
  607|       |
  608|   146k|    if (state == st_stream) {
  ------------------
  |  Branch (608:9): [True: 14.2k, False: 132k]
  ------------------
  609|  14.2k|        util::assertion(!stack.empty(), "stack empty in st_stream");
  610|  14.2k|        auto& tos = stack.back();
  611|  14.2k|        util::assertion(tos.object.isStream(), "current object is not stream in st_stream");
  612|  14.2k|        if (key == "dict") {
  ------------------
  |  Branch (612:13): [True: 3.63k, False: 10.5k]
  ------------------
  613|  3.63k|            saw_dict = true;
  614|  3.63k|            if (setNextStateIfDictionary("stream.dict", value, st_object)) {
  ------------------
  |  Branch (614:17): [True: 3.08k, False: 548]
  ------------------
  615|  3.08k|                tos.object.replaceDict(makeObject(value));
  616|  3.08k|                return true;
  617|  3.08k|            }
  618|    548|            return true; // An error had already been given by setNextStateIfDictionary
  619|  3.63k|        }
  620|  10.5k|        if (key == "data") {
  ------------------
  |  Branch (620:13): [True: 8.09k, False: 2.47k]
  ------------------
  621|  8.09k|            saw_data = true;
  622|  8.09k|            std::string v;
  623|  8.09k|            if (!value.getString(v)) {
  ------------------
  |  Branch (623:17): [True: 2.23k, False: 5.86k]
  ------------------
  624|  2.23k|                error(value.getStart(), "\"stream.data\" must be a string");
  625|  2.23k|                tos.object.replaceStreamData("", {}, {});
  626|  2.23k|                return true;
  627|  2.23k|            }
  628|       |            // The range includes the quotes.
  629|  5.86k|            auto start = value.getStart() + 1;
  630|  5.86k|            auto end = value.getEnd() - 1;
  631|  5.86k|            util::assertion(end >= start, "QPDF_json: JSON string length < 0");
  632|  5.86k|            tos.object.replaceStreamData(provide_data(is, start, end), {}, {});
  633|  5.86k|            return true;
  634|  8.09k|        }
  635|  2.47k|        if (key == "datafile") {
  ------------------
  |  Branch (635:13): [True: 1.66k, False: 809]
  ------------------
  636|  1.66k|            saw_datafile = true;
  637|  1.66k|            std::string filename;
  638|  1.66k|            if (!value.getString(filename)) {
  ------------------
  |  Branch (638:17): [True: 345, False: 1.32k]
  ------------------
  639|    345|                error(
  640|    345|                    value.getStart(),
  641|    345|                    "\"stream.datafile\" must be a string containing a file name");
  642|    345|                tos.object.replaceStreamData("", {}, {});
  643|    345|                return true;
  644|    345|            }
  645|  1.32k|            tos.object.replaceStreamData(QUtil::file_provider(filename), {}, {});
  646|  1.32k|            return true;
  647|  1.66k|        }
  648|    809|        return true; // Ignore unknown keys for forward compatibility.
  649|  2.47k|    }
  650|       |
  651|   132k|    util::assertion(state == st_object, "QPDF_json: unknown state " + std::to_string(state));
  652|   132k|    util::assertion(!stack.empty(), "stack empty in st_object");
  653|   132k|    auto& tos = stack.back();
  654|   132k|    auto dict = tos.object;
  655|   132k|    if (dict.isStream()) {
  ------------------
  |  Branch (655:9): [True: 0, False: 132k]
  ------------------
  656|      0|        dict = dict.getDict();
  657|      0|    }
  658|   132k|    util::assertion(
  659|   132k|        dict.isDictionary(),
  660|   132k|        "current object is not stream or dictionary in st_object dictionary item");
  661|   132k|    dict.replaceKey(
  662|   132k|        is_pdf_name(key) ? QPDFObjectHandle::parse(key.substr(2)).getName() : key,
  ------------------
  |  Branch (662:9): [True: 4.85k, False: 127k]
  ------------------
  663|   132k|        makeObject(value));
  664|   132k|    return true;
  665|   146k|}
_ZN4QPDF11JSONReactor9arrayItemERK4JSON:
  669|  1.96M|{
  670|  1.96M|    if (stack.empty()) {
  ------------------
  |  Branch (670:9): [True: 0, False: 1.96M]
  ------------------
  671|      0|        throw std::logic_error("stack is empty in arrayItem");
  672|      0|    }
  673|  1.96M|    next_state = st_ignore;
  674|  1.96M|    auto state = stack.back().state;
  675|  1.96M|    if (state == st_qpdf) {
  ------------------
  |  Branch (675:9): [True: 15.3k, False: 1.94M]
  ------------------
  676|  15.3k|        if (!this->saw_qpdf_meta) {
  ------------------
  |  Branch (676:13): [True: 5.66k, False: 9.70k]
  ------------------
  677|  5.66k|            this->saw_qpdf_meta = true;
  678|  5.66k|            setNextStateIfDictionary("qpdf[0]", value, st_qpdf_meta);
  679|  9.70k|        } else if (!this->saw_objects) {
  ------------------
  |  Branch (679:20): [True: 5.12k, False: 4.58k]
  ------------------
  680|  5.12k|            this->saw_objects = true;
  681|  5.12k|            setNextStateIfDictionary("qpdf[1]", value, st_objects);
  682|  5.12k|        } else {
  683|  4.58k|            QTC::TC("qpdf", "QPDF_json more than two qpdf elements");
  684|  4.58k|            error(value.getStart(), "\"qpdf\" must have two elements");
  685|  4.58k|        }
  686|  1.94M|    } else if (state == st_object) {
  ------------------
  |  Branch (686:16): [True: 1.81M, False: 137k]
  ------------------
  687|  1.81M|        stack.back().object.appendItem(makeObject(value));
  688|  1.81M|    }
  689|  1.96M|    return true;
  690|  1.96M|}
_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: 11.6k, False: 1.21M]
  ------------------
  697|  11.6k|        descr = std::make_shared<QPDFObject::Description>(
  698|  11.6k|            QPDFObject::JSON_Descr(j_descr.input, cur_object));
  699|  11.6k|    }
  700|       |
  701|  1.23M|    oh.obj_sp()->setDescription(&pdf, descr, value.getStart());
  702|  1.23M|}
_ZN4QPDF11JSONReactor10makeObjectERK4JSON:
  706|  1.96M|{
  707|  1.96M|    QPDFObjectHandle result;
  708|  1.96M|    std::string str_v;
  709|  1.96M|    bool bool_v = false;
  710|  1.96M|    if (value.isDictionary()) {
  ------------------
  |  Branch (710:9): [True: 26.2k, False: 1.93M]
  ------------------
  711|  26.2k|        result = QPDFObjectHandle::newDictionary();
  712|  26.2k|        next_obj = result;
  713|  26.2k|        next_state = st_object;
  714|  1.93M|    } else if (value.isArray()) {
  ------------------
  |  Branch (714:16): [True: 12.1k, False: 1.92M]
  ------------------
  715|  12.1k|        result = QPDFObjectHandle::newArray();
  716|  12.1k|        next_obj = result;
  717|  12.1k|        next_state = st_object;
  718|  1.92M|    } else if (value.isNull()) {
  ------------------
  |  Branch (718:16): [True: 4.68k, False: 1.92M]
  ------------------
  719|  4.68k|        result = QPDFObjectHandle::newNull();
  720|  1.92M|    } else if (value.getBool(bool_v)) {
  ------------------
  |  Branch (720:16): [True: 6.85k, False: 1.91M]
  ------------------
  721|  6.85k|        result = QPDFObjectHandle::newBool(bool_v);
  722|  1.91M|    } else if (value.getNumber(str_v)) {
  ------------------
  |  Branch (722:16): [True: 1.11M, False: 797k]
  ------------------
  723|  1.11M|        if (QUtil::is_long_long(str_v.c_str())) {
  ------------------
  |  Branch (723:13): [True: 1.10M, False: 6.30k]
  ------------------
  724|  1.10M|            result = QPDFObjectHandle::newInteger(QUtil::string_to_ll(str_v.c_str()));
  725|  1.10M|        } else {
  726|       |            // JSON allows scientific notation, but PDF does not.
  727|  6.30k|            if (str_v.find('e') != std::string::npos || str_v.find('E') != std::string::npos) {
  ------------------
  |  Branch (727:17): [True: 780, False: 5.52k]
  |  Branch (727:57): [True: 3.43k, False: 2.08k]
  ------------------
  728|  4.21k|                try {
  729|  4.21k|                    auto v = std::stod(str_v);
  730|  4.21k|                    str_v = QUtil::double_to_string(v);
  731|  4.21k|                } catch (std::exception&) {
  732|       |                    // Keep it as it was
  733|    322|                }
  734|  4.21k|            }
  735|  6.30k|            result = QPDFObjectHandle::newReal(str_v);
  736|  6.30k|        }
  737|  1.11M|    } else if (value.getString(str_v)) {
  ------------------
  |  Branch (737:16): [True: 797k, False: 0]
  ------------------
  738|   797k|        int obj = 0;
  739|   797k|        int gen = 0;
  740|   797k|        std::string str;
  741|   797k|        if (is_indirect_object(str_v, obj, gen)) {
  ------------------
  |  Branch (741:13): [True: 746k, False: 51.0k]
  ------------------
  742|   746k|            result = objects.getObjectForJSON(obj, gen);
  743|   746k|        } else if (is_unicode_string(str_v, str)) {
  ------------------
  |  Branch (743:20): [True: 5.51k, False: 45.5k]
  ------------------
  744|  5.51k|            result = QPDFObjectHandle::newUnicodeString(str);
  745|  45.5k|        } else if (is_binary_string(str_v, str)) {
  ------------------
  |  Branch (745:20): [True: 1.22k, False: 44.3k]
  ------------------
  746|  1.22k|            result = QPDFObjectHandle::newString(QUtil::hex_decode(str));
  747|  44.3k|        } else if (is_name(str_v)) {
  ------------------
  |  Branch (747:20): [True: 14.4k, False: 29.8k]
  ------------------
  748|  14.4k|            result = QPDFObjectHandle::newName(str_v);
  749|  29.8k|        } else if (is_pdf_name(str_v)) {
  ------------------
  |  Branch (749:20): [True: 6.34k, False: 23.5k]
  ------------------
  750|  6.34k|            result = QPDFObjectHandle::parse(str_v.substr(2));
  751|  23.5k|        } else {
  752|  23.5k|            QTC::TC("qpdf", "QPDF_json unrecognized string value");
  753|  23.5k|            error(value.getStart(), "unrecognized string value");
  754|  23.5k|            result = QPDFObjectHandle::newNull();
  755|  23.5k|        }
  756|   797k|    }
  757|  1.96M|    if (!result) {
  ------------------
  |  Branch (757:9): [True: 0, False: 1.96M]
  ------------------
  758|      0|        throw std::logic_error("JSONReactor::makeObject didn't initialize the object");
  759|      0|    }
  760|       |
  761|  1.96M|    if (!result.hasObjectDescription()) {
  ------------------
  |  Branch (761:9): [True: 1.21M, False: 752k]
  ------------------
  762|  1.21M|        setObjectDescription(result, value);
  763|  1.21M|    }
  764|  1.96M|    return result;
  765|  1.96M|}
_ZN4QPDF14createFromJSONENSt3__110shared_ptrI11InputSourceEE:
  775|  7.87k|{
  776|  7.87k|    auto mw = m->cf.max_warnings();
  777|  7.87k|    (void)m->cf.max_warnings(0);
  778|  7.87k|    processMemoryFile(is->getName().c_str(), JSON_PDF, strlen(JSON_PDF));
  779|  7.87k|    (void)m->cf.max_warnings(mw);
  780|  7.87k|    importJSON(is, true);
  781|  7.87k|    (void)m->cf.max_warnings(0);
  782|  7.87k|}
_ZN4QPDF10importJSONENSt3__110shared_ptrI11InputSourceEEb:
  798|  7.87k|{
  799|  7.87k|    JSONReactor reactor(*this, is, must_be_complete);
  800|  7.87k|    try {
  801|  7.87k|        JSON::parse(*is, &reactor);
  802|  7.87k|    } catch (std::runtime_error& e) {
  803|  7.81k|        throw std::runtime_error(is->getName() + ": " + e.what());
  804|  7.81k|    }
  805|     60|    if (reactor.anyErrors()) {
  ------------------
  |  Branch (805:9): [True: 53, False: 7]
  ------------------
  806|     53|        throw std::runtime_error(is->getName() + ": errors found in JSON");
  807|     53|    }
  808|     60|}
QPDF_json.cc:_ZL18is_indirect_objectRKNSt3__112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEERiS8_:
   71|   814k|{
   72|   814k|    char const* p = v.c_str();
   73|   814k|    std::string o_str;
   74|   814k|    std::string g_str;
   75|   814k|    if (!util::is_digit(*p)) {
  ------------------
  |  Branch (75:9): [True: 45.7k, False: 768k]
  ------------------
   76|  45.7k|        return false;
   77|  45.7k|    }
   78|  1.67M|    while (util::is_digit(*p)) {
  ------------------
  |  Branch (78:12): [True: 909k, False: 768k]
  ------------------
   79|   909k|        o_str.append(1, *p++);
   80|   909k|    }
   81|   768k|    if (*p != ' ') {
  ------------------
  |  Branch (81:9): [True: 1.64k, False: 767k]
  ------------------
   82|  1.64k|        return false;
   83|  1.64k|    }
   84|  4.22M|    while (*p == ' ') {
  ------------------
  |  Branch (84:12): [True: 3.45M, False: 767k]
  ------------------
   85|  3.45M|        ++p;
   86|  3.45M|    }
   87|   767k|    if (!util::is_digit(*p)) {
  ------------------
  |  Branch (87:9): [True: 1.70k, False: 765k]
  ------------------
   88|  1.70k|        return false;
   89|  1.70k|    }
   90|  4.69M|    while (util::is_digit(*p)) {
  ------------------
  |  Branch (90:12): [True: 3.92M, False: 765k]
  ------------------
   91|  3.92M|        g_str.append(1, *p++);
   92|  3.92M|    }
   93|   765k|    if (*p != ' ') {
  ------------------
  |  Branch (93:9): [True: 935, False: 764k]
  ------------------
   94|    935|        return false;
   95|    935|    }
   96|  9.55M|    while (*p == ' ') {
  ------------------
  |  Branch (96:12): [True: 8.78M, False: 764k]
  ------------------
   97|  8.78M|        ++p;
   98|  8.78M|    }
   99|   764k|    if (*p++ != 'R') {
  ------------------
  |  Branch (99:9): [True: 2.03k, False: 762k]
  ------------------
  100|  2.03k|        return false;
  101|  2.03k|    }
  102|   762k|    if (*p) {
  ------------------
  |  Branch (102:9): [True: 789, False: 761k]
  ------------------
  103|    789|        return false;
  104|    789|    }
  105|   761k|    obj = QUtil::string_to_int(o_str.c_str());
  106|   761k|    gen = QUtil::string_to_int(g_str.c_str());
  107|   761k|    return obj > 0;
  108|   762k|}
QPDF_json.cc:_ZL10is_obj_keyRKNSt3__112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEERiS8_:
  112|  20.6k|{
  113|  20.6k|    if (v.substr(0, 4) != "obj:") {
  ------------------
  |  Branch (113:9): [True: 3.71k, False: 16.9k]
  ------------------
  114|  3.71k|        return false;
  115|  3.71k|    }
  116|  16.9k|    return is_indirect_object(v.substr(4), obj, gen);
  117|  20.6k|}
QPDF_json.cc:_ZL17is_unicode_stringRKNSt3__112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEERS5_:
  121|  51.0k|{
  122|  51.0k|    if (v.substr(0, 2) == "u:") {
  ------------------
  |  Branch (122:9): [True: 5.51k, False: 45.5k]
  ------------------
  123|  5.51k|        str = v.substr(2);
  124|  5.51k|        return true;
  125|  5.51k|    }
  126|  45.5k|    return false;
  127|  51.0k|}
QPDF_json.cc:_ZL16is_binary_stringRKNSt3__112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEERS5_:
  131|  45.5k|{
  132|  45.5k|    if (v.substr(0, 2) == "b:") {
  ------------------
  |  Branch (132:9): [True: 2.54k, False: 42.9k]
  ------------------
  133|  2.54k|        str = v.substr(2);
  134|  2.54k|        int count = 0;
  135|  26.2k|        for (char c: str) {
  ------------------
  |  Branch (135:20): [True: 26.2k, False: 1.33k]
  ------------------
  136|  26.2k|            if (!util::is_hex_digit(c)) {
  ------------------
  |  Branch (136:17): [True: 1.20k, False: 25.0k]
  ------------------
  137|  1.20k|                return false;
  138|  1.20k|            }
  139|  25.0k|            ++count;
  140|  25.0k|        }
  141|  1.33k|        return (count % 2 == 0);
  142|  2.54k|    }
  143|  42.9k|    return false;
  144|  45.5k|}
QPDF_json.cc:_ZL7is_nameRKNSt3__112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEE:
  148|  44.2k|{
  149|  44.2k|    return v.starts_with('/');
  150|  44.2k|}
QPDF_json.cc:_ZL11is_pdf_nameRKNSt3__112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEE:
  154|   162k|{
  155|   162k|    return v.starts_with("n:/");
  156|   162k|}
_ZN4QPDF11JSONReactor10StackFrameC2ENS0_7state_eEO16QPDFObjectHandle:
  271|  59.8k|            state(state),
  272|  59.8k|            object(object) {};
_ZN4QPDF11JSONReactor10StackFrameC2ENS0_7state_eE:
  269|  35.5k|            state(state) {};
QPDF_json.cc:_ZL12provide_dataNSt3__110shared_ptrI11InputSourceEExx:
  222|  5.86k|{
  223|  5.86k|    return [is, start, end](Pipeline* p) {
  224|  5.86k|        auto data = is->read(QIntC::to_size(end - start), start);
  225|  5.86k|        data = Pl_Base64::decode(data);
  226|  5.86k|        p->write(reinterpret_cast<const unsigned char*>(data.data()), data.size());
  227|  5.86k|        p->finish();
  228|  5.86k|    };
  229|  5.86k|}
_ZN4QPDF11JSONReactorC2ERS_NSt3__110shared_ptrI11InputSourceEEb:
  235|  7.87k|        pdf(pdf),
  236|  7.87k|        is(is),
  237|  7.87k|        must_be_complete(must_be_complete),
  238|       |        descr(
  239|  7.87k|            std::make_shared<QPDFObject::Description>(
  240|  7.87k|                QPDFObject::JSON_Descr(std::make_shared<std::string>(is->getName()), "")))
  241|  7.87k|    {
  242|  7.87k|    }
_ZN4QPDF11JSONReactorD2Ev:
  243|  7.87k|    ~JSONReactor() override = default;

_ZN4QPDF3Doc7Objects18validatePDFVersionERPKcRNSt3__112basic_stringIcNS5_11char_traitsIcEENS5_9allocatorIcEEEE:
  165|  9.45k|{
  166|  9.45k|    if (!util::is_digit(*p)) {
  ------------------
  |  Branch (166:9): [True: 245, False: 9.21k]
  ------------------
  167|    245|        return false;
  168|    245|    }
  169|  19.3k|    while (util::is_digit(*p)) {
  ------------------
  |  Branch (169:12): [True: 10.1k, False: 9.21k]
  ------------------
  170|  10.1k|        version.append(1, *p++);
  171|  10.1k|    }
  172|  9.21k|    if (!(*p == '.' && util::is_digit(*(p + 1)))) {
  ------------------
  |  Branch (172:11): [True: 8.75k, False: 454]
  |  Branch (172:24): [True: 8.55k, False: 207]
  ------------------
  173|    661|        return false;
  174|    661|    }
  175|  8.55k|    version.append(1, *p++);
  176|  21.4k|    while (util::is_digit(*p)) {
  ------------------
  |  Branch (176:12): [True: 12.9k, False: 8.55k]
  ------------------
  177|  12.9k|        version.append(1, *p++);
  178|  12.9k|    }
  179|  8.55k|    return true;
  180|  9.21k|}
_ZN4QPDF3Doc7Objects10findHeaderEv:
  184|  7.87k|{
  185|  7.87k|    qpdf_offset_t global_offset = m->file->tell();
  186|  7.87k|    std::string line = m->file->readLine(1024);
  187|  7.87k|    char const* p = line.data();
  188|  7.87k|    util::assertion(strncmp(p, "%PDF-", 5) == 0, "findHeader is not looking at %PDF-");
  189|  7.87k|    p += 5;
  190|  7.87k|    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.87k|    if (!validatePDFVersion(p, version)) {
  ------------------
  |  Branch (193:9): [True: 0, False: 7.87k]
  ------------------
  194|      0|        return false;
  195|      0|    }
  196|  7.87k|    m->pdf_version = version;
  197|  7.87k|    if (global_offset != 0) {
  ------------------
  |  Branch (197:9): [True: 0, False: 7.87k]
  ------------------
  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.87k|    return true;
  204|  7.87k|}
_ZN4QPDF3Doc7Objects13findStartxrefEv:
  208|  7.87k|{
  209|  7.87k|    if (readToken(*m->file).isWord("startxref") && readToken(*m->file).isInteger()) {
  ------------------
  |  Branch (209:9): [True: 7.87k, False: 0]
  |  Branch (209:9): [True: 7.87k, False: 0]
  |  Branch (209:52): [True: 7.87k, False: 0]
  ------------------
  210|       |        // Position in front of offset token
  211|  7.87k|        m->file->seek(m->file->getLastOffset(), SEEK_SET);
  212|  7.87k|        return true;
  213|  7.87k|    }
  214|      0|    return false;
  215|  7.87k|}
_ZN4QPDF3Doc7Objects5parseEPKc:
  219|  7.87k|{
  220|  7.87k|    if (password) {
  ------------------
  |  Branch (220:9): [True: 0, False: 7.87k]
  ------------------
  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.87k|    PatternFinder hf(*this, &Objects::findHeader);
  226|  7.87k|    if (!m->file->findFirst("%PDF-", 0, 1024, hf)) {
  ------------------
  |  Branch (226:9): [True: 0, False: 7.87k]
  ------------------
  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.87k|    m->file->seek(0, SEEK_END);
  235|  7.87k|    qpdf_offset_t end_offset = m->file->tell();
  236|  7.87k|    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.87k|    if (m->xref_table_max_id > m->xref_table_max_offset / 3) {
  ------------------
  |  Branch (239:9): [True: 7.87k, False: 0]
  ------------------
  240|  7.87k|        m->xref_table_max_id = static_cast<int>(m->xref_table_max_offset / 3);
  241|  7.87k|    }
  242|  7.87k|    qpdf_offset_t start_offset = (end_offset > 1054 ? end_offset - 1054 : 0);
  ------------------
  |  Branch (242:35): [True: 0, False: 7.87k]
  ------------------
  243|  7.87k|    PatternFinder sf(*this, &Objects::findStartxref);
  244|  7.87k|    qpdf_offset_t xref_offset = 0;
  245|  7.87k|    if (m->file->findLast("startxref", start_offset, 0, sf)) {
  ------------------
  |  Branch (245:9): [True: 7.87k, False: 0]
  ------------------
  246|  7.87k|        xref_offset = QUtil::string_to_ll(readToken(*m->file).getValue().c_str());
  247|  7.87k|    }
  248|       |
  249|  7.87k|    try {
  250|  7.87k|        if (xref_offset == 0) {
  ------------------
  |  Branch (250:13): [True: 0, False: 7.87k]
  ------------------
  251|      0|            throw damagedPDF("", -1, "can't find startxref");
  252|      0|        }
  253|  7.87k|        try {
  254|  7.87k|            read_xref(xref_offset);
  255|  7.87k|        } 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.87k|    } 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.87k|    m->encp->initialize(qpdf);
  279|  7.87k|    m->parsed = true;
  280|  7.87k|    if (!m->xref_table.empty() && !qpdf.getRoot().getKey("/Pages").isDictionary()) {
  ------------------
  |  Branch (280:9): [True: 0, False: 7.87k]
  |  Branch (280:9): [True: 0, False: 7.87k]
  |  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.87k|    if (m->cf.max_warnings()) {
  ------------------
  |  Branch (284:9): [True: 0, False: 7.87k]
  ------------------
  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.87k|}
_ZN4QPDF3Doc7Objects7inParseEb:
  294|  15.7k|{
  295|  15.7k|    util::internal_error_if(
  296|  15.7k|        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.7k|    );
  300|  15.7k|    m->in_parse = v;
  301|  15.7k|}
_ZN4QPDF3Doc7Objects10setTrailerE16QPDFObjectHandle:
  305|  7.87k|{
  306|  7.87k|    if (m->trailer) {
  ------------------
  |  Branch (306:9): [True: 0, False: 7.87k]
  ------------------
  307|      0|        return;
  308|      0|    }
  309|  7.87k|    m->trailer = obj;
  310|  7.87k|}
_ZN4QPDF3Doc7Objects9read_xrefExb:
  521|  7.87k|{
  522|  7.87k|    std::map<int, int> free_table;
  523|  7.87k|    std::set<qpdf_offset_t> visited;
  524|  15.7k|    while (xref_offset) {
  ------------------
  |  Branch (524:12): [True: 7.87k, False: 7.87k]
  ------------------
  525|  7.87k|        visited.insert(xref_offset);
  526|  7.87k|        char buf[7];
  527|  7.87k|        memset(buf, 0, sizeof(buf));
  528|  7.87k|        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.87k|        bool done = false;
  534|  7.87k|        bool skipped_space = false;
  535|  15.7k|        while (!done) {
  ------------------
  |  Branch (535:16): [True: 7.87k, False: 7.87k]
  ------------------
  536|  7.87k|            char ch;
  537|  7.87k|            if (1 == m->file->read(&ch, 1)) {
  ------------------
  |  Branch (537:17): [True: 7.87k, False: 0]
  ------------------
  538|  7.87k|                if (util::is_space(ch)) {
  ------------------
  |  Branch (538:21): [True: 0, False: 7.87k]
  ------------------
  539|      0|                    skipped_space = true;
  540|  7.87k|                } else {
  541|  7.87k|                    m->file->unreadCh(ch);
  542|  7.87k|                    done = true;
  543|  7.87k|                }
  544|  7.87k|            } 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.87k|        }
  549|       |
  550|  7.87k|        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.87k|        if ((strncmp(buf, "xref", 4) == 0) && util::is_space(buf[4])) {
  ------------------
  |  Branch (553:13): [True: 7.87k, False: 0]
  |  Branch (553:47): [True: 7.87k, False: 0]
  ------------------
  554|  7.87k|            if (skipped_space) {
  ------------------
  |  Branch (554:17): [True: 0, False: 7.87k]
  ------------------
  555|      0|                warn(damagedPDF("", -1, "extraneous whitespace seen before xref"));
  556|      0|            }
  557|  7.87k|            QTC::TC(
  558|  7.87k|                "qpdf",
  559|  7.87k|                "QPDF xref space",
  560|  7.87k|                ((buf[4] == '\n')       ? 0
  ------------------
  |  Branch (560:18): [True: 7.87k, False: 0]
  ------------------
  561|  7.87k|                     : (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.87k|            int skip = 4;
  565|       |            // buf is null-terminated, and util::is_space('\0') is false, so this won't overrun.
  566|  15.7k|            while (util::is_space(buf[skip])) {
  ------------------
  |  Branch (566:20): [True: 7.87k, False: 7.87k]
  ------------------
  567|  7.87k|                ++skip;
  568|  7.87k|            }
  569|  7.87k|            xref_offset = read_xrefTable(xref_offset + skip);
  570|  7.87k|        } else {
  571|      0|            xref_offset = read_xrefStream(xref_offset, in_stream_recovery);
  572|      0|        }
  573|  7.87k|        if (visited.contains(xref_offset)) {
  ------------------
  |  Branch (573:13): [True: 0, False: 7.87k]
  ------------------
  574|      0|            throw damagedPDF("", -1, "loop detected following xref tables");
  575|      0|        }
  576|  7.87k|    }
  577|       |
  578|  7.87k|    if (!m->trailer) {
  ------------------
  |  Branch (578:9): [True: 0, False: 7.87k]
  ------------------
  579|      0|        throw damagedPDF("", -1, "unable to find trailer while reading xref");
  580|      0|    }
  581|  7.87k|    int size = m->trailer.getKey("/Size").getIntValueAsInt();
  582|  7.87k|    int max_obj = 0;
  583|  7.87k|    if (!m->xref_table.empty()) {
  ------------------
  |  Branch (583:9): [True: 0, False: 7.87k]
  ------------------
  584|      0|        max_obj = m->xref_table.rbegin()->first.getObj();
  585|      0|    }
  586|  7.87k|    if (!m->deleted_objects.empty()) {
  ------------------
  |  Branch (586:9): [True: 7.87k, False: 0]
  ------------------
  587|  7.87k|        max_obj = std::max(max_obj, *(m->deleted_objects.rbegin()));
  588|  7.87k|    }
  589|  7.87k|    if (size < 1 || (size - 1) != max_obj) {
  ------------------
  |  Branch (589:9): [True: 0, False: 7.87k]
  |  Branch (589:21): [True: 0, False: 7.87k]
  ------------------
  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.87k|    m->deleted_objects.clear();
  608|       |
  609|       |    // Make sure we keep only the highest generation for any object.
  610|  7.87k|    QPDFObjGen last_og{-1, 0};
  611|  7.87k|    for (auto const& item: m->xref_table) {
  ------------------
  |  Branch (611:26): [True: 0, False: 7.87k]
  ------------------
  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.87k|}
_ZN4QPDF3Doc7Objects15parse_xrefFirstERKNSt3__112basic_stringIcNS2_11char_traitsIcEENS2_9allocatorIcEEEERiSB_SB_:
  622|  7.87k|{
  623|       |    // is_space and is_digit both return false on '\0', so this will not overrun the null-terminated
  624|       |    // buffer.
  625|  7.87k|    char const* p = line.c_str();
  626|  7.87k|    char const* start = line.c_str();
  627|       |
  628|       |    // Skip zero or more spaces
  629|  7.87k|    while (util::is_space(*p)) {
  ------------------
  |  Branch (629:12): [True: 0, False: 7.87k]
  ------------------
  630|      0|        ++p;
  631|      0|    }
  632|       |    // Require digit
  633|  7.87k|    if (!util::is_digit(*p)) {
  ------------------
  |  Branch (633:9): [True: 0, False: 7.87k]
  ------------------
  634|      0|        return false;
  635|      0|    }
  636|       |    // Gather digits
  637|  7.87k|    std::string obj_str;
  638|  15.7k|    while (util::is_digit(*p)) {
  ------------------
  |  Branch (638:12): [True: 7.87k, False: 7.87k]
  ------------------
  639|  7.87k|        obj_str.append(1, *p++);
  640|  7.87k|    }
  641|       |    // Require space
  642|  7.87k|    if (!util::is_space(*p)) {
  ------------------
  |  Branch (642:9): [True: 0, False: 7.87k]
  ------------------
  643|      0|        return false;
  644|      0|    }
  645|       |    // Skip spaces
  646|  15.7k|    while (util::is_space(*p)) {
  ------------------
  |  Branch (646:12): [True: 7.87k, False: 7.87k]
  ------------------
  647|  7.87k|        ++p;
  648|  7.87k|    }
  649|       |    // Require digit
  650|  7.87k|    if (!util::is_digit(*p)) {
  ------------------
  |  Branch (650:9): [True: 0, False: 7.87k]
  ------------------
  651|      0|        return false;
  652|      0|    }
  653|       |    // Gather digits
  654|  7.87k|    std::string num_str;
  655|  15.7k|    while (util::is_digit(*p)) {
  ------------------
  |  Branch (655:12): [True: 7.87k, False: 7.87k]
  ------------------
  656|  7.87k|        num_str.append(1, *p++);
  657|  7.87k|    }
  658|       |    // Skip any space including line terminators
  659|  15.7k|    while (util::is_space(*p)) {
  ------------------
  |  Branch (659:12): [True: 7.87k, False: 7.87k]
  ------------------
  660|  7.87k|        ++p;
  661|  7.87k|    }
  662|  7.87k|    bytes = toI(p - start);
  663|  7.87k|    obj = QUtil::string_to_int(obj_str.c_str());
  664|  7.87k|    num = QUtil::string_to_int(num_str.c_str());
  665|  7.87k|    return true;
  666|  7.87k|}
_ZN4QPDF3Doc7Objects14read_xrefEntryERxRiRc:
  748|  7.87k|{
  749|  7.87k|    std::array<char, 21> line;
  750|  7.87k|    if (m->file->read(line.data(), 20) != 20) {
  ------------------
  |  Branch (750:9): [True: 0, False: 7.87k]
  ------------------
  751|       |        // C++20: [[unlikely]]
  752|      0|        return false;
  753|      0|    }
  754|  7.87k|    line[20] = '\0';
  755|  7.87k|    char const* p = line.data();
  756|       |
  757|  7.87k|    int f1_len = 0;
  758|  7.87k|    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|  86.5k|    while (*p == '0') {
  ------------------
  |  Branch (764:12): [True: 78.7k, False: 7.87k]
  ------------------
  765|  78.7k|        ++f1_len;
  766|  78.7k|        ++p;
  767|  78.7k|    }
  768|  7.87k|    while (util::is_digit(*p) && f1_len++ < 10) {
  ------------------
  |  Branch (768:12): [True: 0, False: 7.87k]
  |  Branch (768:34): [True: 0, False: 0]
  ------------------
  769|      0|        f1 *= 10;
  770|      0|        f1 += *p++ - '0';
  771|      0|    }
  772|       |    // Require space
  773|  7.87k|    if (!util::is_space(*p++)) {
  ------------------
  |  Branch (773:9): [True: 0, False: 7.87k]
  ------------------
  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.87k|    while (*p == '0') {
  ------------------
  |  Branch (779:12): [True: 0, False: 7.87k]
  ------------------
  780|      0|        ++f2_len;
  781|      0|        ++p;
  782|      0|    }
  783|  47.2k|    while (util::is_digit(*p) && f2_len++ < 5) {
  ------------------
  |  Branch (783:12): [True: 39.3k, False: 7.87k]
  |  Branch (783:34): [True: 39.3k, False: 0]
  ------------------
  784|  39.3k|        f2 *= 10;
  785|  39.3k|        f2 += static_cast<int>(*p++ - '0');
  786|  39.3k|    }
  787|  7.87k|    if (util::is_space(*p++) && (*p == 'f' || *p == 'n')) {
  ------------------
  |  Branch (787:9): [True: 7.87k, False: 0]
  |  Branch (787:34): [True: 7.87k, False: 0]
  |  Branch (787:47): [True: 0, False: 0]
  ------------------
  788|       |        // C++20: [[likely]]
  789|  7.87k|        type = *p;
  790|       |        // No test for valid line[19].
  791|  7.87k|        if (*(++p) && *(++p) && (*p == '\n' || *p == '\r') && f1_len == 10 && f2_len == 5) {
  ------------------
  |  Branch (791:13): [True: 7.87k, False: 0]
  |  Branch (791:23): [True: 7.87k, False: 0]
  |  Branch (791:34): [True: 7.87k, False: 0]
  |  Branch (791:48): [True: 0, False: 0]
  |  Branch (791:63): [True: 7.87k, False: 0]
  |  Branch (791:79): [True: 7.87k, False: 0]
  ------------------
  792|       |            // C++20: [[likely]]
  793|  7.87k|            return true;
  794|  7.87k|        }
  795|  7.87k|    }
  796|      0|    return read_bad_xrefEntry(f1, f2, type);
  797|  7.87k|}
_ZN4QPDF3Doc7Objects14read_xrefTableEx:
  802|  7.87k|{
  803|  7.87k|    m->file->seek(xref_offset, SEEK_SET);
  804|  7.87k|    std::string line;
  805|  7.87k|    while (true) {
  ------------------
  |  Branch (805:12): [True: 7.87k, Folded]
  ------------------
  806|  7.87k|        line.assign(50, '\0');
  807|  7.87k|        m->file->read(line.data(), line.size());
  808|  7.87k|        int obj = 0;
  809|  7.87k|        int num = 0;
  810|  7.87k|        int bytes = 0;
  811|  7.87k|        if (!parse_xrefFirst(line, obj, num, bytes)) {
  ------------------
  |  Branch (811:13): [True: 0, False: 7.87k]
  ------------------
  812|      0|            throw damagedPDF("xref table", "xref syntax invalid");
  813|      0|        }
  814|  7.87k|        m->file->seek(m->file->getLastOffset() + bytes, SEEK_SET);
  815|  15.7k|        for (qpdf_offset_t i = obj; i - num < obj; ++i) {
  ------------------
  |  Branch (815:37): [True: 7.87k, False: 7.87k]
  ------------------
  816|  7.87k|            if (i == 0) {
  ------------------
  |  Branch (816:17): [True: 7.87k, False: 0]
  ------------------
  817|       |                // This is needed by checkLinearization()
  818|  7.87k|                first_xref_item_offset_ = m->file->tell();
  819|  7.87k|            }
  820|       |            // For xref_table, these will always be small enough to be ints
  821|  7.87k|            qpdf_offset_t f1 = 0;
  822|  7.87k|            int f2 = 0;
  823|  7.87k|            char type = '\0';
  824|  7.87k|            if (!read_xrefEntry(f1, f2, type)) {
  ------------------
  |  Branch (824:17): [True: 0, False: 7.87k]
  ------------------
  825|      0|                throw damagedPDF(
  826|      0|                    "xref table", "invalid xref entry (obj=" + std::to_string(i) + ")");
  827|      0|            }
  828|  7.87k|            if (type == 'f') {
  ------------------
  |  Branch (828:17): [True: 7.87k, False: 0]
  ------------------
  829|  7.87k|                insertFreeXrefEntry(QPDFObjGen(toI(i), f2));
  830|  7.87k|            } else {
  831|      0|                insertXrefEntry(toI(i), 1, f1, f2);
  832|      0|            }
  833|  7.87k|        }
  834|  7.87k|        qpdf_offset_t pos = m->file->tell();
  835|  7.87k|        if (readToken(*m->file).isWord("trailer")) {
  ------------------
  |  Branch (835:13): [True: 7.87k, False: 0]
  ------------------
  836|  7.87k|            break;
  837|  7.87k|        } else {
  838|      0|            m->file->seek(pos, SEEK_SET);
  839|      0|        }
  840|  7.87k|    }
  841|       |
  842|       |    // Set offset to previous xref table if any
  843|  7.87k|    QPDFObjectHandle cur_trailer = m->objects.readTrailer();
  844|  7.87k|    if (!cur_trailer.isDictionary()) {
  ------------------
  |  Branch (844:9): [True: 0, False: 7.87k]
  ------------------
  845|      0|        throw damagedPDF("", "expected trailer dictionary");
  846|      0|    }
  847|       |
  848|  7.87k|    if (!m->trailer) {
  ------------------
  |  Branch (848:9): [True: 7.87k, False: 0]
  ------------------
  849|  7.87k|        setTrailer(cur_trailer);
  850|       |
  851|  7.87k|        if (!m->trailer.hasKey("/Size")) {
  ------------------
  |  Branch (851:13): [True: 0, False: 7.87k]
  ------------------
  852|      0|            throw damagedPDF("trailer", "trailer dictionary lacks /Size key");
  853|      0|        }
  854|  7.87k|        if (!m->trailer.getKey("/Size").isInteger()) {
  ------------------
  |  Branch (854:13): [True: 0, False: 7.87k]
  ------------------
  855|      0|            throw damagedPDF("trailer", "/Size key in trailer dictionary is not an integer");
  856|      0|        }
  857|  7.87k|    }
  858|       |
  859|  7.87k|    if (cur_trailer.hasKey("/XRefStm")) {
  ------------------
  |  Branch (859:9): [True: 0, False: 7.87k]
  ------------------
  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.87k|    if (cur_trailer.hasKey("/Prev")) {
  ------------------
  |  Branch (873:9): [True: 0, False: 7.87k]
  ------------------
  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.87k|    return 0;
  881|  7.87k|}
_ZN4QPDF3Doc7Objects19insertFreeXrefEntryE10QPDFObjGen:
 1188|  7.87k|{
 1189|  7.87k|    if (!m->xref_table.contains(og) && og.getObj() <= m->xref_table_max_id) {
  ------------------
  |  Branch (1189:9): [True: 7.87k, False: 0]
  |  Branch (1189:40): [True: 7.87k, False: 0]
  ------------------
 1190|  7.87k|        m->deleted_objects.insert(og.getObj());
 1191|  7.87k|    }
 1192|  7.87k|}
_ZN4QPDF3Doc7Objects11readTrailerEv:
 1294|  7.87k|{
 1295|  7.87k|    qpdf_offset_t offset = m->file->tell();
 1296|  7.87k|    auto object =
 1297|  7.87k|        Parser::parse(*m->file, "trailer", m->tokenizer, nullptr, qpdf, m->reconstructed_xref);
 1298|  7.87k|    if (object.isDictionary() && m->objects.readToken(*m->file).isWord("stream")) {
  ------------------
  |  Branch (1298:9): [True: 7.87k, False: 0]
  |  Branch (1298:9): [True: 0, False: 7.87k]
  |  Branch (1298:34): [True: 0, False: 7.87k]
  ------------------
 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.87k|    m->file->setLastOffset(offset);
 1303|  7.87k|    return object;
 1304|  7.87k|}
_ZN4QPDF3Doc7Objects9readTokenER11InputSourcem:
 1489|  39.3k|{
 1490|  39.3k|    return m->tokenizer.readToken(input, m->last_object_description, true, max_len);
 1491|  39.3k|}
_ZN4QPDF3Doc7Objects11updateCacheE10QPDFObjGenRKNSt3__110shared_ptrI10QPDFObjectEExxb:
 1867|  18.5k|{
 1868|  18.5k|    object->setObjGen(&qpdf, og);
 1869|  18.5k|    if (isCached(og)) {
  ------------------
  |  Branch (1869:9): [True: 18.5k, False: 0]
  ------------------
 1870|  18.5k|        auto& cache = m->obj_cache[og];
 1871|  18.5k|        object->move_to(cache.object, destroy);
 1872|  18.5k|        cache.end_before_space = end_before_space;
 1873|  18.5k|        cache.end_after_space = end_after_space;
 1874|  18.5k|    } else {
 1875|      0|        m->obj_cache[og] = ObjCache(object, end_before_space, end_after_space);
 1876|      0|    }
 1877|  18.5k|}
_ZN4QPDF3Doc7Objects8isCachedE10QPDFObjGen:
 1881|  18.5k|{
 1882|  18.5k|    return m->obj_cache.contains(og);
 1883|  18.5k|}
_ZN4QPDF3Doc7Objects16getObjectForJSONEii:
 1938|   759k|{
 1939|   759k|    auto og = QPDFObjGen(id, gen);
 1940|   759k|    auto [it, inserted] = m->obj_cache.try_emplace(og);
 1941|   759k|    auto& obj = it->second.object;
 1942|   759k|    if (inserted) {
  ------------------
  |  Branch (1942:9): [True: 13.7k, False: 746k]
  ------------------
 1943|  13.7k|        obj = (m->parsed && !m->xref_table.contains(og))
  ------------------
  |  Branch (1943:16): [True: 13.7k, False: 0]
  |  Branch (1943:29): [True: 13.7k, False: 0]
  ------------------
 1944|  13.7k|            ? QPDFObject::create<QPDF_Null>(&qpdf, og)
 1945|  13.7k|            : QPDFObject::create<QPDF_Unresolved>(&qpdf, og);
 1946|  13.7k|    }
 1947|   759k|    return obj;
 1948|   759k|}
_ZN4QPDF9getObjectE10QPDFObjGen:
 1952|  18.5k|{
 1953|  18.5k|    if (auto it = m->obj_cache.find(og); it != m->obj_cache.end()) {
  ------------------
  |  Branch (1953:42): [True: 18.5k, False: 0]
  ------------------
 1954|  18.5k|        return {it->second.object};
 1955|  18.5k|    } 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|  18.5k|}
_ZN4QPDF13replaceObjectE10QPDFObjGen16QPDFObjectHandle:
 1972|  18.5k|{
 1973|  18.5k|    if (!oh || (oh.isIndirect() && !(oh.isStream() && oh.getObjGen() == og))) {
  ------------------
  |  Branch (1973:9): [True: 0, False: 18.5k]
  |  Branch (1973:9): [True: 0, False: 18.5k]
  |  Branch (1973:17): [True: 4.04k, False: 14.4k]
  |  Branch (1973:38): [True: 4.04k, False: 0]
  |  Branch (1973:55): [True: 4.04k, False: 0]
  ------------------
 1974|      0|        throw std::logic_error("QPDF::replaceObject called with indirect object handle");
 1975|      0|    }
 1976|  18.5k|    m->objects.updateCache(og, oh.obj_sp(), -1, -1, false);
 1977|  18.5k|}
_ZN4QPDF3Doc7Objects13PatternFinderC2ERS1_MS1_FbvE:
  147|  15.7k|        o(o),
  148|  15.7k|        checker(checker)
  149|  15.7k|    {
  150|  15.7k|    }
_ZN4QPDF3Doc7Objects13PatternFinder5checkEv:
  154|  15.7k|    {
  155|  15.7k|        return (this->o.*checker)();
  156|  15.7k|    }

_ZN5QUtil13int_to_stringExi:
  331|  1.11M|{
  332|  1.11M|    return int_to_string_base(num, 10, length);
  333|  1.11M|}
_ZN5QUtil18int_to_string_baseExii:
  343|  1.11M|{
  344|  1.11M|    return int_to_string_base_internal(num, base, length);
  345|  1.11M|}
_ZN5QUtil16double_to_stringEdib:
  355|  3.89k|{
  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|  3.89k|    if (decimal_places <= 0) {
  ------------------
  |  Branch (359:9): [True: 3.89k, False: 0]
  ------------------
  360|  3.89k|        decimal_places = 6;
  361|  3.89k|    }
  362|  3.89k|    std::ostringstream buf;
  363|  3.89k|    buf.imbue(std::locale::classic());
  364|  3.89k|    buf << std::setprecision(decimal_places) << std::fixed << num;
  365|  3.89k|    std::string result = buf.str();
  366|  3.89k|    if (trim_trailing_zeroes) {
  ------------------
  |  Branch (366:9): [True: 3.89k, False: 0]
  ------------------
  367|  25.8k|        while ((result.length() > 1) && (result.back() == '0')) {
  ------------------
  |  Branch (367:16): [True: 25.8k, False: 0]
  |  Branch (367:41): [True: 22.0k, False: 3.89k]
  ------------------
  368|  22.0k|            result.pop_back();
  369|  22.0k|        }
  370|  3.89k|        if ((result.length() > 1) && (result.back() == '.')) {
  ------------------
  |  Branch (370:13): [True: 3.89k, False: 0]
  |  Branch (370:38): [True: 3.52k, False: 367]
  ------------------
  371|  3.52k|            result.pop_back();
  372|  3.52k|        }
  373|  3.89k|    }
  374|  3.89k|    return result;
  375|  3.89k|}
_ZN5QUtil12string_to_llEPKc:
  379|  3.78M|{
  380|  3.78M|    errno = 0;
  381|       |#ifdef _MSC_VER
  382|       |    long long result = _strtoi64(str, 0, 10);
  383|       |#else
  384|  3.78M|    long long result = strtoll(str, nullptr, 10);
  385|  3.78M|#endif
  386|  3.78M|    if (errno == ERANGE) {
  ------------------
  |  Branch (386:9): [True: 1.73k, False: 3.77M]
  ------------------
  387|  1.73k|        throw std::range_error(
  388|  1.73k|            std::string("overflow/underflow converting ") + str + " to 64-bit integer");
  389|  1.73k|    }
  390|  3.77M|    return result;
  391|  3.78M|}
_ZN5QUtil13string_to_intEPKc:
  395|  1.54M|{
  396|       |    // QIntC::to_int does range checking
  397|  1.54M|    return QIntC::to_int(string_to_ll(str));
  398|  1.54M|}
_ZN5QUtil12is_long_longEPKc:
  434|  1.11M|{
  435|  1.11M|    try {
  436|  1.11M|        auto i1 = string_to_ll(str);
  437|  1.11M|        std::string s1 = int_to_string(i1);
  438|  1.11M|        return str == s1;
  439|  1.11M|    } catch (std::exception&) {
  440|       |        // overflow or other error
  441|  1.72k|    }
  442|  1.72k|    return false;
  443|  1.11M|}
_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.22k|{
  741|  1.22k|    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.22k|    bool first = true;
  745|  1.22k|    char decoded;
  746|  22.2k|    for (auto ch: input) {
  ------------------
  |  Branch (746:17): [True: 22.2k, False: 1.22k]
  ------------------
  747|  22.2k|        ch = util::hex_decode_char(ch);
  748|  22.2k|        if (ch < '\20') {
  ------------------
  |  Branch (748:13): [True: 22.2k, False: 0]
  ------------------
  749|  22.2k|            if (first) {
  ------------------
  |  Branch (749:17): [True: 11.1k, False: 11.1k]
  ------------------
  750|  11.1k|                decoded = static_cast<char>(ch << 4);
  751|  11.1k|                first = false;
  752|  11.1k|            } else {
  753|  11.1k|                result.push_back(decoded | ch);
  754|  11.1k|                first = true;
  755|  11.1k|            }
  756|  22.2k|        }
  757|  22.2k|    }
  758|  1.22k|    if (!first) {
  ------------------
  |  Branch (758:9): [True: 0, False: 1.22k]
  ------------------
  759|      0|        result.push_back(decoded);
  760|      0|    }
  761|  1.22k|    return result;
  762|  1.22k|}
_ZN5QUtil6toUTF8Em:
 1004|  42.6k|{
 1005|  42.6k|    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.6k|    if (uval > 0x7fffffff) {
  ------------------
  |  Branch (1014:9): [True: 0, False: 42.6k]
  ------------------
 1015|      0|        throw std::runtime_error("bounds error in QUtil::toUTF8");
 1016|  42.6k|    } else if (uval < 128) {
  ------------------
  |  Branch (1016:16): [True: 38.4k, False: 4.23k]
  ------------------
 1017|  38.4k|        result += static_cast<char>(uval);
 1018|  38.4k|    } else {
 1019|  4.23k|        unsigned char bytes[7];
 1020|  4.23k|        bytes[6] = '\0';
 1021|  4.23k|        unsigned char* cur_byte = &bytes[5];
 1022|       |
 1023|       |        // maximum value that will fit in the current number of bytes
 1024|  4.23k|        unsigned char maxval = 0x3f; // six bits
 1025|       |
 1026|  15.1k|        while (uval > QIntC::to_ulong(maxval)) {
  ------------------
  |  Branch (1026:16): [True: 10.9k, False: 4.23k]
  ------------------
 1027|       |            // Assign low six bits plus 10000000 to lowest unused byte position, then shift
 1028|  10.9k|            *cur_byte = static_cast<unsigned char>(0x80 + (uval & 0x3f));
 1029|  10.9k|            uval >>= 6;
 1030|       |            // Maximum that will fit in high byte now shrinks by one bit
 1031|  10.9k|            maxval = static_cast<unsigned char>(maxval >> 1);
 1032|       |            // Slide to the left one byte
 1033|  10.9k|            if (cur_byte <= bytes) {
  ------------------
  |  Branch (1033:17): [True: 0, False: 10.9k]
  ------------------
 1034|      0|                throw std::logic_error("QUtil::toUTF8: overflow error");
 1035|      0|            }
 1036|  10.9k|            --cur_byte;
 1037|  10.9k|        }
 1038|       |        // If maxval is k bits long, the high (7 - k) bits of the resulting byte must be high.
 1039|  4.23k|        *cur_byte = static_cast<unsigned char>(QIntC::to_ulong(0xff - (1 + (maxval << 1))) + uval);
 1040|       |
 1041|  4.23k|        result += reinterpret_cast<char*>(cur_byte);
 1042|  4.23k|    }
 1043|       |
 1044|  42.6k|    return result;
 1045|  42.6k|}
_ZN5QUtil7toUTF16Em:
 1049|  10.3M|{
 1050|  10.3M|    std::string result;
 1051|  10.3M|    if ((uval >= 0xd800) && (uval <= 0xdfff)) {
  ------------------
  |  Branch (1051:9): [True: 17.8k, False: 10.3M]
  |  Branch (1051:29): [True: 429, False: 17.4k]
  ------------------
 1052|    429|        result = "\xff\xfd";
 1053|  10.3M|    } else if (uval <= 0xffff) {
  ------------------
  |  Branch (1053:16): [True: 10.3M, False: 17.3k]
  ------------------
 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: 4.15k, False: 13.1k]
  ------------------
 1059|  4.15k|        char out[4];
 1060|  4.15k|        uval -= 0x10000;
 1061|  4.15k|        unsigned short high = static_cast<unsigned short>(((uval & 0xffc00) >> 10) + 0xd800);
 1062|  4.15k|        unsigned short low = static_cast<unsigned short>((uval & 0x3ff) + 0xdc00);
 1063|  4.15k|        out[0] = static_cast<char>((high & 0xff00) >> 8);
 1064|  4.15k|        out[1] = static_cast<char>(high & 0xff);
 1065|  4.15k|        out[2] = static_cast<char>((low & 0xff00) >> 8);
 1066|  4.15k|        out[3] = static_cast<char>(low & 0xff);
 1067|  4.15k|        result = std::string(out, 4);
 1068|  13.1k|    } else {
 1069|  13.1k|        result = "\xff\xfd";
 1070|  13.1k|    }
 1071|       |
 1072|  10.3M|    return result;
 1073|  10.3M|}
_ZN5QUtil23get_next_utf8_codepointERKNSt3__112basic_stringIcNS0_11char_traitsIcEENS0_9allocatorIcEEEERmRb:
 1479|  27.1M|{
 1480|  27.1M|    auto o_pos = pos;
 1481|  27.1M|    size_t len = utf8_val.length();
 1482|  27.1M|    unsigned char ch = static_cast<unsigned char>(utf8_val.at(pos++));
 1483|  27.1M|    error = false;
 1484|  27.1M|    if (ch < 128) {
  ------------------
  |  Branch (1484:9): [True: 20.7M, False: 6.44M]
  ------------------
 1485|  20.7M|        return static_cast<unsigned long>(ch);
 1486|  20.7M|    }
 1487|       |
 1488|  6.44M|    size_t bytes_needed = 0;
 1489|  6.44M|    unsigned bit_check = 0x40;
 1490|  6.44M|    unsigned char to_clear = 0x80;
 1491|  16.5M|    while (ch & bit_check) {
  ------------------
  |  Branch (1491:12): [True: 10.1M, False: 6.44M]
  ------------------
 1492|  10.1M|        ++bytes_needed;
 1493|  10.1M|        to_clear = static_cast<unsigned char>(to_clear | bit_check);
 1494|  10.1M|        bit_check >>= 1;
 1495|  10.1M|    }
 1496|  6.44M|    if (((bytes_needed > 5) || (bytes_needed < 1)) || ((pos + bytes_needed) > len)) {
  ------------------
  |  Branch (1496:10): [True: 919k, False: 5.53M]
  |  Branch (1496:32): [True: 3.87M, False: 1.66M]
  |  Branch (1496:55): [True: 2.60k, False: 1.65M]
  ------------------
 1497|  4.79M|        error = true;
 1498|  4.79M|        return 0xfffd;
 1499|  4.79M|    }
 1500|       |
 1501|  1.65M|    auto codepoint = static_cast<unsigned long>(ch & ~to_clear);
 1502|  1.83M|    while (bytes_needed > 0) {
  ------------------
  |  Branch (1502:12): [True: 1.77M, False: 62.4k]
  ------------------
 1503|  1.77M|        --bytes_needed;
 1504|  1.77M|        ch = static_cast<unsigned char>(utf8_val.at(pos++));
 1505|  1.77M|        if ((ch & 0xc0) != 0x80) {
  ------------------
  |  Branch (1505:13): [True: 1.59M, False: 177k]
  ------------------
 1506|  1.59M|            --pos;
 1507|  1.59M|            error = true;
 1508|  1.59M|            return 0xfffd;
 1509|  1.59M|        }
 1510|   177k|        codepoint <<= 6;
 1511|   177k|        codepoint += (ch & 0x3f);
 1512|   177k|    }
 1513|  62.4k|    unsigned long lower_bound = 0;
 1514|  62.4k|    switch (pos - o_pos) {
 1515|  20.7k|    case 2:
  ------------------
  |  Branch (1515:5): [True: 20.7k, False: 41.7k]
  ------------------
 1516|  20.7k|        lower_bound = 1 << 7;
 1517|  20.7k|        break;
 1518|  7.07k|    case 3:
  ------------------
  |  Branch (1518:5): [True: 7.07k, False: 55.3k]
  ------------------
 1519|  7.07k|        lower_bound = 1 << 11;
 1520|  7.07k|        break;
 1521|  22.0k|    case 4:
  ------------------
  |  Branch (1521:5): [True: 22.0k, False: 40.4k]
  ------------------
 1522|  22.0k|        lower_bound = 1 << 16;
 1523|  22.0k|        break;
 1524|  6.09k|    case 5:
  ------------------
  |  Branch (1524:5): [True: 6.09k, False: 56.3k]
  ------------------
 1525|  6.09k|        lower_bound = 1 << 12;
 1526|  6.09k|        break;
 1527|  6.54k|    case 6:
  ------------------
  |  Branch (1527:5): [True: 6.54k, False: 55.9k]
  ------------------
 1528|  6.54k|        lower_bound = 1 << 26;
 1529|  6.54k|        break;
 1530|      0|    default:
  ------------------
  |  Branch (1530:5): [True: 0, False: 62.4k]
  ------------------
 1531|      0|        lower_bound = 0;
 1532|  62.4k|    }
 1533|       |
 1534|  62.4k|    if (lower_bound > 0 && codepoint < lower_bound) {
  ------------------
  |  Branch (1534:9): [True: 62.4k, False: 0]
  |  Branch (1534:28): [True: 308, False: 62.1k]
  ------------------
 1535|       |        // Too many bytes were used, but return whatever character was encoded.
 1536|    308|        error = true;
 1537|    308|    }
 1538|  62.4k|    return codepoint;
 1539|  62.4k|}
_ZN5QUtil13utf8_to_utf16ERKNSt3__112basic_stringIcNS0_11char_traitsIcEENS0_9allocatorIcEEEE:
 1637|  4.13k|{
 1638|  4.13k|    return transcode_utf8(utf8, e_utf16, 0);
 1639|  4.13k|}
_ZN5QUtil15utf8_to_pdf_docERKNSt3__112basic_stringIcNS0_11char_traitsIcEENS0_9allocatorIcEEEERS6_c:
 1685|  5.51k|{
 1686|  5.51k|    return transcode_utf8(utf8, pdfdoc, e_pdfdoc, unknown_char);
 1687|  5.51k|}
QUtil.cc:_ZL14transcode_utf8RKNSt3__112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEE10encoding_ec:
 1629|  4.13k|{
 1630|  4.13k|    std::string result;
 1631|  4.13k|    transcode_utf8(utf8_val, result, encoding, unknown);
 1632|  4.13k|    return result;
 1633|  4.13k|}
QUtil.cc:_ZL14transcode_utf8RKNSt3__112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEERS5_10encoding_ec:
 1543|  9.64k|{
 1544|  9.64k|    bool okay = true;
 1545|  9.64k|    result.clear();
 1546|  9.64k|    size_t len = utf8_val.length();
 1547|  9.64k|    switch (encoding) {
 1548|  4.13k|    case e_utf16:
  ------------------
  |  Branch (1548:5): [True: 4.13k, False: 5.51k]
  ------------------
 1549|  4.13k|        result += "\xfe\xff";
 1550|  4.13k|        break;
 1551|  5.51k|    case e_pdfdoc:
  ------------------
  |  Branch (1551:5): [True: 5.51k, False: 4.13k]
  ------------------
 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.51k|        if ((len >= 4) && (utf8_val[0] == '\xc3')) {
  ------------------
  |  Branch (1558:13): [True: 4.19k, False: 1.31k]
  |  Branch (1558:27): [True: 2.44k, False: 1.75k]
  ------------------
 1559|  2.44k|            static std::string fe_ff("\xbe\xc3\xbf");
 1560|  2.44k|            static std::string ff_fe("\xbf\xc3\xbe");
 1561|  2.44k|            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.44k|            if ((utf8_val.compare(1, 3, fe_ff) == 0) || (utf8_val.compare(1, 3, ff_fe) == 0) ||
  ------------------
  |  Branch (1564:17): [True: 198, 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: 308, False: 1.74k]
  ------------------
 1566|    702|                result += unknown;
 1567|    702|                okay = false;
 1568|    702|            }
 1569|  2.44k|        }
 1570|  5.51k|        break;
 1571|      0|    default:
  ------------------
  |  Branch (1571:5): [True: 0, False: 9.64k]
  ------------------
 1572|      0|        break;
 1573|  9.64k|    }
 1574|  9.64k|    size_t pos = 0;
 1575|  27.1M|    while (pos < len) {
  ------------------
  |  Branch (1575:12): [True: 27.1M, False: 9.64k]
  ------------------
 1576|  27.1M|        bool error = false;
 1577|  27.1M|        unsigned long codepoint = QUtil::get_next_utf8_codepoint(utf8_val, pos, error);
 1578|  27.1M|        if (error) {
  ------------------
  |  Branch (1578:13): [True: 6.38M, False: 20.7M]
  ------------------
 1579|  6.38M|            okay = false;
 1580|  6.38M|            if (encoding == e_utf16) {
  ------------------
  |  Branch (1580:17): [True: 3.19M, False: 3.19M]
  ------------------
 1581|  3.19M|                result += "\xff\xfd";
 1582|  3.19M|            } else {
 1583|  3.19M|                result.append(1, unknown);
 1584|  3.19M|            }
 1585|  20.7M|        } else if (codepoint < 128) {
  ------------------
  |  Branch (1585:20): [True: 20.7M, False: 62.1k]
  ------------------
 1586|  20.7M|            char ch = static_cast<char>(codepoint);
 1587|  20.7M|            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: 227]
  |  Branch (1589:68): [True: 196, False: 10.3M]
  |  Branch (1589:85): [True: 1.51k, 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.71k|                okay = false;
 1594|  1.71k|                result.append(1, unknown);
 1595|  10.3M|            } else {
 1596|  10.3M|                result.append(1, ch);
 1597|  10.3M|            }
 1598|  20.7M|        } else if (encoding == e_utf16) {
  ------------------
  |  Branch (1598:20): [True: 30.6k, False: 31.4k]
  ------------------
 1599|  30.6k|            result += QUtil::toUTF16(codepoint);
 1600|  31.4k|        } else if ((codepoint == 0xad) && (encoding == e_pdfdoc)) {
  ------------------
  |  Branch (1600:20): [True: 357, False: 31.1k]
  |  Branch (1600:43): [True: 357, False: 0]
  ------------------
 1601|       |            // PDFDocEncoding omits 0x00ad (soft hyphen).
 1602|    357|            okay = false;
 1603|    357|            result.append(1, unknown);
 1604|  31.1k|        } else if (
 1605|  31.1k|            (codepoint > 160) && (codepoint < 256) &&
  ------------------
  |  Branch (1605:13): [True: 29.0k, False: 2.08k]
  |  Branch (1605:34): [True: 4.31k, False: 24.7k]
  ------------------
 1606|  4.31k|            ((encoding == e_winansi) || (encoding == e_pdfdoc))) {
  ------------------
  |  Branch (1606:14): [True: 0, False: 4.31k]
  |  Branch (1606:41): [True: 4.31k, False: 0]
  ------------------
 1607|  4.31k|            result.append(1, static_cast<char>(codepoint & 0xff));
 1608|  26.7k|        } else {
 1609|  26.7k|            unsigned char ch = '\0';
 1610|  26.7k|            if (encoding == e_winansi) {
  ------------------
  |  Branch (1610:17): [True: 0, False: 26.7k]
  ------------------
 1611|      0|                ch = encode_winansi(codepoint);
 1612|  26.7k|            } else if (encoding == e_macroman) {
  ------------------
  |  Branch (1612:24): [True: 0, False: 26.7k]
  ------------------
 1613|      0|                ch = encode_macroman(codepoint);
 1614|  26.7k|            } else if (encoding == e_pdfdoc) {
  ------------------
  |  Branch (1614:24): [True: 26.7k, False: 0]
  ------------------
 1615|  26.7k|                ch = encode_pdfdoc(codepoint);
 1616|  26.7k|            }
 1617|  26.7k|            if (ch == '\0') {
  ------------------
  |  Branch (1617:17): [True: 26.2k, False: 551]
  ------------------
 1618|  26.2k|                okay = false;
 1619|  26.2k|                ch = static_cast<unsigned char>(unknown);
 1620|  26.2k|            }
 1621|  26.7k|            result.append(1, static_cast<char>(ch));
 1622|  26.7k|        }
 1623|  27.1M|    }
 1624|  9.64k|    return okay;
 1625|  9.64k|}
QUtil.cc:_ZL13encode_pdfdocm:
 1469|  26.7k|{
 1470|  26.7k|    auto i = unicode_to_pdf_doc.find(codepoint);
 1471|  26.7k|    if (i != unicode_to_pdf_doc.end()) {
  ------------------
  |  Branch (1471:9): [True: 551, False: 26.2k]
  ------------------
 1472|    551|        return i->second;
 1473|    551|    }
 1474|  26.2k|    return '\0';
 1475|  26.7k|}
QUtil.cc:_ZL27int_to_string_base_internalIxENSt3__112basic_stringIcNS0_11char_traitsIcEENS0_9allocatorIcEEEET_ii:
  300|  1.11M|{
  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.11M|    if (!((base == 8) || (base == 10) || (base == 16))) {
  ------------------
  |  Branch (304:11): [True: 0, False: 1.11M]
  |  Branch (304:26): [True: 1.11M, 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.11M|    std::string cvt;
  308|  1.11M|    if (base == 10) {
  ------------------
  |  Branch (308:9): [True: 1.11M, False: 0]
  ------------------
  309|       |        // Use the more efficient std::to_string when possible
  310|  1.11M|        cvt = std::to_string(num);
  311|  1.11M|    } 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.11M|    std::string result;
  318|  1.11M|    int str_length = QIntC::to_int(cvt.length());
  319|  1.11M|    if ((length > 0) && (str_length < length)) {
  ------------------
  |  Branch (319:9): [True: 0, False: 1.11M]
  |  Branch (319:25): [True: 0, False: 0]
  ------------------
  320|      0|        result.append(QIntC::to_size(length - str_length), '0');
  321|      0|    }
  322|  1.11M|    result += cvt;
  323|  1.11M|    if ((length < 0) && (str_length < -length)) {
  ------------------
  |  Branch (323:9): [True: 0, False: 1.11M]
  |  Branch (323:25): [True: 0, False: 0]
  ------------------
  324|      0|        result.append(QIntC::to_size(-length - str_length), ' ');
  325|      0|    }
  326|  1.11M|    return result;
  327|  1.11M|}

_ZN4qpdf6global7Options9fuzz_modeEb:
   13|  7.87k|{
   14|  7.87k|    if (value) {
  ------------------
  |  Branch (14:9): [True: 7.87k, False: 0]
  ------------------
   15|  7.87k|        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.87k|        Limits::dct_max_memory(10'000'000);
   21|  7.87k|        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.87k|        dct_throw_on_corrupt_data(true);
   25|  7.87k|        Limits::png_max_memory(1'000'000);
   26|  7.87k|        Limits::flate_max_memory(200'000);
   27|  7.87k|        Limits::run_length_max_memory(1'000'000);
   28|  7.87k|        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.87k|        Limits::doc_max_warnings(200);
   32|  7.87k|    }
   33|  7.87k|}
qpdf_global_set_uint32:
  129|  7.87k|{
  130|  7.87k|    switch (param) {
  131|      0|    case qpdf_p_inspection_mode:
  ------------------
  |  Branch (131:5): [True: 0, False: 7.87k]
  ------------------
  132|      0|        Options::inspection_mode(value);
  133|      0|        return qpdf_r_ok;
  134|  7.87k|    case qpdf_p_fuzz_mode:
  ------------------
  |  Branch (134:5): [True: 7.87k, False: 0]
  ------------------
  135|  7.87k|        Options::fuzz_mode(value);
  136|  7.87k|        return qpdf_r_ok;
  137|      0|    case qpdf_p_default_limits:
  ------------------
  |  Branch (137:5): [True: 0, False: 7.87k]
  ------------------
  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.87k]
  ------------------
  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.87k]
  ------------------
  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.87k]
  ------------------
  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.87k]
  ------------------
  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.87k]
  ------------------
  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.87k]
  ------------------
  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.87k]
  ------------------
  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.87k]
  ------------------
  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.87k]
  ------------------
  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.87k]
  ------------------
  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.87k]
  ------------------
  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.87k]
  ------------------
  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.87k]
  ------------------
  177|      0|        Limits::tiff_max_memory(value);
  178|      0|        return qpdf_r_ok;
  179|      0|    default:
  ------------------
  |  Branch (179:5): [True: 0, False: 7.87k]
  ------------------
  180|      0|        return qpdf_r_bad_parameter;
  181|  7.87k|    }
  182|  7.87k|}

_ZNK4qpdf2is12OffsetBuffer7getNameEv:
   48|   206k|        {
   49|   206k|            return description;
   50|   206k|        }
_ZN4qpdf2is12OffsetBuffer4tellEv:
   54|   203k|        {
   55|   203k|            return pos + global_offset;
   56|   203k|        }
_ZN4qpdf2is12OffsetBuffer8unreadChEc:
   70|  7.87k|        {
   71|  7.87k|            if (pos > 0) {
  ------------------
  |  Branch (71:17): [True: 7.87k, False: 0]
  ------------------
   72|  7.87k|                --pos;
   73|  7.87k|            }
   74|  7.87k|        }
_ZN4qpdf2is12OffsetBufferD2Ev:
   42|  34.8k|        ~OffsetBuffer() final = default;
_ZN4qpdf2is12OffsetBufferC2ERKNSt3__112basic_stringIcNS2_11char_traitsIcEENS2_9allocatorIcEEEENS2_17basic_string_viewIcS5_EEx:
   21|  34.8k|            description(description),
   22|  34.8k|            view_(view),
   23|  34.8k|            global_offset(global_offset)
   24|  34.8k|        {
   25|  34.8k|            if (global_offset < 0) {
  ------------------
  |  Branch (25:17): [True: 0, False: 34.8k]
  ------------------
   26|      0|                throw std::logic_error("is::OffsetBuffer constructed with negative offset");
   27|      0|            }
   28|  34.8k|            last_offset = global_offset;
   29|  34.8k|        }
_ZN11InputSource4readERNSt3__112basic_stringIcNS0_11char_traitsIcEENS0_9allocatorIcEEEEmx:
   87|  7.87k|{
   88|  7.87k|    if (at >= 0) {
  ------------------
  |  Branch (88:9): [True: 0, False: 7.87k]
  ------------------
   89|       |        seek(at, SEEK_SET);
   90|      0|    }
   91|  7.87k|    str.resize(count);
   92|  7.87k|    str.resize(read(str.data(), count));
   93|  7.87k|    return str.size();
   94|  7.87k|}
_ZN11InputSource10loadBufferEv:
  106|  82.7k|{
  107|  82.7k|    buf_idx = 0;
  108|  82.7k|    buf_len = qpdf_offset_t(read(buffer, buf_size));
  109|       |    // NB read sets last_offset
  110|  82.7k|    buf_start = last_offset;
  111|  82.7k|}
_ZN11InputSource8fastTellEv:
  115|   137k|{
  116|   137k|    if (buf_len == 0) {
  ------------------
  |  Branch (116:9): [True: 19.0k, False: 118k]
  ------------------
  117|  19.0k|        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.87k, False: 110k]
  |  Branch (120:33): [True: 55.8k, False: 55.0k]
  ------------------
  121|  63.7k|            loadBuffer();
  122|  63.7k|        } else {
  123|  55.0k|            last_offset = curr;
  124|  55.0k|            buf_idx = curr - buf_start;
  125|  55.0k|        }
  126|   118k|    }
  127|   137k|    return last_offset;
  128|   137k|}
_ZN11InputSource8fastReadERc:
  132|  6.81M|{
  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.81M|    if (buf_idx < buf_len) {
  ------------------
  |  Branch (135:9): [True: 6.75M, False: 62.4k]
  ------------------
  136|  6.75M|        ch = buffer[buf_idx];
  137|  6.75M|        ++(buf_idx);
  138|  6.75M|        ++(last_offset);
  139|  6.75M|        return true;
  140|       |
  141|  6.75M|    } else if (buf_len == 0) {
  ------------------
  |  Branch (141:16): [True: 6.66k, False: 55.8k]
  ------------------
  142|  6.66k|        return false;
  143|  55.8k|    } else {
  144|       |        seek(buf_start + buf_len, SEEK_SET);
  145|  55.8k|        fastTell();
  146|  55.8k|        return fastRead(ch);
  147|  55.8k|    }
  148|  6.81M|}
_ZN11InputSource10fastUnreadEb:
  152|  82.0k|{
  153|  82.0k|    last_offset -= back ? 1 : 0;
  ------------------
  |  Branch (153:20): [True: 59.6k, False: 22.4k]
  ------------------
  154|       |    seek(last_offset, SEEK_SET);
  155|  82.0k|}

_ZNK4qpdf10BaseHandle13raw_type_codeEv:
  933|  8.49M|    {
  934|  8.49M|        return obj ? static_cast<qpdf_object_type_e>(obj->value.index()) : ::ot_uninitialized;
  ------------------
  |  Branch (934:16): [True: 8.49M, False: 0]
  ------------------
  935|  8.49M|    }
_ZNK4qpdf10BaseHandle4qpdfEv:
  927|  7.22M|    {
  928|  7.22M|        return obj ? obj->qpdf : nullptr;
  ------------------
  |  Branch (928:16): [True: 7.22M, False: 0]
  ------------------
  929|  7.22M|    }
_ZNK4qpdf10BaseHandle6offsetEv:
  921|    596|    {
  922|    596|        return obj ? obj->parsed_offset : -1;
  ------------------
  |  Branch (922:16): [True: 596, False: 0]
  ------------------
  923|    596|    }
_ZNK4qpdf10BaseHandle9type_codeEv:
  951|  2.43M|    {
  952|  2.43M|        if (!obj) {
  ------------------
  |  Branch (952:13): [True: 0, False: 2.43M]
  ------------------
  953|      0|            return ::ot_uninitialized;
  954|      0|        }
  955|  2.43M|        if (raw_type_code() == ::ot_unresolved) {
  ------------------
  |  Branch (955:13): [True: 0, False: 2.43M]
  ------------------
  956|      0|            return QPDF::Doc::Resolver::resolved(obj->qpdf, obj->og)->getTypeCode();
  957|      0|        }
  958|  2.43M|        if (raw_type_code() == ::ot_reference) {
  ------------------
  |  Branch (958:13): [True: 420, False: 2.43M]
  ------------------
  959|    420|            return std::get<QPDF_Reference>(obj->value).obj->getTypeCode();
  960|    420|        }
  961|  2.43M|        return raw_type_code();
  962|  2.43M|    }
_ZNK4qpdf10BaseHandle8indirectEv:
  860|  1.78M|    {
  861|  1.78M|        return obj ? obj->og.isIndirect() : false;
  ------------------
  |  Branch (861:16): [True: 1.78M, False: 0]
  ------------------
  862|  1.78M|    }
_ZNK4qpdf10BaseHandle4nullEv:
  907|   163k|    {
  908|   163k|        return !obj || type_code() == ::ot_null;
  ------------------
  |  Branch (908:16): [True: 23.6k, False: 140k]
  |  Branch (908:24): [True: 22.4k, False: 117k]
  ------------------
  909|   163k|    }
_ZNK4qpdf10BaseHandle18resolved_type_codeEv:
  939|  23.6k|    {
  940|  23.6k|        if (!obj) {
  ------------------
  |  Branch (940:13): [True: 0, False: 23.6k]
  ------------------
  941|      0|            return ::ot_uninitialized;
  942|      0|        }
  943|  23.6k|        if (raw_type_code() == ::ot_unresolved) {
  ------------------
  |  Branch (943:13): [True: 0, False: 23.6k]
  ------------------
  944|      0|            return QPDF::Doc::Resolver::resolved(obj->qpdf, obj->og)->getTypeCode();
  945|      0|        }
  946|  23.6k|        return raw_type_code();
  947|  23.6k|    }
_ZN4qpdf10BaseHandleC2ERK16QPDFObjectHandle:
  788|  31.4k|        obj(oh.obj)
  789|  31.4k|    {
  790|  31.4k|    }
_ZN4qpdf10DictionaryC2ERK16QPDFObjectHandle:
  268|  23.6k|            BaseDictionary(oh)
  269|  23.6k|        {
  270|  23.6k|        }
_ZN4qpdf14BaseDictionaryC2ERK16QPDFObjectHandle:
  238|  23.6k|            BaseHandle(oh.resolved_type_code() == ::ot_dictionary ? oh : QPDFObjectHandle())
  ------------------
  |  Branch (238:24): [True: 23.6k, False: 0]
  ------------------
  239|  23.6k|        {
  240|  23.6k|        }
_ZNK4qpdf10BaseHandle2asI15QPDF_DictionaryEEPT_v:
  770|   189k|    {
  771|   189k|        if (!obj) {
  ------------------
  |  Branch (771:13): [True: 0, False: 189k]
  ------------------
  772|      0|            return nullptr;
  773|      0|        }
  774|   189k|        if (std::holds_alternative<T>(obj->value)) {
  ------------------
  |  Branch (774:13): [True: 189k, False: 0]
  ------------------
  775|   189k|            return &std::get<T>(obj->value);
  776|   189k|        }
  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|  29.5k|        {
  698|  29.5k|            if (auto s = as<QPDF_Stream>()) {
  ------------------
  |  Branch (698:22): [True: 29.5k, False: 0]
  ------------------
  699|  29.5k|                if (auto ptr = s->m.get()) {
  ------------------
  |  Branch (699:26): [True: 29.5k, False: 0]
  ------------------
  700|  29.5k|                    return ptr;
  701|  29.5k|                }
  702|      0|                throw std::logic_error("QPDF_Stream: unexpected nullptr");
  703|  29.5k|            }
  704|      0|            throw std::runtime_error("operation for stream attempted on non-stream object");
  705|      0|            return nullptr; // unreachable
  706|  29.5k|        }
_ZNK4qpdf10BaseHandle2asI11QPDF_StreamEEPT_v:
  770|  29.5k|    {
  771|  29.5k|        if (!obj) {
  ------------------
  |  Branch (771:13): [True: 0, False: 29.5k]
  ------------------
  772|      0|            return nullptr;
  773|      0|        }
  774|  29.5k|        if (std::holds_alternative<T>(obj->value)) {
  ------------------
  |  Branch (774:13): [True: 29.5k, False: 0]
  ------------------
  775|  29.5k|            return &std::get<T>(obj->value);
  776|  29.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.87k|            BaseHandle(oh.type_code() == ::ot_integer ? oh : QPDFObjectHandle())
  ------------------
  |  Branch (319:24): [True: 7.87k, False: 0]
  ------------------
  320|  7.87k|        {
  321|  7.87k|        }
_ZN10QPDFObject6createI9QPDF_NullJEEENSt3__110shared_ptrIS_EEDpOT0_:
  988|  28.1k|{
  989|  28.1k|    return std::make_shared<QPDFObject>(std::forward<T>(T(std::forward<Args>(args)...)));
  990|  28.1k|}
_ZNK4qpdf7Integer5valueITkNSt3__18integralEiEET_v:
  361|  7.87k|        {
  362|  7.87k|            try {
  363|  7.87k|                return static_cast<T>(*this);
  364|  7.87k|            } 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.87k|        }
_ZNK4qpdf7IntegercvT_ITkNSt3__18integralEiEEv:
  339|  7.87k|        {
  340|  7.87k|            auto v = value();
  341|       |
  342|  7.87k|            if (std::cmp_greater(v, std::numeric_limits<T>::max())) {
  ------------------
  |  Branch (342:17): [True: 0, False: 7.87k]
  ------------------
  343|      0|                throw std::overflow_error("Integer conversion overflow");
  344|      0|            }
  345|  7.87k|            if (std::cmp_less(v, std::numeric_limits<T>::min())) {
  ------------------
  |  Branch (345:17): [True: 0, False: 7.87k]
  ------------------
  346|      0|                throw std::underflow_error("Integer conversion underflow");
  347|      0|            }
  348|  7.87k|            return static_cast<T>(v);
  349|  7.87k|        }
_ZN4qpdf5ArrayC2ERKNSt3__110shared_ptrI10QPDFObjectEE:
   47|  1.81M|            BaseHandle(obj)
   48|  1.81M|        {
   49|  1.81M|        }
_ZN4qpdf14BaseDictionaryC2ERKNSt3__110shared_ptrI10QPDFObjectEE:
  225|   132k|            BaseHandle(obj)
  226|   132k|        {
  227|   132k|        }
_ZN4qpdf4NullC2Ev:
  483|      2|            BaseHandle(QPDFObject::create<QPDF_Null>())
  484|      2|        {
  485|      2|        }
_ZN4qpdf6StreamC2ERKNSt3__110shared_ptrI10QPDFObjectEE:
  515|  12.8k|            BaseHandle(obj)
  516|  12.8k|        {
  517|  12.8k|        }
_ZN4qpdf6Stream11replaceDictERK16QPDFObjectHandle:
  681|  3.08k|        {
  682|  3.08k|            auto s = stream();
  683|  3.08k|            s->stream_dict = new_dict;
  684|  3.08k|            setDictDescription();
  685|  3.08k|        }
_ZNK4qpdf10BaseHandle6obj_spEv:
  799|  1.25M|    {
  800|  1.25M|        return obj;
  801|  1.25M|    }
_ZNK4qpdf10BaseHandle3getERKNSt3__112basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEE:
  901|  15.7k|    {
  902|  15.7k|        return (*this)[key];
  903|  15.7k|    }
_ZNK16QPDFObjectHandle8as_arrayEN4qpdf5typedE:
 1006|  1.81M|{
 1007|  1.81M|    if (options & qpdf::error) {
  ------------------
  |  Branch (1007:9): [True: 0, False: 1.81M]
  ------------------
 1008|      0|        assertType("array", false);
 1009|      0|    }
 1010|  1.81M|    if (options & qpdf::any_flag || type_code() == ::ot_array ||
  ------------------
  |  Branch (1010:9): [True: 0, False: 1.81M]
  |  Branch (1010:37): [True: 1.81M, False: 0]
  ------------------
 1011|  1.81M|        (options & qpdf::optional && type_code() == ::ot_null)) {
  ------------------
  |  Branch (1011:10): [True: 0, False: 0]
  |  Branch (1011:38): [True: 0, False: 0]
  ------------------
 1012|  1.81M|        return qpdf::Array(obj);
 1013|  1.81M|    }
 1014|      0|    return qpdf::Array(std::shared_ptr<QPDFObject>());
 1015|  1.81M|}
_ZNK16QPDFObjectHandle13as_dictionaryEN4qpdf5typedE:
 1019|   132k|{
 1020|   132k|    if (options & qpdf::any_flag || type_code() == ::ot_dictionary ||
  ------------------
  |  Branch (1020:9): [True: 0, False: 132k]
  |  Branch (1020:37): [True: 132k, False: 0]
  ------------------
 1021|   132k|        (options & qpdf::optional && type_code() == ::ot_null)) {
  ------------------
  |  Branch (1021:10): [True: 0, False: 0]
  |  Branch (1021:38): [True: 0, False: 0]
  ------------------
 1022|   132k|        return qpdf::Dictionary(obj);
 1023|   132k|    }
 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|   132k|}
_ZNK16QPDFObjectHandle9as_streamEN4qpdf5typedE:
 1032|  12.8k|{
 1033|  12.8k|    if (options & qpdf::any_flag || type_code() == ::ot_stream ||
  ------------------
  |  Branch (1033:9): [True: 0, False: 12.8k]
  |  Branch (1033:37): [True: 12.8k, False: 0]
  ------------------
 1034|  12.8k|        (options & qpdf::optional && type_code() == ::ot_null)) {
  ------------------
  |  Branch (1034:10): [True: 0, False: 0]
  |  Branch (1034:38): [True: 0, False: 0]
  ------------------
 1035|  12.8k|        return qpdf::Stream(obj);
 1036|  12.8k|    }
 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.8k|}
_ZN10QPDFObject6createI15QPDF_DictionaryJRKNSt3__13mapINS2_12basic_stringIcNS2_11char_traitsIcEENS2_9allocatorIcEEEE16QPDFObjectHandleNS2_4lessIS9_EENS7_INS2_4pairIKS9_SA_EEEEEEEEENS2_10shared_ptrIS_EEDpOT0_:
  988|  30.0k|{
  989|  30.0k|    return std::make_shared<QPDFObject>(std::forward<T>(T(std::forward<Args>(args)...)));
  990|  30.0k|}
_ZN10QPDFObject6createI15QPDF_DictionaryJNSt3__13mapINS2_12basic_stringIcNS2_11char_traitsIcEENS2_9allocatorIcEEEE16QPDFObjectHandleNS2_4lessIS9_EENS7_INS2_4pairIKS9_SA_EEEEEEEEENS2_10shared_ptrIS_EEDpOT0_:
  988|  7.87k|{
  989|  7.87k|    return std::make_shared<QPDFObject>(std::forward<T>(T(std::forward<Args>(args)...)));
  990|  7.87k|}
_ZN10QPDFObject6createI9QPDF_BoolJRbEEENSt3__110shared_ptrIS_EEDpOT0_:
  988|  6.85k|{
  989|  6.85k|    return std::make_shared<QPDFObject>(std::forward<T>(T(std::forward<Args>(args)...)));
  990|  6.85k|}
_ZN10QPDFObject6createI12QPDF_IntegerJRxEEENSt3__110shared_ptrIS_EEDpOT0_:
  988|  1.11M|{
  989|  1.11M|    return std::make_shared<QPDFObject>(std::forward<T>(T(std::forward<Args>(args)...)));
  990|  1.11M|}
_ZNK4qpdf10BaseHandle2asI12QPDF_IntegerEEPT_v:
  770|  7.87k|    {
  771|  7.87k|        if (!obj) {
  ------------------
  |  Branch (771:13): [True: 0, False: 7.87k]
  ------------------
  772|      0|            return nullptr;
  773|      0|        }
  774|  7.87k|        if (std::holds_alternative<T>(obj->value)) {
  ------------------
  |  Branch (774:13): [True: 7.87k, False: 0]
  ------------------
  775|  7.87k|            return &std::get<T>(obj->value);
  776|  7.87k|        }
  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|  25.3k|{
  989|  25.3k|    return std::make_shared<QPDFObject>(std::forward<T>(T(std::forward<Args>(args)...)));
  990|  25.3k|}
_ZNK4qpdf10BaseHandle2asI9QPDF_NameEEPT_v:
  770|  4.83k|    {
  771|  4.83k|        if (!obj) {
  ------------------
  |  Branch (771:13): [True: 0, False: 4.83k]
  ------------------
  772|      0|            return nullptr;
  773|      0|        }
  774|  4.83k|        if (std::holds_alternative<T>(obj->value)) {
  ------------------
  |  Branch (774:13): [True: 4.83k, False: 0]
  ------------------
  775|  4.83k|            return &std::get<T>(obj->value);
  776|  4.83k|        }
  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.60k|{
  989|  2.60k|    return std::make_shared<QPDFObject>(std::forward<T>(T(std::forward<Args>(args)...)));
  990|  2.60k|}
_ZN10QPDFObject6createI11QPDF_StringJNSt3__112basic_stringIcNS2_11char_traitsIcEENS2_9allocatorIcEEEEEEENS2_10shared_ptrIS_EEDpOT0_:
  988|  4.13k|{
  989|  4.13k|    return std::make_shared<QPDFObject>(std::forward<T>(T(std::forward<Args>(args)...)));
  990|  4.13k|}
_ZN10QPDFObject6createI9QPDF_RealJRKNSt3__112basic_stringIcNS2_11char_traitsIcEENS2_9allocatorIcEEEEEEENS2_10shared_ptrIS_EEDpOT0_:
  988|  6.30k|{
  989|  6.30k|    return std::make_shared<QPDFObject>(std::forward<T>(T(std::forward<Args>(args)...)));
  990|  6.30k|}
_ZN10QPDFObject6createI10QPDF_ArrayJRKNSt3__16vectorI16QPDFObjectHandleNS2_9allocatorIS4_EEEEEEENS2_10shared_ptrIS_EEDpOT0_:
  988|  12.1k|{
  989|  12.1k|    return std::make_shared<QPDFObject>(std::forward<T>(T(std::forward<Args>(args)...)));
  990|  12.1k|}
_ZN15QPDF_DictionaryC2EONSt3__13mapINS0_12basic_stringIcNS0_11char_traitsIcEENS0_9allocatorIcEEEE16QPDFObjectHandleNS0_4lessIS7_EENS5_INS0_4pairIKS7_S8_EEEEEE:
  967|  7.87k|    items(std::move(items))
  968|  7.87k|{
  969|  7.87k|}
_ZNK4qpdf10BaseHandle2asI10QPDF_ArrayEEPT_v:
  770|  1.81M|    {
  771|  1.81M|        if (!obj) {
  ------------------
  |  Branch (771:13): [True: 0, False: 1.81M]
  ------------------
  772|      0|            return nullptr;
  773|      0|        }
  774|  1.81M|        if (std::holds_alternative<T>(obj->value)) {
  ------------------
  |  Branch (774:13): [True: 1.81M, False: 0]
  ------------------
  775|  1.81M|            return &std::get<T>(obj->value);
  776|  1.81M|        }
  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|  8.08k|    {
  330|  8.08k|        return static_cast<qpdf_object_type_e>(value.index());
  331|  8.08k|    }
_ZN10QPDFObjectC2I9QPDF_NullEEOT_:
  300|  28.1k|        value(std::forward<T>(value))
  301|  28.1k|    {
  302|  28.1k|    }
_ZN10QPDF_ArrayC2ERKNSt3__16vectorI16QPDFObjectHandleNS0_9allocatorIS2_EEEE:
   67|  12.1k|        elements(items)
   68|  12.1k|    {
   69|  12.1k|    }
_ZN9QPDF_BoolC2Eb:
   94|  6.85k|        val(val)
   95|  6.85k|    {
   96|  6.85k|    }
_ZN15QPDF_DictionaryC2ERKNSt3__13mapINS0_12basic_stringIcNS0_11char_traitsIcEENS0_9allocatorIcEEEE16QPDFObjectHandleNS0_4lessIS7_EENS5_INS0_4pairIKS7_S8_EEEEEE:
  111|  30.0k|        items(items)
  112|  30.0k|    {
  113|  30.0k|    }
_ZN12QPDF_IntegerC2Ex:
  140|  1.11M|        val(val)
  141|  1.11M|    {
  142|  1.11M|    }
_ZN9QPDF_NameC2ENSt3__112basic_stringIcNS0_11char_traitsIcEENS0_9allocatorIcEEEE:
  154|  25.3k|        name(std::move(name))
  155|  25.3k|    {
  156|  25.3k|    }
_ZN9QPDF_RealC2ENSt3__112basic_stringIcNS0_11char_traitsIcEENS0_9allocatorIcEEEE:
  193|  6.30k|        val(std::move(val))
  194|  6.30k|    {
  195|  6.30k|    }
_ZN14QPDF_ReferenceC2ENSt3__110shared_ptrI10QPDFObjectEE:
  210|  18.5k|        obj(std::move(obj))
  211|  18.5k|    {
  212|  18.5k|    }
_ZN11QPDF_Stream7MembersC2E16QPDFObjectHandlem:
  232|  3.83k|            stream_dict(std::move(stream_dict)),
  233|  3.83k|            length(length)
  234|  3.83k|        {
  235|  3.83k|        }
_ZN11QPDF_StreamC2E16QPDFObjectHandlem:
  254|  3.83k|        m(std::make_unique<Members>(stream_dict, length))
  255|  3.83k|    {
  256|  3.83k|        if (!stream_dict.isDictionary()) {
  ------------------
  |  Branch (256:13): [True: 0, False: 3.83k]
  ------------------
  257|      0|            throw std::logic_error(
  258|      0|                "stream object instantiated with non-dictionary object for dictionary");
  259|      0|        }
  260|  3.83k|    }
_ZN11QPDF_StringC2ERKNSt3__112basic_stringIcNS0_11char_traitsIcEENS0_9allocatorIcEEEE:
  279|  2.60k|        val(val)
  280|  2.60k|    {
  281|  2.60k|    }
_ZN11QPDF_StringC2EONSt3__112basic_stringIcNS0_11char_traitsIcEENS0_9allocatorIcEEEE:
  283|  4.13k|        val(std::move(val))
  284|  4.13k|    {
  285|  4.13k|    }
_ZN10QPDFObject7move_toERNSt3__110shared_ptrIS_EEb:
  343|  18.5k|    {
  344|  18.5k|        o->value = std::move(value);
  345|  18.5k|        o->qpdf = qpdf;
  346|  18.5k|        o->og = og;
  347|  18.5k|        o->object_description = object_description;
  348|  18.5k|        o->parsed_offset = parsed_offset;
  349|  18.5k|        if (!destroy) {
  ------------------
  |  Branch (349:13): [True: 18.5k, False: 0]
  ------------------
  350|  18.5k|            value = QPDF_Reference(o);
  351|  18.5k|        }
  352|  18.5k|    }
_ZN10QPDFObject9setObjGenEP4QPDF10QPDFObjGen:
  364|  18.5k|    {
  365|  18.5k|        qpdf = a_qpdf;
  366|  18.5k|        og = a_og;
  367|  18.5k|    }
_ZN10QPDFObject10JSON_DescrC2ENSt3__110shared_ptrINS1_12basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEEEERKS8_:
  378|  19.5k|            input(input),
  379|  19.5k|            object(object)
  380|  19.5k|        {
  381|  19.5k|        }
_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: 174k, False: 1.79M]
  |  Branch (445:38): [True: 580k, False: 1.21M]
  ------------------
  446|  1.96M|    }
_ZN10QPDFObject15setParsedOffsetEx:
  449|  1.26M|    {
  450|  1.26M|        if (parsed_offset < 0) {
  ------------------
  |  Branch (450:13): [True: 1.24M, False: 20.4k]
  ------------------
  451|  1.24M|            parsed_offset = offset;
  452|  1.24M|        }
  453|  1.26M|    }
_ZN10QPDFObject7getQPDFEv:
  456|   268k|    {
  457|   268k|        return qpdf;
  458|   268k|    }
_ZN10QPDFObject9getObjGenEv:
  461|  68.9k|    {
  462|  68.9k|        return og;
  463|  68.9k|    }
_ZN10QPDFObjectC2I15QPDF_DictionaryEEOT_:
  300|  37.9k|        value(std::forward<T>(value))
  301|  37.9k|    {
  302|  37.9k|    }
_ZN10QPDFObjectC2I9QPDF_BoolEEOT_:
  300|  6.85k|        value(std::forward<T>(value))
  301|  6.85k|    {
  302|  6.85k|    }
_ZN10QPDFObjectC2I12QPDF_IntegerEEOT_:
  300|  1.11M|        value(std::forward<T>(value))
  301|  1.11M|    {
  302|  1.11M|    }
_ZN10QPDFObjectC2I9QPDF_RealEEOT_:
  300|  6.30k|        value(std::forward<T>(value))
  301|  6.30k|    {
  302|  6.30k|    }
_ZN10QPDFObjectC2I11QPDF_StringEEOT_:
  300|  6.74k|        value(std::forward<T>(value))
  301|  6.74k|    {
  302|  6.74k|    }
_ZN10QPDFObjectC2I9QPDF_NameEEOT_:
  300|  25.3k|        value(std::forward<T>(value))
  301|  25.3k|    {
  302|  25.3k|    }
_ZN10QPDFObjectC2I10QPDF_ArrayEEOT_:
  300|  12.1k|        value(std::forward<T>(value))
  301|  12.1k|    {
  302|  12.1k|    }
_ZN10QPDF_ArrayC2EOS_:
   58|  13.4k|    QPDF_Array(QPDF_Array&&) = default;
_ZN10QPDFObject6createI11QPDF_StreamJ16QPDFObjectHandleRmEEENSt3__110shared_ptrIS_EEP4QPDF10QPDFObjGenDpOT0_:
  318|  3.83k|    {
  319|  3.83k|        return std::make_shared<QPDFObject>(
  320|  3.83k|            qpdf, og, std::forward<T>(T(std::forward<Args>(args)...)));
  321|  3.83k|    }
_ZN10QPDFObjectC2I11QPDF_StreamEEP4QPDF10QPDFObjGenOT_:
  306|  3.83k|        value(std::forward<T>(value)),
  307|  3.83k|        qpdf(qpdf),
  308|  3.83k|        og(og)
  309|  3.83k|    {
  310|  3.83k|    }
_ZN10QPDF_ArrayaSEOS_:
   59|    528|    QPDF_Array& operator=(QPDF_Array&&) = default;
_ZN10QPDFObject6createI9QPDF_NullJEEENSt3__110shared_ptrIS_EEP4QPDF10QPDFObjGenDpOT0_:
  318|  13.7k|    {
  319|  13.7k|        return std::make_shared<QPDFObject>(
  320|  13.7k|            qpdf, og, std::forward<T>(T(std::forward<Args>(args)...)));
  321|  13.7k|    }
_ZN10QPDFObjectC2I9QPDF_NullEEP4QPDF10QPDFObjGenOT_:
  306|  13.7k|        value(std::forward<T>(value)),
  307|  13.7k|        qpdf(qpdf),
  308|  13.7k|        og(og)
  309|  13.7k|    {
  310|  13.7k|    }

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

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

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

_ZN4qpdf4util17internal_error_ifIRA28_KcEEvbOT_:
   36|   194k|    {
   37|   194k|        if (cond) {
  ------------------
  |  Branch (37:13): [True: 0, False: 194k]
  ------------------
   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|   194k|    }
_ZN4qpdf4util15hex_decode_charEc:
   99|  1.31M|    {
  100|  1.31M|        return digit <= '9' && digit >= '0'
  ------------------
  |  Branch (100:16): [True: 1.24M, False: 69.8k]
  |  Branch (100:32): [True: 1.15M, False: 88.4k]
  ------------------
  101|  1.31M|            ? char(digit - '0')
  102|  1.31M|            : (digit >= 'a' ? char(digit - 'a' + 10)
  ------------------
  |  Branch (102:16): [True: 47.0k, False: 111k]
  ------------------
  103|   158k|                            : (digit >= 'A' ? char(digit - 'A' + 10) : '\20'));
  ------------------
  |  Branch (103:32): [True: 16.1k, False: 95.1k]
  ------------------
  104|  1.31M|    }
_ZN4qpdf4util12is_hex_digitEc:
  108|  26.2k|    {
  109|  26.2k|        return hex_decode_char(ch) < '\20';
  110|  26.2k|    }
_ZN4qpdf4util8is_spaceEc:
  114|   223k|    {
  115|   223k|        return ch == ' ' || ch == '\n' || ch == '\r' || ch == '\t' || ch == '\f' || ch == '\v';
  ------------------
  |  Branch (115:16): [True: 62.9k, False: 160k]
  |  Branch (115:29): [True: 39.3k, False: 121k]
  |  Branch (115:43): [True: 5, False: 121k]
  |  Branch (115:57): [True: 5, False: 121k]
  |  Branch (115:71): [True: 0, False: 121k]
  |  Branch (115:85): [True: 0, False: 121k]
  ------------------
  116|   223k|    }
_ZN4qpdf4util8is_digitEc:
  120|  8.13M|    {
  121|  8.13M|        return (ch >= '0' && ch <= '9');
  ------------------
  |  Branch (121:17): [True: 6.50M, False: 1.63M]
  |  Branch (121:30): [True: 6.48M, False: 18.5k]
  ------------------
  122|  8.13M|    }
_ZN4qpdf4util9assertionIRA83_KcEEvbOT_:
   27|  23.6k|    {
   28|  23.6k|        if (!cond) {
  ------------------
  |  Branch (28:13): [True: 0, False: 23.6k]
  ------------------
   29|      0|            throw std::logic_error(std::forward<T>(msg));
   30|      0|        }
   31|  23.6k|    }
_ZN4qpdf4util9assertionINSt3__112basic_stringIcNS2_11char_traitsIcEENS2_9allocatorIcEEEEEEvbOT_:
   27|   132k|    {
   28|   132k|        if (!cond) {
  ------------------
  |  Branch (28:13): [True: 0, False: 132k]
  ------------------
   29|      0|            throw std::logic_error(std::forward<T>(msg));
   30|      0|        }
   31|   132k|    }
_ZN4qpdf4util4fitsIjTkNSt3__18integralElQsr3stdE8integralIT_EEEbT0_:
   63|  7.87k|    {
   64|       |        if constexpr (std::cmp_less(
   65|       |                          std::numeric_limits<decltype(val)>::min(),
   66|  7.87k|                          std::numeric_limits<T>::min())) {
   67|  7.87k|            if (std::cmp_less(val, std::numeric_limits<T>::min())) {
  ------------------
  |  Branch (67:17): [True: 0, False: 7.87k]
  ------------------
   68|      0|                return false;
   69|      0|            }
   70|  7.87k|        }
   71|       |        if constexpr (std::cmp_greater(
   72|       |                          std::numeric_limits<decltype(val)>::max(),
   73|  7.87k|                          std::numeric_limits<T>::max())) {
   74|  7.87k|            if (std::cmp_greater(val, std::numeric_limits<T>::max())) {
  ------------------
  |  Branch (74:17): [True: 0, False: 7.87k]
  ------------------
   75|      0|                return false;
   76|      0|            }
   77|  7.87k|        }
   78|  7.87k|        return true;
   79|  7.87k|    }
_ZN4qpdf4util4fitsIjTkNSt3__18integralEiQsr3stdE8integralIT_EEEbT0_:
   63|  7.87k|    {
   64|       |        if constexpr (std::cmp_less(
   65|       |                          std::numeric_limits<decltype(val)>::min(),
   66|  7.87k|                          std::numeric_limits<T>::min())) {
   67|  7.87k|            if (std::cmp_less(val, std::numeric_limits<T>::min())) {
  ------------------
  |  Branch (67:17): [True: 0, False: 7.87k]
  ------------------
   68|      0|                return false;
   69|      0|            }
   70|  7.87k|        }
   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.87k|        return true;
   79|  7.87k|    }
_ZN4qpdf4util4fitsIjTkNSt3__18integralEyQsr3stdE8integralIT_EEEbT0_:
   63|  31.4k|    {
   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|  31.4k|                          std::numeric_limits<T>::max())) {
   74|  31.4k|            if (std::cmp_greater(val, std::numeric_limits<T>::max())) {
  ------------------
  |  Branch (74:17): [True: 0, False: 31.4k]
  ------------------
   75|      0|                return false;
   76|      0|            }
   77|  31.4k|        }
   78|  31.4k|        return true;
   79|  31.4k|    }
_ZN4qpdf4util9assertionIRA40_KcEEvbOT_:
   27|  28.1k|    {
   28|  28.1k|        if (!cond) {
  ------------------
  |  Branch (28:13): [True: 0, False: 28.1k]
  ------------------
   29|      0|            throw std::logic_error(std::forward<T>(msg));
   30|      0|        }
   31|  28.1k|    }
_ZN4qpdf4util9assertionIRA46_KcEEvbOT_:
   27|  28.1k|    {
   28|  28.1k|        if (!cond) {
  ------------------
  |  Branch (28:13): [True: 0, False: 28.1k]
  ------------------
   29|      0|            throw std::logic_error(std::forward<T>(msg));
   30|      0|        }
   31|  28.1k|    }
_ZN4qpdf4util9assertionIRA25_KcEEvbOT_:
   27|   146k|    {
   28|   146k|        if (!cond) {
  ------------------
  |  Branch (28:13): [True: 0, False: 146k]
  ------------------
   29|      0|            throw std::logic_error(std::forward<T>(msg));
   30|      0|        }
   31|   146k|    }
_ZN4qpdf4util9assertionIRA42_KcEEvbOT_:
   27|  14.2k|    {
   28|  14.2k|        if (!cond) {
  ------------------
  |  Branch (28:13): [True: 0, False: 14.2k]
  ------------------
   29|      0|            throw std::logic_error(std::forward<T>(msg));
   30|      0|        }
   31|  14.2k|    }
_ZN4qpdf4util9assertionIRA34_KcEEvbOT_:
   27|  5.86k|    {
   28|  5.86k|        if (!cond) {
  ------------------
  |  Branch (28:13): [True: 0, False: 5.86k]
  ------------------
   29|      0|            throw std::logic_error(std::forward<T>(msg));
   30|      0|        }
   31|  5.86k|    }
_ZN4qpdf4util9assertionIRA72_KcEEvbOT_:
   27|   132k|    {
   28|   132k|        if (!cond) {
  ------------------
  |  Branch (28:13): [True: 0, False: 132k]
  ------------------
   29|      0|            throw std::logic_error(std::forward<T>(msg));
   30|      0|        }
   31|   132k|    }
_ZN4qpdf4util9assertionIRA35_KcEEvbOT_:
   27|  7.87k|    {
   28|  7.87k|        if (!cond) {
  ------------------
  |  Branch (28:13): [True: 0, False: 7.87k]
  ------------------
   29|      0|            throw std::logic_error(std::forward<T>(msg));
   30|      0|        }
   31|  7.87k|    }
_ZN4qpdf4util17internal_error_ifIRA34_KcEEvbOT_:
   36|  15.7k|    {
   37|  15.7k|        if (cond) {
  ------------------
  |  Branch (37:13): [True: 0, False: 15.7k]
  ------------------
   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.7k|    }

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

