blob: 8815c3ead59424e9b60346b2100a1c1dee1639dd [file] [log] [blame]
// Copyright (C) 2017-2021 Free Software Foundation, Inc.
//
// This file is part of the GNU ISO C++ Library. This library is free
// software; you can redistribute it and/or modify it under the
// terms of the GNU General Public License as published by the
// Free Software Foundation; either version 3, 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 General Public License for more details.
// You should have received a copy of the GNU General Public License along
// with this library; see the file COPYING3. If not see
// <http://www.gnu.org/licenses/>.
// { dg-do run { target c++11 } }
#include <locale>
#include <codecvt>
#include <testsuite_hooks.h>
using std::codecvt_base;
using std::codecvt_mode;
using std::codecvt_utf16;
using std::wstring_convert;
using std::mbstate_t;
constexpr codecvt_mode
operator|(codecvt_mode m1, codecvt_mode m2)
{
using underlying = std::underlying_type<codecvt_mode>::type;
return static_cast<codecvt_mode>(static_cast<underlying>(m1) | m2);
}
// Read/write UTF-16 code units from data not correctly aligned for char16_t
void
test01()
{
mbstate_t st;
constexpr codecvt_mode m = std::consume_header|std::generate_header;
codecvt_utf16<char16_t, 0x10FFFF, m> conv;
const char src[] = "-\xFE\xFF\0\x61\xAB\xCD";
const char* const src_end = src + 7;
int len = conv.length(st, src + 1, src_end, 1);
VERIFY( len == 4 );
len = conv.length(st, src + 1, src_end, 2);
VERIFY( len == 6 );
char16_t dst[2];
char16_t* const dst_end = dst + 2;
char16_t* dst_next;
const char* src_cnext;
auto res = conv.in(st, src + 1, src_end, src_cnext, dst, dst_end, dst_next);
VERIFY( res == codecvt_base::ok );
VERIFY( dst[0] == 0x0061 );
VERIFY( dst[1] == 0xabcd );
VERIFY( src_cnext == src_end );
VERIFY( dst_next == dst_end );
char out[sizeof(src)] = { src[0] };
char* const out_end = out + 7;
char* out_next;
const char16_t* dst_cnext;
res = conv.out(st, dst, dst_end, dst_cnext, out + 1, out_end, out_next);
VERIFY( res == codecvt_base::ok );
VERIFY( out_next == out_end );
VERIFY( dst_cnext == dst_end );
VERIFY( out[1] == src[1] );
VERIFY( out[2] == src[2] );
VERIFY( out[3] == src[3] );
VERIFY( out[4] == src[4] );
VERIFY( out[5] == src[5] );
VERIFY( out[6] == src[6] );
codecvt_utf16<char16_t, 0x10FFFF, m|std::little_endian> conv_le;
len = conv_le.length(st, src + 1, src_end, 1);
VERIFY( len == 4 );
len = conv_le.length(st, src + 1, src_end, 2);
VERIFY( len == 6 );
res = conv_le.in(st, src + 1, src_end, src_cnext, dst, dst_end, dst_next);
VERIFY( res == codecvt_base::ok );
VERIFY( dst[0] == 0x0061 );
VERIFY( dst[1] == 0xabcd );
VERIFY( src_cnext == src_end );
VERIFY( dst_next == dst_end );
res = conv_le.out(st, dst, dst_end, dst_cnext, out + 1, out_end, out_next);
VERIFY( res == codecvt_base::ok );
VERIFY( out_next == out_end );
VERIFY( dst_cnext == dst_end );
VERIFY( out[1] == src[2] );
VERIFY( out[2] == src[1] );
VERIFY( out[3] == src[4] );
VERIFY( out[4] == src[3] );
VERIFY( out[5] == src[6] );
VERIFY( out[6] == src[5] );
}
void
test02()
{
mbstate_t st;
constexpr codecvt_mode m = std::consume_header|std::generate_header;
codecvt_utf16<char32_t, 0x10FFFF, m> conv;
const char src[] = "-\xFE\xFF\0\x61\xAB\xCD\xD8\x08\xDF\x45";
const char* const src_end = src + 11;
int len = conv.length(st, src + 1, src_end, 1);
VERIFY( len == 4 );
len = conv.length(st, src + 1, src_end, 2);
VERIFY( len == 6 );
len = conv.length(st, src + 1, src_end, -1ul);
VERIFY( len == 10 );
char32_t dst[3];
char32_t* const dst_end = dst + 3;
char32_t* dst_next;
const char* src_cnext;
auto res = conv.in(st, src + 1, src_end, src_cnext, dst, dst_end, dst_next);
VERIFY( res == codecvt_base::ok );
VERIFY( dst[0] == 0x0061 );
VERIFY( dst[1] == 0xabcd );
VERIFY( dst[2] == 0x012345 );
VERIFY( src_cnext == src_end );
VERIFY( dst_next == dst_end );
char out[sizeof(src)] = { src[0] };
char* const out_end = out + 11;
char* out_next;
const char32_t* dst_cnext;
res = conv.out(st, dst, dst_end, dst_cnext, out + 1, out_end, out_next);
VERIFY( res == codecvt_base::ok );
VERIFY( out_next == out_end );
VERIFY( dst_cnext == dst_end );
VERIFY( out[1] == src[1] );
VERIFY( out[2] == src[2] );
VERIFY( out[3] == src[3] );
VERIFY( out[4] == src[4] );
VERIFY( out[5] == src[5] );
VERIFY( out[6] == src[6] );
VERIFY( out[7] == src[7] );
VERIFY( out[8] == src[8] );
VERIFY( out[9] == src[9] );
VERIFY( out[10] == src[10] );
codecvt_utf16<char32_t, 0x10FFFF, m|std::little_endian> conv_le;
len = conv_le.length(st, src + 1, src_end, 1);
VERIFY( len == 4 );
len = conv_le.length(st, src + 1, src_end, 2);
VERIFY( len == 6 );
len = conv.length(st, src + 1, src_end, -1ul);
VERIFY( len == 10 );
res = conv_le.in(st, src + 1, src_end, src_cnext, dst, dst_end, dst_next);
VERIFY( res == codecvt_base::ok );
VERIFY( dst[0] == 0x0061 );
VERIFY( dst[1] == 0xabcd );
VERIFY( dst[2] == 0x012345 );
VERIFY( src_cnext == src_end );
VERIFY( dst_next == dst_end );
res = conv_le.out(st, dst, dst_end, dst_cnext, out + 1, out_end, out_next);
VERIFY( res == codecvt_base::ok );
VERIFY( out_next == out_end );
VERIFY( dst_cnext == dst_end );
VERIFY( out[1] == src[2] );
VERIFY( out[2] == src[1] );
VERIFY( out[3] == src[4] );
VERIFY( out[4] == src[3] );
VERIFY( out[5] == src[6] );
VERIFY( out[6] == src[5] );
VERIFY( out[7] == src[8] );
VERIFY( out[8] == src[7] );
VERIFY( out[9] == src[10] );
VERIFY( out[10] == src[9] );
}
void
test03()
{
#ifdef _GLIBCXX_USE_WCHAR_T
mbstate_t st;
constexpr codecvt_mode m = std::consume_header|std::generate_header;
codecvt_utf16<wchar_t, 0x10FFFF, m> conv;
const char src[] = "-\xFE\xFF\0\x61\xAB\xCD\xD8\x08\xDF\x45";
const size_t in_len = sizeof(wchar_t) == 4 ? 11 : 7;
const size_t out_len = sizeof(wchar_t) == 4 ? 3 : 2;
const char* const src_end = src + in_len;
int len = conv.length(st, src + 1, src_end, 1);
VERIFY( len == 4 );
len = conv.length(st, src + 1, src_end, 2);
VERIFY( len == 6 );
if (sizeof(wchar_t) == 4)
{
len = conv.length(st, src + 1, src_end, -1ul);
VERIFY( len == 10 );
}
wchar_t dst[out_len];
wchar_t* const dst_end = dst + out_len;
wchar_t* dst_next;
const char* src_cnext;
auto res = conv.in(st, src + 1, src_end, src_cnext, dst, dst_end, dst_next);
VERIFY( res == codecvt_base::ok );
VERIFY( dst[0] == 0x0061 );
VERIFY( dst[1] == 0xabcd );
if (sizeof(wchar_t) == 4)
VERIFY( dst[2] == 0x012345 );
VERIFY( src_cnext == src_end );
VERIFY( dst_next == dst_end );
char out[sizeof(src)] = { src[0] };
char* const out_end = out + in_len;
char* out_next;
const wchar_t* dst_cnext;
res = conv.out(st, dst, dst_end, dst_cnext, out + 1, out_end, out_next);
VERIFY( res == codecvt_base::ok );
VERIFY( out_next == out_end );
VERIFY( dst_cnext == dst_end );
VERIFY( out[1] == src[1] );
VERIFY( out[2] == src[2] );
VERIFY( out[3] == src[3] );
VERIFY( out[4] == src[4] );
VERIFY( out[5] == src[5] );
VERIFY( out[6] == src[6] );
if (sizeof(wchar_t) == 4)
{
VERIFY( out[7] == src[7] );
VERIFY( out[8] == src[8] );
VERIFY( out[9] == src[9] );
VERIFY( out[10] == src[10] );
}
codecvt_utf16<wchar_t, 0x10FFFF, m|std::little_endian> conv_le;
len = conv_le.length(st, src + 1, src_end, 1);
VERIFY( len == 4 );
len = conv_le.length(st, src + 1, src_end, 2);
VERIFY( len == 6 );
if (sizeof(wchar_t) == 4)
{
len = conv.length(st, src + 1, src_end, -1ul);
VERIFY( len == 10 );
}
res = conv_le.in(st, src + 1, src_end, src_cnext, dst, dst_end, dst_next);
VERIFY( res == codecvt_base::ok );
VERIFY( dst[0] == 0x0061 );
VERIFY( dst[1] == 0xabcd );
if (sizeof(wchar_t) == 4)
VERIFY( dst[2] == 0x012345 );
VERIFY( src_cnext == src_end );
VERIFY( dst_next == dst_end );
res = conv_le.out(st, dst, dst_end, dst_cnext, out + 1, out_end, out_next);
VERIFY( res == codecvt_base::ok );
VERIFY( out_next == out_end );
VERIFY( dst_cnext == dst_end );
VERIFY( out[1] == src[2] );
VERIFY( out[2] == src[1] );
VERIFY( out[3] == src[4] );
VERIFY( out[4] == src[3] );
VERIFY( out[5] == src[6] );
VERIFY( out[6] == src[5] );
if (sizeof(wchar_t) == 4)
{
VERIFY( out[7] == src[8] );
VERIFY( out[8] == src[7] );
VERIFY( out[9] == src[10] );
VERIFY( out[10] == src[9] );
}
#endif
}
int
main()
{
test01();
test02();
test03();
}