Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -778,6 +778,8 @@
<Compile Include="$(CommonPath)System\LocalAppContextSwitches.Common.cs" Link="System\LocalAppContextSwitches.Common.cs" />
<Compile Include="System\Xml\Core\LocalAppContextSwitches.cs" />
<Compile Include="$(CommonPath)System\CSharpHelpers.cs" />
<Compile Include="$(CommonPath)System\Text\ValueStringBuilder.cs"
Link="Common\System\Text\ValueStringBuilder.cs" />
</ItemGroup>
<ItemGroup Condition="'$(TargetsWindows)'=='true'">
<Compile Include="System\Xml\Xsl\Runtime\XmlCollation.Windows.cs" />
Expand Down
152 changes: 77 additions & 75 deletions src/libraries/System.Private.Xml/src/System/Xml/Schema/XsdDateTime.cs
Original file line number Diff line number Diff line change
Expand Up @@ -494,76 +494,79 @@ public static implicit operator DateTimeOffset(XsdDateTime xdt)
/// </summary>
public override string ToString()
{
StringBuilder sb = new StringBuilder(64);
char[] text;
var vsb = new ValueStringBuilder(stackalloc char[64]);
switch (InternalTypeCode)
{
case DateTimeTypeCode.DateTime:
PrintDate(sb);
sb.Append('T');
PrintTime(sb);
PrintDate(ref vsb);
vsb.Append('T');
PrintTime(ref vsb);
break;
case DateTimeTypeCode.Time:
PrintTime(sb);
PrintTime(ref vsb);
break;
case DateTimeTypeCode.Date:
PrintDate(sb);
PrintDate(ref vsb);
break;
case DateTimeTypeCode.GYearMonth:
text = new char[s_lzyyyy_MM];
IntToCharArray(text, 0, Year, 4);
text[s_lzyyyy] = '-';
ShortToCharArray(text, s_lzyyyy_, Month);
sb.Append(text);
break;
{
Span<char> text = vsb.AppendSpan(s_lzyyyy_MM);
IntToCharArray(ref text, 0, Year, 4);
text[s_lzyyyy] = '-';
ShortToCharArray(ref text, s_lzyyyy_, Month);
break;
Comment thread
TrayanZapryanov marked this conversation as resolved.
Outdated
}
case DateTimeTypeCode.GYear:
text = new char[s_lzyyyy];
IntToCharArray(text, 0, Year, 4);
sb.Append(text);
break;
{
Span<char> text = vsb.AppendSpan(s_lzyyyy);
IntToCharArray(ref text, 0, Year, 4);
break;
}
case DateTimeTypeCode.GMonthDay:
text = new char[s_lz__mm_dd];
text[0] = '-';
text[s_Lz_] = '-';
ShortToCharArray(text, s_Lz__, Month);
text[s_lz__mm] = '-';
ShortToCharArray(text, s_lz__mm_, Day);
sb.Append(text);
{
Span<char> text = vsb.AppendSpan(s_lz__mm_dd);
text[0] = '-';
text[s_Lz_] = '-';
ShortToCharArray(ref text, s_Lz__, Month);
text[s_lz__mm] = '-';
ShortToCharArray(ref text, s_lz__mm_, Day);
}
break;
case DateTimeTypeCode.GDay:
text = new char[s_lz___dd];
text[0] = '-';
text[s_Lz_] = '-';
text[s_Lz__] = '-';
ShortToCharArray(text, s_Lz___, Day);
sb.Append(text);
break;
{
Span<char> text = vsb.AppendSpan(s_lz___dd);
text[0] = '-';
text[s_Lz_] = '-';
text[s_Lz__] = '-';
ShortToCharArray(ref text, s_Lz___, Day);
break;
}
case DateTimeTypeCode.GMonth:
text = new char[s_lz__mm__];
text[0] = '-';
text[s_Lz_] = '-';
ShortToCharArray(text, s_Lz__, Month);
text[s_lz__mm] = '-';
text[s_lz__mm_] = '-';
sb.Append(text);
break;
{
Span<char> text = vsb.AppendSpan(s_lz__mm__);
text[0] = '-';
text[s_Lz_] = '-';
ShortToCharArray(ref text, s_Lz__, Month);
text[s_lz__mm] = '-';
text[s_lz__mm_] = '-';
break;
}
}
PrintZone(sb);
return sb.ToString();
PrintZone(ref vsb);
return vsb.ToString();
}

// Serialize year, month and day
private void PrintDate(StringBuilder sb)
private void PrintDate(ref ValueStringBuilder vsb)
{
char[] text = new char[s_lzyyyy_MM_dd];
Span<char> text = vsb.AppendSpan(s_lzyyyy_MM_dd);
int year, month, day;
GetYearMonthDay(out year, out month, out day);
IntToCharArray(text, 0, year, 4);
IntToCharArray(ref text, 0, year, 4);
text[s_lzyyyy] = '-';
ShortToCharArray(text, s_lzyyyy_, month);
ShortToCharArray(ref text, s_lzyyyy_, month);
text[s_lzyyyy_MM] = '-';
ShortToCharArray(text, s_lzyyyy_MM_, day);
sb.Append(text);
ShortToCharArray(ref text, s_lzyyyy_MM_, day);
}

// When printing the date, we need the year, month and the day. When
Expand Down Expand Up @@ -620,15 +623,14 @@ private void GetYearMonthDay(out int year, out int month, out int day)
}

// Serialize hour, minute, second and fraction
private void PrintTime(StringBuilder sb)
private void PrintTime(ref ValueStringBuilder vsb)
{
char[] text = new char[s_lzHH_mm_ss];
ShortToCharArray(text, 0, Hour);
Span<char> text = vsb.AppendSpan(s_lzHH_mm_ss);
ShortToCharArray(ref text, 0, Hour);
text[s_lzHH] = ':';
ShortToCharArray(text, s_lzHH_, Minute);
ShortToCharArray(ref text, s_lzHH_, Minute);
text[s_lzHH_mm] = ':';
ShortToCharArray(text, s_lzHH_mm_, Second);
sb.Append(text);
ShortToCharArray(ref text, s_lzHH_mm_, Second);
int fraction = Fraction;
if (fraction != 0)
{
Expand All @@ -638,38 +640,38 @@ private void PrintTime(StringBuilder sb)
fractionDigits--;
fraction /= 10;
}
text = new char[fractionDigits + 1];
text = vsb.AppendSpan(fractionDigits + 1);
text[0] = '.';
IntToCharArray(text, 1, fraction, fractionDigits);
sb.Append(text);
IntToCharArray(ref text, 1, fraction, fractionDigits);
}
}

// Serialize time zone
private void PrintZone(StringBuilder sb)
private void PrintZone(ref ValueStringBuilder vsb)
{
char[] text;
switch (InternalKind)
{
case XsdDateTimeKind.Zulu:
sb.Append('Z');
vsb.Append('Z');
break;
case XsdDateTimeKind.LocalWestOfZulu:
text = new char[s_lz_zz_zz];
text[0] = '-';
ShortToCharArray(text, s_Lz_, ZoneHour);
text[s_lz_zz] = ':';
ShortToCharArray(text, s_lz_zz_, ZoneMinute);
sb.Append(text);
break;
{
Span<char> text = vsb.AppendSpan(s_lz_zz_zz);
text[0] = '-';
ShortToCharArray(ref text, s_Lz_, ZoneHour);
text[s_lz_zz] = ':';
ShortToCharArray(ref text, s_lz_zz_, ZoneMinute);
break;
}
Comment thread
TrayanZapryanov marked this conversation as resolved.
Outdated
case XsdDateTimeKind.LocalEastOfZulu:
text = new char[s_lz_zz_zz];
text[0] = '+';
ShortToCharArray(text, s_Lz_, ZoneHour);
text[s_lz_zz] = ':';
ShortToCharArray(text, s_lz_zz_, ZoneMinute);
sb.Append(text);
break;
{
Span<char> text = vsb.AppendSpan(s_lz_zz_zz);
text[0] = '+';
ShortToCharArray(ref text, s_Lz_, ZoneHour);
text[s_lz_zz] = ':';
ShortToCharArray(ref text, s_lz_zz_, ZoneMinute);
break;
}
default:
// do nothing
break;
Expand All @@ -678,7 +680,7 @@ private void PrintZone(StringBuilder sb)

// Serialize integer into character array starting with index [start].
// Number of digits is set by [digits]
private void IntToCharArray(char[] text, int start, int value, int digits)
private static void IntToCharArray(ref Span<char> text, int start, int value, int digits)
Comment thread
TrayanZapryanov marked this conversation as resolved.
Outdated
{
while (digits-- != 0)
{
Expand All @@ -688,7 +690,7 @@ private void IntToCharArray(char[] text, int start, int value, int digits)
}
Comment thread
TrayanZapryanov marked this conversation as resolved.

// Serialize two digit integer into character array starting with index [start].
private void ShortToCharArray(char[] text, int start, int value)
private static void ShortToCharArray(ref Span<char> text, int start, int value)
Comment thread
TrayanZapryanov marked this conversation as resolved.
Outdated
{
text[start] = (char)(value / 10 + '0');
text[start + 1] = (char)(value % 10 + '0');
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -339,93 +339,94 @@ public override string ToString()
/// </summary>
internal string ToString(DurationType durationType)
{
StringBuilder sb = new StringBuilder(20);
var vsb = new ValueStringBuilder(stackalloc char[20]);
int nanoseconds, digit, zeroIdx, len;

if (IsNegative)
sb.Append('-');
vsb.Append('-');

sb.Append('P');
vsb.Append('P');

if (durationType != DurationType.DayTimeDuration)
{
if (_years != 0)
{
sb.Append(XmlConvert.ToString(_years));
sb.Append('Y');
XmlConvert.AppendInt(ref vsb, _years);
vsb.Append('Y');
}

if (_months != 0)
{
sb.Append(XmlConvert.ToString(_months));
sb.Append('M');
XmlConvert.AppendInt(ref vsb, _months);
vsb.Append('M');
}
}

if (durationType != DurationType.YearMonthDuration)
{
if (_days != 0)
{
sb.Append(XmlConvert.ToString(_days));
sb.Append('D');
XmlConvert.AppendInt(ref vsb, _days);
vsb.Append('D');
}

if (_hours != 0 || _minutes != 0 || _seconds != 0 || Nanoseconds != 0)
{
sb.Append('T');
vsb.Append('T');
if (_hours != 0)
{
sb.Append(XmlConvert.ToString(_hours));
sb.Append('H');
XmlConvert.AppendInt(ref vsb, _hours);
vsb.Append('H');
}

if (_minutes != 0)
{
sb.Append(XmlConvert.ToString(_minutes));
sb.Append('M');
XmlConvert.AppendInt(ref vsb, _minutes);
vsb.Append('M');
}

nanoseconds = Nanoseconds;
if (_seconds != 0 || nanoseconds != 0)
{
sb.Append(XmlConvert.ToString(_seconds));
XmlConvert.AppendInt(ref vsb, _seconds);
if (nanoseconds != 0)
{
sb.Append('.');
vsb.Append('.');

len = sb.Length;
sb.Length += 9;
zeroIdx = sb.Length - 1;
len = vsb.Length;
Span<char> tmpSpan = stackalloc char[9];
zeroIdx = len + 8;

for (int idx = zeroIdx; idx >= len; idx--)
{
digit = nanoseconds % 10;
sb[idx] = (char)(digit + '0');
tmpSpan[idx - len] = (char)(digit + '0');

if (zeroIdx == idx && digit == 0)
zeroIdx--;

nanoseconds /= 10;
}

sb.Length = zeroIdx + 1;
vsb.EnsureCapacity(zeroIdx + 1);
vsb.Append(tmpSpan.Slice(0, zeroIdx - len + 1));
}
sb.Append('S');
vsb.Append('S');
}
}

// Zero is represented as "PT0S"
if (sb[sb.Length - 1] == 'P')
sb.Append("T0S");
if (vsb[vsb.Length - 1] == 'P')
vsb.Append("T0S");
}
else
{
// Zero is represented as "T0M"
if (sb[sb.Length - 1] == 'P')
sb.Append("0M");
if (vsb[vsb.Length - 1] == 'P')
vsb.Append("0M");
}

return sb.ToString();
return vsb.ToString();
}

internal static Exception? TryParse(string s, out XsdDuration result)
Expand Down
12 changes: 12 additions & 0 deletions src/libraries/System.Private.Xml/src/System/Xml/XmlConvert.cs
Original file line number Diff line number Diff line change
Expand Up @@ -693,6 +693,18 @@ public static string ToString(int value)
return value.ToString(null, s_invariantCultureInfo);
}

internal static void AppendInt(ref ValueStringBuilder vsb, int value)
{
Span<char> tmpSpanDestination = stackalloc char[11];
if (value.TryFormat(tmpSpanDestination, out int charsWritten, provider: s_invariantCultureInfo))
{
var vsbSpan = vsb.AppendSpan(charsWritten);
tmpSpanDestination.Slice(0, charsWritten).CopyTo(vsbSpan);
}
else
vsb.Append(value.ToString(null, s_invariantCultureInfo));
Comment thread
TrayanZapryanov marked this conversation as resolved.
Outdated
}
Comment thread
TrayanZapryanov marked this conversation as resolved.

public static string ToString(long value)
{
return value.ToString(null, s_invariantCultureInfo);
Expand Down