Author: lehmi
Date: Wed Jun 18 14:47:27 2025
New Revision: 1926545
URL: http://svn.apache.org/viewvc?rev=1926545&view=rev
Log:
PDFBOX-5997: avoid creation of temporary objects as proposed by Axel Howind
Modified:
pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/cos/COSString.java
pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/util/Hex.java
Modified: pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/cos/COSString.java
URL:
http://svn.apache.org/viewvc/pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/cos/COSString.java?rev=1926545&r1=1926544&r2=1926545&view=diff
==============================================================================
--- pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/cos/COSString.java
(original)
+++ pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/cos/COSString.java Wed
Jun 18 14:47:27 2025
@@ -135,36 +135,60 @@ public final class COSString extends COS
*/
public static COSString parseHex(String hex) throws IOException
{
- StringBuilder hexBuffer = new StringBuilder(hex.trim());
-
- // if odd number then the last hex digit is assumed to be 0
- if (hexBuffer.length() % 2 != 0)
+ // skip leading and trailing whitespace
+ int end = hex.length();
+ while (end > 0 && Character.isWhitespace(hex.charAt(end - 1)))
+ {
+ end--;
+ }
+ int start = 0;
+ while (start < end && Character.isWhitespace(hex.charAt(start)))
{
- hexBuffer.append('0');
+ start++;
}
- int length = hexBuffer.length();
+ int length = end - start;
ByteArrayOutputStream bytes = new ByteArrayOutputStream((length + 1) /
2);
+
+ boolean isLengthUneven = length % 2 != 0;
+ if (isLengthUneven)
+ {
+ length--;
+ }
for (int i = 0; i < length; i += 2)
{
- try
+ int value = 16 * Hex.getHexValue(hex.charAt(i)) +
Hex.getHexValue(hex.charAt(i + 1));
+ if (value >= 0)
+ {
+ bytes.write(value);
+ }
+ else if (FORCE_PARSING)
{
- bytes.write(Integer.parseInt(hexBuffer.substring(i, i + 2),
16));
+ LOG.warn("Encountered a malformed hex string");
+ bytes.write('?'); // todo: what does Acrobat do? Any example
PDFs?
}
- catch (NumberFormatException e)
+ else
{
- if (FORCE_PARSING)
- {
- LOG.warn("Encountered a malformed hex string");
- bytes.write('?'); // todo: what does Acrobat do? Any
example PDFs?
- }
- else
- {
- throw new IOException("Invalid hex string: " + hex, e);
- }
+ throw new IOException("Invalid hex string: " + hex);
+ }
+ }
+ if (isLengthUneven)
+ {
+ int value = 16 * Hex.getHexValue(hex.charAt(length));
+ if (value >= 0)
+ {
+ bytes.write(value);
+ }
+ else if (FORCE_PARSING)
+ {
+ LOG.warn("Encountered a malformed hex string");
+ bytes.write('?'); // todo: what does Acrobat do? Any example
PDFs?
+ }
+ else
+ {
+ throw new IOException("Invalid hex string: " + hex);
}
}
-
return new COSString(bytes.toByteArray());
}
Modified: pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/util/Hex.java
URL:
http://svn.apache.org/viewvc/pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/util/Hex.java?rev=1926545&r1=1926544&r2=1926545&view=diff
==============================================================================
--- pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/util/Hex.java (original)
+++ pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/util/Hex.java Wed Jun
18 14:47:27 2025
@@ -228,19 +228,46 @@ public final class Hex
}
else
{
- String hexByte = s.substring(i, i + 2);
- try
+ int value = 16 * getHexValue(s.charAt(i)) +
getHexValue(s.charAt(i + 1));
+ if (value >= 0)
{
- baos.write(Integer.parseInt(hexByte, 16)); //
Byte.parseByte won't work with "9C"
+ baos.write(value);
}
- catch (NumberFormatException ex)
+ else
{
- LOG.error(() -> "Can't parse " + hexByte + ", aborting
decode", ex);
- break;
+ String hexByte = s.substring(i, i + 2);
+ LOG.error("Can't parse " + hexByte + ", aborting decode");
}
i += 2;
}
}
return baos.toByteArray();
}
+
+ /**
+ * Converts a given character to its corresponding hexadecimal value.
Valid characters are '0'-'9', 'A'-'F', or
+ * 'a'-'f'. Returns -256 for invalid characters.
+ * <p>
+ * The value of -256 is chosen so that to hex digits can be combined
before checking for an invalid hex string
+ *
+ * @param c the character to be converted to a hexadecimal value
+ * @return the hexadecimal value of the character, or -256 if the
character is invalid
+ */
+ public static int getHexValue(char c)
+ {
+ if (c >= '0' && c <= '9')
+ {
+ return c - '0';
+ }
+ else if (c >= 'A' && c <= 'F')
+ {
+ return c - 'A' + 10;
+ }
+ else if (c >= 'a' && c <= 'f')
+ {
+ return c - 'a' + 10;
+ }
+ return -256;
+ }
+
}