From 44032bfd4c9b3a3e56c90942f924d8a1f4d1f308 Mon Sep 17 00:00:00 2001 From: m-holger Date: Mon, 10 Nov 2025 16:45:27 +0000 Subject: [PATCH] Refactor `FormField`: replace `getFullyQualifiedName`, `getPartialName`, `getAlternativeName`, and `getMappingName` with streamlined implementations using `fully_qualified_name`, `partial_name`, `alternative_name`, and `mapping_name`. Simplify logic and enhance consistency across methods. --- libqpdf/QPDFFormFieldObjectHelper.cc | 52 ++++++++++++++++++++++++---------------------------- libqpdf/qpdf/FormField.hh | 80 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--------- qpdf/qpdf.testcov | 4 ---- 3 files changed, 95 insertions(+), 41 deletions(-) diff --git a/libqpdf/QPDFFormFieldObjectHelper.cc b/libqpdf/QPDFFormFieldObjectHelper.cc index efb08ed..a7cd52f 100644 --- a/libqpdf/QPDFFormFieldObjectHelper.cc +++ b/libqpdf/QPDFFormFieldObjectHelper.cc @@ -140,23 +140,24 @@ QPDFFormFieldObjectHelper::getFieldType() std::string QPDFFormFieldObjectHelper::getFullyQualifiedName() { - return m->getFullyQualifiedName(); + return m->fully_qualified_name(); } std::string -FormField::getFullyQualifiedName() +FormField::fully_qualified_name() const { std::string result; - QPDFObjectHandle node = oh(); + auto node = *this; QPDFObjGen::set seen; - while (!node.null() && seen.add(node)) { - if (node.getKey("/T").isString()) { + size_t depth = 0; // Don't bother with loop detection until depth becomes suspicious + while (node && (++depth < 10 || seen.add(node))) { + if (auto T = node.T()) { if (!result.empty()) { - result = "." + result; + result.insert(0, 1, '.'); } - result = node.getKey("/T").getUTF8Value() + result; + result.insert(0, T.utf8_value()); } - node = node.getKey("/Parent"); + node = node.Parent(); } return result; } @@ -164,51 +165,46 @@ FormField::getFullyQualifiedName() std::string QPDFFormFieldObjectHelper::getPartialName() { - return m->getPartialName(); + return m->partial_name(); } std::string -FormField::getPartialName() +FormField::partial_name() const { - std::string result; - if (oh().getKey("/T").isString()) { - result = oh().getKey("/T").getUTF8Value(); + if (auto pn = T()) { + return pn.utf8_value(); } - return result; + return {}; } std::string QPDFFormFieldObjectHelper::getAlternativeName() { - return m->getAlternativeName(); + return m->alternative_name(); } std::string -FormField::getAlternativeName() +FormField::alternative_name() const { - if (oh().getKey("/TU").isString()) { - QTC::TC("qpdf", "QPDFFormFieldObjectHelper TU present"); - return oh().getKey("/TU").getUTF8Value(); + if (auto an = TU()) { + return an.utf8_value(); } - QTC::TC("qpdf", "QPDFFormFieldObjectHelper TU absent"); - return getFullyQualifiedName(); + return fully_qualified_name(); } std::string QPDFFormFieldObjectHelper::getMappingName() { - return m->getMappingName(); + return m->mapping_name(); } std::string -FormField::getMappingName() +FormField::mapping_name() const { - if (oh().getKey("/TM").isString()) { - QTC::TC("qpdf", "QPDFFormFieldObjectHelper TM present"); - return oh().getKey("/TM").getUTF8Value(); + if (auto mn = TM()) { + return mn.utf8_value(); } - QTC::TC("qpdf", "QPDFFormFieldObjectHelper TM absent"); - return getAlternativeName(); + return alternative_name(); } QPDFObjectHandle diff --git a/libqpdf/qpdf/FormField.hh b/libqpdf/qpdf/FormField.hh index 8d8b25f..9dba5a6 100644 --- a/libqpdf/qpdf/FormField.hh +++ b/libqpdf/qpdf/FormField.hh @@ -105,9 +105,10 @@ namespace qpdf::impl std::string inheritable_string(std::string const& name) const; /// @brief Retrieves the field type (/FT attribute). + /// /// @param inherit If set to `true`, the function will attempt to retrieve the value by /// inheritance from the parent hierarchy of the form field. Defaults to `true`. - /// @return Returns the field type if found; otherwise, returns a default-constructed + /// @return Returns the field type if found; otherwise, returns a default-constructed /// `Name`. Name FT(bool inherit = true) const @@ -115,17 +116,78 @@ namespace qpdf::impl return inheritable_value("/FT"); } - std::string getFullyQualifiedName(); + /// @brief Retrieves the partial field name (/T attribute). + /// + /// @return Returns the partial field name if found; otherwise, returns a + /// default-constructed `String`. + String + T() const + { + return {get("/T")}; + } + + /// @brief Retrieves the alternative name (/TU attribute). + /// + /// @return Returns the alternative name if found; otherwise, returns a default-constructed + /// `String`. + String + TU() const + { + return {get("/TU")}; + } + + /// @brief Retrieves the mapping name (/TM attribute). + /// + /// @return Returns the mapping name if found; otherwise, returns a default-constructed + /// `String`. + String + TM() const + { + return {get("/TM")}; + } + + /// @brief Retrieves the fully qualified name of the form field. + /// + /// This method constructs the fully qualified name of the form field by traversing through + /// its parent hierarchy. The fully qualified name is constructed by concatenating the /T + /// (field name) attribute of each parent node with periods as separators, starting from the + /// root of the hierarchy. + /// + /// If the field has no parent hierarchy, the result will simply be the /T attribute of the + /// current field. In cases of potential circular references, loop detection is applied. + /// + /// @return A string representing the fully qualified name of the field. + std::string fully_qualified_name() const; - std::string getPartialName(); + /// @brief Retrieves the partial name (/T attribute) of the form field. + /// + /// This method returns the value of the field's /T attribute, which is the partial name + /// used to identify the field within its parent hierarchy. If the attribute is not set, an + /// empty string is returned. + /// + /// @return A string representing the partial name of the field in UTF-8 encoding, or an + /// empty string if the /T attribute is not present. + std::string partial_name() const; - // Return the alternative field name (/TU), which is the field name intended to be presented - // to users. If not present, fall back to the fully qualified name. - std::string getAlternativeName(); + /// @brief Retrieves the alternative name for the form field. + /// + /// This method attempts to return the alternative name (/TU) of the form field, which is + /// the field name intended to be presented, to users as a UTF-8 string, if it exists. If + /// the alternative name is not present, the method falls back to the fully qualified name + /// of the form field. + /// + /// @return The alternative name of the form field as a string, or the + /// fully qualified name if the alternative name is unavailable. + std::string alternative_name() const; - // Return the mapping field name (/TM). If not present, fall back to the alternative name, - // then to the partial name. - std::string getMappingName(); + /// @brief Retrieves the mapping field name (/TM) for the form field. + /// + /// If the mapping name (/TM) is present, it is returned as a UTF-8 string. If not, it falls + /// back to the 'alternative name', which is obtained using the `alternative_name()` method. + /// + /// @return The mapping field name (/TM) as a UTF-8 string or the alternative name + /// if the mapping name is absent. + std::string mapping_name() const; QPDFObjectHandle getValue(); diff --git a/qpdf/qpdf.testcov b/qpdf/qpdf.testcov index 157e38d..66407cd 100644 --- a/qpdf/qpdf.testcov +++ b/qpdf/qpdf.testcov @@ -174,10 +174,6 @@ QPDFObjectHandle dictionary empty map for asMap 0 QPDFObjectHandle numeric non-numeric 0 QPDFObjectHandle erase array bounds 0 qpdf-c called qpdf_check_pdf 0 -QPDFFormFieldObjectHelper TU present 0 -QPDFFormFieldObjectHelper TM present 0 -QPDFFormFieldObjectHelper TU absent 0 -QPDFFormFieldObjectHelper TM absent 0 QPDFFormFieldObjectHelper Q present 1 QPDFFormFieldObjectHelper DA present 1 QPDFAcroFormDocumentHelper field found 1 -- libgit2 0.21.4