742 lines
19 KiB
C#
742 lines
19 KiB
C#
using System;
|
|
using System.Text;
|
|
|
|
// ReSharper disable once CheckNamespace
|
|
namespace GameDevWare.Serialization
|
|
{
|
|
internal static class JsonUtils
|
|
{
|
|
internal static readonly long UnixEpochTicks = new DateTime(0x7b2, 1, 1, 0, 0, 0, DateTimeKind.Utc).Ticks;
|
|
|
|
private static readonly char[] ZerBuff = new char[] {'0', '0', '0', '0', '0', '0', '0', '0',};
|
|
private static readonly char[] HexChar = "0123456789ABCDEF".ToCharArray();
|
|
|
|
public static string UnescapeAndUnquote(string stringToUnescape)
|
|
{
|
|
if (stringToUnescape == null)
|
|
throw new ArgumentNullException("stringToUnescape");
|
|
|
|
|
|
var start = 0;
|
|
var len = stringToUnescape.Length;
|
|
|
|
if (stringToUnescape.Length > 0 && stringToUnescape[0] == '"')
|
|
{
|
|
start += 1;
|
|
len -= 2;
|
|
}
|
|
|
|
return UnescapeBuffer(stringToUnescape.ToCharArray(), start, len);
|
|
}
|
|
|
|
public static string EscapeAndQuote(string stringToEscape)
|
|
{
|
|
if (stringToEscape == null)
|
|
throw new ArgumentNullException("stringToEscape");
|
|
|
|
|
|
var stringHasNonLatinCharacters = false;
|
|
var newSize = stringToEscape.Length + 2;
|
|
for (var i = 0; i < stringToEscape.Length; i++)
|
|
{
|
|
var charToCheck = stringToEscape[i];
|
|
var isNonLatinOrSpecial = ((int) charToCheck < 32 || charToCheck == '\\' || charToCheck == '"');
|
|
|
|
if (isNonLatinOrSpecial)
|
|
newSize += 5; // encoded characters add 4 hex symbols and "u"
|
|
|
|
stringHasNonLatinCharacters = stringHasNonLatinCharacters || isNonLatinOrSpecial;
|
|
}
|
|
|
|
// if it"s a latin - write as is
|
|
if (!stringHasNonLatinCharacters)
|
|
return string.Concat("\"", stringToEscape, "\"");
|
|
|
|
// else tranform and write
|
|
var sb = new StringBuilder(newSize);
|
|
var hexBuff = new char[12]; // 4 for zeroes and 8 for number
|
|
|
|
sb.Append('"');
|
|
for (var i = 0; i < stringToEscape.Length; i++)
|
|
{
|
|
var charToCheck = stringToEscape[i];
|
|
|
|
if ((int) charToCheck < 32 || charToCheck == '\\' || charToCheck == '"')
|
|
{
|
|
sb.Append("\\u");
|
|
Buffer.BlockCopy(ZerBuff, 0, hexBuff, 0, sizeof (char)*8); // clear buffer with "0"
|
|
var hexlen = UInt32ToHexBuffer((uint) charToCheck, hexBuff, 4);
|
|
sb.Append(hexBuff, hexlen, 4);
|
|
}
|
|
else
|
|
sb.Append(charToCheck);
|
|
}
|
|
sb.Append('"');
|
|
|
|
return sb.ToString();
|
|
}
|
|
|
|
public static int EscapeBuffer(string value, ref int offset, char[] outputBuffer, int outputBufferOffset)
|
|
{
|
|
if (value == null)
|
|
throw new ArgumentNullException("value");
|
|
if (offset < 0 || offset >= value.Length)
|
|
throw new ArgumentOutOfRangeException("offset");
|
|
if (outputBuffer == null)
|
|
throw new ArgumentNullException("outputBuffer");
|
|
if (outputBufferOffset < 0 || outputBufferOffset >= outputBuffer.Length)
|
|
throw new ArgumentOutOfRangeException("outputBufferOffset");
|
|
|
|
|
|
const ushort LOWER_BOUND_CHAR = 32;
|
|
const ushort QUOTE_CHAR = '\\';
|
|
const ushort DOUBLE_QUOTE_CHAR = '"';
|
|
|
|
var written = 0;
|
|
for (; offset < value.Length; offset++)
|
|
{
|
|
var charCode = (ushort) value[offset];
|
|
if (charCode < LOWER_BOUND_CHAR || charCode == QUOTE_CHAR || charCode == DOUBLE_QUOTE_CHAR)
|
|
{
|
|
if (outputBuffer.Length - outputBufferOffset < 6)
|
|
return written;
|
|
|
|
outputBuffer[outputBufferOffset++] = '\\';
|
|
outputBuffer[outputBufferOffset++] = 'u';
|
|
outputBufferOffset += UInt16ToPaddedHexBuffer(charCode, outputBuffer, outputBufferOffset);
|
|
written += 6;
|
|
}
|
|
else
|
|
{
|
|
if (outputBuffer.Length - outputBufferOffset == 0)
|
|
return written;
|
|
|
|
// dont escape
|
|
outputBuffer[outputBufferOffset++] = (char) charCode;
|
|
written++;
|
|
}
|
|
}
|
|
|
|
return written;
|
|
}
|
|
|
|
public static string UnescapeBuffer(char[] charsToUnescape, int start, int length)
|
|
{
|
|
if (charsToUnescape == null)
|
|
throw new ArgumentNullException("charsToUnescape");
|
|
if (start < 0 || start + length > charsToUnescape.Length)
|
|
throw new ArgumentOutOfRangeException("start");
|
|
|
|
|
|
var sb = new StringBuilder(length);
|
|
var plainStart = start;
|
|
var plainLen = 0;
|
|
var end = start + length;
|
|
for (var i = start; i < end; i++)
|
|
{
|
|
var ch = charsToUnescape[i];
|
|
if (ch == '\\')
|
|
{
|
|
var seqLength = 1;
|
|
// append unencoded chunk
|
|
if (plainLen != 0)
|
|
{
|
|
sb.Append(charsToUnescape, plainStart, plainLen);
|
|
plainLen = 0;
|
|
}
|
|
|
|
var seqKind = charsToUnescape[i + 1];
|
|
switch (seqKind)
|
|
{
|
|
case 'n':
|
|
sb.Append('\n');
|
|
break;
|
|
case 'r':
|
|
sb.Append('\r');
|
|
break;
|
|
case 'b':
|
|
sb.Append('\b');
|
|
break;
|
|
case 'f':
|
|
sb.Append('\f');
|
|
break;
|
|
case 't':
|
|
sb.Append('\t');
|
|
break;
|
|
case '\\':
|
|
sb.Append('\\');
|
|
break;
|
|
case '\'':
|
|
sb.Append('\'');
|
|
break;
|
|
case '\"':
|
|
sb.Append('\"');
|
|
break;
|
|
// unicode symbol
|
|
case 'u':
|
|
sb.Append((char) HexStringToUInt32(charsToUnescape, i + 2, 4));
|
|
seqLength = 5;
|
|
break;
|
|
// latin hex encoded symbol
|
|
case 'x':
|
|
sb.Append((char) HexStringToUInt32(charsToUnescape, i + 2, 2));
|
|
seqLength = 3;
|
|
break;
|
|
// latin dec encoded symbol
|
|
case '1':
|
|
case '2':
|
|
case '3':
|
|
case '4':
|
|
case '5':
|
|
case '6':
|
|
case '7':
|
|
case '8':
|
|
case '9':
|
|
case '0':
|
|
sb.Append((char) StringToInt32(charsToUnescape, i + 1, 3));
|
|
seqLength = 3;
|
|
break;
|
|
default:
|
|
#if STRICT
|
|
throw new Exceptions.UnknownEscapeSequence("\\" + seqKind.ToString(), null);
|
|
#else
|
|
sb.Append(charsToUnescape[i + 1]);
|
|
break;
|
|
#endif
|
|
}
|
|
|
|
// set next chunk start right after this escape
|
|
plainStart = i + seqLength + 1;
|
|
i += seqLength;
|
|
}
|
|
else
|
|
plainLen++;
|
|
}
|
|
|
|
// append last unencoded chunk
|
|
if (plainLen != 0)
|
|
sb.Append(charsToUnescape, plainStart, plainLen);
|
|
|
|
return sb.ToString();
|
|
}
|
|
|
|
public static uint HexStringToUInt32(char[] buffer, int start, int len)
|
|
{
|
|
if (buffer == null)
|
|
throw new ArgumentNullException("buffer");
|
|
if (start < 0)
|
|
throw new ArgumentOutOfRangeException("start");
|
|
if (len < 0)
|
|
throw new ArgumentOutOfRangeException("len");
|
|
if (start + len > buffer.Length)
|
|
throw new ArgumentOutOfRangeException();
|
|
|
|
|
|
const uint ZERO = (ushort) '0';
|
|
const uint a = (ushort) 'a';
|
|
const uint A = (ushort) 'A';
|
|
|
|
var result = 0u;
|
|
for (var i = 0; i < len; i++)
|
|
{
|
|
var c = buffer[start + i];
|
|
var d = 0u;
|
|
if (c >= '0' && c <= '9')
|
|
d = (c - ZERO);
|
|
else if (c >= 'a' && c <= 'f')
|
|
d = 10u + (c - a);
|
|
else if (c >= 'A' && c <= 'F')
|
|
d = 10u + (c - A);
|
|
else
|
|
throw new FormatException();
|
|
|
|
result = 16u*result + d;
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
public static int UInt32ToHexBuffer(uint uvalue, char[] buffer, int start)
|
|
{
|
|
if (buffer == null)
|
|
throw new ArgumentNullException("buffer");
|
|
if (start < 0 || start >= buffer.Length)
|
|
throw new ArgumentOutOfRangeException("start");
|
|
|
|
|
|
var hex = HexChar;
|
|
|
|
if (uvalue == 0)
|
|
{
|
|
buffer[start] = '0';
|
|
return 1;
|
|
}
|
|
|
|
var length = 0;
|
|
for (var i = 0; i < 8; i++)
|
|
{
|
|
var c = hex[((uvalue >> i*4) & 15u)];
|
|
buffer[start + i] = c;
|
|
}
|
|
|
|
for (length = 8; length > 0; length--)
|
|
if (buffer[start + length - 1] != '0')
|
|
break;
|
|
|
|
Array.Reverse(buffer, start, length);
|
|
|
|
return length;
|
|
}
|
|
|
|
public static int UInt16ToPaddedHexBuffer(ushort uvalue, char[] buffer, int start)
|
|
{
|
|
if (buffer == null)
|
|
throw new ArgumentNullException("buffer");
|
|
if (start < 0 || start >= buffer.Length)
|
|
throw new ArgumentOutOfRangeException("start");
|
|
|
|
|
|
const int LENGTH = 4;
|
|
const string HEX = "0123456789ABCDEF";
|
|
|
|
var end = start + LENGTH;
|
|
if (uvalue == 0)
|
|
{
|
|
for (var i = start; i < end; i++)
|
|
buffer[i] = '0';
|
|
return LENGTH;
|
|
}
|
|
|
|
for (var i = 0; i < LENGTH; i++)
|
|
{
|
|
var c = HEX[(int) ((uvalue >> i*4) & 15u)];
|
|
buffer[end - i - 1] = c;
|
|
}
|
|
|
|
|
|
return LENGTH;
|
|
}
|
|
|
|
public static ushort PaddedHexStringToUInt16(char[] buffer, int start, int len)
|
|
{
|
|
if (buffer == null)
|
|
throw new ArgumentNullException("buffer");
|
|
if (start < 0)
|
|
throw new ArgumentOutOfRangeException("start");
|
|
if (len < 0)
|
|
throw new ArgumentOutOfRangeException("len");
|
|
if (start + len > buffer.Length)
|
|
throw new ArgumentOutOfRangeException();
|
|
|
|
|
|
const uint ZERO = (ushort) '0';
|
|
const uint a = (ushort) 'a';
|
|
const uint A = (ushort) 'A';
|
|
|
|
var result = 0u;
|
|
for (var i = 0; i < len; i++)
|
|
{
|
|
var c = buffer[start + i];
|
|
var d = 0u;
|
|
if (c >= '0' && c <= '9')
|
|
d = (c - ZERO);
|
|
else if (c >= 'a' && c <= 'f')
|
|
d = 10u + (c - a);
|
|
else if (c >= 'A' && c <= 'F')
|
|
d = 10u + (c - A);
|
|
else
|
|
throw new FormatException();
|
|
|
|
result = 16u*result + d;
|
|
}
|
|
|
|
return checked((ushort) result);
|
|
}
|
|
|
|
public static long StringToInt64(char[] buffer, int start, int len, IFormatProvider formatProvider = null)
|
|
{
|
|
if (buffer == null)
|
|
throw new ArgumentNullException("buffer");
|
|
if (start < 0)
|
|
throw new ArgumentOutOfRangeException("start");
|
|
if (len < 0)
|
|
throw new ArgumentOutOfRangeException("len");
|
|
if (start + len > buffer.Length)
|
|
throw new ArgumentOutOfRangeException();
|
|
|
|
|
|
const ulong ZERO = (ushort) '0';
|
|
|
|
var result = 0UL;
|
|
var neg = false;
|
|
for (var i = 0; i < len; i++)
|
|
{
|
|
var c = buffer[start + i];
|
|
if (i == 0 && c == '-')
|
|
{
|
|
neg = true;
|
|
continue;
|
|
}
|
|
else if (c < '0' || c > '9')
|
|
throw new FormatException();
|
|
|
|
result = checked(10UL*result + (c - ZERO));
|
|
}
|
|
|
|
if (neg)
|
|
return -(long) (result);
|
|
else
|
|
return (long) result;
|
|
}
|
|
|
|
public static int StringToInt32(char[] buffer, int start, int len, IFormatProvider formatProvider = null)
|
|
{
|
|
if (buffer == null)
|
|
throw new ArgumentNullException("buffer");
|
|
if (start < 0)
|
|
throw new ArgumentOutOfRangeException("start");
|
|
if (len < 0)
|
|
throw new ArgumentOutOfRangeException("len");
|
|
if (start + len > buffer.Length)
|
|
throw new ArgumentOutOfRangeException();
|
|
|
|
|
|
const uint ZERO = (ushort) '0';
|
|
|
|
var result = 0u;
|
|
var neg = false;
|
|
for (var i = 0; i < len; i++)
|
|
{
|
|
var c = buffer[start + i];
|
|
if (i == 0 && c == '-')
|
|
{
|
|
neg = true;
|
|
continue;
|
|
}
|
|
else if (c < '0' || c > '9')
|
|
throw new FormatException();
|
|
|
|
result = checked(10u*result + (c - ZERO));
|
|
}
|
|
|
|
if (neg)
|
|
return -(int) (result);
|
|
else
|
|
return (int) result;
|
|
}
|
|
|
|
public static ulong StringToUInt64(char[] buffer, int start, int len, IFormatProvider formatProvider = null)
|
|
{
|
|
if (buffer == null)
|
|
throw new ArgumentNullException("buffer");
|
|
if (start < 0)
|
|
throw new ArgumentOutOfRangeException("start");
|
|
if (len < 0)
|
|
throw new ArgumentOutOfRangeException("len");
|
|
if (start + len > buffer.Length)
|
|
throw new ArgumentOutOfRangeException();
|
|
|
|
|
|
const ulong ZERO = (ushort) '0';
|
|
|
|
var result = 0UL;
|
|
for (var i = 0; i < len; i++)
|
|
{
|
|
var c = buffer[start + i];
|
|
if (c < '0' || c > '9')
|
|
throw new FormatException();
|
|
|
|
result = checked(10UL*result + (c - ZERO));
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
public static uint StringToUInt32(char[] buffer, int start, int len, IFormatProvider formatProvider = null)
|
|
{
|
|
if (buffer == null)
|
|
throw new ArgumentNullException("buffer");
|
|
if (start < 0)
|
|
throw new ArgumentOutOfRangeException("start");
|
|
if (len < 0)
|
|
throw new ArgumentOutOfRangeException("len");
|
|
if (start + len > buffer.Length)
|
|
throw new ArgumentOutOfRangeException();
|
|
|
|
|
|
const uint ZERO = (ushort) '0';
|
|
|
|
var result = 0U;
|
|
for (var i = 0; i < len; i++)
|
|
{
|
|
var c = buffer[start + i];
|
|
if (c < '0' || c > '9')
|
|
throw new FormatException();
|
|
|
|
result = checked(10*result + (c - ZERO));
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
public static double StringToDouble(char[] buffer, int start, int len, IFormatProvider formatProvider = null)
|
|
{
|
|
if (buffer == null)
|
|
throw new ArgumentNullException("buffer");
|
|
if (start < 0)
|
|
throw new ArgumentOutOfRangeException("start");
|
|
if (len < 0)
|
|
throw new ArgumentOutOfRangeException("len");
|
|
if (start + len > buffer.Length)
|
|
throw new ArgumentOutOfRangeException();
|
|
|
|
|
|
/*
|
|
const uint ZERO = (ushort)'0';
|
|
char decimalSep = '.';
|
|
|
|
var whole = 0UL;
|
|
var fraction = 0U;
|
|
var fracCount = 0;
|
|
var neg = false;
|
|
var decimals = false;
|
|
|
|
for (var i = 0; i < len; i++)
|
|
{
|
|
var c = buffer[start + i];
|
|
if (i == 0 && c == '-')
|
|
{
|
|
neg = true;
|
|
continue;
|
|
}
|
|
else if (c == decimalSep)
|
|
{
|
|
decimals = true;
|
|
continue;
|
|
}
|
|
else if (c < '0' || c > '9')
|
|
throw new FormatException();
|
|
|
|
if (decimals)
|
|
{
|
|
if (fracCount >= 9) // maximum precision 9 digits
|
|
break;
|
|
fraction = checked(10U * fraction + (c - ZERO));
|
|
fracCount++;
|
|
}
|
|
else
|
|
whole = checked(10UL * whole + (c - ZERO));
|
|
}
|
|
|
|
var result = checked((double)whole + (fraction / pow10d[fracCount]));
|
|
|
|
if (neg) result = -result;
|
|
|
|
return result;
|
|
*/
|
|
|
|
return double.Parse(new string(buffer, start, len), formatProvider);
|
|
}
|
|
|
|
public static float StringToFloat(char[] buffer, int start, int len, IFormatProvider formatProvider = null)
|
|
{
|
|
if (buffer == null)
|
|
throw new ArgumentNullException("buffer");
|
|
if (start < 0)
|
|
throw new ArgumentOutOfRangeException("start");
|
|
if (len < 0)
|
|
throw new ArgumentOutOfRangeException("len");
|
|
if (start + len > buffer.Length)
|
|
throw new ArgumentOutOfRangeException();
|
|
|
|
|
|
/*
|
|
const uint ZERO = (ushort)'0';
|
|
char decimalSep = '.';
|
|
|
|
var whole = 0U;
|
|
var fraction = 0U;
|
|
var fracCount = 0;
|
|
var neg = false;
|
|
var decimals = false;
|
|
|
|
for (var i = 0; i < len; i++)
|
|
{
|
|
var c = buffer[start + i];
|
|
if (i == 0 && c == '-')
|
|
{
|
|
neg = true;
|
|
continue;
|
|
}
|
|
else if (c == decimalSep)
|
|
{
|
|
decimals = true;
|
|
continue;
|
|
}
|
|
else if (c < '0' || c > '9')
|
|
throw new FormatException();
|
|
|
|
if (decimals)
|
|
{
|
|
if (fracCount > 9) // maximum precision 9 digits
|
|
break;
|
|
fraction = checked(10U * fraction + (c - ZERO));
|
|
fracCount++;
|
|
}
|
|
else
|
|
whole = checked(10U * whole + (c - ZERO));
|
|
}
|
|
|
|
var result = checked((float)whole + (fraction / pow10s[fracCount]));
|
|
|
|
if (neg) result = -result;
|
|
|
|
return result;
|
|
*/
|
|
|
|
return float.Parse(new string(buffer, start, len), formatProvider);
|
|
}
|
|
|
|
public static decimal StringToDecimal(char[] buffer, int start, int len, IFormatProvider formatProvider = null)
|
|
{
|
|
if (buffer == null)
|
|
throw new ArgumentNullException("buffer");
|
|
if (start < 0)
|
|
throw new ArgumentOutOfRangeException("start");
|
|
if (len < 0)
|
|
throw new ArgumentOutOfRangeException("len");
|
|
if (start + len > buffer.Length)
|
|
throw new ArgumentOutOfRangeException();
|
|
|
|
|
|
return decimal.Parse(new string(buffer, start, len), formatProvider);
|
|
}
|
|
|
|
public static int Int32ToBuffer(int value, char[] buffer, int start, IFormatProvider formatProvider = null)
|
|
{
|
|
if (buffer == null)
|
|
throw new ArgumentNullException("buffer");
|
|
if (start < 0 || start >= buffer.Length)
|
|
throw new ArgumentOutOfRangeException("start");
|
|
|
|
|
|
const int ZERO = (ushort) '0';
|
|
|
|
var idx = start;
|
|
var neg = value < 0;
|
|
// Take care of sign
|
|
var uvalue = neg ? (uint) (-value) : (uint) value;
|
|
// Conversion. Number is reversed.
|
|
do buffer[idx++] = (char) (ZERO + (uvalue%10)); while ((uvalue /= 10) != 0);
|
|
if (neg) buffer[idx++] = '-';
|
|
|
|
var length = idx - start;
|
|
// Reverse string
|
|
Array.Reverse(buffer, start, length);
|
|
|
|
return length;
|
|
}
|
|
|
|
public static int Int64ToBuffer(long value, char[] buffer, int start, IFormatProvider formatProvider = null)
|
|
{
|
|
if (buffer == null)
|
|
throw new ArgumentNullException("buffer");
|
|
if (start < 0 || start >= buffer.Length)
|
|
throw new ArgumentOutOfRangeException("start");
|
|
|
|
|
|
const int ZERO = (ushort) '0';
|
|
|
|
var idx = start;
|
|
// Take care of sign
|
|
var neg = (value < 0);
|
|
var uvalue = neg ? (ulong) (-value) : (ulong) value;
|
|
// Conversion. Number is reversed.
|
|
do buffer[idx++] = (char) (ZERO + (uvalue%10)); while ((uvalue /= 10) != 0);
|
|
if (neg) buffer[idx++] = '-';
|
|
|
|
var length = idx - start;
|
|
// Reverse string
|
|
Array.Reverse(buffer, start, length);
|
|
|
|
return length;
|
|
}
|
|
|
|
public static int UInt32ToBuffer(uint uvalue, char[] buffer, int start, IFormatProvider formatProvider = null)
|
|
{
|
|
if (buffer == null)
|
|
throw new ArgumentNullException("buffer");
|
|
if (start < 0 || start >= buffer.Length)
|
|
throw new ArgumentOutOfRangeException("start");
|
|
|
|
|
|
const int ZERO = (ushort) '0';
|
|
|
|
var idx = start;
|
|
// Take care of sign
|
|
// Conversion. Number is reversed.
|
|
do buffer[idx++] = (char) (ZERO + (uvalue%10)); while ((uvalue /= 10) != 0);
|
|
|
|
var length = idx - start;
|
|
// Reverse string
|
|
Array.Reverse(buffer, start, length);
|
|
|
|
return length;
|
|
}
|
|
|
|
public static int UInt64ToBuffer(ulong uvalue, char[] buffer, int start, IFormatProvider formatProvider = null)
|
|
{
|
|
if (buffer == null)
|
|
throw new ArgumentNullException("buffer");
|
|
if (start < 0 || start >= buffer.Length)
|
|
throw new ArgumentOutOfRangeException("start");
|
|
|
|
|
|
const ulong ZERO = (ulong) '0';
|
|
|
|
var idx = start;
|
|
// Conversion. Number is reversed.
|
|
do buffer[idx++] = (char) (ZERO + (uvalue%10)); while ((uvalue /= 10) != 0UL);
|
|
|
|
var length = idx - start;
|
|
// Reverse string
|
|
Array.Reverse(buffer, start, length);
|
|
|
|
return length;
|
|
}
|
|
|
|
public static int SingleToBuffer(float value, char[] buffer, int start, IFormatProvider formatProvider = null)
|
|
{
|
|
if (buffer == null)
|
|
throw new ArgumentNullException("buffer");
|
|
if (start < 0 || start >= buffer.Length)
|
|
throw new ArgumentOutOfRangeException("start");
|
|
|
|
|
|
var valueStr = value.ToString("R", formatProvider);
|
|
valueStr.CopyTo(0, buffer, start, valueStr.Length);
|
|
return valueStr.Length;
|
|
}
|
|
|
|
public static int DoubleToBuffer(double value, char[] buffer, int start, IFormatProvider formatProvider = null)
|
|
{
|
|
if (buffer == null)
|
|
throw new ArgumentNullException("buffer");
|
|
if (start < 0 || start >= buffer.Length)
|
|
throw new ArgumentOutOfRangeException("start");
|
|
|
|
|
|
var valueStr = value.ToString("R", formatProvider);
|
|
valueStr.CopyTo(0, buffer, start, valueStr.Length);
|
|
return valueStr.Length;
|
|
}
|
|
|
|
public static int DecimalToBuffer(decimal value, char[] buffer, int start, IFormatProvider formatProvider = null)
|
|
{
|
|
var valueStr = value.ToString(null, formatProvider);
|
|
valueStr.CopyTo(0, buffer, start, valueStr.Length);
|
|
return valueStr.Length;
|
|
}
|
|
}
|
|
}
|