/*
 * tkresolver
 *
 * Copyright (C) 2004-2007 Robert Ham <rah@bash.sh>
 *
 * GPL
 *
 */

#ifndef _GNU_SOURCE
#define _GNU_SOURCE
#endif

#include <wchar.h>
#include <errno.h>

#include "mbs.h"

using namespace TkResolver;

wchar_t *
TkResolver:: mbstowcs_alloc (const char *string)
{
  mbstate_t state;
  const char *str = string;
  size_t buf_size = strlen(string) + 1;
  wchar_t * buf = static_cast<wchar_t *> (malloc (buf_size * sizeof (wchar_t)));
  wchar_t * conversion_start = buf;
  size_t buf_done = 0;
  size_t converted;

  memset(&state, '\0', sizeof(state));
      
  while (1)
    {
      converted = mbsrtowcs(conversion_start, &str, buf_size - buf_done, &state);
	  
      if (converted == (size_t)(-1))
	throw UnixError("Could not convert multi-byte string to wide-character string: ", errno);
	  
      if (str == NULL)
	break;
	  
      buf_done += converted;
      buf_size += 1;
      buf = static_cast<wchar_t *>( realloc(buf, buf_size * sizeof(wchar_t)) );
      conversion_start = buf + buf_done;
    }
      
  return buf;
}

char *
TkResolver:: wcstombs_alloc (const wchar_t * string)
{
  mbstate_t state;
  const wchar_t *str = string;
  size_t buf_size = wcslen(string) + 1;
  char * buf = static_cast<char *> (malloc (buf_size * sizeof (char)));
  char * conversion_start = buf;
  size_t buf_done = 0;
  size_t converted;

  memset(&state, '\0', sizeof(state));
      
  while (1)
    {
      converted = wcsrtombs(conversion_start, &str, buf_size - buf_done, &state);
	  
      if (converted == (size_t)(-1))
	throw UnixError("Could not convert wide-character string to multi-byte string: ", errno);
	  
      if (str == NULL)
	break;
	  
      buf_done += converted;
      buf_size += 1;
      buf = static_cast<char *>( realloc(buf, buf_size * sizeof(char)) );
      conversion_start = buf + buf_done;
    }
      
  return buf;
}
