xref: /Universal-ctags/main/mbcs.c (revision f38d6693208ea5a7f60d44f253d90567ab505254)
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