/*
 * $Id$
 *
 * New generation of string handling functions safe from a memory management point of view 
 * Developped by Andree Leidenfrost
 */

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <time.h>

#include "mr_mem.h"

// to get bool type
#define _MY_STUFF_H_
#include "my-stuff.h"
 
/**
 * Safe alternative to standard function strtok()
 * @param instr
 * @param delims
 * @param lastpos
 * @return @p
 * @note this function allocates memory that needs to be freed by caller
 **/
char *mr_strtok(char *instr, const char *delims, int *lastpos) {

char *token = NULL;
char *strptr = NULL;
size_t pos1 = 0;
size_t pos2 = 0;

if (instr == NULL) {
	*lastpos = 0;
	return token;
}

if (delims == NULL) {
	*lastpos = 0;
	return token;
}

if (strlen(instr) <= *lastpos) {
	*lastpos = 0;
	return token;
}

strptr = instr + *lastpos;
pos2 = strspn(strptr, delims);
strptr += pos2;
pos1 = strcspn(strptr, delims);
token = (char *)mr_malloc(sizeof(*token) * (pos1 + 1));
strncpy(token, strptr, pos1);
token[pos1] = '\0';
*lastpos = *lastpos + pos1 + pos2 + 1;

return token;
}


/**
 * Returns the string fed to it 'inptr' with all characters to escape given
 * in 'toesc' prepended by escaping character 'escchr'.
 * (Prepare strings for use in system() or popen() with this function.)
 * @param instr
 * @param toesc
 * @param escchr
 * @note this function allocates memory that needs to be freed by caller
 **/
char *mr_stresc(char *instr, char *toesc, const char escchr, const char specialchr) {

char *inptr = NULL;
char *retstr = NULL;
char *retptr = NULL;
char *escptr = NULL;
int cnt = 0;
bool found = FALSE;

inptr = instr;
// Count how many characters need escaping.
while (*inptr != '\0') {
	escptr = toesc;
	while (*escptr != '\0') {
		if (*inptr == *escptr) {
			// Found it, skip the rest.
			cnt++;
			// if specialchar (' or ") then replace it with '\'' or "\"" so adds 2 chars
			if (*inptr == specialchr) {
				cnt += 2;
			}
			break;
		}
		escptr++;
	}
	inptr++;
}

inptr = instr;
retstr = (char *) mr_malloc(strlen(inptr) + cnt + 1);
retptr = retstr;

// Prepend specified characters with escape character.
while (*inptr != '\0') {
	escptr = toesc;
	while (*escptr != '\0') {
		if (*inptr == *escptr) {
			// Found it, skip the rest.
			// if specialchar (' or ") then replace it with '\'' or "\"" so adds 2 chars
			if (*inptr == specialchr) {
				*retptr = specialchr;
				retptr++;
				*retptr = escchr;
				retptr++;
				found = TRUE;
			} else {
				*retptr = escchr;
				retptr++;
			}
			break;
		}
		escptr++;
	}
	*retptr = *inptr;
	retptr++;
	inptr++;
	if (found) {
		// finish to put the remaining specialchr
		*retptr = specialchr;
		retptr++;
		found = FALSE;
	}
}
*retptr = '\0';

return(retstr);
}

/* Return a string containing the date */
char *mr_date(void) {

time_t tcurr;

tcurr = time(NULL);
return(ctime(&tcurr));
}

/* Return an allocated string containing the date
char *mr_date(void) {
	
	time_t tcurr;
	char *tmp = NULL;

	tcurr = time(NULL);
	mr_asprintf(tmp, "%s", ctime(&tcurr));
	mr_chomp(tmp);
	return(tmp);
}
 */

/**
 * Remove all characters whose ASCII value is less than or equal to 32
 * (spaces and control characters) from both sides of @p instr.
 * @param instr The string to strip spaces/control characters from
 * returns a newly allocated string without the spaces that needs to be freed
 * by the caller
 */
char *mr_strip_spaces(const char *instr) {

char *q = NULL;
char *outstr = NULL;

if (instr == NULL) {
	return(NULL);
}

/* Skip initial spaces and special chars */
while (*instr <= ' ' && *instr != '\0') {
	instr++;
}

if (*instr == '\0') {
	mr_asprintf(outstr, "");
	return(outstr);
}

mr_asprintf(outstr, "%s", instr);
q = outstr + strlen(outstr) - 1;

/* Skip final spaces and special chars */
while (*q <= ' ' && q != outstr) {
	q--;
}

/* The string now ends after that char */
q++;
*q = '\0';
return(outstr);
}

/*  Subsitute the string "token" in the string "in" by the string "subst" */
char *mr_str_substitute(const char *in, const char *token, const char *subst) {

char *output = NULL;
char *tmp = NULL;
int i = 0;

mr_asprintf(output, "%s", in);
tmp = strstr(output, token);
if (tmp == NULL) {
	// token not found returning initial string unmodified
	return(output);
}
// token found: end string here for now
*tmp = '\0';

// Add subst content to the string
mr_strcat(output,subst);

// now add the rest of in
tmp = strstr(in, token);
for (; i < strlen(token) ; i++) {
	tmp++;
}
mr_strcat(output,tmp);
return(output);
}


/*
 * Remove '\n' char from both sides of @p in_out.
 * @param in_out The string to strip characters from (modified).

void mr_chomp(char *in_out) {

	mr_strip_char(in_out, "\n");
}
*/

/**
 * Remove all characters in caracs from begining and end of string @p in_out
 * @param in_out The string to strip char characters from (modified).

void mr_strip_char(char *in_out, char *caracs) {
	int i = 0;
	int j = 0;
	size_t length = 0;

	if (caracs == NULL) {
		return;
	}
	if (in_out == NULL) {
		return;
	}
	length = strlen(in_out);

	// Skip initial caracs
	for (i = 0; index(caracs, in_out[i]) != NULL && i < (int)length ; i++);

	// Shift the string to the begining if needed
	if (i != 0) {
		for (j = 0; i < (int)length ; i++, j++) {
			in_out[j] = in_out[i];
		}
		// Erase the end of the string if needed
		j++;
		in_out[j] = '\0';
	}

	// Skip final caracs
	for (i = (int)strlen(in_out) - 1; i >= 0  && index(caracs, in_out[i]) != NULL; i--);

	// The string now ends after that char
	i++;
	in_out[i] = '\0';
}
*/

