1 // Character Traits for use by standard string and iostream -*- C++ -*- 2 3 // Copyright (C) 1997-2018 Free Software Foundation, Inc. 4 // 5 // This file is part of the GNU ISO C++ Library. This library is free 6 // software; you can redistribute it and/or modify it under the 7 // terms of the GNU General Public License as published by the 8 // Free Software Foundation; either version 3, or (at your option) 9 // any later version. 10 11 // This library is distributed in the hope that it will be useful, 12 // but WITHOUT ANY WARRANTY; without even the implied warranty of 13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 // GNU General Public License for more details. 15 16 // Under Section 7 of GPL version 3, you are granted additional 17 // permissions described in the GCC Runtime Library Exception, version 18 // 3.1, as published by the Free Software Foundation. 19 20 // You should have received a copy of the GNU General Public License and 21 // a copy of the GCC Runtime Library Exception along with this program; 22 // see the files COPYING3 and COPYING.RUNTIME respectively. If not, see 23 // <http://www.gnu.org/licenses/>. 24 25 /** @file bits/char_traits.h 26 * This is an internal header file, included by other library headers. 27 * Do not attempt to use it directly. @headername{string} 28 */ 29 30 // 31 // ISO C++ 14882: 21 Strings library 32 // 33 34 #ifndef _CHAR_TRAITS_H 35 #define _CHAR_TRAITS_H 1 36 37 #pragma GCC system_header 38 39 #include <bits/stl_algobase.h> // std::copy, std::fill_n 40 #include <bits/postypes.h> // For streampos 41 #include <cwchar> // For WEOF, wmemmove, wmemset, etc. 42 43 #ifndef _GLIBCXX_ALWAYS_INLINE 44 #define _GLIBCXX_ALWAYS_INLINE inline __attribute__((__always_inline__)) 45 #endif 46 47 namespace __gnu_cxx _GLIBCXX_VISIBILITY(default) 48 { 49 _GLIBCXX_BEGIN_NAMESPACE_VERSION 50 51 /** 52 * @brief Mapping from character type to associated types. 53 * 54 * @note This is an implementation class for the generic version 55 * of char_traits. It defines int_type, off_type, pos_type, and 56 * state_type. By default these are unsigned long, streamoff, 57 * streampos, and mbstate_t. Users who need a different set of 58 * types, but who don't need to change the definitions of any function 59 * defined in char_traits, can specialize __gnu_cxx::_Char_types 60 * while leaving __gnu_cxx::char_traits alone. */ 61 template<typename _CharT> 62 struct _Char_types 63 { 64 typedef unsigned long int_type; 65 typedef std::streampos pos_type; 66 typedef std::streamoff off_type; 67 typedef std::mbstate_t state_type; 68 }; 69 70 71 /** 72 * @brief Base class used to implement std::char_traits. 73 * 74 * @note For any given actual character type, this definition is 75 * probably wrong. (Most of the member functions are likely to be 76 * right, but the int_type and state_type typedefs, and the eof() 77 * member function, are likely to be wrong.) The reason this class 78 * exists is so users can specialize it. Classes in namespace std 79 * may not be specialized for fundamental types, but classes in 80 * namespace __gnu_cxx may be. 81 * 82 * See https://gcc.gnu.org/onlinedocs/libstdc++/manual/strings.html#strings.string.character_types 83 * for advice on how to make use of this class for @a unusual character 84 * types. Also, check out include/ext/pod_char_traits.h. 85 */ 86 template<typename _CharT> 87 struct char_traits 88 { 89 typedef _CharT char_type; 90 typedef typename _Char_types<_CharT>::int_type int_type; 91 typedef typename _Char_types<_CharT>::pos_type pos_type; 92 typedef typename _Char_types<_CharT>::off_type off_type; 93 typedef typename _Char_types<_CharT>::state_type state_type; 94 95 static _GLIBCXX14_CONSTEXPR void 96 assign(char_type& __c1, const char_type& __c2) 97 { __c1 = __c2; } 98 99 static _GLIBCXX_CONSTEXPR bool 100 eq(const char_type& __c1, const char_type& __c2) 101 { return __c1 == __c2; } 102 103 static _GLIBCXX_CONSTEXPR bool 104 lt(const char_type& __c1, const char_type& __c2) 105 { return __c1 < __c2; } 106 107 static _GLIBCXX14_CONSTEXPR int 108 compare(const char_type* __s1, const char_type* __s2, std::size_t __n); 109 110 static _GLIBCXX14_CONSTEXPR std::size_t 111 length(const char_type* __s); 112 113 static _GLIBCXX14_CONSTEXPR const char_type* 114 find(const char_type* __s, std::size_t __n, const char_type& __a); 115 116 static char_type* 117 move(char_type* __s1, const char_type* __s2, std::size_t __n); 118 119 static char_type* 120 copy(char_type* __s1, const char_type* __s2, std::size_t __n); 121 122 static char_type* 123 assign(char_type* __s, std::size_t __n, char_type __a); 124 125 static _GLIBCXX_CONSTEXPR char_type 126 to_char_type(const int_type& __c) 127 { return static_cast<char_type>(__c); } 128 129 static _GLIBCXX_CONSTEXPR int_type 130 to_int_type(const char_type& __c) 131 { return static_cast<int_type>(__c); } 132 133 static _GLIBCXX_CONSTEXPR bool 134 eq_int_type(const int_type& __c1, const int_type& __c2) 135 { return __c1 == __c2; } 136 137 static _GLIBCXX_CONSTEXPR int_type 138 eof() 139 { return static_cast<int_type>(_GLIBCXX_STDIO_EOF); } 140 141 static _GLIBCXX_CONSTEXPR int_type 142 not_eof(const int_type& __c) 143 { return !eq_int_type(__c, eof()) ? __c : to_int_type(char_type()); } 144 }; 145 146 #define __cpp_lib_constexpr_char_traits 201611 147 148 template<typename _CharT> 149 _GLIBCXX14_CONSTEXPR int 150 char_traits<_CharT>:: 151 compare(const char_type* __s1, const char_type* __s2, std::size_t __n) 152 { 153 for (std::size_t __i = 0; __i < __n; ++__i) 154 if (lt(__s1[__i], __s2[__i])) 155 return -1; 156 else if (lt(__s2[__i], __s1[__i])) 157 return 1; 158 return 0; 159 } 160 161 template<typename _CharT> 162 _GLIBCXX14_CONSTEXPR std::size_t 163 char_traits<_CharT>:: 164 length(const char_type* __p) 165 { 166 std::size_t __i = 0; 167 while (!eq(__p[__i], char_type())) 168 ++__i; 169 return __i; 170 } 171 172 template<typename _CharT> 173 _GLIBCXX14_CONSTEXPR const typename char_traits<_CharT>::char_type* 174 char_traits<_CharT>:: 175 find(const char_type* __s, std::size_t __n, const char_type& __a) 176 { 177 for (std::size_t __i = 0; __i < __n; ++__i) 178 if (eq(__s[__i], __a)) 179 return __s + __i; 180 return 0; 181 } 182 183 template<typename _CharT> 184 typename char_traits<_CharT>::char_type* 185 char_traits<_CharT>:: 186 move(char_type* __s1, const char_type* __s2, std::size_t __n) 187 { 188 return static_cast<_CharT*>(__builtin_memmove(__s1, __s2, 189 __n * sizeof(char_type))); 190 } 191 192 template<typename _CharT> 193 typename char_traits<_CharT>::char_type* 194 char_traits<_CharT>:: 195 copy(char_type* __s1, const char_type* __s2, std::size_t __n) 196 { 197 // NB: Inline std::copy so no recursive dependencies. 198 std::copy(__s2, __s2 + __n, __s1); 199 return __s1; 200 } 201 202 template<typename _CharT> 203 typename char_traits<_CharT>::char_type* 204 char_traits<_CharT>:: 205 assign(char_type* __s, std::size_t __n, char_type __a) 206 { 207 // NB: Inline std::fill_n so no recursive dependencies. 208 std::fill_n(__s, __n, __a); 209 return __s; 210 } 211 212 _GLIBCXX_END_NAMESPACE_VERSION 213 } // namespace 214 215 namespace std _GLIBCXX_VISIBILITY(default) 216 { 217 _GLIBCXX_BEGIN_NAMESPACE_VERSION 218 219 #if __cplusplus > 201402 220 /** 221 * @brief Determine whether the characters of a NULL-terminated 222 * string are known at compile time. 223 * @param __s The string. 224 * 225 * Assumes that _CharT is a built-in character type. 226 */ 227 template<typename _CharT> 228 static _GLIBCXX_ALWAYS_INLINE constexpr bool 229 __constant_string_p(const _CharT* __s) 230 { 231 while (__builtin_constant_p(*__s) && *__s) 232 __s++; 233 return __builtin_constant_p(*__s); 234 } 235 236 /** 237 * @brief Determine whether the characters of a character array are 238 * known at compile time. 239 * @param __a The character array. 240 * @param __n Number of characters. 241 * 242 * Assumes that _CharT is a built-in character type. 243 */ 244 template<typename _CharT> 245 static _GLIBCXX_ALWAYS_INLINE constexpr bool 246 __constant_char_array_p(const _CharT* __a, size_t __n) 247 { 248 size_t __i = 0; 249 while (__builtin_constant_p(__a[__i]) && __i < __n) 250 __i++; 251 return __i == __n; 252 } 253 #endif 254 255 // 21.1 256 /** 257 * @brief Basis for explicit traits specializations. 258 * 259 * @note For any given actual character type, this definition is 260 * probably wrong. Since this is just a thin wrapper around 261 * __gnu_cxx::char_traits, it is possible to achieve a more 262 * appropriate definition by specializing __gnu_cxx::char_traits. 263 * 264 * See https://gcc.gnu.org/onlinedocs/libstdc++/manual/strings.html#strings.string.character_types 265 * for advice on how to make use of this class for @a unusual character 266 * types. Also, check out include/ext/pod_char_traits.h. 267 */ 268 template<class _CharT> 269 struct char_traits : public __gnu_cxx::char_traits<_CharT> 270 { }; 271 272 273 /// 21.1.3.1 char_traits specializations 274 template<> 275 struct char_traits<char> 276 { 277 typedef char char_type; 278 typedef int int_type; 279 typedef streampos pos_type; 280 typedef streamoff off_type; 281 typedef mbstate_t state_type; 282 283 static _GLIBCXX17_CONSTEXPR void 284 assign(char_type& __c1, const char_type& __c2) _GLIBCXX_NOEXCEPT 285 { __c1 = __c2; } 286 287 static _GLIBCXX_CONSTEXPR bool 288 eq(const char_type& __c1, const char_type& __c2) _GLIBCXX_NOEXCEPT 289 { return __c1 == __c2; } 290 291 static _GLIBCXX_CONSTEXPR bool 292 lt(const char_type& __c1, const char_type& __c2) _GLIBCXX_NOEXCEPT 293 { 294 // LWG 467. 295 return (static_cast<unsigned char>(__c1) 296 < static_cast<unsigned char>(__c2)); 297 } 298 299 static _GLIBCXX17_CONSTEXPR int 300 compare(const char_type* __s1, const char_type* __s2, size_t __n) 301 { 302 #if __cplusplus > 201402 303 if (__builtin_constant_p(__n) 304 && __constant_char_array_p(__s1, __n) 305 && __constant_char_array_p(__s2, __n)) 306 return __gnu_cxx::char_traits<char_type>::compare(__s1, __s2, __n); 307 #endif 308 if (__n == 0) 309 return 0; 310 return __builtin_memcmp(__s1, __s2, __n); 311 } 312 313 static _GLIBCXX17_CONSTEXPR size_t 314 length(const char_type* __s) 315 { 316 #if __cplusplus > 201402 317 if (__constant_string_p(__s)) 318 return __gnu_cxx::char_traits<char_type>::length(__s); 319 #endif 320 return __builtin_strlen(__s); 321 } 322 323 static _GLIBCXX17_CONSTEXPR const char_type* 324 find(const char_type* __s, size_t __n, const char_type& __a) 325 { 326 #if __cplusplus > 201402 327 if (__builtin_constant_p(__n) 328 && __builtin_constant_p(__a) 329 && __constant_char_array_p(__s, __n)) 330 return __gnu_cxx::char_traits<char_type>::find(__s, __n, __a); 331 #endif 332 if (__n == 0) 333 return 0; 334 return static_cast<const char_type*>(__builtin_memchr(__s, __a, __n)); 335 } 336 337 static char_type* 338 move(char_type* __s1, const char_type* __s2, size_t __n) 339 { 340 if (__n == 0) 341 return __s1; 342 return static_cast<char_type*>(__builtin_memmove(__s1, __s2, __n)); 343 } 344 345 static char_type* 346 copy(char_type* __s1, const char_type* __s2, size_t __n) 347 { 348 if (__n == 0) 349 return __s1; 350 return static_cast<char_type*>(__builtin_memcpy(__s1, __s2, __n)); 351 } 352 353 static char_type* 354 assign(char_type* __s, size_t __n, char_type __a) 355 { 356 if (__n == 0) 357 return __s; 358 return static_cast<char_type*>(__builtin_memset(__s, __a, __n)); 359 } 360 361 static _GLIBCXX_CONSTEXPR char_type 362 to_char_type(const int_type& __c) _GLIBCXX_NOEXCEPT 363 { return static_cast<char_type>(__c); } 364 365 // To keep both the byte 0xff and the eof symbol 0xffffffff 366 // from ending up as 0xffffffff. 367 static _GLIBCXX_CONSTEXPR int_type 368 to_int_type(const char_type& __c) _GLIBCXX_NOEXCEPT 369 { return static_cast<int_type>(static_cast<unsigned char>(__c)); } 370 371 static _GLIBCXX_CONSTEXPR bool 372 eq_int_type(const int_type& __c1, const int_type& __c2) _GLIBCXX_NOEXCEPT 373 { return __c1 == __c2; } 374 375 static _GLIBCXX_CONSTEXPR int_type 376 eof() _GLIBCXX_NOEXCEPT 377 { return static_cast<int_type>(_GLIBCXX_STDIO_EOF); } 378 379 static _GLIBCXX_CONSTEXPR int_type 380 not_eof(const int_type& __c) _GLIBCXX_NOEXCEPT 381 { return (__c == eof()) ? 0 : __c; } 382 }; 383 384 385 #ifdef _GLIBCXX_USE_WCHAR_T 386 /// 21.1.3.2 char_traits specializations 387 template<> 388 struct char_traits<wchar_t> 389 { 390 typedef wchar_t char_type; 391 typedef wint_t int_type; 392 typedef streamoff off_type; 393 typedef wstreampos pos_type; 394 typedef mbstate_t state_type; 395 396 static _GLIBCXX17_CONSTEXPR void 397 assign(char_type& __c1, const char_type& __c2) _GLIBCXX_NOEXCEPT 398 { __c1 = __c2; } 399 400 static _GLIBCXX_CONSTEXPR bool 401 eq(const char_type& __c1, const char_type& __c2) _GLIBCXX_NOEXCEPT 402 { return __c1 == __c2; } 403 404 static _GLIBCXX_CONSTEXPR bool 405 lt(const char_type& __c1, const char_type& __c2) _GLIBCXX_NOEXCEPT 406 { return __c1 < __c2; } 407 408 static _GLIBCXX17_CONSTEXPR int 409 compare(const char_type* __s1, const char_type* __s2, size_t __n) 410 { 411 #if __cplusplus > 201402 412 if (__builtin_constant_p(__n) 413 && __constant_char_array_p(__s1, __n) 414 && __constant_char_array_p(__s2, __n)) 415 return __gnu_cxx::char_traits<char_type>::compare(__s1, __s2, __n); 416 #endif 417 if (__n == 0) 418 return 0; 419 else 420 return wmemcmp(__s1, __s2, __n); 421 } 422 423 static _GLIBCXX17_CONSTEXPR size_t 424 length(const char_type* __s) 425 { 426 #if __cplusplus > 201402 427 if (__constant_string_p(__s)) 428 return __gnu_cxx::char_traits<char_type>::length(__s); 429 else 430 #endif 431 return wcslen(__s); 432 } 433 434 static _GLIBCXX17_CONSTEXPR const char_type* 435 find(const char_type* __s, size_t __n, const char_type& __a) 436 { 437 #if __cplusplus > 201402 438 if (__builtin_constant_p(__n) 439 && __builtin_constant_p(__a) 440 && __constant_char_array_p(__s, __n)) 441 return __gnu_cxx::char_traits<char_type>::find(__s, __n, __a); 442 #endif 443 if (__n == 0) 444 return 0; 445 else 446 return wmemchr(__s, __a, __n); 447 } 448 449 static char_type* 450 move(char_type* __s1, const char_type* __s2, size_t __n) 451 { 452 if (__n == 0) 453 return __s1; 454 return wmemmove(__s1, __s2, __n); 455 } 456 457 static char_type* 458 copy(char_type* __s1, const char_type* __s2, size_t __n) 459 { 460 if (__n == 0) 461 return __s1; 462 return wmemcpy(__s1, __s2, __n); 463 } 464 465 static char_type* 466 assign(char_type* __s, size_t __n, char_type __a) 467 { 468 if (__n == 0) 469 return __s; 470 return wmemset(__s, __a, __n); 471 } 472 473 static _GLIBCXX_CONSTEXPR char_type 474 to_char_type(const int_type& __c) _GLIBCXX_NOEXCEPT 475 { return char_type(__c); } 476 477 static _GLIBCXX_CONSTEXPR int_type 478 to_int_type(const char_type& __c) _GLIBCXX_NOEXCEPT 479 { return int_type(__c); } 480 481 static _GLIBCXX_CONSTEXPR bool 482 eq_int_type(const int_type& __c1, const int_type& __c2) _GLIBCXX_NOEXCEPT 483 { return __c1 == __c2; } 484 485 static _GLIBCXX_CONSTEXPR int_type 486 eof() _GLIBCXX_NOEXCEPT 487 { return static_cast<int_type>(WEOF); } 488 489 static _GLIBCXX_CONSTEXPR int_type 490 not_eof(const int_type& __c) _GLIBCXX_NOEXCEPT 491 { return eq_int_type(__c, eof()) ? 0 : __c; } 492 }; 493 #endif //_GLIBCXX_USE_WCHAR_T 494 495 _GLIBCXX_END_NAMESPACE_VERSION 496 } // namespace 497 498 #if ((__cplusplus >= 201103L) \ 499 && defined(_GLIBCXX_USE_C99_STDINT_TR1)) 500 501 #include <cstdint> 502 503 namespace std _GLIBCXX_VISIBILITY(default) 504 { 505 _GLIBCXX_BEGIN_NAMESPACE_VERSION 506 507 template<> 508 struct char_traits<char16_t> 509 { 510 typedef char16_t char_type; 511 typedef uint_least16_t int_type; 512 typedef streamoff off_type; 513 typedef u16streampos pos_type; 514 typedef mbstate_t state_type; 515 516 static _GLIBCXX17_CONSTEXPR void 517 assign(char_type& __c1, const char_type& __c2) noexcept 518 { __c1 = __c2; } 519 520 static constexpr bool 521 eq(const char_type& __c1, const char_type& __c2) noexcept 522 { return __c1 == __c2; } 523 524 static constexpr bool 525 lt(const char_type& __c1, const char_type& __c2) noexcept 526 { return __c1 < __c2; } 527 528 static _GLIBCXX17_CONSTEXPR int 529 compare(const char_type* __s1, const char_type* __s2, size_t __n) 530 { 531 for (size_t __i = 0; __i < __n; ++__i) 532 if (lt(__s1[__i], __s2[__i])) 533 return -1; 534 else if (lt(__s2[__i], __s1[__i])) 535 return 1; 536 return 0; 537 } 538 539 static _GLIBCXX17_CONSTEXPR size_t 540 length(const char_type* __s) 541 { 542 size_t __i = 0; 543 while (!eq(__s[__i], char_type())) 544 ++__i; 545 return __i; 546 } 547 548 static _GLIBCXX17_CONSTEXPR const char_type* 549 find(const char_type* __s, size_t __n, const char_type& __a) 550 { 551 for (size_t __i = 0; __i < __n; ++__i) 552 if (eq(__s[__i], __a)) 553 return __s + __i; 554 return 0; 555 } 556 557 static char_type* 558 move(char_type* __s1, const char_type* __s2, size_t __n) 559 { 560 if (__n == 0) 561 return __s1; 562 return (static_cast<char_type*> 563 (__builtin_memmove(__s1, __s2, __n * sizeof(char_type)))); 564 } 565 566 static char_type* 567 copy(char_type* __s1, const char_type* __s2, size_t __n) 568 { 569 if (__n == 0) 570 return __s1; 571 return (static_cast<char_type*> 572 (__builtin_memcpy(__s1, __s2, __n * sizeof(char_type)))); 573 } 574 575 static char_type* 576 assign(char_type* __s, size_t __n, char_type __a) 577 { 578 for (size_t __i = 0; __i < __n; ++__i) 579 assign(__s[__i], __a); 580 return __s; 581 } 582 583 static constexpr char_type 584 to_char_type(const int_type& __c) noexcept 585 { return char_type(__c); } 586 587 static constexpr int_type 588 to_int_type(const char_type& __c) noexcept 589 { return __c == eof() ? int_type(0xfffd) : int_type(__c); } 590 591 static constexpr bool 592 eq_int_type(const int_type& __c1, const int_type& __c2) noexcept 593 { return __c1 == __c2; } 594 595 static constexpr int_type 596 eof() noexcept 597 { return static_cast<int_type>(-1); } 598 599 static constexpr int_type 600 not_eof(const int_type& __c) noexcept 601 { return eq_int_type(__c, eof()) ? 0 : __c; } 602 }; 603 604 template<> 605 struct char_traits<char32_t> 606 { 607 typedef char32_t char_type; 608 typedef uint_least32_t int_type; 609 typedef streamoff off_type; 610 typedef u32streampos pos_type; 611 typedef mbstate_t state_type; 612 613 static _GLIBCXX17_CONSTEXPR void 614 assign(char_type& __c1, const char_type& __c2) noexcept 615 { __c1 = __c2; } 616 617 static constexpr bool 618 eq(const char_type& __c1, const char_type& __c2) noexcept 619 { return __c1 == __c2; } 620 621 static constexpr bool 622 lt(const char_type& __c1, const char_type& __c2) noexcept 623 { return __c1 < __c2; } 624 625 static _GLIBCXX17_CONSTEXPR int 626 compare(const char_type* __s1, const char_type* __s2, size_t __n) 627 { 628 for (size_t __i = 0; __i < __n; ++__i) 629 if (lt(__s1[__i], __s2[__i])) 630 return -1; 631 else if (lt(__s2[__i], __s1[__i])) 632 return 1; 633 return 0; 634 } 635 636 static _GLIBCXX17_CONSTEXPR size_t 637 length(const char_type* __s) 638 { 639 size_t __i = 0; 640 while (!eq(__s[__i], char_type())) 641 ++__i; 642 return __i; 643 } 644 645 static _GLIBCXX17_CONSTEXPR const char_type* 646 find(const char_type* __s, size_t __n, const char_type& __a) 647 { 648 for (size_t __i = 0; __i < __n; ++__i) 649 if (eq(__s[__i], __a)) 650 return __s + __i; 651 return 0; 652 } 653 654 static char_type* 655 move(char_type* __s1, const char_type* __s2, size_t __n) 656 { 657 if (__n == 0) 658 return __s1; 659 return (static_cast<char_type*> 660 (__builtin_memmove(__s1, __s2, __n * sizeof(char_type)))); 661 } 662 663 static char_type* 664 copy(char_type* __s1, const char_type* __s2, size_t __n) 665 { 666 if (__n == 0) 667 return __s1; 668 return (static_cast<char_type*> 669 (__builtin_memcpy(__s1, __s2, __n * sizeof(char_type)))); 670 } 671 672 static char_type* 673 assign(char_type* __s, size_t __n, char_type __a) 674 { 675 for (size_t __i = 0; __i < __n; ++__i) 676 assign(__s[__i], __a); 677 return __s; 678 } 679 680 static constexpr char_type 681 to_char_type(const int_type& __c) noexcept 682 { return char_type(__c); } 683 684 static constexpr int_type 685 to_int_type(const char_type& __c) noexcept 686 { return int_type(__c); } 687 688 static constexpr bool 689 eq_int_type(const int_type& __c1, const int_type& __c2) noexcept 690 { return __c1 == __c2; } 691 692 static constexpr int_type 693 eof() noexcept 694 { return static_cast<int_type>(-1); } 695 696 static constexpr int_type 697 not_eof(const int_type& __c) noexcept 698 { return eq_int_type(__c, eof()) ? 0 : __c; } 699 }; 700 701 _GLIBCXX_END_NAMESPACE_VERSION 702 } // namespace 703 704 #endif 705 706 #endif // _CHAR_TRAITS_H 707