/* This file is part of GMetaDOM * a generic bind package for the Document Object Model API. * Copyright (C) 2001-2002 Luca Padovani * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * For more information, please visit the project home page * http://gmetadom.sourceforge.net * or send an email to */ #include #include #include #include #include #include #include #include #include #include "GdomeSmartDOMGdomeString.hh" #include "GdomeSmartDOMUTF8String.hh" #include "GdomeSmartDOMUTF16String.hh" #include "GdomeSmartDOMUCS4String.hh" #if defined(WORDS_BIGENDIAN) #define ICONV_UTF16 ICONV_UTF16BE #else #if !defined(ICONV_UTF16LE) #define ICONV_UTF16 ICONV_UTF16BE #define UTF16_BIGENDIAN #else #define ICONV_UTF16 ICONV_UTF16LE #endif #endif #if defined(WORDS_BIGENDIAN) #define ICONV_UCS4 ICONV_UCS4BE #else #if !defined(ICONV_UCS4LE) #define ICONV_UCS4 ICONV_UCS4BE #define UCS4_BIGENDIAN #else #define ICONV_UCS4 ICONV_UCS4LE #endif #endif namespace GdomeSmartDOM { static size_t convertString(const void* source, size_t inBytesLeft, const char* sourceEnc, void** dest, const char* destEnc) { assert(source != 0); assert(sourceEnc != 0); assert(dest != 0); assert(destEnc != 0); *dest = 0; iconv_t cd = iconv_open(destEnc, sourceEnc); if (cd == (iconv_t) -1) return 0; static char buffer[128]; size_t outBytesLeft = sizeof(buffer); #ifdef ICONV_CONST const char* inbuf = reinterpret_cast(source); #else char* inbuf = new char[inBytesLeft]; assert(inbuf != NULL); memcpy(inbuf, source, inBytesLeft); char* inbuf0 = inbuf; #endif // ICONV_CONST char* outbuf = reinterpret_cast(buffer); char* outbuf0 = buffer; size_t nConv = 0; char* res = NULL; while (inBytesLeft > 0) { //cout << "before: " << (void*) inbuf << " " << inBytesLeft << " " << (void*) outbuf << " " << outBytesLeft << endl; size_t iconv_res = iconv(cd, (const char**)&inbuf, &inBytesLeft, &outbuf, &outBytesLeft); //cout << "after: " << (void*) inbuf << " " << inBytesLeft << " " << (void*) outbuf << " " << outBytesLeft << endl; unsigned n = outbuf - outbuf0; if (res == NULL) { nConv = n; res = new char[nConv]; assert(res != NULL); memcpy(res, buffer, n); } else { char* newRes = new char[n + nConv]; assert(res != NULL); memcpy(newRes, res, nConv); memcpy(newRes + nConv, buffer, n); delete [] res; res = newRes; nConv += n; } if (iconv_res == (size_t) -1) { if (errno == E2BIG) { outbuf = outbuf0; outBytesLeft = sizeof(buffer); } else { perror("iconv: "); break; } } } *dest = res; #ifndef ICONV_CONST delete [] inbuf0; #endif // ICONV_CONST iconv_close(cd); return nConv; } static size_t UCS4ofUTF8(const Char8* source, size_t size, Char32** dest) { assert(dest != 0); size_t length = convertString(source, size * sizeof(Char8), ICONV_UTF8, reinterpret_cast(dest), ICONV_UCS4); length /= sizeof(Char32); #if !defined(WORDS_BIGENDIAN) && defined(UCS4_BIGENDIAN) for (unsigned i = 0; i < length; i++) (*dest)[i] = GUINT32_SWAP_LE_BE((*dest)[i]); #endif return length; } static size_t UTF8ofUCS4(const Char32* source, size_t size, Char8** dest) { assert(dest != 0); #if !defined(WORDS_BIGENDIAN) && defined(UCS4_BIGENDIAN) Char32* sourceBuffer = new Char32[size]; for (unsigned i = 0; i < size; i++) sourceBuffer[i] = GUINT32_SWAP_LE_BE(source[i]); #else const Char32* sourceBuffer = source; #endif size_t length = convertString(sourceBuffer, size * sizeof(Char32), ICONV_UCS4, reinterpret_cast(dest), ICONV_UTF8); length /= sizeof(Char8); #if !defined(WORDS_BIGENDIAN) && defined(UCS4_BIGENDIAN) delete [] sourceBuffer; #endif return length; } static size_t UTF16ofUTF8(const Char8* source, size_t size, Char16** dest) { assert(dest != 0); size_t length = convertString(source, size * sizeof(Char8), ICONV_UTF8, reinterpret_cast(dest), ICONV_UTF16); length /= sizeof(Char16); #if !defined(WORDS_BIGENDIAN) && defined(UTF16_BIGENDIAN) for (unsigned i = 0; i < length; i++) (*dest)[i] = GUINT16_SWAP_LE_BE((*dest)[i]); #endif return length; } static size_t UTF8ofUTF16(const Char16* source, size_t size, Char8** dest) { assert(dest != 0); #if !defined(WORDS_BIGENDIAN) && defined(UTF16_BIGENDIAN) Char16* sourceBuffer = new Char16[size]; for (unsigned i = 0; i < size; i++) sourceBuffer[i] = GUINT16_SWAP_LE_BE(source[i]); #else const Char16* sourceBuffer = source; #endif size_t length = convertString(sourceBuffer, size * sizeof(Char16), ICONV_UTF16, reinterpret_cast(dest), ICONV_UTF8); length /= sizeof(Char8); #if !defined(WORDS_BIGENDIAN) && defined(UTF16_BIGENDIAN) delete [] sourceBuffer; #endif return length; } GdomeString::GdomeString() { str = 0; } GdomeString::GdomeString(const char* s) { if (s == 0) str = 0; else str = gdome_str_mkref_dup(s); } GdomeString::GdomeString(const UTF8String& s) { if (s.data() == 0) str = 0; else { assert(sizeof(char) == sizeof(Char8)); char* buffer = reinterpret_cast(malloc((s.length() + 1) * sizeof(char))); memcpy(buffer, s.data(), s.length()); buffer[s.length()] = '\0'; str = gdome_str_mkref_own(buffer); } } GdomeString::GdomeString(const UTF16String& s) { if (s.data() == 0) str = 0; else { assert(sizeof(char) == sizeof(Char8)); Char8* destBuffer; size_t length = UTF8ofUTF16(s.data(), s.length(), &destBuffer); char* buffer = reinterpret_cast(malloc((length + 1) * sizeof(char))); memcpy(buffer, destBuffer, length); buffer[length] = '\0'; delete [] destBuffer; str = gdome_str_mkref_own(buffer); } } GdomeString::GdomeString(const UCS4String& s) { if (s.data() == 0) str = 0; else { assert(sizeof(char) == sizeof(Char8)); Char8* destBuffer; size_t length = UTF8ofUCS4(s.data(), s.length(), &destBuffer); char* buffer = reinterpret_cast(malloc((length + 1) * sizeof(char))); memcpy(buffer, destBuffer, length); buffer[length] = '\0'; delete [] destBuffer; str = gdome_str_mkref_own(buffer); } } GdomeString::GdomeString(GdomeDOMString* s) { str = s; if (str != 0) gdome_str_ref(str); } GdomeString::GdomeString(const GdomeString& s) { str = s.str; if (str != 0) gdome_str_ref(str); } GdomeString::~GdomeString() { if (str != 0) { gdome_str_unref(str); str = 0; } } bool GdomeString::empty(void) const { if (str == 0) throw NullString(); else { unsigned length = gdome_str_length(str); for (unsigned i = 0; i < length; i++) if (!isspace(str->str[i])) return false; return true; } } bool GdomeString::operator==(const GdomeString& s) const { if (str == 0) return (s.str == 0); else if (s.str == 0) return false; else return gdome_str_equal(str, s.str) ? true : false; } GdomeString& GdomeString::operator=(const GdomeString& s) { if (this == &s) return *this; if (s.str != 0) gdome_str_ref(s.str); if (str != 0) gdome_str_unref(str); str = s.str; return *this; } GdomeString GdomeString::operator+(const GdomeString& s) const { if (str == 0) return GdomeString(s.str); else if (s.str == 0) return *this; else return GdomeString(gdome_str_concat(str, s.str), false); } unsigned GdomeString::length() const { if (str == 0) throw NullString(); else return gdome_str_length(str); } GdomeDOMString* GdomeString::gdome_str() const { if (str != 0) gdome_str_ref(str); return str; } GdomeString::operator UTF8String() const { if (str == 0) throw NullString(); return UTF8String(reinterpret_cast(str->str), this->length()); } GdomeString::operator UTF16String() const { if (str == 0) throw NullString(); assert(sizeof(char) == sizeof(Char8)); Char16* destBuffer; size_t length = UTF16ofUTF8(reinterpret_cast(str->str), this->length(), &destBuffer); UTF16String res(destBuffer, length); delete [] destBuffer; return res; } GdomeString::operator UCS4String() const { if (str == 0) throw NullString(); assert(sizeof(char) == sizeof(Char8)); Char32* destBuffer; size_t length = UCS4ofUTF8(reinterpret_cast(str->str), this->length(), &destBuffer); UCS4String res(destBuffer, length); delete [] destBuffer; return res; } std::ostream& operator<<(std::ostream& o, const GdomeString& str) { if (str.null()) o << "(null)"; else o << (char*) str.str->str; return o; } }