/* constructor */
static VALUE
XMLParser_new(int argc, VALUE* argv, VALUE klass)
{
XMLParser* parser;
VALUE obj;
VALUE arg1;
VALUE arg2;
VALUE arg3;
int count;
char* encoding = NULL;
#ifdef NEW_EXPAT
char* nssep = NULL;
#endif
char* context = NULL;
XMLParser* rootparser = NULL;
VALUE parent = Qnil;
count = rb_scan_args(argc, argv, "03", &arg1, &arg2, &arg3);
if (count == 1) {
/* new(encoding) */
if (TYPE(arg1) != T_NIL) {
Check_Type(arg1, T_STRING); /* encoding */
encoding = RSTRING_PTR(arg1);
}
}
else if (count == 2) {
/* new(encoding, nschar) */
/* new(parser, context) */
#ifdef NEW_EXPAT
if (TYPE(arg1) != T_DATA) {
if (TYPE(arg1) != T_NIL) {
Check_Type(arg1, T_STRING); /* encoding */
encoding = RSTRING_PTR(arg1);
}
Check_Type(arg2, T_STRING); /* nschar */
nssep = RSTRING_PTR(arg2);
}
else {
#endif
Check_Type(arg1, T_DATA); /* parser */
GET_PARSER(arg1, rootparser);
if (!NIL_P(arg2)) {
Check_Type(arg2, T_STRING); /* context */
context = RSTRING_PTR(arg2);
}
parent = arg1;
#ifdef NEW_EXPAT
}
#endif
}
else if (count == 3) {
/* new(parser, context, encoding) */
Check_Type(arg1, T_DATA); /* parser */
GET_PARSER(arg1, rootparser);
if (!NIL_P(arg2)) {
Check_Type(arg2, T_STRING); /* context */
context = RSTRING_PTR(arg2);
}
Check_Type(arg3, T_STRING); /* encoding */
encoding = RSTRING_PTR(arg3);
parent = arg1;
}
/* create object */
obj = Data_Make_Struct(klass, XMLParser,
XMLParser_mark, XMLParser_free, parser);
/* create parser */
if (rootparser == NULL) {
#ifdef NEW_EXPAT
if (nssep == NULL)
parser->parser = XML_ParserCreate(encoding);
else
parser->parser = XML_ParserCreateNS(encoding, nssep[0]);
#else
parser->parser = XML_ParserCreate(encoding);
#endif
parser->tainted = 0;
parser->context = NULL;
}
else {
parser->parser = XML_ExternalEntityParserCreate(rootparser->parser,
context, encoding);
/* clear all inhrited handlers,
because handlers should be set in "parse" method */
XML_SetElementHandler(parser->parser, NULL, NULL);
XML_SetCharacterDataHandler(parser->parser, NULL);
XML_SetProcessingInstructionHandler(parser->parser, NULL);
XML_SetDefaultHandler(parser->parser, NULL);
XML_SetUnparsedEntityDeclHandler(parser->parser, NULL);
XML_SetNotationDeclHandler(parser->parser, NULL);
XML_SetExternalEntityRefHandler(parser->parser, NULL);
#ifdef NEW_EXPAT
XML_SetCommentHandler(parser->parser, NULL);
XML_SetCdataSectionHandler(parser->parser, NULL, NULL);
XML_SetNamespaceDeclHandler(parser->parser, NULL, NULL);
XML_SetNotStandaloneHandler(parser->parser, NULL);
#endif
#ifdef HAVE_XML_SETDOCTYPEDECLHANDLER
XML_SetDoctypeDeclHandler(parser->parser, NULL, NULL);
#endif
#ifdef HAVE_EXPAT_H
XML_SetElementDeclHandler(parser->parser, NULL);
XML_SetAttlistDeclHandler(parser->parser, NULL);
XML_SetXmlDeclHandler(parser->parser, NULL);
XML_SetEntityDeclHandler(parser->parser, NULL);
#endif
#if 0
XML_SetExternalParsedEntityDeclHandler(parser->parser, NULL);
XML_SetInternalParsedEntityDeclHandler(parser->parser, NULL);
#endif
#ifdef HAVE_XML_SETSKIPPEDENTITYHANDLER
XML_SetSkippedEntityHandler(parser->parser, NULL);
#endif
if (rootparser->tainted)
parser->tainted |= 1;
parser->context = context;
}
if (!parser->parser)
rb_raise(eXMLParserError, "cannot create parser");
/* setting up internal data */
XML_SetUserData(parser->parser, (void*)obj);
parser->iterator = 0;
parser->defaultCurrent = 0;
#ifdef NEW_EXPAT
parser->lastAttrs = NULL;
#endif
parser->parent = parent;
parser->detectedEncoding = NULL;
rb_obj_call_init(obj, argc, argv);
return obj;
}