Skip to content

Commit

Permalink
Changed to native BigInt
Browse files Browse the repository at this point in the history
  • Loading branch information
ip2location committed Apr 27, 2023
1 parent 0415eb3 commit 7d986cd
Show file tree
Hide file tree
Showing 4 changed files with 52 additions and 60 deletions.
2 changes: 1 addition & 1 deletion LICENSE
Original file line number Diff line number Diff line change
@@ -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
Expand Down
3 changes: 1 addition & 2 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "ip2location-nodejs",
"version": "9.4.2",
"version": "9.4.3",
"description": "IP2Location geolocation component",
"keywords": [
"ip2location",
Expand All @@ -22,7 +22,6 @@
"types": "src/ip2location.d.ts",
"license": "MIT",
"dependencies": {
"big-integer": "^1.6.47",
"csv-parser": "^3.0.0"
},
"repository": {
Expand Down
14 changes: 7 additions & 7 deletions src/ip2location.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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;
Expand All @@ -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;
/**
Expand All @@ -62,22 +62,22 @@ 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;
/**
* Reads either unsigned 32-bit or 128-bit integer from file.
*
* @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;
/**
Expand Down Expand Up @@ -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;
/**
Expand Down
93 changes: 43 additions & 50 deletions src/ip2location.js
Original file line number Diff line number Diff line change
@@ -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,
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -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":
Expand All @@ -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;
Expand Down Expand Up @@ -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;
}
Expand Down Expand Up @@ -571,19 +567,19 @@ 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;
high = this.#myDB.dbCount;
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;
Expand All @@ -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();
Expand All @@ -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;
Expand Down Expand Up @@ -790,7 +786,7 @@ class IP2Location {
}
return;
} else {
if (ipFrom.gt(ipNumber)) {
if (ipFrom > ipNumber) {
high = mid - 1;
} else {
low = mid + 1;
Expand Down Expand Up @@ -1032,37 +1028,34 @@ 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(":") : [];
let myArrRight = m[1] != "" ? m[1].split(":") : [];
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));
}
}

Expand Down Expand Up @@ -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;
}

Expand Down Expand Up @@ -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;
Expand Down

0 comments on commit 7d986cd

Please sign in to comment.