<commit_before>/* Copyright (c) 2010 <NAME>
 * 
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 * 
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */

#include "config.h"

#include <lua.h>
#include <lauxlib.h>
#include <lualib.h>

#include <stdlib.h>
#include <string.h>
#include <expat.h>
#include <errno.h>

#include <ratchet.h>

#include "xml.h"

/* {{{ generic_start_cb() */
static void XMLCALL generic_start_cb (void *user_data, const char *name, const char **atts)
{
	lua_State *L = (lua_State *) user_data;
	int i;

	lua_getfield (L, 1, "start_cb");
	lua_getfield (L, 1, "state");
	lua_pushstring (L, name);
	lua_newtable (L);
	for (i=0; atts[i] != NULL; i+=2)
	{
		lua_pushstring (L, atts[i]);
		lua_pushstring (L, atts[i+1]);
		lua_rawset (L, -3);
	}
	lua_call (L, 3, 0);
}
/* }}} */

/* {{{ generic_end_cb() */
static void XMLCALL generic_end_cb (void *user_data, const char *name)
{
	lua_State *L = (lua_State *) user_data;

	lua_getfield (L, 1, "end_cb");
	lua_getfield (L, 1, "state");
	lua_pushstring (L, name);
	lua_call (L, 2, 0);
}
/* }}} */

/* {{{ generic_data_cb() */
static void generic_data_cb (void *user_data, const char *s, int len)
{
	lua_State *L = (lua_State *) user_data;

	lua_getfield (L, 1, "data_cb");
	lua_getfield (L, 1, "state");
	lua_pushlstring (L, s, (size_t) len);
	lua_call (L, 2, 0);
}
/* }}} */

/* {{{ myxml_init() */
static int myxml_init (lua_State *L)
{
	lua_settop (L, 5);
	const char *encoding = NULL;
	XML_StartElementHandler start_cb = NULL;
	XML_EndElementHandler end_cb = NULL;
	XML_CharacterDataHandler data_cb = NULL;

	lua_newtable (L);
	lua_setfield (L, 1, "state");

	/* Grab the named parameters. */
	for (lua_pushnil (L); lua_next (L, 2) != 0; lua_pop (L, 1))
	{
		if (rhelp_strequal (L, -2, "state"))
		{
			lua_pushvalue (L, -1);
			lua_setfield (L, 1, "state");
		}
		else if (rhelp_strequal (L, -2, "startelem"))
		{
			lua_pushvalue (L, -1);
			lua_setfield (L, 1, "start_cb");
			start_cb = generic_start_cb;
		}
		else if (rhelp_strequal (L, -2, "endelem"))
		{
			lua_pushvalue (L, -1);
			lua_setfield (L, 1, "end_cb");
			end_cb = generic_end_cb;
		}
		else if (rhelp_strequal (L, -2, "elemdata"))
		{
			lua_pushvalue (L, -1);
			lua_setfield (L, 1, "data_cb");
			data_cb = generic_data_cb;
		}
		else if (rhelp_strequal (L, -2, "encoding"))
			encoding = lua_tostring (L, -1);
		else
			luaL_argerror (L, 2, "unknown named params given");
	}

	XML_Parser parser = XML_ParserCreate (encoding);
	if (!parser)
		return luaL_error (L, "XML parser create failed");

	XML_SetUserData (parser, L);
	if (start_cb || end_cb)
		XML_SetElementHandler (parser, start_cb, end_cb);
	if (data_cb)
		XML_SetCharacterDataHandler (parser, data_cb);

	lua_pushlightuserdata (L, parser);
	lua_setfield (L, 1, "parser");

	return 0;
}
/* }}} */

/* {{{ myxml_del() */
static int myxml_del (lua_State *L)
{
	lua_getfield (L, 1, "parser");
	XML_Parser parser = (XML_Parser) lua_touserdata (L, -1);
	lua_pop (L, 1);

	if (parser)
		XML_ParserFree (parser);

	lua_pushlightuserdata (L, NULL);
	lua_setfield (L, 1, "parser");

	return 0;
}
/* }}} */

/* {{{ myxml_parse() */
static int myxml_parse (lua_State *L)
{
	const char *data;
	size_t datalen;
	int more_coming = 0;

	lua_settop (L, 3);

	lua_getfield (L, 1, "parser");
	XML_Parser parser = (XML_Parser) lua_touserdata (L, -1);
	lua_pop (L, 1);

	data = lua_tolstring (L, 2, &datalen);
	more_coming = lua_toboolean (L, 3);

	int ret = XML_Parse (parser, data, datalen, (more_coming ? 0 : 1));
	if (ret == 0)
	{
		lua_pushboolean (L, 0);
		int error = (int) XML_GetErrorCode (parser);
		lua_pushstring (L, XML_ErrorString (error));
	}
	else<commit_msg>No need to update an object being deleted.<commit_after>/* Copyright (c) 2010 <NAME>
 * 
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 * 
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */

#include "config.h"

#include <lua.h>
#include <lauxlib.h>
#include <lualib.h>

#include <stdlib.h>
#include <string.h>
#include <expat.h>
#include <errno.h>

#include <ratchet.h>

#include "xml.h"

/* {{{ generic_start_cb() */
static void XMLCALL generic_start_cb (void *user_data, const char *name, const char **atts)
{
	lua_State *L = (lua_State *) user_data;
	int i;

	lua_getfield (L, 1, "start_cb");
	lua_getfield (L, 1, "state");
	lua_pushstring (L, name);
	lua_newtable (L);
	for (i=0; atts[i] != NULL; i+=2)
	{
		lua_pushstring (L, atts[i]);
		lua_pushstring (L, atts[i+1]);
		lua_rawset (L, -3);
	}
	lua_call (L, 3, 0);
}
/* }}} */

/* {{{ generic_end_cb() */
static void XMLCALL generic_end_cb (void *user_data, const char *name)
{
	lua_State *L = (lua_State *) user_data;

	lua_getfield (L, 1, "end_cb");
	lua_getfield (L, 1, "state");
	lua_pushstring (L, name);
	lua_call (L, 2, 0);
}
/* }}} */

/* {{{ generic_data_cb() */
static void generic_data_cb (void *user_data, const char *s, int len)
{
	lua_State *L = (lua_State *) user_data;

	lua_getfield (L, 1, "data_cb");
	lua_getfield (L, 1, "state");
	lua_pushlstring (L, s, (size_t) len);
	lua_call (L, 2, 0);
}
/* }}} */

/* {{{ myxml_init() */
static int myxml_init (lua_State *L)
{
	lua_settop (L, 5);
	const char *encoding = NULL;
	XML_StartElementHandler start_cb = NULL;
	XML_EndElementHandler end_cb = NULL;
	XML_CharacterDataHandler data_cb = NULL;

	lua_newtable (L);
	lua_setfield (L, 1, "state");

	/* Grab the named parameters. */
	for (lua_pushnil (L); lua_next (L, 2) != 0; lua_pop (L, 1))
	{
		if (rhelp_strequal (L, -2, "state"))
		{
			lua_pushvalue (L, -1);
			lua_setfield (L, 1, "state");
		}
		else if (rhelp_strequal (L, -2, "startelem"))
		{
			lua_pushvalue (L, -1);
			lua_setfield (L, 1, "start_cb");
			start_cb = generic_start_cb;
		}
		else if (rhelp_strequal (L, -2, "endelem"))
		{
			lua_pushvalue (L, -1);
			lua_setfield (L, 1, "end_cb");
			end_cb = generic_end_cb;
		}
		else if (rhelp_strequal (L, -2, "elemdata"))
		{
			lua_pushvalue (L, -1);
			lua_setfield (L, 1, "data_cb");
			data_cb = generic_data_cb;
		}
		else if (rhelp_strequal (L, -2, "encoding"))
			encoding = lua_tostring (L, -1);
		else
			luaL_argerror (L, 2, "unknown named params given");
	}

	XML_Parser parser = XML_ParserCreate (encoding);
	if (!parser)
		return luaL_error (L, "XML parser create failed");

	XML_SetUserData (parser, L);
	if (start_cb || end_cb)
		XML_SetElementHandler (parser, start_cb, end_cb);
	if (data_cb)
		XML_SetCharacterDataHandler (parser, data_cb);

	lua_pushlightuserdata (L, parser);
	lua_setfield (L, 1, "parser");

	return 0;
}
/* }}} */

/* {{{ myxml_del() */
static int myxml_del (lua_State *L)
{
	lua_getfield (L, 1, "parser");
	XML_Parser parser = (XML_Parser) lua_touserdata (L, -1);
	lua_pop (L, 1);

	if (parser)
		XML_ParserFree (parser);

	return 0;
}
/* }}} */

/* {{{ myxml_parse() */
static int myxml_parse (lua_State *L)
{
	const char *data;
	size_t datalen;
	int more_coming = 0;

	lua_settop (L, 3);

	lua_getfield (L, 1, "parser");
	XML_Parser parser = (XML_Parser) lua_touserdata (L, -1);
	lua_pop (L, 1);

	data = lua_tolstring (L, 2, &datalen);
	more_coming = lua_toboolean (L, 3);

	int ret = XML_Parse (parser, data, datalen, (more_coming ? 0 : 1));
	if (ret == 0)
	{
		lua_pushboolean (L, 0);
		int error = (int) XML_GetErrorCode (parser);
		lua_pushstring (L, XML_ErrorString (error));
	}
	else
{'fraction_non_alphanumeric': 0.14462272333044232, 'fraction_numerical': 0.012467476149176062, 'mean_word_length': 4.105146651909242, 'pattern_counts': {'":': 0, '<': 21, '<?xml version=': 0, '>': 21, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 14}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5169546', 'n_tokens_mistral': 3733, 'n_tokens_neox': 3464, 'n_words': 1095}