PageRenderTime 38ms CodeModel.GetById 13ms RepoModel.GetById 0ms app.codeStats 0ms

/source/library/Interlace/PropertyLists/Writer.cs

https://bitbucket.org/VahidN/interlace
C# | 187 lines | 137 code | 23 blank | 27 comment | 25 complexity | d05721876502b5187798c52dc0b88b2e MD5 | raw file
  1. #region Using Directives and Copyright Notice
  2. // Copyright (c) 2007-2010, Computer Consultancy Pty Ltd
  3. // All rights reserved.
  4. //
  5. // Redistribution and use in source and binary forms, with or without
  6. // modification, are permitted provided that the following conditions are met:
  7. // * Redistributions of source code must retain the above copyright
  8. // notice, this list of conditions and the following disclaimer.
  9. // * Redistributions in binary form must reproduce the above copyright
  10. // notice, this list of conditions and the following disclaimer in the
  11. // documentation and/or other materials provided with the distribution.
  12. // * Neither the name of the Computer Consultancy Pty Ltd nor the
  13. // names of its contributors may be used to endorse or promote products
  14. // derived from this software without specific prior written permission.
  15. //
  16. // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
  17. // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  18. // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  19. // ARE DISCLAIMED. IN NO EVENT SHALL COMPUTER CONSULTANCY PTY LTD BE LIABLE
  20. // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  21. // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
  22. // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
  23. // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  24. // LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  25. // OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
  26. // DAMAGE.
  27. using System;
  28. using System.Collections.Generic;
  29. using System.Text;
  30. using System.Text.RegularExpressions;
  31. #endregion
  32. namespace Interlace.PropertyLists
  33. {
  34. class Writer
  35. {
  36. StringBuilder _builder = new StringBuilder();
  37. const int _indentSpaces = 4;
  38. int _currentIndentLevel = 0;
  39. bool _atLineStart = true;
  40. Regex _isPlainString = new Regex("^[A-Za-z]+$");
  41. Regex _isTrue = new Regex("^true$");
  42. Regex _isFalse = new Regex("^false$");
  43. Regex _isQuotableCharacter = new Regex("(\\n|\"|\\\\)");
  44. void EnsureIndentWritten()
  45. {
  46. if (_atLineStart)
  47. {
  48. _builder.Append("".PadLeft(_currentIndentLevel * _indentSpaces));
  49. _atLineStart = false;
  50. }
  51. }
  52. void Append(string format, params object[] args)
  53. {
  54. EnsureIndentWritten();
  55. _builder.Append(string.Format(format, args));
  56. }
  57. void AppendLine(string format, params object[] args)
  58. {
  59. EnsureIndentWritten();
  60. _builder.AppendLine(string.Format(format, args));
  61. _atLineStart = true;
  62. }
  63. void Indent()
  64. {
  65. _currentIndentLevel++;
  66. }
  67. void Dedent()
  68. {
  69. _currentIndentLevel--;
  70. }
  71. string ReplaceQuotedCharacter(Match match)
  72. {
  73. switch (match.Groups[1].Value)
  74. {
  75. case "\n":
  76. return "\\n";
  77. case "\\":
  78. return "\\\\";
  79. case "\"":
  80. return "\\\"";
  81. default:
  82. throw new InvalidOperationException();
  83. }
  84. }
  85. void WriteObject(object obj)
  86. {
  87. if (obj is string)
  88. {
  89. string str = (string)obj;
  90. // If it's not a plain string, it needs quoting. The strings "true" and "false" also
  91. // need quoting so they aren't parsed back in as booleans.
  92. if (_isPlainString.IsMatch(str) && !_isTrue.IsMatch(str) && !_isFalse.IsMatch(str))
  93. {
  94. Append((string)obj);
  95. }
  96. else
  97. {
  98. Append("\"{0}\"", _isQuotableCharacter.Replace(str, ReplaceQuotedCharacter));
  99. }
  100. }
  101. else if (obj is int || obj is byte || obj is short)
  102. {
  103. Append("{0}", Convert.ToInt32(obj));
  104. }
  105. else if (obj is double)
  106. {
  107. Append("{0}", Convert.ToDouble(obj));
  108. }
  109. else if (obj is bool)
  110. {
  111. Append("{0}", obj.ToString().ToLower());
  112. }
  113. else if (obj is PropertyDictionary)
  114. {
  115. WriteDictionary(obj as PropertyDictionary);
  116. }
  117. else if (obj is PropertyArray)
  118. {
  119. WriteArray(obj as PropertyArray);
  120. }
  121. else if (obj is DateTime)
  122. {
  123. Append("\"{0}\"", ((DateTime)obj).ToUniversalTime().ToString("s"));
  124. }
  125. else
  126. {
  127. throw new NotImplementedException(
  128. "Only strings, integers, and other property dictionaries can be persisted.");
  129. }
  130. }
  131. public void WriteArray(PropertyArray array)
  132. {
  133. AppendLine("{0}", "(");
  134. Indent();
  135. for (int i = 0; i < array.Count; i++)
  136. {
  137. WriteObject(array[i]);
  138. if (i != array.Count - 1) AppendLine(", ");
  139. }
  140. Dedent();
  141. Append("{0}", ")");
  142. }
  143. public void WriteDictionary(PropertyDictionary dictionary)
  144. {
  145. AppendLine("{0}", "{");
  146. Indent();
  147. foreach (object key in dictionary.Keys)
  148. {
  149. object value = dictionary.ValueFor(key);
  150. if (value == null) continue;
  151. WriteObject(key);
  152. Append(" = ");
  153. WriteObject(value);
  154. AppendLine(";");
  155. }
  156. Dedent();
  157. Append("{0}", "}");
  158. }
  159. public override string ToString()
  160. {
  161. return _builder.ToString();
  162. }
  163. }
  164. }