Skip to content
This repository was archived by the owner on Jul 19, 2025. It is now read-only.

Commit 05ac3ab

Browse files
committed
move to string flags to xml serialization settings
1 parent 72dc4ec commit 05ac3ab

8 files changed

Lines changed: 135 additions & 66 deletions

File tree

source/JSON/SerializationSettings.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,15 +6,15 @@ namespace Serialization.JSON
66
public struct SerializationSettings
77
{
88
public const int DefaultIndentation = 4;
9-
public static readonly SerializationSettings Default = new();
10-
public static readonly SerializationSettings JSON5 = new(Flags.QuotelessNames | Flags.SingleQuotedText);
9+
public static readonly SerializationSettings Default = new(Flags.None, 0);
10+
public static readonly SerializationSettings JSON5 = new(Flags.QuotelessNames | Flags.SingleQuotedText, 0);
1111
public static readonly SerializationSettings PrettyPrinted = new(Flags.CarrierReturn | Flags.LineFeed | Flags.SpaceAfterColon, DefaultIndentation);
1212
public static readonly SerializationSettings JSON5PrettyPrinted = new(Flags.CarrierReturn | Flags.LineFeed | Flags.QuotelessNames | Flags.SingleQuotedText | Flags.SpaceAfterColon, DefaultIndentation);
1313

1414
public Flags flags;
1515
public int indent;
1616

17-
public SerializationSettings(Flags flags, int indent = 0)
17+
public SerializationSettings(Flags flags, int indent)
1818
{
1919
this.flags = flags;
2020
this.indent = indent;

source/Serialization.csproj

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,10 @@
1919
<ItemGroup>
2020
<ProjectReference Include="..\..\collections\source\Collections.csproj"/>
2121
<ProjectReference Include="..\..\unmanaged\core\Unmanaged.Core.csproj"/>
22+
<ProjectReference Include="..\..\unmanaged\generator\Unmanaged.Generator.csproj">
23+
<OutputItemType>Analyzer</OutputItemType>
24+
<ReferenceOutputAssembly>false</ReferenceOutputAssembly>
25+
</ProjectReference>
2226
</ItemGroup>
2327

2428
</Project>
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
using System;
2+
using Unmanaged;
3+
4+
namespace Serialization.XML
5+
{
6+
public struct SerializationSettings
7+
{
8+
public const int DefaultIndentation = 2;
9+
public static readonly SerializationSettings Default = new(default, 0);
10+
public static readonly SerializationSettings PrettyPrinted = new(Flags.CarriageReturn | Flags.LineFeed, DefaultIndentation);
11+
12+
public Flags flags;
13+
public int indent;
14+
15+
public SerializationSettings(Flags flags, int indent)
16+
{
17+
this.flags = flags;
18+
this.indent = indent;
19+
}
20+
21+
public readonly void Indent(Text text)
22+
{
23+
text.Append(' ', indent);
24+
}
25+
26+
public readonly void Indent(ByteWriter writer)
27+
{
28+
for (int i = 0; i < indent; i++)
29+
{
30+
writer.WriteUTF8(' ');
31+
}
32+
}
33+
34+
public readonly void NewLine(Text text)
35+
{
36+
if ((flags & Flags.CarriageReturn) == Flags.CarriageReturn)
37+
{
38+
text.Append('\r');
39+
}
40+
41+
if ((flags & Flags.LineFeed) == Flags.LineFeed)
42+
{
43+
text.Append('\n');
44+
}
45+
}
46+
47+
[Flags]
48+
public enum Flags : byte
49+
{
50+
None = 0,
51+
CarriageReturn = 1,
52+
LineFeed = 2,
53+
RootSpacing = 4,
54+
SkipEmptyNodes = 8
55+
}
56+
}
57+
}

source/XML/ToStringFlags.cs

Lines changed: 0 additions & 13 deletions
This file was deleted.

source/XML/XMLNode.cs

Lines changed: 44 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,9 @@ public readonly ReadOnlySpan<char> this[ReadOnlySpan<char> name]
7878
public readonly bool IsDisposed => name.IsDisposed;
7979

8080
#if NET
81+
/// <summary>
82+
/// Creates an empty XML node.
83+
/// </summary>
8184
public XMLNode()
8285
{
8386
name = new(4);
@@ -148,17 +151,16 @@ public void Dispose()
148151
public readonly override string ToString()
149152
{
150153
Text buffer = new(0);
151-
ToStringFlags flags = ToStringFlags.CarriageReturn | ToStringFlags.LineFeed;
152-
ToString(buffer, " ", flags);
154+
ToString(buffer, SerializationSettings.PrettyPrinted);
153155
string str = buffer.AsSpan().ToString();
154156
buffer.Dispose();
155157
return str;
156158
}
157159

158-
public readonly string ToString(string indent, ToStringFlags flags = default)
160+
public readonly string ToString(SerializationSettings settings)
159161
{
160162
Text buffer = new(0);
161-
ToString(buffer, indent, flags);
163+
ToString(buffer, settings);
162164
string str = buffer.AsSpan().ToString();
163165
buffer.Dispose();
164166
return str;
@@ -167,8 +169,15 @@ public readonly string ToString(string indent, ToStringFlags flags = default)
167169
readonly void ISerializable.Write(ByteWriter writer)
168170
{
169171
Text buffer = new(0);
170-
ToStringFlags flags = ToStringFlags.CarriageReturn | ToStringFlags.LineFeed;
171-
ToString(buffer, default, flags, 0);
172+
ToString(buffer, SerializationSettings.PrettyPrinted, 0);
173+
writer.WriteSpan(buffer.AsSpan());
174+
buffer.Dispose();
175+
}
176+
177+
public readonly void Write(ByteWriter writer, SerializationSettings settings)
178+
{
179+
Text buffer = new(0);
180+
ToString(buffer, settings, 0);
172181
writer.WriteSpan(buffer.AsSpan());
173182
buffer.Dispose();
174183
}
@@ -312,21 +321,16 @@ void ISerializable.Read(ByteReader reader)
312321
}
313322
}
314323

315-
public readonly void ToString(Text destination, ReadOnlySpan<char> indent = default, ToStringFlags flags = default)
324+
public readonly void ToString(Text destination, SerializationSettings settings = default)
316325
{
317-
ToString(destination, indent, flags, 0);
326+
ToString(destination, settings, 0);
318327
}
319328

320-
public readonly void ToString(Text destination, string indent = "", ToStringFlags flags = default)
321-
{
322-
ToString(destination, indent.AsSpan(), flags, 0);
323-
}
324-
325-
private readonly void ToString(Text destination, ReadOnlySpan<char> indent, ToStringFlags flags, byte depth)
329+
private readonly void ToString(Text destination, SerializationSettings settings, byte depth)
326330
{
327331
for (int i = 0; i < depth; i++)
328332
{
329-
Indent(indent);
333+
settings.Indent(destination);
330334
}
331335

332336
destination.Append('<');
@@ -336,14 +340,17 @@ private readonly void ToString(Text destination, ReadOnlySpan<char> indent, ToSt
336340
}
337341

338342
destination.Append(Name);
339-
for (int i = 0; i < attributes.Count; i++)
343+
344+
Span<XMLAttribute> attributesSpan = attributes.AsSpan();
345+
for (int i = 0; i < attributesSpan.Length; i++)
340346
{
341347
destination.Append(' ');
342-
XMLAttribute attribute = attributes[i];
348+
XMLAttribute attribute = attributesSpan[i];
343349
attribute.ToString(destination);
344350
}
345351

346-
if (content.Length > 0 || children.Count > 0)
352+
Span<XMLNode> childrenSpan = children.AsSpan();
353+
if (content.Length > 0 || childrenSpan.Length > 0)
347354
{
348355
if (prologue)
349356
{
@@ -356,30 +363,37 @@ private readonly void ToString(Text destination, ReadOnlySpan<char> indent, ToSt
356363

357364
destination.Append('>');
358365
destination.Append(Content);
359-
360-
if (children.Count > 0)
366+
if (childrenSpan.Length > 0)
361367
{
362-
foreach (XMLNode child in children)
368+
for (int c = 0; c < childrenSpan.Length; c++)
363369
{
364-
if (depth == 1 && (flags & ToStringFlags.RootSpacing) == ToStringFlags.RootSpacing)
370+
XMLNode child = childrenSpan[c];
371+
if ((settings.flags & SerializationSettings.Flags.SkipEmptyNodes) == SerializationSettings.Flags.SkipEmptyNodes)
372+
{
373+
if (child.content.Length == 0 && child.children.Count == 0 && child.attributes.Count == 0)
374+
{
375+
continue;
376+
}
377+
}
378+
379+
if (depth == 1 && (settings.flags & SerializationSettings.Flags.RootSpacing) == SerializationSettings.Flags.RootSpacing)
365380
{
366-
NewLine();
381+
settings.NewLine(destination);
367382
}
368383

369-
NewLine();
370-
child.ToString(destination, indent, flags, depth);
384+
settings.NewLine(destination);
385+
child.ToString(destination, settings, depth);
371386
}
372387

373-
374-
if (depth == 1 && (flags & ToStringFlags.RootSpacing) == ToStringFlags.RootSpacing)
388+
if (depth == 1 && (settings.flags & SerializationSettings.Flags.RootSpacing) == SerializationSettings.Flags.RootSpacing)
375389
{
376-
NewLine();
390+
settings.NewLine(destination);
377391
}
378392

379-
NewLine();
393+
settings.NewLine(destination);
380394
for (int i = 0; i < depth - 1; i++)
381395
{
382-
Indent(indent);
396+
settings.Indent(destination);
383397
}
384398
}
385399

@@ -396,24 +410,6 @@ private readonly void ToString(Text destination, ReadOnlySpan<char> indent, ToSt
396410
destination.Append('/');
397411
destination.Append('>');
398412
}
399-
400-
void NewLine()
401-
{
402-
if ((flags & ToStringFlags.CarriageReturn) == ToStringFlags.CarriageReturn)
403-
{
404-
destination.Append('\r');
405-
}
406-
407-
if ((flags & ToStringFlags.LineFeed) == ToStringFlags.LineFeed)
408-
{
409-
destination.Append('\n');
410-
}
411-
}
412-
413-
void Indent(ReadOnlySpan<char> indent)
414-
{
415-
destination.Append(indent);
416-
}
417413
}
418414

419415
/// <summary>

source/XML/XMLReader.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,7 @@ public readonly bool PeekToken(int position, out Token token)
103103
}
104104
else if (!char.IsLetterOrDigit(c))
105105
{
106-
throw new Exception($"Invalid XML, unknown symbol '{c}' inside node");
106+
throw new Exception($"Invalid XML, unknown symbol `{c}` inside node");
107107
}
108108
}
109109

tests/Serialization.Tests.csproj

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,10 @@
3737
<ProjectReference Include="..\..\unmanaged\tests\Unmanaged.Tests.csproj" />
3838
<ProjectReference Include="..\source\Serialization.csproj" />
3939
<ProjectReference Include="..\..\unmanaged\core\Unmanaged.Core.csproj" />
40+
<ProjectReference Include="..\..\unmanaged\generator\Unmanaged.Generator.csproj">
41+
<OutputItemType>Analyzer</OutputItemType>
42+
<ReferenceOutputAssembly>false</ReferenceOutputAssembly>
43+
</ProjectReference>
4044
</ItemGroup>
4145

4246
<ItemGroup>

tests/XMLTests.cs

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,7 @@ public void EmptyNode()
8989

9090
reader.Position = 0;
9191
using XMLNode node = reader.ReadObject<XMLNode>();
92-
string str = node.ToString("");
92+
string str = node.ToString(SerializationSettings.Default);
9393
Assert.That(str, Is.EqualTo(Sample));
9494
}
9595

@@ -149,5 +149,26 @@ public void ReadWithPrologue()
149149
using XMLNode node = xmlReader.ReadNode();
150150
Assert.That(node.IsPrologue, Is.True);
151151
}
152+
153+
[Test]
154+
public void SkipEmptyNodes()
155+
{
156+
using XMLNode node = new("Root");
157+
node.Add(new("Name", "Boa"));
158+
node.Add(new("Type", "Box"));
159+
node.Add(new("Empty"));
160+
161+
SerializationSettings settings = SerializationSettings.PrettyPrinted;
162+
settings.flags |= SerializationSettings.Flags.SkipEmptyNodes;
163+
164+
using ByteReader reader = ByteReader.CreateFromUTF8(node.ToString(settings));
165+
using XMLNode readNode = reader.ReadObject<XMLNode>();
166+
Assert.That(readNode.Name.ToString(), Is.EqualTo("Root"));
167+
Assert.That(readNode.Children.Length, Is.EqualTo(2));
168+
Assert.That(readNode.Children[0].Name.ToString(), Is.EqualTo("Name"));
169+
Assert.That(readNode.Children[0].Content.ToString(), Is.EqualTo("Boa"));
170+
Assert.That(readNode.Children[1].Name.ToString(), Is.EqualTo("Type"));
171+
Assert.That(readNode.Children[1].Content.ToString(), Is.EqualTo("Box"));
172+
}
152173
}
153174
}

0 commit comments

Comments
 (0)