gonzui 1.2-x86-mswin32-60
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.
- data/AUTHORS.txt +9 -0
- data/History.txt +5539 -0
- data/Manifest.txt +115 -0
- data/PostInstall.txt +17 -0
- data/README.rdoc +149 -0
- data/Rakefile +28 -0
- data/bin/gonzui-db +167 -0
- data/bin/gonzui-import +177 -0
- data/bin/gonzui-remove +58 -0
- data/bin/gonzui-search +68 -0
- data/bin/gonzui-server +176 -0
- data/bin/gonzui-update +53 -0
- data/data/gonzui/catalog/catalog.ja +80 -0
- data/data/gonzui/doc/favicon.ico +0 -0
- data/data/gonzui/doc/folder.png +0 -0
- data/data/gonzui/doc/gonzui.css +279 -0
- data/data/gonzui/doc/gonzui.js +111 -0
- data/data/gonzui/doc/text.png +0 -0
- data/data/gonzuirc.sample +29 -0
- data/ext/autopack/autopack.c +88 -0
- data/ext/autopack/extconf.rb +3 -0
- data/ext/delta/delta.c +147 -0
- data/ext/delta/extconf.rb +5 -0
- data/ext/texttokenizer/extconf.rb +5 -0
- data/ext/texttokenizer/texttokenizer.c +93 -0
- data/ext/xmlformatter/extconf.rb +5 -0
- data/ext/xmlformatter/xmlformatter.c +207 -0
- data/lib/gonzui.rb +59 -0
- data/lib/gonzui/apt.rb +193 -0
- data/lib/gonzui/autopack.so +0 -0
- data/lib/gonzui/bdbdbm.rb +118 -0
- data/lib/gonzui/cmdapp.rb +14 -0
- data/lib/gonzui/cmdapp/app.rb +175 -0
- data/lib/gonzui/cmdapp/search.rb +134 -0
- data/lib/gonzui/config.rb +117 -0
- data/lib/gonzui/content.rb +19 -0
- data/lib/gonzui/dbm.rb +673 -0
- data/lib/gonzui/deindexer.rb +162 -0
- data/lib/gonzui/delta.rb +49 -0
- data/lib/gonzui/delta.so +0 -0
- data/lib/gonzui/extractor.rb +347 -0
- data/lib/gonzui/fetcher.rb +309 -0
- data/lib/gonzui/gettext.rb +144 -0
- data/lib/gonzui/importer.rb +84 -0
- data/lib/gonzui/indexer.rb +316 -0
- data/lib/gonzui/info.rb +80 -0
- data/lib/gonzui/license.rb +100 -0
- data/lib/gonzui/logger.rb +48 -0
- data/lib/gonzui/monitor.rb +177 -0
- data/lib/gonzui/progressbar.rb +235 -0
- data/lib/gonzui/remover.rb +38 -0
- data/lib/gonzui/searcher.rb +330 -0
- data/lib/gonzui/searchquery.rb +235 -0
- data/lib/gonzui/searchresult.rb +111 -0
- data/lib/gonzui/texttokenizer.so +0 -0
- data/lib/gonzui/updater.rb +254 -0
- data/lib/gonzui/util.rb +415 -0
- data/lib/gonzui/vcs.rb +128 -0
- data/lib/gonzui/webapp.rb +25 -0
- data/lib/gonzui/webapp/advsearch.rb +123 -0
- data/lib/gonzui/webapp/filehandler.rb +24 -0
- data/lib/gonzui/webapp/jsfeed.rb +61 -0
- data/lib/gonzui/webapp/markup.rb +445 -0
- data/lib/gonzui/webapp/search.rb +269 -0
- data/lib/gonzui/webapp/servlet.rb +319 -0
- data/lib/gonzui/webapp/snippet.rb +155 -0
- data/lib/gonzui/webapp/source.rb +37 -0
- data/lib/gonzui/webapp/stat.rb +137 -0
- data/lib/gonzui/webapp/top.rb +63 -0
- data/lib/gonzui/webapp/uri.rb +140 -0
- data/lib/gonzui/webapp/webrick.rb +48 -0
- data/lib/gonzui/webapp/xmlformatter.so +0 -0
- data/script/console +10 -0
- data/script/destroy +14 -0
- data/script/generate +14 -0
- data/script/makemanifest.rb +21 -0
- data/tasks/extconf.rake +13 -0
- data/tasks/extconf/autopack.rake +43 -0
- data/tasks/extconf/delta.rake +43 -0
- data/tasks/extconf/texttokenizer.rake +43 -0
- data/tasks/extconf/xmlformatter.rake +43 -0
- data/test/_external_tools.rb +13 -0
- data/test/_test-util.rb +142 -0
- data/test/foo/Makefile.foo +66 -0
- data/test/foo/bar.c +5 -0
- data/test/foo/bar.h +6 -0
- data/test/foo/foo.c +25 -0
- data/test/foo/foo.spec +33 -0
- data/test/test_apt.rb +42 -0
- data/test/test_autopack_extn.rb +7 -0
- data/test/test_bdbdbm.rb +79 -0
- data/test/test_cmdapp-app.rb +35 -0
- data/test/test_cmdapp-search.rb +99 -0
- data/test/test_config.rb +28 -0
- data/test/test_content.rb +15 -0
- data/test/test_dbm.rb +171 -0
- data/test/test_deindexer.rb +50 -0
- data/test/test_delta.rb +66 -0
- data/test/test_extractor.rb +78 -0
- data/test/test_fetcher.rb +75 -0
- data/test/test_gettext.rb +50 -0
- data/test/test_gonzui.rb +11 -0
- data/test/test_helper.rb +10 -0
- data/test/test_importer.rb +56 -0
- data/test/test_indexer.rb +37 -0
- data/test/test_info.rb +82 -0
- data/test/test_license.rb +49 -0
- data/test/test_logger.rb +60 -0
- data/test/test_monitor.rb +23 -0
- data/test/test_searcher.rb +37 -0
- data/test/test_searchquery.rb +27 -0
- data/test/test_searchresult.rb +43 -0
- data/test/test_texttokenizer.rb +47 -0
- data/test/test_updater.rb +95 -0
- data/test/test_util.rb +149 -0
- data/test/test_vcs.rb +61 -0
- data/test/test_webapp-markup.rb +42 -0
- data/test/test_webapp-util.rb +19 -0
- data/test/test_webapp-xmlformatter.rb +19 -0
- metadata +292 -0
Binary file
|
@@ -0,0 +1,29 @@
|
|
1
|
+
{
|
2
|
+
:access_log_file => "access.log",
|
3
|
+
:base_mount_point => "",
|
4
|
+
:cache_directory => "gonzui.db/cache",
|
5
|
+
# :catalog_directory => "catalog",
|
6
|
+
:daemon => false,
|
7
|
+
:db_cache_size => 5242880,
|
8
|
+
:db_directory => "gonzui.db",
|
9
|
+
:default_results_per_page => 10,
|
10
|
+
# :doc_directory => "doc",
|
11
|
+
:encoding_preference => ["iso-2022-jp", "euc-jp", "utf-8", "shift_jis", "cp932", "iso-8859-1", "ascii"],
|
12
|
+
:exclude_pattern => /~$|\.bak$|CVS|\.svn|\.git/,
|
13
|
+
:gonzui_log_file => "gonzui.log",
|
14
|
+
:group => "Administrators",
|
15
|
+
:http_port => 46984,
|
16
|
+
:max_packages_per_page => 100,
|
17
|
+
:max_pages => 20,
|
18
|
+
:max_results_per_page => 50,
|
19
|
+
:max_words => 10,
|
20
|
+
:noindex_formats => [],
|
21
|
+
:nresults_candidates => [10, 20, 30, 50],
|
22
|
+
:pid_file => "gonzui.pid",
|
23
|
+
:quiet => false,
|
24
|
+
:site_title => "gonzui",
|
25
|
+
# :temporary_directory => "/tmp",
|
26
|
+
:user => "Administrator",
|
27
|
+
:utf8 => true,
|
28
|
+
:verbose => false,
|
29
|
+
}
|
@@ -0,0 +1,88 @@
|
|
1
|
+
/* -*- mode: C; indent-tabs-mode: nil; c-basic-offset: 2 c-style: "BSD" -*- */
|
2
|
+
/*
|
3
|
+
* autopack.c - C functions for AutoPack module.
|
4
|
+
*
|
5
|
+
* Copyright (C) 2005 Satoru Takabayashi <satoru@namazu.org>
|
6
|
+
* All rights reserved.
|
7
|
+
* This is free software with ABSOLUTELY NO WARRANTY.
|
8
|
+
*
|
9
|
+
* You can redistribute it and/or modify it under the terms of
|
10
|
+
* the GNU General Public License version 2.
|
11
|
+
*/
|
12
|
+
|
13
|
+
#include <ruby.h>
|
14
|
+
|
15
|
+
#ifndef RSTRING_PTR
|
16
|
+
# define RSTRING_PTR(s) (RSTRING(s)->ptr)
|
17
|
+
#endif
|
18
|
+
|
19
|
+
static VALUE
|
20
|
+
rb_autopack_pack_fixnum(VALUE obj, VALUE value)
|
21
|
+
{
|
22
|
+
int n;
|
23
|
+
unsigned char str[4];
|
24
|
+
if (TYPE(value) != T_FIXNUM) {
|
25
|
+
rb_raise(rb_eTypeError, "Fixnum expected");
|
26
|
+
}
|
27
|
+
n = FIX2INT(value);
|
28
|
+
str[0] = (n >> 24) & 0xff;
|
29
|
+
str[1] = (n >> 16) & 0xff;
|
30
|
+
str[2] = (n >> 8) & 0xff;
|
31
|
+
str[3] = n & 0xff;
|
32
|
+
return rb_str_new(str, 4);
|
33
|
+
}
|
34
|
+
|
35
|
+
static VALUE
|
36
|
+
rb_autopack_pack_id2(VALUE obj, VALUE id1, VALUE id2)
|
37
|
+
{
|
38
|
+
int n1, n2;
|
39
|
+
unsigned char str[8];
|
40
|
+
if (!(TYPE(id1) == T_FIXNUM && TYPE(id2) == T_FIXNUM)) {
|
41
|
+
rb_raise(rb_eTypeError, "Fixnum expected");
|
42
|
+
}
|
43
|
+
n1 = FIX2INT(id1);
|
44
|
+
n2 = FIX2INT(id2);
|
45
|
+
str[0] = (n1 >> 24) & 0xff;
|
46
|
+
str[1] = (n1 >> 16) & 0xff;
|
47
|
+
str[2] = (n1 >> 8) & 0xff;
|
48
|
+
str[3] = n1 & 0xff;
|
49
|
+
str[4] = (n2 >> 24) & 0xff;
|
50
|
+
str[5] = (n2 >> 16) & 0xff;
|
51
|
+
str[6] = (n2 >> 8) & 0xff;
|
52
|
+
str[7] = n2 & 0xff;
|
53
|
+
return rb_str_new(str, 8);
|
54
|
+
}
|
55
|
+
|
56
|
+
static VALUE
|
57
|
+
rb_autopack_unpack_fixnum(VALUE obj, VALUE value)
|
58
|
+
{
|
59
|
+
int n;
|
60
|
+
unsigned char *str;
|
61
|
+
if (TYPE(value) != T_STRING) {
|
62
|
+
rb_raise(rb_eTypeError, "String expected");
|
63
|
+
}
|
64
|
+
str = RSTRING_PTR(value);
|
65
|
+
n = (str[0] << 24) + (str[1] << 16) + (str[2] << 8) + str[3];
|
66
|
+
return INT2FIX(n);
|
67
|
+
}
|
68
|
+
|
69
|
+
void Init_autopack()
|
70
|
+
{
|
71
|
+
VALUE mGonzui, mAutoPack;
|
72
|
+
mGonzui = rb_define_module("Gonzui");
|
73
|
+
mAutoPack = rb_define_module_under(mGonzui, "AutoPack");
|
74
|
+
|
75
|
+
rb_define_module_function(mAutoPack, "pack_id",
|
76
|
+
rb_autopack_pack_fixnum, 1);
|
77
|
+
rb_define_module_function(mAutoPack, "unpack_id",
|
78
|
+
rb_autopack_unpack_fixnum, 1);
|
79
|
+
|
80
|
+
rb_define_module_function(mAutoPack, "pack_fixnum",
|
81
|
+
rb_autopack_pack_fixnum, 1);
|
82
|
+
rb_define_module_function(mAutoPack, "unpack_fixnum",
|
83
|
+
rb_autopack_unpack_fixnum, 1);
|
84
|
+
rb_define_module_function(mAutoPack, "pack_id2",
|
85
|
+
rb_autopack_pack_id2, 2);
|
86
|
+
}
|
87
|
+
|
88
|
+
|
data/ext/delta/delta.c
ADDED
@@ -0,0 +1,147 @@
|
|
1
|
+
/* -*- mode: C; indent-tabs-mode: nil; c-basic-offset: 2 c-style: "BSD" -*- */
|
2
|
+
/*
|
3
|
+
* delta.c - byte-oriented delta compression implementation
|
4
|
+
*
|
5
|
+
* Copyright (C) 2005 Satoru Takabayashi <satoru@namazu.org>
|
6
|
+
* Copyright (C) 2005 Keisuke Nishida <knishida@open-cobol.org>
|
7
|
+
* All rights reserved.
|
8
|
+
* This is free software with ABSOLUTELY NO WARRANTY.
|
9
|
+
*
|
10
|
+
* You can redistribute it and/or modify it under the terms of
|
11
|
+
* the GNU General Public License version 2.
|
12
|
+
*/
|
13
|
+
|
14
|
+
#include <ruby.h>
|
15
|
+
#include <assert.h>
|
16
|
+
|
17
|
+
#ifndef RARRAY_PTR
|
18
|
+
# define RARRAY_PTR(str) (RARRAY(str)->ptr)
|
19
|
+
#endif
|
20
|
+
#ifndef RARRAY_LEN
|
21
|
+
# define RARRAY_LEN(str) (RARRAY(str)->len)
|
22
|
+
#endif
|
23
|
+
|
24
|
+
typedef void (*CodeFunc)(VALUE *p, int i, int *prev);
|
25
|
+
|
26
|
+
static inline void
|
27
|
+
decode(VALUE *p, int i, int *prev)
|
28
|
+
{
|
29
|
+
int this;
|
30
|
+
if (TYPE(p[i]) != T_FIXNUM) {
|
31
|
+
rb_raise(rb_eTypeError, "wrong argument type (fixnum required)");
|
32
|
+
}
|
33
|
+
this = FIX2INT(p[i]);
|
34
|
+
p[i] = INT2FIX(this + *prev);
|
35
|
+
*prev = FIX2INT(p[i]);
|
36
|
+
}
|
37
|
+
|
38
|
+
static inline void
|
39
|
+
encode(VALUE *p, int i, int *prev)
|
40
|
+
{
|
41
|
+
int this;
|
42
|
+
if (TYPE(p[i]) != T_FIXNUM) {
|
43
|
+
rb_raise(rb_eTypeError, "wrong argument type (fixnum required)");
|
44
|
+
}
|
45
|
+
|
46
|
+
this = FIX2INT(p[i]);
|
47
|
+
p[i] = INT2FIX(this - *prev);
|
48
|
+
if (FIX2INT(p[i]) < 0) {
|
49
|
+
rb_raise(rb_eArgError, "Encode failed: value becomes minus");
|
50
|
+
}
|
51
|
+
*prev = this;
|
52
|
+
}
|
53
|
+
|
54
|
+
static VALUE
|
55
|
+
rb_delta_code_tuples(VALUE obj, VALUE list,
|
56
|
+
VALUE delta_size, VALUE unit_size, CodeFunc code)
|
57
|
+
{
|
58
|
+
enum { PREV_MAX = 128 };
|
59
|
+
int i, j;
|
60
|
+
int dsize;
|
61
|
+
int usize;
|
62
|
+
long len;
|
63
|
+
int prev[PREV_MAX];
|
64
|
+
VALUE *p;
|
65
|
+
|
66
|
+
if (!(TYPE(list) == T_ARRAY && TYPE(delta_size) == T_FIXNUM &&
|
67
|
+
TYPE(unit_size) == T_FIXNUM && FIX2INT(delta_size) < PREV_MAX ))
|
68
|
+
{
|
69
|
+
rb_raise(rb_eTypeError, "wrong argument type");
|
70
|
+
}
|
71
|
+
|
72
|
+
dsize = FIX2INT(delta_size);
|
73
|
+
usize = FIX2INT(unit_size);
|
74
|
+
len = RARRAY_LEN(list);
|
75
|
+
if (!(len % usize == 0 && dsize <= usize)) {
|
76
|
+
rb_raise(rb_eArgError, "wrong argument size");
|
77
|
+
}
|
78
|
+
p = RARRAY_PTR(list);
|
79
|
+
memset(prev, 0, sizeof(int) * dsize);
|
80
|
+
for (i = 0; i < len; i += usize) {
|
81
|
+
for (j = 0; j < dsize; j++) {
|
82
|
+
code(p, i + j, prev + j);
|
83
|
+
}
|
84
|
+
}
|
85
|
+
return list;
|
86
|
+
}
|
87
|
+
|
88
|
+
static VALUE
|
89
|
+
rb_delta_decode_tuples(VALUE obj, VALUE list,
|
90
|
+
VALUE delta_size, VALUE unit_size)
|
91
|
+
{
|
92
|
+
return rb_delta_code_tuples(obj, list, delta_size, unit_size, decode);
|
93
|
+
}
|
94
|
+
|
95
|
+
static VALUE
|
96
|
+
rb_delta_encode_tuples(VALUE obj, VALUE list,
|
97
|
+
VALUE delta_size, VALUE unit_size)
|
98
|
+
{
|
99
|
+
return rb_delta_code_tuples(obj, list, delta_size, unit_size, encode);
|
100
|
+
}
|
101
|
+
|
102
|
+
static VALUE
|
103
|
+
rb_delta_code_fixnums(VALUE obj, VALUE list, CodeFunc code)
|
104
|
+
{
|
105
|
+
int i;
|
106
|
+
long len;
|
107
|
+
VALUE *p;
|
108
|
+
int prev = 0;
|
109
|
+
if (TYPE(list) != T_ARRAY) {
|
110
|
+
rb_raise(rb_eTypeError, "wrong argument type");
|
111
|
+
}
|
112
|
+
p = RARRAY_PTR(list);
|
113
|
+
len = RARRAY_LEN(list);
|
114
|
+
for (i = 0; i < len; i++) {
|
115
|
+
code(p, i, &prev);
|
116
|
+
}
|
117
|
+
return list;
|
118
|
+
}
|
119
|
+
|
120
|
+
static VALUE
|
121
|
+
rb_delta_decode_fixnums(VALUE obj, VALUE list)
|
122
|
+
{
|
123
|
+
rb_delta_code_fixnums(obj, list, decode);
|
124
|
+
}
|
125
|
+
|
126
|
+
static VALUE
|
127
|
+
rb_delta_encode_fixnums(VALUE obj, VALUE list)
|
128
|
+
{
|
129
|
+
rb_delta_code_fixnums(obj, list, encode);
|
130
|
+
}
|
131
|
+
|
132
|
+
void Init_delta()
|
133
|
+
{
|
134
|
+
VALUE mGonzui, mDelta;
|
135
|
+
mGonzui = rb_define_module("Gonzui");
|
136
|
+
mDelta = rb_define_module_under(mGonzui, "DeltaDumper");
|
137
|
+
rb_define_module_function(mDelta, "encode_tuples",
|
138
|
+
rb_delta_encode_tuples, 3);
|
139
|
+
rb_define_module_function(mDelta, "decode_tuples",
|
140
|
+
rb_delta_decode_tuples, 3);
|
141
|
+
rb_define_module_function(mDelta, "encode_fixnums",
|
142
|
+
rb_delta_encode_fixnums, 1);
|
143
|
+
rb_define_module_function(mDelta, "decode_fixnums",
|
144
|
+
rb_delta_decode_fixnums, 1);
|
145
|
+
}
|
146
|
+
|
147
|
+
|
@@ -0,0 +1,93 @@
|
|
1
|
+
/* -*- mode: C; indent-tabs-mode: nil; c-basic-offset: 2 c-style: "BSD" -*- */
|
2
|
+
/*
|
3
|
+
* texttokenizer.c - a simple text tokenizer
|
4
|
+
*
|
5
|
+
* Copyright (C) 2005 Satoru Takabayashi <satoru@namazu.org>
|
6
|
+
* Copyright (C) 2005 Keisuke Nishida <knishida@open-cobol.org>
|
7
|
+
* All rights reserved.
|
8
|
+
* This is free software with ABSOLUTELY NO WARRANTY.
|
9
|
+
*
|
10
|
+
* You can redistribute it and/or modify it under the terms of
|
11
|
+
* the GNU General Public License version 2.
|
12
|
+
*
|
13
|
+
*
|
14
|
+
*/
|
15
|
+
|
16
|
+
#include <assert.h>
|
17
|
+
#include <ruby.h>
|
18
|
+
|
19
|
+
#ifndef RSTRING_PTR
|
20
|
+
# define RSTRING_PTR(s) (RSTRING(s)->ptr)
|
21
|
+
#endif
|
22
|
+
#ifndef RSTRING_LEN
|
23
|
+
# define RSTRING_LEN(s) (RSTRING(s)->len)
|
24
|
+
#endif
|
25
|
+
|
26
|
+
static inline int utf8len(const unsigned char *s, const unsigned char *eot)
|
27
|
+
{
|
28
|
+
int len = 0;
|
29
|
+
if (*s < 0x80) {
|
30
|
+
len = 1;
|
31
|
+
} else if ((s + 1 < eot) && (*s & 0xe0) == 0xc0) {
|
32
|
+
len = 2;
|
33
|
+
} else if ((s + 2 < eot) && (*s & 0xf0) == 0xe0) {
|
34
|
+
len = 3;
|
35
|
+
} else if ((s + 3 < eot) && (*s & 0xf8) == 0xf0) {
|
36
|
+
len = 4;
|
37
|
+
} else if ((s + 4 < eot) && (*s & 0xfc) == 0xf8) {
|
38
|
+
len = 5;
|
39
|
+
} else if ((s + 5 < eot) && (*s & 0xfe) == 0xfc) {
|
40
|
+
len = 6;
|
41
|
+
} else {
|
42
|
+
rb_raise(rb_eArgError, "invalid UTF-8 character");
|
43
|
+
}
|
44
|
+
return len;
|
45
|
+
}
|
46
|
+
|
47
|
+
static inline unsigned char *
|
48
|
+
skip(unsigned char *s, unsigned char *eot)
|
49
|
+
{
|
50
|
+
for (; s < eot; s++)
|
51
|
+
if (isalnum(*s) || *s >= 0x80)
|
52
|
+
break;
|
53
|
+
return s;
|
54
|
+
}
|
55
|
+
|
56
|
+
/*
|
57
|
+
* Iterate over each word.
|
58
|
+
* word: [a-zA-Z0-9]+ or single multi-byte UTF-8 character
|
59
|
+
*/
|
60
|
+
static VALUE texttokenizer_each_word(VALUE obj, VALUE text)
|
61
|
+
{
|
62
|
+
VALUE str;
|
63
|
+
unsigned char *s, *beg, *eot;
|
64
|
+
|
65
|
+
str = rb_obj_as_string(text);
|
66
|
+
beg = RSTRING_PTR(str);
|
67
|
+
eot = beg + RSTRING_LEN(str);
|
68
|
+
s = skip(beg, eot);
|
69
|
+
|
70
|
+
while (s < eot) {
|
71
|
+
unsigned char *b = s;
|
72
|
+
if (*s >= 0x80) {
|
73
|
+
s += utf8len(s, eot);
|
74
|
+
} else {
|
75
|
+
for (; s < eot; s++)
|
76
|
+
if (!((isalnum(*s) || *s == '_')))
|
77
|
+
break;
|
78
|
+
}
|
79
|
+
rb_yield_values(2, rb_str_new(b, s - b), INT2FIX(b - beg));
|
80
|
+
s = skip(s, eot);
|
81
|
+
}
|
82
|
+
return Qnil;
|
83
|
+
}
|
84
|
+
|
85
|
+
void Init_texttokenizer()
|
86
|
+
{
|
87
|
+
VALUE mGonzui, mTextTokenizer;
|
88
|
+
mGonzui = rb_define_module("Gonzui");
|
89
|
+
mTextTokenizer = rb_define_module_under(mGonzui, "TextTokenizer");
|
90
|
+
|
91
|
+
rb_define_module_function(mTextTokenizer, "each_word",
|
92
|
+
texttokenizer_each_word, 1);
|
93
|
+
}
|
@@ -0,0 +1,207 @@
|
|
1
|
+
/* -*- mode: C; indent-tabs-mode: nil; c-basic-offset: 2 c-style: "BSD" -*- */
|
2
|
+
/*
|
3
|
+
* xmlformatter.c - a simple class for generating XML texts
|
4
|
+
*
|
5
|
+
* Copyright (C) 2004-2005 Keisuke Nishida <knishida@open-cobol.org>
|
6
|
+
* All rights reserved.
|
7
|
+
* This is free software with ABSOLUTELY NO WARRANTY.
|
8
|
+
*
|
9
|
+
* You can redistribute it and/or modify it under the terms of
|
10
|
+
* the GNU General Public License version 2.
|
11
|
+
*/
|
12
|
+
|
13
|
+
#include <ruby.h>
|
14
|
+
#include <st.h>
|
15
|
+
|
16
|
+
#define BLOCK_SIZE (128 * 1024) /* 128 KB */
|
17
|
+
|
18
|
+
#ifndef RARRAY_PTR
|
19
|
+
# define RARRAY_PTR(str) (RARRAY(str)->ptr)
|
20
|
+
#endif
|
21
|
+
#ifndef RARRAY_LEN
|
22
|
+
# define RARRAY_LEN(str) (RARRAY(str)->len)
|
23
|
+
#endif
|
24
|
+
|
25
|
+
#ifndef RSTRING_PTR
|
26
|
+
# define RSTRING_PTR(s) (RSTRING(s)->ptr)
|
27
|
+
#endif
|
28
|
+
#ifndef RSTRING_LEN
|
29
|
+
# define RSTRING_LEN(s) (RSTRING(s)->len)
|
30
|
+
#endif
|
31
|
+
|
32
|
+
typedef struct gonzui_xmlformatter {
|
33
|
+
char *data;
|
34
|
+
size_t size;
|
35
|
+
size_t max_size;
|
36
|
+
} gonzui_xmlformatter_t;
|
37
|
+
|
38
|
+
static gonzui_xmlformatter_t *xmlformatter_new(void)
|
39
|
+
{
|
40
|
+
gonzui_xmlformatter_t *xf = malloc(sizeof(gonzui_xmlformatter_t));
|
41
|
+
memset(xf, 0, sizeof(gonzui_xmlformatter_t));
|
42
|
+
xf->max_size = BLOCK_SIZE;
|
43
|
+
xf->size = 0;
|
44
|
+
xf->data = malloc(xf->max_size);
|
45
|
+
return xf;
|
46
|
+
}
|
47
|
+
|
48
|
+
static void xmlformatter_write(gonzui_xmlformatter_t *xf, char *data)
|
49
|
+
{
|
50
|
+
long size = strlen(data);
|
51
|
+
if (xf->size + size > xf->max_size) {
|
52
|
+
xf->max_size += BLOCK_SIZE;
|
53
|
+
xf->data = realloc(xf->data, xf->max_size);
|
54
|
+
}
|
55
|
+
memcpy(xf->data + xf->size, data, size);
|
56
|
+
xf->size += size;
|
57
|
+
}
|
58
|
+
|
59
|
+
static void xmlformatter_write_obj(gonzui_xmlformatter_t *xf, VALUE obj)
|
60
|
+
{
|
61
|
+
char *p;
|
62
|
+
char *data;
|
63
|
+
size_t size;
|
64
|
+
if (SYMBOL_P(obj)) {
|
65
|
+
data = rb_id2name(SYM2ID(obj));
|
66
|
+
size = strlen(data);
|
67
|
+
} else {
|
68
|
+
VALUE s = rb_obj_as_string(obj);
|
69
|
+
data = RSTRING_PTR(s);
|
70
|
+
size = RSTRING_LEN(s);
|
71
|
+
}
|
72
|
+
if (xf->size + size * 6 > xf->max_size) {
|
73
|
+
xf->max_size += BLOCK_SIZE;
|
74
|
+
xf->data = realloc(xf->data, xf->max_size);
|
75
|
+
}
|
76
|
+
for (p = data; *p; p++) {
|
77
|
+
int c = *p;
|
78
|
+
if (c == '<') {
|
79
|
+
memcpy(xf->data + xf->size, "<", 4);
|
80
|
+
xf->size += 4;
|
81
|
+
} else if (c == '>') {
|
82
|
+
memcpy(xf->data + xf->size, ">", 4);
|
83
|
+
xf->size += 4;
|
84
|
+
} else if (c == '&') {
|
85
|
+
memcpy(xf->data + xf->size, "&", 5);
|
86
|
+
xf->size += 5;
|
87
|
+
} else if (c == '"') {
|
88
|
+
memcpy(xf->data + xf->size, """, 6);
|
89
|
+
xf->size += 6;
|
90
|
+
} else {
|
91
|
+
xf->data[xf->size++] = c;
|
92
|
+
}
|
93
|
+
}
|
94
|
+
}
|
95
|
+
|
96
|
+
static void xmlformatter_free(gonzui_xmlformatter_t *xf)
|
97
|
+
{
|
98
|
+
if (xf == NULL)
|
99
|
+
return;
|
100
|
+
free(xf->data);
|
101
|
+
free(xf);
|
102
|
+
}
|
103
|
+
|
104
|
+
static VALUE xmlformatter_s_allocate(VALUE klass)
|
105
|
+
{
|
106
|
+
return Data_Wrap_Struct(klass, NULL, xmlformatter_free, NULL);
|
107
|
+
}
|
108
|
+
|
109
|
+
static VALUE xmlformatter_initialize(VALUE self)
|
110
|
+
{
|
111
|
+
gonzui_xmlformatter_t *xf;
|
112
|
+
Data_Get_Struct(self, gonzui_xmlformatter_t, xf);
|
113
|
+
if (xf)
|
114
|
+
rb_raise(rb_eArgError, "called twice");
|
115
|
+
|
116
|
+
DATA_PTR(self) = xmlformatter_new();
|
117
|
+
return self;
|
118
|
+
}
|
119
|
+
|
120
|
+
static VALUE xmlformatter_add_xml_declaration(VALUE self)
|
121
|
+
{
|
122
|
+
gonzui_xmlformatter_t *xf;
|
123
|
+
Data_Get_Struct(self, gonzui_xmlformatter_t, xf);
|
124
|
+
if (xf)
|
125
|
+
xmlformatter_write(xf, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n");
|
126
|
+
return Qnil;
|
127
|
+
}
|
128
|
+
|
129
|
+
static VALUE xmlformatter_add_doctype(VALUE self)
|
130
|
+
{
|
131
|
+
gonzui_xmlformatter_t *xf;
|
132
|
+
Data_Get_Struct(self, gonzui_xmlformatter_t, xf);
|
133
|
+
if (xf)
|
134
|
+
xmlformatter_write(xf, "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Strict//EN\"\n"
|
135
|
+
" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd\">\n");
|
136
|
+
return Qnil;
|
137
|
+
}
|
138
|
+
|
139
|
+
static int format_hash(VALUE key, VALUE val, gonzui_xmlformatter_t *xf)
|
140
|
+
{
|
141
|
+
xmlformatter_write(xf, " ");
|
142
|
+
xmlformatter_write_obj(xf, key);
|
143
|
+
xmlformatter_write(xf, "=\"");
|
144
|
+
xmlformatter_write_obj(xf, val);
|
145
|
+
xmlformatter_write(xf, "\"");
|
146
|
+
return ST_CONTINUE;
|
147
|
+
}
|
148
|
+
|
149
|
+
static void format(gonzui_xmlformatter_t *xf, VALUE xml)
|
150
|
+
{
|
151
|
+
if (rb_type(xml) == T_ARRAY) {
|
152
|
+
/* array */
|
153
|
+
long i = 0;
|
154
|
+
long len = RARRAY_LEN(xml);
|
155
|
+
VALUE *a = RARRAY_PTR(xml);
|
156
|
+
VALUE tag;
|
157
|
+
|
158
|
+
if (len == 0)
|
159
|
+
rb_raise(rb_eArgError, "too short");
|
160
|
+
|
161
|
+
/* start tag */
|
162
|
+
tag = a[i++];
|
163
|
+
xmlformatter_write(xf, "<");
|
164
|
+
xmlformatter_write_obj(xf, tag);
|
165
|
+
|
166
|
+
/* attributes */
|
167
|
+
if (i < len && rb_type(a[i]) == T_HASH)
|
168
|
+
st_foreach(RHASH(a[i++])->tbl, format_hash, (st_data_t)xf);
|
169
|
+
|
170
|
+
/* body, end tag */
|
171
|
+
if (i >= len) {
|
172
|
+
xmlformatter_write(xf, "\n/>");
|
173
|
+
} else {
|
174
|
+
xmlformatter_write(xf, "\n>");
|
175
|
+
for (; i < len; i++)
|
176
|
+
format(xf, a[i]);
|
177
|
+
xmlformatter_write(xf, "</");
|
178
|
+
xmlformatter_write_obj(xf, tag);
|
179
|
+
xmlformatter_write(xf, "\n>");
|
180
|
+
}
|
181
|
+
} else {
|
182
|
+
/* other nobject */
|
183
|
+
xmlformatter_write_obj(xf, xml);
|
184
|
+
}
|
185
|
+
}
|
186
|
+
|
187
|
+
static VALUE xmlformatter_format(VALUE self, VALUE xml)
|
188
|
+
{
|
189
|
+
gonzui_xmlformatter_t *xf;
|
190
|
+
Data_Get_Struct(self, gonzui_xmlformatter_t, xf);
|
191
|
+
if (xf == NULL)
|
192
|
+
return Qnil;
|
193
|
+
Check_Type(xml, T_ARRAY);
|
194
|
+
format(xf, xml);
|
195
|
+
return rb_str_new(xf->data, xf->size);
|
196
|
+
}
|
197
|
+
|
198
|
+
void Init_xmlformatter()
|
199
|
+
{
|
200
|
+
VALUE Gonzui = rb_define_module("Gonzui");
|
201
|
+
VALUE XMLFormatter = rb_define_class_under(Gonzui, "XMLFormatter", rb_cData);
|
202
|
+
rb_define_alloc_func(XMLFormatter, xmlformatter_s_allocate);
|
203
|
+
rb_define_method(XMLFormatter, "initialize", xmlformatter_initialize, 0);
|
204
|
+
rb_define_method(XMLFormatter, "add_xml_declaration", xmlformatter_add_xml_declaration, 0);
|
205
|
+
rb_define_method(XMLFormatter, "add_doctype", xmlformatter_add_doctype, 0);
|
206
|
+
rb_define_method(XMLFormatter, "format", xmlformatter_format, 1);
|
207
|
+
}
|