ALib C++ Library
Library Version: 2510 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;
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{
47 FMTCallerInfo fmtCI{*box.Unbox<CallerInfo*>() };
48 fmtCI.Format( formatSpec.IsNotEmpty() ? formatSpec
49 #if ALIB_CAMP
50 : BASECAMP.GetResource("FMTCI")
51 #else
52 : A_CHAR( "[@ sf:sl from ''ya'' by ''ta'']")
53 #endif
54 , target );
55}
56
57AString& FMTCallerInfo::Format( Substring format, AString& target, lang::CurrentData targetData ) const
58{
59 if ( targetData == lang::CurrentData::Clear )
60 target.Reset();
61
62 // this ensures that target is not nulled, as all other appends are NC-versions
63 target._("");
64
65 while ( format.IsNotEmpty() )
66 {
67 // read n equal characters
68 int n= 1;
69 character c= format.ConsumeChar();
70 while ( format.ConsumeChar(c) )
71 ++n;
72
73 switch (c)
74 {
75 case '\'': // single quotes
76 {
77 // one or more pairs of single quotes?
78 if ( n > 1 )
79 {
80 int pairs= n / 2;
81 target.InsertChars<NC>( '\'', pairs );
82 n-= (pairs * 2);
83 }
84
85 // one single quote?
86 if ( n == 1 )
87 {
88 // search end
89 integer end= format.IndexOf( '\'' );
90 if ( end < 1 )
91 {
92 ALIB_WARNING( "ALIB", "Format Error: Missing single Quote" )
93 target << "Format Error: Missing closing single quote character <'>" ;
94 return target;
95 }
96
97 target._<NC>( format, 0, end );
98 format.ConsumeChars<NC>( end + 1 );
99 }
100
101 } break;
102
103 // source information
104 case 's':
105 {
106 if ( n == 1 )
107 {
108 if ( format.ConsumeChar('f') )
109 {
110 if( ci.File ) target._<NC>( ci.File );
111 else target._<NC>( "<NULL>" );
112 break;
113 }
114 if ( format.ConsumeChar('l') )
115 {
116 if( ci.File )
117 target._<NC>( ci.Line );
118 break;
119 }
120 if ( format.ConsumeChar('m') )
121 {
122 if( ci.File )
123 target._<NC>( ci.Func );
124 break;
125 }
126 }
127 // otherwise: copy what was in
128 target.InsertChars<NC>( c, n );
129 break;
130 }
131
132 #if !ALIB_SINGLE_THREADED
133 // thread information
134 case 't':
135 {
136 if ( n == 1 )
137 {
138 Thread* thread= Thread::Get(ci.ThreadID);
139
140 // alib thread name
141 if ( format.ConsumeChar('n') )
142 {
143 target._<NC>( thread ? thread->GetName()
144 #if ALIB_CAMP
145 : BASECAMP.GetResource("FMTCINT")
146 #else
147 : A_CHAR( "<None>" )
148 #endif
149 );
150 break;
151 }
152 // alib thread id
153 if ( format.ConsumeChar('i') )
154 {
155 if ( thread ) target._<NC>( thread->GetID() );
156 #if ALIB_CAMP
157 else target._<NC>( BASECAMP.GetResource("FMTCINR") );
158 #else
159 else target._<NC>( A_CHAR("<Null>") );
160 #endif
161 break;
162 }
163
164 // native thread id
165 if ( format.ConsumeChar('c') )
166 {
167 if constexpr ( sizeof(std::thread::id) == sizeof(uint16_t) )
168 {
169 uint16_t nativeID= 0;
170 memcpy(&nativeID, &ci.ThreadID, 2);
171 target._<NC>("0x")._<NC>(Hex(nativeID, 4));
172 }
173 if constexpr ( sizeof(std::thread::id) == sizeof(uint32_t) )
174 {
175 uint32_t nativeID= 0;
176 memcpy(&nativeID, &ci.ThreadID, 4);
177 target._<NC>("0x")._<NC>(Hex(nativeID, 8));
178 }
179 if constexpr ( sizeof(std::thread::id) == sizeof(uint64_t) )
180 {
181 uint64_t nativeID= 0;
182 memcpy(&nativeID, &ci.ThreadID, 8);
183 target._<NC>("0x")._<NC>(Hex(nativeID, 16));
184 }
185
186 break;
187 }
188
189 // all/auto
190 if ( format.ConsumeChar('a') )
191 {
192 target._<NC>( ci.ThreadID );
193 break;
194 }
195 }
196 // otherwise: copy what was in
197 target.InsertChars<NC>( c, n );
198 break;
199 }
200 #endif // !ALIB_SINGLE_THREADED
201
202 // type information
203 case 'y':
204 {
205 if ( n == 1 )
206 {
207 // full type name
208 if ( format.ConsumeChar('f') )
209 {
210 #if !ALIB_DEBUG
211 target._<NC>( BASECAMP.GetResource("FMTCINY") );
212 #else
213 if (!ci.TypeInfo) target._<NC>(
214 #if ALIB_CAMP
215 BASECAMP.GetResource("FMTCINY")
216 #else
217 A_CHAR( "<None>" )
218 #endif
219 );
220 else target << lang::DbgTypeDemangler(*ci.TypeInfo).Get();
221 #endif
222 break;
223 }
224
225 // stripped type name
226 if ( format.ConsumeChar('n') )
227 {
228 #if !ALIB_DEBUG
229 target._<NC>( BASECAMP.GetResource("FMTCINY") );
230 #else
231 if (!ci.TypeInfo)
232 target._<NC>(
233 #if ALIB_CAMP
234 BASECAMP.GetResource("FMTCINY")
235 #else
236 A_CHAR( "<None>" )
237 #endif
238 );
239 else
240 {
241 NString2K typeName(*ci.TypeInfo);
242 target._<NC>( typeName );
243 }
244 #endif
245 break;
246 }
247
248 // automatic type together with shortened function name
249 if ( format.ConsumeChar('a') )
250 {
251 #if !ALIB_DEBUG
252 target._<NC>( ci.Func )._<NC>("()");
253 #else
254 if (ci.TypeInfo)
255 target._<NC>( *ci.TypeInfo )._<NC>("::");
256 target._<NC>( ci.Func )._<NC>("()");
257 #endif
258 break;
259 }
260
261 }
262 // otherwise: copy what was in
263 target.InsertChars<NC>( c, n );
264 break;
265 }
266
267 default: // otherwise: copy what was in
268 target.InsertChars<NC>( c, n );
269 break;
270 }
271
272 }
273
274 return target;
275}
276
277
278// #################################################################################################
279// FFormat_DateTime
280// #################################################################################################
281#if !DOXYGEN
282DOX_MARKER([DOX_BOXING_IFORMAT_DATETIME])
283void FFormat_DateTime( const Box& box, const String& formatSpec, NumberFormat&, AString& target )
284{
285 strings::util::CalendarDateTime tct( box.Unbox<DateTime>() );
286 tct.Format( formatSpec.IsNotEmpty() ? formatSpec
287 #if ALIB_CAMP
288 : BASECAMP.GetResource("FMTDT"),
289 #else
290 : A_CHAR( "yyyy-MM-dd HH:mm:ss" ),
291 #endif
292 target );
293}
294DOX_MARKER([DOX_BOXING_IFORMAT_DATETIME])
295#endif
296
297
298// #################################################################################################
299// format::ByteSize
300// #################################################################################################
301#if !DOXYGEN
302
304
305namespace {
306
307double convertTo(uinteger val, ByteSizeUnits unit)
308{
309 double v= double(val);
310 int loopEnd;
311 double divisor;
312 if( unit < ByteSizeUnits::IEC_END)
313 {
314 loopEnd= int(unit);
315 divisor= double(1024);
316 }
317 else
318 {
319 loopEnd= int(unit - ByteSizeUnits::SI);
320 divisor= double(1000);
321 }
322
323 for (int i = 0; i < loopEnd; ++i)
324 v/= divisor;
325 return v;
326}
327
329std::pair<double,ByteSizeUnits> getMagnitude( uinteger val, uinteger byteLimit, uinteger factor)
330{
332 if( val < byteLimit )
333 return std::make_pair( double(val), ByteSizeUnits(0) );
334
335 while(val != 0)
336 {
337 ++unit;
338 if( val < byteLimit * factor)
339 return std::make_pair( double(val) / double(factor), unit );
340
341 val/= factor;
342 }
343}
345} // namespace alib::format[::anonymous]
346
347void FormatByteSize(AString& target, uinteger val, uint16_t magnitudeThreshold,
348 char unitSeparator, ByteSizeUnits unit, NumberFormat& nf)
349{
350 target.EnsureRemainingCapacity(128);
351
352 auto magnitude= (unit == ByteSizeUnits::IEC) ? getMagnitude(val, magnitudeThreshold, 1024ull)
353 : getMagnitude(val, magnitudeThreshold, 1000ull);
354
355 if( magnitude.second == ByteSizeUnits::IEC )
356 target << Dec( val, nullptr );
357 else
358 target.SetLength( strings::detail::WriteFloat( magnitude.first,
359 target.VBuffer(), target.Length(), 0, nf) );
360
361 if( unitSeparator )
362 target << unitSeparator;
363 target << (magnitude.second + unit);
364} // FormatByteSize()
365
366std::pair<double, ByteSizeUnits> ByteSizeIEC::GetMagnitude()
367{
368 auto result= getMagnitude( Value, MagnitudeThreshold, 1024 );
369 result.second+= ByteSizeUnits::IEC;
370 return result;
371}
372
373std::pair<double,ByteSizeUnits> ByteSizeSI::GetMagnitude()
374{
375 auto result= getMagnitude( Value, MagnitudeThreshold, 1000 );
376 result.second+= ByteSizeUnits::SI;
377 return result;
378}
379
380double ByteSizeIEC::ConvertTo(ByteSizeUnits unit) { return convertTo(Value, unit); };
381double ByteSizeSI ::ConvertTo(ByteSizeUnits unit) { return convertTo(Value, unit); };
382
383
384} namespace alib::strings {
385
386void AppendableTraits< format::ByteSizeSI, character, lang::HeapAllocator>::operator()( AString& target, const format::ByteSizeSI src )
387{
388 format::FormatByteSize( target, src.Value, src.MagnitudeThreshold, src.UnitSeparator,
389 format::ByteSizeUnits::SI, * format::BYTESIZE_NUMBER_FORMAT );
390}
391void AppendableTraits< format::ByteSizeIEC, character, lang::HeapAllocator>::operator()( AString& target, const format::ByteSizeIEC src )
392{
393 format::FormatByteSize( target, src.Value, src.MagnitudeThreshold, src.UnitSeparator,
394 format::ByteSizeUnits::IEC, * format::BYTESIZE_NUMBER_FORMAT );
395}
396
397} // namespace [alib::strings]
398
399ALIB_BOXING_VTABLE_DEFINE( alib::format::ByteSizeIEC , vt_lang_format_bytesize_iec )
400ALIB_BOXING_VTABLE_DEFINE( alib::format::ByteSizeSI , vt_lang_format_bytesize_si )
401ALIB_BOXING_VTABLE_DEFINE( alib::format::ByteSizeUnits , vt_lang_format_bytesize_units )
402
403
404#endif //!DOXYGEN
405
406
const String & GetResource(const NString &name)
Definition camp.inl:265
TAString & _(const TAppendable &src)
static ALIB_DLL Thread * Get(std::thread::id nativeID)
Definition thread.cpp:329
#define ALIB_BOXING_VTABLE_DEFINE(TMapped, Identifier)
#define A_CHAR(STR)
#define ALIB_WARNINGS_RESTORE
Definition alib.inl:705
#define ALIB_WARNING(domain,...)
Definition alib.inl:1046
#define ALIB_WARNINGS_IGNORE_NOTHING_RETURNED
Definition alib.inl:681
#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:545
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:224
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:389
strings::THex< character > Hex
Type alias in namespace alib.
Definition format.inl:554
boxing::Box Box
Type alias in namespace alib.
Definition box.inl:1216
lang::CallerInfo CallerInfo
Type alias in namespace alib.
strings::TString< character > String
Type alias in namespace alib.
Definition string.inl:2381
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