// recover all low level hashs from given data. hashs are assumed to be ordered in left to right - no identifier used bool CAICHHashTree::LoadLowestLevelHashs(CFileDataIO* fileInput){ if (m_nDataSize <= GetBaseSize()){ // sanity // lowest level, read hash m_Hash.Read(fileInput); //theApp.AddDebugLogLine(false,m_Hash.GetString()); m_bHashValid = true; return true; } else{ uint64 nBlocks = m_nDataSize / GetBaseSize() + ((m_nDataSize % GetBaseSize() != 0 )? 1:0); uint64 nLeft = ( ((m_bIsLeftBranch) ? nBlocks+1:nBlocks) / 2)* GetBaseSize(); uint64 nRight = m_nDataSize - nLeft; if (m_pLeftTree == NULL) m_pLeftTree = new CAICHHashTree(nLeft, true, (nLeft <= PARTSIZE) ? EMBLOCKSIZE : PARTSIZE); else{ ASSERT( m_pLeftTree->m_nDataSize == nLeft ); } if (m_pRightTree == NULL) m_pRightTree = new CAICHHashTree(nRight, false, (nRight <= PARTSIZE) ? EMBLOCKSIZE : PARTSIZE); else{ ASSERT( m_pRightTree->m_nDataSize == nRight ); } return m_pLeftTree->LoadLowestLevelHashs(fileInput) && m_pRightTree->LoadLowestLevelHashs(fileInput); } }
// write the hash, specified by wHashIdent, with Data from fileInput. bool CAICHHashTree::SetHash(CFileDataIO* fileInput, uint32 wHashIdent, sint8 nLevel, bool bAllowOverwrite){ if (nLevel == (-1)){ // first call, check how many level we need to go uint8 i; for (i = 0; i != 32 && (wHashIdent & 0x80000000) == 0; i++){ wHashIdent <<= 1; } if (i > 31){ theApp.QueueDebugLogLine(/*DLP_HIGH,*/ false, _T("CAICHHashTree::SetHash - found invalid HashIdent (0)")); return false; } else{ nLevel = 31 - i; } } if (nLevel == 0){ // this is the searched hash if (m_bHashValid && !bAllowOverwrite){ // not allowed to overwrite this hash, however move the filepointer by reading a hash CAICHHash(file); return true; } m_Hash.Read(fileInput); m_bHashValid = true; return true; } else if (m_nDataSize <= GetBaseSize()){ // sanity // this is already the last level, cant go deeper ASSERT( false ); return false; } else{ // adjust ident to point the path to the next node wHashIdent <<= 1; nLevel--; uint64 nBlocks = m_nDataSize / GetBaseSize() + ((m_nDataSize % GetBaseSize() != 0 )? 1:0); uint64 nLeft = ( ((m_bIsLeftBranch) ? nBlocks+1:nBlocks) / 2)* GetBaseSize(); uint64 nRight = m_nDataSize - nLeft; if ((wHashIdent & 0x80000000) > 0){ if (m_pLeftTree == NULL) m_pLeftTree = new CAICHHashTree(nLeft, true, (nLeft <= PARTSIZE) ? EMBLOCKSIZE : PARTSIZE); else{ ASSERT( m_pLeftTree->m_nDataSize == nLeft ); } return m_pLeftTree->SetHash(fileInput, wHashIdent, nLevel); } else{ if (m_pRightTree == NULL) m_pRightTree = new CAICHHashTree(nRight, false, (nRight <= PARTSIZE) ? EMBLOCKSIZE : PARTSIZE); else{ ASSERT( m_pRightTree->m_nDataSize == nRight ); } return m_pRightTree->SetHash(fileInput, wHashIdent, nLevel); } } }
// recursive const CAICHHashTree* CAICHHashTree::FindExistingHash(uint64 nStartPos, uint64 nSize, uint8* nLevel) const { (*nLevel)++; if (*nLevel > 22){ // sanity ASSERT( false ); return false; } if (nStartPos + nSize > m_nDataSize){ // sanity ASSERT ( false ); return NULL; } if (nSize > m_nDataSize){ // sanity ASSERT ( false ); return NULL; } if (nStartPos == 0 && nSize == m_nDataSize){ // this is the searched hash return this; } else if (m_nDataSize <= GetBaseSize()){ // sanity // this is already the last level, cant go deeper ASSERT( false ); return NULL; } else{ uint64 nBlocks = m_nDataSize / GetBaseSize() + ((m_nDataSize % GetBaseSize() != 0 )? 1:0); uint64 nLeft = ( ((m_bIsLeftBranch) ? nBlocks+1:nBlocks) / 2)* GetBaseSize(); uint64 nRight = m_nDataSize - nLeft; if (nStartPos < nLeft){ if (nStartPos + nSize > nLeft){ // sanity ASSERT ( false ); return NULL; } if (m_pLeftTree == NULL) return NULL; else{ ASSERT( m_pLeftTree->m_nDataSize == nLeft ); return m_pLeftTree->FindHash(nStartPos, nSize, nLevel); } } else{ nStartPos -= nLeft; if (nStartPos + nSize > nRight){ // sanity ASSERT ( false ); return NULL; } if (m_pRightTree == NULL) return NULL; else{ ASSERT( m_pRightTree->m_nDataSize == nRight ); return m_pRightTree->FindHash(nStartPos, nSize, nLevel); } } } }
bool CAICHHashTree::CreatePartRecoveryData(uint64 nStartPos, uint64 nSize, CFileDataIO* fileDataOut, uint32 wHashIdent, bool b32BitIdent){ if (nStartPos + nSize > m_nDataSize){ // sanity ASSERT ( false ); return false; } if (nSize > m_nDataSize){ // sanity ASSERT ( false ); return false; } if (nStartPos == 0 && nSize == m_nDataSize){ // this is the searched part, now write all blocks of this part // hashident for this level will be adjsuted by WriteLowestLevelHash return WriteLowestLevelHashs(fileDataOut, wHashIdent, false, b32BitIdent); } else if (m_nDataSize <= GetBaseSize()){ // sanity // this is already the last level, cant go deeper ASSERT( false ); return false; } else{ wHashIdent <<= 1; wHashIdent |= (m_bIsLeftBranch) ? 1: 0; uint64 nBlocks = m_nDataSize / GetBaseSize() + ((m_nDataSize % GetBaseSize() != 0 )? 1:0); uint64 nLeft = ( ((m_bIsLeftBranch) ? nBlocks+1:nBlocks) / 2)* GetBaseSize(); uint64 nRight = m_nDataSize - nLeft; if (m_pLeftTree == NULL || m_pRightTree == NULL){ ASSERT( false ); return false; } if (nStartPos < nLeft){ if (nStartPos + nSize > nLeft || !m_pRightTree->m_bHashValid){ // sanity ASSERT ( false ); return false; } m_pRightTree->WriteHash(fileDataOut, wHashIdent, b32BitIdent); return m_pLeftTree->CreatePartRecoveryData(nStartPos, nSize, fileDataOut, wHashIdent, b32BitIdent); } else{ nStartPos -= nLeft; if (nStartPos + nSize > nRight || !m_pLeftTree->m_bHashValid){ // sanity ASSERT ( false ); return false; } m_pLeftTree->WriteHash(fileDataOut, wHashIdent, b32BitIdent); return m_pRightTree->CreatePartRecoveryData(nStartPos, nSize, fileDataOut, wHashIdent, b32BitIdent); } } }
// write lowest level hashs into file, ordered from left to right optional without identifier bool CAICHHashTree::WriteLowestLevelHashs(CFileDataIO* fileDataOut, uint32 wHashIdent, bool bNoIdent, bool b32BitIdent) const{ wHashIdent <<= 1; wHashIdent |= (m_bIsLeftBranch) ? 1: 0; if (m_pLeftTree == NULL && m_pRightTree == NULL){ if (m_nDataSize <= GetBaseSize() && m_bHashValid ){ if (!bNoIdent && !b32BitIdent){ ASSERT( wHashIdent <= 0xFFFF ); fileDataOut->WriteUInt16((uint16)wHashIdent); } else if (!bNoIdent && b32BitIdent) fileDataOut->WriteUInt32(wHashIdent); m_Hash.Write(fileDataOut); //theApp.AddDebugLogLine(false,_T("%s"),m_Hash.GetString(), wHashIdent, this); return true; } else{ ASSERT( false ); return false; } } else if (m_pLeftTree == NULL || m_pRightTree == NULL){ ASSERT( false ); return false; } else{ return m_pLeftTree->WriteLowestLevelHashs(fileDataOut, wHashIdent, bNoIdent, b32BitIdent) && m_pRightTree->WriteLowestLevelHashs(fileDataOut, wHashIdent, bNoIdent, b32BitIdent); } }
BOOL CRectItem::UpdateExtent() { // get size in pixels CSize size; if (!GetCachedExtent(&size)) return FALSE; // blank Invalidate(); // invalidate the old size/position CSize sizeBase = GetBaseSize(); if (size == sizeBase) // no change return FALSE; // if new object (i.e. m_extent is empty) setup position if (sizeBase == CSize(0,0)) { // convert to document coords CSize sizeNew(MulDiv(size.cx, 10, 254), - MulDiv(size.cy, 10, 254)); SetSize(sizeNew); } else { if (!IsInPlaceActive() && size != sizeBase) { // data changed and not inplace, so scale up rect as well CSize sizeCur = GetSize(); sizeCur.cx = MulDiv(sizeCur.cx, size.cx, sizeBase.cx); sizeCur.cy = - MulDiv(-sizeCur.cy, size.cy, sizeBase.cy); SetSize(sizeCur); } } SetBaseSize(size); Invalidate(); // as well as the new size/position return TRUE; }