-
Notifications
You must be signed in to change notification settings - Fork 30.2k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
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: #21475 Reviewed-By: Anna Henningsen <anna@addaleax.net> Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
- Loading branch information
Showing
4 changed files
with
391 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,68 @@ | ||
// 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. | ||
|
||
#ifndef SRC_TRACING_TRACED_VALUE_H_ | ||
#define SRC_TRACING_TRACED_VALUE_H_ | ||
|
||
#include "node_internals.h" | ||
#include "v8.h" | ||
|
||
#include <stddef.h> | ||
#include <memory> | ||
#include <string> | ||
|
||
namespace node { | ||
namespace tracing { | ||
|
||
class TracedValue : public v8::ConvertableToTraceFormat { | ||
public: | ||
~TracedValue() override; | ||
|
||
static std::unique_ptr<TracedValue> Create(); | ||
static std::unique_ptr<TracedValue> CreateArray(); | ||
|
||
void EndDictionary(); | ||
void EndArray(); | ||
|
||
// These methods assume that |name| is a long lived "quoted" string. | ||
void SetInteger(const char* name, int value); | ||
void SetDouble(const char* name, double value); | ||
void SetBoolean(const char* name, bool value); | ||
void SetNull(const char* name); | ||
void SetString(const char* name, const char* value); | ||
void SetString(const char* name, const std::string& value) { | ||
SetString(name, value.c_str()); | ||
} | ||
void BeginDictionary(const char* name); | ||
void BeginArray(const char* name); | ||
|
||
void AppendInteger(int); | ||
void AppendDouble(double); | ||
void AppendBoolean(bool); | ||
void AppendNull(); | ||
void AppendString(const char*); | ||
void AppendString(const std::string& value) { AppendString(value.c_str()); } | ||
void BeginArray(); | ||
void BeginDictionary(); | ||
|
||
// ConvertableToTraceFormat implementation. | ||
void AppendAsTraceFormat(std::string* out) const override; | ||
|
||
private: | ||
explicit TracedValue(bool root_is_array = false); | ||
|
||
void WriteComma(); | ||
void WriteName(const char* name); | ||
|
||
std::string data_; | ||
bool first_item_; | ||
bool root_is_array_; | ||
|
||
DISALLOW_COPY_AND_ASSIGN(TracedValue); | ||
}; | ||
|
||
} // namespace tracing | ||
} // namespace node | ||
|
||
#endif // SRC_TRACING_TRACED_VALUE_H_ |
Oops, something went wrong.