gonzui 1.2
Sign up to get free protection for your applications and to get access to all the features.
- 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/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/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/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/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 +291 -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
|
+
}
|