Codebase list unrtf / bd13ae3a-94e6-40bf-b472-38179327dae8/main src / my_iconv.c
bd13ae3a-94e6-40bf-b472-38179327dae8/main

Tree @bd13ae3a-94e6-40bf-b472-38179327dae8/main (Download .tar.gz)

my_iconv.c @bd13ae3a-94e6-40bf-b472-38179327dae8/main

d5eaff9
 
 
 
 
 
 
 
 
4329b02
d5eaff9
 
 
 
dff09ba
4329b02
dff09ba
4329b02
 
d5eaff9
 
 
 
 
 
 
 
 
dff09ba
 
4329b02
 
 
 
641be09
4329b02
 
 
641be09
dff09ba
 
641be09
dff09ba
641be09
4329b02
dff09ba
4329b02
 
dff09ba
 
 
4329b02
dff09ba
4329b02
 
 
 
 
dff09ba
 
641be09
dff09ba
4329b02
 
dff09ba
 
641be09
dff09ba
641be09
4329b02
 
 
 
 
 
 
 
d5eaff9
 
 
 
 
 
dff09ba
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
d5eaff9
 
 
 
 
 
 
 
 
 
4329b02
dff09ba
4329b02
dff09ba
d5eaff9
dff09ba
d5eaff9
dff09ba
 
d5eaff9
dff09ba
 
 
 
 
 
d5eaff9
dff09ba
 
 
 
 
 
 
 
 
 
 
d5eaff9
4329b02
dff09ba
 
 
 
 
d5eaff9
 
 
dff09ba
d5eaff9
dff09ba
d5eaff9
 
 
 
 
 
 
 
 
 
 
 
 
dff09ba
 
 
 
d5eaff9
 
 
 
 
 
dff09ba
d5eaff9
 
dff09ba
d5eaff9
 
 
 
 
dff09ba
 
d5eaff9
dff09ba
 
d5eaff9
dff09ba
d5eaff9
 
 
 
 
 
 
dff09ba
d5eaff9
 
 
/*----------------------------------------------------------------------
 * Module name:  my_iconv
 * Author name:  Arkadiusz Firus
 * Create date:  07 Sep 08
 * Purpose:    iconv handles
 *----------------------------------------------------------------------
 Changes:
 * 04 Jan 10, daved@physiol.usyd.edu.au: use path specfied with -P to
 *	load charmap file(s)
 * 07 Oct 11, jf@dockes.org, major changes to unicode translations
 *--------------------------------------------------------------------*/

#include <stdio.h>
#include <string.h>
#ifndef _WIN32
#include <unistd.h>
#endif
#include <stdlib.h>
#include <errno.h>

#include "malloc.h"
#include "my_iconv.h"
#include "util.h"
#include "unicode.h"
#include "path.h"

extern int verbose_mode;

/* Convert from charmap file entry to charmap table one.
   1st byte in table entry is code length
*/
static char *
get_code_str(FILE *f, iconv_t desc)
{
	char *icp, *ocp0, *ocp;
	size_t ibytes, obytes;
	char *obuf;

	char *utf8 = get_unicode_utf8(f);
	if (utf8 == NULL || *utf8 == 0)
	{
		/* fprintf(stderr, "get_code_str: NULL entry\n");*/
		my_free(utf8);
		return NULL;
	}
#if 0 /* debug */
	fprintf(stderr, "get_code_str: utf8: ");
	for (ocp = utf8; *ocp; ocp++)
	{
		fprintf(stderr, "%x", (unsigned)*ocp);
	}
	fprintf(stderr, "\n");
#endif

	obytes = 10;
	ibytes = strlen(utf8);
	obuf = malloc(obytes);
	if (obuf == NULL)
	{
		my_free(utf8);
		return NULL;
	}
	icp = utf8;
	ocp0 = ocp = obuf + 1;
	if (iconv(desc, &icp, &ibytes, &ocp, &obytes) == -1)
	{
		/*        fprintf(stderr, "unrtf: my_iconv: iconv error\n");*/
		my_free(utf8);
		return NULL;
	}

	// Set 1st byte to length
	obuf[0] = ocp - ocp0;
	my_free(utf8);
	return obuf;
}

my_iconv_t
my_iconv_open(const char *tocode, const char *fromcode)
{
	FILE *f;
	my_iconv_t cd = MY_ICONV_T_CLEAR;
	int c, i;
	/*      fprintf(stderr, "my_iconv_open: from %s to %s\n", fromcode, tocode);*/
	if ((cd.desc = iconv_open(tocode, fromcode)) == (iconv_t) - 1)
	{
		char *path = search_in_path(fromcode, "charmap");
		if (path == NULL)
		{
			return cd;
		}
		if ((f = fopen(path, "r")) == NULL && verbose_mode)
		{
			fprintf(stderr, "failed to open charmap file %s\n", path);
		}

		if (f != NULL)
		{
			/* Open iconv utf8->tocode conversion */
			iconv_t desc;
			if ((desc = iconv_open(tocode, "UTF-8")) == (iconv_t) - 1)
			{
				fclose(f);
				return cd;
			}
			cd.char_table = (char **)my_malloc(char_table_size *
			                                   sizeof(char *));
			c = fgetc(f);

			for (i = 0; i < char_table_size && c != EOF; i++)
			{
				if (c == '<')
				{
					cd.char_table[i] = get_code_str(f, desc);
				}
				leave_line(f);//read up to including \n or eof
				c = fgetc(f);
			}
			iconv_close(desc);
			fclose(f);
		}

		my_free(path);
	}

	return cd;
}

size_t
my_iconv(my_iconv_t cd, char **inbuf, size_t *inbytesleft, char **outbuf, size_t *outbytesleft)
{
	int c, i;
	size_t result = 0;
	**outbuf = 0;
	if (cd.desc == (iconv_t) - 1)
	{
		if (cd.char_table != NULL)
		{
			while (*inbytesleft > 0 && *outbytesleft > 0)
			{
				c = **(unsigned char **)inbuf;
				if (cd.char_table[c] != NULL)
				{
					for (i = 0; i < cd.char_table[c][0] && *outbytesleft > 0; i++)
					{
						**outbuf = cd.char_table[c][i + 1];
						(*outbytesleft)--;
						(*outbuf)++;
					}
				}
				else
				{
					/*                    fprintf(stderr, "my_iconv: no conversion for 0x%x\n",
						      (unsigned)c);*/
					errno = EILSEQ;
					return (size_t) - 1;
				}

				(*inbuf)++;
				(*inbytesleft)--;
				result++;
			}

			if (*outbytesleft == 0 && *inbytesleft > 0)
			{
				errno = E2BIG;
				result = (size_t) - 1;
			}
		}
	}
	else
	{
		result = iconv(cd.desc, inbuf, inbytesleft, outbuf, outbytesleft);
	}

	return result;
}

my_iconv_t
my_iconv_close(my_iconv_t cd)
{
	int i;

	if (cd.char_table != NULL)
	{
		for (i = 0; i < char_table_size; i++)
		{
			if (cd.char_table[i] != NULL)
			{
				my_free(cd.char_table[i]);
			}
		}

		my_free((void *)cd.char_table);
		cd.char_table = NULL;
	}

	if (cd.desc != (iconv_t) - 1)
	{
		iconv_close(cd.desc);
		cd.desc = (iconv_t) - 1;
	}

	return cd;
}

int
my_iconv_is_valid(my_iconv_t cd)
{
	if (cd.desc != (iconv_t) - 1 || cd.char_table != NULL)
	{
		return 1;
	}

	return 0;
}

void
my_iconv_t_make_invalid(my_iconv_t *cd)
{
	cd->desc = (iconv_t) - 1;
	cd->char_table = NULL;
}