<commit_before>﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Cryptography;
using System.Text;
using JetBrains.Annotations;

namespace JoinRpg.Helpers
{
  public static class StaticStringHelpers
  {
    [NotNull]
    public static string JoinIfNotNullOrWhitespace([NotNull, ItemCanBeNull] this IEnumerable<string> strings, [NotNull] string separator)
    {
      return string.Join(separator, strings.WhereNotNullOrWhiteSpace());
    }

    [NotNull, ItemNotNull]
    public static IEnumerable<string> WhereNotNullOrWhiteSpace([ItemCanBeNull] [NotNull] this IEnumerable<string> strings)
    {
      if (strings == null) throw new ArgumentNullException(nameof(strings));
      return strings.Where(s => !string.IsNullOrWhiteSpace(s));
    }

    [NotNull]
    public static string JoinStrings([NotNull] [ItemNotNull] this IEnumerable<string> strings,
      [NotNull] string separator)
    {
      if (strings == null) throw new ArgumentNullException(nameof(strings));
      if (separator == null) throw new ArgumentNullException(nameof(separator));
      return string.Join(separator, strings);
    }

    [NotNull]
    public static string JoinStrings([NotNull] this IEnumerable<char> strings,
      [NotNull] string separator)
    {
      if (strings == null) throw new ArgumentNullException(nameof(strings));
      if (separator == null) throw new ArgumentNullException(nameof(separator));
      return string.Join(separator, strings);
    }

    public static IEnumerable<int> UnprefixNumbers([NotNull, ItemNotNull] this IEnumerable<string> enumerable, [NotNull] string prefix)
    {
      return enumerable.Where(key => key.StartsWith(prefix)).Select(key=> key.Substring(prefix.Length)).Select(int.Parse);
    }

    public static int? UnprefixNumber([NotNull] this string number, [NotNull] string prefix)
    {
      return number.StartsWith(prefix) ? (int?) int.Parse(number.Substring(prefix.Length)) : null;
    }

    [NotNull]
    public static string ToHexString([NotNull] this IEnumerable<byte> bytes)
    {
      if (bytes == null) throw new ArgumentNullException(nameof(bytes));
      return bytes.Select(b => $"{b:x2}").JoinStrings("");
    }

    [NotNull]
    public static byte[] FromHexString ([NotNull] this string str)
    {
      if (str == null) throw new ArgumentNullException(nameof(str));

      str = str.Trim();
      if (str.Length%2 == 1)
      {
        str = "0" + str;
      }
      var result = new byte[str.Length/2];
      for (int i = 0; i < str.Length; i += 2)
      {
        result[i / 2] = (byte) (HexCharToInt(str[i + 1]) + HexCharToInt(str[i]) * 16);
      }
      return result;
    }

    private static int HexCharToInt(char ch)
    {
      if (char.IsDigit(ch))
      {
        return ch - '0';
      }
      ch = char.ToLowerInvariant(ch);
      if (ch >= 'a' && ch <= 'f')
      {
        return ch - 'a' + 10;
      }
      throw new ArgumentException(nameof(ch));
    }


    public static string RemoveFromString([NotNull] this string url, [NotNull, ItemNotNull] IEnumerable<string> tokensToRemove)
    {
      if (url == null) throw new ArgumentNullException(nameof(url));
      if (tokensToRemove == null) throw new ArgumentNullException(nameof(tokensToRemove));
      return tokensToRemove.Aggregate(url, (current, replaceToken) => current.Replace(replaceToken, ""));
    }

    public static string ToHexHash(this string str, HashAlgorithm hashAlgorithm)
    {
      var bytes = Encoding.UTF8.GetBytes(str); //TODO: In what encoding Allrpg.info saves passwords? Do not want to think about it....
      return hashAlgorithm.ComputeHash(bytes).ToHexString();
    }

    public static string AfterSeparator(this string str, char separator)
    {
      return str.SkipWhile(c => c!=separator).Skip(1).JoinStrings("");
    }

    public static string BeforeSeparator(this string str, char separator)
    {
      return str.TakeWhile(c=> c!=separator).JoinStrings("");
    }

    public static int[] ToIntList([CanBeNull] this string claimIds)
    {
      if (claimIds == null)
      {
        return Array.Empty<int>();
      }
      return claimIds.Split(',').Select(int.Parse).ToArray();
    }

    [NotNull]
    public static IEnumerable<byte> AsUtf8BytesWithLimit([NotNull] string formattableString, int bytesLimit)
    {
      if (formattableString == null) throw new ArgumentNullException(nameof(formattableString));<commit_msg>Fix bug with empty lists<commit_after>﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Cryptography;
using System.Text;
using JetBrains.Annotations;

namespace JoinRpg.Helpers
{
  public static class StaticStringHelpers
  {
    [NotNull]
    public static string JoinIfNotNullOrWhitespace([NotNull, ItemCanBeNull] this IEnumerable<string> strings, [NotNull] string separator)
    {
      return string.Join(separator, strings.WhereNotNullOrWhiteSpace());
    }

    [NotNull, ItemNotNull]
    public static IEnumerable<string> WhereNotNullOrWhiteSpace([ItemCanBeNull] [NotNull] this IEnumerable<string> strings)
    {
      if (strings == null) throw new ArgumentNullException(nameof(strings));
      return strings.Where(s => !string.IsNullOrWhiteSpace(s));
    }

    [NotNull]
    public static string JoinStrings([NotNull] [ItemNotNull] this IEnumerable<string> strings,
      [NotNull] string separator)
    {
      if (strings == null) throw new ArgumentNullException(nameof(strings));
      if (separator == null) throw new ArgumentNullException(nameof(separator));
      return string.Join(separator, strings);
    }

    [NotNull]
    public static string JoinStrings([NotNull] this IEnumerable<char> strings,
      [NotNull] string separator)
    {
      if (strings == null) throw new ArgumentNullException(nameof(strings));
      if (separator == null) throw new ArgumentNullException(nameof(separator));
      return string.Join(separator, strings);
    }

    public static IEnumerable<int> UnprefixNumbers([NotNull, ItemNotNull] this IEnumerable<string> enumerable, [NotNull] string prefix)
    {
      return enumerable.Where(key => key.StartsWith(prefix)).Select(key=> key.Substring(prefix.Length)).Select(int.Parse);
    }

    public static int? UnprefixNumber([NotNull] this string number, [NotNull] string prefix)
    {
      return number.StartsWith(prefix) ? (int?) int.Parse(number.Substring(prefix.Length)) : null;
    }

    [NotNull]
    public static string ToHexString([NotNull] this IEnumerable<byte> bytes)
    {
      if (bytes == null) throw new ArgumentNullException(nameof(bytes));
      return bytes.Select(b => $"{b:x2}").JoinStrings("");
    }

    [NotNull]
    public static byte[] FromHexString ([NotNull] this string str)
    {
      if (str == null) throw new ArgumentNullException(nameof(str));

      str = str.Trim();
      if (str.Length%2 == 1)
      {
        str = "0" + str;
      }
      var result = new byte[str.Length/2];
      for (int i = 0; i < str.Length; i += 2)
      {
        result[i / 2] = (byte) (HexCharToInt(str[i + 1]) + HexCharToInt(str[i]) * 16);
      }
      return result;
    }

    private static int HexCharToInt(char ch)
    {
      if (char.IsDigit(ch))
      {
        return ch - '0';
      }
      ch = char.ToLowerInvariant(ch);
      if (ch >= 'a' && ch <= 'f')
      {
        return ch - 'a' + 10;
      }
      throw new ArgumentException(nameof(ch));
    }


    public static string RemoveFromString([NotNull] this string url, [NotNull, ItemNotNull] IEnumerable<string> tokensToRemove)
    {
      if (url == null) throw new ArgumentNullException(nameof(url));
      if (tokensToRemove == null) throw new ArgumentNullException(nameof(tokensToRemove));
      return tokensToRemove.Aggregate(url, (current, replaceToken) => current.Replace(replaceToken, ""));
    }

    public static string ToHexHash(this string str, HashAlgorithm hashAlgorithm)
    {
      var bytes = Encoding.UTF8.GetBytes(str); //TODO: In what encoding Allrpg.info saves passwords? Do not want to think about it....
      return hashAlgorithm.ComputeHash(bytes).ToHexString();
    }

    public static string AfterSeparator(this string str, char separator)
    {
      return str.SkipWhile(c => c!=separator).Skip(1).JoinStrings("");
    }

    public static string BeforeSeparator(this string str, char separator)
    {
      return str.TakeWhile(c=> c!=separator).JoinStrings("");
    }

    [NotNull]
    public static int[] ToIntList([CanBeNull] this string claimIds)
    {
      if (string.IsNullOrWhiteSpace(claimIds))
      {
        return Array.Empty<int>();
      }
      return claimIds.Split(',').Select(int.Parse).ToArray();
    }

    [NotNull]
    public static IEnumerable<byte> AsUtf8BytesWithLimit([NotNull] string formattableString, int bytesLimit)
    {
      if (formattableString == null) throw new ArgumentNullException(nameof(formattableString));
{'fraction_non_alphanumeric': 0.11991458754776355, 'fraction_numerical': 0.003821083389525736, 'mean_word_length': 3.425161611138737, 'pattern_counts': {'":': 0, '<': 29, '<?xml version=': 0, '>': 41, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '7375901', 'n_tokens_mistral': 2617, 'n_tokens_neox': 2547, 'n_words': 655}