nodejs client finish binary search
This commit is contained in:
parent
401e5bc795
commit
63cd3fa085
|
|
@ -1,55 +1,87 @@
|
|||
/**
|
||||
* ip2region client for nodejs
|
||||
*
|
||||
* project: https://github.com/lionsoul2016/ip2region
|
||||
* project: https://github.com/lionsoul2014/ip2region
|
||||
*
|
||||
* @author dongyado<dongyado@gmail.com>
|
||||
* */
|
||||
|
||||
|
||||
function Ip2region(db_path)
|
||||
{
|
||||
var fs = require('fs');
|
||||
|
||||
var ipbase = [16777216, 65536, 256, 1]; // for ip2long
|
||||
var db_file_path = null;
|
||||
var db_fd = null;
|
||||
|
||||
// db file check
|
||||
if (typeof(db_path) == "undefined" || fs.exists(db_path) ) {
|
||||
throw("[ip2region] db file not exists : " + db_path);
|
||||
}
|
||||
|
||||
db_file_path = db_path;
|
||||
|
||||
try {
|
||||
db_fd = fs.openSync(db_file_path, 'r');
|
||||
} catch(e) {
|
||||
throw("[ip2region] Can not open ip2region.db file , path : " + db_file_path);
|
||||
}
|
||||
var ip2region = {};
|
||||
ip2region.db_file_path = null;
|
||||
ip2region.db_fd = null;
|
||||
|
||||
var totalBlocks = 0;
|
||||
var firstIndexPtr = 0;
|
||||
var lastIndexPtr = 0;
|
||||
var superBlock = new Buffer(8);
|
||||
|
||||
this.binarySearch = function(ip)
|
||||
{
|
||||
if (typeof(ip) == 'string') ip = ip2long(ip);
|
||||
var indexBlockLength = 12;
|
||||
var totalHeaderLength = 4096;
|
||||
|
||||
// init basic search environment
|
||||
if (totalBlocks == 0) {
|
||||
fs.readSync(ip2r.db_fd, superBlock, 0, 8, 0);
|
||||
firstIndexPtr = getLong(superBlock, 0);
|
||||
lastIndexPtr = getLong(superBlock, 4);
|
||||
}
|
||||
|
||||
/**
|
||||
* binary search
|
||||
* */
|
||||
ip2region.binarySearch = function(ip)
|
||||
{
|
||||
if( typeof(ip) == 'string' )
|
||||
ip = ip2long(ip);
|
||||
|
||||
// search
|
||||
var low = 0;
|
||||
var mid = 0;
|
||||
var high = totalBlocks;
|
||||
var dataPos = 0;
|
||||
var pos = 0;
|
||||
var sip = 0;
|
||||
var eip = 0;
|
||||
var indexBuffer = new Buffer(12);
|
||||
|
||||
return ip2long(ip);
|
||||
// binary search
|
||||
while( low <= high ) {
|
||||
mid = ((low + high) >> 1);
|
||||
pos = firstIndexPtr + mid * indexBlockLength;
|
||||
fs.readSync(this.db_fd, indexBuffer, 0, indexBlockLength, pos);
|
||||
sip = getLong(indexBuffer, 0);
|
||||
|
||||
//console.log( ' sip : ' + sip + ' eip : ' + eip );
|
||||
if ( ip < sip) {
|
||||
high = mid - 1;
|
||||
} else {
|
||||
eip = getLong(indexBuffer, 4);
|
||||
if ( ip > eip ) {
|
||||
low = mid + 1;
|
||||
} else {
|
||||
dataPos = getLong(indexBuffer, 8);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// read data
|
||||
if (dataPos == 0) return null;
|
||||
var dataLen = ((dataPos >> 24) & 0xFF);
|
||||
var dataPos = (dataPos & 0x00FFFFFF);
|
||||
var dataBuffer = new Buffer(dataLen);
|
||||
|
||||
fs.readSync(this.db_fd, dataBuffer, 0, dataLen, dataPos);
|
||||
|
||||
var city_id = getLong(dataBuffer, 0);
|
||||
var data = dataBuffer.toString('utf8', 4, dataLen);
|
||||
|
||||
//console.log(city_id);
|
||||
//console.log(data);
|
||||
|
||||
return { city: city_id, region: data };
|
||||
}
|
||||
|
||||
|
||||
this.btreeSearch = function(ip)
|
||||
/**
|
||||
* btree search
|
||||
* */
|
||||
ip2region.btreeSearch = function(ip)
|
||||
{
|
||||
return ip2long(ip);
|
||||
}
|
||||
|
|
@ -74,13 +106,53 @@ function Ip2region(db_path)
|
|||
* */
|
||||
function getLong(buffer, offset)
|
||||
{
|
||||
return (
|
||||
var val = (
|
||||
(buffer[offset] & 0x000000FF) |
|
||||
((buffer[offset + 1] << 8) & 0x0000FF00) |
|
||||
((buffer[offset + 2] << 16) & 0x00FF0000) |
|
||||
((buffer[offset + 3] << 24) & 0xFF000000)
|
||||
);
|
||||
|
||||
// convert to unsigned int
|
||||
if (val < 0) {
|
||||
val = val >>> 0;
|
||||
}
|
||||
return val;
|
||||
}
|
||||
|
||||
module.exports = Ip2region;
|
||||
|
||||
// api for create
|
||||
exports.create = function(db_path) {
|
||||
|
||||
// db file check
|
||||
if (typeof(db_path) == "undefined" || fs.exists(db_path) ) {
|
||||
throw("[ip2region] db file not exists : " + db_path);
|
||||
}
|
||||
|
||||
ip2region.db_file_path = db_path;
|
||||
|
||||
try {
|
||||
ip2region.db_fd = fs.openSync(ip2region.db_file_path, 'r');
|
||||
} catch(e) {
|
||||
throw("[ip2region] Can not open ip2region.db file , path : "
|
||||
+ ip2region.db_file_path);
|
||||
}
|
||||
|
||||
// init basic search environment
|
||||
if (totalBlocks == 0) {
|
||||
fs.readSync(ip2region.db_fd, superBlock, 0, 8, 0);
|
||||
firstIndexPtr = getLong(superBlock, 0);
|
||||
lastIndexPtr = getLong(superBlock, 4);
|
||||
totalBlocks = (lastIndexPtr - firstIndexPtr)
|
||||
/ indexBlockLength + 1;
|
||||
}
|
||||
|
||||
return ip2region;
|
||||
}
|
||||
|
||||
|
||||
// api for destroy
|
||||
exports.destroy = function(ip2rObj){
|
||||
ip2rObj.db_file_path = null;
|
||||
fs.closeSync(ip2rObj.db_fd);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,6 +3,13 @@
|
|||
* */
|
||||
|
||||
var Ip2region = require('./ip2region');
|
||||
var ip2region = new Ip2region('../../data/ip2region.db');
|
||||
//var ip2region = new Ip2region();
|
||||
|
||||
console.log(ip2region.binarySearch("255.255.255.255"));
|
||||
// 1. create a ip2region object
|
||||
var ipObj = Ip2region.create('../../data/ip2region.db');
|
||||
|
||||
// 2. use
|
||||
console.log(ipObj.binarySearch("120.24.78.68"));
|
||||
|
||||
// 3. destroy
|
||||
Ip2region.destroy(ipObj);
|
||||
|
|
|
|||
Loading…
Reference in New Issue