123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144 |
- package geodb
- import (
- "fmt"
- "net"
- "strconv"
- "strings"
- )
- type trie_Node struct {
- childrens [2]*trie_Node
- ends bool
- cc string
- }
- // Initializing the root of the trie
- type trie struct {
- root *trie_Node
- }
- func ipToBitString(ip string) string {
- // Parse the IP address string into a net.IP object
- parsedIP := net.ParseIP(ip)
- // Convert the IP address to a 4-byte slice
- ipBytes := parsedIP.To4()
- if ipBytes == nil {
- //This is an IPv6 address
- ipBytes = parsedIP.To16()
- }
- // Convert each byte in the IP address to its 8-bit binary representation
- var result []string
- for _, b := range ipBytes {
- result = append(result, fmt.Sprintf("%08b", b))
- }
- // Join the binary representation of each byte with dots to form the final bit string
- return strings.Join(result, "")
- }
- func bitStringToIp(bitString string) string {
- // Check if the bit string represents an IPv4 or IPv6 address
- isIPv4 := len(bitString) == 32
- // Split the bit string into 8-bit segments
- segments := make([]string, 0)
- if isIPv4 {
- for i := 0; i < 4; i++ {
- segments = append(segments, bitString[i*8:(i+1)*8])
- }
- } else {
- for i := 0; i < 16; i++ {
- segments = append(segments, bitString[i*8:(i+1)*8])
- }
- }
- // Convert each segment to its decimal equivalent
- decimalSegments := make([]int, len(segments))
- for i, s := range segments {
- val, _ := strconv.ParseInt(s, 2, 64)
- decimalSegments[i] = int(val)
- }
- // Construct the IP address string based on the type (IPv4 or IPv6)
- if isIPv4 {
- return fmt.Sprintf("%d.%d.%d.%d", decimalSegments[0], decimalSegments[1], decimalSegments[2], decimalSegments[3])
- } else {
- ip := make(net.IP, net.IPv6len)
- for i := 0; i < net.IPv6len; i++ {
- ip[i] = byte(decimalSegments[i])
- }
- return ip.String()
- }
- }
- // inititlaizing a new trie
- func newTrie() *trie {
- t := new(trie)
- t.root = new(trie_Node)
- return t
- }
- // Passing words to trie
- func (t *trie) insert(ipAddr string, cc string) {
- word := ipToBitString(ipAddr)
- current := t.root
- for _, wr := range word {
- index := wr - '0'
- if current.childrens[index] == nil {
- current.childrens[index] = &trie_Node{
- childrens: [2]*trie_Node{},
- ends: false,
- cc: cc,
- }
- }
- current = current.childrens[index]
- }
- current.ends = true
- }
- func isReservedIP(ip string) bool {
- parsedIP := net.ParseIP(ip)
- if parsedIP == nil {
- return false
- }
- // Check if the IP address is a loopback address
- if parsedIP.IsLoopback() {
- return true
- }
- // Check if the IP address is in the link-local address range
- if parsedIP.IsLinkLocalUnicast() || parsedIP.IsLinkLocalMulticast() {
- return true
- }
- if parsedIP.IsPrivate() {
- return true
- }
- // If the IP address is not a reserved address, return false
- return false
- }
- // Initializing the search for word in node
- func (t *trie) search(ipAddr string) string {
- if isReservedIP(ipAddr) {
- return ""
- }
- word := ipToBitString(ipAddr)
- current := t.root
- for _, wr := range word {
- index := wr - '0'
- if current.childrens[index] == nil {
- return current.cc
- }
- current = current.childrens[index]
- }
- if current.ends {
- return current.cc
- }
- //Not found
- return ""
- }
|