From 1f33554abb31ee66b0b61be508d91d1cafdc4b0b Mon Sep 17 00:00:00 2001 From: Paolo Carlini Date: Wed, 19 Nov 2003 11:38:40 +0000 Subject: [PATCH] codecvt_members.cc (do_out): If we can upper bound the total number of external chars to something smaller... 2003-11-19 Paolo Carlini * config/locale/gnu/codecvt_members.cc (do_out): If we can upper bound the total number of external chars to something smaller than __to_end - __to, avoid the temporary buffer, the memcopy and simplify the loop. * config/locale/generic/codecvt_members.cc (do_out): Likewise. From-SVN: r73733 --- libstdc++-v3/ChangeLog | 9 ++++ .../config/locale/generic/codecvt_members.cc | 57 ++++++++++++++------- libstdc++-v3/config/locale/gnu/codecvt_members.cc | 59 ++++++++++++++-------- 3 files changed, 86 insertions(+), 39 deletions(-) diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog index dfea3ea..330c0c4 100644 --- a/libstdc++-v3/ChangeLog +++ b/libstdc++-v3/ChangeLog @@ -1,3 +1,12 @@ +2003-11-19 Paolo Carlini + + * config/locale/gnu/codecvt_members.cc (do_out): If + we can upper bound the total number of external chars + to something smaller than __to_end - __to, avoid the + temporary buffer, the memcopy and simplify the loop. + * config/locale/generic/codecvt_members.cc (do_out): + Likewise. + 2003-11-19 Andreas Tobler * testsuite/lib/libstdc++.exp: Add DYLD_LIBRARY_PATH for darwin. diff --git a/libstdc++-v3/config/locale/generic/codecvt_members.cc b/libstdc++-v3/config/locale/generic/codecvt_members.cc index 183439d..8bdc227 100644 --- a/libstdc++-v3/config/locale/generic/codecvt_members.cc +++ b/libstdc++-v3/config/locale/generic/codecvt_members.cc @@ -49,32 +49,51 @@ namespace std result __ret = ok; // The conversion must be done using a temporary destination buffer // since it is not possible to pass the size of the buffer to wcrtomb - extern_type __buf[MB_LEN_MAX]; - // A temporary state must be used since the result of the last - // conversion may be thrown away. state_type __tmp_state(__state); - + // The conversion must be done by calling wcrtomb in a loop rather // than using wcsrtombs because wcsrtombs assumes that the input is // zero-terminated. - while (__from < __from_end && __to < __to_end) + + // Either we can upper bound the total number of external characters to + // something smaller than __to_end - __to or the conversion must be done + // using a temporary destination buffer since it is not possible to + // pass the size of the buffer to wcrtomb + if (MB_CUR_MAX * (__from_end - __from) - (__to_end - __to) <= 0) + while (__from < __from_end) + { + const size_t __conv = wcrtomb(__to, *__from, &__tmp_state); + if (__conv == static_cast(-1)) + { + __ret = error; + break; + } + __state = __tmp_state; + __to += __conv; + __from++; + } + else { - size_t __conv = wcrtomb(__buf, *__from, &__tmp_state); - if (__conv == static_cast(-1)) - { - __ret = error; - break; - } - else if (__conv > static_cast(__to_end - __to)) + extern_type __buf[MB_LEN_MAX]; + while (__from < __from_end && __to < __to_end) { - __ret = partial; - break; + const size_t __conv = wcrtomb(__buf, *__from, &__tmp_state); + if (__conv == static_cast(-1)) + { + __ret = error; + break; + } + else if (__conv > static_cast(__to_end - __to)) + { + __ret = partial; + break; + } + + memcpy(__to, __buf, __conv); + __state = __tmp_state; + __to += __conv; + __from++; } - - memcpy(__to, __buf, __conv); - __state = __tmp_state; - __to += __conv; - __from++; } if (__ret == ok && __from < __from_end) diff --git a/libstdc++-v3/config/locale/gnu/codecvt_members.cc b/libstdc++-v3/config/locale/gnu/codecvt_members.cc index 7d80076..54930fc0c 100644 --- a/libstdc++-v3/config/locale/gnu/codecvt_members.cc +++ b/libstdc++-v3/config/locale/gnu/codecvt_members.cc @@ -48,13 +48,10 @@ namespace std extern_type*& __to_next) const { result __ret = ok; - // The conversion must be done using a temporary destination buffer - // since it is not possible to pass the size of the buffer to wcrtomb - extern_type __buf[MB_LEN_MAX]; // A temporary state must be used since the result of the last // conversion may be thrown away. - state_type __tmp_state(__state); - + state_type __tmp_state(__state); + #if __GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ > 2) __c_locale __old = __uselocale(_M_c_locale_codecvt); #endif @@ -62,24 +59,46 @@ namespace std // The conversion must be done by calling wcrtomb in a loop rather // than using wcsrtombs because wcsrtombs assumes that the input is // zero-terminated. - while (__from < __from_end && __to < __to_end) + + // Either we can upper bound the total number of external characters to + // something smaller than __to_end - __to or the conversion must be done + // using a temporary destination buffer since it is not possible to + // pass the size of the buffer to wcrtomb + if (MB_CUR_MAX * (__from_end - __from) - (__to_end - __to) <= 0) + while (__from < __from_end) + { + const size_t __conv = wcrtomb(__to, *__from, &__tmp_state); + if (__conv == static_cast(-1)) + { + __ret = error; + break; + } + __state = __tmp_state; + __to += __conv; + __from++; + } + else { - size_t __conv = wcrtomb(__buf, *__from, &__tmp_state); - if (__conv == static_cast(-1)) + extern_type __buf[MB_LEN_MAX]; + while (__from < __from_end && __to < __to_end) { - __ret = error; - break; + const size_t __conv = wcrtomb(__buf, *__from, &__tmp_state); + if (__conv == static_cast(-1)) + { + __ret = error; + break; + } + else if (__conv > static_cast(__to_end - __to)) + { + __ret = partial; + break; + } + + memcpy(__to, __buf, __conv); + __state = __tmp_state; + __to += __conv; + __from++; } - else if (__conv > static_cast(__to_end - __to)) - { - __ret = partial; - break; - } - - memcpy(__to, __buf, __conv); - __state = __tmp_state; - __to += __conv; - __from++; } #if __GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ > 2) -- 2.7.4