ALib C++ Library
Library Version: 2402 R1
Documentation generated by doxygen
Loading...
Searching...
No Matches
formatterjavastyle.hpp
Go to the documentation of this file.
1/** ************************************************************************************************
2 * \file
3 * This header file is part of sub-namespace #alib::lang::format of module \alib_basecamp of
4 * the \aliblong.
5 *
6 * \emoji :copyright: 2013-2024 A-Worx GmbH, Germany.
7 * Published under \ref mainpage_license "Boost Software License".
8 **************************************************************************************************/
9#ifndef HPP_ALIB_LANG_FORMAT_FORMATTER_JAVASTYLE
10#define HPP_ALIB_LANG_FORMAT_FORMATTER_JAVASTYLE 1
11
12#if !defined (HPP_ALIB_LANG_FORMAT_FORMATTER_STD)
14#endif
15
16namespace alib::lang::format {
17
18/** ************************************************************************************************
19 * Implements a \alib{lang::format;Formatter} according to the
20 * \https{formatting standards of the Java language,docs.oracle.com/javase/8/docs/api/java/util/Formatter.html}.
21 *
22 * \note
23 * Inherited, public fields of parent class \b FormatterStdImpl provide important possibilities
24 * for changing the formatting behavior of instances of this class. Therefore, do not forget
25 * to consult the \ref alib::lang::format::FormatterStdImpl "parent classes documentation".
26 *
27 * In general, the original specification is covered quite well. The differences and specialties
28 * are:
29 * - In deviation of the Java specification, after creation, a formatter in this implementation
30 * does not produce locale aware output. Instead, number formatting is set to "computational",
31 * hence the decimal point separator is <c>'.'</c> and the grouping character <c>','</c>.
32 * As the syntax specification does not provide a feature to switch between standard and locale
33 * setting, the corresponding fields of #AlternativeNumberFormat are not used with this formatter.
34 * Instead, to enable localized output, method
35 * \alib{strings;TNumberFormat::SetFromLocale;NumberFormat::SetFromLocale}
36 * has to be invoked on field
37 * \alib{lang::format;FormatterStdImpl::DefaultNumberFormat;FormatterStdImpl::DefaultNumberFormat}.
38 * Alternatively, attributes of this object may be changed manually or by other means to reflect
39 * a desired locale.
40 * - Hexadecimal floating point output (conversion type \c 'a' and \c 'A') is not supported.
41 * - Flag <c>'('</c>, used to write negative numbers in round brackets, is not supported.
42 * - Addressing the previous argument index using \c '%<' is already allowed with the first
43 * placeholder.
44 * This Chooses the first argument. (In Java a \b MissingFormatArgumentException would be thrown.)
45 * - Flag \c '^' is an extension to the standard and denotes
46 * center-alignment - just like \c '-' in the standard denotes left-alignment.
47 * Right-alignment is the default.
48 *
49 *<p>
50 * - <b>Floating point values:</b>
51 * - If standard field type \c 's' is given together with a precision, the field is cut, even if
52 * it cuts the number somewhere. (This is just a warning and same behavior as in original
53 * specification.)
54 * - For lower case floating point format types (\c 'f', \c 'g' and \c 'e'), the values specified
55 * in attributes \b %ExponentSeparator, \b %NANLiteral and \b %INFLiteral of object
56 * \alib{lang::format;FormatterStdImpl::AlternativeNumberFormat;FormatterStdImpl::AlternativeNumberFormat}
57 * are used. For upper case types (\c 'G' and \c 'E'), the corresponding attributes in
58 * \alib{lang::format;FormatterStdImpl::DefaultNumberFormat;FormatterStdImpl::DefaultNumberFormat} apply.
59 * - Fixed point format (\c 'f' ) is not supported to use arbitrary length.
60 * See class \alib{strings;TNumberFormat;NumberFormat} for the limits.
61 * Due to this limitation, the default number of fractional digits is not set with type \c 'f',
62 * while in Java it is set to \c 6. This is to allow higher numbers up to \c 1.e13 to be printed
63 * in non-scientific format
64 * - When both, a \p{width} and a \p{precision} is given, then the \p{precision} determines the
65 * fractional part, even if the type is \b 'g' or \b 'G'. This is different than specified with
66 * Java formatter, which uses \p{precision} as the overall width in case of types
67 * \b 'g' or \b 'G'.
68 *
69 *<p>
70 * - <b>Hexadecimal and Octal Numbers:</b>
71 * - Hexadecimal and octal output is <b>cut in size</b> (!) when a field width is given that
72 * is smaller than the resulting amount of digits of the number arguments provided.
73 * \note This implies that a value written might not be equal to the value given.
74 * This is not a bug but a design decision. The rationale behind this is that with this
75 * behavior, there is no need to mask lower digits when passing the arguments to the
76 * format invocation. In other words, the formatter "assumes" that the given field width
77 * indicates that only a corresponding number of lower digits are of interest.
78 *
79 * - If no width is given and the argument contains a boxed pointer, then the platform-dependent
80 * full output width of pointer types is used.
81 * - The number <b>grouping option</b> (<c>','</c>) can also be used with binary, hexadecimal
82 * and octal output.
83 * The types support different grouping separators for nibbles, bytes, 16-bit and 32-bit words.
84 * Changing the separator symbols, is not possible with the format fields of the format strings
85 * (if it was, this would become very incompatible to Java standards). Changes have to be made
86 * prior to the format operation by modifying field
87 * \alib{lang::format;FormatterStdImpl::AlternativeNumberFormat;FormatterStdImpl::AlternativeNumberFormat}
88 * which is provided through parent class \b %FormatterStdImpl.
89 *
90 * - Alternative form (\c '#') adds prefixes as specified in members
91 * - \alib{strings;TNumberFormat::HexLiteralPrefix;HexLiteralPrefix} and
92 * - \alib{strings;TNumberFormat::OctLiteralPrefix;OctLiteralPrefix}.
93 *
94 * For upper case formats, those are taken from field
95 * \alib{lang::format;FormatterStdImpl::DefaultNumberFormat;FormatterStdImpl::DefaultNumberFormat},
96 * for lower case formats from
97 * \alib{lang::format;FormatterStdImpl::AlternativeNumberFormat;FormatterStdImpl::AlternativeNumberFormat}.
98 * All defaults may be changed by the user.
99 *
100 *<p>
101 * - <b>Time and Date:</b>
102 * - In this C++ version of the class, boxed values of type \alib{time;DateTime} are applicable
103 * to conversion type \c 't'.
104 * - The following time conversion suffix characters are supported:
105 * \c 'H', \c 'k', \c 'I', \c 'l', \c 'M', \c 'S', \c 'B', \c 'b', \c 'h', \c 'A', \c 'a',
106 * \c 'Y', \c 'y', \c 'm', \c 'd', \c 'e', \c 'R', \c 'T', \c 'D' and \c 'F'
107 * - The following time conversion suffix characters are \b not supported:
108 * \c 'L', \c 'N', \c 'p', \c 'z', \c 'Z', \c 's', \c 'Q', \c 'C', \c 'j', \c 'r' and \c 'c'.
109 *
110\I{################################################################################################}
111 * # Reference Documentation #
112 * @throws <b>alib::lang::format::FMTExceptions</b>
113 * - \alib{lang::format::FMTExceptions;ArgumentIndexIs0}
114 * - \alib{lang::format::FMTExceptions;ArgumentIndexOutOfBounds}
115 * - \alib{lang::format::FMTExceptions;IncompatibleTypeCode}
116 * - \alib{lang::format::FMTExceptions;NegativeValuesInBracketsNotSupported}
117 * - \alib{lang::format::FMTExceptions;MissingPrecisionValueJS}
118 * - \alib{lang::format::FMTExceptions;HexadecimalFloatFormatNotSupported}
119 * - \alib{lang::format::FMTExceptions;NoAlternateFormOfConversion}
120 * - \alib{lang::format::FMTExceptions;NoPrecisionWithConversion}
121 * - \alib{lang::format::FMTExceptions;UnknownDateTimeConversionSuffix}
122 * - \alib{lang::format::FMTExceptions;UnknownConversionJS}
123 *
124 **************************************************************************************************/
126{
127 // #############################################################################################
128 // Protected fields
129 // #############################################################################################
130 protected:
131 /**
132 * Set of extended placeholder attributes, needed for this type of formatter in
133 * addition to parent's \alib{lang::format::FormatterStdImpl;PlaceholderAttributes}.
134 */
136 {
137 /** The character after conversion type 't'/'T'. */
139
140 /** The value read from the precision field.
141 * This is set to \c -1 in #resetPlaceholder. */
142 int8_t Precision;
143
144 /** The default precision if not given.
145 * This is set to \c 6 in #resetPlaceholder, but is changed when specified. */
147
148 /** Convert to upper case. */
150
151 /** Alternate form given ('#'). */
153 };
154
155 /** The extended placeholder attributes. */
157
158
159 // #############################################################################################
160 // Constructor/Destructor
161 // #############################################################################################
162 public:
163 /** ****************************************************************************************
164 * Constructs this formatter.
165 * Inherited field #DefaultNumberFormat is initialized to meet the formatting defaults of
166 * Java.
167 ******************************************************************************************/
170
171 /** ****************************************************************************************
172 * Clones and returns a copy of this formatter.
173 *
174 * If the formatter attached to field
175 * \alib{lang::format;Formatter::Next} is of type \b %FormatterStdImpl, then that
176 * formatter is copied as well.
177 *
178 * @returns An object of type \b %FormatterPythonStyle and with the same custom settings
179 * than this.
180 ******************************************************************************************/
181 ALIB_API virtual
182 FormatterStdImpl* Clone() override;
183
184
185
186 // #############################################################################################
187 // Implementation of FormatterStdImpl interface
188 // #############################################################################################
189 protected:
190
191 /** ****************************************************************************************
192 * Invokes parent implementation and then applies some changes to reflect what is defined as
193 * default in the Java string format specification.
194 ******************************************************************************************/
196 virtual void resetPlaceholder() override;
197
198 /** ****************************************************************************************
199 * Searches for \c '\%' which is not '%%' or '%n'.
200 *
201 * @return The index found, -1 if not found.
202 ******************************************************************************************/
204 virtual integer findPlaceholder() override;
205
206 /** ****************************************************************************************
207 * Parses placeholder field in Java syntax. The portion \p{format_spec} is not set as this
208 * is not supported by the syntax.
209 *
210 * @return \c true on success, \c false on errors.
211 ******************************************************************************************/
213 virtual bool parsePlaceholder() override;
214
215 /** ****************************************************************************************
216 * Does nothing. Java does not support custom format specifications.
217 *
218 * @return \c true to indicate success.
219 ******************************************************************************************/
220 virtual bool parseStdFormatSpec() override
221 {
222 return true;
223 }
224
225 /** ****************************************************************************************
226 * Implementation of abstract method \alib{lang::format;FormatterStdImpl::writeStringPortion}.<br>
227 * Replaces \c "%%" with \c '\%' and \c "%n" with ascii \c 0x0a. In addition applies
228 * \alib{strings;TFormat::Escape;Format::Escape} on \p{target} which replaces
229 * standard codes like \c "\\n", \c "\\r" or \c "\\t" with corresponding ascii codes.
230 * (The latter is an extension to the standard behavior of Java formatter.)
231 *
232 * @param length The number of characters to write.
233 ******************************************************************************************/
235 virtual void writeStringPortion( integer length ) override;
236
237 /** ****************************************************************************************
238 * All that this formatter does with this overridden method is to convert strings to
239 * upper case.
240 *
241 * @param startIdx The index of the start of the field written in #targetString.
242 * \c -1 indicates pre-phase.
243 * @param target The target string, only if different from field #targetString, which
244 * indicates intermediate phase.
245 * @return \c false, if the placeholder should be skipped (nothing is written for it).
246 * \c true otherwise.
247 ******************************************************************************************/
249 virtual bool preAndPostProcess( integer startIdx,
250 AString* target ) override;
251
252 /** ****************************************************************************************
253 * Makes some attribute adjustments and invokes standard implementation
254 * @return \c true if OK, \c false if replacement should be aborted.
255 ******************************************************************************************/
257 virtual bool checkStdFieldAgainstArgument() override;
258};
259
260} // namespace [alib::lang::format]
261
262#endif // HPP_ALIB_LANG_FORMAT_FORMATTER_JAVASTYLE
virtual ALIB_API integer findPlaceholder() override
virtual ALIB_API bool preAndPostProcess(integer startIdx, AString *target) override
virtual ALIB_API bool checkStdFieldAgainstArgument() override
virtual ALIB_API FormatterStdImpl * Clone() override
virtual ALIB_API bool parsePlaceholder() override
virtual ALIB_API void writeStringPortion(integer length) override
virtual ALIB_API void resetPlaceholder() override
#define ALIB_API
Definition alib.hpp:538
platform_specific integer
Definition integers.hpp:50
characters::character character
Type alias in namespace alib.