ALib C++ Library
Library Version: 2511 R0
Documentation generated by doxygen
Loading...
Searching...
No Matches
fmtvarious.cpp
1//##################################################################################################
2// ALib C++ Library
3//
4// Copyright 2013-2025 A-Worx GmbH, Germany
5// Published under 'Boost Software License' (a free software license, see LICENSE.txt)
6//##################################################################################################
7#include "alib_precompile.hpp"
8#if !defined(ALIB_C20_MODULES) || ((ALIB_C20_MODULES != 0) && (ALIB_C20_MODULES != 1))
9# error "Symbol ALIB_C20_MODULES has to be given to the compiler as either 0 or 1"
10#endif
11#if ALIB_C20_MODULES
12 module;
13#endif
14//========================================= Global Fragment ========================================
15#include <cmath>
16#include <cstring>
18//============================================== Module ============================================
19#if ALIB_C20_MODULES
20 module ALib.Format;
21 import ALib.Lang;
22 import ALib.Time;
23 import ALib.Strings;
24 import ALib.Strings.Calendar;
25 import ALib.Boxing;
26# if ALIB_SYSTEM
27 import ALib.System;
28# endif
29#if ALIB_CAMP
30 import ALib.Camp.Base;
31# endif
32#else
33# include "ALib.Lang.H"
34# include "ALib.Time.H"
35# include "ALib.Strings.H"
37# include "ALib.Boxing.H"
38# include "ALib.System.H"
39# include "ALib.Format.H"
40# include "ALib.Camp.Base.H"
41#endif
42//========================================== Implementation ========================================
43namespace alib::format {
44
45void FFormat_CallerInfo(const Box& box, const String& formatSpec, NumberFormat&, AString& target) {
46 FMTCallerInfo fmtCI{*box.Unbox<CallerInfo*>() };
47 fmtCI.Format( formatSpec.IsNotEmpty() ? formatSpec
48 #if ALIB_CAMP
49 : BASECAMP.GetResource("FMTCI")
50 #else
51 : A_CHAR( "[@ sf:sl from ''ya'' by ''ta'']")
52 #endif
53 , target );
54}
55
57 lang::CurrentData targetData ) const {
58 if ( targetData == lang::CurrentData::Clear )
59 target.Reset();
60
61 // this ensures that target is not nulled, as all other appends are NC-versions
62 target._("");
63
64 while ( format.IsNotEmpty() ) {
65 // read n equal characters
66 int n= 1;
67 character c= format.ConsumeChar();
68 while ( format.ConsumeChar(c) )
69 ++n;
70
71 switch (c) {
72 case '\'': // single quotes
73 {
74 // one or more pairs of single quotes?
75 if ( n > 1 ) {
76 int pairs= n / 2;
77 target.InsertChars<NC>( '\'', pairs );
78 n-= (pairs * 2);
79 }
80
81 // one single quote?
82 if ( n == 1 ) {
83 // search end
84 integer end= format.IndexOf( '\'' );
85 if ( end < 1 ) {
86 ALIB_WARNING( "ALIB", "Format Error: Missing single Quote" )
87 target << "Format Error: Missing closing single quote character <'>" ;
88 return target;
89 }
90
91 target._<NC>( format, 0, end );
92 format.ConsumeChars<NC>( end + 1 );
93 }
94
95 } break;
96
97 // source information
98 case 's':
99 {
100 if ( n == 1 ) {
101 if ( format.ConsumeChar('f') ) {
102 if( ci.File ) target._<NC>( ci.File );
103 else target._<NC>( "<NULL>" );
104 break;
105 }
106 if ( format.ConsumeChar('l') ) {
107 if( ci.File )
108 target._<NC>( ci.Line );
109 break;
110 }
111 if ( format.ConsumeChar('m') ) {
112 if( ci.File )
113 target._<NC>( ci.Func );
114 break;
115 } }
116 // otherwise: copy what was in
117 target.InsertChars<NC>( c, n );
118 break;
119 }
120
121 #if !ALIB_SINGLE_THREADED
122 // thread information
123 case 't':
124 {
125 if ( n == 1 ) {
126 Thread* thread= Thread::Get(ci.ThreadID);
127
128 // alib thread name
129 if ( format.ConsumeChar('n') ) {
130 target._<NC>( thread ? thread->GetName()
131 #if ALIB_CAMP
132 : BASECAMP.GetResource("FMTCINT")
133 #else
134 : A_CHAR( "<None>" )
135 #endif
136 );
137 break;
138 }
139 // alib thread id
140 if ( format.ConsumeChar('i') ) {
141 if ( thread ) target._<NC>( thread->GetID() );
142 #if ALIB_CAMP
143 else target._<NC>( BASECAMP.GetResource("FMTCINR") );
144 #else
145 else target._<NC>( A_CHAR("<Null>") );
146 #endif
147 break;
148 }
149
150 // native thread id
151 if ( format.ConsumeChar('c') ) {
152 if constexpr ( sizeof(std::thread::id) == sizeof(uint16_t) ) {
153 uint16_t nativeID= 0;
154 memcpy(&nativeID, &ci.ThreadID, 2);
155 target._<NC>("0x")._<NC>(Hex(nativeID, 4));
156 }
157 if constexpr ( sizeof(std::thread::id) == sizeof(uint32_t) ) {
158 uint32_t nativeID= 0;
159 memcpy(&nativeID, &ci.ThreadID, 4);
160 target._<NC>("0x")._<NC>(Hex(nativeID, 8));
161 }
162 if constexpr ( sizeof(std::thread::id) == sizeof(uint64_t) ) {
163 uint64_t nativeID= 0;
164 memcpy(&nativeID, &ci.ThreadID, 8);
165 target._<NC>("0x")._<NC>(Hex(nativeID, 16));
166 }
167
168 break;
169 }
170
171 // all/auto
172 if ( format.ConsumeChar('a') ) {
173 target._<NC>( ci.ThreadID );
174 break;
175 } }
176 // otherwise: copy what was in
177 target.InsertChars<NC>( c, n );
178 break;
179 }
180 #endif // !ALIB_SINGLE_THREADED
181
182 // type information
183 case 'y':
184 {
185 if ( n == 1 ) {
186 // full type name
187 if ( format.ConsumeChar('f') ) {
188 #if !ALIB_DEBUG
189 target._<NC>(
190 #if ALIB_CAMP
191 BASECAMP.GetResource("FMTCINY")
192 #else
193 A_CHAR( "<None>" )
194 #endif
195 );
196 #else
197 if (!ci.TypeInfo) target._<NC>(
198 #if ALIB_CAMP
199 BASECAMP.GetResource("FMTCINY")
200 #else
201 A_CHAR( "<None>" )
202 #endif
203 );
204 else target << lang::DbgTypeDemangler(*ci.TypeInfo).Get();
205 #endif
206 break;
207 }
208
209 // stripped type name
210 if ( format.ConsumeChar('n') ) {
211 #if !ALIB_DEBUG
212 target._<NC>(
213 #if ALIB_CAMP
214 BASECAMP.GetResource("FMTCINY")
215 #else
216 A_CHAR( "<None>" )
217 #endif
218 );
219 #else
220 if (!ci.TypeInfo)
221 target._<NC>(
222 #if ALIB_CAMP
223 BASECAMP.GetResource("FMTCINY")
224 #else
225 A_CHAR( "<None>" )
226 #endif
227 );
228 else {
229 NString2K typeName(*ci.TypeInfo);
230 target._<NC>( typeName );
231 }
232 #endif
233 break;
234 }
235
236 // automatic type together with shortened function name
237 if ( format.ConsumeChar('a') ) {
238 #if !ALIB_DEBUG
239 target._<NC>( ci.Func )._<NC>("()");
240 #else
241 if (ci.TypeInfo)
242 target._<NC>( *ci.TypeInfo )._<NC>("::");
243 target._<NC>( ci.Func )._<NC>("()");
244 #endif
245 break;
246 }
247
248 }
249 // otherwise: copy what was in
250 target.InsertChars<NC>( c, n );
251 break;
252 }
253
254 default: // otherwise: copy what was in
255 target.InsertChars<NC>( c, n );
256 break;
257 }
258
259 }
260
261 return target;
262}
263
264
265//##################################################################################################
266// FFormat_DateTime
267//##################################################################################################
268#if !DOXYGEN
269DOX_MARKER([DOX_BOXING_IFORMAT_DATETIME])
270void FFormat_DateTime( const Box& box, const String& formatSpec, NumberFormat&, AString& target ) {
271 strings::util::CalendarDateTime tct( box.Unbox<DateTime>() );
272 tct.Format( formatSpec.IsNotEmpty() ? formatSpec
273 #if ALIB_CAMP
274 : BASECAMP.GetResource("FMTDT"),
275 #else
276 : A_CHAR( "yyyy-MM-dd HH:mm:ss" ),
277 #endif
278 target );
279}
280DOX_MARKER([DOX_BOXING_IFORMAT_DATETIME])
281#endif
282
283
284//##################################################################################################
285// format::ByteSize
286//##################################################################################################
287#if !DOXYGEN
288
290
291namespace {
292
293double convertTo(uinteger val, ByteSizeUnits unit) {
294 double v= double(val);
295 int loopEnd;
296 double divisor;
297 if( unit < ByteSizeUnits::IEC_END) {
298 loopEnd= int(unit);
299 divisor= double(1024);
300 } else {
301 loopEnd= int(unit - ByteSizeUnits::SI);
302 divisor= double(1000);
303 }
304
305 for (int i = 0; i < loopEnd; ++i)
306 v/= divisor;
307 return v;
308}
309
311std::pair<double,ByteSizeUnits> getMagnitude( uinteger val, uinteger byteLimit, uinteger factor) {
313 if( val < byteLimit )
314 return std::make_pair( double(val), ByteSizeUnits(0) );
315
316 while(val != 0) {
317 ++unit;
318 if( val < byteLimit * factor)
319 return std::make_pair( double(val) / double(factor), unit );
320
321 val/= factor;
322} }
324} // namespace alib::format[::anonymous]
325
326void FormatByteSize(AString& target, uinteger val, uint16_t magnitudeThreshold,
327 char unitSeparator, ByteSizeUnits unit, NumberFormat& nf) {
328 target.EnsureRemainingCapacity(128);
329
330 auto magnitude= (unit == ByteSizeUnits::IEC) ? getMagnitude(val, magnitudeThreshold, 1024ull)
331 : getMagnitude(val, magnitudeThreshold, 1000ull);
332
333 if( magnitude.second == ByteSizeUnits::IEC )
334 target << Dec( val, nullptr );
335 else
336 target.SetLength( strings::detail::WriteFloat( magnitude.first,
337 target.VBuffer(), target.Length(), 0, nf) );
338
339 if( unitSeparator )
340 target << unitSeparator;
341 target << (magnitude.second + unit);
342} // FormatByteSize()
343
344std::pair<double, ByteSizeUnits> ByteSizeIEC::GetMagnitude() {
345 auto result= getMagnitude( Value, MagnitudeThreshold, 1024 );
346 result.second+= ByteSizeUnits::IEC;
347 return result;
348}
349
350std::pair<double,ByteSizeUnits> ByteSizeSI::GetMagnitude() {
351 auto result= getMagnitude( Value, MagnitudeThreshold, 1000 );
352 result.second+= ByteSizeUnits::SI;
353 return result;
354}
355
356double ByteSizeIEC::ConvertTo(ByteSizeUnits unit) { return convertTo(Value, unit); };
357double ByteSizeSI ::ConvertTo(ByteSizeUnits unit) { return convertTo(Value, unit); };
358
359
360} namespace alib::strings {
361
362void AppendableTraits< format::ByteSizeSI, character, lang::HeapAllocator>::operator()( AString& target, const format::ByteSizeSI src )
363{
364 format::FormatByteSize( target, src.Value, src.MagnitudeThreshold, src.UnitSeparator,
365 format::ByteSizeUnits::SI, * format::BYTESIZE_NUMBER_FORMAT );
366}
367void AppendableTraits< format::ByteSizeIEC, character, lang::HeapAllocator>::operator()( AString& target, const format::ByteSizeIEC src )
368{
369 format::FormatByteSize( target, src.Value, src.MagnitudeThreshold, src.UnitSeparator,
370 format::ByteSizeUnits::IEC, * format::BYTESIZE_NUMBER_FORMAT );
371}
372
373} // namespace [alib::strings]
374
375ALIB_BOXING_VTABLE_DEFINE( alib::format::ByteSizeIEC , vt_lang_format_bytesize_iec )
376ALIB_BOXING_VTABLE_DEFINE( alib::format::ByteSizeSI , vt_lang_format_bytesize_si )
377ALIB_BOXING_VTABLE_DEFINE( alib::format::ByteSizeUnits , vt_lang_format_bytesize_units )
378
379
380#endif //!DOXYGEN
const String & GetResource(const NString &name)
Definition camp.inl:260
TAString & _(const TAppendable &src)
static ALIB_DLL Thread * Get(std::thread::id nativeID)
Definition thread.cpp:314
#define ALIB_BOXING_VTABLE_DEFINE(TMapped, Identifier)
#define A_CHAR(STR)
#define ALIB_WARNINGS_RESTORE
Definition alib.inl:719
#define ALIB_WARNING(domain,...)
Definition alib.inl:1063
#define ALIB_WARNINGS_IGNORE_NOTHING_RETURNED
Definition alib.inl:695
#define ALIB_CAMP
Definition alib.inl:226
void typeName(const detail::VTable *vtable, AString &result)
NumberFormat * BYTESIZE_NUMBER_FORMAT
ALIB_DLL void FormatByteSize(AString &target, uinteger byteSize, uint16_t magnitudeThreshold, char unitSeparator, ByteSizeUnits unit, NumberFormat &nf)
ALIB_DLL void FFormat_CallerInfo(const Box &self, const String &formatSpec, NumberFormat &nf, AString &target)
ALIB_DLL void FFormat_DateTime(const Box &self, const String &formatSpec, NumberFormat &nf, AString &target)
@ Clear
Chooses to clear existing data.
ALIB_DLL integer WriteFloat(double value, TChar *buffer, integer idx, int minWidth, const TNumberFormat< TChar > &nf)
strings::TDec< character > Dec
Type alias in namespace alib.
Definition format.inl:541
strings::TAString< character, lang::HeapAllocator > AString
Type alias in namespace alib.
camp::Basecamp BASECAMP
The singleton instance of ALib Camp class Basecamp.
Definition basecamp.cpp:81
NLocalString< 2048 > NString2K
Type alias name for TLocalString<nchar,2048>.
time::DateTime DateTime
Type alias in namespace alib.
Definition datetime.inl:185
lang::integer integer
Type alias in namespace alib.
Definition integers.inl:149
strings::TNumberFormat< character > NumberFormat
Type alias in namespace alib.
threads::Thread Thread
Type alias in namespace alib.
Definition thread.inl:387
strings::THex< character > Hex
Type alias in namespace alib.
Definition format.inl:550
boxing::Box Box
Type alias in namespace alib.
Definition box.inl:1149
lang::CallerInfo CallerInfo
Type alias in namespace alib.
strings::TString< character > String
Type alias in namespace alib.
Definition string.inl:2189
characters::character character
Type alias in namespace alib.
lang::uinteger uinteger
Type alias in namespace alib.
Definition integers.inl:152
strings::TSubstring< character > Substring
Type alias in namespace alib.
ALIB_DLL std::pair< double, ByteSizeUnits > GetMagnitude()
ALIB_DLL double ConvertTo(ByteSizeUnits unit)
ALIB_DLL std::pair< double, ByteSizeUnits > GetMagnitude()
const lang::CallerInfo & ci
The wrapped caller information.
ALIB_DLL AString & Format(Substring format, AString &target, lang::CurrentData targetData=lang::CurrentData::Keep) const