Exemple #1
0
        /// <exception cref="System.IO.IOException"></exception>
        internal virtual ObjectLoader Load(WindowCursor curs, long pos)
        {
            try
            {
                byte[]         ib     = curs.tempId;
                PackFile.Delta delta  = null;
                byte[]         data   = null;
                int            type   = Constants.OBJ_BAD;
                bool           cached = false;
                for (; ;)
                {
                    ReadFully(pos, ib, 0, 20, curs);
                    int  c        = ib[0] & unchecked ((int)(0xff));
                    int  typeCode = (c >> 4) & 7;
                    long sz       = c & 15;
                    int  shift    = 4;
                    int  p        = 1;
                    while ((c & unchecked ((int)(0x80))) != 0)
                    {
                        c      = ib[p++] & unchecked ((int)(0xff));
                        sz    += (c & unchecked ((int)(0x7f))) << shift;
                        shift += 7;
                    }
                    switch (typeCode)
                    {
                    case Constants.OBJ_COMMIT:
                    case Constants.OBJ_TREE:
                    case Constants.OBJ_BLOB:
                    case Constants.OBJ_TAG:
                    {
                        if (sz < curs.GetStreamFileThreshold())
                        {
                            data = Decompress(pos + p, (int)sz, curs);
                        }
                        if (delta != null)
                        {
                            type = typeCode;
                            goto SEARCH_break;
                        }
                        if (data != null)
                        {
                            return(new ObjectLoader.SmallObject(typeCode, data));
                        }
                        else
                        {
                            return(new LargePackedWholeObject(typeCode, sz, pos, p, this, curs.db));
                        }
                        goto case Constants.OBJ_OFS_DELTA;
                    }

                    case Constants.OBJ_OFS_DELTA:
                    {
                        c = ib[p++] & unchecked ((int)(0xff));
                        long @base = c & 127;
                        while ((c & 128) != 0)
                        {
                            @base  += 1;
                            c       = ib[p++] & unchecked ((int)(0xff));
                            @base <<= 7;
                            @base  += (c & 127);
                        }
                        @base = pos - @base;
                        delta = new PackFile.Delta(delta, pos, (int)sz, p, @base);
                        if (sz != delta.deltaSize)
                        {
                            goto SEARCH_break;
                        }
                        DeltaBaseCache.Entry e = DeltaBaseCache.Get(this, @base);
                        if (e != null)
                        {
                            type   = e.type;
                            data   = e.data;
                            cached = true;
                            goto SEARCH_break;
                        }
                        pos = @base;
                        goto SEARCH_continue;
                    }

                    case Constants.OBJ_REF_DELTA:
                    {
                        ReadFully(pos + p, ib, 0, 20, curs);
                        long @base = FindDeltaBase(ObjectId.FromRaw(ib));
                        delta = new PackFile.Delta(delta, pos, (int)sz, p + 20, @base);
                        if (sz != delta.deltaSize)
                        {
                            goto SEARCH_break;
                        }
                        DeltaBaseCache.Entry e = DeltaBaseCache.Get(this, @base);
                        if (e != null)
                        {
                            type   = e.type;
                            data   = e.data;
                            cached = true;
                            goto SEARCH_break;
                        }
                        pos = @base;
                        goto SEARCH_continue;
                    }

                    default:
                    {
                        throw new IOException(MessageFormat.Format(JGitText.Get().unknownObjectType, typeCode
                                                                   ));
                    }
                    }
                    SEARCH_continue :;
                }
                SEARCH_break :;
                // At this point there is at least one delta to apply to data.
                // (Whole objects with no deltas to apply return early above.)
                if (data == null)
                {
                    return(delta.Large(this, curs));
                }
                do
                {
                    // Cache only the base immediately before desired object.
                    if (cached)
                    {
                        cached = false;
                    }
                    else
                    {
                        if (delta.next == null)
                        {
                            DeltaBaseCache.Store(this, delta.basePos, data, type);
                        }
                    }
                    pos = delta.deltaPos;
                    byte[] cmds = Decompress(pos + delta.hdrLen, delta.deltaSize, curs);
                    if (cmds == null)
                    {
                        data = null;
                        // Discard base in case of OutOfMemoryError
                        return(delta.Large(this, curs));
                    }
                    long sz = BinaryDelta.GetResultSize(cmds);
                    if (int.MaxValue <= sz)
                    {
                        return(delta.Large(this, curs));
                    }
                    byte[] result;
                    try
                    {
                        result = new byte[(int)sz];
                    }
                    catch (OutOfMemoryException)
                    {
                        data = null;
                        // Discard base in case of OutOfMemoryError
                        return(delta.Large(this, curs));
                    }
                    BinaryDelta.Apply(data, cmds, result);
                    data  = result;
                    delta = delta.next;
                }while (delta != null);
                return(new ObjectLoader.SmallObject(type, data));
            }
            catch (SharpZipBaseException dfe)
            {
                CorruptObjectException coe = new CorruptObjectException(MessageFormat.Format(JGitText
                                                                                             .Get().objectAtHasBadZlibStream, pos, GetPackFile()));
                Sharpen.Extensions.InitCause(coe, dfe);
                throw coe;
            }
        }