ALib C++ Library
Library Version: 2412 R0
Documentation generated by doxygen
Loading...
Searching...
No Matches
formatterjavastyle.cpp
1// #################################################################################################
2// ALib C++ Library
3//
4// Copyright 2013-2024 A-Worx GmbH, Germany
5// Published under 'Boost Software License' (a free software license, see LICENSE.txt)
6// #################################################################################################
8
9#if !DOXYGEN
12#endif // !DOXYGEN
13
14
15
16using namespace alib::strings;
17namespace alib::lang::format {
18
19
21: FormatterStdImpl( A_CHAR( "FormatterJavaStyle" ) )
22{
23 // arguments are counted starting with 1.
25
26 // set number format to Java defaults
27 DefaultNumberFormat.Flags -= NumberFormatFlags::ForceDecimalPoint;
28 DefaultNumberFormat.Flags += NumberFormatFlags::WriteExponentPlusSign;
29
30 // set number format to Java defaults
32
35
38 DefaultNumberFormat .INFLiteral = A_CHAR( "INFINITY" );
40}
41
42
44{
45 SPFormatter clone;
47
48 // create a clone of #Next, in the case that next is derived from std base class
49 if( Next )
50 clone->Next= Next->Clone();
51
52 // copy my settings, that's it
53 clone->CloneSettings( *this );
54
55 return clone;
56}
57
58
59
61{
62 // first invoke parent's setting...
64
65 // ...then make some "Java like" adjustments
68
69 placeholder.NF.Flags -= NumberFormatFlags::ForceDecimalPoint;
70 placeholder.NF.Flags -= NumberFormatFlags::OmitTrailingFractionalZeros;
71
73
76}
77
78
80{
81 integer idx= 0;
82 while( (idx= parser.IndexOf('%', idx )) >= 0
83 && ( parser.CharAt( idx + 1 ) == '%'
84 || parser.CharAt( idx + 1 ) == 'n' ) )
85 {
86 // double ESC found (escaped %% or %n)
87 idx+= + 2;
88 }
89 return idx;
90}
91
92
94{
95 if( length == 0)
96 return;
97
100 auto* src = parser.Buffer();
101 auto* dest= targetString->VBuffer() + targetString->Length();
102 parser.ConsumeChars( length );
103
104 character c1;
105 character c2= *src;
106 while( length > 1 )
107 {
108 c1= c2;
109 c2= *++src;
110
111 if( ( c1 == '%' && c2 =='%')
112 || c1 == '\\' )
113 {
114 if( c1 == '\\' )
115 switch(c2)
116 {
117 case 'r': c1= '\r' ; break;
118 case 'n': c1= '\n' ; break;
119 case 't': c1= '\t' ; break;
120 case 'a': c1= '\a' ; break;
121 case 'b': c1= '\b' ; break;
122 case 'v': c1= '\v' ; break;
123 case 'f': c1= '\f' ; break;
124 case '"': c1= '"' ; break;
125 default: c1= '?' ; break;
126 }
127
128 c2= *++src;
129 --length;
130 }
131 else if( c1 == '%' && c2 =='n' )
132 {
133 c1= '\n';
134 ++src;
135 --length;
136 }
137
138 *dest++= c1;
139 --length;
140 }
142
143 // copy last character and adjust target string length:
144 // Note: length usually is 1. Only if last character is an escape sequence, it is 0.
145 if( length == 1)
146 *dest= *src;
147 targetString->SetLength( dest - targetString->VBuffer() + length);
148}
149
150
151
153{
154 enum states
155 {
156 POSITION = 1,
157 FLAGS = 2,
158 WIDTH = 3,
159 PRECISION = 4,
160 TYPE = 5,
161 TYPE_SUFFIX = 6,
162 END = 10,
163 };
164
165 states state= POSITION;
166 #define NEXTSTATE(s) { state= s; continue; }
167
168 while( true )
169 {
170 // switch over state. With 'break' we consume one character (kind of success) while
171 // with 'continue' we keep the current character (and go to another state)
172 switch ( state )
173 {
174 case POSITION:
175 {
176 int argNo= -1;
177 if ( parser.ConsumeChar('<') )
178 {
179 argNo= placeholder.PreviousArgIdx + 1;
180 }
181 else
182 {
183 integer i= 0;
184 while( i < parser.Length()
185 && isdigit( parser.CharAt<NC>(i) ) )
186 ++i;
187
188 if( i > 0 && parser.CharAt<NC>(i) == '$')
189 {
191 parser.ConsumeChar('$') , true )
192 }
193 }
194 if( argNo >= 0 )
195 setArgument( argNo );
196
197 NEXTSTATE(FLAGS)
198 }
199
200 case FLAGS:
201 {
202 bool flagsDone= false;
203 while(!flagsDone)
204 {
205 switch ( parser.CharAtStart() )
206 {
207 case '-':
210 break;
211
212 case '^':
215 break;
216
217 case '#':
218 {
221 placeholder.NF.Flags += NumberFormatFlags::ForceDecimalPoint;
222 placeholder.NF.Flags -= NumberFormatFlags::OmitTrailingFractionalZeros;
223 break;
224 }
225
226 case '+':
227 case ' ':
229 break;
230
231 case '0':
233 break;
234
235 case ',':
236 placeholder.NF.Flags += NumberFormatFlags::WriteGroupChars;
237 break;
238
239 case '(':
242
243 default:
244 flagsDone= true;
245 break;
246 }
247
248 if( !flagsDone )
249 parser.ConsumeChars( 1 );
250 }
251 NEXTSTATE(WIDTH)
252 }
253
254
255 case WIDTH:
256 {
257 if( isdigit( parser.CharAtStart() ) )
259
260 NEXTSTATE(PRECISION)
261 }
262
263 case PRECISION:
264 {
268
269 NEXTSTATE(TYPE)
270 }
271
272 case TYPE:
273 {
275 parser.ConsumeChars( 1 );
276
278
279 if ( typeCharLower == 'a' )
280 {
283 }
284
285 if( placeholderJS.AlternateForm && String( A_CHAR( "sSbBhHgGcCtT" ) ).IndexOf( placeholder.TypeCode ) >= 0 )
289
290 if( String(A_CHAR( "seg" )).IndexOf( placeholder.TypeCode ) >= 0 )
291 {
292 if( placeholder.TypeCode != 's' )
296 }
297
298 if( String(A_CHAR( "SBCT" )).IndexOf( placeholder.TypeCode ) >= 0 )
300
301 if( NCString("egf").IndexOf( static_cast<nchar>(typeCharLower) ) < 0 )
303
304 if( placeholderJS.Precision >=0 && String(A_CHAR( "cCtTd" )).IndexOf( placeholder.TypeCode ) >= 0 )
308
309 if( placeholder.TypeCode == 'X' || placeholder.TypeCode == 'H' ) placeholder.NF.Flags -= NumberFormatFlags::HexLowerCase;
311
312
313 switch ( typeCharLower )
314 {
315 case 's': placeholderJS.Precision= -1;
316 break;
317
318 case 'b': placeholder.Type= PHTypes::Bool; break;
319 case 'c': placeholder.Type= PHTypes::Character; break;
320 case 'd': placeholder.Type= PHTypes::IntBase10; break;
321 case 'o': placeholder.Type= PHTypes::IntOctal; break;
322 case 'x': placeholder.Type= PHTypes::IntHex; break;
323 case 'h': placeholder.Type= PHTypes::IntHex; break;
325 placeholder.NF.Flags+= NumberFormatFlags::ForceScientific; break;
326 case 'g': placeholder.Type= PHTypes::Float; break;
330
332 parser.ConsumeChars( 1 );
333 switch( placeholderJS.DateTime )
334 {
335 case 'H': placeholder.FormatSpec= A_CHAR( "HH" ) ; break;
336 case 'k': placeholder.FormatSpec= A_CHAR( "H" ) ; break;
337 case 'I': placeholder.FormatSpec= A_CHAR( "KK" ) ; break;
338 case 'l': placeholder.FormatSpec= A_CHAR( "K" ) ; break;
339 case 'M': placeholder.FormatSpec= A_CHAR( "mm" ) ; break;
340 case 'S': placeholder.FormatSpec= A_CHAR( "ss" ) ; break;
341 // not supported: case 'L': ;
342 // not supported: case 'N': ;
343 // not supported: case 'p': ;
344 // not supported: case 'z': ;
345 // not supported: case 'Z': ;
346 // not supported: case 's': ;
347 // not supported: case 'Q': ;
348 case 'B': placeholder.FormatSpec= A_CHAR( "MMMM" ); break;
349 case 'b': placeholder.FormatSpec= A_CHAR( "MMM" ); break;
350 case 'h':
351 case 'A': placeholder.FormatSpec= A_CHAR( "dddd" ); break;
352 case 'a': placeholder.FormatSpec= A_CHAR( "ddd" ); break;
353 // not supported: case 'C': ;
354 case 'Y': placeholder.FormatSpec= A_CHAR( "yyyy" ); break;
355 case 'y': placeholder.FormatSpec= A_CHAR( "yy" ); break;
356 // not supported: case 'j': ;
357 case 'm': placeholder.FormatSpec= A_CHAR( "MM" ); break;
358 case 'd': placeholder.FormatSpec= A_CHAR( "dd" ); break;
359 case 'e': placeholder.FormatSpec= A_CHAR( "d" ); break;
360
361 case 'R': placeholder.FormatSpec= A_CHAR( "HH:mm" ); break;
362 case 'T': placeholder.FormatSpec= A_CHAR( "HH:mm:ss" ); break;
363 // not supported: case 'r': ;
364
365 case 'D': placeholder.FormatSpec= A_CHAR( "MM/dd/yy" ); break;
366 case 'F': placeholder.FormatSpec= A_CHAR( "yyyy-MM-dd" ); break;
367 // not supported: case 'c': ;
368
369 default:
373 }
374 break;
375
376 default:
380 }
381
382 NEXTSTATE(TYPE_SUFFIX)
383 }
384
385 case TYPE_SUFFIX:
386 {
387 NEXTSTATE(END)
388 }
389
390 case END:
391 //parser.ConsumeChars(1);
392 return true;
393
394 default: ALIB_ERROR("Illegal switch state.") break;
395 } // state switch
396
397 } // read loop
398
399}
400
401
403{
404 if( startIdx >= 0 && placeholderJS.ConversionUpper && target == nullptr )
405 targetString->ToUpper( startIdx );
406 return true;
407}
408
409
431
432} // namespace [alib::lang::format]
433
void InsertDerived(TArgs &&... args)
virtual ALIB_API integer findPlaceholder() override
virtual ALIB_API bool preAndPostProcess(integer startIdx, AString *target) override
virtual ALIB_API bool checkStdFieldAgainstArgument() override
PlaceholderAttributesJS placeholderJS
The extended placeholder attributes.
virtual ALIB_API SPFormatter Clone() override
virtual ALIB_API bool parsePlaceholder() override
virtual ALIB_API void writeStringPortion(integer length) override
virtual ALIB_API void resetPlaceholder() override
@ Float
Outputs a number in floating point format.
@ IntBase10
Outputs a given number in base 10. The default.
@ IntHex
Outputs a given number in base 16.
@ IntOctal
Outputs a given number in base 8.
String formatString
The format string as provided with method Format.
AString * targetString
The target string as provided with method Format.
Substring parser
The current (remaining) format string.
virtual ALIB_API void CloneSettings(Formatter &reference)
Definition formatter.cpp:95
SharedPtr< Formatter > Next
TAString & ToUpper(integer regionStart=0, integer regionLength=MAX_LEN)
void EnsureRemainingCapacity(integer spaceNeeded)
Definition tastring.inl:742
TChar * VBuffer() const
Definition tastring.inl:843
void SetLength(integer newLength)
Definition tastring.inl:924
integer IndexOf(TChar needle, integer startIdx=0) const
Definition string.hpp:896
TChar CharAt(integer idx) const
Definition string.hpp:444
constexpr integer Length() const
Definition string.hpp:326
TChar CharAtStart() const
Definition string.hpp:466
constexpr const TChar * Buffer() const
Definition string.hpp:319
integer ConsumeChars(integer regionLength, TSubstring *target=nullptr)
bool ConsumeDecDigits(TIntegral &result)
#define ALIB_ASSERT_RESULT_EQUALS( func, value)
Definition alib.hpp:1286
#define ALIB_CALLER_NULLED
Definition alib.hpp:1173
#define A_CHAR(STR)
#define ALIB_WARNINGS_RESTORE
Definition alib.hpp:849
#define ALIB_ERROR(...)
Definition alib.hpp:1267
#define ALIB_WARNINGS_ALLOW_UNSAFE_BUFFER_USAGE
Definition alib.hpp:760
TChar ToLower(TChar c)
platform_specific integer
Definition integers.hpp:43
@ Center
Chooses centered alignment.
@ Right
Chooses right alignment.
@ Left
Chooses left alignment.
lang::Exception Exception
Type alias in namespace alib.
strings::TCString< nchar > NCString
Type alias in namespace alib.
characters::character character
Type alias in namespace alib.
characters::nchar nchar
Type alias in namespace alib.
character DateTime
The character after conversion type 't'/'T'.
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".
TCString< TChar > HexLiteralPrefix
TCString< TChar > ExponentSeparator
TCString< TChar > INFLiteral
Defines what is written and parsed for infinite double values.