mittens 0.3.2 → 0.3.4
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/CHANGELOG.md +8 -0
- data/ext/mittens/ext.c +88 -42
- data/ext/mittens/extconf.rb +2 -0
- data/lib/mittens/version.rb +1 -1
- metadata +1 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: d7e35e680454076f43e5973db399645697e0e98732555293d6b5e3bae115308d
|
|
4
|
+
data.tar.gz: 6c619fe9518ba5ddd42001ee0e99b4883b0fa703d5bf7b45e9022a039c78fb7d
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 1148ef35cf15d3027b51934844763437f1a606b2eed92dec9ccb17c86a78e544d664a51e6470da7d117c3a30fb1e0638119f3f1091fb203b29630e11513d5672
|
|
7
|
+
data.tar.gz: c1cc877ce40bf0c2fc3dd9a7946b4cf0165f870392ff87024c3a717cfe742420b8de6b1bbe8ecf5645e0566f81ed906f1ce87a9072ba645c4ca3096702b253d8
|
data/CHANGELOG.md
CHANGED
data/ext/mittens/ext.c
CHANGED
|
@@ -1,21 +1,37 @@
|
|
|
1
|
+
#include <limits.h>
|
|
2
|
+
|
|
1
3
|
#include "libstemmer.h"
|
|
2
4
|
#include "ruby/ruby.h"
|
|
3
5
|
|
|
6
|
+
#define GetAlgorithm(language) (NIL_P(language) ? "english" : StringValueCStr(language))
|
|
7
|
+
#define GetStemmer(obj, ptr) TypedData_Get_Struct((obj), stemmer_t, &stemmer_data_type, (ptr))
|
|
8
|
+
|
|
4
9
|
typedef struct stemmer {
|
|
5
|
-
struct sb_stemmer
|
|
10
|
+
struct sb_stemmer* stemmer;
|
|
11
|
+
VALUE language;
|
|
6
12
|
} stemmer_t;
|
|
7
13
|
|
|
8
|
-
static void
|
|
14
|
+
static void stemmer_mark(void* ptr)
|
|
9
15
|
{
|
|
10
|
-
stemmer_t
|
|
11
|
-
|
|
12
|
-
|
|
16
|
+
stemmer_t* stemmer = (stemmer_t*) ptr;
|
|
17
|
+
rb_gc_mark(stemmer->language);
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
static void stemmer_free(void* ptr)
|
|
21
|
+
{
|
|
22
|
+
stemmer_t* stemmer = (stemmer_t*) ptr;
|
|
23
|
+
|
|
24
|
+
// safe to pass null pointer, but check anyways
|
|
25
|
+
if (stemmer->stemmer != NULL)
|
|
26
|
+
sb_stemmer_delete(stemmer->stemmer);
|
|
27
|
+
|
|
13
28
|
xfree(ptr);
|
|
14
29
|
}
|
|
15
30
|
|
|
16
31
|
const rb_data_type_t stemmer_data_type = {
|
|
17
|
-
.wrap_struct_name = "
|
|
32
|
+
.wrap_struct_name = "Mittens::Stemmer",
|
|
18
33
|
.function = {
|
|
34
|
+
.dmark = stemmer_mark,
|
|
19
35
|
.dfree = stemmer_free,
|
|
20
36
|
},
|
|
21
37
|
.flags = RUBY_TYPED_FREE_IMMEDIATELY
|
|
@@ -23,74 +39,104 @@ const rb_data_type_t stemmer_data_type = {
|
|
|
23
39
|
|
|
24
40
|
static VALUE stemmer_allocate(VALUE klass)
|
|
25
41
|
{
|
|
26
|
-
stemmer_t
|
|
42
|
+
stemmer_t* stemmer;
|
|
27
43
|
VALUE obj = TypedData_Make_Struct(klass, stemmer_t, &stemmer_data_type, stemmer);
|
|
28
44
|
stemmer->stemmer = NULL;
|
|
45
|
+
stemmer->language = Qnil;
|
|
29
46
|
return obj;
|
|
30
47
|
}
|
|
31
48
|
|
|
32
49
|
static VALUE stemmer_initialize(int argc, VALUE* argv, VALUE self)
|
|
33
50
|
{
|
|
34
|
-
|
|
35
|
-
|
|
51
|
+
stemmer_t* stemmer;
|
|
52
|
+
GetStemmer(self, stemmer);
|
|
36
53
|
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
VALUE language = rb_hash_aref(opts, ID2SYM(rb_intern("language")));
|
|
40
|
-
if (!NIL_P(language)) {
|
|
41
|
-
Check_Type(language, T_STRING);
|
|
42
|
-
algorithm = RSTRING_PTR(language);
|
|
43
|
-
}
|
|
44
|
-
}
|
|
54
|
+
if (stemmer->stemmer != NULL)
|
|
55
|
+
rb_raise(rb_eRuntimeError, "stemmer already initialized");
|
|
45
56
|
|
|
46
|
-
|
|
47
|
-
|
|
57
|
+
VALUE opts;
|
|
58
|
+
rb_scan_args(argc, argv, ":", &opts);
|
|
48
59
|
|
|
49
|
-
|
|
50
|
-
|
|
60
|
+
VALUE language = Qnil;
|
|
61
|
+
if (!NIL_P(opts))
|
|
62
|
+
language = rb_hash_aref(opts, ID2SYM(rb_intern("language")));
|
|
51
63
|
|
|
52
64
|
// if adding support for encoding, may want to change encoding returned from stem
|
|
53
|
-
stemmer->stemmer = sb_stemmer_new(
|
|
54
|
-
if (stemmer->stemmer == NULL)
|
|
55
|
-
|
|
65
|
+
stemmer->stemmer = sb_stemmer_new(GetAlgorithm(language), NULL);
|
|
66
|
+
if (stemmer->stemmer == NULL)
|
|
67
|
+
{
|
|
68
|
+
if (!NIL_P(language))
|
|
69
|
+
rb_raise(rb_eArgError, "unknown language: %" PRIsVALUE, language);
|
|
70
|
+
|
|
71
|
+
rb_raise(rb_eNoMemError, "failed to allocate memory");
|
|
56
72
|
}
|
|
57
73
|
|
|
74
|
+
// copy (after GetAlgorithm) in case string is modified in future
|
|
75
|
+
stemmer->language = rb_obj_dup(language);
|
|
76
|
+
|
|
58
77
|
return self;
|
|
59
78
|
}
|
|
60
79
|
|
|
61
80
|
static VALUE stemmer_stem(VALUE self, VALUE value)
|
|
62
81
|
{
|
|
63
|
-
stemmer_t
|
|
64
|
-
|
|
82
|
+
stemmer_t* stemmer;
|
|
83
|
+
GetStemmer(self, stemmer);
|
|
84
|
+
|
|
85
|
+
if (stemmer->stemmer == NULL)
|
|
86
|
+
rb_raise(rb_eRuntimeError, "stemmer not initialized");
|
|
65
87
|
|
|
66
|
-
|
|
88
|
+
const char* word = StringValuePtr(value);
|
|
89
|
+
long size = RSTRING_LEN(value);
|
|
90
|
+
if (size > INT_MAX)
|
|
91
|
+
rb_raise(rb_eArgError, "string exceeds max length");
|
|
67
92
|
|
|
68
|
-
const sb_symbol
|
|
69
|
-
int
|
|
70
|
-
const sb_symbol * pointer_out = sb_stemmer_stem(stemmer->stemmer, word, size);
|
|
93
|
+
const sb_symbol* pointer_out = sb_stemmer_stem(stemmer->stemmer, (const sb_symbol*) word, (int) size);
|
|
94
|
+
int length_out = sb_stemmer_length(stemmer->stemmer);
|
|
71
95
|
|
|
72
|
-
|
|
96
|
+
// place after last use of word
|
|
97
|
+
RB_GC_GUARD(value);
|
|
98
|
+
|
|
99
|
+
return rb_utf8_str_new((char*) pointer_out, (long) length_out);
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
static VALUE stemmer_initialize_copy(VALUE self, VALUE orig)
|
|
103
|
+
{
|
|
104
|
+
stemmer_t* stemmer;
|
|
105
|
+
GetStemmer(self, stemmer);
|
|
106
|
+
|
|
107
|
+
stemmer_t* orig_stemmer;
|
|
108
|
+
GetStemmer(orig, orig_stemmer);
|
|
109
|
+
|
|
110
|
+
if (stemmer->stemmer != NULL)
|
|
111
|
+
rb_raise(rb_eRuntimeError, "stemmer already initialized");
|
|
112
|
+
|
|
113
|
+
stemmer->stemmer = sb_stemmer_new(GetAlgorithm(orig_stemmer->language), NULL);
|
|
114
|
+
if (stemmer->stemmer == NULL)
|
|
115
|
+
rb_raise(rb_eNoMemError, "failed to allocate memory");
|
|
116
|
+
|
|
117
|
+
stemmer->language = orig_stemmer->language;
|
|
118
|
+
|
|
119
|
+
return self;
|
|
73
120
|
}
|
|
74
121
|
|
|
75
122
|
static VALUE stemmer_languages(VALUE klass)
|
|
76
123
|
{
|
|
77
124
|
VALUE out = rb_ary_new();
|
|
78
125
|
|
|
79
|
-
const char
|
|
80
|
-
while (*language != NULL)
|
|
81
|
-
rb_ary_push(out, rb_utf8_str_new_cstr(*language));
|
|
82
|
-
language++;
|
|
83
|
-
}
|
|
126
|
+
const char** language = sb_stemmer_list();
|
|
127
|
+
while (*language != NULL)
|
|
128
|
+
rb_ary_push(out, rb_utf8_str_new_cstr(*language++));
|
|
84
129
|
|
|
85
130
|
return out;
|
|
86
131
|
}
|
|
87
132
|
|
|
88
133
|
void Init_ext(void)
|
|
89
134
|
{
|
|
90
|
-
VALUE
|
|
91
|
-
VALUE
|
|
92
|
-
rb_define_alloc_func(
|
|
93
|
-
rb_define_method(
|
|
94
|
-
rb_define_method(
|
|
95
|
-
|
|
135
|
+
VALUE mMittens = rb_define_module("Mittens");
|
|
136
|
+
VALUE cStemmer = rb_define_class_under(mMittens, "Stemmer", rb_cObject);
|
|
137
|
+
rb_define_alloc_func(cStemmer, stemmer_allocate);
|
|
138
|
+
rb_define_method(cStemmer, "initialize", stemmer_initialize, -1);
|
|
139
|
+
rb_define_method(cStemmer, "stem", stemmer_stem, 1);
|
|
140
|
+
rb_define_method(cStemmer, "initialize_copy", stemmer_initialize_copy, 1);
|
|
141
|
+
rb_define_singleton_method(cStemmer, "languages", stemmer_languages, 0);
|
|
96
142
|
}
|
data/ext/mittens/extconf.rb
CHANGED
|
@@ -10,6 +10,8 @@ output, status = Open3.capture2(make_cmd, "CFLAGS=#{cflags}", chdir: vendor)
|
|
|
10
10
|
puts output
|
|
11
11
|
raise "Command failed" unless status.success?
|
|
12
12
|
|
|
13
|
+
append_cflags("-Wall -Wextra -Wpedantic -Wconversion")
|
|
14
|
+
|
|
13
15
|
$INCFLAGS += " -I$(srcdir)/../../vendor/snowball/include"
|
|
14
16
|
$LDFLAGS += " $(srcdir)/../../vendor/snowball/libstemmer.a"
|
|
15
17
|
|
data/lib/mittens/version.rb
CHANGED