Skip to content

Commit

Permalink
peel off the parser to adapt kinds of data file such as 17mon,qqwry...
Browse files Browse the repository at this point in the history
  • Loading branch information
hanguofeng committed Mar 14, 2014
1 parent a67c043 commit 258bbd1
Show file tree
Hide file tree
Showing 4 changed files with 133 additions and 114 deletions.
119 changes: 5 additions & 114 deletions ipquery.go
Original file line number Diff line number Diff line change
@@ -1,15 +1,8 @@
package ipquery

import (
"bufio"
"bytes"
"encoding/binary"
"errors"
"io/ioutil"
//"log"
"net"
"os"
"strings"
)

type QueryServer struct {
Expand All @@ -19,76 +12,19 @@ type QueryServer struct {
items []DataItem
}

type DataItem struct {
Ip uint32
Address *Address
}

type Address struct {
Country string
Province string
City string
}

func (this *QueryServer) Load(dataFile string) error {
f, err := os.Open(dataFile)
parser := &Parser_17mon{}
items, err := parser.ParseData(dataFile)
if nil != err {
return err
} else {
this.items = items
return nil
}

reader := bufio.NewReader(f)
data, err := ioutil.ReadAll(reader)
if nil != err {
return err
}

this.dataFile = dataFile
this.data = data

this.length = this.getLength()
this.ParseData()

return nil
}

func (this *QueryServer) ParseData() error {
data := this.data
startPos, readBytesCnt := binary.Varint(data[4:8])
if readBytesCnt != 1 {
//log.Fatalf("[ParseData] Get start position failed,readBytesCnt:%d ", readBytesCnt)
return errors.New("[ParseData] Get start position failed")
}
endPos := int64(this.length - 1024)
//log.Printf("[ParseData] StartPos:%d,EndPos:%d", startPos, endPos)

this.initItemData()
for i := startPos + 1028; i < endPos; i += 8 {
var ip []byte
var offset uint32
var length uint32
var result string
bufOffset := make([]byte, 4)

ip = data[i+0 : i+4]
bufOffset[0] = data[i+4]
bufOffset[1] = data[i+5]
bufOffset[2] = data[i+6]
bufOffset[3] = 0
binary.Read(bytes.NewBuffer(bufOffset), binary.LittleEndian, &offset)
offset = offset + this.length - 1024
length = uint32(data[i+7])
result = string(data[offset : offset+length])
this.addItemData(ip, result)

//log.Printf("[ParseData] Got Item: {ip:%c,offset:%d,length:%s}", ip, offset, length)
//log.Printf("[ParseData] Addr: %s", result)
}

//log.Printf("[ParseData]item data length:%d", len(this.items))
return nil

}

func (this *QueryServer) FindIp(ipstr string) (*Address, bool) {
ip := net.ParseIP(ipstr)
if nil == ip {
Expand Down Expand Up @@ -134,48 +70,3 @@ func (this *QueryServer) FindIp(ipstr string) (*Address, bool) {

return nil, false
}

func (this *QueryServer) getLength() uint32 {
var length uint32
data := this.data
lengthBytes := data[0:4]
binary.Read(bytes.NewBuffer(lengthBytes), binary.BigEndian, &length)
//log.Printf("[getLength]length:%d", length)
return length
}

func (this *QueryServer) initItemData() {
this.items = []DataItem{}
}

func (this *QueryServer) addItemData(ip []byte, address string) {
address_struct := getAddressStructByAddressString(address)
item := DataItem{Ip: ip2long(ip), Address: address_struct}
this.items = append(this.items, item)
}

func getAddressStructByAddressString(address string) *Address {
address_arr := strings.Split(address, "\t")
country := ""
province := ""
city := ""

if len(address_arr) > 0 {
country = address_arr[0]
}
if len(address_arr) > 1 {
province = address_arr[1]
}
if len(address_arr) > 2 {
city = address_arr[2]
}

address_struct := &Address{Country: country, Province: province, City: city}
return address_struct
}

func ip2long(ip []byte) uint32 {
var iplong uint32
binary.Read(bytes.NewBuffer(ip), binary.BigEndian, &iplong)
return iplong
}
83 changes: 83 additions & 0 deletions parser_17mon.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
package ipquery

import (
"bufio"
"bytes"
"encoding/binary"
"errors"
"io/ioutil"
//"log"
"os"
)

type Parser_17mon struct {
}

func (this *Parser_17mon) ParseData(dataFile string) ([]DataItem, error) {

/* --Read the file */
f, err := os.Open(dataFile)
if nil != err {
return nil, err
}

reader := bufio.NewReader(f)
data, err := ioutil.ReadAll(reader)
if nil != err {
return nil, err
}

/* --Get record length */
var length uint32
lengthBytes := data[0:4]
binary.Read(bytes.NewBuffer(lengthBytes), binary.BigEndian, &length)

/* --Calc start position and end position */
startPos, readBytesCnt := binary.Varint(data[4:8])
if readBytesCnt != 1 {
//log.Fatalf("[ParseData] Get start position failed,readBytesCnt:%d ", readBytesCnt)
return nil, errors.New("[ParseData] Get start position failed")
}
endPos := int64(length - 1024)
//log.Printf("[ParseData] StartPos:%d,EndPos:%d", startPos, endPos)

/* --Parse items */
items := []DataItem{}
for i := startPos + 1028; i < endPos; i += 8 {
var ip []byte
var offset uint32
var strlength uint32
var result string

/* --- Ip */
ip = data[i+0 : i+4]
/* --- Offset */
bufOffset := make([]byte, 4)
bufOffset[0] = data[i+4]
bufOffset[1] = data[i+5]
bufOffset[2] = data[i+6]
bufOffset[3] = 0
binary.Read(bytes.NewBuffer(bufOffset), binary.LittleEndian, &offset)
offset = offset + length - 1024
/* --- StrLength */
strlength = uint32(data[i+7])
/* --- Get result string */
result = string(data[offset : offset+strlength])
/* --- Append to items */
items = append(items, makeItemData(ip, result))

//log.Printf("[ParseData] Got Item: {ip:%c,offset:%d,strlength:%s}", ip, offset, strlength)
//log.Printf("[ParseData] Addr: %s", result)
}

//log.Printf("[ParseData]item data length:%d", len(this.items))

return items, nil

}

func makeItemData(ip []byte, address string) DataItem {
address_struct := getAddressStructByAddressString(address)
item := DataItem{Ip: ip2long(ip), Address: address_struct}
return item
}
12 changes: 12 additions & 0 deletions type.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package ipquery

type DataItem struct {
Ip uint32
Address *Address
}

type Address struct {
Country string
Province string
City string
}
33 changes: 33 additions & 0 deletions util.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package ipquery

import (
"bytes"
"encoding/binary"
"strings"
)

func getAddressStructByAddressString(address string) *Address {
address_arr := strings.Split(address, "\t")
country := ""
province := ""
city := ""

if len(address_arr) > 0 {
country = address_arr[0]
}
if len(address_arr) > 1 {
province = address_arr[1]
}
if len(address_arr) > 2 {
city = address_arr[2]
}

address_struct := &Address{Country: country, Province: province, City: city}
return address_struct
}

func ip2long(ip []byte) uint32 {
var iplong uint32
binary.Read(bytes.NewBuffer(ip), binary.BigEndian, &iplong)
return iplong
}

0 comments on commit 258bbd1

Please sign in to comment.