| /* | |
| * Copyright (C) 2025 The Android Open Source Project | |
| * | |
| * Licensed under the Apache License, Version 2.0 (the "License"); | |
| * you may not use this file except in compliance with the License. | |
| * You may obtain a copy of the License at | |
| * | |
| * http://www.apache.org/licenses/LICENSE-2.0 | |
| * | |
| * Unless required by applicable law or agreed to in writing, software | |
| * distributed under the License is distributed on an "AS IS" BASIS, | |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
| * See the License for the specific language governing permissions and | |
| * limitations under the License. | |
| */ | |
| #ifndef SRC_TRACE_PROCESSOR_UTIL_JSON_VALUE_H_ | |
| #define SRC_TRACE_PROCESSOR_UTIL_JSON_VALUE_H_ | |
| #include <cstddef> | |
| #include <cstdint> | |
| #include <iterator> | |
| #include <map> | |
| #include <string> | |
| #include <string_view> | |
| #include <utility> | |
| #include <variant> | |
| #include <vector> | |
| #include "perfetto/ext/base/status_or.h" | |
| namespace perfetto::trace_processor::json { | |
| // Type of JSON value. | |
| enum class Type { | |
| kNull, | |
| kBool, | |
| kInt, | |
| kUint, | |
| kReal, | |
| kString, | |
| kArray, | |
| kObject, | |
| }; | |
| // Forward declaration. | |
| class Dom; | |
| // Returns a reference to a static null Dom value. | |
| const Dom& NullDom(); | |
| // DOM-based JSON value class. | |
| // Provides a jsoncpp-like API for reading and writing JSON values. | |
| class Dom { | |
| public: | |
| using Object = std::map<std::string, Dom>; | |
| using Array = std::vector<Dom>; | |
| // Default constructor creates null value. | |
| Dom() : data_(std::monostate{}) {} | |
| // Type constructor. | |
| explicit Dom(Type type); | |
| // Value constructors. | |
| Dom(bool v) : data_(v) {} | |
| Dom(int v) : data_(static_cast<int64_t>(v)) {} | |
| Dom(int64_t v) : data_(v) {} | |
| Dom(uint64_t v) : data_(v) {} | |
| Dom(double v) : data_(v) {} | |
| Dom(const char* v) : data_(std::string(v)) {} | |
| Dom(std::string v) : data_(std::move(v)) {} | |
| Dom(std::string_view v) : data_(std::string(v)) {} | |
| // Move only - FlatHashMap doesn't support copy. | |
| Dom(const Dom& other) = delete; | |
| Dom& operator=(const Dom& other) = delete; | |
| Dom(Dom&& other) noexcept = default; | |
| Dom& operator=(Dom&& other) noexcept = default; | |
| // Type queries. | |
| Type type() const; | |
| bool IsNull() const { return std::holds_alternative<std::monostate>(data_); } | |
| bool IsBool() const { return std::holds_alternative<bool>(data_); } | |
| bool IsInt() const { return std::holds_alternative<int64_t>(data_); } | |
| bool IsUint() const { return std::holds_alternative<uint64_t>(data_); } | |
| bool IsDouble() const { return std::holds_alternative<double>(data_); } | |
| bool IsIntegral() const { return IsInt() || IsUint(); } | |
| bool IsNumeric() const { return IsIntegral() || IsDouble(); } | |
| bool IsString() const { return std::holds_alternative<std::string>(data_); } | |
| bool IsArray() const { return std::holds_alternative<Array>(data_); } | |
| bool IsObject() const { return std::holds_alternative<Object>(data_); } | |
| // Value accessors with type coercion. | |
| bool AsBool() const; | |
| int AsInt() const; | |
| int64_t AsInt64() const; | |
| uint64_t AsUint() const; | |
| uint64_t AsUint64() const; | |
| double AsDouble() const; | |
| std::string AsString() const; | |
| const char* AsCString() const; | |
| // Object operations. | |
| Dom& operator[](const char* key); | |
| Dom& operator[](const std::string& key); | |
| const Dom& operator[](const char* key) const; | |
| const Dom& operator[](const std::string& key) const; | |
| bool HasMember(const char* key) const; | |
| bool HasMember(const std::string& key) const; | |
| std::vector<std::string> GetMemberNames() const; | |
| void RemoveMember(const char* key); | |
| void RemoveMember(const std::string& key); | |
| // Array operations. | |
| Dom& operator[](size_t index); | |
| const Dom& operator[](size_t index) const; | |
| Dom& operator[](int index); | |
| const Dom& operator[](int index) const; | |
| void Append(Dom&& value); | |
| // Size/empty. | |
| size_t size() const; | |
| bool empty() const; | |
| void Clear(); | |
| // Array iteration. | |
| class ArrayIterator { | |
| public: | |
| using iterator_category = std::forward_iterator_tag; | |
| using value_type = Dom; | |
| using difference_type = std::ptrdiff_t; | |
| using pointer = const Dom*; | |
| using reference = const Dom&; | |
| ArrayIterator() = default; | |
| explicit ArrayIterator(Array::const_iterator it) : it_(it) {} | |
| reference operator*() const { return *it_; } | |
| pointer operator->() const { return &(*it_); } | |
| ArrayIterator& operator++() { | |
| ++it_; | |
| return *this; | |
| } | |
| ArrayIterator operator++(int) { | |
| ArrayIterator tmp = *this; | |
| ++it_; | |
| return tmp; | |
| } | |
| bool operator==(const ArrayIterator& other) const { | |
| return it_ == other.it_; | |
| } | |
| bool operator!=(const ArrayIterator& other) const { | |
| return it_ != other.it_; | |
| } | |
| private: | |
| Array::const_iterator it_; | |
| }; | |
| ArrayIterator begin() const; | |
| ArrayIterator end() const; | |
| // Access underlying data for serialization. | |
| const Array* GetArray() const { return std::get_if<Array>(&data_); } | |
| const Object* GetObject() const { return std::get_if<Object>(&data_); } | |
| Array* GetMutableArray() { return std::get_if<Array>(&data_); } | |
| Object* GetMutableObject() { return std::get_if<Object>(&data_); } | |
| // Deep copy. | |
| Dom Copy() const; | |
| private: | |
| std::variant<std::monostate, // null | |
| bool, | |
| int64_t, | |
| uint64_t, | |
| double, | |
| std::string, | |
| Array, | |
| Object> | |
| data_; | |
| }; | |
| // Serializes a Dom value to a JSON string. | |
| std::string Serialize(const Dom& value); | |
| // Parses a JSON string into a Dom value. | |
| // Returns an error status if parsing fails. | |
| base::StatusOr<Dom> Parse(std::string_view json); | |
| } // namespace perfetto::trace_processor::json | |
| #endif // SRC_TRACE_PROCESSOR_UTIL_JSON_VALUE_H_ |