@@ -197,6 +197,168 @@ public void AppendFormat<T1, T2, T3>(
197197 }
198198 }
199199
200+ /// <summary>
201+ /// Appends the format string to the given <see cref="ValueStringBuilder"/> instance.
202+ /// </summary>
203+ /// <param name="format">Format string.</param>
204+ /// <param name="arg1">Argument for <c>{0}</c>.</param>
205+ /// <param name="arg2">Argument for <c>{1}</c>.</param>
206+ /// <param name="arg3">Argument for <c>{2}</c>.</param>
207+ /// <param name="arg4">Argument for <c>{3}</c>.</param>
208+ /// <typeparam name="T1">Any type for <param name="arg1"></param>.</typeparam>
209+ /// <typeparam name="T2">Any type for <param name="arg2"></param>.</typeparam>
210+ /// <typeparam name="T3">Any type for <param name="arg3"></param>.</typeparam>
211+ /// <typeparam name="T4">Any type for <param name="arg4"></param>.</typeparam>
212+ /// <remarks>
213+ /// The current version does not allow for a custom format.
214+ /// So: <code>AppendFormat("{0:00}")</code> is not allowed and will result in an exception.
215+ /// </remarks>
216+ [ MethodImpl ( MethodImplOptions . AggressiveOptimization ) ]
217+ public void AppendFormat < T1 , T2 , T3 , T4 > (
218+ [ StringSyntax ( StringSyntaxAttribute . CompositeFormat ) ] ReadOnlySpan < char > format ,
219+ T1 arg1 ,
220+ T2 arg2 ,
221+ T3 arg3 ,
222+ T4 arg4 )
223+ {
224+ var formatIndex = 0 ;
225+ var start = 0 ;
226+ while ( formatIndex < format . Length )
227+ {
228+ var c = format [ formatIndex ] ;
229+ if ( c == '{' )
230+ {
231+ var endIndex = format [ ( formatIndex + 1 ) ..] . IndexOf ( '}' ) ;
232+ if ( endIndex == - 1 )
233+ {
234+ Append ( format ) ;
235+ return ;
236+ }
237+
238+ if ( start != formatIndex )
239+ {
240+ Append ( format [ start ..formatIndex ] ) ;
241+ }
242+
243+ var placeholder = format . Slice ( formatIndex , endIndex + 2 ) ;
244+
245+ var index = GetValidArgumentIndex ( placeholder , 3 ) ;
246+
247+ switch ( index )
248+ {
249+ case 0 :
250+ AppendInternal ( arg1 ) ;
251+ break ;
252+ case 1 :
253+ AppendInternal ( arg2 ) ;
254+ break ;
255+ case 2 :
256+ AppendInternal ( arg3 ) ;
257+ break ;
258+ case 3 :
259+ AppendInternal ( arg4 ) ;
260+ break ;
261+ }
262+
263+ formatIndex += endIndex + 2 ;
264+ start = formatIndex ;
265+ }
266+ else
267+ {
268+ formatIndex ++ ;
269+ }
270+ }
271+
272+ if ( start != formatIndex )
273+ {
274+ Append ( format [ start ..formatIndex ] ) ;
275+ }
276+ }
277+
278+ /// <summary>
279+ /// Appends the format string to the given <see cref="ValueStringBuilder"/> instance.
280+ /// </summary>
281+ /// <param name="format">Format string.</param>
282+ /// <param name="arg1">Argument for <c>{0}</c>.</param>
283+ /// <param name="arg2">Argument for <c>{1}</c>.</param>
284+ /// <param name="arg3">Argument for <c>{2}</c>.</param>
285+ /// <param name="arg4">Argument for <c>{3}</c>.</param>
286+ /// <param name="arg5">Argument for <c>{4}</c>.</param>
287+ /// <typeparam name="T1">Any type for <param name="arg1"></param>.</typeparam>
288+ /// <typeparam name="T2">Any type for <param name="arg2"></param>.</typeparam>
289+ /// <typeparam name="T3">Any type for <param name="arg3"></param>.</typeparam>
290+ /// <typeparam name="T4">Any type for <param name="arg4"></param>.</typeparam>
291+ /// <typeparam name="T5">Any type for <param name="arg5"></param>.</typeparam>
292+ /// <remarks>
293+ /// The current version does not allow for a custom format.
294+ /// So: <code>AppendFormat("{0:00}")</code> is not allowed and will result in an exception.
295+ /// </remarks>
296+ [ MethodImpl ( MethodImplOptions . AggressiveOptimization ) ]
297+ public void AppendFormat < T1 , T2 , T3 , T4 , T5 > (
298+ [ StringSyntax ( StringSyntaxAttribute . CompositeFormat ) ] ReadOnlySpan < char > format ,
299+ T1 arg1 ,
300+ T2 arg2 ,
301+ T3 arg3 ,
302+ T4 arg4 ,
303+ T5 arg5 )
304+ {
305+ var formatIndex = 0 ;
306+ var start = 0 ;
307+ while ( formatIndex < format . Length )
308+ {
309+ var c = format [ formatIndex ] ;
310+ if ( c == '{' )
311+ {
312+ var endIndex = format [ ( formatIndex + 1 ) ..] . IndexOf ( '}' ) ;
313+ if ( endIndex == - 1 )
314+ {
315+ Append ( format ) ;
316+ return ;
317+ }
318+
319+ if ( start != formatIndex )
320+ {
321+ Append ( format [ start ..formatIndex ] ) ;
322+ }
323+
324+ var placeholder = format . Slice ( formatIndex , endIndex + 2 ) ;
325+
326+ var index = GetValidArgumentIndex ( placeholder , 4 ) ;
327+
328+ switch ( index )
329+ {
330+ case 0 :
331+ AppendInternal ( arg1 ) ;
332+ break ;
333+ case 1 :
334+ AppendInternal ( arg2 ) ;
335+ break ;
336+ case 2 :
337+ AppendInternal ( arg3 ) ;
338+ break ;
339+ case 3 :
340+ AppendInternal ( arg4 ) ;
341+ break ;
342+ case 4 :
343+ AppendInternal ( arg5 ) ;
344+ break ;
345+ }
346+
347+ formatIndex += endIndex + 2 ;
348+ start = formatIndex ;
349+ }
350+ else
351+ {
352+ formatIndex ++ ;
353+ }
354+ }
355+
356+ if ( start != formatIndex )
357+ {
358+ Append ( format [ start ..formatIndex ] ) ;
359+ }
360+ }
361+
200362 [ MethodImpl ( MethodImplOptions . AggressiveInlining ) ]
201363 private static int GetValidArgumentIndex ( ReadOnlySpan < char > placeholder , int allowedRange )
202364 {
0 commit comments