@@ -11,6 +11,10 @@ namespace Datamodel.Codecs
11
11
[ CodecFormat ( "keyvalues2" , 2 ) ]
12
12
[ CodecFormat ( "keyvalues2" , 3 ) ]
13
13
[ CodecFormat ( "keyvalues2" , 4 ) ]
14
+ [ CodecFormat ( "keyvalues2_noids" , 1 ) ]
15
+ [ CodecFormat ( "keyvalues2_noids" , 2 ) ]
16
+ [ CodecFormat ( "keyvalues2_noids" , 3 ) ]
17
+ [ CodecFormat ( "keyvalues2_noids" , 4 ) ]
14
18
class KeyValues2 : ICodec , IDisposable
15
19
{
16
20
TextReader Reader ;
@@ -59,7 +63,7 @@ public int Indent
59
63
set
60
64
{
61
65
indent_count = value ;
62
- indent_string = "\n " + String . Concat ( Enumerable . Repeat ( "\t " , value ) ) ;
66
+ indent_string = "\n " + string . Concat ( Enumerable . Repeat ( " " , value ) ) ;
63
67
}
64
68
}
65
69
int indent_count = 0 ;
@@ -91,7 +95,7 @@ public void Write(string value)
91
95
92
96
public void WriteTokens ( params string [ ] values )
93
97
{
94
- Output . Write ( " \" {0} \" " , String . Join ( "\" \" " , values . Select ( s => Sanitise ( s ) ) ) ) ;
98
+ Output . Write ( '"' + string . Join ( "\" \" " , values . Select ( s => Sanitise ( s ) ) ) + '"' ) ;
95
99
}
96
100
97
101
public void WriteLine ( )
@@ -129,12 +133,16 @@ public void Flush()
129
133
Output . Flush ( ) ;
130
134
}
131
135
}
136
+
137
+ string Encoding ;
132
138
int EncodingVersion ;
133
139
134
140
// Multi-referenced elements are written out as a separate block at the end of the file.
135
141
// In-line only the id is written.
136
142
Dictionary < Element , int > ReferenceCount ;
137
143
144
+ bool SupportsReferenceIds ;
145
+
138
146
void CountReferences ( Element elem )
139
147
{
140
148
if ( ReferenceCount . ContainsKey ( elem ) )
@@ -210,24 +218,29 @@ void WriteAttribute(string name, Type type, object value, bool in_array)
210
218
211
219
if ( in_array )
212
220
{
213
- if ( elem != null && ReferenceCount [ elem ] == 1 )
221
+ if ( ShouldBeReferenced ( elem ) )
222
+ {
223
+ Writer . WriteTokenLine ( "element" , id ) ;
224
+ }
225
+ else
214
226
{
215
227
Writer . WriteLine ( ) ;
216
228
WriteElement ( elem ) ;
217
229
}
218
- else
219
- Writer . WriteTokenLine ( "element" , id ) ;
230
+
220
231
Writer . Write ( "," ) ;
221
232
}
222
233
else
223
234
{
224
- if ( elem != null && ReferenceCount . ContainsKey ( elem ) && ReferenceCount [ elem ] == 1 )
235
+ if ( ShouldBeReferenced ( elem ) )
225
236
{
226
- Writer . WriteLine ( String . Format ( "\" {0}\" " , name ) ) ;
227
- WriteElement ( elem ) ;
237
+ Writer . WriteTokenLine ( name , "element" , id ) ;
228
238
}
229
239
else
230
- Writer . WriteTokenLine ( name , "element" , id ) ;
240
+ {
241
+ Writer . WriteLine ( $ "\" { name } \" ") ;
242
+ WriteElement ( elem ) ;
243
+ }
231
244
}
232
245
}
233
246
else
@@ -237,13 +250,13 @@ void WriteAttribute(string name, Type type, object value, bool in_array)
237
250
else if ( type == typeof ( float ) )
238
251
value = ( float ) value ;
239
252
else if ( type == typeof ( byte [ ] ) )
240
- value = BitConverter . ToString ( ( byte [ ] ) value ) . Replace ( "-" , String . Empty ) ;
253
+ value = BitConverter . ToString ( ( byte [ ] ) value ) . Replace ( "-" , string . Empty ) ;
241
254
else if ( type == typeof ( TimeSpan ) )
242
255
value = ( ( TimeSpan ) value ) . TotalSeconds ;
243
256
else if ( type == typeof ( Color ) )
244
257
{
245
258
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 } ) ;
247
260
}
248
261
else if ( value is ulong ulong_value )
249
262
value = $ "0x{ ulong_value : X} ";
@@ -267,13 +280,11 @@ void WriteAttribute(string name, Type type, object value, bool in_array)
267
280
}
268
281
else if ( type == typeof ( Quaternion ) )
269
282
{
270
- var arr = new float [ 4 ] ;
271
283
var q = ( Quaternion ) value ;
272
284
value = string . Join ( " " , q . X , q . Y , q . Z , q . W ) ;
273
285
}
274
286
else if ( type == typeof ( Matrix4x4 ) )
275
287
{
276
- var arr = new float [ 4 * 4 ] ;
277
288
var m = ( Matrix4x4 ) value ;
278
289
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 ) ;
279
290
}
@@ -290,14 +301,21 @@ void WriteAttribute(string name, Type type, object value, bool in_array)
290
301
291
302
}
292
303
304
+ private bool ShouldBeReferenced ( Element elem )
305
+ {
306
+ return SupportsReferenceIds && ( elem == null || ReferenceCount . TryGetValue ( elem , out var refCount ) && refCount > 1 ) ;
307
+ }
308
+
293
309
void WriteElement ( Element element )
294
310
{
295
311
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 } \" " ) ;
297
313
Writer . WriteTokens ( element . ClassName ) ;
298
314
Writer . WriteLine ( "{" ) ;
299
315
Writer . Indent ++ ;
300
- Writer . WriteTokenLine ( "id" , "elementid" , element . ID . ToString ( ) ) ;
316
+
317
+ if ( SupportsReferenceIds )
318
+ Writer . WriteTokenLine ( "id" , "elementid" , element . ID . ToString ( ) ) ;
301
319
302
320
// Skip empty names right now.
303
321
if ( ! string . IsNullOrEmpty ( element . Name ) )
@@ -317,12 +335,15 @@ void WriteElement(Element element)
317
335
Writer . WriteLine ( "}" ) ;
318
336
}
319
337
320
- public void Encode ( Datamodel dm , int encoding_version , Stream stream )
338
+ public void Encode ( Datamodel dm , string encoding , int encoding_version , Stream stream )
321
339
{
322
340
Writer = new KV2Writer ( stream ) ;
341
+ Encoding = encoding ;
323
342
EncodingVersion = encoding_version ;
324
343
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 ) ) ;
326
347
Writer . WriteLine ( ) ;
327
348
328
349
ReferenceCount = new Dictionary < Element , int > ( ) ;
@@ -340,17 +361,22 @@ public void Encode(Datamodel dm, int encoding_version, Stream stream)
340
361
Writer . WriteLine ( ) ;
341
362
}
342
363
343
- CountReferences ( dm . Root ) ;
364
+ if ( SupportsReferenceIds )
365
+ CountReferences ( dm . Root ) ;
366
+
344
367
WriteElement ( dm . Root ) ;
345
368
Writer . WriteLine ( ) ;
346
369
347
- foreach ( var pair in ReferenceCount . Where ( pair => pair . Value > 1 ) )
370
+ if ( SupportsReferenceIds )
348
371
{
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
+ }
354
380
}
355
381
356
382
Writer . Flush ( ) ;
@@ -559,10 +585,13 @@ object Decode_ParseValue(Type type, string value)
559
585
else throw new ArgumentException ( $ "Internal error: ParseValue passed unsupported type: { type } .") ;
560
586
}
561
587
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 )
563
589
{
564
590
DM = new Datamodel ( format , format_version ) ;
565
591
592
+ if ( encoding == "keyvalues2_noids" )
593
+ throw new NotImplementedException ( "KeyValues2_noids decoding not implemented." ) ;
594
+
566
595
stream . Seek ( 0 , SeekOrigin . Begin ) ;
567
596
Reader = new StreamReader ( stream , Datamodel . TextEncoding ) ;
568
597
Reader . ReadLine ( ) ; // skip DMX header
0 commit comments