Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

470 lines
12 KiB

  1. /*****************************************************************************
  2. * *
  3. * BTKEY.C *
  4. * *
  5. * Copyright (C) Microsoft Corporation 1989 - 1994. *
  6. * All Rights reserved. *
  7. * *
  8. ******************************************************************************
  9. * *
  10. * Module Intent *
  11. * *
  12. * Functions to deal with (i.e. size, compare) keys of all types. *
  13. * *
  14. ******************************************************************************
  15. * *
  16. * Current Owner: BinhN *
  17. * *
  18. *****************************************************************************/
  19. /*****************************************************************************
  20. *
  21. * Revision History: Created 05/11/89 by JohnSc
  22. *
  23. * 08/21/90 JohnSc autodocified
  24. * 3/05/97 erinfox Change errors to HRESULTS
  25. *
  26. *****************************************************************************/
  27. static char s_aszModule[] = __FILE__; /* For error report */
  28. #include <mvopsys.h>
  29. #include <orkin.h>
  30. #include <iterror.h>
  31. #include <string.h>
  32. #include <misc.h>
  33. #include <wrapstor.h>
  34. #include <mvdbcs.h>
  35. #include <mvsearch.h>
  36. #include "common.h"
  37. #include <_mvutil.h>
  38. // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
  39. // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
  40. // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
  41. // When ligature tables are implemented again, take this out !!!!!!!!!!
  42. //#define NOCHARTABLES_FIXME
  43. // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
  44. // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
  45. // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
  46. /*****************************************************************************
  47. * *
  48. * Macros *
  49. * *
  50. *****************************************************************************/
  51. #define StCopy(st1, st2) (ST)QVCOPY((st1), (st2), (LONG)*(st2))
  52. #define CbLenSt(st) ((WORD)*(st))
  53. /***************************************************************************
  54. *
  55. * @doc INTERNAL
  56. *
  57. * @func SHORT PASCAL FAR | WCmpKey |
  58. * Compare two keys.
  59. *
  60. * @parm KEY | key1 |
  61. * the UNCOMPRESSED keys to compare
  62. *
  63. * @parm KEY | key2 |
  64. * the UNCOMPRESSED keys to compare
  65. *
  66. * @parm QBTHR | qbthr |
  67. * qbthr->bth.rgchFormat[0] - key type
  68. * [qbthr->??? - other info ???]
  69. *
  70. * @rdesc -1 if key1 < key2; 0 if key1 == key2; 1 if key1 > key2
  71. * args OUT: [if comparing compressed keys, change state in qbthr->???]
  72. *
  73. * @comm Might be best to have this routine assume keys are expanded
  74. * and do something else to compare keys in the scan routines.
  75. * We're assuming fixed length keys are SZs. Alternative
  76. * would be to use a memcmp() function.
  77. *
  78. ***************************************************************************/
  79. PUBLIC SHORT PASCAL FAR WCmpKey(KEY key1, KEY key2, QBTHR qbthr)
  80. {
  81. SHORT w;
  82. LONG l;
  83. KT kt = (KT)qbthr->bth.rgchFormat[ 0 ];
  84. LONG l1, l2;
  85. switch (kt) {
  86. #ifdef FULL_BTREE // {
  87. case KT_VSTI:
  88. {
  89. SZ sz1, sz2;
  90. WORD wl1,wl2;
  91. BYTE far *qbLigatures = NULL;
  92. wl1=(WORD)FoFromSz((SZ)key1).dwOffset;
  93. sz1 = (SZ)key1;
  94. ADVANCE_FO(sz1);
  95. key1 = (KEY)sz1;
  96. wl2=(WORD)FoFromSz((SZ)key2).dwOffset;
  97. sz2 = (SZ)key2;
  98. ADVANCE_FO(sz2);
  99. key2 = (KEY)sz2;
  100. if (qbthr->lrglpCharTab)
  101. qbLigatures=(BYTE FAR *)((LPCHARTAB)*qbthr->lrglpCharTab)->lpLigature;
  102. w=WCmpiSnn((SZ)key1, (SZ)key2, qbLigatures , wl1, wl2);
  103. break;
  104. }
  105. case KT_SZDEL: // assume keys have been expanded for delta codeds
  106. case KT_SZDELMIN:
  107. case KT_SZ:
  108. case KT_SZMIN:
  109. case '1': case '2': case '3': case '4': case '5': // assume null term
  110. case '6': case '7': case '8': case '9': case 'a':
  111. case 'b': case 'c': case 'd': case 'e': case 'f':
  112. w = STRCMP((char *)key1, (char *)key2);
  113. break;
  114. case KT_SZI:
  115. w = WCmpiSz((SZ)key1, (SZ)key2,
  116. (BYTE FAR *)((LPCHARTAB)*qbthr->lrglpCharTab)->lpLigature);
  117. break;
  118. case KT_SZISCAND:
  119. w = WCmpiScandSz((SZ)key1, (SZ)key2);
  120. break;
  121. case KT_SZMAP:
  122. #ifdef NOCHARTABLES_FIXME
  123. w=STRCMP((SZ)key1, (SZ)key2);
  124. #else
  125. if (PRIMARYLANGID(LANGIDFROMLCID(qbthr->bth.lcid)) == LANG_JAPANESE)
  126. w = StringJCompare (0L, (SZ)key1, STRLEN((char *)key1),
  127. (SZ)key2, STRLEN((char *)key2));
  128. else
  129. w = StrFntMappedLigatureComp((SZ)key1, (SZ)key2,
  130. qbthr->lrglpCharTab);
  131. #endif
  132. break;
  133. #endif // }
  134. case KT_EXTSORT:
  135. if (qbthr->pITSortKey == NULL ||
  136. FAILED(qbthr->pITSortKey->Compare((LPCVOID) key1,
  137. (LPCVOID) key2,
  138. &l, NULL)))
  139. {
  140. l = 0;
  141. ITASSERT(FALSE);
  142. }
  143. // Reduce the long -/0/+ result to a word -/0/+.
  144. w = (SHORT) ((LOWORD(l) & 0x7fff) | ((LOWORD(l) >> 1) & 0x7fff) | HIWORD(l));
  145. break;
  146. #ifdef FULL_BTREE // {
  147. case KT_ST:
  148. case KT_STMIN:
  149. case KT_STDEL:
  150. case KT_STDELMIN:
  151. w = WCmpSt((ST)key1, (ST)key2);
  152. break;
  153. #endif // }
  154. case KT_LONG:
  155. l1 = *(LONG FAR *)key1;
  156. l2 = *(LONG FAR *)key2;
  157. if (l1 < l2)
  158. w = -1;
  159. else if (l2 < l1)
  160. w = 1;
  161. else
  162. w = 0;
  163. break;
  164. }
  165. return w;
  166. }
  167. /***************************************************************************
  168. *
  169. * @doc INTERNAL
  170. *
  171. * @func SHORT PASCAL FAR | CbSizeKey |
  172. * Return the key size (compressed or un-) in bytes
  173. *
  174. * @parm KEY | key
  175. * @parm QBTHR | qbthr
  176. * @parm BOOL | fCompressed |
  177. * TRUE to get the compressed size,
  178. * FALSE to get the uncompressed size.
  179. *
  180. * @rdesc size of the key in bytes
  181. *
  182. * @comm It's impossible to tell how much suffix was discarded for
  183. * the KT_*MIN key types.
  184. *
  185. ***************************************************************************/
  186. PUBLIC SHORT PASCAL CbSizeKey(KEY key, QBTHR qbthr, BOOL fCompressed)
  187. {
  188. SHORT cb;
  189. DWORD dwKeySize;
  190. KT kt = (KT)qbthr->bth.rgchFormat[ 0 ];
  191. switch(kt) {
  192. #ifdef FULL_BTREE // {
  193. case KT_SZ:
  194. case KT_SZMIN:
  195. case KT_SZI:
  196. case KT_SZISCAND:
  197. case KT_SZMAP:
  198. cb = STRLEN((char *)key) + 1;
  199. break;
  200. case KT_VSTI:
  201. cb = (SHORT)LenSzFo((LPBYTE)key) + (SHORT)FoFromSz((LPBYTE)key).dwOffset;
  202. break;
  203. case KT_SZDEL:
  204. case KT_SZDELMIN:
  205. if (fCompressed)
  206. cb = 1 + STRLEN((char *)key + 1) + 1;
  207. else
  208. cb = *(QB)key + STRLEN((char *)key + 1) + 1;
  209. break;
  210. case KT_ST:
  211. case KT_STMIN:
  212. case KT_STI:
  213. cb = CbLenSt((ST)key) + 1/* ? */;
  214. break;
  215. case KT_STDEL:
  216. case KT_STDELMIN:
  217. if (fCompressed)
  218. cb = 1 + CbLenSt((ST)key + 1);
  219. else
  220. cb = *(QB)key + CbLenSt((ST)key + 1) + 1;
  221. break;
  222. #endif // }
  223. case KT_EXTSORT:
  224. if (qbthr->pITSortKey == NULL ||
  225. FAILED(qbthr->pITSortKey->GetSize((LPCVOID) key, &dwKeySize)))
  226. {
  227. dwKeySize = 0;
  228. ITASSERT(FALSE);
  229. }
  230. // Key size can't exceed 32K - 1. Such a key never should have been
  231. // allowed in to begin with. We'll assert for the debug version.
  232. // We'll use 32K - 1 for the size for now, but there's a pretty
  233. // good chance a GP fault will occur if the sort object
  234. // ever has to visit parts of the key at 32K and beyond!
  235. if (dwKeySize <= 0x7fff)
  236. cb = (SHORT) dwKeySize;
  237. else
  238. {
  239. cb = 0x7fff;
  240. ITASSERT(FALSE);
  241. }
  242. break;
  243. case KT_LONG:
  244. cb = sizeof(LONG);
  245. break;
  246. case '1': case '2': case '3': case '4': case '5':
  247. case '6': case '7': case '8': case '9':
  248. cb = kt - '0';
  249. break;
  250. case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':
  251. cb = kt - 'a' + 10;
  252. break;
  253. }
  254. return cb;
  255. }
  256. /***************************************************************************
  257. *
  258. * @doc INTERNAL
  259. *
  260. * @func BOOL FAR PASCAL | FIsPrefix |
  261. * Determines whether string key1 is a prefix of key2.
  262. *
  263. * @parm HBT | hbt |
  264. * handle to a btree with string keys
  265. *
  266. * @parm KEY | key1 |
  267. * Uncompressed key
  268. *
  269. * @parm KEY | key2 |
  270. * Uncompressed key
  271. *
  272. * @rdesc TRUE if the string key1 is a prefix of the string key2
  273. * FALSE if it isn't or if hbt doesn't contain string keys
  274. *
  275. * @comm Bugs: Doesn't work on STs yet
  276. *
  277. * Method: temporarily shortens the second string so it can
  278. * compare prefixes
  279. *
  280. ***************************************************************************/
  281. PUBLIC BOOL FAR PASCAL FIsPrefix(HBT hbt, KEY key1, KEY key2)
  282. {
  283. QBTHR qbthr;
  284. KT kt;
  285. BOOL f;
  286. ERRB errb;
  287. HRESULT hr;
  288. #ifdef FULL_BTREE
  289. SHORT cb1, cb2;
  290. unsigned char c;
  291. #endif
  292. if ((qbthr = (QBTHR) _GLOBALLOCK(hbt)) == NULL)
  293. {
  294. SetErrCode (&errb, E_INVALIDARG);
  295. return(FALSE);
  296. }
  297. assert(qbthr != NULL);
  298. kt = (KT)qbthr->bth.rgchFormat[ 0 ];
  299. switch(kt) {
  300. #ifdef FULL_BTREE // {
  301. case KT_SZ:
  302. case KT_SZMIN:
  303. case KT_SZI:
  304. case KT_SZISCAND:
  305. case KT_SZDEL:
  306. case KT_SZDELMIN:
  307. case KT_SZMAP:
  308. /* both keys assumed to have been decompressed */
  309. cb1 = STRLEN((char *)key1);
  310. cb2 = STRLEN((char *)key2);
  311. break;
  312. case KT_ST:
  313. case KT_STMIN:
  314. case KT_STI:
  315. case KT_STDEL:
  316. case KT_STDELMIN:
  317. /* STs unimplemented */
  318. SetErrCode (&errb, E_NOTSUPPORTED);
  319. _GLOBALUNLOCK(hbt);
  320. return FALSE;
  321. break;
  322. #endif // }
  323. case KT_EXTSORT:
  324. if (qbthr->pITSortKey == NULL ||
  325. FAILED(hr = qbthr->pITSortKey->IsRelated((LPCVOID) key1,
  326. (LPCVOID) key2,
  327. (DWORD) IITSK_KEYRELATION_PREFIX, NULL)))
  328. {
  329. ITASSERT(FALSE);
  330. f = FALSE;
  331. }
  332. else
  333. f = (GetScode(hr) == S_OK);
  334. _GLOBALUNLOCK(hbt);
  335. return (f);
  336. break;
  337. case KT_LONG:
  338. case '1': case '2': case '3': case '4': case '5':
  339. case '6': case '7': case '8': case '9':
  340. case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':
  341. default:
  342. /* prefix doesn't make sense */
  343. SetErrCode (&errb, E_NOTSUPPORTED);
  344. _GLOBALUNLOCK(hbt);
  345. return FALSE;
  346. break;
  347. }
  348. #ifdef FULL_BTREE // {
  349. // The length check and truncation method works as long as
  350. // ligatures aren't involved. We won't worry about this for
  351. // IT 4.0 because the CharTab KTs won't be used.
  352. if (cb1 > cb2) {
  353. _GLOBALUNLOCK(hbt);
  354. return FALSE;
  355. }
  356. // Truncate longer string (key2).
  357. c = ((SZ)key2)[ cb1 ];
  358. ((SZ)key2)[ cb1 ] = '\0';
  359. switch (kt)
  360. {
  361. case KT_SZ:
  362. case KT_SZMIN:
  363. case KT_SZDEL:
  364. case KT_SZDELMIN:
  365. f = STRCMP((char *)key1, (char *)key2) <=0;
  366. break;
  367. case KT_SZI:
  368. f = WCmpiSz((SZ)key1, (SZ)key2,
  369. (BYTE FAR *) (*((LPCHARTAB FAR *)qbthr->lrglpCharTab))->lpLigature) <= 0;
  370. break;
  371. case KT_SZISCAND:
  372. f = WCmpiScandSz((SZ)key1, (SZ)key2) <= 0;
  373. break;
  374. case KT_SZMAP:
  375. #ifdef NOCHARTABLES_FIXME
  376. f=(STRCMP((SZ)key1, (SZ)key2) <= 0);
  377. #else
  378. if (PRIMARYLANGID(LANGIDFROMLCID(qbthr->bth.lcid)) == LANG_JAPANESE)
  379. f = (StringJCompare (0L, (SZ)key1, STRLEN((char *)key1),
  380. (SZ)key2, STRLEN((char *)key2)) <= 0);
  381. else
  382. f = (StrFntMappedLigatureComp((SZ)key1,
  383. (SZ)key2, qbthr->lrglpCharTab) <= 0);
  384. #endif
  385. break;
  386. default:
  387. assert(FALSE);
  388. break;
  389. }
  390. // Restore the longer string.
  391. ((SZ)key2)[ cb1 ] = c;
  392. _GLOBALUNLOCK(hbt);
  393. return f;
  394. #endif // }
  395. }
  396. /* EOF */