[stdlib] CString.swift initializers


(Ben Rimmington) #1

The new initializers in "CString.swift" have a precondition:

public init(cString: UnsafePointer<CChar>) {
    _precondition(cString != nil, "cString must not be nil")
}

public init?(validatingUTF8 cString: UnsafePointer<CChar>) {
    _precondition(cString != nil, "cString must not be nil")
}

<https://github.com/apple/swift/blob/swift-3-api-guidelines/stdlib/public/core/CString.swift>

The old `String.fromCString` function was convenient for wrapping inessential C function calls, if the `nil` coalescing operator can provide a fallback:

let message =
    String.fromCString(sqlite3_errmsg(handle)) ??
    String.fromCString(sqlite3_errstr(result)) ?? ""

I also think the `validatingUTF8` argument label is misleading, because neither initializer allows ill-formed UTF-8 data to be copied.

If the precondition is removed, it should be possible to combine the initializers:

/// Create a new `String` by copying the nul-terminated UTF-8 data
/// referenced by a `cString`.
///
/// Fails if the `cString` is `NULL`; or if it contains ill-formed code
/// units and no repairing has been requested. Otherwise replaces
/// ill-formed code units with replacement characters (U+FFFD).
public init?(
  cString: UnsafePointer<CChar>,
  repairingInvalidCodeUnits isRepairing: Bool = true
) {
  guard let (result, _) = String.decodeCString(
    UnsafePointer(cString),
      as: UTF8.self,
      repairingInvalidCodeUnits: isRepairing) else {
    return nil
  }
  self = result
}

-- Ben


(Dmitri Gribenko) #2

The new initializers in "CString.swift" have a precondition:

public init(cString: UnsafePointer<CChar>) {
    _precondition(cString != nil, "cString must not be nil")
}

public init?(validatingUTF8 cString: UnsafePointer<CChar>) {
    _precondition(cString != nil, "cString must not be nil")
}

<https://github.com/apple/swift/blob/swift-3-api-guidelines/stdlib/public/core/CString.swift>

The old `String.fromCString` function was convenient for wrapping inessential C function calls, if the `nil` coalescing operator can provide a fallback:

let message =
    String.fromCString(sqlite3_errmsg(handle)) ??
    String.fromCString(sqlite3_errstr(result)) ?? ""

It is a part of a long-term strategy to make UnsafePointer
non-nullable. Nullable pointers will be modeled as optional pointers.
So this code would look like this, assuming that sqlite3 is returning
optional (nullable) pointers:

let message = sqlite3_errmsg(handle).map { String.fromCString($0) } ??
sqlite3_errstr(result).map { String.fromCString($0) }

I also think the `validatingUTF8` argument label is misleading, because neither initializer allows ill-formed UTF-8 data to be copied.

That's what the 'validating' label is saying -- we're validating the
input and rejecting invalid inputs.

The non-failable initializer accepts ill-formed UTF-8, and repairs it.

Dmitri

···

On Thu, Feb 25, 2016 at 9:45 AM, Ben Rimmington via swift-evolution <swift-evolution@swift.org> wrote:

--
main(i,j){for(i=2;;i++){for(j=2;j<i;j++){if(!(i%j)){j=0;break;}}if
(j){printf("%d\n",i);}}} /*Dmitri Gribenko <gribozavr@gmail.com>*/


(Ben Rimmington) #3

Thanks, that also explains why the no-argument initializers were removed from unsafe pointer types.

-- Ben

···

On 25 Feb 2016, at 21:02, Dmitri Gribenko <gribozavr@gmail.com> wrote:

It is a part of a long-term strategy to make UnsafePointer
non-nullable. Nullable pointers will be modeled as optional pointers.