|
1 | 1 | package org.perlonjava.operators; |
2 | 2 |
|
3 | 3 | import org.perlonjava.operators.unpack.*; |
4 | | -import org.perlonjava.runtime.PerlCompilerException; |
5 | | -import org.perlonjava.runtime.RuntimeBase; |
6 | | -import org.perlonjava.runtime.RuntimeList; |
7 | | -import org.perlonjava.runtime.RuntimeScalar; |
| 4 | +import org.perlonjava.runtime.*; |
8 | 5 |
|
9 | 6 | import java.util.*; |
10 | 7 |
|
| 8 | +import static org.perlonjava.runtime.RuntimeScalarCache.scalarUndef; |
| 9 | + |
11 | 10 | /** |
12 | 11 | * Provides functionality to unpack binary data into a list of scalars |
13 | 12 | * based on a specified template, similar to Perl's unpack function. |
@@ -41,20 +40,22 @@ public class Unpack { |
41 | 40 | handlers.put('H', new HexStringFormatHandler('H')); |
42 | 41 | handlers.put('W', new WFormatHandler()); |
43 | 42 | handlers.put('x', new XFormatHandler()); |
| 43 | + handlers.put('X', new XBackwardHandler()); // Add this line |
44 | 44 | handlers.put('w', new WBERFormatHandler()); |
45 | 45 | handlers.put('p', new PointerFormatHandler()); |
46 | 46 | handlers.put('u', new UuencodeFormatHandler()); |
47 | 47 | handlers.put('@', new AtFormatHandler()); // Add this line |
48 | 48 | // Note: U handler is created dynamically based on startsWithU |
49 | 49 | } |
50 | 50 |
|
51 | | - public static RuntimeList unpack(RuntimeList args) { |
52 | | - if (args.elements.size() < 2) { |
53 | | - throw new PerlCompilerException("unpack: not enough arguments"); |
54 | | - } |
55 | | - |
56 | | - RuntimeScalar templateScalar = (RuntimeScalar) args.elements.get(0); |
57 | | - RuntimeScalar packedData = args.elements.get(1).scalar(); |
| 51 | + /** unpack(template, data) |
| 52 | + * |
| 53 | + * @param args |
| 54 | + * @return |
| 55 | + */ |
| 56 | + public static RuntimeList unpack(int ctx, RuntimeBase... args) { |
| 57 | + RuntimeScalar templateScalar = (RuntimeScalar) args[0]; |
| 58 | + RuntimeScalar packedData = args.length > 1 ? args[1].scalar() : scalarUndef; |
58 | 59 |
|
59 | 60 | String template = templateScalar.toString(); |
60 | 61 | String dataString = packedData.toString(); |
@@ -210,13 +211,16 @@ public static RuntimeList unpack(RuntimeList args) { |
210 | 211 | boolean hasStarAfterSlash = false; |
211 | 212 | if (i + 1 < template.length() && template.charAt(i + 1) == '*') { |
212 | 213 | hasStarAfterSlash = true; |
213 | | - i++; // consume the '*' |
| 214 | + i++; // Move to the '*' |
214 | 215 | } |
215 | 216 |
|
216 | 217 | // Unpack the string with the count from the previous numeric value |
217 | 218 | FormatHandler stringHandler = handlers.get(stringFormat); |
218 | | - // Pass slashCount as the count, and hasStarAfterSlash as isStarCount |
219 | 219 | stringHandler.unpack(state, values, slashCount, hasStarAfterSlash); |
| 220 | + |
| 221 | + // IMPORTANT: Skip past all characters we've processed |
| 222 | + // The continue statement will skip the normal i++ at the end of the loop |
| 223 | + i++; // Move past the last character we processed |
220 | 224 | continue; |
221 | 225 | } |
222 | 226 |
|
@@ -251,14 +255,21 @@ public static RuntimeList unpack(RuntimeList args) { |
251 | 255 | while (j < template.length() && Character.isDigit(template.charAt(j))) { |
252 | 256 | j++; |
253 | 257 | } |
254 | | - count = Integer.parseInt(template.substring(i + 1, j)); |
| 258 | + String countStr = template.substring(i + 1, j); |
| 259 | + count = Integer.parseInt(countStr); |
| 260 | + if (format == '@') { |
| 261 | + System.err.println("DEBUG: @ count string '" + countStr + "' parsed to " + count); |
| 262 | + } |
255 | 263 | i = j - 1; |
256 | 264 | } |
257 | 265 | } |
258 | 266 |
|
259 | 267 | // Get handler and unpack |
260 | 268 | FormatHandler handler = getHandler(format, startsWithU); |
261 | 269 | if (handler != null) { |
| 270 | + if (format == '@') { |
| 271 | + System.err.println("DEBUG: Calling @ handler with count=" + count); |
| 272 | + } |
262 | 273 | // For 'p' format, check and consume endianness modifiers |
263 | 274 | if (format == 'p' && i + 1 < template.length()) { |
264 | 275 | char nextChar = template.charAt(i + 1); |
|
0 commit comments