reader.go 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158
  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. )
  11. type Reader struct {
  12. access sync.Mutex
  13. reader io.ReadSeeker
  14. bufferedReader *bufio.Reader
  15. metadataIndex int64
  16. domainIndex map[string]int
  17. domainLength map[string]int
  18. }
  19. func Open(path string) (*Reader, []string, error) {
  20. content, err := os.Open(path)
  21. if err != nil {
  22. return nil, nil, err
  23. }
  24. reader, codes, err := NewReader(content)
  25. if err != nil {
  26. content.Close()
  27. return nil, nil, err
  28. }
  29. return reader, codes, nil
  30. }
  31. func NewReader(readSeeker io.ReadSeeker) (*Reader, []string, error) {
  32. reader := &Reader{
  33. reader: readSeeker,
  34. }
  35. err := reader.readMetadata()
  36. if err != nil {
  37. return nil, nil, err
  38. }
  39. codes := make([]string, 0, len(reader.domainIndex))
  40. for code := range reader.domainIndex {
  41. codes = append(codes, code)
  42. }
  43. return reader, codes, nil
  44. }
  45. type geositeMetadata struct {
  46. Code string
  47. Index uint64
  48. Length uint64
  49. }
  50. func (r *Reader) readMetadata() error {
  51. counter := &readCounter{Reader: r.reader}
  52. reader := bufio.NewReader(counter)
  53. version, err := reader.ReadByte()
  54. if err != nil {
  55. return err
  56. }
  57. if version != 0 {
  58. return E.New("unknown version")
  59. }
  60. entryLength, err := binary.ReadUvarint(reader)
  61. if err != nil {
  62. return err
  63. }
  64. keys := make([]string, entryLength)
  65. domainIndex := make(map[string]int)
  66. domainLength := make(map[string]int)
  67. for i := 0; i < int(entryLength); i++ {
  68. var (
  69. code string
  70. codeIndex uint64
  71. codeLength uint64
  72. )
  73. code, err = readString(reader)
  74. if err != nil {
  75. return err
  76. }
  77. keys[i] = code
  78. codeIndex, err = binary.ReadUvarint(reader)
  79. if err != nil {
  80. return err
  81. }
  82. codeLength, err = binary.ReadUvarint(reader)
  83. if err != nil {
  84. return err
  85. }
  86. domainIndex[code] = int(codeIndex)
  87. domainLength[code] = int(codeLength)
  88. }
  89. r.domainIndex = domainIndex
  90. r.domainLength = domainLength
  91. r.metadataIndex = counter.count - int64(reader.Buffered())
  92. r.bufferedReader = reader
  93. return nil
  94. }
  95. func (r *Reader) Read(code string) ([]Item, error) {
  96. index, exists := r.domainIndex[code]
  97. if !exists {
  98. return nil, E.New("code ", code, " not exists!")
  99. }
  100. _, err := r.reader.Seek(r.metadataIndex+int64(index), io.SeekStart)
  101. if err != nil {
  102. return nil, err
  103. }
  104. r.bufferedReader.Reset(r.reader)
  105. itemList := make([]Item, r.domainLength[code])
  106. for i := range itemList {
  107. typeByte, err := r.bufferedReader.ReadByte()
  108. if err != nil {
  109. return nil, err
  110. }
  111. itemList[i].Type = ItemType(typeByte)
  112. itemList[i].Value, err = readString(r.bufferedReader)
  113. if err != nil {
  114. return nil, err
  115. }
  116. }
  117. return itemList, nil
  118. }
  119. func (r *Reader) Upstream() any {
  120. return r.reader
  121. }
  122. type readCounter struct {
  123. io.Reader
  124. count int64
  125. }
  126. func (r *readCounter) Read(p []byte) (n int, err error) {
  127. n, err = r.Reader.Read(p)
  128. if n > 0 {
  129. atomic.AddInt64(&r.count, int64(n))
  130. }
  131. return
  132. }
  133. func readString(reader io.ByteReader) (string, error) {
  134. length, err := binary.ReadUvarint(reader)
  135. if err != nil {
  136. return "", err
  137. }
  138. bytes := make([]byte, length)
  139. for i := range bytes {
  140. bytes[i], err = reader.ReadByte()
  141. if err != nil {
  142. return "", err
  143. }
  144. }
  145. return string(bytes), nil
  146. }