Line data Source code
1 : //@HEADER 2 : // ************************************************************************ 3 : // 4 : // Kokkos v. 4.0 5 : // Copyright (2022) National Technology & Engineering 6 : // Solutions of Sandia, LLC (NTESS). 7 : // 8 : // Under the terms of Contract DE-NA0003525 with NTESS, 9 : // the U.S. Government retains certain rights in this software. 10 : // 11 : // Part of Kokkos, under the Apache License v2.0 with LLVM Exceptions. 12 : // See https://kokkos.org/LICENSE for license information. 13 : // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 14 : // 15 : //@HEADER 16 : 17 : #ifndef KOKKOS_STRING_MANIPULATION_HPP 18 : #define KOKKOS_STRING_MANIPULATION_HPP 19 : 20 : #include <Kokkos_Macros.hpp> 21 : #include <cstddef> 22 : #include <type_traits> 23 : 24 : namespace Kokkos { 25 : namespace Impl { 26 : 27 : // This header provides a subset of the functionality from <cstring>. In 28 : // contrast to the standard library header, functions are usable on the device 29 : // and in constant expressions. It also includes functionality from <charconv> 30 : // to convert an integer value to a character sequence. 31 : 32 : //<editor-fold desc="String examination"> 33 : // returns the length of a given string 34 0 : KOKKOS_INLINE_FUNCTION constexpr std::size_t strlen(const char *str) { 35 0 : std::size_t i = 0; 36 0 : while (str[i] != '\0') { 37 0 : ++i; 38 : } 39 0 : return i; 40 : } 41 : 42 : // compares two strings 43 : KOKKOS_INLINE_FUNCTION constexpr int strcmp(const char *lhs, const char *rhs) { 44 : while (*lhs == *rhs++) { 45 : if (*lhs++ == '\0') { 46 : return 0; 47 : } 48 : } 49 : return static_cast<unsigned int>(*lhs) - 50 : static_cast<unsigned int>(*(rhs - 1)); 51 : } 52 : 53 : // compares a certain number of characters from two strings 54 : KOKKOS_INLINE_FUNCTION constexpr int strncmp(const char *lhs, const char *rhs, 55 : std::size_t count) { 56 : for (std::size_t i = 0; i < count; ++i) { 57 : if (lhs[i] != rhs[i]) { 58 : return lhs[i] < rhs[i] ? -1 : 1; 59 : } else if (lhs[i] == '\0') { 60 : return 0; 61 : } 62 : } 63 : return 0; 64 : } 65 : //</editor-fold> 66 : 67 : //<editor-fold desc="String manipulation"> 68 : // copies one string to another 69 : KOKKOS_INLINE_FUNCTION constexpr char *strcpy(char *dest, const char *src) { 70 : char *d = dest; 71 : for (; (*d = *src) != '\0'; ++d, ++src) { 72 : } 73 : return dest; 74 : } 75 : 76 : // copies a certain amount of characters from one string to another 77 : KOKKOS_INLINE_FUNCTION constexpr char *strncpy(char *dest, const char *src, 78 : std::size_t count) { 79 : if (count != 0) { 80 : char *d = dest; 81 : do { 82 : if (char const c = (*d++ = *src++); c == '\0') { 83 : while (--count != 0) { 84 : *d++ = '\0'; 85 : } 86 : break; 87 : } 88 : } while (--count != 0); 89 : } 90 : return dest; 91 : } 92 : 93 : // concatenates two strings 94 0 : KOKKOS_INLINE_FUNCTION constexpr char *strcat(char *dest, const char *src) { 95 0 : char *d = dest; 96 0 : for (; *d != '\0'; ++d) { 97 : } 98 0 : while ((*d++ = *src++) != '\0') { 99 : } 100 0 : return dest; 101 : } 102 : 103 : // concatenates a certain amount of characters of two strings 104 0 : KOKKOS_INLINE_FUNCTION constexpr char *strncat(char *dest, const char *src, 105 : std::size_t count) { 106 0 : if (count != 0) { 107 : char *d = dest; 108 0 : for (; *d != '\0'; ++d) { 109 : } 110 0 : do { 111 0 : if (char const c = (*d = *src++); c == '\0') { 112 : break; 113 : } 114 0 : d++; 115 0 : } while (--count != 0); 116 0 : *d = '\0'; 117 : } 118 0 : return dest; 119 : } 120 : //</editor-fold> 121 : 122 : //<editor-fold desc="Character conversions"> 123 : template <class Unsigned> 124 : KOKKOS_FUNCTION constexpr unsigned int to_chars_len(Unsigned val) { 125 : unsigned int const base = 10; 126 : static_assert(std::is_integral_v<Unsigned>, "implementation bug"); 127 : static_assert(std::is_unsigned_v<Unsigned>, "implementation bug"); 128 : unsigned int n = 1; 129 0 : while (val >= base) { 130 0 : val /= base; 131 0 : ++n; 132 : } 133 : return n; 134 : } 135 : template <class Unsigned> 136 0 : KOKKOS_FUNCTION constexpr void to_chars_impl(char *first, unsigned int len, 137 : Unsigned val) { 138 0 : unsigned int const base = 10; 139 : static_assert(std::is_integral_v<Unsigned>, "implementation bug"); 140 : static_assert(std::is_unsigned_v<Unsigned>, "implementation bug"); 141 0 : unsigned int pos = len - 1; 142 0 : while (val > 0) { 143 0 : auto const num = val % base; 144 0 : val /= base; 145 0 : first[pos] = '0' + num; 146 0 : --pos; 147 : } 148 : } 149 : 150 : // define values of portable error conditions that correspond to the POSIX error 151 : // codes 152 : enum class errc { 153 : value_too_large = 75 // equivalent POSIX error is EOVERFLOW 154 : }; 155 : struct to_chars_result { 156 : char *ptr; 157 : errc ec; 158 : }; 159 : 160 : // converts an integer value to a character sequence 161 : template <class Integral> 162 0 : KOKKOS_FUNCTION constexpr to_chars_result to_chars_i(char *first, char *last, 163 : Integral value) { 164 : using Unsigned = std::conditional_t<sizeof(Integral) <= sizeof(unsigned int), 165 : unsigned int, unsigned long long>; 166 0 : Unsigned unsigned_val = value; 167 0 : if (value == 0) { 168 0 : *first = '0'; 169 0 : return {first + 1, {}}; 170 : } else if constexpr (std::is_signed_v<Integral>) { 171 : if (value < 0) { 172 : *first++ = '-'; 173 : unsigned_val = Unsigned(~value) + Unsigned(1); 174 : } 175 : } 176 0 : std::ptrdiff_t const len = to_chars_len(unsigned_val); 177 0 : if (last - first < len) { 178 0 : return {last, errc::value_too_large}; 179 : } 180 0 : to_chars_impl(first, len, unsigned_val); 181 0 : return {first + len, {}}; 182 : } 183 : //</editor-fold> 184 : 185 : } // namespace Impl 186 : } // namespace Kokkos 187 : 188 : #endif