diff options
author | James M Snell <jasnell@gmail.com> | 2018-06-22 12:50:01 -0700 |
---|---|---|
committer | James M Snell <jasnell@gmail.com> | 2018-07-12 10:32:26 -0700 |
commit | d85449dcdf60513dc8bb8d54b22fdb1da5316bad (patch) | |
tree | 972f1c715c78baeed913b60edf8a0e5c3f406777 /src/tracing/traced_value.cc | |
parent | d4164ca559f5d458384b379852972c84ff918ab4 (diff) | |
download | node-new-d85449dcdf60513dc8bb8d54b22fdb1da5316bad.tar.gz |
trace_events: add traced_value.cc/traced_value.h
Port of the V8 internal v8::tracing::TracedValue that allows
structured data to be included in the trace event. The v8 class
is not exported in the public API so we cannot use it directly.
This is a simplified and slightly modified port. This commit only
adds the class, it does not add uses of it. Those will come in
separate PRs/commits.
PR-URL: https://github.com/nodejs/node/pull/21475
Reviewed-By: Anna Henningsen <anna@addaleax.net>
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
Diffstat (limited to 'src/tracing/traced_value.cc')
-rw-r--r-- | src/tracing/traced_value.cc | 224 |
1 files changed, 224 insertions, 0 deletions
diff --git a/src/tracing/traced_value.cc b/src/tracing/traced_value.cc new file mode 100644 index 0000000000..e256df267e --- /dev/null +++ b/src/tracing/traced_value.cc @@ -0,0 +1,224 @@ +// Copyright 2016 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "tracing/traced_value.h" + +#include <math.h> +#include <sstream> +#include <stdio.h> +#include <string> + +#if defined(NODE_HAVE_I18N_SUPPORT) +#include <unicode/utf8.h> +#include <unicode/utypes.h> +#endif + +#if defined(_STLP_VENDOR_CSTD) +// STLPort doesn't import fpclassify into the std namespace. +#define FPCLASSIFY_NAMESPACE +#else +#define FPCLASSIFY_NAMESPACE std +#endif + +namespace node { +namespace tracing { + +namespace { + +std::string EscapeString(const char* value) { + std::string result; + result += '"'; + char number_buffer[10]; +#if defined(NODE_HAVE_I18N_SUPPORT) + int32_t len = strlen(value); + int32_t p = 0; + int32_t i = 0; + for (; i < len; p = i) { + UChar32 c; + U8_NEXT_OR_FFFD(value, i, len, c); + switch (c) { + case '\b': result += "\\b"; break; + case '\f': result += "\\f"; break; + case '\n': result += "\\n"; break; + case '\r': result += "\\r"; break; + case '\t': result += "\\t"; break; + case '\\': result += "\\\\"; break; + case '"': result += "\\\""; break; + default: + if (c < 32 || c > 126) { + snprintf( + number_buffer, arraysize(number_buffer), "\\u%04X", + static_cast<uint16_t>(static_cast<uint16_t>(c))); + result += number_buffer; + } else { + result.append(value + p, i - p); + } + } + } +#else + // If we do not have ICU, use a modified version of the non-UTF8 aware + // code from V8's own TracedValue implementation. Note, however, This + // will not produce correctly serialized results for UTF8 values. + while (*value) { + char c = *value++; + switch (c) { + case '\b': result += "\\b"; break; + case '\f': result += "\\f"; break; + case '\n': result += "\\n"; break; + case '\r': result += "\\r"; break; + case '\t': result += "\\t"; break; + case '\\': result += "\\\\"; break; + case '"': result += "\\\""; break; + default: + if (c < '\x20') { + snprintf( + number_buffer, arraysize(number_buffer), "\\u%04X", + static_cast<unsigned>(static_cast<unsigned char>(c))); + result += number_buffer; + } else { + result += c; + } + } + } +#endif // defined(NODE_HAVE_I18N_SUPPORT) + result += '"'; + return result; +} + +std::string DoubleToCString(double v) { + switch (FPCLASSIFY_NAMESPACE::fpclassify(v)) { + case FP_NAN: return "\"NaN\""; + case FP_INFINITE: return (v < 0.0 ? "\"-Infinity\"" : "\"Infinity\""); + case FP_ZERO: return "0"; + default: + // This is a far less sophisticated version than the one used inside v8. + std::ostringstream stream; + stream.imbue(std::locale("C")); // Ignore locale + stream << v; + return stream.str(); + } +} + +} // namespace + +std::unique_ptr<TracedValue> TracedValue::Create() { + return std::unique_ptr<TracedValue>(new TracedValue(false)); +} + +std::unique_ptr<TracedValue> TracedValue::CreateArray() { + return std::unique_ptr<TracedValue>(new TracedValue(true)); +} + +TracedValue::TracedValue(bool root_is_array) : + first_item_(true), root_is_array_(root_is_array) {} + +TracedValue::~TracedValue() {} + +void TracedValue::SetInteger(const char* name, int value) { + WriteName(name); + data_ += std::to_string(value); +} + +void TracedValue::SetDouble(const char* name, double value) { + WriteName(name); + data_ += DoubleToCString(value); +} + +void TracedValue::SetBoolean(const char* name, bool value) { + WriteName(name); + data_ += value ? "true" : "false"; +} + +void TracedValue::SetNull(const char* name) { + WriteName(name); + data_ += "null"; +} + +void TracedValue::SetString(const char* name, const char* value) { + WriteName(name); + data_ += EscapeString(value); +} + +void TracedValue::BeginDictionary(const char* name) { + WriteName(name); + data_ += '{'; + first_item_ = true; +} + +void TracedValue::BeginArray(const char* name) { + WriteName(name); + data_ += '['; + first_item_ = true; +} + +void TracedValue::AppendInteger(int value) { + WriteComma(); + data_ += std::to_string(value); +} + +void TracedValue::AppendDouble(double value) { + WriteComma(); + data_ += DoubleToCString(value); +} + +void TracedValue::AppendBoolean(bool value) { + WriteComma(); + data_ += value ? "true" : "false"; +} + +void TracedValue::AppendNull() { + WriteComma(); + data_ += "null"; +} + +void TracedValue::AppendString(const char* value) { + WriteComma(); + data_ += EscapeString(value); +} + +void TracedValue::BeginDictionary() { + WriteComma(); + data_ += '{'; + first_item_ = true; +} + +void TracedValue::BeginArray() { + WriteComma(); + data_ += '['; + first_item_ = true; +} + +void TracedValue::EndDictionary() { + data_ += '}'; + first_item_ = false; +} + +void TracedValue::EndArray() { + data_ += ']'; + first_item_ = false; +} + +void TracedValue::WriteComma() { + if (first_item_) { + first_item_ = false; + } else { + data_ += ','; + } +} + +void TracedValue::WriteName(const char* name) { + WriteComma(); + data_ += '"'; + data_ += name; + data_ += "\":"; +} + +void TracedValue::AppendAsTraceFormat(std::string* out) const { + *out += root_is_array_ ? '[' : '{'; + *out += data_; + *out += root_is_array_ ? ']' : '}'; +} + +} // namespace tracing +} // namespace node |