示例#1
0
        private VltBlockContainer ReadBlock(BinaryReader reader)
        {
            if (reader.BaseStream.Position == reader.BaseStream.Length)
            {
                return(null);
            }

            var block = new VltBlock
            {
                Position    = reader.BaseStream.Position,
                Type        = (VltMarker)reader.ReadInt32(),
                BlockLength = reader.ReadInt32(),
            };

            if (!block.IsBlank())
            {
                var vltType = block.Type;

                VltBlockContainer bc;

                switch (vltType)
                {
                case VltMarker.VltMagic:
                    bc = new HeaderBlock();
                    break;

                case VltMarker.TableStart:
                    bc = new TableStartBlock();
                    break;

                case VltMarker.TableEnd:
                    bc = new TableEndBlock();
                    break;

                default:
                    bc = new PlaceholderBlock();
                    break;
                }

                bc.Block = block;
                bc.Read(reader);
                block.SeekToNextBlock(reader.BaseStream);

                return(bc);
            }

            return(null);
        }
示例#2
0
        /// <summary>
        /// Ensure that the given range of placeholders is granular.
        /// </summary>
        /// <param name="id">Start of the range, measured in granular placeholders</param>
        /// <param name="size">Size of the range, measured in granular placeholders</param>
        /// <param name="splitPlaceholderCallback">Callback function to run when splitting placeholders, calls with (start, middle)</param>
        public void EnsurePlaceholders(ulong id, ulong size, Action <ulong, ulong> splitPlaceholderCallback)
        {
            // Search 1 before and after the placeholders, as we may need to expand/join granular regions surrounding the requested area.

            ulong endId         = id + size;
            ulong searchStartId = id == 0 ? 0 : (id - 1);
            int   blockCount    = _placeholders.FindOverlapsNonOverlapping(searchStartId, (endId - searchStartId) + 1, ref _foundBlocks);

            PlaceholderBlock first        = _foundBlocks[0];
            PlaceholderBlock last         = _foundBlocks[blockCount - 1];
            bool             overlapStart = first.EndAddress >= id && id != 0;
            bool             overlapEnd   = last.Address <= endId;

            for (int i = 0; i < blockCount; i++)
            {
                // Go through all non-granular blocks in the range and create placeholders.
                PlaceholderBlock block = _foundBlocks[i];

                if (block.Address <= id && block.EndAddress >= endId && block.IsGranular)
                {
                    return; // The region we're searching for is already granular.
                }

                if (!block.IsGranular)
                {
                    ulong placeholderStart = Math.Max(block.Address, id);
                    ulong placeholderEnd   = Math.Min(block.EndAddress - 1, endId);

                    if (placeholderStart != block.Address && placeholderStart != block.EndAddress)
                    {
                        splitPlaceholderCallback(block.Address, placeholderStart - block.Address);
                    }

                    for (ulong j = placeholderStart; j < placeholderEnd; j++)
                    {
                        splitPlaceholderCallback(j, 1);
                    }
                }

                if (!((block == first && overlapStart) || (block == last && overlapEnd)))
                {
                    // Remove blocks that will be replaced
                    _placeholders.Remove(block);
                }
            }

            if (overlapEnd)
            {
                if (!(first == last && overlapStart))
                {
                    _placeholders.Remove(last);
                }

                if (last.IsGranular)
                {
                    endId = last.EndAddress;
                }
                else if (last.EndAddress != endId)
                {
                    _placeholders.Add(new PlaceholderBlock(endId, last.EndAddress - endId, false));
                }
            }

            if (overlapStart && first.IsGranular)
            {
                first.ExtendTo(endId);
            }
            else
            {
                if (overlapStart)
                {
                    first.ExtendTo(id);
                }

                _placeholders.Add(new PlaceholderBlock(id, endId - id, true));
            }

            ValidateList();
        }
示例#3
0
        /// <summary>
        /// Coalesces placeholders in a given region, as they are not being used.
        /// This assumes that the region only contains placeholders - all views and allocations must have been replaced with placeholders.
        /// </summary>
        /// <param name="id">Start of the range, measured in granular placeholders</param>
        /// <param name="size">Size of the range, measured in granular placeholders</param>
        /// <param name="coalescePlaceholderCallback">Callback function to run when coalescing two placeholders, calls with (start, end)</param>
        public void RemovePlaceholders(ulong id, ulong size, Action <ulong, ulong> coalescePlaceholderCallback)
        {
            ulong endId      = id + size;
            int   blockCount = _placeholders.FindOverlapsNonOverlapping(id, size, ref _foundBlocks);

            PlaceholderBlock first = _foundBlocks[0];
            PlaceholderBlock last  = _foundBlocks[blockCount - 1];

            // All granular blocks must have non-granular blocks surrounding them, unless they start at 0.
            // We must extend the non-granular blocks into the granular ones. This does mean that we need to search twice.

            if (first.IsGranular || last.IsGranular)
            {
                ulong surroundStart = Math.Max(0, (first.IsGranular && first.Address != 0) ? first.Address - 1 : id);
                blockCount = _placeholders.FindOverlapsNonOverlapping(
                    surroundStart,
                    (last.IsGranular ? last.EndAddress + 1 : endId) - surroundStart,
                    ref _foundBlocks);

                first = _foundBlocks[0];
                last  = _foundBlocks[blockCount - 1];
            }

            if (first == last)
            {
                return; // Already coalesced.
            }

            PlaceholderBlock extendBlock = id == 0 ? null : first;
            bool             newBlock    = false;

            for (int i = extendBlock == null ? 0 : 1; i < blockCount; i++)
            {
                // Go through all granular blocks in the range and extend placeholders.
                PlaceholderBlock block = _foundBlocks[i];

                ulong blockEnd = block.EndAddress;
                ulong extendFrom;
                ulong extent = Math.Min(blockEnd, endId);

                if (block.Address < id && blockEnd > id)
                {
                    block.ExtendTo(id);
                    extendBlock = null;
                }
                else
                {
                    _placeholders.Remove(block);
                }

                if (extendBlock == null)
                {
                    extendFrom  = id;
                    extendBlock = new PlaceholderBlock(id, extent - id, false);
                    _placeholders.Add(extendBlock);

                    if (blockEnd > extent)
                    {
                        _placeholders.Add(new PlaceholderBlock(extent, blockEnd - extent, true));

                        // Skip the next non-granular block, and extend from that into the granular block afterwards.
                        // (assuming that one is still in the requested range)

                        if (i + 1 < blockCount)
                        {
                            extendBlock = _foundBlocks[i + 1];
                        }

                        i++;
                    }

                    newBlock = true;
                }
                else
                {
                    extendFrom = extendBlock.Address;
                    extendBlock.ExtendTo(block.IsGranular ? extent : block.EndAddress);
                }

                if (block.IsGranular)
                {
                    ulong placeholderStart = Math.Max(block.Address, id);
                    ulong placeholderEnd   = extent;

                    if (newBlock)
                    {
                        placeholderStart++;
                        newBlock = false;
                    }

                    for (ulong j = placeholderStart; j < placeholderEnd; j++)
                    {
                        coalescePlaceholderCallback(extendFrom, (j + 1) - extendFrom);
                    }

                    if (extent < block.EndAddress)
                    {
                        _placeholders.Add(new PlaceholderBlock(placeholderEnd, block.EndAddress - placeholderEnd, true));
                        ValidateList();
                        return;
                    }
                }
                else
                {
                    coalescePlaceholderCallback(extendFrom, block.EndAddress - extendFrom);
                }
            }

            ValidateList();
        }
示例#4
0
        public BlockBase CreateAndInitialiseBlock(View hostView, Node parentNode, BlockBase parentBlock, BlockDefinition definition, FieldList contentData, bool isRoot)
        {
            if (definition != null)
            {
                BlockBase block = null;

                if (definition is ContainerBlockDefinition)
                {
                    ContainerBlockDefinition cdef = (ContainerBlockDefinition)definition;

                    switch (cdef.HintedType)
                    {
                    case UIHintedType.ApplicationBar:
                        block = new ApplicationBarBlock(hostView, parentNode, parentBlock, definition, contentData, isRoot);
                        break;

                    case UIHintedType.NativeMessageBox:
                        block = new NativeMessageBoxBlock(hostView, parentNode, parentBlock, definition, contentData, isRoot);
                        break;

                    case UIHintedType.TabBar:
                        block = new TabBarBlock(hostView, parentNode, parentBlock, definition, contentData, isRoot);
                        break;

                    case UIHintedType.ActionSheet:
                        block = new ActionSheetBlock(hostView, parentNode, parentBlock, definition, contentData, isRoot);
                        break;

                    case UIHintedType.Pivot:
                        block = new PivotBlock(hostView, parentNode, parentBlock, definition, contentData, isRoot);
                        break;

                    case UIHintedType.Panorama:
                        block = new PanoramaBlock(hostView, parentNode, parentBlock, definition, contentData, isRoot);
                        break;

                    case UIHintedType.None:
                    default:
                    {
                        if (cdef is BoxLayoutBlockDefinition)
                        {
                            block = new BoxLayoutBlock(hostView, parentNode, parentBlock, definition, contentData, isRoot);
                        }
                        else if (cdef is GridBlockDefinition)
                        {
                            block = new GridBlock(hostView, parentNode, parentBlock, definition, contentData, isRoot);
                        }
                        else if (cdef is ListBlockDefinition)
                        {
                            block = new ListBlock(hostView, parentNode, parentBlock, definition, contentData, isRoot);
                        }
                        else if (cdef is FrameDefinition)
                        {
                            block = new FrameBlock(hostView, parentNode, parentBlock, definition, contentData, isRoot);
                        }

                        break;
                    }
                    }
                }
                else if (definition is CommonAtomicBlockDefinition)
                {
                    CommonAtomicBlockDefinition cabdef = (CommonAtomicBlockDefinition)definition;

                    switch (cabdef.HintedType)
                    {
                    case UIHintedType.ApplicationBarOptions:
                        block = new ApplicationBarOptionsBlock(hostView, parentNode, parentBlock, definition, contentData, isRoot);
                        break;

                    case UIHintedType.ApplicationBarButton:
                        block = new ApplicationBarButtonBlock(hostView, parentNode, parentBlock, definition, contentData, isRoot);
                        break;

                    case UIHintedType.ApplicationBarMenuItem:
                        block = new ApplicationBarMenuItemBlock(hostView, parentNode, parentBlock, definition, contentData, isRoot);
                        break;

                    case UIHintedType.NativeMessageBoxBody:
                        block = new NativeMessageBoxBodyBlock(hostView, parentNode, parentBlock, definition, contentData, isRoot);
                        break;

                    case UIHintedType.NativeMessageBoxButton:
                        block = new NativeMessageBoxButtonBlock(hostView, parentNode, parentBlock, definition, contentData, isRoot);
                        break;

                    case UIHintedType.TabBarButton:
                        block = new TabBarButtonBlock(hostView, parentNode, parentBlock, definition, contentData, isRoot);
                        break;

                    case UIHintedType.SystemTray:
                        block = new SystemTrayBlock(hostView, parentNode, parentBlock, definition, contentData, isRoot);
                        break;

                    case UIHintedType.Placeholder:
                        block = new PlaceholderBlock(hostView, parentNode, parentBlock, definition, contentData, isRoot);
                        break;

                    case UIHintedType.None:
                    default:
                    {
                        if (cabdef is AtomicBlockDefinition)
                        {
                            block = new AtomicBlock(hostView, parentNode, parentBlock, definition, contentData, isRoot);
                        }
                        else if (cabdef is SingleSlotBlockDefinition)
                        {
                            block = new SingleSlotBlock(hostView, parentNode, parentBlock, definition, contentData, isRoot);
                        }

                        break;
                    }
                    }
                }
                else if (definition is ScrollingTextBlockDefinition)
                {
                    block = new ScrollingTextBlock(hostView, parentNode, parentBlock, definition, contentData, isRoot);
                }
                else if (definition is MapPluginBlockDefinition)
                {
                    block = new MapPluginBlock(hostView, parentNode, parentBlock, definition, contentData, isRoot);
                }

                if (block != null)
                {
                    if (block.IsHidden)
                    {
                        block.Visibility = Visibility.Collapsed;
                    }

                    return(block);
                }
            }

            return(null);
        }