759 if (output.remaining() < outLenNeeded) { |
759 if (output.remaining() < outLenNeeded) { |
760 throw new ShortBufferException("Need at least " + outLenNeeded |
760 throw new ShortBufferException("Need at least " + outLenNeeded |
761 + " bytes of space in output buffer"); |
761 + " bytes of space in output buffer"); |
762 } |
762 } |
763 |
763 |
|
764 // detecting input and output buffer overlap may be tricky |
|
765 // we can only write directly into output buffer when we |
|
766 // are 100% sure it's safe to do so |
|
767 |
764 boolean a1 = input.hasArray(); |
768 boolean a1 = input.hasArray(); |
765 boolean a2 = output.hasArray(); |
769 boolean a2 = output.hasArray(); |
766 int total = 0; |
770 int total = 0; |
767 byte[] inArray, outArray; |
771 |
768 if (a2) { // output has an accessible byte[] |
772 if (a1) { // input has an accessible byte[] |
769 outArray = output.array(); |
773 byte[] inArray = input.array(); |
770 int outPos = output.position(); |
774 int inOfs = input.arrayOffset() + inPos; |
771 int outOfs = output.arrayOffset() + outPos; |
775 |
772 |
776 if (a2) { // output has an accessible byte[] |
773 if (a1) { // input also has an accessible byte[] |
777 byte[] outArray = output.array(); |
774 inArray = input.array(); |
778 int outPos = output.position(); |
775 int inOfs = input.arrayOffset() + inPos; |
779 int outOfs = output.arrayOffset() + outPos; |
|
780 |
|
781 // check array address and offsets and use temp output buffer |
|
782 // if output offset is larger than input offset and |
|
783 // falls within the range of input data |
|
784 boolean useTempOut = false; |
|
785 if (inArray == outArray && |
|
786 ((inOfs < outOfs) && (outOfs < inOfs + inLen))) { |
|
787 useTempOut = true; |
|
788 outArray = new byte[outLenNeeded]; |
|
789 outOfs = 0; |
|
790 } |
776 if (isUpdate) { |
791 if (isUpdate) { |
777 total = engineUpdate(inArray, inOfs, inLen, outArray, outOfs); |
792 total = engineUpdate(inArray, inOfs, inLen, outArray, outOfs); |
778 } else { |
793 } else { |
779 total = engineDoFinal(inArray, inOfs, inLen, outArray, outOfs); |
794 total = engineDoFinal(inArray, inOfs, inLen, outArray, outOfs); |
780 } |
795 } |
|
796 if (useTempOut) { |
|
797 output.put(outArray, outOfs, total); |
|
798 } else { |
|
799 // adjust output position manually |
|
800 output.position(outPos + total); |
|
801 } |
|
802 // adjust input position manually |
781 input.position(inLimit); |
803 input.position(inLimit); |
782 } else { // input does not have accessible byte[] |
804 } else { // output does not have an accessible byte[] |
783 inArray = new byte[getTempArraySize(inLen)]; |
805 byte[] outArray = null; |
784 do { |
|
785 int chunk = Math.min(inLen, inArray.length); |
|
786 if (chunk > 0) { |
|
787 input.get(inArray, 0, chunk); |
|
788 } |
|
789 int n; |
|
790 if (isUpdate || (inLen > chunk)) { |
|
791 n = engineUpdate(inArray, 0, chunk, outArray, outOfs); |
|
792 } else { |
|
793 n = engineDoFinal(inArray, 0, chunk, outArray, outOfs); |
|
794 } |
|
795 total += n; |
|
796 outOfs += n; |
|
797 inLen -= chunk; |
|
798 } while (inLen > 0); |
|
799 } |
|
800 output.position(outPos + total); |
|
801 } else { // output does not have an accessible byte[] |
|
802 if (a1) { // but input has an accessible byte[] |
|
803 inArray = input.array(); |
|
804 int inOfs = input.arrayOffset() + inPos; |
|
805 if (isUpdate) { |
806 if (isUpdate) { |
806 outArray = engineUpdate(inArray, inOfs, inLen); |
807 outArray = engineUpdate(inArray, inOfs, inLen); |
807 } else { |
808 } else { |
808 outArray = engineDoFinal(inArray, inOfs, inLen); |
809 outArray = engineDoFinal(inArray, inOfs, inLen); |
809 } |
810 } |
810 input.position(inLimit); |
|
811 if (outArray != null && outArray.length != 0) { |
811 if (outArray != null && outArray.length != 0) { |
812 output.put(outArray); |
812 output.put(outArray); |
813 total = outArray.length; |
813 total = outArray.length; |
814 } |
814 } |
815 } else { // input also does not have an accessible byte[] |
815 // adjust input position manually |
816 inArray = new byte[getTempArraySize(inLen)]; |
816 input.position(inLimit); |
817 do { |
817 } |
818 int chunk = Math.min(inLen, inArray.length); |
818 } else { // input does not have an accessible byte[] |
819 if (chunk > 0) { |
819 // have to assume the worst, since we have no way of determine |
820 input.get(inArray, 0, chunk); |
820 // if input and output overlaps or not |
821 } |
821 byte[] tempOut = new byte[outLenNeeded]; |
822 int n; |
822 int outOfs = 0; |
823 if (isUpdate || (inLen > chunk)) { |
823 |
824 outArray = engineUpdate(inArray, 0, chunk); |
824 byte[] tempIn = new byte[getTempArraySize(inLen)]; |
825 } else { |
825 do { |
826 outArray = engineDoFinal(inArray, 0, chunk); |
826 int chunk = Math.min(inLen, tempIn.length); |
827 } |
827 if (chunk > 0) { |
828 if (outArray != null && outArray.length != 0) { |
828 input.get(tempIn, 0, chunk); |
829 output.put(outArray); |
829 } |
830 total += outArray.length; |
830 int n; |
831 } |
831 if (isUpdate || (inLen > chunk)) { |
832 inLen -= chunk; |
832 n = engineUpdate(tempIn, 0, chunk, tempOut, outOfs); |
833 } while (inLen > 0); |
833 } else { |
|
834 n = engineDoFinal(tempIn, 0, chunk, tempOut, outOfs); |
|
835 } |
|
836 outOfs += n; |
|
837 total += n; |
|
838 inLen -= chunk; |
|
839 } while (inLen > 0); |
|
840 if (total > 0) { |
|
841 output.put(tempOut, 0, total); |
834 } |
842 } |
835 } |
843 } |
|
844 |
836 return total; |
845 return total; |
837 } |
846 } |
838 |
847 |
839 /** |
848 /** |
840 * Wrap a key. |
849 * Wrap a key. |