Skip to content

Instantly share code, notes, and snippets.

@iosdevzone
Last active April 22, 2018 13:20
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save iosdevzone/a1525c43128056ee7684d88a62386df0 to your computer and use it in GitHub Desktop.
Save iosdevzone/a1525c43128056ee7684d88a62386df0 to your computer and use it in GitHub Desktop.
A function to find the offsets of newlines ('\n') in UTF-16 encoded string. Try as I might, I cannot get a Swift version within an order of magnitude of the C++ version. Both routines must return arrays of the same size and with equal elements.
#import <Foundation/Foundation.h>
#import <vector> // Needed for gist to compile.
#pragma mark - Pure Implementation Functions
const static unichar kUTF16Newline = (unichar)'\n'; // old naming habits die hard!
/**
* Calculates an array of line end "positions" for a given string.
* The equivalent Swift function was `(String) -> [Int]` or `(NSString) -> [Int]`
*
* In this context a "position" is the zero-based index of a newline
* character in the string as if it were an array of UTF-16 codepoints.
*
* @param s the string.
* @return: an array of newline positions.
*/
std::vector<size_t> LineEndsFind(NSString* s) {
assert(s);
std::vector<size_t> lineEnds;
unichar *const start = (unichar *)[s cStringUsingEncoding:NSUTF16StringEncoding];
unichar *current = start;
while (*current != 0) {
unichar c = *current++;
if (c == kUTF16Newline) {
lineEnds.push_back(current - start);
}
}
return lineEnds;
}
/// This is a first, very Objective-C like version of
/// `makeLineEndArray`.
///
public class func makeLineEndArray(string: NSString) -> [Int] {
precondition(string.length != 0)
var lineEnds = [Int]()
for i in 0..<string.length {
let c = string.character(at: i)
if c == 10 {
lineEnds.append(i)
}
}
print("From swift: (returning line ends) lineEndsCount = \(lineEnds.count)")
return lineEnds
}
/// 2nd more Swifty attempt UTF16 view.
/// Didn't return just for testiing
public class func makeLineEndArray2(string: String) {
precondition(!string.isEmpty)
var lineEnds = [Int]()
for i in 0..<string.utf16.count {
if string.utf16[String.UTF16View.Index(i)] == 10 {
lineEnds.append(i)
}
}
print("From swift: lineEndsCount = \(lineEnds.count)")
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment