You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

set.go 3.2KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144
  1. // Copyright (c) 2017 Daniel Oaks <daniel@danieloaks.net>
  2. // released under the MIT license
  3. package caps
  4. import (
  5. "bytes"
  6. "sort"
  7. "github.com/oragono/oragono/irc/utils"
  8. )
  9. // Set holds a set of enabled capabilities.
  10. type Set [bitsetLen]uint32
  11. // Values holds capability values.
  12. type Values map[Capability]string
  13. // NewSet returns a new Set, with the given capabilities enabled.
  14. func NewSet(capabs ...Capability) *Set {
  15. var newSet Set
  16. newSet.Enable(capabs...)
  17. return &newSet
  18. }
  19. // NewCompleteSet returns a new Set, with all defined capabilities enabled.
  20. func NewCompleteSet() *Set {
  21. var newSet Set
  22. asSlice := newSet[:]
  23. for i := 0; i < numCapabs; i += 1 {
  24. utils.BitsetSet(asSlice, uint(i), true)
  25. }
  26. return &newSet
  27. }
  28. // Enable enables the given capabilities.
  29. func (s *Set) Enable(capabs ...Capability) {
  30. asSlice := s[:]
  31. for _, capab := range capabs {
  32. utils.BitsetSet(asSlice, uint(capab), true)
  33. }
  34. }
  35. // Disable disables the given capabilities.
  36. func (s *Set) Disable(capabs ...Capability) {
  37. asSlice := s[:]
  38. for _, capab := range capabs {
  39. utils.BitsetSet(asSlice, uint(capab), false)
  40. }
  41. }
  42. // Add adds the given capabilities to this set.
  43. // this is just a wrapper to allow more clear use.
  44. func (s *Set) Add(capabs ...Capability) {
  45. s.Enable(capabs...)
  46. }
  47. // Remove removes the given capabilities from this set.
  48. // this is just a wrapper to allow more clear use.
  49. func (s *Set) Remove(capabs ...Capability) {
  50. s.Disable(capabs...)
  51. }
  52. // Has returns true if this set has the given capability.
  53. func (s *Set) Has(capab Capability) bool {
  54. return utils.BitsetGet(s[:], uint(capab))
  55. }
  56. // HasAll returns true if the set has all the given capabilities.
  57. func (s *Set) HasAll(capabs ...Capability) bool {
  58. for _, capab := range capabs {
  59. if !s.Has(capab) {
  60. return false
  61. }
  62. }
  63. return true
  64. }
  65. // Union adds all the capabilities of another set to this set.
  66. func (s *Set) Union(other *Set) {
  67. utils.BitsetUnion(s[:], other[:])
  68. }
  69. // Subtract removes all the capabilities of another set from this set.
  70. func (s *Set) Subtract(other *Set) {
  71. utils.BitsetSubtract(s[:], other[:])
  72. }
  73. // Empty returns whether the set is empty.
  74. func (s *Set) Empty() bool {
  75. return utils.BitsetEmpty(s[:])
  76. }
  77. const maxPayloadLength = 440
  78. // Strings returns all of our enabled capabilities as a slice of strings.
  79. func (s *Set) Strings(version Version, values Values) (result []string) {
  80. var strs sort.StringSlice
  81. var capab Capability
  82. asSlice := s[:]
  83. for capab = 0; capab < numCapabs; capab++ {
  84. // skip any capabilities that are not enabled
  85. if !utils.BitsetGet(asSlice, uint(capab)) {
  86. continue
  87. }
  88. capString := capab.Name()
  89. if version >= Cap302 {
  90. val, exists := values[capab]
  91. if exists {
  92. capString += "=" + val
  93. }
  94. }
  95. strs = append(strs, capString)
  96. }
  97. if len(strs) == 0 {
  98. return []string{""}
  99. }
  100. // sort the cap string before we send it out
  101. sort.Sort(strs)
  102. var buf bytes.Buffer
  103. for _, str := range strs {
  104. tokenLen := len(str)
  105. if buf.Len() != 0 {
  106. tokenLen += 1
  107. }
  108. if maxPayloadLength < buf.Len()+tokenLen {
  109. result = append(result, buf.String())
  110. buf.Reset()
  111. }
  112. if buf.Len() != 0 {
  113. buf.WriteByte(' ')
  114. }
  115. buf.WriteString(str)
  116. }
  117. if buf.Len() != 0 {
  118. result = append(result, buf.String())
  119. }
  120. return
  121. }