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.

1167 lines
30 KiB

  1. //+---------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1991 - 2000.
  5. //
  6. // File: Key.hxx
  7. //
  8. // Contents: Normalized key class
  9. //
  10. // Classes: CKey, CKeyBuf
  11. //
  12. // History: 29-Mar-91 BartoszM Created
  13. //
  14. // Notes: Key comparison is tricky. The global Compare function
  15. // is the basis for key sorting. Searching may involve
  16. // wildcard pidAll.
  17. //
  18. //----------------------------------------------------------------------------
  19. #pragma once
  20. #include <sstream.hxx>
  21. #include <streams.hxx>
  22. #include <bitoff.hxx>
  23. // size of key prefix in bytes (STRING_KEY and VALUE_KEY)
  24. const unsigned cbKeyPrefix = 1;
  25. // maximum size of key (in bytes)
  26. const unsigned MAXKEYSIZE = 128 + cbKeyPrefix;
  27. const BYTE MAX_BYTE = 0xff;
  28. // maximum size of key (in WCHARs)
  29. const unsigned cwcMaxKey = (MAXKEYSIZE - cbKeyPrefix)/sizeof(WCHAR);
  30. const BYTE STRING_KEY = 0;
  31. const BYTE VALUE_KEY = 1;
  32. //+---------------------------------------------------------------------------
  33. //
  34. // Class: CKey
  35. //
  36. // Purpose: Content index key. Used in data structures holding
  37. // potentially large numbers of keys.
  38. //
  39. // History: 29-Mar-91 BartoszM Created
  40. // 27-Oct-27 DwightKr Added Type() method
  41. //
  42. //----------------------------------------------------------------------------
  43. class CKey
  44. {
  45. friend class CKeyBuf;
  46. public:
  47. CKey () : cb(0), buf(0) {}
  48. inline CKey ( const CKeyBuf& keyBuf );
  49. inline CKey ( const CKey& key );
  50. CKey ( CStream & stream ) { Init( stream ); }
  51. inline ~CKey();
  52. void Init() {
  53. cb = 0;
  54. buf = 0;
  55. }
  56. inline void Init( CStream & stream );
  57. void Free()
  58. {
  59. delete buf;
  60. buf = 0;
  61. }
  62. inline void operator= ( const CKey& key );
  63. inline void operator= ( const CKeyBuf& keybuf );
  64. BOOL IsMinKey() const { return 0 == cb && pidAll == pid; }
  65. inline int Compare ( const CKey& key ) const;
  66. inline int Compare ( const CKeyBuf& key ) const;
  67. inline int CompareStr ( const CKeyBuf & key) const;
  68. inline int CompareStr ( const CKey & key) const;
  69. inline BOOL IsExactMatch ( const CKey& key ) const;
  70. BYTE const* GetBuf() const { return buf; }
  71. unsigned Count() const { return cb; }
  72. PROPID Pid() const { return pid; }
  73. void SetPid( PROPID newpid ) { pid = newpid; }
  74. BOOL MatchPid ( const CKeyBuf& key ) const;
  75. inline void FillMax ();
  76. inline void FillMax ( const CKey& key );
  77. inline void FillMin ();
  78. inline void Serialize( CStream & stream ) const;
  79. inline BOOL IsValue() const { return ( *buf != STRING_KEY ); }
  80. inline BYTE Type() const { return *buf; }
  81. inline void Acquire(CKey & key) {
  82. Win4Assert(0 == buf);
  83. cb = key.cb;
  84. buf = key.buf;
  85. pid = key.pid;
  86. key.buf = 0;
  87. key.cb = 0;
  88. key.pid = 0;
  89. }
  90. //
  91. // Serialization
  92. //
  93. inline void Marshall( PSerStream & stm ) const;
  94. inline CKey( PDeSerStream & stm );
  95. WCHAR* GetStr() const;
  96. unsigned StrLen() const;
  97. #ifdef CIEXTMODE
  98. void CiExtDump(void *ciExtSelf);
  99. #endif
  100. private:
  101. unsigned cb;
  102. BYTE* buf;
  103. PROPID pid;
  104. };
  105. //+---------------------------------------------------------------------------
  106. //
  107. // Class: CKeyBuf
  108. //
  109. // Purpose: Content index key buffer. Used for holding key data.
  110. // It has a large fixed size buffer. Use sparingly.
  111. //
  112. // History: 29-Mar-91 BartoszM Created
  113. // 27-Oct-27 DwightKr Added Type() method
  114. //
  115. //----------------------------------------------------------------------------
  116. class CKeyBuf
  117. {
  118. public:
  119. inline CKeyBuf( PROPID pid, BYTE const * pb, unsigned cb );
  120. inline CKeyBuf() : cb(0)
  121. #if CIDBG == 1
  122. , pid(0)
  123. #endif // CIDBG == 1
  124. {}
  125. #if 0 // STACKSTACK
  126. inline CKeyBuf(const CKey& key);
  127. #endif
  128. inline void operator=(const CKeyBuf & key);
  129. inline void operator=(const CKey & key);
  130. inline void FillMax();
  131. inline void FillMin();
  132. inline BOOL IsMaxKey() const;
  133. inline BOOL IsMinKey() const;
  134. inline int CompareStr ( const CKeyBuf & key) const;
  135. inline int CompareStr ( const CKey & key) const;
  136. inline int Compare ( const CKeyBuf& key ) const;
  137. inline int Compare ( const CKey& key ) const;
  138. inline BOOL IsPossibleRW();
  139. BYTE const* GetBuf() const { return (BYTE *)buf; }
  140. BYTE * GetWritableBuf() { return (BYTE *)buf; }
  141. unsigned Count() const { return cb; }
  142. unsigned * GetWritableCount() { return &cb; }
  143. PROPID Pid() const { return pid; }
  144. void SetCount(unsigned i) {cb = i;}
  145. void SetPid ( PROPID pidNew ) {pid = pidNew;}
  146. unsigned* GetCountAddress() {return(&cb);}
  147. BOOL IsValue() const { return ( *buf != STRING_KEY ); }
  148. BYTE Type() const { return *buf; }
  149. WCHAR* GetStr() const;
  150. unsigned StrLen() const;
  151. #ifdef CIEXTMODE
  152. void CiExtDump(void *ciExtSelf);
  153. #endif
  154. private:
  155. unsigned cb;
  156. BYTE buf[MAXKEYSIZE];
  157. PROPID pid;
  158. };
  159. class SKeyBuf
  160. {
  161. public :
  162. SKeyBuf(CKeyBuf * pKeyBuf) { _pKeyBuf = pKeyBuf;
  163. }
  164. ~SKeyBuf() { delete _pKeyBuf; }
  165. CKeyBuf * operator -> () { return _pKeyBuf; }
  166. CKeyBuf & operator * () { return *_pKeyBuf; }
  167. CKeyBuf * Acquire()
  168. { CKeyBuf * pTemp = _pKeyBuf; _pKeyBuf = 0; return pTemp; }
  169. private:
  170. CKeyBuf * _pKeyBuf;
  171. };
  172. //+---------------------------------------------------------------------------
  173. //
  174. // Function: Compare
  175. //
  176. // Synopsis: Compare two unsigned longs
  177. //
  178. // Arguments: [ul1] -- first ulong
  179. // [ul2] -- second ulong
  180. //
  181. // Returns: "difference" ul1 - ul2
  182. //
  183. // History: 07-May-91 BartoszM Created
  184. //
  185. //----------------------------------------------------------------------------
  186. inline int Compare ( ULONG u1, ULONG u2 )
  187. {
  188. return ( u1 > u2 )? 1 : (( u1 < u2 )? -1: 0);
  189. }
  190. //+---------------------------------------------------------------------------
  191. //
  192. // Class: CDirectoryKey
  193. //
  194. // Purpose: Key class for use in the (downlevel) directory
  195. //
  196. // History: 3-May-95 dlee created
  197. //
  198. // Notes: Directory keys look like this:
  199. //
  200. // cb of the key (2 bytes)
  201. // BitOffset (8 bytes)
  202. // PROPID (4 bytes)
  203. // the key (cb bytes)
  204. //
  205. // There are no alignment constraints on any of the fields.
  206. //
  207. //----------------------------------------------------------------------------
  208. #include <pshpack1.h>
  209. const BYTE pidIdMaxSmallPid = 0x40; // 1-byte pids > this are 4096-based
  210. const ULONG pidNewPidBase = INIT_DOWNLEVEL_PID; // base of CI's new pids
  211. class CDirectoryKey
  212. {
  213. public:
  214. void * operator new( size_t size, void *pv ) { return pv; }
  215. void operator delete( void * p ) {}
  216. unsigned Count()
  217. {
  218. return (unsigned) _cbKey;
  219. }
  220. BYTE * Key()
  221. {
  222. Win4Assert( 0 != this );
  223. return (BYTE *) ( this + 1 ) + ExtraPropIdSize();
  224. }
  225. PROPID PropId()
  226. {
  227. Win4Assert( 0 != this );
  228. if ( 0 == _bPropId )
  229. return * (UNALIGNED PROPID *) ( this + 1 );
  230. if ( _bPropId > pidIdMaxSmallPid )
  231. return (PROPID) _bPropId - pidIdMaxSmallPid + pidNewPidBase - 1;
  232. return (PROPID) _bPropId;
  233. }
  234. void PropId( PROPID & pid )
  235. {
  236. pid = PropId();
  237. }
  238. void Offset( BitOffset & offset )
  239. {
  240. Win4Assert( 0 != this );
  241. offset.SetPage( * (UNALIGNED ULONG *) &_oPage );
  242. offset.SetOff( * (UNALIGNED USHORT *) &_oBit );
  243. }
  244. void Write( BYTE cbKey,
  245. BitOffset bitOffset,
  246. PROPID pid,
  247. const BYTE * buf )
  248. {
  249. * (UNALIGNED ULONG *) &_oPage = bitOffset.Page();
  250. Win4Assert( bitOffset.Offset() <= 0xffff );
  251. * (UNALIGNED USHORT *) &_oBit = (USHORT) bitOffset.Offset();
  252. BYTE * pbKey = (BYTE *) (this + 1);
  253. if ( pid <= pidIdMaxSmallPid )
  254. {
  255. _bPropId = (BYTE) pid;
  256. }
  257. else if ( ( pid >= pidNewPidBase ) &&
  258. ( pid < ( pidNewPidBase + 0xfd - pidIdMaxSmallPid ) ) )
  259. {
  260. _bPropId = (BYTE) ( pid - pidNewPidBase + pidIdMaxSmallPid + 1 );
  261. }
  262. else
  263. {
  264. _bPropId = 0;
  265. RtlCopyMemory( pbKey, &pid, sizeof ULONG );
  266. pbKey += sizeof ULONG;
  267. }
  268. _cbKey = cbKey;
  269. RtlCopyMemory( pbKey, buf, cbKey );
  270. }
  271. unsigned Size()
  272. {
  273. return sizeof CDirectoryKey + ExtraPropIdSize() + Count();
  274. }
  275. static unsigned ComputeSize( BYTE cbKey, PROPID pid )
  276. {
  277. unsigned cbPid = 0;
  278. if ( ! ( ( pid <= pidIdMaxSmallPid ) ||
  279. ( ( pid >= pidNewPidBase ) &&
  280. ( pid < ( pidNewPidBase + 0xfd - pidIdMaxSmallPid ) ) ) ) )
  281. cbPid = sizeof ULONG;
  282. return sizeof CDirectoryKey + cbPid + cbKey;
  283. }
  284. CDirectoryKey * NextKey()
  285. {
  286. Win4Assert( 0 != this );
  287. return (CDirectoryKey *) ( (BYTE *) this + Size() );
  288. }
  289. BOOL IsGreaterThanKeyBuf( const CKeyBuf & key )
  290. {
  291. // return TRUE if "this" is greater than key
  292. Win4Assert( 0 != this );
  293. Win4Assert( 0 != &key );
  294. Win4Assert( pidAll != PropId() );
  295. unsigned count = Count();
  296. unsigned long mincb = __min( count, key.Count() );
  297. int diff = memcmp( Key(), key.GetBuf(), mincb );
  298. if ( 0 == diff )
  299. {
  300. diff = count - key.Count();
  301. if ( 0 == diff )
  302. {
  303. diff = ::Compare( PropId(), key.Pid() );
  304. }
  305. }
  306. return diff > 0;
  307. }
  308. void MakeKeyBuf( CKeyBuf & keyBuf )
  309. {
  310. // copy the count and key
  311. unsigned cbKey = Count();
  312. keyBuf.SetCount( cbKey );
  313. RtlCopyMemory( keyBuf.GetWritableBuf(),
  314. Key(),
  315. cbKey );
  316. // copy the pid
  317. keyBuf.SetPid( PropId() );
  318. }
  319. private:
  320. unsigned ExtraPropIdSize()
  321. {
  322. return ( 0 == _bPropId ) ? sizeof ULONG : 0;
  323. }
  324. ULONG _oPage; // page number
  325. USHORT _oBit; // bit offset in the page
  326. BYTE _bPropId; // Byte form of propid, or 0 if it won't fit
  327. BYTE _cbKey; // Byte count of the key following
  328. };
  329. #include <poppack.h>
  330. //+---------------------------------------------------------------------------
  331. //
  332. // Member: CKey::~Ckey
  333. //
  334. // Synopsis: Free memory
  335. //
  336. // History: 07-May-91 BartoszM Created
  337. //
  338. //----------------------------------------------------------------------------
  339. inline CKey::~CKey()
  340. {
  341. delete buf;
  342. }
  343. inline void CKey::Marshall( PSerStream & stm ) const
  344. {
  345. stm.PutULong( pid );
  346. stm.PutULong( cb );
  347. stm.PutBlob( buf, cb );
  348. }
  349. inline CKey::CKey( PDeSerStream & stm )
  350. : buf(0)
  351. {
  352. pid = stm.GetULong();
  353. cb = stm.GetULong();
  354. // Guard against attack
  355. if ( cb >= 65536 )
  356. THROW( CException( E_INVALIDARG ) );
  357. buf = new BYTE[cb];
  358. stm.GetBlob( buf, cb );
  359. }
  360. inline void CKey::Init( CStream & stream )
  361. {
  362. stream.Read( &cb, sizeof( cb ) );
  363. buf = new BYTE[cb];
  364. stream.Read( buf, sizeof( buf[0] ) * cb );
  365. stream.Read( &pid, sizeof( pid ) );
  366. }
  367. inline void CKey::Serialize( CStream & stream ) const
  368. {
  369. stream.Write( &cb, sizeof( cb ) );
  370. stream.Write( buf, sizeof( buf[0] ) * cb );
  371. stream.Write( &pid, sizeof( pid ) );
  372. }
  373. //+---------------------------------------------------------------------------
  374. //
  375. // Member: CKey::FillMax
  376. //
  377. // Synopsis: Makes a max key, greater or equal to any key.
  378. //
  379. // History: 07-May-91 BartoszM Created
  380. //
  381. //----------------------------------------------------------------------------
  382. inline void CKey::FillMax ()
  383. {
  384. Win4Assert ( pidInvalid == 0xffffffff );
  385. pid = pidInvalid;
  386. cb = MAXKEYSIZE;
  387. Win4Assert ( buf == 0 );
  388. buf = new BYTE[MAXKEYSIZE];
  389. memset( buf, MAX_BYTE, MAXKEYSIZE);
  390. }
  391. //+---------------------------------------------------------------------------
  392. //
  393. // Member: CKey::FillMax
  394. //
  395. // Synopsis: Treats [key] as a prefix. Creates a key that is greater
  396. // than any other key with the same prefix.
  397. // Used for end of range
  398. //
  399. // Arguments: [key] -- prefix
  400. //
  401. // History: 07-May-91 BartoszM Created
  402. //
  403. //----------------------------------------------------------------------------
  404. inline void CKey::FillMax ( const CKey& key )
  405. {
  406. Win4Assert ( &key != 0 );
  407. Win4Assert ( this != 0 );
  408. buf = new BYTE[MAXKEYSIZE];
  409. cb = MAXKEYSIZE;
  410. pid = key.Pid();
  411. memcpy ( buf, key.GetBuf(), key.Count());
  412. memset ( buf + key.Count(), MAX_BYTE, MAXKEYSIZE - key.Count() );
  413. }
  414. //+---------------------------------------------------------------------------
  415. //
  416. // Member: CKey::FillMin
  417. //
  418. // Synopsis: Creates a minimum key
  419. //
  420. // History: 07-May-91 BartoszM Created
  421. //
  422. //----------------------------------------------------------------------------
  423. inline void CKey::FillMin()
  424. {
  425. cb = 0;
  426. pid = 0;
  427. }
  428. //+---------------------------------------------------------------------------
  429. //
  430. // Member: CKey::CKey
  431. //
  432. // Synopsis: Creates CKey based on CKeyBuf
  433. //
  434. // Arguments: [keybuf] -- original
  435. //
  436. // History: 07-May-91 BartoszM Created
  437. //
  438. //----------------------------------------------------------------------------
  439. inline CKey::CKey ( const CKeyBuf& keybuf )
  440. : buf(0)
  441. {
  442. Win4Assert ( &keybuf != 0 );
  443. Win4Assert ( this != 0 );
  444. cb = keybuf.Count();
  445. pid = keybuf.Pid();
  446. buf = new BYTE [cb];
  447. memcpy ( buf, keybuf.GetBuf(), cb );
  448. }
  449. //+---------------------------------------------------------------------------
  450. //
  451. // Member: CKey::CKey
  452. //
  453. // Synopsis: Copy constructor
  454. //
  455. // Arguments: [keySrc] -- original
  456. //
  457. // History: 07-May-91 BartoszM Created
  458. //
  459. //----------------------------------------------------------------------------
  460. inline CKey::CKey ( const CKey& keySrc )
  461. : buf(0)
  462. {
  463. Win4Assert ( &keySrc != 0 );
  464. Win4Assert ( this != 0 );
  465. cb = keySrc.cb;
  466. pid = keySrc.pid;
  467. buf = new BYTE [cb];
  468. memcpy ( buf, keySrc.buf, cb );
  469. }
  470. //+---------------------------------------------------------------------------
  471. //
  472. // Member: CKey::operator=
  473. //
  474. // Synopsis: Creates CKey based on CKeyBuf
  475. //
  476. // Arguments: [keybuf] -- original
  477. //
  478. // History: 07-May-91 BartoszM Created
  479. //
  480. //----------------------------------------------------------------------------
  481. inline void CKey::operator= ( const CKeyBuf& keybuf )
  482. {
  483. Win4Assert ( &keybuf != 0 );
  484. Win4Assert ( this != 0 );
  485. cb = keybuf.Count();
  486. pid = keybuf.Pid();
  487. Win4Assert ( buf == 0 );
  488. buf = new BYTE [cb];
  489. memcpy ( buf, keybuf.GetBuf(), cb );
  490. }
  491. //+---------------------------------------------------------------------------
  492. //
  493. // Member: CKey::operator=
  494. //
  495. // Synopsis: Creates CKey based on another CKey
  496. //
  497. // Arguments: [key] -- original
  498. //
  499. // History: 07-May-91 BartoszM Created
  500. //
  501. //----------------------------------------------------------------------------
  502. inline void CKey::operator= ( const CKey& key )
  503. {
  504. Win4Assert ( &key != 0 );
  505. Win4Assert ( this != 0 );
  506. cb = key.cb;
  507. pid = key.pid;
  508. Win4Assert ( buf == 0 );
  509. buf = new BYTE [cb];
  510. memcpy ( buf, key.buf, cb );
  511. }
  512. //+---------------------------------------------------------------------------
  513. //
  514. // Member: CKey::MatchPid
  515. //
  516. // Synopsis: Compares pids, "this" may have wildcard pidAll
  517. //
  518. // Arguments: [key] -- the other key (not pidAll)
  519. //
  520. // History: 29-Nov-94 BartoszM Created
  521. //
  522. //----------------------------------------------------------------------------
  523. inline BOOL CKey::MatchPid ( const CKeyBuf& key ) const
  524. {
  525. Win4Assert (key.Pid() != pidAll);
  526. return ( Pid() == pidAll && key.Pid() != pidRevName ) || Pid() == key.Pid();
  527. }
  528. //+---------------------------------------------------------------------------
  529. //
  530. // Function: Compare
  531. //
  532. // Synopsis: Compare two keys
  533. //
  534. // Arguments: [key1] -- first key
  535. // [key2] -- second key
  536. //
  537. // Returns: "difference" key1 - key2
  538. //
  539. // Requires: key1 != NULL && key2 != NULL
  540. //
  541. // History: 06-May-91 BartoszM Created
  542. //
  543. // Notice: No wildcard pidAll allowed
  544. //
  545. //----------------------------------------------------------------------------
  546. inline int Compare ( const CKeyBuf* key1, const CKeyBuf* key2 )
  547. {
  548. Win4Assert ( key1 != 0 );
  549. Win4Assert ( key2 != 0 );
  550. Win4Assert ( key1->Pid() != pidAll );
  551. Win4Assert ( key2->Pid() != pidAll );
  552. int result;
  553. unsigned long mincb = __min(key1->Count(), key2->Count());
  554. result = memcmp(key1->GetBuf(), key2->GetBuf(), mincb);
  555. if (result == 0)
  556. {
  557. result = key1->Count() - key2->Count();
  558. if ( result == 0 )
  559. result = Compare ( key1->Pid(), key2->Pid() );
  560. }
  561. return result;
  562. }
  563. //+---------------------------------------------------------------------------
  564. //
  565. // Function: AreEqual
  566. //
  567. // Synopsis: Compare two keys for equality. Early exit when lengths differ
  568. //
  569. // Arguments: [key1] -- first key
  570. // [key2] -- second key
  571. //
  572. // Returns: TRUE when equal
  573. //
  574. // Requires: key1 != NULL && key2 != NULL
  575. //
  576. // History: 06-May-91 BartoszM Created
  577. //
  578. // Notice: No wildcard pidAll allowed
  579. //
  580. //----------------------------------------------------------------------------
  581. inline BOOL AreEqual ( const CKeyBuf* key1, const CKeyBuf* key2 )
  582. {
  583. Win4Assert ( key1 != 0 );
  584. Win4Assert ( key2 != 0 );
  585. Win4Assert ( key1->Pid() != pidAll );
  586. Win4Assert ( key2->Pid() != pidAll );
  587. unsigned len = key1->Count();
  588. if (key2->Count() != len)
  589. return(FALSE);
  590. if ( memcmp(key1->GetBuf(), key2->GetBuf(), len) != 0 )
  591. return(FALSE);
  592. return ( key1->Pid() == key2->Pid() );
  593. }
  594. //+---------------------------------------------------------------------------
  595. //
  596. // Function: AreEqualStr
  597. //
  598. // Synopsis: Compare two keys for equality of buffers (disregard PID).
  599. // Early exit when lengths differ
  600. //
  601. // Arguments: [key1] -- first key
  602. // [key2] -- second key
  603. //
  604. // Returns: TRUE when equal
  605. //
  606. // Requires: key1 != NULL && key2 != NULL
  607. //
  608. // History: 06-May-91 BartoszM Created
  609. //
  610. // Notice: No wildcard pidAll allowed
  611. //
  612. //----------------------------------------------------------------------------
  613. inline BOOL AreEqualStr ( const CKeyBuf* key1, const CKeyBuf* key2 )
  614. {
  615. Win4Assert ( key1 != 0 );
  616. Win4Assert ( key2 != 0 );
  617. Win4Assert ( key1->Pid() != pidAll );
  618. Win4Assert ( key2->Pid() != pidAll );
  619. unsigned len = key1->Count();
  620. if (key2->Count() != len)
  621. return(FALSE);
  622. return memcmp(key1->GetBuf(), key2->GetBuf(), len) == 0;
  623. }
  624. //+---------------------------------------------------------------------------
  625. //
  626. // Member: CKey::Compare
  627. //
  628. // Synopsis: Compare this with another key
  629. //
  630. // Arguments: [key] -- key to compare with
  631. //
  632. // Returns: "difference" this - key
  633. // this key can have wildcard pidAll
  634. // but it will be treated like any other pid
  635. //
  636. // Requires: [key]'s pid cannot be pidAll
  637. //
  638. // History: 14-Sep-92 BartoszM Created
  639. //
  640. //----------------------------------------------------------------------------
  641. inline int CKey::Compare( const CKey & key) const
  642. {
  643. Win4Assert ( this != 0 );
  644. Win4Assert ( &key != 0 );
  645. Win4Assert ( key.Pid() != pidAll );
  646. unsigned long mincb = __min(cb, key.Count());
  647. int diff = memcmp(buf, key.GetBuf(), mincb);
  648. if (diff == 0)
  649. { // this->buf == key.buf
  650. diff = cb - key.Count();
  651. if (diff == 0)
  652. {
  653. diff = ::Compare ( pid, key.Pid());
  654. }
  655. }
  656. return(diff);
  657. }
  658. //+---------------------------------------------------------------------------
  659. //
  660. // Member: CKey::Compare
  661. //
  662. // Synopsis: Compare this with another key
  663. //
  664. // Arguments: [key] -- key to compare with
  665. //
  666. // Returns: "difference" this - key
  667. // this key can have wildcard pidAll
  668. // but it will be treated like any other pid
  669. //
  670. // Requires: [key]'s pid cannot be pidAll
  671. //
  672. // History: 14-Sep-92 BartoszM Created
  673. //
  674. //----------------------------------------------------------------------------
  675. inline int CKey::Compare( const CKeyBuf & key) const
  676. {
  677. Win4Assert ( this != 0 );
  678. Win4Assert ( &key != 0 );
  679. Win4Assert ( key.Pid() != pidAll );
  680. unsigned long mincb = __min(cb, key.Count());
  681. int diff = memcmp(buf, key.GetBuf(), mincb);
  682. if (diff == 0)
  683. { // this->buf == key.buf
  684. diff = cb - key.Count();
  685. if (diff == 0)
  686. {
  687. diff = ::Compare ( pid, key.Pid());
  688. }
  689. }
  690. return(diff);
  691. }
  692. //+---------------------------------------------------------------------------
  693. //
  694. // Member: CKey::CompareStr
  695. //
  696. // Synopsis: Compare this with another key ignoring pid
  697. //
  698. // Arguments: [key] -- key to compare with
  699. //
  700. // Returns: "difference" this - key
  701. //
  702. // History: 14-Sep-92 BartoszM Created
  703. //
  704. //----------------------------------------------------------------------------
  705. inline int CKey::CompareStr( const CKeyBuf & key) const
  706. {
  707. Win4Assert ( this != 0 );
  708. Win4Assert ( &key != 0 );
  709. unsigned long mincb = __min(cb, key.Count());
  710. int diff = memcmp(buf, key.GetBuf(), mincb);
  711. if (diff == 0)
  712. { // this->buf == key.buf
  713. diff = cb - key.Count();
  714. }
  715. return(diff);
  716. }
  717. //+---------------------------------------------------------------------------
  718. //
  719. // Member: CKey::CompareStr
  720. //
  721. // Synopsis: Compare this with another key ignoring pid
  722. //
  723. // Arguments: [key] -- key to compare with
  724. //
  725. // Returns: "difference" this - key
  726. //
  727. // History: 14-Sep-92 BartoszM Created
  728. //
  729. //----------------------------------------------------------------------------
  730. inline int CKeyBuf::CompareStr( const CKey & key) const
  731. {
  732. Win4Assert ( this != 0 );
  733. Win4Assert ( &key != 0 );
  734. unsigned long mincb = __min(cb, key.Count());
  735. int diff = memcmp(buf, key.GetBuf(), mincb);
  736. if (diff == 0)
  737. { // this->buf == key.buf
  738. diff = cb - key.Count();
  739. }
  740. return(diff);
  741. }
  742. //+---------------------------------------------------------------------------
  743. //
  744. // Member: CKey::CompareStr
  745. //
  746. // Synopsis: Compare this with another key ignoring pid
  747. //
  748. // Arguments: [key] -- key to compare with
  749. //
  750. // Returns: "difference" this - key
  751. //
  752. // History: 14-Sep-92 BartoszM Created
  753. //
  754. //----------------------------------------------------------------------------
  755. inline int CKey::CompareStr( const CKey & key) const
  756. {
  757. Win4Assert ( this != 0 );
  758. Win4Assert ( &key != 0 );
  759. unsigned long mincb = __min(cb, key.Count());
  760. int diff = memcmp(buf, key.GetBuf(), mincb);
  761. if (diff == 0)
  762. { // this->buf == key.buf
  763. diff = cb - key.Count();
  764. }
  765. return(diff);
  766. }
  767. //+---------------------------------------------------------------------------
  768. //
  769. // Method: IsExactMatch
  770. //
  771. // Synopsis: Compare for exact equality. Early exit when lengths differ
  772. //
  773. // Arguments: [key] -- key to compare with
  774. //
  775. // Returns: TRUE when equal
  776. //
  777. // Requires: key1 != NULL && key2 != NULL
  778. //
  779. // History: 06-Oct-94 BartoszM Created
  780. //
  781. // Notice: pidAll allowed in both. Use to compare keys in query
  782. //
  783. //----------------------------------------------------------------------------
  784. inline BOOL CKey::IsExactMatch ( const CKey& key ) const
  785. {
  786. Win4Assert (this != 0);
  787. Win4Assert (&key != 0);
  788. return cb == key.Count()
  789. && pid == key.Pid()
  790. && memcmp(buf, key.GetBuf(), cb) == 0;
  791. }
  792. //+---------------------------------------------------------------------------
  793. //
  794. // Member: CKeyBuf::IsPossibleRW, public
  795. //
  796. // Synopsis: Determine whether a word can be a relevant word or not.
  797. //
  798. // Returns: TRUE if no digits and > 2 characters long
  799. //
  800. // Notes: All of these characters are deemed 'digits' by Win32
  801. //
  802. // History: 6-May-94 v-dlee Created
  803. //
  804. //----------------------------------------------------------------------------
  805. #define _IsADigit(x) (((x) >= 0x30 && (x) <= 0x39) || \
  806. ((x) >= 0xb2 && (x) <= 0xb3) || \
  807. ((x) == 0xb9) || \
  808. ((x) >= 0x660 && (x) <= 0x669) || \
  809. ((x) >= 0x6f0 && (x) <= 0x6f9) || \
  810. ((x) >= 0x966 && (x) <= 0x96f) || \
  811. ((x) >= 0x9e6 && (x) <= 0x9ef) || \
  812. ((x) >= 0xa66 && (x) <= 0xa6f) || \
  813. ((x) >= 0xae6 && (x) <= 0xaef) || \
  814. ((x) >= 0xb66 && (x) <= 0xb6f) || \
  815. ((x) >= 0xbe7 && (x) <= 0xbef) || \
  816. ((x) >= 0xbf0 && (x) <= 0xbf2) || \
  817. ((x) >= 0xc66 && (x) <= 0xc6f) || \
  818. ((x) >= 0xce6 && (x) <= 0xcef) || \
  819. ((x) >= 0xd66 && (x) <= 0xd6f) || \
  820. ((x) >= 0xe50 && (x) <= 0xe59) || \
  821. ((x) >= 0xed0 && (x) <= 0xed9) || \
  822. ((x) >= 0x1040 && (x) <= 0x1049) || \
  823. ((x) == 0x2070) || \
  824. ((x) >= 0x2074 && (x) <= 0x2079) || \
  825. ((x) >= 0x2080 && (x) <= 0x2089) || \
  826. ((x) >= 0xff10 && (x) <= 0xff19))
  827. inline BOOL CKeyBuf::IsPossibleRW()
  828. {
  829. unsigned uCount = Count();
  830. if (uCount > (1 + 2 * sizeof(WCHAR)))
  831. {
  832. const BYTE * p = (BYTE *) &buf;
  833. p++;
  834. for (unsigned c = 0; c < uCount; c += 2, p += 2)
  835. {
  836. WCHAR wc = MAKEWORD(*(p + 1),*p);
  837. if (_IsADigit(wc))
  838. {
  839. return FALSE;
  840. }
  841. }
  842. }
  843. else return FALSE;
  844. return TRUE;
  845. } //IsPossibleRW
  846. inline CKeyBuf::CKeyBuf( PROPID p, BYTE const * pb, unsigned count )
  847. : pid( p ),
  848. cb( count )
  849. {
  850. memcpy( buf, pb, count );
  851. }
  852. //+---------------------------------------------------------------------------
  853. //
  854. // Member: CKeyBuf::operator=, public
  855. //
  856. // Synopsis: Assignment operator
  857. //
  858. // Arguments: [key] -- CKeyBuf to assign to this.
  859. //
  860. // History: 26-Jun-91 KyleP Created.
  861. //
  862. //----------------------------------------------------------------------------
  863. inline void CKeyBuf::operator=(const CKeyBuf & key)
  864. {
  865. cb = key.Count();
  866. pid = key.Pid();
  867. memcpy(buf, key.GetBuf(), cb);
  868. }
  869. //+---------------------------------------------------------------------------
  870. //
  871. // Member: CKeyBuf::CKeyBuf, public
  872. //
  873. // Synopsis: Assignment operator
  874. //
  875. // Arguments: [key] -- CKeyBuf to assign to this.
  876. //
  877. // History: 26-Jun-91 KyleP Created.
  878. //
  879. //----------------------------------------------------------------------------
  880. #if 0 //STACKSTACK
  881. inline CKeyBuf::CKeyBuf(const CKey& key)
  882. {
  883. *this = key;
  884. }
  885. #endif
  886. inline void CKeyBuf::operator=( const CKey& key)
  887. {
  888. Win4Assert( key.Count() <= MAXKEYSIZE );
  889. cb = key.Count();
  890. pid = key.Pid();
  891. memcpy(buf, key.GetBuf(), cb);
  892. }
  893. //+---------------------------------------------------------------------------
  894. //
  895. // Member: CKeyBuf::FillMax
  896. //
  897. // Synopsis: Makes a max key, greater or equal to any key.
  898. //
  899. // History: 07-May-91 BartoszM Created
  900. //
  901. //----------------------------------------------------------------------------
  902. inline void CKeyBuf::FillMax ()
  903. {
  904. Win4Assert ( pidInvalid == 0xffffffff );
  905. pid = pidInvalid;
  906. cb = MAXKEYSIZE;
  907. memset( buf, MAX_BYTE, MAXKEYSIZE);
  908. }
  909. inline void CKeyBuf::FillMin()
  910. {
  911. cb = 0;
  912. pid = 0;
  913. }
  914. //+---------------------------------------------------------------------------
  915. //
  916. // Member: CKeyBuf::IsMaxKey
  917. //
  918. // Synopsis: Returns TRUE if this is the maximum possible key
  919. //
  920. // History: 07-May-91 BartoszM Created
  921. //
  922. //----------------------------------------------------------------------------
  923. inline BOOL CKeyBuf::IsMaxKey() const
  924. {
  925. if (cb == MAXKEYSIZE)
  926. {
  927. for(unsigned n = 0; n < MAXKEYSIZE; n++)
  928. {
  929. if (buf[n] != MAX_BYTE)
  930. {
  931. return(FALSE);
  932. }
  933. }
  934. return(TRUE);
  935. }
  936. else
  937. return(FALSE);
  938. }
  939. inline BOOL CKeyBuf::IsMinKey() const
  940. {
  941. return ( 0 == cb ) && ( 0 == pid );
  942. }
  943. //+---------------------------------------------------------------------------
  944. //
  945. // Member: CKeyBuf::CompareStr
  946. //
  947. // Synopsis: Compare this with another key ignoring pid
  948. //
  949. // Arguments: [key] -- key to compare with
  950. //
  951. // Returns: "difference" this - key
  952. //
  953. // History: 14-Sep-92 BartoszM Created
  954. // 15-Dec-93 w-PatG Stolen from CKey
  955. //
  956. //----------------------------------------------------------------------------
  957. inline int CKeyBuf::CompareStr( const CKeyBuf & key) const
  958. {
  959. Win4Assert ( this != 0 );
  960. Win4Assert ( &key != 0 );
  961. unsigned long mincb = __min(cb, key.Count());
  962. int diff = memcmp(buf, key.GetBuf(), mincb);
  963. if (diff == 0)
  964. { // this->buf == key.buf
  965. diff = cb - key.Count();
  966. }
  967. return(diff);
  968. }
  969. inline int CKeyBuf::Compare( const CKeyBuf & key) const
  970. {
  971. Win4Assert ( this != 0 );
  972. Win4Assert ( &key != 0 );
  973. Win4Assert ( key.Pid() != pidAll );
  974. unsigned long mincb = __min(cb, key.Count());
  975. int diff = memcmp(buf, key.GetBuf(), mincb);
  976. if (diff == 0)
  977. { // this->buf == key.buf
  978. diff = cb - key.Count();
  979. if (diff == 0)
  980. {
  981. diff = ::Compare ( pid, key.Pid());
  982. }
  983. }
  984. return(diff);
  985. }
  986. inline int CKeyBuf::Compare( const CKey & key) const
  987. {
  988. Win4Assert ( this != 0 );
  989. Win4Assert ( &key != 0 );
  990. Win4Assert ( key.Pid() != pidAll );
  991. unsigned long mincb = __min(cb, key.Count());
  992. int diff = memcmp(buf, key.GetBuf(), mincb);
  993. if (diff == 0)
  994. { // this->buf == key.buf
  995. diff = cb - key.Count();
  996. if (diff == 0)
  997. {
  998. diff = ::Compare ( pid, key.Pid());
  999. }
  1000. }
  1001. return(diff);
  1002. }