Direct-BT  2.3.1
Direct-BT - Direct Bluetooth Programming.
string_util.hpp
Go to the documentation of this file.
1 /*
2  * Author: Sven Gothel <sgothel@jausoft.com>
3  * Copyright (c) 2021 Gothel Software e.K.
4  *
5  * Permission is hereby granted, free of charge, to any person obtaining
6  * a copy of this software and associated documentation files (the
7  * "Software"), to deal in the Software without restriction, including
8  * without limitation the rights to use, copy, modify, merge, publish,
9  * distribute, sublicense, and/or sell copies of the Software, and to
10  * permit persons to whom the Software is furnished to do so, subject to
11  * the following conditions:
12  *
13  * The above copyright notice and this permission notice shall be
14  * included in all copies or substantial portions of the Software.
15  *
16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20  * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21  * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22  * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23  */
24 
25 #ifndef JAU_STRING_UTIL_HPP_
26 #define JAU_STRING_UTIL_HPP_
27 
28 #include <cstdint>
29 #include <cstring>
30 #include <string>
31 #include <memory>
32 #include <type_traits>
33 
34 #include <jau/cpp_lang_util.hpp>
35 #include <jau/packed_attribute.hpp>
37 
38 #include <jau/int_types.hpp>
39 #include <jau/int_math.hpp>
40 
41 namespace jau {
42 
43  /**
44  * Returns a C++ String taken from buffer with maximum length of min(max_len, max_len).
45  * <p>
46  * The maximum length only delimits the string length and does not contain the EOS null byte.
47  * An EOS null byte will will be added.
48  * </p>
49  * <p>
50  * The source string within buffer is not required to contain an EOS null byte;
51  * </p>
52  */
53  std::string get_string(const uint8_t *buffer, nsize_t const buffer_len, nsize_t const max_len) noexcept;
54 
55  /** trim in place */
56  void trimInPlace(std::string &s) noexcept;
57 
58  /** trim copy */
59  std::string trimCopy(const std::string &s) noexcept;
60 
61  /**
62  // *************************************************
63  // *************************************************
64  // *************************************************
65  */
66 
67  /**
68  * Produce a hexadecimal string representation of the given byte values.
69  * <p>
70  * If lsbFirst is true, orders LSB left -> MSB right, usual for byte streams. Result will not have a leading `0x`.<br>
71  * Otherwise orders MSB left -> LSB right, usual for readable integer values. Result will have a leading `0x`.
72  * </p>
73  * @param bytes pointer to the first byte to print, less offset
74  * @param offset offset to bytes pointer to the first byte to print
75  * @param length number of bytes to print
76  * @param lsbFirst true having the least significant byte printed first (lowest addressed byte to highest),
77  * otherwise have the most significant byte printed first (highest addressed byte to lowest).
78  * A leading `0x` will be prepended if `lsbFirst == false`.
79  * @param lowerCase true to use lower case hex-chars, otherwise capital letters are being used.
80  * @return the hex-string representation of the data
81  */
82  std::string bytesHexString(const uint8_t * bytes, const nsize_t offset, const nsize_t length,
83  const bool lsbFirst, const bool lowerCase=true) noexcept;
84 
85  /**
86  * Produce a hexadecimal string representation of the given byte value.
87  * @param dest the std::string reference destination to append
88  * @param value the byte value to represent
89  * @param lowerCase true to use lower case hex-chars, otherwise capital letters are being used.
90  * @return the given std::string reference for chaining
91  */
92  std::string& byteHexString(std::string& dest, const uint8_t value, const bool lowerCase) noexcept;
93 
94  /**
95  * Produce a lower-case hexadecimal string representation of the given pointer.
96  * @tparam value_type a pointer type
97  * @param v the pointer of given pointer type
98  * @return the hex-string representation of the value
99  * @see bytesHexString()
100  */
101  template< class value_type,
102  std::enable_if_t<std::is_pointer_v<value_type>,
103  bool> = true>
104  std::string to_hexstring(value_type const & v) noexcept
105  {
106  const uint64_t v2 = reinterpret_cast<uint64_t>(v);
107  return bytesHexString(pointer_cast<const uint8_t*>(&v2), 0, sizeof(v), false /* lsbFirst */);
108  }
109 
110  /**
111  * Produce a lower-case hexadecimal string representation of the given value with standard layout.
112  * @tparam value_type a standard layout value type
113  * @param v the value of given standard layout type
114  * @return the hex-string representation of the value
115  * @see bytesHexString()
116  */
117  template< class value_type,
118  std::enable_if_t<!std::is_pointer_v<value_type> &&
119  std::is_standard_layout_v<value_type>,
120  bool> = true>
121  std::string to_hexstring(value_type const & v) noexcept
122  {
123  return bytesHexString(pointer_cast<const uint8_t*>(&v), 0, sizeof(v), false /* lsbFirst */);
124  }
125 
126  /**
127  // *************************************************
128  // *************************************************
129  // *************************************************
130  */
131 
132  /**
133  * Produce a decimal string representation of an integral integer value.
134  * @tparam T an integral integer type
135  * @param v the integral integer value
136  * @param separator if not 0, use as separation character, otherwise no separation characters are being used
137  * @param width the minimum number of characters to be printed. Add padding with blank space if result is shorter.
138  * @return the string representation of the integral integer value
139  */
140  template< class value_type,
141  std::enable_if_t< std::is_integral_v<value_type>,
142  bool> = true>
143  std::string to_decstring(const value_type& v, const char separator=',', const nsize_t width=0) noexcept {
144  const snsize_t v_sign = jau::sign<value_type>(v);
145  const nsize_t digit10_count1 = jau::digits10<value_type>(v, v_sign, true /* sign_is_digit */);
146  const nsize_t digit10_count2 = v_sign < 0 ? digit10_count1 - 1 : digit10_count1; // less sign
147 
148  const nsize_t comma_count = 0 == separator ? 0 : ( digit10_count1 - 1 ) / 3;
149  const nsize_t net_chars = digit10_count1 + comma_count;
150  const nsize_t total_chars = std::max<nsize_t>(width, net_chars);
151  std::string res(total_chars, ' ');
152 
153  value_type n = v;
154  nsize_t char_iter = 0;
155 
156  for(nsize_t digit10_iter = 0; digit10_iter < digit10_count2 /* && char_iter < total_chars */; digit10_iter++ ) {
157  const int digit = v_sign < 0 ? invert_sign( n % 10 ) : n % 10;
158  n /= 10;
159  if( 0 < digit10_iter && 0 == digit10_iter % 3 ) {
160  res[total_chars-1-(char_iter++)] = separator;
161  }
162  res[total_chars-1-(char_iter++)] = '0' + digit;
163  }
164  if( v_sign < 0 /* && char_iter < total_chars */ ) {
165  res[total_chars-1-(char_iter++)] = '-';
166  }
167  return res;
168  }
169 
170  /**
171  // *************************************************
172  // *************************************************
173  // *************************************************
174  */
175 
176  template< class value_type,
177  std::enable_if_t< std::is_integral_v<value_type> ||
178  std::is_floating_point_v<value_type>,
179  bool> = true>
180  std::string to_string(const value_type & ref)
181  {
182  return std::to_string(ref);
183  }
184  template< class value_type,
185  std::enable_if_t<!std::is_integral_v<value_type> &&
186  !std::is_floating_point_v<value_type> &&
187  std::is_pointer_v<value_type>,
188  bool> = true>
189  std::string to_string(const value_type & ref)
190  {
191  return to_hexstring((void*)ref);
192  }
193 
194  template< class value_type,
195  std::enable_if_t<!std::is_integral_v<value_type> &&
196  !std::is_floating_point_v<value_type> &&
197  !std::is_pointer_v<value_type> &&
198  jau::has_toString_v<value_type>,
199  bool> = true>
200  std::string to_string(const value_type & ref) {
201  return ref.toString();
202  }
203 
204  template< class value_type,
205  std::enable_if_t<!std::is_integral_v<value_type> &&
206  !std::is_floating_point_v<value_type> &&
207  !std::is_pointer_v<value_type> &&
208  !jau::has_toString_v<value_type> &&
209  jau::has_to_string_v<value_type>,
210  bool> = true>
211  std::string to_string(const value_type & ref) {
212  return ref.to_string();
213  }
214 
215  template< class value_type,
216  std::enable_if_t<!std::is_integral_v<value_type> &&
217  !std::is_floating_point_v<value_type> &&
218  !std::is_pointer_v<value_type> &&
219  !jau::has_toString_v<value_type> &&
220  !jau::has_to_string_v<value_type> &&
221  jau::has_member_of_pointer_v<value_type>,
222  bool> = true>
223  std::string to_string(const value_type & ref) {
224  return to_hexstring((void*)ref.operator->());
225  }
226 
227  template< class value_type,
228  std::enable_if_t<!std::is_integral_v<value_type> &&
229  !std::is_floating_point_v<value_type> &&
230  !std::is_pointer_v<value_type> &&
231  !jau::has_toString_v<value_type> &&
232  !jau::has_to_string_v<value_type> &&
233  !jau::has_member_of_pointer_v<value_type>,
234  bool> = true>
235  std::string to_string(const value_type & ref) {
236  (void)ref;
237  return "jau::to_string<T> not available for "+type_cue<value_type>::print("unknown", TypeTraitGroup::ALL);
238  }
239 
240 } // namespace jau
241 
242 /** \example test_intdecstring01.cpp
243  * This C++ unit test validates the jau::to_decstring implementation
244  */
245 
246 #endif /* JAU_STRING_UTIL_HPP_ */
jau::trimInPlace
void trimInPlace(std::string &s) noexcept
trim in place
Definition: basic_types.cpp:77
jau::bytesHexString
std::string bytesHexString(const uint8_t *bytes, const nsize_t offset, const nsize_t length, const bool lsbFirst, const bool lowerCase=true) noexcept
Produce a hexadecimal string representation of the given byte values.
Definition: basic_types.cpp:167
jau::to_decstring
std::string to_decstring(const value_type &v, const char separator=',', const nsize_t width=0) noexcept
Produce a decimal string representation of an integral integer value.
Definition: string_util.hpp:143
jau::get_string
std::string get_string(const uint8_t *buffer, nsize_t const buffer_len, nsize_t const max_len) noexcept
Returns a C++ String taken from buffer with maximum length of min(max_len, max_len).
Definition: basic_types.cpp:69
packed_attribute.hpp
jau::type_cue::print
static void print(const std::string &typedefname, const TypeTraitGroup verbosity=TypeTraitGroup::NONE)
Print information of this type to stdout, potentially with all Type traits known.
Definition: type_traits_queries.hpp:135
jau::invert_sign
constexpr T invert_sign(const T x) noexcept
Safely inverts the sign of an integral number.
Definition: int_math.hpp:85
jau::to_string
std::string to_string(const value_type &ref)
Definition: string_util.hpp:180
jau
Definition: basic_algos.hpp:34
int_math.hpp
jau::to_string
PRAGMA_DISABLE_WARNING_POP constexpr_cxx20 std::string to_string(const endian &v) noexcept
Return std::string representation of the given jau::endian.
Definition: byte_util.hpp:198
jau::byteHexString
std::string & byteHexString(std::string &dest, const uint8_t value, const bool lowerCase) noexcept
Produce a hexadecimal string representation of the given byte value.
Definition: basic_types.cpp:203
type_traits_queries.hpp
jau::TypeTraitGroup::ALL
@ ALL
ALL.
jau::to_hexstring
std::string to_hexstring(value_type const &v) noexcept
Produce a lower-case hexadecimal string representation of the given pointer.
Definition: string_util.hpp:104
jau::snsize_t
int_fast32_t snsize_t
Natural 'ssize_t' alternative using int_fast32_t as its natural sized type.
Definition: int_types.hpp:56
jau::nsize_t
uint_fast32_t nsize_t
Natural 'size_t' alternative using uint_fast32_t as its natural sized type.
Definition: int_types.hpp:44
cpp_lang_util.hpp
int_types.hpp
jau::trimCopy
std::string trimCopy(const std::string &s) noexcept
trim copy
Definition: basic_types.cpp:86