PageRenderTime 45ms CodeModel.GetById 20ms RepoModel.GetById 0ms app.codeStats 0ms

/src/sys/dotnet/fan/sys/Range.cs

https://bitbucket.org/bedlaczech/fan-1.0
C# | 284 lines | 226 code | 36 blank | 22 comment | 55 complexity | 96af8288c8a77b23c8158af236331f6e MD5 | raw file
Possible License(s): CC-BY-SA-3.0
  1. //
  2. // Copyright (c) 2006, Brian Frank and Andy Frank
  3. // Licensed under the Academic Free License version 3.0
  4. //
  5. // History:
  6. // 29 Jan 07 Andy Frank Creation
  7. //
  8. using System;
  9. using System.Globalization;
  10. namespace Fan.Sys
  11. {
  12. /// <summary>
  13. /// Range.
  14. /// </summary>
  15. public sealed class Range : FanObj
  16. {
  17. //////////////////////////////////////////////////////////////////////////
  18. // Constructors
  19. //////////////////////////////////////////////////////////////////////////
  20. public static Range makeInclusive(long start, long end)
  21. {
  22. return new Range(start, end, false);
  23. }
  24. public static Range makeExclusive(long start, long end)
  25. {
  26. return new Range(start, end, true);
  27. }
  28. public static Range make(long start, long end, bool exclusive)
  29. {
  30. return new Range(start, end, exclusive);
  31. }
  32. public static Range fromStr(string s) { return fromStr(s, true); }
  33. public static Range fromStr(string s, bool check)
  34. {
  35. try
  36. {
  37. int dot = s.IndexOf('.');
  38. if (s[dot+1] != '.') throw new Exception();
  39. bool exclusive = s[dot+2] == '<';
  40. long start = Convert.ToInt64(s.Substring(0, dot));
  41. long end = Convert.ToInt64(s.Substring(dot + (exclusive?3:2)));
  42. return new Range(start, end, exclusive);
  43. }
  44. catch (Exception) {}
  45. if (!check) return null;
  46. throw ParseErr.make("Range", s).val;
  47. }
  48. private Range(long start, long end, bool exclusive)
  49. {
  50. this.m_start = start;
  51. this.m_end = end;
  52. this.m_exclusive = exclusive;
  53. }
  54. //////////////////////////////////////////////////////////////////////////
  55. // Range
  56. //////////////////////////////////////////////////////////////////////////
  57. public long start()
  58. {
  59. return m_start;
  60. }
  61. public long end()
  62. {
  63. return m_end;
  64. }
  65. public bool inclusive()
  66. {
  67. return !m_exclusive;
  68. }
  69. public bool exclusive()
  70. {
  71. return m_exclusive;
  72. }
  73. public bool isEmpty()
  74. {
  75. return m_exclusive && m_start == m_end;
  76. }
  77. public Long min()
  78. {
  79. if (isEmpty()) return null;
  80. if (m_end < m_start) return Long.valueOf(m_exclusive ? m_end+1 : m_end);
  81. return Long.valueOf(m_start);
  82. }
  83. public Long max()
  84. {
  85. if (isEmpty()) return null;
  86. if (m_end < m_start) return Long.valueOf(m_start);
  87. return Long.valueOf(m_exclusive ? m_end-1 : m_end);
  88. }
  89. public Long first()
  90. {
  91. if (isEmpty()) return null;
  92. return Long.valueOf(m_start);
  93. }
  94. public Long last()
  95. {
  96. if (isEmpty()) return null;
  97. if (!m_exclusive) return Long.valueOf(m_end);
  98. if (m_start < m_end) return Long.valueOf(m_end-1);
  99. return Long.valueOf(m_end+1);
  100. }
  101. public Range offset(long offset)
  102. {
  103. if (offset == 0) return this;
  104. return new Range(m_start+offset, m_end+offset, m_exclusive);
  105. }
  106. public bool contains(long i)
  107. {
  108. if (m_start < m_end)
  109. {
  110. if (m_exclusive)
  111. return m_start <= i && i < m_end;
  112. else
  113. return m_start <= i && i <= m_end;
  114. }
  115. else
  116. {
  117. if (m_exclusive)
  118. return m_end < i && i <= m_start;
  119. else
  120. return m_end <= i && i <= m_start;
  121. }
  122. }
  123. public void each(Func f)
  124. {
  125. long start = m_start;
  126. long end = m_end;
  127. if (start < end)
  128. {
  129. if (m_exclusive) --end;
  130. for (long i=start; i<=end; ++i) f.call(i);
  131. }
  132. else
  133. {
  134. if (m_exclusive) ++end;
  135. for (long i=start; i>=end; --i) f.call(i);
  136. }
  137. }
  138. public List map(Func f)
  139. {
  140. long start = m_start;
  141. long end = m_end;
  142. Type r = f.returns();
  143. if (r == Sys.VoidType) r = Sys.ObjType.toNullable();
  144. List acc = new List(r);
  145. if (start < end)
  146. {
  147. if (m_exclusive) --end;
  148. for (long i=start; i<=end; ++i) acc.add(f.call(i));
  149. }
  150. else
  151. {
  152. if (m_exclusive) ++end;
  153. for (long i=start; i>=end; --i) acc.add(f.call(i));
  154. }
  155. return acc;
  156. }
  157. public List toList()
  158. {
  159. int start = (int)m_start;
  160. int end = (int)m_end;
  161. List acc = new List(Sys.IntType);
  162. if (start < end)
  163. {
  164. if (m_exclusive) --end;
  165. acc.capacity(end-start+1);
  166. for (int i=start; i<=end; ++i)
  167. acc.add(Long.valueOf(i));
  168. }
  169. else
  170. {
  171. if (m_exclusive) ++end;
  172. acc.capacity(start-end+1);
  173. for (int i=start; i>=end; --i)
  174. acc.add(Long.valueOf(i));
  175. }
  176. return acc;
  177. }
  178. public long random()
  179. {
  180. return FanInt.random(this);
  181. }
  182. public override bool Equals(object obj)
  183. {
  184. if (obj is Range)
  185. {
  186. Range that = (Range)obj;
  187. return this.m_start == that.m_start &&
  188. this.m_end == that.m_end &&
  189. this.m_exclusive == that.m_exclusive;
  190. }
  191. return false;
  192. }
  193. public override int GetHashCode()
  194. {
  195. return m_start.GetHashCode() ^ m_end.GetHashCode();
  196. }
  197. public override long hash()
  198. {
  199. return m_start ^ m_end;
  200. }
  201. public override string toStr()
  202. {
  203. if (m_exclusive)
  204. return m_start.ToString() + "..<" + m_end.ToString();
  205. else
  206. return m_start.ToString() + ".." + m_end.ToString();
  207. }
  208. public override Type @typeof() { return Sys.RangeType; }
  209. //////////////////////////////////////////////////////////////////////////
  210. // Slice Utils
  211. //////////////////////////////////////////////////////////////////////////
  212. internal int start(int size)
  213. {
  214. int x = (int)m_start;
  215. if (x < 0) x = size + x;
  216. if (x > size) throw IndexErr.make(this).val;
  217. return x;
  218. }
  219. internal long start(long size)
  220. {
  221. long x = m_start;
  222. if (x < 0) x = size + x;
  223. if (x > size) throw IndexErr.make(this).val;
  224. return x;
  225. }
  226. internal int end(int size)
  227. {
  228. int x = (int)m_end;
  229. if (x < 0) x = size + x;
  230. if (m_exclusive) x--;
  231. if (x >= size) throw IndexErr.make(this).val;
  232. return x;
  233. }
  234. internal long end(long size)
  235. {
  236. long x = m_end;
  237. if (x < 0) x = size + x;
  238. if (m_exclusive) x--;
  239. if (x >= size) throw IndexErr.make(this).val;
  240. return x;
  241. }
  242. //////////////////////////////////////////////////////////////////////////
  243. // Fields
  244. //////////////////////////////////////////////////////////////////////////
  245. private long m_start, m_end;
  246. private bool m_exclusive;
  247. }
  248. }