Skip to content

Commit bb7e525

Browse files
committed
keyvalues2_noids encoding support
1 parent ab4143d commit bb7e525

File tree

4 files changed

+72
-38
lines changed

4 files changed

+72
-38
lines changed

Codecs/Binary.cs

+2-2
Original file line numberDiff line numberDiff line change
@@ -228,7 +228,7 @@ public void WriteSelf()
228228
}
229229
StringDictionary StringDict;
230230

231-
public void Encode(Datamodel dm, int encoding_version, Stream stream)
231+
public void Encode(Datamodel dm, string encoding, int encoding_version, Stream stream)
232232
{
233233
using var writer = new DmxBinaryWriter(stream);
234234
var encoder = new Encoder(writer, dm, encoding_version);
@@ -316,7 +316,7 @@ object ReadValue(Datamodel dm, Type type, bool raw_string)
316316
throw new ArgumentException(type == null ? "No type provided to GetValue()" : "Cannot read value of type " + type.Name);
317317
}
318318

319-
public Datamodel Decode(int encoding_version, string format, int format_version, Stream stream, DeferredMode defer_mode)
319+
public Datamodel Decode(string encoding, int encoding_version, string format, int format_version, Stream stream, DeferredMode defer_mode)
320320
{
321321
stream.Seek(0, SeekOrigin.Begin);
322322
while (true)

Codecs/KeyValues2.cs

+54-25
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,10 @@ namespace Datamodel.Codecs
1111
[CodecFormat("keyvalues2", 2)]
1212
[CodecFormat("keyvalues2", 3)]
1313
[CodecFormat("keyvalues2", 4)]
14+
[CodecFormat("keyvalues2_noids", 1)]
15+
[CodecFormat("keyvalues2_noids", 2)]
16+
[CodecFormat("keyvalues2_noids", 3)]
17+
[CodecFormat("keyvalues2_noids", 4)]
1418
class KeyValues2 : ICodec, IDisposable
1519
{
1620
TextReader Reader;
@@ -59,7 +63,7 @@ public int Indent
5963
set
6064
{
6165
indent_count = value;
62-
indent_string = "\n" + String.Concat(Enumerable.Repeat("\t", value));
66+
indent_string = "\n" + string.Concat(Enumerable.Repeat(" ", value));
6367
}
6468
}
6569
int indent_count = 0;
@@ -91,7 +95,7 @@ public void Write(string value)
9195

9296
public void WriteTokens(params string[] values)
9397
{
94-
Output.Write("\"{0}\"", String.Join("\" \"", values.Select(s => Sanitise(s))));
98+
Output.Write('"' + string.Join("\" \"", values.Select(s => Sanitise(s))) + '"');
9599
}
96100

97101
public void WriteLine()
@@ -129,12 +133,16 @@ public void Flush()
129133
Output.Flush();
130134
}
131135
}
136+
137+
string Encoding;
132138
int EncodingVersion;
133139

134140
// Multi-referenced elements are written out as a separate block at the end of the file.
135141
// In-line only the id is written.
136142
Dictionary<Element, int> ReferenceCount;
137143

144+
bool SupportsReferenceIds;
145+
138146
void CountReferences(Element elem)
139147
{
140148
if (ReferenceCount.ContainsKey(elem))
@@ -210,24 +218,29 @@ void WriteAttribute(string name, Type type, object value, bool in_array)
210218

211219
if (in_array)
212220
{
213-
if (elem != null && ReferenceCount[elem] == 1)
221+
if (ShouldBeReferenced(elem))
222+
{
223+
Writer.WriteTokenLine("element", id);
224+
}
225+
else
214226
{
215227
Writer.WriteLine();
216228
WriteElement(elem);
217229
}
218-
else
219-
Writer.WriteTokenLine("element", id);
230+
220231
Writer.Write(",");
221232
}
222233
else
223234
{
224-
if (elem != null && ReferenceCount.ContainsKey(elem) && ReferenceCount[elem] == 1)
235+
if (ShouldBeReferenced(elem))
225236
{
226-
Writer.WriteLine(String.Format("\"{0}\" ", name));
227-
WriteElement(elem);
237+
Writer.WriteTokenLine(name, "element", id);
228238
}
229239
else
230-
Writer.WriteTokenLine(name, "element", id);
240+
{
241+
Writer.WriteLine($"\"{name}\" ");
242+
WriteElement(elem);
243+
}
231244
}
232245
}
233246
else
@@ -237,13 +250,13 @@ void WriteAttribute(string name, Type type, object value, bool in_array)
237250
else if (type == typeof(float))
238251
value = (float)value;
239252
else if (type == typeof(byte[]))
240-
value = BitConverter.ToString((byte[])value).Replace("-", String.Empty);
253+
value = BitConverter.ToString((byte[])value).Replace("-", string.Empty);
241254
else if (type == typeof(TimeSpan))
242255
value = ((TimeSpan)value).TotalSeconds;
243256
else if (type == typeof(Color))
244257
{
245258
var c = (Color)value;
246-
value = String.Join(" ", new int[] { c.R, c.G, c.B, c.A });
259+
value = string.Join(" ", new int[] { c.R, c.G, c.B, c.A });
247260
}
248261
else if (value is ulong ulong_value)
249262
value = $"0x{ulong_value:X}";
@@ -267,13 +280,11 @@ void WriteAttribute(string name, Type type, object value, bool in_array)
267280
}
268281
else if (type == typeof(Quaternion))
269282
{
270-
var arr = new float[4];
271283
var q = (Quaternion)value;
272284
value = string.Join(" ", q.X, q.Y, q.Z, q.W);
273285
}
274286
else if (type == typeof(Matrix4x4))
275287
{
276-
var arr = new float[4 * 4];
277288
var m = (Matrix4x4)value;
278289
value = string.Join(" ", m.M11, m.M12, m.M13, m.M14, m.M21, m.M22, m.M23, m.M24, m.M31, m.M32, m.M33, m.M34, m.M41, m.M42, m.M43, m.M44);
279290
}
@@ -290,14 +301,21 @@ void WriteAttribute(string name, Type type, object value, bool in_array)
290301

291302
}
292303

304+
private bool ShouldBeReferenced(Element elem)
305+
{
306+
return SupportsReferenceIds && (elem == null || ReferenceCount.TryGetValue(elem, out var refCount) && refCount > 1);
307+
}
308+
293309
void WriteElement(Element element)
294310
{
295311
if (TypeNames.ContainsValue(element.ClassName))
296-
throw new CodecException(String.Format("Element {0} uses reserved type name \"{1}\".", element.ID, element.ClassName));
312+
throw new CodecException($"Element {element.ID} uses reserved type name \"{element.ClassName}\"");
297313
Writer.WriteTokens(element.ClassName);
298314
Writer.WriteLine("{");
299315
Writer.Indent++;
300-
Writer.WriteTokenLine("id", "elementid", element.ID.ToString());
316+
317+
if (SupportsReferenceIds)
318+
Writer.WriteTokenLine("id", "elementid", element.ID.ToString());
301319

302320
// Skip empty names right now.
303321
if (!string.IsNullOrEmpty(element.Name))
@@ -317,12 +335,15 @@ void WriteElement(Element element)
317335
Writer.WriteLine("}");
318336
}
319337

320-
public void Encode(Datamodel dm, int encoding_version, Stream stream)
338+
public void Encode(Datamodel dm, string encoding, int encoding_version, Stream stream)
321339
{
322340
Writer = new KV2Writer(stream);
341+
Encoding = encoding;
323342
EncodingVersion = encoding_version;
324343

325-
Writer.Write(String.Format(CodecUtilities.HeaderPattern, "keyvalues2", encoding_version, dm.Format, dm.FormatVersion));
344+
SupportsReferenceIds = Encoding != "keyvalues2_noids";
345+
346+
Writer.Write(String.Format(CodecUtilities.HeaderPattern, encoding, encoding_version, dm.Format, dm.FormatVersion));
326347
Writer.WriteLine();
327348

328349
ReferenceCount = new Dictionary<Element, int>();
@@ -340,17 +361,22 @@ public void Encode(Datamodel dm, int encoding_version, Stream stream)
340361
Writer.WriteLine();
341362
}
342363

343-
CountReferences(dm.Root);
364+
if (SupportsReferenceIds)
365+
CountReferences(dm.Root);
366+
344367
WriteElement(dm.Root);
345368
Writer.WriteLine();
346369

347-
foreach (var pair in ReferenceCount.Where(pair => pair.Value > 1))
370+
if (SupportsReferenceIds)
348371
{
349-
if (pair.Key == dm.Root)
350-
continue;
351-
Writer.WriteLine();
352-
WriteElement(pair.Key);
353-
Writer.WriteLine();
372+
foreach (var pair in ReferenceCount.Where(pair => pair.Value > 1))
373+
{
374+
if (pair.Key == dm.Root)
375+
continue;
376+
Writer.WriteLine();
377+
WriteElement(pair.Key);
378+
Writer.WriteLine();
379+
}
354380
}
355381

356382
Writer.Flush();
@@ -559,10 +585,13 @@ object Decode_ParseValue(Type type, string value)
559585
else throw new ArgumentException($"Internal error: ParseValue passed unsupported type: {type}.");
560586
}
561587

562-
public Datamodel Decode(int encoding_version, string format, int format_version, Stream stream, DeferredMode defer_mode)
588+
public Datamodel Decode(string encoding, int encoding_version, string format, int format_version, Stream stream, DeferredMode defer_mode)
563589
{
564590
DM = new Datamodel(format, format_version);
565591

592+
if (encoding == "keyvalues2_noids")
593+
throw new NotImplementedException("KeyValues2_noids decoding not implemented.");
594+
566595
stream.Seek(0, SeekOrigin.Begin);
567596
Reader = new StreamReader(stream, Datamodel.TextEncoding);
568597
Reader.ReadLine(); // skip DMX header

Datamodel.cs

+12-7
Original file line numberDiff line numberDiff line change
@@ -143,13 +143,18 @@ public static void RegisterCodec(Type type)
143143
foreach (var version in format_attr.Versions)
144144
{
145145
var reg = new CodecRegistration(format_attr.Name, version);
146-
if (Codecs.ContainsKey(reg) && Codecs[reg] != type)
147-
{
148-
Trace.TraceInformation("Datamodel.NET: Replacing existing codec for {0} {1} ({2}) with {3}", format_attr.Name, version, Codecs[reg].Name, type.Name);
149-
}
146+
AddCodec(type, format_attr, reg);
147+
}
148+
}
150149

151-
Codecs[reg] = type;
150+
static void AddCodec(Type type, CodecFormatAttribute format_attr, CodecRegistration reg)
151+
{
152+
if (Codecs.ContainsKey(reg) && Codecs[reg] != type)
153+
{
154+
Trace.TraceInformation("Datamodel.NET: Replacing existing codec for {0} {1} ({2}) with {3}", format_attr.Name, reg.Item2, Codecs[reg].Name, type.Name);
152155
}
156+
157+
Codecs[reg] = type;
153158
}
154159
}
155160

@@ -202,7 +207,7 @@ public void Save(Stream stream, string encoding, int encoding_version)
202207
throw new InvalidOperationException(FormatBlankError);
203208
}
204209

205-
GetCodec(encoding, encoding_version).Encode(this, encoding_version, stream);
210+
GetCodec(encoding, encoding_version).Encode(this, encoding, encoding_version, stream);
206211
}
207212

208213
/// <summary>
@@ -289,7 +294,7 @@ private static Datamodel Load_Internal(Stream stream, DeferredMode defer_mode =
289294

290295
ICodec codec = GetCodec(encoding, encoding_version);
291296

292-
var dm = codec.Decode(encoding_version, format, format_version, stream, defer_mode);
297+
var dm = codec.Decode(encoding, encoding_version, format, format_version, stream, defer_mode);
293298
if (defer_mode == DeferredMode.Automatic && codec is IDeferredAttributeCodec deferredCodec)
294299
{
295300
dm.Stream = stream;

ICodec.cs

+4-4
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ public interface ICodec
1818
/// <param name="dm">The Datamodel to encode.</param>
1919
/// <param name="encoding_version">The encoding version to use.</param>
2020
/// <param name="stream">The output stream.</param>
21-
void Encode(Datamodel dm, int encoding_version, Stream stream);
21+
void Encode(Datamodel dm, string encoding, int encoding_version, Stream stream);
2222

2323
/// <summary>
2424
/// Decodes a <see cref="Datamodel"/> from a <see cref="Stream"/>.
@@ -29,7 +29,7 @@ public interface ICodec
2929
/// <param name="stream">The input stream. Its position will always be 0. Do not dispose.</param>
3030
/// <param name="defer_mode">The deferred loading mode specified by the caller. Only relevant to implementers of <see cref="IDeferredAttributeCodec"/></param>
3131
/// <returns></returns>
32-
Datamodel Decode(int encoding_version, string format, int format_version, Stream stream, DeferredMode defer_mode);
32+
Datamodel Decode(string encoding, int encoding_version, string format, int format_version, Stream stream, DeferredMode defer_mode);
3333
}
3434

3535
/// <summary>
@@ -154,7 +154,7 @@ public static System.Collections.IList MakeList(Type t, System.Collections.IEnum
154154
if (t == typeof(byte))
155155
return new ByteArray(source.Cast<byte>());
156156
if (t == typeof(ulong))
157-
return new UInt64Array(source.Cast<UInt64>());
157+
return new UInt64Array(source.Cast<ulong>());
158158

159159
throw new ArgumentException("Unrecognised Type.");
160160
}
@@ -167,7 +167,7 @@ public static System.Collections.IList MakeList(Type t, System.Collections.IEnum
167167
/// <param name="defer_offset">The location in the encoded DMX stream at which this Attribute's value can be found.</param>
168168
public static void AddDeferredAttribute(Element elem, string key, long offset)
169169
{
170-
if (offset <= 0) throw new ArgumentOutOfRangeException("offset", "Address must be greater than 0.");
170+
if (offset <= 0) throw new ArgumentOutOfRangeException(nameof(offset), "Address must be greater than 0.");
171171
elem.Add(key, offset);
172172
}
173173
}

0 commit comments

Comments
 (0)