Files
swift-mirror/stdlib/public/Cxx/std/String.swift
Alex Lorenz c8fa166e58 [cxx][windows] fix the CxxStdlib build for recent MSVC versions after recent regression
The build regressed after cbaef38968 as newer versions of MSVC that aren't used in the OSS CI yet fail to build CxxStdlib now
2024-08-19 10:55:22 -07:00

282 lines
7.8 KiB
Swift

//===----------------------------------------------------------------------===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2022 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//
import CxxStdlibShim
// MARK: Initializing C++ string from a Swift String
extension std.string {
/// Creates a C++ string having the same content as the given Swift string.
///
/// - Complexity: O(*n*), where *n* is the number of UTF-8 code units in the
/// Swift string.
public init(_ string: String) {
self = string.withCString(encodedAs: UTF8.self) { buffer in
#if os(Windows)
// Use the 2 parameter constructor.
// The MSVC standard library has a enable_if template guard
// on the 3 parameter constructor, and thus it's not imported into Swift.
std.string(buffer, string.utf8.count)
#else
std.string(buffer, string.utf8.count, .init())
#endif
}
}
public init(_ string: UnsafePointer<CChar>?) {
if let str = string {
#if os(Windows)
// Use the 2 parameter constructor.
// The MSVC standard library has a enable_if template guard
// on the 3 parameter constructor, and thus it's not imported into Swift.
self.init(str, UTF8._nullCodeUnitOffset(in: str))
#else
self.init(str, UTF8._nullCodeUnitOffset(in: str), .init())
#endif
} else {
self.init()
}
}
}
extension std.u16string {
/// Creates a C++ UTF-16 string having the same content as the given Swift
/// string.
///
/// - Complexity: O(*n*), where *n* is the number of UTF-16 code units in the
/// Swift string.
public init(_ string: String) {
self.init()
for char in string.utf16 {
self.push_back(char)
}
}
}
extension std.u32string {
/// Creates a C++ UTF-32 string having the same content as the given Swift
/// string.
///
/// - Complexity: O(*n*), where *n* is the number of UTF-32 code units in the
/// Swift string.
public init(_ string: String) {
self.init()
for char in string.unicodeScalars {
self.push_back(char)
}
}
}
// MARK: Initializing C++ string from a Swift String literal
extension std.string: ExpressibleByStringLiteral {
public init(stringLiteral value: String) {
self.init(value)
}
}
extension std.u16string: ExpressibleByStringLiteral {
public init(stringLiteral value: String) {
self.init(value)
}
}
extension std.u32string: ExpressibleByStringLiteral {
public init(stringLiteral value: String) {
self.init(value)
}
}
// MARK: Concatenating and comparing C++ strings
extension std.string: Equatable {
public static func ==(lhs: std.string, rhs: std.string) -> Bool {
return lhs.compare(rhs) == 0
}
public static func +=(lhs: inout std.string, rhs: std.string) {
lhs.append(rhs)
}
@inlinable
public mutating func append(_ other: std.string) {
__appendUnsafe(other) // ignore the returned pointer
}
public static func +(lhs: std.string, rhs: std.string) -> std.string {
var copy = lhs
copy += rhs
return copy
}
}
extension std.u16string: Equatable {
public static func ==(lhs: std.u16string, rhs: std.u16string) -> Bool {
return lhs.compare(rhs) == 0
}
public static func +=(lhs: inout std.u16string, rhs: std.u16string) {
lhs.append(rhs)
}
@inlinable
public mutating func append(_ other: std.u16string) {
__appendUnsafe(other) // ignore the returned pointer
}
public static func +(lhs: std.u16string, rhs: std.u16string) -> std.u16string {
var copy = lhs
copy += rhs
return copy
}
}
extension std.u32string: Equatable {
public static func ==(lhs: std.u32string, rhs: std.u32string) -> Bool {
return lhs.compare(rhs) == 0
}
public static func +=(lhs: inout std.u32string, rhs: std.u32string) {
lhs.append(rhs)
}
@inlinable
public mutating func append(_ other: std.u32string) {
__appendUnsafe(other) // ignore the returned pointer
}
public static func +(lhs: std.u32string, rhs: std.u32string) -> std.u32string {
var copy = lhs
copy += rhs
return copy
}
}
// MARK: Hashing C++ strings
extension std.string: Hashable {
public func hash(into hasher: inout Hasher) {
// Call std::hash<std::string>::operator()
let cxxHash = __swift_interopHashOfString().callAsFunction(self)
hasher.combine(cxxHash)
}
}
extension std.u16string: Hashable {
public func hash(into hasher: inout Hasher) {
// Call std::hash<std::u16string>::operator()
let cxxHash = __swift_interopHashOfU16String().callAsFunction(self)
hasher.combine(cxxHash)
}
}
extension std.u32string: Hashable {
public func hash(into hasher: inout Hasher) {
// Call std::hash<std::u32string>::operator()
let cxxHash = __swift_interopHashOfU32String().callAsFunction(self)
hasher.combine(cxxHash)
}
}
// MARK: Getting a Swift description of a C++ string
extension std.string: CustomDebugStringConvertible {
public var debugDescription: String {
return "std.string(\(String(self)))"
}
}
extension std.u16string: CustomDebugStringConvertible {
public var debugDescription: String {
return "std.u16string(\(String(self)))"
}
}
extension std.u32string: CustomDebugStringConvertible {
public var debugDescription: String {
return "std.u32string(\(String(self)))"
}
}
extension std.string: CustomStringConvertible {
public var description: String {
return String(self)
}
}
extension std.u16string: CustomStringConvertible {
public var description: String {
return String(self)
}
}
extension std.u32string: CustomStringConvertible {
public var description: String {
return String(self)
}
}
// MARK: Initializing Swift String from a C++ string
extension String {
/// Creates a String having the same content as the given C++ string.
///
/// If `cxxString` contains ill-formed UTF-8 code unit sequences, this
/// initializer replaces them with the Unicode replacement character
/// (`"\u{FFFD}"`).
///
/// - Complexity: O(*n*), where *n* is the number of bytes in the C++ string.
public init(_ cxxString: std.string) {
let buffer = UnsafeBufferPointer<CChar>(
start: cxxString.__c_strUnsafe(),
count: cxxString.size())
self = buffer.withMemoryRebound(to: UInt8.self) {
String(decoding: $0, as: UTF8.self)
}
withExtendedLifetime(cxxString) {}
}
/// Creates a String having the same content as the given C++ UTF-16 string.
///
/// If `cxxString` contains ill-formed UTF-16 code unit sequences, this
/// initializer replaces them with the Unicode replacement character
/// (`"\u{FFFD}"`).
///
/// - Complexity: O(*n*), where *n* is the number of bytes in the C++ UTF-16
/// string.
public init(_ cxxU16String: std.u16string) {
let buffer = UnsafeBufferPointer<UInt16>(
start: cxxU16String.__dataUnsafe(),
count: cxxU16String.size())
self = String(decoding: buffer, as: UTF16.self)
withExtendedLifetime(cxxU16String) {}
}
/// Creates a String having the same content as the given C++ UTF-32 string.
///
/// If `cxxString` contains ill-formed UTF-32 code unit sequences, this
/// initializer replaces them with the Unicode replacement character
/// (`"\u{FFFD}"`).
///
/// - Complexity: O(*n*), where *n* is the number of bytes in the C++ UTF-32
/// string.
public init(_ cxxU32String: std.u32string) {
let buffer = UnsafeBufferPointer<Unicode.Scalar>(
start: cxxU32String.__dataUnsafe(),
count: cxxU32String.size())
self = buffer.withMemoryRebound(to: UInt32.self) {
String(decoding: $0, as: UTF32.self)
}
withExtendedLifetime(cxxU32String) {}
}
}