From 7d986cd147da337bc0d46cb8d4d297138a66067a Mon Sep 17 00:00:00 2001 From: IP2Location Date: Thu, 27 Apr 2023 08:34:55 +0800 Subject: [PATCH] Changed to native BigInt --- LICENSE | 2 +- package.json | 3 +- src/ip2location.d.ts | 14 +++---- src/ip2location.js | 93 ++++++++++++++++++++------------------------ 4 files changed, 52 insertions(+), 60 deletions(-) diff --git a/LICENSE b/LICENSE index ed5c13b..3f56aae 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ MIT License -Copyright (c) 2022 IP2Location.com +Copyright (c) 2023 IP2Location.com Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/package.json b/package.json index f0a5f51..1b6c19f 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "ip2location-nodejs", - "version": "9.4.2", + "version": "9.4.3", "description": "IP2Location geolocation component", "keywords": [ "ip2location", @@ -22,7 +22,6 @@ "types": "src/ip2location.d.ts", "license": "MIT", "dependencies": { - "big-integer": "^1.6.47", "csv-parser": "^3.0.0" }, "repository": { diff --git a/src/ip2location.d.ts b/src/ip2location.d.ts index c1bc0c4..cc9df08 100644 --- a/src/ip2location.d.ts +++ b/src/ip2location.d.ts @@ -13,7 +13,7 @@ export class IP2Location { * @param readBytes The number of bytes to read. * @param position The file offset to start reading. * @param readType The data type to convert the bytes to. (Valid values: int8|int32|uint32|float|str|int128) - * @param isBigInt Whether to convert to BigInteger object. + * @param isBigInt Whether to convert to BigInt. * @returns The value of the specified data type. */ readBin(readBytes: number, position: number, readType: string, isBigInt: boolean): any; @@ -36,7 +36,7 @@ export class IP2Location { * Reads unsigned 32-bit integer from file. * * @param position The file offset to start reading. - * @param isBigInt Whether to convert to BigInteger object. + * @param isBigInt Whether to convert to BigInt. * @returns Unsigned 32-bit integer. */ read32(position: number, isBigInt: boolean): number; @@ -53,7 +53,7 @@ export class IP2Location { * * @param position The buffer offset to start reading. * @param buffer The buffer containing the data. - * @returns BigInteger object. + * @returns BigInt. */ read128Row(position: number, buffer: any): any; /** @@ -62,7 +62,7 @@ export class IP2Location { * @param position The buffer offset to start reading. * @param buffer The buffer containing the data. * @param len The number of bytes to read. - * @returns BigInteger object or unsigned 32-bit integer. + * @returns BigInt or unsigned 32-bit integer. */ read32Or128Row(position: number, buffer: any, len: number): any; /** @@ -70,14 +70,14 @@ export class IP2Location { * * @param position The file offset to start reading. * @param ipType 4 for IPv4 or 6 for IPv6. - * @returns BigInteger object or unsigned 32-bit integer. + * @returns BigInt or unsigned 32-bit integer. */ read32Or128(position: number, ipType: number): any; /** * Reads unsigned 128-bit integer from file. * * @param position The file offset to start reading. - * @returns BigInteger object. + * @returns BigInt. */ read128(position: number): any; /** @@ -418,7 +418,7 @@ export class IPTools { * Converts an IPv6 address to IP number. * * @param myIP The IP address to convert. - * @returns The IP number in a BigInteger object. + * @returns The IP number in a BigInt. */ ipV6ToDecimal(myIP: string): any; /** diff --git a/src/ip2location.js b/src/ip2location.js index ab9540a..04f6f5a 100644 --- a/src/ip2location.js +++ b/src/ip2location.js @@ -1,11 +1,10 @@ var net = require("net"); var fs = require("fs"); -var bigInt = require("big-integer"); var https = require("https"); const csv = require("csv-parser"); // For BIN queries -const VERSION = "9.4.2"; +const VERSION = "9.4.3"; const MAX_INDEX = 65536; const COUNTRY_POSITION = [ 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, @@ -81,13 +80,13 @@ const ADDRESS_TYPE_POSITION = [ const CATEGORY_POSITION = [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22, ]; -const MAX_IPV4_RANGE = bigInt(4294967295); -const MAX_IPV6_RANGE = bigInt("340282366920938463463374607431768211455"); -const FROM_6TO4 = bigInt("42545680458834377588178886921629466624"); -const TO_6TO4 = bigInt("42550872755692912415807417417958686719"); -const FROM_TEREDO = bigInt("42540488161975842760550356425300246528"); -const TO_TEREDO = bigInt("42540488241204005274814694018844196863"); -const LAST_32_BITS = bigInt("4294967295"); +const MAX_IPV4_RANGE = BigInt(4294967295); +const MAX_IPV6_RANGE = BigInt("340282366920938463463374607431768211455"); +const FROM_6TO4 = BigInt("42545680458834377588178886921629466624"); +const TO_6TO4 = BigInt("42550872755692912415807417417958686719"); +const FROM_TEREDO = BigInt("42540488161975842760550356425300246528"); +const TO_TEREDO = BigInt("42540488241204005274814694018844196863"); +const LAST_32_BITS = BigInt("4294967295"); const MODES = { COUNTRY_SHORT: 1, @@ -239,7 +238,7 @@ class IP2Location { break; case "uint32": return isBigInt - ? bigInt(buffer.readUInt32LE(0)) + ? BigInt(buffer.readUInt32LE(0)) : buffer.readUInt32LE(0); break; case "float": @@ -249,12 +248,10 @@ class IP2Location { return buffer.toString("utf8"); break; case "int128": - let myBig = bigInt(); // zero + let myBig = BigInt(0); // zero let bitShift = 8; for (let x = 0; x < 16; x++) { - myBig = myBig.add( - bigInt(buffer.readUInt8(x)).shiftLeft(bitShift * x) - ); + myBig = myBig + (BigInt(buffer.readUInt8(x)) << (bitShift * x)); } return myBig; break; @@ -288,13 +285,12 @@ class IP2Location { // Read 128 bits integer in the buffer read128Row(position, buffer) { - let myBig = bigInt(); // zero + let myBig = BigInt(0); // zero let bitShift = 8; for (let x = 0; x < 16; x++) { let pos = position + x; - myBig = myBig.add( - bigInt(this.read8Row(pos, buffer)).shiftLeft(bitShift * x) - ); + myBig = + myBig + (BigInt(this.read8Row(pos, buffer)) << BigInt(bitShift * x)); } return myBig; } @@ -571,8 +567,8 @@ class IP2Location { ipNumber = ip2No(myIP); if ( - (ipNumber.geq(FROM_6TO4) && ipNumber.leq(TO_6TO4)) || - (ipNumber.geq(FROM_TEREDO) && ipNumber.leq(TO_TEREDO)) + (ipNumber >= FROM_6TO4 && ipNumber <= TO_6TO4) || + (ipNumber >= FROM_TEREDO && ipNumber <= TO_TEREDO) ) { ipType = 4; MAX_IP_RANGE = MAX_IPV4_RANGE; @@ -580,10 +576,10 @@ class IP2Location { baseAddress = this.#myDB.baseAddress; columnSize = this.#ipV4ColumnSize; - if (ipNumber.geq(FROM_6TO4) && ipNumber.leq(TO_6TO4)) { - ipNumber = ipNumber.shiftRight(80).and(LAST_32_BITS).toJSNumber(); + if (ipNumber >= FROM_6TO4 && ipNumber <= TO_6TO4) { + ipNumber = Number((ipNumber >> BigInt(80)) & LAST_32_BITS); } else { - ipNumber = ipNumber.not().and(LAST_32_BITS).toJSNumber(); + ipNumber = Number(~ipNumber & LAST_32_BITS); } if (this.#myDB.indexed == 1) { indexAddress = ipNumber >>> 16; @@ -593,17 +589,17 @@ class IP2Location { } else { firstCol = 16; // IPv6 is 16 bytes if (this.#myDB.indexedIPV6 == 1) { - indexAddress = ipNumber.shiftRight(112).toJSNumber(); + indexAddress = Number(ipNumber >> BigInt(112)); low = this.#indexArrayIPV6[indexAddress][0]; high = this.#indexArrayIPV6[indexAddress][1]; } } } data.ip = myIP; - ipNumber = bigInt(ipNumber); + ipNumber = BigInt(ipNumber); - if (ipNumber.geq(MAX_IP_RANGE)) { - ipNumber = MAX_IP_RANGE.minus(1); + if (ipNumber >= MAX_IP_RANGE) { + ipNumber = MAX_IP_RANGE - BigInt(1); } data.ipNo = ipNumber.toString(); @@ -618,10 +614,10 @@ class IP2Location { ipFrom = this.read32Or128Row(0, fullRow, firstCol); ipTo = this.read32Or128Row(columnSize, fullRow, firstCol); - ipFrom = bigInt(ipFrom); - ipTo = bigInt(ipTo); + ipFrom = BigInt(ipFrom); + ipTo = BigInt(ipTo); - if (ipFrom.leq(ipNumber) && ipTo.gt(ipNumber)) { + if (ipFrom <= ipNumber && ipTo > ipNumber) { loadMesg(data, MSG_NOT_SUPPORTED); // load default message let rowLen = columnSize - firstCol; @@ -790,7 +786,7 @@ class IP2Location { } return; } else { - if (ipFrom.gt(ipNumber)) { + if (ipFrom > ipNumber) { high = mid - 1; } else { low = mid + 1; @@ -1032,7 +1028,7 @@ function ip2No(ipV6) { let sectionBits = 16; // 16 bits per section let m = ipV6.split("::"); - let total = bigInt(); // zero + let total = BigInt(0); // zero if (m.length == 2) { let myArrLeft = m[0] != "" ? m[0].split(":") : []; @@ -1040,29 +1036,26 @@ function ip2No(ipV6) { let myArrMid = maxSections - myArrLeft.length - myArrRight.length; for (let x = 0; x < myArrLeft.length; x++) { - total = total.add( - bigInt(parseInt("0x" + myArrLeft[x])).shiftLeft( - (maxSections - (x + 1)) * sectionBits - ) - ); + total = + total + + (BigInt(parseInt("0x" + myArrLeft[x])) << + BigInt((maxSections - (x + 1)) * sectionBits)); } for (let x = 0; x < myArrRight.length; x++) { - total = total.add( - bigInt(parseInt("0x" + myArrRight[x])).shiftLeft( - (myArrRight.length - (x + 1)) * sectionBits - ) - ); + total = + total + + (BigInt(parseInt("0x" + myArrRight[x])) << + BigInt((myArrRight.length - (x + 1)) * sectionBits)); } } else if (m.length == 1) { let myArr = m[0].split(":"); for (let x = 0; x < myArr.length; x++) { - total = total.add( - bigInt(parseInt("0x" + myArr[x])).shiftLeft( - (maxSections - (x + 1)) * sectionBits - ) - ); + total = + total + + (BigInt(parseInt("0x" + myArr[x])) << + BigInt((maxSections - (x + 1)) * sectionBits)); } } @@ -1231,10 +1224,10 @@ class IPTools { // Convert IP number to IPv6 address decimalToIPV6(ipNum) { if (typeof ipNum == "string" || typeof ipNum == "number") { - ipNum = bigInt(ipNum); + ipNum = BigInt(ipNum); } - if (ipNum.lt(bigInt.zero) || ipNum.gt(MAX_IPV6_RANGE)) { + if (ipNum < BigInt(0) || ipNum > MAX_IPV6_RANGE) { return null; } @@ -1348,7 +1341,7 @@ class IPTools { return null; } - let ipNum = bigInt(myBin, 2); + let ipNum = BigInt("0b" + myBin); let v6 = this.decimalToIPV6(ipNum); return v6;