< Summary

Class:Itinero.Network.Tiles.Standalone.StandaloneNetworkTile
Assembly:Itinero
File(s):/home/runner/work/routing2/routing2/src/Itinero/Network/Tiles/Standalone/StandaloneNetworkTile.Attributes.cs
/home/runner/work/routing2/routing2/src/Itinero/Network/Tiles/Standalone/StandaloneNetworkTile.Boundaries.cs
/home/runner/work/routing2/routing2/src/Itinero/Network/Tiles/Standalone/StandaloneNetworkTile.cs
/home/runner/work/routing2/routing2/src/Itinero/Network/Tiles/Standalone/StandaloneNetworkTile.Global.cs
/home/runner/work/routing2/routing2/src/Itinero/Network/Tiles/Standalone/StandaloneNetworkTile.Serialization.cs
Covered lines:0
Uncovered lines:348
Coverable lines:348
Total lines:568
Line coverage:0% (0 of 348)
Covered branches:0
Total branches:74
Branch coverage:0% (0 of 74)
Tag:251_23667616543

Metrics

MethodBranch coverage Cyclomatic complexity Line coverage
.ctor(...)100%10%
SetAttributes(...)0%80%
GetAttributes()0%60%
AddOrGetString(...)0%60%
WriteAttributesTo(...)0%40%
ReadAttributesFrom(...)0%40%
ReadAttributesFrom(...)0%20%
WriteAttributesTo(...)0%20%
.ctor(...)100%10%
AddBoundaryCrossing(...)0%40%
GetBoundaryCrossings()0%40%
.ctor(...)100%10%
get_NetworkTile()100%10%
GetEnumerator()100%10%
get_TileId()100%10%
.ctor(...)100%10%
AddGlobalRestriction(...)0%100%
GetGlobalRestrictions()0%80%
WriteGlobal(...)0%20%
ReadGlobal(...)0%20%
ReadGlobal(...)100%10%
WriteGlobal(...)100%10%
WriteTo(...)100%10%
WriteEdgesAndVerticesTo(...)0%20%
ReadFrom(...)0%20%
ReadEdgesAndVerticesFrom(...)0%20%
ReadFrom(...)0%20%
ReadEdgesAndVerticesFrom(...)100%10%
ToBytes()0%20%
WriteToBuffer(...)100%10%
WriteEdgesAndVerticesTo(...)100%10%
GetSerializedSizeUpperBound()0%20%

File(s)

/home/runner/work/routing2/routing2/src/Itinero/Network/Tiles/Standalone/StandaloneNetworkTile.Attributes.cs

#LineLine coverage
 1using System;
 2using System.Collections.Generic;
 3using System.IO;
 4using Itinero.IO;
 5using Itinero.Network.Storage;
 6
 7namespace Itinero.Network.Tiles.Standalone;
 8
 9public partial class StandaloneNetworkTile
 10{
 11    /// <summary>
 12    /// Stores the attributes, starting with the number of attributes and then alternating key-value pairs.
 13    /// </summary>
 14    private byte[] _attributes;
 15
 016    private uint _nextAttributePointer = 0;
 17
 18    /// <summary>
 19    /// Stores each string once.
 20    /// </summary>
 21    private string[] _strings;
 22
 023    private uint _nextStringId = 0;
 24
 25    private uint SetAttributes(IEnumerable<(string key, string value)> attributes)
 026    {
 027        var start = _nextAttributePointer;
 28
 029        long cPos = start;
 030        long p = start + 1;
 031        var c = 0;
 032        foreach (var (key, value) in attributes)
 033        {
 034            if (_attributes.Length <= p + 16)
 035            {
 036                Array.Resize(ref _attributes, (int)(_attributes.Length + 256));
 037            }
 38
 039            var id = this.AddOrGetString(key);
 040            p += _attributes.SetDynamicUInt32(p, id);
 041            id = this.AddOrGetString(value);
 042            p += _attributes.SetDynamicUInt32(p, id);
 43
 044            c++;
 045            if (c == 255)
 046            {
 047                _attributes[(int)cPos] = 255;
 048                c = 0;
 049                cPos = p;
 050                p++;
 051            }
 052        }
 53
 054        if (_attributes.Length <= cPos)
 055        {
 056            Array.Resize(ref _attributes, (int)(_attributes.Length + 256));
 057        }
 58
 059        _attributes[(int)cPos] = (byte)c;
 60
 061        _nextAttributePointer = (uint)p;
 62
 063        return start;
 064    }
 65
 66    internal IEnumerable<(string key, string value)> GetAttributes(uint? pointer)
 067    {
 068        if (pointer == null)
 069        {
 070            yield break;
 71        }
 72
 073        var p = pointer.Value;
 74
 075        var count = -1;
 76        do
 077        {
 078            count = _attributes[p];
 079            p++;
 80
 081            for (var i = 0; i < count; i++)
 082            {
 083                p += (uint)_attributes.GetDynamicUInt32(p, out var keyId);
 084                p += (uint)_attributes.GetDynamicUInt32(p, out var valId);
 85
 086                yield return (_strings[keyId], _strings[valId]);
 087            }
 088        } while (count == 255);
 089    }
 90
 91    private uint AddOrGetString(string s)
 092    {
 093        for (uint i = 0; i < _nextStringId; i++)
 094        {
 095            var existing = _strings[i];
 096            if (existing == s)
 097            {
 098                return i;
 99            }
 0100        }
 101
 0102        if (_strings.Length <= _nextStringId)
 0103        {
 0104            Array.Resize(ref _strings, (int)(_strings.Length + 256));
 0105        }
 106
 0107        var id = _nextStringId;
 0108        _nextStringId++;
 109
 0110        _strings[id] = s;
 0111        return id;
 0112    }
 113
 114    private void WriteAttributesTo(Stream stream)
 0115    {
 0116        stream.WriteVarUInt32(_nextAttributePointer);
 0117        for (var i = 0; i < _nextAttributePointer; i++)
 0118        {
 0119            stream.WriteByte(_attributes[i]);
 0120        }
 121
 0122        stream.WriteVarUInt32(_nextStringId);
 0123        for (var i = 0; i < _nextStringId; i++)
 0124        {
 0125            stream.WriteWithSize(_strings[i]);
 0126        }
 0127    }
 128
 129    private void ReadAttributesFrom(Stream stream)
 0130    {
 0131        _nextAttributePointer = stream.ReadVarUInt32();
 0132        _attributes = new byte[_nextAttributePointer];
 0133        for (var i = 0; i < _nextAttributePointer; i++)
 0134        {
 0135            _attributes[i] = (byte)stream.ReadByte();
 0136        }
 137
 0138        _nextStringId = stream.ReadVarUInt32();
 0139        _strings = new string[_nextStringId];
 0140        for (var i = 0; i < _nextStringId; i++)
 0141        {
 0142            _strings[i] = stream.ReadWithSizeString();
 0143        }
 0144    }
 145
 146    private void ReadAttributesFrom(byte[] data, ref int offset)
 0147    {
 0148        _nextAttributePointer = BitCoderBuffer.GetVarUInt32(data, ref offset);
 0149        _attributes = new byte[_nextAttributePointer];
 0150        Buffer.BlockCopy(data, offset, _attributes, 0, (int)_nextAttributePointer);
 0151        offset += (int)_nextAttributePointer;
 152
 0153        _nextStringId = BitCoderBuffer.GetVarUInt32(data, ref offset);
 0154        _strings = new string[_nextStringId];
 0155        for (var i = 0; i < _nextStringId; i++)
 0156        {
 0157            _strings[i] = BitCoderBuffer.GetWithSizeString(data, ref offset);
 0158        }
 0159    }
 160
 161    private void WriteAttributesTo(byte[] data, ref int offset)
 0162    {
 0163        BitCoderBuffer.SetVarUInt32(data, ref offset, _nextAttributePointer);
 0164        Buffer.BlockCopy(_attributes, 0, data, offset, (int)_nextAttributePointer);
 0165        offset += (int)_nextAttributePointer;
 166
 0167        BitCoderBuffer.SetVarUInt32(data, ref offset, _nextStringId);
 0168        for (var i = 0; i < _nextStringId; i++)
 0169        {
 0170            BitCoderBuffer.SetWithSizeString(data, ref offset, _strings[i]);
 0171        }
 0172    }
 173}

/home/runner/work/routing2/routing2/src/Itinero/Network/Tiles/Standalone/StandaloneNetworkTile.Boundaries.cs

#LineLine coverage
 1using System;
 2using System.Collections.Generic;
 3using Itinero.Network.Storage;
 4using Itinero.Network.Tiles.Standalone.Global;
 5
 6namespace Itinero.Network.Tiles.Standalone;
 7
 8public partial class StandaloneNetworkTile
 9{
 010    private byte[] _crossings = new byte[1024];
 11    private uint _crossingsPointer;
 12
 13    internal void AddBoundaryCrossing(bool isIncoming, GlobalEdgeId globalEdgeId, VertexId vertex,
 14        IEnumerable<(string key, string value)> attributes, uint edgeTypeId)
 015    {
 016        if (vertex.TileId != this.NetworkTile.TileId)
 017            throw new ArgumentException("Can only add boundary crossings that cross into the tile");
 18
 019        ArrayBaseExtensions.EnsureMinimumSize(ref _crossings, _crossingsPointer + 36);
 020        if (isIncoming)
 021        {
 22            // incoming if vertex is encoded as a positive number.
 023            _crossingsPointer += _crossings.SetDynamicInt32(_crossingsPointer, (int)(vertex.LocalId + 1));
 024        }
 25        else
 026        {
 27            // outgoing if vertex is encode as a negative number.
 028            _crossingsPointer += _crossings.SetDynamicInt32(_crossingsPointer, -(int)(vertex.LocalId + 1));
 029        }
 030        _crossingsPointer += _crossings.SetDynamicUInt32(_crossingsPointer, edgeTypeId);
 031        _crossingsPointer += _crossings.SetGlobalEdgeId(_crossingsPointer, globalEdgeId);
 32
 033        var a = this.SetAttributes(attributes);
 034        _crossingsPointer += _crossings.SetDynamicUInt32(_crossingsPointer, a);
 035    }
 36
 37    /// <summary>
 38    /// Gets all boundary crossing edges.
 39    /// </summary>
 40    /// <returns>An enumerable with all boundary crossing edges.</returns>
 41    public IEnumerable<(bool isIncoming, GlobalEdgeId globalEdgeId, VertexId vertex,
 42        IEnumerable<(string key, string value)> attributes, uint edgeTypeId)> GetBoundaryCrossings()
 043    {
 044        var pointer = 0L;
 045        while (pointer < _crossingsPointer)
 046        {
 047            pointer += _crossings.GetDynamicInt32(pointer, out var localIdSigned);
 48            bool isIncoming;
 49            uint localId;
 050            if (localIdSigned > 0)
 051            {
 052                localId = (uint)(localIdSigned - 1);
 053                isIncoming = true;
 054            }
 55            else
 056            {
 057                localId = (uint)(-localIdSigned - 1);
 058                isIncoming = false;
 059            }
 060            pointer += _crossings.GetDynamicUInt32(pointer, out var edgeTypeId);
 061            pointer += _crossings.GetGlobalEdgeId(pointer, out var globalEdgeId);
 062            pointer += _crossings.GetDynamicUInt32(pointer, out var a);
 63
 064            yield return (isIncoming, globalEdgeId, new VertexId(this.TileId, localId), this.GetAttributes(a),
 065                edgeTypeId);
 066        }
 067    }
 68}

/home/runner/work/routing2/routing2/src/Itinero/Network/Tiles/Standalone/StandaloneNetworkTile.cs

#LineLine coverage
 1namespace Itinero.Network.Tiles.Standalone;
 2
 3/// <summary>
 4/// A standalone network tile.
 5/// </summary>
 6public partial class StandaloneNetworkTile
 7{
 08    internal StandaloneNetworkTile(NetworkTile networkTile)
 09    {
 010        _attributes = new byte[1024];
 011        _strings = new string[128];
 12
 013        this.NetworkTile = networkTile;
 014    }
 15
 016    internal NetworkTile NetworkTile { get; }
 17
 18    /// <summary>
 19    /// Gets an enumerator to access the non-boundary edges.
 20    /// </summary>
 21    /// <returns></returns>
 22    public IStandaloneNetworkTileEnumerator GetEnumerator()
 023    {
 024        var enumerator = new NetworkTileEnumerator();
 025        enumerator.MoveTo(this.NetworkTile);
 026        return enumerator;
 027    }
 28
 29    /// <summary>
 30    /// Gets the tile id.
 31    /// </summary>
 032    public uint TileId => this.NetworkTile.TileId;
 33}

/home/runner/work/routing2/routing2/src/Itinero/Network/Tiles/Standalone/StandaloneNetworkTile.Global.cs

#LineLine coverage
 1using System;
 2using System.Collections.Generic;
 3using System.IO;
 4using System.Linq;
 5using Itinero.IO;
 6using Itinero.Network.Storage;
 7using Itinero.Network.Tiles.Standalone.Global;
 8using Itinero.Network.TurnCosts;
 9
 10namespace Itinero.Network.Tiles.Standalone;
 11
 12public partial class StandaloneNetworkTile
 13{
 14    // here we store all the data about global restrictions that could not be turned into turn costs yet because the net
 15    // the edge of the tiles. we store the global edge ids of the restriction along with the type so we can create the t
 16    // is being completed
 17    private uint _globalRestrictionsPointer;
 018    private byte[] _globalRestrictions = new byte[0];
 19
 20    /// <summary>
 21    /// Adds a global restriction for processing when the tile is loaded.
 22    /// </summary>
 23    /// <param name="sequence">The sequence of global edge ids with local edge ids if they are already known.</param>
 24    /// <param name="isProhibitory">The type of restriction.</param>
 25    /// <param name="turnCostTypeId">The turn cost type, already determined.</param>
 26    /// <param name="attributes">The raw attributes of the restriction.</param>
 27    public void AddGlobalRestriction(IEnumerable<(GlobalEdgeId globalEdgeId, EdgeId? edge)> sequence,
 28        bool isProhibitory, uint turnCostTypeId, IEnumerable<(string key, string value)> attributes)
 029    {
 030        var edges = sequence.ToList();
 031        if (edges.Count > OrderCoder.MaxOrderHeadTail) throw new ArgumentException(
 032                $"Cannot add turn costs for vertices with more than {OrderCoder.MaxOrderHeadTail} edges.");
 33
 34        // make sure there is space in the turn cost array.
 035        var maxLength = _globalRestrictionsPointer + 5 + 5 + 5 +
 036                        (edges.Count * (9 + 5 + 5 + 5));
 037        while (_globalRestrictions.Length < maxLength)
 038        {
 039            Array.Resize(ref _globalRestrictions, (int)(_globalRestrictions.Length + 256));
 040        }
 41
 42        // add turn.
 043        var a = this.SetAttributes(attributes);
 044        _globalRestrictionsPointer += _globalRestrictions.SetDynamicUInt32(_globalRestrictionsPointer, a);
 045        if (isProhibitory)
 046        {
 47            // isProhibitory if turnCostTypeId is encoded as a positive number.
 048            _globalRestrictionsPointer += _globalRestrictions.SetDynamicInt32(_globalRestrictionsPointer, (int)(turnCost
 049        }
 50        else
 051        {
 52            // not isProhibitory if turnCostTypeId is encoded as a negative number.
 053            _globalRestrictionsPointer += _globalRestrictions.SetDynamicInt32(_globalRestrictionsPointer, -(int)(turnCos
 054        }
 055        _globalRestrictionsPointer += _globalRestrictions.SetDynamicUInt32(_globalRestrictionsPointer, (uint)edges.Count
 056        foreach (var (globalEdgeId, edgeId) in edges)
 057        {
 058            _globalRestrictionsPointer += _globalRestrictions.SetGlobalEdgeId(_globalRestrictionsPointer, globalEdgeId);
 059            if (edgeId == null)
 060            {
 061                _globalRestrictionsPointer += _globalRestrictions.SetDynamicUInt32Nullable(_globalRestrictionsPointer,
 062                    null);
 063            }
 64            else
 065            {
 066                _globalRestrictionsPointer += _globalRestrictions.SetDynamicUInt32Nullable(_globalRestrictionsPointer,
 067                    edgeId.Value.LocalId);
 068            }
 069        }
 070    }
 71
 72    /// <summary>
 73    /// Gets all the global restrictions.
 74    /// </summary>
 75    /// <returns></returns>
 76    public IEnumerable<(IReadOnlyList<(GlobalEdgeId globalEdgeId, EdgeId? edgeId)> edges, bool isProhibitory, uint turnC
 77        IEnumerable<(string key, string value)> attributes)> GetGlobalRestrictions()
 078    {
 079        var pointer = 0L;
 080        while (pointer < _globalRestrictionsPointer)
 081        {
 082            pointer += _globalRestrictions.GetDynamicUInt32(pointer, out var a);
 083            pointer += _globalRestrictions.GetDynamicInt32(pointer, out var turnCostTypeSigned);
 84            uint turnCostType;
 85            bool isProhibitory;
 086            if (turnCostTypeSigned > 0)
 087            {
 088                isProhibitory = true;
 089                turnCostType = (uint)turnCostTypeSigned - 1;
 090            }
 91            else
 092            {
 093                isProhibitory = false;
 094                turnCostType = (uint)(-turnCostTypeSigned - 1);
 095            }
 096            pointer += _globalRestrictions.GetDynamicUInt32(pointer, out var edgeCount);
 097            var edges = new (GlobalEdgeId globalEdgeId, EdgeId? edge)[edgeCount];
 098            for (var i = 0; i < edgeCount; i++)
 099            {
 0100                pointer += _globalRestrictions.GetGlobalEdgeId(pointer, out var globalEdgeId);
 0101                pointer += _globalRestrictions.GetDynamicUInt32Nullable(pointer,
 0102                    out var localId);
 103
 0104                EdgeId? edgeId = null;
 0105                if (localId != null)
 0106                {
 0107                    edgeId = new EdgeId(this.TileId, localId.Value);
 0108                }
 109
 0110                edges[i] = (globalEdgeId, edgeId);
 0111            }
 112
 0113            yield return (edges, isProhibitory, turnCostType, this.GetAttributes(a));
 0114        }
 0115    }
 116
 117    private void WriteGlobal(Stream stream)
 0118    {
 0119        stream.WriteVarUInt32(_globalRestrictionsPointer);
 0120        for (var i = 0; i < _globalRestrictionsPointer; i++)
 0121        {
 0122            stream.WriteByte(_globalRestrictions[i]);
 0123        }
 0124    }
 125
 126    private void ReadGlobal(Stream stream)
 0127    {
 0128        _globalRestrictionsPointer = stream.ReadVarUInt32();
 0129        _globalRestrictions = new byte[_globalRestrictionsPointer];
 0130        for (var i = 0; i < _globalRestrictionsPointer; i++)
 0131        {
 0132            _globalRestrictions[i] = (byte)stream.ReadByte();
 0133        }
 0134    }
 135
 136    private void ReadGlobal(byte[] data, ref int offset)
 0137    {
 0138        _globalRestrictionsPointer = BitCoderBuffer.GetVarUInt32(data, ref offset);
 0139        _globalRestrictions = new byte[_globalRestrictionsPointer];
 0140        Buffer.BlockCopy(data, offset, _globalRestrictions, 0, (int)_globalRestrictionsPointer);
 0141        offset += (int)_globalRestrictionsPointer;
 0142    }
 143
 144    private void WriteGlobal(byte[] data, ref int offset)
 0145    {
 0146        BitCoderBuffer.SetVarUInt32(data, ref offset, _globalRestrictionsPointer);
 0147        Buffer.BlockCopy(_globalRestrictions, 0, data, offset, (int)_globalRestrictionsPointer);
 0148        offset += (int)_globalRestrictionsPointer;
 0149    }
 150}

/home/runner/work/routing2/routing2/src/Itinero/Network/Tiles/Standalone/StandaloneNetworkTile.Serialization.cs

#LineLine coverage
 1using System;
 2using System.IO;
 3using Itinero.IO;
 4
 5namespace Itinero.Network.Tiles.Standalone;
 6
 7public partial class StandaloneNetworkTile
 8{
 9    public void WriteTo(Stream stream)
 010    {
 011        var version = 2;
 012        stream.WriteVarInt32(version);
 13
 14        // write base tile.
 015        this.NetworkTile.WriteTo(stream);
 16
 17        // write edges and vertices for boundary crossings.
 018        this.WriteEdgesAndVerticesTo(stream);
 19
 20        // write attributes.
 021        this.WriteAttributesTo(stream);
 22
 23        // write global ids.
 024        this.WriteGlobal(stream);
 025    }
 26
 27    private void WriteEdgesAndVerticesTo(Stream stream)
 028    {
 029        stream.WriteVarUInt32(_crossingsPointer);
 030        for (var i = 0; i < _crossingsPointer; i++)
 031        {
 032            stream.WriteByte(_crossings[i]);
 033        }
 034    }
 35
 36    public static StandaloneNetworkTile ReadFrom(Stream stream)
 037    {
 038        var version = stream.ReadVarInt32();
 039        if (version != 2)
 040        {
 041            throw new InvalidDataException("Cannot deserialize tiles: Invalid version #.");
 42        }
 43
 044        var networkTile = NetworkTile.ReadFrom(stream);
 045        var standaloneNetworkTile = new StandaloneNetworkTile(networkTile);
 46
 47        // read boundary crossings.
 048        standaloneNetworkTile.ReadEdgesAndVerticesFrom(stream);
 49
 50        // read attributes.
 051        standaloneNetworkTile.ReadAttributesFrom(stream);
 52
 53        // read global.
 054        standaloneNetworkTile.ReadGlobal(stream);
 55
 056        return standaloneNetworkTile;
 057    }
 58
 59    private void ReadEdgesAndVerticesFrom(Stream stream)
 060    {
 61        // read vertex pointers.
 062        _crossingsPointer = stream.ReadVarUInt32();
 063        _crossings = new byte[_crossingsPointer];
 064        for (var i = 0; i < _crossingsPointer; i++)
 065        {
 066            _crossings[i] = (byte)stream.ReadByte();
 067        }
 068    }
 69
 70    public static StandaloneNetworkTile ReadFrom(byte[] data, int offset)
 071    {
 072        var version = BitCoderBuffer.GetVarInt32(data, ref offset);
 073        if (version != 2)
 074        {
 075            throw new InvalidDataException("Cannot deserialize tiles: Invalid version #.");
 76        }
 77
 078        var networkTile = NetworkTile.ReadFromBuffer(data, ref offset);
 079        var standaloneNetworkTile = new StandaloneNetworkTile(networkTile);
 80
 081        standaloneNetworkTile.ReadEdgesAndVerticesFrom(data, ref offset);
 082        standaloneNetworkTile.ReadAttributesFrom(data, ref offset);
 083        standaloneNetworkTile.ReadGlobal(data, ref offset);
 84
 085        return standaloneNetworkTile;
 086    }
 87
 88    private void ReadEdgesAndVerticesFrom(byte[] data, ref int offset)
 089    {
 090        _crossingsPointer = BitCoderBuffer.GetVarUInt32(data, ref offset);
 091        _crossings = new byte[_crossingsPointer];
 092        Buffer.BlockCopy(data, offset, _crossings, 0, (int)_crossingsPointer);
 093        offset += (int)_crossingsPointer;
 094    }
 95
 96    public byte[] ToBytes()
 097    {
 098        var maxSize = this.GetSerializedSizeUpperBound();
 099        var buffer = new byte[maxSize];
 0100        var offset = 0;
 0101        this.WriteToBuffer(buffer, ref offset);
 0102        if (offset == maxSize) return buffer;
 0103        var result = new byte[offset];
 0104        Buffer.BlockCopy(buffer, 0, result, 0, offset);
 0105        return result;
 0106    }
 107
 108    private void WriteToBuffer(byte[] data, ref int offset)
 0109    {
 110        const int version = 2;
 0111        BitCoderBuffer.SetVarInt32(data, ref offset, version);
 112
 0113        this.NetworkTile.WriteToBuffer(data, ref offset);
 0114        this.WriteEdgesAndVerticesTo(data, ref offset);
 0115        this.WriteAttributesTo(data, ref offset);
 0116        this.WriteGlobal(data, ref offset);
 0117    }
 118
 119    private void WriteEdgesAndVerticesTo(byte[] data, ref int offset)
 0120    {
 0121        BitCoderBuffer.SetVarUInt32(data, ref offset, _crossingsPointer);
 0122        Buffer.BlockCopy(_crossings, 0, data, offset, (int)_crossingsPointer);
 0123        offset += (int)_crossingsPointer;
 0124    }
 125
 126    private int GetSerializedSizeUpperBound()
 0127    {
 0128        var size = 5;
 0129        size += this.NetworkTile.GetSerializedSizeUpperBound();
 130
 0131        size += 5 + (int)_crossingsPointer;
 132
 0133        size += 5 + (int)_nextAttributePointer;
 0134        size += 5;
 0135        for (var i = 0; i < _nextStringId; i++)
 0136        {
 0137            size += 8 + System.Text.Encoding.Unicode.GetByteCount(_strings[i]);
 0138        }
 139
 0140        size += 5 + (int)_globalRestrictionsPointer;
 141
 0142        return size;
 0143    }
 144}