-
-
Notifications
You must be signed in to change notification settings - Fork 31.4k
trace_events: add traced_value.cc/traced_value.h #21475
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
509a715
629f936
239e870
8f25cc1
c62c810
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
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_ ? ']' : '}'; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Same here, seems like it might be nicer to make There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is part of the v8 trace event API and really isn't under our control, unfortunately. |
||
} | ||
|
||
} // namespace tracing | ||
} // namespace node |
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_; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. not following how this is being used, and how its value is correct after a call sequence like There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Look within the The original implementation in V8 has |
||
bool root_is_array_; | ||
|
||
DISALLOW_COPY_AND_ASSIGN(TracedValue); | ||
}; | ||
|
||
} // namespace tracing | ||
} // namespace node | ||
|
||
#endif // SRC_TRACING_TRACED_VALUE_H_ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Does
return std::to_string(v);
do the trick here too, for thedefault
case?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'll double check
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah, right, the challenge with
std::to_string(v)
is that it ignores any reasonable precision on the double and always prints six decimals, whereas the version used here will print with actual scientific notation (e.g.std::to_string(v)
whenv = 1.23e7
, will print12300000.000000
whereas the version used here will print1.23e+07
as one would more reasonably expect.