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
			| 
								 
											3 years ago
										 
									 | 
							
								"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;
							 | 
						||
| 
								 | 
							
								};
							 |