/// <summary> /// Gets the path for a Transform from the root, e.g. '/root/parent/mytransform' /// </summary> public static string GetPath(Transform t) { if (t == null) { return(null); } string path = null; StringBuilder b = null; try { b = StringBuilderPool.Get(); b = GetPathFrom(t, null, b); if (b[0] != '/') { b.Insert(0, "/"); } path = b.ToString(); } finally { if (b != null) { StringBuilderPool.Return(b); } } return(path); }
private static string Describe(ErrorResponseMessage errorMessage) { if (errorMessage.ErrorCount == 0) { return("Server returned an error with no description."); } var sb = StringBuilderPool.Get(); try { for (var i = 0; i < errorMessage.ErrorCount - 1; ++i, sb.Append(", ")) { var error = errorMessage.Errors[i]; sb.Append(error.Value); } return(sb.ToString()); } finally { StringBuilderPool.Free(ref sb); } }
private bool AddWordCapitalized(string word, FlagSet flags, MorphSet morphs, CapitalizationType capType) { // add inner capitalized forms to handle the following allcap forms: // Mixed caps: OpenOffice.org -> OPENOFFICE.ORG // Allcaps with suffixes: CIA's -> CIA'S if ( ( capType == CapitalizationType.Huh || capType == CapitalizationType.HuhInit || (capType == CapitalizationType.All && flags.HasItems) ) && !flags.Contains(Affix.ForbiddenWord) ) { flags = Builder.Dedup(FlagSet.Union(flags, SpecialFlags.OnlyUpcaseFlag)); var textInfo = Affix.Culture.TextInfo; var initCapBuilder = StringBuilderPool.Get(word); if (initCapBuilder.Length > 0) { initCapBuilder[0] = textInfo.ToUpper(initCapBuilder[0]); for (var i = 1; i < initCapBuilder.Length; i++) { initCapBuilder[i] = textInfo.ToLower(initCapBuilder[i]); } } return(AddWord(StringBuilderPool.GetStringAndReturn(initCapBuilder), flags, morphs, true)); } return(false); }
public static string HashPath(string path) { var md5 = new MD5CryptoServiceProvider(); var ret = md5.ComputeHash(Encoding.UTF8.GetBytes(path)); var builder = StringBuilderPool.Get(); foreach (var b in ret) { builder.Append(b.ToString("x2")); } var str = builder.ToString(); StringBuilderPool.Return(builder); builder = StringBuilderPool.Get(); builder.Append(str.Substring(0, 2)); builder.Append("/"); builder.Append(str.Substring(2, 2)); builder.Append("/"); builder.Append(str); var hashed = builder.ToString(); StringBuilderPool.Return(builder); return(hashed); }
public bool TryConvert(string text, out string converted) { var convertedBuilder = StringBuilderPool.Get(text.Length); var appliedConversion = false; for (var i = 0; i < text.Length; i++) { var replacementEntry = FindLargestMatchingConversion(text.Subslice(i)); var replacementText = replacementEntry == null ? string.Empty : replacementEntry.ExtractReplacementText(text.Length - i, i == 0); if (replacementText.Length == 0) { convertedBuilder.Append(text[i]); } else { convertedBuilder.Append(replacementText); i += replacementEntry.Pattern.Length - 1; appliedConversion = true; } } converted = StringBuilderPool.GetStringAndReturn(convertedBuilder); return(appliedConversion); }
public static bool AddReplacementEntry(this Dictionary <string, MultiReplacementEntry> list, string pattern1, string pattern2) { if (string.IsNullOrEmpty(pattern1) || pattern2 == null) { return(false); } var pattern1Builder = StringBuilderPool.Get(pattern1); ReplacementValueType type; var trailingUnderscore = pattern1Builder.EndsWith('_'); if (pattern1Builder.StartsWith('_')) { if (trailingUnderscore) { type = ReplacementValueType.Isol; pattern1Builder.Remove(pattern1Builder.Length - 1, 1); } else { type = ReplacementValueType.Ini; } pattern1Builder.Remove(0, 1); } else { if (trailingUnderscore) { type = ReplacementValueType.Fin; pattern1Builder.Remove(pattern1Builder.Length - 1, 1); } else { type = ReplacementValueType.Med; } } pattern1Builder.Replace('_', ' '); pattern1 = StringBuilderPool.GetStringAndReturn(pattern1Builder); pattern2 = pattern2.Replace('_', ' '); // find existing entry MultiReplacementEntry entry; if (list.TryGetValue(pattern1, out entry)) { entry = entry.With(type, pattern2); } else { // make a new entry if none exists entry = new MultiReplacementEntry(pattern1, type, pattern2); } list[pattern1] = entry; return(true); }
public string ReadLine() { if (!hasCheckedForPreamble) { ReadPreamble(); } var builder = StringBuilderPool.Get(); char[] readChars = null; while ((readChars = ReadNextChars()) != null) { if (ProcessCharsForLine(readChars, builder)) { break; } } if (readChars == null && builder.Length == 0) { return(null); } return(ProcessLine(StringBuilderPool.GetStringAndReturn(builder))); }
public async Task <string> ReadLineAsync() { if (!hasCheckedForPreamble) { await ReadPreambleAsync().ConfigureAwait(false); } var builder = StringBuilderPool.Get(); char[] readChars = null; while ((readChars = await ReadNextCharsAsync().ConfigureAwait(false)) != null) { if (ProcessCharsForLine(readChars, builder)) { break; } } if (readChars == null && builder.Length == 0) { return(null); } return(ProcessLine(StringBuilderPool.GetStringAndReturn(builder))); }
internal static StringBuilder RequestStringBuilder() { #if GEBO_COMMON_FULL return(StringBuilderPool.Get()); #else return(new StringBuilder()); #endif }
/// <summary> /// Setups the parameters. /// </summary> /// <param name="Count">The count.</param> /// <param name="FinalParameters">The final parameters.</param> /// <param name="Finalizable">if set to <c>true</c> [finalizable].</param> /// <param name="FinalSQLCommand">The final SQL command.</param> private int SetupParameters(int Count, List <IParameter> FinalParameters, ref bool Finalizable, ref string FinalSQLCommand) { var ParameterTotal = 0; var Builder = StringBuilderPool?.Get() ?? new StringBuilder(); Builder.Append(FinalSQLCommand); for (var y = 0; y < Headers.Count; ++y) { var Command = Headers[y]; if (ParameterTotal + Command.Parameters.Length >= 2000) { break; } ParameterTotal += Command.Parameters.Length; Finalizable |= Command.Finalizable; if (Command.CommandType == CommandType.Text) { var TempCommandText = Command.SQLCommand ?? string.Empty; Builder.Append(Command.SQLCommand ?? string.Empty).Append(Environment.NewLine); for (int i = 0, CommandParametersLength = Command.Parameters.Length; i < CommandParametersLength; i++) { var TempParameter = Command.Parameters[i]; FinalParameters.Add(TempParameter.CreateCopy(string.Empty)); } } else { Builder.Append(Command.SQLCommand).Append(Environment.NewLine); for (int i = 0, CommandParametersLength = Command.Parameters.Length; i < CommandParametersLength; i++) { var TempParameter = Command.Parameters[i]; FinalParameters.Add(TempParameter.CreateCopy(string.Empty)); } } } for (var y = Count; y < Commands.Count; ++y) { var Command = Commands[y]; if (ParameterTotal + Command.Parameters.Length >= 2000) { break; } ParameterTotal += Command.Parameters.Length; Finalizable |= Command.Finalizable; if (Command.CommandType == CommandType.Text) { var TempCommandText = Command.SQLCommand ?? string.Empty; var Suffix = "Command" + Count.ToString(CultureInfo.InvariantCulture); Builder.Append(string.IsNullOrEmpty(Command.SQLCommand) ? string.Empty : ParameterRegex.Replace(Command.SQLCommand, x => { var Param = Array.Find(Command.Parameters, z => z.ID == x.Groups["ParamName"].Value); return(!(Param is null) ? x.Value + Suffix : x.Value); })).Append(Environment.NewLine);
private bool TryParseReplacements(string parameterText, List <SingleReplacement> entries) { var parameters = parameterText.SliceOnTabOrSpace(); if (parameters.Length == 0) { Builder.LogWarning("Failed to parse replacements from: " + parameterText); return(false); } var patternBuilder = StringBuilderPool.Get(parameters[0]); var outString = parameters.Length > 1 ? parameters[1].ToString() : string.Empty; ReplacementValueType type; var hasTrailingDollar = patternBuilder.EndsWith('$'); if (patternBuilder.StartsWith('^')) { if (hasTrailingDollar) { type = ReplacementValueType.Isol; patternBuilder.Remove(patternBuilder.Length - 1, 1); } else { type = ReplacementValueType.Ini; } patternBuilder.Remove(0, 1); } else { if (hasTrailingDollar) { type = ReplacementValueType.Fin; patternBuilder.Remove(patternBuilder.Length - 1, 1); } else { type = ReplacementValueType.Med; } } patternBuilder.Replace('_', ' '); entries.Add(new SingleReplacement( Builder.Dedup(StringBuilderPool.GetStringAndReturn(patternBuilder)), Builder.Dedup(outString.Replace('_', ' ')), type)); return(true); }
/// <summary> /// Build CSS class string from boolean properties of objects in arguments, from strings in arguments. /// </summary> public static string CssClass(params object[] args) { var builder = StringBuilderPool.Get(); try { var _1st = true; foreach (var arg in args) { if (arg is string s) { if (!_1st) { builder.Append(' '); } _1st = false; builder.Append(s); } else if (arg is Enum e) { if (!_1st) { builder.Append(' '); } _1st = false; builder.Append(GetHyphenatedName(e.ToString())); } else { foreach (var(name, getter) in GetPropEntriesFromCache(arg)) { if ((bool)getter.Invoke(arg, null)) { if (!_1st) { builder.Append(' '); } _1st = false; builder.Append(name); } } } } return(builder.ToString()); } finally { StringBuilderPool.Return(builder); } }
private void NextLine(bool noWait = false) { StringBuilder stringBuilder = StringBuilderPool.Get(); stringBuilder.Append(((ReactiveProperty <string>) this._name).get_Value()); stringBuilder.Append(": "); stringBuilder.Append(this._textBuffer[this._currentLine]); ((ReactiveProperty <string>) this._message).set_Value(stringBuilder.ToString()); ++this._currentLine; this.FontSpeed = Manager.Config.GameData.FontSpeed; if (noWait && !this._typefaceAnimator.isNoWait) { this.FontSpeed = 100; } this._typefaceAnimator.Play(); }
protected override void LoadAssetAtPathInternal(string path, Type type) { var resPath = PathUtility.RelativeProjectPathToRelativeResourcesPath(path); var sb = StringBuilderPool.Get(); sb.Append(Path.GetDirectoryName(resPath)); sb.Append("/"); sb.Append(Path.GetFileNameWithoutExtension(resPath)); _request = Resources.LoadAsync(sb.ToString(), type); if (_request == null) { throw new BundleAssetLoadFailedException( string.Format("Cannot load asset {0} from resources: ", sb)); } StringBuilderPool.Return(sb); }
/// <summary> /// Recursive search for right ss - sharp s permutations /// </summary> private WordEntry SpellSharps(ref string @base, int nPos, int n, int repNum, ref SpellCheckResultType info, out string root) { var pos = @base.IndexOfOrdinal("ss", nPos); if (pos >= 0 && n < MaxSharps) { var baseBuilder = StringBuilderPool.Get(@base, @base.Length); baseBuilder[pos] = 'ß'; baseBuilder.Remove(pos + 1, 1); @base = baseBuilder.ToString(); var h = SpellSharps(ref @base, pos + 1, n + 1, repNum + 1, ref info, out root); if (h != null) { return(h); } baseBuilder.Clear(); baseBuilder.Append(@base); baseBuilder[pos] = 's'; baseBuilder.Insert(pos + 1, 's'); @base = StringBuilderPool.GetStringAndReturn(baseBuilder); h = SpellSharps(ref @base, pos + 2, n + 1, repNum, ref info, out root); if (h != null) { return(h); } } else if (repNum > 0) { return(CheckWord(@base, ref info, out root)); } root = null; return(null); }
protected override void LoadAssetInternal() { Logs.Logger.LogInfo("Start synchronously loading asset: {0}", _path); #if UNITY_EDITOR if (_context.Options.UseAssetDatabaseInsteadOfResources) { _asset = AssetDatabase.LoadAssetAtPath(_path, _type); if (!_asset) { throw new BundleAssetLoadFailedException("Could not load asset from AssetDatabase: " + _path); } } else #endif { var resPath = PathUtility.RelativeProjectPathToRelativeResourcesPath(_path); var sb = StringBuilderPool.Get(); sb.Append(Path.GetDirectoryName(resPath)); sb.Append("/"); sb.Append(Path.GetFileNameWithoutExtension(resPath)); _asset = Resources.Load(sb.ToString(), _type); if (!_asset) { throw new BundleAssetLoadFailedException("Could not load asset from resources: " + _path); } StringBuilderPool.Return(sb); } IsDone = true; Logs.Logger.LogInfo("End synchronously loading asset: {0}", _path); }
public void AddMessage(int _actorID, string _message) { if (_message.IsNullOrEmpty() && _message == null) { _message = string.Empty; } OneColor oneColor = this.PersonColor(_actorID); string self = this.PersonName(_actorID) ?? string.Empty; if (self.IsNullOrEmpty() && _message.IsNullOrEmpty()) { Debug.LogWarning((object)"AddNotify: キャラ名もメッセージも空っぽだったので追加せず"); } else if (self.IsNullOrEmpty()) { this.AddLog(_message); } else { if ((string)oneColor != (string)null) { StringBuilder toRelease = StringBuilderPool.Get(); toRelease.AppendFormat("<color={0}>{1}</color>{2}", (object)oneColor, (object)self, (object)_message); _message = toRelease.ToString(); StringBuilderPool.Release(toRelease); } else { StringBuilder toRelease = StringBuilderPool.Get(); toRelease.AppendFormat("{0}{1}", (object)self, (object)_message); _message = toRelease.ToString(); StringBuilderPool.Release(toRelease); } this.AddLog(_message); } }
public static unsafe IReadOnlyList <string> Perform( IReadOnlyList <PostgresPropertySetting> settings, PostgresCommand command) { var parameters = command.Parameters; var sql = command.CommandText; if (sql == null) { return(EmptyList <string> .Value); } DemandStandardSettings(settings); var queries = new List <string>(); var sb = StringBuilderPool.Get(sql.Length); var lastChar = '\0'; fixed(char *sqlPtr = sql) for (var i = 0; i < sql.Length; ++i) { var chr = sqlPtr[i]; var nextChr = i == sql.Length - 1 ? '\0' : sqlPtr[i + 1]; switch (chr) { // Handle strings made with quotes, 'foo' and E'foo' case '\'': var escapedQuotes = lastChar == 'E'; sb.Append(chr); lastChar = '\0'; for (++i; i < sql.Length; ++i) { chr = sqlPtr[i]; sb.Append(chr); // Quotes (chr == '\'') can be inside a string // in several ways: // * If they're doubled up. // * If we're inside an escape string escaped // with a backslash. if (chr == '\'' && lastChar != '\'' && !(escapedQuotes && lastChar == '\\')) { goto next; } lastChar = chr; } continue; // Handle dollar strings, $$foo$$ and $bar$foo$bar$ case '$': var k = i + 1; // Syntax is "$abc$" or "$$", if "named" then "a" // must be a letter. bc+ can be letter or digit. // But "$5" is also valid syntax for parameter // access, so we must respect those. if (k >= sql.Length) { goto default; } var chrK = sqlPtr[k]; if (chrK == '$') { var indexOf = sql.IndexOf("$$", k, StringComparison.Ordinal); // Really... it's invalid syntax. if (indexOf == -1) { goto default; } // 2 is length of "$$" sb.Append(sql, i, indexOf - i + 2); i = indexOf + 1; goto next; } if (!char.IsLetter(chrK)) { goto default; } sb.Append('$'); sb.Append(chrK); for (++k; k < sql.Length; ++k) { chrK = sqlPtr[k]; sb.Append(chrK); if (chrK == '$') { break; } if (!char.IsLetterOrDigit(chrK)) { goto default; } } // +1 to account for final $. ++k; var namedStringStart = i; var matchIndex = namedStringStart; var matchedCount = 0; var matchLength = k - namedStringStart; for (i = k; i < sql.Length; ++i) { for (var m = i; m < sql.Length; ++m, ++matchIndex) { chr = sqlPtr[m]; sb.Append(chr); lastChar = chr; if (chr != sqlPtr[matchIndex]) { i = m; matchedCount = 0; matchIndex = namedStringStart; break; } if (++matchedCount == matchLength) { i = m; // Match success. goto next; } } } // If we enumerate the entire string and do not // find a match, it's technically invalid syntax // but that's the user's problem. They're better // off getting the actual error from postgres. continue; // Handle @@NotNamedParameter case '@' when nextChr == '@': // Append and fast forward past next one. sb.Append(chr); ++i; lastChar = '\0'; continue; // Handle @NamedParameter case '@': var start = i + 1; var offset = 0; for (i = start; i < sql.Length; ++i) { if (!char.IsLetterOrDigit(sqlPtr[i])) { --i; offset = 1; break; } } var name = sql.Substring(start, i - start + offset); var paramIndex = parameters.IndexOf(name); if (paramIndex == -1) { throw new ArgumentOutOfRangeException( "parameterName", name, "Parameter inside query was not found inside parameter list."); } sb.Append('$'); sb.Append(paramIndex + 1); lastChar = '\0'; continue; // Handle -- quotes. case '-' when lastChar == '-': sb.Append(chr); lastChar = '\0'; for (++i; i < sql.Length; ++i) { chr = sqlPtr[i]; sb.Append(chr); lastChar = chr; if (chr == '\n') { break; } } continue; // Handle /* */ quotes. case '*' when lastChar == '/': if (i == sql.Length - 1) { goto default; } var indexOfComment = sql.IndexOf("*/", i + 1); // Really... it's invalid syntax. if (indexOfComment == -1) { goto default; } // 2 is length of "*/" sb.Append(sql, i, indexOfComment - i + 2); i = indexOfComment + 1; continue; case ';': var singleSqlCommand = sb.ToStringTrim(); sb.Clear(); if (!string.IsNullOrWhiteSpace(singleSqlCommand)) { queries.Add(singleSqlCommand); } continue; default: sb.Append(chr); lastChar = chr; continue; } next :; } if (sb.Length > 0) { var singleSqlCommand = sb.ToStringTrim(); if (!string.IsNullOrWhiteSpace(singleSqlCommand)) { queries.Add(singleSqlCommand); } } StringBuilderPool.Free(ref sb); return(queries); }
/// <summary> /// <para>Turns a TimeSpan into a human-readable text.</para> /// <para>Uses the specified timeSpanFormatOptions.</para> /// <para>For example: "31.23:59:00.555" = "31 days 23 hours 59 minutes 0 seconds 555 milliseconds"</para> /// </summary> /// <param name="FromTime"></param> /// <param name="options"> /// <para>A combination of flags that determine the formatting options.</para> /// <para>These will be combined with the default timeSpanFormatOptions.</para> /// </param> /// <param name="timeTextInfo">An object that supplies the text to use for output</param> public static string ToTimeString(this TimeSpan FromTime, TimeSpanFormatOptions options, TimeTextInfo timeTextInfo) { // If there are any missing options, merge with the defaults: // Also, as a safeguard against missing DefaultFormatOptions, let's also merge with the AbsoluteDefaults: options = options.Merge(DefaultFormatOptions).Merge(AbsoluteDefaults); // Extract the individual options: var rangeMax = options.Mask(RangeAll).AllFlags().Last(); var rangeMin = options.Mask(RangeAll).AllFlags().First(); var truncate = options.Mask(TruncateAll).AllFlags().First(); var lessThan = options.Mask(LessThanAll) != TimeSpanFormatOptions.LessThanOff; var abbreviate = options.Mask(AbbreviateAll) != TimeSpanFormatOptions.AbbreviateOff; var round = lessThan ? (Func <double, double>)Math.Floor : Math.Ceiling; switch (rangeMin) { case TimeSpanFormatOptions.RangeWeeks: FromTime = TimeSpan.FromDays(round(FromTime.TotalDays / 7) * 7); break; case TimeSpanFormatOptions.RangeDays: FromTime = TimeSpan.FromDays(round(FromTime.TotalDays)); break; case TimeSpanFormatOptions.RangeHours: FromTime = TimeSpan.FromHours(round(FromTime.TotalHours)); break; case TimeSpanFormatOptions.RangeMinutes: FromTime = TimeSpan.FromMinutes(round(FromTime.TotalMinutes)); break; case TimeSpanFormatOptions.RangeSeconds: FromTime = TimeSpan.FromSeconds(round(FromTime.TotalSeconds)); break; case TimeSpanFormatOptions.RangeMilliSeconds: FromTime = TimeSpan.FromMilliseconds(round(FromTime.TotalMilliseconds)); break; } // Create our result: var textStarted = false; var result = StringBuilderPool.Get(); for (var i = rangeMax; i >= rangeMin; i = (TimeSpanFormatOptions)((int)i >> 1)) { // Determine the value and title: int value; switch (i) { case TimeSpanFormatOptions.RangeWeeks: value = (int)Math.Floor(FromTime.TotalDays / 7); FromTime -= TimeSpan.FromDays(value * 7); break; case TimeSpanFormatOptions.RangeDays: value = (int)Math.Floor(FromTime.TotalDays); FromTime -= TimeSpan.FromDays(value); break; case TimeSpanFormatOptions.RangeHours: value = (int)Math.Floor(FromTime.TotalHours); FromTime -= TimeSpan.FromHours(value); break; case TimeSpanFormatOptions.RangeMinutes: value = (int)Math.Floor(FromTime.TotalMinutes); FromTime -= TimeSpan.FromMinutes(value); break; case TimeSpanFormatOptions.RangeSeconds: value = (int)Math.Floor(FromTime.TotalSeconds); FromTime -= TimeSpan.FromSeconds(value); break; case TimeSpanFormatOptions.RangeMilliSeconds: value = (int)Math.Floor(FromTime.TotalMilliseconds); FromTime -= TimeSpan.FromMilliseconds(value); break; default: // This code is unreachable, but it prevents compile-errors. throw new ArgumentException("TimeSpanUtility"); } //Determine whether to display this value var displayThisValue = false; var breakFor = false; // I wish C# supported "break for;" (like how VB supports "Exit For" from within a "Select Case" statement) switch (truncate) { case TimeSpanFormatOptions.TruncateShortest: if (textStarted) { breakFor = true; break; } if (value > 0) { displayThisValue = true; } break; case TimeSpanFormatOptions.TruncateAuto: if (value > 0) { displayThisValue = true; } break; case TimeSpanFormatOptions.TruncateFill: if (textStarted || value > 0) { displayThisValue = true; } break; case TimeSpanFormatOptions.TruncateFull: displayThisValue = true; break; } if (breakFor) { break; } //we need to display SOMETHING (even if it's zero) if (i == rangeMin && textStarted == false) { displayThisValue = true; if (lessThan && value < 1) { // Output the "less than 1 unit" text: var unitTitle = timeTextInfo.GetUnitText(rangeMin, 1, abbreviate); result.Append(timeTextInfo.GetLessThanText(unitTitle)); displayThisValue = false; } } // Output the value: if (displayThisValue) { if (textStarted) { result.Append(" "); } var unitTitle = timeTextInfo.GetUnitText(i, value, abbreviate); result.Append(unitTitle); textStarted = true; } } var ret = result.ToString(); StringBuilderPool.Release(result); return(ret); }
public static Guid GetCharaGuid(this SaveData.CharaData charaData, int guidVersion = PluginDataInfo.CurrentCharaGuidVersion) { if (guidVersion > PluginDataInfo.MaxCharaGuidVersion) { throw new ArgumentOutOfRangeException(nameof(guidVersion), $"Unknown guidVersion ({guidVersion})"); } if (guidVersion < PluginDataInfo.MinimumSupportedCharaGuidVersion || charaData == null || !charaData.charFileInitialized) { return(Guid.Empty); } var guidKeyBuilder = StringBuilderPool.Get(); var intFmt = "{0:04}"; try { switch (guidVersion) { case 5: guidKeyBuilder .AppendFormat(intFmt, charaData is SaveData.Heroine heroine5 ? heroine5.FixCharaIDOrPersonality : charaData.personality) .Append('/') .AppendFormat(intFmt, charaData.schoolClass) .Append('/') .AppendFormat(intFmt, charaData.schoolClassIndex) .Append('/') .Append(charaData.Name); break; case 6: guidKeyBuilder .AppendFormat(intFmt, charaData is SaveData.Heroine heroine6 ? heroine6.FixCharaIDOrPersonality : charaData.personality) .Append('/') .AppendFormat(intFmt, charaData.schoolClass) .Append('/') .AppendFormat(intFmt, charaData.schoolClassIndex) .Append('/') .Append(charaData.firstname) .Append('/') .Append(charaData.lastname) .Append('/') .Append(charaData.parameter.sex); break; default: throw new ArgumentOutOfRangeException(nameof(guidVersion), $"Unsupported guidVersion ({guidVersion})"); } if (guidKeyBuilder.Length == 0) { return(Guid.Empty); } var guidKey = guidKeyBuilder.ToString(); var result = GuidCache.Get(guidKey); Logger?.DebugLogDebug( $"{nameof(GetCharaGuid)} (version={guidVersion}): guidKey={guidKey}, result={result}"); return(result); } finally { StringBuilderPool.Release(guidKeyBuilder); } }
private bool TryParseAffixIntoList <TEntry>(string parameterText, ref List <AffixEntryGroup.Builder <TEntry> > groups) where TEntry : AffixEntry, new() { if (groups == null) { groups = new List <AffixEntryGroup.Builder <TEntry> >(); } var lineMatch = AffixLineRegex.Match(parameterText); if (!lineMatch.Success) { Builder.LogWarning("Failed to parse affix line: " + parameterText); return(false); } var lineMatchGroups = lineMatch.Groups; FlagValue characterFlag; if (!TryParseFlag(lineMatchGroups[1].Value, out characterFlag)) { Builder.LogWarning($"Failed to parse affix flag for {lineMatchGroups[1].Value} from: {parameterText}"); return(false); } var affixGroup = groups.FindLast(g => g.AFlag == characterFlag); var contClass = FlagSet.Empty; if (lineMatchGroups[2].Success && lineMatchGroups[3].Success) { if (affixGroup != null) { Builder.LogWarning($"Duplicate affix group definition for {affixGroup.AFlag} from: {parameterText}"); return(false); } var options = AffixEntryOptions.None; if (lineMatchGroups[2].Value.StartsWith('Y')) { options |= AffixEntryOptions.CrossProduct; } if (Builder.IsAliasM) { options |= AffixEntryOptions.AliasM; } if (Builder.IsAliasF) { options |= AffixEntryOptions.AliasF; } int expectedEntryCount; IntEx.TryParseInvariant(lineMatchGroups[3].Value, out expectedEntryCount); affixGroup = new AffixEntryGroup.Builder <TEntry> { AFlag = characterFlag, Options = options, Entries = new List <TEntry>(expectedEntryCount) }; groups.Add(affixGroup); return(true); } else if (lineMatchGroups[4].Success && lineMatchGroups[5].Success && lineMatchGroups[6].Success) { // piece 3 - is string to strip or 0 for null var strip = lineMatchGroups[4].Value; if (strip == "0") { strip = string.Empty; } else if (EnumEx.HasFlag(Builder.Options, AffixConfigOptions.ComplexPrefixes)) { strip = strip.Reverse(); } // piece 4 - is affix string or 0 for null var affixInput = lineMatchGroups[5].Value; var affixSlashIndex = affixInput.IndexOf('/'); StringBuilder affixText; if (affixSlashIndex >= 0) { var slashPartOffset = affixSlashIndex + 1; var slashPartLength = affixInput.Length - slashPartOffset; affixText = StringBuilderPool.Get(affixInput, 0, affixSlashIndex); if (Builder.IsAliasF) { int aliasNumber; if (IntEx.TryParseInvariant(affixInput.Subslice(slashPartOffset, slashPartLength), out aliasNumber) && aliasNumber > 0 && aliasNumber <= Builder.AliasF.Count) { contClass = Builder.AliasF[aliasNumber - 1]; } else { Builder.LogWarning($"Failed to parse contclasses from : {parameterText}"); return(false); } } else { contClass = ParseFlags(affixInput.Subslice(slashPartOffset, slashPartLength)); } } else { affixText = StringBuilderPool.Get(affixInput); } if (Builder.IgnoredChars != null && Builder.IgnoredChars.HasItems) { affixText.RemoveChars(Builder.IgnoredChars); } if (EnumEx.HasFlag(Builder.Options, AffixConfigOptions.ComplexPrefixes)) { affixText.Reverse(); } if (affixText.Length == 1 && affixText[0] == '0') { affixText.Clear(); } // piece 5 - is the conditions descriptions var conditionText = lineMatchGroups[6].Value; if (EnumEx.HasFlag(Builder.Options, AffixConfigOptions.ComplexPrefixes)) { conditionText = ReverseCondition(conditionText); } var conditions = CharacterCondition.Parse(conditionText); if (!string.IsNullOrEmpty(strip) && !conditions.AllowsAnySingleCharacter) { bool isRedundant; if (typeof(TEntry) == typeof(PrefixEntry)) { isRedundant = RedundantConditionPrefix(strip, conditions); } else if (typeof(TEntry) == typeof(SuffixEntry)) { isRedundant = RedundantConditionSuffix(strip, conditions); } else { throw new NotSupportedException(); } if (isRedundant) { conditions = CharacterConditionGroup.AllowAnySingleCharacter; } } // piece 6 MorphSet morph; if (lineMatchGroups[7].Success) { var morphAffixText = lineMatchGroups[7].Value; if (Builder.IsAliasM) { int morphNumber; if (IntEx.TryParseInvariant(morphAffixText, out morphNumber) && morphNumber > 0 && morphNumber <= Builder.AliasM.Count) { morph = Builder.AliasM[morphNumber - 1]; } else { Builder.LogWarning($"Failed to parse morph {morphAffixText} from: {parameterText}"); return(false); } } else { if (EnumEx.HasFlag(Builder.Options, AffixConfigOptions.ComplexPrefixes)) { morphAffixText = morphAffixText.Reverse(); } morph = Builder.Dedup(MorphSet.TakeArray(Builder.DedupInPlace(morphAffixText.SplitOnTabOrSpace()))); } } else { morph = MorphSet.Empty; } if (affixGroup == null) { affixGroup = new AffixEntryGroup.Builder <TEntry> { AFlag = characterFlag, Options = AffixEntryOptions.None, Entries = new List <TEntry>() }; } if (!Builder.HasContClass && contClass.HasItems) { Builder.HasContClass = true; } affixGroup.Entries.Add(AffixEntry.Create <TEntry>( Builder.Dedup(strip), Builder.Dedup(StringBuilderPool.GetStringAndReturn(affixText)), Builder.Dedup(conditions), morph, contClass)); return(true); } else { Builder.LogWarning("Affix line not fully parsed: " + parameterText); return(false); } }
private static string ReverseCondition(string conditionText) { if (string.IsNullOrEmpty(conditionText)) { return(conditionText); } var chars = StringBuilderPool.Get(conditionText); chars.Reverse(); var neg = false; var lastIndex = chars.Length - 1; for (int k = lastIndex; k >= 0; k--) { switch (chars[k]) { case '[': if (neg) { if (k < lastIndex) { chars[k + 1] = '['; } } else { chars[k] = ']'; } break; case ']': chars[k] = '['; if (neg && k < lastIndex) { chars[k + 1] = '^'; } neg = false; break; case '^': if (k < lastIndex) { if (chars[k + 1] == ']') { neg = true; } else { chars[k + 1] = chars[k]; } } break; default: if (neg && k < lastIndex) { chars[k + 1] = chars[k]; } break; } } return(StringBuilderPool.GetStringAndReturn(chars)); }