BsonRegularExpression.cs 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340
  1. /* Copyright 2010-2014 MongoDB Inc.
  2. *
  3. * Licensed under the Apache License, Version 2.0 (the "License");
  4. * you may not use this file except in compliance with the License.
  5. * You may obtain a copy of the License at
  6. *
  7. * http://www.apache.org/licenses/LICENSE-2.0
  8. *
  9. * Unless required by applicable law or agreed to in writing, software
  10. * distributed under the License is distributed on an "AS IS" BASIS,
  11. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. * See the License for the specific language governing permissions and
  13. * limitations under the License.
  14. */
  15. using System;
  16. using System.Text.RegularExpressions;
  17. namespace MongoDB.Bson
  18. {
  19. /// <summary>
  20. /// Represents a BSON regular expression value.
  21. /// </summary>
  22. [Serializable]
  23. public class BsonRegularExpression : BsonValue, IComparable<BsonRegularExpression>, IEquatable<BsonRegularExpression>
  24. {
  25. // private fields
  26. private string _pattern;
  27. private string _options;
  28. // constructors
  29. /// <summary>
  30. /// Initializes a new instance of the BsonRegularExpression class.
  31. /// </summary>
  32. /// <param name="pattern">A regular expression pattern.</param>
  33. public BsonRegularExpression(string pattern)
  34. : base(BsonType.RegularExpression)
  35. {
  36. if (pattern == null)
  37. {
  38. throw new ArgumentNullException("pattern");
  39. }
  40. if (pattern.Length > 0 && pattern[0] == '/')
  41. {
  42. var index = pattern.LastIndexOf('/');
  43. var escaped = pattern.Substring(1, index - 1);
  44. var unescaped = (escaped == "(?:)") ? "" : escaped.Replace("\\/", "/");
  45. _pattern = unescaped;
  46. _options = pattern.Substring(index + 1);
  47. }
  48. else
  49. {
  50. _pattern = pattern;
  51. _options = "";
  52. }
  53. }
  54. /// <summary>
  55. /// Initializes a new instance of the BsonRegularExpression class.
  56. /// </summary>
  57. /// <param name="pattern">A regular expression pattern.</param>
  58. /// <param name="options">Regular expression options.</param>
  59. public BsonRegularExpression(string pattern, string options)
  60. : base(BsonType.RegularExpression)
  61. {
  62. if (pattern == null)
  63. {
  64. throw new ArgumentNullException("pattern");
  65. }
  66. _pattern = pattern;
  67. _options = options ?? "";
  68. }
  69. /// <summary>
  70. /// Initializes a new instance of the BsonRegularExpression class.
  71. /// </summary>
  72. /// <param name="regex">A Regex.</param>
  73. public BsonRegularExpression(Regex regex)
  74. : base(BsonType.RegularExpression)
  75. {
  76. if (regex == null)
  77. {
  78. throw new ArgumentNullException("regex");
  79. }
  80. _pattern = regex.ToString();
  81. _options = "";
  82. if ((regex.Options & RegexOptions.IgnoreCase) != 0)
  83. {
  84. _options += "i";
  85. }
  86. if ((regex.Options & RegexOptions.Multiline) != 0)
  87. {
  88. _options += "m";
  89. }
  90. if ((regex.Options & RegexOptions.IgnorePatternWhitespace) != 0)
  91. {
  92. _options += "x";
  93. }
  94. if ((regex.Options & RegexOptions.Singleline) != 0)
  95. {
  96. _options += "s";
  97. }
  98. }
  99. // public properties
  100. /// <summary>
  101. /// Gets the regular expression pattern.
  102. /// </summary>
  103. public string Pattern
  104. {
  105. get { return _pattern; }
  106. }
  107. /// <summary>
  108. /// Gets the regular expression options.
  109. /// </summary>
  110. public string Options
  111. {
  112. get { return _options; }
  113. }
  114. // public operators
  115. /// <summary>
  116. /// Converts a Regex to a BsonRegularExpression.
  117. /// </summary>
  118. /// <param name="value">A Regex.</param>
  119. /// <returns>A BsonRegularExpression.</returns>
  120. public static implicit operator BsonRegularExpression(Regex value)
  121. {
  122. return new BsonRegularExpression(value);
  123. }
  124. /// <summary>
  125. /// Converts a string to a BsonRegularExpression.
  126. /// </summary>
  127. /// <param name="value">A string.</param>
  128. /// <returns>A BsonRegularExpression.</returns>
  129. public static implicit operator BsonRegularExpression(string value)
  130. {
  131. return new BsonRegularExpression(value);
  132. }
  133. /// <summary>
  134. /// Compares two BsonRegularExpression values.
  135. /// </summary>
  136. /// <param name="lhs">The first BsonRegularExpression.</param>
  137. /// <param name="rhs">The other BsonRegularExpression.</param>
  138. /// <returns>True if the two BsonRegularExpression values are not equal according to ==.</returns>
  139. public static bool operator !=(BsonRegularExpression lhs, BsonRegularExpression rhs)
  140. {
  141. return !(lhs == rhs);
  142. }
  143. /// <summary>
  144. /// Compares two BsonRegularExpression values.
  145. /// </summary>
  146. /// <param name="lhs">The first BsonRegularExpression.</param>
  147. /// <param name="rhs">The other BsonRegularExpression.</param>
  148. /// <returns>True if the two BsonRegularExpression values are equal according to ==.</returns>
  149. public static bool operator ==(BsonRegularExpression lhs, BsonRegularExpression rhs)
  150. {
  151. if (object.ReferenceEquals(lhs, null)) { return object.ReferenceEquals(rhs, null); }
  152. return lhs.Equals(rhs);
  153. }
  154. // public methods
  155. /// <summary>
  156. /// Creates a new BsonRegularExpression.
  157. /// </summary>
  158. /// <param name="value">An object to be mapped to a BsonRegularExpression.</param>
  159. /// <returns>A BsonRegularExpression or null.</returns>
  160. public new static BsonRegularExpression Create(object value)
  161. {
  162. if (value != null)
  163. {
  164. return (BsonRegularExpression)BsonTypeMapper.MapToBsonValue(value, BsonType.RegularExpression);
  165. }
  166. else
  167. {
  168. return null;
  169. }
  170. }
  171. /// <summary>
  172. /// Creates a new instance of the BsonRegularExpression class.
  173. /// </summary>
  174. /// <param name="regex">A Regex.</param>
  175. /// <returns>A BsonRegularExpression.</returns>
  176. [Obsolete("Use new BsonRegularExpression(Regex regex) instead.")]
  177. public static BsonRegularExpression Create(Regex regex)
  178. {
  179. if (regex != null)
  180. {
  181. return new BsonRegularExpression(regex);
  182. }
  183. else
  184. {
  185. return null;
  186. }
  187. }
  188. /// <summary>
  189. /// Creates a new instance of the BsonRegularExpression class.
  190. /// </summary>
  191. /// <param name="pattern">A regular expression pattern.</param>
  192. /// <returns>A BsonRegularExpression.</returns>
  193. [Obsolete("Use new BsonRegularExpression(string pattern) instead.")]
  194. public static BsonRegularExpression Create(string pattern)
  195. {
  196. if (pattern != null)
  197. {
  198. return new BsonRegularExpression(pattern);
  199. }
  200. else
  201. {
  202. return null;
  203. }
  204. }
  205. /// <summary>
  206. /// Creates a new instance of the BsonRegularExpression class.
  207. /// </summary>
  208. /// <param name="pattern">A regular expression pattern.</param>
  209. /// <param name="options">Regular expression options.</param>
  210. /// <returns>A BsonRegularExpression.</returns>
  211. [Obsolete("Use new BsonRegularExpression(string pattern, string options) instead.")]
  212. public static BsonRegularExpression Create(string pattern, string options)
  213. {
  214. if (pattern != null)
  215. {
  216. return new BsonRegularExpression(pattern, options);
  217. }
  218. else
  219. {
  220. return null;
  221. }
  222. }
  223. // public methods
  224. /// <summary>
  225. /// Compares this BsonRegularExpression to another BsonRegularExpression.
  226. /// </summary>
  227. /// <param name="other">The other BsonRegularExpression.</param>
  228. /// <returns>A 32-bit signed integer that indicates whether this BsonRegularExpression is less than, equal to, or greather than the other.</returns>
  229. public int CompareTo(BsonRegularExpression other)
  230. {
  231. if (other == null) { return 1; }
  232. int r = _pattern.CompareTo(other._pattern);
  233. if (r != 0) { return r; }
  234. return _options.CompareTo(other._options);
  235. }
  236. /// <summary>
  237. /// Compares the BsonRegularExpression to another BsonValue.
  238. /// </summary>
  239. /// <param name="other">The other BsonValue.</param>
  240. /// <returns>A 32-bit signed integer that indicates whether this BsonRegularExpression is less than, equal to, or greather than the other BsonValue.</returns>
  241. public override int CompareTo(BsonValue other)
  242. {
  243. if (other == null) { return 1; }
  244. var otherRegularExpression = other as BsonRegularExpression;
  245. if (otherRegularExpression != null)
  246. {
  247. return _options.CompareTo(otherRegularExpression);
  248. }
  249. return CompareTypeTo(other);
  250. }
  251. /// <summary>
  252. /// Compares this BsonRegularExpression to another BsonRegularExpression.
  253. /// </summary>
  254. /// <param name="rhs">The other BsonRegularExpression.</param>
  255. /// <returns>True if the two BsonRegularExpression values are equal.</returns>
  256. public bool Equals(BsonRegularExpression rhs)
  257. {
  258. if (object.ReferenceEquals(rhs, null) || GetType() != rhs.GetType()) { return false; }
  259. return _pattern == rhs._pattern && _options == rhs._options;
  260. }
  261. /// <summary>
  262. /// Compares this BsonRegularExpression to another object.
  263. /// </summary>
  264. /// <param name="obj">The other object.</param>
  265. /// <returns>True if the other object is a BsonRegularExpression and equal to this one.</returns>
  266. public override bool Equals(object obj)
  267. {
  268. return Equals(obj as BsonRegularExpression); // works even if obj is null or of a different type
  269. }
  270. /// <summary>
  271. /// Gets the hash code.
  272. /// </summary>
  273. /// <returns>The hash code.</returns>
  274. public override int GetHashCode()
  275. {
  276. // see Effective Java by Joshua Bloch
  277. int hash = 17;
  278. hash = 37 * hash + BsonType.GetHashCode();
  279. hash = 37 * hash + _pattern.GetHashCode();
  280. hash = 37 * hash + _options.GetHashCode();
  281. return hash;
  282. }
  283. /// <summary>
  284. /// Converts the BsonRegularExpression to a Regex.
  285. /// </summary>
  286. /// <returns>A Regex.</returns>
  287. public Regex ToRegex()
  288. {
  289. var options = RegexOptions.None;
  290. if (_options.IndexOf('i') != -1)
  291. {
  292. options |= RegexOptions.IgnoreCase;
  293. }
  294. if (_options.IndexOf('m') != -1)
  295. {
  296. options |= RegexOptions.Multiline;
  297. }
  298. if (_options.IndexOf('x') != -1)
  299. {
  300. options |= RegexOptions.IgnorePatternWhitespace;
  301. }
  302. if (_options.IndexOf('s') != -1)
  303. {
  304. options |= RegexOptions.Singleline;
  305. }
  306. return new Regex(_pattern, options);
  307. }
  308. /// <summary>
  309. /// Returns a string representation of the value.
  310. /// </summary>
  311. /// <returns>A string representation of the value.</returns>
  312. public override string ToString()
  313. {
  314. var escaped = (_pattern == "") ? "(?:)" :_pattern.Replace("/", @"\/");
  315. return string.Format("/{0}/{1}", escaped, _options);
  316. }
  317. }
  318. }