diff --git a/genericfileelement.h b/genericfileelement.h index 2a4a053..bdc2981 100644 --- a/genericfileelement.h +++ b/genericfileelement.h @@ -101,8 +101,8 @@ public: const ImplementationType* firstChild() const; ImplementationType* lastChild(); const ImplementationType* lastChild() const; - ImplementationType* subelementByPath(const std::initializer_list &path, Diagnostics &diag); - ImplementationType* subelementByPath(std::list &path, Diagnostics &diag); + ImplementationType* subelementByPath(Diagnostics &diag, IdentifierType item); + ImplementationType* subelementByPath(Diagnostics &diag, IdentifierType item, IdentifierType remainingPath...); ImplementationType* childById(const IdentifierType &id, Diagnostics &diag); ImplementationType* siblingById(const IdentifierType &id, Diagnostics &diag, bool includeThis = false); bool isParent() const; @@ -522,7 +522,7 @@ inline const ImplementationType *GenericFileElement::lastChi } /*! - * \brief Returns the sub element for the specified \a path. + * \brief Returns the sub element for the specified path. * * The current element keeps ownership over the returned element. * If no element could be found nullptr is returned. @@ -531,41 +531,45 @@ inline const ImplementationType *GenericFileElement::lastChi * \throws Throws std::ios_base::failure when an IO error occurs. */ template -inline ImplementationType *GenericFileElement::subelementByPath(const std::initializer_list &path, Diagnostics &diag) +ImplementationType *GenericFileElement::subelementByPath(Diagnostics &diag, IdentifierType item) { - std::list::IdentifierType> list(path); - return subelementByPath(list, diag); + // ensure element is parsed + parse(diag); + // return the element if it matches the current and last item in the path + if(item == id()) { + return static_cast(this); + } + // check whether a sibling matches the item + if(nextSibling()) { + return nextSibling()->subelementByPath(diag, item); + } + return nullptr; } /*! - * \brief Returns the sub element for the specified \a path. + * \brief Returns the sub element for the specified path. * * The current element keeps ownership over the returned element. * If no element could be found nullptr is returned. - * The specified \a path will modified. * * \throws Throws a parsing exception when a parsing error occurs. * \throws Throws std::ios_base::failure when an IO error occurs. */ template -ImplementationType *GenericFileElement::subelementByPath(std::list &path, Diagnostics &diag) +ImplementationType *GenericFileElement::subelementByPath(Diagnostics &diag, IdentifierType item, IdentifierType remainingPath...) { - parse(diag); // ensure element is parsed - if(path.size()) { - if(path.front() == id()) { - if(path.size() == 1) { - return static_cast(this); - } else { - if(firstChild()) { - path.pop_front(); - return firstChild()->subelementByPath(path, diag); - } - } - } else { - if(nextSibling()) { - return nextSibling()->subelementByPath(path, diag); - } + // ensure element is parsed + parse(diag); + // continue with next item in path if the element matches the current item + if(item == id()) { + if(!firstChild()) { + return nullptr; } + return firstChild()->subelementByPath(diag, remainingPath); + } + // check whether a sibling matches the current item + if(nextSibling()) { + return nextSibling()->subelementByPath(diag, item, remainingPath); } return nullptr; } diff --git a/mp4/mp4container.cpp b/mp4/mp4container.cpp index 867662a..3baf9c6 100644 --- a/mp4/mp4container.cpp +++ b/mp4/mp4container.cpp @@ -50,7 +50,7 @@ ElementPosition Mp4Container::determineTagPosition(Diagnostics &diag) const { if(m_firstElement) { const Mp4Atom *mediaDataAtom = m_firstElement->siblingById(Mp4AtomIds::MediaData, diag); - const Mp4Atom *userDataAtom = m_firstElement->subelementByPath({Mp4AtomIds::Movie, Mp4AtomIds::UserData}, diag); + const Mp4Atom *userDataAtom = m_firstElement->subelementByPath(diag, Mp4AtomIds::Movie, Mp4AtomIds::UserData); if(mediaDataAtom && userDataAtom) { return userDataAtom->startOffset() < mediaDataAtom->startOffset() ? ElementPosition::BeforeData : ElementPosition::AfterData; } @@ -89,7 +89,7 @@ void Mp4Container::internalParseHeader(Diagnostics &diag) void Mp4Container::internalParseTags(Diagnostics &diag) { const string context("parsing tags of MP4 container"); - if(Mp4Atom *udtaAtom = firstElement()->subelementByPath({Mp4AtomIds::Movie, Mp4AtomIds::UserData}, diag)) { + if(Mp4Atom *udtaAtom = firstElement()->subelementByPath(diag, Mp4AtomIds::Movie, Mp4AtomIds::UserData)) { Mp4Atom *metaAtom = udtaAtom->childById(Mp4AtomIds::Meta, diag); bool surplusMetaAtoms = false; while(metaAtom) { @@ -153,7 +153,7 @@ void Mp4Container::internalParseTracks(Diagnostics &diag) diag.emplace_back(DiagLevel::Critical, "mvhd atom is does not exist.", context); } // get mvex atom which holds default values for fragmented files - if(Mp4Atom *mehdAtom = moovAtom->subelementByPath({Mp4AtomIds::MovieExtends, Mp4AtomIds::MovieExtendsHeader}, diag)) { + if(Mp4Atom *mehdAtom = moovAtom->subelementByPath(diag, Mp4AtomIds::MovieExtends, Mp4AtomIds::MovieExtendsHeader)) { m_fragmented = true; if(mehdAtom->dataSize() > 0) { stream().seekg(static_cast(mehdAtom->dataOffset()));