Last active
March 9, 2021 17:02
-
-
Save mraleph/4eb5ccbb38904075141e to your computer and use it in GitHub Desktop.
manual big endian conversion in Dart
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
library writer; | |
import 'dart:typed_data'; | |
/// Writer wraps a fixed size Uint8List and writes values into it using | |
/// big-endian byte order. | |
class Writer { | |
/// Output buffer. | |
final Uint8List out; | |
/// Current position within [out]. | |
var position = 0; | |
Writer._create(this.out); | |
factory Writer(size) { | |
final out = new Uint8List(size); | |
if (Endianness.HOST_ENDIAN == Endianness.LITTLE_ENDIAN) { | |
return new _WriterForLEHost._create(out); | |
} else { | |
return new _WriterForBEHost._create(out); | |
} | |
} | |
writeFloat64(double v); | |
writeFloat32(double v); | |
writeInt32(int v) { | |
out[position + 3] = v; | |
out[position + 2] = (v >> 8); | |
out[position + 1] = (v >> 16); | |
out[position + 0] = (v >> 24); | |
position += 4; | |
} | |
writeInt16(int v) { | |
out[position + 1] = v; | |
out[position + 0] = (v >> 8); | |
position += 2; | |
} | |
writeInt8(int v) { | |
out[position] = v; | |
position++; | |
} | |
writeString(String str) { | |
out.setAll(position, str.codeUnits); | |
position += str.codeUnits.length; | |
} | |
} | |
/// Lists used for data convertion (alias each other). | |
final Uint8List _convU8 = new Uint8List(8); | |
final Float32List _convF32 = new Float32List.view(_convU8.buffer); | |
final Float64List _convF64 = new Float64List.view(_convU8.buffer); | |
/// Writer used on little-endian host. | |
class _WriterForLEHost extends Writer { | |
_WriterForLEHost._create(out) : super._create(out); | |
writeFloat64(double v) { | |
_convF64[0] = v; | |
out[position + 7] = _convU8[0]; | |
out[position + 6] = _convU8[1]; | |
out[position + 5] = _convU8[2]; | |
out[position + 4] = _convU8[3]; | |
out[position + 3] = _convU8[4]; | |
out[position + 2] = _convU8[5]; | |
out[position + 1] = _convU8[6]; | |
out[position + 0] = _convU8[7]; | |
position += 8; | |
} | |
writeFloat32(double v) { | |
_convF32[0] = v; | |
out[position + 3] = _convU8[0]; | |
out[position + 2] = _convU8[1]; | |
out[position + 1] = _convU8[2]; | |
out[position + 0] = _convU8[3]; | |
position += 4; | |
} | |
} | |
/// Writer used on the big-endian host. | |
class _WriterForBEHost extends Writer { | |
_WriterForBEHost._create(out) : super._create(out); | |
writeFloat64(double v) { | |
_convF64[0] = v; | |
out[position + 0] = _convU8[0]; | |
out[position + 1] = _convU8[1]; | |
out[position + 2] = _convU8[2]; | |
out[position + 3] = _convU8[3]; | |
out[position + 4] = _convU8[4]; | |
out[position + 5] = _convU8[5]; | |
out[position + 6] = _convU8[6]; | |
out[position + 7] = _convU8[7]; | |
position += 8; | |
} | |
writeFloat32(double v) { | |
_convF32[0] = v; | |
out[position + 0] = _convU8[0]; | |
out[position + 1] = _convU8[1]; | |
out[position + 2] = _convU8[2]; | |
out[position + 3] = _convU8[3]; | |
position += 4; | |
} | |
} |
If you want to understand fundamentals then you should study how different types are represented in memory and have a grasp of things like big/little endian byte orders.
For parsing you can use ByteData class, it allows you to extract specific types from a sequence of bytes.
If data arrives to you as hex string you can convert it into a List<int>
using hex
codec from package:convert
, after that you can create ByteData
from it, e.g.
import 'dart:typed_data';
import 'package:convert/convert.dart';
void parse(String s) {
// Convert hex from the given string to a sequence of bytes (first two characters become first byte and so on).
final bd = ByteData.sublistView(Uint8List.fromList(hex.decode(s)));
print(bd.getInt32(10, Endian.little)); // print timestamp (should print 1615217400)
}
void main() {
parse('534D627480650300A201F84246600000F0420000F2420000F4420000803F000000400000404000007A4400002041005043470050C3466666663FCDCC4C3F3333333F00007042333333333333E33F9A9999999999D93F40016001200100E700E700E700E700E700E7B803BD03B30332');
}
@mraleph thank you so much!
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
@mraleph I'm getting something like this:
534D627480650300A201F84246600000F0420000F2420000F4420000803F000000400000404000007A4400002041005043470050C3466666663FCDCC4C3F3333333F00007042333333333333E33F9A9999999999D93F40016001200100E700E700E700E700E700E7B803BD03B30332
this data comes from a bluetooth device. Then I need to break this in parts and extract some informations.
Timestamp is in the position 20-28. Some values are float, some are int. What I need to do is get this values and parse to the correct type.
What should I study do understand how this conversions work? Thank you!