Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Array of Struct #52

Closed
psamim opened this issue Jul 21, 2016 · 5 comments
Closed

Array of Struct #52

psamim opened this issue Jul 21, 2016 · 5 comments

Comments

@psamim
Copy link

psamim commented Jul 21, 2016

Hi,

I am new to jBinary and have not used it before. Sorry if this issue is more like a question than a real issue or bug, but I really could not figure it out from the wiki documents.

I have an array of a struct in a file, the below code does not work. Am I using jBinary incorrectly? Maybe someone can correct me or point me to an example?.

var fs = require('fs');
var jBinary = require('jbinary');

var TIME_T = {
    'u32': 'uint32',
    'time': {
        hour: 'int16',
        min: 'int8',
        type: 'int8'
    }
};

var DATE_T = {
    u32: 'uint32',
    date: {
        day: 'int8',
        month: 'int8',
        year: 'int16'
    }
};

var LOG_T = {
    time: TIME_T, // time of log
    date: DATE_T, // date of log
    temp: 'float', // chamber temperature
    tempSp: 'float', // temperature set point
    tmpRamp: 'float', // temperature ramp
    hum: 'float', // chamber humidity
    humSp: 'float', // humidity set point
    light: 'uint8', // chamber light
    fan: 'uint8', // chamber fan
    tmpMax: 'float', // maximum temperature allowed
    tmpMin: 'float', // minimum temperature allowed
    humMax: 'float', // maximum humidity allowed
    humMin: 'float', // minimum humidity allowed
    roomTemp: 'uint8', // room temperature
    alarmStatus: 'uint16' // alarm status (refer to alarm mask defines)
};

For reading it as an array, the below code does not do the job:

FLGTypeSet = {
    'jBinary.all': 'All',
    Log: LOG_T,
    All : ['array', 'Log']
}

jBinary.load('10.FLG', FLGTypeSet, function(err, binary) {
    console.log(binary.readAll());
};

or maybe I should define another type, which does not work too:

FLGTypeSet = {
    'jBinary.all': 'All',

    // declaring custom type by wrapping structure
    Log: jBinary.Template({
        setParams: function (itemType) {
            this.baseType = {
                length: LOG_T,
                values: LOG_T
            };
        },
        read: function () {
            return this.baseRead().values;
        },
        write: function (values) {
            this.baseWrite({
                length: values.length,
                values: values
            });
        }
    }),

    All : ['array', 'Log']
}

jBinary.load('10.FLG', FLGTypeSet, function(err, binary) {
    console.log(binary.readAll());
};

Thanks

@RReverser
Copy link
Member

For reading it as an array, the below code does not do the job

What you're getting as a result? Can you put the code and sample file together in some repo I could take a look at?

@psamim
Copy link
Author

psamim commented Jul 21, 2016

@RReverser Thank for the quick reply! I appreciate it. The code is as above but as requested I put it in the a repo along with the binary file and its C header. I get no results and no errors.

https://github.com/psamim/jbinary-test/blob/master/index.js

@RReverser
Copy link
Member

RReverser commented Jul 21, 2016

First mistake - I see that C version defines DATE_t and TIME_t as unions of u32 and struct (that is, they both point to the same data), while you define them as consequent fields in JS version, which makes them reading 2 times more bytes than needed, and then everything goes wrong. I guess you don't really care about u32 part, so can just drop it and leave fields inside of structure like following:

var TIME_T = {
      hour: 'int16',
      min: 'int8',
      type: 'int8'
};

var DATE_T = {
      day: 'int8',
      month: 'int8',
      year: 'int16'
};

Second - if I understand correctly, in C, you're reading structures by simply mapping them onto the memory region. The problem that happens is that in C, structures are automatically aligned (not packed) by default for performance reasons, while jBinary does not make any assumptions about the behavior of the underlying data types. If you compile your C version with -Wpadded, you can see where compiler adds alignment bytes, and replicate them in your data structures explicitly using skip type:

screen shot 2016-07-21 at 14 22 46

    LOG_T: {
        time: 'TIME_T', // time of log
        date: 'DATE_T', // date of log
        temp: 'float', // chamber temperature
        tempSp: 'float', // temperature set point
        tmpRamp: 'float', // temperature ramp
        hum: 'float', // chamber humidity
        humSp: 'float', // humidity set point
        light: 'uint8', // chamber light
        fan: 'uint8', // chamber fan
        _align1: ['skip', 2], // simulating C alignment
        tmpMax: 'float', // maximum temperature allowed
        tmpMin: 'float', // minimum temperature allowed
        humMax: 'float', // maximum humidity allowed
        humMin: 'float', // minimum humidity allowed
        roomTemp: 'uint8', // room temperature
        _align2: ['skip', 1], // simulating C alignment
        alarmStatus: 'uint16' // alarm status (refer to alarm mask defines)
    }

Finally, looks like you're assuming little-endian byte order (most common on x86 CPUs). If so, you need to add 'jBinary.littleEndian': true to your typeset.

With these fixes, everything should work fine. I played a bit with your code and you can find version with those modifications here: https://gist.github.com/RReverser/bf31bfd30a09362c95a78894a73d359b

Good luck! :)

@psamim
Copy link
Author

psamim commented Jul 22, 2016

Thanks for taking your time and this complete answer. I did not know about the concepts you mentioned above. Your code works as expected.

May I ask what is the program in the screenshot, that indicated the alignments as warnings? How did you find them?

@RReverser
Copy link
Member

May I ask what is the program in the screenshot, that indicated the alignments as warnings? How did you find them?

Sure. I wrote above:

If you compile your C version with -Wpadded

So you can just pass this as an argument to gcc / clang when compiling C version, and it will report those paddings as warnings. Specific editor doesn't really matter.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants