View Javadoc
1   /*
2   Copyright (c) 2005 Health Market Science, Inc.
3   
4   Licensed under the Apache License, Version 2.0 (the "License");
5   you may not use this file except in compliance with the License.
6   You may obtain a copy of the License at
7   
8       http://www.apache.org/licenses/LICENSE-2.0
9   
10  Unless required by applicable law or agreed to in writing, software
11  distributed under the License is distributed on an "AS IS" BASIS,
12  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  See the License for the specific language governing permissions and
14  limitations under the License.
15  */
16  
17  package com.healthmarketscience.jackcess.impl;
18  
19  import java.nio.ByteBuffer;
20  
21  /**
22   * Bitmask that indicates whether or not each column in a row is null.  Also
23   * holds values of boolean columns.
24   * @author Tim McCune
25   */
26  public class NullMask {
27    
28    /** num row columns */
29    private final int _columnCount;
30    /** The actual bitmask */
31    private final byte[] _mask;
32    
33    /**
34     * @param columnCount Number of columns in the row that this mask will be
35     *    used for
36     */
37    public NullMask(int columnCount) {
38      _columnCount = columnCount;
39      // we leave everything initially marked as null so that we don't need to
40      // do anything for deleted columns (we only need to mark as non-null
41      // valid columns for which we actually have values).
42      _mask = new byte[(_columnCount + 7) / 8];
43    }
44    
45    /**
46     * Read a mask in from a buffer
47     */
48    public void read(ByteBuffer buffer) {
49      buffer.get(_mask);
50    }
51  
52    /**
53     * Write a mask to a buffer
54     */
55    public void write(ByteBuffer buffer) {
56      buffer.put(_mask);
57    }
58  
59    /**
60     * @param column column to test for {@code null}
61     * @return Whether or not the value for that column is null.  For boolean
62     *    columns, returns the actual value of the column (where
63     *    non-{@code null} == {@code true})
64     */
65    public boolean isNull(ColumnImpl column) {
66      int columnNumber = column.getColumnNumber();
67      // if new columns were added to the table, old null masks may not include
68      // them (meaning the field is null)
69      if(columnNumber >= _columnCount) {
70        // it's null
71        return true;
72      }
73      return (_mask[byteIndex(columnNumber)] & bitMask(columnNumber)) == 0;
74    }
75  
76    /**
77     * Indicate that the column with the given number is not {@code null} (or a
78     * boolean value is {@code true}).
79     * @param column column to be marked non-{@code null}
80     */
81    public void markNotNull(ColumnImpl column) {
82      int columnNumber = column.getColumnNumber();
83      int maskIndex = byteIndex(columnNumber);
84      _mask[maskIndex] = (byte) (_mask[maskIndex] | bitMask(columnNumber));
85    }
86    
87    /**
88     * @return Size in bytes of this mask
89     */
90    public int byteSize() {
91      return _mask.length;
92    }
93  
94    private static int byteIndex(int columnNumber) {
95      return columnNumber / 8;
96    }
97  
98    private static byte bitMask(int columnNumber) {
99      return (byte) (1 << (columnNumber % 8));
100   }
101 }