Implement class regex_traits.

2013-07-09  Tim Shen  <timshen91@gmail.com>

	Implement class regex_traits.
	* include/bits/regex.h: Implement lookup_classname and
	lookup_collatename; modify isctype; partially implement
	transform_primary.
	* testsuite/28_regex/traits/char/isctype.cc: Add more test cases.
	* testsuite/28_regex/traits/char/lookup_classname.cc: Likewise.
	* testsuite/28_regex/traits/char/lookup_collatename.cc: Likewise.
	* testsuite/28_regex/traits/char/transform_primary.cc: Likewise.
	* testsuite/28_regex/traits/wchar_t/isctype.cc: New.
	* testsuite/28_regex/traits/wchar_t/lookup_classname.cc: New.
	* testsuite/28_regex/traits/wchar_t/lookup_collatename.cc: New.
	* testsuite/28_regex/traits/wchar_t/transform_primary.cc: New.

From-SVN: r200818
This commit is contained in:
Tim Shen 2013-07-09 13:41:10 +00:00 committed by Edward Smith-Rowland
parent 309f50b920
commit b3ebe3d0e0
10 changed files with 597 additions and 44 deletions

View File

@ -1,3 +1,18 @@
2013-07-09 Tim Shen <timshen91@gmail.com>
Implement class regex_traits.
* include/bits/regex.h: Implement lookup_classname and
lookup_collatename; modify isctype; partially implement
transform_primary.
* testsuite/28_regex/traits/char/isctype.cc: Add more test cases.
* testsuite/28_regex/traits/char/lookup_classname.cc: Likewise.
* testsuite/28_regex/traits/char/lookup_collatename.cc: Likewise.
* testsuite/28_regex/traits/char/transform_primary.cc: Likewise.
* testsuite/28_regex/traits/wchar_t/isctype.cc: New.
* testsuite/28_regex/traits/wchar_t/lookup_classname.cc: New.
* testsuite/28_regex/traits/wchar_t/lookup_collatename.cc: New.
* testsuite/28_regex/traits/wchar_t/transform_primary.cc: New.
2013-07-07 Ed Smith-Rowland <3dw4rd@verizon.net>
* doc/xml/manual/status_cxx2014.xml: Add links for papers.

View File

@ -54,7 +54,74 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
typedef _Ch_type char_type;
typedef std::basic_string<char_type> string_type;
typedef std::locale locale_type;
typedef std::ctype_base::mask char_class_type;
private:
struct _RegexMask
{
typedef typename std::ctype<char_type>::mask _BaseType;
_BaseType _M_base;
unsigned char _M_extended;
static constexpr unsigned char _S_under = 1 << 0;
// _S_blank should be removed in the future, when locale's complete.
static constexpr unsigned char _S_blank = 1 << 1;
static constexpr unsigned char _S_valid_mask = 0x3;
constexpr _RegexMask(_BaseType __base = 0,
unsigned char __extended = 0)
: _M_base(__base), _M_extended(__extended)
{ }
constexpr _RegexMask
operator&(_RegexMask __other) const
{
return _RegexMask(_M_base & __other._M_base,
_M_extended & __other._M_extended);
}
constexpr _RegexMask
operator|(_RegexMask __other) const
{
return _RegexMask(_M_base | __other._M_base,
_M_extended | __other._M_extended);
}
constexpr _RegexMask
operator^(_RegexMask __other) const
{
return _RegexMask(_M_base ^ __other._M_base,
_M_extended ^ __other._M_extended);
}
constexpr _RegexMask
operator~() const
{ return _RegexMask(~_M_base, ~_M_extended); }
constexpr _RegexMask&
operator&=(_RegexMask __other)
{ return *this = (*this) & __other; }
constexpr _RegexMask&
operator|=(_RegexMask __other)
{ return *this = (*this) | __other; }
constexpr _RegexMask&
operator^=(_RegexMask __other)
{ return *this = (*this) ^ __other; }
constexpr bool
operator==(_RegexMask __other) const
{
return (_M_extended & _S_valid_mask)
== (__other._M_extended & _S_valid_mask)
&& _M_base == __other._M_base;
}
constexpr bool
operator!=(_RegexMask __other) const
{ return !((*this) == __other); }
};
public:
typedef _RegexMask char_class_type;
public:
/**
@ -151,7 +218,21 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
template<typename _Fwd_iter>
string_type
transform_primary(_Fwd_iter __first, _Fwd_iter __last) const
{ return string_type(); }
{
__try
{
typedef std::ctype<char_type> __ctype_type;
const __ctype_type& __fctyp(use_facet<__ctype_type>(_M_locale));
std::vector<char_type> __v(__first, __last);
// FIXME : this is not entirely correct
__fctyp.tolower(&*__v.begin(), &*__v.end());
return this->transform(&*__v.begin(), &*__v.end());
}
__catch (...)
{
}
return string_type();
}
/**
* @brief Gets a collation element by name.
@ -163,13 +244,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
* collating element consisting of the character sequence designated by
* the iterator range [__first, __last). Returns an empty string if the
* character sequence is not a valid collating element.
*
* @todo Implement this function.
*/
template<typename _Fwd_iter>
string_type
lookup_collatename(_Fwd_iter __first, _Fwd_iter __last) const
{ return string_type(); }
lookup_collatename(_Fwd_iter __first, _Fwd_iter __last) const;
/**
* @brief Maps one or more characters to a named character
@ -207,14 +285,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
* - space
* - upper
* - xdigit
*
* @todo Implement this function.
*/
template<typename _Fwd_iter>
char_class_type
lookup_classname(_Fwd_iter __first, _Fwd_iter __last,
bool __icase = false) const
{ return 0; }
bool __icase = false) const;
/**
* @brief Determines if @p c is a member of an identified class.
@ -274,6 +349,245 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
locale_type _M_locale;
};
template<typename _Ch_type>
template<typename _Fwd_iter>
typename regex_traits<_Ch_type>::string_type
regex_traits<_Ch_type>::
lookup_collatename(_Fwd_iter __first, _Fwd_iter __last) const
{
typedef std::ctype<char_type> __ctype_type;
const __ctype_type& __fctyp(use_facet<__ctype_type>(_M_locale));
static const char* __collatenames[] =
{
"NUL",
"SOH",
"STX",
"ETX",
"EOT",
"ENQ",
"ACK",
"alert",
"backspace",
"tab",
"newline",
"vertical-tab",
"form-feed",
"carriage-return",
"SO",
"SI",
"DLE",
"DC1",
"DC2",
"DC3",
"DC4",
"NAK",
"SYN",
"ETB",
"CAN",
"EM",
"SUB",
"ESC",
"IS4",
"IS3",
"IS2",
"IS1",
"space",
"exclamation-mark",
"quotation-mark",
"number-sign",
"dollar-sign",
"percent-sign",
"ampersand",
"apostrophe",
"left-parenthesis",
"right-parenthesis",
"asterisk",
"plus-sign",
"comma",
"hyphen",
"period",
"slash",
"zero",
"one",
"two",
"three",
"four",
"five",
"six",
"seven",
"eight",
"nine",
"colon",
"semicolon",
"less-than-sign",
"equals-sign",
"greater-than-sign",
"question-mark",
"commercial-at",
"A",
"B",
"C",
"D",
"E",
"F",
"G",
"H",
"I",
"J",
"K",
"L",
"M",
"N",
"O",
"P",
"Q",
"R",
"S",
"T",
"U",
"V",
"W",
"X",
"Y",
"Z",
"left-square-bracket",
"backslash",
"right-square-bracket",
"circumflex",
"underscore",
"grave-accent",
"a",
"b",
"c",
"d",
"e",
"f",
"g",
"h",
"i",
"j",
"k",
"l",
"m",
"n",
"o",
"p",
"q",
"r",
"s",
"t",
"u",
"v",
"w",
"x",
"y",
"z",
"left-curly-bracket",
"vertical-line",
"right-curly-bracket",
"tilde",
"DEL",
""
};
// same as boost
static const char* __digraphs[] =
{
"ae",
"Ae",
"AE",
"ch",
"Ch",
"CH",
"ll",
"Ll",
"LL",
"ss",
"Ss",
"SS",
"nj",
"Nj",
"NJ",
"dz",
"Dz",
"DZ",
"lj",
"Lj",
"LJ",
""
};
std::string __s(__last - __first, '?');
string_type a(__first, __last);
__fctyp.narrow(__first, __last, '?', &*__s.begin());
for (unsigned int __i = 0; *__collatenames[__i]; __i++)
if (__s == __collatenames[__i])
return string_type(1, __fctyp.widen((char)__i));
for (unsigned int __i = 0; *__digraphs[__i]; __i++)
{
const char* __now = __digraphs[__i];
if (__s == __now)
{
string_type ret(__s.size(), __fctyp.widen('?'));
__fctyp.widen(__now, __now + 2/* ouch */, &*ret.begin());
return ret;
}
}
return string_type();
}
template<typename _Ch_type>
template<typename _Fwd_iter>
typename regex_traits<_Ch_type>::char_class_type
regex_traits<_Ch_type>::
lookup_classname(_Fwd_iter __first, _Fwd_iter __last, bool __icase) const
{
typedef std::ctype<char_type> __ctype_type;
typedef std::ctype<char> __cctype_type;
typedef const pair<const char*, char_class_type> _ClassnameEntry;
const __ctype_type& __fctyp(use_facet<__ctype_type>(_M_locale));
const __cctype_type& __cctyp(use_facet<__cctype_type>(_M_locale));
static _ClassnameEntry __classnames[] =
{
{"d", ctype_base::digit},
{"w", {ctype_base::alnum, _RegexMask::_S_under}},
{"s", ctype_base::space},
{"alnum", ctype_base::alnum},
{"alpha", ctype_base::alpha},
{"blank", {0, _RegexMask::_S_blank}},
{"cntrl", ctype_base::cntrl},
{"digit", ctype_base::digit},
{"graph", ctype_base::graph},
{"lower", ctype_base::lower},
{"print", ctype_base::print},
{"punct", ctype_base::punct},
{"space", ctype_base::space},
{"upper", ctype_base::upper},
{"xdigit", ctype_base::xdigit},
};
std::string __s(__last - __first, '?');
__fctyp.narrow(__first, __last, '?', &__s[0]);
__cctyp.tolower(&*__s.begin(), &*__s.end());
for (_ClassnameEntry* __it = __classnames;
__it < *(&__classnames + 1);
++__it)
{
if (__s == __it->first)
{
if (__icase
&& ((__it->second & (ctype_base::lower | ctype_base::upper)) != 0))
return ctype_base::alpha;
return __it->second;
}
}
return 0;
}
template<typename _Ch_type>
bool
regex_traits<_Ch_type>::
@ -282,30 +596,14 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
typedef std::ctype<char_type> __ctype_type;
const __ctype_type& __fctyp(use_facet<__ctype_type>(_M_locale));
if (__fctyp.is(__f, __c))
return true;
// special case of underscore in [[:w:]]
if (__c == __fctyp.widen('_'))
{
const char __wb[] = "w";
char_class_type __wt = this->lookup_classname(__wb,
__wb + sizeof(__wb));
if (__f | __wt)
return true;
}
// special case of [[:space:]] in [[:blank:]]
if (__fctyp.is(std::ctype_base::space, __c))
{
const char __bb[] = "blank";
char_class_type __bt = this->lookup_classname(__bb,
__bb + sizeof(__bb));
if (__f | __bt)
return true;
}
return false;
return __fctyp.is(__f._M_base, __c)
// [[:w:]]
|| ((__f._M_extended & _RegexMask::_S_under)
&& __c == __fctyp.widen('_'))
// [[:blank:]]
|| ((__f._M_extended & _RegexMask::_S_blank)
&& (__c == __fctyp.widen(' ')
|| __c == __fctyp.widen('\t')));
}
template<typename _Ch_type>

View File

@ -1,4 +1,4 @@
// { dg-do run { xfail *-*-* } }
// { dg-do run }
// { dg-options "-std=c++0x" }
//
@ -35,10 +35,28 @@ test01()
typedef char CharT;
typedef std::regex_traits<CharT> traits;
char name[] = "lower";
traits t;
const CharT lower[] = "lOWer";
const CharT upper[] = "UPPER";
const CharT nothing[] = "nothing";
const CharT word[] = "w";
const CharT blank[] = "blank";
const CharT digit[] = "digit";
traits t;
VERIFY( t.isctype('e', t.lookup_classname(name, name+sizeof(name)-1)) );
#define range(s) s, s+sizeof(s)/sizeof(s[0])-1
VERIFY( t.isctype('_', t.lookup_classname(range(word))));
VERIFY( t.isctype('A', t.lookup_classname(range(word))));
VERIFY(!t.isctype('~', t.lookup_classname(range(word))));
VERIFY(!t.isctype('e', t.lookup_classname(range(upper))));
VERIFY( t.isctype('e', t.lookup_classname(range(lower))));
VERIFY(!t.isctype('e', t.lookup_classname(range(nothing))));
VERIFY(!t.isctype('_', t.lookup_classname(range(digit))));
VERIFY( t.isctype(' ', t.lookup_classname(range(blank))));
VERIFY( t.isctype('\t', t.lookup_classname(range(blank))));
VERIFY(!t.isctype('\n', t.lookup_classname(range(blank))));
VERIFY( t.isctype('t', t.lookup_classname(range(upper), true)));
VERIFY( t.isctype('T', t.lookup_classname(range(lower), true)));
#undef range
}
int main()

View File

@ -1,4 +1,4 @@
// { dg-do run { xfail *-*-* } }
// { dg-do run }
// { dg-options "-std=c++0x" }
//

View File

@ -1,4 +1,4 @@
// { dg-do run { xfail *-*-* } }
// { dg-do run }
// { dg-options "-std=c++0x" }
//

View File

@ -1,5 +1,5 @@
// { dg-options "-std=c++0x" }
// { dg-do run { xfail *-*-* } }
// { dg-do run }
//
// 2010-02-17 Stephen M. Webb <stephen.webb@bregmasoft.ca>
@ -42,10 +42,12 @@ test01()
traits::string_type J = "ABC";
VERIFY( G < H );
VERIFY( t.transform_primary(G.begin(), G.end()) < t.transform_primary(H.begin(), H.end()) );
VERIFY( t.transform_primary(G.begin(), G.end())
< t.transform_primary(H.begin(), H.end()) );
VERIFY( G == H );
VERIFY( t.transform_primary(G.begin(), G.end()) == t.transform_primary(J.begin(), J.end()) );
VERIFY( G > J );
VERIFY( t.transform_primary(G.begin(), G.end())
== t.transform_primary(J.begin(), J.end()) );
}
int main()

View File

@ -0,0 +1,63 @@
// { dg-do run }
// { dg-options "-std=c++0x" }
// Copyright (C) 2010-2013 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/>.
// 28.3 Requirements [re.req]
// 28.2(4) Table 127 - Regular expression traits class requirements
// 28.7(11) Class template regex_traits [re.traits]
#include <regex>
#include <testsuite_hooks.h>
void
test01()
{
bool test __attribute__((unused)) = true;
typedef wchar_t CharT;
typedef std::regex_traits<CharT> traits;
const CharT lower[] = L"lOWer";
const CharT upper[] = L"UPPER";
const CharT nothing[] = L"nothing";
const CharT word[] = L"w";
const CharT blank[] = L"blank";
const CharT digit[] = L"digit";
traits t;
#define range(s) s, s+sizeof(s)/sizeof(s[0])-1
VERIFY( t.isctype(L'_', t.lookup_classname(range(word))));
VERIFY( t.isctype(L'A', t.lookup_classname(range(word))));
VERIFY(!t.isctype(L'~', t.lookup_classname(range(word))));
VERIFY(!t.isctype(L'e', t.lookup_classname(range(upper))));
VERIFY( t.isctype(L'e', t.lookup_classname(range(lower))));
VERIFY(!t.isctype(L'e', t.lookup_classname(range(nothing))));
VERIFY(!t.isctype(L'_', t.lookup_classname(range(digit))));
VERIFY( t.isctype(L' ', t.lookup_classname(range(blank))));
VERIFY( t.isctype(L'\t', t.lookup_classname(range(blank))));
VERIFY(!t.isctype(L'\n', t.lookup_classname(range(blank))));
VERIFY( t.isctype(L't', t.lookup_classname(range(upper), true)));
VERIFY( t.isctype(L'T', t.lookup_classname(range(lower), true)));
#undef range
}
int main()
{
test01();
return 0;
}

View File

@ -0,0 +1,53 @@
// { dg-do run }
// { dg-options "-std=c++0x" }
// Copyright (C) 2010-2013 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/>.
// 28.3 Requirements [re.req]
// 28.2(4) Table 127 - Regular expression traits class requirements
// 28.7(9) Class template regex_traits [re.traits]
#include <regex>
#include <testsuite_hooks.h>
void
test01()
{
bool test __attribute__((unused)) = true;
typedef wchar_t CharT;
typedef std::regex_traits<CharT> traits;
wchar_t n1[] = L"lower";
wchar_t n2[] = L"alpha";
traits t;
#define range(s) s, s+sizeof(s)/sizeof(s[0])-1
traits::char_class_type c1 = t.lookup_classname(range(n1));
VERIFY( c1 != 0 );
traits::char_class_type c2 = t.lookup_classname(range(n1), true);
traits::char_class_type c3 = t.lookup_classname(range(n2), true);
VERIFY( c2 == c3 );
#undef range
}
int main()
{
test01();
return 0;
}

View File

@ -0,0 +1,49 @@
// { dg-do run }
// { dg-options "-std=c++0x" }
//
// Copyright (C) 2010-2013 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/>.
// 28.3 Requirements [re.req]
// 28.2 (4) Table 127 - Regular expression traits class requirements
// 28.7 (8) Class template regex_traits [re.traits]
#include <regex>
#include <testsuite_hooks.h>
void
test01()
{
bool test __attribute__((unused)) = true;
typedef wchar_t CharT;
typedef std::regex_traits<CharT> traits;
wchar_t name[] = L"ll";
traits t;
traits::string_type sname =
t.lookup_collatename(name, name+sizeof(name)/sizeof(*name)-1);
VERIFY( !sname.empty() );
}
int main()
{
test01();
return 0;
}

View File

@ -0,0 +1,55 @@
// { dg-options "-std=c++0x" }
// { dg-do run }
//
// Copyright (C) 2010-2013 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/>.
// 28.3 Requirements [re.req]
// 28.2 (4) Table 127 - Regular expression traits class requirements
// 28.7 Class template regex_traits [re.traits]
#include <regex>
#include <string>
#include <testsuite_hooks.h>
void
test01()
{
bool test __attribute__((unused)) = true;
typedef wchar_t CharT;
typedef std::regex_traits<CharT> traits;
traits t;
traits::string_type G = L"abc";
traits::string_type H = L"def";
traits::string_type J = L"ABC";
VERIFY( G < H );
VERIFY( t.transform_primary(G.begin(), G.end())
< t.transform_primary(H.begin(), H.end()) );
VERIFY( G > J );
VERIFY( t.transform_primary(G.begin(), G.end())
== t.transform_primary(J.begin(), J.end()) );
}
int main()
{
test01();
return 0;
}