Coverage

100%
131
131
0

/Users/sebastiansandqvist/Documents/Sites & Projects/apps/~modules/s-binary/index.js

100%
131
131
0
LineHitsSource
11'use strict';
2
3// ----------------------------------------------------------------------
4// ----- main exported object
5// includes:
6// 1. unit conversions
7// 2. arithmetic functions
8// 3. logical operators
9// 4. helper methods
10// ----------------------------------------------------------------------
11
121var binary = module.exports = {};
13
14
15// ----- unit conversion
16// ---------------------------------------
171binary.toInt = function(str) {
1810 return parseInt(str, 2);
19};
20
211binary.toHex = function(str) {
222 return parseInt(str, 2).toString(16);
23};
24
25// binary.toBase64 = function(str) {
26// str = parseInt(str, 2).toString();
27// var buf = new Buffer(str);
28// return buf.toString('base64');
29// };
30
31// @param n {Number | String | Buffer} input
32// @param len? {Number} optional bitlength restriction
33// @return {String} 8bit binary conversion
341binary.toBinary = function(n, len) {
35
368 var type = Object.prototype.toString.call(n);
37
388 if (type === '[object Number]') {
39
404 if (len) {
412 return binary.pad(n.toString(2), len);
42 }
43 else {
442 return n.toString(2);
45 }
46
47 }
48
494 var output = '';
50
514 for (var i = 0; i < n.length; i++) {
52
5322 var cur = typeof n[i] === 'number' ?
54 binary.pad(n[i].toString(2), 8) // buffers
55 : binary.pad(n.charCodeAt(i).toString(2), 8); // strings
56
5722 output += cur;
58
59 }
60
614 return output;
62
63};
64
65
66// @param str {String} binary string
67// @return {String} Unicode string
681binary.toUnicode = function(str) {
69
702 var arr = binary.split(str);
712 var output = '';
72
732 for (var i = 0, len = arr.length; i < len; i++) {
746 var integer = binary.toInt(arr[i]);
756 output += String.fromCharCode(integer);
76 }
77
782 return output;
79
80};
81
82
83// ----- arithmetic
84// ---------------------------------------
85
86// @param a {String} binary number
87// @param b {String} binary number
88// @param len? {Number} optional bitLength restriction
891binary.add = function(a, b, len) {
90
9135 if (!len) {
927 a = parseInt(a, 2);
937 b = parseInt(b, 2);
947 return (a + b).toString(2);
95 }
96
9728 a = binary.pad(a, len);
9828 b = binary.pad(b, len);
99
10028 var result = '';
10128 var carry = '0';
102
10328 for (var i = len - 1; i >= 0; i--) {
104
105112 var and = binary.and(a[i], b[i]);
106112 var xor = binary.xor(a[i], b[i]);
107112 var sum = binary.xor(xor, carry);
108
109112 result = sum + result;
110112 carry = binary.or(and, binary.and(xor, carry));
111
112 }
113
11428 return result;
115
116};
117
1181binary.addBits = function(a, b) {
119
1204 a = a === '1' ? 1 : 0;
1214 b = b === '1' ? 1 : 0;
122
1234 var sum = a ^ b;
1244 var carry = a & b;
125
1264 return [sum.toString(), carry.toString()];
127
128};
129
130// @param a {String} binary number
131// @param b {String} binary number
132// todo: @param n {Number} optional bitLength restriction
1331binary.multiply = function(a, b) {
1346 a = parseInt(a, 2);
1356 b = parseInt(b, 2);
1366 return (a * b).toString(2);
137};
138
139// @param a {String} binary number
140// @param b {String} binary number
141// todo: @param n {Number} optional bitLength restriction
1421binary.divide = function(a, b) {
1436 a = parseInt(a, 2);
1446 b = parseInt(b, 2);
1456 return (a / b).toString(2);
146};
147
148
149// ----- logic
150// ---------------------------------------
1511binary.not = function(str) {
152
15314 var inverse = '';
154
15514 for (var i = 0; i < str.length; i++) {
15687 inverse += str[i] === '1' ? '0' : '1';
157 }
158
15914 return inverse;
160
161};
162
1631binary.and = function(a, b) {
164
165231 var eq = binary.equalize(a, b);
166231 a = eq[0];
167231 b = eq[1];
168
169231 var result = '';
170
171231 for (var i = 0; i < a.length; i++) {
172252 if (a[i] === b[i]) {
173163 result += a[i];
174 }
175 else {
17689 result += '0';
177 }
178 }
179
180231 return result;
181
182};
183
1841binary.or = function(a, b) {
185
186120 var eq = binary.equalize(a, b);
187120 a = eq[0];
188120 b = eq[1];
189
190120 var result = '';
191
192120 for (var i = 0; i < a.length; i++) {
193144 if (a[i] === '1' || b[i] === '1') {
19445 result += '1';
195 }
196 else {
19799 result += '0';
198 }
199 }
200
201120 return result;
202
203};
204
2051binary.nand = function(a, b) {
2063 var and = binary.and(a, b);
2073 return binary.not(and);
208};
209
2101binary.nor = function(a, b) {
2114 var or = binary.or(a, b);
2124 return binary.not(or);
213};
214
215// http://jsperf.com/bitwise-vs-string-operations
2161binary.xor = function(a, b) {
217
218228 var eq = binary.equalize(a, b);
219228 a = eq[0];
220228 b = eq[1];
221
222228 var result = '';
223
224228 for (var i = 0; i < a.length; i++) {
225240 if (a[i] === b[i]) {
226160 result += '0';
227 }
228 else {
22980 result += '1';
230 }
231 }
232
233228 return result;
234
235};
236
2371binary.complement = function(str) {
2385 var inverse = binary.not(str);
2395 var complement = binary.add(inverse, 1);
2405 return binary.pad(complement, str.length);
241};
242
243
244// ----- etc
245// ---------------------------------------
246
247// @param str {String} binary string
248// @param n {Number} length of output
249// @return {String} left-padded binary string
2501binary.pad = function(str, n) {
25199 while (str.length < n) {
252194 str = '0' + str;
253 }
25499 return str;
255};
256
257// @param str {String} binary string
258// @param n {Number} length of output
259// @param fn {Function} callback
260// @return {Function} callback(err, result)
2611binary.padSafe = function(str, n, fn) {
262
2632 while (str.length < n) {
2644 str = '0' + str;
265 }
266
2672 if (str.length > n) {
2681 var err = new Error('input length exceeds expected length of output');
2691 return fn(err, str);
270 }
271
2721 return fn(null, str);
273
274};
275
276// @param a {String} binary string
277// @param b {String} binary string
278// @return {Array} [(padded) a, (padded) b]
2791binary.equalize = function(a, b) {
280
281581 var aLen = a.length;
282581 var bLen = b.length;
283
284581 if (aLen > bLen) {
2851 b = binary.pad(b, aLen);
286 }
287
288581 if (bLen > aLen) {
28910 a = binary.pad(a, bLen);
290 }
291
292581 return [a, b];
293
294};
295
296// @param str {String} binary string
297// @param len? {Number} optional number of characters per chunk; default is 8
298// @return {Array}
2991binary.split = function(str, len) {
3006 if (!len) {
3013 len = 8;
302 }
3036 var regex = new RegExp('.{1,' + len + '}', 'g'); // /.{1,8}/g
3046 return str.match(regex);
305};
306
307// @param arr {Array} array of equal length binary strings
308// @return {String} least significant bits
3091binary.lsb = function(arr) {
310
3111 var output = '';
312
3131 for (var i = 0, len = arr.length; i < len; i++) {
31414 var byteLength = arr[i].length;
31514 var bit = arr[i][byteLength - 1];
31614 var out = bit === '0' ? '0' : '1';
31714 output += out;
318 }
319
3201 return output;
321
322};