示例#1
0
        private object DecodeMapToType(Type expectedType, long offset, int size, out long outOffset,
                                       InjectableValues injectables)
        {
            var constructor = _typeAcivatorCreator.GetActivator(expectedType);
            var parameters  = constructor.DefaultParameters();

            for (var i = 0; i < size; i++)
            {
                var key = DecodeKey(offset, out offset);
                if (constructor.DeserializationParameters.ContainsKey(key))
                {
                    var param     = constructor.DeserializationParameters[key];
                    var paramType = param.ParameterType;
                    var value     = Decode(paramType, offset, out offset, injectables);
                    parameters[param.Position] = value;
                }
                else
                {
                    offset = NextValueOffset(offset, 1);
                }
            }

            SetInjectables(constructor, parameters, injectables);
            SetAlwaysCreatedParams(constructor, parameters, injectables);

            outOffset = offset;
            return(constructor.Activator(parameters));
        }
        private object Decode(Type expectedType, long offset, out long outOffset, InjectableValues injectables = null)
        {
            int size;
            var type = CtrlData(offset, out size, out offset);

            return(DecodeByType(expectedType, type, offset, size, out outOffset, injectables));
        }
示例#3
0
        /// <summary>
        ///     Decodes the type of the by.
        /// </summary>
        /// <param name="expectedType"></param>
        /// <param name="type">The type.</param>
        /// <param name="offset">The offset.</param>
        /// <param name="size">The size.</param>
        /// <param name="outOffset">The out offset</param>
        /// <param name="injectables"></param>
        /// <returns></returns>
        /// <exception cref="Exception">Unable to handle type!</exception>
        private object DecodeByType(Type expectedType, ObjectType type, long offset, int size, out long outOffset,
                                    InjectableValues injectables)
        {
            outOffset = offset + size;

            switch (type)
            {
            case ObjectType.Pointer:
                var pointer = DecodePointer(offset, size, out offset);
                outOffset = offset;
                if (!_followPointers)
                {
                    return(pointer);
                }
                long ignore;
                var  result = Decode(expectedType, Convert.ToInt32(pointer), out ignore, injectables);
                return(result);

            case ObjectType.Map:
                return(DecodeMap(expectedType, offset, size, out outOffset, injectables));

            case ObjectType.Array:
                return(DecodeArray(expectedType, size, offset, out outOffset, injectables));

            case ObjectType.Boolean:
                outOffset = offset;
                return(DecodeBoolean(expectedType, size));

            case ObjectType.Utf8String:
                return(DecodeString(expectedType, offset, size));

            case ObjectType.Double:
                return(DecodeDouble(expectedType, offset, size));

            case ObjectType.Float:
                return(DecodeFloat(expectedType, offset, size));

            case ObjectType.Bytes:
                return(DecodeBytes(expectedType, offset, size));

            case ObjectType.Uint16:
                return(DecodeInteger(expectedType, offset, size));

            case ObjectType.Uint32:
                return(DecodeLong(expectedType, offset, size));

            case ObjectType.Int32:
                return(DecodeInteger(expectedType, offset, size));

            case ObjectType.Uint64:
                return(DecodeUInt64(expectedType, offset, size));

            case ObjectType.Uint128:
                return(DecodeBigInteger(expectedType, offset, size));

            default:
                throw new InvalidDatabaseException("Unable to handle type:" + type);
            }
        }
        private T ResolveDataPointer <T>(int pointer, InjectableValues injectables) where T : class
        {
            var resolved = (pointer - Metadata.NodeCount) + Metadata.SearchTreeSize;

            if (resolved >= _database.Length)
            {
                throw new InvalidDatabaseException(
                          "The MaxMind Db file's search tree is corrupt: "
                          + "contains pointer larger than the database.");
            }

            return(Decoder.Decode <T>(resolved, out long ignore, injectables));
        }
示例#5
0
        /// <summary>
        ///     Decodes the array.
        /// </summary>
        /// <param name="expectedType"></param>
        /// <param name="size">The size.</param>
        /// <param name="offset">The offset.</param>
        /// <param name="outOffset">The out offset.</param>
        /// <param name="injectables"></param>
        /// <returns></returns>
        private object DecodeArray(Type expectedType, int size, long offset, out long outOffset,
                                   InjectableValues injectables)
        {
            var genericArgs   = expectedType.GetGenericArguments();
            var argType       = genericArgs.Length == 0 ? typeof(object) : genericArgs[0];
            var interfaceType = typeof(ICollection <>).MakeGenericType(argType);

            var array = _listActivatorCreator.GetActivator(expectedType)(size);

            for (var i = 0; i < size; i++)
            {
                var r = Decode(argType, offset, out offset, injectables);
                interfaceType.GetMethod("Add").Invoke(array, new[] { r });
            }

            outOffset = offset;
            return(array);
        }
示例#6
0
        /// <summary>
        ///     Decodes the map.
        /// </summary>
        /// <param name="expectedType"></param>
        /// <param name="offset">The offset.</param>
        /// <param name="size">The size.</param>
        /// <param name="outOffset">The out offset.</param>
        /// <param name="injectables"></param>
        /// <returns></returns>
        private object DecodeMap(Type expectedType, long offset, int size, out long outOffset,
                                 InjectableValues injectables)
        {
            var objDictType = typeof(Dictionary <string, object>);

            if (!expectedType.GetTypeInfo().IsGenericType&& expectedType.IsAssignableFrom(objDictType))
            {
                expectedType = objDictType;
            }

            // Currently we don't support non-dict generic types
            if (expectedType.GetTypeInfo().IsGenericType)
            {
                return(DecodeMapToDictionary(expectedType, offset, size, out outOffset, injectables));
            }

            return(DecodeMapToType(expectedType, offset, size, out outOffset, injectables));
        }
示例#7
0
        private object DecodeMapToDictionary(Type expectedType, long offset, int size, out long outOffset,
                                             InjectableValues injectables)
        {
            var genericArgs = expectedType.GetGenericArguments();

            if (genericArgs.Length != 2)
            {
                throw new DeserializationException(
                          $"Unexpected number of Dictionary generic arguments: {genericArgs.Length}");
            }

            var obj = (IDictionary)_dictionaryActivatorCreator.GetActivator(expectedType)(size);

            for (var i = 0; i < size; i++)
            {
                var key   = Decode(genericArgs[0], offset, out offset);
                var value = Decode(genericArgs[1], offset, out offset, injectables);
                obj.Add(key, value);
            }

            outOffset = offset;

            return(obj);
        }
示例#8
0
 /// <summary>
 ///     Decodes the object at the specified offset.
 /// </summary>
 /// <param name="offset">The offset.</param>
 /// <param name="outOffset">The out offset</param>
 /// <param name="injectables"></param>
 /// <returns>An object containing the data read from the stream</returns>
 internal T Decode <T>(long offset, out long outOffset, InjectableValues injectables = null) where T : class
 {
     return(Decode(typeof(T), offset, out outOffset, injectables) as T);
 }
示例#9
0
        private static void SetInjectables(TypeActivator constructor, object[] parameters, InjectableValues injectables)
        {
            foreach (var item in constructor.InjectableParameters)
            {
                if (injectables == null || !injectables.Values.ContainsKey(item.Key))
                {
                    throw new DeserializationException($"No injectable value found for {item.Key}");
                }

                parameters[item.Value.Position] = injectables.Values[item.Key];
            }
        }
示例#10
0
 private void SetAlwaysCreatedParams(TypeActivator constructor, object[] parameters, InjectableValues injectables)
 {
     foreach (var param in constructor.AlwaysCreatedParameters)
     {
         if (parameters[param.Position] == null)
         {
             var activator   = _typeAcivatorCreator.GetActivator(param.ParameterType);
             var cstorParams = activator.DefaultParameters();
             SetInjectables(activator, cstorParams, injectables);
             SetAlwaysCreatedParams(activator, cstorParams, injectables);
             parameters[param.Position] = activator.Activator(cstorParams);
         }
     }
 }
示例#11
0
        /// <summary>
        ///     Finds the data related to the specified address.
        /// </summary>
        /// <param name="ipAddress">The IP address.</param>
        /// <param name="prefixLength">The network prefix length for the network record in the database containing the IP address looked up.</param>
        /// <param name="injectables">Value to inject during deserialization</param>
        /// <returns>An object containing the IP related data</returns>
        public T Find <T>(IPAddress ipAddress, out int prefixLength, InjectableValues injectables = null) where T : class
        {
            var pointer = FindAddressInTree(ipAddress, out prefixLength);

            return(pointer == 0 ? null : ResolveDataPointer <T>(pointer, injectables));
        }
示例#12
0
        /// <summary>
        /// Get an enumerator that iterates all data nodes in the database. Do not modify the object as it may be cached.
        /// </summary>
        /// <param name="injectables">Value to inject during deserialization</param>
        /// <param name="cacheSize">The size of the data cache. This can greatly speed enumeration at the cost of memory usage.</param>
        /// <returns>Enumerator for all data nodes</returns>
        public IEnumerable <Reader.ReaderIteratorNode <T> > FindAll <T>(InjectableValues injectables = null, int cacheSize = 16384) where T : class
        {
            int            byteCount = (Metadata.IPVersion == 6 ? 16 : 4);
            int            prefixMax = byteCount * 8;
            List <NetNode> nodes     = new List <NetNode>();
            NetNode        root      = new NetNode {
                IPBytes = new byte[byteCount]
            };

            nodes.Add(root);
            CachedDictionary <int, T> dataCache = new CachedDictionary <int, T>(cacheSize, null);

            while (nodes.Count > 0)
            {
                NetNode node = nodes[nodes.Count - 1];
                nodes.RemoveAt(nodes.Count - 1);
                while (true)
                {
                    if (node.Pointer < Metadata.NodeCount)
                    {
                        byte[] ipRight = new byte[byteCount];
                        Array.Copy(node.IPBytes, ipRight, ipRight.Length);
                        if (ipRight.Length <= (node.Bit >> 3))
                        {
                            throw new InvalidDataException("Invalid search tree, bad bit " + node.Bit);
                        }
                        ipRight[node.Bit >> 3] |= (byte)(1 << (7 - (node.Bit % 8)));
                        int rightPointer = ReadNode(node.Pointer, 1);
                        node.Bit++;
                        nodes.Add(new NetNode {
                            Pointer = rightPointer, IPBytes = ipRight, Bit = node.Bit
                        });
                        node.Pointer = ReadNode(node.Pointer, 0);
                    }
                    else
                    {
                        if (node.Pointer > Metadata.NodeCount)
                        {
                            // data node, we are done with this branch
                            if (!dataCache.TryGetValue(node.Pointer, out T data))
                            {
                                data = ResolveDataPointer <T>(node.Pointer, injectables);
                                dataCache.Add(node.Pointer, data);
                            }
                            bool isIPV4 = true;
                            for (int i = 0; i < node.IPBytes.Length - 4; i++)
                            {
                                if (node.IPBytes[i] != 0)
                                {
                                    isIPV4 = false;
                                    break;
                                }
                            }
                            if (!isIPV4 || node.IPBytes.Length == 4)
                            {
                                yield return(new ReaderIteratorNode <T>(new IPAddress(node.IPBytes), node.Bit, data));
                            }
                            else
                            {
                                yield return(new ReaderIteratorNode <T>(new IPAddress(node.IPBytes.Skip(12).Take(4).ToArray()), node.Bit - 96, data));
                            }
                        }
                        // else node is an empty node (terminator node), we are done with this branch
                        break;
                    }
                }
            }
        }
示例#13
0
 /// <summary>
 ///     Finds the data related to the specified address.
 /// </summary>
 /// <param name="ipAddress">The IP address.</param>
 /// <param name="injectables">Value to inject during deserialization</param>
 /// <returns>An object containing the IP related data</returns>
 public T Find <T>(IPAddress ipAddress, InjectableValues injectables = null) where T : class
 {
     return(Find <T>(ipAddress, out _, injectables));
 }
示例#14
0
        /// <summary>
        ///     Finds the data related to the specified address.
        /// </summary>
        /// <param name="ipAddress">The IP address.</param>
        /// <param name="injectables">Value to inject during deserialization</param>
        /// <returns>An object containing the IP related data</returns>
        public T Find <T>(IPAddress ipAddress, InjectableValues injectables = null) where T : class
        {
            int prefixLength;

            return(Find <T>(ipAddress, out prefixLength, injectables));
        }