forked from joey/godottest
216 lines
6.3 KiB
GDScript
216 lines
6.3 KiB
GDScript
extends RefCounted
|
|
class_name GedisSets
|
|
|
|
var _gedis: Gedis
|
|
|
|
func _init(gedis: Gedis):
|
|
_gedis = gedis
|
|
|
|
# ----
|
|
# Sets
|
|
# ----
|
|
func sadd(key: String, member) -> int:
|
|
_gedis._core._touch_type(key, _gedis._core._sets)
|
|
var s: Dictionary = _gedis._core._sets.get(key, {})
|
|
var existed := int(s.has(member))
|
|
s[member] = true
|
|
_gedis._core._sets[key] = s
|
|
_gedis.publish("gedis:keyspace:" + key, "set")
|
|
return 1 - existed
|
|
|
|
func srem(key: String, member) -> int:
|
|
if _gedis._expiry._is_expired(key):
|
|
return 0
|
|
if not _gedis._core._sets.has(key):
|
|
return 0
|
|
var s: Dictionary = _gedis._core._sets[key]
|
|
var existed := int(s.has(member))
|
|
s.erase(member)
|
|
if s.is_empty():
|
|
_gedis._core._sets.erase(key)
|
|
_gedis.publish("gedis:keyspace:" + key, "del")
|
|
else:
|
|
_gedis._core._sets[key] = s
|
|
return existed
|
|
|
|
func smembers(key: String) -> Array:
|
|
if _gedis._expiry._is_expired(key):
|
|
return []
|
|
var s: Dictionary = _gedis._core._sets.get(key, {})
|
|
return s.keys()
|
|
|
|
func sismember(key: String, member) -> bool:
|
|
if _gedis._expiry._is_expired(key):
|
|
return false
|
|
var s: Dictionary = _gedis._core._sets.get(key, {})
|
|
return s.has(member)
|
|
|
|
func scard(key: String) -> int:
|
|
if _gedis._expiry._is_expired(key):
|
|
return 0
|
|
return _gedis._core._sets.get(key, {}).size()
|
|
|
|
func sexists(key: String) -> bool:
|
|
if _gedis._expiry._is_expired(key):
|
|
return false
|
|
return _gedis._core._sets.has(key)
|
|
|
|
func spop(key: String):
|
|
if _gedis._expiry._is_expired(key):
|
|
return null
|
|
if not _gedis._core._sets.has(key):
|
|
return null
|
|
var s: Dictionary = _gedis._core._sets[key]
|
|
var keys_arr: Array = s.keys()
|
|
if keys_arr.is_empty():
|
|
return null
|
|
var idx = randi() % keys_arr.size()
|
|
var member = keys_arr[idx]
|
|
s.erase(member)
|
|
if s.is_empty():
|
|
_gedis._core._sets.erase(key)
|
|
_gedis.publish("gedis:keyspace:" + key, "del")
|
|
else:
|
|
_gedis._core._sets[key] = s
|
|
return member
|
|
|
|
func smove(source: String, destination: String, member) -> bool:
|
|
if _gedis._expiry._is_expired(source):
|
|
return false
|
|
if not sismember(source, member):
|
|
return false
|
|
# remove from source
|
|
srem(source, member)
|
|
# add to destination (creates destination set)
|
|
sadd(destination, member)
|
|
return true
|
|
|
|
# Computes the union of multiple sets.
|
|
# ---
|
|
# @param keys: An array of set keys.
|
|
# @return: An array containing the members of the resulting union set.
|
|
func sunion(keys: Array) -> Array:
|
|
var result_set := {}
|
|
for key in keys:
|
|
var members = smembers(key)
|
|
for member in members:
|
|
result_set[member] = true
|
|
return result_set.keys()
|
|
|
|
# Computes the intersection of multiple sets.
|
|
# ---
|
|
# @param keys: An array of set keys.
|
|
# @return: An array containing the members of the resulting intersection set.
|
|
func sinter(keys: Array) -> Array:
|
|
if keys.is_empty():
|
|
return []
|
|
|
|
var result_set := {}
|
|
var first_set_members = smembers(keys[0])
|
|
for member in first_set_members:
|
|
result_set[member] = true
|
|
|
|
for i in range(1, keys.size()):
|
|
var next_set_members = smembers(keys[i])
|
|
var current_members = result_set.keys()
|
|
for member in current_members:
|
|
if not next_set_members.has(member):
|
|
result_set.erase(member)
|
|
|
|
return result_set.keys()
|
|
|
|
# Computes the difference between multiple sets.
|
|
# The difference is calculated as the members of the first set minus the members of all subsequent sets.
|
|
# ---
|
|
# @param keys: An array of set keys. The first key is the set to subtract from.
|
|
# @return: An array containing the members of the resulting difference set.
|
|
func sdiff(keys: Array) -> Array:
|
|
if keys.is_empty():
|
|
return []
|
|
|
|
var result_set := {}
|
|
var first_set_members = smembers(keys[0])
|
|
for member in first_set_members:
|
|
result_set[member] = true
|
|
|
|
for i in range(1, keys.size()):
|
|
var next_set_members = smembers(keys[i])
|
|
for member in next_set_members:
|
|
if result_set.has(member):
|
|
result_set.erase(member)
|
|
|
|
return result_set.keys()
|
|
|
|
# Computes the union of multiple sets and stores the result in a new set.
|
|
# ---
|
|
# @param destination: The key to store the resulting union set in.
|
|
# @param keys: An array of set keys.
|
|
# @return: The number of members in the resulting union set.
|
|
func sunionstore(destination: String, keys: Array) -> int:
|
|
var result_members = sunion(keys)
|
|
_gedis._core._sets.erase(destination)
|
|
for member in result_members:
|
|
sadd(destination, member)
|
|
return result_members.size()
|
|
|
|
# Computes the intersection of multiple sets and stores the result in a new set.
|
|
# ---
|
|
# @param destination: The key to store the resulting intersection set in.
|
|
# @param keys: An array of set keys.
|
|
# @return: The number of members in the resulting intersection set.
|
|
func sinterstore(destination: String, keys: Array) -> int:
|
|
var result_members = sinter(keys)
|
|
_gedis._core._sets.erase(destination)
|
|
for member in result_members:
|
|
sadd(destination, member)
|
|
return result_members.size()
|
|
|
|
# Computes the difference between multiple sets and stores the result in a new set.
|
|
# ---
|
|
# @param destination: The key to store the resulting difference set in.
|
|
# @param keys: An array of set keys. The first key is the set to subtract from.
|
|
# @return: The number of members in the resulting difference set.
|
|
func sdiffstore(destination: String, keys: Array) -> int:
|
|
var result_members = sdiff(keys)
|
|
_gedis._core._sets.erase(destination)
|
|
for member in result_members:
|
|
sadd(destination, member)
|
|
return result_members.size()
|
|
|
|
# Gets one or more random members from a set.
|
|
# ---
|
|
# @param key: The key of the set.
|
|
# @param count: The number of random members to return. If positive, returns unique members. If negative, allows for repetitions.
|
|
# @return: A single random member if count is 1, or an array of random members. Returns null or an empty array if the set is empty.
|
|
func srandmember(key: String, count: int = 1):
|
|
if _gedis._expiry._is_expired(key):
|
|
return null if count == 1 else []
|
|
|
|
var s: Dictionary = _gedis._core._sets.get(key, {})
|
|
var members = s.keys()
|
|
if members.is_empty():
|
|
return null if count == 1 else []
|
|
|
|
if count == 1:
|
|
return members.pick_random()
|
|
|
|
var result = []
|
|
if count > 0:
|
|
# Positive count: return unique elements
|
|
if count >= members.size():
|
|
members.shuffle()
|
|
return members
|
|
|
|
var used_indices = {}
|
|
while result.size() < count:
|
|
var idx = randi() % members.size()
|
|
if not used_indices.has(idx):
|
|
result.append(members[idx])
|
|
used_indices[idx] = true
|
|
else: # count < 0
|
|
# Negative count: repetitions are allowed
|
|
var abs_count = abs(count)
|
|
for _i in range(abs_count):
|
|
result.append(members.pick_random())
|
|
|
|
return result |