Skip to content

Instantly share code, notes, and snippets.

@milseman
Last active January 29, 2019 21:39
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save milseman/b73a4b07dcf613703cb72363bf377673 to your computer and use it in GitHub Desktop.
Save milseman/b73a4b07dcf613703cb72363bf377673 to your computer and use it in GitHub Desktop.
String Index Explicit Offsets
extension String.Index {
/// Creates a new index at the specified UTF-16 code unit offset
///
/// - Parameter offset: An offset in UTF-16 code units.
public init(offset: Int, within utf16: String.UTF16View) {
let (start, end) = (utf16.startIndex, utf16.endIndex)
guard offset >= 0,
let idx = utf16.index(start, offsetBy: offset, limitedBy: end)
else {
self = end
return
}
self = idx
}
/// Creates a new index at the specified UTF-8 code unit offset
///
/// - Parameter offset: An offset in UTF-8 code units.
public init(offset: Int, within utf8: String.UTF8View) {
let (start, end) = (utf8.startIndex, utf8.endIndex)
guard offset >= 0,
let idx = utf8.index(start, offsetBy: offset, limitedBy: end)
else {
self = end
return
}
self = idx
}
/// Creates a new index at the specified Unicode scalar offset
///
/// - Parameter offset: An offset in terms of Unicode scalar values
public init(offset: Int, within scalars: String.UnicodeScalarView) {
let (start, end) = (scalars.startIndex, scalars.endIndex)
guard offset >= 0,
let idx = scalars.index(start, offsetBy: offset, limitedBy: end)
else {
self = end
return
}
self = idx
}
/// Creates a new index at the specified Character offset
///
/// - Parameter offset: An offset in terms of Characters
public init(offset: Int, within str: String) {
let (start, end) = (str.startIndex, str.endIndex)
guard offset >= 0,
let idx = str.index(start, offsetBy: offset, limitedBy: end)
else {
self = end
return
}
self = idx
}
/// The UTF-16 code unit offset corresponding to this Index
public func offset(within utf16: String.UTF16View) -> Int {
return utf16.distance(from: utf16.startIndex, to: self)
}
/// The UTF-8 code unit offset corresponding to this Index
public func offset(within utf8: String.UTF8View) -> Int {
return utf8.distance(from: utf8.startIndex, to: self)
}
/// The Unicode scalar offset corresponding to this Index
public func offset(within scalars: String.UnicodeScalarView) -> Int {
return scalars.distance(from: scalars.startIndex, to: self)
}
/// The Character offset corresponding to this Index
public func offset(within str: String) -> Int {
return str.distance(from: str.startIndex, to: self)
}
}
let myString = "abcde\u{301}あいう𓀎𓃶"
for index in myString.indices {
print("Character offset: \(index.offset(within: myString))")
}
for index in myString.utf8.indices {
print("UTF-8 offset: \(index.offset(within: myString.utf8))")
}
for index in myString.utf16.indices {
print("UTF-16 offset: \(index.offset(within: myString.utf16))")
}
for index in myString.unicodeScalars.indices {
print("Scalar offset: \(index.offset(within: myString.unicodeScalars))")
}
print("UTF-8")
for i in 0..<myString.utf8.count {
print(myString.utf8[String.Index(offset: i, within: myString.utf8)])
}
print("UTF-16")
for i in 0..<myString.utf16.count {
print(myString.utf16[String.Index(offset: i, within: myString.utf16)])
}
print("Scalars")
for i in 0..<myString.unicodeScalars.count {
print(myString.unicodeScalars[String.Index(offset: i, within: myString.unicodeScalars)])
}
print("Characters")
for i in 0..<myString.count {
print(myString[String.Index(offset: i, within: myString)])
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment