Change StringToCode() to return Optional<uint32_t> type.

This CL changes StringToCode() to return Optional<uint32_t> type, so
that pdfium::nullopt can be used as the return value to indicate
invalid string, since Acrobat allows character codes which cover the
whole uint32_t range. Right now this CL treats pdfium::nullopt as 0
to avoid behavior changes. A future CL will handle return value 0
differently (as a valid value).

Bug: pdfium:1422
Change-Id: I91db0d010eef5102b67ac2fb0a0118368a83a5d7
Reviewed-on: https://pdfium-review.googlesource.com/c/pdfium/+/64510
Commit-Queue: Hui Yingst <nigi@chromium.org>
Reviewed-by: Lei Zhang <thestig@chromium.org>
diff --git a/core/fpdfapi/font/cpdf_tounicodemap.cpp b/core/fpdfapi/font/cpdf_tounicodemap.cpp
index b275434..acef5e4 100644
--- a/core/fpdfapi/font/cpdf_tounicodemap.cpp
+++ b/core/fpdfapi/font/cpdf_tounicodemap.cpp
@@ -72,10 +72,10 @@
 }
 
 // static
-uint32_t CPDF_ToUnicodeMap::StringToCode(ByteStringView str) {
+pdfium::Optional<uint32_t> CPDF_ToUnicodeMap::StringToCode(ByteStringView str) {
   size_t len = str.GetLength();
   if (len == 0 || str[0] != '<')
-    return 0;
+    return pdfium::nullopt;
 
   uint32_t result = 0;
   for (size_t i = 1; i < len && std::isxdigit(str[i]); ++i) {
@@ -140,7 +140,8 @@
     if (word.IsEmpty() || word == "endbfchar")
       return;
 
-    SetCode(StringToCode(word), StringToWideString(pParser->GetWord()));
+    SetCode(StringToCode(word).value_or(0),
+            StringToWideString(pParser->GetWord()));
   }
 }
 
@@ -151,8 +152,10 @@
       return;
 
     ByteStringView high = pParser->GetWord();
-    uint32_t lowcode = StringToCode(low);
-    uint32_t highcode = (lowcode & 0xffffff00) | (StringToCode(high) & 0xff);
+    uint32_t lowcode = StringToCode(low).value_or(0);
+    uint32_t highcode =
+        (lowcode & 0xffffff00) | (StringToCode(high).value_or(0) & 0xff);
+
     if (highcode == 0xffffffff)
       return;
 
@@ -166,7 +169,7 @@
 
     WideString destcode = StringToWideString(start);
     if (destcode.GetLength() == 1) {
-      uint32_t value = StringToCode(start);
+      uint32_t value = StringToCode(start).value_or(0);
       for (uint32_t code = lowcode; code <= highcode; code++)
         m_Map[code] = value++;
     } else {
diff --git a/core/fpdfapi/font/cpdf_tounicodemap.h b/core/fpdfapi/font/cpdf_tounicodemap.h
index e3d04ed..9eaf625 100644
--- a/core/fpdfapi/font/cpdf_tounicodemap.h
+++ b/core/fpdfapi/font/cpdf_tounicodemap.h
@@ -28,7 +28,7 @@
   friend class cpdf_tounicodemap_StringToCode_Test;
   friend class cpdf_tounicodemap_StringToWideString_Test;
 
-  static uint32_t StringToCode(ByteStringView str);
+  static pdfium::Optional<uint32_t> StringToCode(ByteStringView str);
   static WideString StringToWideString(ByteStringView str);
 
   void Load(const CPDF_Stream* pStream);
diff --git a/core/fpdfapi/font/cpdf_tounicodemap_unittest.cpp b/core/fpdfapi/font/cpdf_tounicodemap_unittest.cpp
index bca94f3..891fa08 100644
--- a/core/fpdfapi/font/cpdf_tounicodemap_unittest.cpp
+++ b/core/fpdfapi/font/cpdf_tounicodemap_unittest.cpp
@@ -7,11 +7,20 @@
 #include "testing/gtest/include/gtest/gtest.h"
 
 TEST(cpdf_tounicodemap, StringToCode) {
-  EXPECT_EQ(0u, CPDF_ToUnicodeMap::StringToCode(""));
-  EXPECT_EQ(0u, CPDF_ToUnicodeMap::StringToCode("12"));
-  EXPECT_EQ(194u, CPDF_ToUnicodeMap::StringToCode("<c2"));
-  EXPECT_EQ(162u, CPDF_ToUnicodeMap::StringToCode("<A2"));
-  EXPECT_EQ(2802u, CPDF_ToUnicodeMap::StringToCode("<Af2"));
+  Optional<uint32_t> result = CPDF_ToUnicodeMap::StringToCode("<c2");
+  ASSERT_TRUE(result.has_value());
+  EXPECT_EQ(194u, result.value());
+
+  result = CPDF_ToUnicodeMap::StringToCode("<A2");
+  ASSERT_TRUE(result.has_value());
+  EXPECT_EQ(162u, result.value());
+
+  result = CPDF_ToUnicodeMap::StringToCode("<Af2");
+  ASSERT_TRUE(result.has_value());
+  EXPECT_EQ(2802u, result.value());
+
+  EXPECT_FALSE(CPDF_ToUnicodeMap::StringToCode("").has_value());
+  EXPECT_FALSE(CPDF_ToUnicodeMap::StringToCode("12").has_value());
 }
 
 TEST(cpdf_tounicodemap, StringToWideString) {