version_sorter 1.1.1 → 2.0.0
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 +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
|
- - ">="
|