Skip to main content

hmap.go

hmap.go - Overview

This file implements a HashMap data structure and related functions for use in the DiceDB system. It includes methods for getting, setting, and incrementing values in the HashMap, as well as helper functions for building and retrieving values from the map.

Detailed Documentation

type HashMap map[string]string

type HashMap map[string]string
  • Purpose: Defines a HashMap as a map of string keys to string values.

func (h HashMap) Get(k string) (*string, bool)

func (h HashMap) Get(k string) (*string, bool) {
value, ok := h[k]
if !ok {
return nil, false
}
return &value, true
}
  • Purpose: Retrieves a value from the HashMap by key.
    • Parameters:
      • k: The key to retrieve the value for.
    • Returns:
      • *string: A pointer to the value if the key exists, nil otherwise.
      • bool: True if the key exists, false otherwise.

func (h HashMap) Set(k string, v string) (*string, bool)

func (h HashMap) Set(k, v string) (*string, bool) {
value, ok := h[k]
if ok {
oldValue := value
h[k] = v
return &oldValue, true
}

h[k] = v
return nil, false
}
  • Purpose: Sets a value in the HashMap for a given key.
    • Parameters:
      • k: The key to set the value for.
      • v: The value to set.
    • Returns:
      • *string: A pointer to the old value if the key existed, nil otherwise.
      • bool: True if the key existed, false otherwise.

func hashMapBuilder(keyValuePairs []string, currentHashMap HashMap) (HashMap, int64, error)

func hashMapBuilder(keyValuePairs []string, currentHashMap HashMap) (HashMap, int64, error) {
var hmap HashMap
var numKeysNewlySet int64

if currentHashMap == nil {
hmap = make(HashMap)
} else {
hmap = currentHashMap
}

iter := 0
argLength := len(keyValuePairs)

for iter <= argLength-1 {
if iter >= argLength-1 || iter+1 > argLength-1 {
return hmap, -1, diceerrors.ErrWrongArgumentCount("HSET")
}

k := keyValuePairs[iter]
v := keyValuePairs[iter+1]

_, present := hmap.Set(k, v)
if !present {
numKeysNewlySet++
}
iter += 2
}

return hmap, numKeysNewlySet, nil
}
  • Purpose: Builds a HashMap from a slice of key-value pairs.
    • Parameters:
      • keyValuePairs: A slice of strings representing the key-value pairs.
      • currentHashMap: An existing HashMap to add the key-value pairs to, or nil to create a new HashMap.
    • Returns:
      • HashMap: The resulting HashMap.
      • int64: The number of keys that were newly set.
      • error: An error if the number of key-value pairs is incorrect.

func getValueFromHashMap(key string, field string, store *dstore.Store) *EvalResponse

func getValueFromHashMap(key, field string, store *dstore.Store) *EvalResponse {
obj := store.Get(key)
if obj == nil {
return &EvalResponse{
Result: NIL,
Error: nil,
}
}

hashMap, ok := obj.Value.(HashMap)
if !ok {
return &EvalResponse{
Result: nil,
Error: diceerrors.ErrWrongTypeOperation,
}
}

val, present := hashMap.Get(field)
if !present {
return &EvalResponse{
Result: NIL,
Error: nil,
}
}

return &EvalResponse{
Result: *val,
Error: nil,
}
}
  • Purpose: Retrieves a value from a HashMap stored in the store.
    • Parameters:
      • key: The key of the object in the store.
      • field: The key within the HashMap.
      • store: The data store.
    • Returns: An EvalResponse containing the result or an error if the key or field is not found or if the object is not a HashMap.

func (h HashMap) incrementValue(field string, increment int64) (int64, error)

func (h HashMap) incrementValue(field string, increment int64) (int64, error) {
val, ok := h[field]
if !ok {
h[field] = fmt.Sprintf("%v", increment)
return increment, nil
}

i, err := strconv.ParseInt(val, 10, 64)
if err != nil {
return -1, diceerrors.NewErr(diceerrors.HashValueNotIntegerErr)
}

if (i > 0 && increment > 0 && i > math.MaxInt64-increment) || (i < 0 && increment < 0 && i < math.MinInt64-increment) {
return -1, diceerrors.NewErr(diceerrors.IncrDecrOverflowErr)
}

total := i + increment
h[field] = fmt.Sprintf("%v", total)

return total, nil
}
  • Purpose: Increments a value in the HashMap by a given integer.
    • Parameters:
      • field: The field (key) to increment.
      • increment: The amount to increment by.
    • Returns:
      • int64: The new value after incrementing.
      • error: An error if the value is not an integer or if an overflow occurs.

func (h HashMap) incrementFloatValue(field string, incr float64) (string, error)

func (h HashMap) incrementFloatValue(field string, incr float64) (string, error) {
val, ok := h[field]
if !ok {
h[field] = fmt.Sprintf("%v", incr)
strValue := formatFloat(incr, false)
return strValue, nil
}

i, err := strconv.ParseFloat(val, 64)
if err != nil {
return "-1", diceerrors.NewErr(diceerrors.IntOrFloatErr)
}

if math.IsInf(i+incr, 1) || math.IsInf(i+incr, -1) {
return "-1", diceerrors.NewErr(diceerrors.IncrDecrOverflowErr)
}

total := i + incr
strValue := formatFloat(total, false)
h[field] = fmt.Sprintf("%v", total)

return strValue, nil
}
  • Purpose: Increments a value in the HashMap by a given float.
    • Parameters:
      • field: The field (key) to increment.
      • incr: The amount to increment by.
    • Returns:
      • string: The new value after incrementing, formatted as a string.
      • error: An error if the value is not a float or if an overflow occurs.

func selectRandomFields(hashMap HashMap, count int, withValues bool) *EvalResponse

func selectRandomFields(hashMap HashMap, count int, withValues bool) *EvalResponse {
keys := make([]string, 0, len(hashMap))
for k := range hashMap {
keys = append(keys, k)
}

var results []string
resultSet := make(map[string]struct{})

abs := func(x int) int {
if x < 0 {
return -x
}
return x
}

for i := 0; i < abs(count); i++ {
if count > 0 && len(resultSet) == len(keys) {
break
}

randomIndex, _ := rand.Int(rand.Reader, big.NewInt(int64(len(keys))))
randomField := keys[randomIndex.Int64()]

if count > 0 {
if _, exists := resultSet[randomField]; exists {
i--
continue
}
resultSet[randomField] = struct{}{}
}

results = append(results, randomField)
if withValues {
results = append(results, hashMap[randomField])
}
}

return &EvalResponse{
Result: results,
Error: nil,
}
}
  • Purpose: Selects random fields from a hash map.
    • Parameters:
      • hashMap: The hash map to select from.
      • count: The number of random fields to select. If positive, selects distinct fields. If negative, allows duplicates.
      • withValues: Whether to include the values of the selected fields in the result.
    • Returns:
      • *EvalResponse: An EvalResponse containing the list of random fields (and their values if withValues is true).

Getting Started Relevance: NO