mirror of
https://github.com/nodejs/node.git
synced 2025-08-15 13:48:44 +02:00

Use `std::string_view` for process.report code and related code, drop a few unnecessary `std::to_string` calls, and use `MaybeStackBuffer` instead of `MallocedBuffer`, all in order to avoid unnecessary heap allocations. PR-URL: https://github.com/nodejs/node/pull/46723 Backport-PR-URL: https://github.com/nodejs/node/pull/47435 Reviewed-By: Tobias Nießen <tniessen@tnie.de> Reviewed-By: Yagiz Nizipli <yagiz@nizipli.com> Reviewed-By: James M Snell <jasnell@gmail.com> Reviewed-By: Darshan Sen <raisinten@gmail.com> Reviewed-By: Chengzhong Wu <legendecas@gmail.com>
172 lines
3.8 KiB
C++
172 lines
3.8 KiB
C++
#ifndef SRC_JSON_UTILS_H_
|
|
#define SRC_JSON_UTILS_H_
|
|
|
|
#if defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS
|
|
|
|
#include <iomanip>
|
|
#include <limits>
|
|
#include <ostream>
|
|
#include <string>
|
|
#include <string_view>
|
|
|
|
namespace node {
|
|
|
|
constexpr bool NeedsJsonEscape(std::string_view str) {
|
|
for (const char c : str) {
|
|
if (c == '\\' || c == '"' || c < 0x20) return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
std::string EscapeJsonChars(std::string_view str);
|
|
std::string Reindent(const std::string& str, int indentation);
|
|
|
|
// JSON compiler definitions.
|
|
class JSONWriter {
|
|
public:
|
|
JSONWriter(std::ostream& out, bool compact)
|
|
: out_(out), compact_(compact) {}
|
|
|
|
private:
|
|
inline void indent() { indent_ += 2; }
|
|
inline void deindent() { indent_ -= 2; }
|
|
inline void advance() {
|
|
if (compact_) return;
|
|
for (int i = 0; i < indent_; i++) out_ << ' ';
|
|
}
|
|
inline void write_one_space() {
|
|
if (compact_) return;
|
|
out_ << ' ';
|
|
}
|
|
inline void write_new_line() {
|
|
if (compact_) return;
|
|
out_ << '\n';
|
|
}
|
|
|
|
public:
|
|
inline void json_start() {
|
|
if (state_ == kAfterValue) out_ << ',';
|
|
write_new_line();
|
|
advance();
|
|
out_ << '{';
|
|
indent();
|
|
state_ = kObjectStart;
|
|
}
|
|
|
|
inline void json_end() {
|
|
write_new_line();
|
|
deindent();
|
|
advance();
|
|
out_ << '}';
|
|
state_ = kAfterValue;
|
|
}
|
|
template <typename T>
|
|
inline void json_objectstart(T key) {
|
|
if (state_ == kAfterValue) out_ << ',';
|
|
write_new_line();
|
|
advance();
|
|
write_string(key);
|
|
out_ << ':';
|
|
write_one_space();
|
|
out_ << '{';
|
|
indent();
|
|
state_ = kObjectStart;
|
|
}
|
|
|
|
template <typename T>
|
|
inline void json_arraystart(T key) {
|
|
if (state_ == kAfterValue) out_ << ',';
|
|
write_new_line();
|
|
advance();
|
|
write_string(key);
|
|
out_ << ':';
|
|
write_one_space();
|
|
out_ << '[';
|
|
indent();
|
|
state_ = kObjectStart;
|
|
}
|
|
inline void json_objectend() {
|
|
write_new_line();
|
|
deindent();
|
|
advance();
|
|
out_ << '}';
|
|
if (indent_ == 0) {
|
|
// Top-level object is complete, so end the line.
|
|
out_ << '\n';
|
|
}
|
|
state_ = kAfterValue;
|
|
}
|
|
|
|
inline void json_arrayend() {
|
|
write_new_line();
|
|
deindent();
|
|
advance();
|
|
out_ << ']';
|
|
state_ = kAfterValue;
|
|
}
|
|
template <typename T, typename U>
|
|
inline void json_keyvalue(const T& key, const U& value) {
|
|
if (state_ == kAfterValue) out_ << ',';
|
|
write_new_line();
|
|
advance();
|
|
write_string(key);
|
|
out_ << ':';
|
|
write_one_space();
|
|
write_value(value);
|
|
state_ = kAfterValue;
|
|
}
|
|
|
|
template <typename U>
|
|
inline void json_element(const U& value) {
|
|
if (state_ == kAfterValue) out_ << ',';
|
|
write_new_line();
|
|
advance();
|
|
write_value(value);
|
|
state_ = kAfterValue;
|
|
}
|
|
|
|
struct Null {}; // Usable as a JSON value.
|
|
|
|
struct ForeignJSON {
|
|
std::string as_string;
|
|
};
|
|
|
|
private:
|
|
template <typename T,
|
|
typename test_for_number = typename std::
|
|
enable_if<std::numeric_limits<T>::is_specialized, bool>::type>
|
|
inline void write_value(T number) {
|
|
if constexpr (std::is_same<T, bool>::value)
|
|
out_ << (number ? "true" : "false");
|
|
else
|
|
out_ << number;
|
|
}
|
|
|
|
inline void write_value(Null null) { out_ << "null"; }
|
|
inline void write_value(std::string_view str) { write_string(str); }
|
|
|
|
inline void write_value(const ForeignJSON& json) {
|
|
out_ << Reindent(json.as_string, indent_);
|
|
}
|
|
|
|
inline void write_string(std::string_view str) {
|
|
out_ << '"';
|
|
if (NeedsJsonEscape(str)) // only create temporary std::string if necessary
|
|
out_ << EscapeJsonChars(str);
|
|
else
|
|
out_ << str;
|
|
out_ << '"';
|
|
}
|
|
|
|
enum JSONState { kObjectStart, kAfterValue };
|
|
std::ostream& out_;
|
|
bool compact_;
|
|
int indent_ = 0;
|
|
int state_ = kObjectStart;
|
|
};
|
|
|
|
} // namespace node
|
|
|
|
#endif // defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS
|
|
|
|
#endif // SRC_JSON_UTILS_H_
|