mutable
A Database System for Research and Fast Prototyping
Loading...
Searching...
No Matches
fn.cpp
Go to the documentation of this file.
1#include <mutable/util/fn.hpp>
2
3#if __linux
4#include <sys/types.h>
5#include <unistd.h>
6#elif __APPLE__
7#include <string.h>
8#include <unistd.h>
9#endif
10
11
12using namespace m;
13
14
15std::string m::escape(const std::string &str, char esc, char quote)
16{
17 std::string res;
18 res.reserve(str.length());
19
20 for (auto c : str) {
21 if (c == esc or c == quote) {
22 res += esc;
23 res += c;
24 } else if (c == '\n') {
25 res += esc;
26 res += 'n';
27 } else {
28 res += c;
29 }
30 }
31
32 return res;
33}
34
35std::string m::unescape(const std::string &str, char esc, char quote)
36{
37 std::string res;
38 res.reserve(str.length());
39
40 for (auto it = str.begin(), end = str.end(); it != end; ++it) {
41 if (*it == esc) {
42 ++it;
43 if (*it == esc or *it == quote) {
44 res += *it;
45 } else if (*it == 'n') {
46 res += '\n';
47 } else {
48 /* invalid escape sequence; do not unescape */
49 res += esc;
50 --it;
51 }
52 } else {
53 res += *it;
54 }
55 }
56
57 return res;
58}
59
60std::string m::html_escape(std::string str)
61{
62 str = replace_all(str, "&", "&amp;");
63 str = replace_all(str, "<", "&lt;");
64 str = replace_all(str, ">", "&gt;");
65 return str;
66} // M_LCOV_EXCL_LINE
67
68bool m::like(const std::string &str, const std::string &pattern, const char escape_char)
69{
70 M_insist('_' != escape_char and '%' != escape_char, "illegal escape character");
71
72 bool dp[pattern.length() + 1][str.length() + 1]; // dp[i][j] == true iff pattern[:i] contains str[:j]
73
74 dp[0][0] = true; // empty pattern contains empty string
75 for (std::size_t j = 1; j <= str.length(); ++j)
76 dp[0][j] = false; // empty pattern does not contain non-empty string
77 std::size_t escaped_row = 0;
78 for (std::size_t i = 1; i <= pattern.length(); ++i) {
79 const auto c = pattern[i - 1];
80 const auto escaped = i == escaped_row;
81 if (escaped and '_' != c and '%' != c and escape_char != c)
82 throw m::runtime_error("invalid escape sequence");
83 if (not escaped and escape_char == c)
84 escaped_row = i + 1; // next row is escaped
85 if (not escaped and '%' == c)
86 dp[i][0] = dp[i - 1][0]; // pattern `X%` contains empty string iff `X` contains empty string
87 else
88 dp[i][0] = false; // pattern without `%`-wildcard does not contain empty string
89 }
90 if (pattern.length() + 1 == escaped_row)
91 throw m::runtime_error("invalid escape sequence");
92
93 escaped_row = 0;
94 for (std::size_t i = 1; i <= pattern.length(); ++i) {
95 const auto c = pattern[i - 1];
96 const auto escaped = i == escaped_row;
97 if (not escaped and escape_char == c) {
98 /* Set `escaped_row` and copy entire above row. */
99 escaped_row = i + 1;
100 for (std::size_t j = 0; j <= str.length(); ++j)
101 dp[i][j] = dp[i - 1][j];
102 continue;
103 }
104 for (std::size_t j = 1; j <= str.length(); ++j) {
105 if (not escaped and '%' == c) {
106 /* pattern `X%` contains string `c_0...c_n` iff either `X%` contains `c_0...c_{n-1}
107 * or `X` contains `c_0...c_n` */
108 dp[i][j] = dp[i][j - 1] or dp[i - 1][j];
109 } else if ((not escaped and '_' == c) or str[j - 1] == c) {
110 /* pattern `X_` contains string `c_0...c_n` iff `X` contains `c_0...c_{n-1}`,
111 * pattern `Xa` contains string `c_0...c_{n-1}a` iff `X` contains `c_0...c_{n-1}` */
112 dp[i][j] = dp[i - 1][j - 1];
113 } else {
114 /* pattern `Xa` does not contain string `c_0...c_n` if a != c_n */
115 dp[i][j] = false;
116 }
117 }
118 }
119
120 return dp[pattern.length()][str.length()];
121}
122
123void m::exec(const char *executable, std::initializer_list<const char*> args)
124{
125#if __linux || __APPLE__
126 if (fork()) {
127 /* parent, nothing to be done */
128 } else {
129 /* child */
130 char **c_args = new char*[args.size() + 2];
131 char **p = c_args;
132 *p++ = strdup(executable);
133 for (auto arg : args)
134 *p++ = strdup(arg);
135 *p = nullptr;
136 execv(executable, c_args);
137 M_unreachable("Invalid executable path or arguments"); // M_LCOV_EXCL_LINE
138 }
139#endif
140}
141
142std::size_t m::get_pagesize()
143{
144 static std::size_t pagesize(0);
145 if (0 == pagesize)
146 pagesize = sysconf(_SC_PAGESIZE);
147 return pagesize;
148}
struct @5 args
#define M_unreachable(MSG)
Definition: macro.hpp:146
#define M_insist(...)
Definition: macro.hpp:129
‍mutable namespace
Definition: Backend.hpp:10
std::string replace_all(std::string str, const std::string &from, const std::string &to)
Definition: fn.hpp:35
std::string escape(char c)
Definition: fn.hpp:292
std::string quote(const std::string &str)
Definition: fn.hpp:306
std::string M_EXPORT unescape(const std::string &str, char esc='\\', char quote='"')
Definition: fn.cpp:35
void M_EXPORT exec(const char *executable, std::initializer_list< const char * > args)
Definition: fn.cpp:123
std::string M_EXPORT html_escape(std::string str)
Escapes special characters in a string to be printable in HTML documents.
Definition: fn.cpp:60
and
Definition: enum_ops.hpp:12
std::size_t M_EXPORT get_pagesize()
Returns the page size of the system.
Definition: fn.cpp:142
bool M_EXPORT like(const std::string &str, const std::string &pattern, const char escape_char='\\')
Compares a SQL-style LIKE pattern with the given std::string.
Definition: fn.cpp:68
Signals a runtime error that mu*t*able is not responsible for and that mu*t*able was not able to reco...
Definition: exception.hpp:49