Giter VIP home page Giter VIP logo

jdataview's Introduction

Build Status NPM version jDataView - A unique way to work with a binary file in JavaScript.

jDataView provides a layer on top of DataView to make modifying binary data a pleasure.

jDataView is a drop-in replacement for the native DataView, adding methods for setting string, arbitrary-sized integers, and more.

Documentation

History

There are three ways to read a binary file from the browser.

  • The first one is to download the file through XHR with charset=x-user-defined. You get the file as a String, convert it to byte Array and you have to rewrite all the decoding and encoding functions (getUint16, getFloat32, ...). All the browsers support this.

  • Then browsers that implemented Canvas also added CanvasPixelArray as part of ImageData. It is fast byte array that is created and used internally by <canvas /> element for manipulating low-level image data. We can create such host element and use it as factory for our own instances of this array.

  • Then browsers that implemented WebGL added ArrayBuffer. It is a plain buffer that can be read with views called TypedArrays (Int32Array, Float64Array, ...). You can use them to decode the file but this is not very handy. It has big drawback, it can't read non-aligned data (but we can actually hack that). So they replaced CanvasPixelArray with Uint8ClampedArray (same as Uint8Array, but cuts off numbers outside 0..255 range).

  • A new revision of the specification added DataViews. It is a view around your buffer that can read/write arbitrary data types directly through functions: getUint32, getFloat64 ...

And one way to read a binary file from the server.

jDataView provided a polyfill for the DataView API with own convenient extensions using the best available option between Arrays, TypedArrays, NodeJS Buffers and DataViews.

Now that DataView is natively available in all engines, jDataView 3 acts as a layer on top of it with powerful methods for dealing with non-standard binary data types, such as strings and arbitrary-sized integers.

Also check out (jBinary)

For complicated binary structures, it may be hard enough to use only low-level get/set operations for parsing, processing and writing data.

In addition, most likely you might need convenient I/O methods for retrieving data from external sources such like local files (using File API or from Node.js), remote files (via HTTP(S)), data-URIs, Node.js streams etc. as well as for displaying generated content to user on webpage in image/video/audio/... containers or even as simple download link.

If you faced any of these problems, you might want to check out new jBinary library that works on top of jDataView and allows to operate with binary data in structured and convenient way.

Demos

HTTP Live Streaming realtime converter and player demo implemented using jBinary data structures. Screenshot


A World of Warcraft Model Viewer. It uses jDataView+jBinary to read the binary file and then WebGL to display it. Screenshot


A PhotoSynth WebGL Viewer by Visual Experiments. It uses jDataView to read the binary file and then WebGL to display it. Screenshot


A simple tar viewer. It is a "Hello World" demo of how easy it is to use the library.


JavaScript TrueTypeFont library demo which uses jDataView to read and display glyphs from TrueType file.

--

jBinary.Repo ready-to-use typesets and corresponding demos of using jDataView+jBinary for reading popular file formats like GZIP archives, TAR archives, ICO images, BMP images, MP3 tags etc.


Talking image - animation and audio in one package powered by HTML5 Audio, jDataView and jBinary.


Please tell us if you made something with jDataView :)

jdataview's People

Contributors

bitdeli-chef avatar clockworkgeek avatar danvk avatar divergentdave avatar gitter-badger avatar gmarty avatar grant avatar koteswar375 avatar mithgol avatar mmthomas avatar nelhage avatar reggino avatar rreverser avatar scintill avatar vjeux avatar zadeviggers avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

jdataview's Issues

Refactor tests

Use mocha's "describe" and "it" for hierarchic structure and correct engine switcher (right now Mocha calls tests asynchronously so all of them in real use Array engine).

Denormalized values aren't set properly when DataView and ArrayBuffer aren't available

I added the following denormalized boundary values to the Float64 setter tests and get errors when DataView and ArrayBuffer are not available. I haven't tried similar Float32 denormalized boundary values, but since the logic for 32/64-bit values is shared, I suspect they will also be incorrect.

Math.pow(2, -1074),
-Math.pow(2, -1074),
Math.pow(2, -1022),
-Math.pow(2, -1022),

If it helps, there is code at http://blog.coolmuse.com/2012/06/21/getting-the-exponent-and-mantissa-from-a-javascript-number which also works for the denormalized values.

Getting an error only after minification of dist/browser/jdataview.js?

When I package dist/browser/jdataview.js in a minified build (run it through google closure compiler with dojo), it ends up that the module that is given to me in the AMD is an empty Object e.g. {} from chrome devtools

This is a fairly weird because the unminified build does not have this problem? I managed to boil it down into a pretty simple test to try, I guess I have only tried dojo so far on it but could try other AMD loaders perhaps https://github.com/cmdcolin/jdataview_tester

Screenshots from unminified

virtualbox_lubuntu_13_07_2017_01_25_41

Screenshot after minified

virtualbox_lubuntu_13_07_2017_01_32_26

Any ideas? I guess I realize this might not be a jdataview specific issue so I cross posted here https://stackoverflow.com/questions/45072183/jdataview-module-not-working-in-amd-after-running-through-minification-with-goog

2.4.6: Uncaught ReferenceError: NODE is not defined

Unable to use version 2.4.6 because of above mentioned exception:

Uncaught ReferenceError: NODE is not defined jdataview.js:3

And unable to use earlier version with bower. Only latest one is made available.

Diff with previous version shows the following:

  • version 2.4.6
var compatibility = {
    // NodeJS Buffer in v0.5.5 and newer
    NodeBuffer: NODE && 'Buffer' in global,
...
  • 2.4.5
var compatibility = {
    // NodeJS Buffer in v0.5.5 and newer
    NodeBuffer: 'Buffer' in global && 'readInt16LE' in Buffer.prototype,
...

jDataView should not have intrinsic endianness

According to the current (Editor's Draft 02 April 2012) and the previous (Version 1.0, 08 February 2011) version of DataView specifications,

  • the constructor of DataView has only three arguments (buffer, byteOffset, byteLength), but does not have the fourth (littleEndian);
  • consequently, the DataView object does not have any endianness of its own;
  • when optional boolean argument littleEndian in any of the read/write multi-byte methods is missing, it does not mean “use the object's endianness given in the constructor”, it simply means that the value is stored in big-endian byte order.

The current implementation of jDataView does not correspond to the above mentioned details of DataView specifications:

  • the constructor of jDataView has four arguments (buffer, byteOffset, byteLength, littleEndian);
  • the fourth of those arguments (littleEndian) defines the object's intrinsic endianness (_littleEndian property);
  • when optional boolean argument littleEndian in any of the read/write multi-byte methods is missing, the value of _littleEndian property is used instead of the big-endian byte order.

The difference between jDataView and DataView does not exist unless someone actually gives some fourth argument to the constructor — and that person probably knows what it means, I presume.

However, this difference adds an unnecessary processing complexity to the implementation. For each read/write multi-byte operation, an additional check becomes necessary:

if (littleEndian === undefined) {
   littleEndian = this._littleEndian;
}

That's why I believe that jDataView implementation may become faster if the littleEndian argument in the constructor and the _littleEndian property in the object are eliminated (with all of the code lines that use them).

Weird Float types (48 & 80 bit)

I thought to make a note that about weird, archaic floating point bit-sizes (the real 48-bit, and long double 80 bit).

A tiny library I wrote can read these, called Float80. I had to write it because I couldn't find anything else.

Perhaps referencing it somewhere from jDataView (e.g. the Wiki / ) might save someone else a bit of effort.

In any case, feel free to close this at will as I'm not really reporting a real issue with jDataView.

🍻

float32 values corrupted in firefox after reading a uint16

Hi, In firefox, when I read an uint16 then some float32, the float32 aren't ok, even though they are fine if I remove the uint16 :

var file = jDataView.createBuffer(
0x80, 0x3F,
0x00, 0x00, 0x00, 0xBF,
0x00, 0x00, 0x00, 0xBF,
0x00, 0x00, 0x80, 0x3F
);

var view = new jDataView(file);

console.log(view.getUint16());
console.log(view.getFloat32());
console.log(view.getFloat32());
console.log(view.getFloat32());

output :
16256
5.877426211911347e-39
5.877426211911347e-39
5.854557020973566e-39

If I remove 0x80, 0x3F and the "console.log(view.getUint16());", the output is :
-0.5
-0.5
1

When I run :
console.log('arrayBuffer?', view._isArrayBuffer);
console.log('dataView?', view._isDataView);

The output is :
arrayBuffer? true
dataView? false

Thank you!

Values don't read right in Safari and Webkit under windows

It seems to be working great in most browsers (tested opera, firefox and chrome).

In webkit and safari under windows, when trying to read the content of a file, the getInt8 function returns 0xfd for every value over 0x7f. It seems to be working fine in the version of safari mobile
running on the Ipad though.

Regards, and thank you for the great work!

Bitfields doesn't work well in littleEndian mode

The following code works as expected:

      var view = new jDataView([0x4f, 0x01, 0x18], littleEndian = false);
      console.log("value: " + view.getInt16());
      console.log("ch1: "+ view.getUnsigned(1))
      console.log("ch2: "+ view.getUnsigned(1))
      console.log("ch3: "+ view.getUnsigned(1))
      console.log("ch4: "+ view.getUnsigned(1))
      console.log("ch5: "+ view.getUnsigned(1))
      console.log("ch6: "+ view.getUnsigned(1))
      console.log("ch7: "+ view.getUnsigned(1))
      console.log("ch8: "+ view.getUnsigned(1))

However, when setting littleEndian = true the browser (Firefox and Chrome) gives an out of bounds exception:

Uncaught RangeError: Offsets are out of bounds.
    e._checkBounds @ jdataview.js:263
    e._getBytes @ jdataview.js:317
    e._getBitRangeData @ jdataview.js:574
    e.getUnsigned @ jdataview.js:599
    (anonymous function) @ (index):54

Easier IE binary response parsing

When I did own "research" project (any-palette BMP viewer (demo)), I learned different ways for reading binary data from XHR response in IE9 too, and I found out that using special Visual Basic script that was describen as the only way of getting that data, is not really needed. I used such implementation of AJAX request (I didn't really want to use jQuery, but that doesn't matter) and it worked in both IE9 and normal browsers (incl. IE10) as well.

// reading image with AJAX request

var xhr = new XMLHttpRequest;
xhr.open('GET', source, true);

// new browsers (XMLHttpRequest2-compliant)
if ('responseType' in xhr) {
    xhr.responseType = 'arraybuffer';
}
// old browsers (XMLHttpRequest-compliant)
else if ('overrideMimeType' in xhr) {
    xhr.overrideMimeType('text/plain; charset=x-user-defined');
}
// IE9 (Microsoft.XMLHTTP-compliant)
else {
    xhr.setRequestHeader('Accept-Charset', 'x-user-defined');
}

xhr.onload = function() {
    if (this.status != 200) {
        throw new Error(this.statusText);
    }
    // emulating response field for IE9
    if (!('response' in this)) {
        this.response = new VBArray(this.responseBody).toArray().map(String.fromCharCode).join('');
    }
    callbackImg(this.response);
}

xhr.send();

How about changing that ugly VB script to new VBArray(this.responseBody).toArray().map(String.fromCharCode).join(''); for reading binary data?

jDataView => jdataview npm package rename

Due to relatively new npm restrictions and for ability to publish future version via API jDataView package was renamed to jdataview in npm registry (that's tricky, but possible).

As npm documentation states, we can create redirection from npm package name to some another registry url.
So I tried curl -v -u ***** -X PUT -H "Accept: text/plain,text/html,application/json" "Content-Type: application/json" -d '{"name":"jDataView",...}' http://registry.npmjs.org/jDataView for putting redirect from old name to new one, but got {"error":"forbidden","reason":"New packages must have all-lowercase names"}.

Tried to do the same via couchapp (Futon), no luck.

So currently wrote e-mail to @isaacs for setting redirect as was with other packages with similar issue, meanwhile please update your package.json to point to new dependency (I'm going to send pull requests to all the found on GitHub though).

Sorry for inconveniences.

probably, broken release 2.2.3

in npm registry 2.2.3 contains no folder src. 2.2.2 is ok. Please, reupload.

PS. Also, please, use git tags to mark your release points.

PPS. Here are examples of .npmignore and Makefile, to automate publishing process. That helps to avoid mistakes.

TAR example not working with IE 8 or 9

TAR example is not working out of the box on IE 8. Tries to use Array.prototype.map which is IE 9 only. Also using 'dataview' in $.get() fails as there is no type dataview in the modified jQuery. Am I missing something? Trying to use with jParser.

Using jDataView in chrome throws Uncaught ReferenceError: NODE is not defined

var compatibility = {
// NodeJS Buffer in v0.5.5 and newer
NodeBuffer: NODE && 'Buffer' in global,
DataView: 'DataView' in global,
ArrayBuffer: 'ArrayBuffer' in global,
PixelData: BROWSER && 'CanvasPixelArray' in global && !('Uint8ClampedArray' in global) && 'document' in global
};

Uncaught ReferenceError: NODE is not defined(anonymous function) @ jdataview.js:4

readme update?

from ken russell:

At this point, Chrome, Safari, Opera, and even IE 10 support DataView. Firefox is the only outlier, but https://bugzilla.mozilla.org/show_bug.cgi?id=575688 is in progress, and per agreement from all of the browser developers, in order to pass the next version of the WebGL conformance suite, DataView support will be required.

Incorrect output for IE10 and Chrome but Correct for Firefox

I have tried to use jDataView in my project and have insert a Double and the rest Integer in my document. I used getFloat64() and then start the byte with 8 and getInt32(). For such, Firefox is returning correct value, but not Chrome and IE10. Any potential bugs is foreseen here?

By the way the document I wrote in Binary was using C# Binary Writer, therefore the littleEndian is set to True.

Thanks
Bernad

Uint64.toString fails for large numbers

For example:

new jDataView.Uint64(12345678, 12345678).toString()  // "53024283269292370"

Whereas in Python, with arbitrary-precision numbers, I get:

print 12345678 * 2**32 + 12345678  # 53024283269292366

These differ in the last decimal.

The .valueOf() method has to round off, but there's no reason .toString() should.

Out of bounds access (RangeError) with minimified script

Hello,
I have the following error when I use jdataview on iPad 2 (ios 8.1.1) using chrome or safari. I only have this error while using repeatedly jdataview several times in a short period of time. Using the non-minimified version corrects the issue.

The byteOffset is negative.

Out of bounds access (RangeError)
setInt8@_dataViewAction@/lib/jdataview/jdataview.js:1:3838
at _action@/lib/jdataview/jdataview.js:1:3678
at /lib/jdataview/jdataview.js:1:17904
at /lib/jdataview/jdataview.js:1:9343

readString() with variable 7-bit based integer as prefix length

Hello!

So basically i'm trying to read a binary file that was created in C#, now C# (and maybe other programming languages that has a BinaryWriter) has a WriteString(string) method, what's so magic about it is that it prefixes the string with a length, but this length can vary in byte size depending on the actual length of a string, if it's a small length e.g "56", it'll be 1-byte sized, therefore I can use readUint8() in your library.
However if the length gets superior, this prefixed length becomes 2-byte sized, and in extreme cases scenarios even 4-byte sized.

Now C# doesn't have to deal with this problem because the ReadString(string) method from BinaryReader in .NET already solves this problem.
Here's how the magic works according to MSDN: Link

Now I see that you have a readString(length) method that takes a length, is there a way so that it can guess the length based on this prefix? Knowing that this prefix length can be variable in byte-sized?

Thanks in advance!

Remove old fallbacks

When this library was created, DataView was a new WebGL extension available only in some browsers, but nowadays it's universally supported in JS engines.

We should remove old polyfills and let jDataView just take care of helper functionality (seeking, new types, etc.).

If someone wants to take this, please let me know.

Cannot use 'in' operator to search for 'Buffer' in undefined

Hi,

I am trying to update this plugin https://github.com/chemoish/videojs-bif that uses jDataView to analyze a bif image.

But I keep running into this error.

Cannot use 'in' operator to search for 'Buffer' in undefined
In jDataView it is stopping at this line.

NodeBuffer: !0 && "Buffer" in global,
Seems to be an issue with the global.

You can see the file that calls the jDataView here.

https://github.com/chemoish/videojs-bif/blob/master/src/parser.js

It works on the old version but not the latest one I am just a bit confused with how to resolve this error been stuck on it for a while now.

Maybe it has something to do with the way the new video-js plugin generator is setup https://github.com/videojs/generator-videojs-plugin

Not sure any help would be appreciated thanks.

drop support for Node v0.5.4

Current version of jdataview.js contains the following code:

// 0.6.0 -> readInt8LE(offset)
NodeBufferFull: typeof Buffer !== 'undefined' && 'readInt8LE' in Buffer,
// 0.5.0 -> readInt8(offset, endian)
NodeBufferEndian: typeof Buffer !== 'undefined' && 'readInt8' in Buffer

If NodeBufferEndian is true, jDataView assumes it's safe to call methods like readInt16(offset, endian) where endian is a boolean value (true for little-endian, false for big-endian). If NodeBufferFull is true, methods like readInt16LE(offset) and readInt16BE(offset) are called.

There is a couple of problems related to that.

First of all, it's 'readInt16' you'd check. Endianness does not affect single-byte values, that's why even in Node v0.8.1 there is readInt8 (and not readInt8LE and readInt8BE).

The second problem is that even when some readUInt16 is encountered, its second argument is not necessarily a boolean: according to the docs, in Node v0.5.3 (and the previous versions of Node) readUInt16 method existed, but its syntax was different. Literal 'little' or 'big' strings were the values:

console.log(buf.readUInt16(0, 'little'));
console.log(buf.readUInt16(1, 'big'));

In Node v0.5.5 (and all the following versions) the syntax was already modern, with LE and BE suffixes:

console.log(buf.readUInt16LE(0));
console.log(buf.readUInt16BE(1));

That's why NodeBufferEndian in jDataView seems to exist only for the sake of one Node version: 0.5.4.

A single minor version that, according to changelog, appeared in 2011.08.12 and existed for a fortnight until v0.5.5 appeared in 2011.08.26.

This support should be dropped already.

Use backing buffer/view's methods when available.

If DataView is available and the backing buffer is an ArrayView, use DataView's methods (with some indirection to change the internal offsets, I guess) instead.

This should increase performance.

for the sake of speed, move compatibility checks out of your methods

Currently you make a compatibility check each time a method is called — this slows down the code.

The engine won't change (if you are running under Node, then typeof Buffer won't become 'undefined'), so it's fine and enough to detect it only once and pick one fast method out of a few alternatives at start time instead of running a check at runtime.

Example of the current (slow) approach:

jDataView.createBuffer = function () {
    if (compatibility.NodeBuffer) {
        var buffer = new Buffer(arguments.length);
        for (var i = 0; i < arguments.length; ++i) {
            buffer[i] = arguments[i];
        }
        return buffer;
    }
    if (compatibility.ArrayBuffer) {
        var buffer = new ArrayBuffer(arguments.length);
        var view = new Int8Array(buffer);
        for (var i = 0; i < arguments.length; ++i) {
            view[i] = arguments[i];
        }
        return buffer;
    }

    return String.fromCharCode.apply(null, arguments);
};

Suggested optimization:

if (compatibility.NodeBuffer) {
    jDataView.createBuffer = function () {
        var buffer = new Buffer(arguments.length);
        for (var i = 0; i < arguments.length; ++i) {
            buffer[i] = arguments[i];
        }
        return buffer;
    }
} else if (compatibility.ArrayBuffer) {
    jDataView.createBuffer = function () {
        var buffer = new ArrayBuffer(arguments.length);
        var view = new Int8Array(buffer);
        for (var i = 0; i < arguments.length; ++i) {
            view[i] = arguments[i];
        }
        return buffer;
    }
} else {
    jDataView.createBuffer = function () {
        return String.fromCharCode.apply(null, arguments);
    }
}

The same optimizations can be made inside your large jDataView.prototype['get' + type] = … assignment, where the prototype method function (byteOffset, littleEndian) { … } checks several things such as this._isDataView and this._isNodeBuffer && compatibility.NodeBufferFull and this._isNodeBuffer && compatibility.NodeBufferEndian each time the method is called.

Most of those things are stable after the constructor is called; you could make the constructor pick one of the engine-specific methods.

Dist file without sourceMappingURL

It would be great to build a dist file without the sourceMappingURL (the one directly in the dist folder for example), so it can be included in projects without getting 404s.

Constuctor doesn't work the same as a real DataView?

AFAICT a real DataView requires an ArrayBuffer in it's constructor but a JDataView requires a Buffer or Uint8Array

Trying this in the browser console

  new DataView(new Uint8Array(3)); 

In Chrome I get Uncaught TypeError: First argument to DataView constructor must be an ArrayBuffer and in Firefox I get TypeError: DataView: expected ArrayBuffer, got Uint8Array.

If I use

  new DataView(new Uint8Array(3).buffer);

Then it works in both.

Conversely with JDataView 2.5.0 the first one succeeds even though it shouldn't according to the spec. The second one fails.

Is that what you want to happen?

Question: Is jDataView runnable in web worker?

In my project, I'd like to download a big binary file and decode it in the web worker for the better performance. However, it seems that the native DataView object is inaccessible in web worker.
So, I wonder whether jDataView is runnable in the web worker or not?

untar demo intersperses chunks of JavaScript in textareas

In both Firefox (Mozilla/5.0 (X11; Linux x86_64; rv:55.0) Gecko/20100101 Firefox/55.0) and Chromium (57.0.2987.133 (Developer Build) Fedora Project (64-bit)), the nifty http://jdataview.github.io/jDataView/untar/ demo intersperses textareas with the tar file's contents. In between the objects for "src/outro.js" and "src/css.js" is a textarea containing just

'}}(window);"

then after that there are several textareas containing chunks of

(function( jQuery ) {
...
})( jQuery );

code. I see no warnings in the JavaScript console.

Add `alignBy(byteCount = 1, offset = 0)` method

Needed for easy alignment after read/write operation to position divisible by certain count of bytes.

byteCount can be 1 (default) if alignment after bit operations is needed.
offset is starting offset from which alignment should be ensured.

Bitfield API ignores endianness.

As it stands, the Bitfield API does not care about the value of _littleEndian, which results in unexpected behavior. Currently, the Bitfield API assumes big endian data.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.