Back to index

lightning-sunbird  0.9+nobinonly
nsUint8Array.cpp
Go to the documentation of this file.
00001 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
00002 /* ***** BEGIN LICENSE BLOCK *****
00003  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
00004  *
00005  * The contents of this file are subject to the Mozilla Public License Version
00006  * 1.1 (the "License"); you may not use this file except in compliance with
00007  * the License. You may obtain a copy of the License at
00008  * http://www.mozilla.org/MPL/
00009  *
00010  * Software distributed under the License is distributed on an "AS IS" basis,
00011  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
00012  * for the specific language governing rights and limitations under the
00013  * License.
00014  *
00015  * The Original Code is mozilla.org code.
00016  *
00017  * The Initial Developer of the Original Code is
00018  * Netscape Communications Corporation.
00019  * Portions created by the Initial Developer are Copyright (C) 1999
00020  * the Initial Developer. All Rights Reserved.
00021  *
00022  * Contributor(s):
00023  *
00024  * Alternatively, the contents of this file may be used under the terms of
00025  * either of the GNU General Public License Version 2 or later (the "GPL"),
00026  * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00027  * in which case the provisions of the GPL or the LGPL are applicable instead
00028  * of those above. If you wish to allow use of your version of this file only
00029  * under the terms of either the GPL or the LGPL, and not to allow others to
00030  * use your version of this file under the terms of the MPL, indicate your
00031  * decision by deleting the provisions above and replace them with the notice
00032  * and other provisions required by the GPL or the LGPL. If you do not delete
00033  * the provisions above, a recipient may use your version of this file under
00034  * the terms of any one of the MPL, the GPL or the LGPL.
00035  *
00036  * ***** END LICENSE BLOCK ***** */
00037 
00038 #include "msgCore.h"
00039 #include "nsUint8Array.h"
00040 
00041 MOZ_DECL_CTOR_COUNTER(nsUint8Array)
00042 
00043 nsUint8Array::nsUint8Array()
00044 {
00045        m_pData = nsnull;
00046        m_nSize = m_nMaxSize = m_nGrowBy = 0;
00047 }
00048 
00049 nsUint8Array::~nsUint8Array()
00050 {
00051        PR_Free(m_pData);
00052 }
00053 
00054 void nsUint8Array::SetSize(PRInt32 nNewSize, PRInt32 nGrowBy)
00055 {
00056 //     AssertValid(this);
00057        NS_ASSERTION(nNewSize >= 0, "can't set size to negative value");
00058 
00059        if (nGrowBy != -1)
00060               m_nGrowBy = nGrowBy;  // set new size
00061 
00062        if (nNewSize == 0)
00063        {
00064               // shrink to nothing
00065               PR_Free(m_pData);
00066               m_pData = nsnull;
00067               m_nSize = m_nMaxSize = 0;
00068        }
00069        else if (m_pData == nsnull)
00070        {
00071               // create one with exact size
00072               m_pData = (PRUint8*)PR_Malloc(nNewSize * sizeof(PRUint8));
00073 
00074               memset(m_pData, 0, nNewSize * sizeof(PRUint8));  // zero fill
00075 
00076               m_nSize = m_nMaxSize = nNewSize;
00077        }
00078        else if (nNewSize <= m_nMaxSize)
00079        {
00080     // it fits
00081     if (nNewSize > m_nSize)
00082     {
00083            // initialize the new elements
00084 
00085       memset(&m_pData[m_nSize], 0, (nNewSize-m_nSize) * sizeof(PRUint8));
00086 
00087     }
00088 
00089               m_nSize = nNewSize;
00090        }
00091        else
00092        {
00093               // otherwise, grow array
00094               PRInt32 nGrowBy = m_nGrowBy;
00095               if (nGrowBy == 0)
00096               {
00097                      nGrowBy = PR_MIN(1024, PR_MAX(4, m_nSize / 8));
00098               }
00099               PRInt32 nNewMax;
00100               if (nNewSize < m_nMaxSize + nGrowBy)
00101                      nNewMax = m_nMaxSize + nGrowBy;  // granularity
00102               else
00103                      nNewMax = nNewSize;  // no slush
00104 
00105               NS_ASSERTION(nNewMax >= m_nMaxSize, "no wraparound");  // no wrap around
00106               PRUint8* pNewData = (PRUint8*)PR_Malloc(nNewMax * sizeof(PRUint8));
00107 
00108               // copy new data from old
00109         memcpy(pNewData, m_pData, m_nSize * sizeof(PRUint8));
00110 
00111               NS_ASSERTION(nNewSize > m_nSize, "did't grow size");
00112 
00113               memset(&pNewData[m_nSize], 0, (nNewSize-m_nSize) * sizeof(PRUint8));
00114 
00115               PR_Free(m_pData);
00116               m_pData = pNewData;
00117               m_nSize = nNewSize;
00118               m_nMaxSize = nNewMax;
00119        }
00120 }
00121 
00122 void nsUint8Array::FreeExtra()
00123 {
00124 
00125        if (m_nSize != m_nMaxSize)
00126        {
00127               // shrink to desired size
00128               PRUint8* pNewData = nsnull;
00129               if (m_nSize != 0)
00130               {
00131                      pNewData = (PRUint8*)PR_Malloc(m_nSize * sizeof(PRUint8));
00132                      // copy new data from old
00133                      memcpy(pNewData, m_pData, m_nSize * sizeof(PRUint8));
00134               }
00135 
00136               // get rid of old stuff (note: no destructors called)
00137               PR_Free(m_pData);
00138               m_pData = pNewData;
00139               m_nMaxSize = m_nSize;
00140        }
00141 }
00142 
00143 void nsUint8Array::CopyArray(nsUint8Array &aSrcArray)
00144 {
00145   PR_FREEIF(m_pData);
00146   m_nSize = aSrcArray.m_nSize;
00147   m_nMaxSize = aSrcArray.m_nSize;
00148   m_pData = (PRUint8*)PR_Malloc(m_nSize * sizeof(PRUint8));
00149   if (m_pData)
00150    memcpy(m_pData, aSrcArray.m_pData, m_nSize * sizeof(PRUint8));
00151 }
00152 
00154 
00155 void nsUint8Array::SetAtGrow(PRInt32 nIndex, PRUint8 newElement)
00156 {
00157        NS_ASSERTION(nIndex >= 0, "can't insert at negative index");
00158 
00159        if (nIndex >= m_nSize)
00160               SetSize(nIndex+1);
00161        m_pData[nIndex] = newElement;
00162 }
00163 
00164 nsresult nsUint8Array::InsertAt(PRInt32 nIndex, PRUint8 newElement, PRInt32 nCount)
00165 {
00166        NS_ASSERTION(nIndex >= 0, "can't insert at negative index");
00167        NS_ASSERTION(nCount > 0, "have to insert something");     // zero or negative size not allowed
00168 
00169        if (nIndex >= m_nSize)
00170        {
00171               // adding after the end of the array
00172               SetSize(nIndex + nCount);  // grow so nIndex is valid
00173        }
00174        else
00175        {
00176               // inserting in the middle of the array
00177               PRInt32 nOldSize = m_nSize;
00178               SetSize(m_nSize + nCount);  // grow it to new size
00179               // shift old data up to fill gap
00180         memmove(&m_pData[nIndex+nCount], &m_pData[nIndex],
00181                 (nOldSize-nIndex) * sizeof(PRUint8));
00182 
00183               // re-init slots we copied from
00184 
00185               memset(&m_pData[nIndex], 0, nCount * sizeof(PRUint8));
00186 
00187        }
00188 
00189        // insert new value in the gap
00190        NS_ASSERTION(nIndex + nCount <= m_nSize, "overflow");
00191        while (nCount--)
00192               m_pData[nIndex++] = newElement;
00193   return NS_OK;
00194 }
00195 
00196 void nsUint8Array::RemoveAt(PRInt32 nIndex, PRInt32 nCount)
00197 {
00198   if (nIndex < 0 || nCount < 0 || nIndex + nCount > m_nSize)
00199   {
00200     NS_ASSERTION(PR_FALSE, "bad remove index or count");
00201     return;
00202   }
00203 
00204        // just remove a range
00205        PRInt32 nMoveCount = m_nSize - (nIndex + nCount);
00206 
00207        NS_ASSERTION(nMoveCount >= 0, "can't remove nothing");
00208        if (nMoveCount >= 0)
00209       memmove(&m_pData[nIndex], &m_pData[nIndex + nCount],
00210               nMoveCount * sizeof(PRUint8));
00211        m_nSize -= nCount;
00212 }
00213 
00214 nsresult nsUint8Array::InsertAt(PRInt32 nStartIndex, nsUint8Array* pNewArray)
00215 {
00216   NS_ENSURE_ARG(pNewArray);
00217        NS_ASSERTION(nStartIndex >= 0, "start index must be positive");
00218 
00219        if (pNewArray->GetSize() > 0)
00220        {
00221               InsertAt(nStartIndex, pNewArray->GetAt(0), pNewArray->GetSize());
00222               for (PRInt32 i = 0; i < pNewArray->GetSize(); i++)
00223                      SetAt(nStartIndex + i, pNewArray->GetAt(i));
00224        }
00225   return NS_OK;
00226 }
00227 
00228 
00229  PRInt32 nsUint8Array::GetSize() const
00230        { return m_nSize; }
00231  PRInt32 nsUint8Array::GetUpperBound() const
00232        { return m_nSize-1; }
00233  void nsUint8Array::RemoveAll()
00234        { SetSize(0); }
00235  PRUint8 nsUint8Array::GetAt(PRInt32 nIndex) const
00236        { NS_ASSERTION(nIndex >= 0 && nIndex < m_nSize, "out of bounds");
00237               return m_pData[nIndex]; }
00238  void nsUint8Array::SetAt(PRInt32 nIndex, PRUint8 newElement)
00239        { NS_ASSERTION(nIndex >= 0 && nIndex < m_nSize, "out of bounds");
00240               m_pData[nIndex] = newElement; }
00241  PRUint8& nsUint8Array::ElementAt(PRInt32 nIndex)
00242        { NS_ASSERTION(nIndex >= 0 && nIndex < m_nSize, "out of bounds");
00243               return m_pData[nIndex]; }
00244  PRInt32 nsUint8Array::Add(PRUint8 newElement)
00245        { PRInt32 nIndex = m_nSize;
00246               SetAtGrow(nIndex, newElement);
00247               return nIndex; }
00248  PRUint8 nsUint8Array::operator[](PRInt32 nIndex) const
00249        { return GetAt(nIndex); }
00250  PRUint8& nsUint8Array::operator[](PRInt32 nIndex)
00251        { return ElementAt(nIndex); }
00252 
00253 
00255 // Diagnostics
00256 
00257 #ifdef _DEBUG
00258 
00259 void nsUint8Array::AssertValid() const
00260 {
00261 }
00262 #endif //_DEBUG
00263 
00264