<commit_before>/*
 * This file is part of libdom.
 * Licensed under the MIT License,
 *                http://www.opensource.org/licenses/mit-license.php
 * Copyright 2007 <NAME> <<EMAIL>>
 * Copyright 2009 <NAME> <<EMAIL>>
 */

#include <assert.h>
#include <stdlib.h>

#include <dom/functypes.h>
#include <dom/core/attr.h>
#include <dom/core/element.h>
#include <dom/core/document.h>
#include <dom/core/implementation.h>

#include "core/string.h"
#include "core/attr.h"
#include "core/cdatasection.h"
#include "core/comment.h"
#include "core/document.h"
#include "core/doc_fragment.h"
#include "core/element.h"
#include "core/entity_ref.h"
#include "core/namednodemap.h"
#include "core/nodelist.h"
#include "core/pi.h"
#include "core/text.h"
#include "utils/validate.h"
#include "utils/namespace.h"
#include "utils/utils.h"

/**
 * Item in list of active nodelists
 */
struct dom_doc_nl {
	dom_nodelist *list;	/**< Nodelist */

	struct dom_doc_nl *next;	/**< Next item */
	struct dom_doc_nl *prev;	/**< Previous item */
};

/* The virtual functions of this dom_document */
static struct dom_document_vtable document_vtable = {
	{
		{
			DOM_NODE_EVENT_TARGET_VTABLE
		},
		DOM_NODE_VTABLE_DOCUMENT
	},
	DOM_DOCUMENT_VTABLE
};

static struct dom_node_protect_vtable document_protect_vtable = {
	DOM_DOCUMENT_PROTECT_VTABLE
};


/*----------------------------------------------------------------------*/

/* Internally used helper functions */
static dom_exception dom_document_dup_node(dom_document *doc, 
		dom_node *node, bool deep, dom_node **result, 
		dom_node_operation opt);


/*----------------------------------------------------------------------*/

/* The constructors and destructors */

/**
 * Create a Document
 *
 * \param doc    Pointer to location to receive created document
 * \param daf    The default action fetcher
 * \return DOM_NO_ERR on success, DOM_NO_MEM_ERR on memory exhaustion.
 *
 * The returned document will already be referenced.
 */
dom_exception _dom_document_create(dom_events_default_action_fetcher daf,
		dom_document **doc)
{
	dom_document *d;
	dom_exception err;

	/* Create document */
	d = malloc(sizeof(dom_document));
	if (d == NULL)
		return DOM_NO_MEM_ERR;

	/* Initialise the virtual table */
	d->base.base.vtable = &document_vtable;
	d->base.vtable = &document_protect_vtable;

	/* Initialise base class -- the Document has no parent, so
	 * destruction will be attempted as soon as its reference count
	 * reaches zero. Documents own themselves (this simplifies the 
	 * rest of the code, as it doesn't need to special case Documents)
	 */
	err = _dom_document_initialise(d, daf);
	if (err != DOM_NO_ERR) {
		/* Clean up document */
		free(d);
		return err;
	}

	*doc = d;

	return DOM_NO_ERR;
}

/* Initialise the document */
dom_exception _dom_document_initialise(dom_document *doc, 
		dom_events_default_action_fetcher daf)
{
	dom_exception err;
	dom_string *name;

	err = dom_string_create((const uint8_t *) "#document", 
			SLEN("#document"), &name);
	if (err != DOM_NO_ERR)
		return err;

	doc->nodelists = NULL;

	err = _dom_node_initialise(&doc->base, doc, DOM_DOCUMENT_NODE,
			name, NULL, NULL, NULL);
	dom_string_unref(name);
        if (err != DOM_NO_ERR)
          return err;

	list_init(&doc->pending_nodes);

	doc->id_name = NULL;
	doc->quirks = DOM_DOCUMENT_QUIRKS_MODE_NONE;

	err = dom_string_create_interned((const uint8_t *) "class",
			SLEN("class"), &doc->class_string);
	if (err != DOM_NO_ERR)
		return err;

	/* Intern the empty string. The use of a space in the constant
	 * is to prevent the compiler warning about an empty string.
	 */
	err = dom_string_create_interned((const uint8_t *) ' ', 0,
					 &doc->_memo_empty);
	if (err != DOM_NO_ERR) {
		dom_string_unref(doc->class_string);
		return err;
	}

	/* We should not pass a NULL when all things hook up */
	return _dom_document_event_internal_initialise(doc, &doc->dei, daf);
}


/* Finalise the document */
bool _dom_document_finalise(dom_document *doc)
{
	/* Finalise base class, delete the tree in force */
	_dom_node_finalise(&doc->base);

	/* Now, the first_child and last_child should be null */
	doc->base.first_child = NULL;
	doc->base.last_child = NULL;

	/* Ensure list of nodes pending deletion is empty. If not,
	 * then we can't yet destroy the document (its destruction will
	 * have to wait until the pending nodes are destroyed) */
	if (doc->pending_nodes.next != &doc->pending_nodes)
		return false;

	/* Ok, the document tree is empty, as is the list of nodes pending
	 * deletion. Therefore, it is safe to destroy the document. */

	/* This is paranoia -- if there are any remaining nodelists,
	 * then the document's reference count will be
	 * non-zero as these data structures reference the document because
	 * they are held by the client. */
	doc->nodelists = NULL;

	if (doc->id_name != NULL)
		dom_string_unref(doc->id_name);

	dom_string_unref(doc->class_string);
	
	_dom_document_event_internal_finalise(doc, &doc->dei);

	return true;
}



/*----------------------------------------------------------------------*/<commit_msg>DOMDocument: Actually free the empty memoised string<commit_after>/*
 * This file is part of libdom.
 * Licensed under the MIT License,
 *                http://www.opensource.org/licenses/mit-license.php
 * Copyright 2007 <NAME> <<EMAIL>>
 * Copyright 2009 <NAME> <<EMAIL>>
 */

#include <assert.h>
#include <stdlib.h>

#include <dom/functypes.h>
#include <dom/core/attr.h>
#include <dom/core/element.h>
#include <dom/core/document.h>
#include <dom/core/implementation.h>

#include "core/string.h"
#include "core/attr.h"
#include "core/cdatasection.h"
#include "core/comment.h"
#include "core/document.h"
#include "core/doc_fragment.h"
#include "core/element.h"
#include "core/entity_ref.h"
#include "core/namednodemap.h"
#include "core/nodelist.h"
#include "core/pi.h"
#include "core/text.h"
#include "utils/validate.h"
#include "utils/namespace.h"
#include "utils/utils.h"

/**
 * Item in list of active nodelists
 */
struct dom_doc_nl {
	dom_nodelist *list;	/**< Nodelist */

	struct dom_doc_nl *next;	/**< Next item */
	struct dom_doc_nl *prev;	/**< Previous item */
};

/* The virtual functions of this dom_document */
static struct dom_document_vtable document_vtable = {
	{
		{
			DOM_NODE_EVENT_TARGET_VTABLE
		},
		DOM_NODE_VTABLE_DOCUMENT
	},
	DOM_DOCUMENT_VTABLE
};

static struct dom_node_protect_vtable document_protect_vtable = {
	DOM_DOCUMENT_PROTECT_VTABLE
};


/*----------------------------------------------------------------------*/

/* Internally used helper functions */
static dom_exception dom_document_dup_node(dom_document *doc, 
		dom_node *node, bool deep, dom_node **result, 
		dom_node_operation opt);


/*----------------------------------------------------------------------*/

/* The constructors and destructors */

/**
 * Create a Document
 *
 * \param doc    Pointer to location to receive created document
 * \param daf    The default action fetcher
 * \return DOM_NO_ERR on success, DOM_NO_MEM_ERR on memory exhaustion.
 *
 * The returned document will already be referenced.
 */
dom_exception _dom_document_create(dom_events_default_action_fetcher daf,
		dom_document **doc)
{
	dom_document *d;
	dom_exception err;

	/* Create document */
	d = malloc(sizeof(dom_document));
	if (d == NULL)
		return DOM_NO_MEM_ERR;

	/* Initialise the virtual table */
	d->base.base.vtable = &document_vtable;
	d->base.vtable = &document_protect_vtable;

	/* Initialise base class -- the Document has no parent, so
	 * destruction will be attempted as soon as its reference count
	 * reaches zero. Documents own themselves (this simplifies the 
	 * rest of the code, as it doesn't need to special case Documents)
	 */
	err = _dom_document_initialise(d, daf);
	if (err != DOM_NO_ERR) {
		/* Clean up document */
		free(d);
		return err;
	}

	*doc = d;

	return DOM_NO_ERR;
}

/* Initialise the document */
dom_exception _dom_document_initialise(dom_document *doc, 
		dom_events_default_action_fetcher daf)
{
	dom_exception err;
	dom_string *name;

	err = dom_string_create((const uint8_t *) "#document", 
			SLEN("#document"), &name);
	if (err != DOM_NO_ERR)
		return err;

	doc->nodelists = NULL;

	err = _dom_node_initialise(&doc->base, doc, DOM_DOCUMENT_NODE,
			name, NULL, NULL, NULL);
	dom_string_unref(name);
        if (err != DOM_NO_ERR)
          return err;

	list_init(&doc->pending_nodes);

	doc->id_name = NULL;
	doc->quirks = DOM_DOCUMENT_QUIRKS_MODE_NONE;

	err = dom_string_create_interned((const uint8_t *) "class",
			SLEN("class"), &doc->class_string);
	if (err != DOM_NO_ERR)
		return err;

	/* Intern the empty string. The use of a space in the constant
	 * is to prevent the compiler warning about an empty string.
	 */
	err = dom_string_create_interned((const uint8_t *) " ", 0,
					 &doc->_memo_empty);
	if (err != DOM_NO_ERR) {
		dom_string_unref(doc->class_string);
		return err;
	}

	/* We should not pass a NULL when all things hook up */
	return _dom_document_event_internal_initialise(doc, &doc->dei, daf);
}


/* Finalise the document */
bool _dom_document_finalise(dom_document *doc)
{
	/* Finalise base class, delete the tree in force */
	_dom_node_finalise(&doc->base);

	/* Now, the first_child and last_child should be null */
	doc->base.first_child = NULL;
	doc->base.last_child = NULL;

	/* Ensure list of nodes pending deletion is empty. If not,
	 * then we can't yet destroy the document (its destruction will
	 * have to wait until the pending nodes are destroyed) */
	if (doc->pending_nodes.next != &doc->pending_nodes)
		return false;

	/* Ok, the document tree is empty, as is the list of nodes pending
	 * deletion. Therefore, it is safe to destroy the document. */

	/* This is paranoia -- if there are any remaining nodelists,
	 * then the document's reference count will be
	 * non-zero as these data structures reference the document because
	 * they are held by the client. */
	doc->nodelists = NULL;

	if (doc->id_name != NULL)
		dom_string_unref(doc->id_name);

	dom_string_unref(doc->class_string);
	dom_string_unref(doc->_memo_empty);
	
	_dom_document_event_internal_finalise(doc, &doc->dei);

	return true;
}



/*----------------------------------------------------------------------*/
{'fraction_non_alphanumeric': 0.15428125609518237, 'fraction_numerical': 0.0023405500292568754, 'mean_word_length': 3.3416596104995766, 'pattern_counts': {'":': 0, '<': 35, '<?xml version=': 0, '>': 72, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, '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': '7349282', 'n_tokens_mistral': 3526, 'n_tokens_neox': 3311, 'n_words': 939}