stdlib/NSString APIs on String: add more tests and fix a crash in

_countFormatSpecifiers() that was triggered by non-BMP characters in the format
string


Swift SVN r21014
This commit is contained in:
Dmitri Hrybenko
2014-08-04 15:37:58 +00:00
parent ef6748571a
commit a75c7a427a
5 changed files with 42 additions and 22 deletions

View File

@@ -259,6 +259,7 @@ public struct _StringCore {
let p = UnsafeMutablePointer<UInt8>(_pointerToNth(position).value)
// Always dereference two bytes, but when elements are 8 bits we
// multiply the high byte by 0.
// FIXME(performance): use masking instead of multiplication.
return UTF16.CodeUnit(p.memory)
+ UTF16.CodeUnit((p + 1).memory) * _highByteMultiplier
}

View File

@@ -159,7 +159,7 @@ extension String {
}
res = res * 10
var d = Int(c.value - _asUnicodeScalar("0").value)
var d = Int(c.value - UnicodeScalar("0").value)
// Underflow occurs if res - d < Int.min.
if res < Int.min + d {
return .None

View File

@@ -233,16 +233,6 @@ public func <(lhs: UnicodeScalar, rhs: UnicodeScalar) -> Bool {
return lhs.value < rhs.value
}
/// Helper to provide type context to guide type inference in code like::
///
/// var value = digit - _asUnicodeScalar("0")
public func _asUnicodeScalar(us: UnicodeScalar) -> UnicodeScalar {
return us
}
public func _asUTF16CodeUnit(us: UnicodeScalar) -> UTF16.CodeUnit {
return UTF16.CodeUnit(us.value)
}
extension UnicodeScalar {
struct UTF16View {
var value: UnicodeScalar

View File

@@ -35,21 +35,27 @@ func _toNSRange(r: Range<String.Index>) -> NSRange {
}
func _countFormatSpecifiers(a: String) -> Int {
var lastChar = _asUTF16CodeUnit(".") // anything other than % would work here
// The implementation takes advantage of the fact that internal
// representation of String is UTF-16. Because we only care about the ASCII
// percent character, we don't need to decode UTF-16.
let percentUTF16 = UTF16.CodeUnit(("%" as UnicodeScalar).value)
let notPercentUTF16: UTF16.CodeUnit = 0
var lastChar = notPercentUTF16 // anything other than % would work here
var count = 0
for c in a.unicodeScalars {
if lastChar == _asUTF16CodeUnit("%") {
if c == "%" {
for c in a.utf16 {
if lastChar == percentUTF16 {
if c == percentUTF16 {
// a "%" following this one should not be taken as literal
lastChar = _asUTF16CodeUnit(".")
lastChar = notPercentUTF16
}
else {
++count
lastChar = _asUTF16CodeUnit(c)
lastChar = c
}
} else {
lastChar = _asUTF16CodeUnit(c)
lastChar = c
}
}
return count

View File

@@ -717,12 +717,21 @@ NSStringAPIs.test("init(utf16CodeUnitsNoCopy:count:freeWhenDone:)") {
}
NSStringAPIs.test("init(format:_:...)") {
expectEqual("", String(format: ""))
expectEqual(
"abc абв \u{0001F60A}", String(format: "abc абв \u{0001F60A}"))
let world: NSString = "world"
expectEqual("Hello, world!%42",
String(format: "Hello, %@!%%%ld", world, 42))
}
NSStringAPIs.test("init(format:arguments:)") {
expectEqual("", String(format: "", arguments: []))
expectEqual(
"abc абв \u{0001F60A}",
String(format: "abc абв \u{0001F60A}", arguments: []))
let world: NSString = "world"
let args: [CVarArgType] = [ world, 42 ]
expectEqual("Hello, world!%42",
@@ -1079,6 +1088,17 @@ NSStringAPIs.test("stringByAddingPercentEscapesUsingEncoding(_:)") {
}
NSStringAPIs.test("stringByAppendingFormat(_:_:...)") {
expectEqual("", "".stringByAppendingFormat(""))
expectEqual("a", "a".stringByAppendingFormat(""))
expectEqual(
"abc абв \u{0001F60A}",
"abc абв \u{0001F60A}".stringByAppendingFormat(""))
let formatArg: NSString = "привет мир \u{0001F60A}"
expectEqual(
"abc абв \u{0001F60A}def привет мир \u{0001F60A} 42",
"abc абв \u{0001F60A}"
.stringByAppendingFormat("def %@ %ld", formatArg, 42))
// FIXME
}
@@ -1091,7 +1111,10 @@ NSStringAPIs.test("stringByAppendingPathExtension(_:)") {
}
NSStringAPIs.test("stringByAppendingString(_:)") {
// FIXME
expectEqual("", "".stringByAppendingString(""))
expectEqual("a", "a".stringByAppendingString(""))
expectEqual("a", "".stringByAppendingString("a"))
expectEqual("\u{3099}", "".stringByAppendingString("\u{3099}"))
}
NSStringAPIs.test("stringByDeletingLastPathComponent") {