Skip to content

Commit 626409a

Browse files
Implement sorting tables (#251)
1 parent c1a83e5 commit 626409a

File tree

3 files changed

+227
-15
lines changed

3 files changed

+227
-15
lines changed

libcobj/app/src/main/java/jp/osscons/opensourcecobol/libcobj/data/CobolDataStorage.java

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,10 +71,19 @@ public CobolDataStorage() {
7171
this.data = null;
7272
}
7373

74+
public void setDataRefAndIndex(CobolDataStorage data, int index) {
75+
this.data = data.data;
76+
this.index = index;
77+
}
78+
7479
public int getIndex() {
7580
return this.index;
7681
}
7782

83+
public void setIndex(int index) {
84+
this.index = index;
85+
}
86+
7887
public byte[] getRefOfData() {
7988
return this.data;
8089
}

libcobj/app/src/main/java/jp/osscons/opensourcecobol/libcobj/file/CobolFileSort.java

Lines changed: 174 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131
import jp.osscons.opensourcecobol.libcobj.common.CobolUtil;
3232
import jp.osscons.opensourcecobol.libcobj.data.AbstractCobolField;
3333
import jp.osscons.opensourcecobol.libcobj.data.CobolDataStorage;
34+
import jp.osscons.opensourcecobol.libcobj.data.CobolFieldAttribute;
3435
import jp.osscons.opensourcecobol.libcobj.data.CobolFieldFactory;
3536
import jp.osscons.opensourcecobol.libcobj.exceptions.CobolStopRunException;
3637

@@ -903,4 +904,177 @@ public static void performReturn(CobolFile f) {
903904
return;
904905
}
905906
}
907+
908+
/* Table sort */
909+
private static int sortNKeys;
910+
private static CobolFileKey[] sortKeys;
911+
private static CobolDataStorage sortCollate;
912+
private static CobolDataStorage pivotStorage = new CobolDataStorage();
913+
private static CobolDataStorage leftStorage = new CobolDataStorage();
914+
private static CobolDataStorage rightStorage = new CobolDataStorage();
915+
private static CobolDataStorage cmpStorage1 = new CobolDataStorage();
916+
private static CobolDataStorage cmpStorage2 = new CobolDataStorage();
917+
private static CobolDataStorage copyBuffer = null;
918+
private static CobolDataStorage tmpRecord = new CobolDataStorage();
919+
private static int copyBufferSizeMax = 0;
920+
private static int[] sortBuffer = null;
921+
private static AbstractCobolField cmpField1 =
922+
CobolFieldFactory.makeCobolField(
923+
0,
924+
cmpStorage1,
925+
new CobolFieldAttribute(CobolFieldAttribute.COB_TYPE_ALPHANUMERIC, 0, 0, 0, null));
926+
private static AbstractCobolField cmpField2 =
927+
CobolFieldFactory.makeCobolField(
928+
0,
929+
cmpStorage2,
930+
new CobolFieldAttribute(CobolFieldAttribute.COB_TYPE_ALPHANUMERIC, 0, 0, 0, null));
931+
932+
public static void sortTableInit(int nkeys, int collatingSequence) {
933+
sortTableInit(nkeys, null);
934+
}
935+
936+
public static void sortTableInit(int nkeys, CobolDataStorage collatingSequence) {
937+
sortNKeys = 0;
938+
if (sortKeys == null || sortKeys.length < nkeys) {
939+
sortKeys = new CobolFileKey[nkeys];
940+
}
941+
if (collatingSequence != null) {
942+
sortCollate = collatingSequence;
943+
} else {
944+
sortCollate = CobolModule.getCurrentModule().collating_sequence;
945+
}
946+
}
947+
948+
public static void sortTableInitKey(int flag, AbstractCobolField field, int offset) {
949+
if (sortKeys[sortNKeys] == null) {
950+
sortKeys[sortNKeys] = new CobolFileKey();
951+
}
952+
sortKeys[sortNKeys].setFlag(flag);
953+
sortKeys[sortNKeys].setField(
954+
CobolFieldFactory.makeCobolField(
955+
field.getSize(), (CobolDataStorage) null, field.getAttribute()));
956+
sortKeys[sortNKeys].setOffset(offset);
957+
sortNKeys++;
958+
}
959+
960+
public static void sortTable(AbstractCobolField f, int n) {
961+
int recordSize = f.getSize();
962+
if (sortBuffer == null || sortBuffer.length < n) {
963+
sortBuffer = new int[n];
964+
}
965+
for (int i = 0; i < n; ++i) {
966+
sortBuffer[i] = i;
967+
}
968+
CobolDataStorage baseStorage = f.getDataStorage();
969+
int baseStorageBaseIndex = baseStorage.getIndex();
970+
indexQuickSort(f.getDataStorage(), 0, n, recordSize);
971+
972+
int copyBufferSize = n * f.getSize();
973+
if (copyBuffer == null || copyBufferSizeMax < copyBufferSize) {
974+
copyBuffer = new CobolDataStorage(copyBufferSize);
975+
copyBufferSizeMax = copyBufferSize;
976+
}
977+
978+
for (int i = 0; i < n; ++i, copyBuffer.addIndex(recordSize)) {
979+
tmpRecord.setDataRefAndIndex(baseStorage, baseStorageBaseIndex + recordSize * sortBuffer[i]);
980+
copyBuffer.memcpy(tmpRecord, recordSize);
981+
}
982+
copyBuffer.setIndex(0);
983+
baseStorage.memcpy(copyBuffer, copyBufferSize);
984+
}
985+
986+
private static void indexQuickSort(
987+
CobolDataStorage base, int mostLeft, int mostRight, int recordSize) {
988+
989+
if (mostRight - mostLeft <= 1) {
990+
return;
991+
}
992+
993+
int pivot = (mostRight + mostLeft) / 2;
994+
int left = mostLeft, right = mostRight - 1;
995+
996+
while (true) {
997+
pivotStorage.setDataRefAndIndex(base, base.getIndex() + sortBuffer[pivot] * recordSize);
998+
boolean elementBiggerThanPivot = false;
999+
for (; left < pivot; ++left) {
1000+
leftStorage.setDataRefAndIndex(base, base.getIndex() + sortBuffer[left] * recordSize);
1001+
if (compareStorageForSort(leftStorage, pivotStorage) > 0) {
1002+
elementBiggerThanPivot = true;
1003+
break;
1004+
}
1005+
}
1006+
boolean elementSmallerThanPivot = false;
1007+
for (; right > pivot; --right) {
1008+
rightStorage.setDataRefAndIndex(base, base.getIndex() + sortBuffer[right] * recordSize);
1009+
if (compareStorageForSort(pivotStorage, rightStorage) > 0) {
1010+
elementSmallerThanPivot = true;
1011+
break;
1012+
}
1013+
}
1014+
if (elementBiggerThanPivot && elementSmallerThanPivot) {
1015+
swap2Indecies(left, right);
1016+
++left;
1017+
--right;
1018+
} else if (elementBiggerThanPivot && !elementSmallerThanPivot) {
1019+
if (left + 1 == pivot) {
1020+
swap2Indecies(left, pivot);
1021+
} else {
1022+
rotate3Indecies(pivot, pivot - 1, left);
1023+
}
1024+
--pivot;
1025+
} else if (!elementBiggerThanPivot && elementSmallerThanPivot) {
1026+
if (right - 1 == pivot) {
1027+
swap2Indecies(pivot, right);
1028+
} else {
1029+
rotate3Indecies(pivot, pivot + 1, right);
1030+
}
1031+
++pivot;
1032+
} else {
1033+
break;
1034+
}
1035+
}
1036+
indexQuickSort(base, mostLeft, pivot, recordSize);
1037+
indexQuickSort(base, pivot + 1, mostRight, recordSize);
1038+
}
1039+
1040+
private static int compareStorageForSort(CobolDataStorage s1, CobolDataStorage s2) {
1041+
for (int i = 0; i < sortNKeys; ++i) {
1042+
int keySize = sortKeys[i].getField().getSize();
1043+
cmpField1.setSize(keySize);
1044+
cmpField2.setSize(keySize);
1045+
1046+
CobolFieldAttribute attr = sortKeys[i].getField().getAttribute();
1047+
cmpField1.setAttribute(attr);
1048+
cmpField2.setAttribute(attr);
1049+
1050+
cmpStorage1.setDataRefAndIndex(s1, s1.getIndex() + sortKeys[i].getOffset());
1051+
cmpStorage2.setDataRefAndIndex(s2, s2.getIndex() + sortKeys[i].getOffset());
1052+
1053+
int cmp;
1054+
if (attr.isTypeNumeric()) {
1055+
cmp = cmpField1.numericCompareTo(cmpField2);
1056+
} else if (attr.isTypeNational()) {
1057+
cmp = CobolUtil.nationalCmps(s1, s2, keySize, sortCollate);
1058+
} else {
1059+
cmp = cmpField1.cmpAlnum(cmpField2);
1060+
}
1061+
if (cmp != 0) {
1062+
return (sortKeys[i].getFlag() == COB_ASCENDING) ? cmp : -cmp;
1063+
}
1064+
}
1065+
return 0;
1066+
}
1067+
1068+
private static void swap2Indecies(int a, int b) {
1069+
int tmp = sortBuffer[a];
1070+
sortBuffer[a] = sortBuffer[b];
1071+
sortBuffer[b] = tmp;
1072+
}
1073+
1074+
private static void rotate3Indecies(int a, int b, int c) {
1075+
int tmp = sortBuffer[c];
1076+
sortBuffer[c] = sortBuffer[b];
1077+
sortBuffer[b] = sortBuffer[a];
1078+
sortBuffer[a] = tmp;
1079+
}
9061080
}

tests/run.src/miscellaneous.at

Lines changed: 44 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1366,30 +1366,50 @@ AT_CLEANUP
13661366

13671367

13681368
AT_SETUP([SORT: table sort])
1369-
AT_CHECK([${SKIP_TEST}])
13701369

13711370
AT_DATA([prog.cob], [
13721371
IDENTIFICATION DIVISION.
13731372
PROGRAM-ID. prog.
13741373
DATA DIVISION.
13751374
WORKING-STORAGE SECTION.
13761375
01 G VALUE "d4b2e1a3c5".
1377-
02 TBL OCCURS 5.
1376+
02 TBL-G OCCURS 5.
13781377
03 X PIC X.
13791378
03 Y PIC 9.
1380-
PROCEDURE DIVISION.
1381-
SORT TBL ASCENDING KEY X.
1382-
DISPLAY G
1383-
END-DISPLAY.
1384-
SORT TBL DESCENDING KEY Y.
1385-
DISPLAY G
1386-
END-DISPLAY.
1387-
SORT TBL ASCENDING KEY TBL.
1388-
DISPLAY G
1389-
END-DISPLAY.
1390-
SORT TBL DESCENDING KEY.
1391-
DISPLAY G
1392-
END-DISPLAY.
1379+
01 H VALUE "d4Db2Be3Ea5Ac6Cf1F".
1380+
02 TBL-H OCCURS 6.
1381+
03 A PIC X.
1382+
03 B PIC 9.
1383+
03 C PIC X.
1384+
PROCEDURE DIVISION.
1385+
SORT TBL-G ASCENDING KEY X.
1386+
DISPLAY G.
1387+
SORT TBL-G DESCENDING KEY Y.
1388+
DISPLAY G.
1389+
SORT TBL-G ASCENDING KEY TBL-G.
1390+
DISPLAY G.
1391+
SORT TBL-G DESCENDING KEY.
1392+
DISPLAY G.
1393+
1394+
SORT TBL-H ASCENDING KEY A.
1395+
DISPLAY H.
1396+
SORT TBL-H DESCENDING KEY B.
1397+
DISPLAY H.
1398+
SORT TBL-H DESCENDING KEY C.
1399+
DISPLAY H.
1400+
SORT TBL-H ASCENDING KEY TBL-H.
1401+
DISPLAY H.
1402+
SORT TBL-H DESCENDING KEY.
1403+
DISPLAY H.
1404+
1405+
SORT TBL-G ASCENDING KEY X.
1406+
DISPLAY G.
1407+
SORT TBL-G DESCENDING KEY Y.
1408+
DISPLAY G.
1409+
SORT TBL-G ASCENDING KEY TBL-G.
1410+
DISPLAY G.
1411+
SORT TBL-G DESCENDING KEY.
1412+
DISPLAY G.
13931413
STOP RUN.
13941414
])
13951415

@@ -1399,6 +1419,15 @@ AT_CHECK([java prog], [0],
13991419
c5d4a3b2e1
14001420
a3b2c5d4e1
14011421
e1d4c5b2a3
1422+
a5Ab2Bc6Cd4De3Ef1F
1423+
c6Ca5Ad4De3Eb2Bf1F
1424+
f1Fe3Ed4Dc6Cb2Ba5A
1425+
a5Ab2Bc6Cd4De3Ef1F
1426+
f1Fe3Ed4Dc6Cb2Ba5A
1427+
a3b2c5d4e1
1428+
c5d4a3b2e1
1429+
a3b2c5d4e1
1430+
e1d4c5b2a3
14021431
])
14031432

14041433
AT_CLEANUP

0 commit comments

Comments
 (0)