Leaked source code of windows server 2003
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.

1253 lines
23 KiB

  1. /*
  2. * This module contains the definitions for the inline functions used by the
  3. * name undecorator. It is intended that this file should be included
  4. * somewhere in the source file for the undecorator to maximise the chance
  5. * that they will be truly inlined.
  6. */
  7. // The following class is a special node class, used in the implementation
  8. // of the internal chaining mechanism of the 'DName's
  9. class charNode;
  10. class pcharNode;
  11. class pDNameNode;
  12. class DNameStatusNode;
  13. #if ( NO_VIRTUAL )
  14. enum NodeType
  15. {
  16. charNode_t,
  17. pcharNode_t,
  18. pDNameNode_t,
  19. DNameStatusNode_t
  20. };
  21. #endif // NO_VIRTUAL
  22. class DNameNode
  23. {
  24. private:
  25. #if NO_VIRTUAL
  26. NodeType typeIndex;
  27. #endif // NO_VIRTUAL
  28. DNameNode * next;
  29. protected:
  30. #if ( !NO_VIRTUAL )
  31. DNameNode ();
  32. #else // } elif NO_VIRTUAL {
  33. DNameNode ( NodeType );
  34. #endif // NO_VIRTUAL
  35. DNameNode ( const DNameNode & );
  36. public:
  37. virtual int length () const PURE;
  38. virtual char getLastChar () const PURE;
  39. virtual pchar_t getString ( pchar_t, int ) const PURE;
  40. DNameNode * clone ();
  41. DNameNode * nextNode () const;
  42. DNameNode & operator += ( DNameNode * );
  43. };
  44. class charNode : public DNameNode
  45. {
  46. private:
  47. char me;
  48. public:
  49. charNode ( char );
  50. virtual int length () const;
  51. virtual char getLastChar () const;
  52. virtual pchar_t getString ( pchar_t, int ) const;
  53. };
  54. class pcharNode : public DNameNode
  55. {
  56. private:
  57. pchar_t me;
  58. int myLen;
  59. public:
  60. pcharNode ( pcchar_t, int = 0 );
  61. virtual int length () const;
  62. virtual char getLastChar () const;
  63. virtual pchar_t getString ( pchar_t, int ) const;
  64. };
  65. class pDNameNode : public DNameNode
  66. {
  67. private:
  68. DName * me;
  69. public:
  70. pDNameNode ( DName * );
  71. virtual int length () const;
  72. virtual char getLastChar () const;
  73. virtual pchar_t getString ( pchar_t, int ) const;
  74. };
  75. class DNameStatusNode : public DNameNode
  76. {
  77. private:
  78. #define TruncationMessage (" ?? ")
  79. #define TruncationMessageLength (4)
  80. DNameStatus me;
  81. int myLen;
  82. public:
  83. DNameStatusNode ( DNameStatus );
  84. virtual int length () const;
  85. virtual char getLastChar () const;
  86. virtual pchar_t getString ( pchar_t, int ) const;
  87. };
  88. // Memory allocation functions
  89. inline void * operator new ( size_t sz, HeapManager &, int noBuffer )
  90. { return heap.getMemory ( sz, noBuffer ); }
  91. void * HeapManager::getMemory ( size_t sz, int noBuffer )
  92. {
  93. // Align the allocation on an appropriate boundary
  94. sz = (( sz + PACK_SIZE-1 ) & ~(PACK_SIZE-1) );
  95. if ( noBuffer )
  96. return ( *pOpNew )( sz );
  97. else
  98. {
  99. // Handle a potential request for no space
  100. if ( !sz )
  101. sz = PACK_SIZE;
  102. if ( blockLeft < sz )
  103. {
  104. // Is the request greater than the largest buffer size ?
  105. if ( sz > memBlockSize )
  106. return 0; // If it is, there is nothing we can do
  107. // Allocate a new block
  108. Block * pNewBlock = rnew Block;
  109. // Did the allocation succeed ? If so connect it up
  110. if ( pNewBlock )
  111. {
  112. // Handle the initial state
  113. if ( tail )
  114. tail = tail->next = pNewBlock;
  115. else
  116. head = tail = pNewBlock;
  117. // Compute the remaining space
  118. blockLeft = memBlockSize - sz;
  119. } // End of IF then
  120. else
  121. return 0; // Oh-oh! Memory allocation failure
  122. } // End of IF then
  123. else
  124. blockLeft -= sz; // Deduct the allocated amount
  125. // And return the buffer address
  126. return &( tail->memBlock[ blockLeft ]);
  127. } // End of IF else
  128. } // End of "HeapManager" FUNCTION "getMemory(size_t,int)"
  129. // Friend functions of 'DName'
  130. inline DName operator + ( char c, const DName & rd )
  131. { return DName ( c ) + rd; }
  132. inline DName operator + ( DNameStatus st, const DName & rd )
  133. { return DName ( st ) + rd; }
  134. inline DName operator + ( pcchar_t s, const DName & rd )
  135. { return DName ( s ) + rd; }
  136. // The 'DName' constructors
  137. inline DName::DName () { node = 0; stat = DN_valid; isIndir = 0; isAUDC = 0; isAUDTThunk = 0; isArrayType = 0; NoTE = 0; }
  138. inline DName::DName ( DNameNode * pd ) { node = pd; stat = DN_valid; isIndir = 0; isAUDC = 0; isAUDTThunk = 0; isArrayType = 0; NoTE = 0; }
  139. DName::DName ( char c )
  140. {
  141. stat = DN_valid;
  142. isIndir = 0;
  143. isAUDC = 0;
  144. isAUDTThunk = 0;
  145. isArrayType = 0;
  146. node = 0;
  147. NoTE = 0;
  148. // The NULL character is boring, do not copy
  149. if ( c )
  150. doPchar ( &c, 1 );
  151. } // End of "DName" CONSTRUCTOR '(char)'
  152. inline DName::DName ( const DName & rd )
  153. {
  154. stat = rd.stat;
  155. isIndir = rd.isIndir;
  156. isAUDC = rd.isAUDC;
  157. isAUDTThunk = rd.isAUDTThunk;
  158. isArrayType = rd.isArrayType;
  159. node = rd.node;
  160. NoTE = rd.NoTE;
  161. } // End of "DName" CONSTRUCTOR '(const DName&)'
  162. DName::DName ( DName * pd )
  163. {
  164. if ( pd )
  165. {
  166. node = gnew pDNameNode ( pd );
  167. stat = ( node ? DN_valid : DN_error );
  168. } // End of IF else
  169. else
  170. {
  171. stat = DN_valid;
  172. node = 0;
  173. } // End of IF else
  174. isIndir = 0;
  175. isAUDC = 0;
  176. isAUDTThunk = 0;
  177. isArrayType = 0;
  178. NoTE = 0;
  179. } // End of "DName" CONSTRUCTOR '( DName* )'
  180. DName::DName ( pcchar_t s )
  181. {
  182. stat = DN_valid;
  183. node = 0;
  184. isIndir = 0;
  185. isAUDC = 0;
  186. isAUDTThunk = 0;
  187. isArrayType = 0;
  188. NoTE = 0;
  189. if ( s )
  190. doPchar ( s, und_strlen ( s ));
  191. } // End of "DName" CONSTRUCTOR '(pcchar_t)'
  192. DName::DName ( pcchar_t & name, char terminator )
  193. {
  194. stat = DN_valid;
  195. isIndir = 0;
  196. isAUDC = 0;
  197. isAUDTThunk = 0;
  198. isArrayType = 0;
  199. node = 0;
  200. NoTE = 0;
  201. // Is there a string ?
  202. if ( name )
  203. if ( *name )
  204. {
  205. int len = 0;
  206. // How long is the string ?
  207. pcchar_t s;
  208. for ( s = name; *name && ( *name != terminator ); name++ )
  209. if ( isValidIdentChar ( *name ) || UnDecorator::doNoIdentCharCheck () )
  210. len++;
  211. else
  212. {
  213. stat = DN_invalid;
  214. return;
  215. } // End of IF else
  216. // Copy the name string fragment
  217. doPchar ( s, len );
  218. // Now gobble the terminator if present, handle error conditions
  219. if ( *name )
  220. {
  221. if ( *name++ != terminator )
  222. {
  223. stat = DN_error;
  224. node = 0;
  225. } // End of IF then
  226. else
  227. stat = DN_valid;
  228. } // End of IF then
  229. elif ( status () == DN_valid )
  230. stat = DN_truncated;
  231. } // End of IF then
  232. else
  233. stat = DN_truncated;
  234. else
  235. stat = DN_invalid;
  236. } // End of "DName" CONSTRUCTOR '(pcchar_t&,char)'
  237. DName::DName ( unsigned __int64 num )
  238. {
  239. char buf[ 21 ];
  240. char * pBuf = buf + 20;
  241. stat = DN_valid;
  242. node = 0;
  243. isIndir = 0;
  244. isAUDC = 0;
  245. isAUDTThunk = 0;
  246. isArrayType = 0;
  247. NoTE = 0;
  248. // Essentially, 'ultoa ( num, buf, 10 )' :-
  249. *pBuf = 0;
  250. do
  251. {
  252. *( --pBuf ) = (char)(( num % 10ui64 ) + '0' );
  253. num /= 10ui64;
  254. } while ( num );
  255. doPchar ( pBuf, ( 20 - (int) ( pBuf - buf )));
  256. } // End of "DName" CONSTRUCTOR '(unsigned long)'
  257. DName::DName ( __int64 num )
  258. {
  259. char buf[ 22 ];
  260. char * pBuf = buf + 21;
  261. stat = DN_valid;
  262. node = 0;
  263. isIndir = 0;
  264. isAUDC = 0;
  265. isAUDTThunk = 0;
  266. isArrayType = 0;
  267. NoTE = 0;
  268. // Essentially, 'ltoa ( num, buf, 10 )' :-
  269. *pBuf = 0;
  270. bool fSigned = false;
  271. if (num < 0) {
  272. fSigned = true;
  273. num = -num;
  274. }
  275. do
  276. {
  277. *( --pBuf ) = (char)(( num % 10ui64 ) + '0' );
  278. num /= 10ui64;
  279. } while ( num );
  280. if (fSigned) {
  281. *(--pBuf) = '-';
  282. }
  283. doPchar ( pBuf, ( 21 - (int) ( pBuf - buf )));
  284. }
  285. DName::DName ( DNameStatus st )
  286. {
  287. stat = ((( st == DN_invalid ) || ( st == DN_error )) ? st : DN_valid );
  288. node = gnew DNameStatusNode ( st );
  289. isIndir = 0;
  290. isAUDC = 0;
  291. isAUDTThunk = 0;
  292. isArrayType = 0;
  293. NoTE = 0;
  294. if ( !node )
  295. stat = DN_error;
  296. } // End of "DName" CONSTRUCTOR '(DNameStatus)'
  297. // Now the member functions for 'DName'
  298. int DName::isValid () const { return (( status () == DN_valid ) || ( status () == DN_truncated )); }
  299. int DName::isEmpty () const { return (( node == 0 ) || !isValid ()); }
  300. inline DNameStatus DName::status () const { return (DNameStatus)stat; } // The cast is to keep Glockenspiel quiet
  301. inline void DName::clearStatus () { stat = DN_valid; }
  302. inline DName & DName::setPtrRef () { isIndir = 1; return *this; }
  303. inline int DName::isPtrRef () const { return isIndir; }
  304. inline int DName::isUDC () const { return ( !isEmpty () && isAUDC ); }
  305. inline void DName::setIsUDC () { if ( !isEmpty ()) isAUDC = TRUE; }
  306. inline int DName::isUDTThunk () const { return ( !isEmpty () && isAUDTThunk ); }
  307. inline void DName::setIsUDTThunk () { if ( !isEmpty ()) isAUDTThunk = TRUE; }
  308. inline void DName::setIsArray () { isArrayType = 1; }
  309. inline int DName::isArray () const { return isArrayType; }
  310. inline int DName::isNoTE () const { return NoTE; }
  311. inline void DName::setIsNoTE () { NoTE = TRUE; }
  312. int DName::length () const
  313. {
  314. int len = 0;
  315. if ( !isEmpty ())
  316. for ( DNameNode * pNode = node; pNode; pNode = pNode->nextNode ())
  317. len += pNode->length ();
  318. return len;
  319. } // End of "DName" FUNCTION "length"
  320. char DName::getLastChar () const
  321. {
  322. DNameNode * pLast = 0;
  323. if ( !isEmpty ())
  324. for ( DNameNode * pNode = node; pNode; pNode = pNode->nextNode ())
  325. if ( pNode->length () != 0 )
  326. pLast = pNode;
  327. return pLast != 0 ? pLast->getLastChar () : '\0';
  328. } // End of "DName" FUNCTION "getLastChar"
  329. pchar_t DName::getString ( pchar_t buf, int max ) const
  330. {
  331. if ( !isEmpty ())
  332. {
  333. // Does the caller want a buffer allocated ?
  334. if ( !buf )
  335. {
  336. max = length () + 1;
  337. buf = gnew char[ max ]; // Get a buffer big enough
  338. } // End of IF then
  339. // If memory allocation failure, then return no buffer
  340. if ( buf )
  341. {
  342. // Now, go through the process of filling the buffer (until max is reached)
  343. int curLen = max;
  344. DNameNode * curNode = node;
  345. pchar_t curBuf = buf;
  346. while ( curNode && ( curLen > 0 ))
  347. {
  348. int fragLen = curNode->length ();
  349. pchar_t fragBuf = 0;
  350. // Skip empty nodes
  351. if ( fragLen )
  352. {
  353. // Handle buffer overflow
  354. if (( curLen - fragLen ) < 0 )
  355. fragLen = curLen;
  356. // Now copy 'len' number of bytes of the piece to the buffer
  357. fragBuf = curNode->getString ( curBuf, fragLen );
  358. // Should never happen, but handle it anyway
  359. if ( fragBuf )
  360. {
  361. // Update string position
  362. curLen -= fragLen;
  363. curBuf += fragLen;
  364. } // End of IF
  365. } // End of IF
  366. // Move on to the next name fragment
  367. curNode = curNode->nextNode ();
  368. } // End of WHILE
  369. *curBuf = 0; // Always NULL terminate the resulting string
  370. } // End of IF
  371. } // End of IF then
  372. elif ( buf )
  373. *buf = 0;
  374. // Return the buffer
  375. return buf;
  376. } // End of "DName" FUNCTION "getString(pchar_t,int)"
  377. DName DName::operator + ( char ch ) const
  378. {
  379. DName local ( *this );
  380. if ( local.isEmpty ())
  381. local = ch;
  382. else
  383. local += ch;
  384. // And return the newly formed 'DName'
  385. return local;
  386. } // End of "DName" OPERATOR "+(char)"
  387. DName DName::operator + ( pcchar_t str ) const
  388. {
  389. DName local ( *this );
  390. if ( local.isEmpty ())
  391. local = str;
  392. else
  393. local += str;
  394. // And return the newly formed 'DName'
  395. return local;
  396. } // End of "DName" OPERATOR "+(pcchar_t)"
  397. DName DName::operator + ( const DName & rd ) const
  398. {
  399. DName local ( *this );
  400. if ( local.isEmpty ())
  401. local = rd;
  402. elif ( rd.isEmpty ())
  403. local += rd.status ();
  404. else
  405. local += rd;
  406. // And return the newly formed 'DName'
  407. return local;
  408. } // End of "DName" OPERATOR "+(const DName&)"
  409. DName DName::operator + ( DName * pd ) const
  410. {
  411. DName local ( *this );
  412. if ( local.isEmpty ())
  413. local = pd;
  414. else
  415. local += pd;
  416. // And return the newly formed 'DName'
  417. return local;
  418. } // End of "DName" OPERATOR "+(DName*)"
  419. DName DName::operator + ( DNameStatus st ) const
  420. {
  421. DName local ( *this );
  422. if ( local.isEmpty ())
  423. local = st;
  424. else
  425. local += st;
  426. // And return the newly formed 'DName'
  427. return local;
  428. } // End of "DName" OPERATOR "+(DNameStatus)"
  429. DName & DName::operator += ( char ch )
  430. {
  431. if ( ch )
  432. if ( isEmpty ())
  433. *this = ch;
  434. else
  435. {
  436. node = node->clone ();
  437. if ( node )
  438. *node += gnew charNode ( ch );
  439. else
  440. stat = DN_error;
  441. } // End of IF
  442. // And return self
  443. return *this;
  444. } // End of "DName" OPERATOR "+=(char)"
  445. DName & DName::operator += ( pcchar_t str )
  446. {
  447. if ( str && *str )
  448. if ( isEmpty ())
  449. *this = str;
  450. else
  451. {
  452. node = node->clone ();
  453. if ( node )
  454. *node += gnew pcharNode ( str );
  455. else
  456. stat = DN_error;
  457. } // End of IF
  458. // And return self
  459. return *this;
  460. } // End of "DName" OPERATOR "+=(pcchar_t)"
  461. DName & DName::operator += ( const DName & rd )
  462. {
  463. if ( rd.isEmpty ())
  464. *this += rd.status ();
  465. else
  466. if ( isEmpty ())
  467. *this = rd;
  468. else
  469. {
  470. node = node->clone ();
  471. if ( node )
  472. *node += rd.node;
  473. else
  474. stat = DN_error;
  475. } // End of IF
  476. // And return self
  477. return *this;
  478. } // End of "DName" OPERATOR "+=(const DName&)"
  479. DName & DName::operator += ( DName * pd )
  480. {
  481. if ( pd )
  482. if ( isEmpty ())
  483. *this = pd;
  484. elif (( pd->status () == DN_valid ) || ( pd->status () == DN_truncated ))
  485. {
  486. DNameNode * pNew = gnew pDNameNode ( pd );
  487. if ( pNew )
  488. {
  489. node = node->clone ();
  490. if ( node )
  491. *node += pNew;
  492. } // End of IF then
  493. else
  494. node = 0;
  495. if ( !node )
  496. stat = DN_error;
  497. } // End of IF then
  498. else
  499. *this += pd->status ();
  500. // And return self
  501. return *this;
  502. } // End of "DName" OPERATOR "+=(DName*)"
  503. DName & DName::operator += ( DNameStatus st )
  504. {
  505. if ( isEmpty () || (( st == DN_invalid ) || ( st == DN_error )))
  506. *this = st;
  507. else
  508. {
  509. DNameNode * pNew = gnew DNameStatusNode ( st );
  510. if ( pNew )
  511. {
  512. node = node->clone ();
  513. if ( node )
  514. *node += pNew;
  515. } // End of IF then
  516. else
  517. node = 0;
  518. if ( !node )
  519. stat = DN_error;
  520. } // End of IF else
  521. // Return self
  522. return *this;
  523. } // End of "DName" OPERATOR "+=(DNameStatus)"
  524. DName & DName::operator |= ( const DName & rd )
  525. {
  526. // Attenuate the error status. Always becomes worse. Don't propogate truncation
  527. if (( status () != DN_error ) && !rd.isValid ())
  528. stat = rd.status ();
  529. // And return self
  530. return *this;
  531. } // End of "DName" OPERATOR '|=(const DName&)'
  532. DName & DName::operator = ( char ch )
  533. {
  534. isIndir = 0;
  535. isAUDC = 0;
  536. isAUDTThunk = 0;
  537. isArrayType = 0;
  538. doPchar ( &ch, 1 );
  539. return *this;
  540. } // End of "DName" OPERATOR '=(char)'
  541. DName & DName::operator = ( pcchar_t str )
  542. {
  543. isIndir = 0;
  544. isAUDC = 0;
  545. isAUDTThunk = 0;
  546. isArrayType = 0;
  547. doPchar ( str, und_strlen ( str ));
  548. // And return self
  549. return *this;
  550. } // End of "DName" OPERATOR '=(pcchar_t)'
  551. DName & DName::operator = ( const DName & rd )
  552. {
  553. if (( status () == DN_valid ) || ( status () == DN_truncated ))
  554. {
  555. stat = rd.stat;
  556. isIndir = rd.isIndir;
  557. isAUDC = rd.isAUDC;
  558. isAUDTThunk = rd.isAUDTThunk;
  559. isArrayType = rd.isArrayType;
  560. node = rd.node;
  561. } // End of IF
  562. // And return self
  563. return *this;
  564. } // End of "DName" OPERATOR '=(const DName&)'
  565. DName & DName::operator = ( DName * pd )
  566. {
  567. if (( status () == DN_valid ) || ( status () == DN_truncated ))
  568. if ( pd )
  569. {
  570. isIndir = 0;
  571. isAUDC = 0;
  572. isAUDTThunk = 0;
  573. isArrayType = 0;
  574. node = gnew pDNameNode ( pd );
  575. if ( !node )
  576. stat = DN_error;
  577. } // End of IF then
  578. else
  579. *this = DN_error;
  580. // And return self
  581. return *this;
  582. } // End of "DName" OPERATOR '=(DName*)'
  583. DName & DName::operator = ( DNameStatus st )
  584. {
  585. if (( st == DN_invalid ) || ( st == DN_error ))
  586. {
  587. node = 0;
  588. if ( status () != DN_error )
  589. stat = st;
  590. } // End of IF then
  591. elif (( status () == DN_valid ) || ( status () == DN_truncated ))
  592. {
  593. isIndir = 0;
  594. isAUDC = 0;
  595. isAUDTThunk = 0;
  596. isArrayType = 0;
  597. node = gnew DNameStatusNode ( st );
  598. if ( !node )
  599. stat = DN_error;
  600. } // End of ELIF then
  601. // And return self
  602. return *this;
  603. } // End of "DName" OPERATOR '=(DNameStatus)'
  604. // Private implementation functions for 'DName'
  605. void DName::doPchar ( pcchar_t str, int len )
  606. {
  607. if ( !(( status () == DN_invalid ) || ( status () == DN_error )))
  608. if ( node )
  609. *this = DN_error;
  610. elif ( str && len )
  611. {
  612. // Allocate as economically as possible
  613. switch ( len )
  614. {
  615. case 0:
  616. stat = DN_error;
  617. break;
  618. case 1:
  619. node = gnew charNode ( *str );
  620. if ( !node )
  621. stat = DN_error;
  622. break;
  623. default:
  624. node = gnew pcharNode ( str, len );
  625. if ( !node )
  626. stat = DN_error;
  627. break;
  628. } // End of SWITCH
  629. } // End of ELIF
  630. else
  631. stat = DN_invalid;
  632. } // End of "DName" FUNCTION "doPchar(pcchar_t,int)"
  633. // The member functions for the 'Replicator'
  634. inline int Replicator::isFull () const { return ( index == 9 ); }
  635. inline Replicator::Replicator ()
  636. : ErrorDName ( DN_error ), InvalidDName ( DN_invalid )
  637. { index = -1; }
  638. Replicator & Replicator::operator += ( const DName & rd )
  639. {
  640. if ( !isFull () && !rd.isEmpty ())
  641. {
  642. DName * pNew = gnew DName ( rd );
  643. // Don't update if failed
  644. if ( pNew )
  645. dNameBuffer[ ++index ] = pNew;
  646. } // End of IF
  647. return *this;
  648. } // End of "Replicator" OPERATOR '+=(const DName&)'
  649. const DName & Replicator::operator [] ( int x ) const
  650. {
  651. if (( x < 0 ) || ( x > 9 ))
  652. return ErrorDName;
  653. elif (( index == -1 ) || ( x > index ))
  654. return InvalidDName;
  655. else
  656. return *dNameBuffer[ x ];
  657. } // End of "Replicator" OPERATOR '[](int)'
  658. // The member functions for the 'DNameNode' classes
  659. #if ( !NO_VIRTUAL )
  660. DNameNode::DNameNode ()
  661. #else // } elif NO_VIRTUAL {
  662. DNameNode::DNameNode ( NodeType ndTy )
  663. : typeIndex ( ndTy )
  664. #endif // NO_VIRTUAL
  665. { next = 0; }
  666. inline DNameNode::DNameNode ( const DNameNode & rd ) { next = (( rd.next ) ? rd.next->clone () : 0 ); }
  667. inline DNameNode * DNameNode::nextNode () const { return next; }
  668. DNameNode * DNameNode::clone ()
  669. {
  670. return gnew pDNameNode ( gnew DName ( this ));
  671. }
  672. #if ( NO_VIRTUAL )
  673. int DNameNode::length () const
  674. { // Pure function, should not be called
  675. switch ( typeIndex )
  676. {
  677. case charNode_t:
  678. return ((charNode*)this )->length ();
  679. case pcharNode_t:
  680. return ((pcharNode*)this )->length ();
  681. case pDNameNode_t:
  682. return ((pDNameNode*)this )->length ();
  683. case DNameStatusNode_t:
  684. return ((DNameStatusNode*)this )->length ();
  685. } // End of SWITCH
  686. return 0;
  687. }
  688. char DNameNode::getLastChar () const
  689. { // Pure function, should not be called
  690. switch ( typeIndex )
  691. {
  692. case charNode_t:
  693. return ((charNode*)this )->getLastChar ();
  694. case pcharNode_t:
  695. return ((pcharNode*)this )->getLastChar ();
  696. case pDNameNode_t:
  697. return ((pDNameNode*)this )->getLastChar ();
  698. case DNameStatusNode_t:
  699. return ((DNameStatusNode*)this )->getLastChar ();
  700. } // End of SWITCH
  701. return 0;
  702. }
  703. pchar_t DNameNode::getString ( pchar_t s, int l ) const
  704. { // Pure function, should not be called
  705. switch ( typeIndex )
  706. {
  707. case charNode_t:
  708. return ((charNode*)this )->getString ( s, l );
  709. case pcharNode_t:
  710. return ((pcharNode*)this )->getString ( s, l );
  711. case pDNameNode_t:
  712. return ((pDNameNode*)this )->getString ( s, l );
  713. case DNameStatusNode_t:
  714. return ((DNameStatusNode*)this )->getString ( s, l );
  715. } // End of SWITCH
  716. return 0;
  717. }
  718. #endif // NO_VIRTUAL
  719. DNameNode & DNameNode::operator += ( DNameNode * pNode )
  720. {
  721. if ( pNode )
  722. {
  723. if ( next )
  724. {
  725. // Skip to the end of the chain
  726. DNameNode* pScan;
  727. for ( pScan = next; pScan->next; pScan = pScan->next )
  728. ;
  729. // And append the new node
  730. pScan->next = pNode;
  731. } // End of IF then
  732. else
  733. next = pNode;
  734. } // End of IF
  735. // And return self
  736. return *this;
  737. } // End of "DNameNode" OPERATOR '+=(DNameNode*)'
  738. // The 'charNode' virtual functions
  739. charNode::charNode ( char ch )
  740. #if ( NO_VIRTUAL )
  741. : DNameNode ( charNode_t )
  742. #endif // NO_VIRTUAL
  743. { me = ch; }
  744. inline int charNode::length () const { return 1; }
  745. inline char charNode::getLastChar () const { return me; }
  746. pchar_t charNode::getString ( pchar_t buf, int len ) const
  747. {
  748. if ( buf && len )
  749. *buf = me;
  750. else
  751. buf = 0;
  752. // Now return the character
  753. return buf;
  754. } // End of "charNode" FUNCTION "getString(pchar_t,int)"
  755. // The 'pcharNode' virtual functions
  756. inline int pcharNode::length () const { return myLen; }
  757. inline char pcharNode::getLastChar () const { return ( myLen ? me[ myLen - 1 ] : '\0' ); }
  758. pcharNode::pcharNode ( pcchar_t str, int len )
  759. #if ( NO_VIRTUAL )
  760. : DNameNode ( pcharNode_t )
  761. #endif // NO_VIRTUAL
  762. {
  763. // Get length if not supplied
  764. if ( !len && str )
  765. len = und_strlen ( str );
  766. // Allocate a new string buffer if valid state
  767. if ( len && str )
  768. {
  769. me = gnew char[ len ];
  770. myLen = len;
  771. if ( me )
  772. und_strncpy ( me, str, len );
  773. } // End of IF then
  774. else
  775. {
  776. me = 0;
  777. myLen = 0;
  778. } // End of IF else
  779. } // End of "pcharNode" CONSTRUCTOR '(pcchar_t,int)'
  780. pchar_t pcharNode::getString ( pchar_t buf, int len ) const
  781. {
  782. // Use the shorter of the two lengths (may not be NULL terminated)
  783. if ( len > pcharNode::length ())
  784. len = pcharNode::length ();
  785. // Do the copy as appropriate
  786. return (( me && buf && len ) ? und_strncpy ( buf, me, len ) : 0 );
  787. } // End of "pcharNode" FUNCTION "getString(pchar_t,int)"
  788. // The 'pDNameNode' virtual functions
  789. pDNameNode::pDNameNode ( DName * pName )
  790. #if ( NO_VIRTUAL )
  791. : DNameNode ( pDNameNode_t )
  792. #endif // NO_VIRTUAL
  793. { me = (( pName && (( pName->status () == DN_invalid ) || ( pName->status () == DN_error ))) ? 0 : pName ); }
  794. inline int pDNameNode::length () const { return ( me ? me->length () : 0 ); }
  795. inline char pDNameNode::getLastChar () const { return ( me ? me->getLastChar () : '\0' ); }
  796. pchar_t pDNameNode::getString ( pchar_t buf, int len ) const
  797. { return (( me && buf && len ) ? me->getString ( buf, len ) : 0 ); }
  798. // The 'DNameStatusNode' virtual functions
  799. DNameStatusNode::DNameStatusNode ( DNameStatus stat )
  800. #if ( NO_VIRTUAL )
  801. : DNameNode ( DNameStatusNode_t )
  802. #endif // NO_VIRTUAL
  803. { me = stat; myLen = (( me == DN_truncated ) ? TruncationMessageLength : 0 ); }
  804. inline int DNameStatusNode::length () const { return myLen; }
  805. inline char DNameStatusNode::getLastChar () const
  806. { return (( me == DN_truncated ) ? TruncationMessage[ TruncationMessageLength - 1 ] : '\0' ); }
  807. pchar_t DNameStatusNode::getString ( pchar_t buf, int len ) const
  808. {
  809. // Use the shorter of the two lengths (may not be NULL terminated)
  810. if ( len > DNameStatusNode::length ())
  811. len = DNameStatusNode::length ();
  812. // Do the copy as appropriate
  813. return ((( me == DN_truncated ) && buf && len ) ? und_strncpy ( buf, TruncationMessage, len ) : 0 );
  814. } // End of "DNameStatusNode" FUNCTION "getString(pchar_t,int)"
  815. static unsigned int und_strlen ( pcchar_t str )
  816. {
  817. unsigned int len;
  818. for ( len = 0; *str; str++ )
  819. len++;
  820. return len;
  821. } // End of FUNCTION "und_strlen"
  822. static pchar_t und_strncpy ( pchar_t dst, pcchar_t src, unsigned int len )
  823. {
  824. for ( char * d = dst; ( len && ( *d = *src )); d++, src++, len-- )
  825. ;
  826. return dst;
  827. } // End of FUNCTION "und_strncpy"
  828. static unsigned int und_strncmp ( pcchar_t first, pcchar_t last, unsigned int count)
  829. {
  830. if (!count)
  831. return(0);
  832. while (--count && *first && *first == *last)
  833. {
  834. first++;
  835. last++;
  836. }
  837. return( *(unsigned char *)first - *(unsigned char *)last );
  838. }