Titan Core Initial Contribution
[deliverable/titan.core.git] / regression_test / iconv / iconver.cc
1 ///////////////////////////////////////////////////////////////////////////////
2 // Copyright (c) 2000-2014 Ericsson Telecom AB
3 // All rights reserved. This program and the accompanying materials
4 // are made available under the terms of the Eclipse Public License v1.0
5 // which accompanies this distribution, and is available at
6 // http://www.eclipse.org/legal/epl-v10.html
7 ///////////////////////////////////////////////////////////////////////////////
8 #include <TTCN3.hh>
9 #include <iconv.h>
10 #include <errno.h>
11 #include <vector>
12
13 #if defined(WIN32)
14 #include <cygwin/version.h>
15 #endif
16
17 #if defined(LINUX) || defined(INTERIX) || (CYGWIN_VERSION_DLL_MAJOR >= 1007)
18 #define ICONV_INPUT_TYPE char*
19 #else
20 #define ICONV_INPUT_TYPE const char*
21 #endif
22
23 static const universal_char ucs4_bom = { 0,0,0xFE,0xFF };
24
25 namespace converter
26 {
27 // Convert from octetstring in UTF-8 to universal charstring
28 INTEGER o2u(const CHARSTRING& encoding, const OCTETSTRING& input, UNIVERSAL_CHARSTRING& output)
29 {
30 errno = 0;
31 iconv_t t = iconv_open("UCS-4BE", (const char*)encoding); // to, from
32 if ((iconv_t)-1 == t) {
33 perror(encoding);
34 return errno;
35 }
36 size_t inbytesleft = input.lengthof();
37 ICONV_INPUT_TYPE inptr = (ICONV_INPUT_TYPE)(const unsigned char *)input;
38
39 // Scott Meyers, Effective STL, Item 16.
40 // Don't even think of using Titan's vector like this!
41 std::vector<universal_char> outbuf(inbytesleft + 1);
42 // +1 for the BOM that Solaris iconv likes to put in at the front
43 char* outptr = (char*)&outbuf.front();
44 size_t const outbytes = outbuf.size() * 4; // size is in universal_char
45 size_t outbytesleft = outbytes; // will be modified by iconv
46
47 size_t rez = iconv(t, &inptr, &inbytesleft, &outptr, &outbytesleft);
48 if (rez == (size_t)-1) {
49 perror("*** iconv ***"); // oh dear
50 }
51 else {
52 size_t is_bom = ( ucs4_bom == outbuf.front() );
53 output = UNIVERSAL_CHARSTRING((outbytes - outbytesleft - is_bom) / 4, &outbuf[is_bom]);
54 errno = 0; // Solaris iconv may set errno to nonzero even after successful conversion :-O
55 }
56 iconv_close(t);
57
58 return errno;
59 }
60
61 // Convert from universal charstring to octetstring in UTF-8
62 INTEGER u2o(const CHARSTRING& encoding, const UNIVERSAL_CHARSTRING& input, OCTETSTRING& output)
63 {
64 errno = 0;
65 iconv_t t = iconv_open((const char*)encoding, "UCS-4BE"); // to, from
66 if ((iconv_t)-1 == t) {
67 perror(encoding);
68 return errno;
69 }
70
71 size_t inbytesleft = input.lengthof(); // in characters
72 size_t to_be = inbytesleft * 6; // max 6 bytes in UTF-8 per character
73 inbytesleft *= 4; // count in bytes
74
75 char* const inbuf = (char*)input.operator const universal_char*();
76 ICONV_INPUT_TYPE inptr = inbuf; // will be modified by iconv
77 std::vector<unsigned char> outbuf(to_be | !to_be);
78 // to_be, or not to_be, that is the question.
79 // This makes sure that the vector's size is at least 1.
80 char* outptr = (char*)&outbuf.front();
81
82 size_t rez = iconv(t, &inptr, &inbytesleft, &outptr, &to_be);
83 if (rez == (size_t)-1) {
84 perror("*** iconv ***"); // oh dear
85 }
86 else {
87 output = OCTETSTRING(outbuf.size() - (to_be | !to_be), &outbuf.front());
88 errno = 0; // Solaris iconv may set errno to nonzero even after successful conversion :-O
89 }
90 iconv_close(t);
91
92 return errno;
93 }
94
95 } // namespace
96
97 // Drag o2u and u2o out to the global namespace for compatibility with old names.
98 // Ifdef-ing the namespace away will probably fail when this file is used
99 // from projects where old naming is permanently disabled.
100
101 INTEGER o2u(const CHARSTRING& encoding, const OCTETSTRING& input, UNIVERSAL_CHARSTRING& output) {
102 return converter::o2u(encoding, input, output);
103 }
104
105 INTEGER u2o(const CHARSTRING& encoding, const UNIVERSAL_CHARSTRING& input, OCTETSTRING& output) {
106 return converter::u2o(encoding, input, output);
107 }
108
This page took 0.039411 seconds and 5 git commands to generate.