wwstring.h 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735
  1. /*
  2. ** Command & Conquer Generals(tm)
  3. ** Copyright 2025 Electronic Arts Inc.
  4. **
  5. ** This program is free software: you can redistribute it and/or modify
  6. ** it under the terms of the GNU General Public License as published by
  7. ** the Free Software Foundation, either version 3 of the License, or
  8. ** (at your option) any later version.
  9. **
  10. ** This program is distributed in the hope that it will be useful,
  11. ** but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. ** GNU General Public License for more details.
  14. **
  15. ** You should have received a copy of the GNU General Public License
  16. ** along with this program. If not, see <http://www.gnu.org/licenses/>.
  17. */
  18. /***********************************************************************************************
  19. *** C O N F I D E N T I A L --- W E S T W O O D S T U D I O S ***
  20. ***********************************************************************************************
  21. * *
  22. * Project Name : WWSaveLoad *
  23. * *
  24. * $Archive:: /Commando/Code/wwlib/wwstring.h $*
  25. * *
  26. * Author:: Patrick Smith *
  27. * *
  28. * $Modtime:: 8/28/01 11:43a $*
  29. * *
  30. * $Revision:: 30 $*
  31. * *
  32. *---------------------------------------------------------------------------------------------*
  33. * Functions: *
  34. * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
  35. #if defined(_MSC_VER)
  36. #pragma once
  37. #endif
  38. #ifndef __WWSTRING_H
  39. #define __WWSTRING_H
  40. #include "always.h"
  41. #include "mutex.h"
  42. #include <string.h>
  43. #include <stdarg.h>
  44. #include <tchar.h>
  45. #include <wwdebug.h>
  46. #ifdef _UNIX
  47. #include "osdep.h"
  48. #endif
  49. //////////////////////////////////////////////////////////////////////
  50. //
  51. // StringClass
  52. //
  53. // Note: This class is UNICODE friendly. That means it can be
  54. // compiled using either single-byte or double-byte strings. There
  55. // are no assumptions made as to the size of a character.
  56. //
  57. // Any method that takes a parameter with the word 'len' or 'length'
  58. // in it refers to a count of characters. If the name contains 'byte'
  59. // it is talking about the memory size.
  60. //
  61. //////////////////////////////////////////////////////////////////////
  62. class StringClass
  63. {
  64. public:
  65. ////////////////////////////////////////////////////////////
  66. // Public constructors/destructors
  67. ////////////////////////////////////////////////////////////
  68. StringClass (bool hint_temporary);
  69. StringClass (int initial_len = 0, bool hint_temporary = false);
  70. StringClass (const StringClass &string, bool hint_temporary = false);
  71. StringClass (const TCHAR *string, bool hint_temporary = false);
  72. StringClass (TCHAR ch, bool hint_temporary = false);
  73. ~StringClass (void);
  74. ////////////////////////////////////////////////////////////
  75. // Public operators
  76. ////////////////////////////////////////////////////////////
  77. bool operator== (const TCHAR *rvalue) const;
  78. bool operator!= (const TCHAR *rvalue) const;
  79. inline const StringClass &operator= (const StringClass &string);
  80. inline const StringClass &operator= (const TCHAR *string);
  81. inline const StringClass &operator= (TCHAR ch);
  82. const StringClass &operator+= (const StringClass &string);
  83. const StringClass &operator+= (const TCHAR *string);
  84. const StringClass &operator+= (TCHAR ch);
  85. friend StringClass operator+ (const StringClass &string1, const StringClass &string2);
  86. friend StringClass operator+ (const TCHAR *string1, const StringClass &string2);
  87. friend StringClass operator+ (const StringClass &string1, const TCHAR *string2);
  88. bool operator < (const TCHAR *string) const;
  89. bool operator <= (const TCHAR *string) const;
  90. bool operator > (const TCHAR *string) const;
  91. bool operator >= (const TCHAR *string) const;
  92. const TCHAR & operator[] (int index) const;
  93. TCHAR & operator[] (int index);
  94. inline operator const TCHAR * (void) const;
  95. ////////////////////////////////////////////////////////////
  96. // Public methods
  97. ////////////////////////////////////////////////////////////
  98. int Compare (const TCHAR *string) const;
  99. int Compare_No_Case (const TCHAR *string) const;
  100. inline int Get_Length (void) const;
  101. bool Is_Empty (void) const;
  102. void Erase (int start_index, int char_count);
  103. int _cdecl Format (const TCHAR *format, ...);
  104. int _cdecl Format_Args (const TCHAR *format, const va_list & arg_list );
  105. TCHAR * Get_Buffer (int new_length);
  106. TCHAR * Peek_Buffer (void);
  107. const TCHAR * Peek_Buffer (void) const;
  108. ////////////////////////////////////////////////////////////
  109. // Static methods
  110. ////////////////////////////////////////////////////////////
  111. void Release_Resources (void); //why was this static? -MW
  112. private:
  113. ////////////////////////////////////////////////////////////
  114. // Private structures
  115. ////////////////////////////////////////////////////////////
  116. typedef struct _HEADER
  117. {
  118. int allocated_length;
  119. int length;
  120. } HEADER;
  121. ////////////////////////////////////////////////////////////
  122. // Private constants
  123. ////////////////////////////////////////////////////////////
  124. // Note: Don't change these enums without withs checking the Get_String() and Free_String() function!
  125. enum
  126. {
  127. MAX_TEMP_STRING = 8,
  128. MAX_TEMP_LEN = 256-sizeof(_HEADER),
  129. MAX_TEMP_BYTES = (MAX_TEMP_LEN * sizeof (TCHAR)) + sizeof (HEADER),
  130. ALL_TEMP_STRINGS_USED_MASK = 0xff
  131. };
  132. ////////////////////////////////////////////////////////////
  133. // Private methods
  134. ////////////////////////////////////////////////////////////
  135. void Get_String (int length, bool is_temp);
  136. TCHAR * Allocate_Buffer (int length);
  137. void Resize (int size);
  138. void Uninitialised_Grow (int length);
  139. void Free_String (void);
  140. inline void Store_Length (int length);
  141. inline void Store_Allocated_Length (int allocated_length);
  142. inline HEADER * Get_Header (void) const;
  143. int Get_Allocated_Length (void) const;
  144. void Set_Buffer_And_Allocated_Length (TCHAR *buffer, int length);
  145. ////////////////////////////////////////////////////////////
  146. // Private member data
  147. ////////////////////////////////////////////////////////////
  148. TCHAR * m_Buffer;
  149. ////////////////////////////////////////////////////////////
  150. // Static member data
  151. ////////////////////////////////////////////////////////////
  152. static unsigned ReservedMask;
  153. static char m_TempStrings[];
  154. static CriticalSectionClass m_Mutex;
  155. static TCHAR m_NullChar;
  156. static TCHAR * m_EmptyString;
  157. };
  158. ///////////////////////////////////////////////////////////////////
  159. // operator=
  160. ///////////////////////////////////////////////////////////////////
  161. inline const StringClass &
  162. StringClass::operator= (const StringClass &string)
  163. {
  164. // return operator= ((const TCHAR *)string);
  165. int len = string.Get_Length();
  166. Uninitialised_Grow(len+1);
  167. Store_Length(len);
  168. ::memcpy (m_Buffer, string.m_Buffer, (len+1) * sizeof (TCHAR));
  169. return (*this);
  170. }
  171. ///////////////////////////////////////////////////////////////////
  172. // operator=
  173. ///////////////////////////////////////////////////////////////////
  174. inline const StringClass &
  175. StringClass::operator= (const TCHAR *string)
  176. {
  177. if (string != 0) {
  178. int len = _tcslen (string);
  179. Uninitialised_Grow (len+1);
  180. Store_Length (len);
  181. ::memcpy (m_Buffer, string, (len + 1) * sizeof (TCHAR));
  182. }
  183. return (*this);
  184. }
  185. ///////////////////////////////////////////////////////////////////
  186. // operator=
  187. ///////////////////////////////////////////////////////////////////
  188. inline const StringClass &
  189. StringClass::operator= (TCHAR ch)
  190. {
  191. Uninitialised_Grow (2);
  192. m_Buffer[0] = ch;
  193. m_Buffer[1] = m_NullChar;
  194. Store_Length (1);
  195. return (*this);
  196. }
  197. ///////////////////////////////////////////////////////////////////
  198. // StringClass
  199. ///////////////////////////////////////////////////////////////////
  200. inline
  201. StringClass::StringClass (bool hint_temporary)
  202. : m_Buffer (m_EmptyString)
  203. {
  204. Get_String (MAX_TEMP_LEN, hint_temporary);
  205. m_Buffer[0] = m_NullChar;
  206. return ;
  207. }
  208. ///////////////////////////////////////////////////////////////////
  209. // StringClass
  210. ///////////////////////////////////////////////////////////////////
  211. inline
  212. StringClass::StringClass (int initial_len, bool hint_temporary)
  213. : m_Buffer (m_EmptyString)
  214. {
  215. Get_String (initial_len, hint_temporary);
  216. m_Buffer[0] = m_NullChar;
  217. return ;
  218. }
  219. ///////////////////////////////////////////////////////////////////
  220. // StringClass
  221. ///////////////////////////////////////////////////////////////////
  222. inline
  223. StringClass::StringClass (TCHAR ch, bool hint_temporary)
  224. : m_Buffer (m_EmptyString)
  225. {
  226. Get_String (2, hint_temporary);
  227. (*this) = ch;
  228. return ;
  229. }
  230. ///////////////////////////////////////////////////////////////////
  231. // StringClass
  232. ///////////////////////////////////////////////////////////////////
  233. inline
  234. StringClass::StringClass (const StringClass &string, bool hint_temporary)
  235. : m_Buffer (m_EmptyString)
  236. {
  237. if (hint_temporary || (string.Get_Length()>0)) {
  238. Get_String (string.Get_Length()+1, hint_temporary);
  239. }
  240. (*this) = string;
  241. return ;
  242. }
  243. ///////////////////////////////////////////////////////////////////
  244. // StringClass
  245. ///////////////////////////////////////////////////////////////////
  246. inline
  247. StringClass::StringClass (const TCHAR *string, bool hint_temporary)
  248. : m_Buffer (m_EmptyString)
  249. {
  250. int len=string ? _tcsclen(string) : 0;
  251. if (hint_temporary || len>0) {
  252. Get_String (len+1, hint_temporary);
  253. }
  254. (*this) = string;
  255. return ;
  256. }
  257. ///////////////////////////////////////////////////////////////////
  258. // ~StringClass
  259. ///////////////////////////////////////////////////////////////////
  260. inline
  261. StringClass::~StringClass (void)
  262. {
  263. Free_String ();
  264. return ;
  265. }
  266. ///////////////////////////////////////////////////////////////////
  267. // Is_Empty
  268. ///////////////////////////////////////////////////////////////////
  269. inline bool
  270. StringClass::Is_Empty (void) const
  271. {
  272. return (m_Buffer[0] == m_NullChar);
  273. }
  274. ///////////////////////////////////////////////////////////////////
  275. // Compare
  276. ///////////////////////////////////////////////////////////////////
  277. inline int
  278. StringClass::Compare (const TCHAR *string) const
  279. {
  280. return _tcscmp (m_Buffer, string);
  281. }
  282. ///////////////////////////////////////////////////////////////////
  283. // Compare_No_Case
  284. ///////////////////////////////////////////////////////////////////
  285. inline int
  286. StringClass::Compare_No_Case (const TCHAR *string) const
  287. {
  288. return _tcsicmp (m_Buffer, string);
  289. }
  290. ///////////////////////////////////////////////////////////////////
  291. // operator[]
  292. ///////////////////////////////////////////////////////////////////
  293. inline const TCHAR &
  294. StringClass::operator[] (int index) const
  295. {
  296. WWASSERT (index >= 0 && index < Get_Length ());
  297. return m_Buffer[index];
  298. }
  299. ///////////////////////////////////////////////////////////////////
  300. // operator[]
  301. ///////////////////////////////////////////////////////////////////
  302. inline TCHAR &
  303. StringClass::operator[] (int index)
  304. {
  305. WWASSERT (index >= 0 && index < Get_Length ());
  306. return m_Buffer[index];
  307. }
  308. ///////////////////////////////////////////////////////////////////
  309. // operator const TCHAR *
  310. ///////////////////////////////////////////////////////////////////
  311. inline
  312. StringClass::operator const TCHAR * (void) const
  313. {
  314. return m_Buffer;
  315. }
  316. ///////////////////////////////////////////////////////////////////
  317. // operator==
  318. ///////////////////////////////////////////////////////////////////
  319. inline bool
  320. StringClass::operator== (const TCHAR *rvalue) const
  321. {
  322. return (Compare (rvalue) == 0);
  323. }
  324. ///////////////////////////////////////////////////////////////////
  325. // operator!=
  326. ///////////////////////////////////////////////////////////////////
  327. inline bool
  328. StringClass::operator!= (const TCHAR *rvalue) const
  329. {
  330. return (Compare (rvalue) != 0);
  331. }
  332. ///////////////////////////////////////////////////////////////////
  333. // operator <
  334. ///////////////////////////////////////////////////////////////////
  335. inline bool
  336. StringClass::operator < (const TCHAR *string) const
  337. {
  338. return (_tcscmp (m_Buffer, string) < 0);
  339. }
  340. ///////////////////////////////////////////////////////////////////
  341. // operator <=
  342. ///////////////////////////////////////////////////////////////////
  343. inline bool
  344. StringClass::operator <= (const TCHAR *string) const
  345. {
  346. return (_tcscmp (m_Buffer, string) <= 0);
  347. }
  348. ///////////////////////////////////////////////////////////////////
  349. // operator >
  350. ///////////////////////////////////////////////////////////////////
  351. inline bool
  352. StringClass::operator > (const TCHAR *string) const
  353. {
  354. return (_tcscmp (m_Buffer, string) > 0);
  355. }
  356. ///////////////////////////////////////////////////////////////////
  357. // operator >=
  358. ///////////////////////////////////////////////////////////////////
  359. inline bool
  360. StringClass::operator >= (const TCHAR *string) const
  361. {
  362. return (_tcscmp (m_Buffer, string) >= 0);
  363. }
  364. ///////////////////////////////////////////////////////////////////
  365. // Erase
  366. ///////////////////////////////////////////////////////////////////
  367. inline void
  368. StringClass::Erase (int start_index, int char_count)
  369. {
  370. int len = Get_Length ();
  371. if (start_index < len) {
  372. if (start_index + char_count > len) {
  373. char_count = len - start_index;
  374. }
  375. ::memmove ( &m_Buffer[start_index],
  376. &m_Buffer[start_index + char_count],
  377. (len - (start_index + char_count) + 1) * sizeof (TCHAR));
  378. Store_Length( len - char_count );
  379. }
  380. return ;
  381. }
  382. ///////////////////////////////////////////////////////////////////
  383. // operator+=
  384. ///////////////////////////////////////////////////////////////////
  385. inline const StringClass &
  386. StringClass::operator+= (const TCHAR *string)
  387. {
  388. WWASSERT (string != NULL);
  389. int cur_len = Get_Length ();
  390. int src_len = _tcslen (string);
  391. int new_len = cur_len + src_len;
  392. //
  393. // Make sure our buffer is large enough to hold the new string
  394. //
  395. Resize (new_len + 1);
  396. Store_Length (new_len);
  397. //
  398. // Copy the new string onto our the end of our existing buffer
  399. //
  400. ::memcpy (&m_Buffer[cur_len], string, (src_len + 1) * sizeof (TCHAR));
  401. return (*this);
  402. }
  403. ///////////////////////////////////////////////////////////////////
  404. // operator+=
  405. ///////////////////////////////////////////////////////////////////
  406. inline const StringClass &
  407. StringClass::operator+= (TCHAR ch)
  408. {
  409. int cur_len = Get_Length ();
  410. Resize (cur_len + 2);
  411. m_Buffer[cur_len] = ch;
  412. m_Buffer[cur_len + 1] = m_NullChar;
  413. if (ch != m_NullChar) {
  414. Store_Length (cur_len + 1);
  415. }
  416. return (*this);
  417. }
  418. ///////////////////////////////////////////////////////////////////
  419. // Get_Buffer
  420. ///////////////////////////////////////////////////////////////////
  421. inline TCHAR *
  422. StringClass::Get_Buffer (int new_length)
  423. {
  424. Uninitialised_Grow (new_length);
  425. return m_Buffer;
  426. }
  427. ///////////////////////////////////////////////////////////////////
  428. // Peek_Buffer
  429. ///////////////////////////////////////////////////////////////////
  430. inline TCHAR *
  431. StringClass::Peek_Buffer (void)
  432. {
  433. return m_Buffer;
  434. }
  435. ///////////////////////////////////////////////////////////////////
  436. // Peek_Buffer
  437. ///////////////////////////////////////////////////////////////////
  438. inline const TCHAR *
  439. StringClass::Peek_Buffer (void) const
  440. {
  441. return m_Buffer;
  442. }
  443. ///////////////////////////////////////////////////////////////////
  444. // operator+=
  445. ///////////////////////////////////////////////////////////////////
  446. inline const StringClass &
  447. StringClass::operator+= (const StringClass &string)
  448. {
  449. int src_len = string.Get_Length();
  450. if (src_len > 0) {
  451. int cur_len = Get_Length ();
  452. int new_len = cur_len + src_len;
  453. //
  454. // Make sure our buffer is large enough to hold the new string
  455. //
  456. Resize (new_len + 1);
  457. Store_Length (new_len);
  458. //
  459. // Copy the new string onto our the end of our existing buffer
  460. //
  461. ::memcpy (&m_Buffer[cur_len], (const TCHAR *)string, (src_len + 1) * sizeof (TCHAR));
  462. }
  463. return (*this);
  464. }
  465. ///////////////////////////////////////////////////////////////////
  466. // operator+=
  467. ///////////////////////////////////////////////////////////////////
  468. inline StringClass
  469. operator+ (const StringClass &string1, const StringClass &string2)
  470. {
  471. StringClass new_string(string1, true);
  472. new_string += string2;
  473. return new_string;
  474. }
  475. ///////////////////////////////////////////////////////////////////
  476. // operator+=
  477. ///////////////////////////////////////////////////////////////////
  478. inline StringClass
  479. operator+ (const TCHAR *string1, const StringClass &string2)
  480. {
  481. StringClass new_string(string1, true);
  482. new_string += string2;
  483. return new_string;
  484. }
  485. ///////////////////////////////////////////////////////////////////
  486. // operator+=
  487. ///////////////////////////////////////////////////////////////////
  488. inline StringClass
  489. operator+ (const StringClass &string1, const TCHAR *string2)
  490. {
  491. StringClass new_string(string1, true);
  492. new_string += string2;
  493. return new_string;
  494. }
  495. ///////////////////////////////////////////////////////////////////
  496. // Get_Allocated_Length
  497. //
  498. // Return allocated size of the string buffer
  499. ///////////////////////////////////////////////////////////////////
  500. inline int
  501. StringClass::Get_Allocated_Length (void) const
  502. {
  503. int allocated_length = 0;
  504. //
  505. // Read the allocated length from the header
  506. //
  507. if (m_Buffer != m_EmptyString) {
  508. HEADER *header = Get_Header ();
  509. allocated_length = header->allocated_length;
  510. }
  511. return allocated_length;
  512. }
  513. ///////////////////////////////////////////////////////////////////
  514. // Get_Length
  515. //
  516. // Return text legth. If length is not known calculate it, otherwise
  517. // just return the previously stored value (strlen tends to take
  518. // quite a lot cpu time if a lot of string combining operations are
  519. // performed.
  520. ///////////////////////////////////////////////////////////////////
  521. inline int
  522. StringClass::Get_Length (void) const
  523. {
  524. int length = 0;
  525. if (m_Buffer != m_EmptyString) {
  526. //
  527. // Read the length from the header
  528. //
  529. HEADER *header = Get_Header ();
  530. length = header->length;
  531. //
  532. // Hmmm, a zero length was stored in the header,
  533. // we better manually get the string length.
  534. //
  535. if (length == 0) {
  536. length = _tcslen (m_Buffer);
  537. ((StringClass *)this)->Store_Length (length);
  538. }
  539. }
  540. return length;
  541. }
  542. ///////////////////////////////////////////////////////////////////
  543. // Set_Buffer_And_Allocated_Length
  544. //
  545. // Set buffer pointer and init size variable. Length is set to 0
  546. // as the contents of the new buffer are not necessarily defined.
  547. ///////////////////////////////////////////////////////////////////
  548. inline void
  549. StringClass::Set_Buffer_And_Allocated_Length (TCHAR *buffer, int length)
  550. {
  551. Free_String ();
  552. m_Buffer = buffer;
  553. //
  554. // Update the header (if necessary)
  555. //
  556. if (m_Buffer != m_EmptyString) {
  557. Store_Allocated_Length (length);
  558. Store_Length (0);
  559. } else {
  560. WWASSERT (length == 0);
  561. }
  562. return ;
  563. }
  564. ///////////////////////////////////////////////////////////////////
  565. // Allocate_Buffer
  566. ///////////////////////////////////////////////////////////////////
  567. inline TCHAR *
  568. StringClass::Allocate_Buffer (int length)
  569. {
  570. //
  571. // Allocate a buffer that is 'length' characters long, plus the
  572. // bytes required to hold the header.
  573. //
  574. char *buffer = W3DNEWARRAY char[(sizeof (TCHAR) * length) + sizeof (StringClass::_HEADER)];
  575. //
  576. // Fill in the fields of the header
  577. //
  578. HEADER *header = reinterpret_cast<HEADER *>(buffer);
  579. header->length = 0;
  580. header->allocated_length = length;
  581. //
  582. // Return the buffer as if it was a TCHAR pointer
  583. //
  584. return reinterpret_cast<TCHAR *>(buffer + sizeof (StringClass::_HEADER));
  585. }
  586. ///////////////////////////////////////////////////////////////////
  587. // Get_Header
  588. ///////////////////////////////////////////////////////////////////
  589. inline StringClass::HEADER *
  590. StringClass::Get_Header (void) const
  591. {
  592. return reinterpret_cast<HEADER *>(((char *)m_Buffer) - sizeof (StringClass::_HEADER));
  593. }
  594. ///////////////////////////////////////////////////////////////////
  595. // Store_Allocated_Length
  596. ///////////////////////////////////////////////////////////////////
  597. inline void
  598. StringClass::Store_Allocated_Length (int allocated_length)
  599. {
  600. if (m_Buffer != m_EmptyString) {
  601. HEADER *header = Get_Header ();
  602. header->allocated_length = allocated_length;
  603. } else {
  604. WWASSERT (allocated_length == 0);
  605. }
  606. return ;
  607. }
  608. ///////////////////////////////////////////////////////////////////
  609. // Store_Length
  610. //
  611. // Set length... The caller of this (private) function better
  612. // be sure that the len is correct.
  613. ///////////////////////////////////////////////////////////////////
  614. inline void
  615. StringClass::Store_Length (int length)
  616. {
  617. if (m_Buffer != m_EmptyString) {
  618. HEADER *header = Get_Header ();
  619. header->length = length;
  620. } else {
  621. WWASSERT (length == 0);
  622. }
  623. return ;
  624. }
  625. #endif //__WWSTRING_H