Mozdev
mozilla/verbosio/datatypes/nsWritableDataMatrix.cpp
author Alex Vincent@SKYFIREDEMO1
Mon Oct 20 22:25:52 2008 -0700 (15 months ago)
changeset 46 9db1ccb62e4d
parent 320fef113e1411
permissions -rw-r--r--
Remove more JSLib cruft.
     1 #include "nsWritableDataMatrix.h"
     2 #include "nsServiceManagerUtils.h"
     3 #include "nsMemoryArray.h"
     4 
     5 NS_IMPL_ISUPPORTS2_CI(nsWritableDataMatrix,
     6                       nsIDataMatrix,
     7                       nsIWritableDataMatrix)
     8 
     9 nsWritableDataMatrix::nsWritableDataMatrix() :
    10   mColumnCount(0)
    11 {
    12   // do nothing, we take care of everything in Init().
    13 }
    14 
    15 nsresult
    16 nsWritableDataMatrix::Init()
    17 {
    18   return NS_OK;
    19 }
    20 
    21 nsWritableDataMatrix::~nsWritableDataMatrix()
    22 {
    23   Clear();
    24 }
    25 
    26 NS_IMETHODIMP // nsIDataMatrix
    27 nsWritableDataMatrix::GetRowCount(PRUint32 *aRowCount)
    28 {
    29   *aRowCount = matrix.Length();
    30   return NS_OK;
    31 }
    32 
    33 NS_IMETHODIMP // nsIDataMatrix
    34 nsWritableDataMatrix::GetColumnCount(PRUint32 *aColumnCount)
    35 {
    36   *aColumnCount = mColumnCount;
    37   return NS_OK;
    38 }
    39 
    40 NS_IMETHODIMP // nsIDataMatrix
    41 nsWritableDataMatrix::GetRow(PRUint32 rowNumber,
    42                              PRUint32 *columnCount,
    43                              nsISupports ***columns)
    44 {
    45   if (rowNumber >= matrix.Length())
    46     return NS_ERROR_INVALID_ARG;
    47 
    48   MatrixRow* row = matrix.ElementAt(rowNumber);
    49 
    50   nsresult rv;
    51   nsMemoryRefArray<nsISupports*> mem(mColumnCount, rv);
    52   NS_ENSURE_SUCCESS(rv, rv);
    53 
    54   for (PRUint32 i = 0; i < mColumnCount; i++)
    55     mem.setIndex(i, row->SafeElementAt(i));
    56 
    57   mem.Finalize(columnCount, columns);
    58   return NS_OK;
    59 }
    60 
    61 NS_IMETHODIMP // nsIDataMatrix
    62 nsWritableDataMatrix::GetColumn(PRUint32 columnNumber,
    63                                 PRUint32 *rowCount,
    64                                 nsISupports ***rows)
    65 {
    66   if (columnNumber > mColumnCount)
    67     return NS_ERROR_INVALID_ARG;
    68 
    69   PRUint32 count = matrix.Length();
    70 
    71   nsresult rv;
    72   nsMemoryRefArray<nsISupports*> mem(count, rv);
    73   NS_ENSURE_SUCCESS(rv, rv);
    74   
    75   for (PRUint32 i = 0; i < count; i++)
    76   {
    77     MatrixRow* row = matrix.ElementAt(i);
    78     mem.setIndex(i, row->SafeElementAt(columnNumber));
    79   }
    80 
    81   mem.Finalize(rowCount, rows);
    82   return NS_OK;
    83 }
    84 
    85 NS_IMETHODIMP // nsIDataMatrix
    86 nsWritableDataMatrix::GetCell(PRUint32 rowNumber,
    87                               PRUint32 columnNumber,
    88                               nsISupports **_retval)
    89 {
    90   if (rowNumber >= matrix.Length())
    91     return NS_ERROR_INVALID_ARG;
    92   if (columnNumber > mColumnCount)
    93     return NS_ERROR_INVALID_ARG;
    94 
    95   MatrixRow* row = matrix.ElementAt(rowNumber);
    96   if (row->Length() <= columnNumber) {
    97     *_retval = nsnull;
    98     return NS_OK;
    99   }
   100 
   101   NS_IF_ADDREF(*_retval = row->ElementAt(columnNumber));
   102   return NS_OK;
   103 }
   104 
   105 void
   106 nsWritableDataMatrix::EnsureColumnCount(PRUint32 columnCount)
   107 {
   108   if (columnCount > mColumnCount)
   109     mColumnCount = columnCount;
   110 }
   111 
   112 nsresult
   113 nsWritableDataMatrix::GetEnsuredRow(PRUint32 rowIndex,
   114                                     MatrixRow **row)
   115 {
   116   while (matrix.Length() <= rowIndex)
   117   {
   118     MatrixRow* emptyRow = new MatrixRow;
   119     if (!emptyRow)
   120       return NS_ERROR_OUT_OF_MEMORY;
   121     MatrixRow* insertedRow = matrix.AppendElement(emptyRow)->get();
   122     NS_ENSURE_TRUE(insertedRow, NS_ERROR_OUT_OF_MEMORY);
   123     NS_ENSURE_TRUE(insertedRow == emptyRow, NS_ERROR_UNEXPECTED);
   124   }
   125 
   126   *row = matrix.ElementAt(rowIndex);
   127   return NS_OK;
   128 }
   129 
   130 NS_IMETHODIMP // nsIWritableDataMatrix
   131 nsWritableDataMatrix::InsertRow(PRUint32 rowNumber,
   132                                 PRUint32 columnCount,
   133                                 nsISupports **columns)
   134 {
   135   MatrixRow* oldRow;
   136   if (rowNumber > 1) {
   137     nsresult rv = GetEnsuredRow(rowNumber - 1, &oldRow);
   138     NS_ENSURE_SUCCESS(rv, rv);
   139   }
   140 
   141   MatrixRow* newRow = new MatrixRow;
   142   NS_ENSURE_TRUE(newRow, NS_ERROR_OUT_OF_MEMORY);
   143 
   144   for (PRUint32 i = 0; i < columnCount; i++)
   145   {
   146     newRow->AppendElement(columns[i]);
   147     NS_IF_ADDREF(columns[i]);
   148   }
   149 
   150   MatrixRow* insertedRow = matrix.InsertElementAt(rowNumber, newRow)->get();
   151   NS_ENSURE_TRUE(insertedRow, NS_ERROR_OUT_OF_MEMORY);
   152   NS_ENSURE_TRUE(insertedRow == newRow, NS_ERROR_UNEXPECTED);
   153   EnsureColumnCount(columnCount);
   154   return NS_OK;
   155 }
   156 
   157 NS_IMETHODIMP // nsIWritableDataMatrix
   158 nsWritableDataMatrix::DeleteRow(PRUint32 rowNumber)
   159 {
   160   if (!(rowNumber < matrix.Length()))
   161     return NS_ERROR_INVALID_ARG;
   162 
   163   MatrixRow* row = matrix.ElementAt(rowNumber);
   164   PRUint32 columnCount = row->Length();
   165   for (PRUint32 i = 0; i < columnCount; i++)
   166   {
   167     nsISupports* cell = row->ElementAt(i);
   168     NS_IF_RELEASE(cell);
   169   }
   170   matrix.RemoveElementAt(rowNumber);
   171   return NS_OK;
   172 }
   173 
   174 NS_IMETHODIMP // nsIWritableDataMatrix
   175 nsWritableDataMatrix::ReplaceRow(PRUint32 rowNumber,
   176                                  PRUint32 columnCount,
   177                                  nsISupports **columns)
   178 {
   179   if (!(rowNumber < matrix.Length()))
   180     return NS_ERROR_INVALID_ARG;
   181 
   182   nsresult rv = DeleteRow(rowNumber);
   183 
   184   if (NS_FAILED(rv))
   185     return rv;
   186 
   187   return InsertRow(rowNumber, columnCount, columns);
   188 }
   189 
   190 static nsresult
   191 EnsureRowHasColumn(MatrixRow* row, PRUint32 columnIndex)
   192 {
   193   while (row->Length() <= columnIndex) {
   194     nsISupports** elem = row->AppendElement();
   195     NS_ENSURE_TRUE(elem, NS_ERROR_OUT_OF_MEMORY);
   196     *elem = nsnull;
   197   }
   198   return NS_OK;
   199 }
   200 
   201 void
   202 nsWritableDataMatrix::TruncateExtraColumns()
   203 {
   204   PRUint32 rowCount = matrix.Length();
   205   for (PRUint32 i = 0; i < rowCount; i++)
   206   {
   207     MatrixRow* row = matrix.ElementAt(i);
   208     while (row->Length() > mColumnCount)
   209     {
   210       NS_ERROR("Truncating row (how did we need this?)");
   211 
   212       nsISupports* cell = row->ElementAt(mColumnCount);
   213       NS_ASSERTION(!cell, "Truncating a non-null value?  Loss of data!");
   214       NS_IF_RELEASE(cell);
   215       row->RemoveElementAt(mColumnCount);
   216     }
   217   }
   218 }
   219 
   220 static nsresult
   221 InsertCell(MatrixRow* row,
   222            PRUint32 index,
   223            nsISupports* cell)
   224 {
   225   if ((index == row->Length() - 1) &&
   226       (row->ElementAt(index) == nsnull))
   227   {
   228     row->ElementAt(index) = cell;
   229     return NS_OK;
   230   }
   231 
   232   nsISupports** insert = row->InsertElementAt(index, cell);
   233   NS_ENSURE_TRUE(*insert == cell, NS_ERROR_UNEXPECTED);
   234   return NS_OK;
   235 }
   236 
   237 NS_IMETHODIMP // nsIWritableDataMatrix
   238 nsWritableDataMatrix::InsertColumn(PRUint32 columnNumber,
   239                                    PRUint32 rowCount,
   240                                    nsISupports **rows)
   241 {
   242   MatrixRow* lastRow = nsnull;
   243   nsresult rv = GetEnsuredRow(rowCount - 1, &lastRow);
   244   NS_ENSURE_SUCCESS(rv, rv);
   245   NS_ENSURE_TRUE(lastRow, NS_ERROR_OUT_OF_MEMORY);
   246   
   247   for (PRUint32 rowIndex = 0; rowIndex < rowCount; rowIndex++)
   248   {
   249     MatrixRow* matrixRow = matrix.ElementAt(rowIndex);
   250     rv = EnsureRowHasColumn(matrixRow, columnNumber);
   251     if (NS_FAILED(rv))
   252       return rv;
   253 
   254     nsISupports* cell = rows[rowIndex];
   255     rv = InsertCell(matrixRow, columnNumber, cell);
   256     if (NS_FAILED(rv))
   257       return rv;
   258 
   259     NS_IF_ADDREF(cell);
   260   }
   261 
   262   for (PRUint32 rowIndex = rowCount; rowIndex < matrix.Length(); rowIndex++)
   263   {
   264     MatrixRow* matrixRow = matrix.ElementAt(rowIndex);
   265     rv = EnsureRowHasColumn(matrixRow, columnNumber);
   266     if (NS_FAILED(rv))
   267       return rv;
   268 
   269     rv = InsertCell(matrixRow, columnNumber, nsnull);
   270     if (NS_FAILED(rv))
   271       return rv;
   272   }
   273 
   274   mColumnCount = PR_MAX(mColumnCount, columnNumber) + 1;
   275   TruncateExtraColumns();
   276   return NS_OK;
   277 }
   278 
   279 NS_IMETHODIMP // nsIWritableDataMatrix
   280 nsWritableDataMatrix::DeleteColumn(PRUint32 columnNumber)
   281 {
   282   if (!(columnNumber < mColumnCount))
   283     return NS_ERROR_INVALID_ARG;
   284 
   285   PRUint32 rowCount = matrix.Length();
   286   for (PRUint32 rowIndex = 0; rowIndex < rowCount; rowIndex++)
   287   {
   288     MatrixRow* row = matrix.ElementAt(rowIndex);
   289     if (row->Length() <= columnNumber)
   290       continue;
   291 
   292     nsISupports* cell = row->ElementAt(columnNumber);
   293 #ifdef DEBUG
   294     PRUint32 oldLength = row->Length();
   295 #endif
   296     row->RemoveElementAt(columnNumber);
   297     NS_ASSERTION(oldLength == row->Length() + 1, "Didn't really remove, did we?");
   298     NS_IF_RELEASE(cell);
   299   }
   300 
   301   mColumnCount--;
   302   TruncateExtraColumns();
   303   return NS_OK;
   304 }
   305 
   306 NS_IMETHODIMP // nsIWritableDataMatrix
   307 nsWritableDataMatrix::ReplaceColumn(PRUint32 columnNumber,
   308                                     PRUint32 rowCount,
   309                                     nsISupports **rows)
   310 {
   311   if (!(columnNumber < mColumnCount))
   312     return NS_ERROR_INVALID_ARG;
   313 
   314   nsresult rv = DeleteColumn(columnNumber);
   315   if (NS_FAILED(rv))
   316     return rv;
   317 
   318   return InsertColumn(columnNumber, rowCount, rows);
   319 }
   320 
   321 NS_IMETHODIMP // nsIWritableDataMatrix
   322 nsWritableDataMatrix::SetCell(PRUint32 rowNumber,
   323                               PRUint32 columnNumber,
   324                               nsISupports *cellValue)
   325 {
   326   // Remove the old entry.
   327   if ((rowNumber < matrix.Length()) &&
   328       (columnNumber < mColumnCount)) {
   329     MatrixRow* row = matrix.ElementAt(rowNumber);
   330     NS_ENSURE_TRUE(row, NS_ERROR_UNEXPECTED);
   331     if (columnNumber < row->Length()) {
   332       nsISupports* oldCell = row->SafeElementAt(columnNumber);
   333       NS_IF_RELEASE(oldCell);
   334     }
   335   }
   336 
   337   // Set the new entry.
   338   {
   339     MatrixRow* row = nsnull;
   340     nsresult rv = GetEnsuredRow(rowNumber, &row);
   341     if (NS_FAILED(rv))
   342       return rv;
   343 
   344     rv = EnsureRowHasColumn(row, columnNumber);
   345     if (NS_FAILED(rv))
   346       return rv;
   347 
   348     if (cellValue) {
   349       rv = InsertCell(row, columnNumber, cellValue);
   350       if (NS_FAILED(rv))
   351         return rv;
   352       NS_ADDREF(cellValue);
   353     }
   354   }
   355 
   356   EnsureColumnCount(columnNumber + 1);
   357   TruncateExtraColumns();
   358   return NS_OK;
   359 }
   360 
   361 NS_IMETHODIMP // nsIWritableDataMatrix
   362 nsWritableDataMatrix::Clear()
   363 {
   364   PRUint32 rowCount = matrix.Length();
   365   for (PRUint32 i = 0; i < rowCount; i++)
   366   {
   367     MatrixRow* row = matrix.ElementAt(i);
   368     PRUint32 colCount = row->Length();
   369     for (PRUint32 j = 0; j < colCount; j++)
   370       NS_IF_RELEASE(row->ElementAt(j));
   371   }
   372   matrix.Clear();
   373   mColumnCount = 0;
   374   return NS_OK;
   375 }