summaryrefslogtreecommitdiff
path: root/src/jsutil.cc
blob: ca74b48dfc89d0c3c26f1cc01d5301422ceafaae (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
#include "common.hh"

#include "jsutil.hh"

namespace js {

namespace {

constexpr const char kSingleQuoteChars[] = "'\0\\\n\r\v\t\b\f";
constexpr const char kDoubleQuoteChars[] = "\"\0\\\n\r\v\t\b\f";

}  // namespace

std::string quote(std::string_view in, QuoteChar quote_char) {
  std::string ret;
  quote(in, ret, quote_char);
  return ret;
}

void quote(std::string_view in, std::string& out, QuoteChar quote_char) {
  out.reserve(out.size() + 2 + in.size());
  std::string_view chars;
  switch (quote_char) {
  case QuoteChar::SINGLE:
    chars = std::string_view(kSingleQuoteChars, sizeof(kSingleQuoteChars) - 1);
    break;
  case QuoteChar::DOUBLE:
    chars = std::string_view(kDoubleQuoteChars, sizeof(kDoubleQuoteChars) - 1);
    break;
  }
  out.push_back(chars.front());
  size_t last = 0;
  while (true) {
    auto next = in.find_first_of(chars, last);
    if (next == std::string::npos) {
      out.append(in, last);
      break;
    }
    out.append(in, last, next - last);
    out.push_back('\\');
    switch (in[next]) {
    case '\0':
      out.push_back('0');
      break;
    case '\n':
      out.push_back('n');
      break;
    case '\r':
      out.push_back('r');
      break;
    case '\v':
      out.push_back('v');
      break;
    case '\t':
      out.push_back('t');
      break;
    case '\b':
      out.push_back('b');
      break;
    case '\f':
      out.push_back('f');
      break;
    default:
      out.push_back(in[next]);
      break;
    }
    last = next + 1;
  }
  out.push_back(chars.front());
}

}  // namespace js