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