| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137 | 
							- package geosite
 
- import (
 
- 	"bufio"
 
- 	"encoding/binary"
 
- 	"io"
 
- 	"os"
 
- 	"sync"
 
- 	"sync/atomic"
 
- 	E "github.com/sagernet/sing/common/exceptions"
 
- 	"github.com/sagernet/sing/common/varbin"
 
- )
 
- type Reader struct {
 
- 	access         sync.Mutex
 
- 	reader         io.ReadSeeker
 
- 	bufferedReader *bufio.Reader
 
- 	metadataIndex  int64
 
- 	domainIndex    map[string]int
 
- 	domainLength   map[string]int
 
- }
 
- func Open(path string) (*Reader, []string, error) {
 
- 	content, err := os.Open(path)
 
- 	if err != nil {
 
- 		return nil, nil, err
 
- 	}
 
- 	reader, codes, err := NewReader(content)
 
- 	if err != nil {
 
- 		content.Close()
 
- 		return nil, nil, err
 
- 	}
 
- 	return reader, codes, nil
 
- }
 
- func NewReader(readSeeker io.ReadSeeker) (*Reader, []string, error) {
 
- 	reader := &Reader{
 
- 		reader: readSeeker,
 
- 	}
 
- 	err := reader.readMetadata()
 
- 	if err != nil {
 
- 		return nil, nil, err
 
- 	}
 
- 	codes := make([]string, 0, len(reader.domainIndex))
 
- 	for code := range reader.domainIndex {
 
- 		codes = append(codes, code)
 
- 	}
 
- 	return reader, codes, nil
 
- }
 
- type geositeMetadata struct {
 
- 	Code   string
 
- 	Index  uint64
 
- 	Length uint64
 
- }
 
- func (r *Reader) readMetadata() error {
 
- 	counter := &readCounter{Reader: r.reader}
 
- 	reader := bufio.NewReader(counter)
 
- 	version, err := reader.ReadByte()
 
- 	if err != nil {
 
- 		return err
 
- 	}
 
- 	if version != 0 {
 
- 		return E.New("unknown version")
 
- 	}
 
- 	entryLength, err := binary.ReadUvarint(reader)
 
- 	if err != nil {
 
- 		return err
 
- 	}
 
- 	keys := make([]string, entryLength)
 
- 	domainIndex := make(map[string]int)
 
- 	domainLength := make(map[string]int)
 
- 	for i := 0; i < int(entryLength); i++ {
 
- 		var (
 
- 			code       string
 
- 			codeIndex  uint64
 
- 			codeLength uint64
 
- 		)
 
- 		code, err = varbin.ReadValue[string](reader, binary.BigEndian)
 
- 		if err != nil {
 
- 			return err
 
- 		}
 
- 		keys[i] = code
 
- 		codeIndex, err = binary.ReadUvarint(reader)
 
- 		if err != nil {
 
- 			return err
 
- 		}
 
- 		codeLength, err = binary.ReadUvarint(reader)
 
- 		if err != nil {
 
- 			return err
 
- 		}
 
- 		domainIndex[code] = int(codeIndex)
 
- 		domainLength[code] = int(codeLength)
 
- 	}
 
- 	r.domainIndex = domainIndex
 
- 	r.domainLength = domainLength
 
- 	r.metadataIndex = counter.count - int64(reader.Buffered())
 
- 	r.bufferedReader = reader
 
- 	return nil
 
- }
 
- func (r *Reader) Read(code string) ([]Item, error) {
 
- 	index, exists := r.domainIndex[code]
 
- 	if !exists {
 
- 		return nil, E.New("code ", code, " not exists!")
 
- 	}
 
- 	_, err := r.reader.Seek(r.metadataIndex+int64(index), io.SeekStart)
 
- 	if err != nil {
 
- 		return nil, err
 
- 	}
 
- 	r.bufferedReader.Reset(r.reader)
 
- 	itemList := make([]Item, r.domainLength[code])
 
- 	err = varbin.Read(r.bufferedReader, binary.BigEndian, &itemList)
 
- 	if err != nil {
 
- 		return nil, err
 
- 	}
 
- 	return itemList, nil
 
- }
 
- func (r *Reader) Upstream() any {
 
- 	return r.reader
 
- }
 
- type readCounter struct {
 
- 	io.Reader
 
- 	count int64
 
- }
 
- func (r *readCounter) Read(p []byte) (n int, err error) {
 
- 	n, err = r.Reader.Read(p)
 
- 	if n > 0 {
 
- 		atomic.AddInt64(&r.count, int64(n))
 
- 	}
 
- 	return
 
- }
 
 
  |