/* parse method */
static VALUE
XMLParser_parse(int argc, VALUE* argv, VALUE obj)
{
XMLParser* parser;
int ret;
VALUE str;
VALUE isFinal;
int final = 1;
int count;
int fromStream = 0;
ID mid = rb_intern("gets");
ID linebuf = rb_intern("_linebuf");
count = rb_scan_args(argc, argv, "02", &str, &isFinal);
/* If "str" has public "gets" method, it will be considered *stream* */
if (!rb_obj_is_kind_of(str, rb_cString) &&
rb_method_boundp(CLASS_OF(str), mid, 1)) {
fromStream = 1;
}
else if (!NIL_P(str)) {
Check_Type(str, T_STRING);
}
if (count >= 2) {
if (isFinal == Qtrue)
final = 1;
else if (isFinal == Qfalse)
final = 0;
else
rb_raise(rb_eTypeError, "not valid value");
}
GET_PARSER(obj, parser);
parser->iterator = rb_block_given_p();
/* Setup event handlers */
setup_evnet_handlers(parser, obj);
/* Parse from stream (probably slightly slow) */
if (fromStream) {
VALUE buf;
if (OBJ_TAINTED(str))
taintParser(parser);
do {
buf = rb_funcall(str, mid, 0);
if (!NIL_P(buf)) {
Check_Type(buf, T_STRING);
if (OBJ_TAINTED(buf))
taintParser(parser);
rb_ivar_set(obj, linebuf, buf); /* protect buf from GC (reasonable?)*/
ret = XML_Parse(parser->parser,
RSTRING_PTR(buf), RSTRING_LEN(buf), 0);
}
else {
ret = XML_Parse(parser->parser, NULL, 0, 1);
}
if (!ret) {
int err = XML_GetErrorCode(parser->parser);
const char* errStr = XML_ErrorString(err);
rb_raise(eXMLParserError, (char*)errStr);
}
} while (!NIL_P(buf));
return Qnil;
}
/* Parse string */
if (!NIL_P(str)) {
#if defined(HAVE_RUBY_ENCODING_H) && defined(HAVE_XML_PARSERRESET)
int err;
#endif
if (OBJ_TAINTED(str))
taintParser(parser);
ret = XML_Parse(parser->parser,
RSTRING_PTR(str), RSTRING_LEN(str), final);
#if defined(HAVE_RUBY_ENCODING_H) && defined(HAVE_XML_PARSERRESET)
/* Ruby 1.9.1 Encoding conversion */
err = XML_GetErrorCode(parser->parser);
if (final && err == XML_ERROR_UNKNOWN_ENCODING) {
rb_encoding* enc;
volatile VALUE encobj;
volatile VALUE ustr;
enc = rb_enc_find(parser->detectedEncoding);
if ((int)ENC_TO_ENCINDEX(enc) != rb_ascii8bit_encindex()) {
rb_enc_associate(str, enc);
encobj = rb_enc_from_encoding(enc_xml);
/* rb_str_encode may raises an exception */
ustr = rb_str_encode(str, encobj, 0, Qnil);
if (!NIL_P(ustr)) {
XML_ParserReset(parser->parser, "utf-8");
XML_SetUserData(parser->parser, (void*)obj);
parser->defaultCurrent = 0;
#ifdef NEW_EXPAT
parser->lastAttrs = NULL;
#endif
parser->detectedEncoding = NULL;
setup_evnet_handlers(parser, obj);
ret = XML_Parse(parser->parser,
RSTRING_PTR(ustr), RSTRING_LEN(ustr), final);
}
}
}
#endif
}
else
ret = XML_Parse(parser->parser, NULL, 0, final);
if (!ret) {
int err = XML_GetErrorCode(parser->parser);
const char* errStr = XML_ErrorString(err);
rb_raise(eXMLParserError, (char*)errStr);
}
return Qnil;
}