Untitled diff
719 lines
//===----------------------------------------------------------------------===//
//===----------------------------------------------------------------------===//
//
//
// This source file is part of the Swift.org open source project
// This source file is part of the Swift.org open source project
//
//
// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors
// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
// Licensed under Apache License v2.0 with Runtime Library Exception
//
//
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//
//===----------------------------------------------------------------------===//
//===----------------------------------------------------------------------===//
//
//
// Exposing the API of NSString on Swift's String
// Exposing the API of NSString on Swift's String
//
//
//===----------------------------------------------------------------------===//
//===----------------------------------------------------------------------===//
@_exported import Foundation // Clang module
// Open Issues
// Open Issues
// ===========
// ===========
//
//
// Property Lists need to be properly bridged
// Property Lists need to be properly bridged
//
//
func _toNSArray<T, U : AnyObject>(_ a: [T], f: (T) -> U) -> NSArray {
func _toNSArray<T, U : AnyObject>(_ a: [T], f: (T) -> U) -> NSArray {
let result = NSMutableArray(capacity: a.count)
let result = NSMutableArray(capacity: a.count)
for s in a {
for s in a {
result.add(f(s))
result.add(f(s))
}
}
return result
return result
}
}
func _toNSRange(_ r: Range<String.Index>) -> NSRange {
func _toNSRange(_ r: Range<String.Index>) -> NSRange {
return NSRange(
return NSRange(
location: r.lowerBound.encodedOffset,
location: r.lowerBound.encodedOffset,
length: r.upperBound.encodedOffset - r.lowerBound.encodedOffset)
length: r.upperBound.encodedOffset - r.lowerBound.encodedOffset)
}
}
// We only need this for UnsafeMutablePointer, but there's not currently a way
// to write that constraint.
extension Optional {
/// Invokes `body` with `nil` if `self` is `nil`; otherwise, passes the
/// address of `object` to `body`.
///
/// This is intended for use with Foundation APIs that return an Objective-C
/// type via out-parameter where it is important to be able to *ignore* that
/// parameter by passing `nil`. (For some APIs, this may allow the
/// implementation to avoid some work.)
///
/// In most cases it would be simpler to just write this code inline, but if
/// `body` is complicated than that results in unnecessarily repeated code.
internal func _withNilOrAddress<NSType : AnyObject, ResultType>(
of object: inout NSType?,
_ body:
(AutoreleasingUnsafeMutablePointer<NSType?>?) -> ResultType
) -> ResultType {
return self == nil ? body(nil) : body(&object)
}
}
extension String {
extension String {
//===--- Class Methods --------------------------------------------------===//
//===--- Class Methods --------------------------------------------------===//
//===--------------------------------------------------------------------===//
//===--------------------------------------------------------------------===//
// @property (class) const NSStringEncoding *availableStringEncodings;
// @property (class) const NSStringEncoding *availableStringEncodings;
/// An array of the encodings that strings support in the application's
/// An array of the encodings that strings support in the application's
/// environment.
/// environment.
public static var availableStringEncodings: [Encoding] {
public static var availableStringEncodings: [Encoding] {
var result = [Encoding]()
var result = [Encoding]()
var p = NSString.availableStringEncodings
var p = NSString.availableStringEncodings
while p.pointee != 0 {
while p.pointee != 0 {
result.append(Encoding(rawValue: p.pointee))
result.append(Encoding(rawValue: p.pointee))
p += 1
p += 1
}
}
return result
return result
}
}
// @property (class) NSStringEncoding defaultCStringEncoding;
// @property (class) NSStringEncoding defaultCStringEncoding;
/// The C-string encoding assumed for any method accepting a C string as an
/// The C-string encoding assumed for any method accepting a C string as an
/// argument.
/// argument.
public static var defaultCStringEncoding: Encoding {
public static var defaultCStringEncoding: Encoding {
return Encoding(rawValue: NSString.defaultCStringEncoding)
return Encoding(rawValue: NSString.defaultCStringEncoding)
}
}
// + (NSString *)localizedNameOfStringEncoding:(NSStringEncoding)encoding
// + (NSString *)localizedNameOfStringEncoding:(NSStringEncoding)encoding
/// Returns a human-readable string giving the name of the specified encoding.
/// Returns a human-readable string giving the name of the specified encoding.
///
///
/// - Parameter encoding: A string encoding. For possible values, see
/// - Parameter encoding: A string encoding. For possible values, see
/// `String.Encoding`.
/// `String.Encoding`.
/// - Returns: A human-readable string giving the name of `encoding` in the
/// - Returns: A human-readable string giving the name of `encoding` in the
/// current locale.
/// current locale.
public static func localizedName(
public static func localizedName(
of encoding: Encoding
of encoding: Encoding
) -> String {
) -> String {
return NSString.localizedName(of: encoding.rawValue)
return NSString.localizedName(of: encoding.rawValue)
}
}
// + (instancetype)localizedStringWithFormat:(NSString *)format, ...
// + (instancetype)localizedStringWithFormat:(NSString *)format, ...
/// Returns a string created by using a given format string as a
/// Returns a string created by using a given format string as a
/// template into which the remaining argument values are substituted
/// template into which the remaining argument values are substituted
/// according to the user's default locale.
/// according to the user's default locale.
public static func localizedStringWithFormat(
public static func localizedStringWithFormat(
_ format: String, _ arguments: CVarArg...
_ format: String, _ arguments: CVarArg...
) -> String {
) -> String {
return String(format: format, locale: Locale.current,
return String(format: format, locale: Locale.current,
arguments: arguments)
arguments: arguments)
}
}
//===--------------------------------------------------------------------===//
//===--------------------------------------------------------------------===//
// NSString factory functions that have a corresponding constructor
// NSString factory functions that have a corresponding constructor
// are omitted.
// are omitted.
//
//
// + (instancetype)string
// + (instancetype)string
//
//
// + (instancetype)
// + (instancetype)
// stringWithCharacters:(const unichar *)chars length:(NSUInteger)length
// stringWithCharacters:(const unichar *)chars length:(NSUInteger)length
//
//
// + (instancetype)stringWithFormat:(NSString *)format, ...
// + (instancetype)stringWithFormat:(NSString *)format, ...
//
//
// + (instancetype)
// + (instancetype)
// stringWithContentsOfFile:(NSString *)path
// stringWithContentsOfFile:(NSString *)path
// encoding:(NSStringEncoding)enc
// encoding:(NSStringEncoding)enc
// error:(NSError **)error
// error:(NSError **)error
//
//
// + (instancetype)
// + (instancetype)
// stringWithContentsOfFile:(NSString *)path
// stringWithContentsOfFile:(NSString *)path
// usedEncoding:(NSStringEncoding *)enc
// usedEncoding:(NSStringEncoding *)enc
// error:(NSError **)error
// error:(NSError **)error
//
//
// + (instancetype)
// + (instancetype)
// stringWithContentsOfURL:(NSURL *)url
// stringWithContentsOfURL:(NSURL *)url
// encoding:(NSStringEncoding)enc
// encoding:(NSStringEncoding)enc
// error:(NSError **)error
// error:(NSError **)error
//
//
// + (instancetype)
// + (instancetype)
// stringWithContentsOfURL:(NSURL *)url
// stringWithContentsOfURL:(NSURL *)url
// usedEncoding:(NSStringEncoding *)enc
// usedEncoding:(NSStringEncoding *)enc
// error:(NSError **)error
// error:(NSError **)error
//
//
// + (instancetype)
// + (instancetype)
// stringWithCString:(const char *)cString
// stringWithCString:(const char *)cString
// encoding:(NSStringEncoding)enc
// encoding:(NSStringEncoding)enc
//===--------------------------------------------------------------------===//
//===--------------------------------------------------------------------===//
//===--- Adds nothing for String beyond what String(s) does -------------===//
//===--- Adds nothing for String beyond what String(s) does -------------===//
// + (instancetype)stringWithString:(NSString *)aString
// + (instancetype)stringWithString:(NSString *)aString
//===--------------------------------------------------------------------===//
//===--------------------------------------------------------------------===//
// + (instancetype)stringWithUTF8String:(const char *)bytes
// + (instancetype)stringWithUTF8String:(const char *)bytes
/// Creates a string by copying the data from a given
/// Creates a string by copying the data from a given
/// C array of UTF8-encoded bytes.
/// C array of UTF8-encoded bytes.
public init?(utf8String bytes: UnsafePointer<CChar>) {
public init?(utf8String bytes: UnsafePointer<CChar>) {
if let ns = NSString(utf8String: bytes) {
if let ns = NSString(utf8String: bytes) {
self = ns as String
self = ns._swiftObject
} else {
} else {
return nil
return nil
}
}
}
}
}
}
extension String {
extension String {
//===--- Already provided by String's core ------------------------------===//
//===--- Already provided by String's core ------------------------------===//
// - (instancetype)init
// - (instancetype)init
//===--- Initializers that can fail -------------------------------------===//
//===--- Initializers that can fail -------------------------------------===//
// - (instancetype)
// - (instancetype)
// initWithBytes:(const void *)bytes
// initWithBytes:(const void *)bytes
// length:(NSUInteger)length
// length:(NSUInteger)length
// encoding:(NSStringEncoding)encoding
// encoding:(NSStringEncoding)encoding
/// Creates a new string equivalent to the given bytes interpreted in the
/// Creates a new string equivalent to the given bytes interpreted in the
/// specified encoding.
/// specified encoding.
///
///
/// - Parameters:
/// - Parameters:
/// - bytes: A sequence of bytes to interpret using `encoding`.
/// - bytes: A sequence of bytes to interpret using `encoding`.
/// - encoding: The ecoding to use to interpret `bytes`.
/// - encoding: The ecoding to use to interpret `bytes`.
public init? <S: Sequence>(bytes: S, encoding: Encoding)
public init? <S: Sequence>(bytes: S, encoding: Encoding)
where S.Iterator.Element == UInt8 {
where S.Iterator.Element == UInt8 {
let byteArray = Array(bytes)
let byteArray = Array(bytes)
if let ns = NSString(
if let ns = NSString(
bytes: byteArray, length: byteArray.count, encoding: encoding.rawValue) {
bytes: byteArray, length: byteArray.count, encoding: encoding.rawValue) {
self = String._unconditionallyBridgeFromObjectiveC(ns)
self = ns as String
} else {
} else {
return nil
return nil
}
}
}
}
// - (instancetype)
// - (instancetype)
// initWithBytesNoCopy:(void *)bytes
// initWithBytesNoCopy:(void *)bytes
// length:(NSUInteger)length
// length:(NSUInteger)length
// encoding:(NSStringEncoding)encoding
// encoding:(NSStringEncoding)encoding
// freeWhenDone:(BOOL)flag
// freeWhenDone:(BOOL)flag
/// Creates a new string that contains the specified number of bytes from the
/// Creates a new string that contains the specified number of bytes from the
/// given buffer, interpreted in the specified encoding, and optionally
/// given buffer, interpreted in the specified encoding, and optionally
/// frees the buffer.
/// frees the buffer.
///
///
/// - Warning: This initializer is not memory-safe!
/// - Warning: This initializer is not memory-safe!
public init?(
public init?(
bytesNoCopy bytes: UnsafeMutableRawPointer, length: Int,
bytesNoCopy bytes: UnsafeMutableRawPointer, length: Int,
encoding: Encoding, freeWhenDone flag: Bool
encoding: Encoding, freeWhenDone flag: Bool
) {
) {
if let ns = NSString(
if let ns = NSString(
bytesNoCopy: bytes, length: length, encoding: encoding.rawValue,
bytesNoCopy: bytes, length: length, encoding: encoding.rawValue,
freeWhenDone: flag) {
freeWhenDone: flag) {
self = String._unconditionallyBridgeFromObjectiveC(ns)
self = ns as String
} else {
} else {
return nil
return nil
}
}
}
}
// - (instancetype)
// - (instancetype)
// initWithCharacters:(const unichar *)characters
// initWithCharacters:(const unichar *)characters
// length:(NSUInteger)length
// length:(NSUInteger)length
/// Creates a new string that contains the specified number of characters
/// Creates a new string that contains the specified number of characters
/// from the given C array of Unicode characters.
/// from the given C array of Unicode characters.
public init(
public init(
utf16CodeUnits: UnsafePointer<unichar>,
utf16CodeUnits: UnsafePointer<unichar>,
count: Int
count: Int
) {
) {
self = NSString(characters: utf16CodeUnits, length: count) as String
self = String._unconditionallyBridgeFromObjectiveC(NSString(characters: utf16CodeUnits, length: count))
}
}
// - (instancetype)
// - (instancetype)
// initWithCharactersNoCopy:(unichar *)characters
// initWithCharactersNoCopy:(unichar *)characters
// length:(NSUInteger)length
// length:(NSUInteger)length
// freeWhenDone:(BOOL)flag
// freeWhenDone:(BOOL)flag
/// Creates a new string that contains the specified number of characters
/// Creates a new string that contains the specified number of characters
/// from the given C array of UTF-16 code units.
/// from the given C array of UTF-16 code units.
public init(
public init(
utf16CodeUnitsNoCopy: UnsafePointer<unichar>,
utf16CodeUnitsNoCopy: UnsafePointer<unichar>,
count: Int,
count: Int,
freeWhenDone flag: Bool
freeWhenDone flag: Bool
) {
) {
self = NSString(
self = String._unconditionallyBridgeFromObjectiveC(NSString(
charactersNoCopy: UnsafeMutablePointer(mutating: utf16CodeUnitsNoCopy),
charactersNoCopy: UnsafeMutablePointer(mutating: utf16CodeUnitsNoCopy),
length: count,
length: count,
freeWhenDone: flag) as String
freeWhenDone: flag))
}
}
//===--- Initializers that can fail -------------------------------------===//
//===--- Initializers that can fail -------------------------------------===//
// - (instancetype)
// - (instancetype)
// initWithContentsOfFile:(NSString *)path
// initWithContentsOfFile:(NSString *)path
// encoding:(NSStringEncoding)enc
// encoding:(NSStringEncoding)enc
// error:(NSError **)error
// error:(NSError **)error
//
//
/// Produces a string created by reading data from the file at a
/// Produces a string created by reading data from the file at a
/// given path interpreted using a given encoding.
/// given path interpreted using a given encoding.
public init(
public init(
contentsOfFile path: String,
contentsOfFile path: String,
encoding enc: Encoding
encoding enc: Encoding
) throws {
) throws {
let ns = try NSString(contentsOfFile: path, encoding: enc.rawValue)
let ns = try NSString(contentsOfFile: path, encoding: enc.rawValue)
self = ns as String
self = String._unconditionallyBridgeFromObjectiveC(ns)
}
}
// - (instancetype)
// - (instancetype)
// initWithContentsOfFile:(NSString *)path
// initWithContentsOfFile:(NSString *)path
// usedEncoding:(NSStringEncoding *)enc
// usedEncoding:(NSStringEncoding *)enc
// error:(NSError **)error
// error:(NSError **)error
/// Produces a string created by reading data from the file at
/// Produces a string created by reading data from the file at
/// a given path and returns by reference the encoding used to
/// a given path and returns by reference the encoding used to
/// interpret the file.
/// interpret the file.
public init(
public init(
contentsOfFile path: String,
contentsOfFile path: String,
usedEncoding: inout Encoding
usedEncoding: inout Encoding
) throws {
) throws {
var enc: UInt = 0
var enc: UInt = 0
let ns = try NSString(contentsOfFile: path, usedEncoding: &enc)
let ns = try NSString(contentsOfFile: path, usedEncoding: &enc)
usedEncoding = Encoding(rawValue: enc)
usedEncoding = Encoding(rawValue: enc)
self = ns as String
self = String._unconditionallyBridgeFromObjectiveC(ns)
}
}
public init(
public init(
contentsOfFile path: String
contentsOfFile path: String
) throws {
) throws {
let ns = try NSString(contentsOfFile: path, usedEncoding: nil)
let ns = try NSString(contentsOfFile: path, usedEncoding: nil)
self = ns as String
self = String._unconditionallyBridgeFromObjectiveC(ns)
}
}
// - (instancetype)
// - (instancetype)
// initWithContentsOfURL:(NSURL *)url
// initWithContentsOfURL:(NSURL *)url
// encoding:(NSStringEncoding)enc
// encoding:(NSStringEncoding)enc
// error:(NSError**)error
// error:(NSError**)error
/// Produces a string created by reading data from a given URL
/// Produces a string created by reading data from a given URL
/// interpreted using a given encoding. Errors are written into the
/// interpreted using a given encoding. Errors are written into the
/// inout `error` argument.
/// inout `error` argument.
public init(
public init(
contentsOf url: URL,
contentsOf url: URL,
encoding enc: Encoding
encoding enc: Encoding
) throws {
) throws {
let ns = try NSString(contentsOf: url, encoding: enc.rawValue)
let ns = try NSString(contentsOf: url, encoding: enc.rawValue)
self = ns as String
self = String._unconditionallyBridgeFromObjectiveC(ns)
}
}
// - (instancetype)
// - (instancetype)
// initWithContentsOfURL:(NSURL *)url
// initWithContentsOfURL:(NSURL *)url
// usedEncoding:(NSStringEncoding *)enc
// usedEncoding:(NSStringEncoding *)enc
// error:(NSError **)error
// error:(NSError **)error
/// Produces a string created by reading data from a given URL
/// Produces a string created by reading data from a given URL
/// and returns by reference the encoding used to interpret the
/// and returns by reference the encoding used to interpret the
/// data. Errors are written into the inout `error` argument.
/// data. Errors are written into the inout `error` argument.
public init(
public init(
contentsOf url: URL,
contentsOf url: URL,
usedEncoding: inout Encoding
usedEncoding: inout Encoding
) throws {
) throws {
var enc: UInt = 0
var enc: UInt = 0
let ns = try NSString(contentsOf: url as URL, usedEncoding: &enc)
let ns = try NSString(contentsOf: url as URL, usedEncoding: &enc)
usedEncoding = Encoding(rawValue: enc)
usedEncoding = Encoding(rawValue: enc)
self = ns as String
self = String._unconditionallyBridgeFromObjectiveC(ns)
}
}
public init(
public init(
contentsOf url: URL
contentsOf url: URL
) throws {
) throws {
let ns = try NSString(contentsOf: url, usedEncoding: nil)
let ns = try NSString(contentsOf: url, usedEncoding: nil)
self = ns as String
self = String._unconditionallyBridgeFromObjectiveC(ns)
}
}
// - (instancetype)
// - (instancetype)
// initWithCString:(const char *)nullTerminatedCString
// initWithCString:(const char *)nullTerminatedCString
// encoding:(NSStringEncoding)encoding
// encoding:(NSStringEncoding)encoding
/// Produces a string containing the bytes in a given C array,
/// Produces a string containing the bytes in a given C array,
/// interpreted according to a given encoding.
/// interpreted according to a given encoding.
public init?(
public init?(
cString: UnsafePointer<CChar>,
cString: UnsafePointer<CChar>,
encoding enc: Encoding
encoding enc: Encoding
) {
) {
if let ns = NSString(cString: cString, encoding: enc.rawValue) {
if let ns = NSString(cString: cString, encoding: enc.rawValue) {
self = ns as String
self = String._unconditionallyBridgeFromObjectiveC(ns)
} else {
} else {
return nil
return nil
}
}
}
}
// FIXME: handle optional locale with default arguments
// FIXME: handle optional locale with default arguments
// - (instancetype)
// - (instancetype)
// initWithData:(NSData *)data
// initWithData:(NSData *)data
// encoding:(NSStringEncoding)encoding
// encoding:(NSStringEncoding)encoding
/// Returns a `String` initialized by converting given `data` into
/// Returns a `String` initialized by converting given `data` into
/// Unicode characters using a given `encoding`.
/// Unicode characters using a given `encoding`.
public init?(data: Data, encoding: Encoding) {
public init?(data: Data, encoding: Encoding) {
guard let s = NSString(data: data, encoding: encoding.rawValue) else { return nil }
guard let s = NSString(data: data, encoding: encoding.rawValue) else { return nil }
self = s as String
self = String._unconditionallyBridgeFromObjectiveC(s)
}
}
// - (instancetype)initWithFormat:(NSString *)format, ...
// - (instancetype)initWithFormat:(NSString *)format, ...
/// Returns a `String` object initialized by using a given
/// Returns a `String` object initialized by using a given
/// format string as a template into which the remaining argument
/// format string as a template into which the remaining argument
/// values are substituted.
/// values are substituted.
public init(format: String, _ arguments: CVarArg...) {
public init(format: String, _ arguments: CVarArg...) {
self = String(format: format, arguments: arguments)
self = String(format: format, arguments: arguments)
}
}
// - (instancetype)
// - (instancetype)
// initWithFormat:(NSString *)format
// initWithFormat:(NSString *)format
// arguments:(va_list)argList
// arguments:(va_list)argList
/// Returns a `String` object initialized by using a given
/// Returns a `String` object initialized by using a given
/// format string as a template into which the remaining argument
/// format string as a template into which the remaining argument
/// values are substituted according to the user's default locale.
/// values are substituted according to the user's default locale.
public init(format: String, arguments: [CVarArg]) {
public init(format: String, arguments: [CVarArg]) {
self = String(format: format, locale: nil, arguments: arguments)
self = String(format: format, locale: nil, arguments: arguments)
}
}
// - (instancetype)initWithFormat:(NSString *)format locale:(id)locale, ...
// - (instancetype)initWithFormat:(NSString *)format locale:(id)locale, ...
/// Returns a `String` object initialized by using a given
/// Returns a `String` object initialized by using a given
/// format string as a template into which the remaining argument
/// format string as a template into which the remaining argument
/// values are substituted according to given locale information.
/// values are substituted according to given locale information.
public init(format: String, locale: Locale?, _ args: CVarArg...) {
public init(format: String, locale: Locale?, _ args: CVarArg...) {
self = String(format: format, locale: locale, arguments: args)
self = String(format: format, locale: locale, arguments: args)
}
}
// - (instancetype)
// - (instancetype)
// initWithFormat:(NSString *)format
// initWithFormat:(NSString *)format
// locale:(id)locale
// locale:(id)locale
// arguments:(va_list)argList
// arguments:(va_list)argList
/// Returns a `String` object initialized by using a given
/// Returns a `String` object initialized by using a given
/// format string as a template into which the remaining argument
/// format string as a template into which the remaining argument
/// values are substituted according to given locale information.
/// values are substituted according to given locale information.
public init(format: String, locale: Locale?, arguments: [CVarArg]) {
public init(format: String, locale: Locale?, arguments: [CVarArg]) {
self = withVaList(arguments) {
self = withVaList(arguments) {
NSString(format: format, locale: locale, arguments: $0) as String
String._unconditionallyBridgeFromObjectiveC(
NSString(format: format, locale: locale?._bridgeToObjectiveC(), arguments: $0)
)
}
}
}
}
}
}
extension StringProtocol where Index == String.Index {
extension StringProtocol where Index == String.Index {
//===--- Bridging Helpers -----------------------------------------------===//
//===--- Bridging Helpers -----------------------------------------------===//
//===--------------------------------------------------------------------===//
//===--------------------------------------------------------------------===//
/// The corresponding `NSString` - a convenience for bridging code.
/// The corresponding `NSString` - a convenience for bridging code.
// FIXME(strings): There is probably a better way to bridge Self to NSString
// FIXME(strings): There is probably a better way to bridge Self to NSString
var _ns: NSString {
var _ns: NSString {
return self._ephemeralString as NSString
return self._ephemeralString._bridgeToObjectiveC()
}
}
/// Return an `Index` corresponding to the given offset in our UTF-16
/// Return an `Index` corresponding to the given offset in our UTF-16
/// representation.
/// representation.
func _index(_ utf16Index: Int) -> Index {
func _index(_ utf16Index: Int) -> Index {
return Index(encodedOffset: utf16Index)
return Index(encodedOffset: utf16Index)
}
}
/// Return a `Range<Index>` corresponding to the given `NSRange` of
/// Return a `Range<Index>` corresponding to the given `NSRange` of
/// our UTF-16 representation.
/// our UTF-16 representation.
func _range(_ r: NSRange) -> Range<Index> {
func _range(_ r: NSRange) -> Range<Index> {
return _index(r.location)..<_index(r.location + r.length)
return _index(r.location)..<_index(r.location + r.length)
}
}
/// Return a `Range<Index>?` corresponding to the given `NSRange` of
/// Return a `Range<Index>?` corresponding to the given `NSRange` of
/// our UTF-16 representation.
/// our UTF-16 representation.
func _optionalRange(_ r: NSRange) -> Range<Index>? {
func _optionalRange(_ r: NSRange) -> Range<Index>? {
if r.location == NSNotFound {
if r.location == NSNotFound {
return nil
return nil
}
}
return _range(r)
return _range(r)
}
}
/// Invoke `body` on an `Int` buffer. If `index` was converted from
/// Invoke `body` on an `Int` buffer. If `index` was converted from
/// non-`nil`, convert the buffer to an `Index` and write it into the
/// non-`nil`, convert the buffer to an `Index` and write it into the
/// memory referred to by `index`
/// memory referred to by `index`
func _withOptionalOutParameter<Result>(
func _withOptionalOutParameter<Result>(
_ index: UnsafeMutablePointer<Index>?,
_ index: UnsafeMutablePointer<Index>?,
_ body: (UnsafeMutablePointer<Int>?) -> Result
_ body: (UnsafeMutablePointer<Int>?) -> Result
) -> Result {
) -> Result {
var utf16Index: Int = 0
var utf16Index: Int = 0
let result = (index != nil ? body(&utf16Index) : body(nil))
let result = (index != nil ? body(&utf16Index) : body(nil))
index?.pointee = _index(utf16Index)
index?.pointee = _index(utf16Index)
return result
return result
}
}
/// Invoke `body` on an `NSRange` buffer. If `range` was converted
/// Invoke `body` on an `NSRange` buffer. If `range` was converted
/// from non-`nil`, convert the buffer to a `Range<Index>` and write
/// from non-`nil`, convert the buffer to a `Range<Index>` and write
/// it into the memory referred to by `range`
/// it into the memory referred to by `range`
func _withOptionalOutParameter<Result>(
func _withOptionalOutParameter<Result>(
_ range: UnsafeMutablePointer<Range<Index>>?,
_ range: UnsafeMutablePointer<Range<Index>>?,
_ body: (UnsafeMutablePointer<NSRange>?) -> Result
_ body: (UnsafeMutablePointer<NSRange>?) -> Result
) -> Result {
) -> Result {
var nsRange = NSRange(location: 0, length: 0)
var nsRange = NSRange(location: 0, length: 0)
let result = (range != nil ? body(&nsRange) : body(nil))
let result = (range != nil ? body(&nsRange) : body(nil))
range?.pointee = self._range(nsRange)
range?.pointee = self._range(nsRange)
return result
return result
}
}
//===--- Instance Methods/Properties-------------------------------------===//
//===--- Instance Methods/Properties-------------------------------------===//
//===--------------------------------------------------------------------===//
//===--------------------------------------------------------------------===//
//===--- Omitted by agreement during API review 5/20/2014 ---------------===//
//===--- Omitted by agreement during API review 5/20/2014 ---------------===//
// @property BOOL boolValue;
// @property BOOL boolValue;
// - (BOOL)canBeConvertedToEncoding:(NSStringEncoding)encoding
// - (BOOL)canBeConvertedToEncoding:(NSStringEncoding)encoding
/// Returns a Boolean value that indicates whether the string can be
/// Returns a Boolean value that indicates whether the string can be
/// converted to the specified encoding without loss of information.
/// converted to the specified encoding without loss of information.
///
///
/// - Parameter encoding: A string encoding.
/// - Parameter encoding: A string encoding.
/// - Returns: `true` if the string can be encoded in `encoding` without loss
/// - Returns: `true` if the string can be encoded in `encoding` without loss
/// of information; otherwise, `false`.
/// of information; otherwise, `false`.
public func canBeConverted(to encoding: String.Encoding) -> Bool {
public func canBeConverted(to encoding: String.Encoding) -> Bool {
return _ns.canBeConverted(to: encoding.rawValue)
return _ns.canBeConverted(to: encoding.rawValue)
}
}
// @property NSString* capitalizedString
// @property NSString* capitalizedString
/// A copy of the string with each word changed to its corresponding
/// A copy of the string with each word changed to its corresponding
/// capitalized spelling.
/// capitalized spelling.
///
///
/// This property performs the canonical (non-localized) mapping. It is
/// This property performs the canonical (non-localized) mapping. It is
/// suitable for programming operations that require stable results not
/// suitable for programming operations that require stable results not
/// depending on the current locale.
/// depending on the current locale.
///
///
/// A capitalized string is a string with the first character in each word
/// A capitalized string is a string with the first character in each word
/// changed to its corresponding uppercase value, and all remaining
/// changed to its corresponding uppercase value, and all remaining
/// characters set to their corresponding lowercase values. A "word" is any
/// characters set to their corresponding lowercase values. A "word" is any
/// sequence of characters delimited by spaces, tabs, or line terminators.
/// sequence of characters delimited by spaces, tabs, or line terminators.
/// Some common word delimiting punctuation isn't considered, so this
/// Some common word delimiting punctuation isn't considered, so this
/// property may not generally produce the desired results for multiword
/// property may not generally produce the desired results for multiword
/// strings. See the `getLineStart(_:end:contentsEnd:for:)` method for
/// strings. See the `getLineStart(_:end:contentsEnd:for:)` method for
/// additional information.
/// additional information.
///
///
/// Case transformations aren’t guaranteed to be symmetrical or to produce
/// Case transformations aren’t guaranteed to be symmetrical or to produce
/// strings of the same lengths as the originals.
/// strings of the same lengths as the originals.
public var capitalized: String {
public var capitalized: String {
return _ns.capitalized as String
return _ns.capitalized as String
}
}
// @property (readonly, copy) NSString *localizedCapitalizedString NS_AVAILABLE(10_11, 9_0);
// @property (readonly, copy) NSString *localizedCapitalizedString NS_AVAILABLE(10_11, 9_0);
/// A capitalized representation of the string that is produced
/// A capitalized representation of the string that is produced
/// using the current locale.
/// using the current locale.
@available(OSX 10.11, iOS 9.0, *)
@available(OSX 10.11, iOS 9.0, *)
public var localizedCapitalized: String {
public var localizedCapitalized: String {
return _ns.localizedCapitalized
return _ns.localizedCapitalized
}
}
// - (NSString *)capitalizedStringWithLocale:(Locale *)locale
// - (NSString *)capitalizedStringWithLocale:(Locale *)locale
/// Returns a capitalized representation of the string
/// Returns a capitalized representation of the string
/// using the specified locale.
/// using the specified locale.
public func capitalized(with locale: Locale?) -> String {
public func capitalized(with locale: Locale?) -> String {
return _ns.capitalized(with: locale) as String
return _ns.capitalized(with: locale) as String
}
}
// - (NSComparisonResult)caseInsensitiveCompare:(NSString *)aString
// - (NSComparisonResult)caseInsensitiveCompare:(NSString *)aString
/// Returns the result of invoking `compare:options:` with
/// Returns the result of invoking `compare:options:` with
/// `NSCaseInsensitiveSearch` as the only option.
/// `NSCaseInsensitiveSearch` as the only option.
public func caseInsensitiveCompare<
public func caseInsensitiveCompare<
T : StringProtocol
T : StringProtocol
>(_ aString: T) -> ComparisonResult {
>(_ aString: T) -> ComparisonResult {
return _ns.caseInsensitiveCompare(aString._ephemeralString)
return _ns.caseInsensitiveCompare(aString._ephemeralString)
}
}
//===--- Omitted by agreement during API review 5/20/2014 ---------------===//
//===--- Omitted by agreement during API review 5/20/2014 ---------------===//
// - (unichar)characterAtIndex:(NSUInteger)index
// - (unichar)characterAtIndex:(NSUInteger)index
//
//
// We have a different meaning for "Character" in Swift, and we are
// We have a different meaning for "Character" in Swift, and we are
// trying not to expose error-prone UTF-16 integer indexes
// trying not to expose error-prone UTF-16 integer indexes
// - (NSString *)
// - (NSString *)
// commonPrefixWithString:(NSString *)aString
// commonPrefixWithString:(NSString *)aString
// options:(StringCompareOptions)mask
// options:(StringCompareOptions)mask
/// Returns a string containing characters this string and the
/// Returns a string containing characters this string and the
/// given string have in common, starting from the beginning of each
/// given string have in common, starting from the beginning of each
/// up to the first characters that aren't equivalent.
/// up to the first characters that aren't equivalent.
public func commonPrefix<
public func commonPrefix<
T : StringProtocol
T : StringProtocol
>(with aString: T, options: String.CompareOptions = []) -> String {
>(with aString: T, options: String.CompareOptions = []) -> String {
return _ns.commonPrefix(with: aString._ephemeralString, options: options)
return _ns.commonPrefix(with: aString._ephemeralString, options: options)
}
}
// - (NSComparisonResult)
// - (NSComparisonResult)
// compare:(NSString *)aString
// compare:(NSString *)aString
//
//
// - (NSComparisonResult)
// - (NSComparisonResult)
// compare:(NSString *)aString options:(StringCompareOptions)mask
// compare:(NSString *)aString options:(StringCompareOptions)mask
//
//
// - (NSComparisonResult)
// - (NSComparisonResult)
// compare:(NSString *)aString options:(StringCompareOptions)mask
// compare:(NSString *)aString options:(StringCompareOptions)mask
// range:(NSRange)range
// range:(NSRange)range
//
//
// - (NSComparisonResult)
// - (NSComparisonResult)
// compare:(NSString *)aString options:(StringCompareOptions)mask
// compare:(NSString *)aString options:(StringCompareOptions)mask
// range:(NSRange)range locale:(id)locale
// range:(NSRange)range locale:(id)locale
/// Compares the string using the specified options and
/// Compares the string using the specified options and
/// returns the lexical ordering for the range.
/// returns the lexical ordering for the range.
public func compare<T : StringProtocol>(
public func compare<T : StringProtocol>(
_ aString: T,
_ aString: T,
options mask: String.CompareOptions = [],
options mask: String.CompareOptions = [],
range: Range<Index>? = nil,
range: Range<Index>? = nil,
locale: Locale? = nil
locale: Locale? = nil
) -> ComparisonResult {
) -> ComparisonResult {
// According to Ali Ozer, there may be some real advantage to
// According to Ali Ozer, there may be some real advantage to
// dispatching to the minimal selector for the supplied options.
// dispatching to the minimal selector for the supplied options.
// So let's do that; the switch should compile away anyhow.
// So let's do that; the switch should compile away anyhow.
let aString = aString._ephemeralString
let aString = aString._ephemeralString
return locale != nil ? _ns.compare(
return locale != nil ? _ns.compare(
aString,
aString,
options: mask,
options: mask,
range: _toNSRange(
range: _toNSRange(
range ?? startIndex..<endIndex
range ?? startIndex..<endIndex
),
),
locale: locale
locale: locale?._bridgeToObjectiveC()
)
)
: range != nil ? _ns.compare(
: range != nil ? _ns.compare(
aString,
aString,
options: mask,
options: mask,
range: _toNSRange(range!)
range: _toNSRange(range!)
)
)
: !mask.isEmpty ? _ns.compare(aString, options: mask)
: !mask.isEmpty ? _ns.compare(aString, options: mask)
: _ns.compare(aString)
: _ns.compare(aString)
}
}
// - (NSUInteger)
// - (NSUInteger)
// completePathIntoString:(NSString **)outputName
// completePathIntoString:(NSString **)outputName
// caseSensitive:(BOOL)flag
// caseSensitive:(BOOL)flag
// matchesIntoArray:(NSArray **)outputArray
// matchesIntoArray:(NSArray **)outputArray
// filterTypes:(NSArray *)filterTypes
// filterTypes:(NSArray *)filterTypes
/// Interprets the string as a path in the file system and
/// Interprets the string as a path in the file system and
/// attempts to perform filename completion, returning a numeric
/// attempts to perform filename completion, returning a numeric
/// value that indicates whether a match was possible, and by
/// value that indicates whether a match was possible, and by
/// reference the longest path that matches the string.
/// reference the longest path that matches the string.
///
///
/// - Returns: The actual number of matching paths.
/// - Returns: The actual number of matching paths.
public func completePath(
public func completePath(
into outputName: UnsafeMutablePointer<String>? = nil,
into outputName: UnsafeMutablePointer<String>? = nil,
caseSensitive: Bool,
caseSensitive: Bool,
matchesInto outputArray: UnsafeMutablePointer<[String]>? = nil,
matchesInto outputArray: UnsafeMutablePointer<[String]>? = nil,
filterTypes: [String]? = nil
filterTypes: [String]? = nil
) -> Int {
) -> Int {
var nsMatches: NSArray?
var nsOutputName: NSString?
let result: Int = outputName._withNilOrAddress(of: &nsOutputName) {
outputName in outputArray._withNilOrAddress(of: &nsMatches) {
outputArray in
// FIXME: completePath(...) is incorrectly annotated as requiring
// non-optional output parameters. rdar://problem/25494184
let outputNonOptionalName = unsafeBitCast(
outputName, to: AutoreleasingUnsafeMutablePointer<NSString?>.self)
let outputNonOptionalArray = unsafeBitCast(
outputArray, to: AutoreleasingUnsafeMutablePointer<NSArray?>.self)
return self._ns.completePath(
into: outputNonOptionalName,
caseSensitive: caseSensitive,
matchesInto: outputNonOptionalArray,
filterTypes: filterTypes
)
}
}
if let matches = nsMatches {
// Since this function is effectively a bridge thunk, use the
// bridge thunk semantics for the NSArray conversion
outputArray?.pointee = matches as! [String]
}
if let n = nsOutputName {
var outputNamePlaceholder: String?
outputName?.pointee = n as String
var outputArrayPlaceholder = [String]()
let res = self._ns.completePath(
into: &outputNamePlaceholder,
caseSensitive: caseSensitive,
matchesInto: &outputArrayPlaceholder,
filterTypes: filterTypes
)
if let n = outputNamePlaceholder {
outputName?.pointee = n
} else {
outputName?.pointee = ""
}
}
return result
outputArray?.pointee = outputArrayPlaceholder
return res
}
}
// - (NSArray *)
// - (NSArray *)
// componentsSeparatedByCharactersInSet:(NSCharacterSet *)separator
// componentsSeparatedByCharactersInSet:(NSCharacterSet *)separator
/// Returns an array containing substrings from the string
/// Returns an array containing substrings from the string
/// that have been divided by characters in the given set.
/// that have been divided by characters in the given set.
public func components(separatedBy separator: CharacterSet) -> [String] {
public func components(separatedBy separator: CharacterSet) -> [String] {
return _ns.components(separatedBy: separator)
return _ns.components(separatedBy: separator)
}
}
// - (NSArray *)componentsSeparatedByString:(NSString *)separator
// - (NSArray *)componentsSeparatedByString:(NSString *)separator
/// Returns an array containing substrings from the string that have been
/// Returns an array containing substrings from the string that have been
/// divided by the given separator.
/// divided by the given separator.
///
///
/// The substrings in the resulting array appear in the same order as the
/// The substrings in the resulting array appear in the same order as the
/// original string. Adjacent occurrences of the separator string produce
/// original string. Adjacent occurrences of the separator string produce
/// empty strings in the result. Similarly, if the string begins or ends
/// empty strings in the result. Similarly, if the string begins or ends
/// with the separator, the first or last substring, respectively, is empty.
/// with the separator, the first or last substring, respectively, is empty.
/// The following example shows this behavior:
/// The following example shows this behavior:
///
///
/// let list1 = "Karin, Carrie, David"
/// let list1 = "Karin, Carrie, David"
/// let items1 = list1.components(separatedBy: ", ")
/// let items1 = list1.components(separatedBy: ", ")
/// // ["Karin", "Carrie", "David"]
/// // ["Karin", "Carrie", "David"]
///
///
/// // Beginning with the separator:
/// // Beginning with the separator:
/// let list2 = ", Norman, Stanley, Fletcher"
/// let list2 = ", Norman, Stanley, Fletcher"
/// let items2 = list2.components(separatedBy: ", ")
/// let items2 = list2.components(separatedBy: ", ")
/// // ["", "Norman", "Stanley", "Fletcher"
/// // ["", "Norman", "Stanley", "Fletcher"
///
///
/// If the list has no separators, the array contains only the original
/// If the list has no separators, the array contains only the original
/// string itself.
/// string itself.
///
///
/// let name = "Karin"
/// let name = "Karin"
/// let list = name.components(separatedBy: ", ")
/// let list = name.components(separatedBy: ", ")
/// // ["Karin"]
/// // ["Karin"]
///
///
/// - Parameter separator: The separator string.
/// - Parameter separator: The separator string.
/// - Returns: An array containing substrings that have been divided from the
/// - Returns: An array containing substrings that have been divided from the
/// string using `separator`.
/// string using `separator`.
// FIXME(strings): now when String conforms to Collection, this can be
// FIXME(strings): now when String conforms to Collection, this can be
// replaced by split(separator:maxSplits:omittingEmptySubsequences:)
// replaced by split(separator:maxSplits:omittingEmptySubsequences:)
public func components<
public func components<
T : StringProtocol
T : StringProtocol
>(separatedBy separator: T) -> [String] {
>(separatedBy separator: T) -> [String] {
return _ns.components(separatedBy: separator._ephemeralString)
return _ns.components(separatedBy: separator._ephemeralString)
}
}
// - (const char *)cStringUsingEncoding:(NSStringEncoding)encoding
// - (const char *)cStringUsingEncoding:(NSStringEncoding)encoding
/// Returns a representation of the string as a C string
/// Returns a representation of the string as a C string
/// using a given encoding.
/// using a given encoding.
public func cString(using encoding: String.Encoding) -> [CChar]? {
public func cString(using encoding: String.Encoding) -> [CChar]? {
return withExtendedLifetime(_ns) {
return withExtendedLifetime(_ns) {
(s: NSString) -> [CChar]? in
(s: NSString) -> [CChar]? in
_persistCString(s.cString(using: encoding.rawValue))
_persistCString(s.cString(using: encoding.rawValue))
}
}
}
}
// - (NSData *)dataUsingEncoding:(NSStringEncoding)encoding
// - (NSData *)dataUsingEncoding:(NSStringEncoding)encoding
//
//
// - (NSData *)
// - (NSData *)
// dataUsingEncoding:(NSStringEncoding)encoding
// dataUsingEncoding:(NSStringEncoding)encoding
// allowLossyConversion:(BOOL)flag
// allowLossyConversion:(BOOL)flag
/// Returns a `Data` containing a representation of
/// Returns a `Data` containing a representation of
/// the `String` encoded using a given encoding.
/// the `String` encoded using a given encoding.
public func data(
public func data(
using encoding:
using encoding: String.Encoding,
allowLossyConversion: Bool = false
) -> Data? {
return _ns.data(
using: encoding.rawValue,
allowLossyConversion: allowLossyConversion)
}
// @property NSString* decomposedStringWithCanonicalMapping;
/// A string created by normalizing the string's contents using Form D.
public var decomposedStringWithCanonicalMapping: String {
return _ns.decomposedStringWithCanonicalMapping
}
// @property NSString* decomposedStringWithCompatibilityMapping;
/// A string created by normalizing the string's contents using Form KD.
public var decomposedStringWithCompatibilityMapping: String {
return _ns.decomposedStringWithCompatibilityMapping
}
//===--- Importing Foundation should not affect String printing ---------===//
// Therefore, we're not exposing this:
//
// @property NSString* description
//===--- Omitted for consistency with API review results 5/20/2014 -----===//
// @property double doubleValue;
// - (void)
// enumerateLinesUsing:(void (^)(NSString *line, BOOL *stop))block
/// Enumerates all the lines in a string.
public func enum