/* Copyright (C) 2007-2008 The Android Open Source Project
**
** This software is licensed under the terms of the GNU General Public
** License version 2, as published by the Free Software Foundation, and
** may be copied, distributed, and modified under those terms.
**
** 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.
*/

#include "android/utils/misc.h"

#include "android/utils/debug.h"
#include "android/utils/stralloc.h"

#include <errno.h>
#include <limits.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>

#define  E(...)    derror(__VA_ARGS__)

extern void
print_tabular( const char** strings, int  count,
               const char*  prefix,  int  width )
{
    int  nrows, ncols, r, c, n, maxw = 0;

    for (n = 0; n < count; n++) {
        int  len = strlen(strings[n]);
        if (len > maxw)
            maxw = len;
    }
    maxw += 2;
    ncols = width/maxw;
    nrows = (count + ncols-1)/ncols;

    for (r = 0; r < nrows; r++) {
        printf( "%s", prefix );
        for (c = 0; c < ncols; c++) {
            int  index = c*nrows + r;
            if (index >= count) {
                break;
            }
            printf( "%-*s", maxw, strings[index] );
        }
        printf( "\n" );
    }
}

extern void
string_translate_char( char*  str, char from, char to )
{
    char*  p = str;
    while (p != NULL && (p = strchr(p, from)) != NULL)
        *p++ = to;
}

extern void
buffer_translate_char( char*        buff,
                       unsigned     buffLen,
                       const char*  src,
                       char         fromChar,
                       char         toChar )
{
    int len = strlen(src);
    buffer_translate_char_with_len(buff, buffLen, src, len, fromChar, toChar);
}

extern void
buffer_translate_char_with_len(char*        buff,
                               unsigned     buffLen,
                               const char*  src,
                               unsigned     srcLen,
                               char         fromChar,
                               char         toChar)
{
    if (srcLen >= buffLen)
        srcLen = buffLen-1;

    memcpy(buff, src, srcLen);
    buff[srcLen] = 0;

    string_translate_char( buff, fromChar, toChar );
}


/** TEMP CHAR STRINGS
 **
 ** implement a circular ring of temporary string buffers
 **/

typedef struct Temptring {
    struct TempString*  next;
    char*               buffer;
    int                 size;
} TempString;

#define  MAX_TEMP_STRINGS   16

static TempString  _temp_strings[ MAX_TEMP_STRINGS ];
static int         _temp_string_n;

extern char*
tempstr_get( int  size )
{
    TempString*  t = &_temp_strings[_temp_string_n];

    if ( ++_temp_string_n >= MAX_TEMP_STRINGS )
        _temp_string_n = 0;

    size += 1;  /* reserve 1 char for terminating zero */

    if (t->size < size) {
        t->buffer = realloc( t->buffer, size );
        if (t->buffer == NULL) {
            derror( "%s: could not allocate %d bytes",
                    __FUNCTION__, size );
            exit(1);
        }
        t->size   = size;
    }
    return  t->buffer;
}

extern char*
tempstr_format( const char*  fmt, ... )
{
    va_list  args;
    char*    result;
    STRALLOC_DEFINE(s);
    va_start(args, fmt);
    stralloc_formatv(s, fmt, args);
    va_end(args);
    result = stralloc_to_tempstr(s);
    stralloc_reset(s);
    return result;
}

/** QUOTING
 **
 ** dumps a human-readable version of a string. this replaces
 ** newlines with \n, etc...
 **/

extern const char*
quote_bytes( const char*  str, int  len )
{
    STRALLOC_DEFINE(s);
    char*  q;

    stralloc_add_quote_bytes( s, str, len );
    q = stralloc_to_tempstr( s );
    stralloc_reset(s);
    return q;
}

extern const char*
quote_str( const char*  str )
{
    int  len = strlen(str);
    return quote_bytes( str, len );
}

/** HEXADECIMAL CHARACTER SEQUENCES
 **/

static int
hexdigit( int  c )
{
    unsigned  d;

    d = (unsigned)(c - '0');
    if (d < 10) return d;

    d = (unsigned)(c - 'a');
    if (d < 6) return d+10;

    d = (unsigned)(c - 'A');
    if (d < 6) return d+10;

    return -1;
}

int
hex2int( const uint8_t*  hex, int  len )
{
    int  result = 0;
    while (len > 0) {
        int  c = hexdigit(*hex++);
        if (c < 0)
            return -1;

        result = (result << 4) | c;
        len --;
    }
    return result;
}

void
int2hex( uint8_t*  hex, int  len, int  val )
{
    static const uint8_t  hexchars[16] = "0123456789abcdef";
    while ( --len >= 0 )
        *hex++ = hexchars[(val >> (len*4)) & 15];
}

/** STRING PARAMETER PARSING
 **/

int
strtoi(const char *nptr, char **endptr, int base)
{
    long val;

    errno = 0;
    val = strtol(nptr, endptr, base);
    if (errno) {
        return (val == LONG_MAX) ? INT_MAX : INT_MIN;
    } else {
        if (val == (int)val) {
            return (int)val;
        } else {
            errno = ERANGE;
            return val > 0 ? INT_MAX : INT_MIN;
        }
    }
}

int
get_token_value(const char* params, const char* name, char* value, int val_size)
{
    const char* val_end;
    int len = strlen(name);
    const char* par_end = params + strlen(params);
    const char* par_start = strstr(params, name);

    /* Search for 'name=' */
    while (par_start != NULL) {
        /* Make sure that we're within the parameters buffer. */
        if ((par_end - par_start) < len) {
            par_start = NULL;
            break;
        }
        /* Make sure that par_start starts at the beginning of <name>, and only
         * then check for '=' value separator. */
        if ((par_start == params || (*(par_start - 1) == ' ')) &&
                par_start[len] == '=') {
            break;
        }
        /* False positive. Move on... */
        par_start = strstr(par_start + 1, name);
    }
    if (par_start == NULL) {
        return -1;
    }

    /* Advance past 'name=', and calculate value's string length. */
    par_start += len + 1;
    val_end = strchr(par_start, ' ');
    if (val_end == NULL) {
        val_end = par_start + strlen(par_start);
    }
    len = val_end - par_start;

    /* Check if fits... */
    if ((len + 1) <= val_size) {
        memcpy(value, par_start, len);
        value[len] = '\0';
        return 0;
    } else {
        return len + 1;
    }
}

int
get_token_value_alloc(const char* params, const char* name, char** value)
{
    char tmp;
    int res;

    /* Calculate size of string buffer required for the value. */
    const int val_size = get_token_value(params, name, &tmp, 0);
    if (val_size < 0) {
        *value = NULL;
        return val_size;
    }

    /* Allocate string buffer, and retrieve the value. */
    *value = (char*)malloc(val_size);
    if (*value == NULL) {
        E("%s: Unable to allocated %d bytes for string buffer.",
          __FUNCTION__, val_size);
        return -2;
    }
    res = get_token_value(params, name, *value, val_size);
    if (res) {
        E("%s: Unable to retrieve value into allocated buffer.", __FUNCTION__);
        free(*value);
        *value = NULL;
    }

    return res;
}

int
get_token_value_int(const char* params, const char* name, int* value)
{
    char val_str[64];   // Should be enough for all numeric values.
    if (!get_token_value(params, name, val_str, sizeof(val_str))) {
        errno = 0;
        *value = strtoi(val_str, (char**)NULL, 10);
        if (errno) {
            E("%s: Value '%s' of the parameter '%s' in '%s' is not a decimal number.",
              __FUNCTION__, val_str, name, params);
            return -2;
        } else {
            return 0;
        }
    } else {
        return -1;
    }
}
