trie.go 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131
  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. // Convert each byte in the IP address to its 8-bit binary representation
  23. var result []string
  24. for _, b := range ipBytes {
  25. result = append(result, fmt.Sprintf("%08b", b))
  26. }
  27. // Join the binary representation of each byte with dots to form the final bit string
  28. return strings.Join(result, "")
  29. }
  30. func bitStringToIp(bitString string) string {
  31. // Split the bit string into four 8-bit segments
  32. segments := []string{
  33. bitString[:8],
  34. bitString[8:16],
  35. bitString[16:24],
  36. bitString[24:32],
  37. }
  38. // Convert each segment to its decimal equivalent
  39. var decimalSegments []int
  40. for _, s := range segments {
  41. i, _ := strconv.ParseInt(s, 2, 64)
  42. decimalSegments = append(decimalSegments, int(i))
  43. }
  44. // Join the decimal segments with dots to form the IP address string
  45. return fmt.Sprintf("%d.%d.%d.%d", decimalSegments[0], decimalSegments[1], decimalSegments[2], decimalSegments[3])
  46. }
  47. // inititlaizing a new trie
  48. func newTrie() *trie {
  49. t := new(trie)
  50. t.root = new(trie_Node)
  51. return t
  52. }
  53. // Passing words to trie
  54. func (t *trie) insert(ipAddr string, cc string) {
  55. word := ipToBitString(ipAddr)
  56. current := t.root
  57. for _, wr := range word {
  58. index := wr - '0'
  59. if current.childrens[index] == nil {
  60. current.childrens[index] = &trie_Node{
  61. childrens: [2]*trie_Node{},
  62. ends: false,
  63. cc: cc,
  64. }
  65. }
  66. current = current.childrens[index]
  67. }
  68. current.ends = true
  69. }
  70. func isReservedIP(ip string) bool {
  71. parsedIP := net.ParseIP(ip)
  72. if parsedIP == nil {
  73. return false
  74. }
  75. // Check if the IP address is a loopback address
  76. if parsedIP.IsLoopback() {
  77. return true
  78. }
  79. // Check if the IP address is in the link-local address range
  80. if parsedIP.IsLinkLocalUnicast() || parsedIP.IsLinkLocalMulticast() {
  81. return true
  82. }
  83. // Check if the IP address is in the private address ranges
  84. privateRanges := []*net.IPNet{
  85. {IP: net.ParseIP("10.0.0.0"), Mask: net.CIDRMask(8, 32)},
  86. {IP: net.ParseIP("172.16.0.0"), Mask: net.CIDRMask(12, 32)},
  87. {IP: net.ParseIP("192.168.0.0"), Mask: net.CIDRMask(16, 32)},
  88. }
  89. for _, r := range privateRanges {
  90. if r.Contains(parsedIP) {
  91. return true
  92. }
  93. }
  94. // If the IP address is not a reserved address, return false
  95. return false
  96. }
  97. // Initializing the search for word in node
  98. func (t *trie) search(ipAddr string) string {
  99. if isReservedIP(ipAddr) {
  100. return ""
  101. }
  102. word := ipToBitString(ipAddr)
  103. current := t.root
  104. for _, wr := range word {
  105. index := wr - '0'
  106. if current.childrens[index] == nil {
  107. return current.cc
  108. }
  109. current = current.childrens[index]
  110. }
  111. if current.ends {
  112. return current.cc
  113. }
  114. //Not found
  115. return ""
  116. }