Example #1
0
        internal static bool UsualArithmeticConversion(object left, object right, out object leftConverted,
                                                       out object rightConverted)
        {
            left           = PSObject.Unwrap(left);
            right          = PSObject.Unwrap(right);
            leftConverted  = null;
            rightConverted = null;
            // 6.15 Usual arithmetic conversions
            // If neither operand designates a value having numeric type, then
            if ((
                    left == null || right == null ||                              // one operand is null => it needs to be converted to a number
                    (!left.GetType().IsNumeric() && !right.GetType().IsNumeric()) // if both aren't numbers, convert
                    ) &&
                !UsualArithmeticConversionOneOperand(ref left, ref right))        // actually convert
            {
                return(false);
            }
            Type leftType  = left.GetType();
            Type rightType = right.GetType();

            // Numeric conversions:
            // Otherwise, if one operand designates a value of type float, the values designated by both operands are
            // converted to type double, if necessary. The result has type double.
            if (leftType == typeof(float) || rightType == typeof(float))
            {
                return(TryConvertToAnyNumericWithLeastType(left, typeof(double), out leftConverted) &&
                       TryConvertToAnyNumericWithLeastType(right, typeof(double), out rightConverted));
            }

            // If one operand designates a value of type decimal, the value designated by the other operand is converted
            // to that type, if necessary. The result has type decimal.
            // Otherwise, if one operand designates a value of type double, the value designated by the
            // other operand is converted to that type, if necessary. The result has type double.
            // Otherwise, if one operand designates a value of type long, the value designated by the other operand
            // value is converted to that type, if necessary. The result has the type first in the sequence long and
            // double that can represent its value.
            // Otherwise, the values designated by both operands are converted to type int, if necessary.
            foreach (var type in new [] { typeof(decimal), typeof(double), typeof(long), typeof(int) })
            {
                // NOTE: the specification tells us, that if e.g. the left is int, the right should be
                // converted to int. However, if it doesn't fit in an int, we need to try more!
                if (leftType == type)
                {
                    leftConverted = left;
                    return(TryConvertToAnyNumericWithLeastType(right, type, out rightConverted));
                }
                if (rightType == type)
                {
                    rightConverted = right;
                    return(TryConvertToAnyNumericWithLeastType(left, type, out leftConverted));
                }
            }
            // shouldn't happen as one operand should be of one of the numeric types
            return(false);
        }
Example #2
0
 /// <summary>
 /// Returns an IEnumerable for a given object compatable with the shell.
 /// </summary>
 /// <param name="obj">The object to use.</param>
 /// <returns>The enumerator if it can work, null otherwise.</returns>
 public static IEnumerable GetEnumerable(object obj)
 {
     obj = PSObject.Unwrap(obj);
     // Powershell seems to exclude a few types from from being enumerables
     if (ShouldPreventEnumeration(obj))
     {
         return(null);
     }
     // either return it as enumerable or null
     return(obj as IEnumerable);
 }
Example #3
0
 /// <summary>
 /// Returns an IEnumerable for a given object compatable with the shell.
 /// </summary>
 /// <param name="obj">The object to use.</param>
 /// <returns>The enumerator if it can work, null otherwise.</returns>
 public static IEnumerable GetEnumerable(object obj)
 {
     obj = PSObject.Unwrap(obj);
     // Powershell seems to exclude a few types from from being enumerables
     if (obj is IDictionary || obj is string || obj is XmlDocument)
     {
         return(null);
     }
     // either return it as enumerable or null
     return(obj as IEnumerable);
 }
Example #4
0
        /// <summary>
        /// The parse currently adds each parameter without value and each value without parameter name, because
        /// it doesn't know at parse time whether the value belongs to the paramater or if the parameter is a switch
        /// parameter and the value is just a positional parameter. As we now know more abot the parameters, we can
        /// merge all parameters with the upcoming value if it's not a switch parameter
        /// </summary>
        private void MergeParameters()
        {
            var oldParameters = new Collection <CommandParameter>(new List <CommandParameter>(Parameters));

            Parameters.Clear();
            int numParams = oldParameters.Count;

            for (int i = 0; i < numParams; i++)
            {
                var current      = oldParameters[i];
                var peek         = (i < numParams - 1) ? oldParameters[i + 1] : null;
                var hasValidName = !String.IsNullOrEmpty(current.Name);
                // if we have a switch parameter, set default value or pre-convert to bool if numeric
                if (hasValidName && IsSwitchParameter(current.Name))
                {
                    // if null (=unset) it's true; even if it's explicitly set to null
                    object value = current.Value;
                    if (current.Value == null)
                    {
                        Parameters.Add(current.Name, true);
                        continue;
                    }
                    // strange thing in PS: While LanguagePrimitives aren't able to convert from numerics to
                    // SwitchParameter, it does work with parameters. So we check it here
                    else if (PSObject.Unwrap(current.Value).GetType().IsNumeric())
                    {
                        value = LanguagePrimitives.ConvertTo <bool>(current.Value);
                    }
                    Parameters.Add(current.Name, value);
                }
                // if the current parameter has no argument (and not explicilty set to null), try to merge the next
                else if (peek != null &&
                         hasValidName &&
                         current.Value == null &&

                         String.IsNullOrEmpty(peek.Name))
                {
                    Parameters.Add(current.Name, peek.Value);
                    i++; // skip next element as it was merged
                }
                // otherwise we have a usual parameter/argument set
                else
                {
                    Parameters.Add(current);
                }
            }
        }
Example #5
0
 private static bool ConvertToBool(object rawValue)
 {
     rawValue = PSObject.Unwrap(rawValue); // just make this sure
     if (rawValue == null)
     {
         return(false);
     }
     if (rawValue is bool)
     {
         return((bool)rawValue);
     }
     else if (rawValue is string)
     {
         return(((string)rawValue).Length != 0);
     }
     else if (rawValue is IList)
     {
         var list = rawValue as IList;
         if (list.Count > 1)
         {
             return(true);
         }
         else if (list.Count == 1)
         {
             return(ConvertToBool(list[0]));
         }
         else // empty list
         {
             return(false);
         }
     }
     else if (rawValue.GetType().IsNumeric())
     {
         return(((dynamic)rawValue) != 0);
     }
     else if (rawValue is char)
     {
         return(((char)rawValue) != ((char)0));
     }
     else if (rawValue is SwitchParameter)
     {
         return(((SwitchParameter)rawValue).IsPresent);
     }
     return(true); // any object that's not null
 }
Example #6
0
        /// <summary>
        /// Returns an enumerator for a given object compatable with the shell.
        /// </summary>
        /// <param name="obj">The object to use.</param>
        /// <returns>The enumerator if it can work, null otherwise.</returns>
        public static IEnumerator GetEnumerator(object obj)
        {
            obj = PSObject.Unwrap(obj);
            // Powershell seems to exclude a few types from from being enumerables
            if (ShouldPreventEnumeration(obj))
            {
                return(null);
            }
            var enumerable = GetEnumerable(obj);

            if (enumerable != null)
            {
                return(enumerable.GetEnumerator());
            }
            if (obj is IEnumerator)
            {
                return(obj as IEnumerator);
            }
            return(null);
        }
Example #7
0
        /// <summary>
        /// Returns an enumerator for a given object compatable with the shell.
        /// </summary>
        /// <param name="obj">The object to use.</param>
        /// <returns>The enumerator if it can work, null otherwise.</returns>
        public static IEnumerator GetEnumerator(object obj)
        {
            obj = PSObject.Unwrap(obj);
            // Powershell seems to exclude dictionaries and strings from being enumerables
            if (obj is IDictionary || obj is string)
            {
                return(null);
            }
            var enumerable = GetEnumerable(obj);

            if (enumerable != null)
            {
                return(enumerable.GetEnumerator());
            }
            if (obj is IEnumerator)
            {
                return(obj as IEnumerator);
            }
            return(null);
        }
Example #8
0
        private static string ConvertToString(object rawValue, IFormatProvider formatProvider)
        {
            rawValue = PSObject.Unwrap(rawValue);
            // A value of null type is converted to the empty string.
            if (rawValue == null)
            {
                return(string.Empty);
            }
            // The bool value $false is converted to "False"; the bool value $true is converted to "True".
            if (rawValue is bool)
            {
                return((bool)rawValue ? "True" : "False");
            }
            // A char type value is converted to a 1-character string containing that char.
            if (rawValue is char)
            {
                return(new string((char)rawValue, 1));
            }
            // A numeric type value is converted to a string having the form of a corresponding numeric literal.
            // However, the result has no leading or trailing spaces, no leading plus sign, integers have base 10, and
            // there is no type suffix. For a decimal conversion, the scale is preserved. For values of -∞, +∞, and
            // NaN, the resulting strings are "-Infinity", "Infinity", and "NaN", respectively.
            if (rawValue is byte || rawValue is short || rawValue is int || rawValue is long)
            {
                return(Convert.ToInt64(rawValue).ToString(formatProvider));
            }
            if (rawValue is decimal)
            {
                return(((decimal)rawValue).ToString(formatProvider));
            }
            if (rawValue is float)
            {
                return(((float)rawValue).ToString(formatProvider));
            }
            if (rawValue is double)
            {
                return(((double)rawValue).ToString(formatProvider));
            }
            // For an enumeration type value, the result is a string containing the name of each enumeration
            // constant encoded in that value, separated by commas.
            if (rawValue is Enum)
            {
                // Nicely enough, this is the format specified by the G format specifier. Except for the spaces
                // after the comma. But PowerShell seems to do exactly the same.
                return(((Enum)rawValue).ToString("G"));
            }
            // For a 1-dimensional array, the result is a string containing the value of each element in that array, from
            // start to end, converted to string, with elements being separated by the current Output Field
            // Separator (§2.3.2.2). For an array having elements that are themselves arrays, only the top-level
            // elements are converted. The string used to represent the value of an element that is an array, is
            // implementation defined. For a multi-dimensional array, it is flattened (§9.12) and then treated as a
            // 1-dimensional array.
            // Windows PowerShell: For other enumerable types, the source value is treated like a 1-dimensional
            // array.
            IEnumerable enumerable = GetEnumerable(rawValue);

            if (enumerable != null)
            {
                var runspace = Runspaces.Runspace.DefaultRunspace;
                var ofsV     = runspace.SessionStateProxy.GetVariable("OFS");
                var ofs      = ofsV != null?ofsV.ToString() : " ";

                // Linq handles flattening
                return(String.Join(ofs, from o in enumerable.Cast <object>()
                                   select o == null ? "" : PSObject.Unwrap(o).ToString()));
            }
            // A scriptblock type value is converted to a string containing the text of that block without the
            // delimiting { and } characters.
            if (rawValue is ScriptBlock)
            {
                var scriptBlock = (ScriptBlock)rawValue;
                var ast         = (ScriptBlockAst)scriptBlock.Ast;
                // TODO: I would have thought ast.EndBlock.Extent.Text would suffice here, but this corresponds to only the first token in the script block
            }

            // For other reference type values, if the reference type supports such a conversion, that conversion is
            // used; otherwise, the conversion is in error.
            // Windows PowerShell: The string used to represent the value of an element that is an array has the
            // form System.type[], System.type[,], and so on.
            // Windows PowerShell: For other reference types, the method ToString is called.
            return(Convert.ToString(rawValue, formatProvider));
        }