2 Copyright (c) 2003-2006 Niels Kokholm and Peter Sestoft
3 Permission is hereby granted, free of charge, to any person obtaining a copy
4 of this software and associated documentation files (the "Software"), to deal
5 in the Software without restriction, including without limitation the rights
6 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7 copies of the Software, and to permit persons to whom the Software is
8 furnished to do so, subject to the following conditions:
10 The above copyright notice and this permission notice shall be included in
11 all copies or substantial portions of the Software.
13 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
24 using System.Reflection;
25 using System.Reflection.Emit;
26 using System.Diagnostics;
32 /// <i>(Describe usage of "L:300" format string.)</i>
34 public interface IShowable : IFormattable
36 //TODO: wonder if we should use TextWriters instead of StringBuilders?
38 /// Format <code>this</code> using at most approximately <code>rest</code> chars and
39 /// append the result, possibly truncated, to stringbuilder.
40 /// Subtract the actual number of used chars from <code>rest</code>.
42 /// <param name="stringbuilder"></param>
43 /// <param name="rest"></param>
44 /// <param name="formatProvider"></param>
45 /// <returns>True if the appended formatted string was complete (not truncated).</returns>
46 bool Show(StringBuilder stringbuilder, ref int rest, IFormatProvider formatProvider);
48 // ------------------------------------------------------------
50 // Static helper methods for Showing collections
55 public static class Showing
58 /// Show <code>Object obj</code> by appending it to <code>stringbuilder</code>
60 /// <param name="obj"></param>
61 /// <param name="stringbuilder"></param>
62 /// <param name="rest"></param>
63 /// <param name="formatProvider"></param>
64 /// <returns>True if <code>obj</code> was shown completely.</returns>
65 public static bool Show(Object obj, StringBuilder stringbuilder, ref int rest, IFormatProvider formatProvider)
70 else if ((showable = obj as IShowable) != null)
71 return showable.Show(stringbuilder, ref rest, formatProvider);
72 int oldLength = stringbuilder.Length;
73 stringbuilder.AppendFormat(formatProvider, "{0}", obj);
74 rest -= (stringbuilder.Length - oldLength);
81 /// <param name="showable"></param>
82 /// <param name="format"></param>
83 /// <param name="formatProvider"></param>
84 /// <returns></returns>
85 public static String ShowString(IShowable showable, String format, IFormatProvider formatProvider)
87 int rest = maxLength(format);
88 StringBuilder sb = new StringBuilder();
89 showable.Show(sb, ref rest, formatProvider);
96 /// <param name="format"></param>
97 /// <returns></returns>
98 static int maxLength(String format)
100 //TODO: validate format string
103 if (format.Length > 1 && format.StartsWith("L"))
105 return int.Parse(format.Substring(1));
114 /// <typeparam name="T"></typeparam>
115 /// <param name="items"></param>
116 /// <param name="stringbuilder"></param>
117 /// <param name="rest"></param>
118 /// <param name="formatProvider"></param>
119 /// <returns>True if collection was shown completely</returns>
120 public static bool ShowCollectionValue<T>(ICollectionValue<T> items, StringBuilder stringbuilder, ref int rest, IFormatProvider formatProvider)
122 string startdelim = "{ ", enddelim = " }";
123 bool showIndexes = false;
124 bool showMultiplicities = false;
125 //TODO: do not test here at run time, but select code at compile time
126 // perhaps by delivering the print type to this metod
128 ICollection<T> coll = items as ICollection<T>;
129 if ((list = items as IList<T>) != null)
133 //TODO: should have been (items as IIndexed<T>).IndexingSpeed
134 showIndexes = list.IndexingSpeed == Speed.Constant;
136 else if (coll != null)
138 if (coll.AllowsDuplicates)
142 if (coll.DuplicatesByCounting)
143 showMultiplicities = true;
147 stringbuilder.Append(startdelim);
148 rest -= 2 * startdelim.Length;
150 bool complete = true;
153 if (showMultiplicities)
155 foreach (KeyValuePair<T, int> p in coll.ItemMultiplicities())
164 stringbuilder.Append(", ");
167 if (complete = Showing.Show(p.Key, stringbuilder, ref rest, formatProvider))
169 string multiplicityString = string.Format("(*{0})", p.Value);
170 stringbuilder.Append(multiplicityString);
171 rest -= multiplicityString.Length;
177 foreach (T x in items)
186 stringbuilder.Append(", ");
191 string indexString = string.Format("{0}:", index++);
192 stringbuilder.Append(indexString);
193 rest -= indexString.Length;
195 complete = Showing.Show(x, stringbuilder, ref rest, formatProvider);
200 stringbuilder.Append("...");
203 stringbuilder.Append(enddelim);
210 /// <typeparam name="K"></typeparam>
211 /// <typeparam name="V"></typeparam>
213 /// <param name="dictionary"></param>
214 /// <param name="stringbuilder"></param>
215 /// <param name="formatProvider"></param>
216 /// <param name="rest"></param>
217 /// <returns></returns>
218 public static bool ShowDictionary<K, V>(IDictionary<K, V> dictionary, StringBuilder stringbuilder, ref int rest, IFormatProvider formatProvider)
220 bool sorted = dictionary is ISortedDictionary<K, V>;
221 stringbuilder.Append(sorted ? "[ " : "{ ");
222 rest -= 4; // Account for "( " and " )"
224 bool complete = true;
226 foreach (KeyValuePair<K, V> p in dictionary)
235 stringbuilder.Append(", ");
238 complete = Showing.Show(p, stringbuilder, ref rest, formatProvider);
242 stringbuilder.Append("...");
245 stringbuilder.Append(sorted ? " ]" : " }");