#include <ctype.h>
#include <crypt.h>
#include <errno.h>
#include <string.h>  
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <time.h>
#include <unistd.h>
#include "my_string.h"

int Substr_count (char *haystack, char *needle)
{
    int  counter = 0;
    char *loc    = NULL;
  
    /* Sanity checks */
    if ((haystack == NULL) || (needle == NULL)) {
        return 0;
    }

    while ((loc = strstr(haystack, needle)) != NULL) {
        counter++;
        haystack = loc + strlen(needle);
    }    

    return counter;
}

char *Stristr(char *haystack, char *needle)
{
    char *haystack_lowered = NULL;
    char *needle_lowered   = NULL;
    char *loc              = NULL;
    int pos                = 0;

    /* Sanity checks */
    if (haystack == NULL) {
        return NULL;
    }

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

    haystack_lowered = (char *)calloc(strlen(haystack) + 1, sizeof(char));    
    needle_lowered = (char *)calloc(strlen(needle) + 1, sizeof(char));    

    strcpy(haystack_lowered, Strtolower(haystack));
    strcpy(needle_lowered, Strtolower(needle));
   
    loc = strstr(haystack_lowered, needle_lowered);
    if (loc != NULL) {
       pos = loc - haystack_lowered;

       free(haystack_lowered);
       free(needle_lowered);
       return haystack + pos;
    }

    free(haystack_lowered);
    free(needle_lowered);

    return NULL;
    
}

char *Chop (char *str)
{
    return Rtrim(str);
}

char *Trim (char *str)
{
    return Ltrim(Rtrim(str));
}

char *Rtrim (char *str)
{
    static char *result = NULL;
    int i               = 0;

    /* Sanity check */
    if (str == NULL) {
        return NULL;
    }

    /* Free memory from the previous substr */
    if (result != NULL) {
        free (result);
    }

    result = (char *)calloc(strlen(str) + 1, sizeof(char)); 

    strcpy(result, str);
    i = strlen(result) - 1;

    while (i >= 0) {
        if ( (result[i] != ' ') && 
             (result[i] != '\t') && 
             (result[i] != '\n') && 
             (result[i] != '\r') && 
             (result[i] != '\x0B') ) {
            break;
        }
        
        result[i] = 0;
        i--;
    }
   
    return result;
}


char *Ltrim (char *str)
{
    static char *result = NULL;
    int i               = 0;
    int len             = 0;

    /* Sanity check */
    if (str == NULL) {
        return NULL;
    }

    /* Free memory from the previous substr */
    if (result != NULL) {
        free (result);
    }


    result = (char *)calloc(strlen(str) + 1, sizeof(char)); 

    strcpy(result, str);

    i = 0;
    len = strlen(result);
    while (1) {
        if ( (result[0] != ' ') && 
             (result[0] != '\t') && 
             (result[0] != '\n') && 
             (result[0] != '\r') && 
             (result[0] != '\x0B') ) {
            break;
        }
        strcpy(result, result + 1);
        len = strlen(result);
    }
   
    return result;
}

char *Str_Rot13(char *str)
{
    static char *result = NULL;
    char *from          = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
    char *to            = "nopqrstuvwxyzabcdefghijklmNOPQRSTUVWXYZABCDEFGHIJKLM";
    char *loc           = NULL;
    int i               = 0;

    /* Sanity check */
    if (str == NULL) {
        return NULL;
    }

    /* Free memory from the previous substr */
    if (result != NULL) {
        free (result);
    }

    result = (char *)calloc(strlen(str) + 1, sizeof(char)); 

    strcpy(result, str);
    i = strlen(result) - 1;

    while (i >= 0) {
        loc = strchr(from, result[i]);
        if (loc != NULL) {
            result[i] = to[loc - from];
        }
        i--;
    }
   
    return result;
}


char *Str_Replace(char *search, char *replace, char *subject)
{
    char *loc           = NULL;
    char *temp          = NULL;
    char *orig          = NULL;
    int diff, size;
    static char *result = NULL;
  
    /* Sanity checks */
    if ((search == NULL) || (replace == NULL) || (subject == NULL)) {
        return NULL;
    }

    /* Free memory from the previous Str_Replace */
    if (result != NULL) {
        free (result);
    }

    /* XXX: very rough approximation for memory allocation */
    diff = strlen(replace) - strlen(search);
    if (diff > 0) {
        /* worse case senario */
        size = (diff+1) * strlen(subject);
    }
    else {
        size = strlen(subject);
    }
    result = (char *)calloc(size + 1, sizeof(char)); 

    temp = strdup(subject);
    orig = temp;
    while ((loc = strstr(temp, search)) != NULL) {
        strncat(result, temp, loc - temp);
        strcat(result, replace);
        temp = loc + strlen(search);
    }    

    if (strlen(temp) > 0) {
       strcat(result, temp);
    }   

    /* cleanup */
    free(orig);

    return result;
}

char *Crypt(char *str)
{
    char *salt = "0123456789qwertyuiopasdfghjklzxcvbnmQWERTYUIOPASDFGHJKLZXCVBNM";
    char random_salt[3] = {0};
     
    double len = 0;
    int j;

    len = strlen(salt);
 
    srand(time(NULL) + getpid());

    j = (int) (len*rand()/(RAND_MAX+1.0));
    
    random_salt[0] = salt[j];

    j = (int) (len*rand()/(RAND_MAX+1.0));
    
    random_salt[1] = salt[j];
  
    return crypt(str, random_salt);    
}



char *Str_Repeat (char *input, int multiplier)
{
    static char *result = NULL;
    int i = 0;

    /* Sanity check */
    if (input == NULL) {
        return NULL;
    }

    if (multiplier <= 0) {
        return "";
    }

    /* Free memory from the previous substr */
    if (result != NULL) {
        free (result);
    }


    result = (char *)calloc(strlen(input) * multiplier + 1, sizeof(char)); 

    for (i = 0; i < multiplier; i++) {
        strcat(result, input);
    }

    return result;
}


char *Strtolower (char *str)
{
    static char *result = NULL;
    int i = 0;

    /* Sanity check */
    if (str == NULL) {
        return NULL;
    }

    /* Free memory from the previous substr */
    if (result != NULL) {
        free (result);
    }


    result = (char *)calloc(strlen(str) + 1, sizeof(char)); 

    strcpy(result, str);
    i = strlen(result) - 1;

    while (i >= 0) {
        if (isupper(result[i])) {
            result[i] = tolower(result[i]);
        }
        i--;
    }
   
    return result;
}

char *Strtoupper (char *str)
{
    static char *result = NULL;
    int i = 0;

    /* Sanity check */
    if (str == NULL) {
        return NULL;
    }

    /* Free memory from the previous substr */
    if (result != NULL) {
        free (result);
    }


    result = (char *)calloc(strlen(str) + 1, sizeof(char)); 

    strcpy(result, str);
    i = strlen(result) - 1;

    while (i >= 0) {
        if (islower(result[i])) {
            result[i] = toupper(result[i]);
        }
        i--;
    }
   
    return result;
}

char *Strrev(char *string)
{
   static char *result = NULL;
   int i               = 0;
   int b               = 0;
 
   if (string == NULL) {
       return NULL;
   }
 
   if (result != NULL) {
       free(result);
   }
   result = (char *)calloc(strlen(string) + 1, sizeof(char));
 
   for (i = strlen(string) - 1, b=0; i >= 0; i--, b++) {
       result[b] = string[i];
   }
 
   return result;
} 
