[Service] Integrate DeviceHome and SignalingServer
[platform/framework/web/wrtjs.git] / device_home / node_modules / socket.io / node_modules / socket.io-client / node_modules / socket.io-parser / binary.js
1 /*global Blob,File*/
2
3 /**
4  * Module requirements
5  */
6
7 var isArray = require('isarray');
8 var isBuf = require('./is-buffer');
9 var toString = Object.prototype.toString;
10 var withNativeBlob = typeof Blob === 'function' || (typeof Blob !== 'undefined' && toString.call(Blob) === '[object BlobConstructor]');
11 var withNativeFile = typeof File === 'function' || (typeof File !== 'undefined' && toString.call(File) === '[object FileConstructor]');
12
13 /**
14  * Replaces every Buffer | ArrayBuffer in packet with a numbered placeholder.
15  * Anything with blobs or files should be fed through removeBlobs before coming
16  * here.
17  *
18  * @param {Object} packet - socket.io event packet
19  * @return {Object} with deconstructed packet and list of buffers
20  * @api public
21  */
22
23 exports.deconstructPacket = function(packet) {
24   var buffers = [];
25   var packetData = packet.data;
26   var pack = packet;
27   pack.data = _deconstructPacket(packetData, buffers);
28   pack.attachments = buffers.length; // number of binary 'attachments'
29   return {packet: pack, buffers: buffers};
30 };
31
32 function _deconstructPacket(data, buffers) {
33   if (!data) return data;
34
35   if (isBuf(data)) {
36     var placeholder = { _placeholder: true, num: buffers.length };
37     buffers.push(data);
38     return placeholder;
39   } else if (isArray(data)) {
40     var newData = new Array(data.length);
41     for (var i = 0; i < data.length; i++) {
42       newData[i] = _deconstructPacket(data[i], buffers);
43     }
44     return newData;
45   } else if (typeof data === 'object' && !(data instanceof Date)) {
46     var newData = {};
47     for (var key in data) {
48       newData[key] = _deconstructPacket(data[key], buffers);
49     }
50     return newData;
51   }
52   return data;
53 }
54
55 /**
56  * Reconstructs a binary packet from its placeholder packet and buffers
57  *
58  * @param {Object} packet - event packet with placeholders
59  * @param {Array} buffers - binary buffers to put in placeholder positions
60  * @return {Object} reconstructed packet
61  * @api public
62  */
63
64 exports.reconstructPacket = function(packet, buffers) {
65   packet.data = _reconstructPacket(packet.data, buffers);
66   packet.attachments = undefined; // no longer useful
67   return packet;
68 };
69
70 function _reconstructPacket(data, buffers) {
71   if (!data) return data;
72
73   if (data && data._placeholder) {
74     return buffers[data.num]; // appropriate buffer (should be natural order anyway)
75   } else if (isArray(data)) {
76     for (var i = 0; i < data.length; i++) {
77       data[i] = _reconstructPacket(data[i], buffers);
78     }
79   } else if (typeof data === 'object') {
80     for (var key in data) {
81       data[key] = _reconstructPacket(data[key], buffers);
82     }
83   }
84
85   return data;
86 }
87
88 /**
89  * Asynchronously removes Blobs or Files from data via
90  * FileReader's readAsArrayBuffer method. Used before encoding
91  * data as msgpack. Calls callback with the blobless data.
92  *
93  * @param {Object} data
94  * @param {Function} callback
95  * @api private
96  */
97
98 exports.removeBlobs = function(data, callback) {
99   function _removeBlobs(obj, curKey, containingObject) {
100     if (!obj) return obj;
101
102     // convert any blob
103     if ((withNativeBlob && obj instanceof Blob) ||
104         (withNativeFile && obj instanceof File)) {
105       pendingBlobs++;
106
107       // async filereader
108       var fileReader = new FileReader();
109       fileReader.onload = function() { // this.result == arraybuffer
110         if (containingObject) {
111           containingObject[curKey] = this.result;
112         }
113         else {
114           bloblessData = this.result;
115         }
116
117         // if nothing pending its callback time
118         if(! --pendingBlobs) {
119           callback(bloblessData);
120         }
121       };
122
123       fileReader.readAsArrayBuffer(obj); // blob -> arraybuffer
124     } else if (isArray(obj)) { // handle array
125       for (var i = 0; i < obj.length; i++) {
126         _removeBlobs(obj[i], i, obj);
127       }
128     } else if (typeof obj === 'object' && !isBuf(obj)) { // and object
129       for (var key in obj) {
130         _removeBlobs(obj[key], key, obj);
131       }
132     }
133   }
134
135   var pendingBlobs = 0;
136   var bloblessData = data;
137   _removeBlobs(bloblessData);
138   if (!pendingBlobs) {
139     callback(bloblessData);
140   }
141 };