Files
swift-mirror/stdlib/core/CString.swift
Jordan Rose 748efed913 [Accessibility] Protocol witnesses must be as accessible as the protocol.
...unless the type has less accessibility than the protocol, in which case
they must be as accessible as the type.

This restriction applies even with access control checking disabled, but
shouldn't affect any decls not already marked with access control modifiers.

Swift SVN r19382
2014-06-30 23:38:35 +00:00

169 lines
5.1 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 {
@public var _bytesPtr: UnsafePointer<UInt8>
@public init(_ bytesPtr: UnsafePointer<UInt8>) {
self._bytesPtr = bytesPtr
}
@public init(_ bytesPtr: UnsafePointer<CChar>) {
self._bytesPtr = UnsafePointer<UInt8>(bytesPtr)
}
@public
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)
}
@public
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
@public 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 = [CChar](count: length + 1, repeatedValue: 0)
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)
}
}