How do I convert the below java code to equivalent dart.
private static final byte[] mIdBytes = new byte[]{(byte) 0x01, (byte) 0x02, (byte) 0x03, (byte) 0x7E};
byte[] data;
System.arraycopy(mIdBytes, 2, data, 0, 4);
Is there any Dart method that does a similar kind of operation?
I was looking into this:
https://pub.dev/documentation/ckb_dart_sdk/latest/ckb-utils_number/arrayCopy.html
To match Java's System.arrayCopy(source, sourceOffset, target, targetOffset, length)
you should use
target.setRange(targetOffset, targetOffset + length, source, sourceOffset);
This is more efficient than using List.copyRange for some lists, for example copying between typed-data lists with the same element size (like two Uint8Lists).
Well, I found the way to do it.
you can just use
List.copyRange(data, 0, mIdBytes, 2);
This is a workaround I kinda found to be done in your case. This is called sublist(), this method will take the start index, and an end index.
IDEA:
Use sublist(), and copy the elements to be started from, that sourcePos = you_pos
Source array will be used like sourceArray.sublist(startIndext, endIndex)
The destination array will be initialized with the value using sublist()
Till what length the item should be added would be mentioned in the end index+2, since it will ignore the last item, and copy till the index-1
FINAL CODE
void main() {
List<int> source = [1, 2, 3, 4, 5, 6];
List<int> target = [];
int startPos = 1;
int length = 4;
// to ensure the length doesn't exceeds limit
// length+2 because, it targets on the end index, that is 4 in source list
// but the end result should be length+2 to contain a length of 5 items
if(length+1 <= source.length-1){
target = source.sublist(startPos, length+2);
print(target);
}else{
print('Cannot copy items till $length: index out of bound');
}
}
//OUTPUT
[2, 3, 4, 5, 6]
Related
Is there a method we use to reach the desired number in an array given in dart language.. I can do this for binary ones, but I can't do it for a code that finds the sum of 3 or more elements
For example
Input: candidates = [10,1,2,7,6,1,5], target = 8
Output:
[
[1,1,6],
[1,2,5],
[1,7],
[2,6]
]
this is the my code i have done until now
void main() {
var candidates = [10, 1, 2, 7, 6, 1, 5], target = 8;
var answer = [];
for (int i = 0; i < candidates.length; i++) {
for (int j = 0; j < candidates.length; j++) {
if (candidates[i] + candidates[j] == target && i != j && i < j) {
answer.add([candidates[i], candidates[j]]);
}
}
}
}
I am sure this can be done more efficient but since the solution is for some Leetcode assignment, I don't really want to spend too much time on optimizations.
I have tried added some comments in the code which explains my way of doing it:
void main() {
getSumLists([10, 1, 2, 7, 6, 1, 5], 8).forEach(print);
// [5, 1, 2]
// [1, 6, 1]
// [1, 7]
// [6, 2]
getSumLists([2, 5, 2, 1, 2], 5).forEach(print);
// [2, 1, 2]
// [5]
}
Iterable<List<int>> getSumLists(
List<int> candidates,
int target, {
List<int>? tempAnswer,
int sum = 0,
}) sync* {
// We cannot use default value in parameter since that makes list const
final tempAnswerNullChecked = tempAnswer ?? [];
if (sum == target) {
// We got a result we can return.
// OPTIMIZATION: If you know the returned list from each found result is not
// being used between found results, you can remove the `.toList()` part.
yield tempAnswerNullChecked.toList();
} else if (sum > target) {
// No need to search further in this branch since we are over the target
return;
}
// Make a copy so we don't destroy the input list but also so it works even
// if provided list as input is non-growing / non-modifiable
final newCandidates = candidates.toList();
while (newCandidates.isNotEmpty) {
// We take numbers from the end of the list since that is more efficient.
final number = newCandidates.removeLast();
// Recursive call where we return all results we are going to find given
// the new parameters
yield* getSumLists(
newCandidates,
target,
tempAnswer: tempAnswerNullChecked..add(number),
sum: sum + number,
);
// Instead of creating a new tempAnswerNullChecked, we just reuse it and
// make sure we remove any value we are temporary adding
tempAnswerNullChecked.removeLast();
// Ensure we don't get duplicate combinations. So if we have checked the
// number `1` we remove all `1` so we don't try the second `1`.
newCandidates.removeWhere((element) => element == number);
}
}
List<int> l = [ 1, 2, 3, 4 ];
var b = ByteData(10);
May I know what is the easiest way to fill b (position 4 ~ 7) with data from l.
I can certainly iterate through l and then fill b one by one. But this is just part of a larger solution. So I hope there is a simpler way (for easy maintenance in future).
ByteData represent an area of memory counted in bytes but does not tell us anything how we want to represent the data inside this block of memory.
Normally, we would use one of the specific data types from dart:typed_data like e.g. Uint8List, Int8List, Uint16List and so on which have a lot more functionality.
But you can easily get the same by making a view over your ByteData. In this example I guess you want to insert your numbers as Uint8:
import 'dart:typed_data';
void main() {
List<int> l = [ 1, 2, 3, 4 ];
var b = ByteData(10);
var uInt8ListViewOverB = b.buffer.asUint8List();
uInt8ListViewOverB.setAll(4, l);
print(uInt8ListViewOverB); // [0, 0, 0, 0, 1, 2, 3, 4, 0, 0]
}
I recommend reading the documentation for the different methods on ByteBuffer (returned by buffer). You can e.g. make subview of a limited part of your ByteData if your ByteData needs to contain different types of data:
https://api.dart.dev/stable/2.15.0/dart-typed_data/ByteBuffer/asUint8List.html
I need to parse an array of 32 bit ints (little endian), from an array of u8s, however the next int only exists if the 31st bit of the current int is set. If the rest don't exist then the rest of the array should be set to zeroes. I'm not sure how to go about conditionally parsing the next element.
Lets say the field is 4 bytes long. Then the result of the parse_field function would be that the 4 bytes would be parsed with le_u32, and that would be the first element in the [u32; 8] array. If however, this field's 31st bit is set. Then there exists another 4 bytes that is also like this field and it goes in the next element in the array. If it is not set then the function must return, the array with the rest of the elements set to zero. And this continue for each existing field.
For example for the following input:
0x8000000a
0x8000000b
...
You would get [0x8000000a, 0x8000000b, 0, 0, 0, 0, 0, 0]
But if the input is
0x8000000a
0x8000000b
0x8000000c
0x8000000d
0x8000000e
....
Then you would get [0x8000000a, 0x8000000b, 0x8000000c, 0x8000000d, 0x8000000e, 0, 0, 0]
extern crate nom;
use nom::*;
#[derive(Clone, Copy, Debug)]
struct Derp {
field: [u32; 8]
}
named!(parse_field<[u32; 8]>,
// what do I do here
);
named!(parse_derp<Derp>,
do_parse!(
field: parse_field >>
(Derp {
field: field
})
)
);
fn main() {
let temp = [0x0a, 0x00, 0x00, 0x80, 0x0b, 0x00, 0x00, 0x80];
println!("{:?}", parse_derp(&temp));
}
Also is it possibly better to use a Vec here?
Here is a parser that matches the last u32 of your input:
named!(last_u32<u32>,
verify!(le_u32, |n:u32| (n & 0b1) != 0) // Matches iff the 31st bit is set
);
you can then use it like this:
named!(parse_field<Vec<u32>>,
map!(
many_till!(le_u32, last_u32),
|(mut v,n)| { v.push(n); v } // Add the last u32 to the vector
)
);
I have a command line Dart script client interacting over a [dart:io] websocket with a Jetty server. I've implemented a custom message subprotocol that uses reflection (both sides) to exchange Dart objects with Java objects in Jetty using binary encoding. PODO -> Uint8List -> wire -> ByteBufer -> POJO (and in reverse for the return trip). The local round trip unit tests execute correctly on either side (i.e. PODO -> Uint8List -> PODO; POJO -> ByteBuffer -> POJO). I've tested the connection with a different service endpoint using a series of simple 'string' exchanges. The transmission from Dart to Jetty works but the response data, although correctly received, produces an odd type that I don't understand and which the decoder doesn't understand as either a Uint8List, ByteBuffer, etc.
Although I can't easily distill this into a small example, here is the relevant code and some output:
Dart Client:
WebSocket.connect(url).then((WebSocket socket) {
_log.finer('connected');
_websocket = socket
..listen(_onResponse, onError: (e, StackTrace st) => print('Session error: $e; $st'));
...
}
_onResponse(data) {
print('response raw data: $data');
InstanceMirror im = reflect(data);
print('instance: $im');
...
decode(data)
}
decode(Uint8List data) {
var b = data.buffer;
ByteData bd = new ByteData.view(b);
int offset = 0;
const ENDIANNESS = Endianness.LITTLE_ENDIAN;
int msgLength = bd.getInt32(offset, ENDIANNESS); // is 6645122; should be 101
...
}
Output:
response raw data: [101, 0, 0, 0, ...]
instance: InstanceMirror on Instance of '_Uint8ArrayView'
The IntelliJ debugger shows:
data = {List[id=1]} size = 101
> im = {_LocalInstanceMirror[id=2]} InstanceMirror on Instance of '_Uint8ArrayView'
_reflectee = {List[id=1]}
_type = null
hasReflectee = true
Dart supports the general ByteBuffer type which just represents a list of bytes as you can see here:
https://api.dartlang.org/apidocs/channels/stable/dartdoc-viewer/dart:typed_data.ByteBuffer
As the ByteBuffer class is abstract, you create lists from either receiving a ByteBuffer object or by instantiating a new list. The list usually is fixed length and working with it is hard. That's why you can create views from a ByteBuffer. A view represents a subset of the ByteBuffers bytes, given by an offset and a length which could also be the whole buffer.
Let's look at a small example:
import 'dart:typed_data';
void main() {
Uint8List data8 = new Uint8List.fromList([1,2,3,4,5,6,256]);
Uint16List data16 = new Uint16List.fromList([1,2,3,4,5,6,256]);
print(data8);
print(data16);
print(data8.buffer.lengthInBytes);
print(data16.buffer.lengthInBytes);
print(data16.buffer.asUint8List());
print(data16.buffer.asUint16List());
}
which gives you:
[1, 2, 3, 4, 5, 6, 0] // List
[1, 2, 3, 4, 5, 6, 256] // List
7
14
[1, 0, 2, 0, 3, 0, 4, 0, 5, 0, 6, 0, 0, 1] // View
[1, 2, 3, 4, 5, 6, 256] // View
This means: ByteBuffer is some abstract class which gives you the interface and basic functionality and you can get views from a buffer to access the data as you need it.
The buffer accessed by 'data.buffer' is an internal buffer backing the Uint8List view referenced by 'data'. The transmitted payload -- what I want to wrap with the ByteData view -- is offset by some number of bytes into this buffer. The 'offset' of the payload can be determined through the 'offsetInBytes' property of the 'data' object. The following changes to decode() make it possible to use the ByteData API to decode various fragments of the payload byte array:
int offset = data.offsetInBytes; // sets offset to the starting position of the payload
int msgLength = bd.getInt32(offset);
double somethingElse = bd.getFloat64(offset+4);
// etc.
In Vala, some methods require an Array of uint8's (uint8[]) as a parameter. For example see http://valadoc.org/#!api=glib-2.0/GLib.FileStream.write
I have the following code, but no idea how to "cast" my value to an array:
...
uint8 some_integer = 7;
desc.write(???, 1);
...
In C I'd simply do:
...
uint8 some_integer = 7;
fwrite(&some_integer, 1, 1, desc);
...
but the Vala compiler is not amused about the &-operator. What to do?
You can create an array in Vala as int[] b = { 2, 4, 6, 8 };. Hence you should be able to create it with a single variable too as uint8 [] some_array = {some_integer};; in your case desc.write({some_integer}, 1);.
Here's a detailed guide on Vala for further references.