listpack 0.0.1.beta
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.gitignore +15 -0
- data/.rspec +3 -0
- data/.ruby-gemset +1 -0
- data/.ruby-version +1 -0
- data/.travis.yml +5 -0
- data/Gemfile +13 -0
- data/Gemfile.lock +46 -0
- data/README.md +58 -0
- data/Rakefile +11 -0
- data/bin/console +14 -0
- data/bin/setup +8 -0
- data/ext/listpack/extconf.rb +5 -0
- data/ext/listpack/listpack.c +783 -0
- data/ext/listpack/listpack.h +61 -0
- data/ext/listpack/listpack_malloc.h +45 -0
- data/ext/listpack/listpack_rb.c +211 -0
- data/lib/listpack.rb +4 -0
- data/lib/listpack/version.rb +5 -0
- data/listpack.gemspec +28 -0
- metadata +78 -0
@@ -0,0 +1,61 @@
|
|
1
|
+
/* Listpack -- A lists of strings serialization format
|
2
|
+
*
|
3
|
+
* This file implements the specification you can find at:
|
4
|
+
*
|
5
|
+
* https://github.com/antirez/listpack
|
6
|
+
*
|
7
|
+
* Copyright (c) 2017, Salvatore Sanfilippo <antirez at gmail dot com>
|
8
|
+
* All rights reserved.
|
9
|
+
*
|
10
|
+
* Redistribution and use in source and binary forms, with or without
|
11
|
+
* modification, are permitted provided that the following conditions are met:
|
12
|
+
*
|
13
|
+
* * Redistributions of source code must retain the above copyright notice,
|
14
|
+
* this list of conditions and the following disclaimer.
|
15
|
+
* * Redistributions in binary form must reproduce the above copyright
|
16
|
+
* notice, this list of conditions and the following disclaimer in the
|
17
|
+
* documentation and/or other materials provided with the distribution.
|
18
|
+
* * Neither the name of Redis nor the names of its contributors may be used
|
19
|
+
* to endorse or promote products derived from this software without
|
20
|
+
* specific prior written permission.
|
21
|
+
*
|
22
|
+
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
23
|
+
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
24
|
+
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
25
|
+
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
26
|
+
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
27
|
+
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
28
|
+
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
29
|
+
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
30
|
+
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
31
|
+
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
32
|
+
* POSSIBILITY OF SUCH DAMAGE.
|
33
|
+
*/
|
34
|
+
|
35
|
+
#ifndef __LISTPACK_H
|
36
|
+
#define __LISTPACK_H
|
37
|
+
|
38
|
+
#include <stdint.h>
|
39
|
+
|
40
|
+
#define LP_INTBUF_SIZE 21 /* 20 digits of -2^63 + 1 null term = 21. */
|
41
|
+
|
42
|
+
/* lpInsert() where argument possible values: */
|
43
|
+
#define LP_BEFORE 0
|
44
|
+
#define LP_AFTER 1
|
45
|
+
#define LP_REPLACE 2
|
46
|
+
|
47
|
+
unsigned char *lpNew(void);
|
48
|
+
void lpFree(unsigned char *lp);
|
49
|
+
unsigned char *lpInsert(unsigned char *lp, unsigned char *ele, uint32_t size, unsigned char *p, int where, unsigned char **newp);
|
50
|
+
unsigned char *lpAppend(unsigned char *lp, unsigned char *ele, uint32_t size);
|
51
|
+
unsigned char *lpDelete(unsigned char *lp, unsigned char *p, unsigned char **newp);
|
52
|
+
uint32_t lpLength(unsigned char *lp);
|
53
|
+
unsigned char *lpGet(unsigned char *p, int64_t *count, unsigned char *intbuf);
|
54
|
+
unsigned char *lpFirst(unsigned char *lp);
|
55
|
+
unsigned char *lpLast(unsigned char *lp);
|
56
|
+
unsigned char *lpNext(unsigned char *lp, unsigned char *p);
|
57
|
+
unsigned char *lpPrev(unsigned char *lp, unsigned char *p);
|
58
|
+
uint32_t lpBytes(unsigned char *lp);
|
59
|
+
unsigned char *lpSeek(unsigned char *lp, long index);
|
60
|
+
|
61
|
+
#endif
|
@@ -0,0 +1,45 @@
|
|
1
|
+
/* Listpack -- A lists of strings serialization format
|
2
|
+
* https://github.com/antirez/listpack
|
3
|
+
*
|
4
|
+
* Copyright (c) 2017, Salvatore Sanfilippo <antirez at gmail dot com>
|
5
|
+
* All rights reserved.
|
6
|
+
*
|
7
|
+
* Redistribution and use in source and binary forms, with or without
|
8
|
+
* modification, are permitted provided that the following conditions are met:
|
9
|
+
*
|
10
|
+
* * Redistributions of source code must retain the above copyright notice,
|
11
|
+
* this list of conditions and the following disclaimer.
|
12
|
+
* * Redistributions in binary form must reproduce the above copyright
|
13
|
+
* notice, this list of conditions and the following disclaimer in the
|
14
|
+
* documentation and/or other materials provided with the distribution.
|
15
|
+
* * Neither the name of Redis nor the names of its contributors may be used
|
16
|
+
* to endorse or promote products derived from this software without
|
17
|
+
* specific prior written permission.
|
18
|
+
*
|
19
|
+
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
20
|
+
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
21
|
+
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
22
|
+
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
23
|
+
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
24
|
+
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
25
|
+
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
26
|
+
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
27
|
+
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
28
|
+
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
29
|
+
* POSSIBILITY OF SUCH DAMAGE.
|
30
|
+
*/
|
31
|
+
|
32
|
+
/* Allocator selection.
|
33
|
+
*
|
34
|
+
* This file is used in order to change the Rax allocator at compile time.
|
35
|
+
* Just define the following defines to what you want to use. Also add
|
36
|
+
* the include of your alternate allocator if needed (not needed in order
|
37
|
+
* to use the default libc allocator). */
|
38
|
+
|
39
|
+
#ifndef LISTPACK_ALLOC_H
|
40
|
+
#define LISTPACK_ALLOC_H
|
41
|
+
//#include "zmalloc.h"
|
42
|
+
#define lp_malloc malloc
|
43
|
+
#define lp_realloc realloc
|
44
|
+
#define lp_free free
|
45
|
+
#endif
|
@@ -0,0 +1,211 @@
|
|
1
|
+
#include <ruby.h>
|
2
|
+
#include <stdint.h>
|
3
|
+
#include "listpack.h"
|
4
|
+
#include "listpack_malloc.h"
|
5
|
+
|
6
|
+
static VALUE Listpack;
|
7
|
+
|
8
|
+
typedef struct {
|
9
|
+
unsigned char *lp;
|
10
|
+
unsigned char *p;
|
11
|
+
} listpack_rb;
|
12
|
+
|
13
|
+
// Internal methods
|
14
|
+
|
15
|
+
/* Loads a listpack format string into the internal struct */
|
16
|
+
VALUE _rb_listpack_load(VALUE self, VALUE rb_str)
|
17
|
+
{
|
18
|
+
listpack_rb *list;
|
19
|
+
Data_Get_Struct(self, listpack_rb, list);
|
20
|
+
size_t str_len = RSTRING_LENINT(rb_str);
|
21
|
+
|
22
|
+
if (list->lp != NULL) {
|
23
|
+
lp_free(list->lp);
|
24
|
+
}
|
25
|
+
|
26
|
+
list->lp = lp_malloc(str_len);
|
27
|
+
|
28
|
+
if (list->lp == NULL) {
|
29
|
+
rb_raise(rb_eNoMemError, "no memory for listpack");
|
30
|
+
}
|
31
|
+
|
32
|
+
memcpy(list->lp, RSTRING_PTR(rb_str), str_len);
|
33
|
+
|
34
|
+
return Qtrue;
|
35
|
+
}
|
36
|
+
|
37
|
+
/* Converts a value from the list to the correct Ruby type */
|
38
|
+
VALUE _rb_listpack_getvalue(unsigned char *p)
|
39
|
+
{
|
40
|
+
if(!p) {
|
41
|
+
return Qnil;
|
42
|
+
}
|
43
|
+
|
44
|
+
unsigned char * result;
|
45
|
+
int64_t num;
|
46
|
+
|
47
|
+
result = lpGet(p, &num, NULL);
|
48
|
+
|
49
|
+
if(result) {
|
50
|
+
return rb_str_new((char *) result, num);
|
51
|
+
} else {
|
52
|
+
return rb_int_new(num);
|
53
|
+
}
|
54
|
+
}
|
55
|
+
|
56
|
+
// Public methods
|
57
|
+
VALUE rb_listpack_append(VALUE self, VALUE rb_ele)
|
58
|
+
{
|
59
|
+
listpack_rb *list;
|
60
|
+
Data_Get_Struct(self, listpack_rb, list);
|
61
|
+
|
62
|
+
list->lp = lpAppend(list->lp, (unsigned char *) RSTRING_PTR(rb_ele), RSTRING_LENINT(rb_ele));
|
63
|
+
|
64
|
+
if (list->lp == NULL) {
|
65
|
+
rb_raise(rb_eNoMemError, "no memory for listpack");
|
66
|
+
}
|
67
|
+
|
68
|
+
return Qtrue;
|
69
|
+
}
|
70
|
+
|
71
|
+
VALUE rb_listpack_current(VALUE self)
|
72
|
+
{
|
73
|
+
listpack_rb *list;
|
74
|
+
Data_Get_Struct(self, listpack_rb, list);
|
75
|
+
|
76
|
+
if (list->p == NULL) {
|
77
|
+
return Qnil;
|
78
|
+
}
|
79
|
+
else {
|
80
|
+
return _rb_listpack_getvalue(list->p);
|
81
|
+
}
|
82
|
+
}
|
83
|
+
|
84
|
+
VALUE rb_listpack_first(VALUE self)
|
85
|
+
{
|
86
|
+
listpack_rb *list;
|
87
|
+
unsigned char *result;
|
88
|
+
Data_Get_Struct(self, listpack_rb, list);
|
89
|
+
|
90
|
+
result = lpFirst(list->lp);
|
91
|
+
|
92
|
+
return _rb_listpack_getvalue(result);
|
93
|
+
}
|
94
|
+
|
95
|
+
VALUE rb_listpack_initialize(int argc, VALUE* argv, VALUE self)
|
96
|
+
{
|
97
|
+
listpack_rb *list;
|
98
|
+
VALUE data;
|
99
|
+
Data_Get_Struct(self, listpack_rb, list);
|
100
|
+
rb_scan_args(argc, argv, "01", &data);
|
101
|
+
|
102
|
+
if (NIL_P(data)) {
|
103
|
+
list->lp = lpNew();
|
104
|
+
}
|
105
|
+
else {
|
106
|
+
_rb_listpack_load(self, data);
|
107
|
+
}
|
108
|
+
|
109
|
+
return Qnil;
|
110
|
+
}
|
111
|
+
|
112
|
+
VALUE rb_listpack_insert(VALUE self, VALUE rb_ele)
|
113
|
+
{
|
114
|
+
listpack_rb *list;
|
115
|
+
Data_Get_Struct(self, listpack_rb, list);
|
116
|
+
|
117
|
+
list->lp = lpInsert(list->lp, (unsigned char *) RSTRING_PTR(rb_ele), RSTRING_LENINT(rb_ele), list->p, LP_AFTER, &list->p);
|
118
|
+
|
119
|
+
if (list->lp == NULL) {
|
120
|
+
rb_raise(rb_eNoMemError, "no memory for listpack");
|
121
|
+
}
|
122
|
+
|
123
|
+
return Qtrue;
|
124
|
+
}
|
125
|
+
|
126
|
+
VALUE rb_listpack_last(VALUE self)
|
127
|
+
{
|
128
|
+
listpack_rb *list;
|
129
|
+
unsigned char *result;
|
130
|
+
Data_Get_Struct(self, listpack_rb, list);
|
131
|
+
|
132
|
+
result = lpLast(list->lp);
|
133
|
+
|
134
|
+
return _rb_listpack_getvalue(result);
|
135
|
+
}
|
136
|
+
|
137
|
+
VALUE rb_listpack_next(VALUE self)
|
138
|
+
{
|
139
|
+
listpack_rb *list;
|
140
|
+
Data_Get_Struct(self, listpack_rb, list);
|
141
|
+
|
142
|
+
if (list->p == NULL) {
|
143
|
+
list->p = lpFirst(list->lp);
|
144
|
+
} else {
|
145
|
+
list->p = lpNext(list->lp, list->p);
|
146
|
+
}
|
147
|
+
|
148
|
+
return _rb_listpack_getvalue(list->p);
|
149
|
+
}
|
150
|
+
|
151
|
+
VALUE rb_listpack_seek(VALUE self, VALUE rb_idx)
|
152
|
+
{
|
153
|
+
listpack_rb *list;
|
154
|
+
Data_Get_Struct(self, listpack_rb, list);
|
155
|
+
|
156
|
+
list->p = lpSeek(list->lp, NUM2UINT(rb_idx));
|
157
|
+
|
158
|
+
return Qnil;
|
159
|
+
}
|
160
|
+
|
161
|
+
VALUE rb_listpack_size(VALUE self)
|
162
|
+
{
|
163
|
+
listpack_rb *list;
|
164
|
+
Data_Get_Struct(self, listpack_rb, list);
|
165
|
+
|
166
|
+
return rb_uint_new(lpLength(list->lp));
|
167
|
+
}
|
168
|
+
|
169
|
+
VALUE rb_listpack_to_s(VALUE self)
|
170
|
+
{
|
171
|
+
listpack_rb *list;
|
172
|
+
Data_Get_Struct(self, listpack_rb, list);
|
173
|
+
|
174
|
+
return rb_str_new((char *) list->lp, lpBytes(list->lp));
|
175
|
+
}
|
176
|
+
|
177
|
+
static void deallocate(listpack_rb *p_list)
|
178
|
+
{
|
179
|
+
lpFree(p_list->lp);
|
180
|
+
xfree(p_list);
|
181
|
+
}
|
182
|
+
|
183
|
+
static VALUE allocate(VALUE klass)
|
184
|
+
{
|
185
|
+
listpack_rb *list;
|
186
|
+
|
187
|
+
if ((list = ALLOC(listpack_rb)) != NULL)
|
188
|
+
{
|
189
|
+
list->lp = NULL;
|
190
|
+
list->p = NULL;
|
191
|
+
}
|
192
|
+
|
193
|
+
return Data_Wrap_Struct(klass, NULL, deallocate, list);
|
194
|
+
}
|
195
|
+
|
196
|
+
void Init_listpack(void) {
|
197
|
+
Listpack = rb_define_class("Listpack", rb_cObject);
|
198
|
+
rb_define_alloc_func(Listpack, allocate);
|
199
|
+
|
200
|
+
rb_define_method(Listpack, "append", rb_listpack_append, 1);
|
201
|
+
rb_define_method(Listpack, "current", rb_listpack_current, 0);
|
202
|
+
rb_define_method(Listpack, "first", rb_listpack_first, 0);
|
203
|
+
rb_define_method(Listpack, "initialize", rb_listpack_initialize, -1);
|
204
|
+
rb_define_method(Listpack, "insert", rb_listpack_insert, 1);
|
205
|
+
rb_define_method(Listpack, "last", rb_listpack_next, 0);
|
206
|
+
rb_define_method(Listpack, "next", rb_listpack_next, 0);
|
207
|
+
rb_define_method(Listpack, "prev", rb_listpack_first, 0);
|
208
|
+
rb_define_method(Listpack, "seek", rb_listpack_seek, 1);
|
209
|
+
rb_define_method(Listpack, "size", rb_listpack_size, 0);
|
210
|
+
rb_define_method(Listpack, "to_s", rb_listpack_to_s, 0);
|
211
|
+
}
|
data/lib/listpack.rb
ADDED
data/listpack.gemspec
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
lib = File.expand_path('lib', __dir__)
|
4
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
5
|
+
|
6
|
+
require "listpack/version"
|
7
|
+
|
8
|
+
Gem::Specification.new do |spec|
|
9
|
+
spec.name = "listpack"
|
10
|
+
spec.version = Listpack::VERSION
|
11
|
+
spec.authors = ["Sebastian Wallin"]
|
12
|
+
spec.email = ["sebastian.wallin@gmail.com"]
|
13
|
+
spec.extensions = ["ext/listpack/extconf.rb"]
|
14
|
+
|
15
|
+
spec.summary = %q{Ruby wrapper for Redis listpack data structure}
|
16
|
+
spec.description = %q{Ruby wrapper for Redis listpack data structure}
|
17
|
+
spec.homepage = "https://github.com/wallin/listpack-rb"
|
18
|
+
spec.license = 'BSD-3-Clause'
|
19
|
+
|
20
|
+
spec.files = `git ls-files -z`.split("\x0").reject do |f|
|
21
|
+
f.match(%r{^(test|spec|features)/})
|
22
|
+
end
|
23
|
+
spec.bindir = "exe"
|
24
|
+
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
25
|
+
spec.require_paths = ["lib"]
|
26
|
+
|
27
|
+
spec.add_dependency "rake-compiler"
|
28
|
+
end
|
metadata
ADDED
@@ -0,0 +1,78 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: listpack
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1.beta
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Sebastian Wallin
|
8
|
+
autorequire:
|
9
|
+
bindir: exe
|
10
|
+
cert_chain: []
|
11
|
+
date: 2018-05-02 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: rake-compiler
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ">="
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ">="
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0'
|
27
|
+
description: Ruby wrapper for Redis listpack data structure
|
28
|
+
email:
|
29
|
+
- sebastian.wallin@gmail.com
|
30
|
+
executables: []
|
31
|
+
extensions:
|
32
|
+
- ext/listpack/extconf.rb
|
33
|
+
extra_rdoc_files: []
|
34
|
+
files:
|
35
|
+
- ".gitignore"
|
36
|
+
- ".rspec"
|
37
|
+
- ".ruby-gemset"
|
38
|
+
- ".ruby-version"
|
39
|
+
- ".travis.yml"
|
40
|
+
- Gemfile
|
41
|
+
- Gemfile.lock
|
42
|
+
- README.md
|
43
|
+
- Rakefile
|
44
|
+
- bin/console
|
45
|
+
- bin/setup
|
46
|
+
- ext/listpack/extconf.rb
|
47
|
+
- ext/listpack/listpack.c
|
48
|
+
- ext/listpack/listpack.h
|
49
|
+
- ext/listpack/listpack_malloc.h
|
50
|
+
- ext/listpack/listpack_rb.c
|
51
|
+
- lib/listpack.rb
|
52
|
+
- lib/listpack/version.rb
|
53
|
+
- listpack.gemspec
|
54
|
+
homepage: https://github.com/wallin/listpack-rb
|
55
|
+
licenses:
|
56
|
+
- BSD-3-Clause
|
57
|
+
metadata: {}
|
58
|
+
post_install_message:
|
59
|
+
rdoc_options: []
|
60
|
+
require_paths:
|
61
|
+
- lib
|
62
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
63
|
+
requirements:
|
64
|
+
- - ">="
|
65
|
+
- !ruby/object:Gem::Version
|
66
|
+
version: '0'
|
67
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
68
|
+
requirements:
|
69
|
+
- - ">"
|
70
|
+
- !ruby/object:Gem::Version
|
71
|
+
version: 1.3.1
|
72
|
+
requirements: []
|
73
|
+
rubyforge_project:
|
74
|
+
rubygems_version: 2.7.6
|
75
|
+
signing_key:
|
76
|
+
specification_version: 4
|
77
|
+
summary: Ruby wrapper for Redis listpack data structure
|
78
|
+
test_files: []
|