11cb0ef41Sopenharmony_ci#include "json_utils.h"
21cb0ef41Sopenharmony_ci
31cb0ef41Sopenharmony_cinamespace node {
41cb0ef41Sopenharmony_ci
51cb0ef41Sopenharmony_cistd::string EscapeJsonChars(std::string_view str) {
61cb0ef41Sopenharmony_ci  // 'static constexpr' is slightly better than static const
71cb0ef41Sopenharmony_ci  // since the initialization occurs at compile time.
81cb0ef41Sopenharmony_ci  // See https://lemire.me/blog/I3Cah
91cb0ef41Sopenharmony_ci  static constexpr std::string_view control_symbols[0x20] = {
101cb0ef41Sopenharmony_ci      "\\u0000", "\\u0001", "\\u0002", "\\u0003", "\\u0004", "\\u0005",
111cb0ef41Sopenharmony_ci      "\\u0006", "\\u0007", "\\b",     "\\t",     "\\n",     "\\u000b",
121cb0ef41Sopenharmony_ci      "\\f",     "\\r",     "\\u000e", "\\u000f", "\\u0010", "\\u0011",
131cb0ef41Sopenharmony_ci      "\\u0012", "\\u0013", "\\u0014", "\\u0015", "\\u0016", "\\u0017",
141cb0ef41Sopenharmony_ci      "\\u0018", "\\u0019", "\\u001a", "\\u001b", "\\u001c", "\\u001d",
151cb0ef41Sopenharmony_ci      "\\u001e", "\\u001f"};
161cb0ef41Sopenharmony_ci
171cb0ef41Sopenharmony_ci  std::string ret;
181cb0ef41Sopenharmony_ci  size_t last_pos = 0;
191cb0ef41Sopenharmony_ci  size_t pos = 0;
201cb0ef41Sopenharmony_ci  for (; pos < str.size(); ++pos) {
211cb0ef41Sopenharmony_ci    std::string replace;
221cb0ef41Sopenharmony_ci    char ch = str[pos];
231cb0ef41Sopenharmony_ci    if (ch == '\\') {
241cb0ef41Sopenharmony_ci      replace = "\\\\";
251cb0ef41Sopenharmony_ci    } else if (ch == '\"') {
261cb0ef41Sopenharmony_ci      replace = "\\\"";
271cb0ef41Sopenharmony_ci    } else {
281cb0ef41Sopenharmony_ci      size_t num = static_cast<size_t>(ch);
291cb0ef41Sopenharmony_ci      if (num < 0x20) replace = control_symbols[num];
301cb0ef41Sopenharmony_ci    }
311cb0ef41Sopenharmony_ci    if (!replace.empty()) {
321cb0ef41Sopenharmony_ci      if (pos > last_pos) {
331cb0ef41Sopenharmony_ci        ret += str.substr(last_pos, pos - last_pos);
341cb0ef41Sopenharmony_ci      }
351cb0ef41Sopenharmony_ci      last_pos = pos + 1;
361cb0ef41Sopenharmony_ci      ret += replace;
371cb0ef41Sopenharmony_ci    }
381cb0ef41Sopenharmony_ci  }
391cb0ef41Sopenharmony_ci  // Append any remaining symbols.
401cb0ef41Sopenharmony_ci  if (last_pos < str.size()) {
411cb0ef41Sopenharmony_ci    ret += str.substr(last_pos, pos - last_pos);
421cb0ef41Sopenharmony_ci  }
431cb0ef41Sopenharmony_ci  return ret;
441cb0ef41Sopenharmony_ci}
451cb0ef41Sopenharmony_ci
461cb0ef41Sopenharmony_cistd::string Reindent(const std::string& str, int indent_depth) {
471cb0ef41Sopenharmony_ci  if (indent_depth <= 0) return str;
481cb0ef41Sopenharmony_ci  const std::string indent(indent_depth, ' ');
491cb0ef41Sopenharmony_ci  std::string out;
501cb0ef41Sopenharmony_ci  std::string::size_type pos = 0;
511cb0ef41Sopenharmony_ci  for (;;) {
521cb0ef41Sopenharmony_ci    std::string::size_type prev_pos = pos;
531cb0ef41Sopenharmony_ci    pos = str.find('\n', pos);
541cb0ef41Sopenharmony_ci
551cb0ef41Sopenharmony_ci    out.append(indent);
561cb0ef41Sopenharmony_ci
571cb0ef41Sopenharmony_ci    if (pos == std::string::npos) {
581cb0ef41Sopenharmony_ci      out.append(str, prev_pos, std::string::npos);
591cb0ef41Sopenharmony_ci      break;
601cb0ef41Sopenharmony_ci    } else {
611cb0ef41Sopenharmony_ci      pos++;
621cb0ef41Sopenharmony_ci      out.append(str, prev_pos, pos - prev_pos);
631cb0ef41Sopenharmony_ci    }
641cb0ef41Sopenharmony_ci  }
651cb0ef41Sopenharmony_ci
661cb0ef41Sopenharmony_ci  return out;
671cb0ef41Sopenharmony_ci}
681cb0ef41Sopenharmony_ci
691cb0ef41Sopenharmony_ci}  // namespace node
70