CPDF_Stream* CPDF_Stream::Clone(FX_BOOL bDirect, FPDF_LPFCloneStreamCallback lpfCallback, FX_LPVOID pUserData) const { CPDF_Dictionary *pCloneDict = (CPDF_Dictionary*)m_pDict->Clone(bDirect); IFX_FileStream *pFS = NULL; if (lpfCallback) { pFS = lpfCallback((CPDF_Stream*)this, pUserData); } if (!pFS) { CPDF_StreamAcc acc; acc.LoadAllData(this, TRUE); FX_DWORD streamSize = acc.GetSize(); return new CPDF_Stream(acc.DetachData(), streamSize, pCloneDict); } CPDF_Stream* pObj = new CPDF_Stream(NULL, 0, NULL); CPDF_StreamFilter *pSF = GetStreamFilter(TRUE); if (pSF) { FX_LPBYTE pBuf = FX_Alloc(FX_BYTE, 4096); FX_DWORD dwRead; do { dwRead = pSF->ReadBlock(pBuf, 4096); if (dwRead) { pFS->WriteBlock(pBuf, dwRead); } } while (dwRead == 4096); pFS->Flush(); FX_Free(pBuf); delete pSF; } pObj->InitStream((IFX_FileRead*)pFS, pCloneDict); return pObj; }
CPDF_Object* CPDF_Stream::CloneNonCyclic( bool bDirect, std::set<const CPDF_Object*>* pVisited) const { pVisited->insert(this); CPDF_StreamAcc acc; acc.LoadAllData(this, TRUE); uint32_t streamSize = acc.GetSize(); CPDF_Dictionary* pDict = GetDict(); if (pDict && !pdfium::ContainsKey(*pVisited, pDict)) { pDict = ToDictionary( static_cast<CPDF_Object*>(pDict)->CloneNonCyclic(bDirect, pVisited)); } return new CPDF_Stream(acc.DetachData(), streamSize, pDict); }
CPDF_Object* CPDF_Object::CloneInternal(FX_BOOL bDirect, CFX_MapPtrToPtr* visited) const { switch (m_Type) { case PDFOBJ_BOOLEAN: return new CPDF_Boolean(((CPDF_Boolean*)this)->m_bValue); case PDFOBJ_NUMBER: return new CPDF_Number(((CPDF_Number*)this)->m_bInteger, &((CPDF_Number*)this)->m_Integer); case PDFOBJ_STRING: return new CPDF_String(((CPDF_String*)this)->m_String, ((CPDF_String*)this)->IsHex()); case PDFOBJ_NAME: return new CPDF_Name(((CPDF_Name*)this)->m_Name); case PDFOBJ_ARRAY: { CPDF_Array* pCopy = new CPDF_Array(); CPDF_Array* pThis = (CPDF_Array*)this; int n = pThis->GetCount(); for (int i = 0; i < n; i ++) { CPDF_Object* value = (CPDF_Object*)pThis->m_Objects.GetAt(i); pCopy->m_Objects.Add(value->CloneInternal(bDirect, visited)); } return pCopy; } case PDFOBJ_DICTIONARY: { CPDF_Dictionary* pCopy = new CPDF_Dictionary(); CPDF_Dictionary* pThis = (CPDF_Dictionary*)this; FX_POSITION pos = pThis->m_Map.GetStartPosition(); while (pos) { CFX_ByteString key; CPDF_Object* value; pThis->m_Map.GetNextAssoc(pos, key, (void*&)value); pCopy->m_Map.SetAt(key, value->CloneInternal(bDirect, visited)); } return pCopy; } case PDFOBJ_NULL: { return new CPDF_Null; } case PDFOBJ_STREAM: { CPDF_Stream* pThis = (CPDF_Stream*)this; CPDF_StreamAcc acc; acc.LoadAllData(pThis, TRUE); FX_DWORD streamSize = acc.GetSize(); CPDF_Stream* pObj; if (pThis->GetDict()) pObj = new CPDF_Stream(acc.DetachData(), streamSize, (CPDF_Dictionary*)((CPDF_Object*)pThis->GetDict())->CloneInternal(bDirect, visited)); else pObj = new CPDF_Stream(acc.DetachData(), streamSize, NULL); return pObj; } case PDFOBJ_REFERENCE: { CPDF_Reference* pRef = (CPDF_Reference*)this; FX_DWORD obj_num = pRef->m_RefObjNum; if (bDirect && !visited->GetValueAt((void*)(FX_UINTPTR)obj_num)) { visited->SetAt((void*)(FX_UINTPTR)obj_num, (void*)1); CPDF_Object* ret; if (pRef->GetDirect()) ret = pRef->GetDirect()->CloneInternal(TRUE, visited); else ret = NULL; return ret; } else { return new CPDF_Reference(pRef->m_pObjList, obj_num); } } } return NULL; }
CPDF_Object* CPDF_Object::CloneInternal(FX_BOOL bDirect, std::set<FX_DWORD>* visited) const { switch (m_Type) { case PDFOBJ_BOOLEAN: return new CPDF_Boolean(AsBoolean()->m_bValue); case PDFOBJ_NUMBER: { const CPDF_Number* pThis = AsNumber(); return new CPDF_Number(pThis->m_bInteger ? pThis->m_Integer : pThis->m_Float); } case PDFOBJ_STRING: { const CPDF_String* pString = AsString(); return new CPDF_String(pString->m_String, pString->IsHex()); } case PDFOBJ_NAME: return new CPDF_Name(AsName()->m_Name); case PDFOBJ_ARRAY: { CPDF_Array* pCopy = new CPDF_Array(); const CPDF_Array* pThis = AsArray(); int n = pThis->GetCount(); for (int i = 0; i < n; i++) { CPDF_Object* value = pThis->m_Objects.GetAt(i); pCopy->m_Objects.Add(value->CloneInternal(bDirect, visited)); } return pCopy; } case PDFOBJ_DICTIONARY: { CPDF_Dictionary* pCopy = new CPDF_Dictionary(); const CPDF_Dictionary* pThis = AsDictionary(); for (const auto& it : *pThis) { pCopy->m_Map.insert(std::make_pair( it.first, it.second->CloneInternal(bDirect, visited))); } return pCopy; } case PDFOBJ_NULL: { return new CPDF_Null; } case PDFOBJ_STREAM: { const CPDF_Stream* pThis = AsStream(); CPDF_StreamAcc acc; acc.LoadAllData(pThis, TRUE); FX_DWORD streamSize = acc.GetSize(); CPDF_Dictionary* pDict = pThis->GetDict(); if (pDict) { pDict = ToDictionary(pDict->CloneInternal(bDirect, visited)); } return new CPDF_Stream(acc.DetachData(), streamSize, pDict); } case PDFOBJ_REFERENCE: { const CPDF_Reference* pRef = AsReference(); FX_DWORD obj_num = pRef->GetRefObjNum(); if (bDirect && !pdfium::ContainsKey(*visited, obj_num)) { visited->insert(obj_num); auto* pDirect = pRef->GetDirect(); return pDirect ? pDirect->CloneInternal(TRUE, visited) : nullptr; } return new CPDF_Reference(pRef->m_pObjList, obj_num); } } return NULL; }