module utils.encoding.iconv;

import
		std.conv,
		std..string,
		std.encoding,

		core.stdc.errno,

		utils.except;


version(linux):

auto iconv(string s, string from, string to)
{
	auto q = to ~ `//IGNORE//TRANSLIT`;
	auto iv = iconv_open(q.toStringz, from.toStringz);

	cast(ptrdiff_t)iv != -1 || throwError!`can't convert from %s to %s`(from, to);

	scope(exit)
	{
		iconv_close(iv);
	}

	auto p = s.ptr;
	auto len = s.length;

	string res;
	char[2048] tmp = void;

	while(len)
	{
		auto b = tmp.ptr;
		auto bs = tmp.length;

		auto c = iconv(iv, cast(char**)&p, &len, &b, &bs);

		c != size_t.max || errno == E2BIG || throwError(`conversion error`);
		res ~= tmp[0..$ - bs];
	}

	return res;
}

extern(C):

void* iconv_open(in char*, in char*);
size_t iconv(void*, char**, size_t*, char**, size_t*);

int iconv_close(void*);