Code:
/ Dotnetfx_Win7_3.5.1 / Dotnetfx_Win7_3.5.1 / 3.5.1 / DEVDIV / depot / DevDiv / releases / Orcas / NetFXw7 / ndp / fx / src / DataEntity / System / Data / Common / EntitySql / Literal.cs / 1 / Literal.cs
//----------------------------------------------------------------------
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
//
// @owner [....] [....]
//---------------------------------------------------------------------
namespace System.Data.Common.EntitySql
{
using System;
using System.Globalization;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Text;
///
/// defines literal value class
///
internal enum LiteralKind
{
Number,
String,
NonUnicodeString,
UnicodeString,
Boolean,
Binary,
DateTime,
Time,
DateTimeOffset,
Guid,
Null
}
///
/// Represents a literal ast node.
///
internal sealed class Literal : Expr
{
private string _originalValue;
private object _computedValue;
private Type _type;
private bool _isNull;
private bool _wasValueComputed = false;
private LiteralKind _literalKind;
private static readonly Byte[] _emptyByteArray = new byte[0];
///
/// initializes a literal ast node.
///
/// literal value in cql string representation
/// literal value class
/// query
/// input position
internal Literal( string originalValue, LiteralKind kind, string query, int inputPos )
: base(query, inputPos)
{
_originalValue = originalValue;
_literalKind = kind;
}
///
/// static factory to create boolean literals by value only
///
///
internal static Literal NewBooleanLiteral( bool value ) { return new Literal(value); }
private Literal( bool boolLiteral )
: base(null, 0)
{
_wasValueComputed = true;
_originalValue = String.Empty;
_computedValue = boolLiteral;
_type = typeof(System.Boolean);
}
///
/// returns true if original value is of number kind
///
internal bool IsNumberKind
{
get
{
return (_literalKind == LiteralKind.Number);
}
}
///
/// returns true if original value is signed
///
internal bool IsSigned
{
get
{
return (_originalValue[0] == '-' || _originalValue[0] == '+');
}
}
///
/// prefix a numeric literal with sign
///
///
internal void PrefixSign( string sign )
{
System.Diagnostics.Debug.Assert(IsNumberKind && !IsSigned);
System.Diagnostics.Debug.Assert(sign[0] == '-' || sign[0] == '+', "sign symbol must be + or -");
System.Diagnostics.Debug.Assert(_computedValue == null);
_originalValue = sign + _originalValue;
}
///
/// returns the original literal value
///
internal string OriginalValue
{
get
{
return _originalValue;
}
}
//
// Computed members
//
///
/// returns literal converted value
///
///
///
///
internal object Value
{
get
{
ComputeValue();
return _computedValue;
}
}
///
/// Returns true if literal value is null, false otherwise
///
///
///
///
internal bool IsNullLiteral
{
get
{
ComputeValue();
return _isNull;
}
}
///
/// returns true if literal is string type, false otherwise
///
///
///
///
internal bool IsString
{
get
{
ComputeValue();
return (_computedValue is String);
}
}
///
/// returns true if literal is unicode string type, false otherwise
///
///
///
///
internal bool IsUnicodeString
{
get
{
return IsString && _literalKind == LiteralKind.UnicodeString;
}
}
///
/// returns literal value type. if value is null, returns null
///
///
///
///
internal Type Type
{
get
{
ComputeValue();
return _type;
}
}
private void ComputeValue()
{
if (!_wasValueComputed)
{
_wasValueComputed = true;
switch (_literalKind)
{
case LiteralKind.Number:
_computedValue = ConvertNumericLiteral(ErrCtx, _originalValue);
break;
case LiteralKind.NonUnicodeString:
_computedValue = GetStringLiteralValue(_originalValue, false /* isUnicode */);
break;
case LiteralKind.UnicodeString:
_computedValue = GetStringLiteralValue(_originalValue, true /* isUnicode */);
break;
case LiteralKind.Boolean:
_computedValue = ConvertBooleanLiteralValue(ErrCtx, _originalValue);
break;
case LiteralKind.Binary:
_computedValue = ConvertBinaryLiteralValue(ErrCtx, _originalValue);
break;
case LiteralKind.DateTime:
_computedValue = ConvertDateTimeLiteralValue(ErrCtx, _originalValue);
break;
case LiteralKind.Time:
_computedValue = ConvertTimeLiteralValue(ErrCtx, _originalValue);
break;
case LiteralKind.DateTimeOffset:
_computedValue = ConvertDateTimeOffsetLiteralValue(ErrCtx, _originalValue);
break;
case LiteralKind.Guid:
_computedValue = ConvertGuidLiteralValue(ErrCtx, _originalValue);
break;
case LiteralKind.Null:
_computedValue = null;
_isNull = true;
break;
default:
throw EntityUtil.NotSupported(System.Data.Entity.Strings.LiteralTypeNotSupported(_literalKind.ToString()));
}
_type = _isNull ? null : _computedValue.GetType();
}
}
//
// Conversion Helpers
//
static char[] numberSuffixes = new char[] { 'U', 'u', 'L', 'l', 'F', 'f', 'M', 'm', 'D', 'd' };
static char[] floatTokens = new char[] { '.', 'E', 'e' };
private static object ConvertNumericLiteral(ErrorContext errCtx , string numericString)
{
int k = numericString.IndexOfAny(numberSuffixes);
if (-1 != k)
{
string suffix = numericString.Substring(k).ToUpperInvariant();
string numberPart = numericString.Substring(0, numericString.Length - suffix.Length);
switch (suffix)
{
case "U":
{
UInt32 value;
if (!UInt32.TryParse(numberPart, NumberStyles.Integer, CultureInfo.InvariantCulture, out value))
{
throw EntityUtil.EntitySqlError(errCtx, System.Data.Entity.Strings.CannotConvertNumericLiteral(numericString, "unsigned int"));
}
return value;
}
;
case "L":
{
long value;
if (!Int64.TryParse(numberPart, NumberStyles.Integer, CultureInfo.InvariantCulture, out value))
{
throw EntityUtil.EntitySqlError(errCtx, System.Data.Entity.Strings.CannotConvertNumericLiteral(numericString, "long"));
}
return value;
}
;
case "UL":
case "LU":
{
UInt64 value;
if (!UInt64.TryParse(numberPart, NumberStyles.Integer, CultureInfo.InvariantCulture, out value))
{
throw EntityUtil.EntitySqlError(errCtx, System.Data.Entity.Strings.CannotConvertNumericLiteral(numericString, "unsigned long"));
}
return value;
}
;
case "F":
{
Single value;
if (!Single.TryParse(numberPart, NumberStyles.Float, CultureInfo.InvariantCulture, out value))
{
throw EntityUtil.EntitySqlError(errCtx, System.Data.Entity.Strings.CannotConvertNumericLiteral(numericString, "float"));
}
return value;
}
;
case "M":
{
Decimal value;
if (!Decimal.TryParse(numberPart, NumberStyles.AllowLeadingSign | NumberStyles.AllowDecimalPoint, CultureInfo.InvariantCulture, out value))
{
throw EntityUtil.EntitySqlError(errCtx, System.Data.Entity.Strings.CannotConvertNumericLiteral(numericString, "decimal"));
}
return value;
}
;
case "D":
{
Double value;
if (!Double.TryParse(numberPart, NumberStyles.Float, CultureInfo.InvariantCulture, out value))
{
throw EntityUtil.EntitySqlError(errCtx, System.Data.Entity.Strings.CannotConvertNumericLiteral(numericString, "double"));
}
return value;
}
;
}
}
//
// if hit this point, try default conversion
//
return DefaultNumericConversion(numericString, errCtx);
}
///
/// performs conversion of numeric strings that have no type suffix hint.
///
///
///
///
private static object DefaultNumericConversion( string numericString, ErrorContext errCtx )
{
if (-1 != numericString.IndexOfAny(floatTokens))
{
Double value;
if (!Double.TryParse(numericString, NumberStyles.Float, CultureInfo.InvariantCulture, out value))
{
throw EntityUtil.EntitySqlError(errCtx, System.Data.Entity.Strings.CannotConvertNumericLiteral(numericString, "double"));
}
return value;
}
else
{
Int32 int32Value;
if (Int32.TryParse(numericString, NumberStyles.Integer, CultureInfo.InvariantCulture, out int32Value))
{
return int32Value;
}
Int64 int64Value;
if (!Int64.TryParse(numericString, NumberStyles.Integer, CultureInfo.InvariantCulture, out int64Value))
{
throw EntityUtil.EntitySqlError(errCtx, System.Data.Entity.Strings.CannotConvertNumericLiteral(numericString, "long"));
}
return int64Value;
}
}
///
/// converts boolean literal value
///
///
///
///
private static bool ConvertBooleanLiteralValue( ErrorContext errCtx, string booleanLiteralValue )
{
bool result = false;
if (!Boolean.TryParse(booleanLiteralValue, out result))
{
throw EntityUtil.EntitySqlError(errCtx, System.Data.Entity.Strings.InvalidLiteralFormat("Boolean", booleanLiteralValue));
}
return result;
}
///
/// returns the string literal value.
///
///
///
///
private static string GetStringLiteralValue( string stringLiteralValue, bool isUnicode )
{
Debug.Assert(stringLiteralValue.Length >= 2);
Debug.Assert(isUnicode == ('N' == stringLiteralValue[0]),"invalid string literal value");
int startIndex = (isUnicode ? 2 : 1);
char delimiter = stringLiteralValue[startIndex - 1];
Debug.Assert(delimiter.Equals('\'') || delimiter.Equals('\"'), "invalid string delimiter");
// NOTE: this is not a precondition validation. This validation is for security purposes based on the
// paranoid assumption that all input is evil. we should not see this exception under normal
// conditions.
if (delimiter != '\'' && delimiter != '\"')
{
throw EntityUtil.EntitySqlError(System.Data.Entity.Strings.MalformedStringLiteralPayload);
}
string result = "";
// NOTE: this is not a precondition validation. This validation is for security purposes based on the
// paranoid assumption that all input is evil. we should not see this exception under normal
// conditions.
int before = stringLiteralValue.Split(new char[] { delimiter }).Length - 1;
Debug.Assert(before % 2 == 0, "must have an even number of delimiters in the string literal");
if (0 != (before % 2))
{
throw EntityUtil.EntitySqlError(System.Data.Entity.Strings.MalformedStringLiteralPayload);
}
//
// extract the payload and replace escaped chars that match the envelope delimiter
//
result = stringLiteralValue.Substring(startIndex, stringLiteralValue.Length - (1 + startIndex));
result = result.Replace(new String(delimiter, 2), new String(delimiter, 1));
// NOTE: this is not a precondition validation. This validation is for security purposes based on the
// paranoid assumption that all input is evil. we should not see this exception under normal
// conditions.
int after = result.Split(new char[] { delimiter }).Length - 1;
Debug.Assert(after == (before - 2) / 2);
if ((after != ((before - 2) / 2)))
{
throw EntityUtil.EntitySqlError(System.Data.Entity.Strings.MalformedStringLiteralPayload);
}
return result;
}
///
/// converts hex string to byte array
///
///
///
///
private static byte[] ConvertBinaryLiteralValue( ErrorContext errCtx, string binaryLiteralValue )
{
Debug.Assert(null != binaryLiteralValue, "binaryStringLiteral must not be null");
if (String.IsNullOrEmpty(binaryLiteralValue))
{
return _emptyByteArray;
}
int startIndex = 0;
int endIndex = binaryLiteralValue.Length - 1;
Debug.Assert(startIndex <= endIndex, "startIndex <= endIndex");
int binaryStringLen = endIndex - startIndex + 1;
int byteArrayLen = binaryStringLen / 2;
bool hasOddBytes = 0 != (binaryStringLen % 2);
if (hasOddBytes)
{
byteArrayLen++;
}
byte[] binaryValue = new byte[byteArrayLen];
int arrayIndex = 0;
if (hasOddBytes)
{
binaryValue[arrayIndex++] = (byte)HexDigitToBinaryValue(binaryLiteralValue[startIndex++]);
}
while (startIndex < endIndex)
{
binaryValue[arrayIndex++] = (byte)((HexDigitToBinaryValue(binaryLiteralValue[startIndex++]) << 4) | HexDigitToBinaryValue(binaryLiteralValue[startIndex++]));
}
return binaryValue;
}
///
/// parse single hex char
/// PRECONDITION - hexChar must be valid hex digit
///
///
///
private static int HexDigitToBinaryValue( char hexChar )
{
if ( hexChar >= '0' && hexChar <= '9' ) return (int)( hexChar - '0' );
if ( hexChar >= 'A' && hexChar <= 'F' ) return (int)( hexChar - 'A' ) + 10;
if ( hexChar >= 'a' && hexChar <= 'f' ) return (int)( hexChar - 'a' ) + 10;
Debug.Assert(false, "Invalid Hexadecimal Digit");
throw EntityUtil.ArgumentOutOfRange("hexadecimal digit is not valid");
}
static readonly char[] _datetimeSeparators = new char[] { ' ', ':', '-', '.' };
static readonly char[] _dateSeparators = new char[] { '-' };
static readonly char[] _timeSeparators = new char[] { ':', '.' };
static readonly char[] _datetimeOffsetSeparators = new char[] { ' ', ':', '-', '.', '+', '-' };
///
/// converts datetime literal value
///
///
///
///
private static DateTime ConvertDateTimeLiteralValue( ErrorContext errCtx, string datetimeLiteralValue )
{
string[] datetimeParts = datetimeLiteralValue.Split(_datetimeSeparators, StringSplitOptions.RemoveEmptyEntries);
Debug.Assert(datetimeParts.Length >= 5, "datetime literal value must have at least 5 parts");
int year;
int month;
int day;
GetDateParts(datetimeLiteralValue, datetimeParts, out year, out month, out day);
int hour;
int minute;
int second;
int ticks;
GetTimeParts(datetimeLiteralValue, datetimeParts, 3, out hour, out minute, out second, out ticks);
Debug.Assert(year >= 1 && year <= 9999);
Debug.Assert(month >= 1 && month <= 12);
Debug.Assert(day >= 1 && day <= 31);
Debug.Assert(hour >= 0 && hour <= 24);
Debug.Assert(minute >= 0 && minute <= 59);
Debug.Assert(second >= 0 && second <= 59);
Debug.Assert(ticks >= 0 && ticks <= 9999999);
DateTime dateTime = new DateTime(year, month, day, hour, minute, second, 0);
dateTime = dateTime.AddTicks(ticks);
return dateTime;
}
private static DateTimeOffset ConvertDateTimeOffsetLiteralValue(ErrorContext errCtx, string datetimeLiteralValue)
{
string[] datetimeParts = datetimeLiteralValue.Split(_datetimeOffsetSeparators, StringSplitOptions.RemoveEmptyEntries);
Debug.Assert(datetimeParts.Length >= 7, "datetime literal value must have at least 7 parts");
int year;
int month;
int day;
GetDateParts(datetimeLiteralValue, datetimeParts, out year, out month, out day);
int hour;
int minute;
int second;
int ticks;
//Copy the time parts into a different array since the last two parts will be handled in this method.
string[] timeParts = new String[datetimeParts.Length - 2];
Array.Copy(datetimeParts, timeParts, datetimeParts.Length - 2);
GetTimeParts(datetimeLiteralValue, timeParts, 3, out hour, out minute, out second, out ticks);
Debug.Assert(year >= 1 && year <= 9999);
Debug.Assert(month >= 1 && month <= 12);
Debug.Assert(day >= 1 && day <= 31);
Debug.Assert(hour >= 0 && hour <= 24);
Debug.Assert(minute >= 0 && minute <= 59);
Debug.Assert(second >= 0 && second <= 59);
Debug.Assert(ticks >= 0 && ticks <= 9999999);
int offsetHours = Int32.Parse(datetimeParts[datetimeParts.Length - 2], NumberStyles.Integer, CultureInfo.InvariantCulture);
int offsetMinutes = Int32.Parse(datetimeParts[datetimeParts.Length - 1], NumberStyles.Integer, CultureInfo.InvariantCulture);
TimeSpan offsetTimeSpan = new TimeSpan(offsetHours, offsetMinutes, 0);
//If DateTimeOffset had a negative offset, we should negate the timespan
if(datetimeLiteralValue.IndexOf('+') == -1)
{
offsetTimeSpan = offsetTimeSpan.Negate();
}
DateTime dateTime = new DateTime(year, month, day, hour, minute, second, 0);
dateTime = dateTime.AddTicks(ticks);
try
{
return new DateTimeOffset(dateTime, offsetTimeSpan);
}
catch (ArgumentOutOfRangeException e)
{
throw EntityUtil.EntitySqlError(errCtx, System.Data.Entity.Strings.InvalidDateTimeOffsetLiteral(datetimeLiteralValue), e);
}
}
///
/// converts time literal value
///
///
///
///
private static TimeSpan ConvertTimeLiteralValue(ErrorContext errCtx, string datetimeLiteralValue)
{
string[] datetimeParts = datetimeLiteralValue.Split(_datetimeSeparators, StringSplitOptions.RemoveEmptyEntries);
Debug.Assert(datetimeParts.Length >= 2, "time literal value must have at least 2 parts");
int hour;
int minute;
int second;
int ticks;
GetTimeParts(datetimeLiteralValue, datetimeParts, 0, out hour, out minute, out second, out ticks);
Debug.Assert(hour >= 0 && hour <= 24);
Debug.Assert(minute >= 0 && minute <= 59);
Debug.Assert(second >= 0 && second <= 59);
Debug.Assert(ticks >= 0 && ticks <= 9999999);
TimeSpan ts = new TimeSpan(hour, minute, second);
ts = ts.Add(new TimeSpan(ticks));
return ts;
}
private static void GetTimeParts(string datetimeLiteralValue, string[] datetimeParts, int timePartStartIndex, out int hour, out int minute, out int second, out int ticks)
{
hour = Int32.Parse(datetimeParts[timePartStartIndex], NumberStyles.Integer, CultureInfo.InvariantCulture);
if (hour > 23)
{
throw EntityUtil.EntitySqlError(System.Data.Entity.Strings.InvalidHour(datetimeParts[timePartStartIndex], datetimeLiteralValue));
}
minute = Int32.Parse(datetimeParts[++timePartStartIndex], NumberStyles.Integer, CultureInfo.InvariantCulture);
if (minute > 59)
{
throw EntityUtil.EntitySqlError(System.Data.Entity.Strings.InvalidMinute(datetimeParts[timePartStartIndex], datetimeLiteralValue));
}
second = 0;
ticks = 0;
timePartStartIndex++;
if (datetimeParts.Length > timePartStartIndex)
{
second = Int32.Parse(datetimeParts[timePartStartIndex], NumberStyles.Integer, CultureInfo.InvariantCulture);
if (second > 59)
{
throw EntityUtil.EntitySqlError(System.Data.Entity.Strings.InvalidSecond(datetimeParts[timePartStartIndex], datetimeLiteralValue));
}
timePartStartIndex++;
if (datetimeParts.Length > timePartStartIndex)
{
//We need fractional time part to be seven digits
string ticksString = datetimeParts[timePartStartIndex].PadRight(7, '0');
ticks = Int32.Parse(ticksString , NumberStyles.Integer, CultureInfo.InvariantCulture);
}
}
}
private static void GetDateParts(string datetimeLiteralValue, string[] datetimeParts, out int year, out int month, out int day)
{
year = Int32.Parse(datetimeParts[0], NumberStyles.Integer, CultureInfo.InvariantCulture);
if (year < 1 || year > 9999)
{
throw EntityUtil.EntitySqlError(System.Data.Entity.Strings.InvalidYear(datetimeParts[0], datetimeLiteralValue));
}
month = Int32.Parse(datetimeParts[1], NumberStyles.Integer, CultureInfo.InvariantCulture);
if (month < 1 || month > 12)
{
throw EntityUtil.EntitySqlError(System.Data.Entity.Strings.InvalidMonth(datetimeParts[1], datetimeLiteralValue));
}
day = Int32.Parse(datetimeParts[2], NumberStyles.Integer, CultureInfo.InvariantCulture);
if (day < 1)
{
throw EntityUtil.EntitySqlError(System.Data.Entity.Strings.InvalidDay(datetimeParts[2], datetimeLiteralValue));
}
if (day > DateTime.DaysInMonth(year, month))
{
throw EntityUtil.EntitySqlError(System.Data.Entity.Strings.InvalidDayInMonth(datetimeParts[2], datetimeParts[1], datetimeLiteralValue));
}
}
///
/// converts guid literal value
///
///
///
///
private static Guid ConvertGuidLiteralValue( ErrorContext errCtx, string guidLiteralValue )
{
return new Guid(guidLiteralValue);
}
}
}
// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
//----------------------------------------------------------------------
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
//
// @owner [....] [....]
//---------------------------------------------------------------------
namespace System.Data.Common.EntitySql
{
using System;
using System.Globalization;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Text;
///
/// defines literal value class
///
internal enum LiteralKind
{
Number,
String,
NonUnicodeString,
UnicodeString,
Boolean,
Binary,
DateTime,
Time,
DateTimeOffset,
Guid,
Null
}
///
/// Represents a literal ast node.
///
internal sealed class Literal : Expr
{
private string _originalValue;
private object _computedValue;
private Type _type;
private bool _isNull;
private bool _wasValueComputed = false;
private LiteralKind _literalKind;
private static readonly Byte[] _emptyByteArray = new byte[0];
///
/// initializes a literal ast node.
///
/// literal value in cql string representation
/// literal value class
/// query
/// input position
internal Literal( string originalValue, LiteralKind kind, string query, int inputPos )
: base(query, inputPos)
{
_originalValue = originalValue;
_literalKind = kind;
}
///
/// static factory to create boolean literals by value only
///
///
internal static Literal NewBooleanLiteral( bool value ) { return new Literal(value); }
private Literal( bool boolLiteral )
: base(null, 0)
{
_wasValueComputed = true;
_originalValue = String.Empty;
_computedValue = boolLiteral;
_type = typeof(System.Boolean);
}
///
/// returns true if original value is of number kind
///
internal bool IsNumberKind
{
get
{
return (_literalKind == LiteralKind.Number);
}
}
///
/// returns true if original value is signed
///
internal bool IsSigned
{
get
{
return (_originalValue[0] == '-' || _originalValue[0] == '+');
}
}
///
/// prefix a numeric literal with sign
///
///
internal void PrefixSign( string sign )
{
System.Diagnostics.Debug.Assert(IsNumberKind && !IsSigned);
System.Diagnostics.Debug.Assert(sign[0] == '-' || sign[0] == '+', "sign symbol must be + or -");
System.Diagnostics.Debug.Assert(_computedValue == null);
_originalValue = sign + _originalValue;
}
///
/// returns the original literal value
///
internal string OriginalValue
{
get
{
return _originalValue;
}
}
//
// Computed members
//
///
/// returns literal converted value
///
///
///
///
internal object Value
{
get
{
ComputeValue();
return _computedValue;
}
}
///
/// Returns true if literal value is null, false otherwise
///
///
///
///
internal bool IsNullLiteral
{
get
{
ComputeValue();
return _isNull;
}
}
///
/// returns true if literal is string type, false otherwise
///
///
///
///
internal bool IsString
{
get
{
ComputeValue();
return (_computedValue is String);
}
}
///
/// returns true if literal is unicode string type, false otherwise
///
///
///
///
internal bool IsUnicodeString
{
get
{
return IsString && _literalKind == LiteralKind.UnicodeString;
}
}
///
/// returns literal value type. if value is null, returns null
///
///
///
///
internal Type Type
{
get
{
ComputeValue();
return _type;
}
}
private void ComputeValue()
{
if (!_wasValueComputed)
{
_wasValueComputed = true;
switch (_literalKind)
{
case LiteralKind.Number:
_computedValue = ConvertNumericLiteral(ErrCtx, _originalValue);
break;
case LiteralKind.NonUnicodeString:
_computedValue = GetStringLiteralValue(_originalValue, false /* isUnicode */);
break;
case LiteralKind.UnicodeString:
_computedValue = GetStringLiteralValue(_originalValue, true /* isUnicode */);
break;
case LiteralKind.Boolean:
_computedValue = ConvertBooleanLiteralValue(ErrCtx, _originalValue);
break;
case LiteralKind.Binary:
_computedValue = ConvertBinaryLiteralValue(ErrCtx, _originalValue);
break;
case LiteralKind.DateTime:
_computedValue = ConvertDateTimeLiteralValue(ErrCtx, _originalValue);
break;
case LiteralKind.Time:
_computedValue = ConvertTimeLiteralValue(ErrCtx, _originalValue);
break;
case LiteralKind.DateTimeOffset:
_computedValue = ConvertDateTimeOffsetLiteralValue(ErrCtx, _originalValue);
break;
case LiteralKind.Guid:
_computedValue = ConvertGuidLiteralValue(ErrCtx, _originalValue);
break;
case LiteralKind.Null:
_computedValue = null;
_isNull = true;
break;
default:
throw EntityUtil.NotSupported(System.Data.Entity.Strings.LiteralTypeNotSupported(_literalKind.ToString()));
}
_type = _isNull ? null : _computedValue.GetType();
}
}
//
// Conversion Helpers
//
static char[] numberSuffixes = new char[] { 'U', 'u', 'L', 'l', 'F', 'f', 'M', 'm', 'D', 'd' };
static char[] floatTokens = new char[] { '.', 'E', 'e' };
private static object ConvertNumericLiteral(ErrorContext errCtx , string numericString)
{
int k = numericString.IndexOfAny(numberSuffixes);
if (-1 != k)
{
string suffix = numericString.Substring(k).ToUpperInvariant();
string numberPart = numericString.Substring(0, numericString.Length - suffix.Length);
switch (suffix)
{
case "U":
{
UInt32 value;
if (!UInt32.TryParse(numberPart, NumberStyles.Integer, CultureInfo.InvariantCulture, out value))
{
throw EntityUtil.EntitySqlError(errCtx, System.Data.Entity.Strings.CannotConvertNumericLiteral(numericString, "unsigned int"));
}
return value;
}
;
case "L":
{
long value;
if (!Int64.TryParse(numberPart, NumberStyles.Integer, CultureInfo.InvariantCulture, out value))
{
throw EntityUtil.EntitySqlError(errCtx, System.Data.Entity.Strings.CannotConvertNumericLiteral(numericString, "long"));
}
return value;
}
;
case "UL":
case "LU":
{
UInt64 value;
if (!UInt64.TryParse(numberPart, NumberStyles.Integer, CultureInfo.InvariantCulture, out value))
{
throw EntityUtil.EntitySqlError(errCtx, System.Data.Entity.Strings.CannotConvertNumericLiteral(numericString, "unsigned long"));
}
return value;
}
;
case "F":
{
Single value;
if (!Single.TryParse(numberPart, NumberStyles.Float, CultureInfo.InvariantCulture, out value))
{
throw EntityUtil.EntitySqlError(errCtx, System.Data.Entity.Strings.CannotConvertNumericLiteral(numericString, "float"));
}
return value;
}
;
case "M":
{
Decimal value;
if (!Decimal.TryParse(numberPart, NumberStyles.AllowLeadingSign | NumberStyles.AllowDecimalPoint, CultureInfo.InvariantCulture, out value))
{
throw EntityUtil.EntitySqlError(errCtx, System.Data.Entity.Strings.CannotConvertNumericLiteral(numericString, "decimal"));
}
return value;
}
;
case "D":
{
Double value;
if (!Double.TryParse(numberPart, NumberStyles.Float, CultureInfo.InvariantCulture, out value))
{
throw EntityUtil.EntitySqlError(errCtx, System.Data.Entity.Strings.CannotConvertNumericLiteral(numericString, "double"));
}
return value;
}
;
}
}
//
// if hit this point, try default conversion
//
return DefaultNumericConversion(numericString, errCtx);
}
///
/// performs conversion of numeric strings that have no type suffix hint.
///
///
///
///
private static object DefaultNumericConversion( string numericString, ErrorContext errCtx )
{
if (-1 != numericString.IndexOfAny(floatTokens))
{
Double value;
if (!Double.TryParse(numericString, NumberStyles.Float, CultureInfo.InvariantCulture, out value))
{
throw EntityUtil.EntitySqlError(errCtx, System.Data.Entity.Strings.CannotConvertNumericLiteral(numericString, "double"));
}
return value;
}
else
{
Int32 int32Value;
if (Int32.TryParse(numericString, NumberStyles.Integer, CultureInfo.InvariantCulture, out int32Value))
{
return int32Value;
}
Int64 int64Value;
if (!Int64.TryParse(numericString, NumberStyles.Integer, CultureInfo.InvariantCulture, out int64Value))
{
throw EntityUtil.EntitySqlError(errCtx, System.Data.Entity.Strings.CannotConvertNumericLiteral(numericString, "long"));
}
return int64Value;
}
}
///
/// converts boolean literal value
///
///
///
///
private static bool ConvertBooleanLiteralValue( ErrorContext errCtx, string booleanLiteralValue )
{
bool result = false;
if (!Boolean.TryParse(booleanLiteralValue, out result))
{
throw EntityUtil.EntitySqlError(errCtx, System.Data.Entity.Strings.InvalidLiteralFormat("Boolean", booleanLiteralValue));
}
return result;
}
///
/// returns the string literal value.
///
///
///
///
private static string GetStringLiteralValue( string stringLiteralValue, bool isUnicode )
{
Debug.Assert(stringLiteralValue.Length >= 2);
Debug.Assert(isUnicode == ('N' == stringLiteralValue[0]),"invalid string literal value");
int startIndex = (isUnicode ? 2 : 1);
char delimiter = stringLiteralValue[startIndex - 1];
Debug.Assert(delimiter.Equals('\'') || delimiter.Equals('\"'), "invalid string delimiter");
// NOTE: this is not a precondition validation. This validation is for security purposes based on the
// paranoid assumption that all input is evil. we should not see this exception under normal
// conditions.
if (delimiter != '\'' && delimiter != '\"')
{
throw EntityUtil.EntitySqlError(System.Data.Entity.Strings.MalformedStringLiteralPayload);
}
string result = "";
// NOTE: this is not a precondition validation. This validation is for security purposes based on the
// paranoid assumption that all input is evil. we should not see this exception under normal
// conditions.
int before = stringLiteralValue.Split(new char[] { delimiter }).Length - 1;
Debug.Assert(before % 2 == 0, "must have an even number of delimiters in the string literal");
if (0 != (before % 2))
{
throw EntityUtil.EntitySqlError(System.Data.Entity.Strings.MalformedStringLiteralPayload);
}
//
// extract the payload and replace escaped chars that match the envelope delimiter
//
result = stringLiteralValue.Substring(startIndex, stringLiteralValue.Length - (1 + startIndex));
result = result.Replace(new String(delimiter, 2), new String(delimiter, 1));
// NOTE: this is not a precondition validation. This validation is for security purposes based on the
// paranoid assumption that all input is evil. we should not see this exception under normal
// conditions.
int after = result.Split(new char[] { delimiter }).Length - 1;
Debug.Assert(after == (before - 2) / 2);
if ((after != ((before - 2) / 2)))
{
throw EntityUtil.EntitySqlError(System.Data.Entity.Strings.MalformedStringLiteralPayload);
}
return result;
}
///
/// converts hex string to byte array
///
///
///
///
private static byte[] ConvertBinaryLiteralValue( ErrorContext errCtx, string binaryLiteralValue )
{
Debug.Assert(null != binaryLiteralValue, "binaryStringLiteral must not be null");
if (String.IsNullOrEmpty(binaryLiteralValue))
{
return _emptyByteArray;
}
int startIndex = 0;
int endIndex = binaryLiteralValue.Length - 1;
Debug.Assert(startIndex <= endIndex, "startIndex <= endIndex");
int binaryStringLen = endIndex - startIndex + 1;
int byteArrayLen = binaryStringLen / 2;
bool hasOddBytes = 0 != (binaryStringLen % 2);
if (hasOddBytes)
{
byteArrayLen++;
}
byte[] binaryValue = new byte[byteArrayLen];
int arrayIndex = 0;
if (hasOddBytes)
{
binaryValue[arrayIndex++] = (byte)HexDigitToBinaryValue(binaryLiteralValue[startIndex++]);
}
while (startIndex < endIndex)
{
binaryValue[arrayIndex++] = (byte)((HexDigitToBinaryValue(binaryLiteralValue[startIndex++]) << 4) | HexDigitToBinaryValue(binaryLiteralValue[startIndex++]));
}
return binaryValue;
}
///
/// parse single hex char
/// PRECONDITION - hexChar must be valid hex digit
///
///
///
private static int HexDigitToBinaryValue( char hexChar )
{
if ( hexChar >= '0' && hexChar <= '9' ) return (int)( hexChar - '0' );
if ( hexChar >= 'A' && hexChar <= 'F' ) return (int)( hexChar - 'A' ) + 10;
if ( hexChar >= 'a' && hexChar <= 'f' ) return (int)( hexChar - 'a' ) + 10;
Debug.Assert(false, "Invalid Hexadecimal Digit");
throw EntityUtil.ArgumentOutOfRange("hexadecimal digit is not valid");
}
static readonly char[] _datetimeSeparators = new char[] { ' ', ':', '-', '.' };
static readonly char[] _dateSeparators = new char[] { '-' };
static readonly char[] _timeSeparators = new char[] { ':', '.' };
static readonly char[] _datetimeOffsetSeparators = new char[] { ' ', ':', '-', '.', '+', '-' };
///
/// converts datetime literal value
///
///
///
///
private static DateTime ConvertDateTimeLiteralValue( ErrorContext errCtx, string datetimeLiteralValue )
{
string[] datetimeParts = datetimeLiteralValue.Split(_datetimeSeparators, StringSplitOptions.RemoveEmptyEntries);
Debug.Assert(datetimeParts.Length >= 5, "datetime literal value must have at least 5 parts");
int year;
int month;
int day;
GetDateParts(datetimeLiteralValue, datetimeParts, out year, out month, out day);
int hour;
int minute;
int second;
int ticks;
GetTimeParts(datetimeLiteralValue, datetimeParts, 3, out hour, out minute, out second, out ticks);
Debug.Assert(year >= 1 && year <= 9999);
Debug.Assert(month >= 1 && month <= 12);
Debug.Assert(day >= 1 && day <= 31);
Debug.Assert(hour >= 0 && hour <= 24);
Debug.Assert(minute >= 0 && minute <= 59);
Debug.Assert(second >= 0 && second <= 59);
Debug.Assert(ticks >= 0 && ticks <= 9999999);
DateTime dateTime = new DateTime(year, month, day, hour, minute, second, 0);
dateTime = dateTime.AddTicks(ticks);
return dateTime;
}
private static DateTimeOffset ConvertDateTimeOffsetLiteralValue(ErrorContext errCtx, string datetimeLiteralValue)
{
string[] datetimeParts = datetimeLiteralValue.Split(_datetimeOffsetSeparators, StringSplitOptions.RemoveEmptyEntries);
Debug.Assert(datetimeParts.Length >= 7, "datetime literal value must have at least 7 parts");
int year;
int month;
int day;
GetDateParts(datetimeLiteralValue, datetimeParts, out year, out month, out day);
int hour;
int minute;
int second;
int ticks;
//Copy the time parts into a different array since the last two parts will be handled in this method.
string[] timeParts = new String[datetimeParts.Length - 2];
Array.Copy(datetimeParts, timeParts, datetimeParts.Length - 2);
GetTimeParts(datetimeLiteralValue, timeParts, 3, out hour, out minute, out second, out ticks);
Debug.Assert(year >= 1 && year <= 9999);
Debug.Assert(month >= 1 && month <= 12);
Debug.Assert(day >= 1 && day <= 31);
Debug.Assert(hour >= 0 && hour <= 24);
Debug.Assert(minute >= 0 && minute <= 59);
Debug.Assert(second >= 0 && second <= 59);
Debug.Assert(ticks >= 0 && ticks <= 9999999);
int offsetHours = Int32.Parse(datetimeParts[datetimeParts.Length - 2], NumberStyles.Integer, CultureInfo.InvariantCulture);
int offsetMinutes = Int32.Parse(datetimeParts[datetimeParts.Length - 1], NumberStyles.Integer, CultureInfo.InvariantCulture);
TimeSpan offsetTimeSpan = new TimeSpan(offsetHours, offsetMinutes, 0);
//If DateTimeOffset had a negative offset, we should negate the timespan
if(datetimeLiteralValue.IndexOf('+') == -1)
{
offsetTimeSpan = offsetTimeSpan.Negate();
}
DateTime dateTime = new DateTime(year, month, day, hour, minute, second, 0);
dateTime = dateTime.AddTicks(ticks);
try
{
return new DateTimeOffset(dateTime, offsetTimeSpan);
}
catch (ArgumentOutOfRangeException e)
{
throw EntityUtil.EntitySqlError(errCtx, System.Data.Entity.Strings.InvalidDateTimeOffsetLiteral(datetimeLiteralValue), e);
}
}
///
/// converts time literal value
///
///
///
///
private static TimeSpan ConvertTimeLiteralValue(ErrorContext errCtx, string datetimeLiteralValue)
{
string[] datetimeParts = datetimeLiteralValue.Split(_datetimeSeparators, StringSplitOptions.RemoveEmptyEntries);
Debug.Assert(datetimeParts.Length >= 2, "time literal value must have at least 2 parts");
int hour;
int minute;
int second;
int ticks;
GetTimeParts(datetimeLiteralValue, datetimeParts, 0, out hour, out minute, out second, out ticks);
Debug.Assert(hour >= 0 && hour <= 24);
Debug.Assert(minute >= 0 && minute <= 59);
Debug.Assert(second >= 0 && second <= 59);
Debug.Assert(ticks >= 0 && ticks <= 9999999);
TimeSpan ts = new TimeSpan(hour, minute, second);
ts = ts.Add(new TimeSpan(ticks));
return ts;
}
private static void GetTimeParts(string datetimeLiteralValue, string[] datetimeParts, int timePartStartIndex, out int hour, out int minute, out int second, out int ticks)
{
hour = Int32.Parse(datetimeParts[timePartStartIndex], NumberStyles.Integer, CultureInfo.InvariantCulture);
if (hour > 23)
{
throw EntityUtil.EntitySqlError(System.Data.Entity.Strings.InvalidHour(datetimeParts[timePartStartIndex], datetimeLiteralValue));
}
minute = Int32.Parse(datetimeParts[++timePartStartIndex], NumberStyles.Integer, CultureInfo.InvariantCulture);
if (minute > 59)
{
throw EntityUtil.EntitySqlError(System.Data.Entity.Strings.InvalidMinute(datetimeParts[timePartStartIndex], datetimeLiteralValue));
}
second = 0;
ticks = 0;
timePartStartIndex++;
if (datetimeParts.Length > timePartStartIndex)
{
second = Int32.Parse(datetimeParts[timePartStartIndex], NumberStyles.Integer, CultureInfo.InvariantCulture);
if (second > 59)
{
throw EntityUtil.EntitySqlError(System.Data.Entity.Strings.InvalidSecond(datetimeParts[timePartStartIndex], datetimeLiteralValue));
}
timePartStartIndex++;
if (datetimeParts.Length > timePartStartIndex)
{
//We need fractional time part to be seven digits
string ticksString = datetimeParts[timePartStartIndex].PadRight(7, '0');
ticks = Int32.Parse(ticksString , NumberStyles.Integer, CultureInfo.InvariantCulture);
}
}
}
private static void GetDateParts(string datetimeLiteralValue, string[] datetimeParts, out int year, out int month, out int day)
{
year = Int32.Parse(datetimeParts[0], NumberStyles.Integer, CultureInfo.InvariantCulture);
if (year < 1 || year > 9999)
{
throw EntityUtil.EntitySqlError(System.Data.Entity.Strings.InvalidYear(datetimeParts[0], datetimeLiteralValue));
}
month = Int32.Parse(datetimeParts[1], NumberStyles.Integer, CultureInfo.InvariantCulture);
if (month < 1 || month > 12)
{
throw EntityUtil.EntitySqlError(System.Data.Entity.Strings.InvalidMonth(datetimeParts[1], datetimeLiteralValue));
}
day = Int32.Parse(datetimeParts[2], NumberStyles.Integer, CultureInfo.InvariantCulture);
if (day < 1)
{
throw EntityUtil.EntitySqlError(System.Data.Entity.Strings.InvalidDay(datetimeParts[2], datetimeLiteralValue));
}
if (day > DateTime.DaysInMonth(year, month))
{
throw EntityUtil.EntitySqlError(System.Data.Entity.Strings.InvalidDayInMonth(datetimeParts[2], datetimeParts[1], datetimeLiteralValue));
}
}
///
/// converts guid literal value
///
///
///
///
private static Guid ConvertGuidLiteralValue( ErrorContext errCtx, string guidLiteralValue )
{
return new Guid(guidLiteralValue);
}
}
}
// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
Link Menu

This book is available now!
Buy at Amazon US or
Buy at Amazon UK
- SessionIDManager.cs
- XmlParser.cs
- SafeRegistryKey.cs
- DataSourceProvider.cs
- UIElement3D.cs
- BindingRestrictions.cs
- ObjectStateManager.cs
- XNameConverter.cs
- AuthenticodeSignatureInformation.cs
- ComponentChangedEvent.cs
- ActiveXHost.cs
- RootContext.cs
- TableRowCollection.cs
- ApplicationProxyInternal.cs
- cookiecollection.cs
- ObjectTag.cs
- Subtree.cs
- LocalsItemDescription.cs
- HttpRequestCacheValidator.cs
- XPathMultyIterator.cs
- WebPartRestoreVerb.cs
- TextAnchor.cs
- ExtensionWindow.cs
- CapabilitiesUse.cs
- WebPartTransformerCollection.cs
- Marshal.cs
- TaskFormBase.cs
- WaitHandleCannotBeOpenedException.cs
- COM2FontConverter.cs
- ListViewContainer.cs
- AssemblySettingAttributes.cs
- AbstractExpressions.cs
- Maps.cs
- securestring.cs
- NameSpaceExtractor.cs
- Simplifier.cs
- PropertyInfo.cs
- ApplicationFileCodeDomTreeGenerator.cs
- MessageHeaderException.cs
- PasswordTextNavigator.cs
- WindowsImpersonationContext.cs
- TextMetrics.cs
- PathGeometry.cs
- ToolboxBitmapAttribute.cs
- HtmlImageAdapter.cs
- PresentationTraceSources.cs
- Rect3D.cs
- MediaTimeline.cs
- DashStyle.cs
- PersonalizationEntry.cs
- comcontractssection.cs
- BamlLocalizer.cs
- ContainerControlDesigner.cs
- Constraint.cs
- TreeBuilderXamlTranslator.cs
- XmlIgnoreAttribute.cs
- BitmapMetadataEnumerator.cs
- ModulesEntry.cs
- Control.cs
- TreeNodeMouseHoverEvent.cs
- SystemIPGlobalProperties.cs
- InstanceData.cs
- ContextQuery.cs
- AsymmetricKeyExchangeFormatter.cs
- InteropAutomationProvider.cs
- SerTrace.cs
- SourceItem.cs
- XmlSchemaInfo.cs
- _NativeSSPI.cs
- VisualTreeFlattener.cs
- CodeSnippetTypeMember.cs
- SocketInformation.cs
- StylusCaptureWithinProperty.cs
- selecteditemcollection.cs
- ColumnMap.cs
- StdValidatorsAndConverters.cs
- WeakReadOnlyCollection.cs
- PageAsyncTaskManager.cs
- PageEventArgs.cs
- WebEventTraceProvider.cs
- RelationshipConstraintValidator.cs
- CommandDesigner.cs
- HttpListener.cs
- PrivilegeNotHeldException.cs
- HScrollProperties.cs
- COSERVERINFO.cs
- CheckBoxFlatAdapter.cs
- DefaultWorkflowSchedulerService.cs
- DecoderReplacementFallback.cs
- HtmlDocument.cs
- CommandLibraryHelper.cs
- PreviewKeyDownEventArgs.cs
- HtmlElementCollection.cs
- CounterCreationData.cs
- TraceEventCache.cs
- XPathParser.cs
- BookmarkNameHelper.cs
- SystemSounds.cs
- EastAsianLunisolarCalendar.cs
- OleStrCAMarshaler.cs