1 package nom.tam.util;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34 import java.io.EOFException;
35 import java.io.IOException;
36 import java.lang.reflect.Array;
37 import java.util.ArrayList;
38 import java.util.Arrays;
39
40 import nom.tam.util.type.ElementType;
41
42 import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63 public class ColumnTable<T> implements DataTable, Cloneable {
64
65
66 private ArrayList<Column<?>> columns = new ArrayList<>();
67
68
69 private int nrow = 0;
70
71
72 private static final int MIN_CAPACITY = 16;
73
74
75
76
77 private T extraState;
78
79
80
81
82
83
84 public ColumnTable() {
85 }
86
87
88
89
90
91
92
93
94
95 public ColumnTable(Object[] arrays, int[] sizes) throws TableException {
96 for (int i = 0; i < arrays.length; i++) {
97 addColumn(arrays[i], sizes[i]);
98 }
99 }
100
101
102
103
104
105
106
107
108
109
110
111 public final boolean isEmpty() {
112 return columns.isEmpty();
113 }
114
115
116
117
118
119
120
121
122 public void clear() {
123 columns.clear();
124 nrow = 0;
125 }
126
127
128
129
130
131
132
133
134
135
136
137
138 public void ensureSize(int rows) {
139 for (Column<?> c : columns) {
140 c.ensureSize(rows);
141 }
142 }
143
144
145
146
147
148
149
150
151
152
153
154 private int checkWrappedColumn(Object newColumn) throws TableException, NullPointerException {
155
156 if (!(newColumn instanceof Object[])) {
157
158 checkFlatColumn(newColumn, 1);
159 return 1;
160 }
161
162 try {
163 int[] dims = ArrayFuncs.checkRegularArray(newColumn, false);
164 if (dims.length != 2) {
165 throw new TableException("Not a 2D array: " + newColumn.getClass());
166 }
167 } catch (Exception e) {
168 throw new TableException(e);
169 }
170
171 Object[] entries = (Object[]) newColumn;
172 if (entries.length == 0) {
173 return 0;
174 }
175
176 Object first = entries[0];
177 if (!first.getClass().getComponentType().isPrimitive()) {
178 throw new TableException("Entries are not a primitive arrays: " + first.getClass());
179 }
180
181 return Array.getLength(first);
182 }
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199 @SuppressWarnings("unchecked")
200 public void addWrappedColumn(Object newColumn) throws TableException {
201 if (newColumn == null) {
202 throw new TableException("Cannot add a null column.");
203 }
204
205 int eCount = checkWrappedColumn(newColumn);
206
207 Class<?> eType = newColumn.getClass().getComponentType();
208 if (eType.isArray()) {
209 eType = eType.getComponentType();
210 }
211
212 @SuppressWarnings("rawtypes")
213 Column c = createColumn(eType, eCount);
214 c.data = newColumn;
215 nrow = Array.getLength(newColumn);
216 columns.add(c);
217 }
218
219
220
221
222
223
224
225
226
227
228
229
230
231 public void addColumn(Class<?> type, int size) throws TableException {
232 columns.add(createColumn(type, size));
233 }
234
235
236
237
238
239
240
241
242
243
244
245
246 private Object wrapColumn(Object data, int size) throws TableException {
247
248 checkFlatColumn(data, size);
249
250
251 Class<?> type = data.getClass().getComponentType();
252 int len = size == 0 ? nrow : Array.getLength(data) / size;
253
254
255 Object[] array = (Object[]) Array.newInstance(data.getClass(), len);
256
257 int offset = 0;
258 for (int i = 0; i < len; i++, offset += size) {
259
260 array[i] = Array.newInstance(type, size);
261 System.arraycopy(data, offset, array[i], 0, size);
262 }
263
264 return array;
265 }
266
267
268
269
270
271
272
273
274
275
276
277
278
279 @SuppressWarnings("unchecked")
280 public void addColumn(Object newColumn, int size) throws TableException {
281 if (newColumn == null) {
282 throw new TableException("Cannot add a null column: we don't know its type.");
283 }
284
285 if (size < 0) {
286 throw new TableException("Invalid element size: " + size);
287 }
288
289 if (size == 1 && newColumn.getClass().getComponentType().isPrimitive()) {
290
291 addWrappedColumn(newColumn);
292 return;
293 }
294
295 checkFlatColumn(newColumn, size);
296
297 @SuppressWarnings("rawtypes")
298 Column c = createColumn(newColumn.getClass().getComponentType(), size);
299 c.data = wrapColumn(newColumn, size);
300
301 columns.add(c);
302 nrow = Array.getLength(c.data);
303 }
304
305
306
307
308
309
310 private int nextLargerCapacity() {
311 return nextLargerCapacity(nrow);
312 }
313
314
315
316
317
318
319
320
321 private int nextLargerCapacity(int rows) {
322 if (rows < MIN_CAPACITY) {
323 return MIN_CAPACITY;
324 }
325
326 return (int) Math.min(Long.highestOneBit(rows) << 1, Integer.MAX_VALUE);
327 }
328
329
330
331
332
333
334
335
336
337 private void checkRow(Object[] row) throws TableException {
338
339 if (row.length != columns.size()) {
340 throw new TableException("Mismatched row size: " + row.length + ", expected " + columns.size());
341 }
342
343 for (int col = 0; col < row.length; col++) {
344 Column<?> c = columns.get(col);
345 c.checkEntry(row[col]);
346 }
347 }
348
349
350
351
352
353
354
355
356
357
358
359
360
361 public void addRow(Object[] row) throws TableException {
362 if (row == null) {
363 throw new TableException("Cannot add null row");
364 }
365
366 if (nrow == Integer.MAX_VALUE) {
367 throw new TableException("Table has reached its capacity limit");
368 }
369
370 if (isEmpty()) {
371
372 try {
373 for (int col = 0; col < row.length; col++) {
374 addColumn(row[col], Array.getLength(row[col]));
375 }
376 return;
377 } catch (TableException e) {
378
379 columns = new ArrayList<>();
380 throw e;
381 }
382 }
383
384 checkRow(row);
385
386
387 int capacity = nextLargerCapacity();
388
389 for (int i = 0; i < row.length; i++) {
390 Column<?> c = columns.get(i);
391 c.ensureSize(capacity);
392 c.checkEntry(row[i]);
393 c.setArrayElement(nrow, row[i]);
394 }
395 nrow++;
396 }
397
398
399
400
401
402
403
404
405
406 private void checkFlatColumn(Object data, int size) throws TableException {
407 if (!data.getClass().isArray()) {
408 throw new TableException("Argument is not an array: " + data.getClass());
409 }
410
411 int len = Array.getLength(data);
412
413
414
415
416
417
418 if (size > 0 && len % size != 0) {
419 throw new TableException("The column size " + len + " is not a multiple of the element size " + size);
420 }
421
422 if (nrow == 0 || size == 0) {
423 return;
424 }
425
426 if (len != nrow * size) {
427 throw new TableException("Mismatched element count: " + len + ", expected " + (nrow * size) + " for " + nrow
428 + " rows of size " + size);
429 }
430 }
431
432 @Override
433 @SuppressWarnings("unchecked")
434 protected ColumnTable<T> clone() {
435 try {
436 return (ColumnTable<T>) super.clone();
437 } catch (CloneNotSupportedException e) {
438 return null;
439 }
440 }
441
442
443
444
445
446
447
448
449
450 @SuppressWarnings("cast")
451 public ColumnTable<T> copy() throws TableException {
452 ColumnTable<T> copy = (ColumnTable<T>) clone();
453 copy.columns = new ArrayList<>(columns.size());
454 for (Column<?> c : columns) {
455 copy.columns.add(c.copy(nrow));
456 }
457 return copy;
458 }
459
460
461
462
463
464
465
466
467
468
469
470
471 public void deleteColumn(int col) throws TableException {
472 if (col < 0 || col >= columns.size()) {
473 throw new TableException("Column out of bounds: col=" + col + ", size=" + columns.size());
474 }
475 columns.remove(col);
476
477 if (isEmpty()) {
478 nrow = 0;
479 }
480 }
481
482
483
484
485
486
487
488
489
490
491
492 public void deleteColumns(int start, int len) throws TableException {
493 if (len == 0) {
494 return;
495 }
496
497 if (start < 0 || len < 0 || start + len > columns.size()) {
498 throw new TableException(
499 "Column eange out of bounds: start=" + start + ", len=" + len + ", size=" + columns.size());
500 }
501
502 ArrayList<Column<?>> c = new ArrayList<>();
503 int i;
504 for (i = 0; i < start; i++) {
505 c.add(columns.get(i));
506 }
507 i += len;
508 for (; i < columns.size(); i++) {
509 c.add(columns.get(i));
510 }
511 columns = c;
512
513 if (isEmpty()) {
514 nrow = 0;
515 }
516 }
517
518
519
520
521
522
523
524
525
526 public final void deleteAllRows() throws TableException {
527 nrow = 0;
528 for (Column<?> c : columns) {
529 c.trim(MIN_CAPACITY);
530 }
531 }
532
533
534
535
536
537
538
539
540
541
542 public final void deleteRow(int row) throws TableException {
543 deleteRows(row, 1);
544 }
545
546
547
548
549
550
551
552
553
554
555
556 public void deleteRows(int from, int length) throws TableException {
557 if (length == 0) {
558 return;
559 }
560
561 if (from < 0 || length < 0 || from + length > nrow) {
562 throw new TableException("Row range out of bounds: start=" + from + ", len=" + length + ", size=" + nrow);
563 }
564
565 int maxSize = nextLargerCapacity(nrow - length);
566 for (Column<?> c : columns) {
567 c.deleteRows(from, length, nrow, maxSize);
568 }
569
570 nrow -= length;
571 }
572
573
574
575
576
577
578
579
580
581
582 public final Class<?> getElementClass(int col) {
583 return columns.get(col).baseType();
584 }
585
586
587
588
589
590
591
592
593
594
595
596 public Class<?>[] getBases() {
597 Class<?>[] bases = new Class<?>[columns.size()];
598 for (int i = 0; i < bases.length; i++) {
599 bases[i] = getElementClass(i);
600 }
601 return bases;
602 }
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621 public Object getWrappedColumn(int col) {
622 Column<?> c = columns.get(col);
623 c.trim(nrow);
624 return c.getData();
625 }
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644 @Override
645 public Object getColumn(int col) {
646 Column<?> c = columns.get(col);
647 c.trim(nrow);
648 return c.getFlatData();
649 }
650
651
652
653
654
655
656
657
658
659
660 public Object[] getColumns() {
661 Object[] table = new Object[columns.size()];
662 for (int i = 0; i < table.length; i++) {
663 table[i] = getColumn(i);
664 }
665 return table;
666 }
667
668 @Override
669 public Object getElement(int row, int col) {
670 if (row < 0 || row >= nrow) {
671 throw new ArrayIndexOutOfBoundsException(row);
672 }
673 return columns.get(col).getArrayElement(row);
674 }
675
676
677
678
679
680
681
682
683
684 public T getExtraState() {
685 return extraState;
686 }
687
688 @Override
689 public final int getNCols() {
690 return columns.size();
691 }
692
693 @Override
694 public final int getNRows() {
695 return nrow;
696 }
697
698 @Override
699 public Object getRow(int row) {
700 if (row < 0 || row >= nrow) {
701 throw new ArrayIndexOutOfBoundsException(row);
702 }
703
704 Object[] x = new Object[columns.size()];
705 for (int col = 0; col < x.length; col++) {
706 x[col] = getElement(row, col);
707 }
708 return x;
709 }
710
711
712
713
714
715
716
717
718
719
720 public final int getElementSize(int col) {
721 return columns.get(col).elementCount();
722 }
723
724
725
726
727
728
729
730
731
732
733
734
735
736 public int[] getSizes() {
737 int[] sizes = new int[columns.size()];
738 for (int i = 0; i < sizes.length; i++) {
739 sizes[i] = getElementSize(i);
740 }
741 return sizes;
742 }
743
744
745
746
747
748
749
750
751
752 public final char getTypeChar(int col) {
753 return columns.get(col).getElementType().type();
754 }
755
756
757
758
759
760
761
762
763
764
765
766 public char[] getTypes() {
767 char[] types = new char[columns.size()];
768 for (int i = 0; i < types.length; i++) {
769 types[i] = getTypeChar(i);
770 }
771 return types;
772 }
773
774
775
776
777
778
779
780
781
782
783
784 public void read(ArrayDataInput in) throws EOFException, IOException {
785 for (int row = 0; row < nrow; row++) {
786 for (Column<?> c : columns) {
787 c.read(row, in);
788 }
789 }
790 }
791
792 @SuppressWarnings("unchecked")
793 @Override
794 public void setColumn(int col, Object newColumn) throws TableException {
795 if (newColumn == null) {
796 throw new TableException("Cannot set column data to null");
797 }
798
799 if (!newColumn.getClass().isArray()) {
800 throw new TableException("Not an array: " + newColumn.getClass().getName());
801 }
802
803 @SuppressWarnings("rawtypes")
804 Column c = columns.get(col);
805
806 if (!c.baseType().equals(newColumn.getClass().getComponentType())) {
807 throw new TableException(
808 "Mismatched type " + newColumn.getClass().getName() + ", expected " + c.baseType().getName());
809 }
810
811 if (Array.getLength(newColumn) != nrow * c.elementCount()) {
812 throw new TableException(
813 "Mismatched size " + Array.getLength(newColumn) + ", expected " + (nrow * c.elementCount()));
814 }
815
816 c.data = c.elementCount() > 1 ? wrapColumn(newColumn, c.elementCount()) : newColumn;
817 }
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836 @SuppressWarnings("unchecked")
837 public void setWrappedColumn(int col, Object newColumn) throws TableException {
838
839 if (!newColumn.getClass().isArray()) {
840 throw new TableException("Not an array: " + newColumn.getClass().getName());
841 }
842
843 if (Array.getLength(newColumn) != nrow) {
844 throw new TableException("Mismatched row count " + Array.getLength(newColumn) + ", expected " + nrow);
845 }
846
847 @SuppressWarnings("rawtypes")
848 Column c = columns.get(col);
849
850 int eSize = 0;
851
852 try {
853 eSize = checkWrappedColumn(newColumn);
854 } catch (Exception e) {
855 throw new TableException(e);
856 }
857
858 if (eSize != c.elementCount()) {
859 throw new TableException("Mismatched element size " + eSize + ", expected " + c.elementCount());
860 }
861
862 Class<?> eType = newColumn.getClass().getComponentType();
863 if (newColumn instanceof Object[]) {
864 eType = eType.getComponentType();
865 }
866
867 if (!c.baseType().equals(eType)) {
868 throw new TableException(
869 "Mismatched type " + newColumn.getClass().getName() + ", expected " + c.baseType().getName());
870 }
871
872 c.data = newColumn;
873 }
874
875 @Override
876 public void setElement(int row, int col, Object x) throws TableException {
877 if (row < 0 || row >= nrow) {
878 throw new ArrayIndexOutOfBoundsException(row);
879 }
880 Column<?> c = columns.get(col);
881 c.checkEntry(x);
882 c.setArrayElement(row, x);
883 }
884
885
886
887
888
889
890
891
892
893
894
895
896 public void setExtraState(T opaque) {
897 extraState = opaque;
898 }
899
900 @Override
901 public void setRow(int row, Object data) throws TableException {
902 if (row < 0 || row >= nrow) {
903 throw new ArrayIndexOutOfBoundsException(row);
904 }
905
906 if (data == null) {
907 throw new TableException("Unexpected null data for row " + row);
908 }
909
910 if (!(data instanceof Object[])) {
911 throw new TableException("Not an Object[] array: " + data.getClass().getName());
912 }
913
914 Object[] r = (Object[]) data;
915
916 checkRow(r);
917
918 for (int i = 0; i < columns.size(); i++) {
919 Column<?> c = columns.get(i);
920 c.checkEntry(r[i]);
921 c.setArrayElement(row, r[i]);
922 }
923
924 }
925
926
927
928
929
930
931
932
933
934
935 public void write(ArrayDataOutput out) throws IOException {
936 for (int row = 0; row < nrow; row++) {
937 for (Column<?> c : columns) {
938 c.write(row, out);
939 }
940 }
941 }
942
943
944
945
946
947
948
949
950
951
952
953 public void write(ArrayDataOutput out, int rowStart, int rowEnd, int col) throws IOException {
954 columns.get(col).write(rowStart, rowEnd - rowStart, out);
955 }
956
957
958
959
960
961
962
963
964
965
966
967
968 public void read(ArrayDataInput in, int rowStart, int rowEnd, int col) throws EOFException, IOException {
969 columns.get(col).read(rowStart, rowEnd - rowStart, in);
970 }
971
972 private Column<?> createColumn(Class<?> type, int size) throws TableException {
973 if (type == null) {
974 throw new TableException("Column type cannot be null.");
975 }
976
977 if (!type.isPrimitive()) {
978 throw new TableException("Not a primitive base type: " + type.getName());
979 }
980
981 if (size == 1) {
982 if (type.equals(byte.class)) {
983 return new Bytes();
984 }
985 if (type.equals(boolean.class)) {
986 return new Booleans();
987 }
988 if (type.equals(char.class)) {
989 return new Chars();
990 }
991 if (type.equals(short.class)) {
992 return new Shorts();
993 }
994 if (type.equals(int.class)) {
995 return new Integers();
996 }
997 if (type.equals(long.class)) {
998 return new Longs();
999 }
1000 if (type.equals(float.class)) {
1001 return new Floats();
1002 }
1003 if (type.equals(double.class)) {
1004 return new Doubles();
1005 }
1006 }
1007 return new Generic(type, size);
1008 }
1009
1010
1011
1012
1013
1014
1015
1016
1017 private abstract static class Column<Data> implements Cloneable {
1018 protected Data data;
1019 private ElementType<?> fitsType;
1020
1021
1022
1023
1024
1025
1026 Column(ElementType<?> fitsType) {
1027 this.fitsType = fitsType;
1028 init(fitsType.primitiveClass());
1029 }
1030
1031 @SuppressWarnings("unchecked")
1032 void init(Class<?> storeType) {
1033 data = (Data) Array.newInstance(storeType, 0);
1034 }
1035
1036
1037
1038
1039
1040
1041
1042 Data getData() {
1043 return data;
1044 }
1045
1046
1047
1048
1049
1050
1051
1052 Object getFlatData() {
1053 return data;
1054 }
1055
1056
1057
1058
1059
1060
1061 ElementType<?> getElementType() {
1062 return fitsType;
1063 }
1064
1065
1066
1067
1068
1069
1070 Class<?> baseType() {
1071 return fitsType.primitiveClass();
1072 }
1073
1074
1075
1076
1077
1078
1079 Class<?> arrayType() {
1080 return data.getClass();
1081 }
1082
1083
1084
1085
1086
1087
1088 int elementCount() {
1089 return 1;
1090 }
1091
1092
1093
1094
1095
1096
1097
1098 int capacity() {
1099 return Array.getLength(data);
1100 }
1101
1102 void deleteRows(int from, int len, int size, int maxCapacity) {
1103 int end = from + len;
1104 System.arraycopy(data, end, data, from, size - end);
1105 trim(maxCapacity);
1106 }
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119 abstract int read(int index, ArrayDataInput in) throws EOFException, IOException;
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129 abstract void write(int index, ArrayDataOutput out) throws IOException;
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143 abstract int read(int from, int n, ArrayDataInput in) throws EOFException, IOException;
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154 abstract void write(int from, int n, ArrayDataOutput out) throws IOException;
1155
1156
1157
1158
1159
1160
1161
1162
1163 void checkEntry(Object x) throws TableException {
1164
1165 if (x == null) {
1166 throw new TableException("Unexpected null element");
1167 }
1168
1169 if (!baseType().equals(x.getClass().getComponentType())) {
1170 throw new TableException(
1171 "Incompatible element type: " + x.getClass().getName() + ", expected " + arrayType());
1172 }
1173
1174 if (Array.getLength(x) != elementCount()) {
1175 throw new TableException(
1176 "Incompatible element size: " + Array.getLength(x) + ", expected " + elementCount());
1177 }
1178
1179 }
1180
1181
1182
1183
1184
1185
1186
1187
1188 abstract Object getArrayElement(int i);
1189
1190
1191
1192
1193
1194
1195
1196 abstract void setArrayElement(int i, Object o);
1197
1198
1199
1200
1201
1202
1203
1204 abstract void resize(int size);
1205
1206
1207
1208
1209
1210
1211
1212 void ensureSize(int size) {
1213 if (size > capacity()) {
1214 resize(size);
1215 }
1216 }
1217
1218
1219
1220
1221
1222
1223
1224 void trim(int size) {
1225 if (capacity() > size) {
1226 resize(size);
1227 }
1228 }
1229
1230 @SuppressWarnings("unchecked")
1231 @Override
1232 protected Column<Data> clone() {
1233 try {
1234 return (Column<Data>) super.clone();
1235 } catch (CloneNotSupportedException e) {
1236 return null;
1237 }
1238 }
1239
1240 @SuppressWarnings("unchecked")
1241 Data copyData(int length) {
1242 Data copy = (Data) Array.newInstance(baseType(), length);
1243 System.arraycopy(data, 0, copy, 0, Math.min(length, Array.getLength(data)));
1244 return copy;
1245 }
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255 Column<Data> copy(int size) {
1256 Column<Data> c = clone();
1257 c.data = copyData(size);
1258 return c;
1259 }
1260 }
1261
1262
1263
1264
1265
1266
1267 private static class Bytes extends Column<byte[]> {
1268
1269
1270 Bytes() {
1271 super(ElementType.BYTE);
1272 }
1273
1274 @Override
1275 void resize(int size) {
1276 data = Arrays.copyOf(data, size);
1277 }
1278
1279 @Override
1280 int read(int index, ArrayDataInput in) throws IOException {
1281 int i = in.read();
1282 if (i < 0) {
1283 throw new EOFException();
1284 }
1285 data[index] = (byte) i;
1286 return 1;
1287 }
1288
1289 @Override
1290 void write(int index, ArrayDataOutput out) throws IOException {
1291 out.write(data[index]);
1292 }
1293
1294 @Override
1295 int read(int from, int n, ArrayDataInput in) throws IOException {
1296 int got = in.read(data, from, n);
1297 if (got < 0) {
1298 throw new EOFException();
1299 }
1300 return -1;
1301 }
1302
1303 @Override
1304 void write(int from, int n, ArrayDataOutput out) throws IOException {
1305 out.write(data, from, n);
1306 }
1307
1308 @Override
1309 byte[] getArrayElement(int i) {
1310 return new byte[] {data[i]};
1311 }
1312
1313 @Override
1314 void setArrayElement(int i, Object o) {
1315 data[i] = ((byte[]) o)[0];
1316 }
1317
1318 }
1319
1320
1321
1322
1323
1324
1325 private static class Booleans extends Column<boolean[]> {
1326
1327
1328 Booleans() {
1329 super(ElementType.BOOLEAN);
1330 }
1331
1332 @Override
1333 void resize(int size) {
1334 data = Arrays.copyOf(data, size);
1335 }
1336
1337 @Override
1338 int read(int index, ArrayDataInput in) throws IOException {
1339 data[index] = in.readBoolean();
1340 return 1;
1341 }
1342
1343 @Override
1344 void write(int index, ArrayDataOutput out) throws IOException {
1345 out.writeBoolean(data[index]);
1346 }
1347
1348 @Override
1349 int read(int from, int n, ArrayDataInput in) throws IOException {
1350 return in.read(data, from, n);
1351 }
1352
1353 @Override
1354 void write(int from, int n, ArrayDataOutput out) throws IOException {
1355 out.write(data, from, n);
1356 }
1357
1358 @Override
1359 boolean[] getArrayElement(int i) {
1360 return new boolean[] {data[i]};
1361 }
1362
1363 @Override
1364 void setArrayElement(int i, Object o) {
1365 data[i] = ((boolean[]) o)[0];
1366 }
1367 }
1368
1369
1370
1371
1372
1373
1374 private static class Chars extends Column<char[]> {
1375
1376
1377 Chars() {
1378 super(ElementType.CHAR);
1379 }
1380
1381 @Override
1382 void resize(int size) {
1383 data = Arrays.copyOf(data, size);
1384 }
1385
1386 @Override
1387 int read(int index, ArrayDataInput in) throws IOException {
1388 data[index] = in.readChar();
1389 return ElementType.CHAR.size();
1390 }
1391
1392 @Override
1393 void write(int index, ArrayDataOutput out) throws IOException {
1394 out.writeChar(data[index]);
1395 }
1396
1397 @SuppressFBWarnings(value = "RR_NOT_CHECKED", justification = "not exposed and never needed locally")
1398 @Override
1399 int read(int from, int n, ArrayDataInput in) throws IOException {
1400 return in.read(data, from, n);
1401 }
1402
1403 @Override
1404 void write(int from, int n, ArrayDataOutput out) throws IOException {
1405 out.write(data, from, n);
1406 }
1407
1408 @Override
1409 char[] getArrayElement(int i) {
1410 return new char[] {data[i]};
1411 }
1412
1413 @Override
1414 void setArrayElement(int i, Object o) {
1415 data[i] = ((char[]) o)[0];
1416 }
1417 }
1418
1419
1420
1421
1422
1423
1424 private static class Shorts extends Column<short[]> {
1425
1426
1427 Shorts() {
1428 super(ElementType.SHORT);
1429 }
1430
1431 @Override
1432 void resize(int size) {
1433 data = Arrays.copyOf(data, size);
1434 }
1435
1436 @Override
1437 int read(int index, ArrayDataInput in) throws IOException {
1438 int i = in.readUnsignedShort();
1439 if (i < 0) {
1440 throw new EOFException();
1441 }
1442 data[index] = (short) i;
1443 return Short.BYTES;
1444 }
1445
1446 @Override
1447 void write(int index, ArrayDataOutput out) throws IOException {
1448 out.writeShort(data[index]);
1449 }
1450
1451 @SuppressFBWarnings(value = "RR_NOT_CHECKED", justification = "not exposed and never needed locally")
1452 @Override
1453 int read(int from, int n, ArrayDataInput in) throws IOException {
1454 return in.read(data, from, n);
1455 }
1456
1457 @Override
1458 void write(int from, int n, ArrayDataOutput out) throws IOException {
1459 out.write(data, from, n);
1460 }
1461
1462 @Override
1463 short[] getArrayElement(int i) {
1464 return new short[] {data[i]};
1465 }
1466
1467 @Override
1468 void setArrayElement(int i, Object o) {
1469 data[i] = ((short[]) o)[0];
1470 }
1471 }
1472
1473
1474
1475
1476
1477
1478 private static class Integers extends Column<int[]> {
1479
1480
1481 Integers() {
1482 super(ElementType.INT);
1483 }
1484
1485 @Override
1486 void resize(int size) {
1487 data = Arrays.copyOf(data, size);
1488 }
1489
1490 @Override
1491 int read(int index, ArrayDataInput in) throws IOException {
1492 data[index] = in.readInt();
1493 return Integer.BYTES;
1494 }
1495
1496 @Override
1497 void write(int index, ArrayDataOutput out) throws IOException {
1498 out.writeInt(data[index]);
1499 }
1500
1501 @Override
1502 int read(int from, int n, ArrayDataInput in) throws IOException {
1503 return in.read(data, from, n);
1504 }
1505
1506 @Override
1507 void write(int from, int n, ArrayDataOutput out) throws IOException {
1508 out.write(data, from, n);
1509 }
1510
1511 @Override
1512 int[] getArrayElement(int i) {
1513 return new int[] {data[i]};
1514 }
1515
1516 @Override
1517 void setArrayElement(int i, Object o) {
1518 data[i] = ((int[]) o)[0];
1519 }
1520 }
1521
1522
1523
1524
1525
1526
1527 private static class Longs extends Column<long[]> {
1528
1529
1530 Longs() {
1531 super(ElementType.LONG);
1532 }
1533
1534 @Override
1535 void resize(int size) {
1536 data = Arrays.copyOf(data, size);
1537 }
1538
1539 @Override
1540 int read(int index, ArrayDataInput in) throws IOException {
1541 data[index] = in.readLong();
1542 return Long.BYTES;
1543 }
1544
1545 @Override
1546 void write(int index, ArrayDataOutput out) throws IOException {
1547 out.writeLong(data[index]);
1548 }
1549
1550 @Override
1551 int read(int from, int n, ArrayDataInput in) throws IOException {
1552 return in.read(data, from, n);
1553 }
1554
1555 @Override
1556 void write(int from, int n, ArrayDataOutput out) throws IOException {
1557 out.write(data, from, n);
1558 }
1559
1560 @Override
1561 long[] getArrayElement(int i) {
1562 return new long[] {data[i]};
1563 }
1564
1565 @Override
1566 void setArrayElement(int i, Object o) {
1567 data[i] = ((long[]) o)[0];
1568 }
1569 }
1570
1571
1572
1573
1574
1575
1576 private static class Floats extends Column<float[]> {
1577
1578
1579 Floats() {
1580 super(ElementType.FLOAT);
1581 }
1582
1583 @Override
1584 void resize(int size) {
1585 data = Arrays.copyOf(data, size);
1586 }
1587
1588 @Override
1589 int read(int index, ArrayDataInput in) throws IOException {
1590 data[index] = in.readFloat();
1591 return Float.BYTES;
1592 }
1593
1594 @Override
1595 void write(int index, ArrayDataOutput out) throws IOException {
1596 out.writeFloat(data[index]);
1597 }
1598
1599 @Override
1600 int read(int from, int n, ArrayDataInput in) throws IOException {
1601 return in.read(data, from, n);
1602 }
1603
1604 @Override
1605 void write(int from, int n, ArrayDataOutput out) throws IOException {
1606 out.write(data, from, n);
1607 }
1608
1609 @Override
1610 float[] getArrayElement(int i) {
1611 return new float[] {data[i]};
1612 }
1613
1614 @Override
1615 void setArrayElement(int i, Object o) {
1616 data[i] = ((float[]) o)[0];
1617 }
1618 }
1619
1620
1621
1622
1623
1624
1625 private static class Doubles extends Column<double[]> {
1626
1627
1628 Doubles() {
1629 super(ElementType.DOUBLE);
1630 }
1631
1632 @Override
1633 void resize(int size) {
1634 data = Arrays.copyOf(data, size);
1635 }
1636
1637 @Override
1638 int read(int index, ArrayDataInput in) throws IOException {
1639 data[index] = in.readDouble();
1640 return Double.BYTES;
1641 }
1642
1643 @Override
1644 void write(int index, ArrayDataOutput out) throws IOException {
1645 out.writeDouble(data[index]);
1646 }
1647
1648 @Override
1649 int read(int from, int n, ArrayDataInput in) throws IOException {
1650 return in.read(data, from, n);
1651 }
1652
1653 @Override
1654 void write(int from, int n, ArrayDataOutput out) throws IOException {
1655 out.write(data, from, n);
1656 }
1657
1658 @Override
1659 double[] getArrayElement(int i) {
1660 return new double[] {data[i]};
1661 }
1662
1663 @Override
1664 void setArrayElement(int i, Object o) {
1665 data[i] = ((double[]) o)[0];
1666 }
1667 }
1668
1669
1670
1671
1672
1673
1674 private static class Generic extends Column<Object[]> {
1675 private Class<?> type;
1676 private int size;
1677
1678
1679
1680
1681
1682
1683
1684 Generic(Class<?> type, int size) {
1685 super(ElementType.forClass(type));
1686 this.type = type;
1687 this.size = size;
1688 }
1689
1690 @Override
1691 void init(Class<?> storeType) {
1692 data = (Object[]) Array.newInstance(storeType, 0, 0);
1693 }
1694
1695 @Override
1696 int elementCount() {
1697 return size;
1698 }
1699
1700 @Override
1701 void resize(int newSize) {
1702 data = Arrays.copyOf(data, newSize);
1703 }
1704
1705 @Override
1706 int read(int index, ArrayDataInput in) throws IOException {
1707 in.readArrayFully(data[index]);
1708 return size * getElementType().size();
1709 }
1710
1711 @Override
1712 void write(int index, ArrayDataOutput out) throws IOException {
1713 out.writeArray(data[index]);
1714 }
1715
1716 @Override
1717 int read(int from, int n, ArrayDataInput in) throws IOException {
1718 int to = from + n;
1719 for (int i = from; i < to; i++) {
1720 in.readArrayFully(data[i]);
1721 }
1722 return n * size * getElementType().size();
1723 }
1724
1725 @Override
1726 void write(int from, int n, ArrayDataOutput out) throws IOException {
1727 int to = from + n;
1728 for (int i = from; i < to; i++) {
1729 out.writeArray(data[i]);
1730 }
1731 }
1732
1733 @Override
1734 Object getArrayElement(int i) {
1735 return data[i];
1736 }
1737
1738 @Override
1739 void setArrayElement(int i, Object o) {
1740 data[i] = o;
1741 }
1742
1743 @Override
1744 Object[] copyData(int length) {
1745 Object[] array = Arrays.copyOf(data, length);
1746 for (int i = 0; i < length; i++) {
1747 array[i] = Array.newInstance(type, size);
1748 System.arraycopy(data[i], 0, array[i], 0, size);
1749 }
1750 return array;
1751 }
1752
1753 @Override
1754 Object getFlatData() {
1755 Object array = Array.newInstance(type, data.length * size);
1756 int offset = 0;
1757 for (int i = 0; i < data.length; i++, offset += size) {
1758 System.arraycopy(data[i], 0, array, offset, size);
1759 }
1760 return array;
1761 }
1762 }
1763
1764 }