You can not select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
					
					
						
							190 lines
						
					
					
						
							4.9 KiB
						
					
					
				
			
		
		
	
	
							190 lines
						
					
					
						
							4.9 KiB
						
					
					
				| "use strict";
 | |
| 
 | |
| var conversions = {};
 | |
| module.exports = conversions;
 | |
| 
 | |
| function sign(x) {
 | |
|     return x < 0 ? -1 : 1;
 | |
| }
 | |
| 
 | |
| function evenRound(x) {
 | |
|     // Round x to the nearest integer, choosing the even integer if it lies halfway between two.
 | |
|     if ((x % 1) === 0.5 && (x & 1) === 0) { // [even number].5; round down (i.e. floor)
 | |
|         return Math.floor(x);
 | |
|     } else {
 | |
|         return Math.round(x);
 | |
|     }
 | |
| }
 | |
| 
 | |
| function createNumberConversion(bitLength, typeOpts) {
 | |
|     if (!typeOpts.unsigned) {
 | |
|         --bitLength;
 | |
|     }
 | |
|     const lowerBound = typeOpts.unsigned ? 0 : -Math.pow(2, bitLength);
 | |
|     const upperBound = Math.pow(2, bitLength) - 1;
 | |
| 
 | |
|     const moduloVal = typeOpts.moduloBitLength ? Math.pow(2, typeOpts.moduloBitLength) : Math.pow(2, bitLength);
 | |
|     const moduloBound = typeOpts.moduloBitLength ? Math.pow(2, typeOpts.moduloBitLength - 1) : Math.pow(2, bitLength - 1);
 | |
| 
 | |
|     return function(V, opts) {
 | |
|         if (!opts) opts = {};
 | |
| 
 | |
|         let x = +V;
 | |
| 
 | |
|         if (opts.enforceRange) {
 | |
|             if (!Number.isFinite(x)) {
 | |
|                 throw new TypeError("Argument is not a finite number");
 | |
|             }
 | |
| 
 | |
|             x = sign(x) * Math.floor(Math.abs(x));
 | |
|             if (x < lowerBound || x > upperBound) {
 | |
|                 throw new TypeError("Argument is not in byte range");
 | |
|             }
 | |
| 
 | |
|             return x;
 | |
|         }
 | |
| 
 | |
|         if (!isNaN(x) && opts.clamp) {
 | |
|             x = evenRound(x);
 | |
| 
 | |
|             if (x < lowerBound) x = lowerBound;
 | |
|             if (x > upperBound) x = upperBound;
 | |
|             return x;
 | |
|         }
 | |
| 
 | |
|         if (!Number.isFinite(x) || x === 0) {
 | |
|             return 0;
 | |
|         }
 | |
| 
 | |
|         x = sign(x) * Math.floor(Math.abs(x));
 | |
|         x = x % moduloVal;
 | |
| 
 | |
|         if (!typeOpts.unsigned && x >= moduloBound) {
 | |
|             return x - moduloVal;
 | |
|         } else if (typeOpts.unsigned) {
 | |
|             if (x < 0) {
 | |
|               x += moduloVal;
 | |
|             } else if (x === -0) { // don't return negative zero
 | |
|               return 0;
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         return x;
 | |
|     }
 | |
| }
 | |
| 
 | |
| conversions["void"] = function () {
 | |
|     return undefined;
 | |
| };
 | |
| 
 | |
| conversions["boolean"] = function (val) {
 | |
|     return !!val;
 | |
| };
 | |
| 
 | |
| conversions["byte"] = createNumberConversion(8, { unsigned: false });
 | |
| conversions["octet"] = createNumberConversion(8, { unsigned: true });
 | |
| 
 | |
| conversions["short"] = createNumberConversion(16, { unsigned: false });
 | |
| conversions["unsigned short"] = createNumberConversion(16, { unsigned: true });
 | |
| 
 | |
| conversions["long"] = createNumberConversion(32, { unsigned: false });
 | |
| conversions["unsigned long"] = createNumberConversion(32, { unsigned: true });
 | |
| 
 | |
| conversions["long long"] = createNumberConversion(32, { unsigned: false, moduloBitLength: 64 });
 | |
| conversions["unsigned long long"] = createNumberConversion(32, { unsigned: true, moduloBitLength: 64 });
 | |
| 
 | |
| conversions["double"] = function (V) {
 | |
|     const x = +V;
 | |
| 
 | |
|     if (!Number.isFinite(x)) {
 | |
|         throw new TypeError("Argument is not a finite floating-point value");
 | |
|     }
 | |
| 
 | |
|     return x;
 | |
| };
 | |
| 
 | |
| conversions["unrestricted double"] = function (V) {
 | |
|     const x = +V;
 | |
| 
 | |
|     if (isNaN(x)) {
 | |
|         throw new TypeError("Argument is NaN");
 | |
|     }
 | |
| 
 | |
|     return x;
 | |
| };
 | |
| 
 | |
| // not quite valid, but good enough for JS
 | |
| conversions["float"] = conversions["double"];
 | |
| conversions["unrestricted float"] = conversions["unrestricted double"];
 | |
| 
 | |
| conversions["DOMString"] = function (V, opts) {
 | |
|     if (!opts) opts = {};
 | |
| 
 | |
|     if (opts.treatNullAsEmptyString && V === null) {
 | |
|         return "";
 | |
|     }
 | |
| 
 | |
|     return String(V);
 | |
| };
 | |
| 
 | |
| conversions["ByteString"] = function (V, opts) {
 | |
|     const x = String(V);
 | |
|     let c = undefined;
 | |
|     for (let i = 0; (c = x.codePointAt(i)) !== undefined; ++i) {
 | |
|         if (c > 255) {
 | |
|             throw new TypeError("Argument is not a valid bytestring");
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     return x;
 | |
| };
 | |
| 
 | |
| conversions["USVString"] = function (V) {
 | |
|     const S = String(V);
 | |
|     const n = S.length;
 | |
|     const U = [];
 | |
|     for (let i = 0; i < n; ++i) {
 | |
|         const c = S.charCodeAt(i);
 | |
|         if (c < 0xD800 || c > 0xDFFF) {
 | |
|             U.push(String.fromCodePoint(c));
 | |
|         } else if (0xDC00 <= c && c <= 0xDFFF) {
 | |
|             U.push(String.fromCodePoint(0xFFFD));
 | |
|         } else {
 | |
|             if (i === n - 1) {
 | |
|                 U.push(String.fromCodePoint(0xFFFD));
 | |
|             } else {
 | |
|                 const d = S.charCodeAt(i + 1);
 | |
|                 if (0xDC00 <= d && d <= 0xDFFF) {
 | |
|                     const a = c & 0x3FF;
 | |
|                     const b = d & 0x3FF;
 | |
|                     U.push(String.fromCodePoint((2 << 15) + (2 << 9) * a + b));
 | |
|                     ++i;
 | |
|                 } else {
 | |
|                     U.push(String.fromCodePoint(0xFFFD));
 | |
|                 }
 | |
|             }
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     return U.join('');
 | |
| };
 | |
| 
 | |
| conversions["Date"] = function (V, opts) {
 | |
|     if (!(V instanceof Date)) {
 | |
|         throw new TypeError("Argument is not a Date object");
 | |
|     }
 | |
|     if (isNaN(V)) {
 | |
|         return undefined;
 | |
|     }
 | |
| 
 | |
|     return V;
 | |
| };
 | |
| 
 | |
| conversions["RegExp"] = function (V, opts) {
 | |
|     if (!(V instanceof RegExp)) {
 | |
|         V = new RegExp(V);
 | |
|     }
 | |
| 
 | |
|     return V;
 | |
| };
 |