shared_ptr<ManifestItem> Package::ManifestItemForCFI(ePub3::CFI &cfi, CFI* pRemainingCFI) const { ManifestItemPtr result; // NB: Package is a friend of CFI, so it can access the components directly if ( cfi._components.size() < 2 ) { HandleError(EPUBError::CFITooShort, "CFI contains less than 2 nodes, so is invalid for package-based lookups."); } // first item directs us to the Spine: check the index against the one we know auto component = cfi._components[0]; if ( component.nodeIndex != _spineCFIIndex ) { HandleError(EPUBError::CFIInvalidSpineLocation, _Str("CFI first node index (spine) is ", component.nodeIndex, " but should be ", _spineCFIIndex)); // fix it ? //component.nodeIndex = _spineCFIIndex; return nullptr; } // second component is the particular spine item component = cfi._components[1]; if ( !component.IsIndirector() ) { HandleError(EPUBError::CFIUnexpectedComponent, "Package-based CFI's second item must be an indirector"); return nullptr; } try { if ( (component.nodeIndex % 2) == 1 ) throw CFI::InvalidCFI("CFI spine item index is odd, which makes no sense for always-empty spine nodes."); SpineItemPtr item = _spine->at((component.nodeIndex/2) - 1); // check and correct any qualifiers item = ConfirmOrCorrectSpineItemQualifier(item, &component); if ( item == nullptr ) { HandleError(EPUBError::CFIIndirectionTargetMissing, "CFI spine node qualifier doesn't match any spine item idref"); return nullptr; } // we know it's not null, because SpineItem::at() throws an exception if out of range result = ManifestItemWithID(item->Idref()); if ( pRemainingCFI != nullptr ) pRemainingCFI->Assign(cfi, 2); } catch (std::out_of_range& e) { HandleError(EPUBError::CFIStepOutOfBounds, _Str("CFI references out-of-range spine item: ", e.what())); } return result; }
const ManifestItem* Package::ManifestItemForCFI(ePub3::CFI &cfi, CFI* pRemainingCFI) const { const ManifestItem* result = nullptr; // NB: Package is a friend of CFI, so it can access the components directly if ( cfi._components.size() < 2 ) throw CFI::InvalidCFI("CFI contains less than 2 nodes, so is invalid for package-based lookups."); // first item directs us to the Spine: check the index against the one we know auto component = cfi._components[0]; if ( component.nodeIndex != _spineCFIIndex ) { throw CFI::InvalidCFI(_Str("CFI first node index (spine) is ", component.nodeIndex, " but should be ", _spineCFIIndex)); } // second component is the particular spine item component = cfi._components[1]; if ( !component.IsIndirector() ) throw CFI::InvalidCFI("Package-based CFI's second item must be an indirector"); try { if ( (component.nodeIndex % 2) == 1 ) throw CFI::InvalidCFI("CFI spine item index is odd, which makes no sense for always-empty spine nodes."); const SpineItem* item = _spine->at(component.nodeIndex/2); // check and correct any qualifiers item = ConfirmOrCorrectSpineItemQualifier(item, &component); if ( item == nullptr ) throw CFI::InvalidCFI("CFI spine node qualifier doesn't match any spine item idref"); // we know it's not null, because SpineItem::at() throws an exception if out of range result = ManifestItemWithID(item->Idref()); if ( pRemainingCFI != nullptr ) pRemainingCFI->Assign(cfi, 2); } catch (std::out_of_range& e) { throw CFI::InvalidCFI("CFI references out-of-range spine item"); } return result; }