reader.go 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137
  1. package geosite
  2. import (
  3. "bufio"
  4. "encoding/binary"
  5. "io"
  6. "os"
  7. "sync"
  8. "sync/atomic"
  9. E "github.com/sagernet/sing/common/exceptions"
  10. "github.com/sagernet/sing/common/varbin"
  11. )
  12. type Reader struct {
  13. access sync.Mutex
  14. reader io.ReadSeeker
  15. bufferedReader *bufio.Reader
  16. metadataIndex int64
  17. domainIndex map[string]int
  18. domainLength map[string]int
  19. }
  20. func Open(path string) (*Reader, []string, error) {
  21. content, err := os.Open(path)
  22. if err != nil {
  23. return nil, nil, err
  24. }
  25. reader, codes, err := NewReader(content)
  26. if err != nil {
  27. content.Close()
  28. return nil, nil, err
  29. }
  30. return reader, codes, nil
  31. }
  32. func NewReader(readSeeker io.ReadSeeker) (*Reader, []string, error) {
  33. reader := &Reader{
  34. reader: readSeeker,
  35. }
  36. err := reader.readMetadata()
  37. if err != nil {
  38. return nil, nil, err
  39. }
  40. codes := make([]string, 0, len(reader.domainIndex))
  41. for code := range reader.domainIndex {
  42. codes = append(codes, code)
  43. }
  44. return reader, codes, nil
  45. }
  46. type geositeMetadata struct {
  47. Code string
  48. Index uint64
  49. Length uint64
  50. }
  51. func (r *Reader) readMetadata() error {
  52. counter := &readCounter{Reader: r.reader}
  53. reader := bufio.NewReader(counter)
  54. version, err := reader.ReadByte()
  55. if err != nil {
  56. return err
  57. }
  58. if version != 0 {
  59. return E.New("unknown version")
  60. }
  61. entryLength, err := binary.ReadUvarint(reader)
  62. if err != nil {
  63. return err
  64. }
  65. keys := make([]string, entryLength)
  66. domainIndex := make(map[string]int)
  67. domainLength := make(map[string]int)
  68. for i := 0; i < int(entryLength); i++ {
  69. var (
  70. code string
  71. codeIndex uint64
  72. codeLength uint64
  73. )
  74. code, err = varbin.ReadValue[string](reader, binary.BigEndian)
  75. if err != nil {
  76. return err
  77. }
  78. keys[i] = code
  79. codeIndex, err = binary.ReadUvarint(reader)
  80. if err != nil {
  81. return err
  82. }
  83. codeLength, err = binary.ReadUvarint(reader)
  84. if err != nil {
  85. return err
  86. }
  87. domainIndex[code] = int(codeIndex)
  88. domainLength[code] = int(codeLength)
  89. }
  90. r.domainIndex = domainIndex
  91. r.domainLength = domainLength
  92. r.metadataIndex = counter.count - int64(reader.Buffered())
  93. r.bufferedReader = reader
  94. return nil
  95. }
  96. func (r *Reader) Read(code string) ([]Item, error) {
  97. index, exists := r.domainIndex[code]
  98. if !exists {
  99. return nil, E.New("code ", code, " not exists!")
  100. }
  101. _, err := r.reader.Seek(r.metadataIndex+int64(index), io.SeekStart)
  102. if err != nil {
  103. return nil, err
  104. }
  105. r.bufferedReader.Reset(r.reader)
  106. itemList := make([]Item, r.domainLength[code])
  107. err = varbin.Read(r.bufferedReader, binary.BigEndian, &itemList)
  108. if err != nil {
  109. return nil, err
  110. }
  111. return itemList, nil
  112. }
  113. func (r *Reader) Upstream() any {
  114. return r.reader
  115. }
  116. type readCounter struct {
  117. io.Reader
  118. count int64
  119. }
  120. func (r *readCounter) Read(p []byte) (n int, err error) {
  121. n, err = r.Reader.Read(p)
  122. if n > 0 {
  123. atomic.AddInt64(&r.count, int64(n))
  124. }
  125. return
  126. }