Exemplo n.º 1
0
 void IterateHandler(AbstractBufferedReader reader, IFieldHandler handler, bool skipping, HashSet <int> knownInlineRefs)
 {
     if (handler is ODBDictionaryFieldHandler)
     {
         var dictId = reader.ReadVUInt64();
         if (!skipping)
         {
             var kvHandlers = ((IFieldHandlerWithNestedFieldHandlers)handler).EnumerateNestedFieldHandlers().ToArray();
             IterateDict(dictId, kvHandlers[0], kvHandlers[1]);
         }
     }
     else if (handler is DBObjectFieldHandler)
     {
         var oid = reader.ReadVInt64();
         if (oid == 0)
         {
             if (!skipping)
             {
                 _visitor?.OidReference(0);
             }
         }
         else if (oid <= int.MinValue || oid > 0)
         {
             if (!skipping)
             {
                 _visitor?.OidReference((ulong)oid);
                 IterateOid((ulong)oid);
             }
         }
         else
         {
             if (knownInlineRefs != null)
             {
                 if (knownInlineRefs.Contains((int)oid))
                 {
                     if (!skipping)
                     {
                         _visitor?.InlineBackRef((int)oid);
                     }
                     return;
                 }
                 if (!skipping)
                 {
                     _visitor?.InlineRef((int)oid);
                 }
                 knownInlineRefs.Add((int)oid);
             }
             var tableId = reader.ReadVUInt32();
             var version = reader.ReadVUInt32();
             if (!skipping)
             {
                 MarkTableIdVersionFieldInfo(tableId, version);
             }
             string tableName;
             var    skip = skipping ||
                           _visitor != null && !_visitor.StartInlineObject(tableId,
                                                                           _tableId2Name.TryGetValue(tableId, out tableName) ? tableName : null, version);
             var tvi = GetTableVersionInfo(tableId, version);
             for (var i = 0; i < tvi.FieldCount; i++)
             {
                 var fi        = tvi[i];
                 var skipField = skip || _visitor != null && !_visitor.StartField(fi.Name);
                 IterateHandler(reader, fi.Handler, skipField, new HashSet <int>());
                 if (!skipField)
                 {
                     _visitor?.EndField();
                 }
             }
             if (!skip)
             {
                 _visitor?.EndInlineObject();
             }
         }
     }
     else if (handler is ListFieldHandler)
     {
         var oid = reader.ReadVInt64();
         if (oid == 0)
         {
             if (!skipping)
             {
                 _visitor?.OidReference(0);
             }
         }
         else if (oid <= int.MinValue || oid > 0)
         {
             if (!skipping)
             {
                 _visitor?.OidReference((ulong)oid);
                 IterateOid((ulong)oid);
             }
         }
         else
         {
             var itemHandler = ((IFieldHandlerWithNestedFieldHandlers)handler).EnumerateNestedFieldHandlers().First();
             IterateInlineList(reader, itemHandler, skipping);
         }
     }
     else if (handler is DictionaryFieldHandler)
     {
         var oid = reader.ReadVInt64();
         if (oid == 0)
         {
             if (!skipping)
             {
                 _visitor?.OidReference(0);
             }
         }
         else if (oid <= int.MinValue || oid > 0)
         {
             if (!skipping)
             {
                 _visitor?.OidReference((ulong)oid);
                 IterateOid((ulong)oid);
             }
         }
         else
         {
             var kvHandlers = ((IFieldHandlerWithNestedFieldHandlers)handler).EnumerateNestedFieldHandlers().ToArray();
             IterateInlineDict(reader, kvHandlers[0], kvHandlers[1], skipping);
         }
     }
     else if (handler is NullableFieldHandler)
     {
         var hasValue = reader.ReadBool();
         if (hasValue)
         {
             var itemHandler = ((IFieldHandlerWithNestedFieldHandlers)handler).EnumerateNestedFieldHandlers().First();
             IterateHandler(reader, itemHandler, skipping, null);
         }
     }
     else if (handler.NeedsCtx() || handler.HandledType() == null)
     {
         throw new BTDBException("Don't know how to iterate " + handler.Name);
     }
     else
     {
         if (skipping || _visitor == null)
         {
             Action <AbstractBufferedReader> skipper;
             if (!_skippers.TryGetValue(handler, out skipper))
             {
                 var meth =
                     ILBuilder.Instance.NewMethod <Action <AbstractBufferedReader> >("Skip" + handler.Name);
                 var il = meth.Generator;
                 handler.Skip(il, il2 => il2.Ldarg(0));
                 il.Ret();
                 skipper = meth.Create();
                 _skippers.Add(handler, skipper);
             }
             skipper(reader);
         }
         else
         {
             Func <AbstractBufferedReader, object> loader;
             if (!_loaders.TryGetValue(handler, out loader))
             {
                 var meth =
                     ILBuilder.Instance.NewMethod <Func <AbstractBufferedReader, object> >("Load" + handler.Name);
                 var il = meth.Generator;
                 handler.Load(il, il2 => il2.Ldarg(0));
                 il.Box(handler.HandledType()).Ret();
                 loader = meth.Create();
                 _loaders.Add(handler, loader);
             }
             var obj = loader(reader);
             if (_visitor.NeedScalarAsObject())
             {
                 _visitor.ScalarAsObject(obj);
             }
             if (_visitor.NeedScalarAsText())
             {
                 _visitor.ScalarAsText(obj == null
                     ? "null"
                     : string.Format(CultureInfo.InvariantCulture, "{0}", obj));
             }
         }
     }
 }
Exemplo n.º 2
0
        void IterateHandler(ref SpanReader reader, IFieldHandler handler, bool skipping, HashSet <int>?knownInlineRefs)
        {
            if (handler is ODBDictionaryFieldHandler)
            {
                var dictId = reader.ReadVUInt64();
                if (!skipping)
                {
                    var kvHandlers = ((IFieldHandlerWithNestedFieldHandlers)handler).EnumerateNestedFieldHandlers().ToArray();
                    IterateDict(dictId, kvHandlers[0], kvHandlers[1]);
                }
            }
            else if (handler is ODBSetFieldHandler)
            {
                var dictId = reader.ReadVUInt64();
                if (!skipping)
                {
                    var keyHandler = ((IFieldHandlerWithNestedFieldHandlers)handler).EnumerateNestedFieldHandlers().First();
                    IterateSet(dictId, keyHandler);
                }
            }
            else if (handler is DBObjectFieldHandler)
            {
                var oid = reader.ReadVInt64();
                if (oid == 0)
                {
                    if (!skipping)
                    {
                        _visitor?.OidReference(0);
                    }
                }
                else if (oid <= int.MinValue || oid > 0)
                {
                    if (!skipping)
                    {
                        _visitor?.OidReference((ulong)oid);
                        IterateOid((ulong)oid);
                    }
                }
                else
                {
                    if (knownInlineRefs != null)
                    {
                        if (knownInlineRefs.Contains((int)oid))
                        {
                            if (!skipping)
                            {
                                _visitor?.InlineBackRef((int)oid);
                            }
                            return;
                        }
                        if (!skipping)
                        {
                            _visitor?.InlineRef((int)oid);
                        }
                        knownInlineRefs.Add((int)oid);
                    }
                    var tableId = reader.ReadVUInt32();
                    var version = reader.ReadVUInt32();
                    if (!skipping)
                    {
                        MarkTableIdVersionFieldInfo(tableId, version);
                    }
                    var skip = skipping ||
                               _visitor != null && !_visitor.StartInlineObject(tableId,
                                                                               _tableId2Name.TryGetValue(tableId, out var tableName) ? tableName : null, version);
                    var tvi = GetTableVersionInfo(tableId, version);
                    var knownInlineRefsNested = new HashSet <int>();
                    for (var i = 0; i < tvi.FieldCount; i++)
                    {
                        var fi        = tvi[i];
                        var skipField = skip || _visitor != null && !_visitor.StartField(fi.Name);
                        IterateHandler(ref reader, fi.Handler !, skipField, knownInlineRefsNested);
                        if (!skipField)
                        {
                            _visitor?.EndField();
                        }
                    }
                    if (!skip)
                    {
                        _visitor?.EndInlineObject();
                    }
                }
            }
            else if (handler is ListFieldHandler)
            {
                var oid = reader.ReadVInt64();
                if (oid == 0)
                {
                    if (!skipping)
                    {
                        _visitor?.OidReference(0);
                    }
                }
                else if (oid <= int.MinValue || oid > 0)
                {
                    if (!skipping)
                    {
                        _visitor?.OidReference((ulong)oid);
                        IterateOid((ulong)oid);
                    }
                }
                else
                {
                    var itemHandler = ((IFieldHandlerWithNestedFieldHandlers)handler).EnumerateNestedFieldHandlers().First();
                    IterateInlineList(ref reader, itemHandler, skipping, knownInlineRefs);
                }
            }
            else if (handler is DictionaryFieldHandler)
            {
                var oid = reader.ReadVInt64();
                if (oid == 0)
                {
                    if (!skipping)
                    {
                        _visitor?.OidReference(0);
                    }
                }
                else if (oid <= int.MinValue || oid > 0)
                {
                    if (!skipping)
                    {
                        _visitor?.OidReference((ulong)oid);
                        IterateOid((ulong)oid);
                    }
                }
                else
                {
                    var kvHandlers = ((IFieldHandlerWithNestedFieldHandlers)handler).EnumerateNestedFieldHandlers().ToArray();
                    IterateInlineDict(ref reader, kvHandlers[0], kvHandlers[1], skipping, knownInlineRefs);
                }
            }
            else if (handler is NullableFieldHandler)
            {
                var hasValue = reader.ReadBool();
                if (hasValue)
                {
                    var itemHandler = ((IFieldHandlerWithNestedFieldHandlers)handler).EnumerateNestedFieldHandlers().First();
                    IterateHandler(ref reader, itemHandler, skipping, null);
                }
            }
            else if (handler is OrderedEncryptedStringHandler)
            {
                var cipher = _tr.Owner.GetSymmetricCipher();
                if (cipher is InvalidSymmetricCipher)
                {
                    var length = reader.ReadVUInt32();
                    _visitor?.ScalarAsText($"Encrypted[{length}]");
                    if (length > 0)
                    {
                        reader.SkipBlock(length - 1);
                    }
                }
                else
                {
                    var enc  = reader.ReadByteArray();
                    var size = cipher.CalcOrderedPlainSizeFor(enc);
                    var dec  = new byte[size];
                    if (!cipher.OrderedDecrypt(enc, dec))
                    {
                        _visitor?.ScalarAsText($"Encrypted[{enc!.Length}] failed to decrypt");
                    }

                    var r = new SpanReader(dec);
                    _visitor?.ScalarAsText(r.ReadString() !);
                }
            }
            else if (handler is EncryptedStringHandler)
            {
                var cipher = _tr.Owner.GetSymmetricCipher();
                if (cipher is InvalidSymmetricCipher)
                {
                    var length = reader.ReadVUInt32();
                    _visitor?.ScalarAsText($"Encrypted[{length}]");
                    if (length > 0)
                    {
                        reader.SkipBlock(length - 1);
                    }
                }
                else
                {
                    var enc  = reader.ReadByteArray();
                    var size = cipher.CalcPlainSizeFor(enc);
                    var dec  = new byte[size];
                    if (!cipher.Decrypt(enc, dec))
                    {
                        _visitor?.ScalarAsText($"Encrypted[{enc!.Length}] failed to decrypt");
                    }

                    var r = new SpanReader(dec);
                    _visitor?.ScalarAsText(r.ReadString() !);
                }
            }
            else if (handler.NeedsCtx() || handler.HandledType() == null)
            {
                throw new BTDBException("Don't know how to iterate " + handler.Name);
            }
            else
            {
                if (skipping || _visitor == null)
                {
                    if (!_skippers.TryGetValue(handler, out var skipper))
                    {
                        var meth =
                            ILBuilder.Instance.NewMethod <SkipperFun>("Skip" + handler.Name);
                        var il = meth.Generator;
                        handler.Skip(il, il2 => il2.Ldarg(0), null);
                        il.Ret();
                        skipper = meth.Create();
                        _skippers.Add(handler, skipper);
                    }
                    skipper(ref reader);
                }
                else
                {
                    if (!_loaders.TryGetValue(handler, out var loader))
                    {
                        var meth =
                            ILBuilder.Instance.NewMethod <LoaderFun>("Load" + handler.Name);
                        var il = meth.Generator;
                        handler.Load(il, il2 => il2.Ldarg(0), null);
                        il.Box(handler.HandledType() !).Ret();
                        loader = meth.Create();
                        _loaders.Add(handler, loader);
                    }
                    var obj = loader(ref reader);
                    if (_visitor.NeedScalarAsObject())
                    {
                        _visitor.ScalarAsObject(obj);
                    }
                    if (_visitor.NeedScalarAsText())
                    {
                        _visitor.ScalarAsText(obj == null
                            ? "null"
                            : string.Format(CultureInfo.InvariantCulture, "{0}", obj));
                    }
                }
            }
        }