List of usage examples for java.nio ByteBuffer position
public final int position()
From source file:com.healthmarketscience.jackcess.impl.TableImpl.java
/** * Serialize a row of Objects into a byte buffer. * //from www . ja v a 2 s .co m * @param rowArray row data, expected to be correct length for this table * @param buffer buffer to which to write the row data * @param minRowSize min size for result row * @param rawVarValues optional, pre-written values for var length columns * (enables re-use of previously written values). * @return the given buffer, filled with the row data */ private ByteBuffer createRow(Object[] rowArray, ByteBuffer buffer, int minRowSize, Map<ColumnImpl, byte[]> rawVarValues) throws IOException { buffer.putShort(_maxColumnCount); NullMask nullMask = new NullMask(_maxColumnCount); //Fixed length column data comes first int fixedDataStart = buffer.position(); int fixedDataEnd = fixedDataStart; for (ColumnImpl col : _columns) { if (col.isVariableLength()) { continue; } Object rowValue = col.getRowValue(rowArray); if (col.storeInNullMask()) { if (col.writeToNullMask(rowValue)) { nullMask.markNotNull(col); } rowValue = null; } if (rowValue != null) { // we have a value to write nullMask.markNotNull(col); // remainingRowLength is ignored when writing fixed length data buffer.position(fixedDataStart + col.getFixedDataOffset()); buffer.put(col.write(rowValue, 0)); } // always insert space for the entire fixed data column length // (including null values), access expects the row to always be at least // big enough to hold all fixed values buffer.position(fixedDataStart + col.getFixedDataOffset() + col.getLength()); // keep track of the end of fixed data if (buffer.position() > fixedDataEnd) { fixedDataEnd = buffer.position(); } } // reposition at end of fixed data buffer.position(fixedDataEnd); // only need this info if this table contains any var length data if (_maxVarColumnCount > 0) { int maxRowSize = getFormat().MAX_ROW_SIZE; // figure out how much space remains for var length data. first, // account for already written space maxRowSize -= buffer.position(); // now, account for trailer space int trailerSize = (nullMask.byteSize() + 4 + (_maxVarColumnCount * 2)); maxRowSize -= trailerSize; // for each non-null long value column we need to reserve a small // amount of space so that we don't end up running out of row space // later by being too greedy for (ColumnImpl varCol : _varColumns) { if ((varCol.getType().isLongValue()) && (varCol.getRowValue(rowArray) != null)) { maxRowSize -= getFormat().SIZE_LONG_VALUE_DEF; } } //Now write out variable length column data short[] varColumnOffsets = new short[_maxVarColumnCount]; int varColumnOffsetsIndex = 0; for (ColumnImpl varCol : _varColumns) { short offset = (short) buffer.position(); Object rowValue = varCol.getRowValue(rowArray); if (rowValue != null) { // we have a value nullMask.markNotNull(varCol); byte[] rawValue = null; ByteBuffer varDataBuf = null; if (((rawValue = rawVarValues.get(varCol)) != null) && (rawValue.length <= maxRowSize)) { // save time and potentially db space, re-use raw value varDataBuf = ByteBuffer.wrap(rawValue); } else { // write column value varDataBuf = varCol.write(rowValue, maxRowSize); } maxRowSize -= varDataBuf.remaining(); if (varCol.getType().isLongValue()) { // we already accounted for some amount of the long value data // above. add that space back so we don't double count maxRowSize += getFormat().SIZE_LONG_VALUE_DEF; } buffer.put(varDataBuf); } // we do a loop here so that we fill in offsets for deleted columns while (varColumnOffsetsIndex <= varCol.getVarLenTableIndex()) { varColumnOffsets[varColumnOffsetsIndex++] = offset; } } // fill in offsets for any remaining deleted columns while (varColumnOffsetsIndex < varColumnOffsets.length) { varColumnOffsets[varColumnOffsetsIndex++] = (short) buffer.position(); } // record where we stopped writing int eod = buffer.position(); // insert padding if necessary padRowBuffer(buffer, minRowSize, trailerSize); buffer.putShort((short) eod); //EOD marker //Now write out variable length offsets //Offsets are stored in reverse order for (int i = _maxVarColumnCount - 1; i >= 0; i--) { buffer.putShort(varColumnOffsets[i]); } buffer.putShort(_maxVarColumnCount); //Number of var length columns } else { // insert padding for row w/ no var cols padRowBuffer(buffer, minRowSize, nullMask.byteSize()); } nullMask.write(buffer); //Null mask buffer.flip(); return buffer; }