str/cexpr: Add a function to make a constexpr generated string

This allows the user to generate an arbitrary length string at compile
time and convert it automatically to an std::array that is embedded in
the program for zero overhead runtime strings.

Change-Id: Ib6c2dd20cac53bb55e7a32e2fca194bdf0e06211
Signed-off-by: William A. Kennington III <wak@google.com>
diff --git a/include/meson.build b/include/meson.build
index dc4de82..c3bfdfe 100644
--- a/include/meson.build
+++ b/include/meson.build
@@ -10,6 +10,7 @@
   'stdplus/raw.hpp',
   'stdplus/signal.hpp',
   'stdplus/str/cat.hpp',
+  'stdplus/str/cexpr.hpp',
   'stdplus/util/cexec.hpp',
   'stdplus/util/string.hpp',
   'stdplus/zstring.hpp',
diff --git a/include/stdplus/str/cexpr.hpp b/include/stdplus/str/cexpr.hpp
new file mode 100644
index 0000000..a3d5f1c
--- /dev/null
+++ b/include/stdplus/str/cexpr.hpp
@@ -0,0 +1,38 @@
+#pragma once
+#include <algorithm>
+#include <array>
+#include <string_view>
+
+namespace stdplus
+{
+
+template <auto f, bool nul>
+consteval auto cexprToStrArr()
+{
+    std::array<typename decltype(f())::value_type, f().size() + (nul ? 1 : 0)>
+        ret;
+    {
+        auto res = f();
+        std::copy(res.begin(), res.end(), ret.begin());
+        if constexpr (nul)
+        {
+            ret[ret.size() - 1] = '\0';
+        }
+    }
+    return ret;
+}
+
+template <auto f, bool nul>
+inline constexpr auto cexprStrArr = cexprToStrArr<f, nul>();
+
+template <auto f>
+consteval auto cexprToSv()
+{
+    constexpr auto& d = cexprStrArr<f, /*nul=*/false>;
+    return std::basic_string_view(d.begin(), d.end());
+}
+
+template <auto f>
+inline constexpr auto cexprSv = cexprToSv<f>();
+
+} // namespace stdplus
diff --git a/include/stdplus/zstring_view.hpp b/include/stdplus/zstring_view.hpp
index 79003bd..0c18bfb 100644
--- a/include/stdplus/zstring_view.hpp
+++ b/include/stdplus/zstring_view.hpp
@@ -1,6 +1,7 @@
 #pragma once
 #include <fmt/core.h>
 
+#include <stdplus/str/cexpr.hpp>
 #include <stdplus/zstring.hpp>
 
 #include <stdexcept>
@@ -318,6 +319,19 @@
 }
 } // namespace zstring_view_literals
 
+template <auto f>
+consteval auto cexprToZsv()
+{
+    constexpr auto& d = cexprStrArr<f, /*nul=*/true>;
+    static_assert(detail::zstring_find_term(d.data(), d.size() - 1, d.size()) >=
+                  0);
+    return detail::unsafe_zstring_view(
+        std::basic_string_view(d.begin(), d.end() - 1));
+}
+
+template <auto f>
+inline constexpr auto cexprZsv = cexprToZsv<f>();
+
 } // namespace stdplus
 
 #define zstring_view_all(char_t, pfx)                                          \