Implementation of GetLoopbackInterfaceIndex on Windows
[mono.git] / mcs / class / referencesource / mscorlib / system / runtime / serialization / formatters / binary / binaryformatterwriter.cs
1 // ==++==
2 //
3 //   Copyright (c) Microsoft Corporation.  All rights reserved.
4 //
5 // ==--==
6 /*============================================================
7  **
8  ** Class: BinaryWriter
9  **
10  **
11  ** Purpose: Writes primitive values to a stream
12  **
13  **
14  ===========================================================*/
15
16 namespace System.Runtime.Serialization.Formatters.Binary {
17
18     using System;
19     using System.Collections;
20     using System.IO;
21     using System.Reflection;
22     using System.Text;
23     using System.Globalization;
24     using System.Runtime.Serialization.Formatters;
25     using System.Configuration.Assemblies;
26     using System.Threading;
27     using System.Runtime.Remoting;
28     using System.Runtime.Serialization;
29
30     internal sealed class __BinaryWriter
31     {
32         internal Stream sout;
33         internal FormatterTypeStyle formatterTypeStyle;
34         internal Hashtable objectMapTable;
35         internal ObjectWriter objectWriter = null;
36         internal BinaryWriter dataWriter = null;
37
38 // disable csharp compiler warning #0414: field assigned unused value
39 #pragma warning disable 0414
40         internal int m_nestedObjectCount;
41 #pragma warning restore 0414
42         private int nullCount = 0; //Count of consecutive array nulls
43
44         // Constructor
45         internal __BinaryWriter(Stream sout, ObjectWriter objectWriter, FormatterTypeStyle formatterTypeStyle)
46         {
47             SerTrace.Log( this, "BinaryWriter ");
48             this.sout = sout;
49             this.formatterTypeStyle = formatterTypeStyle;
50             this.objectWriter = objectWriter;
51             m_nestedObjectCount = 0;
52             dataWriter = new BinaryWriter(sout, Encoding.UTF8);
53         }
54
55         internal void WriteBegin()
56         {
57             BCLDebug.Trace("BINARY", "\n%%%%%BinaryWriterBegin%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n");
58         }
59
60         internal void WriteEnd()
61         {
62             BCLDebug.Trace("BINARY", "\n%%%%%BinaryWriterEnd%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n");
63             dataWriter.Flush();
64         }
65
66         // Methods to write a value onto the stream
67         internal void WriteBoolean(Boolean value)
68         {
69             dataWriter.Write(value);
70         }
71
72         internal void WriteByte(Byte value)
73         {
74             dataWriter.Write(value);
75         }
76
77         private void WriteBytes(Byte[] value)
78         {
79             dataWriter.Write(value);
80         }
81
82         private void WriteBytes(byte[] byteA, int offset, int size)
83         {
84             dataWriter.Write(byteA, offset, size);
85         }
86
87         internal void WriteChar(Char value)
88         {
89             dataWriter.Write(value);
90         }
91
92         internal void WriteChars(Char[] value)
93         {
94             dataWriter.Write(value);
95         }
96
97
98         internal void WriteDecimal(Decimal value)
99         {
100             WriteString(value.ToString(CultureInfo.InvariantCulture));
101         }
102
103         internal void WriteSingle(Single value)
104         {
105             dataWriter.Write(value);
106         }
107
108         internal void WriteDouble(Double value)
109         {
110             dataWriter.Write(value);
111         }
112
113         internal void WriteInt16(Int16 value)
114         {
115             dataWriter.Write(value);
116         }
117
118         internal void WriteInt32(Int32 value)
119         {
120             dataWriter.Write(value);
121         }
122
123         internal void WriteInt64(Int64 value)
124         {
125             dataWriter.Write(value);
126         }
127
128         internal void WriteSByte(SByte value)
129         {
130             WriteByte((Byte)value);
131         }
132
133         internal void WriteString(String value)
134         {
135             dataWriter.Write(value);
136         }
137
138         internal void WriteTimeSpan(TimeSpan value)
139         {
140             WriteInt64(value.Ticks);
141         }
142
143         internal void WriteDateTime(DateTime value)
144         {
145             WriteInt64(value.ToBinaryRaw());
146         }
147
148         internal void WriteUInt16(UInt16 value)
149         {
150             dataWriter.Write(value);
151         }
152
153         internal void WriteUInt32(UInt32 value)
154         {
155             dataWriter.Write(value);
156         }
157
158         internal void WriteUInt64(UInt64 value)
159         {
160             dataWriter.Write(value);
161         }
162
163         internal void WriteObjectEnd(NameInfo memberNameInfo, NameInfo typeNameInfo)
164         {
165         }
166
167         internal void WriteSerializationHeaderEnd()
168         {
169             MessageEnd record = new MessageEnd();
170             record.Dump(sout);
171             record.Write(this);
172         }
173
174         // Methods to write Binary Serialization Record onto the stream, a record is composed of primitive types
175
176         internal void WriteSerializationHeader(int topId, int headerId, int minorVersion, int majorVersion)
177         {
178             SerializationHeaderRecord record = new SerializationHeaderRecord(BinaryHeaderEnum.SerializedStreamHeader, topId, headerId, minorVersion, majorVersion);
179             record.Dump();
180             record.Write(this);
181         }
182
183
184         internal BinaryMethodCall binaryMethodCall;
185         internal void WriteMethodCall()
186         {
187             if (binaryMethodCall == null)
188                 binaryMethodCall = new BinaryMethodCall();
189
190             binaryMethodCall.Dump();
191             binaryMethodCall.Write(this);
192         }
193
194         internal Object[] WriteCallArray(String uri, String methodName, String typeName, Type[] instArgs, Object[] args, Object methodSignature, Object callContext, Object[] properties)
195         {
196             if (binaryMethodCall == null)
197                 binaryMethodCall = new BinaryMethodCall();
198             return binaryMethodCall.WriteArray(uri, methodName, typeName, instArgs, args, methodSignature, callContext, properties);
199         }
200
201         internal BinaryMethodReturn binaryMethodReturn;
202         internal void WriteMethodReturn()
203         {
204             if (binaryMethodReturn == null)
205                 binaryMethodReturn = new BinaryMethodReturn();
206             binaryMethodReturn.Dump();
207             binaryMethodReturn.Write(this);
208         }
209
210         internal Object[] WriteReturnArray(Object returnValue, Object[] args, Exception exception, Object callContext, Object[] properties)
211         {
212             if (binaryMethodReturn == null)
213                 binaryMethodReturn = new BinaryMethodReturn();
214             return binaryMethodReturn.WriteArray(returnValue, args, exception, callContext, properties);
215         }
216
217         internal BinaryObject binaryObject;
218         internal BinaryObjectWithMap binaryObjectWithMap;
219         internal BinaryObjectWithMapTyped binaryObjectWithMapTyped;
220         //internal BinaryCrossAppDomainMap crossAppDomainMap;
221
222         internal void WriteObject(NameInfo nameInfo, NameInfo typeNameInfo, int numMembers, String[] memberNames, Type[] memberTypes, WriteObjectInfo[] memberObjectInfos)
223         {
224             InternalWriteItemNull();
225             int assemId;
226 #if _DEBUG                        
227             nameInfo.Dump("WriteObject nameInfo");
228             typeNameInfo.Dump("WriteObject typeNameInfo");
229 #endif            
230
231             int objectId = (int)nameInfo.NIobjectId;
232
233             //if (objectId < 0)
234             //  objectId = --m_nestedObjectCount;
235
236             if (objectId > 0)
237             {
238                 BCLDebug.Trace("BINARY", "-----Top Level Object-----");
239             }
240
241             String objectName = null;
242             if (objectId < 0)
243             {
244                 // Nested Object
245                 objectName = typeNameInfo.NIname;
246             }
247             else
248             {
249                 // Non-Nested
250                 objectName = nameInfo.NIname;
251             }
252             SerTrace.Log( this, "WriteObject objectName ",objectName);
253
254             if (objectMapTable == null)
255             {
256                 objectMapTable = new Hashtable();
257             }
258
259             ObjectMapInfo objectMapInfo = (ObjectMapInfo)objectMapTable[objectName];
260
261             if (objectMapInfo != null && objectMapInfo.isCompatible(numMembers, memberNames, memberTypes))
262             {
263                 // Object
264                 if (binaryObject == null)
265                     binaryObject = new BinaryObject();            
266                 binaryObject.Set(objectId, objectMapInfo.objectId);
267 #if _DEBUG                        
268                 binaryObject.Dump();
269 #endif
270                 binaryObject.Write(this);
271             }
272             else if (!typeNameInfo.NItransmitTypeOnObject)
273             {
274
275                 // ObjectWithMap
276                 if (binaryObjectWithMap == null)
277                     binaryObjectWithMap = new BinaryObjectWithMap();
278
279                 // BCL types are not placed into table
280                 assemId = (int)typeNameInfo.NIassemId;
281                 binaryObjectWithMap.Set(objectId, objectName, numMembers, memberNames, assemId);
282
283                 binaryObjectWithMap.Dump();
284                 binaryObjectWithMap.Write(this);
285                 if (objectMapInfo == null)
286                     objectMapTable.Add(objectName, new ObjectMapInfo(objectId, numMembers, memberNames, memberTypes));
287             }
288             else
289             {
290                 // ObjectWithMapTyped
291                 BinaryTypeEnum[] binaryTypeEnumA = new BinaryTypeEnum[numMembers];
292                 Object[] typeInformationA = new Object[numMembers];
293                 int[] assemIdA = new int[numMembers];
294                 for (int i=0; i<numMembers; i++)
295                 {
296                     Object typeInformation = null;
297
298                     binaryTypeEnumA[i] = BinaryConverter.GetBinaryTypeInfo(memberTypes[i], memberObjectInfos[i], null, objectWriter, out typeInformation, out assemId);
299                     typeInformationA[i] = typeInformation;
300                     assemIdA[i] = assemId;
301                     SerTrace.Log( this, "WriteObject ObjectWithMapTyped memberNames "
302                                   ,memberNames[i],", memberType ",memberTypes[i]," binaryTypeEnum ",((Enum)binaryTypeEnumA[i]).ToString()
303                                   ,", typeInformation ",typeInformationA[i]," assemId ",assemIdA[i]);
304                 }
305
306                 if (binaryObjectWithMapTyped == null)
307                     binaryObjectWithMapTyped = new BinaryObjectWithMapTyped();            
308
309                 // BCL types are not placed in table
310                 assemId = (int)typeNameInfo.NIassemId;
311                 binaryObjectWithMapTyped.Set(objectId, objectName, numMembers,memberNames, binaryTypeEnumA, typeInformationA, assemIdA, assemId);
312 #if _DEBUG
313                 binaryObjectWithMapTyped.Dump();
314 #endif
315                 binaryObjectWithMapTyped.Write(this);
316                 if (objectMapInfo == null)
317                     objectMapTable.Add(objectName, new ObjectMapInfo(objectId, numMembers, memberNames, memberTypes));
318             }
319         }
320
321         internal BinaryObjectString binaryObjectString;
322         internal BinaryCrossAppDomainString binaryCrossAppDomainString;
323
324         internal void WriteObjectString(int objectId, String value)
325         {
326             InternalWriteItemNull();
327
328             if (binaryObjectString == null)
329                 binaryObjectString = new BinaryObjectString();            
330             binaryObjectString.Set(objectId, value);
331 #if _DEBUG                        
332             binaryObjectString.Dump();
333 #endif
334             binaryObjectString.Write(this);
335         }
336
337         internal BinaryArray binaryArray;
338
339         [System.Security.SecurityCritical]  // auto-generated
340         internal void WriteSingleArray(NameInfo memberNameInfo, NameInfo arrayNameInfo, WriteObjectInfo objectInfo, NameInfo arrayElemTypeNameInfo, int length, int lowerBound, Array array)
341         {
342             InternalWriteItemNull();            
343 #if _DEBUG                        
344             arrayNameInfo.Dump("WriteSingleArray arrayNameInfo");
345             arrayElemTypeNameInfo.Dump("WriteSingleArray arrayElemTypeNameInfo");
346 #endif
347             BinaryArrayTypeEnum binaryArrayTypeEnum;
348             Int32[] lengthA = new Int32[1];
349             lengthA[0] = length;
350             Int32[] lowerBoundA = null;
351             Object typeInformation = null;
352
353             if (lowerBound == 0)
354             {
355                 binaryArrayTypeEnum = BinaryArrayTypeEnum.Single;
356             }
357             else
358             {
359                 binaryArrayTypeEnum = BinaryArrayTypeEnum.SingleOffset;
360                 lowerBoundA = new Int32[1];
361                 lowerBoundA[0] = lowerBound;
362             }
363
364             int assemId;
365
366             BinaryTypeEnum binaryTypeEnum = BinaryConverter.GetBinaryTypeInfo(arrayElemTypeNameInfo.NItype, objectInfo, arrayElemTypeNameInfo.NIname, objectWriter, out typeInformation, out assemId);
367
368             if (binaryArray == null)
369                 binaryArray = new BinaryArray();
370             binaryArray.Set((int)arrayNameInfo.NIobjectId, (int)1, lengthA, lowerBoundA, binaryTypeEnum, typeInformation, binaryArrayTypeEnum, assemId);
371
372             if (arrayNameInfo.NIobjectId >0)
373             {
374                 BCLDebug.Trace("BINARY", "-----Top Level Object-----");
375             }
376 #if _DEBUG                        
377             binaryArray.Dump();
378 #endif
379             binaryArray.Write(this);
380
381             if (Converter.IsWriteAsByteArray(arrayElemTypeNameInfo.NIprimitiveTypeEnum) && (lowerBound == 0))
382             {
383                 //array is written out as an array of bytes
384                 if (arrayElemTypeNameInfo.NIprimitiveTypeEnum == InternalPrimitiveTypeE.Byte)
385                     WriteBytes((Byte[])array);
386                 else if (arrayElemTypeNameInfo.NIprimitiveTypeEnum == InternalPrimitiveTypeE.Char)
387                     WriteChars((char[])array);
388                 else
389                     WriteArrayAsBytes(array, Converter.TypeLength(arrayElemTypeNameInfo.NIprimitiveTypeEnum));
390             }
391         }
392
393         byte[] byteBuffer = null;
394         int chunkSize = 4096;
395
396         [System.Security.SecurityCritical]  // auto-generated
397         private void WriteArrayAsBytes(Array array, int typeLength)
398         {
399             InternalWriteItemNull();
400             int byteLength = array.Length*typeLength;
401             int arrayOffset = 0;
402             if (byteBuffer == null)
403                 byteBuffer = new byte[chunkSize];
404
405             while (arrayOffset < array.Length)
406             {
407                 int numArrayItems = Math.Min(chunkSize/typeLength, array.Length-arrayOffset);
408                 int bufferUsed = numArrayItems*typeLength;
409                 Buffer.InternalBlockCopy(array, arrayOffset*typeLength, byteBuffer, 0, bufferUsed);
410 if (!BitConverter.IsLittleEndian) {
411                 // we know that we are writing a primitive type, so just do a simple swap
412                 for (int i = 0; i < bufferUsed; i += typeLength) 
413                 {
414                     for (int j = 0; j < typeLength / 2; j++) 
415                     {
416                         byte tmp = byteBuffer[i + j];
417                         byteBuffer[i + j] = byteBuffer[i + typeLength-1 - j];
418                         byteBuffer[i + typeLength-1 - j] = tmp;
419                     }
420                 }
421 }
422                 WriteBytes(byteBuffer, 0, bufferUsed);
423                 arrayOffset += numArrayItems;
424             }
425         }
426
427
428         internal void WriteJaggedArray(NameInfo memberNameInfo, NameInfo arrayNameInfo, WriteObjectInfo objectInfo, NameInfo arrayElemTypeNameInfo, int length, int lowerBound)
429         {
430 #if _DEBUG                        
431             arrayNameInfo.Dump("WriteRectangleArray arrayNameInfo");
432             arrayElemTypeNameInfo.Dump("WriteRectangleArray arrayElemTypeNameInfo");
433 #endif     
434             InternalWriteItemNull();
435             BinaryArrayTypeEnum binaryArrayTypeEnum;
436             Int32[] lengthA = new Int32[1];
437             lengthA[0] = length;
438             Int32[] lowerBoundA = null;
439             Object typeInformation = null;
440             int assemId = 0;
441
442             if (lowerBound == 0)
443             {
444                 binaryArrayTypeEnum = BinaryArrayTypeEnum.Jagged;
445             }
446             else
447             {
448                 binaryArrayTypeEnum = BinaryArrayTypeEnum.JaggedOffset;
449                 lowerBoundA = new Int32[1];
450                 lowerBoundA[0] = lowerBound;
451             }
452
453             BinaryTypeEnum binaryTypeEnum = BinaryConverter.GetBinaryTypeInfo(arrayElemTypeNameInfo.NItype, objectInfo, arrayElemTypeNameInfo.NIname, objectWriter, out typeInformation, out assemId);
454
455             if (binaryArray == null)
456                 binaryArray = new BinaryArray();
457             binaryArray.Set((int)arrayNameInfo.NIobjectId, (int)1, lengthA, lowerBoundA, binaryTypeEnum, typeInformation, binaryArrayTypeEnum, assemId);
458
459             if (arrayNameInfo.NIobjectId >0)
460             {
461                 BCLDebug.Trace("BINARY", "-----Top Level Object-----");
462             }
463 #if _DEBUG                        
464             binaryArray.Dump();
465 #endif
466             binaryArray.Write(this);
467         }
468
469         internal void WriteRectangleArray(NameInfo memberNameInfo, NameInfo arrayNameInfo, WriteObjectInfo objectInfo, NameInfo arrayElemTypeNameInfo, int rank, int[] lengthA, int[] lowerBoundA)
470         {
471 #if _DEBUG                        
472             arrayNameInfo.Dump("WriteRectangleArray arrayNameInfo");
473             arrayElemTypeNameInfo.Dump("WriteRectangleArray arrayElemTypeNameInfo");
474 #endif      
475             InternalWriteItemNull();
476
477             BinaryArrayTypeEnum binaryArrayTypeEnum = BinaryArrayTypeEnum.Rectangular;
478             Object typeInformation = null;
479             int assemId = 0;
480             BinaryTypeEnum binaryTypeEnum = BinaryConverter.GetBinaryTypeInfo(arrayElemTypeNameInfo.NItype, objectInfo, arrayElemTypeNameInfo.NIname, objectWriter, out typeInformation, out assemId);
481
482             if (binaryArray == null)
483                 binaryArray = new BinaryArray();
484
485             for (int i=0; i<rank; i++)
486             {
487                 if (lowerBoundA[i] != 0)
488                 {
489                     binaryArrayTypeEnum = BinaryArrayTypeEnum.RectangularOffset;
490                     break;
491                 }
492
493             }
494
495             binaryArray.Set((int)arrayNameInfo.NIobjectId, rank, lengthA, lowerBoundA, binaryTypeEnum, typeInformation, binaryArrayTypeEnum, assemId);
496
497             if (arrayNameInfo.NIobjectId >0)
498             {
499                 BCLDebug.Trace("BINARY", "-----Top Level Object-----");
500             }
501 #if _DEBUG                        
502             binaryArray.Dump();
503 #endif
504             binaryArray.Write(this);
505         }
506
507
508         [System.Security.SecurityCritical]  // auto-generated
509         internal void WriteObjectByteArray(NameInfo memberNameInfo, NameInfo arrayNameInfo, WriteObjectInfo objectInfo, NameInfo arrayElemTypeNameInfo, int length, int lowerBound, Byte[] byteA)
510         {
511 #if _DEBUG                        
512             arrayNameInfo.Dump("WriteObjectByteArray arrayNameInfo");
513             arrayElemTypeNameInfo.Dump("WriteObjectByteArray arrayElemTypeNameInfo");
514 #endif      
515             InternalWriteItemNull();
516             WriteSingleArray(memberNameInfo, arrayNameInfo, objectInfo, arrayElemTypeNameInfo, length, lowerBound, byteA);
517         }
518
519         internal MemberPrimitiveUnTyped memberPrimitiveUnTyped;
520         internal MemberPrimitiveTyped memberPrimitiveTyped;
521
522         internal void WriteMember(NameInfo memberNameInfo, NameInfo typeNameInfo, Object value)
523         {
524 #if _DEBUG                        
525             SerTrace.Log("BinaryWriter", "Write Member memberName ",memberNameInfo.NIname,", value ",value);
526             memberNameInfo.Dump("WriteMember memberNameInfo");
527             typeNameInfo.Dump("WriteMember typeNameInfo");
528 #endif      
529             InternalWriteItemNull();
530             InternalPrimitiveTypeE typeInformation = typeNameInfo.NIprimitiveTypeEnum;
531
532             // Writes Members with primitive values
533
534             if (memberNameInfo.NItransmitTypeOnMember)
535             {
536                 if (memberPrimitiveTyped == null)
537                     memberPrimitiveTyped = new MemberPrimitiveTyped();
538                 memberPrimitiveTyped.Set((InternalPrimitiveTypeE)typeInformation, value);
539
540                 if (memberNameInfo.NIisArrayItem)
541                 {
542                     BCLDebug.Trace("BINARY",  "-----item-----");
543                 }
544                 else
545                 {
546                     BCLDebug.Trace("BINARY","-----",memberNameInfo.NIname,"-----");
547                 }
548                 memberPrimitiveTyped.Dump();
549
550                 memberPrimitiveTyped.Write(this);
551             }
552             else
553             {
554                 if (memberPrimitiveUnTyped == null)
555                     memberPrimitiveUnTyped = new MemberPrimitiveUnTyped();
556                 memberPrimitiveUnTyped.Set(typeInformation, value);
557
558                 if (memberNameInfo.NIisArrayItem)
559                 {
560                     BCLDebug.Trace("BINARY", "-----item-----");
561                 }
562                 else
563                 {
564                     BCLDebug.Trace("BINARY", "-----",memberNameInfo.NIname,"-----");
565                 }
566                 memberPrimitiveUnTyped.Dump();
567
568                 memberPrimitiveUnTyped.Write(this);
569
570             }
571         }
572
573         internal ObjectNull objectNull;
574
575
576         internal void WriteNullMember(NameInfo memberNameInfo, NameInfo typeNameInfo)
577         {
578 #if _DEBUG                        
579             typeNameInfo.Dump("WriteNullMember typeNameInfo");
580 #endif
581             InternalWriteItemNull();
582             if (objectNull == null)
583                 objectNull = new ObjectNull();
584
585             if (memberNameInfo.NIisArrayItem)
586             {
587                 BCLDebug.Trace("BINARY",  "-----item-----");
588             }
589             else
590             {
591                 objectNull.SetNullCount(1);
592                 BCLDebug.Trace("BINARY", "-----",memberNameInfo.NIname,"-----");
593                 objectNull.Dump();
594                 objectNull.Write(this);
595                 nullCount = 0;
596             }
597         }
598
599         internal MemberReference memberReference;
600
601         internal void WriteMemberObjectRef(NameInfo memberNameInfo, int idRef)
602         {
603             InternalWriteItemNull();
604             if (memberReference == null)
605                 memberReference = new MemberReference();
606             memberReference.Set(idRef);
607
608             if (memberNameInfo.NIisArrayItem)
609             {
610                 BCLDebug.Trace("BINARY", "-----item-----");
611             }
612             else
613             {
614                 BCLDebug.Trace("BINARY", "-----",memberNameInfo.NIname,"-----");
615             }
616             memberReference.Dump();
617
618             memberReference.Write(this);
619         }
620
621         internal void WriteMemberNested(NameInfo memberNameInfo)
622         {
623             InternalWriteItemNull();
624             if (memberNameInfo.NIisArrayItem)
625             {
626                 BCLDebug.Trace("BINARY", "-----item-----");
627             }
628             else
629             {
630                 BCLDebug.Trace("BINARY", "-----",memberNameInfo.NIname,"-----");
631             }
632         }
633
634         internal void WriteMemberString(NameInfo memberNameInfo, NameInfo typeNameInfo, String value)
635         {
636             InternalWriteItemNull();
637             if (memberNameInfo.NIisArrayItem)
638             {
639                 BCLDebug.Trace("BINARY", "-----item-----");
640             }
641             else
642             {
643                 BCLDebug.Trace("BINARY", "-----",memberNameInfo.NIname,"-----");
644             }
645             WriteObjectString((int)typeNameInfo.NIobjectId, value);
646         }
647
648         internal void WriteItem(NameInfo itemNameInfo, NameInfo typeNameInfo, Object value)
649         {
650             InternalWriteItemNull();
651             WriteMember(itemNameInfo, typeNameInfo, value);
652         }
653
654         internal void WriteNullItem(NameInfo itemNameInfo, NameInfo typeNameInfo)
655         {
656             nullCount++;
657             InternalWriteItemNull();
658         }
659
660         internal void WriteDelayedNullItem()
661         {
662             nullCount++;
663         }
664
665         internal void WriteItemEnd()
666         {
667             InternalWriteItemNull();
668         }
669
670         private void InternalWriteItemNull()
671         {
672             if (nullCount > 0)
673             {
674                 if (objectNull == null)
675                     objectNull = new ObjectNull();
676                 objectNull.SetNullCount(nullCount);
677                 BCLDebug.Trace("BINARY",  "-----item-----");
678                 objectNull.Dump();
679                 objectNull.Write(this);
680                 nullCount = 0;
681             }
682         }
683
684         internal void WriteItemObjectRef(NameInfo nameInfo, int idRef)
685         {
686             InternalWriteItemNull();
687             WriteMemberObjectRef(nameInfo, idRef);
688         }
689
690
691         internal BinaryAssembly binaryAssembly;
692         internal BinaryCrossAppDomainAssembly crossAppDomainAssembly;
693
694         internal void WriteAssembly(Type type, String assemblyString, int assemId, bool isNew)
695         {
696             SerTrace.Log( this,"WriteAssembly type ",type,", id ",assemId,", name ", assemblyString,", isNew ",isNew);
697             //If the file being tested wasn't built as an assembly, then we're going to get null back
698             //for the assembly name.  This is very unfortunate.
699             InternalWriteItemNull();
700             if (assemblyString==null)
701             {
702                 assemblyString=String.Empty;
703             }
704
705             if (isNew)
706             {
707                 if (binaryAssembly == null)
708                     binaryAssembly = new BinaryAssembly();
709                 binaryAssembly.Set(assemId, assemblyString);
710                 binaryAssembly.Dump();
711                 binaryAssembly.Write(this);
712             }
713         }
714
715         // Method to write a value onto a stream given its primitive type code
716         internal void WriteValue(InternalPrimitiveTypeE code, Object value)
717         {
718             SerTrace.Log( this, "WriteValue Entry ",((Enum)code).ToString()," " , ((value==null)?"<null>":value.GetType().ToString()) , " ",value);
719
720             switch (code)
721             {
722             case InternalPrimitiveTypeE.Boolean:
723                 WriteBoolean(Convert.ToBoolean(value, CultureInfo.InvariantCulture));
724                 break;
725             case InternalPrimitiveTypeE.Byte:
726                 WriteByte(Convert.ToByte(value, CultureInfo.InvariantCulture));
727                 break;
728             case InternalPrimitiveTypeE.Char:
729                 WriteChar(Convert.ToChar(value, CultureInfo.InvariantCulture));
730                 break;
731             case InternalPrimitiveTypeE.Double:
732                 WriteDouble(Convert.ToDouble(value, CultureInfo.InvariantCulture));
733                 break;
734             case InternalPrimitiveTypeE.Int16:
735                 WriteInt16(Convert.ToInt16(value, CultureInfo.InvariantCulture));
736                 break;
737             case InternalPrimitiveTypeE.Int32:
738                 WriteInt32(Convert.ToInt32(value, CultureInfo.InvariantCulture));
739                 break;
740             case InternalPrimitiveTypeE.Int64:
741                 WriteInt64(Convert.ToInt64(value, CultureInfo.InvariantCulture));
742                 break;
743             case InternalPrimitiveTypeE.SByte:
744                 WriteSByte(Convert.ToSByte(value, CultureInfo.InvariantCulture));
745                 break;
746             case InternalPrimitiveTypeE.Single:
747                 WriteSingle(Convert.ToSingle(value, CultureInfo.InvariantCulture));
748                 break;
749             case InternalPrimitiveTypeE.UInt16:
750                 WriteUInt16(Convert.ToUInt16(value, CultureInfo.InvariantCulture));
751                 break;
752             case InternalPrimitiveTypeE.UInt32:
753                 WriteUInt32(Convert.ToUInt32(value, CultureInfo.InvariantCulture));
754                 break;
755             case InternalPrimitiveTypeE.UInt64:
756                 WriteUInt64(Convert.ToUInt64(value, CultureInfo.InvariantCulture));
757                 break;
758             case InternalPrimitiveTypeE.Decimal:
759                 WriteDecimal(Convert.ToDecimal(value, CultureInfo.InvariantCulture));
760                 break;
761             case InternalPrimitiveTypeE.TimeSpan:
762                 WriteTimeSpan((TimeSpan)value);
763                 break;
764             case InternalPrimitiveTypeE.DateTime:
765                 WriteDateTime((DateTime)value);
766                 break;
767             default:
768                 throw new SerializationException(Environment.GetResourceString("Serialization_TypeCode",((Enum)code).ToString()));
769             }
770             SerTrace.Log( this, "Write Exit ");
771         }
772     }
773
774     internal sealed class ObjectMapInfo
775     {
776         internal int objectId;
777         int numMembers;
778         String[] memberNames;
779         Type[] memberTypes;
780
781         internal ObjectMapInfo(int objectId, int numMembers, String[] memberNames, Type[] memberTypes)
782         {
783             this.objectId = objectId;
784             this.numMembers = numMembers;
785             this.memberNames = memberNames;
786             this.memberTypes = memberTypes;
787         }
788
789         internal bool isCompatible(int numMembers, String[] memberNames, Type[] memberTypes)
790         {
791             bool result = true;
792             if (this.numMembers == numMembers)
793             {
794                 for (int i=0; i<numMembers; i++)
795                 {
796                     if (!(this.memberNames[i].Equals(memberNames[i])))
797                     {
798                         result = false;
799                         break;
800                     }
801                     if ((memberTypes != null) && (this.memberTypes[i] != memberTypes[i]))
802                     {
803                         result = false;
804                         break;
805                     }
806                 }
807             }
808             else
809                 result = false;
810             return result;
811         }
812
813     }
814 }