Fix post code parsing

If we use string_view with std::from_chars, we can use begin() and end()
directly (because they return pointers) and not have to do silly things
like dereference end(), which, while works in practice, is technically
undefined behavior, and some static analyzers complain about it.

Tested: Unit tests pass against both old parsePostCode and new.

Change-Id: Icfdec3b81f4a9c9bed3599571a8bc8779f9bfb98
Signed-off-by: Ed Tanous <ed@tanous.net>
diff --git a/redfish-core/lib/log_services.hpp b/redfish-core/lib/log_services.hpp
index 7522c03..9fa4db1 100644
--- a/redfish-core/lib/log_services.hpp
+++ b/redfish-core/lib/log_services.hpp
@@ -2198,8 +2198,8 @@
     return true;
 }
 
-inline void fillHostLoggerEntryJson(const std::string& logEntryID,
-                                    const std::string& msg,
+inline void fillHostLoggerEntryJson(std::string_view logEntryID,
+                                    std::string_view msg,
                                     nlohmann::json::object_t& logEntryJson)
 {
     // Fill in the log entry with the gathered data.
@@ -2368,14 +2368,13 @@
                                        systemName);
             return;
         }
-        const std::string& targetID = param;
+        std::string_view targetID = param;
 
         uint64_t idInt = 0;
 
-        auto [ptr, ec] = std::from_chars(&*targetID.begin(), &*targetID.end(),
+        auto [ptr, ec] = std::from_chars(targetID.begin(), targetID.end(),
                                          idInt);
-        if (ec == std::errc::invalid_argument ||
-            ec == std::errc::result_out_of_range)
+        if (ec != std::errc{} || ptr != targetID.end())
         {
             messages::resourceNotFound(asyncResp->res, "LogEntry", param);
             return;
@@ -3920,31 +3919,38 @@
  *
  * @return bool true if the parsing is successful, false the parsing fails
  */
-inline bool parsePostCode(const std::string& postCodeID, uint64_t& currentValue,
+inline bool parsePostCode(std::string_view postCodeID, uint64_t& currentValue,
                           uint16_t& index)
 {
     std::vector<std::string> split;
     bmcweb::split(split, postCodeID, '-');
-    if (split.size() != 2 || split[0].length() < 2 || split[0].front() != 'B')
+    if (split.size() != 2)
+    {
+        return false;
+    }
+    std::string_view postCodeNumber = split[0];
+    if (postCodeNumber.size() < 2)
+    {
+        return false;
+    }
+    if (postCodeNumber[0] != 'B')
+    {
+        return false;
+    }
+    postCodeNumber.remove_prefix(1);
+    auto [ptrIndex, ecIndex] = std::from_chars(postCodeNumber.begin(),
+                                               postCodeNumber.end(), index);
+    if (ptrIndex != postCodeNumber.end() || ecIndex != std::errc())
     {
         return false;
     }
 
-    auto start = std::next(split[0].begin());
-    auto end = split[0].end();
-    auto [ptrIndex, ecIndex] = std::from_chars(&*start, &*end, index);
+    std::string_view postCodeIndex = split[1];
 
-    if (ptrIndex != &*end || ecIndex != std::errc())
-    {
-        return false;
-    }
+    auto [ptrValue, ecValue] = std::from_chars(
+        postCodeIndex.begin(), postCodeIndex.end(), currentValue);
 
-    start = split[1].begin();
-    end = split[1].end();
-
-    auto [ptrValue, ecValue] = std::from_chars(&*start, &*end, currentValue);
-
-    return ptrValue == &*end && ecValue == std::errc();
+    return ptrValue == postCodeIndex.end() && ecValue == std::errc();
 }
 
 static bool fillPostCodeEntry(
diff --git a/test/redfish-core/lib/log_services_test.cpp b/test/redfish-core/lib/log_services_test.cpp
index 631e3d1..5dc04c8 100644
--- a/test/redfish-core/lib/log_services_test.cpp
+++ b/test/redfish-core/lib/log_services_test.cpp
@@ -63,5 +63,34 @@
     EXPECT_EQ(indexOut, indexIn);
 }
 
+TEST(LogServicesPostCodeParse, PostCodeParse)
+{
+    uint64_t currentValue = 0;
+    uint16_t index = 0;
+    EXPECT_TRUE(parsePostCode("B1-2", currentValue, index));
+    EXPECT_EQ(currentValue, 2);
+    EXPECT_EQ(index, 1);
+    EXPECT_TRUE(parsePostCode("B200-300", currentValue, index));
+    EXPECT_EQ(currentValue, 300);
+    EXPECT_EQ(index, 200);
+
+    EXPECT_FALSE(parsePostCode("", currentValue, index));
+    EXPECT_FALSE(parsePostCode("B", currentValue, index));
+    EXPECT_FALSE(parsePostCode("B1", currentValue, index));
+    EXPECT_FALSE(parsePostCode("B1-", currentValue, index));
+    EXPECT_FALSE(parsePostCode("B1A-2", currentValue, index));
+    EXPECT_FALSE(parsePostCode("B1A-2", currentValue, index));
+    EXPECT_FALSE(parsePostCode("B1A-2z", currentValue, index));
+    // Uint16_t max + 1
+    EXPECT_FALSE(parsePostCode("B65536-1", currentValue, index));
+
+    // Uint64_t max + 1
+    EXPECT_FALSE(parsePostCode("B1-18446744073709551616", currentValue, index));
+
+    // Negative numbers
+    EXPECT_FALSE(parsePostCode("B-1-2", currentValue, index));
+    EXPECT_FALSE(parsePostCode("B-1--2", currentValue, index));
+}
+
 } // namespace
 } // namespace redfish