int
file2wcs (int fd, const char *charset, wchar_t *outbuf, size_t avail)
{
char inbuf[BUFSIZ];
size_t insize = 0;
char *wrptr = (char *) outbuf;
int result = 0;
iconv_t cd;
cd = iconv_open ("WCHAR_T", charset);
if (cd == (iconv_t) -1)
{
/* Yanlış giden birşeyler olabilir. */
if (errno == EINVAL)
error (0, 0, "'%s' için wchar_t cinsinden bir karşılık yok",
charset);
else
perror ("iconv_open");
/* Çıktı dizgesini sonlandıralım. */
*outbuf = L'\0';
return -1;
}
while (avail > 0)
{
size_t nread;
size_t nconv;
char *inptr = inbuf;
/* Girdinin kalanını okuyalım. */
nread = read (fd, inbuf + insize, sizeof (inbuf) - insize);
if (nread == 0)
{
/* Buraya gelimişsek okuma tamamlanmıştır. Ama hala
inbuf içinde kullanılmamış
karakterler kalmış olabilir. Onları geri koyalım. */
if (lseek (fd, -insize, SEEK_CUR) == -1)
result = -1;
/* Gerekliyse, ilk duruma girecek bayt dizilimini yazalım. */
iconv (cd, NULL, NULL, &wrptr, &avail);
break;
}
insize += nread;
/* Dönüşümü yapalım. */
nconv = iconv (cd, &inptr, &insize, &wrptr, &avail);
if (nconv == (size_t) -1)
{
/* Herşey yolunda gitmez. Tamponun sonunda bitmemiş
bir bayt dizilimi olabilir. Kimi zaman da gerçekten
önemli bir sorun olabilir.
if (errno == EINVAL)
/* Bu zararsız. Kullanılmayan baytları tamponun başına
taşıyalım ki, sonraki adımda onlar kullanılabilsin. */
memmove (inbuf, inptr, insize);
else
{
/* Bu gerçekten bir sorun. Ya çıktı tamponu yetersiz
ya da girdi geçersizdir. Her durumda, dosya
göstericisini işlenen son baytın konumuna
ayarlayacağız. */
lseek (fd, -insize, SEEK_CUR);
result = -1;
break;
}
}
}
/* Çıktı dizgesini sonlandıralım. */
if (avail >= sizeof (wchar_t))
*((wchar_t *) wrptr) = L'\0';
if (iconv_close (cd) != 0)
perror ("iconv_close");
return (wchar_t *) wrptr - outbuf;
}