+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.
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:
/**
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.
* 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
* - 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.
};
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>::
isctype(_Ch_type __c, char_class_type __f) const
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>
-// { dg-do run { xfail *-*-* } }
+// { dg-do run }
// { dg-options "-std=c++0x" }
//
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()
-// { dg-do run { xfail *-*-* } }
+// { dg-do run }
// { dg-options "-std=c++0x" }
//
-// { dg-do run { xfail *-*-* } }
+// { dg-do run }
// { dg-options "-std=c++0x" }
//
// { dg-options "-std=c++0x" }
-// { dg-do run { xfail *-*-* } }
+// { dg-do run }
//
// 2010-02-17 Stephen M. Webb <stephen.webb@bregmasoft.ca>
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()
--- /dev/null
+// { 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;
+}
--- /dev/null
+// { 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;
+}
--- /dev/null
+// { 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;
+}
--- /dev/null
+// { 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;
+}