MT5APISearch.h 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403
  1. //+------------------------------------------------------------------+
  2. //| MetaTrader 5 API |
  3. //| Copyright 2000-2019, MetaQuotes Software Corp. |
  4. //| http://www.metaquotes.net |
  5. //+------------------------------------------------------------------+
  6. #pragma once
  7. //+------------------------------------------------------------------+
  8. //| Search functions |
  9. //+------------------------------------------------------------------+
  10. class SMTSearch
  11. {
  12. public:
  13. typedef int (__cdecl *SortFunctionPtr)(const void *, const void *);
  14. public:
  15. //--- insert
  16. static char* Insert(void *base,const void *elem,size_t total,const size_t width,SortFunctionPtr compare);
  17. //--- quick sort
  18. template <class T>
  19. static void QuickSort(T *base,UINT num,SortFunctionPtr compare);
  20. //---
  21. static void* Search(const void *key,void *base,size_t total,const size_t width,SortFunctionPtr compare);
  22. static void* SearchGreatOrEq(const void *key,void *base,size_t total,const size_t width,SortFunctionPtr compare);
  23. static void* SearchGreater(const void *key,void *base,size_t total,const size_t width,SortFunctionPtr compare);
  24. static void* SearchLessOrEq(const void *key,void *base,size_t total,const size_t width,SortFunctionPtr compare);
  25. static void* SearchLess(const void *key,void *base,size_t total,const size_t width,SortFunctionPtr compare);
  26. static void* SearchLeft(const void *key,void *base,size_t total,const size_t width,SortFunctionPtr compare);
  27. static void* SearchRight(const void *key,void *base,size_t total,const size_t width,SortFunctionPtr compare);
  28. private:
  29. template <class T>
  30. static void ShortSort (T *lo,T *hi,SortFunctionPtr compare);
  31. template <class T>
  32. static void Swap(T *a,T *b);
  33. };
  34. //+------------------------------------------------------------------+
  35. //| Returns 0 if record already exist |
  36. //| Returns inserted record otherwise |
  37. //| Array should contain enough free space for new element |
  38. //+------------------------------------------------------------------+
  39. inline char* SMTSearch::Insert(void *base,const void *elem,size_t total,const size_t width,SortFunctionPtr compare)
  40. {
  41. //--- check
  42. if(base==NULL || elem==NULL || compare==NULL) return(NULL);
  43. //--- first element?
  44. if(total<1) { memcpy(base,elem,width); return(char*)(base); }
  45. //--- initialize
  46. char *lo=(char *)base;
  47. char *hi=(char *)base+(total-1)*width,*end=hi;
  48. char *mid;
  49. size_t half;
  50. int result;
  51. //---
  52. while(total>0)
  53. {
  54. half=total/2;
  55. mid =lo+half*width;
  56. //--- compare
  57. if((result=compare(elem,mid))>0) // data[mid]<elem
  58. {
  59. lo =mid+width;
  60. total=total-half-1;
  61. }
  62. else
  63. if(result<0) // data[mid]>elem
  64. {
  65. total=half;
  66. }
  67. else
  68. {
  69. // data[mid]==elem
  70. return(NULL);
  71. }
  72. }
  73. //--- insert new
  74. memmove(lo+width,lo,end-lo+width);
  75. memcpy(lo,elem,width);
  76. //---
  77. return(lo);
  78. }
  79. //+------------------------------------------------------------------+
  80. //| Fast sort |
  81. //+------------------------------------------------------------------+
  82. template<class T>
  83. inline void SMTSearch::ShortSort (T *lo,T *hi,SortFunctionPtr compare)
  84. {
  85. T *p, *maxval;
  86. //--- Note: in assertions below, i and j are alway inside original bound of
  87. //--- array to sort.
  88. //--- While
  89. while(hi > lo)
  90. {
  91. maxval=lo;
  92. for(p=lo+1; p<=hi; p+=1)
  93. if (compare(p, maxval) > 0)
  94. { maxval=p; }
  95. //---
  96. Swap(maxval,hi);
  97. hi-=1;
  98. }
  99. }
  100. //+------------------------------------------------------------------+
  101. //| Swap two records |
  102. //+------------------------------------------------------------------+
  103. template<class T>
  104. inline void SMTSearch::Swap(T *a,T *b)
  105. {
  106. T c(*a);
  107. *a=*b;
  108. *b=c;
  109. }
  110. //+------------------------------------------------------------------+
  111. //| Quick sort from CRT |
  112. //+------------------------------------------------------------------+
  113. template<class T>
  114. inline void SMTSearch::QuickSort(T *base,UINT num,SortFunctionPtr compare)
  115. {
  116. T *lo, *hi; /* ends of sub-array currently sorting */
  117. T *mid; /* points to middle of subarray */
  118. T *loguy, *higuy; /* traveling pointers for partition step */
  119. size_t size; /* size of the sub-array */
  120. T *lostk[30], *histk[30];
  121. int stkptr; /* stack for saving sub-array to be processed */
  122. //---
  123. if (num < 2) return;
  124. stkptr=0; /* initialize stack */
  125. lo=base;
  126. hi=base + (num-1); /* initialize limits */
  127. //---
  128. recurse:
  129. //---
  130. size=(hi - lo) + 1; /* number of el's to sort */
  131. //---
  132. if (size<=8) ShortSort(lo,hi,compare);
  133. else
  134. {
  135. mid=lo + (size/2); /* find middle element */
  136. Swap(mid,lo); /* swap it to beginning of array */
  137. //---
  138. loguy=lo;
  139. higuy=hi + 1;
  140. //---
  141. for(;;)
  142. {
  143. //---
  144. do
  145. {
  146. loguy+=1;
  147. }
  148. while(loguy<=hi && compare(loguy, lo)<=0);
  149. //---
  150. do
  151. {
  152. higuy-=1;
  153. }
  154. while(higuy > lo && compare(higuy, lo)>=0);
  155. //---
  156. if(higuy<loguy) break;
  157. //---
  158. Swap(loguy, higuy);
  159. }
  160. //---
  161. Swap(lo, higuy); /* put partition element in place */
  162. //---
  163. if(higuy-1-lo>=hi-loguy)
  164. {
  165. if(lo + 1 < higuy)
  166. {
  167. lostk[stkptr]=lo;
  168. histk[stkptr]=higuy - 1;
  169. ++stkptr;
  170. }
  171. if(loguy < hi)
  172. {
  173. lo=loguy;
  174. goto recurse; /* do small recursion */
  175. }
  176. }
  177. else
  178. {
  179. if (loguy < hi)
  180. {
  181. lostk[stkptr]=loguy;
  182. histk[stkptr]=hi;
  183. ++stkptr; /* save big recursion for later */
  184. }
  185. if(lo + 1 < higuy)
  186. {
  187. hi=higuy - 1;
  188. goto recurse; /* do small recursion */
  189. }
  190. }
  191. }
  192. //---
  193. --stkptr;
  194. if(stkptr>=0)
  195. {
  196. lo=lostk[stkptr];
  197. hi=histk[stkptr];
  198. goto recurse; /* pop subarray from stack */
  199. }
  200. //---
  201. return; /* all subarrays done */
  202. }
  203. //+------------------------------------------------------------------+
  204. //| Binary search (from CRT) |
  205. //+------------------------------------------------------------------+
  206. inline void* SMTSearch::Search(const void *key,void *base,size_t num,const size_t width,SortFunctionPtr compare)
  207. {
  208. char *lo=(char *)base;
  209. char *hi=(char *)base + (num - 1) * width;
  210. char *mid;
  211. size_t half;
  212. int result;
  213. //--- validation section
  214. if(base==NULL || num<1 || width<=0 || compare==NULL) return(NULL);
  215. //--- We allow a NULL key here because it breaks some older code and because we do not dereference
  216. //--- this ourselves so we can't be sure that it's a problem for the comparison function
  217. while(lo<=hi)
  218. {
  219. if((half=num/2)!=0)
  220. {
  221. mid=lo + (num & 1 ? half : (half - 1)) * width;
  222. if((result=(*compare)(key, mid))==0)
  223. return(mid);
  224. else
  225. if (result < 0)
  226. {
  227. hi=mid - width;
  228. num=num & 1 ? half : half-1;
  229. }
  230. else
  231. {
  232. lo=mid + width;
  233. num=half;
  234. }
  235. }
  236. else
  237. if(num)
  238. return((*compare)(key, lo) ? NULL : lo);
  239. else
  240. break;
  241. }
  242. //---
  243. return(NULL);
  244. }
  245. //+------------------------------------------------------------------+
  246. //| Search great or equal key |
  247. //+------------------------------------------------------------------+
  248. inline void* SMTSearch::SearchGreatOrEq(const void *key,void *base,size_t total,const size_t width,SortFunctionPtr compare)
  249. {
  250. //--- check
  251. if(key==NULL || base==NULL || total<1 || compare==NULL) return(NULL);
  252. //---
  253. char *lo=(char *)base;
  254. char *end=(char *)base+total*width;
  255. char *mid;
  256. size_t half;
  257. //---
  258. while(total>0)
  259. {
  260. half=total/2;
  261. mid =lo+half*width;
  262. //--- compare
  263. if(compare(key,mid)>0) // key>data[mid]
  264. {
  265. lo =mid+width;
  266. total=total-half-1;
  267. }
  268. else total=half;
  269. }
  270. //--- is exist?
  271. return(lo==end)?(NULL):(lo);
  272. }
  273. //+------------------------------------------------------------------+
  274. //| Search great than key |
  275. //+------------------------------------------------------------------+
  276. inline void* SMTSearch::SearchGreater(const void *key,void *base,size_t total,const size_t width,SortFunctionPtr compare)
  277. {
  278. //--- check
  279. if(key==NULL || base==NULL || total<1 || compare==NULL) return(NULL);
  280. //---
  281. char *lo=(char *)base;
  282. char *end=(char *)base+total*width;
  283. char *mid;
  284. size_t half;
  285. //---
  286. while(total>0)
  287. {
  288. half=total/2;
  289. mid =lo+half*width;
  290. //--- compare
  291. if(compare(key,mid)>=0) // key>=data[mid]
  292. {
  293. lo =mid+width;
  294. total=total-half-1;
  295. }
  296. else total=half;
  297. }
  298. //--- is exist?
  299. return(lo==end)?(NULL):(lo);
  300. }
  301. //+------------------------------------------------------------------+
  302. //| Search less or equal key |
  303. //+------------------------------------------------------------------+
  304. inline void* SMTSearch::SearchLessOrEq(const void *key,void *base,size_t total,const size_t width,SortFunctionPtr compare)
  305. {
  306. //--- check
  307. if(key==NULL || base==NULL || total<1 || compare==NULL) return(NULL);
  308. //---
  309. char *lo=(char *)base;
  310. char *beg=(char *)base;
  311. char *mid;
  312. size_t half;
  313. //---
  314. while(total>0)
  315. {
  316. half=total/2;
  317. mid =lo+half*width;
  318. //--- compare
  319. if(compare(key,mid)>=0) // key>=data[mid]
  320. {
  321. lo =mid+width;
  322. total=total-half-1;
  323. }
  324. else total=half;
  325. }
  326. //--- is exist?
  327. return(lo==beg)?(NULL):(lo-width);
  328. }
  329. //+------------------------------------------------------------------+
  330. //| Search less than key |
  331. //+------------------------------------------------------------------+
  332. inline void* SMTSearch::SearchLess(const void *key,void *base,size_t total,const size_t width,SortFunctionPtr compare)
  333. {
  334. //--- check
  335. if(key==NULL || base==NULL || total<1 || compare==NULL) return(NULL);
  336. //---
  337. char *lo=(char *)base;
  338. char *beg=(char *)base;
  339. char *mid;
  340. size_t half;
  341. //---
  342. while(total>0)
  343. {
  344. half=total/2;
  345. mid =lo+half*width;
  346. //--- compare
  347. if(compare(key,mid)>0) // key>data[mid]
  348. {
  349. lo =mid+width;
  350. total=total-half-1;
  351. }
  352. else total=half;
  353. }
  354. //--- is exist?
  355. return(lo==beg)?(NULL):(lo-width);
  356. }
  357. //+------------------------------------------------------------------+
  358. //| Search first equal key |
  359. //+------------------------------------------------------------------+
  360. inline void* SMTSearch::SearchLeft(const void *key,void *base,size_t total,const size_t width,SortFunctionPtr compare)
  361. {
  362. //--- check
  363. if(key==NULL || base==NULL || total<1 || compare==NULL) return(NULL);
  364. //--- search left
  365. char* start=(char*)SearchLess(key,base,total,width,compare);
  366. //---
  367. if(start!=NULL)
  368. {
  369. //--- go to next
  370. start+=width;
  371. //--- check array borders
  372. if(start>=((char*)base+total*width)) return(NULL);
  373. }
  374. else start=(char*)base;
  375. //--- is equal?
  376. if(!compare(key,start)) return(start);
  377. //--- not found
  378. return(NULL);
  379. }
  380. //+------------------------------------------------------------------+
  381. //| Search last equal key |
  382. //+------------------------------------------------------------------+
  383. inline void* SMTSearch::SearchRight(const void *key,void *base,size_t total,const size_t width,SortFunctionPtr compare)
  384. {
  385. //--- check
  386. if(key==NULL || base==NULL || total<1 || compare==NULL) return(NULL);
  387. //--- search right
  388. char* end=(char*)SearchGreater(key,base,total,width,compare);
  389. //---
  390. if(end!=NULL)
  391. {
  392. //--- go to previous
  393. end-=width;
  394. //--- check array borders
  395. if(end<(char*)base) return(NULL);
  396. }
  397. else end=(char*)base+(total-1)*width;
  398. //--- is equal?
  399. if(!compare(key,end)) return(end);
  400. //--- not found
  401. return(NULL);
  402. }
  403. //+------------------------------------------------------------------+