import Foundation public enum RDEPUBCFIGenerator { public static func makeOffsetCFI( href: String, fileIndex: Int, chapterOffset: Int, fragmentID: String? = nil, sideBias: RDEPUBCFISideBias? = nil, textAssertion: RDEPUBCFITextAssertion? = nil, contentPath: RDEPUBCFIPath? = nil ) -> RDEPUBCFI { let packagePath = RDEPUBCFIPath(steps: [ RDEPUBCFIStep(index: 6), RDEPUBCFIStep(index: max((fileIndex + 1) * 2, 2), idAssertion: href) ]) let resolvedContentPath = contentPath ?? RDEPUBCFIPath(steps: [ RDEPUBCFIStep(index: 4), RDEPUBCFIStep(index: 2, idAssertion: fragmentID) ]) return RDEPUBCFI( packagePath: packagePath, contentPath: resolvedContentPath, characterOffset: max(chapterOffset, 0), sideBias: sideBias, textAssertion: textAssertion ) } public static func makeCFI( href: String, fileIndex: Int, contentPath: RDEPUBCFIPath, characterOffset: Int, sideBias: RDEPUBCFISideBias? = nil, textAssertion: RDEPUBCFITextAssertion? = nil ) -> RDEPUBCFI { let packagePath = RDEPUBCFIPath(steps: [ RDEPUBCFIStep(index: 6), RDEPUBCFIStep(index: max((fileIndex + 1) * 2, 2), idAssertion: href) ]) return RDEPUBCFI( packagePath: packagePath, contentPath: contentPath, characterOffset: max(characterOffset, 0), sideBias: sideBias, textAssertion: textAssertion ) } public static func makeOffsetRangeCFI( href: String, fileIndex: Int, startOffset: Int, endOffset: Int, fragmentID: String? = nil, startTextAssertion: RDEPUBCFITextAssertion? = nil, endTextAssertion: RDEPUBCFITextAssertion? = nil, contentPath: RDEPUBCFIPath? = nil ) -> RDEPUBCFIRange { precondition(startOffset <= endOffset, "startOffset (\(startOffset)) must be <= endOffset (\(endOffset))") let start = makeOffsetCFI( href: href, fileIndex: fileIndex, chapterOffset: startOffset, fragmentID: fragmentID, sideBias: .before, textAssertion: startTextAssertion, contentPath: contentPath ) let end = makeOffsetCFI( href: href, fileIndex: fileIndex, chapterOffset: endOffset, fragmentID: fragmentID, sideBias: .after, textAssertion: endTextAssertion, contentPath: contentPath ) let parent = RDEPUBCFI( packagePath: start.packagePath.commonPrefix(with: end.packagePath), contentPath: start.contentPath.commonPrefix(with: end.contentPath) ) return RDEPUBCFIRange(parent: parent, start: start, end: end) } }