AutoArray.h 5.4 KB

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