1 //===-- Collection of utils for implementing ctype functions-------*-C++-*-===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 #ifndef LLVM_LIBC_SRC___SUPPORT_CTYPE_UTILS_H 10 #define LLVM_LIBC_SRC___SUPPORT_CTYPE_UTILS_H 11 12 #include "src/__support/macros/attributes.h" 13 #include "src/__support/macros/config.h" 14 15 namespace LIBC_NAMESPACE_DECL { 16 namespace internal { 17 18 // ----------------------------------------------------------------------------- 19 // ****************** WARNING ****************** 20 // ****************** DO NOT TRY TO OPTIMIZE THESE FUNCTIONS! ****************** 21 // ----------------------------------------------------------------------------- 22 // This switch/case form is easier for the compiler to understand, and is 23 // optimized into a form that is almost always the same as or better than 24 // versions written by hand (see https://godbolt.org/z/qvrebqvvr). Also this 25 // form makes these functions encoding independent. If you want to rewrite these 26 // functions, make sure you have benchmarks to show your new solution is faster, 27 // as well as a way to support non-ASCII character encodings. 28 29 // Similarly, do not change these functions to use case ranges. e.g. 30 // bool islower(int ch) { 31 // switch(ch) { 32 // case 'a'...'z': 33 // return true; 34 // } 35 // } 36 // This assumes the character ranges are contiguous, which they aren't in 37 // EBCDIC. Technically we could use some smaller ranges, but that's even harder 38 // to read. 39 40 LIBC_INLINE static constexpr bool islower(int ch) { 41 switch (ch) { 42 case 'a': 43 case 'b': 44 case 'c': 45 case 'd': 46 case 'e': 47 case 'f': 48 case 'g': 49 case 'h': 50 case 'i': 51 case 'j': 52 case 'k': 53 case 'l': 54 case 'm': 55 case 'n': 56 case 'o': 57 case 'p': 58 case 'q': 59 case 'r': 60 case 's': 61 case 't': 62 case 'u': 63 case 'v': 64 case 'w': 65 case 'x': 66 case 'y': 67 case 'z': 68 return true; 69 default: 70 return false; 71 } 72 } 73 74 LIBC_INLINE static constexpr bool isupper(int ch) { 75 switch (ch) { 76 case 'A': 77 case 'B': 78 case 'C': 79 case 'D': 80 case 'E': 81 case 'F': 82 case 'G': 83 case 'H': 84 case 'I': 85 case 'J': 86 case 'K': 87 case 'L': 88 case 'M': 89 case 'N': 90 case 'O': 91 case 'P': 92 case 'Q': 93 case 'R': 94 case 'S': 95 case 'T': 96 case 'U': 97 case 'V': 98 case 'W': 99 case 'X': 100 case 'Y': 101 case 'Z': 102 return true; 103 default: 104 return false; 105 } 106 } 107 108 LIBC_INLINE static constexpr bool isdigit(int ch) { 109 switch (ch) { 110 case '0': 111 case '1': 112 case '2': 113 case '3': 114 case '4': 115 case '5': 116 case '6': 117 case '7': 118 case '8': 119 case '9': 120 return true; 121 default: 122 return false; 123 } 124 } 125 126 LIBC_INLINE static constexpr int tolower(int ch) { 127 switch (ch) { 128 case 'A': 129 return 'a'; 130 case 'B': 131 return 'b'; 132 case 'C': 133 return 'c'; 134 case 'D': 135 return 'd'; 136 case 'E': 137 return 'e'; 138 case 'F': 139 return 'f'; 140 case 'G': 141 return 'g'; 142 case 'H': 143 return 'h'; 144 case 'I': 145 return 'i'; 146 case 'J': 147 return 'j'; 148 case 'K': 149 return 'k'; 150 case 'L': 151 return 'l'; 152 case 'M': 153 return 'm'; 154 case 'N': 155 return 'n'; 156 case 'O': 157 return 'o'; 158 case 'P': 159 return 'p'; 160 case 'Q': 161 return 'q'; 162 case 'R': 163 return 'r'; 164 case 'S': 165 return 's'; 166 case 'T': 167 return 't'; 168 case 'U': 169 return 'u'; 170 case 'V': 171 return 'v'; 172 case 'W': 173 return 'w'; 174 case 'X': 175 return 'x'; 176 case 'Y': 177 return 'y'; 178 case 'Z': 179 return 'z'; 180 default: 181 return ch; 182 } 183 } 184 185 LIBC_INLINE static constexpr int toupper(int ch) { 186 switch (ch) { 187 case 'a': 188 return 'A'; 189 case 'b': 190 return 'B'; 191 case 'c': 192 return 'C'; 193 case 'd': 194 return 'D'; 195 case 'e': 196 return 'E'; 197 case 'f': 198 return 'F'; 199 case 'g': 200 return 'G'; 201 case 'h': 202 return 'H'; 203 case 'i': 204 return 'I'; 205 case 'j': 206 return 'J'; 207 case 'k': 208 return 'K'; 209 case 'l': 210 return 'L'; 211 case 'm': 212 return 'M'; 213 case 'n': 214 return 'N'; 215 case 'o': 216 return 'O'; 217 case 'p': 218 return 'P'; 219 case 'q': 220 return 'Q'; 221 case 'r': 222 return 'R'; 223 case 's': 224 return 'S'; 225 case 't': 226 return 'T'; 227 case 'u': 228 return 'U'; 229 case 'v': 230 return 'V'; 231 case 'w': 232 return 'W'; 233 case 'x': 234 return 'X'; 235 case 'y': 236 return 'Y'; 237 case 'z': 238 return 'Z'; 239 default: 240 return ch; 241 } 242 } 243 244 LIBC_INLINE static constexpr bool isalpha(int ch) { 245 switch (ch) { 246 case 'a': 247 case 'b': 248 case 'c': 249 case 'd': 250 case 'e': 251 case 'f': 252 case 'g': 253 case 'h': 254 case 'i': 255 case 'j': 256 case 'k': 257 case 'l': 258 case 'm': 259 case 'n': 260 case 'o': 261 case 'p': 262 case 'q': 263 case 'r': 264 case 's': 265 case 't': 266 case 'u': 267 case 'v': 268 case 'w': 269 case 'x': 270 case 'y': 271 case 'z': 272 case 'A': 273 case 'B': 274 case 'C': 275 case 'D': 276 case 'E': 277 case 'F': 278 case 'G': 279 case 'H': 280 case 'I': 281 case 'J': 282 case 'K': 283 case 'L': 284 case 'M': 285 case 'N': 286 case 'O': 287 case 'P': 288 case 'Q': 289 case 'R': 290 case 'S': 291 case 'T': 292 case 'U': 293 case 'V': 294 case 'W': 295 case 'X': 296 case 'Y': 297 case 'Z': 298 return true; 299 default: 300 return false; 301 } 302 } 303 304 LIBC_INLINE static constexpr bool isalnum(int ch) { 305 switch (ch) { 306 case 'a': 307 case 'b': 308 case 'c': 309 case 'd': 310 case 'e': 311 case 'f': 312 case 'g': 313 case 'h': 314 case 'i': 315 case 'j': 316 case 'k': 317 case 'l': 318 case 'm': 319 case 'n': 320 case 'o': 321 case 'p': 322 case 'q': 323 case 'r': 324 case 's': 325 case 't': 326 case 'u': 327 case 'v': 328 case 'w': 329 case 'x': 330 case 'y': 331 case 'z': 332 case 'A': 333 case 'B': 334 case 'C': 335 case 'D': 336 case 'E': 337 case 'F': 338 case 'G': 339 case 'H': 340 case 'I': 341 case 'J': 342 case 'K': 343 case 'L': 344 case 'M': 345 case 'N': 346 case 'O': 347 case 'P': 348 case 'Q': 349 case 'R': 350 case 'S': 351 case 'T': 352 case 'U': 353 case 'V': 354 case 'W': 355 case 'X': 356 case 'Y': 357 case 'Z': 358 case '0': 359 case '1': 360 case '2': 361 case '3': 362 case '4': 363 case '5': 364 case '6': 365 case '7': 366 case '8': 367 case '9': 368 return true; 369 default: 370 return false; 371 } 372 } 373 374 LIBC_INLINE static constexpr int b36_char_to_int(int ch) { 375 switch (ch) { 376 case '0': 377 return 0; 378 case '1': 379 return 1; 380 case '2': 381 return 2; 382 case '3': 383 return 3; 384 case '4': 385 return 4; 386 case '5': 387 return 5; 388 case '6': 389 return 6; 390 case '7': 391 return 7; 392 case '8': 393 return 8; 394 case '9': 395 return 9; 396 case 'a': 397 case 'A': 398 return 10; 399 case 'b': 400 case 'B': 401 return 11; 402 case 'c': 403 case 'C': 404 return 12; 405 case 'd': 406 case 'D': 407 return 13; 408 case 'e': 409 case 'E': 410 return 14; 411 case 'f': 412 case 'F': 413 return 15; 414 case 'g': 415 case 'G': 416 return 16; 417 case 'h': 418 case 'H': 419 return 17; 420 case 'i': 421 case 'I': 422 return 18; 423 case 'j': 424 case 'J': 425 return 19; 426 case 'k': 427 case 'K': 428 return 20; 429 case 'l': 430 case 'L': 431 return 21; 432 case 'm': 433 case 'M': 434 return 22; 435 case 'n': 436 case 'N': 437 return 23; 438 case 'o': 439 case 'O': 440 return 24; 441 case 'p': 442 case 'P': 443 return 25; 444 case 'q': 445 case 'Q': 446 return 26; 447 case 'r': 448 case 'R': 449 return 27; 450 case 's': 451 case 'S': 452 return 28; 453 case 't': 454 case 'T': 455 return 29; 456 case 'u': 457 case 'U': 458 return 30; 459 case 'v': 460 case 'V': 461 return 31; 462 case 'w': 463 case 'W': 464 return 32; 465 case 'x': 466 case 'X': 467 return 33; 468 case 'y': 469 case 'Y': 470 return 34; 471 case 'z': 472 case 'Z': 473 return 35; 474 default: 475 return 0; 476 } 477 } 478 479 LIBC_INLINE static constexpr int int_to_b36_char(int num) { 480 // Can't actually use LIBC_ASSERT here because it depends on integer_to_string 481 // which depends on this. 482 483 // LIBC_ASSERT(num < 36); 484 switch (num) { 485 case 0: 486 return '0'; 487 case 1: 488 return '1'; 489 case 2: 490 return '2'; 491 case 3: 492 return '3'; 493 case 4: 494 return '4'; 495 case 5: 496 return '5'; 497 case 6: 498 return '6'; 499 case 7: 500 return '7'; 501 case 8: 502 return '8'; 503 case 9: 504 return '9'; 505 case 10: 506 return 'a'; 507 case 11: 508 return 'b'; 509 case 12: 510 return 'c'; 511 case 13: 512 return 'd'; 513 case 14: 514 return 'e'; 515 case 15: 516 return 'f'; 517 case 16: 518 return 'g'; 519 case 17: 520 return 'h'; 521 case 18: 522 return 'i'; 523 case 19: 524 return 'j'; 525 case 20: 526 return 'k'; 527 case 21: 528 return 'l'; 529 case 22: 530 return 'm'; 531 case 23: 532 return 'n'; 533 case 24: 534 return 'o'; 535 case 25: 536 return 'p'; 537 case 26: 538 return 'q'; 539 case 27: 540 return 'r'; 541 case 28: 542 return 's'; 543 case 29: 544 return 't'; 545 case 30: 546 return 'u'; 547 case 31: 548 return 'v'; 549 case 32: 550 return 'w'; 551 case 33: 552 return 'x'; 553 case 34: 554 return 'y'; 555 case 35: 556 return 'z'; 557 default: 558 return '!'; 559 } 560 } 561 562 LIBC_INLINE static constexpr bool isspace(int ch) { 563 switch (ch) { 564 case ' ': 565 case '\t': 566 case '\n': 567 case '\v': 568 case '\f': 569 case '\r': 570 return true; 571 default: 572 return false; 573 } 574 } 575 576 // not yet encoding independent. 577 LIBC_INLINE static constexpr bool isgraph(int ch) { 578 return 0x20 < ch && ch < 0x7f; 579 } 580 581 } // namespace internal 582 } // namespace LIBC_NAMESPACE_DECL 583 584 #endif // LLVM_LIBC_SRC___SUPPORT_CTYPE_UTILS_H 585