github.com/intel/goresctrl@v0.5.0/pkg/utils/idset.go (about)

     1  /*
     2  Copyright 2019-2021 Intel Corporation
     3  
     4  Licensed under the Apache License, Version 2.0 (the "License");
     5  you may not use this file except in compliance with the License.
     6  You may obtain a copy of the License at
     7  
     8      http://www.apache.org/licenses/LICENSE-2.0
     9  
    10  Unless required by applicable law or agreed to in writing, software
    11  distributed under the License is distributed on an "AS IS" BASIS,
    12  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13  See the License for the specific language governing permissions and
    14  limitations under the License.
    15  */
    16  
    17  package utils
    18  
    19  import (
    20  	"encoding/json"
    21  	"fmt"
    22  	"sort"
    23  	"strconv"
    24  	"strings"
    25  )
    26  
    27  const (
    28  	// Unknown represents an unknown id.
    29  	Unknown ID = -1
    30  )
    31  
    32  // ID is nn integer id, used to identify packages, CPUs, nodes, etc.
    33  type ID = int
    34  
    35  // IDSet is an unordered set of integer ids.
    36  type IDSet map[ID]struct{}
    37  
    38  // NewIDSet creates a new unordered set of (integer) ids.
    39  func NewIDSet(ids ...ID) IDSet {
    40  	s := make(map[ID]struct{})
    41  
    42  	for _, id := range ids {
    43  		s[id] = struct{}{}
    44  	}
    45  
    46  	return s
    47  }
    48  
    49  // NewIDSetFromIntSlice creates a new unordered set from an integer slice.
    50  func NewIDSetFromIntSlice(ids ...int) IDSet {
    51  	s := make(map[ID]struct{})
    52  
    53  	for _, id := range ids {
    54  		s[ID(id)] = struct{}{}
    55  	}
    56  
    57  	return s
    58  }
    59  
    60  // Clone returns a copy of this IdSet.
    61  func (s IDSet) Clone() IDSet {
    62  	return NewIDSet(s.Members()...)
    63  }
    64  
    65  // Add adds the given ids into the set.
    66  func (s IDSet) Add(ids ...ID) {
    67  	for _, id := range ids {
    68  		s[id] = struct{}{}
    69  	}
    70  }
    71  
    72  // Del deletes the given ids from the set.
    73  func (s IDSet) Del(ids ...ID) {
    74  	if s != nil {
    75  		for _, id := range ids {
    76  			delete(s, id)
    77  		}
    78  	}
    79  }
    80  
    81  // Size returns the number of ids in the set.
    82  func (s IDSet) Size() int {
    83  	return len(s)
    84  }
    85  
    86  // Has tests if all the ids are present in the set.
    87  func (s IDSet) Has(ids ...ID) bool {
    88  	if s == nil {
    89  		return false
    90  	}
    91  
    92  	for _, id := range ids {
    93  		_, ok := s[id]
    94  		if !ok {
    95  			return false
    96  		}
    97  	}
    98  
    99  	return true
   100  }
   101  
   102  // Members returns all ids in the set as a randomly ordered slice.
   103  func (s IDSet) Members() []ID {
   104  	if s == nil {
   105  		return []ID{}
   106  	}
   107  	ids := make([]ID, len(s))
   108  	idx := 0
   109  	for id := range s {
   110  		ids[idx] = id
   111  		idx++
   112  	}
   113  	return ids
   114  }
   115  
   116  // SortedMembers returns all ids in the set as a sorted slice.
   117  func (s IDSet) SortedMembers() []ID {
   118  	ids := s.Members()
   119  	sort.Slice(ids, func(i, j int) bool {
   120  		return ids[i] < ids[j]
   121  	})
   122  	return ids
   123  }
   124  
   125  // String returns the set as a string.
   126  func (s IDSet) String() string {
   127  	return s.StringWithSeparator(",")
   128  }
   129  
   130  // StringWithSeparator returns the set as a string, separated with the given separator.
   131  func (s IDSet) StringWithSeparator(args ...string) string {
   132  	if len(s) == 0 {
   133  		return ""
   134  	}
   135  
   136  	var sep string
   137  
   138  	if len(args) == 1 {
   139  		sep = args[0]
   140  	} else {
   141  		sep = ","
   142  	}
   143  
   144  	str := ""
   145  	t := ""
   146  	for _, id := range s.SortedMembers() {
   147  		str = str + t + strconv.Itoa(int(id))
   148  		t = sep
   149  	}
   150  
   151  	return str
   152  }
   153  
   154  // MarshalJSON is the JSON marshaller for IDSet.
   155  func (s IDSet) MarshalJSON() ([]byte, error) {
   156  	return json.Marshal(s.String())
   157  }
   158  
   159  // UnmarshalJSON is the JSON unmarshaller for IDSet.
   160  func (s *IDSet) UnmarshalJSON(data []byte) error {
   161  	str := ""
   162  	if err := json.Unmarshal(data, &str); err != nil {
   163  		return fmt.Errorf("invalid IDSet entry '%s': %v", string(data), err)
   164  	}
   165  
   166  	*s = NewIDSet()
   167  	if str == "" {
   168  		return nil
   169  	}
   170  
   171  	for _, idstr := range strings.Split(str, ",") {
   172  		id, err := strconv.ParseUint(idstr, 10, 0)
   173  		if err != nil {
   174  			return fmt.Errorf("invalid IDSet entry '%s': %v", idstr, err)
   175  		}
   176  		s.Add(ID(id))
   177  	}
   178  
   179  	return nil
   180  }