@@ -806,4 +806,192 @@ public PBytes maketrans(@SuppressWarnings("unused") PythonClass cls, Object from
806
806
}
807
807
808
808
}
809
+
810
+ // bytes.translate(table, delete=b'')
811
+ // bytearray.translate(table, delete=b'')
812
+ @ Builtin (name = "translate" , minNumOfPositionalArgs = 2 , maxNumOfPositionalArgs = 3 , keywordArguments = {"delete" })
813
+ @ GenerateNodeFactory
814
+ public abstract static class TranslateNode extends PythonBuiltinNode {
815
+
816
+ @ Child BytesNodes .ToBytesNode toBytesNode ;
817
+
818
+ @ CompilationFinal private ConditionProfile isLenTable256Profile ;
819
+
820
+ private BytesNodes .ToBytesNode getToBytesNode () {
821
+ if (toBytesNode == null ) {
822
+ CompilerDirectives .transferToInterpreterAndInvalidate ();
823
+ toBytesNode = insert (BytesNodes .ToBytesNode .create ());
824
+ }
825
+ return toBytesNode ;
826
+ }
827
+
828
+ private void checkLengthOfTable (byte [] table ) {
829
+ if (isLenTable256Profile == null ) {
830
+ CompilerDirectives .transferToInterpreterAndInvalidate ();
831
+ isLenTable256Profile = ConditionProfile .createBinaryProfile ();
832
+ }
833
+
834
+ if (isLenTable256Profile .profile (table .length != 256 )) {
835
+ throw raise (PythonErrorType .ValueError , "translation table must be 256 characters long" );
836
+ }
837
+ }
838
+
839
+ private static class Result {
840
+ byte [] array ;
841
+ // we have to know, whether the result array was changed ->
842
+ // if not in bytes case it has to return the input bytes
843
+ // in bytearray case it has to return always new bytearray
844
+ boolean changed ;
845
+
846
+ public Result (byte [] array , boolean changed ) {
847
+ this .array = array ;
848
+ this .changed = changed ;
849
+ }
850
+ }
851
+
852
+ private static boolean [] createDeleteTable (byte [] delete ) {
853
+ boolean [] result = new boolean [256 ];
854
+ for (int i = 0 ; i < 256 ; i ++) {
855
+ result [i ] = false ;
856
+ }
857
+ for (int i = 0 ; i < delete .length ; i ++) {
858
+ result [delete [i ]] = true ;
859
+ }
860
+ return result ;
861
+ }
862
+
863
+ private static Result delete (byte [] self , byte [] table ) {
864
+ final int length = self .length ;
865
+ byte [] result = new byte [length ];
866
+ int resultLen = 0 ;
867
+ boolean [] toDelete = createDeleteTable (table );
868
+
869
+ for (int i = 0 ; i < length ; i ++) {
870
+ if (!toDelete [self [i ] & 0xFF ]) {
871
+ result [resultLen ] = self [i ];
872
+ resultLen ++;
873
+ }
874
+ }
875
+ if (resultLen == length ) {
876
+ return new Result (result , false );
877
+ }
878
+ return new Result (Arrays .copyOf (result , resultLen ), true );
879
+ }
880
+
881
+ private static Result translate (byte [] self , byte [] table ) {
882
+ final int length = self .length ;
883
+ byte [] result = new byte [length ];
884
+ boolean changed = false ;
885
+ for (int i = 0 ; i < length ; i ++) {
886
+ byte b = table [self [i ]];
887
+ if (!changed && b != self [i ]) {
888
+ changed = true ;
889
+ }
890
+ result [i ] = b ;
891
+ }
892
+ return new Result (result , changed );
893
+ }
894
+
895
+ private static Result translateAndDelete (byte [] self , byte [] table , byte [] delete ) {
896
+ final int length = self .length ;
897
+ byte [] result = new byte [length ];
898
+ int resultLen = 0 ;
899
+ boolean changed = false ;
900
+ boolean [] toDelete = createDeleteTable (delete );
901
+
902
+ for (int i = 0 ; i < length ; i ++) {
903
+ if (!toDelete [self [i ]]) {
904
+ byte b = table [self [i ]];
905
+ if (!changed && b != self [i ]) {
906
+ changed = true ;
907
+ }
908
+ result [resultLen ] = b ;
909
+ resultLen ++;
910
+ }
911
+ }
912
+ if (resultLen == length ) {
913
+ return new Result (result , changed );
914
+ }
915
+ return new Result (Arrays .copyOf (result , resultLen ), true );
916
+ }
917
+
918
+ @ Specialization (guards = "isNoValue(delete)" )
919
+ public PBytes translate (PBytes self , @ SuppressWarnings ("unused" ) PNone table , @ SuppressWarnings ("unused" ) PNone delete ) {
920
+ return self ;
921
+ }
922
+
923
+ @ Specialization (guards = "isNoValue(delete)" )
924
+ public PByteArray translate (PByteArray self , @ SuppressWarnings ("unused" ) PNone table , @ SuppressWarnings ("unused" ) PNone delete ) {
925
+ return factory ().createByteArray (self .getSequenceStorage ().copy ());
926
+ }
927
+
928
+ @ Specialization
929
+ public PBytes translate (PBytes self , Object table , @ SuppressWarnings ("unused" ) PNone delete ) {
930
+ byte [] bTable = getToBytesNode ().execute (table );
931
+ checkLengthOfTable (bTable );
932
+ byte [] bSelf = getToBytesNode ().execute (self );
933
+
934
+ Result result = translate (bSelf , bTable );
935
+ if (result .changed ) {
936
+ return factory ().createBytes (result .array );
937
+ }
938
+ return self ;
939
+ }
940
+
941
+ @ Specialization
942
+ public PByteArray translate (PByteArray self , Object table , @ SuppressWarnings ("unused" ) PNone delete ) {
943
+ byte [] bTable = getToBytesNode ().execute (table );
944
+ checkLengthOfTable (bTable );
945
+ byte [] bSelf = getToBytesNode ().execute (self );
946
+
947
+ Result result = translate (bSelf , bTable );
948
+ return factory ().createByteArray (result .array );
949
+ }
950
+
951
+ @ Specialization (guards = "isNone(table)" )
952
+ public PBytes delete (PBytes self , @ SuppressWarnings ("unused" ) PNone table , Object delete ) {
953
+ byte [] bSelf = getToBytesNode ().execute (self );
954
+ byte [] bDelete = getToBytesNode ().execute (delete );
955
+
956
+ Result result = delete (bSelf , bDelete );
957
+ if (result .changed ) {
958
+ return factory ().createBytes (result .array );
959
+ }
960
+ return self ;
961
+ }
962
+
963
+ @ Specialization (guards = "isNone(table)" )
964
+ public PByteArray delete (PByteArray self , @ SuppressWarnings ("unused" ) PNone table , Object delete ) {
965
+ byte [] bSelf = getToBytesNode ().execute (self );
966
+ byte [] bDelete = getToBytesNode ().execute (delete );
967
+
968
+ Result result = delete (bSelf , bDelete );
969
+ return factory ().createByteArray (result .array );
970
+ }
971
+
972
+ @ Specialization (guards = {"!isPNone(table)" , "!isPNone(delete)" })
973
+ public PBytes translateAndDelete (PBytes self , Object table , Object delete ) {
974
+ byte [] bTable = getToBytesNode ().execute (table );
975
+ checkLengthOfTable (bTable );
976
+ byte [] bDelete = getToBytesNode ().execute (delete );
977
+ byte [] bSelf = getToBytesNode ().execute (self );
978
+
979
+ Result result = translateAndDelete (bSelf , bTable , bDelete );
980
+ if (result .changed ) {
981
+ return factory ().createBytes (result .array );
982
+ }
983
+ return self ;
984
+ }
985
+
986
+ @ Specialization (guards = {"!isPNone(table)" , "!isPNone(delete)" })
987
+ public PByteArray translateAndDelete (PByteArray self , Object table , Object delete ) {
988
+ byte [] bTable = getToBytesNode ().execute (table );
989
+ checkLengthOfTable (bTable );
990
+ byte [] bDelete = getToBytesNode ().execute (delete );
991
+ byte [] bSelf = getToBytesNode ().execute (self );
992
+
993
+ Result result = translateAndDelete (bSelf , bTable , bDelete );
994
+ return factory ().createByteArray (result .array );
995
+ }
996
+ }
809
997
}
0 commit comments