github.com/josephvusich/fdf@v0.0.0-20230522095411-9326dd32e33f/db.go (about)

     1  package main
     2  
     3  type queryGenerator func(r *fileRecord, q *query)
     4  
     5  var queryGenerators [][]queryGenerator
     6  
     7  func init() {
     8  	singles := []queryGenerator{
     9  		0: func(r *fileRecord, q *query) { r.byName(q) },
    10  		1: func(r *fileRecord, q *query) { r.byParent(q) },
    11  		2: func(r *fileRecord, q *query) { r.byPathSuffix(q) },
    12  		3: func(r *fileRecord, q *query) { r.bySize(q) },
    13  		4: func(r *fileRecord, q *query) { r.byChecksum(q) },
    14  	}
    15  
    16  	// Use binary decrement to generate all possible subsets based on bit position
    17  	// We need (2<<N)-1 bits
    18  	counter := 0
    19  	for b := (1 << len(singles)) - 1; b > 0; b-- {
    20  		counter++
    21  
    22  		// queries will never include Checksum without Size
    23  		if (b>>4)&1 == 1 && (b>>3)&1 != 1 {
    24  			continue
    25  		}
    26  
    27  		// queries will never include PathSuffix without Parent
    28  		if (b>>2)&1 == 1 && (b>>1)&1 != 1 {
    29  			continue
    30  		}
    31  
    32  		var combo []queryGenerator
    33  		for i, x := range singles {
    34  			if (b>>i)&1 == 1 {
    35  				combo = append(combo, x)
    36  			}
    37  		}
    38  		queryGenerators = append(queryGenerators, combo)
    39  	}
    40  }
    41  
    42  type query struct {
    43  	Name       string
    44  	Parent     string
    45  	PathSuffix string
    46  	Size       int64
    47  	Checksum   checksum
    48  }
    49  
    50  func (r *fileRecord) byName(q *query) *query {
    51  	q.Name = r.FoldedName
    52  	return q
    53  }
    54  
    55  func (r *fileRecord) byParent(q *query) *query {
    56  	q.Parent = r.FoldedParent
    57  	return q
    58  }
    59  
    60  func (r *fileRecord) byPathSuffix(q *query) *query {
    61  	q = r.byParent(q)
    62  	q.PathSuffix = r.PathSuffix
    63  	return q
    64  }
    65  
    66  func (r *fileRecord) bySize(q *query) *query {
    67  	q.Size = r.Size()
    68  	return q
    69  }
    70  
    71  // If !HasChecksum, equivalent to bySize()
    72  func (r *fileRecord) byChecksum(q *query) *query {
    73  	q = r.bySize(q)
    74  	if r.HasChecksum {
    75  		q.Checksum = r.Checksum
    76  	}
    77  	return q
    78  }
    79  
    80  type db struct {
    81  	m map[query]recordSet
    82  }
    83  
    84  func newDB() *db {
    85  	return &db{
    86  		m: make(map[query]recordSet),
    87  	}
    88  }
    89  
    90  func (d *db) insert(r *fileRecord) {
    91  	var rs recordSet
    92  	var ok bool
    93  
    94  	for _, generatorSet := range queryGenerators {
    95  		var q query
    96  		for _, g := range generatorSet {
    97  			g(r, &q)
    98  		}
    99  
   100  		if rs, ok = d.m[q]; !ok {
   101  			rs = make(recordSet)
   102  		}
   103  		rs[r] = struct{}{}
   104  		d.m[q] = rs
   105  	}
   106  }
   107  
   108  func (d *db) remove(r *fileRecord) {
   109  	for _, generatorSet := range queryGenerators {
   110  		var q query
   111  		for _, g := range generatorSet {
   112  			g(r, &q)
   113  		}
   114  
   115  		if rs, ok := d.m[q]; ok {
   116  			delete(rs, r)
   117  		}
   118  	}
   119  }
   120  
   121  func (d *db) query(q *query) recordSet {
   122  	return d.m[*q]
   123  }