/*
 * stringutil.c - string utilities
 * Copyright (C) 2010  Alexandre Martins <alemartf(at)gmail(dot)com>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program 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 General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along
 * with this program; if not, write to the Free Software Foundation, Inc.,
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 */

#include <string.h>
#include <ctype.h>
#include "stringutil.h"
#include "util.h"

/*
 * str_to_hash()
 * Generates a hash key
 */
int str_to_hash(const char *str)
{
    int hash = 0;
    const char *p;

    for(p=str; *p; p++)
        hash = (int)(*p) + (hash << 6) + (hash << 16) - hash;

    return hash;
}


/*
 * str_to_upper()
 * Upper-case convert
 */
const char *str_to_upper(const char *str)
{
    static char buf[1024];
    char *p;
    int i = 0;

    for(p=buf; *str && i<1023; str++,p++,i++)
        *p = toupper(*str);
    *p = '\0';

    return buf;
}



/*
 * str_to_lower()
 * Lower-case convert
 */
const char *str_to_lower(const char *str)
{
    static char buf[1024];
    char *p;
    int i = 0;

    for(p=buf; *str && i<1023; str++,p++,i++)
        *p = tolower(*str);
    *p = '\0';

    return buf;
}


/*
 * str_icmp()
 * Case-insensitive compare function. Returns
 * 0 if s1==s2, -1 if s1<s2 or 1 if s1>s2.
 */
int str_icmp(const char *s1, const char *s2)
{
    const char *p, *q;
    char a, b;

    for(p=s1,q=s2; *p && *q; p++,q++) {
        a = tolower(*p);
        b = tolower(*q);
        if(a < b)
            return -1;
        else if(a > b)
            return 1;
    }

    if(!*p && *q)
        return -1;
    else if(*p && !*q)
        return 1;
    else
        return 0;
}



/*
 * str_cpy()
 * Safe version of strcpy(). Returns a
 * pointer to dest.
 * If we have something like char str[32], then
 * the dest_size is 32, ie, sizeof(str)
 */
char* str_cpy(char *dest, const char *src, size_t dest_size)
{
    int c;

    for(c=0; c<dest_size-1; c++) {
        dest[c] = src[c];
        if(dest[c] == 0) break;
    }
    dest[dest_size-1] = 0;

    return dest;
}



/*
 * str_trim()
 * Trim
 */
void str_trim(char *dest, const char *src)
{
    const char *p, *q, *t;

    for(p=src; *p && isspace((unsigned char)*p); p++);
    for(q=src+strlen(src)-1; q>p && isspace((unsigned char)*q); q--);
    for(q++,t=p; t!=q; t++) *(dest++) = *t;
    *dest = 0;
}



/*
 * str_dup()
 * Duplicates a string
 */
char *str_dup(const char *str)
{
    char *p = mallocx((strlen(str)+1) * sizeof(char));
    strcpy(p, str);
    return p;
}

/*
 * str_addslashes()
 * replaces " by \\", returning a static char*
 */
const char* str_addslashes(const char *str)
{
    static char buf[1024];
    int i = 0;
    char *p;

    for(p=buf; *str && i<1023; str++,p++,i++) {
        if(*str == '"') {
            *p = '\\';
            if(++i<1023)
                *(++p) = *str;
        }
        else
            *p = *str;
    }
    *p = '\0';

    return buf;
}
