redis源码之动态字符串(sds.h和sds.c)(篇三)

简介

redis 源码版本:3.05.04

如有理解不对的地方,欢迎各位指出,大家共同交流和学习。

源码学习

sdstrim函数

移除字符串

/*
从s中移除所有cset中出现的字符
*/
sds sdstrim(sds s, const char *cset) {
  struct sdshdr *sh = (void*) (s-(sizeof(struct sdshdr)));
  char *start, *end, *sp, *ep;
  size_t len;
  sp = start = s;                 //s是指向sh的buf成员的地址,字符串中的起始地址
  ep = end = s+sdslen(s)-1;      //end指向字符串的结尾,不是结束符‘\0’ 
  while(sp <= end && strchr(cset, *sp)) sp++;  //strchr()函数在字符串中搜索第一次出现某个字符的位置
  while(ep > start && strchr(cset, *ep)) ep--;
  len = (sp > ep) ? 0 : ((ep-sp)+1);           //计算移除后字符串的长度
  if (sh->buf != sp) memmove(sh->buf, sp, len);//移动元素到buf头部
  sh->buf[len] = '\0';
  sh->free = sh->free+(int)(sh->len-len);     //更新剩余空间
  sh->len = (int)len;                         //更新使用空间
  return s;
}

第5、6行代码的start和end含义如下:
在这里插入图片描述
start指向字符串的开头
end指向字符串的结尾,不是结束符‘\0’
假如,用该函数移除"HeAlBIoB"中的字符A和B时,函数调用如下形式:

sdstrim("HeAlBIoB","AB")   //结果:Hello

该函数操作原理如下:
在这里插入图片描述
从上图可以看出,该函数并没有将A和B移除后的空间回收掉,而是采用更新free值,来记录未使用空间,等待以后使用,从而避免内存的频繁分配。

sdsrange函数

截取指定范围的字符

/*
保留s中从start开始到end结束的字符
*/
void sdsrange(sds s, int start, int end) {
    struct sdshdr *sh = (void*) (s-(sizeof(struct sdshdr)));//获取首地址
    size_t newlen, len = sdslen(s);

    if (len == 0) return;      //如果字符串长度为0,直接返回
    if (start < 0) {     		//为负值,从后开始计算
        start = (int)len+start;                                               
        if (start < 0) start = 0;
    }
    if (end < 0) {				//end为负值时处理
        end = (int)len+end;                                                   
        if (end < 0) end = 0;
    }
    newlen = (start > end) ? 0 : (end-start)+1;//计算新的字符长度
    if (newlen != 0) {
        if (start >= (signed)len) {
            newlen = 0;
        } else if (end >= (signed)len) {
            end = (int)len-1;                                                 
            newlen = (start > end) ? 0 : (end-start)+1;
        }
    } else {
        start = 0;
    }
    if (start && newlen) memmove(sh->buf, sh->buf+start, newlen);//从buf+start位置复制newlen个字符到buf中
    //更新属性值
    sh->buf[newlen] = 0;    //等价'\0'
    sh->free = (int)(sh->free+(sh->len-newlen));                               
    sh->len = (int)newlen;                                                   
}

字符串下标从0开始,当start为正n时,表示第n+1个字符,当start为负n时,表示倒数第n个字符。

sdscmp函数

比较两个sds字符串是否相同

/*
返回值:小于0:s1小于s2
       等于0:相等
       大于0:s1大于s2
*/
int sdscmp(const sds s1, const sds s2) {
    size_t l1, l2, minlen;
    int cmp;

    l1 = sdslen(s1);  				   //计算s1字符串已使用空间长度
    l2 = sdslen(s2);  				   //计算s2字符串已使用空间长度
    minlen = (l1 < l2) ? l1 : l2;      //取长度最小的字符
    cmp = memcmp(s1,s2,minlen);        //比较s1和s2的前minlen个字符   memcmp()为c语言函数
    if (cmp == 0) return (int)(l1-l2);                                        
    return cmp;
}

sdstolower 函数

将字符串全部转为小写

void sdstolower(sds s) {
    int len = (int)sdslen(s), j;      //len为字符长度                                          
    for (j = 0; j < len; j++) s[j] = tolower(s[j]);//遍历字符进行转换
}

sdstoupper 函数

将字符串全部转为大写

void sdstoupper(sds s) {
    int len = (int)sdslen(s), j;                                                
    for (j = 0; j < len; j++) s[j] = toupper(s[j]);
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值