|
34 | 34 | import java.io.InputStream; |
35 | 35 | import java.io.OutputStream; |
36 | 36 | import java.lang.management.ManagementFactory; |
| 37 | +import java.nio.ByteBuffer; |
| 38 | +import java.nio.CharBuffer; |
| 39 | +import java.nio.charset.Charset; |
| 40 | +import java.nio.charset.CharsetDecoder; |
| 41 | +import java.nio.charset.CoderResult; |
| 42 | +import java.nio.charset.CodingErrorAction; |
37 | 43 | import java.nio.file.Files; |
38 | 44 | import java.nio.file.InvalidPathException; |
39 | 45 | import java.nio.file.NoSuchFileException; |
@@ -80,6 +86,56 @@ public static void main(String[] args) { |
80 | 86 | new GraalPythonMain().launch(args); |
81 | 87 | } |
82 | 88 |
|
| 89 | + @Override |
| 90 | + protected String decodeArgument(byte[] argument) { |
| 91 | + Charset charset = Charset.defaultCharset(); |
| 92 | + String decoded = new String(argument, charset); |
| 93 | + if (decoded.indexOf('\uFFFD') < 0) { |
| 94 | + return decoded; |
| 95 | + } |
| 96 | + return decodeArgument(argument, charset); |
| 97 | + } |
| 98 | + |
| 99 | + /* |
| 100 | + * Match documented Unix sys.argv behavior: |
| 101 | + * https://docs.python.org/3.12/library/sys.html#sys.argv |
| 102 | + * "When you need original bytes, you can get it by `[os.fsencode(arg) for arg in sys.argv]`." |
| 103 | + */ |
| 104 | + private static String decodeArgument(byte[] argument, Charset charset) { |
| 105 | + CharsetDecoder decoder = charset.newDecoder().onMalformedInput(CodingErrorAction.REPORT).onUnmappableCharacter(CodingErrorAction.REPORT); |
| 106 | + StringBuilder builder = new StringBuilder(argument.length); |
| 107 | + ByteBuffer in = ByteBuffer.wrap(argument); |
| 108 | + CharBuffer out = CharBuffer.allocate(Math.max(1, (int) Math.ceil(argument.length * decoder.maxCharsPerByte()))); |
| 109 | + while (true) { |
| 110 | + CoderResult result = decoder.decode(in, out, true); |
| 111 | + appendDecodedChars(builder, out); |
| 112 | + if (result.isUnderflow()) { |
| 113 | + break; |
| 114 | + } else if (result.isOverflow()) { |
| 115 | + continue; |
| 116 | + } else if (result.isError()) { |
| 117 | + int errorLength = result.length(); |
| 118 | + for (int i = 0; i < errorLength && in.hasRemaining(); i++) { |
| 119 | + builder.append((char) (0xDC00 + (in.get() & 0xff))); |
| 120 | + } |
| 121 | + } |
| 122 | + } |
| 123 | + while (true) { |
| 124 | + CoderResult result = decoder.flush(out); |
| 125 | + appendDecodedChars(builder, out); |
| 126 | + if (result.isUnderflow()) { |
| 127 | + break; |
| 128 | + } |
| 129 | + } |
| 130 | + return builder.toString(); |
| 131 | + } |
| 132 | + |
| 133 | + private static void appendDecodedChars(StringBuilder builder, CharBuffer out) { |
| 134 | + out.flip(); |
| 135 | + builder.append(out); |
| 136 | + out.clear(); |
| 137 | + } |
| 138 | + |
83 | 139 | private static final String LANGUAGE_ID = "python"; |
84 | 140 |
|
85 | 141 | private static final String J_PYENVCFG = "pyvenv.cfg"; |
|
0 commit comments