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 |
namespace |
16 |
{ |
17 |
|
18 |
template <typename Char> |
19 |
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 *)) |
20 |
{ |
21 |
return ::iconv(conversion, const_cast<Char **>(inBytes), inBytesLeft, outBytes, outBytesLeft); |
22 |
} |
23 |
|
24 |
#define Iconv_(conversion, inBytes, inBytesLeft, outBytes, outBytesLeft) Iconv_(conversion, inBytes, inBytesLeft, outBytes, outBytesLeft, &::iconv) |
25 |
|
26 |
} |
27 |
|
28 |
namespace Iconv |
29 |
{ |
30 |
|
31 |
cse::String Iso88591ToUtf8(const ext::Buffer &iso88591) |
32 |
{ |
33 |
::iconv_t conversion(reinterpret_cast<void *>(api::Posix::CheckError(reinterpret_cast<int>(::iconv_open("UTF-8", "ISO-8859-1"))))); |
34 |
ext::Buffer utf8(iso88591.GetSize()); |
35 |
const char *iso88591Bytes(iso88591.Begin()); |
36 |
char *utf8Bytes(utf8.Begin()); |
37 |
size_t code, iso88591BytesLeft(iso88591.GetSize()), utf8BytesLeft(utf8.GetSize()); |
38 |
|
39 |
while ((code = Iconv_(conversion, &iso88591Bytes, &iso88591BytesLeft, &utf8Bytes, &utf8BytesLeft)) == size_t(-1)) |
40 |
if (errno != E2BIG) |
41 |
api::Posix::CheckError(code); |
42 |
else |
43 |
{ |
44 |
utf8.SetSize(utf8.GetSize() + (utf8BytesLeft += iso88591BytesLeft)); |
45 |
|
46 |
utf8Bytes = utf8.End() - utf8BytesLeft; |
47 |
} |
48 |
|
49 |
api::Posix::CheckError(::iconv_close(conversion)); |
50 |
|
51 |
return utf8; |
52 |
} |
53 |
|
54 |
} |