Skip to content

Commit

Permalink
Move encoding conversion routine out of mailinfo to utf8.c
Browse files Browse the repository at this point in the history
This moves the body of convert_to_utf8() routine used in mailinfo
to the utf8.c i18n library.

Signed-off-by: Junio C Hamano <junkio@cox.net>
  • Loading branch information
Junio C Hamano committed Dec 26, 2006
1 parent 6934dec commit b45974a
Show file tree
Hide file tree
Showing 3 changed files with 69 additions and 30 deletions.
39 changes: 9 additions & 30 deletions builtin-mailinfo.c
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
*/
#include "cache.h"
#include "builtin.h"
#include "utf8.h"

static FILE *cmitmsg, *patchfile, *fin, *fout;

Expand Down Expand Up @@ -510,40 +511,18 @@ static int decode_b_segment(char *in, char *ot, char *ep)

static void convert_to_utf8(char *line, char *charset)
{
#ifndef NO_ICONV
char *in, *out;
size_t insize, outsize, nrc;
char outbuf[4096]; /* cheat */
static char latin_one[] = "latin1";
char *input_charset = *charset ? charset : latin_one;
iconv_t conv = iconv_open(metainfo_charset, input_charset);

if (conv == (iconv_t) -1) {
static int warned_latin1_once = 0;
if (input_charset != latin_one) {
fprintf(stderr, "cannot convert from %s to %s\n",
input_charset, metainfo_charset);
*charset = 0;
}
else if (!warned_latin1_once) {
warned_latin1_once = 1;
fprintf(stderr, "tried to convert from %s to %s, "
"but your iconv does not work with it.\n",
input_charset, metainfo_charset);
}
char *out = reencode_string(line, metainfo_charset, input_charset);

if (!out) {
fprintf(stderr, "cannot convert from %s to %s\n",
input_charset, metainfo_charset);
*charset = 0;
return;
}
in = line;
insize = strlen(in);
out = outbuf;
outsize = sizeof(outbuf);
nrc = iconv(conv, &in, &insize, &out, &outsize);
iconv_close(conv);
if (nrc == (size_t) -1)
return;
*out = 0;
strcpy(line, outbuf);
#endif
strcpy(line, out);
free(out);
}

static int decode_header_bq(char *it)
Expand Down
54 changes: 54 additions & 0 deletions utf8.c
Original file line number Diff line number Diff line change
Expand Up @@ -276,3 +276,57 @@ void print_wrapped_text(const char *text, int indent, int indent2, int width)
}
}
}

/*
* Given a buffer and its encoding, return it re-encoded
* with iconv. If the conversion fails, returns NULL.
*/
#ifndef NO_ICONV
char *reencode_string(const char *in, const char *out_encoding, const char *in_encoding)
{
iconv_t conv;
size_t insz, outsz, outalloc;
char *out, *outpos, *cp;

if (!in_encoding)
return NULL;
conv = iconv_open(out_encoding, in_encoding);
if (conv == (iconv_t) -1)
return NULL;
insz = strlen(in);
outsz = insz;
outalloc = outsz + 1; /* for terminating NUL */
out = xmalloc(outalloc);
outpos = out;
cp = (char *)in;

while (1) {
size_t cnt = iconv(conv, &cp, &insz, &outpos, &outsz);

if (cnt == -1) {
size_t sofar;
if (errno != E2BIG) {
free(out);
iconv_close(conv);
return NULL;
}
/* insz has remaining number of bytes.
* since we started outsz the same as insz,
* it is likely that insz is not enough for
* converting the rest.
*/
sofar = outpos - out;
outalloc = sofar + insz * 2 + 32;
out = xrealloc(out, outalloc);
outpos = out + sofar;
outsz = outalloc - sofar - 1;
}
else {
*outpos = '\0';
break;
}
}
iconv_close(conv);
return out;
}
#endif
6 changes: 6 additions & 0 deletions utf8.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,10 @@ int utf8_width(const char **start);
int is_utf8(const char *text);
void print_wrapped_text(const char *text, int indent, int indent2, int len);

#ifndef NO_ICONV
char *reencode_string(const char *in, const char *out_encoding, const char *in_encoding);
#else
#define reencode_string(a,b,c) NULL
#endif

#endif

0 comments on commit b45974a

Please sign in to comment.