version_sorter 1.1.1 → 2.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/LICENSE +20 -0
- data/ext/version_sorter/extconf.rb +0 -2
- data/ext/version_sorter/version_sorter.c +189 -167
- metadata +9 -24
- data/.gitattributes +0 -1
- data/README.markdown +0 -18
- data/Rakefile +0 -36
- data/ext/version_sorter/frameworks/cmockery.framework/Versions/A/Headers/cmockery.h +0 -435
- data/ext/version_sorter/frameworks/cmockery.framework/Versions/A/Resources/English.lproj/InfoPlist.strings +0 -0
- data/ext/version_sorter/frameworks/cmockery.framework/Versions/A/Resources/Info.plist +0 -24
- data/ext/version_sorter/frameworks/cmockery.framework/Versions/A/cmockery +0 -0
- data/ext/version_sorter/frameworks/cmockery.framework/cmockery +0 -0
- data/ext/version_sorter/rb_version_sorter.c +0 -61
- data/ext/version_sorter/test/main.c +0 -124
- data/ext/version_sorter/version_sorter.h +0 -61
- data/ext/version_sorter/version_sorter.xcodeproj/project.pbxproj +0 -269
- data/lib/version_sorter/version.rb +0 -3
- data/test/tags.rb +0 -1
- data/test/tags.txt +0 -1311
- data/test/version_sorter_test.rb +0 -37
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 07d8f2b3a777fa9268641f6e66ec0feaf53173df
|
4
|
+
data.tar.gz: 7e87c239f9aa35b697646588c67f6e789177804a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 05df11ccb84327dc57dccabe71fbdfa847047d28d45a1af451319510746c50b5fe315e7022c50fa6c72cb7c0ac23a65531a71630cbb087d6aeb0e16b22a2fd23
|
7
|
+
data.tar.gz: 8d068f96142e02c18c97459b49efae4338d2cca2b640689a86b918a172c39edf47e7320d3819dfa1021880cf283f6e96ba0414600d2b9195d1536087160e9692
|
data/LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) K. Adam Christensen
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
Software), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED AS IS, WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
@@ -11,203 +11,225 @@
|
|
11
11
|
#include <stdio.h>
|
12
12
|
#include <string.h>
|
13
13
|
#include <ctype.h>
|
14
|
-
#include
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
14
|
+
#include <assert.h>
|
15
|
+
#include <ruby.h>
|
16
|
+
|
17
|
+
#define min(a, b) ((a) < (b) ? (a) : (b))
|
18
|
+
typedef int compare_callback_t(const void *, const void *);
|
19
|
+
|
20
|
+
struct version_number {
|
21
|
+
const char *original;
|
22
|
+
VALUE rb_version;
|
23
|
+
uint64_t num_flags;
|
24
|
+
int32_t size;
|
25
|
+
union version_comp {
|
26
|
+
uint32_t number;
|
27
|
+
struct strchunk {
|
28
|
+
uint16_t offset;
|
29
|
+
uint16_t len;
|
30
|
+
} string;
|
31
|
+
} comp[1];
|
32
|
+
};
|
33
|
+
|
34
|
+
static int
|
35
|
+
strchunk_cmp(const char *original_a, const struct strchunk *a,
|
36
|
+
const char *original_b, const struct strchunk *b)
|
37
|
+
{
|
38
|
+
size_t len = min(a->len, b->len);
|
39
|
+
int cmp = memcmp(original_a + a->offset, original_b + b->offset, len);
|
40
|
+
return cmp ? cmp : (int)(a->len - b->len);
|
41
|
+
}
|
25
42
|
|
26
|
-
|
27
|
-
|
43
|
+
static int
|
44
|
+
compare_version_number(const struct version_number *a,
|
45
|
+
const struct version_number *b)
|
28
46
|
{
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
47
|
+
int n, max_n = min(a->size, b->size);
|
48
|
+
|
49
|
+
for (n = 0; n < max_n; ++n) {
|
50
|
+
int num_a = (a->num_flags & (1ull << n)) != 0;
|
51
|
+
int num_b = (b->num_flags & (1ull << n)) != 0;
|
52
|
+
|
53
|
+
if (num_a == num_b) {
|
54
|
+
const union version_comp *ca = &a->comp[n];
|
55
|
+
const union version_comp *cb = &b->comp[n];
|
56
|
+
int cmp = 0;
|
57
|
+
|
58
|
+
if (num_a) {
|
59
|
+
cmp = (int)ca->number - (int)cb->number;
|
60
|
+
} else {
|
61
|
+
cmp = strchunk_cmp(
|
62
|
+
a->original, &ca->string,
|
63
|
+
b->original, &cb->string);
|
64
|
+
}
|
65
|
+
|
66
|
+
if (cmp) return cmp;
|
67
|
+
} else {
|
68
|
+
return num_a ? 1 : -1;
|
69
|
+
}
|
70
|
+
}
|
71
|
+
|
72
|
+
if (a->size < b->size)
|
73
|
+
return (b->num_flags & (1ull << n)) ? -1 : 1;
|
74
|
+
|
75
|
+
if (a->size > b->size)
|
76
|
+
return (a->num_flags & (1ull << n)) ? 1 : -1;
|
77
|
+
|
78
|
+
return 0;
|
44
79
|
}
|
45
80
|
|
46
|
-
|
47
|
-
|
81
|
+
static int
|
82
|
+
version_compare_cb(const void *a, const void *b)
|
48
83
|
{
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
free(cur->str);
|
53
|
-
free(cur);
|
54
|
-
}
|
55
|
-
if (vsi->normalized != NULL) {
|
56
|
-
free(vsi->normalized);
|
57
|
-
}
|
58
|
-
free(vsi);
|
84
|
+
return compare_version_number(
|
85
|
+
(*(const struct version_number **)a),
|
86
|
+
(*(const struct version_number **)b));
|
59
87
|
}
|
60
88
|
|
61
|
-
|
62
|
-
|
89
|
+
static int
|
90
|
+
version_compare_cb_r(const void *a, const void *b)
|
63
91
|
{
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
}
|
68
|
-
piece->str = str;
|
69
|
-
piece->len = strlen(str);
|
70
|
-
piece->next = NULL;
|
71
|
-
|
72
|
-
if (vsi->head == NULL) {
|
73
|
-
vsi->head = piece;
|
74
|
-
vsi->tail = piece;
|
75
|
-
} else {
|
76
|
-
vsi->tail->next = piece;
|
77
|
-
vsi->tail = piece;
|
78
|
-
}
|
79
|
-
vsi->node_len++;
|
80
|
-
if (piece->len > vsi->widest_len) {
|
81
|
-
vsi->widest_len = piece->len;
|
82
|
-
}
|
92
|
+
return -compare_version_number(
|
93
|
+
(*(const struct version_number **)a),
|
94
|
+
(*(const struct version_number **)b));
|
83
95
|
}
|
84
96
|
|
85
|
-
|
86
|
-
|
97
|
+
static struct version_number *
|
98
|
+
grow_version_number(struct version_number *version, int new_size)
|
87
99
|
{
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
} else {
|
93
|
-
return other;
|
94
|
-
}
|
100
|
+
return xrealloc(version,
|
101
|
+
(sizeof(struct version_number) +
|
102
|
+
sizeof(union version_comp) * new_size));
|
103
|
+
}
|
95
104
|
|
105
|
+
static struct version_number *
|
106
|
+
parse_version_number(const char *string)
|
107
|
+
{
|
108
|
+
struct version_number *version = NULL;
|
109
|
+
uint64_t num_flags = 0x0;
|
110
|
+
uint16_t offset;
|
111
|
+
int comp_n = 0, comp_alloc = 4;
|
112
|
+
|
113
|
+
version = grow_version_number(version, comp_alloc);
|
114
|
+
|
115
|
+
for (offset = 0; string[offset] && comp_n < 64;) {
|
116
|
+
if (comp_n >= comp_alloc) {
|
117
|
+
comp_alloc += 4;
|
118
|
+
version = grow_version_number(version, comp_alloc);
|
119
|
+
}
|
120
|
+
|
121
|
+
if (isdigit(string[offset])) {
|
122
|
+
uint32_t number = 0;
|
123
|
+
uint16_t start = offset;
|
124
|
+
int overflown = 0;
|
125
|
+
|
126
|
+
while (isdigit(string[offset])) {
|
127
|
+
if (!overflown) {
|
128
|
+
uint32_t old_number = number;
|
129
|
+
number = (10 * number) + (string[offset] - '0');
|
130
|
+
if (number < old_number) overflown = 1;
|
131
|
+
}
|
132
|
+
|
133
|
+
offset++;
|
134
|
+
}
|
135
|
+
|
136
|
+
if (overflown) {
|
137
|
+
version->comp[comp_n].string.offset = start;
|
138
|
+
version->comp[comp_n].string.len = offset - start;
|
139
|
+
} else {
|
140
|
+
version->comp[comp_n].number = number;
|
141
|
+
num_flags |= (1 << comp_n);
|
142
|
+
}
|
143
|
+
comp_n++;
|
144
|
+
continue;
|
145
|
+
}
|
146
|
+
|
147
|
+
if (string[offset] == '-' || isalpha(string[offset])) {
|
148
|
+
uint16_t start = offset;
|
149
|
+
|
150
|
+
if (string[offset] == '-')
|
151
|
+
offset++;
|
152
|
+
|
153
|
+
while (isalpha(string[offset]))
|
154
|
+
offset++;
|
155
|
+
|
156
|
+
version->comp[comp_n].string.offset = start;
|
157
|
+
version->comp[comp_n].string.len = offset - start;
|
158
|
+
comp_n++;
|
159
|
+
continue;
|
160
|
+
}
|
161
|
+
|
162
|
+
offset++;
|
163
|
+
}
|
164
|
+
|
165
|
+
version->original = string;
|
166
|
+
version->num_flags = num_flags;
|
167
|
+
version->size = comp_n;
|
168
|
+
|
169
|
+
return version;
|
96
170
|
}
|
97
171
|
|
98
|
-
|
99
|
-
|
172
|
+
static VALUE
|
173
|
+
rb_version_sort_1(VALUE rb_self, VALUE rb_version_array, compare_callback_t cmp)
|
100
174
|
{
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
enum scan_state current_state, next_state;
|
175
|
+
struct version_number **versions;
|
176
|
+
long length, i;
|
177
|
+
VALUE *rb_version_ptr;
|
105
178
|
|
106
|
-
|
107
|
-
current_state = scan_state_get(current_char);
|
179
|
+
Check_Type(rb_version_array, T_ARRAY);
|
108
180
|
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
continue;
|
113
|
-
}
|
181
|
+
length = RARRAY_LEN(rb_version_array);
|
182
|
+
if (!length)
|
183
|
+
return rb_ary_new();
|
114
184
|
|
115
|
-
|
116
|
-
end++;
|
117
|
-
next_char = vsi->original[end];
|
118
|
-
next_state = scan_state_get(next_char);
|
119
|
-
} while (next_char != '\0' && current_state == next_state);
|
185
|
+
versions = xcalloc(length, sizeof(struct version_number *));
|
120
186
|
|
121
|
-
|
187
|
+
for (i = 0; i < length; ++i) {
|
188
|
+
VALUE rb_version = rb_ary_entry(rb_version_array, i);
|
189
|
+
versions[i] = parse_version_number(StringValuePtr(rb_version));
|
190
|
+
versions[i]->rb_version = rb_version;
|
191
|
+
}
|
122
192
|
|
123
|
-
|
124
|
-
|
125
|
-
DIE("ERROR: Not enough memory to allocate word")
|
126
|
-
}
|
193
|
+
qsort(versions, length, sizeof(struct version_number *), cmp);
|
194
|
+
rb_version_ptr = RARRAY_PTR(rb_version_array);
|
127
195
|
|
128
|
-
|
129
|
-
|
196
|
+
for (i = 0; i < length; ++i) {
|
197
|
+
rb_version_ptr[i] = versions[i]->rb_version;
|
198
|
+
xfree(versions[i]);
|
199
|
+
}
|
200
|
+
xfree(versions);
|
201
|
+
return rb_version_array;
|
202
|
+
}
|
130
203
|
|
131
|
-
|
204
|
+
static VALUE
|
205
|
+
rb_version_sort(VALUE rb_self, VALUE rb_versions)
|
206
|
+
{
|
207
|
+
return rb_version_sort_1(rb_self, rb_ary_dup(rb_versions), version_compare_cb);
|
208
|
+
}
|
132
209
|
|
133
|
-
|
134
|
-
|
210
|
+
static VALUE
|
211
|
+
rb_version_sort_r(VALUE rb_self, VALUE rb_versions)
|
212
|
+
{
|
213
|
+
return rb_version_sort_1(rb_self, rb_ary_dup(rb_versions), version_compare_cb_r);
|
135
214
|
}
|
136
215
|
|
137
|
-
|
138
|
-
|
216
|
+
static VALUE
|
217
|
+
rb_version_sort_bang(VALUE rb_self, VALUE rb_versions)
|
139
218
|
{
|
140
|
-
|
141
|
-
int pos, i;
|
142
|
-
|
143
|
-
char *result = malloc(((vsi->node_len * widest_len) + 1) * sizeof(char));
|
144
|
-
if (result == NULL) {
|
145
|
-
DIE("ERROR: Unable to allocate memory")
|
146
|
-
}
|
147
|
-
result[0] = '\0';
|
148
|
-
pos = 0;
|
149
|
-
|
150
|
-
for (cur = vsi->head; cur; cur = cur->next) {
|
151
|
-
|
152
|
-
/* Left-Pad digits with a space */
|
153
|
-
if (cur->len < widest_len && isdigit(cur->str[0])) {
|
154
|
-
for (i = 0; i < widest_len - cur->len; i++) {
|
155
|
-
result[pos] = ' ';
|
156
|
-
pos++;
|
157
|
-
}
|
158
|
-
result[pos] = '\0';
|
159
|
-
}
|
160
|
-
strcat(result, cur->str);
|
161
|
-
pos += cur->len;
|
162
|
-
|
163
|
-
/* Right-Pad words with a space */
|
164
|
-
if (cur->len < widest_len && isalpha(cur->str[0])) {
|
165
|
-
for (i = 0; i < widest_len - cur->len; i++) {
|
166
|
-
result[pos] = ' ';
|
167
|
-
pos++;
|
168
|
-
}
|
169
|
-
result[pos] = '\0';
|
170
|
-
}
|
171
|
-
}
|
172
|
-
vsi->normalized = result;
|
173
|
-
vsi->widest_len = widest_len;
|
219
|
+
return rb_version_sort_1(rb_self, rb_versions, version_compare_cb);
|
174
220
|
}
|
175
221
|
|
176
|
-
|
177
|
-
|
222
|
+
static VALUE
|
223
|
+
rb_version_sort_r_bang(VALUE rb_self, VALUE rb_versions)
|
178
224
|
{
|
179
|
-
|
225
|
+
return rb_version_sort_1(rb_self, rb_versions, version_compare_cb_r);
|
180
226
|
}
|
181
227
|
|
182
|
-
|
183
|
-
version_sorter_sort(char **list, size_t list_len)
|
228
|
+
void Init_version_sorter(void)
|
184
229
|
{
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
for (i = 0; i < list_len; i++) {
|
191
|
-
vsi = version_sorting_item_init(list[i], i);
|
192
|
-
if (vsi->widest_len > widest_len) {
|
193
|
-
widest_len = vsi->widest_len;
|
194
|
-
}
|
195
|
-
sorting_list[i] = vsi;
|
196
|
-
}
|
197
|
-
|
198
|
-
for (i = 0; i < list_len; i++) {
|
199
|
-
create_normalized_version(sorting_list[i], widest_len);
|
200
|
-
}
|
201
|
-
|
202
|
-
qsort((void *) sorting_list, list_len, sizeof(VersionSortingItem *), &compare_by_version);
|
203
|
-
|
204
|
-
for (i = 0; i < list_len; i++) {
|
205
|
-
vsi = sorting_list[i];
|
206
|
-
list[i] = (char *) vsi->original;
|
207
|
-
ordering[i] = vsi->original_idx;
|
208
|
-
version_sorting_item_free(vsi);
|
209
|
-
}
|
210
|
-
free(sorting_list);
|
211
|
-
|
212
|
-
return ordering;
|
230
|
+
VALUE rb_mVersionSorter = rb_define_module("VersionSorter");
|
231
|
+
rb_define_module_function(rb_mVersionSorter, "sort", rb_version_sort, 1);
|
232
|
+
rb_define_module_function(rb_mVersionSorter, "rsort", rb_version_sort_r, 1);
|
233
|
+
rb_define_module_function(rb_mVersionSorter, "sort!", rb_version_sort_bang, 1);
|
234
|
+
rb_define_module_function(rb_mVersionSorter, "rsort!", rb_version_sort_r_bang, 1);
|
213
235
|
}
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: version_sorter
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 2.0.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Chris Wanstrath
|
@@ -9,42 +9,27 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2015-02-
|
12
|
+
date: 2015-02-19 00:00:00.000000000 Z
|
13
13
|
dependencies: []
|
14
|
-
description:
|
14
|
+
description: VersionSorter is a C extension that does fast sorting of large sets of
|
15
|
+
version strings.
|
15
16
|
email: chris@ozmm.org
|
16
17
|
executables: []
|
17
18
|
extensions:
|
18
19
|
- ext/version_sorter/extconf.rb
|
19
|
-
extra_rdoc_files:
|
20
|
-
- README.markdown
|
20
|
+
extra_rdoc_files: []
|
21
21
|
files:
|
22
|
-
-
|
23
|
-
- README.markdown
|
24
|
-
- Rakefile
|
22
|
+
- LICENSE
|
25
23
|
- ext/version_sorter/extconf.rb
|
26
|
-
- ext/version_sorter/frameworks/cmockery.framework/Versions/A/Headers/cmockery.h
|
27
|
-
- ext/version_sorter/frameworks/cmockery.framework/Versions/A/Resources/English.lproj/InfoPlist.strings
|
28
|
-
- ext/version_sorter/frameworks/cmockery.framework/Versions/A/Resources/Info.plist
|
29
|
-
- ext/version_sorter/frameworks/cmockery.framework/Versions/A/cmockery
|
30
|
-
- ext/version_sorter/frameworks/cmockery.framework/cmockery
|
31
|
-
- ext/version_sorter/rb_version_sorter.c
|
32
|
-
- ext/version_sorter/test/main.c
|
33
24
|
- ext/version_sorter/version_sorter.c
|
34
|
-
|
35
|
-
|
36
|
-
-
|
37
|
-
- test/tags.rb
|
38
|
-
- test/tags.txt
|
39
|
-
- test/version_sorter_test.rb
|
40
|
-
homepage: http://github.com/defunkt/version_sorter
|
41
|
-
licenses: []
|
25
|
+
homepage: https://github.com/defunkt/version_sorter
|
26
|
+
licenses:
|
27
|
+
- MIT
|
42
28
|
metadata: {}
|
43
29
|
post_install_message:
|
44
30
|
rdoc_options: []
|
45
31
|
require_paths:
|
46
32
|
- lib
|
47
|
-
- ext
|
48
33
|
required_ruby_version: !ruby/object:Gem::Requirement
|
49
34
|
requirements:
|
50
35
|
- - ">="
|