What is the union of bitfield equivalent in Dart? - dart

I'd like to achieve the following C code in Dart:
union AuxiliaryHardwares {
uint16_t all = 0;
struct {
hasRs485: 1;
hasCanbus: 1;
hasRelay0: 1;
hasRelay1: 1;
};
};
AuxialiaryHardwares ah;
ah.all = 123; // Or any value I read from the network
if (ah.hasCanbus) {
// blah blah
}
if (ah.hasRelay0) {
// blah blah
}

There is no language support for accessing individual bits of an integer as an integer or boolean variable.
Traditionally, you'd write it yourself.
class AuxiliaryHardwares {
static const int _rs485Flag = 1;
static const int _canbusFlag = 2;
static const int _relay0Flag = 4;
static const int _relay1Flag = 8;
int all = 0;
bool get hasRs45 => all & _rs45Flag != 0;
bool get hasCanbus => all & _canbusFlag != 0;
bool get hasRelay0 => all & _relay0Flag != 0;
bool get hasRelay1 => all & _relay1Flag != 0;
// Setters too if you want them, e.g.
void set hasRs45(bool value) {
all = value ? (all | _rs45Flag) : (all & ~_rs45Flag);
}
}
You can probably find a bit-set class somewhere which abstracts over accessing individual bits of an integer, but it'll be extra overhead for very little gain.
I expect that "inline classes" will be the future way to encapsulate integers like this.

Related

Is Dart/Flutter has a listener function?

The listener function can listen to any parameter type(not only listener type). This has nothing related to widgets (this should work successfully in https://dartpad.dev without using the flutter).
ex.
int a = 0;
listener((a>0)=>print("A = $a"));
a= 1; //A = 1
a= -1; //
a= 2; //A = 2
You can use ValueNotifier for this. It's a ChangeNotifier that is triggered when the value is replaced with something that is not equal to the old value as evaluated by the equality operator ==.
Here is a nice tutorial about this approach.
The basic method is to create the function for updating the parameter that you want to add to the listener.
void test() {
int a = 0;
void updateA(newA) {
if(newA is! int) return;
a = newA;
if (a > 0) print("A = $a");
}
updateA(1);
updateA(-1);
updateA(2);
}
A better way is to create parameters with class.
void main() {
ParameterWithListener a = ParameterWithListener(data: 0);
a.listener = () {
if (a.data is int && a.data > 0) print("A = ${a.data}");
};
a.update(1);
a.update(-1);
a.update(2);
}
class ParameterWithListener {
ParameterWithListener({this.data, this.listener});
dynamic data;
Function()? listener;
Future update(data) async {
this.data = data;
if (listener is Function()) await listener!();
}
}
result:
A = 1
A = 2

How to write a function result to instance variable

I have an error in 5 line
The instance member
'generateId' can't be accessed in an initializer. Try replacing the
reference to the instance member with a different expression
what i shoud do to write a function result to instance variable?
import 'dart:math';
class User{
int id = generateId(10); // error i here
String firstName;
String lastName;
String eMail;
String password;
final DateTime regDate = DateTime.now();
User(this.firstName, this.lastName, this.eMail, this.password,){
id = generateId(10);
}
#override
String toString() =>'User: \n$firstName \n$lastName';
int generateId(int count){
int result;
List <int> nums = [];
for (int i = 0; i < count; i++){
nums.add((Random().nextInt(9) + 1).toInt());
}
result = int.parse(nums.join());
return result;
}
}
void main() {
User newUser = User("D", "P", "example#ex.com", "password");
print(newUser);
}
You should make the generateId method static.
The method does not need access to the object, it uses no instance methods or fields, so it can, and should, be declared static.
(It can also be significantly simplified.)
static int generateId(int count){
var result = 0;
var random = Random();
for (var i = 0; i < count; i++) {
result = result * 10 + random.nextInt(9) + 1;
}
return result;
}
Also consider whether you really need all digits to be non-zero, or you just need the first digit to be non-zero. If so, you can do:
final int id = 1000000000 + Random().nextInt(9000000000);
to get a random ten-digit identifier.
Well, since you have only a single constructor and that sets the id anyway, you can basically remove it:
This:
int id = generateId(10); // error i here
becomes:
late int id;
Done.
In case your really, really need that line, you could make the generateId method either a function instead of a class method, or you could make it static. That should work, too.

How to set values of global variables used in function parameters

I can conveniently change opsCount variable directly from inside the function,
because there is only one of that type of variable.
int opsCount = 0;
int jobXCount = 0;
int jobYCount = 0;
int jobZCount = 0;
void doStats(var jobCount) {
opsCount++;
jobCount++;
}
main() {
doStats(jobXCount);
}
But there are many jobCount variables, so how can I change effectively that variable, which is used in parameter, when function is called?
I think I know what you are asking. Unfortunately, the answer is "you can't do this unless you are willing to wrap your integers". Numbers are immutable objects, you can't change their value. Even though Dart's numbers are objects, and they are passed by reference, their intrinsic value can't be changed.
See also Is there a way to pass a primitive parameter by reference in Dart?
You can wrap the variables, then you can pass them as reference:
class IntRef {
IntRef(this.val);
int val;
#override
String toString() => val.toString();
}
IntRef opsCount = new IntRef(0);
IntRef jobXCount = new IntRef(0);
IntRef jobYCount = new IntRef(0);
IntRef jobZCount = new IntRef(0);
void doStats(var jobCount) {
opsCount.val++;
jobCount.val++;
}
main() {
doStats(jobXCount);
print('opsCount: $opsCount; jobXCount: $jobXCount; jobYCount: $jobYCount; jobZCount: $jobZCount');
}
EDIT
According to Roberts comment ..
With a custom operator this would look like:
class IntRef {
IntRef(this.val);
int val;
#override
String toString() => val.toString();
operator +(int other) {
val += other;
return this;
}
}
void doStats(var jobCount) {
opsCount++;
jobCount++;
}

Using scanner to read phrases

Hey StackOverflow Community,
So, I have this line of information from a txt file that I need to parse.
Here is an example lines:
-> date & time AC Power Insolation Temperature Wind Speed
-> mm/dd/yyyy hh:mm.ss kw W/m^2 deg F mph
Using a scanner.nextLine() gives me a String with a whole line in it, and then I pass this off into StringTokenizer, which then separates them into individual Strings using whitespace as a separator.
so for the first line it would break up into:
date
&
time
AC
Power
Insolation
etc...
I need things like "date & time" together, and "AC Power" together. Is there anyway I can specify this using a method already defined in StringTokenizer or Scanner? Or would I have to develop my own algorithm to do this?
Would you guys suggest I use some other form of parsing lines instead of Scanner? Or, is Scanner sufficient enough for my needs?
ejay
oh, this one was tricky, maybe you could build up some Trie structure with your tokens, i was bored and wrote a little class which solves your problem. Warning: it's a bit hacky, but was fun to implement.
The Trie class:
class Trie extends HashMap<String, Trie> {
private static final long serialVersionUID = 1L;
boolean end = false;
public void addToken(String strings) {
addToken(strings.split("\\s+"), 0);
}
private void addToken(String[] strings, int begin) {
if (begin == strings.length) {
end = true;
return;
}
String key = strings[begin];
Trie t = get(key);
if (t == null) {
t = new Trie();
put(key, t);
}
t.addToken(strings, begin + 1);
}
public List<String> tokenize(String data) {
String[] split = data.split("\\s+");
List<String> tokens = new ArrayList<String>();
int pos = 0;
while (pos < split.length) {
int tokenLength = getToken(split, pos, 0);
tokens.add(glue(split, pos, tokenLength));
pos += tokenLength;
}
return tokens;
}
public String glue(String[] parts, int pos, int length) {
StringBuilder sb = new StringBuilder();
sb.append(parts[pos]);
for (int i = pos + 1; i < pos + length; i++) {
sb.append(" ");
sb.append(parts[i]);
}
return sb.toString();
}
private int getToken(String[] tokens, int begin, int length) {
if (end) {
return length;
}
if (begin == tokens.length) {
return 1;
}
String key = tokens[begin];
Trie t = get(key);
if (t != null) {
return t.getToken(tokens, begin + 1, length + 1);
}
return 1;
}
}
and how to use it:
Trie t = new Trie();
t.addToken("AC Power");
t.addToken("date & time");
t.addToken("date & foo");
t.addToken("Speed & fun");
String data = "date & time AC Power Insolation Temperature Wind Speed";
List<String> tokens = t.tokenize(data);
for (String s : tokens) {
System.out.println(s);
}

String Pattern matching in Blackberry

How i can do a simple pattern matching in blackberry OS 6.0. The purpose is to check whether the user name entered to the UserName edit field contains special characters.... plz help me
thanks jibysthomas
A better solution would be to control the user input by adding an appropriate TextFilter to your edit field. That has the added benefit of modifying the on-screen keyboard to match your filter on those devices so equipped.
Here is an example combining the action of two built in text filters to make one that only allows upper letters and numbers:
import net.rim.device.api.ui.text.TextFilter;
import net.rim.device.api.system.Characters;
/**
* A TextFilter class to filter for station identifiers
*/
private static class StationFilter extends TextFilter {
// Order of the supporting filters is important, NUMERIC will convert
// letters to numbers if it gets them first.
private static TextFilter[] _tf = {
TextFilter.get(TextFilter.NUMERIC),
TextFilter.get(TextFilter.UPPERCASE)
};
// Convert using the first supporting filter that has a conversion
public char convert( char character, int status) {
char c = 0;
for (int i = _tf.length - 1; i >= 0; i--) {
c = _tf[i].convert(character, status);
if (c != 0) {
return c;
}
}
return 0;
}
// Validate a space for separator, then by supporting filter
public boolean validate(char character) {
if (character == Characters.SPACE) {
return true;
}
for (int i = _tf.length - 1; i >= 0; i--) {
boolean b = _tf[i].validate(character);
if (b) {
return true;
}
}
return false;
}
}

Resources