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