QueryValue.cs 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556
  1. //------------------------------------------------------------
  2. // Copyright (c) Microsoft Corporation. All rights reserved.
  3. //------------------------------------------------------------
  4. namespace System.ServiceModel.Dispatcher
  5. {
  6. using System.Runtime;
  7. enum ValueDataType : byte
  8. {
  9. None = 0,
  10. Boolean,
  11. Double,
  12. StackFrame,
  13. Sequence,
  14. String
  15. }
  16. // Value is like Variant. Since a Value is only temporary storage, we use memory to avoid typecasting type
  17. // casting, which in C# is expensive. Value contains storage for every possible XPath data type.
  18. // We avoid data copying by being smart about how we pass Value around - values are either accessed via
  19. // method calls, or the value object itself is passed by ref
  20. //
  21. // The filter engine never deals with a single value per se. We only work with Sets of Values. A single value
  22. // is a ValueSet of size 1
  23. //
  24. internal struct Value
  25. {
  26. bool boolVal;
  27. double dblVal;
  28. StackFrame frame;
  29. NodeSequence sequence;
  30. string strVal;
  31. ValueDataType type;
  32. internal bool Boolean
  33. {
  34. get
  35. {
  36. return this.boolVal;
  37. }
  38. set
  39. {
  40. this.type = ValueDataType.Boolean;
  41. this.boolVal = value;
  42. }
  43. }
  44. internal double Double
  45. {
  46. get
  47. {
  48. return this.dblVal;
  49. }
  50. set
  51. {
  52. this.type = ValueDataType.Double;
  53. this.dblVal = value;
  54. }
  55. }
  56. internal StackFrame Frame
  57. {
  58. get
  59. {
  60. return this.frame;
  61. }
  62. #if NO
  63. set
  64. {
  65. this.type = ValueDataType.StackFrame;
  66. this.frame = value;
  67. }
  68. #endif
  69. }
  70. #if NO
  71. internal int FrameCount
  72. {
  73. get
  74. {
  75. return this.frame.Count;
  76. }
  77. }
  78. #endif
  79. internal int FrameEndPtr
  80. {
  81. #if NO
  82. get
  83. {
  84. return this.frame.endPtr;
  85. }
  86. #endif
  87. set
  88. {
  89. Fx.Assert(this.IsType(ValueDataType.StackFrame), "");
  90. this.frame.EndPtr = value;
  91. }
  92. }
  93. #if NO
  94. internal int FrameBasePtr
  95. {
  96. get
  97. {
  98. return this.frame.basePtr;
  99. }
  100. }
  101. internal int StackPtr
  102. {
  103. get
  104. {
  105. return this.frame.basePtr - 1;
  106. }
  107. }
  108. #endif
  109. internal int NodeCount
  110. {
  111. get
  112. {
  113. return this.sequence.Count;
  114. }
  115. }
  116. internal NodeSequence Sequence
  117. {
  118. get
  119. {
  120. return this.sequence;
  121. }
  122. set
  123. {
  124. this.type = ValueDataType.Sequence;
  125. this.sequence = value;
  126. }
  127. }
  128. internal string String
  129. {
  130. get
  131. {
  132. return this.strVal;
  133. }
  134. set
  135. {
  136. this.type = ValueDataType.String;
  137. this.strVal = value;
  138. }
  139. }
  140. internal ValueDataType Type
  141. {
  142. get
  143. {
  144. return this.type;
  145. }
  146. }
  147. internal void Add(double val)
  148. {
  149. Fx.Assert(ValueDataType.Double == this.type, "");
  150. this.dblVal += val;
  151. }
  152. #if NO
  153. internal void Clear()
  154. {
  155. this.type = ValueDataType.None;
  156. this.sequence = null;
  157. }
  158. #endif
  159. internal void Clear(ProcessingContext context)
  160. {
  161. if (ValueDataType.Sequence == this.type)
  162. {
  163. this.ReleaseSequence(context);
  164. }
  165. this.type = ValueDataType.None;
  166. }
  167. // Fully general compare
  168. internal bool CompareTo(ref Value val, RelationOperator op)
  169. {
  170. switch (this.type)
  171. {
  172. default:
  173. throw DiagnosticUtility.ExceptionUtility.ThrowHelperCritical(new QueryProcessingException(QueryProcessingError.TypeMismatch));
  174. case ValueDataType.Boolean:
  175. switch (val.type)
  176. {
  177. default:
  178. throw DiagnosticUtility.ExceptionUtility.ThrowHelperCritical(new QueryProcessingException(QueryProcessingError.TypeMismatch));
  179. case ValueDataType.Boolean:
  180. return QueryValueModel.Compare(this.boolVal, val.boolVal, op);
  181. case ValueDataType.Double:
  182. return QueryValueModel.Compare(this.boolVal, val.dblVal, op);
  183. case ValueDataType.Sequence:
  184. return QueryValueModel.Compare(this.boolVal, val.sequence, op);
  185. case ValueDataType.String:
  186. return QueryValueModel.Compare(this.boolVal, val.strVal, op);
  187. }
  188. case ValueDataType.Double:
  189. switch (val.type)
  190. {
  191. default:
  192. throw DiagnosticUtility.ExceptionUtility.ThrowHelperCritical(new QueryProcessingException(QueryProcessingError.TypeMismatch));
  193. case ValueDataType.Boolean:
  194. return QueryValueModel.Compare(this.dblVal, val.boolVal, op);
  195. case ValueDataType.Double:
  196. return QueryValueModel.Compare(this.dblVal, val.dblVal, op);
  197. case ValueDataType.Sequence:
  198. return QueryValueModel.Compare(this.dblVal, val.sequence, op);
  199. case ValueDataType.String:
  200. return QueryValueModel.Compare(this.dblVal, val.strVal, op);
  201. }
  202. case ValueDataType.Sequence:
  203. switch (val.type)
  204. {
  205. default:
  206. throw DiagnosticUtility.ExceptionUtility.ThrowHelperCritical(new QueryProcessingException(QueryProcessingError.TypeMismatch));
  207. case ValueDataType.Boolean:
  208. return QueryValueModel.Compare(this.sequence, val.boolVal, op);
  209. case ValueDataType.Double:
  210. return QueryValueModel.Compare(this.sequence, val.dblVal, op);
  211. case ValueDataType.Sequence:
  212. return QueryValueModel.Compare(this.sequence, val.sequence, op);
  213. case ValueDataType.String:
  214. return QueryValueModel.Compare(this.sequence, val.strVal, op);
  215. }
  216. case ValueDataType.String:
  217. switch (val.type)
  218. {
  219. default:
  220. throw DiagnosticUtility.ExceptionUtility.ThrowHelperCritical(new QueryProcessingException(QueryProcessingError.TypeMismatch));
  221. case ValueDataType.Boolean:
  222. return QueryValueModel.Compare(this.strVal, val.boolVal, op);
  223. case ValueDataType.Double:
  224. return QueryValueModel.Compare(this.strVal, val.dblVal, op);
  225. case ValueDataType.Sequence:
  226. return QueryValueModel.Compare(this.strVal, val.sequence, op);
  227. case ValueDataType.String:
  228. return QueryValueModel.Compare(this.strVal, val.strVal, op);
  229. }
  230. }
  231. }
  232. internal bool CompareTo(double val, RelationOperator op)
  233. {
  234. switch (this.type)
  235. {
  236. default:
  237. throw DiagnosticUtility.ExceptionUtility.ThrowHelperCritical(new QueryProcessingException(QueryProcessingError.TypeMismatch));
  238. case ValueDataType.Boolean:
  239. return QueryValueModel.Compare(this.boolVal, val, op);
  240. case ValueDataType.Double:
  241. return QueryValueModel.Compare(this.dblVal, val, op);
  242. case ValueDataType.Sequence:
  243. return QueryValueModel.Compare(this.sequence, val, op);
  244. case ValueDataType.String:
  245. return QueryValueModel.Compare(this.strVal, val, op);
  246. }
  247. }
  248. internal void ConvertTo(ProcessingContext context, ValueDataType newType)
  249. {
  250. Fx.Assert(null != context, "");
  251. if (newType == this.type)
  252. {
  253. return;
  254. }
  255. switch (newType)
  256. {
  257. default:
  258. break;
  259. case ValueDataType.Boolean:
  260. this.boolVal = this.ToBoolean();
  261. break;
  262. case ValueDataType.Double:
  263. this.dblVal = this.ToDouble();
  264. break;
  265. case ValueDataType.String:
  266. this.strVal = this.ToString();
  267. break;
  268. }
  269. if (ValueDataType.Sequence == this.type)
  270. {
  271. this.ReleaseSequence(context);
  272. }
  273. this.type = newType;
  274. }
  275. internal bool Equals(string val)
  276. {
  277. switch (this.type)
  278. {
  279. default:
  280. Fx.Assert("Invalid Type");
  281. return false;
  282. case ValueDataType.Boolean:
  283. return QueryValueModel.Equals(this.boolVal, val);
  284. case ValueDataType.Double:
  285. return QueryValueModel.Equals(this.dblVal, val);
  286. case ValueDataType.Sequence:
  287. return QueryValueModel.Equals(this.sequence, val);
  288. case ValueDataType.String:
  289. return QueryValueModel.Equals(this.strVal, val);
  290. }
  291. }
  292. internal bool Equals(double val)
  293. {
  294. switch (this.type)
  295. {
  296. default:
  297. Fx.Assert("Invalid Type");
  298. return false;
  299. case ValueDataType.Boolean:
  300. return QueryValueModel.Equals(this.boolVal, val);
  301. case ValueDataType.Double:
  302. return QueryValueModel.Equals(this.dblVal, val);
  303. case ValueDataType.Sequence:
  304. return QueryValueModel.Equals(this.sequence, val);
  305. case ValueDataType.String:
  306. return QueryValueModel.Equals(val, this.strVal);
  307. }
  308. }
  309. #if NO
  310. internal bool Equals(bool val)
  311. {
  312. switch (this.type)
  313. {
  314. default:
  315. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new QueryProcessingException(QueryProcessingError.TypeMismatch), TraceEventType.Critical);
  316. case ValueDataType.Boolean:
  317. return QueryValueModel.Equals(this.boolVal, val);
  318. case ValueDataType.Double:
  319. return QueryValueModel.Equals(this.dblVal, val);
  320. case ValueDataType.Sequence:
  321. return QueryValueModel.Equals(this.sequence, val);
  322. case ValueDataType.String:
  323. return QueryValueModel.Equals(this.strVal, val);
  324. }
  325. }
  326. #endif
  327. internal bool GetBoolean()
  328. {
  329. if (ValueDataType.Boolean != this.type)
  330. {
  331. throw DiagnosticUtility.ExceptionUtility.ThrowHelperCritical(new QueryProcessingException(QueryProcessingError.TypeMismatch));
  332. }
  333. return this.boolVal;
  334. }
  335. internal double GetDouble()
  336. {
  337. if (ValueDataType.Double != this.type)
  338. {
  339. throw DiagnosticUtility.ExceptionUtility.ThrowHelperCritical(new QueryProcessingException(QueryProcessingError.TypeMismatch));
  340. }
  341. return this.dblVal;
  342. }
  343. internal NodeSequence GetSequence()
  344. {
  345. if (ValueDataType.Sequence != this.type)
  346. {
  347. throw DiagnosticUtility.ExceptionUtility.ThrowHelperCritical(new QueryProcessingException(QueryProcessingError.TypeMismatch));
  348. }
  349. return this.sequence;
  350. }
  351. internal string GetString()
  352. {
  353. if (ValueDataType.String != this.type)
  354. {
  355. throw DiagnosticUtility.ExceptionUtility.ThrowHelperCritical(new QueryProcessingException(QueryProcessingError.TypeMismatch));
  356. }
  357. return this.strVal;
  358. }
  359. internal bool IsType(ValueDataType type)
  360. {
  361. return (type == this.type);
  362. }
  363. internal void Multiply(double val)
  364. {
  365. Fx.Assert(ValueDataType.Double == this.type, "");
  366. this.dblVal *= val;
  367. }
  368. internal void Negate()
  369. {
  370. Fx.Assert(this.type == ValueDataType.Double, "");
  371. this.dblVal = -this.dblVal;
  372. }
  373. internal void Not()
  374. {
  375. Fx.Assert(this.type == ValueDataType.Boolean, "");
  376. this.boolVal = !this.boolVal;
  377. }
  378. internal void ReleaseSequence(ProcessingContext context)
  379. {
  380. Fx.Assert(null != context && this.type == ValueDataType.Sequence && null != this.sequence, "");
  381. context.ReleaseSequence(this.sequence);
  382. this.sequence = null;
  383. }
  384. internal void StartFrame(int start)
  385. {
  386. this.type = ValueDataType.StackFrame;
  387. this.frame.basePtr = start + 1;
  388. this.frame.endPtr = start;
  389. }
  390. #if NO
  391. internal void Subtract(double dblVal)
  392. {
  393. Fx.Assert(ValueDataType.Double == this.type, "");
  394. this.dblVal -= dblVal;
  395. }
  396. #endif
  397. internal bool ToBoolean()
  398. {
  399. switch (this.type)
  400. {
  401. default:
  402. throw DiagnosticUtility.ExceptionUtility.ThrowHelperCritical(new QueryProcessingException(QueryProcessingError.TypeMismatch));
  403. case ValueDataType.Boolean:
  404. return this.boolVal;
  405. case ValueDataType.Double:
  406. return QueryValueModel.Boolean(this.dblVal);
  407. case ValueDataType.Sequence:
  408. return QueryValueModel.Boolean(this.sequence);
  409. case ValueDataType.String:
  410. return QueryValueModel.Boolean(this.strVal);
  411. }
  412. }
  413. internal double ToDouble()
  414. {
  415. switch (this.type)
  416. {
  417. default:
  418. throw DiagnosticUtility.ExceptionUtility.ThrowHelperCritical(new QueryProcessingException(QueryProcessingError.TypeMismatch));
  419. case ValueDataType.Boolean:
  420. return QueryValueModel.Double(this.boolVal);
  421. case ValueDataType.Double:
  422. return this.dblVal;
  423. case ValueDataType.Sequence:
  424. return QueryValueModel.Double(this.sequence);
  425. case ValueDataType.String:
  426. return QueryValueModel.Double(this.strVal);
  427. }
  428. }
  429. public override string ToString()
  430. {
  431. switch (this.type)
  432. {
  433. default:
  434. throw DiagnosticUtility.ExceptionUtility.ThrowHelperCritical(new QueryProcessingException(QueryProcessingError.TypeMismatch));
  435. case ValueDataType.Boolean:
  436. return QueryValueModel.String(this.boolVal);
  437. case ValueDataType.Double:
  438. return QueryValueModel.String(this.dblVal);
  439. case ValueDataType.Sequence:
  440. return QueryValueModel.String(this.sequence);
  441. case ValueDataType.String:
  442. return this.strVal;
  443. }
  444. }
  445. internal void Update(ProcessingContext context, bool val)
  446. {
  447. if (ValueDataType.Sequence == this.type)
  448. {
  449. context.ReleaseSequence(this.sequence);
  450. }
  451. this.Boolean = val;
  452. }
  453. internal void Update(ProcessingContext context, double val)
  454. {
  455. if (ValueDataType.Sequence == this.type)
  456. {
  457. context.ReleaseSequence(this.sequence);
  458. }
  459. this.Double = val;
  460. }
  461. internal void Update(ProcessingContext context, string val)
  462. {
  463. if (ValueDataType.Sequence == this.type)
  464. {
  465. context.ReleaseSequence(this.sequence);
  466. }
  467. this.String = val;
  468. }
  469. internal void Update(ProcessingContext context, NodeSequence val)
  470. {
  471. if (ValueDataType.Sequence == this.type)
  472. {
  473. context.ReleaseSequence(this.sequence);
  474. }
  475. this.Sequence = val;
  476. }
  477. }
  478. }