Ejemplo 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));
             }
         }
     }
 }