QPDF::fixDanglingReferences(bool force)
{
    if (this->m->fixed_dangling_refs && (! force))
    {
        return;
    }
    this->m->fixed_dangling_refs = true;

    // Create a set of all known indirect objects including those
    // we've previously resolved and those that we have created.
    std::set<QPDFObjGen> to_process;
    for (std::map<QPDFObjGen, ObjCache>::iterator iter =
	     this->m->obj_cache.begin();
	 iter != this->m->obj_cache.end(); ++iter)
    {
	to_process.insert((*iter).first);
    }
    for (std::map<QPDFObjGen, QPDFXRefEntry>::iterator iter =
	     this->m->xref_table.begin();
	 iter != this->m->xref_table.end(); ++iter)
    {
	to_process.insert((*iter).first);
    }

    // For each non-scalar item to process, put it in the queue.
    std::list<QPDFObjectHandle> queue;
    queue.push_back(this->m->trailer);
    for (std::set<QPDFObjGen>::iterator iter = to_process.begin();
         iter != to_process.end(); ++iter)
    {
        QPDFObjectHandle obj = QPDFObjectHandle::Factory::newIndirect(
            this, (*iter).getObj(), (*iter).getGen());
        if (obj.isDictionary() || obj.isArray())
        {
            queue.push_back(obj);
        }
        else if (obj.isStream())
        {
            queue.push_back(obj.getDict());
        }
    }

    // Process the queue by recursively resolving all object
    // references. We don't need to do loop detection because we don't
    // traverse known indirect objects when processing the queue.
    while (! queue.empty())
    {
        QPDFObjectHandle obj = queue.front();
        queue.pop_front();
        std::list<QPDFObjectHandle> to_check;
        if (obj.isDictionary())
        {
            std::map<std::string, QPDFObjectHandle> members =
                obj.getDictAsMap();
            for (std::map<std::string, QPDFObjectHandle>::iterator iter =
                     members.begin();
                 iter != members.end(); ++iter)
            {
                to_check.push_back((*iter).second);
            }
        }
        else if (obj.isArray())
        {
            std::vector<QPDFObjectHandle> elements = obj.getArrayAsVector();
            for (std::vector<QPDFObjectHandle>::iterator iter =
                     elements.begin();
                 iter != elements.end(); ++iter)
            {
                to_check.push_back(*iter);
            }
        }
        for (std::list<QPDFObjectHandle>::iterator iter = to_check.begin();
             iter != to_check.end(); ++iter)
        {
            QPDFObjectHandle sub = *iter;
            if (sub.isIndirect())
            {
                if (sub.getOwningQPDF() == this)
                {
                    QPDFObjGen og(sub.getObjGen());
                    if (this->m->obj_cache.count(og) == 0)
                    {
                        QTC::TC("qpdf", "QPDF detected dangling ref");
                        queue.push_back(sub);
                    }
                }
            }
            else
            {
                queue.push_back(sub);
            }
        }

    }
}
QPDF::fixDanglingReferences(bool force)
{
    if (this->m->fixed_dangling_refs && (! force))
    {
        return;
    }
    this->m->fixed_dangling_refs = true;

     
     
    std::set<QPDFObjGen> to_process;
    for (std::map<QPDFObjGen, ObjCache>::iterator iter =
	     this->m->obj_cache.begin();
	 iter != this->m->obj_cache.end(); ++iter)
    {
	to_process.insert((*iter).first);
    }
    for (std::map<QPDFObjGen, QPDFXRefEntry>::iterator iter =
	     this->m->xref_table.begin();
	 iter != this->m->xref_table.end(); ++iter)
    {
	to_process.insert((*iter).first);
    }

     
    std::list<QPDFObjectHandle> queue;
    queue.push_back(this->m->trailer);
    for (std::set<QPDFObjGen>::iterator iter = to_process.begin();
         iter != to_process.end(); ++iter)
    {
        QPDFObjectHandle obj = QPDFObjectHandle::Factory::newIndirect(
            this, (*iter).getObj(), (*iter).getGen());
        if (obj.isDictionary() || obj.isArray())
        {
            queue.push_back(obj);
        }
        else if (obj.isStream())
        {
            queue.push_back(obj.getDict());
        }
    }

     
     
     
    while (! queue.empty())
    {
        QPDFObjectHandle obj = queue.front();
        queue.pop_front();
        std::list<QPDFObjectHandle> to_check;
        if (obj.isDictionary())
        {
            std::map<std::string, QPDFObjectHandle> members =
                obj.getDictAsMap();
            for (std::map<std::string, QPDFObjectHandle>::iterator iter =
                     members.begin();
                 iter != members.end(); ++iter)
            {
                to_check.push_back((*iter).second);
            }
        }
        else if (obj.isArray())
        {
            std::vector<QPDFObjectHandle> elements = obj.getArrayAsVector();
            for (std::vector<QPDFObjectHandle>::iterator iter =
                     elements.begin();
                 iter != elements.end(); ++iter)
            {
                to_check.push_back(*iter);
            }
        }
        for (std::list<QPDFObjectHandle>::iterator iter = to_check.begin();
             iter != to_check.end(); ++iter)
        {
            QPDFObjectHandle sub = *iter;
            if (sub.isIndirect())
            {
                if (sub.getOwningQPDF() == this)
                {
                    QPDFObjGen og(sub.getObjGen());
                    if (this->m->obj_cache.count(og) == 0)
                    {
                        QTC::TC("qpdf", "QPDF detected dangling ref");
                        queue.push_back(sub);
                    }
                }
            }
            else
            {
                queue.push_back(sub);
            }
        }

    }
}