简介
setrange命令主要用于设置value的部分子串,设置时将值从偏移量offset开始覆盖成value值。如果偏移值大于原值的长度,则偏移量之前的字符串由“\x00”填充。
命令格式:
setrange key offset value
setrange 命令
由于要指定值的偏移量,所以setrange在执行时会首先判断offset参数必须为long类型且必须大于等于0,否则设置失败。
与append命令一样,原key在Redis中不存在时,Redis会创建一个robj对象,并将robj先设置到数据库;当key在Redis中存在时,会要求原值必须为string类型,并且由于Redis的限制,value的长度加offset值必须小于512 MB。
if (checkStringLength(c,offset+sdslen(value)) != C_OK)
return;
setrange命令会修改原value值,如果原值是共享类型的,则需解除共享,新创建一个新robj对象,对新对象进行操作。代码实现:
/* Create a copy when the object is shared or encoded. */
o = dbUnshareStringValue(c->db,c->argv[1],o);
考虑到当value的长度加offset会大于原值长度时,需要额外分配空间用于存储新值并返回。此时调用了sdsgrowzero函数。sdsgrowzero函数会进行识别,只有当offset+sdslen(value)大于原值长度时才会扩充空间,否则直接返回原字符串。
o->ptr = sdsgrowzero(o->ptr,offset+sdslen(value));
memcpy((char*)o->ptr+offset,value,sdslen(value));
当有了robj的地址之后,从offset位置开始将value覆盖掉原值,通过memcpy函数来实现。
通过以上步骤,实现了字符串的setrange操作。