1 | 1 | '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 | | |
12 | 1 | var binary = module.exports = {}; |
13 | | |
14 | | |
15 | | // ----- unit conversion |
16 | | // --------------------------------------- |
17 | 1 | binary.toInt = function(str) { |
18 | 10 | return parseInt(str, 2); |
19 | | }; |
20 | | |
21 | 1 | binary.toHex = function(str) { |
22 | 2 | 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 | | // @return {String} 8bit binary conversion |
33 | | // todo: get more test cases & verify |
34 | 1 | binary.toBinary = function(n) { |
35 | | |
36 | 6 | var type = Object.prototype.toString.call(n); |
37 | | |
38 | 6 | if (type === '[object Number]') { |
39 | 2 | return n.toString(2); |
40 | | } |
41 | | |
42 | 4 | var output = ''; |
43 | | |
44 | 4 | for (var i = 0; i < n.length; i++) { |
45 | | |
46 | 22 | var cur = typeof n[i] === 'number' ? |
47 | | binary.pad(n[i].toString(2), 8) // buffers |
48 | | : binary.pad(n.charCodeAt(i).toString(2), 8); // strings |
49 | | |
50 | 22 | output += cur; |
51 | | |
52 | | } |
53 | | |
54 | 4 | return output; |
55 | | |
56 | | }; |
57 | | |
58 | | |
59 | | // @param str {String} binary string |
60 | | // @return {String} Unicode string |
61 | 1 | binary.toUnicode = function(str) { |
62 | | |
63 | 2 | var arr = binary.split(str); |
64 | 2 | var output = ''; |
65 | | |
66 | 2 | for (var i=0, len=arr.length; i<len; i++) { |
67 | 6 | var integer = binary.toInt(arr[i]); |
68 | 6 | output += String.fromCharCode(integer); |
69 | | } |
70 | | |
71 | 2 | return output; |
72 | | |
73 | | }; |
74 | | |
75 | | |
76 | | // ----- arithmetic |
77 | | // --------------------------------------- |
78 | | |
79 | | // @param a {String} binary number |
80 | | // @param b {String} binary number |
81 | | // todo: @param n {Number} optional bitLength restriction |
82 | 1 | binary.add = function(a, b) { |
83 | 6 | a = parseInt(a, 2); |
84 | 6 | b = parseInt(b, 2); |
85 | 6 | return (a + b).toString(2); |
86 | | }; |
87 | | |
88 | 1 | binary.addBits = function(a, b) { |
89 | 4 | a = a === '1' ? 1 : 0; |
90 | 4 | b = b === '1' ? 1 : 0; |
91 | | |
92 | 4 | var sum = a ^ b; |
93 | 4 | var carry = a & b; |
94 | | |
95 | 4 | return { |
96 | | sum: sum.toString(), |
97 | | carry: carry.toString() |
98 | | }; |
99 | | }; |
100 | | |
101 | | // @param a {String} binary number |
102 | | // @param b {String} binary number |
103 | | // todo: @param n {Number} optional bitLength restriction |
104 | 1 | binary.multiply = function(a, b) { |
105 | 6 | a = parseInt(a, 2); |
106 | 6 | b = parseInt(b, 2); |
107 | 6 | return (a * b).toString(2); |
108 | | }; |
109 | | |
110 | | // @param a {String} binary number |
111 | | // @param b {String} binary number |
112 | | // todo: @param n {Number} optional bitLength restriction |
113 | 1 | binary.divide = function(a, b) { |
114 | 6 | a = parseInt(a, 2); |
115 | 6 | b = parseInt(b, 2); |
116 | 6 | return (a / b).toString(2); |
117 | | }; |
118 | | |
119 | | |
120 | | // ----- logic |
121 | | // --------------------------------------- |
122 | 1 | binary.not = function(str) { |
123 | 13 | var inverse = ''; |
124 | 13 | for (var i = 0; i < str.length; i++) { |
125 | 79 | inverse += str[i] === '1' ? '0' : '1'; |
126 | | } |
127 | 13 | return inverse; |
128 | | }; |
129 | | |
130 | 1 | binary.and = function(a, b) { |
131 | | |
132 | 7 | var eq = binary.equalize(a, b); |
133 | 7 | a = eq[0]; |
134 | 7 | b = eq[1]; |
135 | | |
136 | 7 | var result = ''; |
137 | | |
138 | 7 | for (var i = 0; i < a.length; i++) { |
139 | 28 | if (a[i] === b[i]) { |
140 | 6 | result += a[i]; |
141 | | } |
142 | | else { |
143 | 22 | result += '0'; |
144 | | } |
145 | | } |
146 | | |
147 | 7 | return result; |
148 | | |
149 | | }; |
150 | | |
151 | 1 | binary.or = function(a, b) { |
152 | | |
153 | 8 | var eq = binary.equalize(a, b); |
154 | 8 | a = eq[0]; |
155 | 8 | b = eq[1]; |
156 | | |
157 | 8 | var result = ''; |
158 | | |
159 | 8 | for (var i = 0; i < a.length; i++) { |
160 | 32 | if (a[i] === '1' || b[i] === '1') { |
161 | 30 | result += '1'; |
162 | | } |
163 | | else { |
164 | 2 | result += '0'; |
165 | | } |
166 | | } |
167 | | |
168 | 8 | return result; |
169 | | |
170 | | }; |
171 | | |
172 | 1 | binary.nand = function(a, b) { |
173 | 3 | var and = binary.and(a, b); |
174 | 3 | return binary.not(and); |
175 | | }; |
176 | | |
177 | 1 | binary.nor = function(a, b) { |
178 | 4 | var or = binary.or(a, b); |
179 | 4 | return binary.not(or); |
180 | | }; |
181 | | |
182 | 1 | binary.xor = function(a, b) { |
183 | | |
184 | 4 | var eq = binary.equalize(a, b); |
185 | 4 | a = eq[0]; |
186 | 4 | b = eq[1]; |
187 | | |
188 | 4 | var result = ''; |
189 | | |
190 | 4 | for (var i = 0; i < a.length; i++) { |
191 | 16 | if (a[i] !== b[i]) { |
192 | 13 | result += '1'; |
193 | | } |
194 | | else { |
195 | 3 | result += '0'; |
196 | | } |
197 | | } |
198 | | |
199 | 4 | return result; |
200 | | |
201 | | }; |
202 | | |
203 | 1 | binary.complement = function(str) { |
204 | 4 | var inverse = binary.not(str); |
205 | 4 | var complement = binary.add(inverse, 1); |
206 | 4 | return binary.pad(complement, str.length); |
207 | | }; |
208 | | |
209 | | |
210 | | // ----- etc |
211 | | // --------------------------------------- |
212 | | |
213 | | // @param str {String} binary string |
214 | | // @param n {Number} length of output |
215 | | // @return {String} left-padded binary string |
216 | 1 | binary.pad = function(str, n) { |
217 | 40 | while (str.length < n) { |
218 | 62 | str = '0' + str; |
219 | | } |
220 | 40 | return str; |
221 | | }; |
222 | | |
223 | | // @param str {String} binary string |
224 | | // @param n {Number} length of output |
225 | | // @param fn {Function} callback |
226 | | // @return {Function} callback(err, result) |
227 | 1 | binary.padSafe = function(str, n, fn) { |
228 | | |
229 | 2 | while (str.length < n) { |
230 | 4 | str = '0' + str; |
231 | | } |
232 | | |
233 | 2 | if (str.length > n) { |
234 | 1 | var err = new Error('input length exceeds expected length of output'); |
235 | 1 | return fn(err, str); |
236 | | } |
237 | | |
238 | 1 | return fn(null, str); |
239 | | |
240 | | }; |
241 | | |
242 | | // @param a {String} binary string |
243 | | // @param b {String} binary string |
244 | | // @return {Array} [(padded) a, (padded) b] |
245 | 1 | binary.equalize = function(a, b) { |
246 | | |
247 | 21 | var aLen = a.length; |
248 | 21 | var bLen = b.length; |
249 | | |
250 | 21 | if (aLen > bLen) { |
251 | 1 | b = binary.pad(b, aLen); |
252 | | } |
253 | | |
254 | 21 | if (bLen > aLen) { |
255 | 10 | a = binary.pad(a, bLen); |
256 | | } |
257 | | |
258 | 21 | return [a, b]; |
259 | | |
260 | | }; |
261 | | |
262 | | // @param str {String} binary string |
263 | | // @param length {Number} optional number of characters per chunk; default is 8 |
264 | | // @return {Array} |
265 | 1 | binary.split = function(str, length) { |
266 | 6 | if (!length) { |
267 | 3 | length = 8; |
268 | | } |
269 | 6 | var regex = new RegExp('.{1,' + length + '}', 'g'); // /.{1,8}/g |
270 | 6 | return str.match(regex); |
271 | | }; |
272 | | |
273 | | // @param arr {Array} array of equal length binary strings |
274 | | // @return {String} least significant bits |
275 | 1 | binary.lsb = function(arr) { |
276 | | |
277 | 1 | var output = ''; |
278 | | |
279 | 1 | for (var i=0, len=arr.length; i<len; i++) { |
280 | 14 | var byteLength = arr[i].length; |
281 | 14 | var bit = arr[i][byteLength - 1]; |
282 | 14 | var out = bit === '0' ? '0' : '1'; |
283 | 14 | output += out; |
284 | | } |
285 | | |
286 | 1 | return output; |
287 | | |
288 | | }; |