DirectMyFile / coreutils

Coreutils in Dart
4 stars 3 forks source link

Don't use names of binary types. Use binary kinds instead #5

Open mezoni opened 9 years ago

mezoni commented 9 years ago
static dynamic readValue(data) {
    if (data is! BinaryData) {
      return data;
    }

    if (data.isNullPtr) {
      return null;
    }

    if (data.type.name.startsWith("char") && data.type.name != "char") {
      return readNativeString(data);
    } else {
      var v = data.value;
      if (v is List) {
        v = v.map(readValue).toList();
      } else if (v is Map) {
        var out = {};
        for (var k in v.keys) {
          out[k] = readValue(v[k]);
        }
        return out;
      }
      return v;
    }
  }

What is a puprose of dynamic readValue(data)? In C langauge impossible to determine is data string or not.

char *str = "Hello";
char ca[512];
char *bytes = ca;

char *str are string or not? char *bytes are string or not?

Aslo this may not work.

if (data.type.name.startsWith("char") && data.type.name != "char") {

This should work

helper.declare("typedef char SYMBOL;");
helper.declare("typedef SYMBOL MY_CHAR;");
print(types["MY_CHAR"].compatible(types["char"], true));

I ask because once I planned add the support of binary wrappers and binary readers.

Eg.

typedef struct foo {
  int i;
  char *s;
} Foo;
class Foo {
  int i;
  String s;
} 

With binary readers plain old Dart object (PODO) Foo can be filled (hydrated) from the typedef struct foo Foo without a requirements to implementing additional fillers.

var foo = reader.read(binaryData, Foo); // "Foo" is instance of "RuntimeType"
sendToEndUser(foo);

Of course, with a reflection but not so slow (because information about the requested (to read) runtime types (PODO) are cached).

Binary wrappers allows work slightly easier with C structs (binary data).

azenla commented 9 years ago

Thanks. This is the first time I have ever dealt with C, I always used C++ (but I even then only have written maybe 60 lines). If you see anything else I am doing wrong, please let me know :)

mezoni commented 9 years ago

I begun work on binary marshalling. For the purpose: "much less doing wrong" with unmarshalling binary data into Dart classes (structs).

azenla commented 9 years ago

Cool :)

mezoni commented 9 years ago

This protoptype already works:

import "package:binary_types/binary_types.dart";
import "package:binary_marshalling/annotations.dart";
import "package:binary_marshalling/binary_marshalling.dart";

final BinaryUnmarshaller _unmarshaller = new BinaryUnmarshaller();

void main() {
  var types = new BinaryTypes();
  var helper = new BinaryTypeHelper(types);
  helper.declare(_header);
  final data = types["FOO"].alloc(const []);
  final string = helper.allocString("Hello");
  var index = 0;
  for (var c in "Hey!".codeUnits) {
    data["ca"][index++].value = c;
  }

  data["ca"][index++].value = 0;
  data["cp"].value = string;
  data["self"].value = data;
  var count = 3;
  final strings = types["char*"].array(count + 1).alloc(const []);
  final heap = [];
  for (var i = 0; i < count; i++) {
    var object = helper.allocString("String $i");
    // For preventing a deallocation (auto freeing)
    heap.add(object);
    strings[i].value = object;
  }

  for (var i = 0; i < 3; i++) {
    data["cb"][i].value = 41;
  }

  data["strings"].value = strings;
  // Now we have filled "struct foo"
  // Unmarshall it to "Foo"

  // JUST ONE LINE OF CODE!
  Foo foo = _unmarshaller.unmarshall(data, Foo);

  print("ca     : ${foo.ca}");
  print("cb     : ${foo.cb}");
  print("cp     : ${foo.cp}");
  print("i      : ${foo.i}");
  print("self   : ${foo.self}");
  print("strings: ${foo.strings}");
}

const String _header = '''
typedef struct foo {
  // For string
  char ca[10];

  // For bytes
  char cb[10];

  struct foo *self;

  int i;

  char *cp;

  // Ptr to null terminated array of strings
  char **strings;

} FOO;
''';

class Foo {
  String ca;

  @NullTerminated()
  List<int> cb;

  String cp;

  @NullTerminated()
  List<String> strings;

  int i = 0;

  Foo self;
}

Make it available (publish)? Next will be a wrapper for binary structs.

mezoni commented 9 years ago

Results:

ca     : Hey!
cb     : [41, 41, 41, null, null, null, null, null, null, null]
cp     : Hello
i      : 0
self   : Instance of 'Foo'
strings: [String 0, String 1, String 2]
mezoni commented 9 years ago

Slightly improved. An integer and a float values in C does not have a NULL value and they filled (rest of array elements) with an appropriate values (false, 0, 0.0).

const String _header = '''
typedef struct foo {
  _Bool ba[3];

  // For string
  char ca[10];

  // For bytes
  char cb[10];

  struct foo *self;

  int i;

  char *cp;

  // Ptr to null terminated array of strings
  char **strings;  
} FOO;
''';

class Foo {
  List<bool> ba;

  String ca;

  List<int> cb;

  String cp;

  @NullTerminated()
  List<String> strings;

  int i = 0;

  Foo self;
}
ba     : [false, false, false]
ca     : Hey!
cb     : [41, 41, 41, 0, 0, 0, 0, 0, 0, 0]
cp     : Hello
i      : 0
self   : Instance of 'Foo'
strings: [String 0, String 1, String 2]

P.S.

Your opinion plays a role for me.

azenla commented 9 years ago

I like it a lot :)

azenla commented 9 years ago

@mezoni btw, I am moving all my syscall stuff into another package.