ALib C++ Library
Library Version: 2402 R1
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 !defined(ALIB_DOX)
10# if !defined (HPP_ALIB_LANG_FORMAT_FORMATTER_JAVASTYLE)
12# endif
13# if !defined (HPP_ALIB_STRINGS_FORMAT)
15# endif
16# if !defined(HPP_ALIB_LANG_FORMAT_EXCEPTIONS)
18# endif
19#endif // !defined(ALIB_DOX)
20
21
22
23using namespace alib::strings;
24namespace alib::lang::format {
25
26
28: FormatterStdImpl( A_CHAR( "FormatterJavaStyle" ) )
29{
30 // arguments are counted starting with 1.
32
33 // set number format to Java defaults
34 DefaultNumberFormat.Flags -= NumberFormatFlags::ForceDecimalPoint;
35 DefaultNumberFormat.Flags += NumberFormatFlags::WriteExponentPlusSign;
36
37 // set number format to Java defaults
39
42
45 DefaultNumberFormat .INFLiteral = A_CHAR( "INFINITY" );
47}
48
49
51{
52 // create a clone
54
55 // create a clone of #Next, in the case that next is derived from std base class
56 if( Next )
57 clone->Next.reset(Next->Clone());
58
59 // copy my settings, that's it
60 clone->CloneSettings( *this );
61 return clone;
62}
63
64
65
67{
68 // first invoke parent's setting...
70
71 // ...then make some "Java like" adjustments
74
75 placeholder.NF.Flags -= NumberFormatFlags::ForceDecimalPoint;
76 placeholder.NF.Flags -= NumberFormatFlags::OmitTrailingFractionalZeros;
77
79
82}
83
84
86{
87 integer idx= 0;
88 while( (idx= parser.IndexOf('%', idx )) >= 0
89 && ( parser.CharAt( idx + 1 ) == '%'
90 || parser.CharAt( idx + 1 ) == 'n' ) )
91 {
92 // double ESC found (escaped %% or %n)
93 idx+= + 2;
94 }
95 return idx;
96}
97
98
100{
101 if( length == 0)
102 return;
103
106 auto* src = parser.Buffer();
107 auto* dest= targetString->VBuffer() + targetString->Length();
108 parser.ConsumeChars( length );
109
110 character c1;
111 character c2= *src;
112 while( length > 1 )
113 {
114 c1= c2;
115 c2= *++src;
116
117 if( ( c1 == '%' && c2 =='%')
118 || c1 == '\\' )
119 {
120 if( c1 == '\\' )
121 switch(c2)
122 {
123 case 'r': c1= '\r' ; break;
124 case 'n': c1= '\n' ; break;
125 case 't': c1= '\t' ; break;
126 case 'a': c1= '\a' ; break;
127 case 'b': c1= '\b' ; break;
128 case 'v': c1= '\v' ; break;
129 case 'f': c1= '\f' ; break;
130 case '"': c1= '"' ; break;
131 default: c1= '?' ; break;
132 }
133
134 c2= *++src;
135 --length;
136 }
137 else if( c1 == '%' && c2 =='n' )
138 {
139 c1= '\n';
140 ++src;
141 --length;
142 }
143
144 *dest++= c1;
145 --length;
146 }
148
149 // copy last character and adjust target string length:
150 // Note: length usually is 1. Only if last character is an escape sequence, it is 0.
151 if( length == 1)
152 *dest= *src;
153 targetString->SetLength( dest - targetString->VBuffer() + length);
154}
155
156
157
159{
160 enum states
161 {
162 POSITION = 1,
163 FLAGS = 2,
164 WIDTH = 3,
165 PRECISION = 4,
166 TYPE = 5,
167 TYPE_SUFFIX = 6,
168 END = 10,
169 };
170
171 states state= POSITION;
172 #define NEXTSTATE(s) { state= s; continue; }
173
174 while( true )
175 {
176 // switch over state. With 'break' we consume one character (kind of success) while
177 // with 'continue' we keep the current character (and go to another state)
178 switch ( state )
179 {
180 case POSITION:
181 {
182 int argNo= -1;
183 if ( parser.ConsumeChar('<') )
184 {
185 argNo= placeholder.PreviousArgIdx + 1;
186 }
187 else
188 {
189 integer i= 0;
190 while( i < parser.Length()
191 && isdigit( parser.CharAt<false>(i) ) )
192 ++i;
193
194 if( i > 0 && parser.CharAt<false>(i) == '$')
195 {
197 parser.ConsumeChar('$') , true )
198 }
199 }
200 if( argNo >= 0 )
201 setArgument( argNo );
202
203 NEXTSTATE(FLAGS)
204 }
205
206 case FLAGS:
207 {
208 bool flagsDone= false;
209 while(!flagsDone)
210 {
211 switch ( parser.CharAtStart() )
212 {
213 case '-':
216 break;
217
218 case '^':
221 break;
222
223 case '#':
224 {
227 placeholder.NF.Flags += NumberFormatFlags::ForceDecimalPoint;
228 placeholder.NF.Flags -= NumberFormatFlags::OmitTrailingFractionalZeros;
229 break;
230 }
231
232 case '+':
233 case ' ':
235 break;
236
237 case '0':
239 break;
240
241 case ',':
242 placeholder.NF.Flags += NumberFormatFlags::WriteGroupChars;
243 break;
244
245 case '(':
248
249 default:
250 flagsDone= true;
251 break;
252 }
253
254 if( !flagsDone )
255 parser.ConsumeChars( 1 );
256 }
257 NEXTSTATE(WIDTH)
258 }
259
260
261 case WIDTH:
262 {
263 if( isdigit( parser.CharAtStart() ) )
265
266 NEXTSTATE(PRECISION)
267 }
268
269 case PRECISION:
270 {
274
275 NEXTSTATE(TYPE)
276 }
277
278 case TYPE:
279 {
281 parser.ConsumeChars( 1 );
282
284
285 if ( typeCharLower == 'a' )
286 {
289 }
290
291 if( placeholderJS.AlternateForm && String( A_CHAR( "sSbBhHgGcCtT" ) ).IndexOf( placeholder.TypeCode ) >= 0 )
295
296 if( String(A_CHAR( "seg" )).IndexOf( placeholder.TypeCode ) >= 0 )
297 {
298 if( placeholder.TypeCode != 's' )
302 }
303
304 if( String(A_CHAR( "SBCT" )).IndexOf( placeholder.TypeCode ) >= 0 )
306
307 if( NCString("egf").IndexOf( static_cast<nchar>(typeCharLower) ) < 0 )
309
310 if( placeholderJS.Precision >=0 && String(A_CHAR( "cCtTd" )).IndexOf( placeholder.TypeCode ) >= 0 )
314
315 if( placeholder.TypeCode == 'X' || placeholder.TypeCode == 'H' ) placeholder.NF.Flags -= NumberFormatFlags::HexLowerCase;
317
318
319 switch ( typeCharLower )
320 {
321 case 's': placeholderJS.Precision= -1;
322 break;
323
324 case 'b': placeholder.Type= PHTypes::Bool; break;
325 case 'c': placeholder.Type= PHTypes::Character; break;
326 case 'd': placeholder.Type= PHTypes::IntBase10; break;
327 case 'o': placeholder.Type= PHTypes::IntOctal; break;
328 case 'x': placeholder.Type= PHTypes::IntHex; break;
329 case 'h': placeholder.Type= PHTypes::IntHex; break;
331 placeholder.NF.Flags+= NumberFormatFlags::ForceScientific; break;
332 case 'g': placeholder.Type= PHTypes::Float; break;
336
338 parser.ConsumeChars( 1 );
339 switch( placeholderJS.DateTime )
340 {
341 case 'H': placeholder.FormatSpec= A_CHAR( "HH" ) ; break;
342 case 'k': placeholder.FormatSpec= A_CHAR( "H" ) ; break;
343 case 'I': placeholder.FormatSpec= A_CHAR( "KK" ) ; break;
344 case 'l': placeholder.FormatSpec= A_CHAR( "K" ) ; break;
345 case 'M': placeholder.FormatSpec= A_CHAR( "mm" ) ; break;
346 case 'S': placeholder.FormatSpec= A_CHAR( "ss" ) ; break;
347 // not supported: case 'L': ;
348 // not supported: case 'N': ;
349 // not supported: case 'p': ;
350 // not supported: case 'z': ;
351 // not supported: case 'Z': ;
352 // not supported: case 's': ;
353 // not supported: case 'Q': ;
354 case 'B': placeholder.FormatSpec= A_CHAR( "MMMM" ); break;
355 case 'b': placeholder.FormatSpec= A_CHAR( "MMM" ); break;
356 case 'h':
357 case 'A': placeholder.FormatSpec= A_CHAR( "dddd" ); break;
358 case 'a': placeholder.FormatSpec= A_CHAR( "ddd" ); break;
359 // not supported: case 'C': ;
360 case 'Y': placeholder.FormatSpec= A_CHAR( "yyyy" ); break;
361 case 'y': placeholder.FormatSpec= A_CHAR( "yy" ); break;
362 // not supported: case 'j': ;
363 case 'm': placeholder.FormatSpec= A_CHAR( "MM" ); break;
364 case 'd': placeholder.FormatSpec= A_CHAR( "dd" ); break;
365 case 'e': placeholder.FormatSpec= A_CHAR( "d" ); break;
366
367 case 'R': placeholder.FormatSpec= A_CHAR( "HH:mm" ); break;
368 case 'T': placeholder.FormatSpec= A_CHAR( "HH:mm:ss" ); break;
369 // not supported: case 'r': ;
370
371 case 'D': placeholder.FormatSpec= A_CHAR( "MM/dd/yy" ); break;
372 case 'F': placeholder.FormatSpec= A_CHAR( "yyyy-MM-dd" ); break;
373 // not supported: case 'c': ;
374
375 default:
379 }
380 break;
381
382 default:
386 }
387
388 NEXTSTATE(TYPE_SUFFIX)
389 }
390
391 case TYPE_SUFFIX:
392 {
393 NEXTSTATE(END)
394 }
395
396 case END:
397 //parser.ConsumeChars(1);
398 return true;
399
400 } // state switch
401
402 } // read loop
403
404}
405
406
408{
409 if( startIdx >= 0 && placeholderJS.ConversionUpper && target == nullptr )
410 targetString->ToUpper( startIdx );
411 return true;
412}
413
414
436
437} // namespace [alib::lang::format]
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
@ 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.
virtual ALIB_API void CloneSettings(Formatter &reference)
std::shared_ptr< Formatter > Next
TAString & ToUpper(integer regionStart=0, integer regionLength=MAX_LEN)
Definition astring.hpp:1832
void EnsureRemainingCapacity(integer spaceNeeded)
Definition astring.hpp:680
TChar * VBuffer() const
Definition astring.hpp:780
void SetLength(integer newLength)
Definition astring.hpp:861
integer IndexOf(TChar needle, integer startIdx=0) const
Definition string.hpp:889
TChar CharAt(integer idx) const
Definition string.hpp:437
constexpr integer Length() const
Definition string.hpp:357
TChar CharAtStart() const
Definition string.hpp:459
constexpr const TChar * Buffer() const
Definition string.hpp:350
integer ConsumeChars(integer regionLength, TSubstring *target=nullptr)
bool ConsumeDecDigits(TIntegral &result)
#define ALIB_ASSERT_RESULT_EQUALS( func, value)
Definition alib.hpp:999
#define ALIB_CALLER_NULLED
Definition alib.hpp:846
#define A_CHAR(STR)
#define ALIB_WARNINGS_RESTORE
Definition alib.hpp:715
#define ALIB_WARNINGS_ALLOW_UNSAFE_BUFFER_USAGE
Definition alib.hpp:644
platform_specific integer
Definition integers.hpp:50
@ 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.
static TChar ToLower(TChar c)
TCString< TChar > OctLiteralPrefix
TCString< TChar > HexLiteralPrefix
TCString< TChar > ExponentSeparator