rroonga 2.0.0 → 2.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/Rakefile +3 -2
- data/ext/groonga/rb-grn-expression.c +4 -3
- data/ext/groonga/rb-grn-object.c +13 -0
- data/ext/groonga/rb-grn-snippet.c +32 -126
- data/ext/groonga/rb-grn.h +14 -11
- data/rroonga-build.rb +1 -1
- metadata +98 -250
- data/README.textile +0 -73
- data/TODO +0 -0
- data/bug.rb +0 -36
- data/crash.rb +0 -17
- data/ext/groonga/Makefile +0 -260
- data/ext/groonga/groonga.so +0 -0
- data/ext/groonga/rb-grn-accessor.o +0 -0
- data/ext/groonga/rb-grn-array-cursor.o +0 -0
- data/ext/groonga/rb-grn-array.o +0 -0
- data/ext/groonga/rb-grn-column.o +0 -0
- data/ext/groonga/rb-grn-context.o +0 -0
- data/ext/groonga/rb-grn-database.o +0 -0
- data/ext/groonga/rb-grn-double-array-trie-cursor.o +0 -0
- data/ext/groonga/rb-grn-double-array-trie.o +0 -0
- data/ext/groonga/rb-grn-encoding-support.o +0 -0
- data/ext/groonga/rb-grn-encoding.o +0 -0
- data/ext/groonga/rb-grn-exception.o +0 -0
- data/ext/groonga/rb-grn-expression-builder.o +0 -0
- data/ext/groonga/rb-grn-expression.o +0 -0
- data/ext/groonga/rb-grn-fix-size-column.o +0 -0
- data/ext/groonga/rb-grn-hash-cursor.o +0 -0
- data/ext/groonga/rb-grn-hash.o +0 -0
- data/ext/groonga/rb-grn-index-column.o +0 -0
- data/ext/groonga/rb-grn-index-cursor.o +0 -0
- data/ext/groonga/rb-grn-logger.o +0 -0
- data/ext/groonga/rb-grn-object.o +0 -0
- data/ext/groonga/rb-grn-operator.o +0 -0
- data/ext/groonga/rb-grn-patricia-trie-cursor.o +0 -0
- data/ext/groonga/rb-grn-patricia-trie.o +0 -0
- data/ext/groonga/rb-grn-plugin.o +0 -0
- data/ext/groonga/rb-grn-posting.o +0 -0
- data/ext/groonga/rb-grn-procedure.o +0 -0
- data/ext/groonga/rb-grn-record.o +0 -0
- data/ext/groonga/rb-grn-snippet.o +0 -0
- data/ext/groonga/rb-grn-table-cursor-key-support.o +0 -0
- data/ext/groonga/rb-grn-table-cursor.o +0 -0
- data/ext/groonga/rb-grn-table-key-support.o +0 -0
- data/ext/groonga/rb-grn-table.o +0 -0
- data/ext/groonga/rb-grn-type.o +0 -0
- data/ext/groonga/rb-grn-utils.o +0 -0
- data/ext/groonga/rb-grn-variable-size-column.o +0 -0
- data/ext/groonga/rb-grn-variable.o +0 -0
- data/ext/groonga/rb-grn-view-accessor.o +0 -0
- data/ext/groonga/rb-grn-view-cursor.o +0 -0
- data/ext/groonga/rb-grn-view-record.o +0 -0
- data/ext/groonga/rb-grn-view.o +0 -0
- data/ext/groonga/rb-groonga.o +0 -0
data/Rakefile
CHANGED
@@ -87,11 +87,12 @@ Jeweler::Tasks.new do |_spec|
|
|
87
87
|
spec.license = "LGPLv2"
|
88
88
|
spec.files = FileList["{lib,benchmark,misc}/**/*.rb",
|
89
89
|
"bin/*",
|
90
|
-
"
|
90
|
+
"extconf.rb",
|
91
|
+
"rroonga-build.rb",
|
91
92
|
"example/*.rb",
|
92
93
|
"Rakefile",
|
93
94
|
"Gemfile",
|
94
|
-
"ext
|
95
|
+
"ext/**/*.{c,h,rb,def}"]
|
95
96
|
spec.test_files = FileList["test/**/*.rb"]
|
96
97
|
end
|
97
98
|
|
@@ -643,6 +643,7 @@ rb_grn_expression_snippet (int argc, VALUE *argv, VALUE self)
|
|
643
643
|
VALUE rb_width, rb_max_results, rb_tags;
|
644
644
|
VALUE rb_html_escape;
|
645
645
|
VALUE *rb_tag_values;
|
646
|
+
VALUE related_object;
|
646
647
|
unsigned int i;
|
647
648
|
int flags = GRN_SNIP_COPY_TAG;
|
648
649
|
unsigned int width = 100;
|
@@ -723,10 +724,10 @@ rb_grn_expression_snippet (int argc, VALUE *argv, VALUE self)
|
|
723
724
|
(const char **)open_tags, open_tag_lengths,
|
724
725
|
(const char **)close_tags, close_tag_lengths,
|
725
726
|
mapping);
|
726
|
-
|
727
|
-
|
727
|
+
related_object = rb_ary_new3(2, self, rb_ary_new4(argc, argv));
|
728
|
+
rb_grn_context_check(context, related_object);
|
728
729
|
|
729
|
-
return
|
730
|
+
return GRNOBJECT2RVAL(Qnil, context, (grn_obj *)snippet, GRN_TRUE);
|
730
731
|
}
|
731
732
|
|
732
733
|
void
|
data/ext/groonga/rb-grn-object.c
CHANGED
@@ -142,6 +142,10 @@ rb_grn_object_run_finalizer (grn_ctx *context, grn_obj *grn_object,
|
|
142
142
|
rb_grn_expression_finalizer(context, grn_object,
|
143
143
|
RB_GRN_EXPRESSION(rb_grn_object));
|
144
144
|
break;
|
145
|
+
case GRN_SNIP:
|
146
|
+
rb_grn_snippet_finalizer(context, grn_object,
|
147
|
+
RB_GRN_SNIPPET(rb_grn_object));
|
148
|
+
break;
|
145
149
|
default:
|
146
150
|
rb_raise(rb_eTypeError,
|
147
151
|
"unsupported groonga object type for finalizer: %s(%#x)",
|
@@ -239,6 +243,9 @@ rb_grn_object_to_ruby_class (grn_obj *object)
|
|
239
243
|
case GRN_ACCESSOR_VIEW:
|
240
244
|
klass = rb_cGrnViewAccessor;
|
241
245
|
break;
|
246
|
+
case GRN_SNIP:
|
247
|
+
klass = rb_cGrnSnippet;
|
248
|
+
break;
|
242
249
|
case GRN_PROC:
|
243
250
|
klass = rb_cGrnProcedure;
|
244
251
|
break;
|
@@ -441,6 +448,12 @@ rb_grn_object_assign (VALUE klass, VALUE self, VALUE rb_context,
|
|
441
448
|
context, object);
|
442
449
|
rb_grn_expression_bind(RB_GRN_EXPRESSION(rb_grn_object),
|
443
450
|
context, object);
|
451
|
+
} else if (klass == rb_cGrnSnippet) {
|
452
|
+
rb_grn_object = ALLOC(RbGrnSnippet);
|
453
|
+
rb_grn_object_bind_common(klass, self, rb_context, rb_grn_object,
|
454
|
+
context, object);
|
455
|
+
rb_grn_snippet_bind(RB_GRN_SNIPPET(rb_grn_object),
|
456
|
+
context, object);
|
444
457
|
} else {
|
445
458
|
rb_raise(rb_eTypeError,
|
446
459
|
"unsupported groonga object type for assignment: %s(%#x)",
|
@@ -1,6 +1,6 @@
|
|
1
1
|
/* -*- coding: utf-8; c-file-style: "ruby" -*- */
|
2
2
|
/*
|
3
|
-
Copyright (C) 2009-
|
3
|
+
Copyright (C) 2009-2012 Kouhei Sutou <kou@clear-code.com>
|
4
4
|
|
5
5
|
This library is free software; you can redistribute it and/or
|
6
6
|
modify it under the terms of the GNU Lesser General Public
|
@@ -18,15 +18,7 @@
|
|
18
18
|
|
19
19
|
#include "rb-grn.h"
|
20
20
|
|
21
|
-
#define SELF(object) (
|
22
|
-
|
23
|
-
typedef struct _RbGrnSnippet RbGrnSnippet;
|
24
|
-
struct _RbGrnSnippet
|
25
|
-
{
|
26
|
-
grn_ctx *context;
|
27
|
-
grn_snip *snippet;
|
28
|
-
grn_bool owner;
|
29
|
-
};
|
21
|
+
#define SELF(object) ((RbGrnSnippet *)DATA_PTR(object))
|
30
22
|
|
31
23
|
VALUE rb_cGrnSnippet;
|
32
24
|
|
@@ -36,67 +28,30 @@ VALUE rb_cGrnSnippet;
|
|
36
28
|
* スニペット(検索語周辺のテキスト)を生成するためのオブジェクト。
|
37
29
|
*/
|
38
30
|
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
RbGrnSnippet *rb_grn_snippet;
|
43
|
-
|
44
|
-
if (!RVAL2CBOOL(rb_obj_is_kind_of(object, rb_cGrnSnippet))) {
|
45
|
-
rb_raise(rb_eTypeError, "not a groonga snippet");
|
46
|
-
}
|
47
|
-
|
48
|
-
Data_Get_Struct(object, RbGrnSnippet, rb_grn_snippet);
|
49
|
-
if (!rb_grn_snippet)
|
50
|
-
rb_raise(rb_eGrnError, "groonga snippet is NULL");
|
51
|
-
|
52
|
-
return rb_grn_snippet;
|
53
|
-
}
|
54
|
-
|
55
|
-
grn_snip *
|
56
|
-
rb_grn_snippet_from_ruby_object (VALUE object)
|
31
|
+
void
|
32
|
+
rb_grn_snippet_finalizer (grn_ctx *context, grn_obj *object,
|
33
|
+
RbGrnSnippet *rb_grn_snippet)
|
57
34
|
{
|
58
|
-
|
59
|
-
return NULL;
|
60
|
-
|
61
|
-
return SELF(object)->snippet;
|
35
|
+
rb_grn_context_unregister_floating_object(RB_GRN_OBJECT(rb_grn_snippet));
|
62
36
|
}
|
63
37
|
|
64
|
-
|
65
|
-
|
38
|
+
void
|
39
|
+
rb_grn_snippet_bind (RbGrnSnippet *rb_grn_snippet,
|
40
|
+
grn_ctx *context, grn_obj *snippet)
|
66
41
|
{
|
67
|
-
RbGrnSnippet *rb_grn_snippet = object;
|
68
|
-
|
69
|
-
if (!rb_grn_exited &&
|
70
|
-
rb_grn_snippet->owner &&
|
71
|
-
rb_grn_snippet->context && rb_grn_snippet->snippet)
|
72
|
-
grn_snip_close(rb_grn_snippet->context,
|
73
|
-
rb_grn_snippet->snippet);
|
74
|
-
|
75
|
-
xfree(object);
|
76
42
|
}
|
77
43
|
|
78
|
-
|
79
|
-
|
80
|
-
|
44
|
+
void
|
45
|
+
rb_grn_snippet_deconstruct (RbGrnSnippet *rb_grn_snippet,
|
46
|
+
grn_obj **snippet,
|
47
|
+
grn_ctx **context)
|
81
48
|
{
|
82
|
-
|
83
|
-
|
84
|
-
if (!snippet)
|
85
|
-
return Qnil;
|
49
|
+
RbGrnObject *rb_grn_object;
|
86
50
|
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
return Data_Wrap_Struct(rb_cGrnSnippet, NULL,
|
93
|
-
rb_rb_grn_snippet_free, rb_grn_snippet);
|
94
|
-
}
|
95
|
-
|
96
|
-
static VALUE
|
97
|
-
rb_grn_snippet_alloc (VALUE klass)
|
98
|
-
{
|
99
|
-
return Data_Wrap_Struct(klass, NULL, rb_rb_grn_snippet_free, NULL);
|
51
|
+
rb_grn_object = RB_GRN_OBJECT(rb_grn_snippet);
|
52
|
+
rb_grn_object_deconstruct(rb_grn_object, snippet, context,
|
53
|
+
NULL, NULL,
|
54
|
+
NULL, NULL);
|
100
55
|
}
|
101
56
|
|
102
57
|
/*
|
@@ -141,7 +96,6 @@ rb_grn_snippet_alloc (VALUE klass)
|
|
141
96
|
static VALUE
|
142
97
|
rb_grn_snippet_initialize (int argc, VALUE *argv, VALUE self)
|
143
98
|
{
|
144
|
-
RbGrnSnippet *rb_grn_snippet;
|
145
99
|
grn_ctx *context = NULL;
|
146
100
|
grn_snip *snippet = NULL;
|
147
101
|
VALUE options;
|
@@ -202,11 +156,8 @@ rb_grn_snippet_initialize (int argc, VALUE *argv, VALUE self)
|
|
202
156
|
mapping);
|
203
157
|
rb_grn_context_check(context, rb_ary_new4(argc, argv));
|
204
158
|
|
205
|
-
|
206
|
-
DATA_PTR(self)
|
207
|
-
rb_grn_snippet->context = context;
|
208
|
-
rb_grn_snippet->snippet = snippet;
|
209
|
-
rb_grn_snippet->owner = GRN_TRUE;
|
159
|
+
rb_grn_object_assign(Qnil, self, rb_context, context, (grn_obj *)snippet);
|
160
|
+
rb_grn_context_register_floating_object(DATA_PTR(self));
|
210
161
|
|
211
162
|
rb_iv_set(self, "@context", rb_context);
|
212
163
|
|
@@ -234,22 +185,17 @@ rb_grn_snippet_initialize (int argc, VALUE *argv, VALUE self)
|
|
234
185
|
static VALUE
|
235
186
|
rb_grn_snippet_add_keyword (int argc, VALUE *argv, VALUE self)
|
236
187
|
{
|
237
|
-
|
188
|
+
grn_ctx *context;
|
189
|
+
grn_obj *snippet;
|
238
190
|
grn_rc rc;
|
239
191
|
VALUE rb_keyword, options;
|
240
192
|
VALUE rb_open_tag, rb_close_tag;
|
241
193
|
char *keyword, *open_tag = NULL, *close_tag = NULL;
|
242
194
|
unsigned int keyword_length, open_tag_length = 0, close_tag_length = 0;
|
243
195
|
|
244
|
-
|
245
|
-
|
246
|
-
rb_grn_snippet = SELF(self);
|
196
|
+
rb_grn_snippet_deconstruct(SELF(self), &snippet, &context);
|
247
197
|
|
248
|
-
|
249
|
-
rb_raise(rb_eGrnClosed,
|
250
|
-
"can't access already closed groonga object: %s",
|
251
|
-
rb_grn_inspect(CLASS_OF(self)));
|
252
|
-
}
|
198
|
+
rb_scan_args(argc, argv, "11", &rb_keyword, &options);
|
253
199
|
|
254
200
|
keyword = StringValuePtr(rb_keyword);
|
255
201
|
keyword_length = RSTRING_LEN(rb_keyword);
|
@@ -269,8 +215,7 @@ rb_grn_snippet_add_keyword (int argc, VALUE *argv, VALUE self)
|
|
269
215
|
close_tag_length = RSTRING_LEN(rb_close_tag);
|
270
216
|
}
|
271
217
|
|
272
|
-
rc = grn_snip_add_cond(
|
273
|
-
rb_grn_snippet->snippet,
|
218
|
+
rc = grn_snip_add_cond(context, (grn_snip *)snippet,
|
274
219
|
keyword, keyword_length,
|
275
220
|
open_tag, open_tag_length,
|
276
221
|
close_tag, close_tag_length);
|
@@ -288,39 +233,30 @@ rb_grn_snippet_add_keyword (int argc, VALUE *argv, VALUE self)
|
|
288
233
|
static VALUE
|
289
234
|
rb_grn_snippet_execute (VALUE self, VALUE rb_string)
|
290
235
|
{
|
291
|
-
RbGrnSnippet *rb_grn_snippet;
|
292
236
|
grn_rc rc;
|
293
237
|
grn_ctx *context;
|
294
|
-
|
238
|
+
grn_obj *snippet;
|
295
239
|
char *string;
|
296
240
|
unsigned int string_length;
|
297
241
|
unsigned int i, n_results, max_tagged_length;
|
298
242
|
VALUE rb_results;
|
299
243
|
char *result;
|
300
244
|
|
245
|
+
rb_grn_snippet_deconstruct(SELF(self), &snippet, &context);
|
246
|
+
|
301
247
|
if (TYPE(rb_string) != T_STRING) {
|
302
248
|
rb_raise(rb_eGrnInvalidArgument,
|
303
249
|
"snippet text must be String: <%s>",
|
304
250
|
rb_grn_inspect(rb_string));
|
305
251
|
}
|
306
252
|
|
307
|
-
rb_grn_snippet = SELF(self);
|
308
|
-
context = rb_grn_snippet->context;
|
309
|
-
snippet = rb_grn_snippet->snippet;
|
310
|
-
|
311
|
-
if (!snippet) {
|
312
|
-
rb_raise(rb_eGrnClosed,
|
313
|
-
"can't access already closed groonga object: %s",
|
314
|
-
rb_grn_inspect(CLASS_OF(self)));
|
315
|
-
}
|
316
|
-
|
317
253
|
#ifdef HAVE_RUBY_ENCODING_H
|
318
254
|
rb_string = rb_grn_context_rb_string_encode(context, rb_string);
|
319
255
|
#endif
|
320
256
|
string = StringValuePtr(rb_string);
|
321
257
|
string_length = RSTRING_LEN(rb_string);
|
322
258
|
|
323
|
-
rc = grn_snip_exec(context, snippet, string, string_length,
|
259
|
+
rc = grn_snip_exec(context, (grn_snip *)snippet, string, string_length,
|
324
260
|
&n_results, &max_tagged_length);
|
325
261
|
rb_grn_context_check(context, self);
|
326
262
|
rb_grn_rc_check(rc, self);
|
@@ -331,7 +267,8 @@ rb_grn_snippet_execute (VALUE self, VALUE rb_string)
|
|
331
267
|
VALUE rb_result;
|
332
268
|
unsigned result_length;
|
333
269
|
|
334
|
-
rc = grn_snip_get_result(context, snippet,
|
270
|
+
rc = grn_snip_get_result(context, (grn_snip *)snippet,
|
271
|
+
i, result, &result_length);
|
335
272
|
rb_grn_rc_check(rc, self);
|
336
273
|
rb_result = rb_grn_context_rb_string_new(context, result, result_length);
|
337
274
|
rb_ary_push(rb_results, rb_result);
|
@@ -340,39 +277,10 @@ rb_grn_snippet_execute (VALUE self, VALUE rb_string)
|
|
340
277
|
return rb_results;
|
341
278
|
}
|
342
279
|
|
343
|
-
/*
|
344
|
-
* Document-method: close
|
345
|
-
*
|
346
|
-
* call-seq:
|
347
|
-
* snippet.close
|
348
|
-
*
|
349
|
-
* _snippet_ が使用しているリソースを開放する。これ以降 _snippet_ を
|
350
|
-
* 使うことはできない。
|
351
|
-
*/
|
352
|
-
static VALUE
|
353
|
-
rb_grn_snippet_close (VALUE self)
|
354
|
-
{
|
355
|
-
RbGrnSnippet *rb_grn_snippet;
|
356
|
-
grn_ctx *context;
|
357
|
-
grn_snip *snippet;
|
358
|
-
|
359
|
-
rb_grn_snippet = SELF(self);
|
360
|
-
context = rb_grn_snippet->context;
|
361
|
-
snippet = rb_grn_snippet->snippet;
|
362
|
-
if (context && snippet) {
|
363
|
-
grn_snip_close(context, snippet);
|
364
|
-
rb_grn_snippet->context = NULL;
|
365
|
-
rb_grn_snippet->snippet = NULL;
|
366
|
-
}
|
367
|
-
|
368
|
-
return Qnil;
|
369
|
-
}
|
370
|
-
|
371
280
|
void
|
372
281
|
rb_grn_init_snippet (VALUE mGrn)
|
373
282
|
{
|
374
|
-
rb_cGrnSnippet = rb_define_class_under(mGrn, "Snippet",
|
375
|
-
rb_define_alloc_func(rb_cGrnSnippet, rb_grn_snippet_alloc);
|
283
|
+
rb_cGrnSnippet = rb_define_class_under(mGrn, "Snippet", rb_cGrnObject);
|
376
284
|
|
377
285
|
rb_define_method(rb_cGrnSnippet, "initialize",
|
378
286
|
rb_grn_snippet_initialize, -1);
|
@@ -380,6 +288,4 @@ rb_grn_init_snippet (VALUE mGrn)
|
|
380
288
|
rb_grn_snippet_add_keyword, -1);
|
381
289
|
rb_define_method(rb_cGrnSnippet, "execute",
|
382
290
|
rb_grn_snippet_execute, 1);
|
383
|
-
rb_define_method(rb_cGrnSnippet, "close",
|
384
|
-
rb_grn_snippet_close, 0);
|
385
291
|
}
|
data/ext/groonga/rb-grn.h
CHANGED
@@ -72,7 +72,7 @@ RB_GRN_BEGIN_DECLS
|
|
72
72
|
|
73
73
|
#define RB_GRN_MAJOR_VERSION 2
|
74
74
|
#define RB_GRN_MINOR_VERSION 0
|
75
|
-
#define RB_GRN_MICRO_VERSION
|
75
|
+
#define RB_GRN_MICRO_VERSION 1
|
76
76
|
|
77
77
|
#define RB_GRN_QUERY_DEFAULT_MAX_EXPRESSIONS 32
|
78
78
|
|
@@ -88,6 +88,7 @@ RB_GRN_BEGIN_DECLS
|
|
88
88
|
#define RB_GRN_ACCESSOR(object) ((RbGrnAccessor *)(object))
|
89
89
|
#define RB_GRN_ACCESSOR_VIEW(object) ((RbGrnAccessor *)(object))
|
90
90
|
#define RB_GRN_EXPRESSION(object) ((RbGrnExpression *)(object))
|
91
|
+
#define RB_GRN_SNIPPET(object) ((RbGrnSnippet *)(object))
|
91
92
|
#define RB_GRN_UNBIND_FUNCTION(function) ((RbGrnUnbindFunction)(function))
|
92
93
|
|
93
94
|
typedef void (*RbGrnUnbindFunction) (void *object);
|
@@ -188,6 +189,12 @@ struct _RbGrnExpression
|
|
188
189
|
grn_obj *value;
|
189
190
|
};
|
190
191
|
|
192
|
+
typedef struct _RbGrnSnippet RbGrnSnippet;
|
193
|
+
struct _RbGrnSnippet
|
194
|
+
{
|
195
|
+
RbGrnObject parent;
|
196
|
+
};
|
197
|
+
|
191
198
|
typedef struct _RbGrnPlugin RbGrnPlugin;
|
192
199
|
struct _RbGrnPlugin
|
193
200
|
{
|
@@ -597,11 +604,6 @@ VALUE rb_grn_column_expression_builder_build
|
|
597
604
|
#define RVAL2GRNVARIABLE(object, context) \
|
598
605
|
(rb_grn_variable_from_ruby_object(object, context))
|
599
606
|
|
600
|
-
#define GRNSNIPPET2RVAL(context, snippet, owner) \
|
601
|
-
(rb_grn_snippet_to_ruby_object(context, snippet, owner))
|
602
|
-
#define RVAL2GRNSNIPPET(snippet) \
|
603
|
-
(rb_grn_snippet_from_ruby_object(snippet))
|
604
|
-
|
605
607
|
|
606
608
|
grn_encoding rb_grn_encoding_from_ruby_object (VALUE object,
|
607
609
|
grn_ctx *context);
|
@@ -731,11 +733,12 @@ VALUE rb_grn_obj_to_ruby_object (VALUE klass,
|
|
731
733
|
grn_obj *obj,
|
732
734
|
VALUE related_object);
|
733
735
|
|
734
|
-
|
735
|
-
|
736
|
-
|
737
|
-
|
738
|
-
|
736
|
+
void rb_grn_snippet_bind (RbGrnSnippet *rb_grn_snippet,
|
737
|
+
grn_ctx *context,
|
738
|
+
grn_obj *snippet);
|
739
|
+
void rb_grn_snippet_finalizer (grn_ctx *context,
|
740
|
+
grn_obj *grn_object,
|
741
|
+
RbGrnSnippet *rb_grn_snippet);
|
739
742
|
RB_GRN_END_DECLS
|
740
743
|
|
741
744
|
#endif
|