1 /* ///////////////////////////////////////////////////////////////////////
2 * File: string_traits.h
7 * Brief: string_traits class
9 * Note: Make full use of string_traits class, not std_char_traits
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
23 # error string_traits.h need be supported by c++.
26 /* ///////////////////////////////////////////////////////////////////////
30 #include "std/char_traits.h"
31 #include "../algorithm/algorithm.h"
32 #include "../type/traits/is_unsigned.h"
34 /* ///////////////////////////////////////////////////////////////////////
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
>
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
;
68 /// Evaluate whether c is null-terminator
69 static e_bool_t
is_nt(const_reference c
)
71 return eq(c
, char_type('\0'));
75 static e_bool_t
eq(const_reference lhs
, const_reference rhs
)
77 return char_traits_type::eq(lhs
, rhs
);
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);
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);
103 static const_pointer
assign(pointer dest
, const_reference c
, size_type n
)
105 return char_traits_type::assign(dest
, n
, c
);
108 static const_pointer
copy(pointer dest
, const_pointer src
, size_type n
)
110 return char_traits_type::copy(dest
, src
, n
);
114 static const_pointer
copy(pointer dest
, const_pointer src
)
116 EXTL_ASSERT(NULL
!= dest
);
117 EXTL_ASSERT(NULL
!= src
);
120 for(; !is_nt(*src
); ++dest
, ++src
)
122 char_traits_type::assign(*dest
, *src
);
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
)
145 const_pointer p1
= s
+ pos
;
147 /* Finds the position of the first character of the string sub in the s */
149 while(p2
= find(p1
, num
, *sub
), p2
!=NULL
)
154 /* Compares the whole string */
155 if(!compare(p1
, sub
+ 1, sub_n
- 1)) /* optimization */
156 /* if(!traits_type::compare(p2, sub, sub_n)) */
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
;
175 const_pointer p
= s
+ ((pos
< n
- sub_n
)? pos
: (n
- sub_n
));
179 /* compare(p + 1, sub + 1, sub_n - 1)) */
180 !compare(p
, sub
, sub_n
))
190 static e_int_t
compare(const_pointer lhs
, const_pointer rhs
, size_type n
)
192 return char_traits_type::compare(lhs
, rhs
, n
);
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
)
205 return lt(*lhs
, *rhs
)? -1 : + 1;
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
);
223 return lt(lch
, rch
)? -1 : + 1;
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
);
241 return lt(lch
, rch
)? -1 : + 1;
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
)
263 while(*p
!= char_type('\0'))
271 /// Make upper string
272 static const_pointer
to_upper(pointer s
)
275 while(*p
!= char_type('\0'))
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()
301 /// Returns the empty strig
302 static const_pointer
empty()
304 static const char_type empty_str
[1] = { '\0' };
311 /* ///////////////////////////////////////////////////////////////////////
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 /* ///////////////////////////////////////////////////////////////////////
346 #ifdef EXTL_STRING_STRING_TRAITS_TEST_ENABLE
347 # include "unit_test/string_traits_test.h"
350 /* ///////////////////////////////////////////////////////////////////////
355 /* //////////////////////////////////////////////////////////////////// */
356 #endif /* EXTL_STRING_STRING_TRAITS_H */
357 /* //////////////////////////////////////////////////////////////////// */