Sets
The CPE library provides powerful set operations for managing collections of CPE objects, including union, intersection, difference, and criteria-based filtering.
The class diagram below groups the CPESet methods by purpose — creating sets, basic operations, set algebra, and filtering:
And the flow below illustrates the three core set operations over two input sets A and B:
CPESet Structure
CPESet
type CPESet struct {
// Name is the name of the set, used to identify and distinguish sets
Name string
// Description is a detailed description of the set
Description string
// Internal storage of CPE items is hidden
}The CPESet type represents a collection of unique CPE objects with efficient set operations. Uniqueness is determined by each CPE's URI.
Creating Sets
NewCPESet
func NewCPESet(name string, description string) *CPESetCreates a new empty CPE set with the given name and description.
Parameters:
name- Name of the setdescription- Description of the set
Returns:
*CPESet- New empty set
Example:
// Create a new empty set
set := cpeskills.NewCPESet("Microsoft Products", "Collection of Microsoft product CPEs")
fmt.Printf("Created empty set with %d items\n", set.Size())FromArray
func FromArray(cpes []*CPE, name string, description string) *CPESetCreates a CPE set from an array of CPE objects.
Parameters:
cpes- Array of CPE objectsname- Name of the new setdescription- Description of the new set
Returns:
*CPESet- Set containing the CPE objects
Example:
// Create CPEs
cpe1, _ := cpeskills.ParseCpe23("cpe:2.3:a:microsoft:windows:10:*:*:*:*:*:*:*")
cpe2, _ := cpeskills.ParseCpe23("cpe:2.3:a:microsoft:office:2019:*:*:*:*:*:*:*")
cpe3, _ := cpeskills.ParseCpe23("cpe:2.3:a:apache:tomcat:9.0:*:*:*:*:*:*:*")
// Create set from array
cpeArray := []*cpeskills.CPE{cpe1, cpe2, cpe3}
set := cpeskills.FromArray(cpeArray, "My Products", "A collection of products")
fmt.Printf("Created set with %d items\n", set.Size())Basic Operations
Add
func (s *CPESet) Add(cpe *CPE)Adds a CPE object to the set. If an equal CPE (compared by URI) already exists, it is not added again.
Parameters:
cpe- CPE object to add
Example:
set := cpeskills.NewCPESet("demo", "demo set")
cpe1, _ := cpeskills.ParseCpe23("cpe:2.3:a:microsoft:windows:10:*:*:*:*:*:*:*")
cpe2, _ := cpeskills.ParseCpe23("cpe:2.3:a:apache:tomcat:9.0:*:*:*:*:*:*:*")
// Add CPEs one at a time
set.Add(cpe1)
set.Add(cpe2)
set.Add(cpe1) // cpe1 won't be added again (sets contain unique items)
fmt.Printf("Set size after adding: %d\n", set.Size())Remove
func (s *CPESet) Remove(cpe *CPE) boolRemoves a CPE object from the set.
Parameters:
cpe- CPE object to remove
Returns:
bool-trueif the CPE was removed,falseif it wasn't in the set
Example:
cpe1, _ := cpeskills.ParseCpe23("cpe:2.3:a:microsoft:windows:10:*:*:*:*:*:*:*")
set := cpeskills.NewCPESet("demo", "demo set")
set.Add(cpe1)
removed := set.Remove(cpe1)
fmt.Printf("CPE removed: %t\n", removed)
fmt.Printf("Set size after removal: %d\n", set.Size())Contains
func (s *CPESet) Contains(cpe *CPE) boolChecks if the set contains a specific CPE object.
Parameters:
cpe- CPE object to check for
Returns:
bool-trueif the set contains the CPE,falseotherwise
Example:
cpe1, _ := cpeskills.ParseCpe23("cpe:2.3:a:microsoft:windows:10:*:*:*:*:*:*:*")
cpe2, _ := cpeskills.ParseCpe23("cpe:2.3:a:apache:tomcat:9.0:*:*:*:*:*:*:*")
set := cpeskills.NewCPESet("demo", "demo set")
set.Add(cpe1)
fmt.Printf("Contains Windows: %t\n", set.Contains(cpe1))
fmt.Printf("Contains Tomcat: %t\n", set.Contains(cpe2))Size
func (s *CPESet) Size() intReturns the number of CPE objects in the set.
Returns:
int- Number of items in the set
Clear
func (s *CPESet) Clear()Removes all CPE objects from the set.
Example:
set := cpeskills.NewCPESet("demo", "demo set")
// ... add some CPEs ...
fmt.Printf("Size before clear: %d\n", set.Size())
set.Clear()
fmt.Printf("Size after clear: %d\n", set.Size())Set Operations
Union
func (s *CPESet) Union(other *CPESet) *CPESetReturns a new set containing all CPEs from both sets.
Parameters:
other- Another CPE set
Returns:
*CPESet- New set containing union of both sets
Example:
// Create two sets
set1 := cpeskills.NewCPESet("set1", "first set")
set2 := cpeskills.NewCPESet("set2", "second set")
cpe1, _ := cpeskills.ParseCpe23("cpe:2.3:a:microsoft:windows:10:*:*:*:*:*:*:*")
cpe2, _ := cpeskills.ParseCpe23("cpe:2.3:a:apache:tomcat:9.0:*:*:*:*:*:*:*")
cpe3, _ := cpeskills.ParseCpe23("cpe:2.3:a:oracle:java:11:*:*:*:*:*:*:*")
set1.Add(cpe1)
set1.Add(cpe2)
set2.Add(cpe2) // cpe2 is in both sets
set2.Add(cpe3)
// Union operation
unionSet := set1.Union(set2)
fmt.Printf("Set1 size: %d\n", set1.Size())
fmt.Printf("Set2 size: %d\n", set2.Size())
fmt.Printf("Union size: %d\n", unionSet.Size()) // Should be 3 (unique items)Intersection
func (s *CPESet) Intersection(other *CPESet) *CPESetReturns a new set containing only CPEs that exist in both sets.
Parameters:
other- Another CPE set
Returns:
*CPESet- New set containing intersection of both sets
Example:
set1 := cpeskills.NewCPESet("set1", "first set")
set2 := cpeskills.NewCPESet("set2", "second set")
cpe1, _ := cpeskills.ParseCpe23("cpe:2.3:a:microsoft:windows:10:*:*:*:*:*:*:*")
cpe2, _ := cpeskills.ParseCpe23("cpe:2.3:a:apache:tomcat:9.0:*:*:*:*:*:*:*")
cpe3, _ := cpeskills.ParseCpe23("cpe:2.3:a:oracle:java:11:*:*:*:*:*:*:*")
set1.Add(cpe1)
set1.Add(cpe2)
set2.Add(cpe2)
set2.Add(cpe3)
// Intersection operation
intersectionSet := set1.Intersection(set2)
fmt.Printf("Intersection size: %d\n", intersectionSet.Size()) // Should be 1 (cpe2)Difference
func (s *CPESet) Difference(other *CPESet) *CPESetReturns a new set containing CPEs that are in this set but not in the other set.
Parameters:
other- Another CPE set
Returns:
*CPESet- New set containing difference
Example:
set1 := cpeskills.NewCPESet("set1", "first set")
set2 := cpeskills.NewCPESet("set2", "second set")
cpe1, _ := cpeskills.ParseCpe23("cpe:2.3:a:microsoft:windows:10:*:*:*:*:*:*:*")
cpe2, _ := cpeskills.ParseCpe23("cpe:2.3:a:apache:tomcat:9.0:*:*:*:*:*:*:*")
cpe3, _ := cpeskills.ParseCpe23("cpe:2.3:a:oracle:java:11:*:*:*:*:*:*:*")
set1.Add(cpe1)
set1.Add(cpe2)
set2.Add(cpe2)
set2.Add(cpe3)
// Difference operation
diffSet := set1.Difference(set2)
fmt.Printf("Difference size: %d\n", diffSet.Size()) // Should be 1 (cpe1)Set Relations
Equals
func (s *CPESet) Equals(other *CPESet) boolChecks whether two sets contain exactly the same CPEs.
Parameters:
other- Another CPE set
Returns:
bool-trueif both sets contain the same CPEs
IsSubsetOf
func (s *CPESet) IsSubsetOf(other *CPESet) boolChecks whether this set is a subset of other (every CPE in this set is also in other).
Parameters:
other- The candidate superset
Returns:
bool-trueif this set is a subset ofother
IsSupersetOf
func (s *CPESet) IsSupersetOf(other *CPESet) boolChecks whether this set is a superset of other (every CPE in other is also in this set).
Parameters:
other- The candidate subset
Returns:
bool-trueif this set is a superset ofother
Example:
windowsSet := cpeskills.NewCPESet("windows", "all windows")
windows10Set := cpeskills.NewCPESet("windows10", "windows 10 only")
// ... populate sets ...
fmt.Printf("windows10 ⊆ windows: %t\n", windows10Set.IsSubsetOf(windowsSet))
fmt.Printf("windows ⊇ windows10: %t\n", windowsSet.IsSupersetOf(windows10Set))Filtering Operations
Filter
func (s *CPESet) Filter(criteria *CPE, options *MatchOptions) *CPESetReturns a new set containing only the CPEs that match the given criteria CPE. If options is nil, default match options are used.
Parameters:
criteria- CPE object used as the filter criteriaoptions- Match options; ifnil,DefaultMatchOptions()is used
Returns:
*CPESet- New filtered set
Example:
set := cpeskills.NewCPESet("all", "all products")
cpe1, _ := cpeskills.ParseCpe23("cpe:2.3:a:microsoft:windows:10:*:*:*:*:*:*:*")
cpe2, _ := cpeskills.ParseCpe23("cpe:2.3:a:microsoft:office:2019:*:*:*:*:*:*:*")
cpe3, _ := cpeskills.ParseCpe23("cpe:2.3:a:apache:tomcat:9.0:*:*:*:*:*:*:*")
set.Add(cpe1)
set.Add(cpe2)
set.Add(cpe3)
// Filter for Microsoft products
criteria := &cpeskills.CPE{
Vendor: cpeskills.Vendor("microsoft"),
}
microsoftSet := set.Filter(criteria, nil)
fmt.Printf("Microsoft products: %d\n", microsoftSet.Size()) // Should be 2AdvancedFilter
func (s *CPESet) AdvancedFilter(criteria *CPE, options *AdvancedMatchOptions) *CPESetFilters the set using advanced matching criteria such as regex or distance-based matching. If options is nil, NewAdvancedMatchOptions() is used.
Parameters:
criteria- CPE pattern to match againstoptions- Advanced matching options
Returns:
*CPESet- New filtered set
Example:
set := cpeskills.NewCPESet("all", "all products")
// ... populate set ...
// Create advanced matching criteria
criteria := &cpeskills.CPE{
Vendor: cpeskills.Vendor("microsoft"),
}
options := cpeskills.NewAdvancedMatchOptions()
options.MatchMode = "distance"
options.ScoreThreshold = 0.8
// Advanced filter
filteredSet := set.AdvancedFilter(criteria, options)
fmt.Printf("Advanced filtered set size: %d\n", filteredSet.Size())FindRelated
func (s *CPESet) FindRelated(cpe *CPE, options *AdvancedMatchOptions) *CPESetFinds CPEs in the set that are related to the given CPE using loose distance-based matching. If options is nil, default advanced options are used.
Parameters:
cpe- CPE to find related items foroptions- Advanced matching options; ifnil, defaults are used
Returns:
*CPESet- Set of related CPEs
Example:
targetCPE := &cpeskills.CPE{
Vendor: cpeskills.Vendor("microsoft"),
ProductName: cpeskills.Product("windows"),
Version: cpeskills.Version("10"),
}
relatedSet := set.FindRelated(targetCPE, nil)
fmt.Printf("Found %d related CPEs\n", relatedSet.Size())Conversion and Ordering
ToSlice
func (s *CPESet) ToSlice() []*CPEConverts the set to a slice of CPE objects.
Returns:
[]*CPE- Slice containing all CPEs in the set
Sort
func (s *CPESet) Sort(sortBy string, ascending bool) []*CPEReturns the CPEs of the set as a sorted slice. This does not modify the set itself.
Parameters:
sortBy- Sort field:"part","vendor","product","version", or any other value to sort by the CPE 2.3 stringascending-truefor ascending order,falsefor descending
Returns:
[]*CPE- Sorted slice of CPEs
ToString
func (s *CPESet) ToString() stringReturns a string representation of the set, including its name, description, size, and the list of CPEs.
Returns:
string- String representation of the set
Example:
set := cpeskills.NewCPESet("Microsoft", "Microsoft products")
// ... populate set ...
// Convert to slice
cpeSlice := set.ToSlice()
fmt.Printf("Slice length: %d\n", len(cpeSlice))
// Sort by product name, ascending
sorted := set.Sort("product", true)
for i, cpe := range sorted {
fmt.Printf("%d: %s\n", i+1, cpe.Cpe23)
}
// Human-readable representation
fmt.Println(set.ToString())Complete Example
package main
import (
"fmt"
"github.com/scagogogo/cpe-skills"
)
func main() {
// Create CPE objects
cpe1, _ := cpeskills.ParseCpe23("cpe:2.3:a:microsoft:windows:10:*:*:*:*:*:*:*")
cpe2, _ := cpeskills.ParseCpe23("cpe:2.3:a:microsoft:office:2019:*:*:*:*:*:*:*")
cpe3, _ := cpeskills.ParseCpe23("cpe:2.3:a:apache:tomcat:9.0:*:*:*:*:*:*:*")
cpe4, _ := cpeskills.ParseCpe23("cpe:2.3:a:oracle:java:11:*:*:*:*:*:*:*")
// Create sets
fmt.Println("=== Creating Sets ===")
set1 := cpeskills.NewCPESet("Set1", "First set")
set1.Add(cpe1)
set1.Add(cpe2)
set1.Add(cpe3)
set2 := cpeskills.NewCPESet("Set2", "Second set")
set2.Add(cpe3)
set2.Add(cpe4)
fmt.Printf("Set1 size: %d\n", set1.Size())
fmt.Printf("Set2 size: %d\n", set2.Size())
// Set operations
fmt.Println("\n=== Set Operations ===")
unionSet := set1.Union(set2)
intersectionSet := set1.Intersection(set2)
differenceSet := set1.Difference(set2)
fmt.Printf("Union size: %d\n", unionSet.Size())
fmt.Printf("Intersection size: %d\n", intersectionSet.Size())
fmt.Printf("Difference size: %d\n", differenceSet.Size())
// Filtering
fmt.Println("\n=== Filtering ===")
criteria := &cpeskills.CPE{
Vendor: cpeskills.Vendor("microsoft"),
}
microsoftSet := set1.Filter(criteria, nil)
fmt.Printf("Microsoft products: %d\n", microsoftSet.Size())
// Advanced filtering
fmt.Println("\n=== Advanced Filtering ===")
options := cpeskills.NewAdvancedMatchOptions()
options.MatchMode = "exact"
advancedFiltered := set1.AdvancedFilter(criteria, options)
fmt.Printf("Advanced filtered: %d\n", advancedFiltered.Size())
// Convert to slice and sort
fmt.Println("\n=== Conversion ===")
cpeSlice := microsoftSet.ToSlice()
fmt.Printf("Microsoft products (%d):\n", len(cpeSlice))
for i, cpe := range microsoftSet.Sort("product", true) {
fmt.Printf("%d. %s\n", i+1, cpe.Cpe23)
}
// Set membership tests
fmt.Println("\n=== Membership Tests ===")
fmt.Printf("Set1 contains Windows: %t\n", set1.Contains(cpe1))
fmt.Printf("Set1 contains Java: %t\n", set1.Contains(cpe4))
// Create set from array
fmt.Println("\n=== Creating from Array ===")
browsers := []*cpeskills.CPE{cpe1, cpe2}
browserSet := cpeskills.FromArray(browsers, "Browsers", "Browser set")
fmt.Printf("Browser set size: %d\n", browserSet.Size())
}