mirror of
https://github.com/apple/swift.git
synced 2025-12-21 12:14:44 +01:00
Keep calm: remember that the standard library has many more public exports than the average target, and that this contains ALL of them at once. I also deliberately tried to tag nearly every top-level decl, even if that was just to explicitly mark things @internal, to make sure I didn't miss something. This does export more than we might want to, mostly for protocol conformance reasons, along with our simple-but-limiting typealias rule. I tried to also mark things private where possible, but it's really going to be up to the standard library owners to get this right. This is also only validated against top-level access control; I haven't fully tested against member-level access control yet, and none of our semantic restrictions are in place. Along the way I also noticed bits of stdlib cruft; to keep this patch understandable, I didn't change any of them. Swift SVN r19145
167 lines
5.0 KiB
Swift
167 lines
5.0 KiB
Swift
//===----------------------------------------------------------------------===//
|
|
//
|
|
// This source file is part of the Swift.org open source project
|
|
//
|
|
// Copyright (c) 2014 - 2015 Apple Inc. and the Swift project authors
|
|
// Licensed under Apache License v2.0 with Runtime Library Exception
|
|
//
|
|
// See http://swift.org/LICENSE.txt for license information
|
|
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
// CString Type
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// XXX FIXME: we need a clean memory management story here
|
|
|
|
/// An equivalent of nul-terminated `char *` in C.
|
|
///
|
|
/// `CString` behaves exactly like `char *`:
|
|
///
|
|
/// * it does not own the storage;
|
|
///
|
|
/// * it can contain a `NULL` pointer;
|
|
///
|
|
/// * it may not contain well-formed UTF-8. Because of this, comparison
|
|
/// operators `<` and `==` on `CString` use `strcmp` instead of Unicode
|
|
/// comparison algorithms.
|
|
@public struct CString :
|
|
_BuiltinExtendedGraphemeClusterLiteralConvertible,
|
|
ExtendedGraphemeClusterLiteralConvertible,
|
|
_BuiltinStringLiteralConvertible, StringLiteralConvertible,
|
|
LogicValue {
|
|
var _bytesPtr: UnsafePointer<UInt8>
|
|
|
|
@public init(_ bytesPtr: UnsafePointer<UInt8>) {
|
|
self._bytesPtr = bytesPtr
|
|
}
|
|
|
|
@public init(_ bytesPtr: UnsafePointer<CChar>) {
|
|
self._bytesPtr = UnsafePointer<UInt8>(bytesPtr)
|
|
}
|
|
|
|
static func _convertFromBuiltinExtendedGraphemeClusterLiteral(
|
|
start: Builtin.RawPointer,
|
|
byteSize: Builtin.Word,
|
|
isASCII: Builtin.Int1) -> CString {
|
|
|
|
return _convertFromBuiltinStringLiteral(start, byteSize: byteSize,
|
|
isASCII: isASCII)
|
|
}
|
|
|
|
@public static func convertFromExtendedGraphemeClusterLiteral(
|
|
value: CString) -> CString {
|
|
|
|
return convertFromStringLiteral(value)
|
|
}
|
|
|
|
static func _convertFromBuiltinStringLiteral(start: Builtin.RawPointer,
|
|
byteSize: Builtin.Word,
|
|
isASCII: Builtin.Int1) -> CString {
|
|
return CString(UnsafePointer<CChar>(start))
|
|
}
|
|
|
|
@public static func convertFromStringLiteral(value: CString) -> CString {
|
|
return value
|
|
}
|
|
|
|
@transparent
|
|
var _isNull : Bool {
|
|
return _bytesPtr._isNull
|
|
}
|
|
|
|
@transparent @public
|
|
func getLogicValue() -> Bool {
|
|
return !_isNull
|
|
}
|
|
|
|
/// From a non-`nil` `CString` with possibly-transient lifetime, create a
|
|
/// nul-terminated array of 'C' char.
|
|
/// Returns `nil` if the `CString` was created from a null pointer.
|
|
@public func persist() -> CChar[]? {
|
|
if !self {
|
|
return .None
|
|
}
|
|
var length = _strlen(self)
|
|
var result = new CChar[length + 1]
|
|
for var i = 0; i < length; ++i {
|
|
// FIXME: this will not compile on platforms where 'CChar' is unsigned.
|
|
result[i] = _bytesPtr[i].asSigned()
|
|
}
|
|
return result
|
|
}
|
|
}
|
|
|
|
extension CString : DebugPrintable {
|
|
@public var debugDescription: String {
|
|
let (optionalString, hadError) =
|
|
String.fromCStringRepairingIllFormedUTF8(self)
|
|
if let s = optionalString {
|
|
return (hadError ? "<ill-formed UTF-8>" : "") + s.debugDescription
|
|
}
|
|
return "<null C string>"
|
|
}
|
|
}
|
|
|
|
@asmname("strlen")
|
|
func _strlen(arg : CString) -> Int
|
|
@asmname("strcpy")
|
|
func _strcpy(dest: CString, src: CString) -> CString
|
|
@asmname("strcmp")
|
|
func _strcmp(dest: CString, src: CString) -> CInt
|
|
|
|
@transparent @public
|
|
func ==(lhs: CString, rhs: CString) -> Bool {
|
|
if lhs._bytesPtr == rhs._bytesPtr { return true }
|
|
return _strcmp(lhs, rhs) == 0
|
|
}
|
|
|
|
@transparent @public
|
|
func <(lhs: CString, rhs: CString) -> Bool {
|
|
return _strcmp(lhs, rhs) < 0
|
|
}
|
|
|
|
extension CString : Equatable, Hashable, Comparable {
|
|
@transparent @public
|
|
var hashValue: Int {
|
|
if let s = String.fromCStringRepairingIllFormedUTF8(self).0 {
|
|
return s.hashValue
|
|
}
|
|
return 0
|
|
}
|
|
}
|
|
|
|
extension String {
|
|
/// Creates a new `String` by copying the nul-terminated UTF-8 data
|
|
/// referenced by a `CString`.
|
|
///
|
|
/// Returns `nil` if the `CString` is `NULL` or if it contains ill-formed
|
|
/// UTF-8 code unit sequences.
|
|
@public static func fromCString(cs: CString) -> String? {
|
|
if cs._isNull {
|
|
return .None
|
|
}
|
|
let len = Int(_strlen(cs))
|
|
return String._fromCodeUnitSequence(UTF8.self,
|
|
input: UnsafeArray(start: cs._bytesPtr, length: len))
|
|
}
|
|
|
|
/// Creates a new `String` by copying the nul-terminated UTF-8 data
|
|
/// referenced by a `CString`.
|
|
///
|
|
/// Returns `nil` if the `CString` is `NULL`. If `CString` contains
|
|
/// ill-formed UTF-8 code unit sequences, replaces them with replacement
|
|
/// characters (U+FFFD).
|
|
@public static func fromCStringRepairingIllFormedUTF8(cs: CString)
|
|
-> (String?, hadError: Bool) {
|
|
if cs._isNull {
|
|
return (.None, hadError: false)
|
|
}
|
|
let len = Int(_strlen(cs))
|
|
let (result, hadError) = String._fromCodeUnitSequenceWithRepair(UTF8.self,
|
|
input: UnsafeArray(start: cs._bytesPtr, length: len))
|
|
return (result, hadError: hadError)
|
|
}
|
|
}
|
|
|