|
31 | 31 | import jp.osscons.opensourcecobol.libcobj.common.CobolUtil; |
32 | 32 | import jp.osscons.opensourcecobol.libcobj.data.AbstractCobolField; |
33 | 33 | import jp.osscons.opensourcecobol.libcobj.data.CobolDataStorage; |
| 34 | +import jp.osscons.opensourcecobol.libcobj.data.CobolFieldAttribute; |
34 | 35 | import jp.osscons.opensourcecobol.libcobj.data.CobolFieldFactory; |
35 | 36 | import jp.osscons.opensourcecobol.libcobj.exceptions.CobolStopRunException; |
36 | 37 |
|
@@ -903,4 +904,177 @@ public static void performReturn(CobolFile f) { |
903 | 904 | return; |
904 | 905 | } |
905 | 906 | } |
| 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 | + } |
906 | 1080 | } |
0 commit comments