/***************************************************************************
 *   copyright           : (C) 2002 by Hendrik Sattler                     *
 *   mail                : post@hendrik-sattler.de                         *
 *                                                                         *
 *   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.                                   *
 *                                                                         *
 ***************************************************************************/

#include <helper.h>

#include <ctype.h>
#include <string.h>
#include <stdlib.h>

/* requires to link with -lm
 * does not work with Cygwin (log10l() not implemented)
 */
#include <config.h>
#if defined(HAVE_MATH_H) && defined(HAVE_LOG10) && defined(HAVE_LABS)
#include <math.h>
unsigned int numlen (long num) {
  unsigned int a = 1;
  if (num == 0) return 1;
  else if (num < 0) ++a;
  return (unsigned int)(log10((double)labs(num))+a);
}
#else
unsigned int numlen (long num) {
  int retval = 1;

  if (num < 0) {
    ++retval;
    num *= -1;
  }
  while (num >= 10) {
    ++retval;
    num /= 10;
  }
  return retval;
}
#endif

unsigned int hexstr2int (char *hexstring, unsigned int length) {
  unsigned int i = 0;
  unsigned int intvalue = 0;
  unsigned int shift;

  if (str_len(hexstring) < length) length = str_len(hexstring);
  shift = 4*(length-1);
  for (;i < length; ++i) {
    switch (hexstring[i]) {
    case '0':
    case '1':
    case '2':
    case '3':
    case '4':
    case '5':
    case '6':
    case '7':
    case '8':
    case '9':
      intvalue += ((hexstring[i] - '0') << shift);
    default:
      break;
    case 'A':
    case 'B':
    case 'C':
    case 'D':
    case 'E':
    case 'F':
      intvalue += ((hexstring[i] - 'A' + 10) << shift);
      break;
    case 'a':
    case 'b':
    case 'c':
    case 'd':
    case 'e':
    case 'f':
      intvalue += ((hexstring[i] - 'a' + 10) << shift);
      break;
    }
    shift -= 4; //multiplicator: <<4*  = *16^
  }
  return intvalue;
}

int is_number(const char* s) {
  unsigned int i = 0;
  if (str_len(s) == 0) return 0;
  for (; i < strlen(s); ++i) if (isdigit((int)s[i]) == 0) return 0;
  return 1;
}

int is_telephone_number (const char* s) {
  if (str_len(s) == 0) return 0;
  if (s[0] == '+') ++s;
  return is_number(s);
}

uint16_t letohs (uint16_t i) {
  uint8_t* k = (uint8_t*)&i;
  return (uint16_t)(k[0]|(k[1]<<8));
}

uint32_t letohl (uint32_t i) {
  uint8_t* k = (uint8_t*)&i;
  return (uint32_t)(k[0]|(k[1]<<8)|(k[2]<<16)|(k[3]<<24));
}

#include <assert.h>
uint16_t htoles (uint16_t i) {
  union {
    struct __attribute__((packed)) {
      uint8_t low;
      uint8_t high;
    } s;
    uint16_t n;
  } u;
  assert(sizeof(u) == sizeof(uint16_t));
  u.s.low = i&0xFF;
  u.s.high = (i>>8)&0xFF;
  return u.n;  
}

uint32_t htolel (uint32_t i) {
  union {
    struct __attribute__((packed)) {
      uint8_t lowest;
      uint8_t low;
      uint8_t high;
      uint8_t highest;
    } s;
    uint32_t n;
  } u;
  assert(sizeof(u) == sizeof(uint32_t));
  u.s.lowest = i&0xFF;
  u.s.low = (i>>8)&0xFF;
  u.s.high = (i>>16)&0xFF;
  u.s.highest = (i>>24)&0xFF;
  return (uint32_t)u.n;
}
