1 |
// Iconv ISO-8859-1 To UTF-8 |
2 |
// |
3 |
// Douglas Thrift |
4 |
// |
5 |
// $Id$ |
6 |
|
7 |
#include <cxx/standard.hh> |
8 |
|
9 |
#include <hop/function.hpp> |
10 |
|
11 |
#include <iconv.h> |
12 |
|
13 |
#include "Iso88591ToUtf8.hpp" |
14 |
|
15 |
template <typename Char> |
16 |
static _finline size_t Iconv_(::iconv_t conversion, const char **inBytes, size_t *inBytesLeft, char **outBytes, size_t *outBytesLeft, size_t (*)(::iconv_t, Char **, size_t *, char **, size_t *)) |
17 |
{ |
18 |
return ::iconv(conversion, const_cast<Char **>(inBytes), inBytesLeft, outBytes, outBytesLeft); |
19 |
} |
20 |
|
21 |
#define Iconv_(conversion, inBytes, inBytesLeft, outBytes, outBytesLeft) Iconv_(conversion, inBytes, inBytesLeft, outBytes, outBytesLeft, &::iconv) |
22 |
|
23 |
//#define Iconv_(a, b, c, d, e) iconv(a, const_cast<typename hop::FunctionTraits<typeof(iconv)>::Args::Tail::Head>(b), c, d, e) |
24 |
|
25 |
namespace Iconv |
26 |
{ |
27 |
|
28 |
cse::String Iso88591ToUtf8(const ext::Buffer &iso88591) |
29 |
{ |
30 |
::iconv_t conversion(reinterpret_cast<void *>(api::Posix::CheckError(reinterpret_cast<int>(::iconv_open("UTF-8", "ISO-8859-1"))))); |
31 |
ext::Buffer utf8(iso88591.GetSize()); |
32 |
const char *iso88591Bytes(iso88591.Begin()); |
33 |
char *utf8Bytes(utf8.Begin()); |
34 |
size_t code, iso88591BytesLeft(iso88591.GetSize()), utf8BytesLeft(utf8.GetSize()); |
35 |
|
36 |
while ((code = Iconv_(conversion, &iso88591Bytes, &iso88591BytesLeft, &utf8Bytes, &utf8BytesLeft)) == size_t(-1)) |
37 |
if (errno != E2BIG) |
38 |
api::Posix::CheckError(code); |
39 |
else |
40 |
{ |
41 |
utf8.SetSize(utf8.GetSize() + (utf8BytesLeft += iso88591BytesLeft)); |
42 |
|
43 |
utf8Bytes = utf8.End() - utf8BytesLeft; |
44 |
} |
45 |
|
46 |
api::Posix::CheckError(::iconv_close(conversion)); |
47 |
|
48 |
return utf8; |
49 |
} |
50 |
|
51 |
} |