< Summary

Class:Itinero.Network.Attributes.AttributeExtensions
Assembly:Itinero
File(s):/home/runner/work/routing2/routing2/src/Itinero/Network/Attributes/AttributeExtensions.cs
Covered lines:42
Uncovered lines:68
Coverable lines:110
Total lines:217
Line coverage:38.1% (42 of 110)
Covered branches:8
Total branches:34
Branch coverage:23.5% (8 of 34)
Tag:224_14471318300

Metrics

MethodBranch coverage Cyclomatic complexity Line coverage
TryGetValue(...)100%4100%
ContainsSame(...)0%120%
RemoveKey(...)0%40%
AddOrReplace(...)0%40%
AddOrReplace(...)0%40%
WriteAttributesTo(...)100%2100%
ReadAttributesFrom(...)100%2100%
GetHash(...)0%20%
GetDiffHash(...)100%10%

File(s)

/home/runner/work/routing2/routing2/src/Itinero/Network/Attributes/AttributeExtensions.cs

#LineLine coverage
 1using System;
 2using System.Collections.Generic;
 3using System.IO;
 4using System.Linq;
 5using Itinero.IO;
 6
 7namespace Itinero.Network.Attributes;
 8
 9/// <summary>
 10/// Contains extension methods for attribute handling.
 11/// </summary>
 12public static class AttributeExtensions
 13{
 14    /// <summary>
 15    /// Tries to get the value for the given key.
 16    /// </summary>
 17    /// <param name="attributes">The attributes.</param>
 18    /// <param name="key">The key.</param>
 19    /// <param name="value">The value, if any.</param>
 20    /// <returns>True if the key was found, false otherwise.</returns>
 21    public static bool TryGetValue(this IEnumerable<(string key, string value)> attributes, string key,
 22        out string value)
 6423    {
 39024        foreach (var (k, v) in attributes)
 12425        {
 12426            if (key != k)
 7427            {
 7428                continue;
 29            }
 30
 5031            value = v;
 5032            return true;
 33        }
 34
 1435        value = string.Empty;
 1436        return false;
 6437    }
 38
 39    /// <summary>
 40    /// Returns true if the given attribute collection contains the same attributes than the given collection.
 41    /// </summary>
 42    /// <param name="attributes">The attributes.</param>
 43    /// <param name="other">The other attributes.</param>
 44    /// <param name="exclude">Keys to exclude.</param>
 45    /// <returns>Trie of the same attributes.</returns>
 46    public static bool ContainsSame(this IEnumerable<(string key, string value)> attributes,
 47        IEnumerable<(string key, string value)> other, params string[] exclude)
 048    {
 049        var attributesCount = 0;
 050        var otherCount = 0;
 051        foreach (var a in attributes)
 052        {
 053            if (!exclude.Contains(a.key))
 054            {
 055                attributesCount++;
 056                if (!other.Contains(a))
 057                {
 058                    return false;
 59                }
 060            }
 061        }
 62
 063        foreach (var a in other)
 064        {
 065            if (exclude.Contains(a.key))
 066            {
 067                continue;
 68            }
 69
 070            otherCount++;
 071            if (!attributes.Contains(a))
 072            {
 073                return false;
 74            }
 075        }
 76
 077        return attributesCount == otherCount;
 078    }
 79
 80    /// <summary>
 81    /// Removes the attribute with the given key.
 82    /// </summary>
 83    /// <param name="attributes">The attributes.</param>
 84    /// <param name="key">The key.</param>
 85    /// <returns>True if the key was found.</returns>
 86    public static bool RemoveKey(this List<(string key, string value)> attributes, string key)
 087    {
 088        for (var i = 0; i < attributes.Count; i++)
 089        {
 090            var a = attributes[i];
 091            if (a.key != key)
 092            {
 093                continue;
 94            }
 95
 096            attributes.RemoveAt(i);
 097            return true;
 98        }
 99
 0100        return false;
 0101    }
 102
 103    /// <summary>
 104    /// Adds or replaces the value for the given attributes.
 105    /// </summary>
 106    /// <param name="attributes">The attributes.</param>
 107    /// <param name="other">The other attributes.</param>
 108    public static void AddOrReplace(this List<(string key, string value)> attributes,
 109        IEnumerable<(string key, string value)> other)
 0110    {
 0111        if (attributes == null)
 0112        {
 0113            throw new ArgumentNullException(nameof(attributes));
 114        }
 115
 0116        foreach (var a in other)
 0117        {
 0118            attributes.AddOrReplace(a.key, a.value);
 0119        }
 0120    }
 121
 122    /// <summary>
 123    /// Adds or replaces the value for the given key.
 124    /// </summary>
 125    /// <param name="attributes">The attributes.</param>
 126    /// <param name="key">The key.</param>
 127    /// <param name="value">The value.</param>
 128    /// <returns>True if the key was found.</returns>
 129    public static bool AddOrReplace(this List<(string key, string value)> attributes,
 130        string key, string value)
 0131    {
 0132        for (var i = 0; i < attributes.Count; i++)
 0133        {
 0134            var a = attributes[i];
 0135            if (a.key != key)
 0136            {
 0137                continue;
 138            }
 139
 0140            attributes[i] = (key, value);
 0141            return true;
 142        }
 143
 0144        attributes.Add((key, value));
 0145        return false;
 0146    }
 147
 148    /// <summary>
 149    /// Writes the attributes to the given stream starting at the current position of the stream.
 150    /// </summary>
 151    /// <param name="attributes">The attributes to write.</param>
 152    /// <param name="stream"></param>
 153    /// <returns>The number of byte written.</returns>
 154    internal static long WriteAttributesTo(this IEnumerable<(string key, string value)> attributes, Stream stream)
 5155    {
 5156        var pos = stream.Position;
 25157        foreach (var (key, value) in attributes)
 5158        {
 5159            var bytes = System.Text.Encoding.Unicode.GetBytes(key);
 5160            stream.WriteVarInt32(bytes.Length + 1); // 0 is null, end of the attribute set.
 5161            stream.Write(bytes, 0, bytes.Length);
 162
 5163            bytes = System.Text.Encoding.Unicode.GetBytes(value);
 5164            stream.WriteVarInt32(bytes.Length);
 5165            stream.Write(bytes, 0, bytes.Length);
 5166        }
 167
 5168        stream.WriteVarInt32(0);
 169
 5170        return stream.Position - pos;
 5171    }
 172
 173    /// <summary>
 174    /// Reads the attributes from the given stream starting at the current position of the stream.
 175    /// </summary>
 176    /// <param name="stream">The stream to read from.</param>
 177    /// <returns>The attributes read.</returns>
 178    internal static IEnumerable<(string key, string value)> ReadAttributesFrom(this Stream stream)
 4179    {
 4180        var attributes = new List<(string key, string value)>();
 181
 4182        var keySize = stream.ReadVarInt32();
 8183        while (keySize > 0)
 4184        {
 4185            var bytes = new byte[keySize - 1];
 4186            stream.Read(bytes, 0, bytes.Length);
 4187            var key = System.Text.Encoding.Unicode.GetString(bytes);
 188
 4189            var valueSize = stream.ReadVarInt32();
 4190            bytes = new byte[valueSize];
 4191            stream.Read(bytes, 0, bytes.Length);
 4192            var value = System.Text.Encoding.Unicode.GetString(bytes);
 193
 4194            attributes.Add((key, value));
 195
 4196            keySize = stream.ReadVarInt32();
 4197        }
 198
 4199        return attributes;
 4200    }
 201
 202    public static long GetHash(this IEnumerable<(string key, string value)> attributes)
 0203    {
 0204        var hash = 0;
 0205        foreach (var attribute in attributes)
 0206        {
 0207            hash ^= attribute.GetHashCode();
 0208        }
 209
 0210        return hash;
 0211    }
 212
 213    public static long GetDiffHash(this (string key, string value) otherValue, long originalHash)
 0214    {
 0215        return originalHash ^ otherValue.GetHashCode();
 0216    }
 217}