ALib C++ Library
Library Version: 2412 R0
Documentation generated by doxygen
Loading...
Searching...
No Matches
numberformat.hpp
Go to the documentation of this file.
1//==================================================================================================
2/// \file
3/// This header file is part of module \alib_strings of the \aliblong.
4///
5/// \emoji :copyright: 2013-2024 A-Worx GmbH, Germany.
6/// Published under \ref mainpage_license "Boost Software License".
7//==================================================================================================
8#ifndef HPP_ALIB_STRINGS_NUMBERFORMAT
9#define HPP_ALIB_STRINGS_NUMBERFORMAT 1
10#pragma once
12#if ALIB_ENUMS
13# include "alib/enums/bitwise.hpp"
14#endif
15
16namespace alib { namespace strings {
17
18
19/// Flags used with class \alib{strings;TNumberFormat}.
20/// By default (with construction of an instance of \b TNumberFormat), all flags are unset,
21/// except #ForceDecimalPoint.
22enum class NumberFormatFlags : uint8_t
23{
24 /// If assigned, all flags are unset.
25 NONE = 0,
26
27 /// Denotes if grouping characters are ignored when parsing numbers if they are given
28 /// (not set to \c '\0').
29 /// This applies to all number types.<br>
30 /// Defaults to \c false. If set to \c true, grouping characters are just skipped when
31 /// found while parsing numbers, no matter at which position they occur.
33
34 /// Denotes if grouping characters are written if they are given (not set to \c '\0').
35 /// This applies to all number types.
37
38 /// If \c true, the decimal point of floating point values is written, even if the fractional
39 /// part of the float value is zero. If \c false, in this case the decimal point is omitted.<br>
40 /// Defaults to \c true.
42
43 /// Determines if positive exponent values are prepended with an explicit '+' character when
44 /// written using \alib{strings::detail;WriteFloat}.<br>
45 /// Defaults to \c false, as some systems will not accept a plus sign on the exponent value.
46 /// Note that field \alib{strings;TNumberFormat::PlusSign} is not applicable for exponent numbers.
48
49 /// If this flag ist set, then trailing \c '0' digits in the fractional part of a floating
50 /// point value are not written, even if a \alib{strings;TNumberFormat::FractionalPartWidth}
51 /// is set.
53
54
55 /// If this flag ist set, then leading \c '0' digits and group characters are replaced with
56 /// spaces. This applies to integral values and to the integral part of floating point values,
57 /// in the case that \alib{strings;TNumberFormat::DecMinimumFieldWidth}, respectively
58 /// \alib{strings;TNumberFormat::IntegralPartMinimumWidth}, specifies the output to be wider
59 /// than the number printed.
61
62 /// If \c true, scientific format is always used.<br>
63 /// If \c false (the default), function \alib{strings::detail;WriteFloat} writes scientific
64 /// format only if both fields, \alib{strings;TNumberFormat::IntegralPartMinimumWidth} and
65 /// \alib{strings;TNumberFormat::FractionalPartWidth} are evaluating to \c -1 and only for
66 /// numbers smaller than \c 10E-04 or larger than \c 10E+06.<br>
67 ///
68 /// If one of the fields \alib{strings;TNumberFormat::IntegralPartMinimumWidth} or
69 /// \alib{strings;TNumberFormat::FractionalPartWidth} is set to a positive
70 /// value, these limits get extended. Function \alib{strings::detail;WriteFloat} in this case
71 /// keeps non-scientific notation established if possible.
73
74 /// If \c true, lower case letters \c 'a' - \c 'f' are written.
75 /// Defaults to \c false, which writes upper case letters \c 'A' - \c 'F'.
76 HexLowerCase =128,
77}; // enum class NumberFormatFlags
78
79
80//==================================================================================================
81/// This struct defines flags and values that denote the format of conversion of integer and floating
82/// point values to string representations, as well as the reverse operation, thus the
83/// format expected when parsing numbers from strings.
84///
85/// In namespace #alib::strings::detail, corresponding functions that use an instance of this
86/// type are implemented. However, those functions are not intended for common use.
87/// Instead, the interface of classes
88/// \alib{strings;TString;String},
89/// \alib{strings;TSubstring;Substring},
90/// \alib{strings;TAString;AString} or
91/// \alib{lang::format;Formatter}
92/// are preferred to write and parse numbers. Also those accept an object of this type as parameters.
93///
94/// <b>Defined Singletons and User-Defined Instances:</b><br>
95/// Two static singletons of this class, both initialized with function \alib{Bootstrap},
96/// are defined which can be used wherever a number format object is needed as a parameter:
97/// - #Global: Reflects locale-specific settings.
98///
99/// - #Computational:<br>
100/// Intended to be used for writing and parsing numbers which are readable by software (not
101/// humans). Its decimal point character is set to \c '.', the international standard.
102/// Furthermore no group separators are set for decimal and decimal floating point as well as
103/// for binary, hexadecimal and octal conversions.
104///
105/// Any user-defined object defaults to the computational setting after construction.
106///
107/// <b>Output Formats:</b><br>
108/// The following conversion formats are supported:
109///
110/// - \b Decimal<br>
111/// Supports optional minimum output width with field #DecMinimumFieldWidth,
112/// and definable <em>thousands grouping character</em> with field #ThousandsGroupChar, which can
113/// be activated with field #WriteGroupChars.<br>
114/// Furthermore, the plus-sign can be controlled (#PlusSign) to be either omitted or be anything
115/// defined. Of course, values <c>' '</c> and <c>'+'</c> are reasonable options.
116///
117/// - <b>Binary</b><br>
118/// Binary output supports up to 64 digits and different group separators for nibbles, bytes,
119/// 16-bit words and 32 bit words. (See #BinNibbleGroupChar, #BinByteGroupChar,
120/// #BinWordGroupChar and #BinWord32GroupChar ).<br>
121/// When parsing integers, a customizable literal string defined in #BinLiteralPrefix might be used
122/// to auto-detect binary values.
123///
124/// - <b>Hexadecimal</b><br>
125/// Hexadecimal output supports up to 16 digits (64-bit) and different group separators
126/// for bytes, 16-bit words and 32 bit words. (See #HexByteGroupChar, #HexWordGroupChar,
127/// and #HexWord32GroupChar).
128/// When parsing integers, a customizable literal string defined in #HexLiteralPrefix might be used
129/// to auto-detect hexadecimal values.
130///
131/// - <b>Octal</b><br>
132/// Octal output supports up to 22 digits (64-bit) and different a group separator for groups
133/// of three digits defined with #OctGroupChar.
134/// When parsing integers, a customizable literal string defined in #OctLiteralPrefix might be used
135/// to auto-detect hexadecimal values.
136///
137/// - <b>Floating Point</b><br>
138/// The width of the output is provided in two fields, #IntegralPartMinimumWidth and
139/// #FractionalPartWidth. While the integral part is a minimum width (and nothing is ever cut),
140/// the fractional part denotes a fixed width.
141/// Values with higher fractional precision are rounded accordingly.
142/// Note that the parameter of the interface functions that may override the width, in the floating
143/// point case only affects the minimum width of the integral part.<br>
144/// The integral and fractional part of float values are separated by decimalPointChar.
145/// This field of course has to be different from group separator #ThousandsGroupChar, which can
146/// be activated using field #WriteGroupChars.<br>
147/// Other important fields used for writing and parsing floats are: #ExponentSeparator,
148/// #INFLiteral, #NANLiteral, #WriteExponentPlusSign, and #ForceScientific.
149///
150/// <b>Notes on Writing and Parsing Values:</b><br>
151/// For decimal output, the width (#DecMinimumFieldWidth) is a minimum width. This means, that
152/// bigger numbers are written in a higher width.
153///
154/// \attention
155/// This is \c not true for binary, hexadecimal and octal output. In these formats, the width
156/// provided with fields #BinFieldWidth, #HexFieldWidth and #OctFieldWidth, denote an \b absolute
157/// value. Higher digits of numbers are not written! The advantage of this design is that no
158/// masking is needed when just the lower part of an integer number should be written.
159/// However, if a width is set, values might of course change when cut and parsed back later!
160///
161/// All of the integral formats have in common that the output width given includes optional
162/// grouping characters. For example if a width of \b 5 was given for decimal output, the value
163/// \c 12 would be written \c "0,012", hence \b 4 digits plus the grouping character. If grouping
164/// was disabled, the output became \c "00012", which uses one extra digit instead of the group
165/// character.
166/// In contrast to that, sign characters are \c not counted in the width.
167///
168/// When parsing values, grouping characters are ignored at any position within the digits,
169/// except of the start. The same is true for whitespace characters as defined in
170/// #Whitespaces. When this field is \e nulled or empty, then white spaces are \b not ignored.
171/// This might be helpful in some cases where occurrence of white space characters should
172/// indicate an error (or something else) when parsing.
173/// Otherwise, the characters defined in this field are ignored at two places: at the beginning
174/// of a parsing operation and after a sign character was read.
175///
176/// When parsing fails, a value of \c 0 (respectively \c 0.0) is returned by the functions of
177/// namespace #alib::strings::detail which are using this class.
178/// User-friendly classes that use the interface of this type will detect such failure through the
179/// output parameter of the parsing functions, which indicates the index of the end of
180/// the number found.
181///
182/// For each of the four integer formats, decimal, binary, hexadecimal and octal, dedicated
183/// parsing functions exist. Those do not accept literal prefix identifiers as defined in
184/// fields #BinLiteralPrefix, #HexLiteralPrefix and #OctLiteralPrefix. However, the prefixes \b are
185/// identified by function \alib{strings::detail;ParseInt}, which aggregates the other four parsing
186/// functions.<br>
187/// There is no corresponding function defined that writes the literal prefix. When writing
188/// binary, hexadecimal or octal values, such prefixes have to be prepended explicitly by a
189/// user's code.
190///
191/// @tparam TChar The \ref alib_characters_chars "character type" that this class works on.
192/// Alias names for specializations using the different character types are
193/// provided in namespace #alib with type definitions
194/// \alib{NumberFormat},
195/// \alib{NNumberFormat},
196/// \alib{WNumberFormat},
197/// \alib{XNumberFormat},
198/// \alib{ComplementNumberFormat}, and
199/// \alib{StrangeNumberFormat}.
200//==================================================================================================
201template<typename TChar>
203{
204 /// The default static number format object that acts as the default settings of the currently
205 /// running process.<br>
206 /// Function \alib{Bootstrap} invokes #SetFromLocale() on this object and switches grouping
207 /// to \e 'on'.
208 ///
209 /// Classes providing functionality based on this class, might use this as a default
210 /// value for parameters of their interfaces.
212
213 /// A static number format object that may be used to write and parse numbers for 'computational'
214 /// use, which means, that grouping is switched off and decimal point character
215 /// is \c '.'.<br>
216 /// Function \alib{Bootstrap} invokes #SetComputational on this object.
217 ///
218 /// Classes providing functionality based on this class, might use this as a default
219 /// value for parameters of their interfaces.
221
222 // ############################### string members ###################################
223 /// Defines whitespace characters that are ignored when leading the number and after
224 /// the sign-character. Applies to functions
225 /// \alib{strings::detail;ParseInt} and
226 /// \alib{strings::detail;ParseFloat}. In contrast, functions
227 /// \alib{strings::detail;ParseDec},
228 /// \alib{strings::detail;ParseBin},
229 /// \alib{strings::detail;ParseHex}, and
230 /// \alib{strings::detail;ParseOct} do not ignore any whitespace characters.
232
233 /// Defines the decimal exponent symbol of string representations of floating point numbers
234 /// when written or parsed in scientific notation by functions \alib{strings::detail;ParseFloat}
235 /// and \alib{strings::detail;WriteFloat}.<br>
236 /// Function \alib{strings::detail;ParseFloat} accepts characters 'e' and 'E' in addition to
237 /// the character set in this field.<br>
238 /// Defaults to \c 'E'.
240
241 /// Defines what is written and parsed for infinite double values.
243
244 /// Defines what is written and parsed for double values that represent "not a number".
246
247 /// Used by function \alib{strings::detail;ParseInt} to detect binary format of integral values.
248 /// If \e nulled, no binary format is detected.
249 /// Functions provided with \alib are not writing the prefix. If this is desired, it has to
250 /// be performed explicitly by the user code.<br>
251 /// Defaults to \c "0b".
253
254 /// Used by function \alib{strings::detail;ParseInt} to detect hexadecimal format of integer
255 /// values. If \e nulled, no hexadecimal format is detected.
256 /// Functions provided with \alib are not writing the prefix. If this is desired, it has to
257 /// be performed explicitly by the user code.<br>
258 /// Defaults to \c "0x".
260
261 /// Used by function \alib{strings::detail;ParseInt} to detect octal format of integral values.
262 /// If \e nulled, no octal format is detected.
263 /// Functions provided with \alib are not writing the prefix. If this is desired, it has to
264 /// be performed explicitly by the user code.<br>
265 /// Defaults to \c "0o".
267
268 // ############################### character members ###################################
269
270 /// Defines the decimal point character when converting a floating point number to a string
271 /// representation with function \alib{strings::detail;WriteFloat}. Also; function \alib{strings::detail;ParseFloat} uses
272 /// the character provided in this field for parsing the character.<br>
273 /// The field defaults to '.'. By invoking #SetFromLocale(), the current locale's setting is
274 /// determined.
276
277 /// Determines if positive values are prepended with an explicit character (usually '+') when
278 /// written using \alib{strings::detail;WriteFloat} or \alib{strings::detail;WriteDecSigned}.<br>
279 /// Defaults to \c 0 which omits the writing. Usual other values are of course \c '+', but
280 /// also <c>' '</c> (space) which supports better horizontal alignment of numbers when written in
281 /// columns. Note that this is not affecting exponent decimals of floating point values.
282 /// For those, see #WriteExponentPlusSign
283 TChar PlusSign;
284
285 /// Defines the separator character for thousands when converting a number to a string
286 /// representation. In addition, this is used to identify grouping symbols when
287 /// parsing decimal values. If set to \c '\0', no group separator is written and also when
288 /// parsing, a group separator is not accepted.
289 /// If set, still #WriteGroupChars controls if it is written.<br>
290 /// Defaults to \c ','.
291 /// By invoking #SetFromLocale(), the current locale's setting is determined.
293
294 /// This character is written instead of a grouping character in the case that a certain
295 /// output width is requested but a grouping character would be the first character to write.
296 /// Writing this character instead, ensures the field width to be as requested.
297 /// Defaults to space (<c>' '</c>).
299
300
301 /// Defines the separator character for nibbles (4 bits) of binary numbers.
302 /// Defaults to \c '\0' what disables reading and writing of nibble group characters.
304
305 /// Defines the separator character for bytes of binary numbers.
306 /// Defaults to \c '\0' what chooses #BinNibbleGroupChar.
308
309 /// Defines the separator character for 16-bit words of binary numbers.
310 /// Defaults to \c '\0' what chooses #BinByteGroupChar.
312
313 /// Defines the separator character for 32-bit words of binary numbers.
314 /// Defaults to \c '\0' what chooses #BinWordGroupChar.
316
317 /// Defines the separator character for bytes of hexadecimal numbers. Defaults to \c 0,
318 /// Defaults to \c '\0' what disables reading and writing of byte group characters.
320
321 /// Defines the separator character for 16-bit words of hexadecimal numbers.
322 /// Defaults to \c '\0' what chooses #HexByteGroupChar.
324
325 /// Defines the separator character for 32-bit words of hexadecimal numbers.
326 /// Defaults to \c '\0' what chooses #HexWordGroupChar.
328
329 /// Defines the separator character for bytes of hexadecimal numbers.
330 /// Defaults to \c '\0' what disables reading and writing of byte group characters.
332
333 /// The flag field.
335
336 // ############################ width members ###############################
337 /// Defines the minimum digits written for the integral part when converting a floating point
338 /// value into a string.<br>
339 /// If the integral part of the number provided has less digits
340 /// then leading '0' digits are added.<br>
341 /// The maximum value allowed is 15.<br>
342 /// A value of 0 leads to omitting the '0' before the
343 /// decimal separator in the case the value is below 1.0 and higher than -1.0 <br>
344 /// The default value is -1, which writes a minimum of 1 digit.
345 ///
346 /// When either this field or field #FractionalPartWidth is set to a positive value,
347 /// the limits to switch to scientific notation, which otherwise are fixed \c 10E-04 and
348 /// \c 10E+06, get extended. Function \alib{strings::detail;WriteFloat} in this case keeps
349 /// non-scientific notation established if possible.
351
352 /// Defines the number of digits written for the fractional part when converting a floating point
353 /// value into a string. (For integer conversion, see #DecMinimumFieldWidth.)<br>
354 /// If the fractional part of the number provided has less digits then trailing '0'
355 /// digits are added.<br>
356 /// If the fractional part of the number provided has more digits then the fractional part is
357 /// rounded accordingly.<br>
358 /// The maximum value allowed is 15.<br>
359 /// The default value is -1, which writes as many digits as available in the provided float
360 /// variable, with a minimum of 1 digit.
361 ///
362 /// When either this field or field #IntegralPartMinimumWidth is set to a positive value,
363 /// the limits to switch to scientific notation, which otherwise are fixed \c 10E-04 and
364 /// \c 10E+06, get extended. Function \alib{strings::detail;WriteFloat} in this case keeps non-scientific notation
365 /// established if possible.
367
368 /// Defines the minimum digits and grouping symbols written when writing integers in decimal.
369 /// format. If the value to write has less digits (and grouping symbols), then leading '0'
370 /// digits (and eventually grouping symbols) are added.<br> If the value to write has more
371 /// digits, then this field is ignored.
372 /// A sign character is not calculated into the writing width. To have negative and positive
373 /// numbers resulting in the same width, #PlusSign has to be set to a value unequal to \c '\0'
374 /// (usually space character <c>' '</c> or \c '+').
375 ///
376 /// If this field is negative, it is ignored. Defaults to \c -1.
378
379 /// Defines the digits written when writing binary values.
380 /// If the value has less digits, then leading '0' digits are added. If it has more, than
381 /// those digits are \b NOT written (!).<br>
382 /// The default value and minimum value is \c -1, which writes as many bits as necessary.
384
385 /// Defines the digits written when writing hexadecimal values.
386 /// If the value has less digits, then leading '0' digits are added. If it has more, than
387 /// those digits are \b NOT written (!).<br>
388 /// The default value and minimum value is \c -1, which writes as many bits as necessary.
390
391
392 /// Defines the digits written when writing hexadecimal values.
393 /// If the value has less digits, then leading '0' digits are added. If it has more, than
394 /// those digits are \b NOT written (!).<br>
395 /// The default value and minimum value is \c -1, which writes as many bits as necessary.
397
398
399 // #############################################################################################
400 // Interface
401 // #############################################################################################
402
403 //==============================================================================================
404 /// Default constructor. Invokes #SetComputational to reset all fields to their default values.
405 //==============================================================================================
407 {
409 }
410
411 //==============================================================================================
412 /// Copies all fields (settings) from the given object. If no object is provided, values of
413 /// the static singleton found in field #Global are copied
414 ///
415 /// @param other The \b %NumberFormat object to copy the values from.
416 /// Defaults to \c nullptr, which chooses the global singleton.
417 //==============================================================================================
418 void Set( TNumberFormat* other =nullptr );
419
420 //==============================================================================================
421 /// Resets the object to its default values. This method is called in the constructor.
422 ///
423 /// Decimal point character and grouping characters are set as follows:
424 /// <center>Field</center> | <center>Value</center>
425 /// - - - - - - - - - - - - - - - -| - - - -- - - - - - - - - - - - - - - - - - - - - - - - - - -
426 /// #DecimalPointChar | \c .
427 /// #ThousandsGroupChar | \c ,
428 /// #BinNibbleGroupChar | \c '
429 /// #BinByteGroupChar | \c -
430 /// #BinWordGroupChar | <c>' '</c> (space)
431 /// #BinWord32GroupChar | \c #
432 /// #HexWordGroupChar | \c '
433 /// #HexWord32GroupChar | \c '
434 /// #HexByteGroupChar | \c 0 (none)
435 /// #OctGroupChar | \c '
436 ///
437 /// The literal attributes are set as follows:
438 /// <center>Field</center> | <center>Value</center>
439 /// - - - - - - - - - - - - - - - -| - - - -- - - - - - - - - - - - - - - - - - - - - - - - - - -
440 /// #ExponentSeparator | \c "E"
441 /// #INFLiteral | \c "INF"
442 /// #NANLiteral | \c "NAN"
443 /// #BinLiteralPrefix | \c "0b"
444 /// #HexLiteralPrefix | \c "0x"
445 /// #OctLiteralPrefix | \c "0o"
446 ///
447 /// All width-attributes are reset to "automatic mode", \c -1. The attributes are
448 /// #IntegralPartMinimumWidth,
449 /// #FractionalPartWidth,
450 /// #DecMinimumFieldWidth,
451 /// #BinFieldWidth,
452 /// #HexFieldWidth and
453 /// #OctFieldWidth.
454 ///
455 /// Finally, the following further fields are reset to their default values:
456 /// <center>Field</center> | <center>Value</center>
457 /// - - - - - - - - - - - - - - - -| - - - -- - - - - - - - - - - - - - - - - - - - - - - - - - -
458 /// #WriteGroupChars | \c false
459 /// #ForceScientific | \c false
460 /// #ForceDecimalPoint | \c true
461 /// #PlusSign | \c none (0)
462 /// #WriteExponentPlusSign | \c false
463 /// #OmitTrailingFractionalZeros | \c false
464 /// #HexLowerCase | \c false
465 /// #Whitespaces | #alib::DEFAULT_WHITESPACES
466 ///
467 ///
468 /// \note
469 /// With static object
470 /// \ref alib::strings::TNumberFormat::Computational "TNumberFormat::Computational",
471 /// there is a global singleton existing which can be used but must not be changed.
472 //==============================================================================================
474
475 //==============================================================================================
476 /// Sets the field #DecimalPointChar and #ThousandsGroupChar to reflect the current
477 /// system locale setting. No other values are changed.
478 ///
479 /// \note
480 /// Static (global) object \ref alib::strings::TNumberFormat::Global "TNumberFormat::Global",
481 /// implements an instance which has the right locale set (provided that function
482 /// \alib{Bootstrap} was duly invoked by the process).
483 /// Otherwise, this method might be used to initialize a custom object with default values
484 /// to afterwards make some specific changes.
485 //==============================================================================================
487};
488
489//! @cond NO_DOX
490
491extern template ALIB_API void TNumberFormat<nchar>::Set ( TNumberFormat* );
492extern template ALIB_API void TNumberFormat<nchar>::SetFromLocale ();
493
494
495extern template ALIB_API void TNumberFormat<wchar>::Set ( TNumberFormat* );
496extern template ALIB_API void TNumberFormat<wchar>::SetFromLocale ();
497
498
499extern template ALIB_API void TNumberFormat<xchar>::Set ( TNumberFormat* );
500extern template ALIB_API void TNumberFormat<xchar>::SetFromLocale ();
501
502
506
509//! @endcond
510
511} // namespace alib::[strings]
512
513/// Type alias in namespace \b alib.
515
516} // namespace [alib]
517
518#if ALIB_ENUMS
520#endif
521#endif // HPP_ALIB_STRINGS_NUMBERFORMAT
522
#define ALIB_ENUMS_MAKE_BITWISE(TEnum)
Definition bitwise.hpp:109
#define ALIB_API
Definition alib.hpp:639
@ NONE
If assigned, all flags are unset.
Definition alib.cpp:69
TCString< TChar > BinLiteralPrefix
NumberFormatFlags Flags
The flag field.
TCString< TChar > OctLiteralPrefix
TCString< TChar > NANLiteral
Defines what is written and parsed for double values that represent "not a number".
TNumberFormat()
Default constructor. Invokes SetComputational to reset all fields to their default values.
TCString< TChar > HexLiteralPrefix
TCString< TChar > ExponentSeparator
TCString< TChar > INFLiteral
Defines what is written and parsed for infinite double values.
static TNumberFormat Global
void Set(TNumberFormat *other=nullptr)
static TNumberFormat Computational