123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146 |
- /*
- * Copyright (c) 2015, zheng-ji.info
- * */
- package gophone
- import (
- "bytes"
- "encoding/binary"
- "errors"
- "fmt"
- "strconv"
- "strings"
- )
- const (
- IntLen = 4
- CharLen = 1
- PhoneIndexLength = 9
- Chunk = 100
- )
- type GOPhone struct {
- phoneDat []byte
- }
- type PhoneRecord struct {
- PhoneNum string
- Province string
- City string
- ZipCode string
- AreaZone string
- CardType string
- }
- func New(phoneDat []byte) *GOPhone {
- if nil == phoneDat || len(phoneDat) == 0 {
- panic(errors.New("phoneDat is required"))
- }
- return &GOPhone{
- phoneDat: phoneDat,
- }
- }
- func (g *GOPhone) Display() {
- fmt.Println(g.getVersion())
- fmt.Println(g.getTotalRecord())
- fmt.Println(g.getFirstRecordOffset())
- }
- func (pr PhoneRecord) String() string {
- _str := fmt.Sprintf("PhoneNum: %s\nAreaZone: %s\nCardType: %s\nCity: %s\nZipCode: %s\nProvince: %s\n", pr.PhoneNum, pr.AreaZone, pr.CardType, pr.City, pr.ZipCode, pr.Province)
- return _str
- }
- func (g *GOPhone) getVersion() string {
- return string(g.phoneDat[0:IntLen])
- }
- func (g *GOPhone) getTotalRecord() int32 {
- total := (int32(len(g.phoneDat)) - g.getFirstRecordOffset()) / PhoneIndexLength
- return total
- }
- func (g *GOPhone) getFirstRecordOffset() int32 {
- var offset int32
- buffer := bytes.NewBuffer(g.phoneDat[IntLen : IntLen*2])
- _ = binary.Read(buffer, binary.LittleEndian, &offset)
- return offset
- }
- func (g *GOPhone) getIndexRecord(offset int32) (phonePrefix int32, recordOffset int32, cardType byte) {
- buffer := bytes.NewBuffer(g.phoneDat[offset : offset+IntLen])
- _ = binary.Read(buffer, binary.LittleEndian, &phonePrefix)
- buffer = bytes.NewBuffer(g.phoneDat[offset+IntLen : offset+IntLen*2])
- _ = binary.Read(buffer, binary.LittleEndian, &recordOffset)
- buffer = bytes.NewBuffer(g.phoneDat[offset+IntLen*2 : offset+IntLen*2+CharLen])
- _ = binary.Read(buffer, binary.LittleEndian, &cardType)
- return
- }
- func (g *GOPhone) getOpCompany(cardtype byte) string {
- var cardStr = ""
- switch cardtype {
- case '1':
- cardStr = "移动"
- case '2':
- cardStr = "联通"
- case '3':
- cardStr = "电信"
- case '4':
- cardStr = "电信虚拟运营商"
- case '5':
- cardStr = "联通虚拟运营商"
- default:
- cardStr = "移动虚拟运营商"
- }
- return cardStr
- }
- // BinarySearch
- func (g *GOPhone) Find(phoneNum string) (pr *PhoneRecord, err error) {
- err = nil
- if len(phoneNum) < 7 || len(phoneNum) > 11 {
- return nil, errors.New("illegal phone length")
- }
- var left int32 = 0
- phoneSevenInt, _ := strconv.ParseInt(phoneNum[0:7], 10, 32)
- phoneSevenInt32 := int32(phoneSevenInt)
- totalLen := int32(len(g.phoneDat))
- right := g.getTotalRecord()
- firstPhoneRecordOffset := g.getFirstRecordOffset()
- for {
- if left > right {
- break
- }
- mid := (left + right) / 2
- currentOffset := firstPhoneRecordOffset + mid*PhoneIndexLength
- if currentOffset >= totalLen {
- break
- }
- curPhone, recordOffset, cardType := g.getIndexRecord(currentOffset)
- if curPhone > phoneSevenInt32 {
- right = mid - 1
- } else if curPhone < phoneSevenInt32 {
- left = mid + 1
- } else {
- s := recordOffset
- e := recordOffset + int32(strings.Index(string(g.phoneDat[recordOffset:recordOffset+Chunk]), "\000"))
- recordContent := string(g.phoneDat[s:e])
- _tmp := strings.Split(recordContent, "|")
- cardStr := g.getOpCompany(cardType)
- pr = &PhoneRecord{
- PhoneNum: phoneNum,
- Province: _tmp[0],
- City: _tmp[1],
- ZipCode: _tmp[2],
- AreaZone: _tmp[3],
- CardType: cardStr,
- }
- return
- }
- }
- return nil, errors.New("num not found")
- }
|