listpack 0.0.1.beta

Sign up to get free protection for your applications and to get access to all the features.
@@ -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
+ }
@@ -0,0 +1,4 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'listpack/version'
4
+ require 'listpack/listpack'
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ class Listpack
4
+ VERSION = '0.0.1.beta'
5
+ end
@@ -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: []