Constexpr.h 2.7 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091
  1. /*
  2. * Copyright 2016-present Facebook, Inc.
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. */
  16. #pragma once
  17. #include <folly/CPortability.h>
  18. #include <cstdint>
  19. #include <cstring>
  20. #include <type_traits>
  21. namespace folly {
  22. namespace detail {
  23. template <typename Char>
  24. constexpr size_t constexpr_strlen_internal(const Char* s, size_t len) {
  25. // clang-format off
  26. return
  27. *(s + 0) == Char(0) ? len + 0 :
  28. *(s + 1) == Char(0) ? len + 1 :
  29. *(s + 2) == Char(0) ? len + 2 :
  30. *(s + 3) == Char(0) ? len + 3 :
  31. *(s + 4) == Char(0) ? len + 4 :
  32. *(s + 5) == Char(0) ? len + 5 :
  33. *(s + 6) == Char(0) ? len + 6 :
  34. *(s + 7) == Char(0) ? len + 7 :
  35. constexpr_strlen_internal(s + 8, len + 8);
  36. // clang-format on
  37. }
  38. static_assert(
  39. constexpr_strlen_internal("123456789", 0) == 9,
  40. "Someone appears to have broken constexpr_strlen...");
  41. template <typename Char>
  42. constexpr int constexpr_strcmp_internal(const Char* s1, const Char* s2) {
  43. return (*s1 == '\0' || *s1 != *s2)
  44. ? (static_cast<int>(*s1 - *s2))
  45. : constexpr_strcmp_internal(s1 + 1, s2 + 1);
  46. }
  47. } // namespace detail
  48. template <typename Char>
  49. constexpr size_t constexpr_strlen(const Char* s) {
  50. return detail::constexpr_strlen_internal(s, 0);
  51. }
  52. template <>
  53. constexpr size_t constexpr_strlen(const char* s) {
  54. #if FOLLY_HAS_FEATURE(cxx_constexpr_string_builtins)
  55. // clang provides a constexpr builtin
  56. return __builtin_strlen(s);
  57. #elif defined(__GNUC__) && !defined(__clang__)
  58. // strlen() happens to already be constexpr under gcc
  59. return std::strlen(s);
  60. #else
  61. return detail::constexpr_strlen_internal(s, 0);
  62. #endif
  63. }
  64. template <typename Char>
  65. constexpr int constexpr_strcmp(const Char* s1, const Char* s2) {
  66. return detail::constexpr_strcmp_internal(s1, s2);
  67. }
  68. template <>
  69. constexpr int constexpr_strcmp(const char* s1, const char* s2) {
  70. #if FOLLY_HAS_FEATURE(cxx_constexpr_string_builtins)
  71. // clang provides a constexpr builtin
  72. return __builtin_strcmp(s1, s2);
  73. #elif defined(__GNUC__) && !defined(__clang__)
  74. // strcmp() happens to already be constexpr under gcc
  75. return std::strcmp(s1, s2);
  76. #else
  77. return detail::constexpr_strcmp_internal(s1, s2);
  78. #endif
  79. }
  80. } // namespace folly