Skip to content

Commit 711378d

Browse files
committed
[cxx-interop] Add std.string.withUTF8 method
This new overlay method is a safe alternative to `std.string.__c_strUnsafe()`. rdar://112765666
1 parent 8acfbd8 commit 711378d

File tree

2 files changed

+39
-5
lines changed

2 files changed

+39
-5
lines changed

stdlib/public/Cxx/std/String.swift

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -168,13 +168,9 @@ extension String {
168168
///
169169
/// - Complexity: O(*n*), where *n* is the number of bytes in the C++ string.
170170
public init(_ cxxString: std.string) {
171-
let buffer = UnsafeBufferPointer<CChar>(
172-
start: cxxString.__c_strUnsafe(),
173-
count: cxxString.size())
174-
self = buffer.withMemoryRebound(to: UInt8.self) {
171+
self = cxxString.withUTF8 {
175172
String(decoding: $0, as: UTF8.self)
176173
}
177-
withExtendedLifetime(cxxString) {}
178174
}
179175

180176
/// Creates a String having the same content as the given C++ UTF-16 string.
@@ -193,3 +189,17 @@ extension String {
193189
withExtendedLifetime(cxxU16String) {}
194190
}
195191
}
192+
193+
// MARK: Converting a C++ string to a C string
194+
195+
extension std.string {
196+
@inlinable
197+
public borrowing func withUTF8<Result>(
198+
_ body: (UnsafeBufferPointer<UInt8>) throws -> Result
199+
) rethrows -> Result {
200+
let buffer = UnsafeBufferPointer<CChar>(
201+
start: self.__c_strUnsafe(),
202+
count: self.size())
203+
return try buffer.withMemoryRebound(to: UInt8.self, body)
204+
}
205+
}

test/Interop/Cxx/stdlib/overlay/std-string-overlay.swift

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -256,4 +256,28 @@ StdStringOverlayTestSuite.test("std::string from C string") {
256256
expectEqual(str, std.string("abc"))
257257
}
258258

259+
StdStringOverlayTestSuite.test("std::string to UTF-8") {
260+
std.string().withUTF8 { ptr in
261+
expectEqual(ptr.count, 0)
262+
}
263+
std.string("abc").withUTF8 { ptr in
264+
expectEqual(ptr.count, 3)
265+
expectEqual(ptr.baseAddress?.pointee, 97)
266+
expectEqual(ptr.baseAddress?.successor().pointee, 98)
267+
expectEqual(ptr.baseAddress?.successor().successor().pointee, 99)
268+
}
269+
270+
let bytes: [UInt8] = [0xE1, 0xC1, 0xAC]
271+
var str = std.string()
272+
for byte in bytes {
273+
str.push_back(CChar(bitPattern: byte))
274+
}
275+
str.withUTF8 { ptr in
276+
expectEqual(ptr.count, 3)
277+
expectEqual(ptr.baseAddress?.pointee, 0xE1)
278+
expectEqual(ptr.baseAddress?.successor().pointee, 0xC1)
279+
expectEqual(ptr.baseAddress?.successor().successor().pointee, 0xAC)
280+
}
281+
}
282+
259283
runAllTests()

0 commit comments

Comments
 (0)