<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 <ctype.h>
#include <inttypes.h>
#include <stdlib.h>
#include <string.h>

#include <parserutils/charset/utf8.h>

#include "core/string.h"
#include "core/document.h"
#include "utils/utils.h"

/**
 * Type of a DOM string
 */
enum dom_string_type {
	DOM_STRING_CDATA = 0,
	DOM_STRING_INTERNED = 1
};

/**
 * A DOM string
 *
 * Strings are reference counted so destruction is performed correctly.
 */
struct dom_string {
	union {
		struct {
			uint8_t *ptr;	/**< Pointer to string data */
			size_t len;	/**< Byte length of string */
		} cdata;
		lwc_string *intern;	/**< Interned string */
	} data;

	unsigned int refcnt : 31,	/**< Reference count */
		     type   :  1;	/**< String type */
};

/**
 * Empty string, for comparisons against NULL
 */
static const dom_string empty_string = {
	{ { (uint8_t *) "", 0 } },
	0,
	DOM_STRING_CDATA
};

/**
 * Claim a reference on a DOM string
 *
 * \param str  The string to claim a reference on
 * \return \a str
 */
dom_string *dom_string_ref(dom_string *str)
{
	if (str != NULL)
		str->refcnt++;

	return str;
}

/**
 * Release a reference on a DOM string
 *
 * \param str  The string to release the reference from
 *
 * If the reference count reaches zero, any memory claimed by the
 * string will be released
 */
void dom_string_unref(dom_string *str)
{
	if (str != NULL && --str->refcnt == 0) {
		switch (str->type) {
		case DOM_STRING_INTERNED:
			if (str->data.intern != NULL) {
				lwc_string_unref(str->data.intern);
			}
			break;
		case DOM_STRING_CDATA:
			free(str->data.cdata.ptr);
			break;
		}

		free(str);
	}
}

/**
 * Create a DOM string from a string of characters
 *
 * \param ptr    Pointer to string of characters
 * \param len    Length, in bytes, of string of characters
 * \param str    Pointer to location to receive result
 * \return DOM_NO_ERR on success, DOM_NO_MEM_ERR on memory exhaustion
 *
 * The returned string will already be referenced, so there is no need
 * to explicitly reference it.
 *
 * The string of characters passed in will be copied for use by the 
 * returned DOM string.
 */
dom_exception dom_string_create(const uint8_t *ptr, size_t len, 
		dom_string **str)
{
	dom_string *ret;

	if (ptr == NULL || len == 0) {
		ptr = (const uint8_t *) "";
		len = 0;
	}

	ret = malloc(sizeof(dom_string));
	if (ret == NULL)
		return DOM_NO_MEM_ERR;

	ret->data.cdata.ptr = malloc(len);
	if (ret->data.cdata.ptr == NULL) {
		free(ret);
		return DOM_NO_MEM_ERR;
	}

	memcpy(ret->data.cdata.ptr, ptr, len);

	ret->data.cdata.len = len;

	ret->refcnt = 1;

	ret->type = DOM_STRING_CDATA;

	*str = ret;

	return DOM_NO_ERR;<commit_msg>Fix malloc(0)<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 <ctype.h>
#include <inttypes.h>
#include <stdlib.h>
#include <string.h>

#include <parserutils/charset/utf8.h>

#include "core/string.h"
#include "core/document.h"
#include "utils/utils.h"

/**
 * Type of a DOM string
 */
enum dom_string_type {
	DOM_STRING_CDATA = 0,
	DOM_STRING_INTERNED = 1
};

/**
 * A DOM string
 *
 * Strings are reference counted so destruction is performed correctly.
 */
struct dom_string {
	union {
		struct {
			uint8_t *ptr;	/**< Pointer to string data */
			size_t len;	/**< Byte length of string */
		} cdata;
		lwc_string *intern;	/**< Interned string */
	} data;

	unsigned int refcnt : 31,	/**< Reference count */
		     type   :  1;	/**< String type */
};

/**
 * Empty string, for comparisons against NULL
 */
static const dom_string empty_string = {
	{ { (uint8_t *) "", 0 } },
	0,
	DOM_STRING_CDATA
};

/**
 * Claim a reference on a DOM string
 *
 * \param str  The string to claim a reference on
 * \return \a str
 */
dom_string *dom_string_ref(dom_string *str)
{
	if (str != NULL)
		str->refcnt++;

	return str;
}

/**
 * Release a reference on a DOM string
 *
 * \param str  The string to release the reference from
 *
 * If the reference count reaches zero, any memory claimed by the
 * string will be released
 */
void dom_string_unref(dom_string *str)
{
	if (str != NULL && --str->refcnt == 0) {
		switch (str->type) {
		case DOM_STRING_INTERNED:
			if (str->data.intern != NULL) {
				lwc_string_unref(str->data.intern);
			}
			break;
		case DOM_STRING_CDATA:
			free(str->data.cdata.ptr);
			break;
		}

		free(str);
	}
}

/**
 * Create a DOM string from a string of characters
 *
 * \param ptr    Pointer to string of characters
 * \param len    Length, in bytes, of string of characters
 * \param str    Pointer to location to receive result
 * \return DOM_NO_ERR on success, DOM_NO_MEM_ERR on memory exhaustion
 *
 * The returned string will already be referenced, so there is no need
 * to explicitly reference it.
 *
 * The string of characters passed in will be copied for use by the 
 * returned DOM string.
 */
dom_exception dom_string_create(const uint8_t *ptr, size_t len, 
		dom_string **str)
{
	dom_string *ret;

	if (ptr == NULL || len == 0) {
		ptr = (const uint8_t *) "";
		len = 0;
	}

	ret = malloc(sizeof(dom_string));
	if (ret == NULL)
		return DOM_NO_MEM_ERR;

	ret->data.cdata.ptr = malloc((len > 0) ? len : 1);
	if (ret->data.cdata.ptr == NULL) {
		free(ret);
		return DOM_NO_MEM_ERR;
	}

	memcpy(ret->data.cdata.ptr, ptr, len);

	ret->data.cdata.len = len;

	ret->refcnt = 1;

	ret->type = DOM_STRING_CDATA;

	*str = ret;

	return DOM_NO_ERR;
{'fraction_non_alphanumeric': 0.13313609467455623, 'fraction_numerical': 0.008875739644970414, 'mean_word_length': 3.1826783114992723, 'pattern_counts': {'":': 0, '<': 37, '<?xml version=': 0, '>': 52, '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': '3577789', 'n_tokens_mistral': 2153, 'n_tokens_neox': 1987, 'n_words': 623}