/*
 * Copyright (C) Birb Developers
 *
 * Birb is the legal property of its developers, whose names are too numerous
 * to list here. Please refer to the AUTHORS file distributed with this source
 * distribution
 *
 * This library is free software; you can redistribute it and/or modify it
 * under the terms of the GNU Lesser General Public License as published by the
 * Free Software Foundation; either version 2.1 of the License, or (at your
 * option) any later version.
 *
 * This library is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
 * for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with this library; if not, see <https://www.gnu.org/licenses/>.
 */

#if !defined(BIRB_GLOBAL_HEADER_INSIDE) && !defined(BIRB_COMPILATION)
# error "only <birb.h> may be included directly"
#endif

#ifndef BIRB_STR_H
#define BIRB_STR_H

#ifdef _WIN32
# include <windows.h>
#endif

#include <string.h>

#include <glib.h>

#include "birbversion.h"

G_BEGIN_DECLS

/**
 * birb_str_is_empty:
 * @str: (nullable): the string to check
 *
 * Determines if @str is empty or not.
 *
 * Returns: true if @str is empty; false otherwise.
 *
 * Since: 0.4
 */
BIRB_AVAILABLE_STATIC_INLINE_IN_0_4
static inline gboolean
birb_str_is_empty(const char *str) {
	return (str == NULL || str[0] == '\0');
}

/**
 * birb_str_equal:
 * @str1: (nullable): the first string
 * @str2: (nullable): the second string
 *
 * Checks if @str1 is equal to @str2.
 *
 * Returns: true if the strings are equal; false otherwise.
 *
 * Since: 0.4
 */
BIRB_AVAILABLE_STATIC_INLINE_IN_0_4
static inline gboolean
birb_str_equal(const char *str1, const char *str2) {
	return (g_strcmp0(str1, str2) == 0);
}

/**
 * birb_str_matches:
 * @pattern: the pattern to search for
 * @str: the string to check
 *
 * Checks if @pattern occurs in sequential order in @str in a caseless fashion,
 * ignoring characters in between.
 *
 * For example, if @pattern was `Br` and @str was `biRb`, this will return
 * %TRUE.
 *
 * Returns: %TRUE if @pattern occurs in sequential order in @str.
 *
 * Since: 0.6
 */
BIRB_AVAILABLE_IN_0_6
gboolean birb_str_matches(const char *pattern, const char *str);

/**
 * birb_str_to_uint:
 * @str: (nullable): a string to convert to an unsigned integer
 *
 * Converts @str to an unsigned integer.
 *
 * Returns: The converted value or 0 on error.
 *
 * Since: 0.4
 */
BIRB_AVAILABLE_STATIC_INLINE_IN_0_4
static inline guint
birb_str_to_uint(const char *str) {
	int ivalue;

	if(birb_str_is_empty(str)) {
		return 0;
	}

	ivalue = atoi(str);

	return (guint)ivalue;
}

/**
 * birb_str_wipe:
 * @str: (transfer full)(nullable): a null terminated string to wipe
 *
 * Securely erases and frees the given string.
 *
 * This uses the best available method on each platform, but will fallback to
 * memset if the platform is unknown.
 *
 * Since: 0.7
 */
BIRB_AVAILABLE_STATIC_INLINE_IN_0_7
static inline void
birb_str_wipe(char *str) {
#ifdef _WIN32
	if(str == NULL) {
		return;
	}

	SecureZeroMemory(str, strlen(str));
	g_free(str);
#else
	/* This implementation is based on egg_secure_clear from gcr.
	 * https://gitlab.gnome.org/GNOME/gcr/-/blob/fcfb16d74531376e22b6d9416fd2f7c33e540c37/egg/egg-secure-memory.c#L1350
	 */
	volatile unsigned char *sp = NULL;
	size_t length = 0;

	if(str == NULL) {
		return;
	}

	sp = (volatile unsigned char *)str;
	length = strlen(str);
	while(length > 0) {
		*sp = 0xAA;
		sp++;
		length--;
	}

	g_free(str);
#endif
}

G_END_DECLS

#endif /* BIRB_STR_H */
