tetl 0.1.0
Embedded Template Library
Loading...
Searching...
No Matches
cstr.hpp
Go to the documentation of this file.
1// SPDX-License-Identifier: BSL-1.0
2// SPDX-FileCopyrightText: Copyright (C) 2021 Tobias Hienzsch
3
4#ifndef TETL_CSTRING_ALGORITHM_HPP
5#define TETL_CSTRING_ALGORITHM_HPP
6
7namespace etl::detail {
8
9template <typename CharT>
10[[nodiscard]] constexpr auto strcpy(CharT* dest, CharT const* src) -> CharT*
11{
12 auto* temp = dest;
13 while ((*dest++ = *src++) != CharT(0)) { }
14 return temp;
15}
16
17template <typename CharT, typename SizeT>
18[[nodiscard]] constexpr auto strncpy(CharT* dest, CharT const* src, SizeT count) -> CharT*
19{
20 auto* temp = dest;
21 for (SizeT counter = 0; counter != count and *src != CharT(0);) {
22 *dest = *src;
23 ++src;
24 ++dest;
25 ++counter;
26 }
27
28 return temp;
29}
30
31template <typename CharT, typename SizeT>
32[[nodiscard]] constexpr auto strlen(CharT const* str) -> SizeT
33{
34 CharT const* s = nullptr;
35 for (s = str; *s != CharT(0); ++s) { }
36 return static_cast<SizeT>(s - str);
37}
38
39template <typename CharT, typename SizeT>
40[[nodiscard]] constexpr auto strcat(CharT* dest, CharT const* src) -> CharT*
41{
42 auto* ptr = dest + strlen<CharT, SizeT>(dest);
43 while (*src != CharT(0)) {
44 *ptr++ = *src++;
45 }
46 *ptr = CharT(0);
47 return dest;
48}
49
50template <typename CharT, typename SizeT>
51[[nodiscard]] constexpr auto strncat(CharT* dest, CharT const* src, SizeT const count) -> CharT*
52{
53 auto* ptr = dest + strlen<CharT, SizeT>(dest);
54 SizeT localCounter = 0;
55 while (*src != CharT(0) && localCounter != count) {
56 *ptr++ = *src++;
57 ++localCounter;
58 }
59
60 *ptr = CharT(0);
61 return dest;
62}
63
64template <typename CharT>
65[[nodiscard]] constexpr auto strcmp(CharT const* lhs, CharT const* rhs) -> int
66{
67 for (; *lhs != CharT(0); ++lhs, ++rhs) {
68 if (*lhs != *rhs) {
69 break;
70 }
71 }
72 return static_cast<int>(*lhs) - static_cast<int>(*rhs);
73}
74
75template <typename CharT, typename SizeT>
76[[nodiscard]] constexpr auto strncmp(CharT const* lhs, CharT const* rhs, SizeT const count) -> int
77{
78 CharT u1{};
79 CharT u2{};
80
81 auto localCount = count;
82 while (localCount-- > 0) {
83 u1 = static_cast<CharT>(*lhs++);
84 u2 = static_cast<CharT>(*rhs++);
85 if (u1 != u2) {
86 return static_cast<int>(u1 - u2);
87 }
88 if (u1 == CharT(0)) {
89 return 0;
90 }
91 }
92
93 return 0;
94}
95
96template <typename CharT>
97[[nodiscard]] constexpr auto strchr(CharT* str, int ch) -> CharT*
98{
99 while (*str != CharT(0)) {
100 if (*str == static_cast<CharT>(ch)) {
101 return str;
102 }
103 ++str;
104 }
105
106 if (static_cast<CharT>(ch) == CharT(0)) {
107 return str;
108 }
109 return nullptr;
110}
111
112template <typename CharT, typename SizeT>
113[[nodiscard]] constexpr auto strrchr(CharT* str, int ch) -> CharT*
114{
115 if (str == nullptr) {
116 return nullptr;
117 }
118 auto len = strlen<CharT, SizeT>(str);
119 if (static_cast<CharT>(ch) == CharT(0)) {
120 return str + len;
121 }
122
123 while (len-- != 0) {
124 if (str[len] == static_cast<CharT>(ch)) {
125 return str + len;
126 }
127 }
128
129 return nullptr;
130}
131
132template <typename CharT, typename SizeT, bool InclusiveSearch>
133[[nodiscard]] constexpr auto is_legal_char(CharT const* options, SizeT len, CharT ch) noexcept -> bool
134{
135 for (SizeT i = 0; i < len; ++i) {
136 if (options[i] == ch) {
137 return InclusiveSearch;
138 }
139 }
140 return !InclusiveSearch;
141}
142
143template <typename CharT, typename SizeT, bool InclusiveSearch>
144[[nodiscard]] constexpr auto strspn(CharT const* dest, CharT const* src) noexcept -> SizeT
145{
146 auto result = SizeT{0};
147 auto const length = strlen<CharT, SizeT>(dest);
148 auto const srcLen = strlen<CharT, SizeT>(src);
149 for (SizeT i = 0; i < length; ++i) {
150 if (!is_legal_char<CharT, SizeT, InclusiveSearch>(src, srcLen, dest[i])) {
151 break;
152 }
153 ++result;
154 }
155
156 return result;
157}
158
159template <typename CharT, typename SizeT>
160[[nodiscard]] constexpr auto strpbrk_impl(CharT* s, CharT* del) noexcept -> CharT*
161{
162 auto const i = strspn<CharT, SizeT, false>(s, del);
163 if (i != 0) {
164 return s + i;
165 }
166 if (is_legal_char<CharT, SizeT, true>(del, strlen<CharT, SizeT>(del), s[0])) {
167 return s;
168 }
169 return nullptr;
170}
171
172template <typename CharT>
173[[nodiscard]] constexpr auto strstr_impl(CharT* haystack, CharT* needle) noexcept -> CharT*
174{
175 while (*haystack != CharT(0)) {
176 if ((*haystack == *needle) && (strcmp(haystack, needle) == 0)) {
177 return haystack;
178 }
179 haystack++;
180 }
181 return nullptr;
182}
183
184template <typename CharT, typename SizeT>
185constexpr auto memcpy(void* dest, void const* src, SizeT n) -> void*
186{
187 auto* dp = static_cast<CharT*>(dest);
188 auto const* sp = static_cast<CharT const*>(src);
189 while (n-- != CharT(0)) {
190 *dp++ = *sp++;
191 }
192 return dest;
193}
194
195template <typename CharT, typename ValT, typename SizeT>
196constexpr auto memset(CharT* const s, ValT const c, SizeT n) -> CharT*
197{
198 auto* p = s;
199 while (n-- != CharT(0)) {
200 *p++ = static_cast<CharT>(c);
201 }
202 return s;
203}
204
205// Check original implementation. They use `__np_anyptrlt` which is not
206// portable. https://clc-wiki.net/wiki/C_standard_library:string.h:memmove
207template <typename CharT, typename SizeT>
208constexpr auto memmove(void* dest, void const* src, SizeT n) -> CharT*
209{
210 auto const* ps = static_cast<CharT const*>(src);
211 auto* pd = static_cast<CharT*>(dest);
212
213 if (ps < pd) {
214 for (pd += n, ps += n; n-- != CharT(0);) {
215 *--pd = *--ps;
216 }
217 } else {
218 while (n-- != CharT(0)) {
219 *pd++ = *ps++;
220 }
221 }
222
223 return static_cast<CharT*>(dest);
224}
225
226template <typename CharT, typename SizeT>
227constexpr auto memchr(CharT* ptr, CharT ch, SizeT n) -> CharT*
228{
229 for (SizeT i{0}; i != n; ++i) {
230 if (ptr[i] == ch) {
231 return ptr + i;
232 }
233 }
234 return nullptr;
235}
236
237} // namespace etl::detail
238
239#endif // TETL_CSTRING_ALGORITHM_HPP
Definition adjacent_find.hpp:9