hashutils.go 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185
  1. package glisp
  2. import (
  3. "errors"
  4. "fmt"
  5. "hash/fnv"
  6. )
  7. func HashExpression(expr Sexp) (int, error) {
  8. switch e := expr.(type) {
  9. case SexpInt:
  10. return int(e), nil
  11. case SexpChar:
  12. return int(e), nil
  13. case SexpSymbol:
  14. return e.number, nil
  15. case SexpStr:
  16. hasher := fnv.New32()
  17. _, err := hasher.Write([]byte(e))
  18. if err != nil {
  19. return 0, err
  20. }
  21. return int(hasher.Sum32()), nil
  22. }
  23. return 0, errors.New(fmt.Sprintf("cannot hash type %T", expr))
  24. }
  25. func MakeHash(args []Sexp, typename string) (SexpHash, error) {
  26. if len(args)%2 != 0 {
  27. return SexpHash{},
  28. errors.New("hash requires even number of arguments")
  29. }
  30. var iface interface{}
  31. var memberCount int
  32. hash := SexpHash{
  33. TypeName: &typename,
  34. Map: make(map[int][]SexpPair),
  35. KeyOrder: &[]Sexp{},
  36. GoStruct: &iface,
  37. NumKeys: &memberCount,
  38. }
  39. k := 0
  40. for i := 0; i < len(args); i += 2 {
  41. key := args[i]
  42. val := args[i+1]
  43. err := hash.HashSet(key, val)
  44. if err != nil {
  45. return hash, err
  46. }
  47. k++
  48. }
  49. return hash, nil
  50. }
  51. func (hash *SexpHash) HashGet(key Sexp) (Sexp, error) {
  52. // this is kind of a hack
  53. // SexpEnd can't be created by user
  54. // so there is no way it would actually show up in the map
  55. val, err := hash.HashGetDefault(key, SexpEnd)
  56. if err != nil {
  57. return SexpNull, err
  58. }
  59. if val == SexpEnd {
  60. msg := fmt.Sprintf("key %s not found", key.SexpString())
  61. return SexpNull, errors.New(msg)
  62. }
  63. return val, nil
  64. }
  65. func (hash *SexpHash) HashGetDefault(key Sexp, defaultval Sexp) (Sexp, error) {
  66. hashval, err := HashExpression(key)
  67. if err != nil {
  68. return SexpNull, err
  69. }
  70. arr, ok := hash.Map[hashval]
  71. if !ok {
  72. return defaultval, nil
  73. }
  74. for _, pair := range arr {
  75. res, err := Compare(pair.head, key)
  76. if err == nil && res == 0 {
  77. return pair.tail, nil
  78. }
  79. }
  80. return defaultval, nil
  81. }
  82. func (hash *SexpHash) HashSet(key Sexp, val Sexp) error {
  83. hashval, err := HashExpression(key)
  84. if err != nil {
  85. return err
  86. }
  87. arr, ok := hash.Map[hashval]
  88. if !ok {
  89. hash.Map[hashval] = []SexpPair{Cons(key, val)}
  90. *hash.KeyOrder = append(*hash.KeyOrder, key)
  91. (*hash.NumKeys)++
  92. return nil
  93. }
  94. found := false
  95. for i, pair := range arr {
  96. res, err := Compare(pair.head, key)
  97. if err == nil && res == 0 {
  98. arr[i] = Cons(key, val)
  99. found = true
  100. }
  101. }
  102. if !found {
  103. arr = append(arr, Cons(key, val))
  104. *hash.KeyOrder = append(*hash.KeyOrder, key)
  105. (*hash.NumKeys)++
  106. }
  107. hash.Map[hashval] = arr
  108. return nil
  109. }
  110. func (hash *SexpHash) HashDelete(key Sexp) error {
  111. hashval, err := HashExpression(key)
  112. if err != nil {
  113. return err
  114. }
  115. arr, ok := hash.Map[hashval]
  116. // if it doesn't exist, no need to delete it
  117. if !ok {
  118. return nil
  119. }
  120. (*hash.NumKeys)--
  121. for i, pair := range arr {
  122. res, err := Compare(pair.head, key)
  123. if err == nil && res == 0 {
  124. hash.Map[hashval] = append(arr[0:i], arr[i+1:]...)
  125. break
  126. }
  127. }
  128. return nil
  129. }
  130. func HashCountKeys(hash SexpHash) int {
  131. var num int
  132. for _, arr := range hash.Map {
  133. num += len(arr)
  134. }
  135. if num != (*hash.NumKeys) {
  136. panic(fmt.Errorf("HashCountKeys disagreement on count: num=%d, (*hash.NumKeys)=%d", num, (*hash.NumKeys)))
  137. }
  138. return num
  139. }
  140. func HashIsEmpty(hash SexpHash) bool {
  141. for _, arr := range hash.Map {
  142. if len(arr) > 0 {
  143. return false
  144. }
  145. }
  146. return true
  147. }
  148. func SetHashKeyOrder(hash *SexpHash, keyOrd Sexp) error {
  149. // truncate down to zero, then build back up correctly.
  150. *(*hash).KeyOrder = (*(*hash).KeyOrder)[:0]
  151. keys, isArr := keyOrd.(SexpArray)
  152. if !isArr {
  153. return fmt.Errorf("must have SexpArray for keyOrd, but instead we have: %T with value='%#v'", keyOrd, keyOrd)
  154. }
  155. for _, key := range keys {
  156. *hash.KeyOrder = append(*hash.KeyOrder, key)
  157. }
  158. return nil
  159. }