Skip to content

Instantly share code, notes, and snippets.

@notfoundry
Created June 24, 2019 01:33
Show Gist options
  • Select an option

  • Save notfoundry/64782aacb650533e6d2563ab3f5a7fdb to your computer and use it in GitHub Desktop.

Select an option

Save notfoundry/64782aacb650533e6d2563ab3f5a7fdb to your computer and use it in GitHub Desktop.
Align raw string literals to a common baseline at compiletime
#include <cstdlib>
#include <array>
#include <boost/mp11/list.hpp>
#include <boost/mp11/algorithm.hpp>
using namespace boost::mp11;
template <class C, C... Cs>
struct nttp_string {};
template <class String, class Acc, class Splits>
struct nttp_string_splitlines;
template <class C, C... String, C... Acc, template <class...> class SplitsC, class... Splits>
struct nttp_string_splitlines<nttp_string<C, C('\n'), String...>, nttp_string<C, Acc...>, SplitsC<Splits...>> {
using type = typename nttp_string_splitlines<
nttp_string<C, String...>, nttp_string<C>, SplitsC<Splits..., nttp_string<C, Acc...>>
>::type;
};
template <class C, C Front, C... String, C... Acc, class Splits>
struct nttp_string_splitlines<nttp_string<C, Front, String...>, nttp_string<C, Acc...>, Splits> {
using type = typename nttp_string_splitlines<
nttp_string<C, String...>, nttp_string<C, Acc..., Front>, Splits
>::type;
};
template <class C, C... Acc, template <class...> class SplitsC, class... Splits>
struct nttp_string_splitlines<nttp_string<C>, nttp_string<C, Acc...>, SplitsC<Splits...>> {
using type = SplitsC<Splits..., nttp_string<C, Acc...>>;
};
template <class Splits, class Acc>
struct nttp_string_joinlines {
using type = Acc;
};
template <template <class...> class SplitsC, class C, C... Cs, class... Splits, C... Acc>
struct nttp_string_joinlines<SplitsC<nttp_string<C, Cs...>, Splits...>, nttp_string<C, Acc...>> {
using type = typename nttp_string_joinlines<SplitsC<Splits...>, nttp_string<C, Acc..., C('\n'), Cs...>>::type;
};
template <std::size_t Count, class C, C Front, C... Rest>
struct nttp_string_drop_impl {
using type = typename nttp_string_drop_impl<Count - 1, C, Rest...>::type;
};
template <class C, C Front, C... Cs>
struct nttp_string_drop_impl<0, C, Front, Cs...> {
using type = nttp_string<C, Front, Cs...>;
};
template <std::size_t Count, class From>
struct nttp_string_drop;
template <std::size_t Count, class C, C... Cs>
struct nttp_string_drop<Count, nttp_string<C, Cs...>> {
using type = typename nttp_string_drop_impl<Count, C, Cs...>::type;
};
template <class From, std::size_t Acc = 0>
struct get_indent;
template <class C, C... From, std::size_t Acc>
struct get_indent<nttp_string<C, C(' '), From...>, Acc> {
constexpr static std::size_t value = get_indent<nttp_string<C, From...>, Acc + 1>::value;
};
template <class C, C... FromCs, std::size_t Acc>
struct get_indent<nttp_string<C, FromCs...>, Acc> {
constexpr static std::size_t value = Acc;
};
template <class S>
struct nttp_string_to_cstring;
template <class C, C... Cs>
struct nttp_string_to_cstring<nttp_string<C, Cs...>> {
constexpr static std::array<C, sizeof...(Cs)> data {Cs...};
constexpr static C const* value = data.data();
};
template <class C, C... Cs>
struct align_impl {
using split = typename nttp_string_splitlines<nttp_string<C, Cs...>, nttp_string<C>, mp_list<>>::type;
using front = mp_front<split>;
using rest = mp_pop_front<split>;
constexpr static std::size_t indent = get_indent<mp_front<rest>>::value;
template <class From>
using strip_indent = typename nttp_string_drop<indent, From>::type;
using stripped_rest = mp_transform<strip_indent, rest>;
using nttp_value = typename nttp_string_joinlines<stripped_rest, front>::type;
constexpr static C const* value = nttp_string_to_cstring<nttp_value>::value;
};
template <class C, C... Cs>
constexpr auto operator""_align() noexcept {
return align_impl<C, Cs...>::value;
}
// let's try it out
auto source = R"(for x in [1, 2, 3]:
squared = x * x
for y in range(squared):
print(y))"_align;
auto expected_output = R"(0
01
012
0123
01234
012345
0123456
01234567
012345678
0123456789)"_align;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment