OmniSciDB  0b528656ed
StringTransform.h
Go to the documentation of this file.
1 /*
2  * Copyright 2017 MapD Technologies, Inc.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #ifndef SHARED_STRINGTRANSFORM_H
18 #define SHARED_STRINGTRANSFORM_H
19 
20 #include "Logger.h"
21 
22 #ifndef __CUDACC__
23 #include <boost/config.hpp>
24 #include <boost/regex.hpp>
25 #include <optional>
26 #include <string_view>
27 #endif // __CUDACC__
28 
29 #include <algorithm>
30 #include <iomanip>
31 #include <sstream>
32 #include <string>
33 #include <vector>
34 
35 #ifndef __CUDACC__
36 void apply_shim(std::string& result,
37  const boost::regex& reg_expr,
38  const std::function<void(std::string&, const boost::smatch&)>& shim_fn);
39 
40 // cat - Concatenate values of arbitrary types into a string.
41 template <typename... Ts>
42 std::string cat(Ts&&... args) {
43  std::ostringstream oss;
44 #ifdef BOOST_NO_CXX17_FOLD_EXPRESSIONS
45  (void)(int[]){0, ((void)(oss << std::forward<Ts>(args)), 0)...};
46 #else
47  (oss << ... << std::forward<Ts>(args));
48 #endif
49  return oss.str();
50 }
51 #endif // __CUDACC__
52 
53 std::vector<std::pair<size_t, size_t>> find_string_literals(const std::string& query);
54 
55 // Replace passwords, keys, etc. in a sql query with 'XXXXXXXX'.
56 std::string hide_sensitive_data_from_query(std::string const& query_str);
57 
58 ssize_t inside_string_literal(
59  const size_t start,
60  const size_t length,
61  const std::vector<std::pair<size_t, size_t>>& literal_positions);
62 
63 template <typename T>
64 std::string join(T const& container, std::string const& delim) {
65  std::stringstream ss;
66  if (!container.empty()) {
67  ss << container.front();
68  for (auto itr = std::next(container.cbegin()); itr != container.cend(); ++itr) {
69  ss << delim << *itr;
70  }
71  }
72  return ss.str();
73 }
74 
75 template <typename T>
76 std::string to_string(T&& v) {
77  std::ostringstream oss;
78  oss << v;
79  return oss.str();
80 }
81 
82 template <>
83 std::string to_string(char const*&& v);
84 
85 template <>
86 std::string to_string(std::string&& v);
87 
88 // NOTE(sy): to_upper/to_lower: As of Feb 2020, this is a solution recommended by Stack
89 // Overflow. Boost's to_upper_copy() is many times slower, maybe because it uses
90 // locale-aware std::toupper. Probably don't bother converting the input parameters to
91 // std::string_view because testing gave a small slowdown for std::string inputs and a
92 // small speedup for c-style string inputs for this usage.
93 
94 inline std::string to_upper(const std::string& str) {
95  auto str_uc = str;
96  std::transform(str_uc.begin(), str_uc.end(), str_uc.begin(), ::toupper);
97  return str_uc;
98 }
99 
100 inline std::string to_lower(const std::string& str) {
101  auto str_lc = str;
102  std::transform(str_lc.begin(), str_lc.end(), str_lc.begin(), ::tolower);
103  return str_lc;
104 }
105 
106 std::string generate_random_string(const size_t len);
107 
108 #ifndef __CUDACC__
109 std::vector<std::string> split(std::string_view str,
111  std::string_view delim = {},
112  std::optional<size_t> maxsplit = std::nullopt);
113 
115 std::string strip(std::string_view str);
116 #endif // __CUDACC__
117 
120  std::string& str) noexcept;
121 
122 // Remove quotes if they match from beginning and end of string.
123 // Return true if string was changed, false if not.
124 // Does not check for escaped quotes within string.
125 bool unquote(std::string&);
126 
127 #ifndef __CUDACC__
128 std::string get_quoted_string(const std::string& filename,
130  char quote = '"',
131  char escape = '\\');
132 
134 void filename_security_check(const std::string& filename);
135 #endif // __CUDACC__
136 
137 #ifndef __CUDACC__
138 namespace {
139 
140 template <typename T>
141 inline decltype(auto) stringlike(T&& parm) {
142  // String.
143  if constexpr (std::is_base_of_v<std::string, std::remove_reference_t<decltype(parm)>>) {
144  return std::forward<T>(parm);
145  }
146 
147  // Char Array.
148  else if constexpr (std::is_array_v<std::remove_reference_t<decltype(parm)>>) {
149  return std::forward<T>(parm);
150  }
151 
152  // Char String.
153  else if constexpr (std::is_same_v<std::remove_reference_t<decltype(parm)>,
154  const char*> ||
155  std::is_same_v<std::remove_reference_t<decltype(parm)>, char*>) {
156  return std::forward<T>(parm);
157  }
158 
159  // Integer or Floating Point.
160  else if constexpr (std::is_integral_v<std::remove_reference_t<decltype(parm)>> ||
161  std::is_floating_point_v<std::remove_reference_t<decltype(parm)>>) {
162  return std::to_string(std::forward<T>(parm));
163  }
164 
165  // Unsupported type that will fail at compile-time.
166  else {
167  static_assert(std::is_base_of_v<void, decltype(parm)>);
168  return std::string(); // unreachable, but needed to avoid extra error messages
169  }
170 }
171 
172 } // anonymous namespace
173 
174 template <typename... Types>
175 std::string concat(Types&&... parms) {
176  struct Joiner {
177  Joiner() {}
178 
179  std::string txt;
180 
181  void append(std::string_view moretxt) { txt += moretxt; }
182  }; // struct Joiner
183  Joiner j{};
184  (j.append(stringlike(std::forward<Types>(parms))), ...);
185  return std::move(j.txt);
186 }
187 
188 template <typename... Types>
189 std::string concat_with(std::string_view with, Types&&... parms) {
190  struct JoinerWith {
191  JoinerWith(std::string_view join) : join(join), first(true) {}
192 
193  std::string_view join;
194  bool first;
195  std::string txt;
196 
197  void append(std::string_view moretxt) {
198  if (!first) {
199  txt += join;
200  } else {
201  first = false;
202  }
203  txt += moretxt;
204  }
205  }; // struct JoinerWith
206  JoinerWith j{with};
207  (j.append(stringlike(std::forward<Types>(parms))), ...);
208  return std::move(j.txt);
209 }
210 #endif // __CUDACC__
211 
212 #endif // SHARED_STRINGTRANSFORM_H
std::string to_lower(const std::string &str)
std::string filename(char const *path)
Definition: Logger.cpp:62
std::string get_quoted_string(const std::string &filename, char quote='"', char escape = '\)
Quote a string while escaping any existing quotes in the string.
void apply_shim(std::string &result, const boost::regex &reg_expr, const std::function< void(std::string &, const boost::smatch &)> &shim_fn)
std::string join(T const &container, std::string const &delim)
std::string hide_sensitive_data_from_query(std::string const &query_str)
std::string to_string(T &&v)
bool unquote(std::string &)
std::string generate_random_string(const size_t len)
std::string concat(Types &&... parms)
std::string cat(Ts &&... args)
std::vector< std::pair< size_t, size_t > > find_string_literals(const std::string &query)
size_t append(FILE *f, const size_t size, int8_t *buf)
Appends the specified number of bytes to the end of the file f from buf.
Definition: File.cpp:135
ssize_t inside_string_literal(const size_t start, const size_t length, const std::vector< std::pair< size_t, size_t >> &literal_positions)
bool remove_unquoted_newlines_linefeeds_and_tabs_from_sql_string(std::string &str) noexcept
sanitize an SQL string
std::string to_upper(const std::string &str)
std::string strip(std::string_view str)
trim any whitespace from the left and right ends of a string
std::vector< std::string > split(std::string_view str, std::string_view delim={}, std::optional< size_t > maxsplit=std::nullopt)
split apart a string into a vector of substrings
std::string concat_with(std::string_view with, Types &&... parms)
void filename_security_check(const std::string &filename)
Throw exception if security problems found in a filename.