AutoArray.h 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310
  1. #pragma once
  2. #ifndef _WIN32
  3. #include <assert.h>
  4. #define _ASSERT assert
  5. #include <winpr/interlocked.h>
  6. #else
  7. #include <crtdbg.h>
  8. #endif
  9. template<class T> class CAutoArray
  10. {
  11. struct CRefNode
  12. {
  13. int m_nSize;
  14. LONG m_nRefCount;
  15. CRefNode() :m_nSize(0), m_nRefCount(1) {}
  16. CRefNode(int nInitSize) :m_nSize(nInitSize), m_nRefCount(1) {}
  17. };
  18. public:
  19. CAutoArray() :m_pData(NULL), m_pRefNode(NULL) {}
  20. CAutoArray(int nInitSize) :m_pData(NULL), m_pRefNode(NULL)
  21. {
  22. _ASSERT(nInitSize >= 0);
  23. if (nInitSize > 0)
  24. Init(nInitSize);
  25. }
  26. CAutoArray(T* pData, int nSize) :m_pData(NULL), m_pRefNode(NULL)
  27. {
  28. Bind(pData, nSize);
  29. }
  30. void Bind(T* pData, int nSize)
  31. {
  32. Init();
  33. _ASSERT(nSize >= 0);
  34. if (nSize == 0 || pData == NULL)
  35. return;
  36. m_pData = pData;
  37. m_pRefNode = new CRefNode(nSize);
  38. InterlockedIncrement(&(m_pRefNode->m_nRefCount));//will not delete inside class
  39. }
  40. CAutoArray(const CAutoArray<T>& Array)
  41. {
  42. m_pData = Array.m_pData;
  43. m_pRefNode = Array.m_pRefNode;
  44. if (m_pRefNode)
  45. InterlockedIncrement(&(m_pRefNode->m_nRefCount));
  46. }
  47. ~CAutoArray()
  48. {
  49. Init();
  50. }
  51. CAutoArray<T>& operator=(const CAutoArray<T>& Array)
  52. {
  53. if (Array.m_pData != m_pData) {
  54. Init();
  55. m_pData = Array.m_pData;
  56. m_pRefNode = Array.m_pRefNode;
  57. if (m_pRefNode)
  58. InterlockedIncrement(&(m_pRefNode->m_nRefCount));
  59. }
  60. return *this;
  61. }
  62. bool operator ==(const CAutoArray<T>& Array)
  63. {
  64. return m_pData == Array.m_pData;
  65. }
  66. bool operator !=(const CAutoArray<T>& Array)
  67. {
  68. return m_pData != Array.m_pData;
  69. }
  70. const T& operator[](int nIndex)const
  71. {
  72. _ASSERT(nIndex >= 0);
  73. _ASSERT(nIndex < GetCount() || nIndex == 0);
  74. return m_pData[nIndex];
  75. }
  76. T& operator[](int nIndex)
  77. {
  78. _ASSERT(nIndex >= 0);
  79. _ASSERT(nIndex < GetCount() || nIndex == 0);
  80. return GetWriteableArray()[nIndex];
  81. }
  82. void Attach(T* pData, int nSize)
  83. {
  84. if (pData == m_pData && m_pRefNode && m_pRefNode->m_nSize == nSize)
  85. return;
  86. Init();
  87. if (nSize == 0) {
  88. m_pData = NULL;
  89. m_pRefNode = NULL;
  90. } else {
  91. m_pData = pData;
  92. m_pRefNode = new CRefNode(nSize);
  93. }
  94. }
  95. T* Detach()
  96. {
  97. T* pRet = m_pData;
  98. m_pData = NULL;
  99. if (m_pRefNode && m_pRefNode->m_nRefCount == 1)
  100. delete m_pRefNode;
  101. m_pRefNode = NULL;
  102. return pRet;
  103. }
  104. void Init(int nInitSize = 0)
  105. {
  106. _ASSERT(nInitSize >= 0);
  107. if (m_pRefNode) {
  108. DecrementRef();
  109. }
  110. if (nInitSize > 0) {
  111. m_pData = new T[nInitSize];
  112. if (m_pData && m_pRefNode == NULL)
  113. m_pRefNode = new CRefNode(nInitSize);
  114. }
  115. }
  116. void Clear()
  117. {
  118. Init();
  119. }
  120. void EnlargeArray(int nNewSize)
  121. {
  122. if (nNewSize <= GetCount())
  123. return;
  124. T* pData = new T[nNewSize];
  125. if (pData) {
  126. if (m_pData) {
  127. for (int i = 0; i < m_pRefNode->m_nSize; i++)
  128. pData[i] = m_pData[i];
  129. if (m_pRefNode->m_nRefCount == 1) {
  130. delete[]m_pData;
  131. m_pRefNode->m_nSize = nNewSize;
  132. } else
  133. DecrementRef();
  134. }
  135. m_pData = pData;
  136. if (m_pRefNode == NULL)
  137. m_pRefNode = new CRefNode(nNewSize);
  138. }
  139. }
  140. void Copy(const T* pData, int nFrom, int nSize)
  141. {
  142. if (pData == NULL || nSize == 0) {
  143. Init();
  144. return;
  145. }
  146. _ASSERT(nFrom >= 0);
  147. _ASSERT(nSize >= 0);
  148. Init(nSize);
  149. if (m_pData) {
  150. const T* pS = pData + nFrom;
  151. for (T* pT = m_pData; pT < m_pData + nSize; pT++, pS++)
  152. *pT = *pS;
  153. }
  154. }
  155. void Copy(const CAutoArray<T>& Array)
  156. {
  157. Copy(Array, 0, Array.GetCount());
  158. }
  159. void Copy(const CAutoArray<T>& Array, int nFrom, int nSize)
  160. {
  161. if (nSize == 0)
  162. return;
  163. _ASSERT(nFrom >= 0);
  164. _ASSERT(nSize >= 0);
  165. _ASSERT(nFrom < Array.GetCount());
  166. int nMaxSize = Array.GetCount() - nFrom;
  167. if (nSize > nMaxSize)nSize = nMaxSize;
  168. Init(nSize);
  169. if (m_pData) {
  170. const T* pS = Array.m_pData + nFrom;
  171. for (T* pT = m_pData; pT < m_pData + nSize; pT++, pS++)
  172. *pT = *pS;
  173. }
  174. }
  175. void Append(const T* pData, int nFrom, int nSize)
  176. {
  177. if (pData == NULL || nSize == 0)
  178. return;
  179. _ASSERT(nFrom >= 0);
  180. _ASSERT(nSize >= 0);
  181. if (GetCount() == 0) {
  182. Copy(pData, nFrom, nSize);
  183. return;
  184. }
  185. int nOldSize = GetCount();
  186. EnlargeArray(nOldSize + nSize);
  187. if (m_pData) {
  188. T* pBegin = m_pData + nOldSize;
  189. const T* pS = pData + nFrom;
  190. for (T* pT = pBegin; pT < pBegin + nSize; pT++, pS++)
  191. *pT = *pS;
  192. }
  193. }
  194. void Append(const CAutoArray<T>& Array, int nFrom, int nSize)
  195. {
  196. if (nSize == 0)
  197. return;
  198. _ASSERT(nFrom >= 0);
  199. _ASSERT(nSize >= 0);
  200. _ASSERT(nFrom < Array.GetCount());
  201. int nMaxSize = Array.GetCount() - nFrom;
  202. if (nSize > nMaxSize)nSize = nMaxSize;
  203. if (nSize == 0)
  204. return;
  205. if (GetCount() == 0) {
  206. Copy(Array, nFrom, nSize);
  207. return;
  208. }
  209. int nOldSize = GetCount();
  210. EnlargeArray(nOldSize + nSize);
  211. if (m_pData) {
  212. T* pBegin = m_pData + nOldSize;
  213. const T* pS = Array.m_pData + nFrom;
  214. for (T* pT = pBegin; pT < pBegin + nSize; pT++, pS++)
  215. *pT = *pS;
  216. }
  217. }
  218. void Append(const CAutoArray<T>& Array)
  219. {
  220. Append(Array, 0, Array.GetCount());
  221. }
  222. CAutoArray<T> Clone()
  223. {
  224. return Clone(0, GetCount());
  225. }
  226. CAutoArray<T> Clone(int nFrom, int nSize)
  227. {
  228. CAutoArray<T> RetArray;
  229. RetArray.Copy(m_pData, nFrom, nSize);
  230. return RetArray;
  231. }
  232. int GetCount() const
  233. {
  234. if (m_pRefNode)
  235. return m_pRefNode->m_nSize;
  236. else
  237. return 0;
  238. }
  239. operator const T* () const
  240. {
  241. return m_pData;
  242. };
  243. T* GetWriteableArray()
  244. {
  245. if (m_pRefNode && m_pRefNode->m_nRefCount > 1) {
  246. int nSize = m_pRefNode->m_nSize;
  247. T* pData = new T[nSize];
  248. if (m_pData) {
  249. for (T* pT = pData, *pS = m_pData; pT < pData + nSize; pT++, pS++)
  250. *pT = *pS;
  251. DecrementRef();
  252. m_pData = pData;
  253. m_pRefNode = new CRefNode(nSize);
  254. }
  255. }
  256. return m_pData;
  257. }
  258. private:
  259. LONG DecrementRef()
  260. {
  261. _ASSERT(m_pRefNode);
  262. LONG nRef = InterlockedDecrement(&(m_pRefNode->m_nRefCount));
  263. if (nRef == 0) {
  264. delete[]m_pData;
  265. delete m_pRefNode;
  266. }
  267. m_pData = NULL;
  268. m_pRefNode = NULL;
  269. return nRef;
  270. }
  271. T* m_pData;
  272. CRefNode* m_pRefNode;
  273. };
  274. typedef CAutoArray<BYTE> CAutoBuffer;