1 // Copyright 2014 The Chromium 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 #ifndef BASE_TRACE_EVENT_TRACED_VALUE_H_
6 #define BASE_TRACE_EVENT_TRACED_VALUE_H_
7 
8 #include <stddef.h>
9 
10 #include <memory>
11 #include <string>
12 #include <vector>
13 
14 #include "base/macros.h"
15 #include "base/pickle.h"
16 #include "base/strings/string_piece.h"
17 #include "base/trace_event/trace_event_impl.h"
18 
19 namespace base {
20 
21 class Value;
22 
23 namespace trace_event {
24 
25 class BASE_EXPORT TracedValue : public ConvertableToTraceFormat {
26  public:
27   // TODO(oysteine): |capacity| is not used in any production code. Consider
28   // removing it.
29   explicit TracedValue(size_t capacity = 0);
30   ~TracedValue() override;
31 
32   void EndDictionary();
33   void EndArray();
34 
35   // These methods assume that |name| is a long lived "quoted" string.
36   void SetInteger(const char* name, int value);
37   void SetDouble(const char* name, double value);
38   void SetBoolean(const char* name, bool value);
39   void SetString(const char* name, base::StringPiece value);
40   void SetValue(const char* name, TracedValue* value);
41   void BeginDictionary(const char* name);
42   void BeginArray(const char* name);
43 
44   // These, instead, can be safely passed a temporary string.
45   void SetIntegerWithCopiedName(base::StringPiece name, int value);
46   void SetDoubleWithCopiedName(base::StringPiece name, double value);
47   void SetBooleanWithCopiedName(base::StringPiece name, bool value);
48   void SetStringWithCopiedName(base::StringPiece name, base::StringPiece value);
49   void SetValueWithCopiedName(base::StringPiece name, TracedValue* value);
50   void BeginDictionaryWithCopiedName(base::StringPiece name);
51   void BeginArrayWithCopiedName(base::StringPiece name);
52 
53   void AppendInteger(int);
54   void AppendDouble(double);
55   void AppendBoolean(bool);
56   void AppendString(base::StringPiece);
57   void BeginArray();
58   void BeginDictionary();
59 
60   // ConvertableToTraceFormat implementation.
61   void AppendAsTraceFormat(std::string* out) const override;
62   bool AppendToProto(ProtoAppender* appender) override;
63 
64   void EstimateTraceMemoryOverhead(TraceEventMemoryOverhead* overhead) override;
65 
66   // A custom serialization class can be supplied by implementing the
67   // Writer interface and supplying a factory class to SetWriterFactoryCallback.
68   // Primarily used by Perfetto to write TracedValues directly into its proto
69   // format, which lets us do a direct memcpy() in AppendToProto() rather than
70   // a JSON serialization step in AppendAsTraceFormat.
71   class BASE_EXPORT Writer {
72    public:
73     virtual ~Writer() = default;
74 
75     virtual void BeginArray() = 0;
76     virtual void BeginDictionary() = 0;
77     virtual void EndDictionary() = 0;
78     virtual void EndArray() = 0;
79 
80     // These methods assume that |name| is a long lived "quoted" string.
81     virtual void SetInteger(const char* name, int value) = 0;
82     virtual void SetDouble(const char* name, double value) = 0;
83     virtual void SetBoolean(const char* name, bool value) = 0;
84     virtual void SetString(const char* name, base::StringPiece value) = 0;
85     virtual void SetValue(const char* name, Writer* value) = 0;
86     virtual void BeginDictionary(const char* name) = 0;
87     virtual void BeginArray(const char* name) = 0;
88 
89     // These, instead, can be safely passed a temporary string.
90     virtual void SetIntegerWithCopiedName(base::StringPiece name,
91                                           int value) = 0;
92     virtual void SetDoubleWithCopiedName(base::StringPiece name,
93                                          double value) = 0;
94     virtual void SetBooleanWithCopiedName(base::StringPiece name,
95                                           bool value) = 0;
96     virtual void SetStringWithCopiedName(base::StringPiece name,
97                                          base::StringPiece value) = 0;
98     virtual void SetValueWithCopiedName(base::StringPiece name,
99                                         Writer* value) = 0;
100     virtual void BeginDictionaryWithCopiedName(base::StringPiece name) = 0;
101     virtual void BeginArrayWithCopiedName(base::StringPiece name) = 0;
102 
103     virtual void AppendInteger(int) = 0;
104     virtual void AppendDouble(double) = 0;
105     virtual void AppendBoolean(bool) = 0;
106     virtual void AppendString(base::StringPiece) = 0;
107 
108     virtual void AppendAsTraceFormat(std::string* out) const = 0;
109 
110     virtual bool AppendToProto(ProtoAppender* appender);
111 
112     virtual void EstimateTraceMemoryOverhead(
113         TraceEventMemoryOverhead* overhead) = 0;
114 
115     virtual bool IsPickleWriter() const = 0;
116     virtual bool IsProtoWriter() const = 0;
117   };
118 
119   typedef std::unique_ptr<Writer> (*WriterFactoryCallback)(size_t capacity);
120   static void SetWriterFactoryCallback(WriterFactoryCallback callback);
121 
122  protected:
123   TracedValue(size_t capacity, bool forced_json);
124 
125   std::unique_ptr<base::Value> ToBaseValue() const;
126 
127  private:
128   std::unique_ptr<Writer> writer_;
129 
130 #ifndef NDEBUG
131   // In debug builds checks the pairings of {Start,End}{Dictionary,Array}
132   std::vector<bool> nesting_stack_;
133 #endif
134 
135   DISALLOW_COPY_AND_ASSIGN(TracedValue);
136 };
137 
138 // TracedValue that is convertable to JSON format. This has lower performance
139 // than the default TracedValue in production code, and should be used only for
140 // testing and debugging. Should be avoided in tracing. It's for
141 // testing/debugging code calling value dumping function designed for tracing,
142 // like the following:
143 //
144 //   TracedValueJSON value;
145 //   AsValueInto(&value);  // which is designed for tracing.
146 //   return value.ToJSON();
147 //
148 // If the code is merely for testing/debugging, base::Value should be used
149 // instead.
150 class BASE_EXPORT TracedValueJSON : public TracedValue {
151  public:
152   explicit TracedValueJSON(size_t capacity = 0)
TracedValue(capacity,true)153       : TracedValue(capacity, /*forced_josn*/ true) {}
154 
155   using TracedValue::ToBaseValue;
156 
157   // Converts the value into a JSON string without formatting. Suitable for
158   // printing a simple value or printing a value in a single line context.
159   std::string ToJSON() const;
160 
161   // Converts the value into a formatted JSON string, with indentation, spaces
162   // and new lines for better human readability of complex values.
163   std::string ToFormattedJSON() const;
164 };
165 
166 }  // namespace trace_event
167 }  // namespace base
168 
169 #endif  // BASE_TRACE_EVENT_TRACED_VALUE_H_
170