Better encapsulate CXFA_MapModule members. Change-Id: Iea93235f038ae6fdf7ae029deab6eeb97d976665 Reviewed-on: https://pdfium-review.googlesource.com/c/pdfium/+/74750 Reviewed-by: Lei Zhang <thestig@chromium.org> Commit-Queue: Tom Sepez <tsepez@chromium.org>
diff --git a/fxjs/xfa/cjx_object.cpp b/fxjs/xfa/cjx_object.cpp index 9443fc5..03bb379 100644 --- a/fxjs/xfa/cjx_object.cpp +++ b/fxjs/xfa/cjx_object.cpp
@@ -112,8 +112,37 @@ static size_t SizeForCapacity(size_t capacity) { return sizeof(XFA_MAPDATABLOCK) + capacity; } + + static XFA_MAPDATABLOCK* CreateForCapacity(size_t capacity) { + return reinterpret_cast<XFA_MAPDATABLOCK*>( + FX_Alloc(uint8_t, SizeForCapacity(capacity))); + } + + static XFA_MAPDATABLOCK* RepurposeForCapacity(XFA_MAPDATABLOCK* ptr, + size_t capacity) { + if (!ptr) + return CreateForCapacity(capacity); + + ptr->FreeInlineResources(); + if (ptr->iBytes != capacity) { + ptr = reinterpret_cast<XFA_MAPDATABLOCK*>( + FX_Realloc(uint8_t, ptr, SizeForCapacity(capacity))); + } + return ptr; + } + uint8_t* GetData() const { return (uint8_t*)this + sizeof(XFA_MAPDATABLOCK); } + void FreeInlineResources() { + if (pCallbackInfo && pCallbackInfo->pFree) + pCallbackInfo->pFree(*(void**)GetData()); + } + + void AdjustInlineResourcesAfterCopy() { + if (pCallbackInfo && pCallbackInfo->pCopy) + pCallbackInfo->pCopy(*(void**)GetData()); + } + const XFA_MAPDATABLOCKCALLBACKINFO* pCallbackInfo; size_t iBytes; }; @@ -123,6 +152,81 @@ CXFA_MapModule() = default; ~CXFA_MapModule() = default; + void Clear() { + for (auto& pair : m_BufferMap) { + XFA_MAPDATABLOCK* pBuffer = pair.second; + if (pBuffer) { + pBuffer->FreeInlineResources(); + FX_Free(pBuffer); + } + } + m_BufferMap.clear(); + m_ValueMap.clear(); + } + + Optional<int32_t> GetValue(uint32_t key) const { + auto it = m_ValueMap.find(key); + if (it == m_ValueMap.end()) + return pdfium::nullopt; + return it->second; + } + + void SetValue(uint32_t key, int32_t value) { m_ValueMap[key] = value; } + + XFA_MAPDATABLOCK* GetBlock(uint32_t key) const { + auto it = m_BufferMap.find(key); + if (it == m_BufferMap.end()) + return nullptr; + return it->second; + } + + void SetBlock(uint32_t key, XFA_MAPDATABLOCK* block) { + m_BufferMap[key] = block; + } + + bool HasKey(uint32_t key) const { + return pdfium::Contains(m_ValueMap, key) || + pdfium::Contains(m_BufferMap, key); + } + + void RemoveKey(uint32_t key) { + auto it = m_BufferMap.find(key); + if (it != m_BufferMap.end()) { + XFA_MAPDATABLOCK* pBuffer = it->second; + if (pBuffer) { + pBuffer->FreeInlineResources(); + FX_Free(pBuffer); + } + m_BufferMap.erase(it); + } + m_ValueMap.erase(key); + } + + void MergeDataFrom(const CXFA_MapModule* pSrc) { + for (const auto& pair : pSrc->m_ValueMap) + m_ValueMap[pair.first] = pair.second; + + for (const auto& pair : pSrc->m_BufferMap) { + XFA_MAPDATABLOCK* pSrcBuffer = pair.second; + XFA_MAPDATABLOCK*& pDstBuffer = m_BufferMap[pair.first]; + if (pSrcBuffer->pCallbackInfo && pSrcBuffer->pCallbackInfo->pFree && + !pSrcBuffer->pCallbackInfo->pCopy) { + if (pDstBuffer) { + pDstBuffer->FreeInlineResources(); + m_BufferMap.erase(pair.first); + } + continue; + } + pDstBuffer = XFA_MAPDATABLOCK::RepurposeForCapacity(pDstBuffer, + pSrcBuffer->iBytes); + pDstBuffer->pCallbackInfo = pSrcBuffer->pCallbackInfo; + pDstBuffer->iBytes = pSrcBuffer->iBytes; + memcpy(pDstBuffer->GetData(), pSrcBuffer->GetData(), pSrcBuffer->iBytes); + pDstBuffer->AdjustInlineResourcesAfterCopy(); + } + } + + private: // These two are keyed by result of GetMapKey_*(). std::map<uint32_t, int32_t> m_ValueMap; // int/enum/bool represented as int. std::map<uint32_t, XFA_MAPDATABLOCK*> m_BufferMap; @@ -838,7 +942,7 @@ } void CJX_Object::SetMapModuleValue(uint32_t key, int32_t value) { - CreateMapModule()->m_ValueMap[key] = value; + CreateMapModule()->SetValue(key, value); } Optional<int32_t> CJX_Object::GetMapModuleValue(uint32_t key) const { @@ -850,14 +954,14 @@ CXFA_MapModule* pModule = pNode->JSObject()->GetMapModule(); if (pModule) { - auto it = pModule->m_ValueMap.find(key); - if (it != pModule->m_ValueMap.end()) - return it->second; + Optional<int32_t> result = pModule->GetValue(key); + if (result.has_value()) + return result; } if (pNode->GetPacketType() == XFA_PacketType::Datasets) break; } - return {}; + return pdfium::nullopt; } Optional<WideString> CJX_Object::GetMapModuleString(uint32_t key) const { @@ -877,26 +981,13 @@ void* pValue, size_t iBytes, const XFA_MAPDATABLOCKCALLBACKINFO* pCallbackInfo) { - XFA_MAPDATABLOCK*& pBuffer = CreateMapModule()->m_BufferMap[key]; - if (!pBuffer) { - pBuffer = reinterpret_cast<XFA_MAPDATABLOCK*>( - FX_Alloc(uint8_t, XFA_MAPDATABLOCK::SizeForCapacity(iBytes))); - } else if (pBuffer->iBytes != iBytes) { - if (pBuffer->pCallbackInfo && pBuffer->pCallbackInfo->pFree) - pBuffer->pCallbackInfo->pFree(*(void**)pBuffer->GetData()); - - pBuffer = reinterpret_cast<XFA_MAPDATABLOCK*>(FX_Realloc( - uint8_t, pBuffer, XFA_MAPDATABLOCK::SizeForCapacity(iBytes))); - } else if (pBuffer->pCallbackInfo && pBuffer->pCallbackInfo->pFree) { - pBuffer->pCallbackInfo->pFree( - *reinterpret_cast<void**>(pBuffer->GetData())); - } - if (!pBuffer) - return; - + CXFA_MapModule* pModule = CreateMapModule(); + XFA_MAPDATABLOCK* pBuffer = pModule->GetBlock(key); + pBuffer = XFA_MAPDATABLOCK::RepurposeForCapacity(pBuffer, iBytes); pBuffer->pCallbackInfo = pCallbackInfo; pBuffer->iBytes = iBytes; memcpy(pBuffer->GetData(), pValue, iBytes); + pModule->SetBlock(key, pBuffer); } bool CJX_Object::GetMapModuleBuffer(uint32_t key, @@ -911,11 +1002,9 @@ CXFA_MapModule* pModule = pNode->JSObject()->GetMapModule(); if (pModule) { - auto it = pModule->m_BufferMap.find(key); - if (it != pModule->m_BufferMap.end()) { - pBuffer = it->second; + pBuffer = pModule->GetBlock(key); + if (pBuffer) break; - } } if (pNode->GetPacketType() == XFA_PacketType::Datasets) break; @@ -930,129 +1019,62 @@ bool CJX_Object::HasMapModuleKey(uint32_t key) { CXFA_MapModule* pModule = GetMapModule(); - return pModule && (pdfium::Contains(pModule->m_ValueMap, key) || - pdfium::Contains(pModule->m_BufferMap, key)); + return pModule && pModule->HasKey(key); } void CJX_Object::ClearMapModuleBuffer() { CXFA_MapModule* pModule = GetMapModule(); - if (!pModule) - return; - - for (auto& pair : pModule->m_BufferMap) { - XFA_MAPDATABLOCK* pBuffer = pair.second; - if (pBuffer) { - if (pBuffer->pCallbackInfo && pBuffer->pCallbackInfo->pFree) - pBuffer->pCallbackInfo->pFree(*(void**)pBuffer->GetData()); - - FX_Free(pBuffer); - } - } - pModule->m_BufferMap.clear(); - pModule->m_ValueMap.clear(); + if (pModule) + pModule->Clear(); } void CJX_Object::RemoveMapModuleKey(uint32_t key) { CXFA_MapModule* pModule = GetMapModule(); - if (!pModule) - return; - - auto it = pModule->m_BufferMap.find(key); - if (it != pModule->m_BufferMap.end()) { - XFA_MAPDATABLOCK* pBuffer = it->second; - if (pBuffer) { - if (pBuffer->pCallbackInfo && pBuffer->pCallbackInfo->pFree) - pBuffer->pCallbackInfo->pFree(*(void**)pBuffer->GetData()); - - FX_Free(pBuffer); - } - pModule->m_BufferMap.erase(it); - } - pModule->m_ValueMap.erase(key); - return; + if (pModule) + pModule->RemoveKey(key); } -void CJX_Object::MergeAllData(CXFA_Object* pDstModule) { - CXFA_MapModule* pDstModuleData = - ToNode(pDstModule)->JSObject()->CreateMapModule(); - CXFA_MapModule* pSrcModuleData = GetMapModule(); - if (!pSrcModuleData) +void CJX_Object::MergeAllData(CXFA_Object* pDstObj) { + CXFA_MapModule* pDstModule = ToNode(pDstObj)->JSObject()->CreateMapModule(); + CXFA_MapModule* pSrcModule = GetMapModule(); + if (!pSrcModule) return; - for (const auto& pair : pSrcModuleData->m_ValueMap) - pDstModuleData->m_ValueMap[pair.first] = pair.second; - - for (const auto& pair : pSrcModuleData->m_BufferMap) { - XFA_MAPDATABLOCK* pSrcBuffer = pair.second; - XFA_MAPDATABLOCK*& pDstBuffer = pDstModuleData->m_BufferMap[pair.first]; - if (pSrcBuffer->pCallbackInfo && pSrcBuffer->pCallbackInfo->pFree && - !pSrcBuffer->pCallbackInfo->pCopy) { - if (pDstBuffer) { - pDstBuffer->pCallbackInfo->pFree(*(void**)pDstBuffer->GetData()); - pDstModuleData->m_BufferMap.erase(pair.first); - } - continue; - } - if (!pDstBuffer) { - pDstBuffer = (XFA_MAPDATABLOCK*)FX_Alloc( - uint8_t, XFA_MAPDATABLOCK::SizeForCapacity(pSrcBuffer->iBytes)); - } else if (pDstBuffer->iBytes != pSrcBuffer->iBytes) { - if (pDstBuffer->pCallbackInfo && pDstBuffer->pCallbackInfo->pFree) { - pDstBuffer->pCallbackInfo->pFree(*(void**)pDstBuffer->GetData()); - } - pDstBuffer = (XFA_MAPDATABLOCK*)FX_Realloc( - uint8_t, pDstBuffer, - XFA_MAPDATABLOCK::SizeForCapacity(pSrcBuffer->iBytes)); - } else if (pDstBuffer->pCallbackInfo && pDstBuffer->pCallbackInfo->pFree) { - pDstBuffer->pCallbackInfo->pFree(*(void**)pDstBuffer->GetData()); - } - if (!pDstBuffer) - continue; - - pDstBuffer->pCallbackInfo = pSrcBuffer->pCallbackInfo; - pDstBuffer->iBytes = pSrcBuffer->iBytes; - memcpy(pDstBuffer->GetData(), pSrcBuffer->GetData(), pSrcBuffer->iBytes); - if (pDstBuffer->pCallbackInfo && pDstBuffer->pCallbackInfo->pCopy) { - pDstBuffer->pCallbackInfo->pCopy(*(void**)pDstBuffer->GetData()); - } - } + pDstModule->MergeDataFrom(pSrcModule); } -void CJX_Object::MoveBufferMapData(CXFA_Object* pDstModule) { - if (!pDstModule) +void CJX_Object::MoveBufferMapData(CXFA_Object* pDstObj) { + if (!pDstObj) return; - if (pDstModule->GetElementType() == GetXFAObject()->GetElementType()) - ToNode(pDstModule)->JSObject()->TakeCalcDataFrom(this); + if (pDstObj->GetElementType() == GetXFAObject()->GetElementType()) + ToNode(pDstObj)->JSObject()->TakeCalcDataFrom(this); - if (!pDstModule->IsNodeV()) + if (!pDstObj->IsNodeV()) return; - WideString wsValue = ToNode(pDstModule)->JSObject()->GetContent(false); + WideString wsValue = ToNode(pDstObj)->JSObject()->GetContent(false); WideString wsFormatValue(wsValue); - CXFA_Node* pNode = ToNode(pDstModule)->GetContainerNode(); + CXFA_Node* pNode = ToNode(pDstObj)->GetContainerNode(); if (pNode) wsFormatValue = pNode->GetFormatDataValue(wsValue); - ToNode(pDstModule) - ->JSObject() - ->SetContent(wsValue, wsFormatValue, true, true, true); + ToNode(pDstObj)->JSObject()->SetContent(wsValue, wsFormatValue, true, true, + true); } -void CJX_Object::MoveBufferMapData(CXFA_Object* pSrcModule, - CXFA_Object* pDstModule) { - if (!pSrcModule || !pDstModule) +void CJX_Object::MoveBufferMapData(CXFA_Object* pSrcObj, CXFA_Object* pDstObj) { + if (!pSrcObj || !pDstObj) return; - CXFA_Node* pSrcChild = ToNode(pSrcModule)->GetFirstChild(); - CXFA_Node* pDstChild = ToNode(pDstModule)->GetFirstChild(); + CXFA_Node* pSrcChild = ToNode(pSrcObj)->GetFirstChild(); + CXFA_Node* pDstChild = ToNode(pDstObj)->GetFirstChild(); while (pSrcChild && pDstChild) { MoveBufferMapData(pSrcChild, pDstChild); - pSrcChild = pSrcChild->GetNextSibling(); pDstChild = pDstChild->GetNextSibling(); } - ToNode(pSrcModule)->JSObject()->MoveBufferMapData(pDstModule); + ToNode(pSrcObj)->JSObject()->MoveBufferMapData(pDstObj); } void CJX_Object::OnChanging(XFA_Attribute eAttr, bool bNotify) {
diff --git a/fxjs/xfa/cjx_object.h b/fxjs/xfa/cjx_object.h index a19890b..140a17a 100644 --- a/fxjs/xfa/cjx_object.h +++ b/fxjs/xfa/cjx_object.h
@@ -211,7 +211,7 @@ CXFA_Measurement GetMeasure(XFA_Attribute eAttr) const; float GetMeasureInUnit(XFA_Attribute eAttr, XFA_Unit unit) const; - void MergeAllData(CXFA_Object* pDstModule); + void MergeAllData(CXFA_Object* pDstObj); CalcData* GetCalcData() const { return calc_data_; } CalcData* GetOrCreateCalcData(cppgc::Heap* heap); @@ -235,7 +235,7 @@ bool bNotify, bool bScriptModify); void DefineMethods(pdfium::span<const CJX_MethodSpec> methods); - void MoveBufferMapData(CXFA_Object* pSrcModule, CXFA_Object* pDstModule); + void MoveBufferMapData(CXFA_Object* pSrcObj, CXFA_Object* pDstObj); void ThrowException(const WideString& str) const; private: @@ -268,7 +268,7 @@ bool HasMapModuleKey(uint32_t key); void RemoveMapModuleKey(uint32_t key); void ClearMapModuleBuffer(); - void MoveBufferMapData(CXFA_Object* pDstModule); + void MoveBufferMapData(CXFA_Object* pDstObj); cppgc::Member<CXFA_Object> object_; cppgc::Member<CXFA_LayoutItem> layout_item_;