<commit_before>// SPDX-FileCopyrightText: 2022 <NAME>
// SPDX-License-Identifier: MPL-2.0

#include <qpdf/Constants.h>
#include <qpdf/Types.h>
#include <qpdf/DLL.h>
#include <qpdf/QPDFExc.hh>
#include <qpdf/PointerHolder.hh>
#include <qpdf/QPDFNameTreeObjectHelper.hh>

#include <pybind11/pybind11.h>
#include <pybind11/stl.h>

#include "pikepdf.h"

// Dummy class to avoid error: undefined symbol: _ZTI24QPDFNameTreeObjectHelper
// That is, "typeinfo for QPDFNameTreeObjectHelper"
// Possibly QPDF needs to export QPDFNameTreeObjectHelper with QPDF_DLL although
// it's not clear why.
// The unique_ptr allows us to hold a QPDFNameTreeObjectHelper without knowing
// its typeinfo. Somehow.
class NameTreeHolder {
public:
    NameTreeHolder(QPDFObjectHandle oh, bool auto_repair = true)
        : ntoh(std::make_unique<QPDFNameTreeObjectHelper>(
              oh, *oh.getOwningQPDF(), auto_repair))
    {
        if (!oh.getOwningQPDF()) {
            throw py::value_error(
                "NameTree must wrap a Dictionary that is owned by a Pdf");
        }
    }

    static NameTreeHolder newEmpty(QPDF &pdf, bool auto_repair = true)
    {
        // Would be a little cleaner to do:
        // auto new_ntoh = QPDFNameTreeObjectHelper::newEmpty(pdf, auto_repair);
        // Then again, it would be clear to eliminate this class entirely.
        // But gcc wants QPDF 10.6.3 to export typeinfo and vtable
        // So work around it for now by duplicating the code in ::newEmpty() to
        // create a root node, make a holder for it.
        auto root = pdf.makeIndirectObject(QPDFObjectHandle::parse("<< /Names [] >>"));
        return NameTreeHolder(root, auto_repair);
    }

    QPDFObjectHandle getObjectHandle() { return this->ntoh->getObjectHandle(); }

    bool hasName(const std::string &utf8) { return this->ntoh->hasName(utf8); }

    bool findObject(const std::string &utf8, QPDFObjectHandle &oh)
    {
        return this->ntoh->findObject(utf8, oh);
    }
<commit_msg>Fix null pointer dereference in NameTreeHolder.<commit_after>// SPDX-FileCopyrightText: 2022 <NAME>
// SPDX-License-Identifier: MPL-2.0

#include <qpdf/Constants.h>
#include <qpdf/Types.h>
#include <qpdf/DLL.h>
#include <qpdf/QPDFExc.hh>
#include <qpdf/PointerHolder.hh>
#include <qpdf/QPDFNameTreeObjectHelper.hh>

#include <pybind11/pybind11.h>
#include <pybind11/stl.h>

#include "pikepdf.h"

// Dummy class to avoid error: undefined symbol: _ZTI24QPDFNameTreeObjectHelper
// That is, "typeinfo for QPDFNameTreeObjectHelper"
// Possibly QPDF needs to export QPDFNameTreeObjectHelper with QPDF_DLL although
// it's not clear why.
// The unique_ptr allows us to hold a QPDFNameTreeObjectHelper without knowing
// its typeinfo. Somehow.
class NameTreeHolder {
public:
    NameTreeHolder(QPDFObjectHandle oh, bool auto_repair = true)
    {
        if (!oh.getOwningQPDF()) {
            throw py::value_error(
                "NameTree must wrap a Dictionary that is owned by a Pdf");
        }
        ntoh = std::make_unique<QPDFNameTreeObjectHelper>(
              oh, *oh.getOwningQPDF(), auto_repair);
    }

    static NameTreeHolder newEmpty(QPDF &pdf, bool auto_repair = true)
    {
        // Would be a little cleaner to do:
        // auto new_ntoh = QPDFNameTreeObjectHelper::newEmpty(pdf, auto_repair);
        // Then again, it would be clear to eliminate this class entirely.
        // But gcc wants QPDF 10.6.3 to export typeinfo and vtable
        // So work around it for now by duplicating the code in ::newEmpty() to
        // create a root node, make a holder for it.
        auto root = pdf.makeIndirectObject(QPDFObjectHandle::parse("<< /Names [] >>"));
        return NameTreeHolder(root, auto_repair);
    }

    QPDFObjectHandle getObjectHandle() { return this->ntoh->getObjectHandle(); }

    bool hasName(const std::string &utf8) { return this->ntoh->hasName(utf8); }

    bool findObject(const std::string &utf8, QPDFObjectHandle &oh)
    {
        return this->ntoh->findObject(utf8, oh);
    }

{'fraction_non_alphanumeric': 0.1095072175211548, 'fraction_numerical': 0.010950721752115481, 'mean_word_length': 3.2664543524416136, 'pattern_counts': {'":': 0, '<': 27, '<?xml version=': 0, '>': 39, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5248231', 'n_tokens_mistral': 1308, 'n_tokens_neox': 1271, 'n_words': 360}