Details

[Home]

Issue of the Implementation # S0675

Brief

codecvt::do_in/do_out functions return "ok" when the output sequence has zero length

Detailed Description

The following member functions of the class codecvt<wchar_t, char, mbstate_t>

result in(stateT& state, const externT* from, const externT* from_end, const externT*& from_next, internT* to, internT* to_limit, internT*& to_next) const

and

result out(stateT& state, const internT* from, const internT* from_end, const internT*& from_next, externT* to, externT* to_limit, externT*& to_next) const

return "ok" if (to==to_limit) but (from < from_end), that is, when the output sequence contains no elements but the input sequence is not empty.

However, as appears from the description of the functions' return values (ISO/IEC 14882, section 22.2.1.5.2.4), "partial" should be returned instead:

ok - completed the conversion
partial - not all source characters converted
error - encountered a character in [from,from_end) that it could not convert
noconv - internT and externT are the same type, and input sequence is identical to converted sequence

Note that these functions do return "partial" if the output sequence is not empty but still not large enough to contain all converted characters from the input sequence, that is, if
0< (to_limit - to) < (from_end - from).

The example below demonstrates this issue.

Problem location(s) in the standard

Linux Standard Base C++ Specification 3.2, Chapter 9. Libraries, 9.1. Interfaces for libstdcxx that refers ISO/IEC 14882: 2003 Programming languages --C++, section 18.6.4

Example

#include <locale>
using namespace std;

/*
 * Derives from codecvt<> class for make destructor
 * and target functions public (instead of protected).
 */
class codecvt_my : public codecvt<wchar_t, char, mbstate_t>
{
public:
    using codecvt<wchar_t, char, mbstate_t>::do_in;
    using codecvt<wchar_t, char, mbstate_t>::do_out;
    
    virtual ~codecvt_my(){};
};
/*
 * Converts integral value of codecvt_base::result
 * to string representation.
 */
const char* result_to_str(codecvt_base::result result)
{
    switch(result)
    {
    case codecvt_base::ok:
        return "ok";
    case codecvt_base::error:
        return "error";
    case codecvt_base::noconv:
        return "noconv";
    case codecvt_base::partial:
        return "partial";
    default:
        return "(unknown result)";
    }
}
/*
 * Test for do_out() function
 * with different sizes of input and ouput sequences.
 */
template<size_t input_size, size_t output_size>
void test_out()
{
    wchar_t from[input_size];
    for(wchar_t *tmp = from; tmp < from + input_size; tmp++)
        *tmp = L'a';
    const wchar_t *from_next;
    
    char to[output_size];
    char *to_next;
    
    codecvt_my obj;
    mbstate_t state = mbstate_t();

    printf("Calls do_out() function when size of input sequence "
           "is %zu, output - %zu:\n",
           input_size, output_size);

    codecvt_base::result result = obj.do_out(state,
        from, from + input_size, from_next,
        to, to + output_size, to_next);

    printf("do_out() returns %s.\n",
        result_to_str(result));
}
/*
 * Test for do_in() function
 * with different sizes of input and ouput sequences.
 */
template<size_t input_size, size_t output_size>
void test_in()
{
    char from[input_size];
    for(char *tmp = from; tmp < from + input_size; tmp++)
        *tmp = 'a';
    const char *from_next;
    
    wchar_t to[output_size];
    wchar_t *to_next;
    
    codecvt_my obj;
    mbstate_t state = mbstate_t();

    printf("Calls do_in() function when size of input sequence" 
           "is %zu, output - %zu:\n",
           input_size, output_size);

    codecvt_base::result result = obj.do_in(state,
        from, from + input_size, from_next,
        to, to + output_size, to_next);

    printf("do_in() returns %s.\n",
        result_to_str(result));
}
int main()
{
    test_out<2,1>();
    test_out<2,0>();
    test_in<2,1>();
    test_in<2,0>();
    return 0;
}

Component

libstdc++

Accepted

GCC Bugzilla 37475

[Home]