QPDFObjectHandle::mergeResources(QPDFObjectHandle other)
{
    if (! (isDictionary() && other.isDictionary()))
    {
        QTC::TC("qpdf", "QPDFObjectHandle merge top type mismatch");
        return;
    }
    std::set<std::string> other_keys = other.getKeys();
    for (std::set<std::string>::iterator iter = other_keys.begin();
         iter != other_keys.end(); ++iter)
    {
        std::string const& key = *iter;
        QPDFObjectHandle other_val = other.getKey(key);
        if (hasKey(key))
        {
            QPDFObjectHandle this_val = getKey(key);
            if (this_val.isDictionary() && other_val.isDictionary())
            {
                if (this_val.isIndirect())
                {
                    QTC::TC("qpdf", "QPDFObjectHandle replace with copy");
                    this_val = this_val.shallowCopy();
                    replaceKey(key, this_val);
                }
                std::set<std::string> other_val_keys = other_val.getKeys();
                for (std::set<std::string>::iterator i2 =
                         other_val_keys.begin();
                     i2 != other_val_keys.end(); ++i2)
                {
                    if (! this_val.hasKey(*i2))
                    {
                        QTC::TC("qpdf", "QPDFObjectHandle merge shallow copy");
                        this_val.replaceKey(
                            *i2, other_val.getKey(*i2).shallowCopy());
                    }
                }
            }
            else if (this_val.isArray() && other_val.isArray())
            {
                std::set<std::string> scalars;
                int n = this_val.getArrayNItems();
                for (int i = 0; i < n; ++i)
                {
                    QPDFObjectHandle this_item = this_val.getArrayItem(i);
                    if (this_item.isScalar())
                    {
                        scalars.insert(this_item.unparse());
                    }
                }
                n = other_val.getArrayNItems();
                for (int i = 0; i < n; ++i)
                {
                    QPDFObjectHandle other_item = other_val.getArrayItem(i);
                    if (other_item.isScalar())
                    {
                        if (scalars.count(other_item.unparse()) == 0)
                        {
                            QTC::TC("qpdf", "QPDFObjectHandle merge array");
                            this_val.appendItem(other_item);
                        }
                        else
                        {
                            QTC::TC("qpdf", "QPDFObjectHandle merge array dup");
                        }
                    }
                }
            }
        }
        else
        {
            QTC::TC("qpdf", "QPDFObjectHandle merge copy from other");
            replaceKey(key, other_val.shallowCopy());
        }
    }
}
QPDFObjectHandle::mergeResources(QPDFObjectHandle other)
{
    if (! (isDictionary() && other.isDictionary()))
    {
        QTC::TC("qpdf", "QPDFObjectHandle merge top type mismatch");
        return;
    }
    std::set<std::string> other_keys = other.getKeys();
    for (std::set<std::string>::iterator iter = other_keys.begin();
         iter != other_keys.end(); ++iter)
    {
        std::string const& key = *iter;
        QPDFObjectHandle other_val = other.getKey(key);
        if (hasKey(key))
        {
            QPDFObjectHandle this_val = getKey(key);
            if (this_val.isDictionary() && other_val.isDictionary())
            {
                if (this_val.isIndirect())
                {
                    QTC::TC("qpdf", "QPDFObjectHandle replace with copy");
                    this_val = this_val.shallowCopy();
                    replaceKey(key, this_val);
                }
                std::set<std::string> other_val_keys = other_val.getKeys();
                for (std::set<std::string>::iterator i2 =
                         other_val_keys.begin();
                     i2 != other_val_keys.end(); ++i2)
                {
                    if (! this_val.hasKey(*i2))
                    {
                        QTC::TC("qpdf", "QPDFObjectHandle merge shallow copy");
                        this_val.replaceKey(
                            *i2, other_val.getKey(*i2).shallowCopy());
                    }
                }
            }
            else if (this_val.isArray() && other_val.isArray())
            {
                std::set<std::string> scalars;
                int n = this_val.getArrayNItems();
                for (int i = 0; i < n; ++i)
                {
                    QPDFObjectHandle this_item = this_val.getArrayItem(i);
                    if (this_item.isScalar())
                    {
                        scalars.insert(this_item.unparse());
                    }
                }
                n = other_val.getArrayNItems();
                for (int i = 0; i < n; ++i)
                {
                    QPDFObjectHandle other_item = other_val.getArrayItem(i);
                    if (other_item.isScalar())
                    {
                        if (scalars.count(other_item.unparse()) == 0)
                        {
                            QTC::TC("qpdf", "QPDFObjectHandle merge array");
                            this_val.appendItem(other_item);
                        }
                        else
                        {
                            QTC::TC("qpdf", "QPDFObjectHandle merge array dup");
                        }
                    }
                }
            }
        }
        else
        {
            QTC::TC("qpdf", "QPDFObjectHandle merge copy from other");
            replaceKey(key, other_val.shallowCopy());
        }
    }
}