sprsquish-blather 0.1 → 0.2.3

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.
Files changed (73) hide show
  1. data/LICENSE +2 -0
  2. data/README.rdoc +100 -0
  3. data/Rakefile +110 -0
  4. data/examples/drb_client.rb +5 -0
  5. data/examples/echo.rb +18 -0
  6. data/ext/extconf.rb +65 -0
  7. data/ext/push_parser.c +231 -0
  8. data/lib/blather/client.rb +219 -44
  9. data/lib/blather/{core/sugar.rb → core_ext/active_support.rb} +25 -13
  10. data/lib/blather/core_ext/libxml.rb +28 -0
  11. data/lib/blather/errors/sasl_error.rb +87 -0
  12. data/lib/blather/errors/stanza_error.rb +262 -0
  13. data/lib/blather/errors/stream_error.rb +253 -0
  14. data/lib/blather/errors.rb +48 -0
  15. data/lib/blather/{core/jid.rb → jid.rb} +15 -26
  16. data/lib/blather/{core/roster.rb → roster.rb} +22 -0
  17. data/lib/blather/{core/roster_item.rb → roster_item.rb} +39 -8
  18. data/lib/blather/stanza/iq/disco.rb +11 -0
  19. data/lib/blather/stanza/iq/discos/disco_info.rb +86 -0
  20. data/lib/blather/stanza/iq/discos/disco_items.rb +61 -0
  21. data/lib/blather/stanza/iq/query.rb +51 -0
  22. data/lib/blather/stanza/iq/roster.rb +90 -0
  23. data/lib/blather/stanza/iq.rb +38 -0
  24. data/lib/blather/stanza/message.rb +58 -0
  25. data/lib/blather/stanza/presence/status.rb +78 -0
  26. data/lib/blather/stanza/presence/subscription.rb +72 -0
  27. data/lib/blather/stanza/presence.rb +45 -0
  28. data/lib/blather/stanza.rb +101 -0
  29. data/lib/blather/stream/client.rb +26 -0
  30. data/lib/blather/stream/component.rb +34 -0
  31. data/lib/blather/stream/parser.rb +70 -0
  32. data/lib/blather/stream/resource.rb +48 -0
  33. data/lib/blather/stream/sasl.rb +173 -0
  34. data/lib/blather/stream/session.rb +36 -0
  35. data/lib/blather/stream/stream_handler.rb +39 -0
  36. data/lib/blather/stream/tls.rb +33 -0
  37. data/lib/blather/stream.rb +249 -0
  38. data/lib/blather/xmpp_node.rb +199 -0
  39. data/lib/blather.rb +40 -41
  40. data/spec/blather/core_ext/libxml_spec.rb +58 -0
  41. data/spec/blather/errors/sasl_error_spec.rb +56 -0
  42. data/spec/blather/errors/stanza_error_spec.rb +148 -0
  43. data/spec/blather/errors/stream_error_spec.rb +114 -0
  44. data/spec/blather/errors_spec.rb +40 -0
  45. data/spec/blather/{core/jid_spec.rb → jid_spec.rb} +9 -1
  46. data/spec/blather/{core/roster_item_spec.rb → roster_item_spec.rb} +6 -1
  47. data/spec/blather/{core/roster_spec.rb → roster_spec.rb} +16 -6
  48. data/spec/blather/stanza/iq/discos/disco_info_spec.rb +207 -0
  49. data/spec/blather/stanza/iq/discos/disco_items_spec.rb +136 -0
  50. data/spec/blather/stanza/iq/query_spec.rb +34 -0
  51. data/spec/blather/stanza/iq/roster_spec.rb +123 -0
  52. data/spec/blather/stanza/iq_spec.rb +40 -0
  53. data/spec/blather/stanza/message_spec.rb +52 -0
  54. data/spec/blather/stanza/presence/status_spec.rb +102 -0
  55. data/spec/blather/stanza/presence/subscription_spec.rb +85 -0
  56. data/spec/blather/stanza/presence_spec.rb +53 -0
  57. data/spec/blather/{core/stanza_spec.rb → stanza_spec.rb} +14 -2
  58. data/spec/blather/stream/client_spec.rb +787 -0
  59. data/spec/blather/stream/component_spec.rb +86 -0
  60. data/spec/blather/{core/xmpp_node_spec.rb → xmpp_node_spec.rb} +76 -23
  61. data/spec/build_safe.rb +20 -0
  62. data/spec/spec_helper.rb +7 -17
  63. metadata +79 -59
  64. data/CHANGELOG +0 -1
  65. data/blather.gemspec +0 -73
  66. data/lib/blather/callback.rb +0 -24
  67. data/lib/blather/core/errors.rb +0 -24
  68. data/lib/blather/core/stanza.rb +0 -90
  69. data/lib/blather/core/stream.rb +0 -179
  70. data/lib/blather/core/xmpp_node.rb +0 -95
  71. data/lib/blather/extensions/last_activity.rb +0 -57
  72. data/lib/blather/extensions/version.rb +0 -85
  73. data/spec/blather/core/stream_spec.rb +0 -263
data/LICENSE CHANGED
@@ -1,3 +1,5 @@
1
+ Blather
2
+
1
3
  Copyright (c) 2008 Jeff Smick
2
4
 
3
5
  Permission is hereby granted, free of charge, to any person obtaining
data/README.rdoc CHANGED
@@ -1,3 +1,103 @@
1
1
  = Blather
2
2
 
3
3
  An evented XMPP library
4
+
5
+ == Features
6
+
7
+ * evented architecture
8
+ * uses libxml
9
+ * simplified starting point
10
+
11
+ == Project Pages
12
+
13
+ GitHub:: https://github.com/sprsquish/blather
14
+
15
+ RubyForge:: http://rubyforge.org/projects/squishtech/
16
+
17
+ == Author
18
+
19
+ Jeff Smick <sprsquish@gmail.com>
20
+
21
+ = Usage
22
+
23
+ == Installation
24
+
25
+ sudo gem install blather
26
+
27
+ == Example
28
+
29
+ See the /examples directory for more advanced examples.
30
+
31
+ This will auto-accept any subscription requests and echo back any chat messages.
32
+
33
+ require 'rubygems'
34
+ require 'blather/client'
35
+
36
+ setup 'echo@jabber.local', 'echo'
37
+
38
+ # Auto approve subscription requests
39
+ subscription :request? do |s|
40
+ write s.approve!
41
+ end
42
+
43
+ # Echo back what was said
44
+ message :chat?, :body do |m|
45
+ write m.reply
46
+ end
47
+
48
+ == Handlers
49
+
50
+ Setup handlers by calling their names as methods.
51
+
52
+ # Will only be called for messages where #chat? responds positively
53
+ # and #body == 'exit'
54
+ message :chat?, :body => 'exit'
55
+
56
+ === Handler Guards
57
+
58
+ Guards act like AND statements. Each condition must be met if the handler is to be used.
59
+
60
+ # Equivalent to saying (stanza.chat? && stanza.body)
61
+ message :chat?, :body
62
+
63
+ There are 5 different types of guards:
64
+
65
+ # Symbol
66
+ # Checks for a non-false reply to calling the symbol on the stanza
67
+ # Equivalent to stanza.chat?
68
+ message :chat?
69
+
70
+ # Hash with value (:body => 'exit')
71
+ # Calls the key on the stanza and checks for equality
72
+ # Equivalent to stanza.body == 'exit'
73
+ message :body => 'exit'
74
+
75
+ # Hash with regular expression (:body => /exit/)
76
+ # Calls the key on the stanza and checks for a match
77
+ # Equivalent to stanza.body.match /exit/
78
+ message :body => /exit/
79
+
80
+ # Proc
81
+ # Calls the proc passing in the stanza
82
+ # Checks that the ID is modulo 3
83
+ message proc { |m| m.id % 3 == 0 }
84
+
85
+ # Array
86
+ # Use arrays with the previous types effectively turns the guard into
87
+ # an OR statement.
88
+ # Equivalent to stanza.body == 'foo' || stanza.body == 'baz'
89
+ message [{:body => 'foo'}, {:body => 'baz'}]
90
+
91
+ = TODO
92
+
93
+ * Cleanup API
94
+ * Add lambda callback ability to Iq stanzas
95
+ * Better Documentation
96
+ * Service Discovery (XEP-0030: http://xmpp.org/extensions/xep-0030.html)
97
+ * PubSub (XEP-0060: http://xmpp.org/extensions/xep-0060.html)
98
+ * More examples (Re-write XMPP4R examples into Blather)
99
+
100
+ = License
101
+
102
+ Please see LICENSE
103
+ The LibXML-Ruby license can be found in its directory
data/Rakefile ADDED
@@ -0,0 +1,110 @@
1
+ require 'rubygems'
2
+ require 'rake'
3
+
4
+ begin
5
+ require 'jeweler'
6
+ Jeweler::Tasks.new do |gem|
7
+ gem.name = 'blather'
8
+ gem.summary = 'An evented XMPP library written on EventMachine and libxml-ruby'
9
+
10
+ gem.email = 'sprsquish@gmail.com'
11
+ gem.homepage = 'http://github.com/sprsquish/blather'
12
+ gem.authors = ['Jeff Smick']
13
+
14
+ gem.rubyforge_project = 'squishtech'
15
+
16
+ gem.extensions = ['Rakefile']
17
+
18
+ gem.add_dependency 'eventmachine', '>= 0.12.6'
19
+ gem.add_dependency 'libxml-ruby', '>= 1.1.3'
20
+
21
+ gem.files = FileList['examples/**/*', 'lib/**/*', 'ext/*'].to_a
22
+
23
+ # gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
24
+ end
25
+ rescue LoadError
26
+ puts "Jeweler (or a dependency) not available. Install it with: sudo gem install jeweler"
27
+ end
28
+
29
+ require 'rake/testtask'
30
+ Rake::TestTask.new(:test) do |test|
31
+ test.libs << 'lib' << 'spec'
32
+ test.pattern = 'spec/**/*_spec.rb'
33
+ test.verbose = true
34
+ end
35
+
36
+ begin
37
+ require 'rcov/rcovtask'
38
+ Rcov::RcovTask.new do |test|
39
+ test.libs << 'spec'
40
+ test.pattern = 'spec/**/*_spec.rb'
41
+ test.rcov_opts += ['--exclude \/Library\/Ruby\/Gems,spec\/', '--xrefs']
42
+ test.verbose = true
43
+ end
44
+ rescue LoadError
45
+ task :rcov do
46
+ abort "RCov is not available. In order to run rcov, you must: sudo gem install spicycode-rcov"
47
+ end
48
+ end
49
+
50
+
51
+ begin
52
+ require 'hanna/rdoctask'
53
+
54
+ Rake::RDocTask.new do |rdoc|
55
+ if File.exist?('VERSION.yml')
56
+ config = YAML.load(File.read('VERSION.yml'))
57
+ version = "#{config[:major]}.#{config[:minor]}.#{config[:patch]}"
58
+ else
59
+ version = ""
60
+ end
61
+
62
+ rdoc.rdoc_dir = 'rdoc'
63
+ rdoc.title = "blather #{version}"
64
+ rdoc.rdoc_files.include('README*')
65
+ rdoc.rdoc_files.include('lib/**/*.rb')
66
+ rdoc.options += %w[-S -T hanna --main README.rdoc --exclude autotest --exclude vendor]
67
+ end
68
+ rescue LoadError
69
+ task :rdoc do
70
+ abort "Hanna is not available. In order to use the Hanna, you must: sudo gem install mislav-hanna"
71
+ end
72
+ end
73
+
74
+ MAKE = ENV['MAKE'] || (RUBY_PLATFORM =~ /mswin/ ? 'nmake' : 'make')
75
+
76
+ namespace :ext do
77
+ ext_sources = FileList['ext/*.{rb,c}']
78
+
79
+ desc 'Compile the makefile'
80
+ file 'ext/Makefile' => ext_sources do
81
+ chdir('ext') { ruby 'extconf.rb' }
82
+ end
83
+
84
+ desc "make extension"
85
+ task :make => ext_sources + ['ext/Makefile'] do
86
+ chdir('ext') { sh MAKE }
87
+ end
88
+
89
+ desc 'Build push parser'
90
+ task :build => :make
91
+
92
+ desc 'Clean extensions'
93
+ task :clean do
94
+ chdir 'ext' do
95
+ sh "rm -f Makefile"
96
+ sh "rm -f *.{o,so,bundle,log}"
97
+ end
98
+ end
99
+ end
100
+
101
+ # If running under rubygems...
102
+ __DIR__ ||= File.expand_path(File.dirname(__FILE__))
103
+ if Gem.path.any? {|path| %r(^#{Regexp.escape path}) =~ __DIR__}
104
+ task :default => :gem_build
105
+ else
106
+ task :default => ['ext:build', :test]
107
+ end
108
+
109
+ desc ":default build when running under rubygems."
110
+ task :gem_build => 'ext:build'
@@ -0,0 +1,5 @@
1
+ %w[rubygems lib/blather/client drb/drb].each { |r| require r }
2
+
3
+ setup 'drb_client@jabber.local', 'drb_client'
4
+
5
+ when_ready { DRb.start_service 'druby://localhost:99843', self }
data/examples/echo.rb ADDED
@@ -0,0 +1,18 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'blather/client'
4
+
5
+ when_ready { puts "Connected ! send messages to #{jid.stripped}." }
6
+
7
+ subscription :request? do |s|
8
+ write s.approve!
9
+ end
10
+
11
+ message :chat?, :body => 'exit' do |m|
12
+ say m.from, 'Exiting ...'
13
+ shutdown
14
+ end
15
+
16
+ message :chat?, :body do |m|
17
+ say m.from, "You sent: #{m.body}"
18
+ end
data/ext/extconf.rb ADDED
@@ -0,0 +1,65 @@
1
+ require 'mkmf'
2
+
3
+ flags = []
4
+
5
+ case RUBY_PLATFORM.split('-',2)[1]
6
+ when 'mswin32', 'mingw32', 'bccwin32'
7
+ unless have_header('windows.h') and
8
+ have_header('winsock.h') and
9
+ have_library('kernel32') and
10
+ have_library('rpcrt4') and
11
+ have_library('gdi32')
12
+ exit
13
+ end
14
+
15
+ flags << "-D OS_WIN32"
16
+ flags << '-D BUILD_FOR_RUBY'
17
+ flags << "-EHs"
18
+ flags << "-GR"
19
+
20
+ dir_config('xml2')
21
+ exit unless have_library('xml2') && have_header('libxml/parser.h')
22
+
23
+ when /solaris/
24
+ unless have_library('pthread') and
25
+ have_library('nsl') and
26
+ have_library('socket')
27
+ exit
28
+ end
29
+
30
+ flags << '-D OS_UNIX'
31
+ flags << '-D OS_SOLARIS8'
32
+ flags << '-D BUILD_FOR_RUBY'
33
+
34
+ dir_config('xml2')
35
+ exit unless have_library('xml2') && find_header('libxml/parser.h', '/usr/include/libxml2')
36
+
37
+ # on Unix we need a g++ link, not gcc.
38
+ #CONFIG['LDSHARED'] = "$(CXX) -shared"
39
+
40
+ when /darwin/
41
+ flags << '-DOS_UNIX'
42
+ flags << '-DBUILD_FOR_RUBY'
43
+
44
+ dir_config('xml2')
45
+ exit unless have_library('xml2') && find_header('libxml/parser.h', '/usr/include/libxml2')
46
+ # on Unix we need a g++ link, not gcc.
47
+ #CONFIG['LDSHARED'] = "$(CXX) " + CONFIG['LDSHARED'].split[1..-1].join(' ')
48
+
49
+ else
50
+ unless have_library('pthread')
51
+ exit
52
+ end
53
+
54
+ flags << '-DOS_UNIX'
55
+ flags << '-DBUILD_FOR_RUBY'
56
+
57
+ dir_config('xml2')
58
+ exit unless have_library('xml2') && find_header('libxml/parser.h', '/usr/include/libxml2')
59
+ # on Unix we need a g++ link, not gcc.
60
+ #CONFIG['LDSHARED'] = "$(CXX) -shared"
61
+ end
62
+
63
+ $CFLAGS += ' ' + flags.join(' ')
64
+
65
+ create_makefile "push_parser"
data/ext/push_parser.c ADDED
@@ -0,0 +1,231 @@
1
+ /*
2
+ * Most of this was ripped from libxml-ruby's SAX handler
3
+ */
4
+
5
+ #include <libxml/parser.h>
6
+ #include <ruby.h>
7
+
8
+ xmlSAXHandler saxHandler;
9
+
10
+ static VALUE
11
+ push_parser_raise_error (
12
+ xmlErrorPtr error)
13
+ {
14
+ rb_raise(rb_eStandardError, "%s", rb_str_new2((const char*)error->message));
15
+ return Qnil;
16
+ }
17
+
18
+ static VALUE
19
+ push_parser_initialize (
20
+ VALUE self,
21
+ VALUE handler)
22
+ {
23
+ xmlParserCtxtPtr ctxt;
24
+ ctxt = xmlCreatePushParserCtxt(&saxHandler, (void *)handler, NULL, 0, NULL);
25
+
26
+ if (!ctxt)
27
+ return push_parser_raise_error(&xmlLastError);
28
+
29
+ ctxt->sax2 = 1;
30
+
31
+ rb_iv_set(self, "@__libxml_push_parser", Data_Wrap_Struct(rb_cData, 0, xmlFreeParserCtxt, ctxt));
32
+
33
+ return self;
34
+ }
35
+
36
+ static VALUE
37
+ push_parser_close (
38
+ VALUE self)
39
+ {
40
+ xmlParserCtxtPtr ctxt;
41
+ Data_Get_Struct(rb_iv_get(self, "@__libxml_push_parser"), xmlParserCtxt, ctxt);
42
+
43
+ if (xmlParseChunk(ctxt, "", 0, 1)) {
44
+ return push_parser_raise_error(&xmlLastError);
45
+ }
46
+ else {
47
+ return Qtrue;
48
+ }
49
+ }
50
+
51
+ static VALUE
52
+ push_parser_receive (
53
+ VALUE self,
54
+ VALUE chunk)
55
+ {
56
+ const char *data = StringValuePtr(chunk);
57
+ int length = RSTRING_LEN(chunk);
58
+
59
+ xmlParserCtxtPtr ctxt;
60
+ Data_Get_Struct(rb_iv_get(self, "@__libxml_push_parser"), xmlParserCtxt, ctxt);
61
+
62
+ // Chunk through in 4KB chunks so as not to overwhelm the buffers
63
+ int i;
64
+ int chunkSize = length < 4096 ? length : 4096;
65
+ for (i = 0; i < length; i += chunkSize) {
66
+ xmlParseChunk(ctxt, data+i, chunkSize, 0);
67
+ }
68
+ if ((i -= length) > 0)
69
+ xmlParseChunk(ctxt, data+(length-i), i, 0);
70
+
71
+ return self;
72
+ }
73
+
74
+ /*********
75
+ CALLBACKS
76
+ **********/
77
+ static void
78
+ push_parser_start_document_callback (
79
+ void *ctx)
80
+ {
81
+ VALUE handler = (VALUE) ctx;
82
+ if (handler != Qnil)
83
+ rb_funcall (handler, rb_intern("on_start_document"), 0);
84
+ }
85
+
86
+ static void
87
+ push_parser_end_document_callback (
88
+ void *ctx)
89
+ {
90
+ VALUE handler = (VALUE) ctx;
91
+ if (handler != Qnil)
92
+ rb_funcall (handler, rb_intern("on_end_document"), 0);
93
+ }
94
+
95
+ static void
96
+ push_parser_start_element_ns_callback (
97
+ void * ctx,
98
+ const xmlChar * localname,
99
+ const xmlChar * prefix,
100
+ const xmlChar * URI,
101
+ int nb_namespaces,
102
+ const xmlChar ** namespaces,
103
+ int nb_attributes,
104
+ int nb_defaulted,
105
+ const xmlChar ** attributes)
106
+ {
107
+ VALUE handler = (VALUE) ctx;
108
+ if (handler == Qnil)
109
+ return;
110
+
111
+ VALUE attrHash = rb_hash_new();
112
+ VALUE nsHash = rb_hash_new();
113
+
114
+ if (attributes)
115
+ {
116
+ /* Each attribute is an array of [localname, prefix, URI, value, end] */
117
+ int i;
118
+ for (i = 0; i < nb_attributes * 5; i += 5)
119
+ {
120
+ rb_hash_aset( attrHash,
121
+ rb_str_new2((const char*)attributes[i+0]),
122
+ rb_str_new((const char*)attributes[i+3], attributes[i+4] - attributes[i+3]));
123
+ }
124
+ }
125
+
126
+ if (namespaces)
127
+ {
128
+ int i;
129
+ for (i = 0; i < nb_namespaces * 2; i += 2)
130
+ {
131
+ rb_hash_aset( nsHash,
132
+ namespaces[i+0] ? rb_str_new2((const char*)namespaces[i+0]) : Qnil,
133
+ namespaces[i+1] ? rb_str_new2((const char*)namespaces[i+1]) : Qnil);
134
+ }
135
+ }
136
+
137
+ rb_funcall(handler, rb_intern("on_start_element_ns"), 5,
138
+ rb_str_new2((const char*)localname),
139
+ attrHash,
140
+ prefix ? rb_str_new2((const char*)prefix) : Qnil,
141
+ URI ? rb_str_new2((const char*)URI) : Qnil,
142
+ nsHash);
143
+ }
144
+
145
+ static void
146
+ push_parser_end_element_ns_callback (
147
+ void * ctx,
148
+ const xmlChar * localname,
149
+ const xmlChar * prefix,
150
+ const xmlChar * URI)
151
+ {
152
+ VALUE handler = (VALUE) ctx;
153
+ if (handler == Qnil)
154
+ return;
155
+
156
+ rb_funcall(handler, rb_intern("on_end_element_ns"), 3,
157
+ rb_str_new2((const char*)localname),
158
+ prefix ? rb_str_new2((const char*)prefix) : Qnil,
159
+ URI ? rb_str_new2((const char*)URI) : Qnil);
160
+ }
161
+
162
+
163
+ static void
164
+ push_parser_characters_callback (
165
+ void *ctx,
166
+ const char *chars,
167
+ int len)
168
+ {
169
+ VALUE handler = (VALUE) ctx;
170
+ if (handler != Qnil)
171
+ rb_funcall (handler, rb_intern("on_characters"), 1, rb_str_new(chars, len));
172
+ }
173
+
174
+ static void
175
+ push_parser_structured_error_callback (
176
+ void *ctx,
177
+ xmlErrorPtr error)
178
+ {
179
+ VALUE handler = (VALUE) ctx;
180
+ if (handler != Qnil)
181
+ rb_funcall (handler, rb_intern("on_error"), 1, rb_str_new2((const char*)error->message));
182
+ }
183
+
184
+ xmlSAXHandler saxHandler = {
185
+ 0, //internalSubset
186
+ 0, //isStandalone
187
+ 0, //hasInternalSubset
188
+ 0, //hasExternalSubset
189
+ 0, //resolveEntity
190
+ 0, //getEntity
191
+ 0, //entityDecl
192
+ 0, //notationDecl
193
+ 0, //attributeDecl
194
+ 0, //elementDecl
195
+ 0, //unparsedEntityDecl
196
+ 0, //setDocumentLocator
197
+ (startDocumentSAXFunc) push_parser_start_document_callback,
198
+ (endDocumentSAXFunc) push_parser_end_document_callback,
199
+ 0, //startElement
200
+ 0, //endElement
201
+ 0, //reference
202
+ (charactersSAXFunc) push_parser_characters_callback,
203
+ 0, //ignorableWhitespace
204
+ 0, //processingInstruction
205
+ 0, //comment
206
+ 0, //warning
207
+ (errorSAXFunc) push_parser_structured_error_callback,
208
+ 0, //fatalError
209
+ 0, //getParameterEntity
210
+ 0, //cdataBlock
211
+ 0, //externalSubset
212
+ XML_SAX2_MAGIC,
213
+ 0, //_private
214
+ (startElementNsSAX2Func) push_parser_start_element_ns_callback,
215
+ (endElementNsSAX2Func) push_parser_end_element_ns_callback,
216
+ (xmlStructuredErrorFunc) push_parser_structured_error_callback
217
+ };
218
+
219
+ void
220
+ Init_push_parser()
221
+ {
222
+ /* SaxPushParser */
223
+ VALUE mLibXML = rb_define_module("LibXML");
224
+ VALUE mXML = rb_define_module_under(mLibXML, "XML");
225
+ VALUE cXMLSaxPushParser = rb_define_class_under(mXML, "SaxPushParser", rb_cObject);
226
+
227
+ /* Instance Methods */
228
+ rb_define_method(cXMLSaxPushParser, "initialize", push_parser_initialize, 1);
229
+ rb_define_method(cXMLSaxPushParser, "receive", push_parser_receive, 1);
230
+ rb_define_method(cXMLSaxPushParser, "close", push_parser_close, 0);
231
+ }