diff --git a/stdlib/private/SwiftPrivate/IO.swift b/stdlib/private/SwiftPrivate/IO.swift index 3c0e8d450969b..7af022901c6f1 100644 --- a/stdlib/private/SwiftPrivate/IO.swift +++ b/stdlib/private/SwiftPrivate/IO.swift @@ -100,14 +100,14 @@ public struct _FDOutputStream : TextOutputStream { } public mutating func write(_ string: String) { - let utf8 = string.nulTerminatedUTF8 - utf8.withUnsafeBufferPointer { - (utf8) -> Void in + let utf8CStr = string.utf8CString + utf8CStr.withUnsafeBufferPointer { + (utf8CStr) -> Void in var writtenBytes = 0 - let bufferSize = utf8.count - 1 + let bufferSize = utf8CStr.count - 1 while writtenBytes != bufferSize { let result = _swift_stdlib_write( - self.fd, UnsafePointer(utf8.baseAddress! + Int(writtenBytes)), + self.fd, UnsafeRawPointer(utf8CStr.baseAddress! + Int(writtenBytes)), bufferSize - writtenBytes) if result < 0 { fatalError("write() returned an error") diff --git a/stdlib/private/SwiftPrivateLibcExtras/SwiftPrivateLibcExtras.swift b/stdlib/private/SwiftPrivateLibcExtras/SwiftPrivateLibcExtras.swift index 99742825d1d17..cbcd1f0bef9c3 100644 --- a/stdlib/private/SwiftPrivateLibcExtras/SwiftPrivateLibcExtras.swift +++ b/stdlib/private/SwiftPrivateLibcExtras/SwiftPrivateLibcExtras.swift @@ -22,11 +22,11 @@ public func _stdlib_mkstemps(_ template: inout String, _ suffixlen: CInt) -> CIn #if os(Android) preconditionFailure("mkstemps doesn't work on Android") #else - var utf8 = template.nulTerminatedUTF8 - let (fd, fileName) = utf8.withUnsafeMutableBufferPointer { - (utf8) -> (CInt, String) in - let fd = mkstemps(UnsafeMutablePointer(utf8.baseAddress!), suffixlen) - let fileName = String(cString: utf8.baseAddress!) + var utf8CStr = template.utf8CString + let (fd, fileName) = utf8CStr.withUnsafeMutableBufferPointer { + (utf8CStr) -> (CInt, String) in + let fd = mkstemps(utf8CStr.baseAddress!, suffixlen) + let fileName = String(cString: utf8CStr.baseAddress!) return (fd, fileName) } template = fileName diff --git a/stdlib/public/core/LifetimeManager.swift b/stdlib/public/core/LifetimeManager.swift index 103df7b9e106f..b31aae506d307 100644 --- a/stdlib/public/core/LifetimeManager.swift +++ b/stdlib/public/core/LifetimeManager.swift @@ -43,8 +43,8 @@ extension String { public func withCString( _ body: @noescape (UnsafePointer) throws -> Result ) rethrows -> Result { - return try self.nulTerminatedUTF8.withUnsafeBufferPointer { - try body(UnsafePointer($0.baseAddress!)) + return try self.utf8CString.withUnsafeBufferPointer { + try body($0.baseAddress!) } } } diff --git a/stdlib/public/core/Pointer.swift b/stdlib/public/core/Pointer.swift index ef5aae684da03..2c28762d2468a 100644 --- a/stdlib/public/core/Pointer.swift +++ b/stdlib/public/core/Pointer.swift @@ -87,6 +87,6 @@ public // COMPILER_INTRINSIC func _convertConstStringToUTF8PointerArgument< ToPointer : _Pointer >(_ str: String) -> (AnyObject?, ToPointer) { - let utf8 = Array(str.nulTerminatedUTF8) + let utf8 = Array(str.utf8CString) return _convertConstArrayToPointerArgument(utf8) } diff --git a/stdlib/public/core/StringUTF8.swift b/stdlib/public/core/StringUTF8.swift index 0b23d2f7cec49..009a49608a367 100644 --- a/stdlib/public/core/StringUTF8.swift +++ b/stdlib/public/core/StringUTF8.swift @@ -383,35 +383,21 @@ extension String { return _core.elementWidth == 1 ? _core.startASCII : nil } - /// A contiguously stored null-terminated UTF-8 representation of - /// the string. + /// A contiguously stored null-terminated UTF-8 representation of the string. /// - /// To access the underlying memory, invoke - /// `withUnsafeBufferPointer` on the array. + /// To access the underlying memory, invoke `withUnsafeBufferPointer` on the + /// array. /// /// let s = "Hello!" - /// let bytes = s.nulTerminatedUTF8 + /// let bytes = s.utf8CString /// print(bytes) /// // Prints "[72, 101, 108, 108, 111, 33, 0]" - /// + /// /// bytes.withUnsafeBufferPointer { ptr in - /// print(strlen(UnsafePointer(ptr.baseAddress!))) + /// print(strlen(ptr.baseAddress!)) /// } /// // Prints "6" - public var nulTerminatedUTF8: ContiguousArray { - var result = ContiguousArray() - result.reserveCapacity(utf8.count + 1) - result += utf8 - result.append(0) - return result - } - - /// A contiguously stored null-terminated UTF-8 representation of - /// the string. - /// - /// This is a variation on nulTerminatedUTF8 that creates an array - /// of element type CChar for use with CString API's. - public var nulTerminatedUTF8CString: ContiguousArray { + public var utf8CString: ContiguousArray { var result = ContiguousArray() result.reserveCapacity(utf8.count + 1) for c in utf8 { @@ -428,7 +414,11 @@ extension String { if ptr != nil { return try body(UnsafeBufferPointer(start: ptr, count: _core.count)) } - return try nulTerminatedUTF8.withUnsafeBufferPointer(body) + var nullTerminatedUTF8 = ContiguousArray() + nullTerminatedUTF8.reserveCapacity(utf8.count + 1) + nullTerminatedUTF8 += utf8 + nullTerminatedUTF8.append(0) + return try nullTerminatedUTF8.withUnsafeBufferPointer(body) } /// Creates a string corresponding to the given sequence of UTF-8 code units. @@ -725,3 +715,9 @@ extension String.UTF8View : CustomPlaygroundQuickLookable { } } +extension String { + @available(*, unavailable, message: "Please use String.utf8CString instead.") + public var nulTerminatedUTF8: ContiguousArray { + Builtin.unreachable() + } +} diff --git a/test/1_stdlib/Runtime.swift.gyb b/test/1_stdlib/Runtime.swift.gyb index 42539405fcdd3..be305de7a6eb4 100644 --- a/test/1_stdlib/Runtime.swift.gyb +++ b/test/1_stdlib/Runtime.swift.gyb @@ -13,20 +13,20 @@ import SwiftShims @_silgen_name("swift_demangle") public func _stdlib_demangleImpl( - mangledName: UnsafePointer?, + mangledName: UnsafePointer?, mangledNameLength: UInt, - outputBuffer: UnsafeMutablePointer?, + outputBuffer: UnsafeMutablePointer?, outputBufferSize: UnsafeMutablePointer?, flags: UInt32 ) -> UnsafeMutablePointer? func _stdlib_demangleName(_ mangledName: String) -> String { - return mangledName.nulTerminatedUTF8.withUnsafeBufferPointer { - (mangledNameUTF8) in + return mangledName.utf8CString.withUnsafeBufferPointer { + (mangledNameUTF8CStr) in let demangledNamePtr = _stdlib_demangleImpl( - mangledName: mangledNameUTF8.baseAddress, - mangledNameLength: UInt(mangledNameUTF8.count - 1), + mangledName: mangledNameUTF8CStr.baseAddress, + mangledNameLength: UInt(mangledNameUTF8CStr.count - 1), outputBuffer: nil, outputBufferSize: nil, flags: 0) diff --git a/test/1_stdlib/StringAPI.swift b/test/1_stdlib/StringAPI.swift index 0d67034b87535..f5ebe3753f3d4 100644 --- a/test/1_stdlib/StringAPI.swift +++ b/test/1_stdlib/StringAPI.swift @@ -483,19 +483,17 @@ CStringTests.test("String.decodeCString") { } } -CStringTests.test("String.nulTerminatedUTF8") { +CStringTests.test("String.utf8CString") { do { let (cstr, dealloc) = getASCIICString() let str = String(cString: cstr) - expectEqualCString(cstr, str.nulTerminatedUTF8) - expectEqualCString(cstr, str.nulTerminatedUTF8CString) + expectEqualCString(cstr, str.utf8CString) dealloc() } do { let (cstr, dealloc) = getNonASCIICString() let str = String(cString: cstr) - expectEqualCString(cstr, str.nulTerminatedUTF8) - expectEqualCString(cstr, str.nulTerminatedUTF8CString) + expectEqualCString(cstr, str.utf8CString) dealloc() } } diff --git a/test/1_stdlib/TestData.swift b/test/1_stdlib/TestData.swift index 714b5686d030f..bb9cf15b1af1c 100644 --- a/test/1_stdlib/TestData.swift +++ b/test/1_stdlib/TestData.swift @@ -127,9 +127,11 @@ class TestData : TestDataSuper { // String of course has its own way to get data, but this way tests our own data struct func dataFrom(_ string : String) -> Data { // Create a Data out of those bytes - return string.nulTerminatedUTF8.withUnsafeBufferPointer { (ptr) in - // Subtract 1 so we don't get the null terminator byte. This matches NSString behavior. - return Data(bytes: ptr.baseAddress!, count: ptr.count - 1) + return string.utf8CString.withUnsafeBufferPointer { (ptr) in + ptr.baseAddress!.withMemoryRebound(to: UInt8.self, capacity: ptr.count) { + // Subtract 1 so we don't get the null terminator byte. This matches NSString behavior. + return Data(bytes: $0, count: ptr.count - 1) + } } }