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.

323 lines
5.8 KiB

  1. //+-------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. //
  5. // Copyright (C) Microsoft Corporation, 1999 - 1999
  6. //
  7. // File: combstr.h
  8. //
  9. //--------------------------------------------------------------------------
  10. #ifndef COMBSTR_H
  11. #define COMBSTR_H
  12. #ifndef BOOL_H
  13. #include <bool.h>
  14. #endif
  15. #ifndef STRCONV_H
  16. #include <strconv.h>
  17. #endif
  18. namespace microsoft {
  19. namespace com {
  20. class bstr
  21. //REVIEW: need to add support for copy-on-write iterators.
  22. {
  23. public: bstr() throw()
  24. : m_Data(NULL)
  25. {
  26. }
  27. public: bstr(const bstr& s) throw()
  28. : m_Data(s.m_Data)
  29. {
  30. _AddRef();
  31. }
  32. public: bstr(const char* s) throw()
  33. : m_Data(new Data(s))
  34. {
  35. ASSERT(m_Data);
  36. }
  37. public: bstr(const wchar_t* s) throw()
  38. : m_Data(new Data(s))
  39. {
  40. }
  41. public: ~bstr() throw()
  42. {
  43. _Free();
  44. }
  45. public: bstr& operator=(const bstr& s) throw()
  46. {
  47. _Free();
  48. m_Data = s.m_Data;
  49. _AddRef();
  50. return *this;
  51. }
  52. public: bstr& operator=(const char* s) throw()
  53. {
  54. _Free();
  55. m_Data = new Data(s);
  56. return *this;
  57. }
  58. public: bstr& operator=(const wchar_t* s) throw()
  59. {
  60. _Free();
  61. m_Data = new Data(s);
  62. return *this;
  63. }
  64. public: bstr& operator+=(const bstr& s) throw()
  65. {
  66. Data* newData = new Data(*this, s);
  67. ASSERT(newData);
  68. _Free();
  69. m_Data = newData;
  70. return *this;
  71. }
  72. public: bstr operator+(const bstr& s) const throw()
  73. {
  74. bstr b = *this;
  75. b += s;
  76. return b;
  77. }
  78. public: operator const wchar_t*() const throw()
  79. {
  80. return m_Data ? m_Data->GetWString() : NULL;
  81. }
  82. public: operator const char*() const throw()
  83. {
  84. return m_Data ? m_Data->GetString() : NULL;
  85. }
  86. public: bool operator!() const throw()
  87. {
  88. return m_Data ? !m_Data->GetWString() : true;
  89. }
  90. public: bool operator==(const bstr& str) const throw()
  91. {
  92. return _Compare(str) == 0;
  93. }
  94. public: bool operator!=(const bstr& str) const throw()
  95. {
  96. return _Compare(str) != 0;
  97. }
  98. public: bool operator<(const bstr& str) const throw()
  99. {
  100. return _Compare(str) < 0;
  101. }
  102. public: bool operator>(const bstr& str) const throw()
  103. {
  104. return _Compare(str) > 0;
  105. }
  106. public: bool operator<=(const bstr& str) const throw()
  107. {
  108. return _Compare(str) <= 0;
  109. }
  110. public: bool operator>=(const bstr& str) const throw()
  111. {
  112. return _Compare(str) >= 0;
  113. }
  114. public: BSTR copy() const throw()
  115. {
  116. return m_Data ? m_Data->Copy() : NULL;
  117. }
  118. public: unsigned int length() const throw()
  119. {
  120. return m_Data ? m_Data->length() : 0;
  121. }
  122. //REVIEW: create size(of)()
  123. private: class Data
  124. {
  125. public: Data(const char* s) throw()
  126. : m_str(NULL), m_RefCount(1)
  127. {
  128. if (s)
  129. {
  130. m_wstr = str2BSTR(s);
  131. ASSERT(m_wstr);
  132. }
  133. else m_wstr = NULL;
  134. }
  135. public: Data(const wchar_t* s) throw()
  136. : m_str(NULL), m_RefCount(1)
  137. {
  138. if (s)
  139. {
  140. m_wstr = wcs2BSTR(s);
  141. ASSERT(m_wstr);
  142. }
  143. else m_wstr = NULL;
  144. }
  145. public: Data(const bstr& s1, const bstr& s2)
  146. : m_str(NULL), m_RefCount(1)
  147. {
  148. const unsigned int l1 = s1.length();
  149. const unsigned int l2 = s2.length();
  150. m_wstr=SysAllocStringLen(s1, l1+l2);
  151. ASSERT(m_wstr);
  152. memcpy(m_wstr+l1, static_cast<const wchar_t*>(s2), l2+1);
  153. }
  154. public: unsigned long AddRef() throw()
  155. {
  156. ASSERT(m_RefCount);
  157. InterlockedIncrement(reinterpret_cast<long*>(&m_RefCount));
  158. return m_RefCount;
  159. }
  160. public: unsigned long Release() throw()
  161. {
  162. ASSERT(m_RefCount);
  163. //REVIEW: may not want InterlockedDecrement for simple speed cases?
  164. if (!InterlockedDecrement(reinterpret_cast<long*>(&m_RefCount)))
  165. delete this;
  166. return m_RefCount;
  167. }
  168. public: operator const wchar_t*() const throw()
  169. {
  170. return m_wstr;
  171. }
  172. public: operator const char*() const throw()
  173. {
  174. return GetString();
  175. }
  176. public: const wchar_t* GetWString() const throw()
  177. {
  178. return m_wstr;
  179. }
  180. public: const char* GetString() const throw()
  181. {
  182. if (!m_str && m_wstr)
  183. {
  184. USES_STRCONV;
  185. const unsigned int len=SysStringLen(m_wstr)+1;
  186. #if _MSC_VER >= 1100
  187. m_str = new char[len];
  188. ASSERT(m_str);
  189. memcpy(m_str, WCS2STR(m_wstr), len);
  190. #else //REVIEW: Strip after v5 ships
  191. const_cast<Data*>(this)->m_str = new char[len];
  192. ASSERT(m_str);
  193. memcpy(const_cast<Data*>(this)->m_str, WCS2STR(m_wstr), len);
  194. #endif // _MSC_VER >= 1100
  195. }
  196. return m_str;
  197. }
  198. public: BSTR Copy() const throw()
  199. {
  200. return m_wstr ? SysAllocStringLen(m_wstr, SysStringLen(m_wstr)) : NULL;
  201. }
  202. public: unsigned int length()
  203. {
  204. return m_wstr ? SysStringLen(m_wstr) : 0;
  205. }
  206. private: wchar_t* m_wstr;
  207. private: mutable char* m_str;
  208. private: unsigned long m_RefCount;
  209. private: Data()
  210. // Never allow default construction
  211. {
  212. }
  213. private: Data(const Data& s) throw()
  214. // Never allow copy
  215. : m_str(NULL), m_RefCount(1)
  216. {
  217. if (s.m_wstr)
  218. {
  219. m_wstr = SysAllocStringLen(s.m_wstr, SysStringLen(s.m_wstr));
  220. ASSERT(m_wstr);
  221. }
  222. else m_wstr = NULL;
  223. }
  224. private: ~Data()
  225. // Prevent deletes from outside. Release() must be used.
  226. // ASSERT if the count is not 0
  227. {
  228. ASSERT(!m_RefCount);
  229. _Free();
  230. }
  231. private: void _Free()
  232. {
  233. if (m_wstr)
  234. SysFreeString(m_wstr);
  235. if (m_str)
  236. delete m_str;
  237. }
  238. }; // class Data
  239. private: Data* m_Data;
  240. private: void _AddRef()
  241. {
  242. if (m_Data)
  243. m_Data->AddRef();
  244. }
  245. private: void _Free() throw()
  246. {
  247. if (m_Data)
  248. {
  249. m_Data->Release();
  250. m_Data = NULL;
  251. }
  252. }
  253. private: int _Compare(const bstr& str) const throw()
  254. {
  255. if (m_Data == str.m_Data)
  256. return 0;
  257. if (!m_Data && str.m_Data)
  258. return -1;
  259. if (m_Data && !str.m_Data)
  260. return 1;
  261. #ifndef OLE2ANSI
  262. return wcscmp(*m_Data, str);
  263. #else
  264. return strcmp(*m_Data, str);
  265. #endif
  266. }
  267. }; // class bstr
  268. } // namespace com
  269. } // namespace microsoft
  270. #ifndef MICROSOFT_NAMESPACE_ON
  271. using namespace microsoft;
  272. #ifndef COM_NAMESPACE_ON
  273. using namespace com;
  274. #endif // COM_NAMESPACE_ON
  275. #endif // MICROSOFT_NAMESPACE_ON
  276. #endif // COMBSTR_H