Skip to content

Commit a5a8813

Browse files
committed
v0.1.3
- Fix retry buffer size calculation in AppendFormatInternal - Add diagnostic info to FormatException
1 parent bcbd957 commit a5a8813

3 files changed

Lines changed: 33 additions & 6 deletions

File tree

CHANGELOG.md

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,45 +2,68 @@
22

33
---
44

5+
## [0.1.3] - 2026-02-26
6+
7+
### Bug Fixes
8+
9+
#### Fix retry buffer size calculation in AppendFormatInternal
10+
11+
- Changed retry buffer from `written > buf.Length ? written : buf.Length * 2` to `buf.Length * 2`
12+
- `written` is unreliable on TryFormat failure (may be 0 or partial), so always double the buffer
13+
14+
### Improvements
15+
16+
#### Add diagnostic info to FormatException
17+
18+
- FormatException message now includes `Type`, `alignment`, `format` for easier debugging
19+
520
## [0.1.2] - 2026-02-26
621

722
### Performance Improvements
823

924
#### Replace Composite Format with Direct TryFormatDelegate
25+
1026
- Removed `AppendFormattedViaComposite`, replaced with `AppendFormatInternal`
1127
- Before: built composite format string (`"{0,alignment:format}"`) on the stack per call, then re-parsed via `_sb.AppendFormat`
1228
- After: calls `FormatterCache<T>.TryFormatDelegate` directly and handles alignment padding inline
1329
- Eliminates composite string construction and re-parsing overhead
1430

1531
#### Avoid Boxing on Null Check (Debug build only)
32+
1633
- Changed null check from `value == null` to `default(T) == null && value == null`
1734
- Prevents unnecessary boxing for value types (null branch entered only for reference types / Nullable)
1835

1936
### Tests
2037

2138
#### Benchmark Test Improvements
39+
2240
- `StringBuilder_FourArgs`: changed from reusing StringBuilder to creating a new instance per iteration (fair comparison)
2341
- `StringBuilder128_FourArgs`: added benchmark that creates a new StringBuilder with initial capacity 128 per iteration
2442
- `StringBuilderShare_FourArgs`: separated the existing shared-StringBuilder approach into its own benchmark
2543

26-
2744
## [0.1.1] - 2026-02-24
2845

2946
### New Features
3047

3148
#### Format Parameter Support
49+
3250
Alignment and format specifiers are now properly supported.
51+
3352
- Fixed: Alignment and format parameters were previously ignored
3453
- Example: `XString.Format($"Score: {score,10:F2}")` aligns to 10 characters with 2 decimal places
3554

3655
#### Support for Up to 16 Format Arguments
56+
3757
Format overloads extended from T1~T4 to T1~T16.
58+
3859
- Example: `XString.Format("{0} {1} ... {15}", arg1, arg2, ..., arg16)`
3960

4061
### Tests
62+
4163
Expanded from 34 to 93 (+174%)
4264

4365
Added tests:
66+
4467
- 4 concurrency tests (multithreading safety)
4568
- 11 edge case tests (boundary conditions, large strings)
4669
- 33 functional tests (various scenarios)

src/XString/Assets/XString/Runtime/XInterpolatedStringHandler.cs

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -225,9 +225,11 @@ private void AppendFormatInternal<T>(T value, int alignment, ReadOnlySpan<char>
225225
if (!FormatterCache<T>.TryFormatDelegate(value, buf, out var written, format))
226226
{
227227
// Retry with larger heap-free buffer.
228-
buf = stackalloc char[written > buf.Length ? written : buf.Length * 2];
228+
buf = stackalloc char[buf.Length * 2];
229229
if (!FormatterCache<T>.TryFormatDelegate(value, buf, out written, format))
230-
throw new FormatException("Failed to format value.");
230+
{
231+
throw new FormatException($"Failed to format value. Type={typeof(T).Name}, alignment=0, format={format.ToString()}");
232+
}
231233
}
232234
_sb.Append(buf.Slice(0, written));
233235
return;
@@ -241,9 +243,11 @@ private void AppendFormatInternal<T>(T value, int alignment, ReadOnlySpan<char>
241243
Span<char> buf = stackalloc char[typeof(T).IsValueType ? Unsafe.SizeOf<T>() * 8 : DefaultFormatBuffer];
242244
if (!FormatterCache<T>.TryFormatDelegate(value, buf, out var written, format))
243245
{
244-
buf = stackalloc char[written > buf.Length ? written : buf.Length * 2];
246+
buf = stackalloc char[buf.Length * 2];
245247
if (!FormatterCache<T>.TryFormatDelegate(value, buf, out written, format))
246-
throw new FormatException("Failed to format value.");
248+
{
249+
throw new FormatException($"Failed to format value. Type={typeof(T).Name}, alignment={alignment}, format={format.ToString()}");
250+
}
247251
}
248252

249253
int padding = width - written;

src/XString/Assets/XString/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "com.xpturn.xstring",
3-
"version": "0.1.2",
3+
"version": "0.1.3",
44
"displayName": "xpTURN.XString",
55
"description": "ZString API wrapper package for Unity. ZString does not provide a dedicated API for interpolated strings, so this package aims to provide `XString.Format($\"...\")` and format-string overloads.",
66
"unity": "2022.3",

0 commit comments

Comments
 (0)