function _fnAddData(settings, dataIn, tr, tds) {
		/* Create the object for storing information about this new row */
		var rowIdx = settings.aoData.length;
		var rowModel = $.extend(true, {}, DataTable.models.oRow, {
			src: tr ? 'dom' : 'data',
			idx: rowIdx
		});

		rowModel._aData = dataIn;
		settings.aoData.push(rowModel);

		var columns = settings.aoColumns;

		for (var i = 0, iLen = columns.length; i < iLen; i++) {
			// Invalidate the column types as the new data needs to be revalidated
			columns[i].sType = null;
		}

		/* Add to the display array */
		settings.aiDisplayMaster.push(rowIdx);

		var id = settings.rowIdFn(dataIn);
		if (id !== undefined) {
			settings.aIds[id] = rowModel;
		}

		/* Create the DOM information, or register it if already present */
		if (tr || !settings.oFeatures.bDeferRender) {
			_fnCreateTr(settings, rowIdx, tr, tds);
		}

		return rowIdx;
	}
Add a data array to the table, creating DOM node etc. This is the parallel to
_fnGatherData, but for adding rows from a Javascript source, rather than a
DOM source.
 @param {object} settings dataTables settings object
 @param {array} data data array to be added
 @param {node} [tr] TR element to add to the table - optional. If not given,
   DataTables will create a row automatically
 @param {array} [tds] Array of TD|TH elements for the row - must be given
   if nTr is.
 @returns {int} >=0 if successful (index of new aoData entry), -1 if failed
 @memberof DataTable#oApi