forked from odashi/iconvpp
/
iconvpp.cpp
executable file
·115 lines (91 loc) · 2.6 KB
/
iconvpp.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
// iconvpp.cpp
// Implementation of following:
// - iconvpp::Converter
#include "iconvpp.h"
#include <cstring>
#include <memory>
#include <utility>
namespace {
const ::iconv_t ICONV_INVALID_HANDLE = reinterpret_cast< ::iconv_t >(-1);
}
// Open iconv handle
// If ::iconv_open() failed, all fields in Converter could not change.
void iconvpp::Converter::open(const std::string& dest_enc, const std::string& src_enc)
{
::iconv_t obj = ::iconv_open(dest_enc.c_str(), src_enc.c_str());
if (ICONV_INVALID_HANDLE == obj)
throw iconvpp::Exception("Initialization failed.");
if (ICONV_INVALID_HANDLE != iconv_)
::iconv_close(iconv_);
iconv_ = obj;
dest_enc_ = dest_enc;
src_enc_ = src_enc;
}
// c-tor
iconvpp::Converter::Converter(const std::string& dest_enc, const std::string& src_enc)
: iconv_(ICONV_INVALID_HANDLE)
, dest_enc_()
, src_enc_()
{
open(dest_enc, src_enc);
}
// Copy c-tor
iconvpp::Converter::Converter(const Converter& src)
: iconv_(ICONV_INVALID_HANDLE)
, dest_enc_()
, src_enc_()
{
open(src.dest_enc_, src.src_enc_);
}
// Move c-tor
iconvpp::Converter::Converter(Converter&& src)
: iconv_(src.iconv_)
, dest_enc_(std::move(src.dest_enc_))
, src_enc_(std::move(src.src_enc_))
{
src.iconv_ = ICONV_INVALID_HANDLE;
}
// d-tor
iconvpp::Converter::~Converter()
{
if (ICONV_INVALID_HANDLE != iconv_)
::iconv_close(iconv_);
}
// Substitution
iconvpp::Converter& iconvpp::Converter::operator=(const Converter& src)
{
if (this == &src)
return *this;
open(src.dest_enc_, src.src_enc_);
return *this;
}
// Move substitution
iconvpp::Converter& iconvpp::Converter::operator=(Converter&& src)
{
if (this == &src)
return *this;
iconv_ = src.iconv_;
dest_enc_ = std::move(src.dest_enc_);
src_enc_ = std::move(src.src_enc_);
src.iconv_ = ICONV_INVALID_HANDLE;
return *this;
}
// Converts string
std::string iconvpp::Converter::convert(const std::string& str)
{
std::size_t from_size = str.size() + 1;
// Max length of a character is 6 bytes in UTF-8.
std::size_t to_size = 6 * from_size + 1;
std::unique_ptr<char[]> from_buf(new char[from_size]);
std::unique_ptr<char[]> to_buf(new char[to_size]);
std::strcpy(from_buf.get(), str.c_str());
// convert
std::size_t from_size_temp = from_size - 1;
std::size_t to_size_temp = to_size - 1;
char* from_ptr = from_buf.get();
char* to_ptr = to_buf.get();
if (-1 == ::iconv(iconv_, &from_ptr, &from_size_temp, &to_ptr, &to_size_temp))
throw iconvpp::Exception("Conversion failed.");
*to_ptr = '\0';
return std::string(to_buf.get());
}