//Author: Matthias Walter (matthias.walter@listrik.de)

#include <stdio.h>
#include <string.h>
#include <stdbool.h>

char * LeftStr(char * dst, char * src, uint8_t dstsize, uint8_t length) {	
	/* LeftStr returns the leftmost characters of a string
	Input:
		char *dst ==> pointer to the destination string
		char *src ==> pointer to the source string
		uint8_t dstsize ==> buffer size of the destination string
		uint8_t length ==> number of characters to extract. (1...n)
	Output:
		Pointer to the destination string
	*/
	if (length > (dstsize - 1)) { length = dstsize - 1; }			
	strncpy(dst, src, length);
	dst[length] = '\0'; // zero terminate 
	return dst;
}

char * MidStr(char * dst, char * src, uint8_t dstsize, uint8_t start, uint8_t length)  {	
	/* MidStr extracts a number of characters from a string
	Input:
		char *dst ==> pointer to the destination string
		char *src ==> pointer to the source string
		uint8_t dstlen ==> buffer size of the destination string
		uint8_t start ==> starting position within the source string. (First position is 1)
		uint8_t length ==> number of characters to extract. (1...n)
	Output:
		Pointer to the destination string
	*/
	if (length > (dstsize - 1)) length = dstsize - 1;	
	if (start > 0) start--; //call starts at 1..., internal start is 0...	
    if (start > (strlen(src) - 1)) dst[0] = '\0';   // out of range
	 else {
	   strncpy(dst, src + start, length);
	   dst[length] = '\0'; // zero terminate 
     }
	 return dst;
}

char * RightStr(char * dst, char * src, uint8_t dstsize, uint8_t length) {	
	/* RightStr returns the rightmost characters of a string
	Input:
		char *dst ==> pointer to the destination string
		char *src ==> pointer to the source string
		uint8_t dstlen ==> string length of the destination string
		uint8_t length ==> number of characters to extract. (1...n)
	Output:
		Pointer to the destination string
	*/
	if (length > (dstsize - 1)) length = dstsize - 1;		
	strncpy(dst, src + strlen(src) - length, length);
	dst[length] = '\0'; // zero terminate 
	return dst;
}

char * UpperCase(char * dst, char * src, uint8_t dst_len) {
	/* UpperCase converts characters a..z to A..Z
	Input:
		char *dst ==> pointer to the destination string
		char *src ==> pointer to the source string
		uint8_t dstlen ==> string length of the destination string
	Output:
		Pointer to the destination string
	*/
	uint8_t srclen;
	 
	srclen= strlen(src);
	if ( (dst_len + 1) < srclen) srclen = dst_len; //ensure available space
	strncpy(dst, src, srclen); //copy max l_puffer bytes from src to dst
	dst[srclen + 1] = '\0';
	strupr(dst);
	return dst;
}	
				
char * LowerCase(char * dst, char * src, uint8_t dst_len) {
	/* LowerCase converts characters A..Z to a..z
	Input:
		char *dst ==> pointer to the destination string
		char *src ==> pointer to the source string
		uint8_t dstlen ==> string length of the destination string
	Output:
		Pointer to the destination string
	*/  
	uint8_t srclen;
	 
	srclen=strlen(src);
	if ( (dst_len + 1) < srclen) srclen = dst_len; //ensure available space
	strncpy(dst, src, srclen); //copy max l_puffer bytes from src to dst
	dst[srclen + 1] = '\0';
	strlwr(dst);
	return dst;
}	

uint8_t InStr(char * source,  char * substr, uint8_t sourcesize, uint8_t start, bool CaseSensitive) {
	/* InString looks for the occurrence of a substr in the source string
	Input:
		char *dst ==> pointer to the destination string
		char *src ==> pointer to the source string
		uint8_t sourcesize ==> buffer size of the source string
		uint8_t start ==> starting position within the source string. (First position is 1)
		bool CaseSensitive ==> true or false
	Output:
		Position of the first occurrence (1...)
		0 = not found
	*/
	uint8_t position;
	char * subs;
	char * src;
	char * found;

	if (start > 0) { start--; } //call starts at 1..., internal start is 0...
	if (start > sourcesize - 2) { //string length - \0 - 1
		position = 0;  //illegal starting position
	}
	else {
		if (CaseSensitive) {
			found = strstr(source, substr);
			if (found != 0) position = found - source;   //strstr returns NULL if item not found
			else position = 0;
		}
		else {
			src = malloc(sourcesize);
			memcpy(src, source + start, sourcesize - start);
			
			subs = malloc(strlen(substr) + 1);
			memcpy(subs, substr, strlen(substr) + 1);
			
			strupr(src);
			strupr(subs);
			
			found = strstr(src, subs);
			if (found != 0) position = found + start - src;   // strstr returns NULL if item not found
			else {position = 0; }
			
			free(src);
			free(subs);
		}
	}
	return position + 1;  //
}

char * PadStr(char * dst,  char * src, uint8_t dstsize, char padchar, bool padleft) {   //left/Right pad with a character
	/* PadString pads the destination string with a character
	Input:
		char *dst ==> pointer to the destination string
		char *src ==> pointer to the source string
		uint8_t destsize ==> buffer size of the destination string
		uint8_t start ==> starting position within the source string. (First position is 1)
		bool CaseSensitive ==> true or false
	Output:
		Pointer to the destination string
	*/
	uint8_t srclen;
	
	srclen = strlen(src);	
	if (srclen > (dstsize - 1)) srclen = dstsize - 1;
	if (padleft) { 
		memset (dst, padchar, dstsize - srclen - 1); //insert padchar
		strncpy(dst + dstsize - srclen -1, src, srclen); 
	}
	else { 
		strncpy(dst, src, srclen);
		memset (dst + srclen, padchar, dstsize - srclen - 1); //insert padchar
	}	
	dst[dstsize -1] = '\0';	
	return dst;
}

char S1[17]={"Hello World"}; //max 16 char available!
char ch={"-"}; //Padchar
char S2[17]={"Wo"}; //Instring
char Tempstr[17];
uint_8 x;

//Example calls
LeftStr(Tempstr,S1,strlen(Tempstr),4); 				//Tempstr="Hello"
MidStr(Tempstr,S1,strlen(Tempstr),5,4); 			//Tempstr="o Wo"
Tempstr=RightStr(Tempstr,S1,strlen(Tempstr),5);  	//Tempstr="World"
UpperCase(tempstr,S1,strlen(Tempstr));    	//Tempstr="HELLO WORLD"
LowerCase(tempstr,S1,strlen(Tempstr));    	//Tempstr="hello world"
x=InStr(S1, S2,strlen(Tempstr),0, false);         	//x=7
PadStr(Tempstr, S1,strlen(Tempstr),ch,true); //Tempstr="-hello world"
