remove \r
[extl.git] / extl / string / string_traits.h
blobe6372c51738b591d09ed73a24e86c786348ee1f9
1 /* ///////////////////////////////////////////////////////////////////////
2 * File: string_traits.h
4 * Created: 08.04.11
5 * Updated: 08.04.14
7 * Brief: string_traits class
9 * Note: Make full use of string_traits class, not std_char_traits
11 * [<Home>]
12 * Copyright (c) 2008-2020, Waruqi All rights reserved.
13 * //////////////////////////////////////////////////////////////////// */
15 #ifndef EXTL_STRING_STRING_TRAITS_H
16 #define EXTL_STRING_STRING_TRAITS_H
18 /*!\file string_traits.h
19 * \brief string_traits class
22 #ifndef __cplusplus
23 # error string_traits.h need be supported by c++.
24 #endif
26 /* ///////////////////////////////////////////////////////////////////////
27 * Includes
29 #include "prefix.h"
30 #include "std/char_traits.h"
31 #include "../algorithm/algorithm.h"
32 #include "../type/traits/is_unsigned.h"
34 /* ///////////////////////////////////////////////////////////////////////
35 * ::extl namespace
37 EXTL_BEGIN_NAMESPACE
39 /*!\brief string_traits class
41 * \param C the character type
42 * \param T the char_traits type
44 * \ingroup extl_group_string
46 template< typename_param_k C
47 #ifdef EXTL_TEMPLATE_CLASS_DEFAULT_ARGUMENT_SUPPORT
48 , typename_param_k T = std_char_traits<C>
49 #else
50 , typename_param_k T
51 #endif
53 struct string_traits
55 public:
56 typedef string_traits<C, T> class_type;
57 typedef T char_traits_type;
58 typedef typename_type_k char_traits_type::char_type char_type;
59 typedef char_type value_type;
60 typedef value_type* pointer;
61 typedef value_type const* const_pointer;
62 typedef value_type& reference;
63 typedef value_type const& const_reference;
64 typedef typename_type_k char_traits_type::size_type size_type;
65 typedef typename_type_k char_traits_type::int_type int_type;
67 public:
68 /// Evaluate whether c is null-terminator
69 static e_bool_t is_nt(const_reference c)
71 return eq(c, char_type('\0'));
74 /// Compare string
75 static e_bool_t eq(const_reference lhs, const_reference rhs)
77 return char_traits_type::eq(lhs, rhs);
80 /// Less than
81 static e_bool_t lt(const_reference lhs, const_reference rhs)
83 return char_traits_type::lt(lhs, rhs);
86 /// Make the lower character
87 static char_type to_lower(const_reference c)
89 if((char_type('A') <= c) && (c <= char_type('Z')))
90 return static_cast<char_type>(static_cast<e_int_t>(c) + 32);
91 else return c;
94 /// Make the upper character
95 static char_type to_upper(const_reference c)
97 if((char_type('a') <= c) && (c <= char_type('z')))
98 return static_cast<char_type>(static_cast<e_int_t>(c) - 32);
99 else return c;
102 /// Assignment
103 static const_pointer assign(pointer dest, const_reference c, size_type n)
105 return char_traits_type::assign(dest, n, c);
107 /// Copy string
108 static const_pointer copy(pointer dest, const_pointer src, size_type n)
110 return char_traits_type::copy(dest, src, n);
113 /// Copy string
114 static const_pointer copy(pointer dest, const_pointer src)
116 EXTL_ASSERT(NULL != dest);
117 EXTL_ASSERT(NULL != src);
119 pointer ret = dest;
120 for(; !is_nt(*src); ++dest, ++src)
122 char_traits_type::assign(*dest, *src);
124 return ret;
127 /// Finds the given character with value c from the given string
128 static const_pointer find(const_pointer s, size_type n, const_reference c)
130 return char_traits_type::find(s, n, c);
133 /// Finds the given string from the given string at the specified position
134 static size_type find(const_pointer s, size_type n, size_type pos, const_pointer sub, size_type sub_n)
136 EXTL_ASSERT(NULL != s);
137 EXTL_ASSERT(NULL != sub);
138 if(NULL == s) return fof();
139 if(NULL == sub || 0 == sub_n) return (pos <= n)? pos : n;
141 size_type num = n - pos;
142 if(pos < n && sub_n <= num)
144 num -= sub_n - 1;
145 const_pointer p1 = s + pos;
147 /* Finds the position of the first character of the string sub in the s */
148 const_pointer p2;
149 while(p2 = find(p1, num, *sub), p2 !=NULL)
151 num -= p2 - p1 + 1;
152 p1 = p2 + 1;
154 /* Compares the whole string */
155 if(!compare(p1, sub + 1, sub_n - 1)) /* optimization */
156 /* if(!traits_type::compare(p2, sub, sub_n)) */
157 return (p2 - s);
160 return fof();
162 /// Reversely finds the given string from the given string at the specified position
163 static size_type rfind(const_pointer s, size_type n, size_type rpos, const_pointer sub, size_type sub_n)
165 EXTL_ASSERT(NULL != s);
166 EXTL_ASSERT(NULL != sub);
167 if(NULL == s) return fof();
169 /* compute position from the given reverse position */
170 size_type pos = n - rpos;
171 if(NULL == sub || 0 == sub_n) return (pos < n)? pos : n;
173 if(sub_n <= n)
175 const_pointer p = s + ((pos < n - sub_n)? pos : (n - sub_n));
176 while(p != s)
178 if(eq(*p, *sub) &&
179 /* compare(p + 1, sub + 1, sub_n - 1)) */
180 !compare(p, sub, sub_n))
181 return p - s;
182 --p;
185 return fof();
189 /// Compare string
190 static e_int_t compare(const_pointer lhs, const_pointer rhs, size_type n)
192 return char_traits_type::compare(lhs, rhs, n);
195 /// Compare string
196 static e_int_t compare(const_pointer lhs, const_pointer rhs)
198 EXTL_ASSERT(NULL != lhs);
199 EXTL_ASSERT(NULL != rhs);
201 for(; !is_nt(*lhs) || !is_nt(*rhs); ++lhs, ++rhs)
203 if(!eq(*lhs, *rhs))
205 return lt(*lhs, *rhs)? -1 : + 1;
208 return 0;
211 /// Compare the given n characters string(case-insensitive)
212 static e_int_t compare_nocase(const_pointer lhs, const_pointer rhs, size_type n)
214 EXTL_ASSERT(NULL != lhs);
215 EXTL_ASSERT(NULL != rhs);
217 for(size_type i = 0; i < n; ++i, ++lhs, ++rhs)
219 char_type lch = to_lower(*lhs);
220 char_type rch = to_lower(*rhs);
221 if(!eq(lch, rch))
223 return lt(lch, rch)? -1 : + 1;
226 return 0;
229 /// Compare string(case-insensitive)
230 static e_int_t compare_nocase(const_pointer lhs, const_pointer rhs)
232 EXTL_ASSERT(NULL != lhs);
233 EXTL_ASSERT(NULL != rhs);
235 for(; !is_nt(*lhs) || !is_nt(*rhs); ++lhs, ++rhs)
237 char_type lch = to_lower(*lhs);
238 char_type rch = to_lower(*rhs);
239 if(!eq(lch, rch))
241 return lt(lch, rch)? -1 : + 1;
244 return 0;
247 /// Move string
248 static const_pointer move(pointer dest, const_pointer src, size_type n)
250 return char_traits_type::move(dest, src, n);
253 /// Get the length of the given string
254 static size_type length(const_pointer s)
256 return char_traits_type::length(s);
259 /// Make lower string
260 static const_pointer to_lower(pointer s)
262 pointer p = s;
263 while(*p != char_type('\0'))
265 *p = to_lower(*p);
266 ++p;
268 return s;
271 /// Make upper string
272 static const_pointer to_upper(pointer s)
274 C* p = s;
275 while(*p != char_type('\0'))
277 *p = to_upper(*p);
278 ++p;
280 return s;
283 /// Evaluate whether the given string is empty
284 static e_bool_t is_empty(const_pointer s)
286 return eq(s[0], char_type('\0'));
289 /// The maximum length of character string
290 static size_type max_length()
292 EXTL_MUST_BE_UNSIGNED(size_type);
293 return static_cast<size_type>(-1);
296 /// The failure to find
297 static size_type fof()
299 return max_length();
301 /// Returns the empty strig
302 static const_pointer empty()
304 static const char_type empty_str[1] = { '\0' };
305 return empty_str;
311 /* ///////////////////////////////////////////////////////////////////////
312 * Optimization
314 #if !defined(EXTL_COMPILER_IS_DMC) && \
315 !defined(EXTL_COMPILER_IS_WATCOM)
317 EXTL_TEMPLATE_SPECIALISATION
318 inline e_char_t const* string_traits<e_char_t>::copy(e_char_t* dest, e_char_t const* src)
320 return std_strcpy_a(dest, src);
323 EXTL_TEMPLATE_SPECIALISATION
324 inline e_wchar_t const* string_traits<e_wchar_t>::copy(e_wchar_t* dest, e_wchar_t const* src)
326 return std_strcpy_w(dest, src);
329 EXTL_TEMPLATE_SPECIALISATION
330 inline e_int_t string_traits<e_char_t>::compare(e_char_t const* lhs, e_char_t const* rhs)
332 return std_strcmp_a(lhs, rhs);
334 EXTL_TEMPLATE_SPECIALISATION
335 inline e_int_t string_traits<e_wchar_t>::compare(e_wchar_t const* lhs, e_wchar_t const* rhs)
337 return std_strcmp_w(lhs, rhs);
340 #endif /* !defined(EXTL_COMPILER_IS_DMC) && \
341 !defined(EXTL_COMPILER_IS_WATCOM) */
343 /* ///////////////////////////////////////////////////////////////////////
344 * Unit-testing
346 #ifdef EXTL_STRING_STRING_TRAITS_TEST_ENABLE
347 # include "unit_test/string_traits_test.h"
348 #endif
350 /* ///////////////////////////////////////////////////////////////////////
351 * ::extl namespace
353 EXTL_END_NAMESPACE
355 /* //////////////////////////////////////////////////////////////////// */
356 #endif /* EXTL_STRING_STRING_TRAITS_H */
357 /* //////////////////////////////////////////////////////////////////// */