X-Git-Url: https://git.lyx.org/gitweb/?a=blobdiff_plain;f=src%2Fsupport%2Funicode.cpp;h=b5839827403ba688987636a2ebc523d5932a7902;hb=8b86f744cb7c88d13983ad6df31187f3bfa183ad;hp=26f834a58bec98aa4c38f2155ebac98365b1b3c5;hpb=41740ea915ee7a95206d780b6256e660cef39c6e;p=lyx.git diff --git a/src/support/unicode.cpp b/src/support/unicode.cpp index 26f834a58b..b583982740 100644 --- a/src/support/unicode.cpp +++ b/src/support/unicode.cpp @@ -49,105 +49,73 @@ namespace lyx { char const * ucs4_codeset = "UCS-4LE"; #endif -static const iconv_t invalid_cd = (iconv_t)(-1); - -class IconvProcessor::Impl -{ - // noncopyable because iconv_close() is called in destructor - Impl(Impl const &); - Impl & operator=(Impl const &); -public: - Impl(string const & to, string const & from) - : cd(invalid_cd), tocode_(to), fromcode_(from) - {} - - ~Impl() - { - if (cd != invalid_cd && iconv_close(cd) == -1) +struct IconvProcessor::Handler { + // assumes cd is valid + Handler(iconv_t const cd) : cd(cd) {} + ~Handler() { + if (iconv_close(cd) == -1) LYXERR0("Error returned from iconv_close(" << errno << ')'); } - - iconv_t cd; - string tocode_; - string fromcode_; + iconv_t const cd; }; -IconvProcessor::IconvProcessor(char const * tocode, char const * fromcode) - : pimpl_(new IconvProcessor::Impl(tocode, fromcode)) -{ -} - - -IconvProcessor::IconvProcessor(IconvProcessor const & other) - : pimpl_(new IconvProcessor::Impl(other.pimpl_->tocode_, other.pimpl_->fromcode_)) -{ -} - - -IconvProcessor::~IconvProcessor() -{ - delete pimpl_; -} +IconvProcessor::IconvProcessor(string tocode, string fromcode) + : tocode_(move(tocode)), fromcode_(move(fromcode)) +{} -IconvProcessor & IconvProcessor::operator=(IconvProcessor const & other) -{ - if (&other != this) { - delete pimpl_; - pimpl_ = new Impl(other.pimpl_->tocode_, other.pimpl_->fromcode_); - } - return *this; -} +// for gcc 4.6 +IconvProcessor::IconvProcessor(IconvProcessor && other) + : tocode_(move(other.tocode_)), fromcode_(move(other.fromcode_)), + h_(move(other.h_)) +{} bool IconvProcessor::init() { - if (pimpl_->cd != invalid_cd) + if (h_) return true; - - pimpl_->cd = iconv_open(pimpl_->tocode_.c_str(), pimpl_->fromcode_.c_str()); - if (pimpl_->cd != invalid_cd) + iconv_t cd = iconv_open(tocode_.c_str(), fromcode_.c_str()); + if (cd != (iconv_t)(-1)) { + h_ = make_unique(cd); return true; - + } lyxerr << "Error returned from iconv_open" << endl; switch (errno) { - case EINVAL: - lyxerr << "EINVAL The conversion from " << pimpl_->fromcode_ - << " to " << pimpl_->tocode_ - << " is not supported by the implementation." - << endl; - break; - default: - lyxerr << "\tSome other error: " << errno << endl; - break; + case EINVAL: + lyxerr << "EINVAL The conversion from " << fromcode_ << " to " + << tocode_ << " is not supported by the implementation." + << endl; + break; + default: + lyxerr << "\tSome other error: " << errno << endl; + break; } return false; } int IconvProcessor::convert(char const * buf, size_t buflen, - char * outbuf, size_t maxoutsize) + char * outbuf, size_t maxoutsize) { if (buflen == 0) return 0; - if (pimpl_->cd == invalid_cd) { - if (!init()) - return -1; - } + if (!h_ && !init()) + return -1; char ICONV_CONST * inbuf = const_cast(buf); size_t inbytesleft = buflen; size_t outbytesleft = maxoutsize; - int res = iconv(pimpl_->cd, &inbuf, &inbytesleft, &outbuf, &outbytesleft); + int res = iconv(h_->cd, &inbuf, &inbytesleft, &outbuf, &outbytesleft); // flush out remaining data. This is needed because iconv sometimes // holds back chars in the stream, waiting for a combination character // (see e.g. http://sources.redhat.com/bugzilla/show_bug.cgi?id=1124) - iconv(pimpl_->cd, NULL, NULL, &outbuf, &outbytesleft); + iconv(h_->cd, NULL, NULL, &outbuf, &outbytesleft); //lyxerr << dec; //lyxerr << "Inbytesleft: " << inbytesleft << endl; @@ -164,25 +132,13 @@ int IconvProcessor::convert(char const * buf, size_t buflen, lyxerr << "E2BIG There is not sufficient room at *outbuf." << endl; break; case EILSEQ: - lyxerr << "EILSEQ An invalid multibyte sequence" - << " has been encountered in the input.\n" - << "When converting from " << pimpl_->fromcode_ - << " to " << pimpl_->tocode_ << ".\n"; - lyxerr << "Input:" << hex; - for (size_t i = 0; i < buflen; ++i) { - // char may be signed, avoid output of - // something like 0xffffffc2 - boost::uint32_t const b = - *reinterpret_cast(buf + i); - lyxerr << " 0x" << (unsigned int)b; - } - lyxerr << dec << endl; - break; case EINVAL: - lyxerr << "EINVAL An incomplete multibyte sequence" - << " has been encountered in the input.\n" - << "When converting from " << pimpl_->fromcode_ - << " to " << pimpl_->tocode_ << ".\n"; + lyxerr << (errno == EINVAL + ? "EINVAL An incomplete " + : "EILSEQ An invalid ") + << "multibyte sequence has been encountered in the input.\n" + << "When converting from " << fromcode_ + << " to " << tocode_ << ".\n"; lyxerr << "Input:" << hex; for (size_t i = 0; i < buflen; ++i) { // char may be signed, avoid output of @@ -198,27 +154,11 @@ int IconvProcessor::convert(char const * buf, size_t buflen, break; } // We got an error so we close down the conversion engine - if (iconv_close(pimpl_->cd) == -1) { - lyxerr << "Error returned from iconv_close(" - << errno << ")" << endl; - } - pimpl_->cd = invalid_cd; + h_.reset(); return -1; } -std::string IconvProcessor::from() const -{ - return pimpl_->fromcode_; -} - - -std::string IconvProcessor::to() const -{ - return pimpl_->tocode_; -} - - namespace { @@ -253,7 +193,7 @@ iconv_convert(IconvProcessor & processor, InType const * buf, size_t buflen) return vector(tmp, tmp + bytes / sizeof(RetType)); } -} // anon namespace +} // namespace IconvProcessor & utf8ToUcs4() @@ -309,6 +249,23 @@ IconvProcessor & ucs4ToUtf8() return *processor.localData(); } +namespace { + +IconvProcessor & getProc(map & processors, + string const & encoding, bool to) +{ + string const & fromcode = to ? ucs4_codeset : encoding; + string const & tocode = to ? encoding : ucs4_codeset; + map::iterator const it = processors.find(encoding); + if (it == processors.end()) { + IconvProcessor p(fromcode, tocode); + return processors.insert(make_pair(encoding, move(p))).first->second; + } else + return it->second; +} + +} // namespace + vector ucs4_to_utf8(char_type c) @@ -341,11 +298,8 @@ eightbit_to_ucs4(char const * s, size_t ls, string const & encoding) if (!static_processors.hasLocalData()) static_processors.setLocalData(new map); map & processors = *static_processors.localData(); - if (processors.find(encoding) == processors.end()) { - IconvProcessor processor(ucs4_codeset, encoding.c_str()); - processors.insert(make_pair(encoding, processor)); - } - return iconv_convert(processors[encoding], s, ls); + IconvProcessor & processor = getProc(processors, encoding, true); + return iconv_convert(processor, s, ls); } @@ -359,32 +313,23 @@ map & ucs4To8bitProcessors() return *processors.localData(); } -} - +} // namespace vector ucs4_to_eightbit(char_type const * ucs4str, size_t ls, string const & encoding) { map & processors(ucs4To8bitProcessors()); - if (processors.find(encoding) == processors.end()) { - IconvProcessor processor(encoding.c_str(), ucs4_codeset); - processors.insert(make_pair(encoding, processor)); - } - return iconv_convert(processors[encoding], ucs4str, ls); + IconvProcessor & processor = getProc(processors, encoding, false); + return iconv_convert(processor, ucs4str, ls); } char ucs4_to_eightbit(char_type ucs4, string const & encoding) { map & processors(ucs4To8bitProcessors()); - map::iterator it = processors.find(encoding); - if (it == processors.end()) { - IconvProcessor processor(encoding.c_str(), ucs4_codeset); - it = processors.insert(make_pair(encoding, processor)).first; - } - + IconvProcessor & processor = getProc(processors, encoding, false); char out; - int const bytes = it->second.convert((char *)(&ucs4), 4, &out, 1); + int const bytes = processor.convert((char *)(&ucs4), 4, &out, 1); if (bytes > 0) return out; return 0; @@ -398,14 +343,9 @@ void ucs4_to_multibytes(char_type ucs4, vector & out, if (!static_processors.hasLocalData()) static_processors.setLocalData(new map); map & processors = *static_processors.localData(); - map::iterator it = processors.find(encoding); - if (it == processors.end()) { - IconvProcessor processor(encoding.c_str(), ucs4_codeset); - it = processors.insert(make_pair(encoding, processor)).first; - } - + IconvProcessor & processor = getProc(processors, encoding, false); out.resize(4); - int bytes = it->second.convert((char *)(&ucs4), 4, &out[0], 4); + int bytes = processor.convert((char *)(&ucs4), 4, &out[0], 4); if (bytes > 0) out.resize(bytes); else