private object MapDouble(string value, Type valType, MappingStack mappingStack,
                          MappingAction mappingAction, out Type mappedType)
 {
     CheckExpectedType(valType, typeof(double), mappingStack);
     mappedType = typeof(double);
     return(OnStack("double", mappingStack, delegate()
     {
         try
         {
             double ret = Double.Parse(value, CultureInfo.InvariantCulture.NumberFormat);
             return ret;
         }
         catch (Exception)
         {
             throw new XmlRpcInvalidXmlRpcException(mappingStack.MappingType
                                                    + " contains invalid double value " + StackDump(mappingStack));
         }
     }));
 }
 private object MapNilValue(string p, Type type, MappingStack mappingStack,
                            MappingAction mappingAction, out Type mappedType)
 {
     if (type == null ||
         (type.GetTypeInfo().IsGenericType&& type.GetGenericTypeDefinition() == typeof(Nullable <>)) ||
         (!type.GetTypeInfo().IsPrimitive || !type.GetTypeInfo().IsValueType) ||
         type == typeof(object))
     {
         mappedType = type;
         return(null);
     }
     else
     {
         throw new XmlRpcInvalidXmlRpcException(mappingStack.MappingType
                                                + " contains <nil> value which cannot be mapped to type "
                                                + (type != null && type != typeof(object) ? type.Name : "object")
                                                + " "
                                                + StackDump(mappingStack));
     }
 }
 private object MapInt(string value, Type valType, MappingStack mappingStack,
                       MappingAction mappingAction, out Type mappedType)
 {
     CheckExpectedType(valType, typeof(int), mappingStack);
     if (valType != null && valType.GetTypeInfo().IsEnum)
     {
         return(MapNumberToEnum(value, valType, "int", mappingStack, mappingAction, out mappedType));
     }
     mappedType = typeof(int);
     return(OnStack("integer", mappingStack, delegate()
     {
         int ret;
         if (!Int32.TryParse(value, out ret))
         {
             throw new XmlRpcInvalidXmlRpcException(mappingStack.MappingType
                                                    + " contains invalid int value " + StackDump(mappingStack));
         }
         return ret;
     }));
 }
 private void CheckExpectedType(Type expectedType, Type actualType, MappingStack mappingStack)
 {
     if (expectedType != null && expectedType.GetTypeInfo().IsEnum)
     {
         Type[] i4Types = new Type[] { typeof(byte), typeof(sbyte), typeof(short),
                                       typeof(ushort), typeof(int) };
         Type[] i8Types        = new Type[] { typeof(uint), typeof(long) };
         Type   underlyingType = Enum.GetUnderlyingType(expectedType);
         if (Array.IndexOf(i4Types, underlyingType) >= 0)
         {
             expectedType = typeof(Int32);
         }
         else if (Array.IndexOf(i8Types, underlyingType) >= 0)
         {
             expectedType = typeof(long);
         }
         else
         {
             throw new XmlRpcInvalidEnumValue(mappingStack.MappingType +
                                              " contains "
                                              + XmlRpcTypeInfo.GetXmlRpcTypeString(actualType)
                                              + " which cannot be mapped to  "
                                              + XmlRpcTypeInfo.GetXmlRpcTypeString(expectedType)
                                              + " " + StackDump(mappingStack));
         }
     }
     // TODO: throw exception for invalid enum type
     if (expectedType != null && expectedType != typeof(Object) &&
         expectedType != actualType &&
         (actualType.GetTypeInfo().IsValueType &&
          expectedType != typeof(Nullable <>).MakeGenericType(actualType)))
     {
         throw new XmlRpcTypeMismatchException(mappingStack.MappingType +
                                               " contains "
                                               + XmlRpcTypeInfo.GetXmlRpcTypeString(actualType)
                                               + " value where "
                                               + XmlRpcTypeInfo.GetXmlRpcTypeString(expectedType)
                                               + " expected " + StackDump(mappingStack));
     }
 }
        protected object MapHashtable(IEnumerator <Node> iter, Type valType, MappingStack mappingStack,
                                      MappingAction mappingAction, out Type mappedType)
        {
            mappedType = null;
            XmlRpcStruct retObj = new XmlRpcStruct();

            mappingStack.Push("struct mapped to XmlRpcStruct");
            try
            {
                while (iter.MoveNext() && iter.Current is StructMember)
                {
                    string rpcName = (iter.Current as StructMember).Value;
                    if (retObj.ContainsKey(rpcName) &&
                        !IgnoreDuplicateMembers)
                    {
                        throw new XmlRpcInvalidXmlRpcException(mappingStack.MappingType
                                                               + " contains struct value with duplicate member "
                                                               + rpcName
                                                               + " " + StackDump(mappingStack));
                    }
                    iter.MoveNext();

                    object value = OnStack(String.Format("member {0}", rpcName),
                                           mappingStack, delegate()
                    {
                        return(MapValueNode(iter, null, mappingStack, mappingAction));
                    });
                    if (!retObj.ContainsKey(rpcName))
                    {
                        retObj[rpcName] = value;
                    }
                }
            }
            finally
            {
                mappingStack.Pop();
            }
            return(retObj);
        }
 private object MapStringToEnum(string value, Type enumType, string xmlRpcType,
                                MappingStack mappingStack, MappingAction mappingAction, out Type mappedType)
 {
     mappedType = enumType;
     return(OnStack(xmlRpcType, mappingStack, delegate()
     {
         try
         {
             object ret = Enum.Parse(enumType, value, true);
             return ret;
         }
         catch (XmlRpcInvalidEnumValue)
         {
             throw;
         }
         catch (Exception ex)
         {
             throw new XmlRpcInvalidEnumValue(mappingStack.MappingType
                                              + " contains invalid or out of range " + xmlRpcType + " value mapped to enum "
                                              + StackDump(mappingStack));
         }
     }));
 }
 private object MapBoolean(string value, Type valType, MappingStack mappingStack,
                           MappingAction mappingAction, out Type mappedType)
 {
     CheckExpectedType(valType, typeof(bool), mappingStack);
     mappedType = typeof(bool);
     return(OnStack("boolean", mappingStack, delegate()
     {
         if (value == "1")
         {
             return true;
         }
         else if (value == "0")
         {
             return false;
         }
         else
         {
             throw new XmlRpcInvalidXmlRpcException(mappingStack.MappingType
                                                    + " contains invalid boolean value "
                                                    + StackDump(mappingStack));
         }
     }));
 }
        XmlRpcFaultException ParseFault(
            IEnumerator <Node> iter,
            MappingStack parseStack,
            MappingAction mappingAction)
        {
            iter.MoveNext(); // move to StructValue
            Type parsedType;
            var  faultStruct = MapHashtable(iter, null, parseStack, mappingAction,
                                            out parsedType) as XmlRpcStruct;
            object faultCode   = faultStruct["faultCode"];
            object faultString = faultStruct["faultString"];

            if (faultCode is string)
            {
                int value;
                if (!Int32.TryParse(faultCode as string, out value))
                {
                    throw new XmlRpcInvalidXmlRpcException("faultCode not int or string");
                }
                faultCode = value;
            }
            return(new XmlRpcFaultException((int)faultCode, (string)faultString));
        }
        void MapMultiDimElements(IEnumerator <Node> iter, int Rank, int CurRank,
                                 Type elemType, List <object> elements, int[] dimLengths,
                                 MappingStack mappingStack, MappingAction mappingAction)
        {
            //XmlNode dataNode = SelectSingleNode(node, "data");
            //XmlNode[] childNodes = SelectNodes(dataNode, "value");
            //int nodeCount = childNodes.Length;
            ////!! check that multi dim array is not jagged
            //if (dimLengths[CurRank] != 0 && nodeCount != dimLengths[CurRank])
            //{
            //  throw new XmlRpcNonRegularArrayException(
            //    "Multi-dimensional array must not be jagged.");
            //}
            //dimLengths[CurRank] = nodeCount;  // in case first array at this rank
            int nodeCount = 0;

            if (CurRank < (Rank - 1))
            {
                while (iter.MoveNext() && iter.Current is ArrayValue)
                {
                    nodeCount++;
                    MapMultiDimElements(iter, Rank, CurRank + 1, elemType,
                                        elements, dimLengths, mappingStack, mappingAction);
                }
            }
            else
            {
                while (iter.MoveNext() && iter.Current is ValueNode)
                {
                    nodeCount++;
                    object value = MapValueNode(iter, elemType, mappingStack, mappingAction);
                    elements.Add(value);
                }
            }
            dimLengths[CurRank] = nodeCount;
        }
        public Object MapValueNode(
            IEnumerator <Node> iter,
            Type valType,
            MappingStack mappingStack,
            MappingAction mappingAction)
        {
            var valueNode = iter.Current as ValueNode;

            // if suppplied type is System.Object then ignore it because
            // if doesn't provide any useful information (parsing methods
            // expect null in this case)
            if (valType != null && valType.GetTypeInfo().BaseType == null)
            {
                valType = null;
            }
            object ret = "";

            if (valueNode is StringValue && valueNode.ImplicitValue)
            {
                CheckImplictString(valType, mappingStack);
            }

            Type mappedType;

            object retObj = null;

            if (iter.Current is ArrayValue)
            {
                retObj = MapArray(iter, valType, mappingStack, mappingAction,
                                  out mappedType);
            }
            else if (iter.Current is StructValue)
            {
                // if we don't know the expected struct type then we must
                // map the XML-RPC struct as an instance of XmlRpcStruct
                if (valType != null && valType != typeof(XmlRpcStruct) &&
                    !valType.GetTypeInfo().IsSubclassOf(typeof(XmlRpcStruct)))
                {
                    retObj = MapStruct(iter, valType, mappingStack, mappingAction,
                                       out mappedType);
                }
                else
                {
                    if (valType == null || valType == typeof(object))
                    {
                        valType = typeof(XmlRpcStruct);
                    }
                    // TODO: do we need to validate type here?
                    retObj = MapHashtable(iter, valType, mappingStack, mappingAction,
                                          out mappedType);
                }
            }
            else if (iter.Current is Base64Value)
            {
                retObj = MapBase64(valueNode.Value, valType, mappingStack, mappingAction,
                                   out mappedType);
            }
            else if (iter.Current is IntValue)
            {
                retObj = MapInt(valueNode.Value, valType, mappingStack, mappingAction,
                                out mappedType);
            }
            else if (iter.Current is LongValue)
            {
                retObj = MapLong(valueNode.Value, valType, mappingStack, mappingAction,
                                 out mappedType);
            }
            else if (iter.Current is StringValue)
            {
                retObj = MapString(valueNode.Value, valType, mappingStack, mappingAction,
                                   out mappedType);
            }
            else if (iter.Current is BooleanValue)
            {
                retObj = MapBoolean(valueNode.Value, valType, mappingStack, mappingAction,
                                    out mappedType);
            }
            else if (iter.Current is DoubleValue)
            {
                retObj = MapDouble(valueNode.Value, valType, mappingStack, mappingAction,
                                   out mappedType);
            }
            else if (iter.Current is DateTimeValue)
            {
                retObj = MapDateTime(valueNode.Value, valType, mappingStack, mappingAction,
                                     out mappedType);
            }
            else if (iter.Current is NilValue)
            {
                retObj = MapNilValue(valueNode.Value, valType, mappingStack, mappingAction,
                                     out mappedType);
            }

            return(retObj);
        }
        private object MapArray(IEnumerator <Node> iter, Type valType,
                                MappingStack mappingStack, MappingAction mappingAction,
                                out Type mappedType)
        {
            mappedType = null;
            // required type must be an array
            if (valType != null &&
                !(valType.IsArray == true ||
                  valType == typeof(Array) ||
                  valType == typeof(object)))
            {
                throw new XmlRpcTypeMismatchException(mappingStack.MappingType
                                                      + " contains array value where "
                                                      + XmlRpcTypeInfo.GetXmlRpcTypeString(valType)
                                                      + " expected " + StackDump(mappingStack));
            }
            if (valType != null)
            {
                XmlRpcType xmlRpcType = XmlRpcTypeInfo.GetXmlRpcType(valType);
                if (xmlRpcType == XmlRpcType.tMultiDimArray)
                {
                    mappingStack.Push("array mapped to type " + valType.Name);
                    Object ret = MapMultiDimArray(iter, valType, mappingStack,
                                                  mappingAction);
                    return(ret);
                }
                mappingStack.Push("array mapped to type " + valType.Name);
            }
            else
            {
                mappingStack.Push("array");
            }

            var  values   = new List <object>();
            Type elemType = DetermineArrayItemType(valType);

            bool bGotType = false;
            Type useType  = null;

            while (iter.MoveNext() && iter.Current is ValueNode)
            {
                mappingStack.Push(String.Format("element {0}", values.Count));
                object value = MapValueNode(iter, elemType, mappingStack, mappingAction);
                values.Add(value);
                mappingStack.Pop();
            }

            foreach (object value in values)
            {
                if (value == null)
                {
                    continue;
                }
                if (bGotType == false)
                {
                    useType  = value.GetType();
                    bGotType = true;
                }
                else
                {
                    if (useType != value.GetType())
                    {
                        useType = null;
                    }
                }
            }

            Object[] args = new Object[1];
            args[0] = values.Count;
            Object retObj = null;

            if (valType != null &&
                valType != typeof(Array) &&
                valType != typeof(object))
            {
                retObj = CreateArrayInstance(valType, args);
            }
            else
            {
                if (useType == null)
                {
                    retObj = CreateArrayInstance(typeof(object[]), args);
                }
                else
                {
                    retObj = Array.CreateInstance(useType, (int)args[0]);
                };
            }
            for (int j = 0; j < values.Count; j++)
            {
                ((Array)retObj).SetValue(values[j], j);
            }

            mappingStack.Pop();

            return(retObj);
        }
        private object MapStruct(IEnumerator <Node> iter, Type valueType, MappingStack mappingStack,
                                 MappingAction mappingAction, out Type mappedType)
        {
            mappedType = null;

            if (valueType.GetTypeInfo().IsPrimitive)
            {
                throw new XmlRpcTypeMismatchException(mappingStack.MappingType
                                                      + " contains struct value where "
                                                      + XmlRpcTypeInfo.GetXmlRpcTypeString(valueType)
                                                      + " expected " + StackDump(mappingStack));
            }
            if (valueType.GetTypeInfo().IsGenericType &&
                valueType.GetGenericTypeDefinition() == typeof(Nullable <>))
            {
                valueType = valueType.GetGenericArguments()[0];
            }
            object retObj;

            try
            {
                retObj = Activator.CreateInstance(valueType);
            }
            catch (Exception)
            {
                throw new XmlRpcTypeMismatchException(mappingStack.MappingType
                                                      + " contains struct value where "
                                                      + XmlRpcTypeInfo.GetXmlRpcTypeString(valueType)
                                                      + " expected (as type " + valueType.Name + ") "
                                                      + StackDump(mappingStack));
            }
            // Note: mapping action on a struct is only applied locally - it
            // does not override the global mapping action when members of the
            // struct are mapped
            MappingAction localAction = mappingAction;

            if (valueType != null)
            {
                mappingStack.Push("struct mapped to type " + valueType.Name);
                localAction = StructMappingAction(valueType, mappingAction);
            }
            else
            {
                mappingStack.Push("struct");
            }
            // create map of field names and remove each name from it as
            // processed so we can determine which fields are missing
            var names = new List <string>();

            CreateFieldNamesMap(valueType, names);
            int           fieldCount = 0;
            List <string> rpcNames   = new List <string>();

            try
            {
                while (iter.MoveNext())
                {
                    if (!(iter.Current is StructMember))
                    {
                        break;
                    }
                    string rpcName = (iter.Current as StructMember).Value;
                    if (rpcNames.Contains(rpcName))
                    {
                        if (!IgnoreDuplicateMembers)
                        {
                            throw new XmlRpcInvalidXmlRpcException(mappingStack.MappingType
                                                                   + " contains struct value with duplicate member "
                                                                   + rpcName
                                                                   + " " + StackDump(mappingStack));
                        }
                        else
                        {
                            continue;
                        }
                    }
                    else
                    {
                        rpcNames.Add(rpcName);
                    }

                    string     name = GetStructName(valueType, rpcName) ?? rpcName;
                    MemberInfo mi   = valueType.GetField(name);
                    if (mi == null)
                    {
                        mi = valueType.GetProperty(name);
                    }
                    if (mi == null)
                    {
                        iter.MoveNext();                          // move to value
                        if (iter.Current is ComplexValueNode)
                        {
                            int depth = iter.Current.Depth;
                            while (!(iter.Current is EndComplexValueNode && iter.Current.Depth == depth))
                            {
                                iter.MoveNext();
                            }
                        }
                        continue;
                    }
                    if (names.Contains(name))
                    {
                        names.Remove(name);
                    }
                    else
                    {
                        //if (Attribute.IsDefined(mi, typeof(NonSerializedAttribute)))
                        //{
                        //  mappingStack.Push(String.Format("member {0}", name));
                        //  throw new XmlRpcNonSerializedMember("Cannot map XML-RPC struct "
                        //  + "member onto member marked as [NonSerialized]: "
                        //  + " " + StackDump(mappingStack));
                        //}
                    }
                    Type memberType = mi is FieldInfo
                                        ? (mi as FieldInfo).FieldType : (mi as PropertyInfo).PropertyType;
                    string mappingMsg = valueType == null
                                                ? String.Format("member {0}", name)
                                                : String.Format("member {0} mapped to type {1}", name, memberType.Name);

                    iter.MoveNext();
                    object valObj = OnStack(mappingMsg, mappingStack, delegate()
                    {
                        return(MapValueNode(iter, memberType, mappingStack, mappingAction));
                    });

                    if (mi is FieldInfo)
                    {
                        (mi as FieldInfo).SetValue(retObj, valObj);
                    }
                    else
                    {
                        (mi as PropertyInfo).SetValue(retObj, valObj, null);
                    }
                    fieldCount++;
                }

                if (localAction == MappingAction.Error && names.Count > 0)
                {
                    ReportMissingMembers(valueType, names, mappingStack);
                }
                return(retObj);
            }
            finally
            {
                mappingStack.Pop();
            }
        }