1 /*
2 * $Id$
3 *
4 * Copyright (c) 2015, vim-jp
5 *
6 * This source code is released for free distribution under the terms of the
7 * GNU General Public License version 2 or (at your option) any later version.
8 *
9 * This module contains functions for checking multibyte character set.
10 */
11
12 /*
13 * INCLUDE FILES
14 */
15 #ifndef __USE_GNU
16 # define __USE_GNU
17 #endif
18 #include "general.h" /* must always come first */
19
20 #ifdef HAVE_ICONV
21
22 #include <stdio.h>
23 #include <string.h>
24 #include <iconv.h>
25 #include <errno.h>
26 #include "options.h"
27 #include "mbcs.h"
28 #include "mbcs_p.h"
29 #include "routines.h"
30
31 static iconv_t iconv_fd = (iconv_t) -1;
32
openConverter(const char * inputEncoding,const char * outputEncoding)33 extern bool openConverter (const char* inputEncoding, const char* outputEncoding)
34 {
35 if (!inputEncoding || !outputEncoding)
36 {
37 static bool warn = false;
38 /* --output-encoding is specified but not --input-encoding provided */
39 if (!warn && outputEncoding)
40 {
41 error (WARNING, "--input-encoding is not specified");
42 warn = true;
43 }
44 return false;
45 }
46 iconv_fd = iconv_open(outputEncoding, inputEncoding);
47 if (iconv_fd == (iconv_t) -1)
48 {
49 error (FATAL,
50 "failed opening encoding from '%s' to '%s'", inputEncoding, outputEncoding);
51 return false;
52 }
53 return true;
54 }
55
isConverting()56 extern bool isConverting ()
57 {
58 return iconv_fd != (iconv_t) -1;
59 }
60
convertString(vString * const string)61 extern bool convertString (vString *const string)
62 {
63 size_t dest_len, src_len;
64 char *dest, *dest_ptr, *src;
65 if (iconv_fd == (iconv_t) -1)
66 return false;
67 src_len = vStringLength (string);
68 /* Should be longest length of bytes. so maybe utf8. */
69 dest_len = src_len * 4;
70 dest_ptr = dest = xCalloc (dest_len, char);
71 if (!dest)
72 return false;
73 src = vStringValue (string);
74 retry:
75 if (iconv (iconv_fd, &src, &src_len, &dest_ptr, &dest_len) == (size_t) -1)
76 {
77 if (errno == EILSEQ)
78 {
79 *dest_ptr++ = '?';
80 dest_len--;
81 src++;
82 src_len--;
83 verbose (" Encoding: %s\n", strerror(errno));
84 goto retry;
85 }
86 eFree (dest);
87 return false;
88 }
89
90 dest_len = dest_ptr - dest;
91
92 vStringClear (string);
93 if (vStringSize (string) < dest_len + 1)
94 vStringResize (string, dest_len + 1);
95 memcpy (vStringValue (string), dest, dest_len + 1);
96 vStringLength (string) = dest_len;
97 eFree (dest);
98
99 iconv (iconv_fd, NULL, NULL, NULL, NULL);
100
101 return true;
102 }
103
closeConverter()104 extern void closeConverter ()
105 {
106 if (iconv_fd != (iconv_t) -1)
107 {
108 iconv_close(iconv_fd);
109 iconv_fd = (iconv_t) -1;
110 }
111 }
112
113 #endif /* HAVE_ICONV */
114