ALib C++ Framework
by
Library Version: 2605 R0
Documentation generated by doxygen
Loading...
Searching...
No Matches
formatterjavastyle.cpp
1using namespace alib::strings;
2namespace alib::format {
3
4
6: FormatterStdImpl( A_CHAR( "FormatterJavaStyle" ) ) {
7 // arguments are counted starting with 1.
9
10 // set number format to Java defaults
11 DefaultNumberFormat.Flags -= NumberFormatFlags::ForceDecimalPoint;
12 DefaultNumberFormat.Flags += NumberFormatFlags::WriteExponentPlusSign;
13
14 // set number format to Java defaults
15 DefaultNumberFormat .HexLiteralPrefix = A_CHAR( "0X" );
16
17 DefaultNumberFormat .OctLiteralPrefix =
18 AlternativeNumberFormat.OctLiteralPrefix = A_CHAR( "0" );
19
20 DefaultNumberFormat .NANLiteral =
21 AlternativeNumberFormat.NANLiteral = A_CHAR( "NaN" );
22 DefaultNumberFormat .INFLiteral = A_CHAR( "INFINITY" );
23 AlternativeNumberFormat.INFLiteral = A_CHAR( "Infinity" );
24}
25
26
28 SPFormatter clone;
30
31 // create a clone of Next, in the case that next is derived from std base class
32 if( Next )
33 clone->Next= Next->Clone();
34
35 // copy my settings, that's it
36 clone->CloneSettings( *this );
37
38 return clone;
39}
40
41
42
44 // first invoke parent's setting...
46
47 // ...then make some "Java like" adjustments
48 placeholderJS.ConversionUpper = false;
49 placeholder.ValueAlignment = lang::Alignment::Right;
50
51 placeholder.NF.Flags -= NumberFormatFlags::ForceDecimalPoint;
52 placeholder.NF.Flags -= NumberFormatFlags::OmitTrailingFractionalZeros;
53
54 placeholderJS.AlternateForm = false;
55
56 placeholderJS.Precision = -1;
57 placeholderJS.DefaultPrecision = 6;
58}
59
60
62 integer idx= 0;
63 while( (idx= parser.IndexOf('%', idx )) >= 0
64 && ( parser.CharAt( idx + 1 ) == '%'
65 || parser.CharAt( idx + 1 ) == 'n' ) )
66 {
67 // double ESC found (escaped %% or %n)
68 idx+= + 2;
69 }
70 return idx;
71}
72
73
75 if( length == 0)
76 return;
77
78 targetString->EnsureRemainingCapacity( length );
79 auto* src = parser.Buffer();
80 auto* dest= targetString->VBuffer() + targetString->Length();
81 parser.ConsumeChars( length );
82
83 character c1;
84 character c2= *src;
85 while( length > 1 ) {
86 c1= c2;
87 c2= *++src;
88
89 if( ( c1 == '%' && c2 =='%')
90 || c1 == '\\' )
91 {
92 if( c1 == '\\' )
93 switch(c2) {
94 case 'r': c1= '\r' ; break;
95 case 'n': c1= '\n' ; break;
96 case 't': c1= '\t' ; break;
97 case 'a': c1= '\a' ; break;
98 case 'b': c1= '\b' ; break;
99 case 'v': c1= '\v' ; break;
100 case 'f': c1= '\f' ; break;
101 case '"': c1= '"' ; break;
102 case '\\': c1='\\' ; break;
103 default: c1= '?' ; break;
104 }
105
106 c2= *++src;
107 --length;
108 }
109 else if( c1 == '%' && c2 =='n' ) {
110 c1= '\n';
111 ++src;
112 --length;
113 }
114
115 *dest++= c1;
116 --length;
117 }
118
119 // copy the last character and adjust target string length:
120 // Note: length usually is 1. Only if last character is an escape sequence, it is 0.
121 if( length == 1)
122 *dest= *src;
123 targetString->SetLength( dest - targetString->VBuffer() + length);
124}
125
126
127
129 enum states {
130 POSITION = 1,
131 FLAGS = 2,
132 WIDTH = 3,
133 PRECISION = 4,
134 TYPE = 5,
135 TYPE_SUFFIX = 6,
136 END = 10,
137 };
138
139 states state= POSITION;
140 #define NEXTSTATE(s) { state= s; continue; }
141
142 while( true ) {
143 // switch over state. With 'break' we consume one character (kind of success) while
144 // with 'continue' we keep the current character (and go to another state)
145 switch ( state ) {
146 case POSITION:
147 {
148 int argNo= -1;
149 if ( parser.ConsumeChar('<') ) {
150 argNo= placeholder.PreviousArgIdx + 1;
151 } else {
152 integer i= 0;
153 while( i < parser.Length()
154 && isdigit( parser.CharAt<NC>(i) ) )
155 ++i;
156
157 if( i > 0 && parser.CharAt<NC>(i) == '$') {
158 parser.ConsumeDecDigits( argNo ); ALIB_ASSERT_RESULT_EQUALS(
159 parser.ConsumeChar('$') , true )
160 } }
161 if( argNo >= 0 )
162 setArgument( argNo );
163
164 NEXTSTATE(FLAGS)
165 }
166
167 case FLAGS:
168 {
169 bool flagsDone= false;
170 while(!flagsDone) {
171 switch ( parser.CharAtStart() ) {
172 case '-':
173 placeholder.ValueAlignment= lang::Alignment::Left;
174 placeholder.AlignmentSpecified= true;
175 break;
176
177 case '^':
178 placeholder.ValueAlignment= lang::Alignment::Center;
179 placeholder.AlignmentSpecified= true;
180 break;
181
182 case '#':
183 {
184 placeholderJS.AlternateForm= true;
185 placeholder.WriteBinOctHexPrefix= true;
186 placeholder.NF.Flags += NumberFormatFlags::ForceDecimalPoint;
187 placeholder.NF.Flags -= NumberFormatFlags::OmitTrailingFractionalZeros;
188 break;
189 }
190
191 case '+':
192 case ' ':
193 placeholder.NF.PlusSign= parser.CharAtStart();
194 break;
195
196 case '0':
197 placeholder.SignPaddingMode= true;
198 break;
199
200 case ',':
201 placeholder.NF.Flags += NumberFormatFlags::WriteGroupChars;
202 break;
203
204 case '(':
206 formatString, formatString.Length() - parser.Length() );
207
208 default:
209 flagsDone= true;
210 break;
211 }
212
213 if( !flagsDone )
214 parser.ConsumeChars( 1 );
215 }
216 NEXTSTATE(WIDTH)
217 }
218
219
220 case WIDTH:
221 {
222 if( isdigit( parser.CharAtStart() ) )
223 parser.ConsumeDecDigits( placeholder.Width );
224
225 NEXTSTATE(PRECISION)
226 }
227
228 case PRECISION:
229 {
230 if( parser.ConsumeChar( '.' ) && !parser.ConsumeDecDigits( placeholderJS.Precision ) )
232 formatString, formatString.Length() - parser.Length() );
233
234 NEXTSTATE(TYPE)
235 }
236
237 case TYPE:
238 {
239 placeholder.TypeCode= parser.CharAtStart();
240 parser.ConsumeChars( 1 );
241
242 character typeCharLower= characters::ToLower( placeholder.TypeCode );
243
244 if ( typeCharLower == 'a' ) {
246 formatString, formatString.Length() - parser.Length() - 1 );
247 }
248
249 if( placeholderJS.AlternateForm && String( A_CHAR( "sSbBhHgGcCtT" ) ).IndexOf( placeholder.TypeCode ) >= 0 )
251 placeholder.TypeCode,
252 formatString, formatString.Length() - parser.Length() - 1 );
253
254 if( String(A_CHAR( "seg" )).IndexOf( placeholder.TypeCode ) >= 0 ) {
255 if( placeholder.TypeCode != 's' )
256 placeholder.NF.ExponentSeparator= AlternativeNumberFormat.ExponentSeparator;
257 placeholder.NF.INFLiteral= AlternativeNumberFormat.INFLiteral;
258 placeholder.NF.NANLiteral= AlternativeNumberFormat.NANLiteral;
259 }
260
261 if( String(A_CHAR( "SBCT" )).IndexOf( placeholder.TypeCode ) >= 0 )
262 placeholderJS.ConversionUpper= true;
263
264 if( NCString("egf").IndexOf( static_cast<nchar>(typeCharLower) ) < 0 )
265 placeholder.CutContent= placeholderJS.Precision;
266
267 if( placeholderJS.Precision >=0 && String(A_CHAR( "cCtTd" )).IndexOf( placeholder.TypeCode ) >= 0 )
269 placeholderJS.Precision, placeholder.TypeCode,
270 formatString, formatString.Length() - parser.Length() - 1 );
271
272 if( placeholder.TypeCode == 'X' || placeholder.TypeCode == 'H' ) placeholder.NF.Flags -= NumberFormatFlags::HexLowerCase;
273 else if( placeholder.TypeCode == 'x' || placeholder.TypeCode == 'h' ) placeholder.NF.HexLiteralPrefix= AlternativeNumberFormat.HexLiteralPrefix;
274
275
276 switch ( typeCharLower ) {
277 case 's': placeholderJS.Precision= -1;
278 break;
279
280 case 'b': placeholder.Type= PHTypes::Bool; break;
281 case 'c': placeholder.Type= PHTypes::Character; break;
282 case 'd': placeholder.Type= PHTypes::IntBase10; break;
283 case 'o': placeholder.Type= PHTypes::IntOctal; break;
284 case 'x': placeholder.Type= PHTypes::IntHex; break;
285 case 'h': placeholder.Type= PHTypes::IntHex; break;
286 case 'e': placeholder.Type= PHTypes::Float;
287 placeholder.NF.Flags+= NumberFormatFlags::ForceScientific; break;
288 case 'g': placeholder.Type= PHTypes::Float; break;
289 case 'f': placeholder.Type= PHTypes::Float;
290 placeholder.NF.IntegralPartMinimumWidth= 1;
291 placeholderJS.DefaultPrecision = -1; break;
292
293 case 't': placeholderJS.DateTime= parser.CharAtStart();
294 parser.ConsumeChars( 1 );
295 switch( placeholderJS.DateTime ) {
296 case 'H': placeholder.FormatSpec= A_CHAR( "HH" ) ; break;
297 case 'k': placeholder.FormatSpec= A_CHAR( "H" ) ; break;
298 case 'I': placeholder.FormatSpec= A_CHAR( "KK" ) ; break;
299 case 'l': placeholder.FormatSpec= A_CHAR( "K" ) ; break;
300 case 'M': placeholder.FormatSpec= A_CHAR( "mm" ) ; break;
301 case 'S': placeholder.FormatSpec= A_CHAR( "ss" ) ; break;
302 // not supported: case 'L': ;
303 // not supported: case 'N': ;
304 // not supported: case 'p': ;
305 // not supported: case 'z': ;
306 // not supported: case 'Z': ;
307 // not supported: case 's': ;
308 // not supported: case 'Q': ;
309 case 'B': placeholder.FormatSpec= A_CHAR( "MMMM" ); break;
310 case 'b': placeholder.FormatSpec= A_CHAR( "MMM" ); break;
311 case 'h':
312 case 'A': placeholder.FormatSpec= A_CHAR( "dddd" ); break;
313 case 'a': placeholder.FormatSpec= A_CHAR( "ddd" ); break;
314 // not supported: case 'C': ;
315 case 'Y': placeholder.FormatSpec= A_CHAR( "yyyy" ); break;
316 case 'y': placeholder.FormatSpec= A_CHAR( "yy" ); break;
317 // not supported: case 'j': ;
318 case 'm': placeholder.FormatSpec= A_CHAR( "MM" ); break;
319 case 'd': placeholder.FormatSpec= A_CHAR( "dd" ); break;
320 case 'e': placeholder.FormatSpec= A_CHAR( "d" ); break;
321
322 case 'R': placeholder.FormatSpec= A_CHAR( "HH:mm" ); break;
323 case 'T': placeholder.FormatSpec= A_CHAR( "HH:mm:ss" ); break;
324 // not supported: case 'r': ;
325
326 case 'D': placeholder.FormatSpec= A_CHAR( "MM/dd/yy" ); break;
327 case 'F': placeholder.FormatSpec= A_CHAR( "yyyy-MM-dd" ); break;
328 // not supported: case 'c': ;
329
330 default:
332 placeholderJS.DateTime,
333 formatString, formatString.Length() - parser.Length() - 1 );
334 }
335 break;
336
337 default:
339 placeholder.TypeCode,
340 formatString, formatString.Length() - parser.Length() - 1 );
341 }
342
343 NEXTSTATE(TYPE_SUFFIX)
344 }
345
346 case TYPE_SUFFIX:
347 {
348 NEXTSTATE(END)
349 }
350
351 case END:
352 //parser.ConsumeChars(1);
353 return true;
354
355 default: ALIB_ERROR( "FORMAT", "Illegal switch state." ) break;
356 } // state switch
357
358 } // read loop
359
360}
361
362
364 if( startIdx >= 0 && placeholderJS.ConversionUpper && target == nullptr )
365 targetString->ToUpper( startIdx );
366 return true;
367}
368
369
371 bool wasFloat= placeholder.Type == PHTypes::Float;
372 if( wasFloat ) {
373 if ( placeholderJS.Precision >= 0 )
374 placeholder.NF.FractionalPartWidth= placeholderJS.Precision;
375 else if( placeholder.NF.FractionalPartWidth < 0 )
376 placeholder.NF.FractionalPartWidth= placeholderJS.DefaultPrecision;
377 }
378
380
381 if( !wasFloat && placeholder.Type == PHTypes::Float ) {
382 if ( placeholderJS.Precision >= 0 )
383 placeholder.NF.FractionalPartWidth= placeholderJS.Precision;
384 }
385
386 return result;
387}
388
389} // namespace [alib::format]
#define ALIB_ASSERT_RESULT_EQUALS( func, value)
#define ALIB_CALLER_NULLED
#define A_CHAR(STR)
#define ALIB_ERROR(domain,...)
void InsertDerived(TArgs &&... args)
virtual void writeStringPortion(integer length) override
virtual void resetPlaceholder() override
virtual SPFormatter Clone() override
PlaceholderAttributesJS placeholderJS
The extended placeholder attributes.
virtual bool checkStdFieldAgainstArgument() override
virtual integer findPlaceholder() override
virtual bool parsePlaceholder() override
virtual bool preAndPostProcess(integer startIdx, AString *target) override
AString * targetString
The target string as provided with method #"Formatter::Format".
FormatterStdImpl(const String &formatterClassName)
Substring parser
The current (remaining) format string.
@ 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 #"Formatter::Format".
NumberFormat DefaultNumberFormat
virtual void CloneSettings(Formatter &reference)
Definition formatter.cpp:76
NumberFormat AlternativeNumberFormat
SharedPtr< Formatter > Next
TChar ToLower(TChar c)
@ Center
Chooses centered alignment.
@ Right
Chooses right alignment.
@ Left
Chooses left alignment.
containers::SharedPtr< format::Formatter > SPFormatter
Definition formatter.hpp:41
strings::TCString< nchar > NCString
Type alias in namespace #"%alib".
Definition cstring.hpp:408
lang::integer integer
Type alias in namespace #"%alib".
Definition integers.hpp:149
strings::TString< character > String
Type alias in namespace #"%alib".
Definition string.hpp:2165
characters::nchar nchar
Type alias in namespace #"%alib".
exceptions::Exception Exception
Type alias in namespace #"%alib".
strings::TAString< character, lang::HeapAllocator > AString
Type alias in namespace #"%alib".
characters::character character
Type alias in namespace #"%alib".