std::vector<std::string> EbmlMaster::FindAllMissingElements() { assert(Context.GetSize() != 0); std::vector<std::string> missingElements; for (size_t ChildElementNo = 0; ChildElementNo < ElementList.size(); ChildElementNo++) { EbmlElement *childElement = ElementList[ChildElementNo]; if (!childElement->ValueIsSet()) { std::string missingValue; missingValue = "The Child Element \""; missingValue.append(EBML_NAME(childElement)); missingValue.append("\" of EbmlMaster \""); missingValue.append(EBML_NAME(this)); missingValue.append("\", does not have a value set."); missingElements.push_back(missingValue); } if (childElement->IsMaster()) { EbmlMaster *childMaster = (EbmlMaster *)childElement; std::vector<std::string> childMissingElements = childMaster->FindAllMissingElements(); for (size_t s = 0; s < childMissingElements.size(); s++) missingElements.push_back(childMissingElements[s]); } } unsigned int EltIdx; for (EltIdx = 0; EltIdx < EBML_CTX_SIZE(Context); EltIdx++) { if (EBML_CTX_IDX(Context,EltIdx).IsMandatory()) { if (FindElt(EBML_CTX_IDX_INFO(Context,EltIdx)) == NULL) { std::string missingElement; missingElement = "Missing element \""; missingElement.append(EBML_INFO_NAME(EBML_CTX_IDX_INFO(Context,EltIdx))); missingElement.append("\" in EbmlMaster \""); missingElement.append(EBML_INFO_NAME(*EBML_CTX_MASTER(Context))); missingElement.append("\""); missingElements.push_back(missingElement); } } } return missingElements; }
EbmlElement *EbmlParser::Get( int n_call ) { int i_ulev = 0; EbmlElement *p_prev = NULL; if( mi_user_level != mi_level ) { return NULL; } if( m_got ) { EbmlElement *ret = m_got; m_got = NULL; return ret; } p_prev = m_el[mi_level]; if( m_el[mi_level] ) { m_el[mi_level]->SkipData( *m_es, EBML_CONTEXT(m_el[mi_level]) ); } // If the parent is a segment, use the segment context when creating children // (to prolong their lifetime), otherwise just continue as normal EbmlSemanticContext e_context = EBML_CTX_MASTER( EBML_CONTEXT(m_el[mi_level - 1]) ) == EBML_CTX_MASTER( Context_KaxSegmentVLC ) ? Context_KaxSegmentVLC : EBML_CONTEXT(m_el[mi_level - 1]); /* Ignore unknown level 0 or 1 elements */ m_el[mi_level] = m_es->FindNextElement( e_context, i_ulev, UINT64_MAX, ( mb_dummy | (mi_level > 1) ), 1 ); if( i_ulev > 0 ) { if( p_prev ) { if( !mb_keep ) { if( MKV_IS_ID( p_prev, KaxBlockVirtual ) ) static_cast<KaxBlockVirtualWorkaround*>(p_prev)->Fix(); // !! WARNING : TODO !! this is undefined-behavior delete p_prev; } mb_keep = false; } while( i_ulev > 0 ) { if( mi_level == 1 ) { mi_level = 0; return NULL; } delete m_el[mi_level - 1]; m_got = m_el[mi_level -1] = m_el[mi_level]; m_el[mi_level] = NULL; mi_level--; i_ulev--; } return NULL; } else if( m_el[mi_level] == NULL ) { msg_Dbg( p_demux,"MKV/Ebml Parser: m_el[mi_level] == NULL" ); } else if( m_el[mi_level]->IsDummy() && !mb_dummy ) { bool b_bad_position = false; /* We got a dummy element but don't want those... * perform a sanity check */ if( !mi_level ) { msg_Err(p_demux, "Got invalid lvl 0 element... Aborting"); return NULL; } if( p_prev && p_prev->IsFiniteSize() && p_prev->GetEndPosition() != m_el[mi_level]->GetElementPosition() && mi_level > 1 ) { msg_Err( p_demux, "Dummy Element at unexpected position... corrupted file?" ); b_bad_position = true; } if( n_call < M_EL_MAXSIZE && !b_bad_position && m_el[mi_level]->IsFiniteSize() && ( !m_el[mi_level-1]->IsFiniteSize() || m_el[mi_level]->GetEndPosition() <= m_el[mi_level-1]->GetEndPosition() ) ) { /* The element fits inside its upper element */ msg_Warn( p_demux, "Dummy element found %" PRIu64 "... skipping it", m_el[mi_level]->GetElementPosition() ); return Get( ++n_call ); } else { /* Too large, misplaced or M_EL_MAXSIZE successive dummy elements */ msg_Err( p_demux, "Dummy element too large or misplaced at %" PRIu64 "... skipping to next upper element", m_el[mi_level]->GetElementPosition() ); if( mi_level >= 1 && m_el[mi_level]->GetElementPosition() >= m_el[mi_level-1]->GetEndPosition() ) { msg_Err(p_demux, "This element is outside its known parent... upping level"); delete m_el[mi_level - 1]; m_got = m_el[mi_level -1] = m_el[mi_level]; m_el[mi_level] = NULL; mi_level--; return NULL; } delete m_el[mi_level]; delete p_prev; m_el[mi_level] = NULL; m_el[mi_level - 1]->SkipData( *m_es, EBML_CONTEXT(m_el[mi_level - 1]) ); return Get(); } } if( p_prev ) { if( !mb_keep ) { if( MKV_IS_ID( p_prev, KaxBlockVirtual ) ) static_cast<KaxBlockVirtualWorkaround*>(p_prev)->Fix(); delete p_prev; } mb_keep = false; } return m_el[mi_level]; }