summaryrefslogtreecommitdiff
path: root/src/strings.cc
blob: 1d74deeec63352a6efed78c36eff5de1a3e799c9 (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
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
// -*- mode: c++; c-basic-offset: 2; -*-

#include "common.hh"

#include "character.hh"
#include "strings.hh"

// static
void Strings::trim(std::string const& str, size_t* start, size_t* end) {
  assert(start && end);
  assert(*start <= *end);
  assert(*end <= str.size());
  while (*start < *end && Character::isspace(str, *start)) ++(*start);
  while (*end > *start && Character::isspace(str, *end - 1)) --(*end);
}

// static
std::string Strings::trim(std::string const& str) {
  return trim(str, 0, str.size());
}

// static
std::string Strings::trim(std::string const& str, size_t start, size_t end) {
  auto s = start, e = end;
  trim(str, &s, &e);
  return str.substr(s, e - s);
}

// static
std::string Strings::quote(std::string const& str) {
  return quote(str, 0, str.size());
}

// static
std::string Strings::quote(std::string const& str, size_t start, size_t end) {
  assert(start <= end);
  assert(end <= str.size());
  auto i = start;
  while (i < end) {
    auto c = str[i];
    if (c == '"' || c == '\\') break;
    ++i;
  }
  std::string ret("\"");
  if (i == end) {
    ret.append(str.substr(start, end - start));
  } else {
    ret.append(str.substr(start, i - start));
    while (true) {
      ret.push_back('\\');
      auto j = i++;
      while (i < end) {
        auto c = str[i];
        if (c == '"' || c == '\\') break;
        ++i;
      }
      ret.append(str.substr(j, i - j));
      if (i == end) break;
    }
  }
  ret.push_back('"');
  return ret;
}

// static
std::string Strings::unquote(std::string const& str) {
  return unquote(str, 0, str.size());
}

// static
std::string Strings::unquote(std::string const& str, size_t start, size_t end) {
  assert(start < end - 1);
  assert(end <= str.size());
  assert(str[start] == '"' && str[end - 1] == '"');
  ++start;
  --end;
  auto i = start;
  while (i < end && str[i] != '\\') ++i;
  if (i == end) return str.substr(start, end - start);
  std::string ret(str.substr(start, i - start));
  while (true) {
    ++i;  // skip backslash
    if (i == end) {
      assert(false);
      ret.push_back('\\');
      break;
    }
    auto j = i++;
    while (i < end && str[i] != '\\') ++i;
    ret.append(str.substr(j, i - j));
    if (i == end) break;
  }
  return ret;
}