From 2c365af630cb869fc3611e4ca4a1454f85916678 Mon Sep 17 00:00:00 2001 From: "Richard (Rikki) Andrew Cattermole" Date: Thu, 27 Mar 2025 08:17:33 +1300 Subject: [PATCH] Fix #10699 - std.format with position with omitted second number does not work --- std/format/spec.d | 18 ++++++++++++++++-- std/format/write.d | 23 ++++++++++++++++++++--- 2 files changed, 36 insertions(+), 5 deletions(-) diff --git a/std/format/spec.d b/std/format/spec.d index 74243becff2..b828bb65b8a 100644 --- a/std/format/spec.d +++ b/std/format/spec.d @@ -127,14 +127,16 @@ if (is(Unqual!Char == Char)) Counting starts with `1`. Set to `0` if not used. Default: `0`. */ - ubyte indexStart; + ushort indexStart; /** Index of the last argument for positional parameter ranges. Counting starts with `1`. Set to `0` if not used. Default: `0`. + + The maximum value of this field is used as a sentinel to indicate the arguments' length. */ - ubyte indexEnd; + ushort indexEnd; version (StdDdoc) { @@ -851,6 +853,18 @@ if (is(Unqual!Char == Char)) assert(f.indexStart == 0); } +// https://github.com/dlang/phobos/issues/10699 +@safe pure unittest +{ + import std.array : appender; + auto f = FormatSpec!char("%1:$d"); + auto w = appender!(char[])(); + + f.writeUpToNextSpec(w); + assert(f.indexStart == 1); + assert(f.indexEnd == ushort.max); +} + /** Helper function that returns a `FormatSpec` for a single format specifier. diff --git a/std/format/write.d b/std/format/write.d index 078fa786e76..d704c14f5fa 100644 --- a/std/format/write.d +++ b/std/format/write.d @@ -648,9 +648,16 @@ uint formattedWrite(Writer, Char, Args...)(auto ref Writer w, const scope Char[] break SWITCH; } default: - throw new FormatException( - text("Positional specifier %", spec.indexStart, '$', spec.spec, - " index exceeds ", Args.length)); + if (spec.indexEnd == spec.indexEnd.max) + break; + else if (spec.indexEnd == spec.indexStart) + throw new FormatException( + text("Positional specifier %", spec.indexStart, '$', spec.spec, + " index exceeds ", Args.length)); + else + throw new FormatException( + text("Positional specifier %", spec.indexStart, ":", spec.indexEnd, '$', spec.spec, + " index exceeds ", Args.length)); } } return currentArg; @@ -1199,6 +1206,16 @@ if (isSomeString!(typeof(fmt))) formattedWrite(stream, "%s", aa); } +// https://github.com/dlang/phobos/issues/10699 +@safe pure unittest +{ + import std.array : appender; + auto w = appender!(char[])(); + + formattedWrite(w, "%1:$d", 1, 2, 3); + assert(w.data == "123"); +} + /** Formats a value of any type according to a format specifier and writes the result to an output range.