123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295 |
- using System;
- using System.Collections.Generic;
- using System.Globalization;
- using System.Linq;
- using System.Numerics;
- using System.Text;
- namespace Masuit.Tools.Strings;
- /// <summary>
- /// 数制格式化器
- /// </summary>
- public class UnicodeFormater
- {
- /// <summary>
- /// 数制表示字符集
- /// </summary>
- private List<string> Characters { get; }
- /// <summary>
- /// 进制长度
- /// </summary>
- public int Length => Characters.Count;
- /// <summary>
- /// 起始值偏移
- /// </summary>
- private readonly byte _offset;
- /// <summary>
- /// 数制格式化器
- /// </summary>
- public UnicodeFormater()
- {
- Characters = new List<string>() { "0", "1", "2", "3", "4", "5", "6", "7", "8", "9" };
- }
- /// <summary>
- /// 数制格式化器
- /// </summary>
- /// <param name="characters">符号集</param>
- /// <param name="offset">起始值偏移</param>
- public UnicodeFormater(string characters, byte offset = 0)
- {
- if (string.IsNullOrEmpty(characters))
- {
- throw new ArgumentException("符号集不能为空");
- }
- var enumerator = StringInfo.GetTextElementEnumerator(characters);
- Characters = new List<string>();
- while (enumerator.MoveNext())
- {
- Characters.Add(enumerator.GetTextElement());
- }
- _offset = offset;
- }
- /// <summary>
- /// 数制格式化器
- /// </summary>
- /// <param name="characters">符号集</param>
- /// <param name="offset">起始值偏移</param>
- public UnicodeFormater(List<string> characters, byte offset = 0)
- {
- if (characters.IsNullOrEmpty())
- {
- throw new ArgumentException("符号集不能为空");
- }
- Characters = characters;
- _offset = offset;
- }
- #if NET5_0_OR_GREATER
- /// <summary>
- /// 数制格式化器
- /// </summary>
- /// <param name="characters">符号集</param>
- /// <param name="offset">起始值偏移</param>
- public UnicodeFormater(ReadOnlySpan<byte> characters, byte offset = 0)
- {
- if (characters == null || characters.Length == 0)
- {
- throw new ArgumentException("符号集不能为空");
- }
- Characters = Encoding.UTF8.GetString(characters).Select(c => c.ToString()).ToList();
- _offset = offset;
- }
- /// <summary>
- /// 数制格式化器
- /// </summary>
- /// <param name="characters">符号集</param>
- /// <param name="offset">起始值偏移</param>
- public UnicodeFormater(ReadOnlySpan<char> characters, byte offset = 0)
- {
- if (characters == null || characters.Length == 0)
- {
- throw new ArgumentException("符号集不能为空");
- }
- Characters = characters.ToString().Select(c => c.ToString()).ToList();
- _offset = offset;
- }
- #endif
- /// <summary>
- /// 数制格式化器
- /// </summary>
- /// <param name="characters">符号集</param>
- /// <param name="offset">起始值偏移</param>
- public UnicodeFormater(byte[] characters, byte offset = 0)
- {
- if (characters == null || characters.Length == 0)
- {
- throw new ArgumentException("符号集不能为空");
- }
- Characters = Encoding.UTF8.GetString(characters).Select(c => c.ToString()).ToList();
- _offset = offset;
- }
- /// <summary>
- /// 数制格式化器
- /// </summary>
- /// <param name="characters">符号集</param>
- /// <param name="offset">起始值偏移</param>
- public UnicodeFormater(char[] characters, byte offset = 0)
- {
- if (characters == null || characters.Length == 0)
- {
- throw new ArgumentException("符号集不能为空");
- }
- Characters = characters.Select(c => c.ToString()).ToList();
- _offset = offset;
- }
- /// <summary>
- /// 数制格式化器
- /// </summary>
- /// <param name="base">进制</param>
- /// <param name="offset">起始值偏移</param>
- public UnicodeFormater(byte @base, byte offset = 0)
- {
- Characters = @base switch
- {
- <= 2 => new List<string>() { "0", "1" },
- > 2 and < 65 => "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ+/".Substring(0, @base).Select(c => c.ToString()).ToList(),
- >= 65 and <= 91 => "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789!#$%&()*+,-.:;<=>?@[]^_`{|}~\"".Substring(0, @base).Select(c => c.ToString()).ToList(),
- _ => throw new ArgumentException("默认进制最大支持91进制")
- };
- if (offset >= @base)
- {
- throw new ArgumentException("偏移量不能超过进制基数" + @base);
- }
- _offset = offset;
- }
- /// <summary>
- /// 数字转换为指定的进制形式字符串
- /// </summary>
- /// <param name="number"></param>
- /// <returns></returns>
- public string ToString(long number)
- {
- int start = 0;
- int resultOffset = 0;
- if (_offset > 0)
- {
- start = 1;
- resultOffset = _offset - 1;
- }
- number -= resultOffset;
- List<string> result = [];
- long t = Math.Abs(number);
- while (t != 0)
- {
- var mod = t % Length;
- t = Math.Abs(t / Length);
- var character = Characters[Convert.ToInt32(mod) - start];
- result.Insert(0, character);
- }
- if (number < 0)
- {
- result.Insert(0, "-");
- }
- return string.Join("", result);
- }
- /// <summary>
- /// 数字转换为指定的进制形式字符串
- /// </summary>
- /// <param name="number"></param>
- /// <returns></returns>
- public string ToString(BigInteger number)
- {
- int start = 0;
- int resultOffset = 0;
- if (_offset > 0)
- {
- start = 1;
- resultOffset = _offset - 1;
- }
- number -= resultOffset;
- List<string> result = [];
- if (number < 0)
- {
- number = -number;
- result.Add("0");
- }
- BigInteger t = number;
- while (t != 0)
- {
- var mod = t % Length;
- t = BigInteger.Abs(BigInteger.Divide(t, Length));
- var character = Characters[(int)mod - start];
- result.Insert(0, character);
- }
- return string.Join("", result);
- }
- /// <summary>
- /// 指定字符串转换为指定进制的数字形式
- /// </summary>
- /// <param name="str"></param>
- /// <returns></returns>
- public long FromString(string str)
- {
- byte start = 0;
- int resultOffset = 0;
- if (_offset > 0)
- {
- start = 1;
- resultOffset = _offset - 1;
- }
- int j = 0;
- var emoji = new List<string>();
- var enumerator = StringInfo.GetTextElementEnumerator(str);
- while (enumerator.MoveNext())
- {
- emoji.Add(enumerator.GetTextElement());
- }
- emoji.Reverse();
- return emoji.Where(Characters.Contains).Sum(ch => (Characters.IndexOf(ch) + start) * (long)Math.Pow(Length, j++)) + resultOffset;
- }
- /// <summary>
- /// 指定字符串转换为指定进制的大数形式
- /// </summary>
- /// <param name="str"></param>
- /// <returns></returns>
- public BigInteger FromStringBig(string str)
- {
- byte start = 0;
- int resultOffset = 0;
- if (_offset > 0)
- {
- start = 1;
- resultOffset = _offset - 1;
- }
- int j = 0;
- var emoji = new List<string>();
- var enumerator = StringInfo.GetTextElementEnumerator(str);
- while (enumerator.MoveNext())
- {
- emoji.Add(enumerator.GetTextElement());
- }
- emoji.Reverse();
- return emoji.Where(Characters.Contains).Aggregate(BigInteger.Zero, (current, c) => current + (Characters.IndexOf(c) + start) * BigInteger.Pow(Length, j++)) + resultOffset;
- }
- /// <summary>Returns a string that represents the current object.</summary>
- /// <returns>A string that represents the current object.</returns>
- public override string ToString()
- {
- return Length + "进制模式,进制符:" + Characters.Join("");
- }
- }
|