Author: lehmi
Date: Wed Jun 18 14:52:44 2025
New Revision: 1926546

URL: http://svn.apache.org/viewvc?rev=1926546&view=rev
Log:
PDFBOX-5997: avoid creation of temporary objects as proposed by Axel Howind

Modified:
    
pdfbox/branches/2.0/pdfbox/src/main/java/org/apache/pdfbox/cos/COSString.java
    pdfbox/branches/2.0/pdfbox/src/main/java/org/apache/pdfbox/util/Hex.java

Modified: 
pdfbox/branches/2.0/pdfbox/src/main/java/org/apache/pdfbox/cos/COSString.java
URL: 
http://svn.apache.org/viewvc/pdfbox/branches/2.0/pdfbox/src/main/java/org/apache/pdfbox/cos/COSString.java?rev=1926546&r1=1926545&r2=1926546&view=diff
==============================================================================
--- 
pdfbox/branches/2.0/pdfbox/src/main/java/org/apache/pdfbox/cos/COSString.java 
(original)
+++ 
pdfbox/branches/2.0/pdfbox/src/main/java/org/apache/pdfbox/cos/COSString.java 
Wed Jun 18 14:52:44 2025
@@ -108,36 +108,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/branches/2.0/pdfbox/src/main/java/org/apache/pdfbox/util/Hex.java
URL: 
http://svn.apache.org/viewvc/pdfbox/branches/2.0/pdfbox/src/main/java/org/apache/pdfbox/util/Hex.java?rev=1926546&r1=1926545&r2=1926546&view=diff
==============================================================================
--- pdfbox/branches/2.0/pdfbox/src/main/java/org/apache/pdfbox/util/Hex.java 
(original)
+++ pdfbox/branches/2.0/pdfbox/src/main/java/org/apache/pdfbox/util/Hex.java 
Wed Jun 18 14:52:44 2025
@@ -280,14 +280,15 @@ 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);
+                    String hexByte = s.substring(i, i + 2);
+                    LOG.error("Can't parse " + hexByte + ", aborting decode");
                     break;
                 }
                 i += 2;
@@ -295,4 +296,31 @@ public final class Hex
         }
         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;
+    }
+
 }


Reply via email to