public void Create_Cache() { var sf = new SmartFormatter(); var format = FormatItemPool.GetFormat(sf.Settings, "the base string"); var fc = FormatCachePool.Get(format); Assert.AreEqual(format, fc.Format); Assert.IsAssignableFrom <Dictionary <string, object> >(fc.CachedObjects); fc.CachedObjects.Add("key", "value"); Assert.IsTrue(fc.CachedObjects["key"].ToString() == "value"); FormatCachePool.Release(fc); }
/// <summary>Returns a substring of the current Format.</summary> public Format Substring(int startIndex, int length) { startIndex = this.startIndex + startIndex; var endIndex = startIndex + length; // Validate the arguments: if (startIndex < this.startIndex || startIndex > this.endIndex) // || endIndex > this.endIndex) { throw new ArgumentOutOfRangeException("startIndex"); } if (endIndex > this.endIndex) { throw new ArgumentOutOfRangeException("length"); } // If startIndex and endIndex already match this item, we're done: if (startIndex == this.startIndex && endIndex == this.endIndex) { return(this); } var substring = FormatItemPool.GetFormat(SmartSettings, baseString, startIndex, endIndex); foreach (var item in Items) { if (item.endIndex <= startIndex) { continue; // Skip first items } if (endIndex <= item.startIndex) { break; // Done } var newItem = item; if (item is LiteralText) // See if we need to slice the LiteralText: { if (startIndex > item.startIndex || item.endIndex > endIndex) { newItem = FormatItemPool.GetLiteralText(SmartSettings, substring, Math.Max(startIndex, item.startIndex), Math.Min(endIndex, item.endIndex)); } } else { // item is a placeholder -- we can't split a placeholder though. substring.HasNested = true; } substring.Items.Add(newItem); } return(substring); }
public override bool TryEvalulateAllLiterals(IFormattingInfo formattingInfo) { var format = formattingInfo.Format; if (format == null) { return(false); } var parameters = format.Split('|', 4); if (parameters.Count < 2) { return(false); } var itemFormat = parameters[0]; // Spacer if (parameters.Count >= 1) { formattingInfo.Write(parameters[0], null); } // Last spacer if (parameters.Count >= 3) { formattingInfo.Write(parameters[2], null); } // Two spacer if (parameters.Count >= 4) { formattingInfo.Write(parameters[3], null); } if (!itemFormat.HasNested) { // The format is not nested, // so we will treat it as an itemFormat: var newItemFormat = FormatItemPool.GetFormat(m_SmartSettings, itemFormat.baseString, itemFormat.startIndex, itemFormat.endIndex, true); var newPlaceholder = FormatItemPool.GetPlaceholder(m_SmartSettings, newItemFormat, itemFormat.startIndex, 0, itemFormat, itemFormat.endIndex); newItemFormat.Items.Add(newPlaceholder); itemFormat = newItemFormat; } formattingInfo.Write(itemFormat, null); return(true); }
public override bool TryEvaluateFormat(IFormattingInfo formattingInfo) { var format = formattingInfo.Format; var current = formattingInfo.CurrentValue; // This method needs the Highest priority so that it comes before the PluralLocalizationExtension and ConditionalExtension // This extension requires at least IEnumerable if (!(current is IEnumerable enumerable)) { return(false); } // Ignore Strings, because they're IEnumerable. // This issue might actually need a solution // for other objects that are IEnumerable. if (current is string) { return(false); } // If the object is IFormattable, ignore it if (current is IFormattable) { return(false); } // This extension requires a | to specify the spacer: if (format == null) { return(false); } var parameters = format.Split('|', 4); if (parameters.Count < 2) { return(false); } // Grab all formatting options: // They must be in one of these formats: // itemFormat|spacer // itemFormat|spacer|lastSpacer // itemFormat|spacer|lastSpacer|twoSpacer var itemFormat = parameters[0]; var spacer = parameters.Count >= 2 ? parameters[1].GetLiteralText() : ""; var lastSpacer = parameters.Count >= 3 ? parameters[2].GetLiteralText() : spacer; var twoSpacer = parameters.Count >= 4 ? parameters[3].GetLiteralText() : lastSpacer; if (!itemFormat.HasNested) { // The format is not nested, // so we will treat it as an itemFormat: var newItemFormat = FormatItemPool.GetFormat(m_SmartSettings, itemFormat.baseString, itemFormat.startIndex, itemFormat.endIndex, true); var newPlaceholder = FormatItemPool.GetPlaceholder(m_SmartSettings, newItemFormat, itemFormat.startIndex, 0, itemFormat, itemFormat.endIndex); newItemFormat.Items.Add(newPlaceholder); itemFormat = newItemFormat; } // Let's buffer all items from the enumerable (to ensure the Count without double-enumeration): List <object> bufferItems = null; if (!(current is ICollection items)) { bufferItems = ListPool <object> .Get(); foreach (var item in enumerable) { bufferItems.Add(item); } items = bufferItems; } var oldCollectionIndex = CollectionIndex; // In case we have nested arrays, we might need to restore the CollectionIndex CollectionIndex = -1; foreach (var item in items) { CollectionIndex += 1; // Keep track of the index // Determine which spacer to write: if (spacer == null || CollectionIndex == 0) { // Don't write the spacer. } else if (CollectionIndex < items.Count - 1) { formattingInfo.Write(spacer); } else if (CollectionIndex == 1) { formattingInfo.Write(twoSpacer); } else { formattingInfo.Write(lastSpacer); } // Output the nested format for this item: formattingInfo.Write(itemFormat, item); } CollectionIndex = oldCollectionIndex; // Restore the CollectionIndex if (bufferItems != null) { ListPool <object> .Release(bufferItems); } return(true); }