redis中有很多内存操作的经典使用,越看越有意思:
- /* Return a ziplist element as an SDS string. */
- sds ziplistGetObject(unsigned char *sptr) {
- unsigned char *vstr;
- unsigned int vlen;
- long long vlong;
-
- serverAssert(sptr != NULL);
- serverAssert(ziplistGet(sptr,&vstr,&vlen,&vlong));
-
- if (vstr) {
- return sdsnewlen((char*)vstr,vlen);
- } else {
- return sdsfromlonglong(vlong);
- }
- }
-
- /* Compare element in sorted set with given element. */
- int zzlCompareElements(unsigned char *eptr, unsigned char *cstr, unsigned int clen) {
- unsigned char *vstr;
- unsigned int vlen;
- long long vlong;
- unsigned char vbuf[32];
- int minlen, cmp;
-
- serverAssert(ziplistGet(eptr,&vstr,&vlen,&vlong));
- if (vstr == NULL) {
- /* Store string representation of long long in buf. */
- vlen = ll2string((char*)vbuf,sizeof(vbuf),vlong);
- vstr = vbuf;
- }
-
- minlen = (vlen < clen) ? vlen : clen;
- cmp = memcmp(vstr,cstr,minlen);
- if (cmp == 0) return vlen-clen;
- return cmp;
- }
-
- unsigned int zzlLength(unsigned char *zl) {
- return ziplistLen(zl)/2;
- }
-
- /* Move to next entry based on the values in eptr and sptr. Both are set to
- * NULL when there is no next entry. */
- void zzlNext(unsigned char *zl, unsigned char **eptr, unsigned char **sptr) {
- unsigned char *_eptr, *_sptr;
- serverAssert(*eptr != NULL && *sptr != NULL);
-
- _eptr = ziplistNext(zl,*sptr);
- if (_eptr != NULL) {
- _sptr = ziplistNext(zl,_eptr);
- serverAssert(_sptr != NULL);
- } else {
- /* No next entry. */
- _sptr = NULL;
- }
-
- *eptr = _eptr;
- *sptr = _sptr;
- }
-
- /* Move to the previous entry based on the values in eptr and sptr. Both are
- * set to NULL when there is no next entry. */
- void zzlPrev(unsigned char *zl, unsigned char **eptr, unsigned char **sptr) {
- unsigned char *_eptr, *_sptr;
- serverAssert(*eptr != NULL && *sptr != NULL);
-
- _sptr = ziplistPrev(zl,*eptr);
- if (_sptr != NULL) {
- _eptr = ziplistPrev(zl,_sptr);
- serverAssert(_eptr != NULL);
- } else {
- /* No previous entry. */
- _eptr = NULL;
- }
-
- *eptr = _eptr;
- *sptr = _sptr;
- }
-
- /* Returns if there is a part of the zset is in range. Should only be used
- * internally by zzlFirstInRange and zzlLastInRange. */
- int zzlIsInRange(unsigned char *zl, zrangespec *range) {
- unsigned char *p;
- double score;
-
- /* Test for ranges that will always be empty. */
- if (range->min > range->max ||
- (range->min == range->max && (range->minex || range->maxex)))
- return 0;
-
- p = ziplistIndex(zl,-1); /* Last score. */
- if (p == NULL) return 0; /* Empty sorted set */
- score = zzlGetScore(p);
- if (!zslValueGteMin(score,range))
- return 0;
-
- p = ziplistIndex(zl,1); /* First score. */
- serverAssert(p != NULL);
- score = zzlGetScore(p);
- if (!zslValueLteMax(score,range))
- return 0;
-
- return 1;
- }
-
- /* Find pointer to the first element contained in the specified range.
- * Returns NULL when no element is contained in the range. */
- unsigned char *zzlFirstInRange(unsigned char *zl, zrangespec *range) {
- unsigned char *eptr = ziplistIndex(zl,0), *sptr;
- double score;
-
- /* If everything is out of range, return early. */
- if (!zzlIsInRange(zl,range)) return NULL;
-
- while (eptr != NULL) {
- sptr = ziplistNext(zl,eptr);
- serverAssert(sptr != NULL);
-
- score = zzlGetScore(sptr);
- if (zslValueGteMin(score,range)) {
- /* Check if score <= max. */
- if (zslValueLteMax(score,range))
- return eptr;
- return NULL;
- }
-
- /* Move to next element. */
- eptr = ziplistNext(zl,sptr);
- }
-
- return NULL;
- }
-
- /* Find pointer to the last element contained in the specified range.
- * Returns NULL when no element is contained in the range. */
- unsigned char *zzlLastInRange(unsigned char *zl, zrangespec *range) {
- unsigned char *eptr = ziplistIndex(zl,-2), *sptr;
- double score;
-
- /* If everything is out of range, return early. */
- if (!zzlIsInRange(zl,range)) return NULL;
-
- while (eptr != NULL) {
- sptr = ziplistNext(zl,eptr);
- serverAssert(sptr != NULL);
-
- score = zzlGetScore(sptr);
- if (zslValueLteMax(score,range)) {
- /* Check if score >= min. */
- if (zslValueGteMin(score,range))
- return eptr;
- return NULL;
- }
-
- /* Move to previous element by moving to the score of previous element.
- * When this returns NULL, we know there also is no element. */
- sptr = ziplistPrev(zl,eptr);
- if (sptr != NULL)
- serverAssert((eptr = ziplistPrev(zl,sptr)) != NULL);
- else
- eptr = NULL;
- }
-
- return NULL;
- }
-
- int zzlLexValueGteMin(unsigned char *p, zlexrangespec *spec) {
- sds value = ziplistGetObject(p);
- int res = zslLexValueGteMin(value,spec);
- sdsfree(value);
- return res;
- }
-
- int zzlLexValueLteMax(unsigned char *p, zlexrangespec *spec) {
- sds value = ziplistGetObject(p);
- int res = zslLexValueLteMax(value,spec);
- sdsfree(value);
- return res;
- }