6
6
module bc.string.format ;
7
7
8
8
import bc.core.intrinsics ;
9
+ import bc.core.system.backtrace ;
9
10
import bc.core.traits ;
10
11
import bc.string .string ;
11
- import core.time : Duration;
12
12
import std.algorithm : among;
13
13
import std.datetime.date : TimeOfDay ;
14
14
import std.traits :
@@ -18,21 +18,39 @@ import std.traits :
18
18
import std.range : ElementEncodingType, isForwardRange, isInputRange;
19
19
import std.typecons : Flag, Tuple , isTuple;
20
20
21
- version (D_BetterC )
22
- {
23
- // can't import std.uuid, std.datetime.systime in betterC
24
- struct Fake {}
25
- alias UUID = Fake;
26
- alias SysTime = Fake;
27
- alias TraceInfo = Fake;
28
- }
21
+ version (D_BetterC ) {}
29
22
else
30
23
{
31
- import bc. core.system.backtrace : TraceInfo ;
24
+ import core.time : Duration ;
32
25
import std.datetime.systime : SysTime;
33
26
import std.uuid : UUID ;
34
27
}
35
28
29
+ private template isUUID (T)
30
+ {
31
+ version (D_BetterC ) enum isUUID = false ;
32
+ else enum isUUID = is (T == UUID );
33
+ }
34
+
35
+ private template isSysTime (T)
36
+ {
37
+ version (D_BetterC ) enum isSysTime = false ;
38
+ else enum isSysTime = is (T == SysTime);
39
+ }
40
+
41
+ private template isDuration (T)
42
+ {
43
+ version (D_BetterC ) enum isDuration = false ;
44
+ else enum isDuration = is (T == Duration);
45
+ }
46
+
47
+ private template isTraceInfo (T)
48
+ {
49
+ version (D_BetterC ) enum isTraceInfo = false ;
50
+ else version (linux ) enum isTraceInfo = is (T == TraceInfo);
51
+ else enum isTraceInfo = false ;
52
+ }
53
+
36
54
/**
37
55
* Formats values to with fmt template into provided sink.
38
56
* Note: it supports only a basic subset of format type specifiers, main usage is for nogc logging
43
61
size_t nogcFormatTo (string fmt = " %s" , S, ARGS ... )(ref S sink, auto ref ARGS args) nothrow @nogc
44
62
{
45
63
// TODO: not pure because of float formatter
64
+ // import std.conv : text;
46
65
alias sfmt = splitFmt! fmt;
47
- static assert (sfmt.numFormatters == ARGS .length, " Expected " ~ text( sfmt.numFormatters) ~
48
- " arguments, got " ~ text( ARGS .length) );
66
+ static assert (sfmt.numFormatters == ARGS .length, " Expected " ~ sfmt.numFormatters.stringof ~
67
+ " arguments, got " ~ ARGS .length.stringof );
49
68
50
69
mixin SinkWriter! S;
51
70
@@ -105,11 +124,11 @@ size_t nogcFormatTo(string fmt = "%s", S, ARGS...)(ref S sink, auto ref ARGS arg
105
124
auto tmp = enumToStr(val);
106
125
if (_expect(tmp is null , false )) advance(s.nogcFormatTo! " %s(%d)" (Typ.stringof, val));
107
126
else write(tmp);
108
- } else static if (is ( Typ == UUID ) ) advance(s.formatUUID(val));
109
- else static if (is ( Typ == SysTime) ) advance(s.formatSysTime(val));
127
+ } else static if (isUUID ! Typ) advance(s.formatUUID(val));
128
+ else static if (isSysTime ! Typ) advance(s.formatSysTime(val));
110
129
else static if (is (Typ == TimeOfDay ))
111
130
advance(s.nogcFormatTo! " %02d:%02d:%02d" (val.hour, val.minute, val.second));
112
- else static if (is ( Typ == Duration) ) advance(s.formatDuration(val));
131
+ else static if (isDuration ! Typ) advance(s.formatDuration(val));
113
132
else static if (isArray! Typ || isInputRange! Typ) {
114
133
import std.range : empty;
115
134
if (! val.empty) advance(s.nogcFormatTo! " [%(%s%|, %)]" (val));
@@ -145,10 +164,15 @@ size_t nogcFormatTo(string fmt = "%s", S, ARGS...)(ref S sink, auto ref ARGS arg
145
164
}
146
165
else static if (is (Typ : Throwable)) {
147
166
auto obj = cast (Object )val;
148
- advance(s.nogcFormatTo! " %s@%s(%d): %s\n ----------------\n %s" (
149
- typeid (obj).name, val.file, val.line, val.msg, TraceInfo(val)));
167
+ static if (__traits(compiles, TraceInfo(val))) {
168
+ advance(s.nogcFormatTo! " %s@%s(%d): %s\n ----------------\n %s" (
169
+ typeid (obj).name, val.file, val.line, val.msg, TraceInfo(val)));
170
+ }
171
+ else
172
+ advance(s.nogcFormatTo! " %s@%s(%d): %s" (
173
+ typeid (obj).name, val.file, val.line, val.msg));
150
174
}
151
- else static if (is ( Typ == TraceInfo) ) {
175
+ else static if (isTraceInfo ! Typ) {
152
176
auto sw = sinkWrap(s);
153
177
val.dumpTo(sw);
154
178
advance(sw.totalLen);
@@ -385,7 +409,7 @@ const(char)[] nogcFormat(string fmt = "%s", ARGS...)(auto ref ARGS args)
385
409
}
386
410
387
411
version (D_BetterC ) {}
388
- else version (Posix )
412
+ else version (linux )
389
413
{
390
414
// Only Posix is supported ATM
391
415
@(" Exception stack trace format" )
@@ -453,6 +477,8 @@ private struct FmtParams
453
477
int prec; // precision, if -1, use previous argument as precision value
454
478
}
455
479
480
+ private bool isDigit ()(immutable char c) { return c >= ' 0' && c <= ' 9' ; }
481
+
456
482
// Parses format specifier in CTFE
457
483
// See: https://dlang.org/phobos/std_format.html for details
458
484
// Note: Just a subset of the specification is supported ATM. Parser here parses the spec, but
@@ -466,7 +492,6 @@ private struct FmtParams
466
492
//
467
493
auto formatSpec ()(FMT f, string spec)
468
494
{
469
- import std.ascii : isDigit;
470
495
FmtParams res; int idx;
471
496
472
497
if (spec.length)
@@ -609,10 +634,22 @@ private ptrdiff_t indexOf()(string fmt, char c)
609
634
// Phobos version has bug in CTFE, see: https://issues.dlang.org/show_bug.cgi?id=20783
610
635
private ptrdiff_t fixedLastIndexOf ()(string s, string sub)
611
636
{
612
- for (ptrdiff_t i = s.length - sub.length; i >= 0 ; -- i)
637
+ if (! __ctfe) assert (0 );
638
+
639
+ LOOP : for (ptrdiff_t i = s.length - sub.length; i >= 0 ; -- i)
613
640
{
614
- if (s[i .. i + sub.length] == sub[])
615
- return i;
641
+ version (D_BetterC )
642
+ {
643
+ // workaround for missing symbol used by DMD
644
+ for (ptrdiff_t j=0 ; j< sub.length; ++ j)
645
+ if (s[i+ j] != sub[j]) continue LOOP ;
646
+ return i;
647
+ }
648
+ else
649
+ {
650
+ if (s[i .. i + sub.length] == sub[])
651
+ return i;
652
+ }
616
653
}
617
654
return - 1 ;
618
655
}
@@ -1236,6 +1273,8 @@ size_t formatDuration(S)(ref S sink, Duration val) @trusted nothrow @nogc pure
1236
1273
return totalLen;
1237
1274
}
1238
1275
1276
+ version (D_BetterC ) {}
1277
+ else
1239
1278
@(" duration" )
1240
1279
@safe unittest
1241
1280
{
0 commit comments