1 //------------------------------------------------------------
2 // Copyright (c) Microsoft Corporation. All rights reserved.
3 //------------------------------------------------------------
4 // PERF, [....], [....]: Make LookupNamespace do something smarter when lots of names
5 // PERF, [....], [....]: Make Attribute lookup smarter when lots of attributes
6 // PERF: [....], [....]: Compare safe/unsafe versions
11 using System.Diagnostics.CodeAnalysis;
12 using System.Globalization;
14 using System.Runtime.Serialization;
15 using System.Security;
18 static class XmlConverter
20 public const int MaxDateTimeChars = 64;
21 public const int MaxInt32Chars = 16;
22 public const int MaxInt64Chars = 32;
23 public const int MaxBoolChars = 5;
24 public const int MaxFloatChars = 16;
25 public const int MaxDoubleChars = 32;
26 public const int MaxDecimalChars = 40;
27 public const int MaxUInt64Chars = 32;
28 public const int MaxPrimitiveChars = MaxDateTimeChars;
30 static char[] whiteSpaceChars = new char[] { ' ', '\t', '\n', '\r' };
31 static UTF8Encoding utf8Encoding;
32 static UnicodeEncoding unicodeEncoding;
33 static Base64Encoding base64Encoding;
35 static public Base64Encoding Base64Encoding
39 if (base64Encoding == null)
40 base64Encoding = new Base64Encoding();
41 return base64Encoding;
45 static UTF8Encoding UTF8Encoding
49 if (utf8Encoding == null)
50 utf8Encoding = new UTF8Encoding(false, true);
55 static UnicodeEncoding UnicodeEncoding
59 if (unicodeEncoding == null)
60 unicodeEncoding = new UnicodeEncoding(false, false, true);
61 return unicodeEncoding;
65 static public bool ToBoolean(string value)
69 return XmlConvert.ToBoolean(value);
71 catch (ArgumentException exception)
73 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(XmlExceptionHelper.CreateConversionException(value, "Boolean", exception));
75 catch (FormatException exception)
77 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(XmlExceptionHelper.CreateConversionException(value, "Boolean", exception));
81 static public bool ToBoolean(byte[] buffer, int offset, int count)
85 byte ch = buffer[offset];
88 else if (ch == (byte)'0')
91 return ToBoolean(ToString(buffer, offset, count));
94 static public int ToInt32(string value)
98 return XmlConvert.ToInt32(value);
100 catch (ArgumentException exception)
102 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(XmlExceptionHelper.CreateConversionException(value, "Int32", exception));
104 catch (FormatException exception)
106 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(XmlExceptionHelper.CreateConversionException(value, "Int32", exception));
108 catch (OverflowException exception)
110 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(XmlExceptionHelper.CreateConversionException(value, "Int32", exception));
114 static public int ToInt32(byte[] buffer, int offset, int count)
117 if (TryParseInt32(buffer, offset, count, out value))
119 return ToInt32(ToString(buffer, offset, count));
122 static public Int64 ToInt64(string value)
126 return XmlConvert.ToInt64(value);
128 catch (ArgumentException exception)
130 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(XmlExceptionHelper.CreateConversionException(value, "Int64", exception));
132 catch (FormatException exception)
134 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(XmlExceptionHelper.CreateConversionException(value, "Int64", exception));
136 catch (OverflowException exception)
138 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(XmlExceptionHelper.CreateConversionException(value, "Int64", exception));
142 static public Int64 ToInt64(byte[] buffer, int offset, int count)
145 if (TryParseInt64(buffer, offset, count, out value))
147 return ToInt64(ToString(buffer, offset, count));
150 static public float ToSingle(string value)
154 return XmlConvert.ToSingle(value);
156 catch (ArgumentException exception)
158 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(XmlExceptionHelper.CreateConversionException(value, "float", exception));
160 catch (FormatException exception)
162 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(XmlExceptionHelper.CreateConversionException(value, "float", exception));
164 catch (OverflowException exception)
166 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(XmlExceptionHelper.CreateConversionException(value, "float", exception));
170 static public float ToSingle(byte[] buffer, int offset, int count)
173 if (TryParseSingle(buffer, offset, count, out value))
175 return ToSingle(ToString(buffer, offset, count));
178 static public double ToDouble(string value)
182 return XmlConvert.ToDouble(value);
184 catch (ArgumentException exception)
186 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(XmlExceptionHelper.CreateConversionException(value, "double", exception));
188 catch (FormatException exception)
190 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(XmlExceptionHelper.CreateConversionException(value, "double", exception));
192 catch (OverflowException exception)
194 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(XmlExceptionHelper.CreateConversionException(value, "double", exception));
198 static public double ToDouble(byte[] buffer, int offset, int count)
201 if (TryParseDouble(buffer, offset, count, out value))
203 return ToDouble(ToString(buffer, offset, count));
206 static public decimal ToDecimal(string value)
210 return XmlConvert.ToDecimal(value);
212 catch (ArgumentException exception)
214 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(XmlExceptionHelper.CreateConversionException(value, "decimal", exception));
216 catch (FormatException exception)
218 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(XmlExceptionHelper.CreateConversionException(value, "decimal", exception));
220 catch (OverflowException exception)
222 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(XmlExceptionHelper.CreateConversionException(value, "decimal", exception));
226 static public decimal ToDecimal(byte[] buffer, int offset, int count)
228 return ToDecimal(ToString(buffer, offset, count));
231 static public DateTime ToDateTime(Int64 value)
235 return DateTime.FromBinary(value);
237 catch (ArgumentException exception)
239 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(XmlExceptionHelper.CreateConversionException(ToString(value), "DateTime", exception));
243 static public DateTime ToDateTime(string value)
247 return XmlConvert.ToDateTime(value, XmlDateTimeSerializationMode.RoundtripKind);
249 catch (ArgumentException exception)
251 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(XmlExceptionHelper.CreateConversionException(value, "DateTime", exception));
253 catch (FormatException exception)
255 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(XmlExceptionHelper.CreateConversionException(value, "DateTime", exception));
259 static public DateTime ToDateTime(byte[] buffer, int offset, int count)
262 if (TryParseDateTime(buffer, offset, count, out value))
264 return ToDateTime(ToString(buffer, offset, count));
267 static public UniqueId ToUniqueId(string value)
271 return new UniqueId(Trim(value));
273 catch (ArgumentException exception)
275 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(XmlExceptionHelper.CreateConversionException(value, "UniqueId", exception));
277 catch (FormatException exception)
279 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(XmlExceptionHelper.CreateConversionException(value, "UniqueId", exception));
283 static public UniqueId ToUniqueId(byte[] buffer, int offset, int count)
285 return ToUniqueId(ToString(buffer, offset, count));
288 static public TimeSpan ToTimeSpan(string value)
292 return XmlConvert.ToTimeSpan(value);
294 catch (ArgumentException exception)
296 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(XmlExceptionHelper.CreateConversionException(value, "TimeSpan", exception));
298 catch (FormatException exception)
300 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(XmlExceptionHelper.CreateConversionException(value, "TimeSpan", exception));
302 catch (OverflowException exception)
304 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(XmlExceptionHelper.CreateConversionException(value, "TimeSpan", exception));
308 static public TimeSpan ToTimeSpan(byte[] buffer, int offset, int count)
310 return ToTimeSpan(ToString(buffer, offset, count));
313 [SuppressMessage("Reliability", "Reliability113", Justification = "Catching expected exceptions inline instead of calling Fx.CreateGuid to minimize code change")]
314 static public Guid ToGuid(string value)
318 return Guid.Parse(Trim(value));
320 catch (FormatException exception)
322 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(XmlExceptionHelper.CreateConversionException(value, "Guid", exception));
324 catch (ArgumentException exception)
326 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(XmlExceptionHelper.CreateConversionException(value, "Guid", exception));
328 catch (OverflowException exception)
330 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(XmlExceptionHelper.CreateConversionException(value, "Guid", exception));
334 static public Guid ToGuid(byte[] buffer, int offset, int count)
336 return ToGuid(ToString(buffer, offset, count));
339 static public UInt64 ToUInt64(string value)
343 return ulong.Parse(value, NumberFormatInfo.InvariantInfo);
345 catch (ArgumentException exception)
347 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(XmlExceptionHelper.CreateConversionException(value, "UInt64", exception));
349 catch (FormatException exception)
351 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(XmlExceptionHelper.CreateConversionException(value, "UInt64", exception));
353 catch (OverflowException exception)
355 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(XmlExceptionHelper.CreateConversionException(value, "UInt64", exception));
359 static public UInt64 ToUInt64(byte[] buffer, int offset, int count)
361 return ToUInt64(ToString(buffer, offset, count));
364 static public string ToString(byte[] buffer, int offset, int count)
368 return UTF8Encoding.GetString(buffer, offset, count);
370 catch (DecoderFallbackException exception)
372 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(XmlExceptionHelper.CreateEncodingException(buffer, offset, count, exception));
376 static public string ToStringUnicode(byte[] buffer, int offset, int count)
380 return UnicodeEncoding.GetString(buffer, offset, count);
382 catch (DecoderFallbackException exception)
384 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(XmlExceptionHelper.CreateEncodingException(buffer, offset, count, exception));
389 static public byte[] ToBytes(string value)
393 return UTF8Encoding.GetBytes(value);
395 catch (DecoderFallbackException exception)
397 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(XmlExceptionHelper.CreateEncodingException(value, exception));
401 static public int ToChars(byte[] buffer, int offset, int count, char[] chars, int charOffset)
405 return UTF8Encoding.GetChars(buffer, offset, count, chars, charOffset);
407 catch (DecoderFallbackException exception)
409 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(XmlExceptionHelper.CreateEncodingException(buffer, offset, count, exception));
413 static public string ToString(bool value) { return value ? "true" : "false"; }
414 static public string ToString(int value) { return XmlConvert.ToString(value); }
415 static public string ToString(Int64 value) { return XmlConvert.ToString(value); }
416 static public string ToString(float value) { return XmlConvert.ToString(value); }
417 static public string ToString(double value) { return XmlConvert.ToString(value); }
418 static public string ToString(decimal value) { return XmlConvert.ToString(value); }
419 static public string ToString(TimeSpan value) { return XmlConvert.ToString(value); }
420 static public string ToString(UniqueId value) { return value.ToString(); }
421 static public string ToString(Guid value) { return value.ToString(); }
422 static public string ToString(UInt64 value) { return value.ToString(NumberFormatInfo.InvariantInfo); }
424 static public string ToString(DateTime value)
426 byte[] dateChars = new byte[MaxDateTimeChars];
427 int count = ToChars(value, dateChars, 0);
428 return ToString(dateChars, 0, count);
431 static string ToString(object value)
434 return ToString((int)value);
435 else if (value is Int64)
436 return ToString((Int64)value);
437 else if (value is float)
438 return ToString((float)value);
439 else if (value is double)
440 return ToString((double)value);
441 else if (value is decimal)
442 return ToString((decimal)value);
443 else if (value is TimeSpan)
444 return ToString((TimeSpan)value);
445 else if (value is UniqueId)
446 return ToString((UniqueId)value);
447 else if (value is Guid)
448 return ToString((Guid)value);
449 else if (value is UInt64)
450 return ToString((UInt64)value);
451 else if (value is DateTime)
452 return ToString((DateTime)value);
453 else if (value is bool)
454 return ToString((bool)value);
456 return value.ToString();
459 static public string ToString(object[] objects)
461 if (objects.Length == 0)
463 string value = ToString(objects[0]);
464 if (objects.Length > 1)
466 StringBuilder sb = new StringBuilder(value);
467 for (int i = 1; i < objects.Length; i++)
470 sb.Append(ToString(objects[i]));
472 value = sb.ToString();
477 static public void ToQualifiedName(string qname, out string prefix, out string localName)
479 int index = qname.IndexOf(':');
482 prefix = string.Empty;
483 localName = Trim(qname);
487 if (index == qname.Length - 1)
488 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new XmlException(SR.GetString(SR.XmlInvalidQualifiedName, qname)));
489 prefix = Trim(qname.Substring(0, index));
490 localName = Trim(qname.Substring(index + 1));
494 static bool TryParseInt32(byte[] chars, int offset, int count, out int result)
500 int offsetMax = offset + count;
501 if (chars[offset] == '-')
505 for (int i = offset + 1; i < offsetMax; i++)
507 int digit = (chars[i] - '0');
510 if (value < int.MinValue / 10)
513 if (value < int.MinValue + digit)
520 for (int i = offset; i < offsetMax; i++)
522 int digit = (chars[i] - '0');
525 if (value > int.MaxValue / 10)
528 if (value > int.MaxValue - digit)
537 static bool TryParseInt64(byte[] chars, int offset, int count, out long result)
543 if (!TryParseInt32(chars, offset, count, out value))
551 int offsetMax = offset + count;
552 if (chars[offset] == '-')
556 for (int i = offset + 1; i < offsetMax; i++)
558 int digit = (chars[i] - '0');
561 if (value < long.MinValue / 10)
564 if (value < long.MinValue + digit)
571 for (int i = offset; i < offsetMax; i++)
573 int digit = (chars[i] - '0');
576 if (value > long.MaxValue / 10)
579 if (value > long.MaxValue - digit)
589 static bool TryParseSingle(byte[] chars, int offset, int count, out float result)
592 int offsetMax = offset + count;
593 bool negative = false;
594 if (offset < offsetMax && chars[offset] == '-')
600 if (count < 1 || count > 10)
604 while (offset < offsetMax)
606 ch = (chars[offset] - '0');
607 if (ch == ('.' - '0'))
611 while (offset < offsetMax)
613 ch = chars[offset] - '0';
614 if (((uint)ch) >= 10)
617 value = value * 10 + ch;
620 // More than 8 characters (7 sig figs and a decimal) and int -> float conversion is lossy, so use double
623 result = (float)((double)value / (double)pow10);
627 result = (float)value / (float)pow10;
633 else if (((uint)ch) >= 10)
635 value = value * 10 + ch;
638 // Ten digits w/out a decimal point might've overflowed the int
648 static bool TryParseDouble(byte[] chars, int offset, int count, out double result)
651 int offsetMax = offset + count;
652 bool negative = false;
653 if (offset < offsetMax && chars[offset] == '-')
659 if (count < 1 || count > 10)
663 while (offset < offsetMax)
665 ch = (chars[offset] - '0');
666 if (ch == ('.' - '0'))
670 while (offset < offsetMax)
672 ch = chars[offset] - '0';
673 if (((uint)ch) >= 10)
676 value = value * 10 + ch;
680 result = -(double)value / pow10;
682 result = (double)value / pow10;
685 else if (((uint)ch) >= 10)
687 value = value * 10 + ch;
690 // Ten digits w/out a decimal point might've overflowed the int
700 static int ToInt32D2(byte[] chars, int offset)
702 byte ch1 = (byte)(chars[offset + 0] - '0');
703 byte ch2 = (byte)(chars[offset + 1] - '0');
704 if (ch1 > 9 || ch2 > 9)
706 return 10 * ch1 + ch2;
709 static int ToInt32D4(byte[] chars, int offset, int count)
711 return ToInt32D7(chars, offset, count);
714 static int ToInt32D7(byte[] chars, int offset, int count)
717 for (int i = 0; i < count; i++)
719 byte ch = (byte)(chars[offset + i] - '0');
722 value = value * 10 + ch;
727 static bool TryParseDateTime(byte[] chars, int offset, int count, out DateTime result)
729 int offsetMax = offset + count;
730 result = DateTime.MaxValue;
736 // 012345678901234567890123456789012
737 // "yyyy-MM-ddTHH:mm:ss"
738 // "yyyy-MM-ddTHH:mm:ss.fffffff"
739 // "yyyy-MM-ddTHH:mm:ss.fffffffZ"
740 // "yyyy-MM-ddTHH:mm:ss.fffffff+xx:yy"
741 // "yyyy-MM-ddTHH:mm:ss.fffffff-xx:yy"
742 if (chars[offset + 4] != '-' || chars[offset + 7] != '-' || chars[offset + 10] != 'T' ||
743 chars[offset + 13] != ':' || chars[offset + 16] != ':')
746 int year = ToInt32D4(chars, offset + 0, 4);
747 int month = ToInt32D2(chars, offset + 5);
748 int day = ToInt32D2(chars, offset + 8);
749 int hour = ToInt32D2(chars, offset + 11);
750 int minute = ToInt32D2(chars, offset + 14);
751 int second = ToInt32D2(chars, offset + 17);
753 if ((year | month | day | hour | minute | second) < 0)
756 DateTimeKind kind = DateTimeKind.Unspecified;
760 if (offset < offsetMax && chars[offset] == '.')
763 int digitOffset = offset;
764 while (offset < offsetMax)
766 byte ch = chars[offset];
767 if (ch < '0' || ch > '9')
771 int digitCount = offset - digitOffset;
772 if (digitCount < 1 || digitCount > 7)
774 ticks = ToInt32D7(chars, digitOffset, digitCount);
777 for (int i = digitCount; i < 7; ++i)
781 bool isLocal = false;
784 if (offset < offsetMax)
786 byte ch = chars[offset];
790 kind = DateTimeKind.Utc;
792 else if (ch == '+' || ch == '-')
795 if (offset + 5 > offsetMax || chars[offset + 2] != ':')
797 kind = DateTimeKind.Utc;
799 hourDelta = ToInt32D2(chars, offset);
800 minuteDelta = ToInt32D2(chars, offset + 3);
801 if ((hourDelta | minuteDelta) < 0)
805 hourDelta = -hourDelta;
806 minuteDelta = -minuteDelta;
811 if (offset < offsetMax)
817 value = new DateTime(year, month, day, hour, minute, second, kind);
819 catch (ArgumentException)
826 value = value.AddTicks(ticks);
832 TimeSpan ts = new TimeSpan(hourDelta, minuteDelta, 0);
833 if (hourDelta >= 0 && (value < DateTime.MaxValue - ts) ||
834 hourDelta < 0 && (value > DateTime.MinValue - ts))
836 value = value.Add(ts).ToLocalTime();
840 value = value.ToLocalTime().Add(ts);
843 catch (ArgumentOutOfRangeException) // Overflow
853 static public int ToChars(bool value, byte[] buffer, int offset)
857 buffer[offset + 0] = (byte)'t';
858 buffer[offset + 1] = (byte)'r';
859 buffer[offset + 2] = (byte)'u';
860 buffer[offset + 3] = (byte)'e';
865 buffer[offset + 0] = (byte)'f';
866 buffer[offset + 1] = (byte)'a';
867 buffer[offset + 2] = (byte)'l';
868 buffer[offset + 3] = (byte)'s';
869 buffer[offset + 4] = (byte)'e';
874 // Works left from offset
875 static public int ToCharsR(int value, byte[] chars, int offset)
882 int valueDiv10 = value / 10;
884 chars[--offset] = (byte)('0' + (value - valueDiv10 * 10));
887 chars[--offset] = (byte)('0' + value);
894 int valueDiv10 = value / 10;
896 chars[--offset] = (byte)('0' - (value - valueDiv10 * 10));
899 chars[--offset] = (byte)('0' - value);
900 chars[--offset] = (byte)'-';
906 static public int ToChars(int value, byte[] chars, int offset)
908 int count = ToCharsR(value, chars, offset + MaxInt32Chars);
909 Buffer.BlockCopy(chars, offset + MaxInt32Chars - count, chars, offset, count);
913 static public int ToCharsR(long value, byte[] chars, int offset)
918 while (value > int.MaxValue)
920 long valueDiv10 = value / 10;
922 chars[--offset] = (byte)('0' + (int)(value - valueDiv10 * 10));
928 while (value < int.MinValue)
930 long valueDiv10 = value / 10;
932 chars[--offset] = (byte)('0' - (int)(value - valueDiv10 * 10));
936 Fx.Assert(value >= int.MinValue && value <= int.MaxValue, "");
937 return count + ToCharsR((int)value, chars, offset);
940 static public int ToChars(long value, byte[] chars, int offset)
942 int count = ToCharsR(value, chars, offset + MaxInt64Chars);
943 Buffer.BlockCopy(chars, offset + MaxInt64Chars - count, chars, offset, count);
947 [Fx.Tag.SecurityNote(Critical = "Contains unsafe code.",
948 Safe = "Unsafe code is effectively encapsulated, all inputs are validated.")]
949 [SecuritySafeCritical]
950 static unsafe bool IsNegativeZero(float value)
952 // Simple equals function will report that -0 is equal to +0, so compare bits instead
953 float negativeZero = -0e0F;
954 return (*(Int32*)&value == *(Int32*)&negativeZero);
957 [Fx.Tag.SecurityNote(Critical = "Contains unsafe code.",
958 Safe = "Unsafe code is effectively encapsulated, all inputs are validated.")]
959 [SecuritySafeCritical]
960 static unsafe bool IsNegativeZero(double value)
962 // Simple equals function will report that -0 is equal to +0, so compare bits instead
963 double negativeZero = -0e0;
964 return (*(Int64*)&value == *(Int64*)&negativeZero);
967 static int ToInfinity(bool isNegative, byte[] buffer, int offset)
971 buffer[offset + 0] = (byte)'-';
972 buffer[offset + 1] = (byte)'I';
973 buffer[offset + 2] = (byte)'N';
974 buffer[offset + 3] = (byte)'F';
979 buffer[offset + 0] = (byte)'I';
980 buffer[offset + 1] = (byte)'N';
981 buffer[offset + 2] = (byte)'F';
986 static int ToZero(bool isNegative, byte[] buffer, int offset)
990 buffer[offset + 0] = (byte)'-';
991 buffer[offset + 1] = (byte)'0';
996 buffer[offset] = (byte)'0';
1001 static public int ToChars(double value, byte[] buffer, int offset)
1003 if (double.IsInfinity(value))
1004 return ToInfinity(double.IsNegativeInfinity(value), buffer, offset);
1006 return ToZero(IsNegativeZero(value), buffer, offset);
1007 return ToAsciiChars(value.ToString("R", NumberFormatInfo.InvariantInfo), buffer, offset);
1010 static public int ToChars(float value, byte[] buffer, int offset)
1012 if (float.IsInfinity(value))
1013 return ToInfinity(float.IsNegativeInfinity(value), buffer, offset);
1015 return ToZero(IsNegativeZero(value), buffer, offset);
1016 return ToAsciiChars(value.ToString("R", NumberFormatInfo.InvariantInfo), buffer, offset);
1019 static public int ToChars(decimal value, byte[] buffer, int offset)
1021 return ToAsciiChars(value.ToString(null, NumberFormatInfo.InvariantInfo), buffer, offset);
1024 static public int ToChars(UInt64 value, byte[] buffer, int offset)
1026 return ToAsciiChars(value.ToString(null, NumberFormatInfo.InvariantInfo), buffer, offset);
1029 static int ToAsciiChars(string s, byte[] buffer, int offset)
1031 for (int i = 0; i < s.Length; i++)
1033 Fx.Assert(s[i] < 128, "");
1034 buffer[offset++] = (byte)s[i];
1039 static int ToCharsD2(int value, byte[] chars, int offset)
1041 Fx.Assert(value >= 0 && value < 100, "");
1044 chars[offset + 0] = (byte)'0';
1045 chars[offset + 1] = (byte)('0' + value);
1049 int valueDiv10 = value / 10;
1050 chars[offset + 0] = (byte)('0' + valueDiv10);
1051 chars[offset + 1] = (byte)('0' + value - valueDiv10 * 10);
1056 static int ToCharsD4(int value, byte[] chars, int offset)
1058 Fx.Assert(value >= 0 && value < 10000, "");
1059 ToCharsD2(value / 100, chars, offset + 0);
1060 ToCharsD2(value % 100, chars, offset + 2);
1064 static int ToCharsD7(int value, byte[] chars, int offset)
1066 Fx.Assert(value >= 0 && value < 10000000, "");
1067 int zeroCount = 7 - ToCharsR(value, chars, offset + 7);
1068 for (int i = 0; i < zeroCount; i++)
1069 chars[offset + i] = (byte)'0';
1071 while (count > 0 && chars[offset + count - 1] == '0')
1076 static public int ToChars(DateTime value, byte[] chars, int offset)
1078 const long TicksPerMillisecond = 10000;
1079 const long TicksPerSecond = TicksPerMillisecond * 1000;
1080 int offsetMin = offset;
1081 // "yyyy-MM-ddTHH:mm:ss.fffffff";
1082 offset += ToCharsD4(value.Year, chars, offset);
1083 chars[offset++] = (byte)'-';
1084 offset += ToCharsD2(value.Month, chars, offset);
1085 chars[offset++] = (byte)'-';
1086 offset += ToCharsD2(value.Day, chars, offset);
1087 chars[offset++] = (byte)'T';
1088 offset += ToCharsD2(value.Hour, chars, offset);
1089 chars[offset++] = (byte)':';
1090 offset += ToCharsD2(value.Minute, chars, offset);
1091 chars[offset++] = (byte)':';
1092 offset += ToCharsD2(value.Second, chars, offset);
1093 int ms = (int)(value.Ticks % TicksPerSecond);
1096 chars[offset++] = (byte)'.';
1097 offset += ToCharsD7(ms, chars, offset);
1101 case DateTimeKind.Unspecified:
1103 case DateTimeKind.Local:
1105 TimeSpan ts = TimeZoneInfo.Local.GetUtcOffset(value);
1107 chars[offset++] = (byte)'-';
1109 chars[offset++] = (byte)'+';
1110 offset += ToCharsD2(Math.Abs(ts.Hours), chars, offset);
1111 chars[offset++] = (byte)':';
1112 offset += ToCharsD2(Math.Abs(ts.Minutes), chars, offset);
1114 case DateTimeKind.Utc:
1116 chars[offset++] = (byte)'Z';
1119 throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException());
1121 return offset - offsetMin;
1124 static public bool IsWhitespace(string s)
1126 for (int i = 0; i < s.Length; i++)
1128 if (!IsWhitespace(s[i]))
1134 static public bool IsWhitespace(char ch)
1136 return (ch <= ' ' && (ch == ' ' || ch == '\t' || ch == '\r' || ch == '\n'));
1139 static public string StripWhitespace(string s)
1141 int count = s.Length;
1142 for (int i = 0; i < s.Length; i++)
1144 if (IsWhitespace(s[i]))
1149 if (count == s.Length)
1151 char[] chars = new char[count];
1153 for (int i = 0; i < s.Length; i++)
1156 if (!IsWhitespace(ch))
1158 chars[count++] = ch;
1161 return new string(chars);
1164 static string Trim(string s)
1167 for (i = 0; i < s.Length && IsWhitespace(s[i]); i++);
1170 for (j = s.Length; j > 0 && IsWhitespace(s[j - 1]); j--);
1172 if (i == 0 && j == s.Length)
1175 return string.Empty;
1177 return s.Substring(i, j - i);