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 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);
        }
        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 IntPtr ReferenceCell(MfsCellId cellId)
        {
            IntPtr block;

            block = this.ReferenceBlock(cellId.Block);

            return(block.Increment(cellId.Cell * _cellSize));
        }
 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 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);
        }
        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, 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));
 }
 internal void DereferenceObject(MfsCellId cellId)
 {
     this.DereferenceCell(cellId);
 }
 private void DereferenceCell(MfsCellId cellId)
 {
     this.DereferenceBlock(cellId.Block);
 }
 internal MemoryObject(MemoryFileSystem fs, MfsCellId cellId)
     : this(fs, cellId, false)
 {
 }