From 75bee2083af461f21aced9e87b0d0559a038e618 Mon Sep 17 00:00:00 2001 From: Daco Harkes Date: Thu, 24 Oct 2019 17:40:27 +0000 Subject: [PATCH] [samples/ffi] Add bitfield sample Issue: https://github.com/dart-lang/sdk/issues/38954 Change-Id: I04b2b81d83a19c5ff88d4364256b23594fe2139b Cq-Include-Trybots: luci.dart.try:vm-ffi-android-debug-arm-try,vm-ffi-android-debug-arm64-try,analyzer-analysis-server-linux-try,analyzer-linux-release-try,front-end-linux-release-x64-try Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/122762 Commit-Queue: Daco Harkes Reviewed-by: Martin Kustermann --- samples/ffi/sample_ffi_bitfield.dart | 123 +++++++++++++++++++++++++++ samples/ffi/samples_test.dart | 2 + 2 files changed, 125 insertions(+) create mode 100644 samples/ffi/sample_ffi_bitfield.dart diff --git a/samples/ffi/sample_ffi_bitfield.dart b/samples/ffi/sample_ffi_bitfield.dart new file mode 100644 index 00000000000..0d91d47b648 --- /dev/null +++ b/samples/ffi/sample_ffi_bitfield.dart @@ -0,0 +1,123 @@ +// 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:ffi'; + +import 'package:ffi/ffi.dart'; +import 'package:expect/expect.dart'; + +/// typedef struct { +/// unsigned int bold : 1; +/// unsigned int underline : 2; +/// unsigned int italic : 1; +/// unsigned int blink : 1; +/// unsigned int reverse : 1; +/// unsigned int strike : 1; +/// unsigned int font : 4; +/// } ScreenCellAttrs; +class ScreenCellAttrs extends Struct { + @Int16() + int bits; + + int get bold => getBits(kBoldFieldOffset, kBoldFieldLength); + void set bold(int value) => + setBits(kBoldFieldOffset, kBoldFieldLength, value); + + int get underline => getBits(kUnderlineFieldOffset, kUnderlineFieldLength); + void set underline(int value) => + setBits(kUnderlineFieldOffset, kUnderlineFieldLength, value); + + int get italic => getBits(kItalicFieldOffset, kItalicFieldLength); + void set italic(int value) => + setBits(kItalicFieldOffset, kItalicFieldLength, value); + + int get blink => getBits(kBlinkFieldOffset, kBlinkFieldLength); + void set blink(int value) => + setBits(kBlinkFieldOffset, kBlinkFieldLength, value); + + int get reverse => getBits(kReverseFieldOffset, kReverseFieldLength); + void set reverse(int value) => + setBits(kReverseFieldOffset, kReverseFieldLength, value); + + int get strike => getBits(kStrikeFieldOffset, kStrikeFieldLength); + void set strike(int value) => + setBits(kStrikeFieldOffset, kStrikeFieldLength, value); + + int get font => getBits(kFontFieldOffset, kFontFieldLength); + void set font(int value) => + setBits(kFontFieldOffset, kFontFieldLength, value); + + int getBits(int offset, int length) => bits.getBits(offset, length); + + void setBits(int offset, int length, int value) { + bits = bits.setBits(offset, length, value); + } +} + +const int kBoldFieldOffset = 0; +const int kBoldFieldLength = 1; +const int kUnderlineFieldOffset = kBoldFieldOffset + kBoldFieldLength; +const int kUnderlineFieldLength = 2; +const int kItalicFieldOffset = kUnderlineFieldOffset + kUnderlineFieldLength; +const int kItalicFieldLength = 1; +const int kBlinkFieldOffset = kItalicFieldOffset + kItalicFieldLength; +const int kBlinkFieldLength = 1; +const int kReverseFieldOffset = kBlinkFieldOffset + kBlinkFieldLength; +const int kReverseFieldLength = 1; +const int kStrikeFieldOffset = kReverseFieldOffset + kReverseFieldLength; +const int kStrikeFieldLength = 1; +const int kFontFieldOffset = kStrikeFieldOffset + kStrikeFieldLength; +const int kFontFieldLength = 4; + +/// Extension to use a 64-bit integer as bit field. +extension IntBitField on int { + static int _bitMask(int offset, int lenght) => ((1 << lenght) - 1) << offset; + + /// Read `length` bits at `offset`. + /// + /// Truncates everything. + int getBits(int offset, int length) { + final mask = _bitMask(offset, length); + return (this & mask) >> offset; + } + + /// Returns a new integer value in which `length` bits are overwritten at + /// `offset`. + /// + /// Truncates everything. + int setBits(int offset, int length, int value) { + final mask = _bitMask(offset, length); + return (this & ~mask) | ((value << offset) & mask); + } +} + +main() { + final p = allocate(count: 3); + + // Zeroes out all fields. + p.ref.bits = 0; + + // Set individual fields. + p.ref.blink = 0; + p.ref.bold = 1; + p.ref.font = 15; + p.ref.italic = 1; + p.ref.reverse = 0; + p.ref.strike = 0; + p.ref.underline = 2; + + // Read individual fields. + print(p.ref.blink); + print(p.ref.bold); + print(p.ref.font); + print(p.ref.italic); + print(p.ref.reverse); + print(p.ref.strike); + print(p.ref.underline); + + // A check for automated testing. + Expect.equals(1933, p.ref.bits); + + free(p); +} diff --git a/samples/ffi/samples_test.dart b/samples/ffi/samples_test.dart index 4abd4468d04..98144638ed0 100644 --- a/samples/ffi/samples_test.dart +++ b/samples/ffi/samples_test.dart @@ -6,6 +6,7 @@ // // SharedObjects=ffi_test_dynamic_library ffi_test_functions +import 'sample_ffi_bitfield.dart' as sample0; import 'sample_ffi_data.dart' as sample1; import 'sample_ffi_dynamic_library.dart' as sample2; import 'sample_ffi_functions_callbacks.dart' as sample3; @@ -14,6 +15,7 @@ import 'sample_ffi_functions.dart' as sample5; import 'sample_ffi_structs.dart' as sample6; main() { + sample0.main(); sample1.main(); sample2.main(); sample3.main();