File: System\Runtime\Serialization\Json\JsonWriterDelegator.cs
Project: ndp\cdf\src\WCF\Serialization\System.Runtime.Serialization.csproj (System.Runtime.Serialization)
//----------------------------------------------------------------
// Copyright (c) Microsoft Corporation.  All rights reserved.
//----------------------------------------------------------------
 
namespace System.Runtime.Serialization.Json
{
    using System.Xml;
    using System.Globalization;
    using System.ServiceModel;
 
#if USE_REFEMIT
    public class JsonWriterDelegator : XmlWriterDelegator
#else
    internal class JsonWriterDelegator : XmlWriterDelegator
#endif
    {
        DateTimeFormat dateTimeFormat;
 
        public JsonWriterDelegator(XmlWriter writer)
            : base(writer)
        {
        }
 
        public JsonWriterDelegator(XmlWriter writer, DateTimeFormat dateTimeFormat)
            : this(writer)
        {
            this.dateTimeFormat = dateTimeFormat;
        }
 
        internal override void WriteChar(char value)
        {
            WriteString(XmlConvert.ToString(value));
        }
 
        internal override void WriteBase64(byte[] bytes)
        {
            if (bytes == null)
            {
                return;
            }
 
            ByteArrayHelperWithString.Instance.WriteArray(Writer, bytes, 0, bytes.Length);
        }
 
        internal override void WriteQName(XmlQualifiedName value)
        {
            if (value != XmlQualifiedName.Empty)
            {
                writer.WriteString(value.Name);
                writer.WriteString(JsonGlobals.NameValueSeparatorString);
                writer.WriteString(value.Namespace);
            }
        }
 
        internal override void WriteUnsignedLong(ulong value)
        {
            WriteDecimal((decimal)value);
        }
 
        internal override void WriteDecimal(decimal value)
        {
            writer.WriteAttributeString(JsonGlobals.typeString, JsonGlobals.numberString);
            base.WriteDecimal(value);
        }
 
        internal override void WriteDouble(double value)
        {
            writer.WriteAttributeString(JsonGlobals.typeString, JsonGlobals.numberString);
            base.WriteDouble(value);
        }
 
        internal override void WriteFloat(float value)
        {
            writer.WriteAttributeString(JsonGlobals.typeString, JsonGlobals.numberString);
            base.WriteFloat(value);
        }
 
        internal override void WriteLong(long value)
        {
            writer.WriteAttributeString(JsonGlobals.typeString, JsonGlobals.numberString);
            base.WriteLong(value);
        }
 
        internal override void WriteSignedByte(sbyte value)
        {
            writer.WriteAttributeString(JsonGlobals.typeString, JsonGlobals.numberString);
            base.WriteSignedByte(value);
        }
 
        internal override void WriteUnsignedInt(uint value)
        {
            writer.WriteAttributeString(JsonGlobals.typeString, JsonGlobals.numberString);
            base.WriteUnsignedInt(value);
        }
 
        internal override void WriteUnsignedShort(ushort value)
        {
            writer.WriteAttributeString(JsonGlobals.typeString, JsonGlobals.numberString);
            base.WriteUnsignedShort(value);
        }
 
        internal override void WriteUnsignedByte(byte value)
        {
            writer.WriteAttributeString(JsonGlobals.typeString, JsonGlobals.numberString);
            base.WriteUnsignedByte(value);
        }
 
        internal override void WriteShort(short value)
        {
            writer.WriteAttributeString(JsonGlobals.typeString, JsonGlobals.numberString);
            base.WriteShort(value);
        }
 
        internal override void WriteBoolean(bool value)
        {
            writer.WriteAttributeString(JsonGlobals.typeString, JsonGlobals.booleanString);
            base.WriteBoolean(value);
        }
 
        internal override void WriteInt(int value)
        {
            writer.WriteAttributeString(JsonGlobals.typeString, JsonGlobals.numberString);
            base.WriteInt(value);
        }
 
 
#if USE_REFEMIT
        public void WriteJsonBooleanArray(bool[] value, XmlDictionaryString itemName, XmlDictionaryString itemNamespace)
#else
        internal void WriteJsonBooleanArray(bool[] value, XmlDictionaryString itemName, XmlDictionaryString itemNamespace)
#endif
        {
            for (int i = 0; i < value.Length; i++)
            {
                WriteBoolean(value[i], itemName, itemNamespace);
            }
        }
 
#if USE_REFEMIT
        public void WriteJsonDateTimeArray(DateTime[] value, XmlDictionaryString itemName, XmlDictionaryString itemNamespace)
#else
        internal void WriteJsonDateTimeArray(DateTime[] value, XmlDictionaryString itemName, XmlDictionaryString itemNamespace)
#endif
        {
            for (int i = 0; i < value.Length; i++)
            {
                WriteDateTime(value[i], itemName, itemNamespace);
            }
        }
 
#if USE_REFEMIT
        public void WriteJsonDecimalArray(decimal[] value, XmlDictionaryString itemName, XmlDictionaryString itemNamespace)
#else
        internal void WriteJsonDecimalArray(decimal[] value, XmlDictionaryString itemName, XmlDictionaryString itemNamespace)
#endif
        {
            for (int i = 0; i < value.Length; i++)
            {
                WriteDecimal(value[i], itemName, itemNamespace);
            }
        }
 
#if USE_REFEMIT
        public void WriteJsonInt32Array(int[] value, XmlDictionaryString itemName, XmlDictionaryString itemNamespace)
#else
        internal void WriteJsonInt32Array(int[] value, XmlDictionaryString itemName, XmlDictionaryString itemNamespace)
#endif
        {
            for (int i = 0; i < value.Length; i++)
            {
                WriteInt(value[i], itemName, itemNamespace);
            }
        }
 
#if USE_REFEMIT
        public void WriteJsonInt64Array(long[] value, XmlDictionaryString itemName, XmlDictionaryString itemNamespace)
#else
        internal void WriteJsonInt64Array(long[] value, XmlDictionaryString itemName, XmlDictionaryString itemNamespace)
#endif
        {
            for (int i = 0; i < value.Length; i++)
            {
                WriteLong(value[i], itemName, itemNamespace);
            }
        }
 
        internal override void WriteDateTime(DateTime value)
        {
            if (this.dateTimeFormat == null)
            {
                WriteDateTimeInDefaultFormat(value);
            }
            else
            {
                writer.WriteString(value.ToString(this.dateTimeFormat.FormatString, this.dateTimeFormat.FormatProvider));
            }
        }
 
        void WriteDateTimeInDefaultFormat(DateTime value)
        {
            // ToUniversalTime() truncates dates to DateTime.MaxValue or DateTime.MinValue instead of throwing
            // This will break round-tripping of these dates (see bug 9690 in CSD Developer Framework)
            if (value.Kind != DateTimeKind.Utc)
            {
                long tickCount;
                if (!LocalAppContextSwitches.DoNotUseTimeZoneInfo)
                {
                    tickCount = value.Ticks - TimeZoneInfo.Local.GetUtcOffset(value).Ticks;
                }
                else
                {
                    tickCount = value.Ticks - TimeZone.CurrentTimeZone.GetUtcOffset(value).Ticks;
                }
                if ((tickCount > DateTime.MaxValue.Ticks) || (tickCount < DateTime.MinValue.Ticks))
                {
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
                        XmlObjectSerializer.CreateSerializationException(SR.GetString(SR.JsonDateTimeOutOfRange), new ArgumentOutOfRangeException("value")));
                }
            }
 
            writer.WriteString(JsonGlobals.DateTimeStartGuardReader);
            writer.WriteValue((value.ToUniversalTime().Ticks - JsonGlobals.unixEpochTicks) / 10000);
 
            switch (value.Kind)
            {
                case DateTimeKind.Unspecified:
                case DateTimeKind.Local:
                    // +"zzzz";
                    TimeSpan ts;
                    if (!LocalAppContextSwitches.DoNotUseTimeZoneInfo)
                    {
                        ts = TimeZoneInfo.Local.GetUtcOffset(value.ToLocalTime());
                    }
                    else
                    {
                        ts = TimeZone.CurrentTimeZone.GetUtcOffset(value.ToLocalTime());
                    }
                    if (ts.Ticks < 0)
                    {
                        writer.WriteString("-");
                    }
                    else
                    {
                        writer.WriteString("+");
                    }
                    int hours = Math.Abs(ts.Hours);
                    writer.WriteString((hours < 10) ? "0" + hours : hours.ToString(CultureInfo.InvariantCulture));
                    int minutes = Math.Abs(ts.Minutes);
                    writer.WriteString((minutes < 10) ? "0" + minutes : minutes.ToString(CultureInfo.InvariantCulture));
                    break;
                case DateTimeKind.Utc:
                    break;
            }
            writer.WriteString(JsonGlobals.DateTimeEndGuardReader);
        }
 
#if USE_REFEMIT
        public void WriteJsonSingleArray(float[] value, XmlDictionaryString itemName, XmlDictionaryString itemNamespace)
#else
        internal void WriteJsonSingleArray(float[] value, XmlDictionaryString itemName, XmlDictionaryString itemNamespace)
#endif
        {
            for (int i = 0; i < value.Length; i++)
            {
                WriteFloat(value[i], itemName, itemNamespace);
            }
        }
 
#if USE_REFEMIT
        public void WriteJsonDoubleArray(double[] value, XmlDictionaryString itemName, XmlDictionaryString itemNamespace)
#else
        internal void WriteJsonDoubleArray(double[] value, XmlDictionaryString itemName, XmlDictionaryString itemNamespace)
#endif
        {
            for (int i = 0; i < value.Length; i++)
            {
                WriteDouble(value[i], itemName, itemNamespace);
            }
        }
 
        internal override void WriteStartElement(string prefix, string localName, string ns)
        {
            if (localName != null && localName.Length == 0)
            {                
                base.WriteStartElement(JsonGlobals.itemString, JsonGlobals.itemString);
                base.WriteAttributeString(null, JsonGlobals.itemString, null, localName);
            }
            else
            {
                base.WriteStartElement(prefix, localName, ns);
            }
        }
    }            
}