Embedded Template Library 1.0
Loading...
Searching...
No Matches
to_string_helper.h
Go to the documentation of this file.
1
2
3/******************************************************************************
4The MIT License(MIT)
5
6Embedded Template Library.
7https://github.com/ETLCPP/etl
8https://www.etlcpp.com
9
10Copyright(c) 2019 John Wellbelove
11
12Permission is hereby granted, free of charge, to any person obtaining a copy
13of this software and associated documentation files(the "Software"), to deal
14in the Software without restriction, including without limitation the rights
15to use, copy, modify, merge, publish, distribute, sublicense, and / or sell
16copies of the Software, and to permit persons to whom the Software is
17furnished to do so, subject to the following conditions :
18
19The above copyright notice and this permission notice shall be included in all
20copies or substantial portions of the Software.
21
22THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
23IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
24FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
25AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
26LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
27OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
28SOFTWARE.
29******************************************************************************/
30
31#ifndef ETL_TO_STRING_HELPER_INCLUDED
32#define ETL_TO_STRING_HELPER_INCLUDED
33
35
36#include "../platform.h"
37#include "../absolute.h"
38#include "../negative.h"
39#include "../basic_format_spec.h"
40#include "../type_traits.h"
41#include "../container.h"
42#include "../absolute.h"
43#include "../algorithm.h"
44#include "../iterator.h"
45#include "../limits.h"
46
47#include <math.h>
48
49#if ETL_USING_STL && ETL_USING_CPP11
50 #include <iterator> // For std::begin, std::end and std::size
51#endif
52
53namespace etl
54{
55 namespace private_to_string
56 {
57#if ETL_NOT_USING_64BIT_TYPES
58 typedef int32_t workspace_t;
59 typedef uint32_t uworkspace_t;
60#else
61 typedef int64_t workspace_t;
62 typedef uint64_t uworkspace_t;
63#endif
64
65 //***************************************************************************
67 //***************************************************************************
68 template <typename TIString>
69 void add_alignment(TIString& str, typename TIString::iterator position, const etl::basic_format_spec<TIString>& format)
70 {
71 uint32_t length = static_cast<uint32_t>(etl::distance(position, str.end()));
72
73 if (length < format.get_width())
74 {
75 uint32_t fill_length = format.get_width() - length;
76
77 if (format.is_left())
78 {
79 // Insert fill characters on the right.
80 str.insert(str.end(), fill_length, format.get_fill());
81 }
82 else
83 {
84 // Insert fill characters on the left.
85 str.insert(position, fill_length, format.get_fill());
86 }
87 }
88 }
89
90 //***************************************************************************
92 //***************************************************************************
93 template <typename TIString>
94 void add_boolean(const bool value,
95 TIString& str,
97 const bool append)
98 {
99 typedef typename TIString::value_type type;
100 typedef typename TIString::iterator iterator;
101
102 static const type t[] = { 't', 'r', 'u', 'e' };
103 static const type f[] = { 'f', 'a', 'l', 's', 'e' };
104
105 if (!append)
106 {
107 str.clear();
108 }
109
110 iterator start = str.end();
111
112 if (format.is_boolalpha())
113 {
114 if (value)
115 {
116 str.insert(str.end(), ETL_OR_STD11::begin(t), ETL_OR_STD11::end(t));
117 }
118 else
119 {
120 str.insert(str.end(), ETL_OR_STD11::begin(f), ETL_OR_STD11::end(f));
121 }
122 }
123 else
124 {
125 if (value)
126 {
127 str.push_back(type('1'));
128 }
129 else
130 {
131 str.push_back(type('0'));
132 }
133 }
134
136 }
137
138 //***************************************************************************
140 //***************************************************************************
141 template <typename T, typename TIString>
142 void add_integral(T value,
143 TIString& str,
145 bool append,
146 const bool negative)
147 {
148 typedef typename TIString::value_type type;
149 typedef typename TIString::iterator iterator;
150
151 if (!append)
152 {
153 str.clear();
154 }
155
156 iterator start = str.end();
157
158 if (value == 0)
159 {
160 // If number is negative, append '-' (a negative zero might occur for fractional numbers > -1.0)
161 if ((format.get_base() == 10U) && negative)
162 {
163 str.push_back(type('-'));
164 }
165
166 str.push_back(type('0'));
167 }
168 else
169 {
170 // Extract the digits, in reverse order.
171 while (value != 0)
172 {
173 T remainder = etl::absolute(value % T(format.get_base()));
174 str.push_back((remainder > 9) ? (format.is_upper_case() ? type('A' + (remainder - 10)) : type('a' + (remainder - 10))) : type('0' + remainder));
175 value = value / T(format.get_base());
176 }
177
178 // If number is negative, append '-'
179 if ((format.get_base() == 10U) && negative)
180 {
181 str.push_back(type('-'));
182 }
183
184 if (format.is_show_base())
185 {
186 switch (format.get_base())
187 {
188 case 2U:
189 {
190 str.push_back(format.is_upper_case() ? type('B') : type('b'));
191 str.push_back(type('0'));
192 break;
193 }
194
195 case 8U:
196 {
197 str.push_back(type('0'));
198 break;
199 }
200
201 case 16U:
202 {
203 str.push_back(format.is_upper_case() ? type('X') : type('x'));
204 str.push_back(type('0'));
205 break;
206 }
207
208 default:
209 {
210 break;
211 }
212 }
213 }
214
215 // Reverse the string we appended.
216 etl::reverse(start, str.end());
217 }
218
220 }
221
222 //***************************************************************************
224 //***************************************************************************
225 template <typename TIString>
226 void add_nan_inf(const bool not_a_number,
227 const bool infinity,
228 TIString& str)
229 {
230 typedef typename TIString::value_type type;
231
232 static const type n[] = { 'n', 'a', 'n' };
233 static const type i[] = { 'i', 'n', 'f' };
234
235 if (not_a_number)
236 {
237 str.insert(str.end(), ETL_OR_STD11::begin(n), ETL_OR_STD11::end(n));
238 }
239 else if (infinity)
240 {
241 str.insert(str.end(), ETL_OR_STD11::begin(i), ETL_OR_STD11::end(i));
242 }
243 }
244
245 //***************************************************************************
247 //***************************************************************************
248 template <typename TIString>
250 const uint32_t fractional,
251 TIString& str,
254 const bool negative)
255 {
256 typedef typename TIString::value_type type;
257
259
260 if (fractional_format.get_precision() > 0)
261 {
262 str.push_back(type('.'));
264 }
265 }
266
267#if ETL_USING_64BIT_TYPES
268 //***************************************************************************
270 //***************************************************************************
271 template <typename TIString>
273 const uint64_t fractional,
274 TIString& str,
277 const bool negative)
278 {
279 typedef typename TIString::value_type type;
280
282
283 if (fractional_format.get_precision() > 0)
284 {
285 str.push_back(type('.'));
287 }
288 }
289#endif
290
291 //***************************************************************************
293 //***************************************************************************
294 template <typename T, typename TIString>
295 void add_floating_point(const T value,
296 TIString& str,
298 const bool append)
299 {
300 typedef typename TIString::iterator iterator;
301 typedef typename TIString::value_type type;
302
303 if (!append)
304 {
305 str.clear();
306 }
307
308 iterator start = str.end();
309
310 if (isnan(value) || isinf(value))
311 {
313 }
314 else
315 {
316 // Make sure we format the two halves correctly.
318
319#if ETL_NOT_USING_64BIT_TYPES
320 if (max_precision > 9)
321 {
322 max_precision = 9;
323 }
324#endif
325
327 integral_format.decimal().width(0).precision(format.get_precision() > max_precision ? max_precision : format.get_precision());
328
330 fractional_format.width(integral_format.get_precision()).fill(type('0')).right();
331
332 uworkspace_t multiplier = 1U;
333
334 for (uint32_t i = 0U; i < fractional_format.get_precision(); ++i)
335 {
336 multiplier *= 10U;
337 }
338
339 // Find the integral part of the floating point
340 T f_integral = floor(etl::absolute(value));
342
343 // Find the fractional part of the floating point.
344 uworkspace_t fractional = static_cast<uworkspace_t>(round((etl::absolute(value) - f_integral) * multiplier));
345
346 // Check for a rounding carry to the integral.
347 if (fractional == multiplier)
348 {
349 ++integral;
350 fractional = 0U;
351 }
352
354 }
355
357 }
358
359 //***************************************************************************
361 //***************************************************************************
362 template <typename T, typename TIString>
363 void add_integral_denominated(const T value,
365 TIString& str,
367 const bool append = false)
368 {
369 typedef typename TIString::iterator iterator;
370 typedef typename TIString::value_type type;
371 typedef typename etl::make_unsigned<T>::type working_t;
372
373 if (!append)
374 {
375 str.clear();
376 }
377
378 iterator start = str.end();
379
380 // Calculate the denominator.
382
383 for (uint32_t i = 0U; i < denominator_exponent; ++i)
384 {
385 denominator *= 10U;
386 }
387
388 // Get the absolute value, taking care of minimum negative values.
389 working_t abs_value = etl::absolute_unsigned(value);
390
391 // Figure out how many decimal digits we have in the value.
393
394 // How many decimal digits are we displaying.
396
397 // Format for the integral part.
399 integral_format.decimal().width(0U);
400
401 // Format for the fractional part.
403 fractional_format.precision(displayed_decimal_digits).width(displayed_decimal_digits).fill(type('0')).right();
404
405 // Do we need to check for rounding?
407 {
408 // Which digit to adjust?
410
411 // The 'round-away-from-zero' value.
412 uint32_t rounding = 5U;
413
414 while (count-- > 1U)
415 {
416 rounding *= 10U;
417 }
418
420 }
421
422 // Split the value into integral and fractional.
425
426 // Move the fractional part to the right place.
428 while (count-- > 0U)
429 {
430 fractional /= 10U;
431 }
432
433 // Create the string.
436 }
437
438 //***************************************************************************
440 //***************************************************************************
441 template <typename TIString>
442 void add_pointer(const volatile void* value,
443 TIString& str,
445 const bool append)
446 {
447 uintptr_t p = reinterpret_cast<uintptr_t>(value);
448
449 return etl::private_to_string::add_integral(p, str, format, append, false);
450 }
451
452 //***************************************************************************
454 //***************************************************************************
455 template <typename TIString>
456 void add_string(const TIString& value,
457 TIString& str,
459 const bool append)
460 {
461 if (!append)
462 {
463 str.clear();
464 }
465
466 typename TIString::iterator start = str.end();
467
468 str.insert(str.end(), value.begin(), value.end());
469
471 }
472
473 //***************************************************************************
475 //***************************************************************************
476 template <typename TSringView, typename TIString>
477 void add_string_view(const TSringView& value,
478 TIString& str,
480 const bool append)
481 {
482 if (!append)
483 {
484 str.clear();
485 }
486
487 typename TIString::iterator start = str.end();
488
489 str.insert(str.end(), value.begin(), value.end());
490
492 }
493
494 //*********************************************************************************************************
495
496 //***************************************************************************
498 //***************************************************************************
499 template <typename TIString>
500 const TIString& to_string(const bool value,
501 TIString& str,
503 const bool append = false)
504 {
505 etl::private_to_string::add_boolean(value, str, format, append);
506
507 return str;
508 }
509
510 //***************************************************************************
512 //***************************************************************************
513 template <typename TIString>
514 const TIString& to_string(const volatile void* value,
515 TIString& str,
517 const bool append = false)
518 {
519 etl::private_to_string::add_pointer(value, str, format, append);
520
521 return str;
522 }
523
524#if ETL_USING_64BIT_TYPES
525 //***************************************************************************
527 //***************************************************************************
528 template <typename T, typename TIString>
532 to_string(const T value, TIString& str, const etl::basic_format_spec<TIString>& format, const bool append = false)
533 {
534 typedef typename etl::conditional<etl::is_signed<T>::value, int32_t, uint32_t>::type type;
535
536 etl::private_to_string::add_integral(type(value), str, format, append, etl::is_negative(value));
537
538 return str;
539 }
540
541 //***************************************************************************
543 //***************************************************************************
544 template <typename T, typename TIString>
548 to_string(const T value, TIString& str, const etl::basic_format_spec<TIString>& format, const bool append = false)
549 {
550 etl::private_to_string::add_integral(value, str, format, append, etl::is_negative(value));
551
552 return str;
553 }
554
555 //***************************************************************************
557 //***************************************************************************
558 template <typename T, typename TIString>
562 to_string(const T value, uint32_t denominator_exponent, TIString& str, const etl::basic_format_spec<TIString>& format, const bool append = false)
563 {
564 typedef typename etl::conditional<etl::is_signed<T>::value, int32_t, uint32_t>::type type;
565
567
568 return str;
569 }
570
571 //***************************************************************************
573 //***************************************************************************
574 template <typename T, typename TIString>
578 to_string(const T value, uint32_t denominator_exponent, TIString& str, const etl::basic_format_spec<TIString>& format, const bool append = false)
579 {
581
582 return str;
583 }
584#else
585 //***************************************************************************
587 //***************************************************************************
588 template <typename T, typename TIString>
590 !etl::is_same<T, bool>::value>::value, const TIString& > ::type
591 to_string(const T value, TIString& str, const etl::basic_format_spec<TIString>& format, const bool append = false)
592 {
593 typedef typename etl::conditional<etl::is_signed<T>::value, int32_t, uint32_t>::type type;
594
595 etl::private_to_string::add_integral(type(value), str, format, append, false);
596
597 return str;
598 }
599
600 //***************************************************************************
602 //***************************************************************************
603 template <typename T, typename TIString>
605 !etl::is_same<T, bool>::value>::value, const TIString& > ::type
606 to_string(const T value, uint32_t denominator_exponent, TIString& str, const etl::basic_format_spec<TIString>& format, const bool append = false)
607 {
608 etl::private_to_string::add_integral_denominated(type(value), denominator_exponent, str, format, append, false);
609
610 return str;
611 }
612#endif
613
614 //***************************************************************************
616 //***************************************************************************
617 template <typename T, typename TIString>
618 typename etl::enable_if<etl::is_floating_point<T>::value, const TIString&>::type
619 to_string(const T value, TIString& str, const etl::basic_format_spec<TIString>& format, const bool append = false)
620 {
622
623 return str;
624 }
625 }
626}
627
628#endif
Definition limits.h:1164
add_pointer
Definition type_traits_generator.h:898
is_same
Definition type_traits_generator.h:1041
bitset_ext
Definition absolute.h:38
Definition type_traits.h:1376
iterator
Definition iterator.h:399
pair holds two objects of arbitrary type
Definition utility.h:164
void add_alignment(TIString &str, typename TIString::iterator position, const etl::basic_format_spec< TIString > &format)
Helper function for left/right alignment.
Definition to_string_helper.h:69
void add_floating_point(const T value, TIString &str, const etl::basic_format_spec< TIString > &format, const bool append)
Helper function for floating point.
Definition to_string_helper.h:295
void add_string(const TIString &value, TIString &str, const etl::basic_format_spec< TIString > &format, const bool append)
Helper function for strings.
Definition to_string_helper.h:456
void add_integral_denominated(const T value, const uint32_t denominator_exponent, TIString &str, const etl::basic_format_spec< TIString > &format, const bool append=false)
Helper function for denominated integers.
Definition to_string_helper.h:363
void add_nan_inf(const bool not_a_number, const bool infinity, TIString &str)
Helper function for floating point nan and inf.
Definition to_string_helper.h:226
void add_integral_and_fractional(const uint32_t integral, const uint32_t fractional, TIString &str, const etl::basic_format_spec< TIString > &integral_format, const etl::basic_format_spec< TIString > &fractional_format, const bool negative)
Helper function for floating point integral and fractional.
Definition to_string_helper.h:249
const TIString & to_string(const bool value, TIString &str, const etl::basic_format_spec< TIString > &format, const bool append=false)
For booleans.
Definition to_string_helper.h:500
void add_integral(T value, TIString &str, const etl::basic_format_spec< TIString > &format, bool append, const bool negative)
Helper function for integrals.
Definition to_string_helper.h:142
void add_string_view(const TSringView &value, TIString &str, const etl::basic_format_spec< TIString > &format, const bool append)
Helper function for string views.
Definition to_string_helper.h:477
void add_pointer(const volatile void *value, TIString &str, const etl::basic_format_spec< TIString > &format, const bool append)
Helper function for pointers.
Definition to_string_helper.h:442
void add_boolean(const bool value, TIString &str, const etl::basic_format_spec< TIString > &format, const bool append)
Helper function for booleans.
Definition to_string_helper.h:94