118334Speter// -*- C++ -*- 290075Sobrien 318334Speter// Testing character type and state type with char_traits and codecvt 418334Speter// specializations for the C++ library testsuite. 518334Speter// 618334Speter// Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009 718334Speter// Free Software Foundation, Inc. 818334Speter// 918334Speter// This file is part of the GNU ISO C++ Library. This library is free 1018334Speter// software; you can redistribute it and/or modify it under the 1118334Speter// terms of the GNU General Public License as published by the 1218334Speter// Free Software Foundation; either version 3, or (at your option) 1318334Speter// any later version. 1418334Speter// 1518334Speter// This library is distributed in the hope that it will be useful, 1618334Speter// but WITHOUT ANY WARRANTY; without even the implied warranty of 1718334Speter// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 1818334Speter// GNU General Public License for more details. 1918334Speter// 2018334Speter// You should have received a copy of the GNU General Public License along 2118334Speter// with this library; see the file COPYING3. If not see 2218334Speter// <http://www.gnu.org/licenses/>. 2318334Speter// 2418334Speter 2518334Speter#ifndef _GLIBCXX_TESTSUITE_CHARACTER_H 2618334Speter#define _GLIBCXX_TESTSUITE_CHARACTER_H 2718334Speter 2818334Speter#include <climits> 2918334Speter#include <string> // for char_traits 3018334Speter#include <locale> // for codecvt 3118334Speter#include <algorithm> // for transform 3290075Sobrien#include <ext/pod_char_traits.h> 3390075Sobrien 3418334Speternamespace __gnu_test 3518334Speter{ 3618334Speter struct pod_int 3718334Speter { 3818334Speter int value; 3990075Sobrien 4018334Speter#ifdef __GXX_EXPERIMENTAL_CXX0X__ 4118334Speter // For std::iota. 4218334Speter pod_int& 4318334Speter operator++() 4418334Speter { 4518334Speter ++value; 4618334Speter return *this; 4718334Speter } 4818334Speter#endif 4918334Speter }; 5018334Speter 5118334Speter // For 20.1 requirements for instantiable type: equality comparable 5290075Sobrien // and less than comparable. 5318334Speter inline bool 5418334Speter operator==(const pod_int& lhs, const pod_int& rhs) 5518334Speter { return lhs.value == rhs.value; } 5618334Speter 5718334Speter inline bool 5818334Speter operator<(const pod_int& lhs, const pod_int& rhs) 5918334Speter { return lhs.value < rhs.value; } 6018334Speter 6118334Speter // For 26 numeric algorithms requirements, need addable, 6218334Speter // subtractable, multiplicable. 6318334Speter inline pod_int 6418334Speter operator+(const pod_int& lhs, const pod_int& rhs) 6590075Sobrien { 6690075Sobrien pod_int ret = { lhs.value + rhs.value }; 6790075Sobrien return ret; 6818334Speter } 6918334Speter 7018334Speter inline pod_int 7190075Sobrien operator-(const pod_int& lhs, const pod_int& rhs) 7218334Speter { 7318334Speter pod_int ret = { lhs.value - rhs.value }; 7418334Speter return ret; 7518334Speter } 7618334Speter 7718334Speter inline pod_int 7818334Speter operator*(const pod_int& lhs, const pod_int& rhs) 7990075Sobrien { 8018334Speter pod_int ret = { lhs.value * rhs.value }; 8118334Speter return ret; 8218334Speter } 8318334Speter 8418334Speter struct pod_state 8518334Speter { 8618334Speter unsigned long value; 8718334Speter }; 8818334Speter 8918334Speter inline bool 9018334Speter operator==(const pod_state& lhs, const pod_state& rhs) 9118334Speter { return lhs.value == rhs.value; } 9218334Speter 9318334Speter inline bool 9418334Speter operator<(const pod_state& lhs, const pod_state& rhs) 9518334Speter { return lhs.value < rhs.value; } 9618334Speter 9718334Speter // Alternate character types. 9818334Speter using __gnu_cxx::character; 9918334Speter typedef character<unsigned char, pod_int, pod_state> pod_char; 10018334Speter typedef character<unsigned char, unsigned int, pod_state> pod_uchar; 10118334Speter typedef character<unsigned short, unsigned int> pod_ushort; 10218334Speter typedef character<unsigned int, unsigned long> pod_uint; 10318334Speter} 10450397Sobrien 10550397Sobriennamespace __gnu_cxx 10650397Sobrien{ 10750397Sobrien // Specializations. 10850397Sobrien // pod_char 10950397Sobrien template<> 11050397Sobrien template<typename V2> 11190075Sobrien inline __gnu_test::pod_char::char_type 11290075Sobrien __gnu_test::pod_char::char_type::from(const V2& v) 11390075Sobrien { 11490075Sobrien char_type ret = { static_cast<value_type>(v.value) }; 11590075Sobrien return ret; 11690075Sobrien } 11790075Sobrien 11890075Sobrien template<> 11990075Sobrien template<typename V2> 12090075Sobrien inline V2 12190075Sobrien __gnu_test::pod_char::char_type::to(const char_type& c) 12290075Sobrien { 12390075Sobrien V2 ret = { c.value }; 12490075Sobrien return ret; 12590075Sobrien } 12690075Sobrien 12790075Sobrien template<> 12890075Sobrien template<typename V2> 12990075Sobrien inline __gnu_test::pod_uchar::char_type 13090075Sobrien __gnu_test::pod_uchar::char_type::from(const V2& v) 13190075Sobrien { 13290075Sobrien char_type ret; 13390075Sobrien ret.value = (v >> 5); 13490075Sobrien return ret; 13590075Sobrien } 13690075Sobrien 13790075Sobrien template<> 13890075Sobrien template<typename V2> 13990075Sobrien inline V2 14090075Sobrien __gnu_test::pod_uchar::char_type::to(const char_type& c) 14190075Sobrien { return static_cast<V2>(c.value << 5); } 14290075Sobrien} // namespace __gnu_test 14390075Sobrien 14490075Sobriennamespace std 14590075Sobrien{ 14690075Sobrien // codecvt specialization 147 // 148 // The conversion performed by the specialization is not supposed to 149 // be useful, rather it has been designed to demonstrate the 150 // essential features of stateful conversions: 151 // * Number and value of bytes for each internal character depends on the 152 // state in addition to the character itself. 153 // * Unshift produces an unshift sequence and resets the state. On input 154 // the unshift sequence causes the state to be reset. 155 // 156 // The conversion for output is as follows: 157 // 1. Calculate the value tmp by xor-ing the state and the internal 158 // character 159 // 2. Split tmp into either two or three bytes depending on the value of 160 // state. Output those bytes. 161 // 3. tmp becomes the new value of state. 162 template<> 163 class codecvt<__gnu_test::pod_uchar, char, __gnu_test::pod_state> 164 : public __codecvt_abstract_base<__gnu_test::pod_uchar, char, 165 __gnu_test::pod_state> 166 { 167 public: 168 typedef codecvt_base::result result; 169 typedef __gnu_test::pod_uchar intern_type; 170 typedef char extern_type; 171 typedef __gnu_test::pod_state state_type; 172 typedef __codecvt_abstract_base<intern_type, extern_type, state_type> 173 base_type; 174 175 explicit codecvt(size_t refs = 0) : base_type(refs) 176 { } 177 178 static locale::id id; 179 180 protected: 181 ~codecvt() 182 { } 183 184 virtual result 185 do_out(state_type& state, const intern_type* from, 186 const intern_type* from_end, const intern_type*& from_next, 187 extern_type* to, extern_type* to_limit, 188 extern_type*& to_next) const 189 { 190 while (from < from_end && to < to_limit) 191 { 192 unsigned char tmp = (state.value ^ from->value); 193 if (state.value & 0x8) 194 { 195 if (to >= to_limit - 2) 196 break; 197 *to++ = (tmp & 0x7); 198 *to++ = ((tmp >> 3) & 0x7); 199 *to++ = ((tmp >> 6) & 0x3); 200 } 201 else 202 { 203 if (to >= to_limit - 1) 204 break; 205 *to++ = (tmp & 0xf); 206 *to++ = ((tmp >> 4) & 0xf); 207 } 208 state.value = tmp; 209 ++from; 210 } 211 212 from_next = from; 213 to_next = to; 214 return (from < from_end) ? partial : ok; 215 } 216 217 virtual result 218 do_in(state_type& state, const extern_type* from, 219 const extern_type* from_end, const extern_type*& from_next, 220 intern_type* to, intern_type* to_limit, 221 intern_type*& to_next) const 222 { 223 while (from < from_end && to < to_limit) 224 { 225 unsigned char c = *from; 226 if (c & 0xc0) 227 { 228 // Unshift sequence 229 state.value &= c; 230 ++from; 231 continue; 232 } 233 234 unsigned char tmp; 235 if (state.value & 0x8) 236 { 237 if (from >= from_end - 2) 238 break; 239 tmp = (*from++ & 0x7); 240 tmp |= ((*from++ << 3) & 0x38); 241 tmp |= ((*from++ << 6) & 0xc0); 242 } 243 else 244 { 245 if (from >= from_end - 1) 246 break; 247 tmp = (*from++ & 0xf); 248 tmp |= ((*from++ << 4) & 0xf0); 249 } 250 to->value = (tmp ^ state.value); 251 state.value = tmp; 252 ++to; 253 } 254 255 from_next = from; 256 to_next = to; 257 return (from < from_end) ? partial : ok; 258 } 259 260 virtual result 261 do_unshift(state_type& state, extern_type* to, extern_type* to_limit, 262 extern_type*& to_next) const 263 { 264 for (unsigned int i = 0; i < CHAR_BIT; ++i) 265 { 266 unsigned int mask = (1 << i); 267 if (state.value & mask) 268 { 269 if (to == to_limit) 270 { 271 to_next = to; 272 return partial; 273 } 274 275 state.value &= ~mask; 276 *to++ = static_cast<unsigned char>(~mask); 277 } 278 } 279 280 to_next = to; 281 return state.value == 0 ? ok : error; 282 } 283 284 virtual int 285 do_encoding() const throw() 286 { return -1; } 287 288 virtual bool 289 do_always_noconv() const throw() 290 { return false; } 291 292 virtual int 293 do_length(state_type& state, const extern_type* from, 294 const extern_type* end, size_t max) const 295 { 296 const extern_type* beg = from; 297 while (from < end && max) 298 { 299 unsigned char c = *from; 300 if (c & 0xc0) 301 { 302 // Unshift sequence 303 state.value &= c; 304 ++from; 305 continue; 306 } 307 308 unsigned char tmp; 309 if (state.value & 0x8) 310 { 311 if (from >= end - 2) 312 break; 313 tmp = (*from++ & 0x7); 314 tmp |= ((*from++ << 3) & 0x38); 315 tmp |= ((*from++ << 6) & 0xc0); 316 } 317 else 318 { 319 if (from >= end - 1) 320 break; 321 tmp = (*from++ & 0xf); 322 tmp |= ((*from++ << 4) & 0xf0); 323 } 324 state.value = tmp; 325 --max; 326 } 327 return from - beg; 328 } 329 330 // Maximum 8 bytes unshift sequence followed by max 3 bytes for 331 // one character. 332 virtual int 333 do_max_length() const throw() 334 { return 11; } 335 }; 336 337 template<> 338 class ctype<__gnu_test::pod_uchar> 339 : public __ctype_abstract_base<__gnu_test::pod_uchar> 340 { 341 public: 342 typedef __gnu_test::pod_uchar char_type; 343 344 explicit ctype(size_t refs = 0) 345 : __ctype_abstract_base<__gnu_test::pod_uchar>(refs) { } 346 347 static locale::id id; 348 349 protected: 350 ~ctype() 351 { } 352 353 virtual bool 354 do_is(mask, char_type) const 355 { return false; } 356 357 virtual const char_type* 358 do_is(const char_type* low, const char_type* high, mask* vec) const 359 { 360 fill_n(vec, high - low, mask()); 361 return high; 362 } 363 364 virtual const char_type* 365 do_scan_is(mask, const char_type*, const char_type* high) const 366 { return high; } 367 368 virtual const char_type* 369 do_scan_not(mask, const char_type* low, const char_type*) const 370 { return low; } 371 372 virtual char_type 373 do_toupper(char_type c) const 374 { return c; } 375 376 virtual const char_type* 377 do_toupper(char_type*, const char_type* high) const 378 { return high; } 379 380 virtual char_type 381 do_tolower(char_type c) const 382 { return c; } 383 384 virtual const char_type* 385 do_tolower(char_type*, const char_type* high) const 386 { return high; } 387 388 virtual char_type 389 do_widen(char c) const 390 { return __gnu_test::pod_uchar::from<char>(c); } 391 392 virtual const char* 393 do_widen(const char* low, const char* high, char_type* dest) const 394 { 395 transform(low, high, dest, &__gnu_test::pod_uchar::from<char>); 396 return high; 397 } 398 399 virtual char 400 do_narrow(char_type, char dfault) const 401 { return dfault; } 402 403 virtual const char_type* 404 do_narrow(const char_type* low, const char_type* high, 405 char dfault, char* dest) const 406 { 407 fill_n(dest, high - low, dfault); 408 return high; 409 } 410 }; 411 412 // numpunct specializations 413 template<> 414 class numpunct<__gnu_test::pod_uint> 415 : public locale::facet 416 { 417 public: 418 typedef __gnu_test::pod_uint char_type; 419 typedef basic_string<char_type> string_type; 420 421 static locale::id id; 422 423 explicit 424 numpunct(size_t refs = 0) 425 : locale::facet(refs) 426 { } 427 428 char_type 429 decimal_point() const 430 { return this->do_decimal_point(); } 431 432 char_type 433 thousands_sep() const 434 { return this->do_thousands_sep(); } 435 436 string 437 grouping() const 438 { return this->do_grouping(); } 439 440 string_type 441 truename() const 442 { return this->do_truename(); } 443 444 string_type 445 falsename() const 446 { return this->do_falsename(); } 447 448 protected: 449 ~numpunct() 450 { } 451 452 virtual char_type 453 do_decimal_point() const 454 { return char_type(); } 455 456 virtual char_type 457 do_thousands_sep() const 458 { return char_type(); } 459 460 virtual string 461 do_grouping() const 462 { return string(); } 463 464 virtual string_type 465 do_truename() const 466 { return string_type(); } 467 468 virtual string_type 469 do_falsename() const 470 { return string_type(); } 471 }; 472 473 template<> 474 class moneypunct<__gnu_test::pod_uint> 475 : public locale::facet, public money_base 476 { 477 public: 478 typedef __gnu_test::pod_uint char_type; 479 typedef basic_string<char_type> string_type; 480 481 static locale::id id; 482 static const bool intl = false; 483 484 explicit 485 moneypunct(size_t refs = 0) 486 : locale::facet(refs) 487 { } 488 489 char_type 490 decimal_point() const 491 { return this->do_decimal_point(); } 492 493 char_type 494 thousands_sep() const 495 { return this->do_thousands_sep(); } 496 497 string 498 grouping() const 499 { return this->do_grouping(); } 500 501 string_type 502 curr_symbol() const 503 { return this->do_curr_symbol(); } 504 505 string_type 506 positive_sign() const 507 { return this->do_positive_sign(); } 508 509 string_type 510 negative_sign() const 511 { return this->do_negative_sign(); } 512 513 int 514 frac_digits() const 515 { return this->do_frac_digits(); } 516 517 pattern 518 pos_format() const 519 { return this->do_pos_format(); } 520 521 pattern 522 neg_format() const 523 { return this->do_neg_format(); } 524 525 protected: 526 ~moneypunct() 527 { } 528 529 virtual char_type 530 do_decimal_point() const 531 { return char_type(); } 532 533 virtual char_type 534 do_thousands_sep() const 535 { return char_type(); } 536 537 virtual string 538 do_grouping() const 539 { return string(); } 540 541 virtual string_type 542 do_curr_symbol() const 543 { return string_type(); } 544 545 string_type 546 do_positive_sign() const 547 { return string_type(); } 548 549 string_type 550 do_negative_sign() const 551 { return string_type(); } 552 553 int 554 do_frac_digits() const 555 { return 0; } 556 557 pattern 558 do_pos_format() const 559 { return pattern(); } 560 561 pattern 562 do_neg_format() const 563 { return pattern(); } 564 }; 565} // namespace std 566 567#endif // _GLIBCXX_TESTSUITE_CHARACTER_H 568 569