| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228 |
- using System;
- using System.Collections.Generic;
- namespace ET.PackageManager.Editor
- {
- [Serializable]
- public struct StrChunk
- {
- /// <summary>
- /// 字符串,或者key
- /// 如果是字符串,keyIndex = 0;
- /// 如果是key,keyIndex表示索引,从1开始
- /// </summary>
- public string TextOrKey;
- /// <summary>
- /// 如果StrOrKey为Key时的索引值,从1开始
- /// </summary>
- public byte KeyIndex;
- }
- public static partial class StrUtil
- {
- /// <summary>
- /// 高性能处理字符串中{%key%num}形式的占位符
- /// 其中key为连续的小写字母,nul为非0开头的连续数字
- /// 返回一个StrChunk数组,方便使用的地方缓存以加速替换占位符
- /// </summary>
- /// <param name="value"></param>
- /// <param name="throwError">
- /// 是否抛出错误
- /// 如果为false,则会进行容错性解析
- /// </param>
- /// <returns></returns>
- public static StrChunk[] GetStrChunk(string value, bool throwError = false)
- {
- if (string.IsNullOrEmpty(value))
- {
- return Array.Empty<StrChunk>();
- }
- var chunks = g_cacheStrChunkList;
- var sb = SbPool.Get();
- var keySb = SbPool.Get();
- var indexSb = SbPool.Get();
- int throwErrId = -1;
- char lastChar = char.MaxValue;
- ReadChunkState state = ReadChunkState.ReadText;
- const char beginChar = '{';
- const char endChar = '}';
- int chrCount = value.Length;
- for (int i = 0; i < chrCount; i++)
- {
- char c = value[i];
- switch (state)
- {
- case ReadChunkState.ReadText:
- switch (c)
- {
- case beginChar:
- state = ReadChunkState.ReadyReadKey;
- break;
- case endChar:
- state = ReadChunkState.Escape;
- break;
- default:
- sb.Append(c);
- break;
- }
- break;
- case ReadChunkState.ReadyReadKey:
- if (c == beginChar)
- {
- //{{,转义为{
- sb.Append(beginChar);
- state = ReadChunkState.ReadText;
- break;
- }
- if (c < 'a' || c > 'z')
- {
- throwErrId = 1;
- sb.Append(beginChar).Append(c);
- state = ReadChunkState.ReadText;
- break;
- }
- keySb.Append(c);
- state = ReadChunkState.ReadKey;
- break;
- case ReadChunkState.ReadKey:
- if (c >= 'a' && c <= 'z')
- {
- keySb.Append(c);
- break;
- }
- if (c >= '1' && c <= '9')
- {
- indexSb.Append(c);
- state = ReadChunkState.ReadIndex;
- break;
- }
- throwErrId = 2;
- sb.Append(beginChar).Append(keySb.ToString()).Append(c);
- keySb.Clear();
- state = ReadChunkState.ReadText;
- break;
- case ReadChunkState.ReadIndex:
- if (c >= '0' && c <= '9')
- {
- indexSb.Append(c);
- break;
- }
- if (c == endChar)
- {
- chunks.Add(new StrChunk() { TextOrKey = sb.ToString() });
- chunks.Add(new StrChunk()
- {
- KeyIndex = byte.Parse(indexSb.ToString()),
- TextOrKey = keySb.ToString()
- });
- sb.Clear();
- }
- else
- {
- throwErrId = 3;
- sb.Append(beginChar)
- .Append(keySb.ToString())
- .Append(indexSb.ToString())
- .Append(c);
- }
- keySb.Clear();
- indexSb.Clear();
- state = ReadChunkState.ReadText;
- break;
- case ReadChunkState.Escape:
- if (c == lastChar)
- {
- sb.Append(c);
- }
- else
- {
- throwErrId = 0;
- sb.Append(lastChar).Append(c);
- }
- state = ReadChunkState.ReadText;
- break;
- }
- //处理错误
- if (throwError && throwErrId > -1)
- {
- switch (throwErrId)
- {
- case 0:
- throw new Exception(string.Format("text={3}, index={0}, chr='{1}':此处只能出现'{2}'", i, c,
- lastChar, value));
- case 1:
- throw new Exception(string.Format("text={2}, index={0}, chr='{1}', 此处只能出现小写英文字符", i, c,
- value));
- case 2:
- throw new Exception(string.Format("text={2}, index={0}, chr='{1}', 此处只能出现小写英文或1-9的数字", i, c,
- value));
- case 3:
- throw new Exception(string.Format("text={2}, index={0}, chr='{1}', 0-9的数字或'}}'", i, c,
- value));
- }
- }
- lastChar = c;
- }
- //结尾处理
- if (state != ReadChunkState.ReadText)
- {
- if (throwError)
- {
- throw new Exception("没有正确结束, state=" + state.ToString());
- }
- sb.Append(keySb.ToString()).Append(indexSb.ToString());
- }
- if (sb.Length > 0)
- {
- chunks.Add(new StrChunk() { TextOrKey = sb.ToString() });
- }
- SbPool.Put(sb);
- SbPool.Put(keySb);
- SbPool.Put(indexSb);
- var arr = chunks.ToArray();
- chunks.Clear();
- return arr;
- }
- private static readonly List<StrChunk> g_cacheStrChunkList = new List<StrChunk>();
- private enum ReadChunkState
- {
- ReadText,
- ReadyReadKey,
- ReadKey,
- ReadIndex,
- //转义处理
- Escape
- }
- }
- }
|