/* Copyright (C) 2015 by ETH Zürich
 * Software engineering by Intevation GmbH
 *
 * This file is free software under the GNU GPL (v>=2)
 * and comes with ABSOLUTELY NO WARRANTY!
 * See LICENSE.txt for details.
 */
#ifndef STRHELP_H
#define STRHELP_H

#ifdef __cplusplus
extern "C" {
#endif

#include <stdbool.h>
#include <stddef.h>

/**
 * @file  strhelp.h
 * @brief Helper functions for c strings and memory management
 * @details strhelp contains terminating memory allocation functions and
 * some conveniance functions to work with c strings or arrays of c
 * strings.
 */

/** @def To avoid that a compiler optimizes certain memset calls away */
#define wipememory2(_ptr,_set,_len) do { \
              volatile char *_vptr=(volatile char *)(_ptr); \
              size_t _vlen=(_len); \
              while(_vlen) { *_vptr=(_set); _vptr++; _vlen--; } \
                  } while(0)
/** @def To avoid that a compiler optimizes certain memset calls away */
#define wipememory(_ptr,_len) wipememory2(_ptr,0,_len)


void *xmalloc( size_t n );
/** @brief like malloc but initalizes the values with 0 */
void *xmalloc0( size_t n );
void *xrealloc( void *a, size_t n );
void *xcalloc( size_t n, size_t m );
char *xstrndup( const char *string, const size_t len );
void xfree ( void *p );

/**
 * @brief Terminating variant of asprintf
 *
 * This function behaves exactly like asprintf(3) but will terminate
 * when an error occures (usally that means that memoy allocation
 * failed).
 */
int xasprintf (char **strp, const char *fmt, ...);

/**
 * @brief Returns the length of the given %NULL-terminated
 * string array str_array.
 * @param[in] str_array a %NULL-terminated array of strings
 * @returns length of str_array.
 */
unsigned int strv_length (char **str_array);

/**
 * @brief append a string to a NULL terminated array of strings.
 *
 * @param[in,out] pArray pointer to the NULL terminated list of string pointers.
 * @param[in] string pointer to the string to append to the list.
 * @param[in] len length of the string to append to the list
 */
void strv_append (char ***pArray, const char *string, const size_t len);

/**
 * @brief append a string to another string.
 *
 * @param[in,out] pDst pointer to the string to be extended.
 * @param[in,out] dst_len length of the dst string. Will be modified.
 * @param[in] appendage pointer to the string to append.
 * @param[in] len length of the string to append.
 */
void str_append_str (char **pDst, size_t *dst_len, const char *appendage,
                    const size_t len);

/**
 * @brief Frees the given %NULL-terminated string array.
 * @param[in,out] str_array a %NULL-terminated array of strings
 */
void strv_free (char **str_array);

/**
 * @brief Checks whether two strings exactly match
 * @param[in] s1 the first string
 * @param[in] s2 the second string
 * @returns true if s1 and s2 are equal
 */
bool str_equal (char *s1, char *s2);

/**
 * @brief Checks whether s2 exactly matches the beginning of s1.
 * @param[in] s1 the string who's beginning is searched
 * @param[in] s2 the string which is searched for
 * @returns true if s1 starts with s2, false otherwise
 */
bool str_starts_with (char *s1, char *s2);

/**
 * @brief Trims all white space from the start and end of string.
 * @details the start of the string is trimmed by setting *s to the
 * first non white space character.  The end is trimmed by setting the
 * first character after the last non white space character to \0.
 * @param[in,out] s ponter to the string to strip
 */
bool str_trim (char **s);

/** @brief decode base64 encoded data
 *
 * The memory allocated for dest needs to be free'd by the
 * caller.
 *
 * _Input warning:_
 * If the input contains invalid base64 characters an error
 * is returned.
 *
 * If the input is invalid base64 but consists of valid
 * base64 characters _no error_ is returned and dst contains
 * the valid input up to the error.
 *
 * @param [out] dst Pointer to the destination. Needs to be NULL
 * @param [out] dst_size Size allocated for the destination.
 * @param [in] src Pointer to the base64 encoded data.
 * @param [in] src_size Size of the encoded data.
 *
 * @returns 0 on success a polarssl error or -1 otherwise
 */
int str_base64_decode(char **dst, size_t *dst_size, char *src,
                      size_t src_size);

#ifdef _WIN32

/** @brief convert a utf8 string to utf16 wchar
 *
 * @param[in] string utf8 string. Must be at least len characters long.
 * @param[in] len number of characters to be converted.
 *
 * @returns pointer to a newly allocated wchar array. NULL on error.
 *
 **/
wchar_t *utf8_to_wchar (const char *string, size_t len);

/** @brief convert a local 8 bit (acp) string to utf16 wchar
 *
 * @param[in] string acp string. Must be at least len characters long.
 * @param[in] len number of characters to be converted.
 *
 * @returns pointer to a newly allocated wchar array. NULL on error.
 *
 **/
wchar_t *acp_to_wchar (const char *string, size_t len);

/** @brief convert a utf16 string to utf8
 *
 * @param[in] string utf16 string. Must be at least len characters long.
 * @param[in] len number of characters to be converted.
 *
 * @returns pointer to a newly allocated char array. NULL on error.
 *
 **/
char *wchar_to_utf8 (const wchar_t *string, size_t len);
#endif

#ifdef __cplusplus
}
#endif

#endif

