native_types: Migrate large functions to shared lib

This speeds up compilation of changes and should save space in users of
the functions.

Change-Id: Iee9029800c11dcd4e94f165766836bae327ee9b5
Signed-off-by: William A. Kennington III <wak@google.com>
diff --git a/include/sdbusplus/message/native_types.hpp b/include/sdbusplus/message/native_types.hpp
index 06547b4..1b5335b 100644
--- a/include/sdbusplus/message/native_types.hpp
+++ b/include/sdbusplus/message/native_types.hpp
@@ -1,10 +1,5 @@
 #pragma once
 
-#include <systemd/sd-bus.h>
-
-#include <sdbusplus/utility/memory.hpp>
-
-#include <array>
 #include <string>
 
 namespace sdbusplus
@@ -147,106 +142,19 @@
         return l < r.str;
     }
 
-    std::string filename() const
-    {
-        size_t firstIndex = str.rfind('/');
-
-        // Dbus paths must start with /, if we don't find one, it's an error
-        if (firstIndex == std::string::npos)
-        {
-            return "";
-        }
-        firstIndex++;
-        // If we don't see that this was encoded by sdbusplus, return the naive
-        // version of the filename path.
-        const char* filename = str.c_str() + firstIndex;
-        if (*filename != '_')
-        {
-            return std::string(filename);
-        }
-
-        _cleanup_free_ char* out = nullptr;
-        int r = sd_bus_path_decode_many(filename, "%", &out);
-        if (r <= 0)
-        {
-            return "";
-        }
-        return std::string(out);
-    }
-
-    string_path_wrapper parent_path() const
-    {
-        auto index = str.rfind('/');
-        if (index == std::string::npos)
-        {
-            return string_path_wrapper("/");
-        }
-        if (index <= 1)
-        {
-            return string_path_wrapper("/");
-        }
-
-        return str.substr(0, index);
-    }
+    std::string filename() const;
+    string_path_wrapper parent_path() const;
+    string_path_wrapper operator/(const char* extId) const;
+    string_path_wrapper& operator/=(const char* extId);
 
     string_path_wrapper operator/(const std::string& extId) const
     {
         return this->operator/(extId.c_str());
     }
 
-    string_path_wrapper operator/(const char* extId) const
-    {
-        string_path_wrapper out;
-        _cleanup_free_ char* encOut = nullptr;
-        int ret = sd_bus_path_encode(str.c_str(), extId, &encOut);
-        if (ret < 0)
-        {
-            return out;
-        }
-        out.str = encOut;
-
-        size_t firstIndex = str.size();
-        if (str != "/")
-        {
-            firstIndex++;
-        }
-
-        // Attempt to encode the first character of the path.  This allows the
-        // filename() method to "detect" that this is a path that's been encoded
-        // and to decode it properly.  This was needed to support a number of
-        // paths that currently dont' have any encoding, and utilize underscores
-        // Ideally this, and the equivalent code in filename() would go away
-        // when all paths are being encoded per systemds methods.
-        if (out.str[firstIndex] == '_')
-        {
-            return out;
-        }
-
-        constexpr std::array<char, 16> hex{'0', '1', '2', '3', '4', '5',
-                                           '6', '7', '8', '9', 'a', 'b',
-                                           'c', 'd', 'e', 'f'};
-        uint8_t firstChar = static_cast<uint8_t>(*extId);
-        out.str[firstIndex] = '_';
-        std::array<char, 2> encoded{hex[(firstChar >> 4) & 0xF],
-                                    hex[firstChar & 0xF]};
-        out.str.insert(out.str.begin() + firstIndex + 1, encoded.begin(),
-                       encoded.end());
-
-        return out;
-    }
-
-    string_path_wrapper& operator/=(const char* extId)
-    {
-        string_path_wrapper out = this->operator/(extId);
-        this->str = std::move(out.str);
-        return *this;
-    }
-
     string_path_wrapper& operator/=(const std::string& extId)
     {
-        string_path_wrapper out = this->operator/(extId);
-        this->str = std::move(out.str);
-        return *this;
+        return this->operator/=(extId.c_str());
     }
 };
 
diff --git a/meson.build b/meson.build
index b116c3c..790684e 100644
--- a/meson.build
+++ b/meson.build
@@ -16,6 +16,7 @@
 libsdbusplus_src = files(
     'src/exception.cpp',
     'src/bus.cpp',
+    'src/message/native_types.cpp',
     'src/sdbus.cpp',
     'src/server/interface.cpp',
     'src/server/transaction.cpp',
diff --git a/src/message/native_types.cpp b/src/message/native_types.cpp
new file mode 100644
index 0000000..5e77cb5
--- /dev/null
+++ b/src/message/native_types.cpp
@@ -0,0 +1,106 @@
+#include <systemd/sd-bus.h>
+
+#include <sdbusplus/message/native_types.hpp>
+#include <sdbusplus/utility/memory.hpp>
+
+#include <array>
+
+namespace sdbusplus
+{
+namespace message
+{
+namespace details
+{
+
+std::string string_path_wrapper::filename() const
+{
+    size_t firstIndex = str.rfind('/');
+
+    // Dbus paths must start with /, if we don't find one, it's an error
+    if (firstIndex == std::string::npos)
+    {
+        return "";
+    }
+    firstIndex++;
+    // If we don't see that this was encoded by sdbusplus, return the naive
+    // version of the filename path.
+    const char* filename = str.c_str() + firstIndex;
+    if (*filename != '_')
+    {
+        return std::string(filename);
+    }
+
+    _cleanup_free_ char* out = nullptr;
+    int r = sd_bus_path_decode_many(filename, "%", &out);
+    if (r <= 0)
+    {
+        return "";
+    }
+    return std::string(out);
+}
+
+string_path_wrapper string_path_wrapper::parent_path() const
+{
+    auto index = str.rfind('/');
+    if (index == std::string::npos)
+    {
+        return string_path_wrapper("/");
+    }
+    if (index <= 1)
+    {
+        return string_path_wrapper("/");
+    }
+
+    return str.substr(0, index);
+}
+
+string_path_wrapper string_path_wrapper::operator/(const char* extId) const
+{
+    string_path_wrapper out;
+    _cleanup_free_ char* encOut = nullptr;
+    int ret = sd_bus_path_encode(str.c_str(), extId, &encOut);
+    if (ret < 0)
+    {
+        return out;
+    }
+    out.str = encOut;
+
+    size_t firstIndex = str.size();
+    if (str != "/")
+    {
+        firstIndex++;
+    }
+
+    // Attempt to encode the first character of the path.  This allows the
+    // filename() method to "detect" that this is a path that's been encoded
+    // and to decode it properly.  This was needed to support a number of
+    // paths that currently dont' have any encoding, and utilize underscores
+    // Ideally this, and the equivalent code in filename() would go away
+    // when all paths are being encoded per systemds methods.
+    if (out.str[firstIndex] == '_')
+    {
+        return out;
+    }
+
+    constexpr std::array<char, 16> hex{'0', '1', '2', '3', '4', '5', '6', '7',
+                                       '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};
+    uint8_t firstChar = static_cast<uint8_t>(*extId);
+    out.str[firstIndex] = '_';
+    std::array<char, 2> encoded{hex[(firstChar >> 4) & 0xF],
+                                hex[firstChar & 0xF]};
+    out.str.insert(out.str.begin() + firstIndex + 1, encoded.begin(),
+                   encoded.end());
+
+    return out;
+}
+
+string_path_wrapper& string_path_wrapper::operator/=(const char* extId)
+{
+    string_path_wrapper out = this->operator/(extId);
+    this->str = std::move(out.str);
+    return *this;
+}
+
+} // namespace details
+} // namespace message
+} // namespace sdbusplus