trie.go 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144
  1. package geodb
  2. import (
  3. "fmt"
  4. "net"
  5. "strconv"
  6. "strings"
  7. )
  8. type trie_Node struct {
  9. childrens [2]*trie_Node
  10. ends bool
  11. cc string
  12. }
  13. // Initializing the root of the trie
  14. type trie struct {
  15. root *trie_Node
  16. }
  17. func ipToBitString(ip string) string {
  18. // Parse the IP address string into a net.IP object
  19. parsedIP := net.ParseIP(ip)
  20. // Convert the IP address to a 4-byte slice
  21. ipBytes := parsedIP.To4()
  22. if ipBytes == nil {
  23. //This is an IPv6 address
  24. ipBytes = parsedIP.To16()
  25. }
  26. // Convert each byte in the IP address to its 8-bit binary representation
  27. var result []string
  28. for _, b := range ipBytes {
  29. result = append(result, fmt.Sprintf("%08b", b))
  30. }
  31. // Join the binary representation of each byte with dots to form the final bit string
  32. return strings.Join(result, "")
  33. }
  34. func bitStringToIp(bitString string) string {
  35. // Check if the bit string represents an IPv4 or IPv6 address
  36. isIPv4 := len(bitString) == 32
  37. // Split the bit string into 8-bit segments
  38. segments := make([]string, 0)
  39. if isIPv4 {
  40. for i := 0; i < 4; i++ {
  41. segments = append(segments, bitString[i*8:(i+1)*8])
  42. }
  43. } else {
  44. for i := 0; i < 16; i++ {
  45. segments = append(segments, bitString[i*8:(i+1)*8])
  46. }
  47. }
  48. // Convert each segment to its decimal equivalent
  49. decimalSegments := make([]int, len(segments))
  50. for i, s := range segments {
  51. val, _ := strconv.ParseInt(s, 2, 64)
  52. decimalSegments[i] = int(val)
  53. }
  54. // Construct the IP address string based on the type (IPv4 or IPv6)
  55. if isIPv4 {
  56. return fmt.Sprintf("%d.%d.%d.%d", decimalSegments[0], decimalSegments[1], decimalSegments[2], decimalSegments[3])
  57. } else {
  58. ip := make(net.IP, net.IPv6len)
  59. for i := 0; i < net.IPv6len; i++ {
  60. ip[i] = byte(decimalSegments[i])
  61. }
  62. return ip.String()
  63. }
  64. }
  65. // inititlaizing a new trie
  66. func newTrie() *trie {
  67. t := new(trie)
  68. t.root = new(trie_Node)
  69. return t
  70. }
  71. // Passing words to trie
  72. func (t *trie) insert(ipAddr string, cc string) {
  73. word := ipToBitString(ipAddr)
  74. current := t.root
  75. for _, wr := range word {
  76. index := wr - '0'
  77. if current.childrens[index] == nil {
  78. current.childrens[index] = &trie_Node{
  79. childrens: [2]*trie_Node{},
  80. ends: false,
  81. cc: cc,
  82. }
  83. }
  84. current = current.childrens[index]
  85. }
  86. current.ends = true
  87. }
  88. func isReservedIP(ip string) bool {
  89. parsedIP := net.ParseIP(ip)
  90. if parsedIP == nil {
  91. return false
  92. }
  93. // Check if the IP address is a loopback address
  94. if parsedIP.IsLoopback() {
  95. return true
  96. }
  97. // Check if the IP address is in the link-local address range
  98. if parsedIP.IsLinkLocalUnicast() || parsedIP.IsLinkLocalMulticast() {
  99. return true
  100. }
  101. if parsedIP.IsPrivate() {
  102. return true
  103. }
  104. // If the IP address is not a reserved address, return false
  105. return false
  106. }
  107. // Initializing the search for word in node
  108. func (t *trie) search(ipAddr string) string {
  109. if isReservedIP(ipAddr) {
  110. return ""
  111. }
  112. word := ipToBitString(ipAddr)
  113. current := t.root
  114. for _, wr := range word {
  115. index := wr - '0'
  116. if current.childrens[index] == nil {
  117. return current.cc
  118. }
  119. current = current.childrens[index]
  120. }
  121. if current.ends {
  122. return current.cc
  123. }
  124. //Not found
  125. return ""
  126. }