redis中 ll2string() 和 string2ll() 的实现

Posted AlphaABCD

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了redis中 ll2string() 和 string2ll() 的实现相关的知识,希望对你有一定的参考价值。

/* Convert a long long into a string. Returns the number of
 * characters needed to represent the number.
 * If the buffer is not big enough to store the string, 0 is returned.
 *
 * Based on the following article (that apparently does not provide a
 * novel approach but only publicizes an already used technique):
 *
 * https://www.facebook.com/notes/facebook-engineering/three-optimization-tips-for-c/10151361643253920
 *
 * Modified in order to handle signed integers since the original code was
 * designed for unsigned integers. */
// long long类型转C字符串,成功返回转换后字符串长度,失败返回0
// 修改以支持有符号整数,因为原始代码是为无符号整数设计的
int ll2string(char *dst, size_t dstlen, long long svalue) 
    static const char digits[201] =
        "0001020304050607080910111213141516171819"
        "2021222324252627282930313233343536373839"
        "4041424344454647484950515253545556575859"
        "6061626364656667686970717273747576777879"
        "8081828384858687888990919293949596979899";
    int negative;
    unsigned long long value;

    /* The main loop works with 64bit unsigned integers for simplicity, so
     * we convert the number here and remember if it is negative. */
	// 为了简单起见,主循环使用64位无符号整数,因此在这里转换数字,并记住是否为负数
    if (svalue < 0) 
        if (svalue != LLONG_MIN) 
            value = -svalue;
         else 
            value = ((unsigned long long) LLONG_MAX)+1;
        
        negative = 1;
     else 
        value = svalue;
        negative = 0;
    

    /* Check length. */
	// 确认预分配空间长度是否足够
    uint32_t const length = digits10(value)+negative;
    if (length >= dstlen) return 0;

    /* Null term. */
    uint32_t next = length;
    dst[next] = '\\0';
    next--;
    while (value >= 100) 
        int const i = (value % 100) * 2;
        value /= 100;
        dst[next] = digits[i + 1];
        dst[next - 1] = digits[i];
        next -= 2;
    

    /* Handle last 1-2 digits. */
    if (value < 10) 
        dst[next] = '0' + (uint32_t) value;
     else 
        int i = (uint32_t) value * 2;
        dst[next] = digits[i + 1];
        dst[next - 1] = digits[i];
    

    /* Add sign. */
    if (negative) dst[0] = '-';
    return length;

/* Convert a string into a long long. Returns 1 if the string could be parsed
 * into a (non-overflowing) long long, 0 otherwise. The value will be set to
 * the parsed value when appropriate.
 *
 * Note that this function demands that the string strictly represents
 * a long long: no spaces or other characters before or after the string
 * representing the number are accepted, nor zeroes at the start if not
 * for the string "0" representing the zero number.
 *
 * Because of its strictness, it is safe to use this function to check if
 * you can convert a string into a long long, and obtain back the string
 * from the number without any loss in the string representation. */
// C字符串转long long 类型,成功返回1
int string2ll(const char *s, size_t slen, long long *value) 
    const char *p = s;
    size_t plen = 0;
    int negative = 0;
    unsigned long long v;

    /* A zero length string is not a valid number. */
	// ERR: 入参字符串为空
    if (plen == slen)
        return 0;

    /* Special case: first and only digit is 0. */
	// 开头为0,且只有1个字符
    if (slen == 1 && p[0] == '0') 
        if (value != NULL) *value = 0;
        return 1;
    

    /* Handle negative numbers: just set a flag and continue like if it
     * was a positive number. Later convert into negative. */
	// 判断是否为负数
    if (p[0] == '-') 
        negative = 1;
        p++; plen++;

        /* Abort on only a negative sign. */
		// ERR: 只有1个负号
        if (plen == slen)
            return 0;
    

    /* First digit should be 1-9, otherwise the string should just be 0. */
	// 最高位应该为 1~9
    if (p[0] >= '1' && p[0] <= '9') 
        v = p[0]-'0';
        p++; plen++;
     else 
        return 0;
    

    /* Parse all the other digits, checking for overflow at every step. */
	// 剩余位数应该为 0~9
    while (plen < slen && p[0] >= '0' && p[0] <= '9') 
        if (v > (ULLONG_MAX / 10)) // 溢出 /* Overflow. */
            return 0;
        v *= 10;

        if (v > (ULLONG_MAX - (p[0]-'0'))) // 溢出 /* Overflow. */
            return 0;
        v += p[0]-'0';

        p++; plen++;
    

    /* Return if not all bytes were used. */
	// ERR: 有字符不是数字
    if (plen < slen)
        return 0;

    /* Convert to negative if needed, and do the final overflow check when
     * converting from unsigned long long to long long. */
	// 符号处理,并判断是否溢出
    if (negative) 
        if (v > ((unsigned long long)(-(LLONG_MIN+1))+1)) /* Overflow. */
            return 0;
        if (value != NULL) *value = -v;
     else 
        if (v > LLONG_MAX) /* Overflow. */
            return 0;
        if (value != NULL) *value = v;
    
    return 1;


以上是关于redis中 ll2string() 和 string2ll() 的实现的主要内容,如果未能解决你的问题,请参考以下文章

redis中 ll2string() 和 string2ll() 的实现

redis中 ll2string() 和 string2ll() 的实现

Java操作redis

笔记一 Redis基础

java操作redis

编程实践Golang 操作 Redis 代码实战