Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
xindoo
redis
提交
11ac6ff6
R
redis
项目概览
xindoo
/
redis
通知
2
Star
2
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
R
redis
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
提交
11ac6ff6
编写于
5月 21, 2010
作者:
P
Pieter Noordhuis
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
implementation for a ziplist with push and pop support
上级
3d04d29e
变更
2
隐藏空白更改
内联
并排
Showing
2 changed file
with
152 addition
and
0 deletion
+152
-0
ziplist.c
ziplist.c
+150
-0
ziplist.h
ziplist.h
+2
-0
未找到文件。
ziplist.c
0 → 100644
浏览文件 @
11ac6ff6
/* Memory layout of a ziplist, containing "foo", "bar", "quux":
* <zlbytes><zllen><len>"foo"<len>"bar"<len>"quux"
*
* <zlbytes> is an unsigned integer to hold the number of bytes that
* the ziplist occupies. This is stored to not have to traverse the ziplist
* to know the new length when pushing.
*
* <zllen> is the number of items in the ziplist. When this value is
* greater than 254, we need to traverse the entire list to know
* how many items it holds.
*
* <len> is the number of bytes occupied by a single entry. When this
* number is greater than 253, the length will occupy 5 bytes, where
* the extra bytes contain an unsigned integer to hold the length.
*/
#include <stdio.h>
#include <string.h>
#include <assert.h>
#include "zmalloc.h"
#include "sds.h"
#include "ziplist.h"
#include "zip.c"
#define ZIPLIST_BYTES(zl) (*((unsigned int*)(zl)))
#define ZIPLIST_LENGTH(zl) (*((zl)+sizeof(unsigned int)))
#define ZIPLIST_HEADER_SIZE (sizeof(unsigned int)+1)
/* Create a new empty ziplist. */
unsigned
char
*
ziplistNew
(
void
)
{
unsigned
int
bytes
=
ZIPLIST_HEADER_SIZE
+
1
;
unsigned
char
*
zl
=
zmalloc
(
bytes
);
ZIPLIST_BYTES
(
zl
)
=
bytes
;
ZIPLIST_LENGTH
(
zl
)
=
0
;
zl
[
bytes
-
1
]
=
ZIP_END
;
return
zl
;
}
static
unsigned
char
*
ziplistResize
(
unsigned
char
*
zl
,
unsigned
int
len
)
{
zl
=
zipResize
(
zl
,
len
);
ZIPLIST_BYTES
(
zl
)
=
len
;
zl
[
len
-
1
]
=
ZIP_END
;
return
zl
;
}
static
unsigned
char
*
ziplistHead
(
unsigned
char
*
zl
)
{
return
zl
+
ZIPLIST_HEADER_SIZE
;
}
static
unsigned
char
*
ziplistTail
(
unsigned
char
*
zl
)
{
unsigned
char
*
p
,
*
q
;
p
=
q
=
ziplistHead
(
zl
);
while
(
*
p
!=
ZIP_END
)
{
q
=
p
;
p
+=
zipRawEntryLength
(
p
);
}
return
q
;
}
unsigned
char
*
ziplistPush
(
unsigned
char
*
zl
,
unsigned
char
*
entry
,
unsigned
int
elen
,
int
where
)
{
unsigned
int
curlen
=
ZIPLIST_BYTES
(
zl
);
unsigned
int
reqlen
=
zipEncodeLength
(
NULL
,
elen
)
+
elen
;
unsigned
char
*
p
;
/* Resize the ziplist */
zl
=
ziplistResize
(
zl
,
curlen
+
reqlen
);
if
(
where
==
ZIPLIST_HEAD
)
{
p
=
zl
+
ZIPLIST_HEADER_SIZE
;
if
(
*
p
!=
ZIP_END
)
{
/* Subtract one because of the ZIP_END bytes */
memmove
(
p
+
reqlen
,
p
,
curlen
-
ZIPLIST_HEADER_SIZE
-
1
);
}
}
else
{
p
=
zl
+
curlen
-
1
;
}
/* Increase length */
if
(
ZIPLIST_LENGTH
(
zl
)
<
ZIP_BIGLEN
)
ZIPLIST_LENGTH
(
zl
)
++
;
/* Write the entry */
p
+=
zipEncodeLength
(
p
,
elen
);
memcpy
(
p
,
entry
,
elen
);
return
zl
;
}
unsigned
char
*
ziplistPop
(
unsigned
char
*
zl
,
sds
*
value
,
int
where
)
{
unsigned
int
curlen
=
ZIPLIST_BYTES
(
zl
),
len
,
rlen
;
unsigned
char
*
p
;
*
value
=
NULL
;
/* Get pointer to element to remove */
p
=
(
where
==
ZIPLIST_HEAD
)
?
ziplistHead
(
zl
)
:
ziplistTail
(
zl
);
if
(
*
p
==
ZIP_END
)
return
zl
;
len
=
zipDecodeLength
(
p
);
*
value
=
sdsnewlen
(
p
+
zipEncodeLength
(
NULL
,
len
),
len
);
/* Move list to front when popping from the head */
rlen
=
zipRawEntryLength
(
p
);
if
(
where
==
ZIPLIST_HEAD
)
{
memmove
(
p
,
p
+
rlen
,
curlen
-
ZIPLIST_HEADER_SIZE
-
len
);
}
/* Resize and update length */
zl
=
ziplistResize
(
zl
,
curlen
-
rlen
);
if
(
ZIPLIST_LENGTH
(
zl
)
<
ZIP_BIGLEN
)
ZIPLIST_LENGTH
(
zl
)
--
;
return
zl
;
}
void
ziplistRepr
(
unsigned
char
*
zl
)
{
unsigned
char
*
p
;
unsigned
int
l
;
printf
(
"{bytes %d} {length %u}
\n
"
,
ZIPLIST_BYTES
(
zl
),
ZIPLIST_LENGTH
(
zl
));
p
=
ziplistHead
(
zl
);
while
(
*
p
!=
ZIP_END
)
{
l
=
zipDecodeLength
(
p
);
printf
(
"{key %u}"
,
l
);
p
+=
zipEncodeLength
(
NULL
,
l
);
fwrite
(
p
,
l
,
1
,
stdout
);
printf
(
"
\n
"
);
p
+=
l
;
}
printf
(
"{end}
\n\n
"
);
}
#ifdef ZIPLIST_TEST_MAIN
int
main
(
int
argc
,
char
**
argv
)
{
unsigned
char
*
zl
;
sds
s
;
zl
=
ziplistNew
();
zl
=
ziplistPush
(
zl
,
(
unsigned
char
*
)
"foo"
,
3
,
ZIPLIST_TAIL
);
ziplistRepr
(
zl
);
zl
=
ziplistPush
(
zl
,
(
unsigned
char
*
)
"quux"
,
4
,
ZIPLIST_TAIL
);
ziplistRepr
(
zl
);
zl
=
ziplistPush
(
zl
,
(
unsigned
char
*
)
"hello"
,
5
,
ZIPLIST_HEAD
);
ziplistRepr
(
zl
);
zl
=
ziplistPop
(
zl
,
&
s
,
ZIPLIST_TAIL
);
printf
(
"Pop tail: %s (length %ld)
\n
"
,
s
,
sdslen
(
s
));
ziplistRepr
(
zl
);
zl
=
ziplistPop
(
zl
,
&
s
,
ZIPLIST_HEAD
);
printf
(
"Pop head: %s (length %ld)
\n
"
,
s
,
sdslen
(
s
));
ziplistRepr
(
zl
);
return
0
;
}
#endif
ziplist.h
0 → 100644
浏览文件 @
11ac6ff6
#define ZIPLIST_HEAD 0
#define ZIPLIST_TAIL 1
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录