| // Copyright (c) 2019, the Dart project authors. Please see the AUTHORS file |
| // for details. All rights reserved. Use of this source code is governed by a |
| // BSD-style license that can be found in the LICENSE file. |
| |
| import 'dart:convert'; |
| import 'dart:ffi'; |
| import 'dart:typed_data'; |
| |
| import 'package:ffi/ffi.dart'; |
| |
| const int _kMaxSmi64 = (1 << 62) - 1; |
| const int _kMaxSmi32 = (1 << 30) - 1; |
| final int _maxSize = sizeOf<IntPtr>() == 8 ? _kMaxSmi64 : _kMaxSmi32; |
| |
| /// [Utf8] implements conversion between Dart strings and null-terminated |
| /// Utf8-encoded "char*" strings in C. |
| /// |
| /// [Utf8] is respresented as a struct so that `Pointer<Utf8>` can be used in |
| /// native function signatures. |
| // |
| // TODO(https://github.com/dart-lang/ffi/issues/4): No need to use |
| // 'asTypedList' when Pointer operations are performant. |
| class Utf8 extends Struct { |
| /// Returns the length of a null-terminated string -- the number of (one-byte) |
| /// characters before the first null byte. |
| static int strlen(Pointer<Utf8> string) { |
| final Pointer<Uint8> array = string.cast<Uint8>(); |
| final Uint8List nativeString = array.asTypedList(_maxSize); |
| return nativeString.indexWhere((char) => char == 0); |
| } |
| |
| /// Creates a [String] containing the characters UTF-8 encoded in [string]. |
| /// |
| /// The [string] must be a zero-terminated byte sequence of valid UTF-8 |
| /// encodings of Unicode scalar values. A [FormatException] is thrown if the |
| /// input is malformed. See [Utf8Decoder] for details on decoding. |
| /// |
| /// Returns a Dart string containing the decoded code points. |
| static String fromUtf8(Pointer<Utf8> string) { |
| final int length = strlen(string); |
| return utf8.decode(Uint8List.view( |
| string.cast<Uint8>().asTypedList(length).buffer, 0, length)); |
| } |
| |
| /// Convert a [String] to a Utf8-encoded null-terminated C string. |
| /// |
| /// If 'string' contains NULL bytes, the converted string will be truncated |
| /// prematurely. Unpaired surrogate code points in [string] will be encoded |
| /// as replacement characters (U+FFFD, encoded as the bytes 0xEF 0xBF 0xBD) |
| /// in the UTF-8 encoded result. See [Utf8Encoder] for details on encoding. |
| /// |
| /// Returns a malloc-allocated pointer to the result. |
| static Pointer<Utf8> toUtf8(String string) { |
| final units = utf8.encode(string); |
| final Pointer<Uint8> result = allocate<Uint8>(count: units.length + 1); |
| final Uint8List nativeString = result.asTypedList(units.length + 1); |
| nativeString.setAll(0, units); |
| nativeString[units.length] = 0; |
| return result.cast(); |
| } |
| |
| String toString() => fromUtf8(addressOf); |
| } |