增加了 ruby 版本的 内存查找

This commit is contained in:
atpking 2022-05-20 14:29:56 +08:00
parent 75bac23722
commit 168ea02ffc
2 changed files with 91 additions and 0 deletions

View File

@ -0,0 +1,76 @@
class Ip2Region
INDEX_BLOCK_LENGTH = 12
TOTAL_HEADER_LENGTH = 8192
attr_accessor :f, :headerSip, :headerPtr, :headerLen, :indexSPtr, :indexLPtr, :indexCount, :dbBinStr
def initialize(dbfile = "../../data/ip2region.db")
initDatabase(dbfile)
true
end
def initDatabase(dbfile = "ip2region.db")
@dbBinStr = File.open(dbfile, 'rb').read
@indexSPtr = getLong(@dbBinStr, 0)
@indexLPtr = getLong(@dbBinStr, 4)
@indexCount = ((indexLPtr - indexSPtr) / INDEX_BLOCK_LENGTH).to_i + 1
# puts "#{@indexSPtr} #{@indexLPtr} #{@indexCount}"
end
def memorySearch(ip)
ip = ip2long(ip)
l, h, dataPtr = 0, indexCount , 0
# print(l,h,dataPtr)
while l <= h
m = (l + h) >> 1
p = m * INDEX_BLOCK_LENGTH + indexSPtr
# puts "m = #{m}, p = #{p}"
sip = getLong(@dbBinStr, p)
# puts "sip = #{sip}"
if ip < sip
h = m - 1
else
eip = getLong(@dbBinStr, p + 4)
if ip > eip
l = m + 1
else
dataPtr = getLong(@dbBinStr, p + 8)
break
end
end
end
if dataPtr == 0
return nil
end
returnData(dataPtr)
end
def returnData(dataPtr)
dataLen = (dataPtr >> 24) & 0xFF
dataPtr = dataPtr & 0x00FFFFFF
data = @dbBinStr[dataPtr, dataLen]
# @dbBinStr.seek(dataPtr)
# data = @dbBinStr.read(dataLen)
return {
:city_id => getLong(data, 0),
:region => data[4..-1].force_encoding("utf-8")
}
end
def getLong(b, offset)
if (b[offset..offset+3] || []).length == 4
# puts "unpack = #{b[offset..offset+3].unpack('I')}"
return b[offset..offset+3].unpack('I')[0].to_i
end
0
end
def ip2long(ip)
ip.split('.').inject(0) {|s,x| s*256 + x.to_i}
end
end

View File

@ -0,0 +1,15 @@
# 只实现了 memory 版本的, 其他的靠兄弟们实现了
require_relative 'ip_2_region'
s = Ip2Region.new
(1..235).each do |i|
ip = "#{i}.#{i}.#{i}.#{i}"
answer = s.memorySearch ip
puts "#{ip} , answer = #{answer}"
end
ip = "27.10.228.9"
answer = s.memorySearch ip
puts "#{ip} , answer = #{answer}"