internal MemoryObject(MemoryFileSystem fs, MfsCellId cellId, bool fsInternal)
        {
            _fs = fs;
            _cellId = cellId;
            _obj = _fs.ReferenceObject(cellId);

            _fsInternal = fsInternal;

            if (!_fsInternal)
                _fs.Reference();

            // Prevent users from disposing the root object wrapper.
            if (_fsInternal)
                this.DisableOwnership(false);
        }
 internal MfsObjectHeader* ReferenceObject(MfsCellId cellId)
 {
     return (MfsObjectHeader*)this.ReferenceCell(cellId);
 }
        private IntPtr ReferenceCell(MfsCellId cellId)
        {
            IntPtr block;

            block = this.ReferenceBlock(cellId.Block);

            return block.Increment(cellId.Cell * _cellSize);
        }
        internal int ReadDataCell(MfsCellId cellId, System.IO.Stream stream, int length)
        {
            MfsDataCell* dc;
            byte[] buf = new byte[_dataCellDataMaxLength];
            int bytesRead = 0;

            while (length > 0)
            {
                MfsCellId newCellId;
                int readLength;

                dc = (MfsDataCell*)this.ReferenceCell(cellId);

                readLength = length > dc->DataLength ? dc->DataLength : length;
                Marshal.Copy(new IntPtr(&dc->Data), buf, 0, readLength);
                stream.Write(buf, 0, readLength);

                bytesRead += readLength;
                length -= readLength;

                newCellId = dc->NextCell;
                this.DereferenceCell(cellId);
                cellId = newCellId;

                if (cellId == MfsCellId.Empty)
                    break;
            }

            return bytesRead;
        }
        internal int ReadDataCell(MfsCellId cellId, byte[] buffer, int offset, int length)
        {
            MfsDataCell* dc;
            int bytesRead = 0;

            Utils.ValidateBuffer(buffer, offset, length);

            while (length > 0)
            {
                MfsCellId newCellId;
                int readLength;

                dc = (MfsDataCell*)this.ReferenceCell(cellId);

                readLength = length > dc->DataLength ? dc->DataLength : length;
                Marshal.Copy(new IntPtr(&dc->Data), buffer, offset, readLength);
                offset += readLength;
                bytesRead += readLength;
                length -= readLength;

                newCellId = dc->NextCell;
                this.DereferenceCell(cellId);
                cellId = newCellId;

                if (cellId == MfsCellId.Empty)
                    break;
            }

            return bytesRead;
        }
 private void InitializeObject(MfsObjectHeader* obj, MfsCellId cellId)
 {
     obj->Flink = cellId;
     obj->Blink = cellId;
     obj->Parent = MfsCellId.Empty;
     obj->ChildFlink = cellId;
     obj->ChildBlink = cellId;
     obj->DataLength = 0;
     obj->Data = MfsCellId.Empty;
     obj->LastData = MfsCellId.Empty;
 }
 internal void DereferenceObject(MfsCellId cellId)
 {
     this.DereferenceCell(cellId);
 }
 private void DereferenceCell(MfsCellId cellId)
 {
     this.DereferenceBlock(cellId.Block);
 }
        internal MfsCellId CreateObject(MfsCellId parent, string name)
        {
            MfsCellId cellId;
            MfsObjectHeader* obj;

            if (_readOnly)
                throw new MfsInvalidOperationException();

            obj = (MfsObjectHeader*)this.AllocateCell(out cellId);
            this.InitializeObject(obj, cellId);
            this.SetObjectName(obj, name);

            obj->Parent = parent;

            MfsObjectHeader* parentObj = this.ReferenceObject(parent);
            MfsCellId blink;
            MfsObjectHeader* blinkObj;

            // Increment the child count.
            parentObj->ChildCount++;

            // Insert tail.
            blink = parentObj->ChildBlink;
            blinkObj = this.ReferenceObject(blink);
            obj->Flink = parent;
            obj->Blink = blink;
            parentObj->ChildBlink = cellId;

            // Special case - we are not using linked lists properly, 
            // so we have to use this hack.
            if (blink == parent)
                blinkObj->ChildFlink = cellId;
            else
                blinkObj->Flink = cellId;

            this.DereferenceObject(blink);
            this.DereferenceObject(parent);
            this.DereferenceObject(cellId);

            return cellId;
        }
        internal MfsCellId CreateDataCell(MfsCellId prev, byte[] buffer, int offset, int length)
        {
            MfsCellId cellId;
            MfsDataCell* dc;
            MfsDataCell* prevDc;

            if (_readOnly)
                throw new MfsInvalidOperationException();

            Utils.ValidateBuffer(buffer, offset, length);

            if (length > _dataCellDataMaxLength)
                throw new ArgumentException("length");

            dc = (MfsDataCell*)this.AllocateCell(out cellId);
            dc->NextCell = MfsCellId.Empty;
            dc->DataLength = length;

            if (prev != MfsCellId.Empty)
            {
                prevDc = (MfsDataCell*)this.ReferenceCell(prev);
                prevDc->NextCell = cellId;
                this.DereferenceCell(prev);
            }

            Marshal.Copy(buffer, offset, new IntPtr(&dc->Data), length);

            this.DereferenceCell(cellId);

            return cellId;
        }
        private IntPtr AllocateCell(out MfsCellId cellIdOut)
        {  
            ushort blockId;
            ushort cellId;
            IntPtr lastBlock;
            MfsBlockHeader* header;

            if (_header->NextFreeBlock == 1)
            {
                // No blocks except for the FS header. Allocate one.
                lastBlock = this.AllocateBlock(out blockId);
            }
            else
            {
                blockId = (ushort)(_header->NextFreeBlock - 1);
                lastBlock = this.ReferenceBlock(blockId);
            }

            header = (MfsBlockHeader*)lastBlock;

            if (header->NextFreeCell == _cellCount)
            {
                // Block full. Allocate a new one.
                this.DereferenceBlock(lastBlock);

                // Fix up the cached reference.
                if (_cachedLastBlockView != null)
                {
                    this.DereferenceBlock(_cachedLastBlockView.BlockId);
                    _cachedLastBlockView = null;
                }

                lastBlock = this.AllocateBlock(out blockId);
                header = (MfsBlockHeader*)lastBlock;

                // Add a new cached reference.
                this.ReferenceBlock(blockId);
                _cachedLastBlockView = _views[blockId];
            }

            cellId = header->NextFreeCell++;
            cellIdOut = new MfsCellId(blockId, cellId);

            return lastBlock.Increment(cellId * _cellSize);
        }
 internal MemoryObject(MemoryFileSystem fs, MfsCellId cellId)
     : this(fs, cellId, false)
 { }