GCC Code Coverage Report | |||||||||||||||||||||
|
|||||||||||||||||||||
Line | Branch | Exec | Source |
1 |
// Copyright 2016 the V8 project authors. All rights reserved. |
||
2 |
// Use of this source code is governed by a BSD-style license that can be |
||
3 |
// found in the LICENSE file. |
||
4 |
|||
5 |
#include "tracing/traced_value.h" |
||
6 |
|||
7 |
#if defined(NODE_HAVE_I18N_SUPPORT) |
||
8 |
#include <unicode/utf8.h> |
||
9 |
#include <unicode/utypes.h> |
||
10 |
#endif |
||
11 |
|||
12 |
#include <cmath> |
||
13 |
#include <cstdio> |
||
14 |
#include <sstream> |
||
15 |
#include <string> |
||
16 |
|||
17 |
#if defined(_STLP_VENDOR_CSTD) |
||
18 |
// STLPort doesn't import fpclassify into the std namespace. |
||
19 |
#define FPCLASSIFY_NAMESPACE |
||
20 |
#else |
||
21 |
#define FPCLASSIFY_NAMESPACE std |
||
22 |
#endif |
||
23 |
|||
24 |
namespace node { |
||
25 |
namespace tracing { |
||
26 |
|||
27 |
namespace { |
||
28 |
|||
29 |
1200 |
std::string EscapeString(const char* value) { |
|
30 |
1200 |
std::string result; |
|
31 |
1200 |
result += '"'; |
|
32 |
char number_buffer[10]; |
||
33 |
#if defined(NODE_HAVE_I18N_SUPPORT) |
||
34 |
1200 |
int32_t len = strlen(value); |
|
35 |
1200 |
int32_t p = 0; |
|
36 |
1200 |
int32_t i = 0; |
|
37 |
✓✓ | 9974 |
for (; i < len; p = i) { |
38 |
UChar32 c; |
||
39 |
✓✓✓✗ ✓✗✓✗ ✓✗✗✗ ✗✗✗✗ ✗✗✓✗ ✗✗✓✗ ✗✓ |
8774 |
U8_NEXT_OR_FFFD(value, i, len, c); |
40 |
✓✓✓✓ ✓✓✓✓ |
8774 |
switch (c) { |
41 |
2 |
case '\b': result += "\\b"; break; |
|
42 |
2 |
case '\f': result += "\\f"; break; |
|
43 |
2 |
case '\n': result += "\\n"; break; |
|
44 |
2 |
case '\r': result += "\\r"; break; |
|
45 |
2 |
case '\t': result += "\\t"; break; |
|
46 |
2 |
case '\\': result += "\\\\"; break; |
|
47 |
10 |
case '"': result += "\\\""; break; |
|
48 |
8752 |
default: |
|
49 |
✓✓✓✓ |
8752 |
if (c < 32 || c > 126) { |
50 |
4 |
snprintf( |
|
51 |
number_buffer, arraysize(number_buffer), "\\u%04X", |
||
52 |
static_cast<uint16_t>(static_cast<uint16_t>(c))); |
||
53 |
4 |
result += number_buffer; |
|
54 |
} else { |
||
55 |
8748 |
result.append(value + p, i - p); |
|
56 |
} |
||
57 |
} |
||
58 |
} |
||
59 |
#else |
||
60 |
// If we do not have ICU, use a modified version of the non-UTF8 aware |
||
61 |
// code from V8's own TracedValue implementation. Note, however, This |
||
62 |
// will not produce correctly serialized results for UTF8 values. |
||
63 |
while (*value) { |
||
64 |
char c = *value++; |
||
65 |
switch (c) { |
||
66 |
case '\b': result += "\\b"; break; |
||
67 |
case '\f': result += "\\f"; break; |
||
68 |
case '\n': result += "\\n"; break; |
||
69 |
case '\r': result += "\\r"; break; |
||
70 |
case '\t': result += "\\t"; break; |
||
71 |
case '\\': result += "\\\\"; break; |
||
72 |
case '"': result += "\\\""; break; |
||
73 |
default: |
||
74 |
if (c < '\x20') { |
||
75 |
snprintf( |
||
76 |
number_buffer, arraysize(number_buffer), "\\u%04X", |
||
77 |
static_cast<unsigned>(static_cast<unsigned char>(c))); |
||
78 |
result += number_buffer; |
||
79 |
} else { |
||
80 |
result += c; |
||
81 |
} |
||
82 |
} |
||
83 |
} |
||
84 |
#endif // defined(NODE_HAVE_I18N_SUPPORT) |
||
85 |
1200 |
result += '"'; |
|
86 |
1200 |
return result; |
|
87 |
} |
||
88 |
|||
89 |
10 |
std::string DoubleToCString(double v) { |
|
90 |
✓✓✗✓ |
10 |
switch (FPCLASSIFY_NAMESPACE::fpclassify(v)) { |
91 |
2 |
case FP_NAN: return "\"NaN\""; |
|
92 |
✓✓ | 4 |
case FP_INFINITE: return (v < 0.0 ? "\"-Infinity\"" : "\"Infinity\""); |
93 |
case FP_ZERO: return "0"; |
||
94 |
4 |
default: |
|
95 |
// This is a far less sophisticated version than the one used inside v8. |
||
96 |
8 |
std::ostringstream stream; |
|
97 |
4 |
stream.imbue(std::locale::classic()); // Ignore current locale |
|
98 |
4 |
stream << v; |
|
99 |
4 |
return stream.str(); |
|
100 |
} |
||
101 |
} |
||
102 |
|||
103 |
} // namespace |
||
104 |
|||
105 |
85 |
std::unique_ptr<TracedValue> TracedValue::Create() { |
|
106 |
85 |
return std::unique_ptr<TracedValue>(new TracedValue(false)); |
|
107 |
} |
||
108 |
|||
109 |
2 |
std::unique_ptr<TracedValue> TracedValue::CreateArray() { |
|
110 |
2 |
return std::unique_ptr<TracedValue>(new TracedValue(true)); |
|
111 |
} |
||
112 |
|||
113 |
87 |
TracedValue::TracedValue(bool root_is_array) : |
|
114 |
87 |
first_item_(true), root_is_array_(root_is_array) {} |
|
115 |
|||
116 |
35 |
void TracedValue::SetInteger(const char* name, int value) { |
|
117 |
35 |
WriteName(name); |
|
118 |
35 |
data_ += std::to_string(value); |
|
119 |
35 |
} |
|
120 |
|||
121 |
5 |
void TracedValue::SetDouble(const char* name, double value) { |
|
122 |
5 |
WriteName(name); |
|
123 |
5 |
data_ += DoubleToCString(value); |
|
124 |
5 |
} |
|
125 |
|||
126 |
2 |
void TracedValue::SetBoolean(const char* name, bool value) { |
|
127 |
2 |
WriteName(name); |
|
128 |
✓✓ | 2 |
data_ += value ? "true" : "false"; |
129 |
2 |
} |
|
130 |
|||
131 |
1 |
void TracedValue::SetNull(const char* name) { |
|
132 |
1 |
WriteName(name); |
|
133 |
1 |
data_ += "null"; |
|
134 |
1 |
} |
|
135 |
|||
136 |
1163 |
void TracedValue::SetString(const char* name, const char* value) { |
|
137 |
1163 |
WriteName(name); |
|
138 |
1163 |
data_ += EscapeString(value); |
|
139 |
1163 |
} |
|
140 |
|||
141 |
117 |
void TracedValue::BeginDictionary(const char* name) { |
|
142 |
117 |
WriteName(name); |
|
143 |
117 |
data_ += '{'; |
|
144 |
117 |
first_item_ = true; |
|
145 |
117 |
} |
|
146 |
|||
147 |
17 |
void TracedValue::BeginArray(const char* name) { |
|
148 |
17 |
WriteName(name); |
|
149 |
17 |
data_ += '['; |
|
150 |
17 |
first_item_ = true; |
|
151 |
17 |
} |
|
152 |
|||
153 |
1 |
void TracedValue::AppendInteger(int value) { |
|
154 |
1 |
WriteComma(); |
|
155 |
1 |
data_ += std::to_string(value); |
|
156 |
1 |
} |
|
157 |
|||
158 |
5 |
void TracedValue::AppendDouble(double value) { |
|
159 |
5 |
WriteComma(); |
|
160 |
5 |
data_ += DoubleToCString(value); |
|
161 |
5 |
} |
|
162 |
|||
163 |
2 |
void TracedValue::AppendBoolean(bool value) { |
|
164 |
2 |
WriteComma(); |
|
165 |
✓✓ | 2 |
data_ += value ? "true" : "false"; |
166 |
2 |
} |
|
167 |
|||
168 |
1 |
void TracedValue::AppendNull() { |
|
169 |
1 |
WriteComma(); |
|
170 |
1 |
data_ += "null"; |
|
171 |
1 |
} |
|
172 |
|||
173 |
37 |
void TracedValue::AppendString(const char* value) { |
|
174 |
37 |
WriteComma(); |
|
175 |
37 |
data_ += EscapeString(value); |
|
176 |
37 |
} |
|
177 |
|||
178 |
1 |
void TracedValue::BeginDictionary() { |
|
179 |
1 |
WriteComma(); |
|
180 |
1 |
data_ += '{'; |
|
181 |
1 |
first_item_ = true; |
|
182 |
1 |
} |
|
183 |
|||
184 |
void TracedValue::BeginArray() { |
||
185 |
WriteComma(); |
||
186 |
data_ += '['; |
||
187 |
first_item_ = true; |
||
188 |
} |
||
189 |
|||
190 |
118 |
void TracedValue::EndDictionary() { |
|
191 |
118 |
data_ += '}'; |
|
192 |
118 |
first_item_ = false; |
|
193 |
118 |
} |
|
194 |
|||
195 |
17 |
void TracedValue::EndArray() { |
|
196 |
17 |
data_ += ']'; |
|
197 |
17 |
first_item_ = false; |
|
198 |
17 |
} |
|
199 |
|||
200 |
1387 |
void TracedValue::WriteComma() { |
|
201 |
✓✓ | 1387 |
if (first_item_) { |
202 |
221 |
first_item_ = false; |
|
203 |
} else { |
||
204 |
1166 |
data_ += ','; |
|
205 |
} |
||
206 |
1387 |
} |
|
207 |
|||
208 |
1340 |
void TracedValue::WriteName(const char* name) { |
|
209 |
1340 |
WriteComma(); |
|
210 |
1340 |
data_ += '"'; |
|
211 |
1340 |
data_ += name; |
|
212 |
1340 |
data_ += "\":"; |
|
213 |
1340 |
} |
|
214 |
|||
215 |
197 |
void TracedValue::AppendAsTraceFormat(std::string* out) const { |
|
216 |
✓✓ | 197 |
*out += root_is_array_ ? '[' : '{'; |
217 |
197 |
*out += data_; |
|
218 |
✓✓ | 197 |
*out += root_is_array_ ? ']' : '}'; |
219 |
197 |
} |
|
220 |
|||
221 |
} // namespace tracing |
||
222 |
} // namespace node |
Generated by: GCOVR (Version 4.2) |