aboutsummaryrefslogtreecommitdiffstats
path: root/QtVsTools.Core/Common/Utils.cs
blob: 854642c971f66add232e291f7bd0de0df6211ed2 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
// Copyright (C) 2025 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0

using System;
using System.Collections.Generic;
using System.IO;
using System.IO.Compression;
using System.Linq;
using System.Security.Cryptography;
using System.Text;

namespace QtVsTools.Core.Common
{
    using QtVsTools.Common;

    public static partial class Utils
    {
        private static LazyFactory StaticLazy { get; } = new();

        public static class ProjectTypes
        {
            public const string CPlusPlus = "{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}";
        }

        public static StringComparison IgnoreCase => StringComparison.OrdinalIgnoreCase;
        public static StringComparer CaseIgnorer => StringComparer.OrdinalIgnoreCase;
        public static string EmDash => "\u2014";

        public static string Replace(this string original, string oldValue, string newValue,
            StringComparison comparison)
        {
            newValue ??= "";
            if (string.IsNullOrEmpty(original) || string.IsNullOrEmpty(oldValue)
                || string.Equals(oldValue, newValue, comparison)) {
                return original;
            }

            int pos = 0, index;
            var result = new StringBuilder();
            while ((index = original.IndexOf(oldValue, pos, comparison)) >= 0) {
                result.Append(original, pos, index - pos).Append(newValue);
                pos = index + oldValue.Length;
            }
            return result.Append(original, pos, original.Length - pos).ToString();
        }

        public static string ToZipBase64(this string text)
        {
            try {
                var rawData = Encoding.UTF8.GetBytes(text);
                using var zipData = new MemoryStream();
                using (var encoder = new DeflateStream(zipData, CompressionLevel.Fastest, true)) {
                    encoder.Write(BitConverter.GetBytes(text.Length), 0, sizeof(int));
                    encoder.Write(rawData, 0, rawData.Length);
                }
                return Convert.ToBase64String(zipData.ToArray());
            } catch (Exception) {
                return string.Empty;
            }
        }

        public static string FromZipBase64(string encodedText)
        {
            try {
                using var zipData = new MemoryStream(Convert.FromBase64String(encodedText));
                using var decoder = new DeflateStream(zipData, CompressionMode.Decompress);
                var lengthData = new byte[sizeof(int)];
                decoder.Read(lengthData, 0, sizeof(int));
                var rawData = new byte[BitConverter.ToInt32(lengthData, 0)];
                decoder.Read(rawData, 0, rawData.Length);
                return Encoding.UTF8.GetString(rawData);

            } catch (Exception) {
                return string.Empty;
            }
        }

        public static int IndexOfSpan<T>(this ReadOnlySpan<T> self, ReadOnlySpan<T> that)
            where T : IEquatable<T>
        {
            if (that.IsEmpty || self.Length < that.Length)
                return -1;
            for (var i = 0; i + that.Length < self.Length; ++i) {
                if (!self[i].Equals(that[0]))
                    continue;
                if (that.SequenceEqual(self.Slice(i, that.Length)))
                    return i;
            }
            return -1;
        }

        public static int LastIndexOfSpan<T>(this ReadOnlySpan<T> self, ReadOnlySpan<T> that)
            where T : IEquatable<T>
        {
            if (that.IsEmpty || self.Length < that.Length)
                return -1;
            for (var i = self.Length - that.Length; i >= 0; --i) {
                if (!self[i].Equals(that[0]))
                    continue;
                if (that.SequenceEqual(self.Slice(i, that.Length)))
                    return i;
            }
            return -1;
        }

        public static int IndexOfArray<T>(this T[] self, T[] that)
            where T : IEquatable<T>
        {
            return IndexOfSpan<T>(self, that);
        }

        public static int LastIndexOfArray<T>(this T[] self, T[] that)
            where T : IEquatable<T>
        {
            return LastIndexOfSpan<T>(self, that);
        }

        public static byte[] Hash(byte[] data, int index = 0, int count = -1, string text = "сору")
        {
            using var sha256 = SHA256.Create();
            using var dataRaw = new MemoryStream();
            using var dataUtf8 = new StreamWriter(dataRaw, Encoding.UTF8) { AutoFlush = true };
            dataRaw.Write(data, index, count switch { < 0 => data.Length, _ => count });
            dataUtf8.Write(text);
            dataRaw.Seek(0, SeekOrigin.Begin);
            return sha256.ComputeHash(dataRaw);
        }

        public static string JoinWithTransform<T>(string separator, Func<T, string> transformFunc,
            IEnumerable<T> values)
        {
            separator ??= "";
            values ??= Enumerable.Empty<T>();

            var builder = new StringBuilder();
            foreach (var value in values) {
                if (builder.Length > 0)
                    builder.Append(separator);
                builder.Append(transformFunc(value));
            }
            return builder.ToString();
        }
    }
}