diff --git a/pkg/iplibrary/default_ip_library_test.go b/pkg/iplibrary/default_ip_library_test.go index ad21559..024536b 100644 --- a/pkg/iplibrary/default_ip_library_test.go +++ b/pkg/iplibrary/default_ip_library_test.go @@ -12,6 +12,15 @@ import ( "time" ) +func TestIPLibrary_Init(t *testing.T) { + var lib = iplibrary.NewIPLibrary() + + err := lib.Init() + if err != nil { + t.Fatal(err) + } +} + func TestIPLibrary_Lookup(t *testing.T) { var stat1 = &runtime.MemStats{} runtime.ReadMemStats(stat1) diff --git a/pkg/iplibrary/ip_item.go b/pkg/iplibrary/ip_item.go index 9b54933..b058c7f 100644 --- a/pkg/iplibrary/ip_item.go +++ b/pkg/iplibrary/ip_item.go @@ -5,16 +5,22 @@ package iplibrary import ( "bytes" "encoding/binary" + "github.com/iwind/TeaGo/types" ) type ipItem struct { + IPFrom uint64 + IPTo uint64 + + Region *ipRegion +} + +type ipRegion struct { CountryId uint32 ProvinceId uint32 CityId uint32 TownId uint32 ProviderId uint32 - IPFrom uint64 - IPTo uint64 } func (this *ipItem) AsBinary() ([]byte, error) { @@ -25,3 +31,21 @@ func (this *ipItem) AsBinary() ([]byte, error) { } return buf.Bytes(), nil } + +func HashRegion(countryId uint32, provinceId uint32, cityId uint32, townId uint32, providerId uint32) string { + var providerHash = "" + if providerId > 0 { + providerHash = "_" + types.String(providerId) + } + + if townId > 0 { + return "t" + types.String(townId) + providerHash + } + if cityId > 0 { + return "c" + types.String(cityId) + providerHash + } + if provinceId > 0 { + return "p" + types.String(provinceId) + providerHash + } + return "a" + types.String(countryId) + providerHash +} diff --git a/pkg/iplibrary/ip_item_test.go b/pkg/iplibrary/ip_item_test.go index cf3b740..fbb1442 100644 --- a/pkg/iplibrary/ip_item_test.go +++ b/pkg/iplibrary/ip_item_test.go @@ -12,11 +12,6 @@ func TestIpItem_AsBinary(t *testing.T) { var item = &ipItem{ IPFrom: 123456789, IPTo: 123456790, - CountryId: 1, - ProvinceId: 2, - CityId: 3, - TownId: 4, - ProviderId: 5, } b, err := item.AsBinary() if err != nil { diff --git a/pkg/iplibrary/reader.go b/pkg/iplibrary/reader.go index faa8dc1..8933a53 100644 --- a/pkg/iplibrary/reader.go +++ b/pkg/iplibrary/reader.go @@ -17,12 +17,16 @@ import ( type Reader struct { meta *Meta + regionMap map[string]*ipRegion + ipV4Items []*ipItem ipV6Items []*ipItem } func NewReader(reader io.Reader) (*Reader, error) { - var libReader = &Reader{} + var libReader = &Reader{ + regionMap: map[string]*ipRegion{}, + } err := libReader.load(reader) if err != nil { return nil, err @@ -186,25 +190,36 @@ func (this *Reader) parse(data []byte) (left []byte, err error) { ipTo = types.Uint64(pieces[2]) + ipFrom } + var countryId = types.Uint32(pieces[3]) + var provinceId = types.Uint32(pieces[4]) + var cityId = types.Uint32(pieces[5]) + var townId = types.Uint32(pieces[6]) + var providerId = types.Uint32(pieces[7]) + var hash = HashRegion(countryId, provinceId, cityId, townId, providerId) + + region, ok := this.regionMap[hash] + if !ok { + region = &ipRegion{ + CountryId: countryId, + ProvinceId: provinceId, + CityId: cityId, + TownId: townId, + ProviderId: providerId, + } + this.regionMap[hash] = region + } + if version == "4" { this.ipV4Items = append(this.ipV4Items, &ipItem{ - IPFrom: ipFrom, - IPTo: ipTo, - CountryId: types.Uint32(pieces[3]), - ProvinceId: types.Uint32(pieces[4]), - CityId: types.Uint32(pieces[5]), - TownId: types.Uint32(pieces[6]), - ProviderId: types.Uint32(pieces[7]), + IPFrom: ipFrom, + IPTo: ipTo, + Region: region, }) } else { this.ipV6Items = append(this.ipV6Items, &ipItem{ - IPFrom: ipFrom, - IPTo: ipTo, - CountryId: types.Uint32(pieces[3]), - ProvinceId: types.Uint32(pieces[4]), - CityId: types.Uint32(pieces[5]), - TownId: types.Uint32(pieces[6]), - ProviderId: types.Uint32(pieces[7]), + IPFrom: ipFrom, + IPTo: ipTo, + Region: region, }) } diff --git a/pkg/iplibrary/reader_result.go b/pkg/iplibrary/reader_result.go index d88733d..2a47321 100644 --- a/pkg/iplibrary/reader_result.go +++ b/pkg/iplibrary/reader_result.go @@ -18,7 +18,7 @@ func (this *QueryResult) IsOk() bool { func (this *QueryResult) CountryId() int64 { if this.item != nil { - return int64(this.item.CountryId) + return int64(this.item.Region.CountryId) } return 0 } @@ -27,8 +27,8 @@ func (this *QueryResult) CountryName() string { if this.item == nil { return "" } - if this.item.CountryId > 0 { - var country = this.meta.CountryWithId(this.item.CountryId) + if this.item.Region.CountryId > 0 { + var country = this.meta.CountryWithId(this.item.Region.CountryId) if country != nil { return country.Name } @@ -40,8 +40,8 @@ func (this *QueryResult) CountryCodes() []string { if this.item == nil { return nil } - if this.item.CountryId > 0 { - var country = this.meta.CountryWithId(this.item.CountryId) + if this.item.Region.CountryId > 0 { + var country = this.meta.CountryWithId(this.item.Region.CountryId) if country != nil { return country.Codes } @@ -51,7 +51,7 @@ func (this *QueryResult) CountryCodes() []string { func (this *QueryResult) ProvinceId() int64 { if this.item != nil { - return int64(this.item.ProvinceId) + return int64(this.item.Region.ProvinceId) } return 0 } @@ -60,8 +60,8 @@ func (this *QueryResult) ProvinceName() string { if this.item == nil { return "" } - if this.item.ProvinceId > 0 { - var province = this.meta.ProvinceWithId(this.item.ProvinceId) + if this.item.Region.ProvinceId > 0 { + var province = this.meta.ProvinceWithId(this.item.Region.ProvinceId) if province != nil { return province.Name } @@ -73,8 +73,8 @@ func (this *QueryResult) ProvinceCodes() []string { if this.item == nil { return nil } - if this.item.ProvinceId > 0 { - var province = this.meta.ProvinceWithId(this.item.ProvinceId) + if this.item.Region.ProvinceId > 0 { + var province = this.meta.ProvinceWithId(this.item.Region.ProvinceId) if province != nil { return province.Codes } @@ -84,7 +84,7 @@ func (this *QueryResult) ProvinceCodes() []string { func (this *QueryResult) CityId() int64 { if this.item != nil { - return int64(this.item.CityId) + return int64(this.item.Region.CityId) } return 0 } @@ -93,8 +93,8 @@ func (this *QueryResult) CityName() string { if this.item == nil { return "" } - if this.item.CityId > 0 { - var city = this.meta.CityWithId(this.item.CityId) + if this.item.Region.CityId > 0 { + var city = this.meta.CityWithId(this.item.Region.CityId) if city != nil { return city.Name } @@ -104,7 +104,7 @@ func (this *QueryResult) CityName() string { func (this *QueryResult) TownId() int64 { if this.item != nil { - return int64(this.item.TownId) + return int64(this.item.Region.TownId) } return 0 } @@ -113,8 +113,8 @@ func (this *QueryResult) TownName() string { if this.item == nil { return "" } - if this.item.TownId > 0 { - var town = this.meta.TownWithId(this.item.TownId) + if this.item.Region.TownId > 0 { + var town = this.meta.TownWithId(this.item.Region.TownId) if town != nil { return town.Name } @@ -124,7 +124,7 @@ func (this *QueryResult) TownName() string { func (this *QueryResult) ProviderId() int64 { if this.item != nil { - return int64(this.item.ProviderId) + return int64(this.item.Region.ProviderId) } return 0 } @@ -133,8 +133,8 @@ func (this *QueryResult) ProviderName() string { if this.item == nil { return "" } - if this.item.ProviderId > 0 { - var provider = this.meta.ProviderWithId(this.item.ProviderId) + if this.item.Region.ProviderId > 0 { + var provider = this.meta.ProviderWithId(this.item.Region.ProviderId) if provider != nil { return provider.Name } @@ -146,8 +146,8 @@ func (this *QueryResult) ProviderCodes() []string { if this.item == nil { return nil } - if this.item.ProviderId > 0 { - var provider = this.meta.ProviderWithId(this.item.ProviderId) + if this.item.Region.ProviderId > 0 { + var provider = this.meta.ProviderWithId(this.item.Region.ProviderId) if provider != nil { return provider.Codes }