Skip to content

Commit 5ebf0d3

Browse files
committed
feat: Add AppendIf methods to ZaSpanStringBuilder for conditional appending
1 parent cae37e2 commit 5ebf0d3

File tree

2 files changed

+237
-0
lines changed

2 files changed

+237
-0
lines changed

src/ZaString/Extensions/ZaSpanStringBuilderExtensions.cs

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,72 @@ public static ref ZaSpanStringBuilder AppendLine(ref this ZaSpanStringBuilder bu
133133
return ref builder.AppendLine();
134134
}
135135

136+
/// <summary>
137+
/// Conditionally appends a string to the builder if the condition is true.
138+
/// </summary>
139+
/// <param name="builder">The builder instance.</param>
140+
/// <param name="condition">The condition to evaluate.</param>
141+
/// <param name="value">The string to append if the condition is true. If null, the operation is a no-op.</param>
142+
/// <returns>A reference to the builder to allow for method chaining.</returns>
143+
public static ref ZaSpanStringBuilder AppendIf(ref this ZaSpanStringBuilder builder, bool condition, string? value)
144+
{
145+
if (condition)
146+
{
147+
builder.Append(value);
148+
}
149+
return ref builder;
150+
}
151+
152+
/// <summary>
153+
/// Conditionally appends a read-only span of characters to the builder if the condition is true.
154+
/// </summary>
155+
/// <param name="builder">The builder instance.</param>
156+
/// <param name="condition">The condition to evaluate.</param>
157+
/// <param name="value">The span of characters to append if the condition is true.</param>
158+
/// <returns>A reference to the builder to allow for method chaining.</returns>
159+
public static ref ZaSpanStringBuilder AppendIf(ref this ZaSpanStringBuilder builder, bool condition, ReadOnlySpan<char> value)
160+
{
161+
if (condition)
162+
{
163+
builder.Append(value);
164+
}
165+
return ref builder;
166+
}
167+
168+
/// <summary>
169+
/// Conditionally appends a single character to the builder if the condition is true.
170+
/// </summary>
171+
/// <param name="builder">The builder instance.</param>
172+
/// <param name="condition">The condition to evaluate.</param>
173+
/// <param name="value">The character to append if the condition is true.</param>
174+
/// <returns>A reference to the builder to allow for method chaining.</returns>
175+
public static ref ZaSpanStringBuilder AppendIf(ref this ZaSpanStringBuilder builder, bool condition, char value)
176+
{
177+
if (condition)
178+
{
179+
builder.Append(value);
180+
}
181+
return ref builder;
182+
}
183+
184+
/// <summary>
185+
/// Conditionally appends a formatted value to the builder if the condition is true.
186+
/// </summary>
187+
/// <typeparam name="T">The type of the value, which must implement ISpanFormattable.</typeparam>
188+
/// <param name="builder">The builder instance.</param>
189+
/// <param name="condition">The condition to evaluate.</param>
190+
/// <param name="value">The value to format and append if the condition is true.</param>
191+
/// <param name="format">An optional format string for the value.</param>
192+
/// <returns>A reference to the builder to allow for method chaining.</returns>
193+
public static ref ZaSpanStringBuilder AppendIf<T>(ref this ZaSpanStringBuilder builder, bool condition, T value, ReadOnlySpan<char> format = default) where T : ISpanFormattable
194+
{
195+
if (condition)
196+
{
197+
builder.Append(value, format);
198+
}
199+
return ref builder;
200+
}
201+
136202
/// <summary>
137203
/// Throws a standardized exception for out-of-range errors.
138204
/// </summary>

tests/ZaString.Tests/ZaSpanStringBuilderBasicTests.cs

Lines changed: 171 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -613,4 +613,175 @@ public void Clear_PreservesCapacity()
613613
Assert.Equal(originalCapacity, builder.Capacity);
614614
Assert.Equal(50, builder.Capacity);
615615
}
616+
617+
[Fact]
618+
public void AppendIf_String_TrueCondition_AppendsValue()
619+
{
620+
Span<char> buffer = stackalloc char[100];
621+
var builder = ZaSpanStringBuilder.Create(buffer);
622+
623+
builder.AppendIf(true, "Hello");
624+
625+
Assert.Equal("Hello", builder.AsSpan());
626+
Assert.Equal(5, builder.Length);
627+
}
628+
629+
[Fact]
630+
public void AppendIf_String_FalseCondition_AppendsNothing()
631+
{
632+
Span<char> buffer = stackalloc char[100];
633+
var builder = ZaSpanStringBuilder.Create(buffer);
634+
635+
builder.AppendIf(false, "Hello");
636+
637+
Assert.Equal("", builder.AsSpan());
638+
Assert.Equal(0, builder.Length);
639+
}
640+
641+
[Fact]
642+
public void AppendIf_String_NullValue_TrueCondition_AppendsNothing()
643+
{
644+
Span<char> buffer = stackalloc char[100];
645+
var builder = ZaSpanStringBuilder.Create(buffer);
646+
647+
builder.AppendIf(true, null);
648+
649+
Assert.Equal("", builder.AsSpan());
650+
Assert.Equal(0, builder.Length);
651+
}
652+
653+
[Fact]
654+
public void AppendIf_ReadOnlySpan_TrueCondition_AppendsValue()
655+
{
656+
Span<char> buffer = stackalloc char[100];
657+
var builder = ZaSpanStringBuilder.Create(buffer);
658+
var span = "World".AsSpan();
659+
660+
builder.AppendIf(true, span);
661+
662+
Assert.Equal("World", builder.AsSpan());
663+
Assert.Equal(5, builder.Length);
664+
}
665+
666+
[Fact]
667+
public void AppendIf_ReadOnlySpan_FalseCondition_AppendsNothing()
668+
{
669+
Span<char> buffer = stackalloc char[100];
670+
var builder = ZaSpanStringBuilder.Create(buffer);
671+
var span = "World".AsSpan();
672+
673+
builder.AppendIf(false, span);
674+
675+
Assert.Equal("", builder.AsSpan());
676+
Assert.Equal(0, builder.Length);
677+
}
678+
679+
[Fact]
680+
public void AppendIf_Char_TrueCondition_AppendsValue()
681+
{
682+
Span<char> buffer = stackalloc char[100];
683+
var builder = ZaSpanStringBuilder.Create(buffer);
684+
685+
builder.AppendIf(true, 'A');
686+
687+
Assert.Equal("A", builder.AsSpan());
688+
Assert.Equal(1, builder.Length);
689+
}
690+
691+
[Fact]
692+
public void AppendIf_Char_FalseCondition_AppendsNothing()
693+
{
694+
Span<char> buffer = stackalloc char[100];
695+
var builder = ZaSpanStringBuilder.Create(buffer);
696+
697+
builder.AppendIf(false, 'A');
698+
699+
Assert.Equal("", builder.AsSpan());
700+
Assert.Equal(0, builder.Length);
701+
}
702+
703+
[Fact]
704+
public void AppendIf_FormattedValue_TrueCondition_AppendsValue()
705+
{
706+
Span<char> buffer = stackalloc char[100];
707+
var builder = ZaSpanStringBuilder.Create(buffer);
708+
709+
builder.AppendIf(true, 42);
710+
711+
Assert.Equal("42", builder.AsSpan());
712+
Assert.Equal(2, builder.Length);
713+
}
714+
715+
[Fact]
716+
public void AppendIf_FormattedValue_FalseCondition_AppendsNothing()
717+
{
718+
Span<char> buffer = stackalloc char[100];
719+
var builder = ZaSpanStringBuilder.Create(buffer);
720+
721+
builder.AppendIf(false, 42);
722+
723+
Assert.Equal("", builder.AsSpan());
724+
Assert.Equal(0, builder.Length);
725+
}
726+
727+
[Fact]
728+
public void AppendIf_FormattedValueWithFormat_TrueCondition_AppendsFormattedValue()
729+
{
730+
Span<char> buffer = stackalloc char[100];
731+
var builder = ZaSpanStringBuilder.Create(buffer);
732+
733+
builder.AppendIf(true, 42, "X4");
734+
735+
Assert.Equal("002A", builder.AsSpan());
736+
Assert.Equal(4, builder.Length);
737+
}
738+
739+
[Fact]
740+
public void AppendIf_ChainedCalls_WorksCorrectly()
741+
{
742+
Span<char> buffer = stackalloc char[100];
743+
var builder = ZaSpanStringBuilder.Create(buffer);
744+
var isAdmin = true;
745+
var hasPermission = false;
746+
747+
builder.Append("Status: ")
748+
.AppendIf(isAdmin, "[Admin]")
749+
.AppendIf(hasPermission, "[Permission]")
750+
.Append(" User");
751+
752+
Assert.Equal("Status: [Admin] User", builder.AsSpan());
753+
Assert.Equal(20, builder.Length);
754+
}
755+
756+
[Fact]
757+
public void AppendIf_MixedWithRegularAppends_WorksCorrectly()
758+
{
759+
Span<char> buffer = stackalloc char[100];
760+
var builder = ZaSpanStringBuilder.Create(buffer);
761+
var showId = true;
762+
var showAge = false;
763+
764+
builder.Append("User: John")
765+
.AppendIf(showId, " (ID: 123)")
766+
.AppendIf(showAge, " Age: 25")
767+
.Append(" - Active");
768+
769+
Assert.Equal("User: John (ID: 123) - Active", builder.AsSpan());
770+
Assert.Equal(29, builder.Length);
771+
}
772+
773+
[Fact]
774+
public void AppendIf_AllTypesWithFalseCondition_ProducesEmptyString()
775+
{
776+
Span<char> buffer = stackalloc char[100];
777+
var builder = ZaSpanStringBuilder.Create(buffer);
778+
779+
builder.AppendIf(false, "string")
780+
.AppendIf(false, "span".AsSpan())
781+
.AppendIf(false, 'c')
782+
.AppendIf(false, 42);
783+
784+
Assert.Equal("", builder.AsSpan());
785+
Assert.Equal(0, builder.Length);
786+
}
616787
}

0 commit comments

Comments
 (0)