added \*frob

master
Avril 4 years ago
parent 40be7c9859
commit 4199c0b3de
Signed by: flanchan
GPG Key ID: 284488987C31F630

@ -1,27 +1,115 @@
#pragma once #pragma once
#include <string>
#include <vector>
namespace frob namespace frob
{ {
using u8 = unsigned char; using u8 = unsigned char;
constexpr u8 rot13(u8 i) constexpr static const u8 ROT13_CONSTANT =
#ifdef FROB_CONSTANT
(u8)(FROB_CONSTANT)
#else
(u8)42;
#endif
constexpr inline u8 rot13(u8 i)
{ {
return i ^ (u8)42; return i ^ ROT13_CONSTANT;
} }
template<std::size_t N> template<std::size_t N, typename CHAR=char>
requires(N > 0) requires(N > 0)
struct cfrob struct cfrob
{ {
char out[N]{}; CHAR out[N]{};
constexpr cfrob(const char (&sz)[N]) inline constexpr operator const char*() const { return out; }
inline operator char*() { return out; }
constexpr cfrob(const CHAR (&sz)[N])
{ {
for(std::size_t i=0;i<N-1;i++) for(std::size_t i=0;i<N-1;i++)
out[i] = rot13((u8)sz[i]); out[i] = rot13((u8)sz[i]);
out[N-1] = 0; out[N-1] = 0;
} }
}; };
// frobnicate functions
template<std::size_t N>
constexpr auto memfrob(const u8 (&sz)[N])
{
return cfrob(sz);
}
template<std::size_t N>
inline auto memfrob(u8 (&sz)[N])
{
for(std::size_t i=0;i<N;i++)
sz[i] = rot13(sz[i]);
return sz;
}
template<typename P = void>
inline P* memfrob(u8* ptr, std::size_t len)
{
for(auto i=0;i<len;i++)
ptr[i] = rot13(ptr[i]);
return (P*)ptr;
}
inline std::vector<u8> memfrob(const u8* ptr, std::size_t len)
{
std::vector<u8> out;
out.reserve(len);
for(std::size_t i=0;i<len;i++)
out.push_back(rot13(ptr[i]));
return out;
}
inline std::vector<u8>& memfrob(std::vector<u8>* _s)
{
std::vector<u8>& s = *_s;
for(auto& b : s) b = rot13(b);
return s;
}
inline std::vector<u8> memfrob(const std::vector<u8>& s)
{
std::vector<u8> out = s;
memfrob(out);
return out;
}
template<std::size_t N>
constexpr inline auto strfrob(const char (&sz)[N])
{
return cfrob(sz);
}
inline std::string strfrob(const std::string& s)
{
std::string out;
out.reserve(s.size());
for(const char& c : s)
out+= rot13((u8)c);
return out;
}
inline std::string& strfrob(std::string* sp)
{
std::string& s = *sp;
for(char& c : s)
c = rot13((u8)c);
return s;
}
inline std::string strfrob(const char* str)
{
return strfrob(std::string(str));
}
inline char* strfrob(char* str)
{
for(;*str;str++)
*str = rot13((u8)*str);
return str;
}
} }
template<frob::cfrob C> template<frob::cfrob C>
constexpr auto operator "" _frob() constexpr auto operator "" _frob()
{ {

@ -10,14 +10,37 @@ constexpr const char* str2 = "Hello world."_frob;
// Can also be stored as normal `const char*` string constant pointer. // Can also be stored as normal `const char*` string constant pointer.
const char* str3 = "Hello world."_frob; const char* str3 = "Hello world."_frob;
void assert_streq(const char* str, const char* str2)
{
if (strcmp(str,str2)!=0)
{
std::cerr << "Mismatch: '" << str << "' is not eq to '" << str2 << "'" << std::endl;
std::terminate();
}
}
#define ASSERT_STREQ(ty, expr, get) do { ty _str = expr; assert_streq(_str get, str2); } while(0)
int main() int main()
{ {
char* str2 = strdup(str); char* str2 = strdup(str);
memfrob(str2, strlen(str)); memfrob(str2, strlen(str));
std::cout << str << std::endl; std::cout << str << std::endl;
std::cout << str2 << std::endl; std::cout << str2 << std::endl;
free(str2);
// test of frob::*frob()
{
ASSERT_STREQ(const auto, frob::strfrob(str), .c_str());
std::string frobbed = frob::strfrob((const char*)str2);
constexpr const auto out = frob::strfrob<>("Hello world."); //for some reason it doesn't prefer the `constexpr` template overload, even in a constexpr context?
auto out2 = frob::strfrob(out);
std::cout << frobbed << std::endl;
std::cout << out << std::endl;
std::cout << out2 << std::endl;
}
free(str2);
return 0; return 0;
} }

Loading…
Cancel
Save