mirror of
https://github.com/TelegramMessenger/Telegram-iOS.git
synced 2026-05-21 18:20:41 +00:00
198 lines
7.0 KiB
Swift
Executable File
198 lines
7.0 KiB
Swift
Executable File
//
|
|
// Created by Mike Griebling on 2022-12-31.
|
|
// Translated from an Objective-C implementation by Kostub Deshmukh.
|
|
//
|
|
// This software may be modified and distributed under the terms of the
|
|
// MIT license. See the LICENSE file for details.
|
|
//
|
|
|
|
import Foundation
|
|
|
|
/**
|
|
* An index that points to a particular character in the MTMathList. The index is a LinkedList that represents
|
|
* a path from the beginning of the MTMathList to reach a particular atom in the list. The next node of the path
|
|
* is represented by the subIndex. The path terminates when the subIndex is nil.
|
|
*
|
|
* If there is a subIndex, the subIndexType denotes what branch the path takes (i.e. superscript, subscript,
|
|
* numerator, denominator etc.).
|
|
* e.g in the expression 25^{2/4} the index of the character 4 is represented as:
|
|
* (1, superscript) -> (0, denominator) -> (0, none)
|
|
* This can be interpreted as start at index 1 (i.e. the 5) go up to the superscript.
|
|
* Then look at index 0 (i.e. 2/4) and go to the denominator. Then look up index 0 (i.e. the 4) which this final
|
|
* index.
|
|
*
|
|
* The level of an index is the number of nodes in the LinkedList to get to the final path.
|
|
*/
|
|
public class MTMathListIndex {
|
|
|
|
/**
|
|
The type of the subindex.
|
|
|
|
The type of the subindex denotes what branch the path to the atom that this index points to takes.
|
|
*/
|
|
public enum MTMathListSubIndexType: Int {
|
|
/// The index denotes the whole atom, subIndex is nil.
|
|
case none = 0
|
|
/// The position in the subindex is an index into the nucleus
|
|
case nucleus
|
|
/// The subindex indexes into the superscript.
|
|
case superscript
|
|
/// The subindex indexes into the subscript
|
|
case ssubscript
|
|
/// The subindex indexes into the numerator (only valid for fractions)
|
|
case numerator
|
|
/// The subindex indexes into the denominator (only valid for fractions)
|
|
case denominator
|
|
/// The subindex indexes into the radicand (only valid for radicals)
|
|
case radicand
|
|
/// The subindex indexes into the degree (only valid for radicals)
|
|
case degree
|
|
}
|
|
|
|
/// The index of the associated atom.
|
|
var atomIndex: Int
|
|
|
|
/// The type of subindex, e.g. superscript, numerator etc.
|
|
var subIndexType: MTMathListSubIndexType = .none
|
|
|
|
/// The index into the sublist.
|
|
var subIndex: MTMathListIndex?
|
|
|
|
var finalIndex: Int {
|
|
if self.subIndexType == .none {
|
|
return self.atomIndex
|
|
} else {
|
|
return self.subIndex?.finalIndex ?? 0
|
|
}
|
|
}
|
|
|
|
/// Returns the previous index if present. Returns `nil` if there is no previous index.
|
|
func prevIndex() -> MTMathListIndex? {
|
|
if self.subIndexType == .none {
|
|
if self.atomIndex > 0 {
|
|
return MTMathListIndex(level0Index: self.atomIndex - 1)
|
|
}
|
|
} else {
|
|
if let prevSubIndex = self.subIndex?.prevIndex() {
|
|
return MTMathListIndex(at: self.atomIndex, with: prevSubIndex, type: self.subIndexType)
|
|
}
|
|
}
|
|
return nil
|
|
}
|
|
|
|
/// Returns the next index.
|
|
func nextIndex() -> MTMathListIndex {
|
|
if self.subIndexType == .none {
|
|
return MTMathListIndex(level0Index: self.atomIndex + 1)
|
|
} else if self.subIndexType == .nucleus {
|
|
return MTMathListIndex(at: self.atomIndex + 1, with: self.subIndex, type: self.subIndexType)
|
|
} else {
|
|
return MTMathListIndex(at: self.atomIndex, with: self.subIndex?.nextIndex(), type: self.subIndexType)
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Returns true if this index represents the beginning of a line. Note there may be multiple lines in a MTMathList,
|
|
* e.g. a superscript or a fraction numerator. This returns true if the innermost subindex points to the beginning of a
|
|
* line.
|
|
*/
|
|
func isBeginningOfLine() -> Bool { self.finalIndex == 0 }
|
|
|
|
func isAtSameLevel(with index: MTMathListIndex?) -> Bool {
|
|
if self.subIndexType != index?.subIndexType {
|
|
return false
|
|
} else if self.subIndexType == .none {
|
|
// No subindexes, they are at the same level.
|
|
return true
|
|
} else if (self.atomIndex != index?.atomIndex) {
|
|
return false
|
|
} else {
|
|
return self.subIndex?.isAtSameLevel(with: index?.subIndex) ?? false
|
|
}
|
|
}
|
|
|
|
/** Returns the type of the innermost sub index. */
|
|
func finalSubIndexType() -> MTMathListSubIndexType {
|
|
if self.subIndex?.subIndex != nil {
|
|
return self.subIndex!.finalSubIndexType()
|
|
} else {
|
|
return self.subIndexType
|
|
}
|
|
}
|
|
|
|
/** Returns true if any of the subIndexes of this index have the given type. */
|
|
func hasSubIndex(ofType type: MTMathListSubIndexType) -> Bool {
|
|
if self.subIndexType == type {
|
|
return true
|
|
} else {
|
|
return self.subIndex?.hasSubIndex(ofType: type) ?? false
|
|
}
|
|
}
|
|
|
|
func levelUp(with subIndex: MTMathListIndex?, type: MTMathListSubIndexType) -> MTMathListIndex {
|
|
if self.subIndexType == .none {
|
|
return MTMathListIndex(at: self.atomIndex, with: subIndex, type: type)
|
|
}
|
|
|
|
return MTMathListIndex(at: self.atomIndex, with: self.subIndex?.levelUp(with: subIndex, type: type), type: self.subIndexType)
|
|
}
|
|
|
|
func levelDown() -> MTMathListIndex? {
|
|
if self.subIndexType == .none {
|
|
return nil
|
|
}
|
|
|
|
if let subIndexDown = self.subIndex?.levelDown() {
|
|
return MTMathListIndex(at: self.atomIndex, with: subIndexDown, type: self.subIndexType)
|
|
} else {
|
|
return MTMathListIndex(level0Index: self.atomIndex)
|
|
}
|
|
}
|
|
|
|
/** Factory function to create a `MTMathListIndex` with no subindexes.
|
|
@param index The index of the atom that the `MTMathListIndex` points at.
|
|
*/
|
|
public init(level0Index: Int) {
|
|
self.atomIndex = level0Index
|
|
}
|
|
|
|
public convenience init(at location: Int, with subIndex: MTMathListIndex?, type: MTMathListSubIndexType) {
|
|
self.init(level0Index: location)
|
|
self.subIndexType = type
|
|
self.subIndex = subIndex
|
|
}
|
|
}
|
|
|
|
extension MTMathListIndex: CustomStringConvertible {
|
|
public var description: String {
|
|
if self.subIndex != nil {
|
|
return "[\(self.atomIndex), \(self.subIndexType.rawValue):\(self.subIndex!)]"
|
|
}
|
|
return "[\(self.atomIndex)]"
|
|
}
|
|
}
|
|
|
|
extension MTMathListIndex: Hashable {
|
|
|
|
public func hash(into hasher: inout Hasher) {
|
|
hasher.combine(self.atomIndex)
|
|
hasher.combine(self.subIndexType)
|
|
hasher.combine(self.subIndex)
|
|
}
|
|
|
|
}
|
|
|
|
extension MTMathListIndex: Equatable {
|
|
public static func ==(lhs: MTMathListIndex, rhs: MTMathListIndex) -> Bool {
|
|
if lhs.atomIndex != rhs.atomIndex || lhs.subIndexType != rhs.subIndexType {
|
|
return false
|
|
}
|
|
|
|
if rhs.subIndex != nil {
|
|
return rhs.subIndex == lhs.subIndex
|
|
} else {
|
|
return lhs.subIndex == nil
|
|
}
|
|
}
|
|
}
|